Tools and the Tool Controller¶
In a typical drawing application, the user is often presented with tools as a set of buttons in a palette - clicking the button selects that tool, putting the application into a mode where mouse activity achieves certain things. While DrawKit certainly has something like this kind of user interface in mind, its definition of a tool is more abstract and not tied to any particular UI.
In DrawKit, a tool is an object that converts mouse events into meaningful actions and behaviours targeted at the active layer or objects within it (or perhaps both, as with the select and edit tool). The tool thus translates the general mouse gestures into specific actions. Because drawables are responsible for the nuts and bolts of their own editing, in DrawKit most tools are quite lightweight objects.
DKToolController is a view controller subclass that manages the tools and coordinates the selecting of the tool and feeding the basic mouse events to them according to the agreed protocol. Only one tool can be set at a time, since this establishes a mode of operation for mouse input, and the user can only use the mouse in one view at a time. Selecting the tool could correspond to a user selecting a button in a palette of tools - in fact implementing this kind of user interface is extremely straightforward, though any other UI that ultimately picks a tool will work equally well.
DrawKit maintains a simple registry of tools (implemented by the DKDrawingTool class) which allows tools to be associated with a name. You can retrieve a tool by name and set it as the current tool in the tool controller. Convenient action methods in DKToolController allow you to do this very easily by hooking up a user interface element that has a -title property to the -setDrawingToolByName: action, set to the name of the desired tool. This could be a button for example (the title itself might be hidden, as with an icon button, but the title string itself is still readable as a tool name by DK’s code).
Tools might vary in their scope of operation. For example one kind of tool might operate only in one particular layer or kind of layer, another might operate in a general way. To establish this, the tool controller initially asks the current tool whether the active layer is useful to it - by returning NO the tool can prevent any further call to itself. If YES, it will subsequently receive the usual mouse event methods. This allows a tool to decide its own target scope. For example, the zoom tool accepts anything, so it works no matter what type of layer is set as the active layer, even a hidden or locked one. Conversely, object creation tools can only work when an object drawing layer is active. This test is performed at mouseDown time, so having an inappropriate active layer doesn’t prevent a tool from being selected, it just stops it from receiving mouse events.