1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | import * as go from '../release/go.js';
|
7 |
|
8 | let myDiagram: go.Diagram;
|
9 | let myPalette: go.Palette;
|
10 |
|
11 | export function init() {
|
12 | if ((window as any).goSamples) (window as any).goSamples();
|
13 | const $ = go.GraphObject.make;
|
14 |
|
15 | myDiagram =
|
16 | $(go.Diagram, 'myDiagramDiv',
|
17 | {
|
18 | 'LinkDrawn': showLinkLabel,
|
19 | 'LinkRelinked': showLinkLabel,
|
20 | 'undoManager.isEnabled': true
|
21 | });
|
22 |
|
23 |
|
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 |
|
36 |
|
37 | function nodeStyle() {
|
38 | return [
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
|
44 | {
|
45 |
|
46 | locationSpot: go.Spot.Center
|
47 | }
|
48 | ];
|
49 | }
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
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 |
|
60 |
|
61 | return $(go.Shape,
|
62 | {
|
63 | fill: "transparent",
|
64 | strokeWidth: 0,
|
65 | width: horizontal ? NaN : 8,
|
66 | height: !horizontal ? NaN : 8,
|
67 | alignment: align,
|
68 | stretch: (horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical),
|
69 | portId: name,
|
70 | fromSpot: spot,
|
71 | fromLinkable: output,
|
72 | toSpot: spot,
|
73 | toLinkable: input,
|
74 | cursor: "pointer",
|
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 |
|
92 |
|
93 | myDiagram.nodeTemplateMap.add("",
|
94 | $(go.Node, "Table", nodeStyle(),
|
95 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
168 | go.Shape.defineFigureGenerator('File', (shape, w, h) => {
|
169 | const geo = new go.Geometry();
|
170 | const fig = new go.PathFigure(0, 0, true);
|
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 |
|
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 |
|
203 | ));
|
204 |
|
205 |
|
206 |
|
207 | myDiagram.linkTemplate =
|
208 | $(go.Link,
|
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 |
|
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,
|
223 | { isPanelMain: true, strokeWidth: 8, stroke: "transparent", name: "HIGHLIGHT" }),
|
224 | $(go.Shape,
|
225 | { isPanelMain: true, stroke: "gray", strokeWidth: 2 }),
|
226 | $(go.Shape,
|
227 | { toArrow: "standard", strokeWidth: 0, fill: "gray" }),
|
228 | $(go.Panel, "Auto",
|
229 | { visible: false, name: "LABEL", segmentIndex: 2, segmentFraction: 0.5 },
|
230 | new go.Binding("visible", "visible").makeTwoWay(),
|
231 | $(go.Shape, "RoundedRectangle",
|
232 | { fill: "#F8F8F8", strokeWidth: 0 }),
|
233 | $(go.TextBlock, "Yes",
|
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 |
|
245 |
|
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 |
|
252 | myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
|
253 | myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal;
|
254 |
|
255 | load();
|
256 |
|
257 |
|
258 | myPalette =
|
259 | $(go.Palette, 'myPaletteDiv',
|
260 | {
|
261 | nodeTemplateMap: myDiagram.nodeTemplateMap,
|
262 | model: new go.GraphLinksModel([
|
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 |
|
272 | (window as any).myDiagram = myDiagram;
|
273 | (window as any).myPalette = myPalette;
|
274 | }
|
275 |
|
276 |
|
277 |
|
278 | const mySavedModel = (document.getElementById('mySavedModel') as HTMLTextAreaElement);
|
279 | function save() {
|
280 | mySavedModel.value = myDiagram.model.toJson();
|
281 | myDiagram.isModified = false;
|
282 | }
|
283 | function load() {
|
284 | myDiagram.model = go.Model.fromJson(mySavedModel.value);
|
285 | }
|
286 |
|
287 |
|
288 | function printDiagram() {
|
289 | const svgWindow = window.open();
|
290 | if (!svgWindow) return;
|
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 |
|
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);
|