UNPKG

13.2 kBPlain TextView Raw
1'use strict';
2/*
3* Copyright (C) 1998-2021 by Northwoods Software Corporation. All Rights Reserved.
4*/
5
6import * as go from '../release/go.js';
7
8let myDiagram: go.Diagram;
9let myPalette: go.Palette;
10
11export function init() {
12 if ((window as any).goSamples) (window as any).goSamples(); // init for these samples -- you don't need to call this
13 const $ = go.GraphObject.make; // for conciseness in defining templates
14
15 myDiagram =
16 $(go.Diagram, 'myDiagramDiv', // must name or refer to the DIV HTML element
17 {
18 'LinkDrawn': showLinkLabel, // this DiagramEvent listener is defined below
19 'LinkRelinked': showLinkLabel,
20 'undoManager.isEnabled': true // enable undo & redo
21 });
22
23 // when the document is modified, add a "*" to the title and enable the "Save" button
24 myDiagram.addDiagramListener('Modified', (e) => {
25 const button = document.getElementById('SaveButton') as HTMLButtonElement;
26 if (button) button.disabled = !myDiagram.isModified;
27 const idx = document.title.indexOf('*');
28 if (myDiagram.isModified) {
29 if (idx < 0) document.title += '*';
30 } else {
31 if (idx >= 0) document.title = document.title.substr(0, idx);
32 }
33 });
34
35 // helper definitions for node templates
36
37 function nodeStyle() {
38 return [
39 // The Node.location comes from the "loc" property of the node data,
40 // converted by the Point.parse static method.
41 // If the Node.location is changed, it updates the "loc" property of the node data,
42 // converting back using the Point.stringify static method.
43 new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
44 {
45 // the Node.location is at the center of each node
46 locationSpot: go.Spot.Center
47 }
48 ];
49 }
50
51 // Define a function for creating a "port" that is normally transparent.
52 // The "name" is used as the GraphObject.portId,
53 // the "align" is used to determine where to position the port relative to the body of the node,
54 // the "spot" is used to control how links connect with the port and whether the port
55 // stretches along the side of the node,
56 // and the boolean "output" and "input" arguments control whether the user can draw links from or to the port.
57 function makePort(name: string, align: go.Spot, spot: go.Spot, output: boolean, input: boolean) {
58 const horizontal = align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
59 // the port is basically just a transparent rectangle that stretches along the side of the node,
60 // and becomes colored when the mouse passes over it
61 return $(go.Shape,
62 {
63 fill: "transparent", // changed to a color in the mouseEnter event handler
64 strokeWidth: 0, // no stroke
65 width: horizontal ? NaN : 8, // if not stretching horizontally, just 8 wide
66 height: !horizontal ? NaN : 8, // if not stretching vertically, just 8 tall
67 alignment: align, // align the port on the main Shape
68 stretch: (horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical),
69 portId: name, // declare this object to be a "port"
70 fromSpot: spot, // declare where links may connect at this port
71 fromLinkable: output, // declare whether the user may draw links from here
72 toSpot: spot, // declare where links may connect at this port
73 toLinkable: input, // declare whether the user may draw links to here
74 cursor: "pointer", // show a different cursor to indicate potential link point
75 mouseEnter: (e: go.InputEvent, port: go.GraphObject) => {
76 if (!e.diagram.isReadOnly && port instanceof go.Shape) port.fill = "rgba(255,0,255,0.5)";
77 },
78 mouseLeave: (e: go.InputEvent, port: go.GraphObject) => {
79 if (port instanceof go.Shape) port.fill = "transparent";
80 }
81 });
82 }
83
84 function textStyle() {
85 return {
86 font: "bold 11pt Helvetica, Arial, sans-serif",
87 stroke: "whitesmoke"
88 }
89 }
90
91 // define the Node templates for regular nodes
92
93 myDiagram.nodeTemplateMap.add("", // the default category
94 $(go.Node, "Table", nodeStyle(),
95 // the main object is a Panel that surrounds a TextBlock with a rectangular Shape
96 $(go.Panel, "Auto",
97 $(go.Shape, "Rectangle",
98 { fill: "#00A9C9", strokeWidth: 0 },
99 new go.Binding("figure", "figure")),
100 $(go.TextBlock, textStyle(),
101 {
102 margin: 8,
103 maxSize: new go.Size(160, NaN),
104 wrap: go.TextBlock.WrapFit,
105 editable: true
106 },
107 new go.Binding("text").makeTwoWay())
108 ),
109 // four named ports, one on each side:
110 makePort("T", go.Spot.Top, go.Spot.TopSide, false, true),
111 makePort("L", go.Spot.Left, go.Spot.LeftSide, true, true),
112 makePort("R", go.Spot.Right, go.Spot.RightSide, true, true),
113 makePort("B", go.Spot.Bottom, go.Spot.BottomSide, true, false)
114 ));
115
116 myDiagram.nodeTemplateMap.add("Conditional",
117 $(go.Node, "Table", nodeStyle(),
118 // the main object is a Panel that surrounds a TextBlock with a rectangular Shape
119 $(go.Panel, "Auto",
120 $(go.Shape, "Diamond",
121 { fill: "#00A9C9", strokeWidth: 0 },
122 new go.Binding("figure", "figure")),
123 $(go.TextBlock, textStyle(),
124 {
125 margin: 8,
126 maxSize: new go.Size(160, NaN),
127 wrap: go.TextBlock.WrapFit,
128 editable: true
129 },
130 new go.Binding("text").makeTwoWay())
131 ),
132 // four named ports, one on each side:
133 makePort("T", go.Spot.Top, go.Spot.Top, false, true),
134 makePort("L", go.Spot.Left, go.Spot.Left, true, true),
135 makePort("R", go.Spot.Right, go.Spot.Right, true, true),
136 makePort("B", go.Spot.Bottom, go.Spot.Bottom, true, false)
137 ));
138
139 myDiagram.nodeTemplateMap.add("Start",
140 $(go.Node, "Table", nodeStyle(),
141 $(go.Panel, "Auto",
142 $(go.Shape, "Circle",
143 { minSize: new go.Size(40, 40), fill: "#79C900", strokeWidth: 0 }),
144 $(go.TextBlock, "Start", textStyle(),
145 new go.Binding("text"))
146 ),
147 // three named ports, one on each side except the top, all output only:
148 makePort("L", go.Spot.Left, go.Spot.Left, true, false),
149 makePort("R", go.Spot.Right, go.Spot.Right, true, false),
150 makePort("B", go.Spot.Bottom, go.Spot.Bottom, true, false)
151 ));
152
153 myDiagram.nodeTemplateMap.add("End",
154 $(go.Node, "Table", nodeStyle(),
155 $(go.Panel, "Auto",
156 $(go.Shape, "Circle",
157 { minSize: new go.Size(40, 40), fill: "#DC3C00", strokeWidth: 0 }),
158 $(go.TextBlock, "End", textStyle(),
159 new go.Binding("text"))
160 ),
161 // three named ports, one on each side except the bottom, all input only:
162 makePort("T", go.Spot.Top, go.Spot.Top, false, true),
163 makePort("L", go.Spot.Left, go.Spot.Left, false, true),
164 makePort("R", go.Spot.Right, go.Spot.Right, false, true)
165 ));
166
167 // taken from ../extensions/Figures.ts:
168 go.Shape.defineFigureGenerator('File', (shape, w, h) => {
169 const geo = new go.Geometry();
170 const fig = new go.PathFigure(0, 0, true); // starting point
171 geo.add(fig);
172 fig.add(new go.PathSegment(go.PathSegment.Line, .75 * w, 0));
173 fig.add(new go.PathSegment(go.PathSegment.Line, w, .25 * h));
174 fig.add(new go.PathSegment(go.PathSegment.Line, w, h));
175 fig.add(new go.PathSegment(go.PathSegment.Line, 0, h).close());
176 const fig2 = new go.PathFigure(.75 * w, 0, false);
177 geo.add(fig2);
178 // The Fold
179 fig2.add(new go.PathSegment(go.PathSegment.Line, .75 * w, .25 * h));
180 fig2.add(new go.PathSegment(go.PathSegment.Line, w, .25 * h));
181 geo.spot1 = new go.Spot(0, .25);
182 geo.spot2 = go.Spot.BottomRight;
183 return geo;
184 });
185
186
187 myDiagram.nodeTemplateMap.add("Comment",
188 $(go.Node, "Auto", nodeStyle(),
189 $(go.Shape, "File",
190 { fill: "#DEE0A3", strokeWidth: 0 }),
191 $(go.TextBlock, textStyle(),
192 {
193 margin: 5,
194 maxSize: new go.Size(200, NaN),
195 wrap: go.TextBlock.WrapFit,
196 textAlign: "center",
197 editable: true,
198 font: "bold 12pt Helvetica, Arial, sans-serif",
199 stroke: '#454545'
200 },
201 new go.Binding("text").makeTwoWay())
202 // no ports, because no links are allowed to connect with a comment
203 ));
204
205
206 // replace the default Link template in the linkTemplateMap
207 myDiagram.linkTemplate =
208 $(go.Link, // the whole link panel
209 {
210 routing: go.Link.AvoidsNodes,
211 curve: go.Link.JumpOver,
212 corner: 5, toShortLength: 4,
213 relinkableFrom: true,
214 relinkableTo: true,
215 reshapable: true,
216 resegmentable: true,
217 // mouse-overs subtly highlight links:
218 mouseEnter: (e: go.InputEvent, link: go.GraphObject) => { if (link instanceof go.Link) (link.findObject("HIGHLIGHT") as go.Shape).stroke = "rgba(30,144,255,0.2)"; },
219 mouseLeave: (e: go.InputEvent, link: go.GraphObject) => { if (link instanceof go.Link) (link.findObject("HIGHLIGHT") as go.Shape).stroke = "transparent"; }
220 },
221 new go.Binding("points").makeTwoWay(),
222 $(go.Shape, // the highlight shape, normally transparent
223 { isPanelMain: true, strokeWidth: 8, stroke: "transparent", name: "HIGHLIGHT" }),
224 $(go.Shape, // the link path shape
225 { isPanelMain: true, stroke: "gray", strokeWidth: 2 }),
226 $(go.Shape, // the arrowhead
227 { toArrow: "standard", strokeWidth: 0, fill: "gray" }),
228 $(go.Panel, "Auto", // the link label, normally not visible
229 { visible: false, name: "LABEL", segmentIndex: 2, segmentFraction: 0.5 },
230 new go.Binding("visible", "visible").makeTwoWay(),
231 $(go.Shape, "RoundedRectangle", // the label shape
232 { fill: "#F8F8F8", strokeWidth: 0 }),
233 $(go.TextBlock, "Yes", // the label
234 {
235 textAlign: "center",
236 font: "10pt helvetica, arial, sans-serif",
237 stroke: "#333333",
238 editable: true
239 },
240 new go.Binding("text").makeTwoWay())
241 )
242 );
243
244 // Make link labels visible if coming out of a "conditional" node.
245 // This listener is called by the "LinkDrawn" and "LinkRelinked" DiagramEvents.
246 function showLinkLabel(e: go.DiagramEvent) {
247 const label = e.subject.findObject('LABEL');
248 if (label !== null) label.visible = (e.subject.fromNode.data.figure === 'Diamond');
249 }
250
251 // temporary links used by LinkingTool and RelinkingTool are also orthogonal:
252 myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
253 myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal;
254
255 load(); // load an initial diagram from some JSON text
256
257 // initialize the Palette that is on the left side of the page
258 myPalette =
259 $(go.Palette, 'myPaletteDiv', // must name or refer to the DIV HTML element
260 {
261 nodeTemplateMap: myDiagram.nodeTemplateMap, // share the templates used by myDiagram
262 model: new go.GraphLinksModel([ // specify the contents of the Palette
263 { category: 'Start', text: 'Start' },
264 { text: 'Step' },
265 { category: 'Conditional', text: '???' },
266 { category: 'End', text: 'End' },
267 { category: 'Comment', text: 'Comment' }
268 ])
269 });
270
271 // Attach to the window so you can manipulate in the console
272 (window as any).myDiagram = myDiagram;
273 (window as any).myPalette = myPalette;
274} // end init
275
276
277// Show the diagram's model in JSON format that the user may edit
278const mySavedModel = (document.getElementById('mySavedModel') as HTMLTextAreaElement);
279function save() {
280 mySavedModel.value = myDiagram.model.toJson();
281 myDiagram.isModified = false;
282}
283function load() {
284 myDiagram.model = go.Model.fromJson(mySavedModel.value);
285}
286
287// print the diagram by opening a new window holding SVG images of the diagram contents for each page
288function printDiagram() {
289 const svgWindow = window.open();
290 if (!svgWindow) return; // failure to open a new Window
291 const printSize = new go.Size(700, 960);
292 const bnds = myDiagram.documentBounds;
293 let x = bnds.x;
294 let y = bnds.y;
295 while (y < bnds.bottom) {
296 while (x < bnds.right) {
297 const svg = (window as any).myDiagram.makeSvg({ scale: 1.0, position: new go.Point(x, y), size: printSize });
298 svgWindow.document.body.appendChild(svg);
299 x += printSize.width;
300 }
301 x = bnds.x;
302 y += printSize.height;
303 }
304 setTimeout(() => svgWindow.print(), 1);
305}
306
307// Add listeners for the buttons:
308(document.getElementById('SaveButton') as HTMLButtonElement).addEventListener('click', save);
309(document.getElementById('LoadButton') as HTMLButtonElement).addEventListener('click', load);
310(document.getElementById('SVGButton') as HTMLButtonElement).addEventListener('click', printDiagram);