Class Tool

GoDiagram®
v10.0.8
by Northwoods Software®

Tools handle mouse, keyboard, and touch events. The currently running tool, CurrentTool, receives all input events from the Diagram via canonicalized InputEvents.

Namespace: Northwoods.Go.Tools
Assembly: Northwoods.GoDiagram.WinForms.dll
Syntax
public abstract class Tool
Remarks

For more discussion, see Introduction to Tools. See samples that make use of tools in the samples index.

Most tools are "mode-less" tools that are managed by the ToolManager, which chooses the current tool based on the kind and position of the mouse event and the parts in the diagram. The ToolManager has properties holding instances of most of the pre-defined Tool classes. These classes include:

The ToolManager chooses a tool to run as the diagram's current tool by finding in its lists of tools the first tool whose CanStart() method returns true. The ToolManager then sets CurrentTool to be that tool.

A tool is in the "running" state when it is the value of CurrentTool. The CurrentTool property setter will call DoStop() on the old tool and then call DoStart() on the new tool.

A tool can then go into the "active" state once it decides it can actually do something. This happens with a call to DoActivate(), normally called by the ToolManager. Later it is deactivated (DoDeactivate()) and then stopped. IsActive should be true when the tool is "active". Often tools should ignore certain common events, such as calls to DoMouseMove(), unless the tool IsActive.

You can prevent a "mode-less" tool (i.e. one managed by the ToolManager) from being started by the ToolManager by setting IsEnabled to false.

You can also go into a particular "mode" by setting CurrentTool explicitly, thereby circumventing the normal operation of the ToolManager. This ignores the IsEnabled property and does not call the CanStart() predicate. The behavior will depend on the tool -- not all of the predefined tools support operating as a "modal" tool.

Tools cannot be shared amongst multiple Diagrams.

If you define a Tool subclass, you may override any of the methods whose names start with "Do" and any other methods that are documented to be overridable, such as CanStart(). However you must seriously consider calling the base method in order to gets its default behavior. There may be situations where not calling the base method may cause subtle bugs. But that depends on the method and the tool. Please read the Introduction page on Extensions for how to override methods and how to call the base method.

Constructors

Tool()

Don't construct this directly -- this is an abstract class.

Declaration
public Tool()

Properties

Diagram

This read-only property returns the Diagram that owns this tool and for which this tool is handling input events.

Declaration
public Diagram Diagram { get; set; }
Property Value
Type Description
Diagram

IsActive

Gets or sets whether this tool is started and is actively doing something.

Declaration
public virtual bool IsActive { get; set; }
Property Value
Type Description
bool
Remarks

You can set this to true after your tool is started (i.e. when it is the CurrentTool and DoStart() had been called), but when it is not yet in a state that it is actually "doing" something, because it is waiting for the right circumstances. This is typically only important when the tool is used in a modal fashion.

The default value is false.

This is normally set by DoActivate() and DoDeactivate().

IsEnabled

Gets or sets whether this tool can be started by a mouse event.

Declaration
public virtual bool IsEnabled { get; set; }
Property Value
Type Description
bool
Remarks

Set this to false to prevent CanStart() from returning true. Setting this property to false should prevent this tool from being used in a mode-less fashion by the ToolManager with a mouse down/move/up event. However, even when this property is false, this tool can still be used in a modal fashion: it can still be started by explicitly setting the CurrentTool property to this tool.

The default value is true.

Name

Gets or sets the name of this tool.

Declaration
public virtual string Name { get; set; }
Property Value
Type Description
string
Remarks

The default name is an empty string, but the constructor for each instance of a subclass of Tool will initialize it appropriately. For example, the name of the DragSelectingTool is "DragSelecting".

This name is sometimes used by tools that use Adornments as the Category for their Adornments. It is also sometimes used by tools that conduct transactions as the transaction name.

TransactionResult

Gets or sets the name of the transaction to be committed by StopTransaction()

Declaration
public virtual string TransactionResult { get; set; }
Property Value
Type Description
string
Remarks

If null, the transaction will be rolled back.

If this is non-null at the time of a call to StopTransaction(), it calls CommitTransaction(string) with this transaction name; if this is null at that time, it calls RollbackTransaction().

The default value is null; StartTransaction(string) will also set this to null. Because a value of null when StopTransaction() is called will rollback the transaction, it is important that your code sets this property to a non-null value when it thinks it has succeeded.

This property exists so that no matter what execution path occurs to end the usage of a tool, any ongoing transaction can be properly committed or rolled-back. Many tools call StartTransaction(string) and StopTransaction(); thus they set this property for their transaction to be committed. DoCancel() also sets this property to null.

Methods

CancelWaitAfter()

This is called to cancel any running "WaitAfter" timer.

Declaration
public virtual void CancelWaitAfter()
Remarks

This is called when a tool is stopped.

This method is rarely overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

CanStart()

This predicate is used by the ToolManager to decide if this tool can be started mode-lessly by mouse and touch events.

Declaration
public virtual bool CanStart()
Returns
Type Description
bool

true if IsEnabled is true and if the ToolManager can make this tool the CurrentTool and then call the DoStart() method.

Remarks

Implementations of this method can look at LastInput to get the mouse event and input state.

By default this method returns IsEnabled.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

CanStartMultiTouch()

Called by DoMouseDown() and DoMouseMove(), this method determines whether or not to allow pinch zooming from a multi-touch event.

Declaration
public virtual bool CanStartMultiTouch()
Returns
Type Description
bool
Remarks

By default this predicate just returns true.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

See Also

DoActivate()

The Diagram calls this method after setting CurrentTool, to make the new tool active.

Declaration
public virtual void DoActivate()
Remarks

This should set IsActive to true. Overrides of this method might call StartTransaction(string), if this tool's activity involves modification of the model. Implementations of this method can look at LastInput to get the mouse event and input state.

You should call this method only after setting CurrentTool to the Tool that you want to activate.

By default this only sets IsActive to true.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

If you override this method, it is commonplace to also override DoDeactivate() to clean up whatever you set up in this method.

DoCancel()

The diagram will call this method when the user wishes to cancel the current tool's operation.

Declaration
public virtual void DoCancel()
Remarks

Typically this is called when the user hits the ESCAPE key. This should restore the original state of what was modified by this tool, and then it should call StopTool(). This method is not responsible for cleaning up any side-effects that should be performed by DoDeactivate() and/or DoStop(), which will always be called whether the tool stops normally or abnormally.

By default this method just sets TransactionResult to null and calls StopTool().

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method. You will want to override this method even in tools that call StartTransaction(string) and StopTransaction(), because the UndoManager might not be enabled.

DoDeactivate()

The Diagram calls this method on the old tool when CurrentTool is set to a new tool.

Declaration
public virtual void DoDeactivate()
Remarks

This needs to set IsActive to false. Overrides of this method might call StopTransaction(), if this tool's activity involves modification of the model.

You should have no reason to call this method, because it is automatically called by the CurrentTool property setter on the old tool.

By default this only sets IsActive to false.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

It is commonplace to override this method in order to clean up whatever you have set up in an override of DoActivate().

DoKeyDown()

The diagram will call this method upon a key down event.

Declaration
public virtual void DoKeyDown()
Remarks

By default this just calls DoCancel() if the key is the ESCAPE key. Implementations of this method can look at LastInput to get the key.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

DoKeyUp()

The diagram will call this method upon a key up event.

Declaration
public virtual void DoKeyUp()
Remarks

Implementations of this method can look at LastInput to get the key.

By default this method does nothing. This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

DoMouseDown()

The diagram will call this method upon a mouse down event.

Declaration
public virtual void DoMouseDown()
Remarks

This is normally overridden for mouse-down tools; it is not called for mouse-move or mouse-up tools. However it may also be called when the tool is run in a modal fashion, when code explicitly sets the diagram's CurrentTool. Implementations of this method can look at LastInput to get the mouse event and input state.

By default this method checks IsActive; if that is false it calls CanStart(). If that in turn is true, this calls DoActivate().

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

DoMouseMove()

The diagram will call this method upon a mouse move event.

Declaration
public virtual void DoMouseMove()
Remarks

This is normally overridden for mouse-move tools; it is not called for mouse-up tools. However it may also be called when the tool is run in a modal fashion, when code explicitly sets the diagram's CurrentTool. An override of this method usually does nothing when IsActive is false. Implementations of this method can look at LastInput to get the mouse event and input state.

By default this method does nothing.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

DoMouseUp()

The diagram will call this method upon a mouse up event.

Declaration
public virtual void DoMouseUp()
Remarks

This is normally overridden for mouse-up tools. An override of this method usually does nothing when IsActive is false, except for calling StopTool(). Tools normally stop upon a mouse up, by calling StopTool(). If you want to handle multiple mouse down-up gestures in one tool activation, you will need to override this method to only stop the tool when you want. Implementations of this method can look at LastInput to get the mouse event and input state.

By default this method just calls StopTool().

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

DoMouseWheel()

The diagram will call this method as the mouse wheel is rotated.

Declaration
public virtual void DoMouseWheel()
Remarks

Implementations of this method can look at LastInput to get the mouse event and input state.

By default this method does nothing. (But the DoMouseWheel() override will call StandardMouseWheel().)

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

DoStart()

The Diagram calls this method when this tool becomes the current tool; you should not call this method.

Declaration
public virtual void DoStart()
Remarks

Tool implementations should perform their per-use initialization here, such as setting up internal data structures, or capturing the mouse. Implementations of this method can look at LastInput to get the mouse event and input state.

You should not call this method -- only the CurrentTool property setter should call this method.

By default this method does nothing.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

If you override this method, it is commonplace to also override DoStop() to clean up whatever you set up in this method.

DoStop()

The Diagram calls this method when this tool stops being the current tool; you should not call this method.

Declaration
public virtual void DoStop()
Remarks

Tool implementations should perform their per-use cleanup here, such as releasing mouse capture.

You should not call this method -- only the CurrentTool property setter should call this method. If you want to stop a tool unexpectedly, you should call DoCancel(). If your implementation of a tool wants to stop itself, you should call StopTool().

By default this method does nothing.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

It is commonplace to override this method in order to clean up whatever you have set up in an override of DoStart().

DoWaitAfter(InputEvent)

This is called a certain delay after a call to StandardWaitAfter(double, InputEvent) if there has not been any call to CancelWaitAfter().

Declaration
public virtual void DoWaitAfter(InputEvent e)
Parameters
Type Name Description
InputEvent e

The event that caused StandardWaitAfter(double, InputEvent).

Remarks

The ToolManager overrides this method in order to implement support for mouse-hover behavior and tooltips.

By default this does nothing. This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

FindToolHandleAt(Point, string)

This convenience function finds the front-most GraphObject that is at a given point and that is an element of an Adornment that is of a given category.

Declaration
public virtual GraphObject FindToolHandleAt(Point p, string category)
Parameters
Type Name Description
Point p

a Point in document coordinates.

string category

the required Category of the Adornment.

Returns
Type Description
GraphObject
Remarks

The tool handle must be an immediate element of the Adornment, not a GraphObject that is nested within Panels within the Adornment.

This method is very infrequently overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

IsBeyondDragSize(Point?, Point?)

Return true when the last mouse point is far enough away from the first mouse down point to constitute a drag operation instead of just a potential click.

Declaration
public virtual bool IsBeyondDragSize(Point? first = null, Point? last = null)
Parameters
Type Name Description
Point? first

Point in view coordinates, defaults to FirstInput's ViewPoint.

Point? last

Point in view coordinates, defaults to LastInput's ViewPoint.

Returns
Type Description
bool
Remarks

This uses the value of DragSize. On touch devices the value is automatically increased to accommodate the unavoidable movement of fingers.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

StandardMouseClick(Func<GraphObject, GraphObject>, Predicate<GraphObject>)

Implement the standard behavior for mouse clicks, searching for and calling click handler functions on GraphObjects or on Diagram, and raising the corresponding DiagramEvent.

Declaration
public virtual bool StandardMouseClick(Func<GraphObject, GraphObject> navig, Predicate<GraphObject> pred)
Parameters
Type Name Description
Func<GraphObject, GraphObject> navig

A custom navigation function to find target objects.

Predicate<GraphObject> pred

A custom predicate function to find target objects. No value means that only objects in layers holding permanent objects.

Returns
Type Description
bool

true if Handled had been set to true on the LastInput.

Remarks

A click on a GraphObject of the diagram will raise one of the following DiagramEvents: ElementSingleClicked, ElementDoubleClicked, ElementContextClicked. This will also look at the corresponding click property: Click, DoubleClick, or ContextClick. If the value is a function, this will call it, passing the current InputEvent and the GraphObject. If the value is null, it tries looking at the parent Panel, and so on, walking up the visual tree until it finds the appropriate function to call. After calling the click function, if the value of Handled is false, this method will continue walking up the visual tree looking for more click functions to call. Once it has looked at the top-level object (a Part) for a click function, this method stops.

A click in the background of the diagram will raise one of the following DiagramEvents: "BackgroundSingleClicked", "BackgroundDoubleClicked", or "BackgroundContextClicked". This will also look at the corresponding click property: Click, DoubleClick, or ContextClick. If the value is a function, this will call it, passing the current InputEvent.

This method is not responsible for selecting or deselecting any parts. Call StandardMouseSelect() for that functionality.

Note that this calls IsEnabledElement() on the target object; if it returns false, no click action will occur.

The ClickSelectingTool calls this method in its override of DoMouseUp() in order to raise "click" events. Note that by default GraphObjects in Layers that are IsTemporary will not be "clicked". To change that behavior it is easiest to set IsActionable to true on those objects for which you wish to handle "click" events. Then the ActionTool's DoMouseUp() override will raise the standard "click" events.

This method may be overridden, but you should consider calling this base method in order to get all of its functionality. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

StandardMouseClick(Func<GraphObject, GraphObject>)

Implement the standard behavior for mouse clicks, searching for and calling click handler functions on GraphObjects or on Diagram, and raising the corresponding DiagramEvent.

Declaration
public virtual bool StandardMouseClick(Func<GraphObject, GraphObject> navig = null)
Parameters
Type Name Description
Func<GraphObject, GraphObject> navig

A custom navigation function to find target objects.

Returns
Type Description
bool

true if Handled had been set to true on the LastInput.

Remarks

A click on a GraphObject of the diagram will raise one of the following DiagramEvents: ElementSingleClicked, ElementDoubleClicked, ElementContextClicked. This will also look at the corresponding click property: Click, DoubleClick, or ContextClick. If the value is a function, this will call it, passing the current InputEvent and the GraphObject. If the value is null, it tries looking at the parent Panel, and so on, walking up the visual tree until it finds the appropriate function to call. After calling the click function, if the value of Handled is false, this method will continue walking up the visual tree looking for more click functions to call. Once it has looked at the top-level object (a Part) for a click function, this method stops.

A click in the background of the diagram will raise one of the following DiagramEvents: "BackgroundSingleClicked", "BackgroundDoubleClicked", or "BackgroundContextClicked". This will also look at the corresponding click property: Click, DoubleClick, or ContextClick. If the value is a function, this will call it, passing the current InputEvent.

This method is not responsible for selecting or deselecting any parts. Call StandardMouseSelect() for that functionality.

Note that this calls IsEnabledElement() on the target object; if it returns false, no click action will occur.

The ClickSelectingTool calls this method in its override of DoMouseUp() in order to raise "click" events. Note that by default GraphObjects in Layers that are IsTemporary will not be "clicked". To change that behavior it is easiest to set IsActionable to true on those objects for which you wish to handle "click" events. Then the ActionTool's DoMouseUp() override will raise the standard "click" events.

This method may be overridden, but you should consider calling this base method in order to get all of its functionality. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

StandardMouseOver()

Implement the standard behavior for mouse enter, over, and leave events, where the mouse is moving but no button is pressed.

Declaration
public virtual void StandardMouseOver()
Remarks

This should be called by mouse move event handlers when wanting to detect and invoke mouse enter/over/leave event handlers.

The MouseEnter property provides a function to call when the mouse first enters an object or any of its contained objects (if the object is actually a Panel).

The MouseLeave property provides a function to call when the mouse leaves an object and all of its contained objects (if the object is actually a Panel).

The MouseOver property and MouseOver properties provide functions to call when the mouse moves but stays within the same GraphObject or when the mouse moves in the background of the Diagram.

This method is also responsible for updating the CurrentCursor according to the value of Cursor and DefaultCursor.

This method may be overridden, but you should consider calling this base method in order to get all of its functionality. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

StandardMouseSelect()

Implement the standard behavior for selecting parts with the mouse, depending on the control and shift modifier keys.

Declaration
public virtual void StandardMouseSelect()
Remarks

Control-clicking on a part will select it if it wasn't already, and will deselect if it had been selected. Shift-clicking on a part will add it to the selection (if it wasn't already). Otherwise, clicking on a part will select it (if it wasn't already).

Note that there are restrictions on selection. For example, a part cannot be selected in this manner if Selectable is false, or if MaxSelectionCount would be exceeded.

A left click in the background of the diagram with no modifier keys clears the selection.

This method does not implement any click event behavior -- that is implemented by StandardMouseClick(Func<GraphObject, GraphObject>).

The ClickSelectingTool calls this method in its override of DoMouseUp() in order to change the selection.

This method may be overridden, but you should consider calling this base method in order to get all of its functionality. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

StandardMouseWheel()

Implement the standard behavior for mouse wheel events. DoMouseWheel() calls this method.

Declaration
public virtual void StandardMouseWheel()
Remarks

Turning the mouse wheel if AllowVerticalScroll is true causes the diagram to scroll up or down. If Shift and AllowHorizontalScroll are true, the diagram scrolls left or right.

If Control and AllowZoom are true, turning the mouse wheel changes the diagram's scale, zooming in or out while trying to keep the point in the model at the same point as the mouse.

The value of MouseWheelBehavior affects what operations might occur upon mouse wheel events.

This method may be overridden, but you should consider calling this base method in order to get all of its functionality. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

StandardPinchZoomMove()

Continues pinch-zooming (started by StandardPinchZoomStart() on multi-touch devices.

Declaration
public virtual void StandardPinchZoomMove()
Remarks

This is called by DoMouseMove() if the LastInput has IsMultiTouch set to true and CanStartMultiTouch() returns true. By default this calls DoCancel() in order to cancel the regular tool behavior caused by the multitouch events. This then calculates the appropriate zoom level and calls CanResetZoom(double) to decide whether to call ResetZoom(double) to actually set Scale.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

See Also

StandardPinchZoomStart()

Initiates pinch-zooming on multi-touch devices.

Declaration
public virtual void StandardPinchZoomStart()
Remarks

This is called by DoMouseDown() if the LastInput has IsMultiTouch set to true and CanStartMultiTouch() returns true.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

See Also

StandardWaitAfter(double, InputEvent)

This is called to start a new timer to call DoWaitAfter(InputEvent) after a given delay. It first cancels any previously running "WaitAfter" timer, by calling CancelWaitAfter().

Declaration
public virtual void StandardWaitAfter(double delay, InputEvent e = null)
Parameters
Type Name Description
double delay

The delay, in milliseconds.

InputEvent e

An optional event that caused this timer. Defaults to LastInput. This gets passed on to DoWaitAfter(InputEvent).

Remarks

This is normally used to implement mouse hover and mouse hold events. If the mouse has moved, it must not have moved beyond the distance as determined by IsBeyondDragSize(Point?, Point?) for it be considered "stationary". So the regular DoMouseMove() implementation only calls this method when the mouse has moved beyond the drag size.

This method is rarely overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

StartTransaction(string)

Call StartTransaction(string) with the given transaction name.

Declaration
public bool StartTransaction(string tname = null)
Parameters
Type Name Description
string tname

a string describing the transaction.

Returns
Type Description
bool

the value of the call to StartTransaction(string).

Remarks

This always sets TransactionResult to null.

This is normally called in an override of DoActivate(), if the tool modifies the model, along with a call to StopTransaction() in an override of DoDeactivate(). Alternatively, you can surround a block of code that sets the TransactionResult with calls to StartTransaction and StopTransaction.

StopTool()

If the CurrentTool is this tool, stop this tool and start the DefaultTool by making it be the new current tool.

Declaration
public virtual void StopTool()
Remarks

The implementation of various tool methods can call this method to stop the current tool. This will call DoStop() -- you should not call that method directly.

If you want to stop the current tool and have it restore the original state, call DoCancel(). Please read the Introduction page on Extensions for how to override methods and how to call this base method.

StopTransaction()

Declaration
public virtual bool StopTransaction()
Returns
Type Description
bool

the result of the call to rollback or commit the transaction.

Remarks

This is normally called in an override of DoDeactivate(), if StartTransaction(string) was called in DoActivate(). Alternatively, you can surround a block of code that sets the TransactionResult with calls to StartTransaction and StopTransaction.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

UpdateAdornments(Part)

The diagram asks each tool to update any adornments the tool might use for a given part.

Declaration
public virtual void UpdateAdornments(Part part)
Parameters
Type Name Description
Part part
Remarks

If the tool uses its own tool handles, this should display them or hide them as appropriate. Typically this should only show them if the part is selected.

By default this method does nothing.

This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.