GoJS® Diagramming Components
version 1.6.19 for JavaScript/HTML
by Northwoods Software®

## Class DraggingTool

Extends Tool. The DraggingTool is used to move or copy selected parts with the mouse. This sets the Part.location property; you may want to save the location to the model by using a TwoWay Binding on the "location" property in your Parts/Nodes/Groups templates.

Dragging the selection moves parts for which Part.canMove is true. If the user holds down the Control key (Option key on Mac), this tool will make a copy of the parts being dragged, for those parts for which Part.canCopy is true.

When the drag starts it calls computeEffectiveCollection to find the actual collection of Parts to be dragged. Normally this collection includes not only the Diagram.selection, but also parts that belong to those selected parts, such as members of groups. If dragsTree is true, the effective collection also includes all of the nodes and links that constitute the subtree starting from selected nodes. The result of computeEffectiveCollection is not a Set but a Map which remembers the original Part.location for all of the dragged parts. This map is saved as the value of draggedParts.

During the drag if the user holds down the Control/Option key this tool makes a copy of the draggedParts and proceeds to drag it around. (It only copies the Diagram.selection, not the whole effective collection, if copiesEffectiveCollection is false.) The collection of copied parts is held by copiedParts. It too is a Map remembering the original locations of the parts. copiedParts will be null when this tool is moving (not copying) at the moment.

Each Part's movement is limited by the computeMove method. By default it limits the Part.location to be within the bounds given by Part.minLocation and Part.maxLocation. (Those default to minus Infinity to plus Infinity.) As a further convenience, the value of NaN in minLocation and maxLocation cause computeMove to use the part's current location. So, for example, an easy way to declare that the user may only drag a node horizontally is to just set:

    $(go.Node,
      . . .
      { minLocation: new go.Point(-Infinity, NaN), maxLocation: new go.Point(Infinity, NaN) },
      . . .
    )

If you set isGridSnapEnabled to true, dragged or copied parts will be snapped to points on a grid. The snapping occurs continuously during a drag unless you set isGridSnapRealtime to false. Normally the grid points come from the Diagram.grid, even if that grid is not GraphObject.visible. However you can override those grid's properties for the snapping grid cell size and offset by setting the properties here: gridSnapCellSize and gridSnapOrigin. This computes the point to snap to for each dragged part. The resulting point is used as the new Part.location.

For the most general control over where a part may be dragged, either set the Part.dragComputation property or override computeMove. For the common case of wanting to keep member nodes within the Group that they are members of, you can do something like:

     // this is a Part.dragComputation function for limiting where a Node may be dragged
     function stayInGroup(part, pt, gridpt) {
       // don't constrain top-level nodes
       var grp = part.containingGroup;
       if (grp === null) return pt;
       // try to stay within the background Shape of the Group
       var back = grp.findObject("SHAPE");
       if (back === null) return pt;
       // allow dragging a Node out of a Group if the Shift key is down
       //if (part.diagram.lastInput.shift) return pt;
       var p1 = back.getDocumentPoint(go.Spot.TopLeft);
       var p2 = back.getDocumentPoint(go.Spot.BottomRight);
       var b = part.actualBounds;
       var loc = part.location;
       // find the padding inside the group's placeholder that is around the member parts
       var m = (grp.placeholder !== null ? grp.placeholder.padding : new go.Margin(0));
       // now limit the location appropriately
       var x = Math.max(p1.x + m.left, Math.min(pt.x, p2.x - m.right - b.width - 1)) + (loc.x-b.x);
       var y = Math.max(p1.y + m.top, Math.min(pt.y, p2.y - m.bottom - b.height - 1)) + (loc.y-b.y);
       return new go.Point(x, y);
     }

Note that this expects there to be a "SHAPE" object within the Group's visual tree that delimits where the part may be dragged within the group. This also expects that Group.computesBoundsIncludingLinks is false. Then in your node template(s), just set:

    $(go.Node,
      . . .,
      { dragComputation: stayInGroup },
      . . .
    )

This tool does not utilize any Adornments or tool handles. If the drag is successful, it raises the "SelectionMoved" or "SelectionCopied" DiagramEvent and produces a "Move" or a "Copy" transaction.

If you want to programmatically start a new user mouse-gesture to drag a particular existing node, you can set the currentPart property and then start and activate the tool.

      var tool = myDiagram.toolManager.draggingTool;
      tool.currentPart = ...;
      myDiagram.currentTool = tool;
      tool.doActivate();

## Constructor Summary Details

Name | Description
--- | ---
DraggingTool() | You do not normally need to create an instance of this tool because one already exists as the ToolManager.draggingTool, which you can modify.More... The Tool.name of this tool is "Dragging".

## Properties Summary Details

Name, Value Type | Description
--- | ---
copiedParts {Map.<Part,DraggingInfo>} | Gets the collection of Parts that this tool has copied.More... The value is a Map mapping Parts to DraggingInfo Objects that have a "point" property remembering the original location of that Part. The value is null when moving instead of copying. draggedParts provides the map of Parts that are being moved and from which this collection was copied.

copiesEffectiveCollection
{boolean}

Gets or sets whether for a copying operation the extended selection is copied or only the selected parts.More... The default value is true. Setting this property does not raise any events.

The CommandHandler.copiesConnectedLinks property serves a similar role for the CommandHandler.copySelection command, when the user types control-C to copy the currently selected parts.

currentPart {Part} | Gets the Part found at the mouse point.
delay {number} | On touch gestures only, this property gets or sets the time in milliseconds for which the mouse must be stationary before this tool can be started.More... The default value is 100 milliseconds. Setting this property does not raise any events.
draggedParts {Map.<Part,DraggingInfo>} | Gets the collection of Parts being moved.More... The value is a Map mapping Parts to DraggingInfo Objects that have a "point" property remembering the original location of that Part. copiedParts provides the map of Parts that have been copied during a copying operation, if any.

dragsLink
{boolean} 1.3

Gets or sets whether the user can drag a single Link, disconnecting it from its connected nodes and possibly connecting it to valid ports when the link is dropped.More...

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

In order to avoid too many cases of having both ends of a dragged Link connect to the same node (if allowed), it is commonplace to decrease the LinkingBaseTool.portGravity to a smaller value such as 10 or 20.

dragsTree
{boolean}

Gets or sets whether moving or copying a node also includes all of the node's tree children and their descendants, along with the links to those additional nodes.More... The default value is false. Setting this property does not raise any events.

The CommandHandler.copiesTree property serves a similar role for the CommandHandler.copySelection command, when the user types control-C to copy the currently selected parts.

gridSnapCellSize {Size} | Gets or sets the size of the grid cell used when snapping during a drag if the value of isGridSnapEnabled is true.More... By default this property is the Size(NaN, NaN), which causes this tool to use the Panel.gridCellSize value of the Diagram.grid. Setting this property does not raise any events.
gridSnapCellSpot {Spot} | Gets or sets the Spot that specifies what point in the grid cell dragged parts snap to, if the value of isGridSnapEnabled is true.More... By default this property is Spot.TopLeft: node locations will snap exactly to the grid point. Setting this property does not raise any events.
gridSnapOrigin {Point} | Gets or sets the snapping grid's origin point, in document coordinates, if the value of isGridSnapEnabled is true.More... By default this property is the Point(NaN, NaN), which causes this tool to use the Panel.gridOrigin value from the Diagram.grid. Setting this property does not raise any events.
isComplexRoutingRealtime {boolean} 1.4 | Gets or sets whether link routing takes some short-cuts during dragging.More... When false Links whose routing is AvoidsNodes are not routed to avoid Nodes, in order to improve dragging performance. The default value is true.
isCopyEnabled {boolean} 1.4 | Gets or sets whether for any internal copying operation is permitted by control-drag-and-drop.More... This property affects the behavior of mayCopy, but does not affect whether copied objects may be dropped into this diagram from a different diagram. The default value is true. Setting this property does not raise any events.
isGridSnapEnabled {boolean} | Gets or sets whether the DraggingTool snaps objects to grid points.More... Whether the snapping movement of the dragged parts occurs during the drag or only upon a drop is determined by the value of isGridSnapRealtime. By default this property is false. Setting this property does not raise any events.
isGridSnapRealtime {boolean} 1.1 | Gets or sets whether the DraggingTool snaps objects to grid points during the drag.More... This property is ignored unless isGridSnapEnabled is true. By default this property is true; when false parts are only snapped to grid locations upon the drop (i.e. mouse-up). Setting this property does not raise any events.
startPoint {Point} | Gets or sets the mouse point from which parts start to move.More... The value is a Point in document coordinates. This property is normally set to the diagram's mouse-down point in doActivate, but may be set to a different point if parts are being copied from a different control. Setting this property does not raise any events.

Properties borrowed from class Tool:
  diagram, isActive, isEnabled, name, transactionResult

## Method Summary Details

Name, Return Type | Description
--- | ---

canStart()
{boolean}

This tool can run if the diagram allows selection and moves/copies/dragging-out, if the mouse has moved far enough away to be a drag and not a click, and if findDraggablePart has found a selectable part at the mouse-down point.More...

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

Returns:
{boolean}

computeEffectiveCollection(parts)
{Map.<Part,DraggingInfo>}

Find the actual collection of nodes and links to be moved or copied, given an initial collection.More... This includes links that connected at both ends to nodes being moved or copied, members of Groups, and if dragsTree is true, this includes nodes and links that are "tree" descendants from selected nodes.

Note that this does not return a simple collection of Parts, but a Map associating a chosen Part with an Object holding its original location Points as the value of the "point" property.

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

Parameters:
{Iterable.<Part>} parts
  A Set or List of Parts.

Returns:
{Map.<Part,DraggingInfo>} a Map mapping Parts to DraggingInfo Objects that have a "point" property remembering the original location of that Part.

computeMove(n, newloc, draggedparts, result)
{Point} 1.1

This method computes the new location for a Node or simple Part, given a new desired location and an optional Map of dragged parts, taking any grid-snapping into consideration, any Part.dragComputation function, and any Part.minLocation and Part.maxLocation.More...

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

Parameters:
{Part} n
  the Node or simple Part that is being moved
{Point} newloc
  the proposed new location
{Map.<Part,DraggingInfo>=} draggedparts
  an optional Map mapping Parts to DraggingInfo Objects that have a "point" property remembering the original location of that Part.
{Point=} result
  an optional Point that is modified and returned

Returns:
{Point} the possibly grid-snapped computed Point that is within the minimum and maximum permitted locations

doActivate() | Start the dragging operation.More... This calls computeEffectiveCollection and saves the result as draggedParts. This starts a "Drag" transaction. Depending on what happens, the transaction may be finished as a "Move" or a "Copy" transaction, or it may be rolled-back if the tool is cancelled.
doCancel() | Abort any dragging operation.
doDeactivate() | Stop the dragging operation by stopping the transaction and cleaning up any temporary state.

doDragOver(pt, obj)
1.1

Perform any additional side-effects during a drag, whether an internal move or copy or an external drag, that may affect the existing non-moved object(s).More...

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

Parameters:
{Point} pt
  a Point in document coordinates.
{GraphObject} obj
  the GraphObject at the point, excluding what is being dragged or temporary objects; the argument may be null if the drag is occurring in the background of the diagram. Use GraphObject.part to get the Node or Part at the root of the visual tree of the stationary object.

doDropOnto(pt, obj)
1.1

Perform any additional side-effects after a drop, whether an internal move or copy or an external drop, that may affect the existing non-moved object(s).More...

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

Parameters:
{Point} pt
  a Point in document coordinates.
{GraphObject} obj
  the GraphObject where the drop occurred, excluding what was dropped or temporary objects; the argument may be null if the drop occurred in the background of the diagram. Use GraphObject.part to get the Node or Part at the root of the visual tree of the stationary object.

doKeyDown() | Handle switching between copying and moving modes as the Control/Option key is pressed or released.
doKeyUp() | Handle switching between copying and moving modes as the Control/Option key is pressed or released.
doMouseMove() | Move the draggedParts (or if copying, the copiedParts) to follow the current mouse point.More... This calls doDragOver for any side-effects on stationary parts.
doMouseUp() | On a mouse-up finish moving or copying the effective selection.More... This calls doDropOnto for any side-effects on stationary parts. This also updates the diagram's bounds, raises a "SelectionCopied" or "SelectionMoved" DiagramEvent, and stops this tool.

findDraggablePart()
{Part}

Return the selectable and movable/copyable Part at the mouse-down point.More... This is called by canStart to decide if this tool is ready to run.

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

Returns:
{Part}

mayCopy()
{boolean}

This predicate is true when the diagram allows objects to be copied and inserted, and some object in the selection is copyable, and the user is holding down the Control key (Option key on Mac).More...

This method may be overridden, although in most cases it is easiest to set Part.copyable. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

Returns:
{boolean}

mayMove()
{boolean}

This predicate is true when the diagram allows objects to be moved, and some object in the selection is movable.More...

This method may be overridden, although in most cases it is easiest to set Part.movable. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

Returns:
{boolean}

moveParts(parts, offset, check)
1.1

Move a collection Map of Parts by a given offset.More...

If check is true this respects the Part.canMove predicate for Nodes or simple Parts when this is the Diagram.currentTool. It also respects isGridSnapEnabled in order to try to automatically snap part locations to a grid. And it also uses the Part.dragComputation function, if any, to determine the new location for each part.

The first argument is a Map as produced by computeEffectiveCollection, not a List or Set or Iterator of Parts. Call Diagram.moveParts if you want to move a simple collection of Parts without having to create the argument Map.

Parameters:
{Map.<Part,DraggingInfo>} parts
  a Map mapping Parts to DraggingInfo Objects that have a "point" property remembering the original location of that Part.
{Point} offset
{boolean} check
  Whether to check Part.canMove on each part.

standardMouseSelect() | This override prevents the Control modifier unselecting an already selected part.More... This also remembers the selectable currentPart at the current mouse point. This method may be overridden. Please read the Introduction page on Extensions for how to override methods and how to call this base method.

Methods borrowed from class Tool:
  cancelWaitAfter, canStartMultiTouch, doMouseDown, doMouseWheel, doStart, doStop, doWaitAfter, findToolHandleAt, isBeyondDragSize, standardMouseClick, standardMouseOver, standardMouseWheel, standardPinchZoomMove, standardPinchZoomStart, standardWaitAfter, startTransaction, stopTool, stopTransaction, updateAdornments