1 | <!DOCTYPE html>
|
2 | <html lang="en">
|
3 | <head>
|
4 | <meta charset="utf-8"/>
|
5 | <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/>
|
6 |
|
7 | <link rel="stylesheet" href="../assets/css/style.css"/>
|
8 | <title> GoJS Tools -- Northwoods Software </title>
|
9 | <link rel="stylesheet" href="../assets/css/prism.css" />
|
10 | </head>
|
11 | <script>
|
12 |
|
13 | window.diagrams = [];
|
14 | window.goCode = function(pre, w, h, parentid, animation) {
|
15 | window.diagrams.push([pre, w, h, parentid, animation]);
|
16 | }
|
17 | </script>
|
18 | <body>
|
19 | <nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary">
|
20 | <div class="w-full container max-w-screen-lg mx-auto flex flex-wrap sm:flex-nowrap items-center justify-between mt-0 py-2">
|
21 | <div class="md:pl-4">
|
22 | <a class="text-white hover:text-white no-underline hover:no-underline
|
23 | font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../">
|
24 | <h1 class="mb-0 p-1 ">GoJS</h1>
|
25 | </a>
|
26 | </div>
|
27 | <button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation">
|
28 | <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
|
29 | <path id="topnavOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
|
30 | <path id="topnavClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
|
31 | </svg>
|
32 | </button>
|
33 | <div id="topnavList" class="hidden sm:block items-center w-auto mt-0 text-white p-0 z-20">
|
34 | <ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0">
|
35 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li>
|
36 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li>
|
37 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li>
|
38 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li>
|
39 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li>
|
40 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li>
|
41 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li>
|
42 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html"
|
43 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li>
|
44 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html"
|
45 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li>
|
46 | </ul>
|
47 | </div>
|
48 | </div>
|
49 | <hr class="border-b border-gray-600 opacity-50 my-0 py-0" />
|
50 | </nav>
|
51 |
|
52 | <div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto">
|
53 |
|
54 | <div id="navSide" class="flex flex-col w-full md:w-40 lg:w-48 text-gray-700 bg-white flex-shrink-0">
|
55 | <div class="flex-shrink-0 px-8 py-4">
|
56 | <button id="navButton" class="rounded-lg md:hidden focus:outline-none focus:ring" aria-label="Navigation">
|
57 | <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
|
58 | <path id="navOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
|
59 | <path id="navClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
|
60 | </svg>
|
61 | </button>
|
62 | </div>
|
63 | <nav id="navList" class="min-h-screen hidden md:block sidebar-nav flex-grow px-1 lg:px-4 pb-4 md:pb-0 md:overflow-y-auto break-words">
|
64 | <a href="index.html">Basics</a>
|
65 | <a href="buildingObjects.html">Building Parts</a>
|
66 | <a href="usingModels.html">Using Models</a>
|
67 | <a href="dataBinding.html">Data Binding</a>
|
68 | <a href="react.html">GoJS with React</a>
|
69 | <a href="angular.html">GoJS with Angular</a>
|
70 | <a href="textBlocks.html">TextBlocks</a>
|
71 | <a href="shapes.html">Shapes</a>
|
72 | <a href="pictures.html">Pictures</a>
|
73 | <a href="panels.html">Panels</a>
|
74 | <a href="tablePanels.html">Table Panels</a>
|
75 | <a href="brush.html">Brushes</a>
|
76 | <a href="sizing.html">Sizing Objects</a>
|
77 | <a href="itemArrays.html">Item Arrays</a>
|
78 | <a href="changedEvents.html">Changed Events</a>
|
79 | <a href="transactions.html">Transactions</a>
|
80 | <a href="viewport.html">Coordinates</a>
|
81 | <a href="initialView.html">Initial View</a>
|
82 | <a href="collections.html">Collections</a>
|
83 | <a href="links.html">Links</a>
|
84 | <a href="linkLabels.html">Link Labels</a>
|
85 | <a href="connectionPoints.html">Link Points</a>
|
86 | <a href="ports.html">Ports</a>
|
87 | <a href="nodes.html">Nodes</a>
|
88 | <a href="debugging.html">Debugging</a>
|
89 | <a href="layouts.html">Layouts</a>
|
90 | <a href="trees.html">Trees</a>
|
91 | <a href="subtrees.html">SubTrees</a>
|
92 | <a href="groups.html">Groups</a>
|
93 | <a href="subgraphs.html">SubGraphs</a>
|
94 | <a href="sizedGroups.html">Sized Groups</a>
|
95 | <a href="selection.html">Selection</a>
|
96 | <a href="highlighting.html">Highlighting</a>
|
97 | <a href="animation.html">Animation</a>
|
98 | <a href="toolTips.html">ToolTips</a>
|
99 | <a href="contextmenus.html">Context Menus</a>
|
100 | <a href="events.html">Diagram Events</a>
|
101 | <a href="tools.html">Tools</a>
|
102 | <a href="commands.html">Commands</a>
|
103 | <a href="permissions.html">Permissions</a>
|
104 | <a href="validation.html">Validation</a>
|
105 | <a href="HTMLInteraction.html">HTML Interaction</a>
|
106 | <a href="layers.html">Layers & Z-ordering</a>
|
107 | <a href="palette.html">Palette</a>
|
108 | <a href="overview.html">Overview</a>
|
109 | <a href="resizing.html">Resizing Diagrams</a>
|
110 | <a href="replacingDeleting.html">Replacing and Deleting</a>
|
111 | <a href="buttons.html">Buttons</a>
|
112 | <a href="templateMaps.html">Template Maps</a>
|
113 | <a href="legends.html">Legends and Titles</a>
|
114 | <a href="extensions.html">Extensions</a>
|
115 | <a href="geometry.html">Geometry Strings</a>
|
116 | <a href="grids.html">Grid Patterns</a>
|
117 | <a href="graduatedPanels.html">Graduated Panels</a>
|
118 | <a href="makingImages.html">Diagram Images</a>
|
119 | <a href="makingSVG.html">Diagram SVG</a>
|
120 | <a href="printing.html">Printing</a>
|
121 | <a href="serverSideImages.html">Server-side Images</a>
|
122 | <a href="nodeScript.html">GoJS in Node.js</a>
|
123 | <a href="testing.html">Testing</a>
|
124 | <a href="storage.html">Storage</a>
|
125 | <a href="performance.html">Performance</a>
|
126 | <a href="source.html">Building from Source</a>
|
127 | <a href="platforms.html">Platforms</a>
|
128 | <a href="deployment.html">Deployment</a>
|
129 | </nav>
|
130 | </div>
|
131 | <div class="pt-4 px-2 md:px-0 lg:px-4 pb-16 w-full overflow-hidden">
|
132 |
|
133 | <h1>Tools</h1>
|
134 | <p>
|
135 | <a>Tool</a>s handle all of the input events.
|
136 | There are many kinds of predefined Tool classes that implement all of the common operations that users do.
|
137 | </p>
|
138 | <p>
|
139 | For flexibility and simplicity, all input events are canonicalized as <a>InputEvent</a>s and
|
140 | redirected by the diagram to go to the <a>Diagram.currentTool</a>.
|
141 | By default the Diagram.currentTool is an instance of <a>ToolManager</a> held as the <a>Diagram.toolManager</a>.
|
142 | The ToolManager implements support for all mode-less tools.
|
143 | The ToolManager is responsible for finding another tool that is ready to run and then making it the new current tool.
|
144 | This causes the new tool to process all of the input events (mouse, keyboard, and touch) until the tool decides that it is finished,
|
145 | at which time the diagram's current tool reverts back to the <a>Diagram.defaultTool</a>, which is normally the ToolManager, again.
|
146 | </p>
|
147 | <p>
|
148 | Although the terminology includes the word "mouse", often that refers to both mouse events and touch events.
|
149 | </p>
|
150 | <p>
|
151 | See samples that make use of <a>Tool</a>s in the <a href="../samples/index.html#tools">samples index</a>.
|
152 | </p>
|
153 |
|
154 | <h2 id="PredefinedTools">Predefined Tools</h2>
|
155 | <p>
|
156 | Each <a>Diagram</a> has an instance of most of the tool classes, all managed by the diagram's <a>ToolManager</a>.
|
157 | If you want to change the interactive behavior, in many common cases you may be able to do so by setting properties
|
158 | on the <a>Diagram</a>, on your <a>Part</a>s, or on individual <a>GraphObject</a>s.
|
159 | But more generally you may need to modify one or more of the tools, which are accessible as properties of the <a>Diagram.toolManager</a>.
|
160 | </p>
|
161 |
|
162 | <p>
|
163 | Some tools want to run when a mouse-down occurs. These tools include:
|
164 | </p>
|
165 | <ul>
|
166 | <li><a>ToolManager.actionTool</a>, an <a>ActionTool</a>, for allowing "buttons" and other <a>GraphObject</a>s to grab events from the regular tools</li>
|
167 | <li><a>ToolManager.relinkingTool</a>, a <a>RelinkingTool</a>, for reconnecting an existing <a>Link</a></li>
|
168 | <li><a>ToolManager.linkReshapingTool</a>, a <a>LinkReshapingTool</a>, for changing the route of a <a>Link</a></li>
|
169 | <li><a>ToolManager.resizingTool</a>, a <a>ResizingTool</a>, for changing the <a>GraphObject.desiredSize</a> of a <a>Part</a> or an object within a <a>Part</a></li>
|
170 | <li><a>ToolManager.rotatingTool</a>, a <a>RotatingTool</a>, for changing the <a>GraphObject.angle</a> of a <a>Part</a> or an object within a <a>Part</a></li>
|
171 | </ul>
|
172 |
|
173 | <p>
|
174 | Some tools want to run when a mouse-move occurs after a mouse-down. These tools include:
|
175 | </p>
|
176 | <ul>
|
177 | <li><a>ToolManager.linkingTool</a>, a <a>LinkingTool</a>, for drawing a new <a>Link</a></li>
|
178 | <li><a>ToolManager.draggingTool</a>, a <a>DraggingTool</a>, for moving or copying selected <a>Part</a>s</li>
|
179 | <li><a>ToolManager.dragSelectingTool</a>, a <a>DragSelectingTool</a>, for rubber-band selection of some <a>Part</a>s within a rectangular area</li>
|
180 | <li><a>ToolManager.panningTool</a>, a <a>PanningTool</a>, for panning/scrolling the diagram</li>
|
181 | </ul>
|
182 |
|
183 | <p>
|
184 | Some tools only want to run upon a mouse-up event after a mouse-down. These tools include:
|
185 | </p>
|
186 | <ul>
|
187 | <li><a>ToolManager.contextMenuTool</a>, a <a>ContextMenuTool</a>, for showing a context menu for a <a>GraphObject</a></li>
|
188 | <li><a>ToolManager.textEditingTool</a>, a <a>TextEditingTool</a>, for in-place editing of <a>TextBlock</a>s in selected <a>Part</a>s</li>
|
189 | <li><a>ToolManager.clickCreatingTool</a>, a <a>ClickCreatingTool</a>, for inserting a new <a>Part</a> when the user clicked</li>
|
190 | <li><a>ToolManager.clickSelectingTool</a>, a <a>ClickSelectingTool</a>, for selecting or de-selecting a <a>Part</a></li>
|
191 | </ul>
|
192 |
|
193 | <p>
|
194 | To change the behavior of a tool, you may be able to set properties on the tool, on the <a>Diagram</a>, on a particular <a>Part</a>,
|
195 | or on a particular <a>GraphObject</a>.
|
196 | </p>
|
197 | <ul>
|
198 | <li>For example, to disable the rubber-band selection tool (<a>DragSelectingTool</a>), set
|
199 | <code>diagram.toolManager.dragSelectingTool.isEnabled = false;</code>.</li>
|
200 | <li>You can change the appearance of a selected Part (actually its selection Adornment) by setting <a>Part.selectionAdornmentTemplate</a>.
|
201 | (See <a href="selection.html">Selection</a> for more discussion.)</li>
|
202 | <li>You can enable users to draw new links interactively (<a>LinkingTool</a>) by
|
203 | setting <a>GraphObject.fromLinkable</a> and <a>GraphObject.toLinkable</a> on the port objects of your nodes.</li>
|
204 | <li>You can disable the movement of a Part (<a>DraggingTool</a>), including Nodes and Groups, by setting <a>Part.movable</a> to false.</li>
|
205 | <li>You can limit the movement of a Part by setting <a>Part.minLocation</a> and/or <a>Part.maxLocation</a>.
|
206 | For more general limitations, set <a>Part.dragComputation</a> to a function that computes the desired new location.</li>
|
207 | <li>You can disable resizing any part (<a>ResizingTool</a>) by setting <a>Diagram.allowResize</a> to false.</li>
|
208 | <li>Tooltips, implemented by the <a>ToolManager</a>, are discussed in <a href="toolTips.html">ToolTips</a>.</li>
|
209 | <li>Context menus, implemented by the <a>ContextMenuTool</a>, are discussed in <a href="contextMenus.html">Context Menus</a>.</li>
|
210 | </ul>
|
211 | <p>
|
212 | More detail is available in the section about <a href="permissions.html">Permissions</a>.
|
213 | </p>
|
214 | <p>
|
215 | Some commonly set properties include:
|
216 | </p>
|
217 | <ul>
|
218 | <li>Enable inserting parts via double-clicking by the <a>ClickCreatingTool</a> by setting <a>ClickCreatingTool.archetypeNodeData</a> to a node data object.</li>
|
219 | <li>Control what parts become selected by <a>DragSelectingTool</a> by setting <a>DragSelectingTool.isPartialInclusion</a>.</li>
|
220 | <li>Customize the link data that is copied when a new link is drawn by <a>LinkingTool</a> by setting <a>LinkingTool.archetypeLinkData</a>.</li>
|
221 | <li>Limit how parts are resized by the <a>ResizingTool</a> by setting <a>ResizingTool.cellSize</a>,
|
222 | <a>ResizingTool.maxSize</a>, or <a>ResizingTool.minSize</a>.</li>
|
223 | <li>Limit how parts are rotated by the <a>RotatingTool</a> by setting <a>RotatingTool.snapAngleEpsilon</a> or
|
224 | <a>RotatingTool.snapAngleMultiple</a>.</li>
|
225 | </ul>
|
226 | <p>
|
227 | Remember that all of the individual tools are available via the <a>Diagram.toolManager</a>.
|
228 | For example, to enable the <a>ClickCreatingTool</a>:
|
229 | </p>
|
230 | <pre class="lang-js"><code>
|
231 | myDiagram.toolManager.clickCreatingTool.archetypeNodeData =
|
232 | { key: "Node", text: "some description", color: "green" };
|
233 | </code></pre>
|
234 | <p>
|
235 | You can also set tool properties when using <a>GraphObject,make</a> to define your <a>Diagram</a>:
|
236 | </p>
|
237 | <pre class="lang-js"><code>
|
238 | var diagram =
|
239 | $(go.Diagram, "myDiagramDiv",
|
240 | {
|
241 | allowCopy: false,
|
242 | "grid.visible": true,
|
243 | "grid.gridCellSize": new go.Size(30, 20),
|
244 | "clickCreatingTool.archetypeNodeData": // a node data JavaScript object
|
245 | { key: "Node", text: "some description", color: "green" },
|
246 | "dragSelectingTool.box": // an unbound Part
|
247 | $(go.Part, { layerName: "Tool" },
|
248 | $(go.Shape, { name: "SHAPE", fill: null, stroke: "blue", strokeWidth: 3 }) ),
|
249 | "draggingTool.isGridSnapEnabled": true,
|
250 | "linkReshapingTool.handleArchetype": // a GraphObject that is copied for each handle
|
251 | $(go.Shape, { width: 10, height: 10, fill: "yellow" }),
|
252 | "resizingTool.isGridSnapEnabled": true,
|
253 | "rotatingTool.snapAngleMultiple": 90,
|
254 | "rotatingTool.snapAngleEpsilon": 45
|
255 | }
|
256 | );
|
257 | </code></pre>
|
258 | <p>
|
259 | At this time the syntax for setting properties on predefined subobjects only works for the <a>Diagram</a> class.
|
260 | </p>
|
261 |
|
262 | <h2 id="ToolLifecycle">The Tool Lifecycle</h2>
|
263 | <p>While each prebuilt tool in GoJS is used for a different purpose, all Tools are guaranteed to share some functions and properties.
|
264 | All tools share a general "lifecycle" -- that is, the order in which these common functions are called. One can think of this
|
265 | cycle as "starting" when the ToolManager is alerted of some input event and begins searching through the pertinent list of tools (i.e.,
|
266 | if the mouse-down event is registered, ToolManager starts searching its <a>ToolManager.mouseDownTools</a> list). Below is a diagram
|
267 | representing the general lifecycle of a tool.
|
268 | <pre class="lang-js" id="toolLifecycle" style="display: none"><code>
|
269 | diagram.nodeTemplate =
|
270 | $(go.Node, "Auto", { locationSpot: go.Spot.Center },
|
271 | new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
|
272 | $(go.Shape, "RoundedRectangle", { fill: "lightgreen", stroke: "lightgray" },
|
273 | new go.Binding("fill", "color")),
|
274 | $(go.TextBlock,
|
275 | {
|
276 | margin: 8,
|
277 | wrap: go.TextBlock.WrapFit,
|
278 | width: 170,
|
279 | font: "bold 10pt sans-serif",
|
280 | textAlign: "center"
|
281 | },
|
282 | new go.Binding("text"))
|
283 | );
|
284 |
|
285 | diagram.linkTemplate =
|
286 | $(go.Link,
|
287 | new go.Binding("curve"),
|
288 | $(go.Shape),
|
289 | $(go.Shape, // the arrowhead
|
290 | { toArrow: "OpenTriangle", fill: null }),
|
291 | $(go.TextBlock, { margin: 1, segmentOffset: new go.Point(0,0) },
|
292 | new go.Binding("text"),
|
293 | new go.Binding("segmentOffset"),
|
294 | new go.Binding("segmentOrientation"))
|
295 | );
|
296 |
|
297 | diagram.model =
|
298 | $(go.GraphLinksModel,
|
299 | {
|
300 | nodeDataArray:
|
301 | [
|
302 | { key: 1, text: "ToolManager receives mouse event and searches a tool list such as mouseDownTools", loc: "50 0" },
|
303 | { key: 2, text: "tool.canStart()", loc: "50 100", color: "lightyellow" },
|
304 | { key: 3, text: "toolManager.currentTool = the chosen tool", loc: "50 200" },
|
305 | { key: 4, text: "tool.doStart()", loc: "50 275", color: "lightyellow" },
|
306 | { key: 5, text: "tool.doActivate()", loc: "50 350", color: "lightyellow" },
|
307 | { key: 6, text: "isActive === true", loc: "50 425" },
|
308 | { key: 7, text: "tool.doMouseDown() or\ntool.doMouseMove() or\ntool.doMouseUp() or\ntool.doMouseWheel() or\ntool.doKeyDown() or\ntool.doKeyUp()",
|
309 | loc: "-200 500", color: "lightyellow" },
|
310 | { key: 8, text: "tool.doCancel()", loc: "250 500", color: "lightyellow" },
|
311 | { key: 9, text: "tool.stopTool()", loc: "50 575", color: "lightyellow" },
|
312 | { key: 10, text: "toolManager.currentTool = toolManager.defaultTool", loc: "50 650" },
|
313 | { key: 11, text: "tool.doDeactivate()", loc: "50 725", color: "lightyellow" },
|
314 | { key: 12, text: "tool.doStop()", loc: "50 800", color: "lightyellow" }
|
315 | ],
|
316 | linkDataArray:
|
317 | [
|
318 | { from: 1, to: 2, text: "on each tool call", segmentOffset: new go.Point(0,-50) },
|
319 | { from: 2, to: 3, text: "if it returns true", segmentOffset: new go.Point(0,-50) },
|
320 | { from: 3, to: 4 },
|
321 | { from: 4, to: 5 },
|
322 | { from: 5, to: 6 },
|
323 | { from: 6, to: 7, text: "Receives input", curve: go.Link.Bezier, segmentOrientation: go.Link.OrientOpposite, segmentOffset: new go.Point(0,10) },
|
324 | { from: 7, to: 6, text: "Input is not terminal", curve: go.Link.Bezier, segmentOrientation: go.Link.OrientAlong, segmentOffset: new go.Point(0,10) },
|
325 | { from: 7, to: 9, text: "Input is terminal", segmentOrientation: go.Link.OrientAlong, segmentOffset: new go.Point(0,10) },
|
326 | { from: 6, to: 8, text: "User cancels tool", segmentOrientation: go.Link.OrientAlong, segmentOffset: new go.Point(0,-10)},
|
327 | { from: 8, to: 9 },
|
328 | { from: 9, to: 10 },
|
329 | { from: 10, to: 11 },
|
330 | { from: 11, to: 12 },
|
331 | ]
|
332 | }
|
333 | );
|
334 | </code></pre>
|
335 | <script>goCode("toolLifecycle", 700, 900)</script>
|
336 | <p>
|
337 | For more information on how these specific functions work, see the <a>Tool</a> documentation.
|
338 | </p>
|
339 |
|
340 |
|
341 | <h2 id="ToolsAndAdornments">Tools and Adornments</h2>
|
342 | <p>
|
343 | <a>Adornment</a>s are used for more than indicating that a <a>Part</a> is selected.
|
344 | Each <a>Tool</a> that is in the <a>ToolManager.mouseDownTools</a> list
|
345 | (in other words, any mode-less tool that is started with a mouse-down or finger-down event)
|
346 | gets the opportunity to add its own Adornments for its own purposes when a Part is selected.
|
347 | </p>
|
348 |
|
349 | <h3 id="ResizingTool">ResizingTool</h3>
|
350 | <p>
|
351 | When a <a>Part</a> is resizable, the <a>ResizingTool</a> adds an <a>Adornment</a> containing eight
|
352 | resize handles, four at the corners and four at the middles of the sides.
|
353 | </p>
|
354 | <p>
|
355 | If you want to let the user resize the whole node, just set <a>Part.resizable</a> to true.
|
356 | In this case resizing will set the Node's <a>GraphObject.desiredSize</a>.
|
357 | </p>
|
358 | <pre class="lang-js" id="resizing"><code>
|
359 | diagram.add(
|
360 | $(go.Node, "Auto",
|
361 | { resizable: true },
|
362 | $(go.Shape, "RoundedRectangle", { fill: "orange" }),
|
363 | $(go.TextBlock, "Hello!", { margin: 5 })
|
364 | ));
|
365 | diagram.commandHandler.selectAll();
|
366 | </code></pre>
|
367 | <script>goCode("resizing", 600, 100)</script>
|
368 |
|
369 | <p>
|
370 | If you want the user to resize a particular object within the node,
|
371 | you need to name that object and assign <a>Part.resizeObjectName</a>.
|
372 | Resizing will set the <a>Part.resizeObject</a>'s <a>GraphObject.desiredSize</a>,
|
373 | in this case the Shape's desiredSize.
|
374 | </p>
|
375 | <pre class="lang-js" id="resizingObject"><code>
|
376 | diagram.add(
|
377 | $(go.Node, "Vertical",
|
378 | { resizable: true, resizeObjectName: "SHAPE", // resize the Shape, not the Node
|
379 | selectionObjectName: "SHAPE" },
|
380 | $(go.Shape, "RoundedRectangle",
|
381 | { name: "SHAPE", fill: "orange", width: 50, height: 30 }),
|
382 | $(go.TextBlock, "Hello!", { margin: 3 })
|
383 | ));
|
384 | diagram.commandHandler.selectAll();
|
385 | </code></pre>
|
386 | <script>goCode("resizingObject", 600, 100)</script>
|
387 |
|
388 | <p>
|
389 | You can limit the minimum and maximum size for the resized object by setting
|
390 | <a>GraphObject.maxSize</a> and <a>GraphObject.minSize</a>.
|
391 | Note that these GraphObject properties are set on the <a>Part.resizeObject</a>, not on the <a>Part</a> itself.
|
392 | </p>
|
393 | <pre class="lang-js" id="resizingMaxMin"><code>
|
394 | diagram.add(
|
395 | $(go.Node, "Vertical",
|
396 | { resizable: true, resizeObjectName: "SHAPE",
|
397 | selectionObjectName: "SHAPE" },
|
398 | $(go.Shape, "RoundedRectangle",
|
399 | { name: "SHAPE", fill: "orange", width: 50, height: 30,
|
400 | // limit size by setting or binding maxSize and/or minSize
|
401 | maxSize: new go.Size(100, 40), minSize: new go.Size(20, 20) }),
|
402 | $(go.TextBlock, "Hello!", { margin: 3 })
|
403 | ));
|
404 | diagram.commandHandler.selectAll();
|
405 | </code></pre>
|
406 | <script>goCode("resizingMaxMin", 600, 100)</script>
|
407 |
|
408 | <p>
|
409 | You can also cause resizing to be multiples of a given size by setting <a>Part.resizeCellSize</a>.
|
410 | </p>
|
411 | <pre class="lang-js" id="resizingCellSize"><code>
|
412 | diagram.add(
|
413 | $(go.Node, "Vertical",
|
414 | { resizable: true, resizeObjectName: "SHAPE",
|
415 | resizeCellSize: new go.Size(10, 10), // new size will be multiples of resizeCellSize
|
416 | selectionObjectName: "SHAPE" },
|
417 | $(go.Shape, "RoundedRectangle",
|
418 | { name: "SHAPE", fill: "orange", width: 50, height: 30,
|
419 | maxSize: new go.Size(100, 40), minSize: new go.Size(20, 20) }),
|
420 | $(go.TextBlock, "Hello!", { margin: 3 })
|
421 | ));
|
422 | diagram.commandHandler.selectAll();
|
423 | </code></pre>
|
424 | <script>goCode("resizingCellSize", 600, 100)</script>
|
425 |
|
426 | <p>
|
427 | When an object is resizable, it is commonplace to try to remember the new size by updating the model data, so that it can be saved and loaded later.
|
428 | This can be accomplished with a TwoWay <a>Binding</a> on the <a>GraphObject.desiredSize</a> property.
|
429 | But note that the binding needs to be on the actual GraphObject that is resized, not on the whole Node.
|
430 | In this case, because the <a>Part.resizeObjectName</a> is referring to a Shape, that means the binding needs to be on the Shape.
|
431 | </p>
|
432 | <pre class="lang-js" id="resizingObjectBinding"><code>
|
433 | diagram.add(
|
434 | $(go.Node, "Vertical",
|
435 | { resizable: true, resizeObjectName: "SHAPE",
|
436 | selectionObjectName: "SHAPE" },
|
437 | $(go.Shape, "RoundedRectangle",
|
438 | { name: "SHAPE", fill: "orange", width: 50, height: 30 },
|
439 | // TwoWay Binding of the desiredSize
|
440 | new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify)),
|
441 | $(go.TextBlock, "Hello!", { margin: 3 })
|
442 | ));
|
443 | diagram.commandHandler.selectAll();
|
444 | </code></pre>
|
445 | <script>goCode("resizingObjectBinding", 600, 100)</script>
|
446 |
|
447 | <p>
|
448 | You can customize the resize handles by setting <a>Part.resizeAdornmentTemplate</a>.
|
449 | For example, to allow the user to only change the width of a Shape in a Node,
|
450 | the <a>Adornment</a> should have only two resize handles: one at the left and one at the right.
|
451 | The Adornment is implemented as a Spot Panel that surrounds a <a>Placeholder</a>,
|
452 | representing the adorned Shape, with two rectangular blue Shapes, each representing a handle.
|
453 | There is also a TextBlock placed above the adorned shape showing the shape's current width.
|
454 | </p>
|
455 | <pre class="lang-js" id="resizingTemplate"><code>
|
456 | diagram.add(
|
457 | $(go.Node, "Vertical",
|
458 | { resizable: true, resizeObjectName: "SHAPE",
|
459 | resizeAdornmentTemplate: // specify what resize handles there are and how they look
|
460 | $(go.Adornment, "Spot",
|
461 | $(go.Placeholder), // takes size and position of adorned object
|
462 | $(go.Shape, "Circle", // left resize handle
|
463 | { alignment: go.Spot.Left, cursor: "col-resize",
|
464 | desiredSize: new go.Size(9, 9), fill: "lightblue", stroke: "dodgerblue" }),
|
465 | $(go.Shape, "Circle", // right resize handle
|
466 | { alignment: go.Spot.Right, cursor: "col-resize",
|
467 | desiredSize: new go.Size(9, 9), fill: "lightblue", stroke: "dodgerblue" }),
|
468 | $(go.TextBlock, // show the width as text
|
469 | { alignment: go.Spot.Top, alignmentFocus: new go.Spot(0.5, 1, 0, -2),
|
470 | stroke: "dodgerblue" },
|
471 | new go.Binding("text", "adornedObject",
|
472 | function(shp) { return shp.naturalBounds.width.toFixed(0); })
|
473 | .ofObject())
|
474 | ),
|
475 | selectionAdorned: false }, // don't show selection Adornment, a rectangle
|
476 | $(go.Shape, "RoundedRectangle",
|
477 | { name: "SHAPE", fill: "orange", width: 50, height: 30,
|
478 | maxSize: new go.Size(100, 40), minSize: new go.Size(20, 20) }),
|
479 | $(go.TextBlock, "Hello!", { margin: 3 })
|
480 | ));
|
481 | diagram.commandHandler.selectAll();
|
482 | </code></pre>
|
483 | <script>goCode("resizingTemplate", 600, 100)</script>
|
484 | <p>
|
485 | Note also that because <a>Part.selectionAdorned</a> is false, there is no blue rectangle default selection adornment.
|
486 | </p>
|
487 | <p>
|
488 | There are examples custom resizing tools defined in the samples and extensions directories:
|
489 | <a href="../extensions/FloorPlanEditor.html">Resize Multiple Tool (in Floor Plan Editor)</a>,
|
490 | <a href="../samples/swimLanes.html">Lane Resizing Tool (in Swim Lanes)</a>, and
|
491 | <a href="../samples/swimLanesVertical.html">Lane Resizing Tool (in Swim Lanes Vertical)</a>.
|
492 | </p>
|
493 |
|
494 | <h3 id="RotatingTool">RotatingTool</h3>
|
495 | <p>
|
496 | When a <a>Part</a> is rotatable, the <a>RotatingTool</a> adds an <a>Adornment</a> containing one
|
497 | rotate handle a short distance from the object at the object's angle.
|
498 | Since the default <a>GraphObject.angle</a> is zero, the rotate handle typically starts to the right of the object.
|
499 | </p>
|
500 | <p>
|
501 | If you want to let the user rotate the whole node, just set <a>Part.rotatable</a> to true.
|
502 | Rotating will set the Node's <a>GraphObject.angle</a>.
|
503 | </p>
|
504 | <pre class="lang-js" id="rotating"><code>
|
505 | diagram.add(
|
506 | $(go.Node, "Auto",
|
507 | { rotatable: true, locationSpot: go.Spot.Center },
|
508 | $(go.Shape, "RoundedRectangle", { fill: "orange" }),
|
509 | $(go.TextBlock, "Hello!", { margin: 5 })
|
510 | ));
|
511 | diagram.commandHandler.selectAll();
|
512 | </code></pre>
|
513 | <script>goCode("rotating", 600, 150)</script>
|
514 |
|
515 | <p>
|
516 | If you want the user to rotate a particular object within the node,
|
517 | you need to name that object and assign <a>Part.rotateObjectName</a>.
|
518 | Rotating will set the <a>Part.rotateObject</a>'s <a>GraphObject.angle</a>,
|
519 | in this case the Shape's angle.
|
520 | </p>
|
521 | <pre class="lang-js" id="rotatingObject"><code>
|
522 | diagram.add(
|
523 | $(go.Node, "Vertical",
|
524 | { rotatable: true, rotateObjectName: "SHAPE", // rotate the Shape, not the Node
|
525 | locationSpot: go.Spot.Center, locationObjectName: "SHAPE",
|
526 | selectionObjectName: "SHAPE" },
|
527 | $(go.Shape, "RoundedRectangle",
|
528 | { name: "SHAPE", fill: "orange", width: 50, height: 30 }),
|
529 | $(go.TextBlock, "Hello!", { margin: 3 })
|
530 | ));
|
531 | diagram.commandHandler.selectAll();
|
532 | </code></pre>
|
533 | <script>goCode("rotatingObject", 600, 150)</script>
|
534 |
|
535 | <p>
|
536 | When an object is rotatable, it is commonplace to try to remember the new angle by updating the model data, so that it can be saved and loaded later.
|
537 | This can be accomplished with a TwoWay <a>Binding</a> on the <a>GraphObject.angle</a> property.
|
538 | But note that the binding needs to be on the actual GraphObject that is rotated, not on the whole Node.
|
539 | In this case, because the <a>Part.rotateObjectName</a> is referring to a Shape, that means the binding needs to be on the Shape.
|
540 | </p>
|
541 | <pre class="lang-js" id="rotatingObjectBinding"><code>
|
542 | diagram.add(
|
543 | $(go.Node, "Vertical",
|
544 | { rotatable: true, rotateObjectName: "SHAPE",
|
545 | locationSpot: go.Spot.Center, locationObjectName: "SHAPE",
|
546 | selectionObjectName: "SHAPE" },
|
547 | $(go.Shape, "RoundedRectangle",
|
548 | { name: "SHAPE", fill: "orange", width: 50, height: 30 },
|
549 | new go.Binding("angle").makeTwoWay()), // TwoWay Binding of angle
|
550 | $(go.TextBlock, "Hello!", { margin: 3 })
|
551 | ));
|
552 | diagram.commandHandler.selectAll();
|
553 | </code></pre>
|
554 | <script>goCode("rotatingObjectBinding", 600, 150)</script>
|
555 |
|
556 | <p>
|
557 | Another common customization is to position the rotate handle above the object when it is not rotated,
|
558 | i.e. when its <a>GraphObject.angle</a> is zero.
|
559 | This is accomplished by setting <a>RotatingTool.handleAngle</a> to 270.
|
560 | </p>
|
561 | <pre class="lang-js" id="rotatingToolAngle"><code>
|
562 | diagram.add(
|
563 | $(go.Node, "Auto",
|
564 | { rotatable: true, locationSpot: go.Spot.Center },
|
565 | new go.Binding("angle").makeTwoWay(), // TwoWay Binding of Node.angle
|
566 | $(go.Shape, "RoundedRectangle", { fill: "orange" }),
|
567 | $(go.TextBlock, "Hello!", { margin: 5 })
|
568 | ));
|
569 | diagram.toolManager.rotatingTool.handleAngle = 270;
|
570 | diagram.commandHandler.selectAll();
|
571 | </code></pre>
|
572 | <script>goCode("rotatingToolAngle", 600, 150)</script>
|
573 |
|
574 | <p>
|
575 | You can customize the rotate handle by setting <a>Part.rotateAdornmentTemplate</a>.
|
576 | </p>
|
577 | <pre class="lang-js" id="rotatingTemplate"><code>
|
578 | diagram.add(
|
579 | $(go.Node, "Vertical",
|
580 | { rotatable: true, rotateObjectName: "SHAPE",
|
581 | locationSpot: go.Spot.Center, locationObjectName: "SHAPE",
|
582 | rotateAdornmentTemplate: // specify appearance of rotation handle
|
583 | $(go.Adornment,
|
584 | { locationSpot: go.Spot.Center },
|
585 | $(go.Shape, "BpmnActivityLoop",
|
586 | { width: 12, height: 12, cursor: "pointer",
|
587 | background: "transparent", stroke: "dodgerblue", strokeWidth: 2 })),
|
588 | selectionObjectName: "SHAPE" },
|
589 | $(go.Shape, "RoundedRectangle",
|
590 | { name: "SHAPE", fill: "orange", width: 50, height: 30 }),
|
591 | $(go.TextBlock, "Hello!", { margin: 3 })
|
592 | ));
|
593 | diagram.commandHandler.selectAll();
|
594 | </code></pre>
|
595 | <script>goCode("rotatingTemplate", 600, 150)</script>
|
596 | <p>
|
597 | There are example custom rotating tools defined in the samples and extensions directories:
|
598 | <a href="../extensions/FloorPlanEditor.html">Rotate Multiple Tool (in Floor Plan Editor)</a> and
|
599 | <a href="../samples/seatingChart.html">Horizontal Text Rotating Tool (in Seating Chart)</a>.
|
600 | </p>
|
601 |
|
602 | <h3 id="RelinkingTool">RelinkingTool</h3>
|
603 | <p>
|
604 | When a <a>Link</a> is <a>Link.relinkableFrom</a> and/or <a>Link.relinkableTo</a>,
|
605 | the <a>RelinkingTool</a> adds one or two <a>Adornment</a>s,
|
606 | a diamond at each relinkable end of a selected link.
|
607 | The user can drag a relinking handle to reconnect that end of the link to another port.
|
608 | </p>
|
609 | <p>
|
610 | The <a>RelinkingTool</a> will automatically update the relationships between the nodes/ports,
|
611 | both in the diagram and in the model. No <a>Binding</a>s are needed for such model updates.
|
612 | </p>
|
613 | <pre class="lang-js" id="relinking"><code>
|
614 | diagram.nodeTemplate =
|
615 | $(go.Node, "Auto",
|
616 | $(go.Shape, "Rectangle",
|
617 | { fill: "lightgray", portId: "", fromLinkable: true, toLinkable: true }),
|
618 | $(go.TextBlock, { margin: 5},
|
619 | new go.Binding("text", "key"))
|
620 | );
|
621 |
|
622 | diagram.linkTemplate =
|
623 | $(go.Link,
|
624 | { relinkableFrom: true, relinkableTo: true },
|
625 | $(go.Shape),
|
626 | $(go.Shape, { toArrow: "Standard" })
|
627 | );
|
628 |
|
629 | var nodeDataArray = [
|
630 | { key: "Alpha" }, { key: "Beta" }, { key: "Gamma" }, { key: "Delta" }
|
631 | ];
|
632 | var linkDataArray = [
|
633 | { from: "Alpha", to: "Delta" }
|
634 | ];
|
635 | diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
|
636 |
|
637 | diagram.select(diagram.findLinkForData(linkDataArray[0]));
|
638 | </code></pre>
|
639 | <script>goCode("relinking", 600, 150)</script>
|
640 | <p>
|
641 | The relinking handles can be customized by setting <a>RelinkingTool.fromHandleArchetype</a>
|
642 | and <a>RelinkingTool.toHandleArchetype</a>.
|
643 | At the current time they cannot be customized by setting a property on the Link.
|
644 | </p>
|
645 | <p>
|
646 | You can limit which pairs of ports between which the user may draw new links or reconnect existing links.
|
647 | This topic is covered by <a href="validation.html">Link Validation</a>.
|
648 | </p>
|
649 |
|
650 | <h3 id="LinkReshapingTool">LinkReshapingTool</h3>
|
651 | <p>
|
652 | When a <a>Link</a> is <a>Part.reshapable</a>, the <a>LinkReshapingTool</a> adds an <a>Adornment</a>
|
653 | with several reshape handles at the interior points of a selected link's route.
|
654 | When the user drags a reshape handle, the route of the Link, held by <a>Link.points</a>, is modified.
|
655 | </p>
|
656 | <p>
|
657 | When a link is reshapable, it is commonplace to try to remember the new route by updating the link data
|
658 | in the <a>GraphLinksModel</a>, so that it can be saved and loaded later.
|
659 | This can be accomplished with a TwoWay <a>Binding</a> on the <a>Link.points</a> property.
|
660 | If one also uses the property name "points" on the link data, <a>Model.toJson</a> will
|
661 | automatically convert the <a>List</a> of <a>Point</a>s into an Array of numbers and vice-versa.
|
662 | </p>
|
663 | <pre class="lang-js" id="linkReshaping"><code>
|
664 | diagram.nodeTemplate =
|
665 | $(go.Node, "Auto",
|
666 | new go.Binding("location", "loc", go.Point.parse),
|
667 | $(go.Shape, "Rectangle", { fill: "lightgray" }),
|
668 | $(go.TextBlock, { margin: 5},
|
669 | new go.Binding("text", "key"))
|
670 | );
|
671 |
|
672 | diagram.linkTemplate =
|
673 | $(go.Link,
|
674 | { reshapable: true, routing: go.Link.Orthogonal },
|
675 | new go.Binding("points").makeTwoWay(), // TwoWay Binding of Link.points
|
676 | $(go.Shape),
|
677 | $(go.Shape, { toArrow: "Standard" })
|
678 | );
|
679 |
|
680 | diagram.model = new go.GraphLinksModel([
|
681 | { key: "Alpha", loc: "0 0" },
|
682 | { key: "Beta", loc: "200 50" }
|
683 | ], [
|
684 | { from: "Alpha", to: "Beta" }
|
685 | ]);
|
686 |
|
687 | diagram.select(diagram.findLinkForData(diagram.model.linkDataArray[0]));
|
688 | </code></pre>
|
689 | <script>goCode("linkReshaping", 600, 150)</script>
|
690 | <p>
|
691 | The reshape handles are small blue squares.
|
692 | The reshape handles can be customized by setting <a>LinkReshapingTool.handleArchetype</a>.
|
693 | At the current time they cannot be customized by setting a property on the Link.
|
694 | </p>
|
695 | <p>
|
696 | By setting <a>Link.resegmentable</a> to true, users can add or remove segments from links.
|
697 | The resegmenting handles are even smaller blue diamonds at the middle of each segment.
|
698 | When the user drags a resegmenting handle, a new segment is inserted into the link's route.
|
699 | For orthogonal links, two new segments are introduced in order to maintain orthogonality.
|
700 | When the user reshapes the link so that adjacent segments are co-linear (or nearly so),
|
701 | the segment(s) are removed from the route.
|
702 | </p>
|
703 | <pre class="lang-js" id="linkResegmenting"><code>
|
704 | diagram.nodeTemplate =
|
705 | $(go.Node, "Auto",
|
706 | new go.Binding("location", "loc", go.Point.parse),
|
707 | $(go.Shape, "Rectangle", { fill: "lightgray" }),
|
708 | $(go.TextBlock, { margin: 5},
|
709 | new go.Binding("text", "key"))
|
710 | );
|
711 |
|
712 | diagram.linkTemplate =
|
713 | $(go.Link,
|
714 | { reshapable: true, resegmentable: true, routing: go.Link.Orthogonal },
|
715 | new go.Binding("points").makeTwoWay(), // TwoWay Binding of Link.points
|
716 | $(go.Shape),
|
717 | $(go.Shape, { toArrow: "Standard" })
|
718 | );
|
719 |
|
720 | diagram.model = new go.GraphLinksModel([
|
721 | { key: "Alpha", loc: "0 0" },
|
722 | { key: "Beta", loc: "200 50" }
|
723 | ], [
|
724 | { from: "Alpha", to: "Beta" }
|
725 | ]);
|
726 |
|
727 | diagram.select(diagram.findLinkForData(diagram.model.linkDataArray[0]));
|
728 | </code></pre>
|
729 | <script>goCode("linkResegmenting", 600, 150)</script>
|
730 | <p>
|
731 | The resegmenting handles can be customized by setting <a>LinkReshapingTool.midHandleArchetype</a>.
|
732 | At the current time they cannot be customized by setting a property on the Link.
|
733 | Also at the current time resegmenting is not supported on Bezier-curved links.
|
734 | </p>
|
735 | <p>
|
736 | If you want your users to be able to reshape Shape geometries that are not Link paths,
|
737 | there is the <a href="../extensions/GeometryReshapingTool.js">Geometry Reshaping Tool</a>
|
738 | used by the <a href="../extensions/PolygonDrawing.html">Polygon Drawing</a> and
|
739 | <a href="../extensions/FreehandDrawing.html">Freehand Drawing</a> samples in the extensions directory.
|
740 | It is defined in a separate JS file that you can load into your app.
|
741 | </p>
|
742 |
|
743 |
|
744 | <h2 id="ToolsAndToolParts">Tools and Tool Parts</h2>
|
745 | <p>
|
746 | Some tools make use of special <a>Part</a>s that they add to the "Tool" <a>Layer</a> as feedback during the tool's operation.
|
747 | </p>
|
748 |
|
749 | <h3 id="DragSelectingTool">DragSelectingTool</h3>
|
750 | <p>
|
751 | The <a>DragSelectingTool</a> uses the <a>DragSelectingTool.box</a> to show the area in which it will select Parts.
|
752 | Normally this is a simple magenta rectangular shape. You can change it. For example here is a drag-selecting box
|
753 | that is in the shape of a blue-outlined cloud.
|
754 | </p>
|
755 | <pre class="lang-js" id="dragSelecting"><code>
|
756 | diagram.nodeTemplate =
|
757 | $(go.Node, "Auto",
|
758 | new go.Binding("location", "loc", go.Point.parse),
|
759 | $(go.Shape, "Rectangle", { fill: "lightgray" }),
|
760 | $(go.TextBlock, { margin: 5},
|
761 | new go.Binding("text", "key"))
|
762 | );
|
763 |
|
764 | diagram.toolManager.dragSelectingTool.isPartialInclusion = true;
|
765 | diagram.toolManager.dragSelectingTool.box =
|
766 | $(go.Part,
|
767 | { layerName: "Tool" },
|
768 | $(go.Shape, "Cloud",
|
769 | { name: "SHAPE", fill: null, stroke: "dodgerblue", strokeWidth: 2 })
|
770 | );
|
771 |
|
772 | diagram.model = new go.GraphLinksModel([
|
773 | { key: "Alpha", loc: "0 0" },
|
774 | { key: "Beta", loc: "200 50" }
|
775 | ], [
|
776 | { from: "Alpha", to: "Beta" }
|
777 | ]);
|
778 | </code></pre>
|
779 | <script>goCode("dragSelecting", 600, 200)</script>
|
780 | <p>
|
781 | Note that the <a>DragSelectingTool</a> expects that the object in the "box" to be resized is named "SHAPE".
|
782 | The object should be rectangular too, or else the user might be misled by the area in which parts will be selected.
|
783 | Finally note also that the box is not an Adornment because it does not "adorn" any Part.
|
784 | It is just an unbound Part that is used temporarily by the DragSelectingTool.
|
785 | </p>
|
786 | <p>
|
787 | There are examples of in-the-background-dragging tools defined in the extensions directory:
|
788 | <a href="../extensions/RealtimeDragSelecting.html">Realtime Drag Selecting Tool</a>,
|
789 | <a href="../extensions/DragCreating.html">Drag Creating Tool</a>, and
|
790 | <a href="../extensions/DragZooming.html">Drag Zooming Tool</a>.
|
791 | Each is defined in a separate JS file that you can load into your app.
|
792 | </p>
|
793 |
|
794 | <h3 id="LinkingToolAndRelinkingTool">LinkingTool and RelinkingTool</h3>
|
795 | <p>
|
796 | The linking tools, <a>LinkingTool</a> and <a>RelinkingTool</a>, inherit from a base class, <a>LinkingBaseTool</a>,
|
797 | that uses several Parts: a temporary Link and temporary "to" and "from" Nodes.
|
798 | </p>
|
799 | <p>
|
800 | To customize the appearance and behavior of the temporary Link that is shown during a linking operation,
|
801 | you need to modify or replace the <a>LinkingBaseTool.temporaryLink</a>.
|
802 | The default temporary link is a blue line with a standard arrowhead.
|
803 | The originating port and the potential target port are shown by the <a>LinkingBaseTool.temporaryFromNode</a>
|
804 | and <a>LinkingBaseTool.temporaryToNode</a>.
|
805 | The default temporary ports are magenta rectangles.
|
806 | </p>
|
807 | <pre class="lang-js" id="linkingTools"><code>
|
808 |
|
809 | diagram.nodeTemplate =
|
810 | $(go.Node, "Spot",
|
811 | new go.Binding("location", "loc", go.Point.parse),
|
812 | $(go.Shape, "RoundedRectangle",
|
813 | { width: 100, height: 40, fill: "lightyellow",
|
814 | portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer" }),
|
815 | $(go.TextBlock,
|
816 | new go.Binding("text", "key"))
|
817 | );
|
818 |
|
819 | diagram.toolManager.linkingTool.temporaryLink =
|
820 | $(go.Link,
|
821 | { layerName: "Tool" },
|
822 | $(go.Shape,
|
823 | { stroke: "red", strokeWidth: 2, strokeDashArray: [4, 2] })
|
824 | );
|
825 |
|
826 | var tempfromnode =
|
827 | $(go.Node,
|
828 | { layerName: "Tool" },
|
829 | $(go.Shape, "RoundedRectangle",
|
830 | { stroke: "chartreuse", strokeWidth: 3, fill: null,
|
831 | portId: "", width: 1, height: 1 })
|
832 | );
|
833 | diagram.toolManager.linkingTool.temporaryFromNode = tempfromnode;
|
834 | diagram.toolManager.linkingTool.temporaryFromPort = tempfromnode.port;
|
835 |
|
836 | var temptonode =
|
837 | $(go.Node,
|
838 | { layerName: "Tool" },
|
839 | $(go.Shape, "RoundedRectangle",
|
840 | { stroke: "cyan", strokeWidth: 3, fill: null,
|
841 | portId: "", width: 1, height: 1 })
|
842 | );
|
843 | diagram.toolManager.linkingTool.temporaryToNode = temptonode;
|
844 | diagram.toolManager.linkingTool.temporaryToPort = temptonode.port;
|
845 |
|
846 | diagram.model = new go.GraphLinksModel([
|
847 | { key: "Alpha", loc: "0 0" },
|
848 | { key: "Beta", loc: "200 50" },
|
849 | { key: "Gamma", loc: "400 0" }
|
850 | ]); // start off with no links
|
851 | </code></pre>
|
852 | <script>goCode("linkingTools", 600, 150)</script>
|
853 | <p>
|
854 | Try drawing a link from one node to the other.
|
855 | You will notice that the nodes (actually the ports) are highlighted by the temporary nodes in chartreuse and cyan.
|
856 | The temporary link is a dashed red line without an arrowhead.
|
857 | </p>
|
858 | <p>
|
859 | If your app also supports relinking you will probably want to do the same customizations on the <a>RelinkingTool</a>.
|
860 | </p>
|
861 | <p>
|
862 | There are examples of linking tools defined in the samples and extensions directories:
|
863 | <a href="../extensions/PolylineLinking.html">Polyline Linking Tool</a>,
|
864 | <a href="../samples/sequenceDiagram.html">Messaging Tool (in Sequence Diagram)</a>, and
|
865 | <a href="../samples/sequenceDiagram.html">Custom Linking Tool (in Grafcet Diagram)</a>
|
866 | </p>
|
867 |
|
868 | <h2 id="CustomTools">Custom Tools</h2>
|
869 | <p>
|
870 | The GoJS samples and extensions demonstrate a number of custom tools, including:
|
871 | <ul style="margin-bottom: 70px;">
|
872 | <li><a href="../extensions/FloorPlanEditor.html">Resize Multiple Tool (in Floor Plan Editor)</a>
|
873 | <li><a href="../samples/swimLanes.html">Lane Resizing Tool (in Swim Lanes)</a>
|
874 | <li><a href="../samples/swimLanesVertical.html">Lane Resizing Tool (in Swim Lanes Vertical)</a>
|
875 | <li><a href="../extensions/FloorPlanEditor.html">Rotate Multiple Tool (in Floor Plan Editor)</a>
|
876 | <li><a href="../samples/seatingChart.html">Horizontal Text Rotating Tool (in Seating Chart)</a>
|
877 | <li><a href="../extensions/GeometryReshapingTool.js">Geometry Reshaping Tool</a>
|
878 | used by the <a href="../extensions/PolygonDrawing.html">Polygon Drawing</a> <a href="../extensions/FreehandDrawing.html">Freehand Drawing</a>
|
879 | <li><a href="../extensions/RealtimeDragSelecting.html">Realtime Drag Selecting Tool</a>
|
880 | <li><a href="../extensions/DragCreating.html">Drag Creating Tool</a>
|
881 | <li><a href="../extensions/DragZooming.html">Drag Zooming Tool</a>
|
882 | <li><a href="../extensions/PolylineLinking.html">Polyline Linking Tool</a>
|
883 | <li><a href="../samples/sequenceDiagram.html">Messaging Tool (in Sequence Diagram)</a>
|
884 | <li><a href="../samples/sequenceDiagram.html">Custom Linking Tool (in Grafcet Diagram)</a>
|
885 | </ul>
|
886 |
|
887 |
|
888 | </div>
|
889 | </div>
|
890 |
|
891 | <div class="bg-nwoods-primary">
|
892 | <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
|
893 | <p id="version" class="leading-none mb-2 my-4">GoJS</p>
|
894 | </section>
|
895 | </div><footer class="bg-nwoods-primary text-white">
|
896 | <div class="container max-w-screen-lg mx-auto px-8">
|
897 | <div class="w-full py-6">
|
898 |
|
899 | <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
|
900 | <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
|
901 | <li class="list-none row-span-2">
|
902 | <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
|
903 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
904 | <li>
|
905 | <a href="../samples/index.html">Samples</a>
|
906 | </li>
|
907 | <li>
|
908 | <a href="../learn/index.html">Learn</a>
|
909 | </li>
|
910 | <li>
|
911 | <a href="../intro/index.html">Intro</a>
|
912 | </li>
|
913 | <li>
|
914 | <a href="../api/index.html">API</a>
|
915 | </li>
|
916 | <li>
|
917 | <a href="../changelog.html">Changelog</a>
|
918 | </li>
|
919 | <li>
|
920 | <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
|
921 | </li>
|
922 | </ul>
|
923 | </li>
|
924 | <li class="list-none row-span-2">
|
925 | <h2 class="text-base font-semibold tracking-wide">Support</h2>
|
926 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
927 | <li>
|
928 | <a href="https://www.nwoods.com/contact.html"
|
929 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
|
930 | </li>
|
931 | <li>
|
932 | <a href="https://forum.nwoods.com/c/gojs">Forum</a>
|
933 | </li>
|
934 | <li>
|
935 | <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
|
936 | </li>
|
937 | <li>
|
938 | <a href="https://www.nwoods.com/sales/index.html"
|
939 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
|
940 | </li>
|
941 | <li>
|
942 | <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
|
943 | </li>
|
944 | </ul>
|
945 | </li>
|
946 | <li class="list-none row-span-2">
|
947 | <h2 class="text-base font-semibold tracking-wide">Company</h2>
|
948 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
949 | <li>
|
950 | <a href="https://www.nwoods.com">Northwoods</a>
|
951 | </li>
|
952 | <li>
|
953 | <a href="https://www.nwoods.com/about.html">About Us</a>
|
954 | </li>
|
955 | <li>
|
956 | <a href="https://www.nwoods.com/contact.html">Contact Us</a>
|
957 | </li>
|
958 | <li>
|
959 | <a href="https://twitter.com/northwoodsgo">Twitter</a>
|
960 | </li>
|
961 |
|
962 | </ul>
|
963 | </li>
|
964 | </ul>
|
965 |
|
966 |
|
967 | <p class="text-sm text-gray-100 md:mb-6">
|
968 | Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
|
969 | </p>
|
970 | </div>
|
971 | </div>
|
972 | </footer> </body>
|
973 |
|
974 | <script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script>
|
975 | <script>
|
976 | window.dataLayer = window.dataLayer || [];
|
977 | function gtag(){dataLayer.push(arguments);}
|
978 | gtag('js', new Date()); gtag('config', 'UA-1506307-5');
|
979 | var getOutboundLink = function(url, label) {
|
980 | gtag('event', 'click', {
|
981 | 'event_category': 'outbound',
|
982 | 'event_label': label,
|
983 | 'transport_type': 'beacon'
|
984 | });
|
985 | }
|
986 |
|
987 |
|
988 | var topButton = document.getElementById("topnavButton");
|
989 | var topnavList = document.getElementById("topnavList");
|
990 | topButton.addEventListener("click", function() {
|
991 | this.classList.toggle("active");
|
992 | topnavList.classList.toggle("hidden");
|
993 | document.getElementById("topnavOpen").classList.toggle("hidden");
|
994 | document.getElementById("topnavClosed").classList.toggle("hidden");
|
995 | });
|
996 | </script>
|
997 | <script src="../assets/js/prism.js"></script>
|
998 | <script src="../release/go.js"></script>
|
999 | <script src="../extensions/Figures.js"></script> <script src="../assets/js/goDoc.js"></script>
|
1000 | <script>
|
1001 | document.addEventListener("DOMContentLoaded", function() {
|
1002 | if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
|
1003 | if (window.goDoc) window.goDoc();
|
1004 | var d = window.diagrams;
|
1005 | for (var i = 0; i < d.length; i++) {
|
1006 | var dargs = d[i];
|
1007 | goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
|
1008 | }
|
1009 | if (window.extra) window.extra();
|
1010 | });
|
1011 | </script>
|
1012 | </html>
|