pict-section-flow 1.4.0 → 2.0.0

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.
Files changed (164) hide show
  1. package/package.json +7 -2
  2. package/source/Pict-Section-Flow.js +20 -14
  3. package/source/providers/PictProvider-Flow-Background.js +303 -0
  4. package/source/providers/PictProvider-Flow-CSS.js +73 -7
  5. package/source/providers/PictProvider-Flow-Geometry.js +11 -421
  6. package/source/providers/PictProvider-Flow-Icons.js +12 -0
  7. package/source/providers/PictProvider-Flow-Layouts.js +107 -0
  8. package/source/services/PictService-Flow-ConnectionRenderer.js +1 -1
  9. package/source/services/PictService-Flow-CursorManager.js +113 -0
  10. package/source/services/PictService-Flow-InteractionManager.js +439 -59
  11. package/source/services/PictService-Flow-Layout.js +21 -16
  12. package/source/services/PictService-Flow-PathGenerator.js +30 -417
  13. package/source/services/PictService-Flow-RenderManager.js +9 -1
  14. package/source/services/PictService-Flow-ViewportManager.js +102 -0
  15. package/source/views/PictView-Flow-FloatingToolbar.js +5 -1
  16. package/source/views/PictView-Flow-Node.js +29 -0
  17. package/source/views/PictView-Flow-Toolbar.js +50 -3
  18. package/source/views/PictView-Flow.js +591 -2
  19. package/.claude/launch.json +0 -11
  20. package/docs/.nojekyll +0 -0
  21. package/docs/Architecture.md +0 -163
  22. package/docs/Custom-Styling.md +0 -275
  23. package/docs/Data_Model.md +0 -149
  24. package/docs/Event_System.md +0 -156
  25. package/docs/Getting_Started.md +0 -237
  26. package/docs/Implementation_Reference.md +0 -528
  27. package/docs/Layout_Persistence.md +0 -117
  28. package/docs/README.md +0 -103
  29. package/docs/Theme_Integration.md +0 -150
  30. package/docs/_brand.json +0 -18
  31. package/docs/_cover.md +0 -17
  32. package/docs/_playground.json +0 -24
  33. package/docs/_sidebar.md +0 -57
  34. package/docs/_topbar.md +0 -8
  35. package/docs/_version.json +0 -7
  36. package/docs/api/PictFlowCard.md +0 -216
  37. package/docs/api/PictFlowCardPropertiesPanel.md +0 -235
  38. package/docs/api/addConnection.md +0 -101
  39. package/docs/api/addNode.md +0 -137
  40. package/docs/api/autoLayout.md +0 -77
  41. package/docs/api/getFlowData.md +0 -112
  42. package/docs/api/marshalToView.md +0 -95
  43. package/docs/api/openPanel.md +0 -128
  44. package/docs/api/registerHandler.md +0 -174
  45. package/docs/api/registerNodeType.md +0 -142
  46. package/docs/api/removeConnection.md +0 -57
  47. package/docs/api/removeNode.md +0 -80
  48. package/docs/api/saveLayout.md +0 -152
  49. package/docs/api/screenToSVGCoords.md +0 -68
  50. package/docs/api/selectNode.md +0 -116
  51. package/docs/api/setTheme.md +0 -168
  52. package/docs/api/setZoom.md +0 -97
  53. package/docs/api/toggleFullscreen.md +0 -68
  54. package/docs/card-help/EACH.md +0 -19
  55. package/docs/card-help/FREAD.md +0 -24
  56. package/docs/card-help/FWRITE.md +0 -24
  57. package/docs/card-help/GET.md +0 -22
  58. package/docs/card-help/ITE.md +0 -23
  59. package/docs/card-help/LOG.md +0 -23
  60. package/docs/card-help/NOTE.md +0 -17
  61. package/docs/card-help/PREV.md +0 -18
  62. package/docs/card-help/SET.md +0 -27
  63. package/docs/card-help/SPKL.md +0 -22
  64. package/docs/card-help/STAT.md +0 -23
  65. package/docs/card-help/SW.md +0 -25
  66. package/docs/diagrams/architecture-at-a-glance.excalidraw +0 -4270
  67. package/docs/diagrams/architecture-at-a-glance.mmd +0 -30
  68. package/docs/diagrams/architecture-at-a-glance.svg +0 -2
  69. package/docs/diagrams/data-flow.excalidraw +0 -1451
  70. package/docs/diagrams/data-flow.mmd +0 -17
  71. package/docs/diagrams/data-flow.svg +0 -2
  72. package/docs/diagrams/high-level-design.excalidraw +0 -5767
  73. package/docs/diagrams/high-level-design.mmd +0 -86
  74. package/docs/diagrams/high-level-design.svg +0 -2
  75. package/docs/diagrams/relationships.excalidraw +0 -3852
  76. package/docs/diagrams/relationships.mmd +0 -9
  77. package/docs/diagrams/relationships.svg +0 -2
  78. package/docs/diagrams/service-initialization-sequence.excalidraw +0 -1466
  79. package/docs/diagrams/service-initialization-sequence.mmd +0 -19
  80. package/docs/diagrams/service-initialization-sequence.svg +0 -2
  81. package/docs/diagrams/svg-layer-structure.excalidraw +0 -1060
  82. package/docs/diagrams/svg-layer-structure.mmd +0 -18
  83. package/docs/diagrams/svg-layer-structure.svg +0 -2
  84. package/docs/examples/README.md +0 -9
  85. package/docs/examples/simple_cards/README.md +0 -677
  86. package/docs/examples/simple_cards/css/flowexample.css +0 -65
  87. package/docs/examples/simple_cards/index.html +0 -32
  88. package/docs/examples/simple_cards/js/pict.min.js +0 -12
  89. package/docs/examples/simple_cards/pict-section-flow-example-simple-cards.compatible.min.js +0 -1
  90. package/docs/index.html +0 -38
  91. package/docs/playground/app.json +0 -6
  92. package/docs/playground/appdata.json +0 -85
  93. package/docs/playground/application.js +0 -23
  94. package/docs/playground/pict.json +0 -17
  95. package/docs/playground/runtime/pict-application.min.js +0 -2
  96. package/docs/playground/runtime/pict-section-flow.min.js +0 -2
  97. package/docs/playground/runtime/pict-section-modal.min.js +0 -2
  98. package/docs/playground/runtime/pict.min.js +0 -12
  99. package/docs/retold-catalog.json +0 -244
  100. package/docs/retold-keyword-index.json +0 -26028
  101. package/example_applications/simple_cards/css/flowexample.css +0 -65
  102. package/example_applications/simple_cards/html/index.html +0 -32
  103. package/example_applications/simple_cards/package.json +0 -52
  104. package/example_applications/simple_cards/source/Pict-Application-FlowExample-Configuration.json +0 -15
  105. package/example_applications/simple_cards/source/Pict-Application-FlowExample.js +0 -539
  106. package/example_applications/simple_cards/source/card-help-content.js +0 -16
  107. package/example_applications/simple_cards/source/cards/FlowCard-Comment.js +0 -38
  108. package/example_applications/simple_cards/source/cards/FlowCard-DataPreview.js +0 -44
  109. package/example_applications/simple_cards/source/cards/FlowCard-Each.js +0 -38
  110. package/example_applications/simple_cards/source/cards/FlowCard-FileRead.js +0 -56
  111. package/example_applications/simple_cards/source/cards/FlowCard-FileWrite.js +0 -50
  112. package/example_applications/simple_cards/source/cards/FlowCard-GetValue.js +0 -37
  113. package/example_applications/simple_cards/source/cards/FlowCard-IfThenElse.js +0 -49
  114. package/example_applications/simple_cards/source/cards/FlowCard-LogValues.js +0 -55
  115. package/example_applications/simple_cards/source/cards/FlowCard-SetValue.js +0 -97
  116. package/example_applications/simple_cards/source/cards/FlowCard-Sparkline.js +0 -100
  117. package/example_applications/simple_cards/source/cards/FlowCard-StatusMonitor.js +0 -46
  118. package/example_applications/simple_cards/source/cards/FlowCard-Switch.js +0 -39
  119. package/example_applications/simple_cards/source/providers/PictRouter-FlowExample-Configuration.json +0 -22
  120. package/example_applications/simple_cards/source/sample-flows.js +0 -410
  121. package/example_applications/simple_cards/source/views/PictView-FlowExample-About.js +0 -184
  122. package/example_applications/simple_cards/source/views/PictView-FlowExample-BottomBar.js +0 -77
  123. package/example_applications/simple_cards/source/views/PictView-FlowExample-Documentation.js +0 -325
  124. package/example_applications/simple_cards/source/views/PictView-FlowExample-FileWriteInfo.js +0 -59
  125. package/example_applications/simple_cards/source/views/PictView-FlowExample-Layout.js +0 -90
  126. package/example_applications/simple_cards/source/views/PictView-FlowExample-MainWorkspace.js +0 -453
  127. package/example_applications/simple_cards/source/views/PictView-FlowExample-TopBar.js +0 -95
  128. package/scripts/generate-card-help.js +0 -214
  129. package/source/providers/edges/Edge-Bezier.js +0 -41
  130. package/source/providers/edges/Edge-Orthogonal.js +0 -37
  131. package/source/providers/edges/Edge-OrthogonalSnap.js +0 -72
  132. package/source/providers/edges/Edge-Perimeter-Linear.js +0 -31
  133. package/source/providers/edges/Edge-Perimeter-Orthogonal.js +0 -39
  134. package/source/providers/edges/Edge-Perimeter.js +0 -48
  135. package/source/providers/edges/Edge-PerimeterMath.js +0 -92
  136. package/source/providers/edges/Edge-Straight.js +0 -24
  137. package/source/providers/layouts/Layout-Circular.js +0 -203
  138. package/source/providers/layouts/Layout-Coerce.js +0 -40
  139. package/source/providers/layouts/Layout-Columnar.js +0 -134
  140. package/source/providers/layouts/Layout-Custom.js +0 -27
  141. package/source/providers/layouts/Layout-ForcedFromCenter.js +0 -256
  142. package/source/providers/layouts/Layout-Grid.js +0 -134
  143. package/source/providers/layouts/Layout-Layered.js +0 -155
  144. package/source/providers/layouts/Layout-Rank.js +0 -141
  145. package/source/providers/layouts/Layout-Staggered.js +0 -131
  146. package/source/providers/layouts/Layout-Tabular.js +0 -94
  147. package/test/CardPalette_tests.js +0 -43
  148. package/test/ConnectionHandleManager_tests.js +0 -717
  149. package/test/ConnectionRenderer_tests.js +0 -591
  150. package/test/ConnectionStyle_tests.js +0 -90
  151. package/test/DataManager_tests.js +0 -859
  152. package/test/Geometry_tests.js +0 -767
  153. package/test/InteractionManager_tests.js +0 -279
  154. package/test/Layout_tests.js +0 -1604
  155. package/test/NodeView_tests.js +0 -66
  156. package/test/PanelManager_tests.js +0 -172
  157. package/test/PathGenerator_tests.js +0 -978
  158. package/test/PortRenderer_tests.js +0 -376
  159. package/test/RenderManager_tests.js +0 -756
  160. package/test/Renderer_tests.js +0 -133
  161. package/test/SelectionManager_tests.js +0 -185
  162. package/test/StylePresets_tests.js +0 -153
  163. package/test/ToolbarExtraButtons_tests.js +0 -138
  164. package/test/UndirectedConnections_tests.js +0 -70
@@ -1,214 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * generate-card-help.js
4
- *
5
- * Reads markdown files from docs/card-help/ and generates a CommonJS module
6
- * that exports an object mapping card codes to rendered HTML strings.
7
- *
8
- * Each markdown file is named by its card code (e.g. ITE.md, SET.md).
9
- * The file content is converted from markdown to HTML and embedded as a
10
- * string in the generated module.
11
- *
12
- * Usage:
13
- * node scripts/generate-card-help.js [source_dir] [output_file]
14
- *
15
- * Defaults:
16
- * source_dir = docs/card-help
17
- * output_file = example_applications/simple_cards/source/card-help-content.js
18
- *
19
- * If the source directory does not exist or contains no markdown files the
20
- * script writes an empty map and exits cleanly — the build never fails due
21
- * to missing documentation.
22
- */
23
-
24
- const libFS = require('fs');
25
- const libPath = require('path');
26
-
27
- // ---------------------------------------------------------------------------
28
- // Minimal markdown-to-HTML converter
29
- // ---------------------------------------------------------------------------
30
- // Handles the subset of markdown used in card help documentation:
31
- // headings (#, ##, ###), bold (**), italic (*), inline code (`),
32
- // unordered lists (- or *), ordered lists (1.), paragraphs, line breaks,
33
- // and horizontal rules (---).
34
- // ---------------------------------------------------------------------------
35
-
36
- function convertMarkdownToHTML(pMarkdown)
37
- {
38
- let tmpLines = pMarkdown.split('\n');
39
- let tmpHTML = [];
40
- let tmpInList = false;
41
- let tmpListType = '';
42
- let tmpParagraph = [];
43
-
44
- function flushParagraph()
45
- {
46
- if (tmpParagraph.length > 0)
47
- {
48
- tmpHTML.push('<p>' + tmpParagraph.join(' ') + '</p>');
49
- tmpParagraph = [];
50
- }
51
- }
52
-
53
- function closeList()
54
- {
55
- if (tmpInList)
56
- {
57
- tmpHTML.push(tmpListType === 'ul' ? '</ul>' : '</ol>');
58
- tmpInList = false;
59
- tmpListType = '';
60
- }
61
- }
62
-
63
- function inlineFormat(pText)
64
- {
65
- // Inline code
66
- pText = pText.replace(/`([^`]+)`/g, '<code>$1</code>');
67
- // Bold (** or __)
68
- pText = pText.replace(/\*\*([^*]+)\*\*/g, '<b>$1</b>');
69
- pText = pText.replace(/__([^_]+)__/g, '<b>$1</b>');
70
- // Italic (* or _)
71
- pText = pText.replace(/\*([^*]+)\*/g, '<i>$1</i>');
72
- pText = pText.replace(/(?<!\w)_([^_]+)_(?!\w)/g, '<i>$1</i>');
73
- // Links
74
- pText = pText.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
75
- return pText;
76
- }
77
-
78
- for (let i = 0; i < tmpLines.length; i++)
79
- {
80
- let tmpLine = tmpLines[i];
81
- let tmpTrimmed = tmpLine.trim();
82
-
83
- // Empty line — flush paragraph
84
- if (tmpTrimmed === '')
85
- {
86
- flushParagraph();
87
- continue;
88
- }
89
-
90
- // Horizontal rule
91
- if (/^-{3,}$/.test(tmpTrimmed) || /^\*{3,}$/.test(tmpTrimmed))
92
- {
93
- flushParagraph();
94
- closeList();
95
- tmpHTML.push('<hr>');
96
- continue;
97
- }
98
-
99
- // Headings
100
- let tmpHeadingMatch = tmpTrimmed.match(/^(#{1,6})\s+(.*)$/);
101
- if (tmpHeadingMatch)
102
- {
103
- flushParagraph();
104
- closeList();
105
- let tmpLevel = tmpHeadingMatch[1].length;
106
- tmpHTML.push('<h' + tmpLevel + '>' + inlineFormat(tmpHeadingMatch[2]) + '</h' + tmpLevel + '>');
107
- continue;
108
- }
109
-
110
- // Unordered list item (- or *)
111
- let tmpULMatch = tmpTrimmed.match(/^[-*]\s+(.*)$/);
112
- if (tmpULMatch)
113
- {
114
- flushParagraph();
115
- if (!tmpInList || tmpListType !== 'ul')
116
- {
117
- closeList();
118
- tmpHTML.push('<ul>');
119
- tmpInList = true;
120
- tmpListType = 'ul';
121
- }
122
- tmpHTML.push('<li>' + inlineFormat(tmpULMatch[1]) + '</li>');
123
- continue;
124
- }
125
-
126
- // Ordered list item (1. 2. etc)
127
- let tmpOLMatch = tmpTrimmed.match(/^\d+\.\s+(.*)$/);
128
- if (tmpOLMatch)
129
- {
130
- flushParagraph();
131
- if (!tmpInList || tmpListType !== 'ol')
132
- {
133
- closeList();
134
- tmpHTML.push('<ol>');
135
- tmpInList = true;
136
- tmpListType = 'ol';
137
- }
138
- tmpHTML.push('<li>' + inlineFormat(tmpOLMatch[1]) + '</li>');
139
- continue;
140
- }
141
-
142
- // Regular text — accumulate into paragraph
143
- closeList();
144
- tmpParagraph.push(inlineFormat(tmpTrimmed));
145
- }
146
-
147
- flushParagraph();
148
- closeList();
149
-
150
- return tmpHTML.join('');
151
- }
152
-
153
- // ---------------------------------------------------------------------------
154
- // Main
155
- // ---------------------------------------------------------------------------
156
-
157
- let tmpModuleRoot = libPath.resolve(__dirname, '..');
158
- let tmpSourceDir = process.argv[2]
159
- ? libPath.resolve(process.argv[2])
160
- : libPath.join(tmpModuleRoot, 'docs', 'card-help');
161
- let tmpOutputFile = process.argv[3]
162
- ? libPath.resolve(process.argv[3])
163
- : libPath.join(tmpModuleRoot, 'example_applications', 'simple_cards', 'source', 'card-help-content.js');
164
-
165
- let tmpHelpMap = {};
166
-
167
- // Gracefully handle missing source directory
168
- if (libFS.existsSync(tmpSourceDir))
169
- {
170
- let tmpFiles = libFS.readdirSync(tmpSourceDir).filter(
171
- (pFile) => { return pFile.endsWith('.md'); }
172
- );
173
-
174
- for (let i = 0; i < tmpFiles.length; i++)
175
- {
176
- let tmpFile = tmpFiles[i];
177
- let tmpCode = libPath.basename(tmpFile, '.md');
178
- try
179
- {
180
- let tmpContent = libFS.readFileSync(libPath.join(tmpSourceDir, tmpFile), 'utf8');
181
- let tmpHTML = convertMarkdownToHTML(tmpContent);
182
- if (tmpHTML.length > 0)
183
- {
184
- tmpHelpMap[tmpCode] = tmpHTML;
185
- }
186
- }
187
- catch (pError)
188
- {
189
- // Skip files that cannot be read — never fail the build
190
- console.warn('generate-card-help: skipping ' + tmpFile + ' (' + pError.message + ')');
191
- }
192
- }
193
-
194
- console.log('generate-card-help: processed ' + Object.keys(tmpHelpMap).length + ' card help files from ' + tmpSourceDir);
195
- }
196
- else
197
- {
198
- console.log('generate-card-help: no docs/card-help directory found — generating empty map');
199
- }
200
-
201
- // Ensure output directory exists
202
- let tmpOutputDir = libPath.dirname(tmpOutputFile);
203
- if (!libFS.existsSync(tmpOutputDir))
204
- {
205
- libFS.mkdirSync(tmpOutputDir, { recursive: true });
206
- }
207
-
208
- // Write the generated module
209
- let tmpOutput = '// Auto-generated by scripts/generate-card-help.js — do not edit manually.\n';
210
- tmpOutput += '// Source markdown files are in docs/card-help/\n';
211
- tmpOutput += 'module.exports = ' + JSON.stringify(tmpHelpMap, null, '\t') + ';\n';
212
-
213
- libFS.writeFileSync(tmpOutputFile, tmpOutput, 'utf8');
214
- console.log('generate-card-help: wrote ' + tmpOutputFile);
@@ -1,41 +0,0 @@
1
- /**
2
- * Edge-Bezier
3
- *
4
- * Default edge theme: smooth cubic bezier between source and target ports,
5
- * with departure/approach geometry derived from each port's `Side`. This
6
- * is a thin wrapper around the renderer's pre-existing bezier path
7
- * generator — selecting it is equivalent to the historical default.
8
- *
9
- * Honors per-connection multi-handle waypoints (BezierHandles) when
10
- * present so user-edited curves still survive.
11
- */
12
- module.exports =
13
- {
14
- Name: 'Bezier',
15
- Label: 'Bezier (smooth)',
16
- Description: 'Smooth cubic curves with side-aware departures.',
17
-
18
- GeneratePath: function (pContext)
19
- {
20
- let tmpHelpers = pContext.Helpers;
21
- let tmpSrc = pContext.Source;
22
- let tmpTgt = pContext.Target;
23
- let tmpData = (pContext.Connection && pContext.Connection.Data) || {};
24
-
25
- // Preserve user-customized multi-handle bezier waypoints.
26
- if (tmpData.HandleCustomized)
27
- {
28
- let tmpHandles = tmpHelpers.getBezierHandles(tmpData);
29
- if (tmpHandles.length > 0)
30
- {
31
- return tmpHelpers.generateMultiBezier(tmpSrc, tmpTgt, tmpHandles);
32
- }
33
- }
34
-
35
- return tmpHelpers.generateBezier(tmpSrc, tmpTgt);
36
- },
37
-
38
- DefaultParameters: {},
39
-
40
- ParameterSchema: {}
41
- };
@@ -1,37 +0,0 @@
1
- /**
2
- * Edge-Orthogonal
3
- *
4
- * Right-angle (Manhattan) routing between source and target. Reads
5
- * cleanly for layered DAGs and grid-shaped layouts. Per-connection
6
- * `OrthoMidOffset` and customized corner overrides are preserved.
7
- */
8
- module.exports =
9
- {
10
- Name: 'Orthogonal',
11
- Label: 'Orthogonal (right-angle)',
12
- Description: 'Right-angle routing — reads well for DAGs and grids.',
13
-
14
- GeneratePath: function (pContext)
15
- {
16
- let tmpHelpers = pContext.Helpers;
17
- let tmpSrc = pContext.Source;
18
- let tmpTgt = pContext.Target;
19
- let tmpData = (pContext.Connection && pContext.Connection.Data) || {};
20
-
21
- let tmpCorners = null;
22
- if (tmpData.HandleCustomized && tmpData.OrthoCorner1X != null)
23
- {
24
- tmpCorners =
25
- {
26
- corner1: { x: tmpData.OrthoCorner1X, y: tmpData.OrthoCorner1Y },
27
- corner2: { x: tmpData.OrthoCorner2X, y: tmpData.OrthoCorner2Y }
28
- };
29
- }
30
-
31
- return tmpHelpers.generateOrthogonal(tmpSrc, tmpTgt, tmpCorners, tmpData.OrthoMidOffset || 0);
32
- },
33
-
34
- DefaultParameters: {},
35
-
36
- ParameterSchema: {}
37
- };
@@ -1,72 +0,0 @@
1
- const libCoerce = require('../layouts/Layout-Coerce.js');
2
-
3
- /**
4
- * Edge-OrthogonalSnap
5
- *
6
- * Demonstrates the "edge theme can affect node placement" axis. Same
7
- * right-angle routing as Edge-Orthogonal, but with an `AdjustLayout`
8
- * pass that snaps every node's X/Y to a grid so corner segments line
9
- * up cleanly across the diagram.
10
- *
11
- * Trade-off: nodes shift slightly from the layout's natural positions
12
- * to gain visual alignment. The user opts into this by picking the
13
- * theme — the layout algorithm itself is unaware.
14
- */
15
- module.exports =
16
- {
17
- Name: 'OrthogonalSnap',
18
- Label: 'Orthogonal (snap to grid)',
19
- Description: 'Right-angle routing; snaps node positions to a grid for cleaner corner alignment. Demonstrates an edge theme that adjusts node placement.',
20
-
21
- GeneratePath: function (pContext)
22
- {
23
- let tmpHelpers = pContext.Helpers;
24
- let tmpSrc = pContext.Source;
25
- let tmpTgt = pContext.Target;
26
- let tmpData = (pContext.Connection && pContext.Connection.Data) || {};
27
-
28
- let tmpCorners = null;
29
- if (tmpData.HandleCustomized && tmpData.OrthoCorner1X != null)
30
- {
31
- tmpCorners =
32
- {
33
- corner1: { x: tmpData.OrthoCorner1X, y: tmpData.OrthoCorner1Y },
34
- corner2: { x: tmpData.OrthoCorner2X, y: tmpData.OrthoCorner2Y }
35
- };
36
- }
37
-
38
- return tmpHelpers.generateOrthogonal(tmpSrc, tmpTgt, tmpCorners, tmpData.OrthoMidOffset || 0);
39
- },
40
-
41
- /**
42
- * Snap each node's (X, Y) to the configured grid after the layout
43
- * has run. Mutates pNodes in place.
44
- *
45
- * @param {Array} pNodes
46
- * @param {Array} pConnections
47
- * @param {Object} pParameters
48
- */
49
- AdjustLayout: function (pNodes, pConnections, pParameters)
50
- {
51
- let tmpGridSize = libCoerce.toFloat((pParameters || {}).GridSize, 20);
52
- if (tmpGridSize <= 0) return;
53
-
54
- for (let i = 0; i < pNodes.length; i++)
55
- {
56
- let tmpNode = pNodes[i];
57
- if (typeof tmpNode.X !== 'number' || typeof tmpNode.Y !== 'number') continue;
58
- tmpNode.X = Math.round(tmpNode.X / tmpGridSize) * tmpGridSize;
59
- tmpNode.Y = Math.round(tmpNode.Y / tmpGridSize) * tmpGridSize;
60
- }
61
- },
62
-
63
- DefaultParameters:
64
- {
65
- GridSize: 20
66
- },
67
-
68
- ParameterSchema:
69
- {
70
- GridSize: { Type: 'PreciseNumber', Label: 'Grid size', Default: 20, Min: 1, Max: 200 }
71
- }
72
- };
@@ -1,31 +0,0 @@
1
- const libPerimeterMath = require('./Edge-PerimeterMath.js');
2
-
3
- /**
4
- * Edge-Perimeter-Linear
5
- *
6
- * Perimeter attachment + literal straight line between the two
7
- * resolved exit points. Reads cleanly for force-directed and circular
8
- * layouts where the topology already determines edge angles, and the
9
- * curves of bezier add visual noise.
10
- */
11
- module.exports =
12
- {
13
- Name: 'Perimeter-Linear',
14
- Label: 'Perimeter (linear)',
15
- Description: 'Each connection exits the node at the perimeter, then runs as a straight line to the other end.',
16
-
17
- GeneratePath: function (pContext)
18
- {
19
- let tmpS = pContext.Source;
20
- let tmpT = pContext.Target;
21
- return `M ${tmpS.x} ${tmpS.y} L ${tmpT.x} ${tmpT.y}`;
22
- },
23
-
24
- ResolveAttachment: function (pContext)
25
- {
26
- return libPerimeterMath.resolvePerimeterAttachment(pContext);
27
- },
28
-
29
- DefaultParameters: {},
30
- ParameterSchema: {}
31
- };
@@ -1,39 +0,0 @@
1
- const libPerimeterMath = require('./Edge-PerimeterMath.js');
2
-
3
- /**
4
- * Edge-Perimeter-Orthogonal
5
- *
6
- * Perimeter attachment + right-angle (Manhattan) routing between
7
- * the two resolved exit points. Best when the layout already has
8
- * grid-like structure (Grid, Mesh) and you want connections to
9
- * leave from whichever side faces the partner.
10
- */
11
- module.exports =
12
- {
13
- Name: 'Perimeter-Orthogonal',
14
- Label: 'Perimeter (orthogonal)',
15
- Description: 'Each connection exits the node at the perimeter, then routes via right-angle segments to the other end.',
16
-
17
- GeneratePath: function (pContext)
18
- {
19
- let tmpData = (pContext.Connection && pContext.Connection.Data) || {};
20
- let tmpCorners = null;
21
- if (tmpData.HandleCustomized && tmpData.OrthoCorner1X != null)
22
- {
23
- tmpCorners =
24
- {
25
- corner1: { x: tmpData.OrthoCorner1X, y: tmpData.OrthoCorner1Y },
26
- corner2: { x: tmpData.OrthoCorner2X, y: tmpData.OrthoCorner2Y }
27
- };
28
- }
29
- return pContext.Helpers.generateOrthogonal(pContext.Source, pContext.Target, tmpCorners, tmpData.OrthoMidOffset || 0);
30
- },
31
-
32
- ResolveAttachment: function (pContext)
33
- {
34
- return libPerimeterMath.resolvePerimeterAttachment(pContext);
35
- },
36
-
37
- DefaultParameters: {},
38
- ParameterSchema: {}
39
- };
@@ -1,48 +0,0 @@
1
- const libPerimeterMath = require('./Edge-PerimeterMath.js');
2
-
3
- /**
4
- * Edge-Perimeter (Bezier)
5
- *
6
- * "Smart exit" routing with smooth bezier curves. Each connection
7
- * exits the node at the perimeter point closest to its target —
8
- * solves star/hub topologies where many connections share one port.
9
- *
10
- * Renders the path as a side-aware bezier (uses the side returned by
11
- * `ResolveAttachment` so the curve departs in the right direction).
12
- *
13
- * See `Edge-Perimeter-Linear` and `Edge-Perimeter-Orthogonal` for the
14
- * straight-line and right-angle variants.
15
- */
16
- module.exports =
17
- {
18
- Name: 'Perimeter',
19
- Label: 'Perimeter (bezier)',
20
- Description: 'Each connection exits the node at the perimeter point closest to its target, with smooth bezier curves. Fixes star/hub topologies where many lines share one port.',
21
-
22
- GeneratePath: function (pContext)
23
- {
24
- // Honor user-edited bezier handles when the connection is selected
25
- // and dragged. Without this, the drag handles render but moving
26
- // them does nothing because Perimeter would always re-emit a
27
- // fresh side-aware bezier.
28
- let tmpHelpers = pContext.Helpers;
29
- let tmpData = (pContext.Connection && pContext.Connection.Data) || {};
30
- if (tmpData.HandleCustomized)
31
- {
32
- let tmpHandles = tmpHelpers.getBezierHandles(tmpData);
33
- if (tmpHandles.length > 0)
34
- {
35
- return tmpHelpers.generateMultiBezier(pContext.Source, pContext.Target, tmpHandles);
36
- }
37
- }
38
- return tmpHelpers.generateBezier(pContext.Source, pContext.Target);
39
- },
40
-
41
- ResolveAttachment: function (pContext)
42
- {
43
- return libPerimeterMath.resolvePerimeterAttachment(pContext);
44
- },
45
-
46
- DefaultParameters: {},
47
- ParameterSchema: {}
48
- };
@@ -1,92 +0,0 @@
1
- /**
2
- * Edge-PerimeterMath
3
- *
4
- * Shared geometry helper for the Perimeter family of edge themes
5
- * (Perimeter, Perimeter-Linear, Perimeter-Orthogonal). Solves the
6
- * "where on this node's bounding box should the line attach so it
7
- * points at the other end" question.
8
- *
9
- * The themes themselves only differ in how they render the path
10
- * between the two attachment points; the attachment math is identical.
11
- */
12
-
13
- /**
14
- * Resolve a perimeter attachment point for one end of a connection.
15
- * Traces a line from the node's center toward the other end and returns
16
- * the first crossing of the node's bounding-box perimeter, plus the
17
- * `side` of that crossing (so the bezier helper departs in the right
18
- * direction).
19
- *
20
- * @param {Object} pContext - the same shape the renderer passes into
21
- * ResolveAttachment (Node, OtherNode, OtherDefaultPosition,
22
- * DefaultPosition, …).
23
- * @returns {{x: number, y: number, side: string}|Object|null}
24
- * Returns null when node geometry is missing; returns
25
- * DefaultPosition (verbatim) for degenerate same-center cases.
26
- */
27
- function _resolvePerimeterAttachment(pContext)
28
- {
29
- let tmpNode = pContext.Node;
30
- if (!tmpNode || typeof tmpNode.X !== 'number' || typeof tmpNode.Y !== 'number') return null;
31
-
32
- let tmpW = tmpNode.Width || 180;
33
- let tmpH = tmpNode.Height || 80;
34
- let tmpCx = tmpNode.X + tmpW / 2;
35
- let tmpCy = tmpNode.Y + tmpH / 2;
36
-
37
- let tmpAimX, tmpAimY;
38
- if (pContext.OtherNode && typeof pContext.OtherNode.X === 'number')
39
- {
40
- let tmpOW = pContext.OtherNode.Width || 180;
41
- let tmpOH = pContext.OtherNode.Height || 80;
42
- tmpAimX = pContext.OtherNode.X + tmpOW / 2;
43
- tmpAimY = pContext.OtherNode.Y + tmpOH / 2;
44
- }
45
- else if (pContext.OtherDefaultPosition)
46
- {
47
- tmpAimX = pContext.OtherDefaultPosition.x;
48
- tmpAimY = pContext.OtherDefaultPosition.y;
49
- }
50
- else
51
- {
52
- return null;
53
- }
54
-
55
- let tmpDX = tmpAimX - tmpCx;
56
- let tmpDY = tmpAimY - tmpCy;
57
-
58
- if (tmpDX === 0 && tmpDY === 0) return pContext.DefaultPosition || null;
59
-
60
- let tmpHalfW = tmpW / 2;
61
- let tmpHalfH = tmpH / 2;
62
-
63
- let tmpTX = (tmpDX > 0) ? tmpHalfW / tmpDX
64
- : (tmpDX < 0) ? -tmpHalfW / tmpDX
65
- : Infinity;
66
- let tmpTY = (tmpDY > 0) ? tmpHalfH / tmpDY
67
- : (tmpDY < 0) ? -tmpHalfH / tmpDY
68
- : Infinity;
69
-
70
- let tmpT, tmpSide;
71
- if (tmpTX < tmpTY)
72
- {
73
- tmpT = tmpTX;
74
- tmpSide = (tmpDX > 0) ? 'right' : 'left';
75
- }
76
- else
77
- {
78
- tmpT = tmpTY;
79
- tmpSide = (tmpDY > 0) ? 'bottom' : 'top';
80
- }
81
-
82
- return {
83
- x: tmpCx + tmpT * tmpDX,
84
- y: tmpCy + tmpT * tmpDY,
85
- side: tmpSide
86
- };
87
- }
88
-
89
- module.exports =
90
- {
91
- resolvePerimeterAttachment: _resolvePerimeterAttachment
92
- };
@@ -1,24 +0,0 @@
1
- /**
2
- * Edge-Straight
3
- *
4
- * Literal straight line from source port to target port. Useful for
5
- * dense clusters where curves add visual noise, and for force-directed
6
- * layouts where the topology already determines edge angles.
7
- */
8
- module.exports =
9
- {
10
- Name: 'Straight',
11
- Label: 'Straight line',
12
- Description: 'Plain straight line between ports.',
13
-
14
- GeneratePath: function (pContext)
15
- {
16
- let tmpSrc = pContext.Source;
17
- let tmpTgt = pContext.Target;
18
- return `M ${tmpSrc.x} ${tmpSrc.y} L ${tmpTgt.x} ${tmpTgt.y}`;
19
- },
20
-
21
- DefaultParameters: {},
22
-
23
- ParameterSchema: {}
24
- };