pict-section-flow 0.0.10 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/launch.json +1 -1
- package/README.md +176 -0
- package/docs/.nojekyll +0 -0
- package/docs/Architecture.md +303 -0
- package/docs/Custom-Styling.md +275 -0
- package/docs/Data_Model.md +158 -0
- package/docs/Event_System.md +156 -0
- package/docs/Getting_Started.md +237 -0
- package/docs/Implementation_Reference.md +528 -0
- package/docs/Layout_Persistence.md +117 -0
- package/docs/README.md +115 -52
- package/docs/_cover.md +11 -0
- package/docs/_sidebar.md +52 -0
- package/docs/_topbar.md +8 -0
- package/docs/api/PictFlowCard.md +216 -0
- package/docs/api/PictFlowCardPropertiesPanel.md +235 -0
- package/docs/api/addConnection.md +101 -0
- package/docs/api/addNode.md +137 -0
- package/docs/api/autoLayout.md +77 -0
- package/docs/api/getFlowData.md +112 -0
- package/docs/api/marshalToView.md +95 -0
- package/docs/api/openPanel.md +128 -0
- package/docs/api/registerHandler.md +174 -0
- package/docs/api/registerNodeType.md +142 -0
- package/docs/api/removeConnection.md +57 -0
- package/docs/api/removeNode.md +80 -0
- package/docs/api/saveLayout.md +152 -0
- package/docs/api/screenToSVGCoords.md +68 -0
- package/docs/api/selectNode.md +116 -0
- package/docs/api/setTheme.md +168 -0
- package/docs/api/setZoom.md +97 -0
- package/docs/api/toggleFullscreen.md +68 -0
- package/docs/card-help/EACH.md +19 -0
- package/docs/card-help/FREAD.md +24 -0
- package/docs/card-help/FWRITE.md +24 -0
- package/docs/card-help/GET.md +22 -0
- package/docs/card-help/ITE.md +23 -0
- package/docs/card-help/LOG.md +23 -0
- package/docs/card-help/NOTE.md +17 -0
- package/docs/card-help/PREV.md +18 -0
- package/docs/card-help/SET.md +27 -0
- package/docs/card-help/SPKL.md +22 -0
- package/docs/card-help/STAT.md +23 -0
- package/docs/card-help/SW.md +25 -0
- package/docs/css/docuserve.css +73 -0
- package/docs/index.html +39 -0
- package/docs/retold-catalog.json +169 -0
- package/docs/retold-keyword-index.json +13942 -0
- package/example_applications/simple_cards/package.json +1 -0
- package/example_applications/simple_cards/source/card-help-content.js +16 -0
- package/example_applications/simple_cards/source/cards/FlowCard-Comment.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-DataPreview.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-Each.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-FileRead.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-FileWrite.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-GetValue.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-IfThenElse.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-LogValues.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-SetValue.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-Sparkline.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-StatusMonitor.js +2 -0
- package/example_applications/simple_cards/source/cards/FlowCard-Switch.js +2 -0
- package/package.json +11 -7
- package/scripts/generate-card-help.js +214 -0
- package/source/Pict-Section-Flow.js +4 -0
- package/source/PictFlowCard.js +3 -1
- package/source/providers/PictProvider-Flow-CSS.js +245 -152
- package/source/providers/PictProvider-Flow-ConnectorShapes.js +24 -0
- package/source/providers/PictProvider-Flow-Geometry.js +195 -38
- package/source/providers/PictProvider-Flow-PanelChrome.js +14 -12
- package/source/services/PictService-Flow-ConnectionHandleManager.js +263 -0
- package/source/services/PictService-Flow-ConnectionRenderer.js +134 -183
- package/source/services/PictService-Flow-DataManager.js +338 -0
- package/source/services/PictService-Flow-InteractionManager.js +165 -7
- package/source/services/PictService-Flow-PathGenerator.js +282 -0
- package/source/services/PictService-Flow-PortRenderer.js +269 -0
- package/source/services/PictService-Flow-RenderManager.js +281 -0
- package/source/services/PictService-Flow-Tether.js +6 -42
- package/source/views/PictView-Flow-Node.js +2 -220
- package/source/views/PictView-Flow-PropertiesPanel.js +89 -44
- package/source/views/PictView-Flow.js +130 -882
- package/test/ConnectionHandleManager_tests.js +717 -0
- package/test/ConnectionRenderer_tests.js +591 -0
- package/test/DataManager_tests.js +859 -0
- package/test/Geometry_tests.js +767 -0
- package/test/PathGenerator_tests.js +978 -0
- package/test/PortRenderer_tests.js +367 -0
- package/test/RenderManager_tests.js +756 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
const libFable = require('fable');
|
|
2
|
+
const libChai = require('chai');
|
|
3
|
+
const libExpect = libChai.expect;
|
|
4
|
+
|
|
5
|
+
const libPortRenderer = require('../source/services/PictService-Flow-PortRenderer.js');
|
|
6
|
+
const libGeometry = require('../source/providers/PictProvider-Flow-Geometry.js');
|
|
7
|
+
|
|
8
|
+
suite
|
|
9
|
+
(
|
|
10
|
+
'PictService-Flow-PortRenderer',
|
|
11
|
+
function ()
|
|
12
|
+
{
|
|
13
|
+
let _Fable;
|
|
14
|
+
let _PortRenderer;
|
|
15
|
+
let _GeometryProvider;
|
|
16
|
+
let _MockFlowView;
|
|
17
|
+
|
|
18
|
+
// Simple mock SVG element for testing
|
|
19
|
+
function createMockSVGElement()
|
|
20
|
+
{
|
|
21
|
+
let tmpSelf =
|
|
22
|
+
{
|
|
23
|
+
_tag: '',
|
|
24
|
+
_attrs: {},
|
|
25
|
+
_children: [],
|
|
26
|
+
textContent: '',
|
|
27
|
+
setAttribute: function (pKey, pVal)
|
|
28
|
+
{
|
|
29
|
+
tmpSelf._attrs[pKey] = pVal;
|
|
30
|
+
},
|
|
31
|
+
getAttribute: function (pKey)
|
|
32
|
+
{
|
|
33
|
+
return tmpSelf._attrs[pKey] || null;
|
|
34
|
+
},
|
|
35
|
+
appendChild: function (pChild)
|
|
36
|
+
{
|
|
37
|
+
tmpSelf._children.push(pChild);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
return tmpSelf;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
setup
|
|
44
|
+
(
|
|
45
|
+
function ()
|
|
46
|
+
{
|
|
47
|
+
_Fable = new libFable({});
|
|
48
|
+
|
|
49
|
+
_GeometryProvider = new libGeometry(_Fable, {}, 'Geometry-Test');
|
|
50
|
+
|
|
51
|
+
_MockFlowView =
|
|
52
|
+
{
|
|
53
|
+
_GeometryProvider: _GeometryProvider,
|
|
54
|
+
_ConnectorShapesProvider: null,
|
|
55
|
+
_SVGHelperProvider:
|
|
56
|
+
{
|
|
57
|
+
createSVGElement: function (pTag)
|
|
58
|
+
{
|
|
59
|
+
let tmpEl = createMockSVGElement();
|
|
60
|
+
tmpEl._tag = pTag;
|
|
61
|
+
return tmpEl;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
_PortRenderer = new libPortRenderer(
|
|
67
|
+
_Fable, { FlowView: _MockFlowView }, 'PortRend-Test');
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// ---- Constructor ----
|
|
72
|
+
|
|
73
|
+
suite
|
|
74
|
+
(
|
|
75
|
+
'Constructor',
|
|
76
|
+
function ()
|
|
77
|
+
{
|
|
78
|
+
test
|
|
79
|
+
(
|
|
80
|
+
'should instantiate with correct serviceType',
|
|
81
|
+
function (fDone)
|
|
82
|
+
{
|
|
83
|
+
libExpect(_PortRenderer.serviceType).to.equal('PictServiceFlowPortRenderer');
|
|
84
|
+
fDone();
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
test
|
|
89
|
+
(
|
|
90
|
+
'should store FlowView reference',
|
|
91
|
+
function (fDone)
|
|
92
|
+
{
|
|
93
|
+
libExpect(_PortRenderer._FlowView).to.equal(_MockFlowView);
|
|
94
|
+
fDone();
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
test
|
|
99
|
+
(
|
|
100
|
+
'should handle missing FlowView',
|
|
101
|
+
function (fDone)
|
|
102
|
+
{
|
|
103
|
+
let tmpRenderer = new libPortRenderer(_Fable, {}, 'NoView');
|
|
104
|
+
libExpect(tmpRenderer._FlowView).to.be.null;
|
|
105
|
+
fDone();
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// ---- renderPorts ----
|
|
112
|
+
|
|
113
|
+
suite
|
|
114
|
+
(
|
|
115
|
+
'renderPorts',
|
|
116
|
+
function ()
|
|
117
|
+
{
|
|
118
|
+
test
|
|
119
|
+
(
|
|
120
|
+
'should render port circles into the group',
|
|
121
|
+
function (fDone)
|
|
122
|
+
{
|
|
123
|
+
let tmpGroup = createMockSVGElement();
|
|
124
|
+
let tmpNodeData =
|
|
125
|
+
{
|
|
126
|
+
Hash: 'node-1',
|
|
127
|
+
Ports:
|
|
128
|
+
[
|
|
129
|
+
{ Hash: 'p1', Direction: 'input', Label: null },
|
|
130
|
+
{ Hash: 'p2', Direction: 'output', Label: null }
|
|
131
|
+
]
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
_PortRenderer.renderPorts(tmpNodeData, tmpGroup, 180, 80, null, 22);
|
|
135
|
+
|
|
136
|
+
// Should have appended port circle elements
|
|
137
|
+
libExpect(tmpGroup._children.length).to.be.at.least(2);
|
|
138
|
+
|
|
139
|
+
// Verify at least one circle element was created
|
|
140
|
+
let tmpCircles = tmpGroup._children.filter(function (pChild)
|
|
141
|
+
{
|
|
142
|
+
return pChild._tag === 'circle';
|
|
143
|
+
});
|
|
144
|
+
libExpect(tmpCircles.length).to.equal(2);
|
|
145
|
+
fDone();
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
test
|
|
150
|
+
(
|
|
151
|
+
'should render port labels when Label is set',
|
|
152
|
+
function (fDone)
|
|
153
|
+
{
|
|
154
|
+
let tmpGroup = createMockSVGElement();
|
|
155
|
+
let tmpNodeData =
|
|
156
|
+
{
|
|
157
|
+
Hash: 'node-2',
|
|
158
|
+
Ports:
|
|
159
|
+
[
|
|
160
|
+
{ Hash: 'p1', Direction: 'input', Label: 'Trigger' }
|
|
161
|
+
]
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
_PortRenderer.renderPorts(tmpNodeData, tmpGroup, 180, 80, null, 22);
|
|
165
|
+
|
|
166
|
+
// Should have badge bg, border path, stripe, circle, text = 5 elements
|
|
167
|
+
libExpect(tmpGroup._children.length).to.equal(5);
|
|
168
|
+
|
|
169
|
+
// Verify text element exists with correct content
|
|
170
|
+
let tmpTextEls = tmpGroup._children.filter(function (pChild)
|
|
171
|
+
{
|
|
172
|
+
return pChild._tag === 'text';
|
|
173
|
+
});
|
|
174
|
+
libExpect(tmpTextEls.length).to.equal(1);
|
|
175
|
+
libExpect(tmpTextEls[0].textContent).to.equal('Trigger');
|
|
176
|
+
fDone();
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
test
|
|
181
|
+
(
|
|
182
|
+
'should do nothing for empty ports array',
|
|
183
|
+
function (fDone)
|
|
184
|
+
{
|
|
185
|
+
let tmpGroup = createMockSVGElement();
|
|
186
|
+
let tmpNodeData = { Hash: 'node-3', Ports: [] };
|
|
187
|
+
|
|
188
|
+
_PortRenderer.renderPorts(tmpNodeData, tmpGroup, 180, 80, null, 22);
|
|
189
|
+
|
|
190
|
+
libExpect(tmpGroup._children.length).to.equal(0);
|
|
191
|
+
fDone();
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
test
|
|
196
|
+
(
|
|
197
|
+
'should do nothing when Ports is missing',
|
|
198
|
+
function (fDone)
|
|
199
|
+
{
|
|
200
|
+
let tmpGroup = createMockSVGElement();
|
|
201
|
+
let tmpNodeData = { Hash: 'node-4' };
|
|
202
|
+
|
|
203
|
+
_PortRenderer.renderPorts(tmpNodeData, tmpGroup, 180, 80, null, 22);
|
|
204
|
+
|
|
205
|
+
libExpect(tmpGroup._children.length).to.equal(0);
|
|
206
|
+
fDone();
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
test
|
|
211
|
+
(
|
|
212
|
+
'should do nothing when no FlowView',
|
|
213
|
+
function (fDone)
|
|
214
|
+
{
|
|
215
|
+
let tmpRenderer = new libPortRenderer(_Fable, {}, 'NoView');
|
|
216
|
+
let tmpGroup = createMockSVGElement();
|
|
217
|
+
let tmpNodeData =
|
|
218
|
+
{
|
|
219
|
+
Hash: 'node-5',
|
|
220
|
+
Ports: [{ Hash: 'p1', Direction: 'input' }]
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
tmpRenderer.renderPorts(tmpNodeData, tmpGroup, 180, 80, null, 22);
|
|
224
|
+
libExpect(tmpGroup._children.length).to.equal(0);
|
|
225
|
+
fDone();
|
|
226
|
+
}
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
test
|
|
230
|
+
(
|
|
231
|
+
'should use ConnectorShapesProvider when available',
|
|
232
|
+
function (fDone)
|
|
233
|
+
{
|
|
234
|
+
let tmpCreatePortCalled = false;
|
|
235
|
+
_MockFlowView._ConnectorShapesProvider =
|
|
236
|
+
{
|
|
237
|
+
createPortElement: function (pPort, pPos, pNodeHash)
|
|
238
|
+
{
|
|
239
|
+
tmpCreatePortCalled = true;
|
|
240
|
+
let tmpEl = createMockSVGElement();
|
|
241
|
+
tmpEl._tag = 'circle';
|
|
242
|
+
return tmpEl;
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
let tmpGroup = createMockSVGElement();
|
|
247
|
+
let tmpNodeData =
|
|
248
|
+
{
|
|
249
|
+
Hash: 'node-6',
|
|
250
|
+
Ports: [{ Hash: 'p1', Direction: 'input' }]
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
_PortRenderer.renderPorts(tmpNodeData, tmpGroup, 180, 80, null, 22);
|
|
254
|
+
libExpect(tmpCreatePortCalled).to.be.true;
|
|
255
|
+
|
|
256
|
+
// Clean up
|
|
257
|
+
_MockFlowView._ConnectorShapesProvider = null;
|
|
258
|
+
fDone();
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
test
|
|
263
|
+
(
|
|
264
|
+
'should set port-type data attribute when PortType is set',
|
|
265
|
+
function (fDone)
|
|
266
|
+
{
|
|
267
|
+
let tmpGroup = createMockSVGElement();
|
|
268
|
+
let tmpNodeData =
|
|
269
|
+
{
|
|
270
|
+
Hash: 'node-7',
|
|
271
|
+
Ports:
|
|
272
|
+
[
|
|
273
|
+
{ Hash: 'p1', Direction: 'input', PortType: 'event-in' }
|
|
274
|
+
]
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
_PortRenderer.renderPorts(tmpNodeData, tmpGroup, 180, 80, null, 22);
|
|
278
|
+
|
|
279
|
+
let tmpCircles = tmpGroup._children.filter(function (pChild)
|
|
280
|
+
{
|
|
281
|
+
return pChild._tag === 'circle';
|
|
282
|
+
});
|
|
283
|
+
libExpect(tmpCircles.length).to.equal(1);
|
|
284
|
+
libExpect(tmpCircles[0]._attrs['data-port-type']).to.equal('event-in');
|
|
285
|
+
fDone();
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
test
|
|
290
|
+
(
|
|
291
|
+
'should group ports by Side value',
|
|
292
|
+
function (fDone)
|
|
293
|
+
{
|
|
294
|
+
let tmpGroup = createMockSVGElement();
|
|
295
|
+
let tmpNodeData =
|
|
296
|
+
{
|
|
297
|
+
Hash: 'node-8',
|
|
298
|
+
Ports:
|
|
299
|
+
[
|
|
300
|
+
{ Hash: 'p1', Direction: 'input', Side: 'left' },
|
|
301
|
+
{ Hash: 'p2', Direction: 'input', Side: 'left' },
|
|
302
|
+
{ Hash: 'p3', Direction: 'output', Side: 'right' },
|
|
303
|
+
{ Hash: 'p4', Direction: 'output', Side: 'bottom' }
|
|
304
|
+
]
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
_PortRenderer.renderPorts(tmpNodeData, tmpGroup, 180, 80, null, 22);
|
|
308
|
+
|
|
309
|
+
let tmpCircles = tmpGroup._children.filter(function (pChild)
|
|
310
|
+
{
|
|
311
|
+
return pChild._tag === 'circle';
|
|
312
|
+
});
|
|
313
|
+
libExpect(tmpCircles.length).to.equal(4);
|
|
314
|
+
fDone();
|
|
315
|
+
}
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
// ---- getPortLocalPosition ----
|
|
321
|
+
|
|
322
|
+
suite
|
|
323
|
+
(
|
|
324
|
+
'getPortLocalPosition',
|
|
325
|
+
function ()
|
|
326
|
+
{
|
|
327
|
+
test
|
|
328
|
+
(
|
|
329
|
+
'should delegate to GeometryProvider',
|
|
330
|
+
function (fDone)
|
|
331
|
+
{
|
|
332
|
+
let tmpPos = _PortRenderer.getPortLocalPosition('left', 0, 1, 180, 80, 22, {});
|
|
333
|
+
|
|
334
|
+
libExpect(tmpPos).to.have.property('x');
|
|
335
|
+
libExpect(tmpPos).to.have.property('y');
|
|
336
|
+
libExpect(tmpPos.x).to.equal(0); // left edge
|
|
337
|
+
fDone();
|
|
338
|
+
}
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
test
|
|
342
|
+
(
|
|
343
|
+
'should return right edge position',
|
|
344
|
+
function (fDone)
|
|
345
|
+
{
|
|
346
|
+
let tmpPos = _PortRenderer.getPortLocalPosition('right', 0, 1, 180, 80, 22, {});
|
|
347
|
+
|
|
348
|
+
libExpect(tmpPos.x).to.equal(180); // right edge
|
|
349
|
+
fDone();
|
|
350
|
+
}
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
test
|
|
354
|
+
(
|
|
355
|
+
'should pass title bar height correctly',
|
|
356
|
+
function (fDone)
|
|
357
|
+
{
|
|
358
|
+
// Port should be below the title bar
|
|
359
|
+
let tmpPos = _PortRenderer.getPortLocalPosition('left', 0, 1, 180, 80, 22, {});
|
|
360
|
+
libExpect(tmpPos.y).to.be.greaterThan(22);
|
|
361
|
+
fDone();
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
);
|