Class LinkingTool

GoDiagram®
v10.0.8
by Northwoods Software®

The LinkingTool lets a user draw a new Link between two ports, using a mouse-drag operation.

Namespace: Northwoods.Go.Tools
Assembly: Northwoods.GoDiagram.WinForms.dll
Syntax
public class LinkingTool : LinkingBaseTool
Remarks

By default an instance of this tool is installed as a mouse-move tool in the ToolManager as the LinkingTool. However this tool may be used modally, as described below.

CanStart() calls FindLinkablePort() to find a valid "port" element from which (or to which) the user may interactively draw a new link. DoActivate() sets up a temporary link and two temporary nodes, one at the start port and one following the mouse.

For a general discussion of validation, see Introduction to Validation.

This tool does not utilize any Adornments or tool handles.

This tool conducts a transaction while the tool is active. A successful linking will result in a "LinkDrawn" DiagramEvent and a "Linking" transaction.

If you want to programmatically start a new user mouse-gesture to draw a new link from a given GraphObject that either is a "port" or may be within the visual tree of a "port", set the StartElement property to let FindLinkablePort() find the real "port" element. Then start and activate this tool:

var tool = myDiagram.ToolManager.LinkingTool;
tool.StartElement = ...;
myDiagram.CurrentTool = tool;
tool.DoActivate();

Constructors

LinkingTool()

You do not normally need to create an instance of this tool because one already exists as the LinkingTool, which you can modify.

The Name of this tool is "Linking".

Declaration
public LinkingTool()

Properties

ArchetypeLabelNodeData

Gets or sets an optional node data object representing a link label, that is copied by InsertLink(Node, GraphObject, Node, GraphObject) and added to the GraphLinksModel<TNodeData, TNodeKey, TSharedData, TLinkData, TLinkKey, TPort> when creating a new Link.

Declaration
public object ArchetypeLabelNodeData { get; set; }
Property Value
Type Description
object
Remarks

The default value is null, which causes no such label node data to be added to the model along with the new link data.

InsertLink(Node, GraphObject, Node, GraphObject) calls AddLabelKeyForLinkData(TLinkData, TNodeKey) to associate the label node data with the link data.

Setting this property does not raise any events. This property is ignored if the Model is not a GraphLinksModel<TNodeData, TNodeKey, TSharedData, TLinkData, TLinkKey, TPort>.

ArchetypeLinkData

Gets or sets a data object that is copied by InsertLink(Node, GraphObject, Node, GraphObject) and added to the GraphLinksModel<TNodeData, TNodeKey, TSharedData, TLinkData, TLinkKey, TPort> when creating a new Link.

Declaration
public object ArchetypeLinkData { get; set; }
Property Value
Type Description
object
Remarks

The default value is an empty Object, which will be copied. The value must be an Object for the linking operation to succeed. A null value will cause InsertLink(Node, GraphObject, Node, GraphObject) to fail.

The copied link data's LinkFromKeyProperty and LinkToKeyProperty properties are set to the corresponding node's data's key values. If the ports have PortId values that are not null, the link data's LinkFromPortIdProperty and LinkToPortIdProperty properties are also set.

Setting this property does not raise any events. This property is ignored if the Model is not a GraphLinksModel<TNodeData, TNodeKey, TSharedData, TLinkData, TLinkKey, TPort>.

Direction

Gets or sets the direction in which new links may be drawn.

Declaration
public LinkingDirection Direction { get; set; }
Property Value
Type Description
LinkingDirection
Remarks

Possible values are ForwardsOnly, BackwardsOnly, or Either. This defaults to Either. Setting this property does not raise any events.

StartElement

Gets or sets the GraphObject at which FindLinkablePort() should start its search.

Declaration
public GraphObject StartElement { get; set; }
Property Value
Type Description
GraphObject
Remarks

The default value is null. Setting this property does not raise any events.

If you want to explicitly start a new user mouse-gesture to draw a new link from a given GraphObject that may be a "port" object or may be within the visual tree of a "port" object, set this property to that object to let FindLinkablePort() find the real "port" object. Then start and activate this tool:

var tool = myDiagram.ToolManager.LinkingTool;
tool.StartElement = ...;
myDiagram.CurrentTool = tool;
tool.DoActivate();

Methods

CanStart()

This tool can run when the diagram allows linking, the model is modifiable, the left-button mouse drag has moved far enough away to not be a click, and when FindLinkablePort() has returned a valid port or when StartElement is a valid port.

Declaration
public override bool CanStart()
Returns
Type Description
bool
Overrides
Remarks

This method may be overridden, but we recommend that you call this base method.

DoActivate()

Start the linking operation.

Declaration
public override void DoActivate()
Overrides
Remarks

This calls FindLinkablePort() to find the port from which to start drawing a new link. If it is not set, it looks for a linkable port at the FirstInput point. If it finds one, it remembers it as the starting port, otherwise it stops this tool.

It then starts a transaction, captures the mouse, and changes the cursor. Next it initializes and adds the TemporaryFromNode, TemporaryToNode, and TemporaryLink to the diagram. The temporary nodes that are positioned and sized to be like the real OriginalFromPort and OriginalToPort ports. The temporary link connects the two temporary ports, of course.

This method may be overridden, but we recommend that you call this base method.

DoDeactivate()

Finishing the linking operation stops the transaction, releases the mouse, and resets the cursor.

Declaration
public override void DoDeactivate()
Overrides
Remarks

This method may be overridden, but we recommend that you call this base method.

DoMouseUp()

A mouse-up ends the linking operation; if there is a valid TargetPort nearby, this adds a new Link by calling InsertLink(Node, GraphObject, Node, GraphObject).

Declaration
public override void DoMouseUp()
Overrides
Remarks

If there is a new link, it is selected and the "LinkDrawn" DiagramEvent is raised with the new link as the Subject. If there is no new link, this calls DoNoLink(Node, GraphObject, Node, GraphObject). In any case this stops the tool.

This method also raises the "ChangingSelection" and "ChangedSelection" diagram events. Changes are performed in a "Linking" transaction, but the "ChangedSelection" event is raised outside the transaction.

This method may be overridden, but we recommend that you call this base method. It is usually easier to override InsertLink(Node, GraphObject, Node, GraphObject) or just set ArchetypeLinkData. It is also common to implement a "LinkDrawn" DiagramEvent listener on the Diagram.

This method is called upon a mouse up when no new link is drawn, either because no valid TargetPort was found or because InsertLink(Node, GraphObject, Node, GraphObject) returned null.

Declaration
public virtual void DoNoLink(Node fromnode, GraphObject fromport, Node tonode, GraphObject toport)
Parameters
Type Name Description
Node fromnode
GraphObject fromport

the from-port, or null to use the node itself

Node tonode
GraphObject toport

the to-port, or null to use the node itself

This method may be overridden. By default this method does nothing. If you want to successfully perform any side-effects, you will need to set TransactionResult to a string; otherwise this tool's transaction will be rolled-back. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

FindLinkablePort()

Return the GraphObject at the mouse-down point, if it is part of a node and if it is valid to link with it.

Declaration
public virtual GraphObject FindLinkablePort()
Returns
Type Description
GraphObject

If the Direction is Either or ForwardsOnly, this checks the element and its parent Node by calling IsValidFrom(Node, GraphObject). If the Direction is Either or BackwardsOnly, this checks the element and its parent Node by calling IsValidTo(Node, GraphObject). In either case finding a matching port will return that port and set IsForwards appropriately. Otherwise this will return null.

Remarks

This starts looking for a port at the StartElement if it is non-null, otherwise it looks for an element at the FirstInput's DocumentPoint. If it finds no element, or if the element it finds is not in a node, this method returns null. If it does find a port, it should set IsForwards to declare which direction the new link is being drawn.

This method may be overridden, but we recommend that you call this base method. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

Make a copy of the ArchetypeLinkData, set its node and port properties, and add it to the GraphLinksModel<TNodeData, TNodeKey, TSharedData, TLinkData, TLinkKey, TPort>. If the model is a TreeModel<TNodeData, TNodeKey, TSharedData>, set the parent key of the child's node data object.

Declaration
public virtual Link InsertLink(Node fromnode, GraphObject fromport, Node tonode, GraphObject toport)
Parameters
Type Name Description
Node fromnode
GraphObject fromport

the from-port, or null to use the node itself

Node tonode
GraphObject toport

the to-port, or null to use the node itself

Returns
Type Description
Link

the newly created Link, or null if it failed.

For GraphLinksModels, if ArchetypeLabelNodeData is non-null, this method also adds that node data as an initial label node for the new link data.

For TreeModels, if IsTreePathToChildren is false, the roles of the fromnode and tonode arguments are exchanged.

This method may be overridden, but we recommend that you call this base method. Usually though it is easiest to just set ArchetypeLinkData to control what kind of link is created. Please read the Introduction page on Extensions for how to override methods and how to call this base method.