pict-section-flow 1.0.0 → 1.0.1
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/docs/Theme_Integration.md +2 -2
- package/docs/index.html +0 -2
- package/package.json +3 -3
- package/source/PictFlowCard.js +2 -2
- package/source/providers/PictProvider-Flow-CSS.js +38 -12
- package/source/providers/PictProvider-Flow-ConnectorShapes.js +8 -8
- package/source/providers/PictProvider-Flow-Icons.js +33 -33
- package/source/providers/PictProvider-Flow-NodeTypes.js +9 -9
- package/source/providers/PictProvider-Flow-Renderer.js +516 -0
- package/source/providers/PictProvider-Flow-StylePresets.js +259 -0
- package/source/providers/PictProvider-Flow-Theme.js +97 -669
- package/source/services/PictService-Flow-ConnectionRenderer.js +6 -6
- package/source/services/PictService-Flow-PortRenderer.js +6 -6
- package/source/views/PictView-Flow-Node.js +1 -1
- package/source/views/PictView-Flow-PropertiesPanel.js +1 -1
- package/source/views/PictView-Flow-Toolbar.js +24 -16
- package/source/views/PictView-Flow.js +172 -47
- package/test/Renderer_tests.js +133 -0
- package/test/StylePresets_tests.js +153 -0
- package/docs/css/docuserve.css +0 -327
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
const libFableServiceProviderBase = require('fable-serviceproviderbase');
|
|
2
|
+
|
|
3
|
+
const _ProviderConfiguration =
|
|
4
|
+
{
|
|
5
|
+
ProviderIdentifier: 'PictProviderFlowRenderer'
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* PictProvider-Flow-Renderer
|
|
10
|
+
*
|
|
11
|
+
* Registry + active-state holder for the FLOW RENDERER axis.
|
|
12
|
+
*
|
|
13
|
+
* A "renderer" answers: *how do we draw a flow* — node body shape, border
|
|
14
|
+
* jitter, connection stroke style, arrowhead style, supplementary CSS for
|
|
15
|
+
* text treatment. It is **independent of color**. Color comes from the
|
|
16
|
+
* active pict-section-theme theme; the renderer only describes the visual
|
|
17
|
+
* vocabulary applied on top of those colors.
|
|
18
|
+
*
|
|
19
|
+
* This is the analogue of `EdgeTheme` for node + arrow + filter treatment.
|
|
20
|
+
* See PictService-Flow-Layout.js for the EdgeTheme pattern this mirrors.
|
|
21
|
+
*
|
|
22
|
+
* ## Renderer shape
|
|
23
|
+
*
|
|
24
|
+
* ```javascript
|
|
25
|
+
* {
|
|
26
|
+
* Key: 'sketch',
|
|
27
|
+
* Label: 'Sketch (jittery)',
|
|
28
|
+
*
|
|
29
|
+
* NodeBodyMode: 'bracket', // 'rect' | 'bracket'
|
|
30
|
+
* BracketConfig: { SerifLength: 20, TitleSeparator: true },
|
|
31
|
+
*
|
|
32
|
+
* NoiseConfig: { // hand-drawn jitter
|
|
33
|
+
* Enabled: true,
|
|
34
|
+
* DefaultLevel: 0.4,
|
|
35
|
+
* MaxJitterPx: 4,
|
|
36
|
+
* AffectsNodes: true,
|
|
37
|
+
* AffectsConnections: true
|
|
38
|
+
* },
|
|
39
|
+
*
|
|
40
|
+
* ConnectionConfig: { // edge stroke style
|
|
41
|
+
* StrokeDashArray: null,
|
|
42
|
+
* StrokeWidth: 1.5,
|
|
43
|
+
* ArrowheadStyle: 'triangle'
|
|
44
|
+
* },
|
|
45
|
+
*
|
|
46
|
+
* ShapeOverrides: { // per-shape SVG attrs
|
|
47
|
+
* 'arrowhead-connection': { Fill: 'var(--theme-color-text-secondary, #555)' },
|
|
48
|
+
* 'arrowhead-connection-selected': { Fill: 'var(--theme-color-brand-primary, #2255aa)' }
|
|
49
|
+
* },
|
|
50
|
+
*
|
|
51
|
+
* GeometryCSS: '', // optional :root :root rules for
|
|
52
|
+
* // --pf-node-body-stroke-width,
|
|
53
|
+
* // --pf-node-body-radius,
|
|
54
|
+
* // --pf-node-shadow*,
|
|
55
|
+
* // --pf-panel-shadow, --pf-panel-radius,
|
|
56
|
+
* // --pf-node-title-size/weight, etc.
|
|
57
|
+
*
|
|
58
|
+
* AdditionalCSS: '' // optional per-renderer extras
|
|
59
|
+
* // (font-family swaps, filters, scanlines)
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* ## API
|
|
64
|
+
*
|
|
65
|
+
* ```javascript
|
|
66
|
+
* pict.providers['PictProviderFlowRenderer'].register(key, definition);
|
|
67
|
+
* pict.providers['PictProviderFlowRenderer'].setRenderer('sketch');
|
|
68
|
+
* pict.providers['PictProviderFlowRenderer'].getActiveRenderer();
|
|
69
|
+
* pict.providers['PictProviderFlowRenderer'].getActiveRendererKey();
|
|
70
|
+
* pict.providers['PictProviderFlowRenderer'].getRendererKeys();
|
|
71
|
+
* pict.providers['PictProviderFlowRenderer'].getNoiseLevel();
|
|
72
|
+
* pict.providers['PictProviderFlowRenderer'].setNoiseLevel(0.5);
|
|
73
|
+
* pict.providers['PictProviderFlowRenderer'].getNodeNoiseAmplitude();
|
|
74
|
+
* pict.providers['PictProviderFlowRenderer'].processPathString(d, seed);
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* The FlowView wires this provider's GeometryCSS + AdditionalCSS into the
|
|
78
|
+
* CSS cascade on each `setRenderer()` call, plus applies ShapeOverrides
|
|
79
|
+
* through ConnectorShapesProvider (same flow the old monolithic theme used).
|
|
80
|
+
*/
|
|
81
|
+
class PictProviderFlowRenderer extends libFableServiceProviderBase
|
|
82
|
+
{
|
|
83
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
84
|
+
{
|
|
85
|
+
let tmpOptions = Object.assign({}, _ProviderConfiguration, pOptions);
|
|
86
|
+
super(pFable, tmpOptions, pServiceHash);
|
|
87
|
+
|
|
88
|
+
this.serviceType = 'PictProviderFlowRenderer';
|
|
89
|
+
|
|
90
|
+
this._FlowView = (pOptions && pOptions.FlowView) ? pOptions.FlowView : null;
|
|
91
|
+
|
|
92
|
+
this._ActiveRendererKey = 'clean';
|
|
93
|
+
this._NoiseLevel = 0;
|
|
94
|
+
this._Renderers = {};
|
|
95
|
+
|
|
96
|
+
this._registerBuiltInRenderers();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ── Registry ──────────────────────────────────────────────────────────
|
|
100
|
+
|
|
101
|
+
_registerBuiltInRenderers()
|
|
102
|
+
{
|
|
103
|
+
// 1. Clean — rectangle bodies, soft shadows, no jitter. Modern default.
|
|
104
|
+
this._Renderers['clean'] =
|
|
105
|
+
{
|
|
106
|
+
Key: 'clean',
|
|
107
|
+
Label: 'Clean',
|
|
108
|
+
NodeBodyMode: 'rect',
|
|
109
|
+
BracketConfig: null,
|
|
110
|
+
NoiseConfig:
|
|
111
|
+
{
|
|
112
|
+
Enabled: false,
|
|
113
|
+
DefaultLevel: 0,
|
|
114
|
+
MaxJitterPx: 0,
|
|
115
|
+
AffectsNodes: false,
|
|
116
|
+
AffectsConnections: false
|
|
117
|
+
},
|
|
118
|
+
ConnectionConfig:
|
|
119
|
+
{
|
|
120
|
+
StrokeDashArray: null,
|
|
121
|
+
StrokeWidth: 2,
|
|
122
|
+
ArrowheadStyle: 'triangle'
|
|
123
|
+
},
|
|
124
|
+
ShapeOverrides: {},
|
|
125
|
+
GeometryCSS: `
|
|
126
|
+
.pict-flow-container {
|
|
127
|
+
--pf-node-body-stroke-width: 1.5;
|
|
128
|
+
--pf-node-body-radius: 6px;
|
|
129
|
+
--pf-node-shadow: drop-shadow(0 1px 3px rgba(0,0,0,0.10));
|
|
130
|
+
--pf-node-shadow-hover: drop-shadow(0 2px 6px rgba(0,0,0,0.15));
|
|
131
|
+
--pf-node-shadow-selected: drop-shadow(0 0 6px var(--theme-color-brand-primary, #2255aa));
|
|
132
|
+
--pf-node-shadow-dragging: drop-shadow(0 4px 10px rgba(0,0,0,0.20));
|
|
133
|
+
--pf-node-title-size: 12px;
|
|
134
|
+
--pf-node-title-weight: 600;
|
|
135
|
+
--pf-panel-radius: 8px;
|
|
136
|
+
--pf-panel-shadow: 0 2px 8px rgba(0,0,0,0.12);
|
|
137
|
+
}
|
|
138
|
+
`,
|
|
139
|
+
AdditionalCSS: ''
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// 2. Bracket — `[ ]` body, no jitter. Sketch-like but precise.
|
|
143
|
+
this._Renderers['bracket'] =
|
|
144
|
+
{
|
|
145
|
+
Key: 'bracket',
|
|
146
|
+
Label: 'Bracket',
|
|
147
|
+
NodeBodyMode: 'bracket',
|
|
148
|
+
BracketConfig:
|
|
149
|
+
{
|
|
150
|
+
SerifLength: 20,
|
|
151
|
+
TitleSeparator: true
|
|
152
|
+
},
|
|
153
|
+
NoiseConfig:
|
|
154
|
+
{
|
|
155
|
+
Enabled: false,
|
|
156
|
+
DefaultLevel: 0,
|
|
157
|
+
MaxJitterPx: 0,
|
|
158
|
+
AffectsNodes: false,
|
|
159
|
+
AffectsConnections: false
|
|
160
|
+
},
|
|
161
|
+
ConnectionConfig:
|
|
162
|
+
{
|
|
163
|
+
StrokeDashArray: null,
|
|
164
|
+
StrokeWidth: 1.5,
|
|
165
|
+
ArrowheadStyle: 'triangle'
|
|
166
|
+
},
|
|
167
|
+
ShapeOverrides:
|
|
168
|
+
{
|
|
169
|
+
'arrowhead-connection': { Fill: 'var(--theme-color-text-secondary, #555555)' },
|
|
170
|
+
'arrowhead-connection-selected': { Fill: 'var(--theme-color-brand-primary, #2255aa)' }
|
|
171
|
+
},
|
|
172
|
+
GeometryCSS: `
|
|
173
|
+
.pict-flow-container {
|
|
174
|
+
--pf-node-body-stroke-width: 1.5;
|
|
175
|
+
--pf-node-body-radius: 0px;
|
|
176
|
+
--pf-node-shadow: none;
|
|
177
|
+
--pf-node-shadow-hover: none;
|
|
178
|
+
--pf-node-shadow-selected: none;
|
|
179
|
+
--pf-node-shadow-dragging: none;
|
|
180
|
+
--pf-node-title-size: 12px;
|
|
181
|
+
--pf-node-title-weight: 500;
|
|
182
|
+
--pf-panel-radius: 0px;
|
|
183
|
+
--pf-panel-shadow: 2px 2px 0px rgba(0,0,0,0.08);
|
|
184
|
+
}
|
|
185
|
+
`,
|
|
186
|
+
AdditionalCSS: ''
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// 3. Sketch — bracket + jitter on nodes and connections. Hand-drawn.
|
|
190
|
+
this._Renderers['sketch'] =
|
|
191
|
+
{
|
|
192
|
+
Key: 'sketch',
|
|
193
|
+
Label: 'Sketch',
|
|
194
|
+
NodeBodyMode: 'bracket',
|
|
195
|
+
BracketConfig:
|
|
196
|
+
{
|
|
197
|
+
SerifLength: 20,
|
|
198
|
+
TitleSeparator: true
|
|
199
|
+
},
|
|
200
|
+
NoiseConfig:
|
|
201
|
+
{
|
|
202
|
+
Enabled: true,
|
|
203
|
+
DefaultLevel: 0.4,
|
|
204
|
+
MaxJitterPx: 4,
|
|
205
|
+
AffectsNodes: true,
|
|
206
|
+
AffectsConnections: true
|
|
207
|
+
},
|
|
208
|
+
ConnectionConfig:
|
|
209
|
+
{
|
|
210
|
+
StrokeDashArray: null,
|
|
211
|
+
StrokeWidth: 1.5,
|
|
212
|
+
ArrowheadStyle: 'triangle'
|
|
213
|
+
},
|
|
214
|
+
ShapeOverrides:
|
|
215
|
+
{
|
|
216
|
+
'arrowhead-connection': { Fill: 'var(--theme-color-text-secondary, #555555)' },
|
|
217
|
+
'arrowhead-connection-selected': { Fill: 'var(--theme-color-brand-primary, #2255aa)' }
|
|
218
|
+
},
|
|
219
|
+
GeometryCSS: `
|
|
220
|
+
.pict-flow-container {
|
|
221
|
+
--pf-node-body-stroke-width: 1.5;
|
|
222
|
+
--pf-node-body-radius: 0px;
|
|
223
|
+
--pf-node-shadow: none;
|
|
224
|
+
--pf-node-shadow-hover: none;
|
|
225
|
+
--pf-node-shadow-selected: none;
|
|
226
|
+
--pf-node-shadow-dragging: none;
|
|
227
|
+
--pf-node-title-size: 12px;
|
|
228
|
+
--pf-node-title-weight: 400;
|
|
229
|
+
--pf-panel-radius: 0px;
|
|
230
|
+
--pf-panel-shadow: 2px 2px 0px rgba(0,0,0,0.08);
|
|
231
|
+
}
|
|
232
|
+
`,
|
|
233
|
+
AdditionalCSS: `
|
|
234
|
+
.pict-flow-node-title,
|
|
235
|
+
.pict-flow-node-type-label,
|
|
236
|
+
.pict-flow-port-label,
|
|
237
|
+
.pict-flow-node-card-code {
|
|
238
|
+
font-family: "Courier New", "Courier", monospace !important;
|
|
239
|
+
}
|
|
240
|
+
.pict-flow-panel-title-text,
|
|
241
|
+
.pict-flow-panel-node-props-title,
|
|
242
|
+
.pict-flow-info-panel {
|
|
243
|
+
font-family: "Courier New", "Courier", monospace !important;
|
|
244
|
+
}
|
|
245
|
+
.pict-flow-node-title-icon {
|
|
246
|
+
filter: brightness(0) !important;
|
|
247
|
+
}
|
|
248
|
+
`
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// 4. CRT — rectangular body + neon drop-shadow glow. No jitter, but a
|
|
252
|
+
// scanline / monospace text treatment for retro vibes.
|
|
253
|
+
this._Renderers['crt'] =
|
|
254
|
+
{
|
|
255
|
+
Key: 'crt',
|
|
256
|
+
Label: 'CRT',
|
|
257
|
+
NodeBodyMode: 'rect',
|
|
258
|
+
BracketConfig: null,
|
|
259
|
+
NoiseConfig:
|
|
260
|
+
{
|
|
261
|
+
Enabled: false,
|
|
262
|
+
DefaultLevel: 0,
|
|
263
|
+
MaxJitterPx: 0,
|
|
264
|
+
AffectsNodes: false,
|
|
265
|
+
AffectsConnections: false
|
|
266
|
+
},
|
|
267
|
+
ConnectionConfig:
|
|
268
|
+
{
|
|
269
|
+
StrokeDashArray: null,
|
|
270
|
+
StrokeWidth: 2,
|
|
271
|
+
ArrowheadStyle: 'triangle'
|
|
272
|
+
},
|
|
273
|
+
ShapeOverrides:
|
|
274
|
+
{
|
|
275
|
+
'arrowhead-connection': { Fill: 'var(--theme-color-brand-primary, #ff00ff)' },
|
|
276
|
+
'arrowhead-connection-selected': { Fill: 'var(--theme-color-brand-accent, #00ffff)' }
|
|
277
|
+
},
|
|
278
|
+
GeometryCSS: `
|
|
279
|
+
.pict-flow-container {
|
|
280
|
+
--pf-node-body-stroke-width: 2;
|
|
281
|
+
--pf-node-body-radius: 0px;
|
|
282
|
+
--pf-node-shadow: drop-shadow(0 0 8px color-mix(in srgb, var(--theme-color-brand-primary, #ff00ff) 40%, transparent));
|
|
283
|
+
--pf-node-shadow-hover: drop-shadow(0 0 12px color-mix(in srgb, var(--theme-color-brand-primary, #ff00ff) 60%, transparent));
|
|
284
|
+
--pf-node-shadow-selected: drop-shadow(0 0 16px color-mix(in srgb, var(--theme-color-brand-accent, #00ffff) 50%, transparent));
|
|
285
|
+
--pf-node-shadow-dragging: drop-shadow(0 0 20px color-mix(in srgb, var(--theme-color-brand-primary, #ff00ff) 70%, transparent));
|
|
286
|
+
--pf-node-title-size: 11px;
|
|
287
|
+
--pf-node-title-weight: 700;
|
|
288
|
+
--pf-panel-radius: 0px;
|
|
289
|
+
--pf-panel-shadow: 0 0 20px color-mix(in srgb, var(--theme-color-brand-primary, #ff00ff) 30%, transparent);
|
|
290
|
+
}
|
|
291
|
+
`,
|
|
292
|
+
AdditionalCSS: `
|
|
293
|
+
.pict-flow-node-title,
|
|
294
|
+
.pict-flow-node-type-label,
|
|
295
|
+
.pict-flow-port-label,
|
|
296
|
+
.pict-flow-node-card-code {
|
|
297
|
+
font-family: "Courier New", monospace !important;
|
|
298
|
+
text-transform: uppercase;
|
|
299
|
+
letter-spacing: 0.5px;
|
|
300
|
+
}
|
|
301
|
+
.pict-flow-connection {
|
|
302
|
+
filter: drop-shadow(0 0 3px color-mix(in srgb, var(--theme-color-brand-primary, #ff00ff) 40%, transparent));
|
|
303
|
+
}
|
|
304
|
+
`
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// 5. Workstation — chunky 90s OS aesthetic. Rectangle with hard offset
|
|
308
|
+
// drop-shadow, no jitter, weighty title bar.
|
|
309
|
+
this._Renderers['workstation'] =
|
|
310
|
+
{
|
|
311
|
+
Key: 'workstation',
|
|
312
|
+
Label: 'Workstation',
|
|
313
|
+
NodeBodyMode: 'rect',
|
|
314
|
+
BracketConfig: null,
|
|
315
|
+
NoiseConfig:
|
|
316
|
+
{
|
|
317
|
+
Enabled: false,
|
|
318
|
+
DefaultLevel: 0,
|
|
319
|
+
MaxJitterPx: 0,
|
|
320
|
+
AffectsNodes: false,
|
|
321
|
+
AffectsConnections: false
|
|
322
|
+
},
|
|
323
|
+
ConnectionConfig:
|
|
324
|
+
{
|
|
325
|
+
StrokeDashArray: null,
|
|
326
|
+
StrokeWidth: 2,
|
|
327
|
+
ArrowheadStyle: 'triangle'
|
|
328
|
+
},
|
|
329
|
+
ShapeOverrides:
|
|
330
|
+
{
|
|
331
|
+
'arrowhead-connection': { Fill: 'var(--theme-color-border-default, #808080)' },
|
|
332
|
+
'arrowhead-connection-selected': { Fill: 'var(--theme-color-focus-outline, #008080)' }
|
|
333
|
+
},
|
|
334
|
+
GeometryCSS: `
|
|
335
|
+
.pict-flow-container {
|
|
336
|
+
--pf-node-body-stroke-width: 1;
|
|
337
|
+
--pf-node-body-radius: 0px;
|
|
338
|
+
--pf-node-shadow: drop-shadow(2px 2px 0px var(--theme-color-border-strong, #404040));
|
|
339
|
+
--pf-node-shadow-hover: drop-shadow(3px 3px 0px var(--theme-color-border-strong, #404040));
|
|
340
|
+
--pf-node-shadow-selected: drop-shadow(2px 2px 0px var(--theme-color-focus-outline, #008080));
|
|
341
|
+
--pf-node-shadow-dragging: drop-shadow(4px 4px 0px var(--theme-color-border-strong, #404040));
|
|
342
|
+
--pf-node-title-size: 11px;
|
|
343
|
+
--pf-node-title-weight: 700;
|
|
344
|
+
--pf-panel-radius: 0px;
|
|
345
|
+
--pf-panel-shadow: 2px 2px 0px var(--theme-color-border-strong, #404040);
|
|
346
|
+
}
|
|
347
|
+
`,
|
|
348
|
+
AdditionalCSS: `
|
|
349
|
+
.pict-flow-node-title,
|
|
350
|
+
.pict-flow-node-type-label,
|
|
351
|
+
.pict-flow-port-label,
|
|
352
|
+
.pict-flow-node-card-code {
|
|
353
|
+
font-family: "MS Sans Serif", "Arial", sans-serif !important;
|
|
354
|
+
}
|
|
355
|
+
`
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ── Public API ────────────────────────────────────────────────────────
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Get the active renderer definition.
|
|
363
|
+
* @returns {Object}
|
|
364
|
+
*/
|
|
365
|
+
getActiveRenderer()
|
|
366
|
+
{
|
|
367
|
+
return this._Renderers[this._ActiveRendererKey] || this._Renderers['clean'];
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Get the active renderer key.
|
|
372
|
+
* @returns {string}
|
|
373
|
+
*/
|
|
374
|
+
getActiveRendererKey()
|
|
375
|
+
{
|
|
376
|
+
return this._ActiveRendererKey;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Switch the active renderer. Updates the noise default, applies shape
|
|
381
|
+
* overrides, and (if available) hands the GeometryCSS + AdditionalCSS
|
|
382
|
+
* to the FlowView's CSS provider for re-injection.
|
|
383
|
+
*
|
|
384
|
+
* @param {string} pRendererKey
|
|
385
|
+
* @returns {boolean}
|
|
386
|
+
*/
|
|
387
|
+
setRenderer(pRendererKey)
|
|
388
|
+
{
|
|
389
|
+
if (!this._Renderers[pRendererKey])
|
|
390
|
+
{
|
|
391
|
+
this.log.warn(`PictProviderFlowRenderer: renderer '${pRendererKey}' not found`);
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
this._ActiveRendererKey = pRendererKey;
|
|
396
|
+
let tmpRenderer = this._Renderers[pRendererKey];
|
|
397
|
+
|
|
398
|
+
// Apply noise defaults from the renderer
|
|
399
|
+
if (tmpRenderer.NoiseConfig && typeof tmpRenderer.NoiseConfig.DefaultLevel === 'number')
|
|
400
|
+
{
|
|
401
|
+
this._NoiseLevel = tmpRenderer.NoiseConfig.DefaultLevel;
|
|
402
|
+
}
|
|
403
|
+
else
|
|
404
|
+
{
|
|
405
|
+
this._NoiseLevel = 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Apply shape overrides through the connector-shapes provider
|
|
409
|
+
if (this._FlowView && this._FlowView._ConnectorShapesProvider)
|
|
410
|
+
{
|
|
411
|
+
this._FlowView._ConnectorShapesProvider.resetToDefaults();
|
|
412
|
+
if (tmpRenderer.ShapeOverrides && Object.keys(tmpRenderer.ShapeOverrides).length > 0)
|
|
413
|
+
{
|
|
414
|
+
this._FlowView._ConnectorShapesProvider.applyThemeOverrides(tmpRenderer.ShapeOverrides);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
this.log.trace(`PictProviderFlowRenderer: switched to '${pRendererKey}'`);
|
|
419
|
+
return true;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Register a custom renderer.
|
|
424
|
+
* @param {string} pKey
|
|
425
|
+
* @param {Object} pDefinition
|
|
426
|
+
*/
|
|
427
|
+
register(pKey, pDefinition)
|
|
428
|
+
{
|
|
429
|
+
if (!pKey || !pDefinition)
|
|
430
|
+
{
|
|
431
|
+
this.log.warn('PictProviderFlowRenderer: register requires key and definition');
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
pDefinition.Key = pKey;
|
|
435
|
+
this._Renderers[pKey] = pDefinition;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Get all registered renderer keys.
|
|
440
|
+
* @returns {Array<string>}
|
|
441
|
+
*/
|
|
442
|
+
getRendererKeys()
|
|
443
|
+
{
|
|
444
|
+
return Object.keys(this._Renderers);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// ── Noise APIs (kept on this provider so consumers don't depend on the
|
|
448
|
+
// legacy Flow-Theme shim) ──────────────────────────────────────────
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Get the current noise level (0 to 1).
|
|
452
|
+
* @returns {number}
|
|
453
|
+
*/
|
|
454
|
+
getNoiseLevel()
|
|
455
|
+
{
|
|
456
|
+
return this._NoiseLevel;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Set the noise level (0 to 1).
|
|
461
|
+
* @param {number} pLevel
|
|
462
|
+
*/
|
|
463
|
+
setNoiseLevel(pLevel)
|
|
464
|
+
{
|
|
465
|
+
this._NoiseLevel = Math.max(0, Math.min(1, pLevel || 0));
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Get the noise amplitude for node bracket rendering.
|
|
470
|
+
* Returns 0 if the active renderer disables noise for nodes.
|
|
471
|
+
* @returns {number}
|
|
472
|
+
*/
|
|
473
|
+
getNodeNoiseAmplitude()
|
|
474
|
+
{
|
|
475
|
+
let tmpRenderer = this.getActiveRenderer();
|
|
476
|
+
if (!tmpRenderer || !tmpRenderer.NoiseConfig || !tmpRenderer.NoiseConfig.Enabled || !tmpRenderer.NoiseConfig.AffectsNodes)
|
|
477
|
+
{
|
|
478
|
+
return 0;
|
|
479
|
+
}
|
|
480
|
+
return this._NoiseLevel * (tmpRenderer.NoiseConfig.MaxJitterPx || 3);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Post-process an SVG path string to apply jitter when the active
|
|
485
|
+
* renderer enables noise for connections.
|
|
486
|
+
*
|
|
487
|
+
* @param {string} pPathString
|
|
488
|
+
* @param {string} pSeedString
|
|
489
|
+
* @returns {string}
|
|
490
|
+
*/
|
|
491
|
+
processPathString(pPathString, pSeedString)
|
|
492
|
+
{
|
|
493
|
+
let tmpRenderer = this.getActiveRenderer();
|
|
494
|
+
if (!tmpRenderer || !tmpRenderer.NoiseConfig || !tmpRenderer.NoiseConfig.Enabled || !tmpRenderer.NoiseConfig.AffectsConnections)
|
|
495
|
+
{
|
|
496
|
+
return pPathString;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
let tmpAmplitude = this._NoiseLevel * (tmpRenderer.NoiseConfig.MaxJitterPx || 3);
|
|
500
|
+
if (tmpAmplitude <= 0)
|
|
501
|
+
{
|
|
502
|
+
return pPathString;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
if (this._FlowView && this._FlowView._NoiseProvider)
|
|
506
|
+
{
|
|
507
|
+
return this._FlowView._NoiseProvider.jitterPath(pPathString, tmpAmplitude, pSeedString);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
return pPathString;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
module.exports = PictProviderFlowRenderer;
|
|
515
|
+
|
|
516
|
+
module.exports.default_configuration = _ProviderConfiguration;
|