pict-section-flow 0.0.1 → 0.0.2
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/README.md +19 -0
- package/{example_application → example_applications/simple_cards}/html/index.html +2 -2
- package/example_applications/simple_cards/package.json +43 -0
- package/example_applications/simple_cards/source/Pict-Application-FlowExample.js +434 -0
- package/example_applications/simple_cards/source/cards/FlowCard-Each.js +36 -0
- package/example_applications/simple_cards/source/cards/FlowCard-FileRead.js +54 -0
- package/example_applications/simple_cards/source/cards/FlowCard-FileWrite.js +48 -0
- package/example_applications/simple_cards/source/cards/FlowCard-GetValue.js +35 -0
- package/example_applications/simple_cards/source/cards/FlowCard-IfThenElse.js +47 -0
- package/example_applications/simple_cards/source/cards/FlowCard-LogValues.js +53 -0
- package/example_applications/simple_cards/source/cards/FlowCard-SetValue.js +95 -0
- package/example_applications/simple_cards/source/cards/FlowCard-Switch.js +37 -0
- package/example_applications/simple_cards/source/views/PictView-FlowExample-FileWriteInfo.js +59 -0
- package/{example_application → example_applications/simple_cards}/source/views/PictView-FlowExample-Layout.js +5 -1
- package/example_applications/simple_cards/source/views/PictView-FlowExample-MainWorkspace.js +312 -0
- package/package.json +6 -6
- package/source/Pict-Section-Flow.js +19 -0
- package/source/PictFlowCard.js +207 -0
- package/source/PictFlowCardPropertiesPanel.js +105 -0
- package/source/panels/FlowCardPropertiesPanel-Form.js +174 -0
- package/source/panels/FlowCardPropertiesPanel-Markdown.js +148 -0
- package/source/panels/FlowCardPropertiesPanel-Template.js +88 -0
- package/source/panels/FlowCardPropertiesPanel-View.js +114 -0
- package/source/providers/PictProvider-Flow-EventHandler.js +19 -8
- package/source/providers/PictProvider-Flow-Geometry.js +64 -0
- package/source/providers/PictProvider-Flow-Layouts.js +284 -0
- package/source/providers/PictProvider-Flow-NodeTypes.js +70 -0
- package/source/providers/PictProvider-Flow-PanelChrome.js +72 -0
- package/source/providers/PictProvider-Flow-SVGHelpers.js +30 -0
- package/source/services/PictService-Flow-ConnectionRenderer.js +324 -66
- package/source/services/PictService-Flow-InteractionManager.js +399 -75
- package/source/services/PictService-Flow-Layout.js +159 -0
- package/source/services/PictService-Flow-PathGenerator.js +199 -0
- package/source/services/PictService-Flow-Tether.js +544 -0
- package/source/views/PictView-Flow-Node.js +95 -18
- package/source/views/PictView-Flow-PropertiesPanel.js +435 -0
- package/source/views/PictView-Flow-Toolbar.js +491 -5
- package/source/views/PictView-Flow.js +830 -8
- package/example_application/package.json +0 -41
- package/example_application/source/Pict-Application-FlowExample.js +0 -241
- package/example_application/source/views/PictView-FlowExample-MainWorkspace.js +0 -191
- /package/{example_application → example_applications/simple_cards}/css/flowexample.css +0 -0
- /package/{example_application → example_applications/simple_cards}/source/Pict-Application-FlowExample-Configuration.json +0 -0
- /package/{example_application → example_applications/simple_cards}/source/providers/PictRouter-FlowExample-Configuration.json +0 -0
- /package/{example_application → example_applications/simple_cards}/source/views/PictView-FlowExample-About.js +0 -0
- /package/{example_application → example_applications/simple_cards}/source/views/PictView-FlowExample-BottomBar.js +0 -0
- /package/{example_application → example_applications/simple_cards}/source/views/PictView-FlowExample-Documentation.js +0 -0
- /package/{example_application → example_applications/simple_cards}/source/views/PictView-FlowExample-TopBar.js +0 -0
|
@@ -11,6 +11,8 @@ const _DefaultConfiguration =
|
|
|
11
11
|
|
|
12
12
|
FlowViewIdentifier: 'Pict-Flow',
|
|
13
13
|
|
|
14
|
+
EnablePalette: true,
|
|
15
|
+
|
|
14
16
|
CSS: /*css*/`
|
|
15
17
|
.pict-flow-toolbar {
|
|
16
18
|
display: flex;
|
|
@@ -74,6 +76,113 @@ const _DefaultConfiguration =
|
|
|
74
76
|
background-color: #fff;
|
|
75
77
|
color: #2c3e50;
|
|
76
78
|
}
|
|
79
|
+
.pict-flow-palette-container {
|
|
80
|
+
border-bottom: 1px solid #e0e0e0;
|
|
81
|
+
background-color: #fafafa;
|
|
82
|
+
}
|
|
83
|
+
.pict-flow-palette-toggle {
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
justify-content: space-between;
|
|
87
|
+
padding: 0.4em 0.75em;
|
|
88
|
+
cursor: pointer;
|
|
89
|
+
user-select: none;
|
|
90
|
+
-webkit-user-select: none;
|
|
91
|
+
font-size: 0.8em;
|
|
92
|
+
color: #7f8c8d;
|
|
93
|
+
background-color: #f4f4f5;
|
|
94
|
+
border-bottom: 1px solid #e0e0e0;
|
|
95
|
+
}
|
|
96
|
+
.pict-flow-palette-toggle:hover {
|
|
97
|
+
background-color: #ecf0f1;
|
|
98
|
+
color: #2c3e50;
|
|
99
|
+
}
|
|
100
|
+
.pict-flow-palette-toggle-arrow {
|
|
101
|
+
font-size: 0.7em;
|
|
102
|
+
transition: transform 0.2s;
|
|
103
|
+
}
|
|
104
|
+
.pict-flow-palette-toggle-arrow.open {
|
|
105
|
+
transform: rotate(180deg);
|
|
106
|
+
}
|
|
107
|
+
.pict-flow-palette-body {
|
|
108
|
+
display: none;
|
|
109
|
+
padding: 0.5em 0.75em 0.75em 0.75em;
|
|
110
|
+
max-height: 280px;
|
|
111
|
+
overflow-y: auto;
|
|
112
|
+
}
|
|
113
|
+
.pict-flow-palette-body.open {
|
|
114
|
+
display: block;
|
|
115
|
+
}
|
|
116
|
+
.pict-flow-palette-category {
|
|
117
|
+
margin-bottom: 0.5em;
|
|
118
|
+
}
|
|
119
|
+
.pict-flow-palette-category:last-child {
|
|
120
|
+
margin-bottom: 0;
|
|
121
|
+
}
|
|
122
|
+
.pict-flow-palette-category-label {
|
|
123
|
+
font-size: 0.7em;
|
|
124
|
+
font-weight: 700;
|
|
125
|
+
text-transform: uppercase;
|
|
126
|
+
letter-spacing: 0.05em;
|
|
127
|
+
color: #95a5a6;
|
|
128
|
+
margin-bottom: 0.35em;
|
|
129
|
+
padding-bottom: 0.2em;
|
|
130
|
+
border-bottom: 1px solid #ecf0f1;
|
|
131
|
+
}
|
|
132
|
+
.pict-flow-palette-cards {
|
|
133
|
+
display: flex;
|
|
134
|
+
flex-wrap: wrap;
|
|
135
|
+
gap: 0.35em;
|
|
136
|
+
}
|
|
137
|
+
.pict-flow-palette-card {
|
|
138
|
+
display: inline-flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
gap: 0.35em;
|
|
141
|
+
padding: 0.35em 0.6em;
|
|
142
|
+
border: 1px solid #d5d8dc;
|
|
143
|
+
border-radius: 4px;
|
|
144
|
+
background-color: #ffffff;
|
|
145
|
+
font-size: 0.8em;
|
|
146
|
+
cursor: pointer;
|
|
147
|
+
transition: background-color 0.15s, border-color 0.15s, box-shadow 0.15s;
|
|
148
|
+
user-select: none;
|
|
149
|
+
-webkit-user-select: none;
|
|
150
|
+
position: relative;
|
|
151
|
+
}
|
|
152
|
+
.pict-flow-palette-card:hover {
|
|
153
|
+
background-color: #eaf2f8;
|
|
154
|
+
border-color: #3498db;
|
|
155
|
+
box-shadow: 0 1px 3px rgba(52, 152, 219, 0.15);
|
|
156
|
+
}
|
|
157
|
+
.pict-flow-palette-card.disabled {
|
|
158
|
+
opacity: 0.45;
|
|
159
|
+
pointer-events: none;
|
|
160
|
+
cursor: default;
|
|
161
|
+
}
|
|
162
|
+
.pict-flow-palette-card-icon {
|
|
163
|
+
font-size: 1.1em;
|
|
164
|
+
line-height: 1;
|
|
165
|
+
}
|
|
166
|
+
.pict-flow-palette-card-swatch {
|
|
167
|
+
width: 10px;
|
|
168
|
+
height: 10px;
|
|
169
|
+
border-radius: 2px;
|
|
170
|
+
flex-shrink: 0;
|
|
171
|
+
}
|
|
172
|
+
.pict-flow-palette-card-title {
|
|
173
|
+
font-weight: 500;
|
|
174
|
+
color: #2c3e50;
|
|
175
|
+
white-space: nowrap;
|
|
176
|
+
}
|
|
177
|
+
.pict-flow-palette-card-code {
|
|
178
|
+
font-size: 0.8em;
|
|
179
|
+
color: #95a5a6;
|
|
180
|
+
font-family: monospace;
|
|
181
|
+
}
|
|
182
|
+
.pict-flow-toolbar-select.layout-select {
|
|
183
|
+
min-width: 120px;
|
|
184
|
+
max-width: 200px;
|
|
185
|
+
}
|
|
77
186
|
`,
|
|
78
187
|
|
|
79
188
|
Templates:
|
|
@@ -85,10 +194,6 @@ const _DefaultConfiguration =
|
|
|
85
194
|
<div class="pict-flow-toolbar-group">
|
|
86
195
|
<span class="pict-flow-toolbar-label">Node:</span>
|
|
87
196
|
<select class="pict-flow-toolbar-select" id="Flow-Toolbar-NodeType-{~D:Record.FlowViewIdentifier~}">
|
|
88
|
-
<option value="default">Default</option>
|
|
89
|
-
<option value="start">Start</option>
|
|
90
|
-
<option value="end">End</option>
|
|
91
|
-
<option value="decision">Decision</option>
|
|
92
197
|
</select>
|
|
93
198
|
<button class="pict-flow-toolbar-btn" data-flow-action="add-node">+ Add Node</button>
|
|
94
199
|
</div>
|
|
@@ -97,12 +202,33 @@ const _DefaultConfiguration =
|
|
|
97
202
|
</div>
|
|
98
203
|
<div class="pict-flow-toolbar-group">
|
|
99
204
|
<button class="pict-flow-toolbar-btn" data-flow-action="zoom-in">Zoom +</button>
|
|
100
|
-
<button class="pict-flow-toolbar-btn" data-flow-action="zoom-out">Zoom
|
|
205
|
+
<button class="pict-flow-toolbar-btn" data-flow-action="zoom-out">Zoom -</button>
|
|
101
206
|
<button class="pict-flow-toolbar-btn" data-flow-action="zoom-fit">Fit</button>
|
|
102
207
|
</div>
|
|
103
208
|
<div class="pict-flow-toolbar-group">
|
|
104
209
|
<button class="pict-flow-toolbar-btn" data-flow-action="auto-layout">Auto Layout</button>
|
|
105
210
|
</div>
|
|
211
|
+
<div class="pict-flow-toolbar-group">
|
|
212
|
+
<span class="pict-flow-toolbar-label">Layouts:</span>
|
|
213
|
+
<select class="pict-flow-toolbar-select layout-select"
|
|
214
|
+
id="Flow-Toolbar-LayoutSelect-{~D:Record.FlowViewIdentifier~}">
|
|
215
|
+
<option value="">-- select layout --</option>
|
|
216
|
+
</select>
|
|
217
|
+
<button class="pict-flow-toolbar-btn" data-flow-action="save-layout" title="Save the current node positions as a named layout">Save</button>
|
|
218
|
+
<button class="pict-flow-toolbar-btn" data-flow-action="restore-layout" title="Restore the selected layout">Restore</button>
|
|
219
|
+
<button class="pict-flow-toolbar-btn danger" data-flow-action="delete-layout" title="Delete the selected saved layout">Delete</button>
|
|
220
|
+
</div>
|
|
221
|
+
<div class="pict-flow-toolbar-group">
|
|
222
|
+
<button class="pict-flow-toolbar-btn" data-flow-action="fullscreen" id="Flow-Toolbar-Fullscreen-{~D:Record.FlowViewIdentifier~}" title="Toggle Fullscreen">⛶ Fullscreen</button>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
<div class="pict-flow-palette-container" id="Flow-Palette-{~D:Record.FlowViewIdentifier~}">
|
|
226
|
+
<div class="pict-flow-palette-toggle" data-flow-action="toggle-palette">
|
|
227
|
+
<span>Card Palette</span>
|
|
228
|
+
<span class="pict-flow-palette-toggle-arrow" id="Flow-Palette-Arrow-{~D:Record.FlowViewIdentifier~}">▼</span>
|
|
229
|
+
</div>
|
|
230
|
+
<div class="pict-flow-palette-body" id="Flow-Palette-Body-{~D:Record.FlowViewIdentifier~}">
|
|
231
|
+
</div>
|
|
106
232
|
</div>
|
|
107
233
|
`
|
|
108
234
|
}
|
|
@@ -129,6 +255,14 @@ class PictViewFlowToolbar extends libPictView
|
|
|
129
255
|
this.serviceType = 'PictViewFlowToolbar';
|
|
130
256
|
|
|
131
257
|
this._FlowView = null;
|
|
258
|
+
this._PaletteOpen = false;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
render(pRenderableHash, pRenderDestinationAddress, pTemplateRecordAddress)
|
|
262
|
+
{
|
|
263
|
+
// Pass this.options as the template record so {~D:Record.FlowViewIdentifier~}
|
|
264
|
+
// resolves correctly in the toolbar template.
|
|
265
|
+
return super.render(pRenderableHash, pRenderDestinationAddress, this.options);
|
|
132
266
|
}
|
|
133
267
|
|
|
134
268
|
onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
|
|
@@ -152,9 +286,306 @@ class PictViewFlowToolbar extends libPictView
|
|
|
152
286
|
});
|
|
153
287
|
}
|
|
154
288
|
|
|
289
|
+
// Bind palette toggle and card click events
|
|
290
|
+
let tmpFlowViewIdentifier = this.options.FlowViewIdentifier;
|
|
291
|
+
let tmpPaletteContainer = this.pict.ContentAssignment.getElement(`#Flow-Palette-${tmpFlowViewIdentifier}`);
|
|
292
|
+
if (tmpPaletteContainer.length > 0)
|
|
293
|
+
{
|
|
294
|
+
tmpPaletteContainer[0].addEventListener('click', (pEvent) =>
|
|
295
|
+
{
|
|
296
|
+
let tmpTarget = pEvent.target;
|
|
297
|
+
if (!tmpTarget) return;
|
|
298
|
+
|
|
299
|
+
// Check for toggle
|
|
300
|
+
let tmpToggle = tmpTarget.closest('[data-flow-action="toggle-palette"]');
|
|
301
|
+
if (tmpToggle)
|
|
302
|
+
{
|
|
303
|
+
this._togglePalette();
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Check for card click
|
|
308
|
+
let tmpCard = tmpTarget.closest('[data-card-type]');
|
|
309
|
+
if (tmpCard)
|
|
310
|
+
{
|
|
311
|
+
let tmpCardType = tmpCard.getAttribute('data-card-type');
|
|
312
|
+
this._addCardFromPalette(tmpCardType);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Populate the node type dropdown, palette, and layout dropdown
|
|
318
|
+
this._populateNodeTypeDropdown();
|
|
319
|
+
this._renderPalette();
|
|
320
|
+
this._populateLayoutDropdown();
|
|
321
|
+
|
|
155
322
|
return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
|
|
156
323
|
}
|
|
157
324
|
|
|
325
|
+
/**
|
|
326
|
+
* Populate the node type dropdown from the registered node types.
|
|
327
|
+
*/
|
|
328
|
+
_populateNodeTypeDropdown()
|
|
329
|
+
{
|
|
330
|
+
if (!this._FlowView || !this._FlowView._NodeTypeProvider)
|
|
331
|
+
{
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
let tmpFlowViewIdentifier = this.options.FlowViewIdentifier;
|
|
336
|
+
let tmpSelectElements = this.pict.ContentAssignment.getElement(`#Flow-Toolbar-NodeType-${tmpFlowViewIdentifier}`);
|
|
337
|
+
if (tmpSelectElements.length < 1)
|
|
338
|
+
{
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
let tmpSelect = tmpSelectElements[0];
|
|
343
|
+
|
|
344
|
+
// Clear existing options
|
|
345
|
+
while (tmpSelect.firstChild)
|
|
346
|
+
{
|
|
347
|
+
tmpSelect.removeChild(tmpSelect.firstChild);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
let tmpTypes = this._FlowView._NodeTypeProvider.getNodeTypes();
|
|
351
|
+
let tmpTypeKeys = Object.keys(tmpTypes);
|
|
352
|
+
|
|
353
|
+
for (let i = 0; i < tmpTypeKeys.length; i++)
|
|
354
|
+
{
|
|
355
|
+
let tmpTypeConfig = tmpTypes[tmpTypeKeys[i]];
|
|
356
|
+
|
|
357
|
+
// Skip disabled cards
|
|
358
|
+
if (tmpTypeConfig.CardMetadata && tmpTypeConfig.CardMetadata.Enabled === false)
|
|
359
|
+
{
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
let tmpOption = document.createElement('option');
|
|
364
|
+
tmpOption.value = tmpTypeKeys[i];
|
|
365
|
+
|
|
366
|
+
if (tmpTypeConfig.CardMetadata && tmpTypeConfig.CardMetadata.Icon)
|
|
367
|
+
{
|
|
368
|
+
tmpOption.textContent = tmpTypeConfig.CardMetadata.Icon + ' ' + tmpTypeConfig.Label;
|
|
369
|
+
}
|
|
370
|
+
else
|
|
371
|
+
{
|
|
372
|
+
tmpOption.textContent = tmpTypeConfig.Label;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
tmpSelect.appendChild(tmpOption);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Populate the layout dropdown from saved layouts in the flow data.
|
|
381
|
+
*/
|
|
382
|
+
_populateLayoutDropdown()
|
|
383
|
+
{
|
|
384
|
+
if (!this._FlowView || !this._FlowView._LayoutProvider)
|
|
385
|
+
{
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
let tmpFlowViewIdentifier = this.options.FlowViewIdentifier;
|
|
390
|
+
let tmpSelectElements = this.pict.ContentAssignment.getElement(
|
|
391
|
+
`#Flow-Toolbar-LayoutSelect-${tmpFlowViewIdentifier}`
|
|
392
|
+
);
|
|
393
|
+
if (tmpSelectElements.length < 1)
|
|
394
|
+
{
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
let tmpSelect = tmpSelectElements[0];
|
|
399
|
+
|
|
400
|
+
// Clear existing options
|
|
401
|
+
while (tmpSelect.firstChild)
|
|
402
|
+
{
|
|
403
|
+
tmpSelect.removeChild(tmpSelect.firstChild);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Add placeholder option
|
|
407
|
+
let tmpPlaceholder = document.createElement('option');
|
|
408
|
+
tmpPlaceholder.value = '';
|
|
409
|
+
tmpPlaceholder.textContent = '-- select layout --';
|
|
410
|
+
tmpSelect.appendChild(tmpPlaceholder);
|
|
411
|
+
|
|
412
|
+
let tmpLayouts = this._FlowView._LayoutProvider.getLayouts();
|
|
413
|
+
for (let i = 0; i < tmpLayouts.length; i++)
|
|
414
|
+
{
|
|
415
|
+
let tmpLayout = tmpLayouts[i];
|
|
416
|
+
let tmpOption = document.createElement('option');
|
|
417
|
+
tmpOption.value = tmpLayout.Hash;
|
|
418
|
+
tmpOption.textContent = tmpLayout.Name;
|
|
419
|
+
tmpSelect.appendChild(tmpOption);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Render the card palette with categories and card chips.
|
|
425
|
+
*/
|
|
426
|
+
_renderPalette()
|
|
427
|
+
{
|
|
428
|
+
if (!this._FlowView || !this._FlowView._NodeTypeProvider) return;
|
|
429
|
+
|
|
430
|
+
let tmpFlowViewIdentifier = this.options.FlowViewIdentifier;
|
|
431
|
+
let tmpPaletteBody = this.pict.ContentAssignment.getElement(`#Flow-Palette-Body-${tmpFlowViewIdentifier}`);
|
|
432
|
+
if (tmpPaletteBody.length < 1) return;
|
|
433
|
+
|
|
434
|
+
let tmpBody = tmpPaletteBody[0];
|
|
435
|
+
|
|
436
|
+
// Clear existing palette content
|
|
437
|
+
while (tmpBody.firstChild)
|
|
438
|
+
{
|
|
439
|
+
tmpBody.removeChild(tmpBody.firstChild);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
let tmpCategories = this._FlowView._NodeTypeProvider.getCardsByCategory();
|
|
443
|
+
let tmpCategoryKeys = Object.keys(tmpCategories);
|
|
444
|
+
|
|
445
|
+
if (tmpCategoryKeys.length === 0)
|
|
446
|
+
{
|
|
447
|
+
// No FlowCards registered - hide the palette
|
|
448
|
+
let tmpPaletteContainer = this.pict.ContentAssignment.getElement(`#Flow-Palette-${tmpFlowViewIdentifier}`);
|
|
449
|
+
if (tmpPaletteContainer.length > 0)
|
|
450
|
+
{
|
|
451
|
+
tmpPaletteContainer[0].style.display = 'none';
|
|
452
|
+
}
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
for (let i = 0; i < tmpCategoryKeys.length; i++)
|
|
457
|
+
{
|
|
458
|
+
let tmpCategoryName = tmpCategoryKeys[i];
|
|
459
|
+
let tmpCards = tmpCategories[tmpCategoryName];
|
|
460
|
+
|
|
461
|
+
let tmpCategoryDiv = document.createElement('div');
|
|
462
|
+
tmpCategoryDiv.className = 'pict-flow-palette-category';
|
|
463
|
+
|
|
464
|
+
let tmpCategoryLabel = document.createElement('div');
|
|
465
|
+
tmpCategoryLabel.className = 'pict-flow-palette-category-label';
|
|
466
|
+
tmpCategoryLabel.textContent = tmpCategoryName;
|
|
467
|
+
tmpCategoryDiv.appendChild(tmpCategoryLabel);
|
|
468
|
+
|
|
469
|
+
let tmpCardsDiv = document.createElement('div');
|
|
470
|
+
tmpCardsDiv.className = 'pict-flow-palette-cards';
|
|
471
|
+
|
|
472
|
+
for (let j = 0; j < tmpCards.length; j++)
|
|
473
|
+
{
|
|
474
|
+
let tmpCardConfig = tmpCards[j];
|
|
475
|
+
let tmpMeta = tmpCardConfig.CardMetadata || {};
|
|
476
|
+
|
|
477
|
+
let tmpCardEl = document.createElement('div');
|
|
478
|
+
tmpCardEl.className = 'pict-flow-palette-card';
|
|
479
|
+
if (tmpMeta.Enabled === false)
|
|
480
|
+
{
|
|
481
|
+
tmpCardEl.classList.add('disabled');
|
|
482
|
+
}
|
|
483
|
+
tmpCardEl.setAttribute('data-card-type', tmpCardConfig.Hash);
|
|
484
|
+
|
|
485
|
+
if (tmpMeta.Tooltip)
|
|
486
|
+
{
|
|
487
|
+
tmpCardEl.setAttribute('title', tmpMeta.Tooltip);
|
|
488
|
+
}
|
|
489
|
+
else if (tmpMeta.Description)
|
|
490
|
+
{
|
|
491
|
+
tmpCardEl.setAttribute('title', tmpMeta.Description);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Icon or color swatch
|
|
495
|
+
if (tmpMeta.Icon)
|
|
496
|
+
{
|
|
497
|
+
let tmpIconSpan = document.createElement('span');
|
|
498
|
+
tmpIconSpan.className = 'pict-flow-palette-card-icon';
|
|
499
|
+
tmpIconSpan.textContent = tmpMeta.Icon;
|
|
500
|
+
tmpCardEl.appendChild(tmpIconSpan);
|
|
501
|
+
}
|
|
502
|
+
else if (tmpCardConfig.TitleBarColor)
|
|
503
|
+
{
|
|
504
|
+
let tmpSwatch = document.createElement('span');
|
|
505
|
+
tmpSwatch.className = 'pict-flow-palette-card-swatch';
|
|
506
|
+
tmpSwatch.style.backgroundColor = tmpCardConfig.TitleBarColor;
|
|
507
|
+
tmpCardEl.appendChild(tmpSwatch);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Title
|
|
511
|
+
let tmpTitleSpan = document.createElement('span');
|
|
512
|
+
tmpTitleSpan.className = 'pict-flow-palette-card-title';
|
|
513
|
+
tmpTitleSpan.textContent = tmpCardConfig.Label;
|
|
514
|
+
tmpCardEl.appendChild(tmpTitleSpan);
|
|
515
|
+
|
|
516
|
+
// Code badge
|
|
517
|
+
if (tmpMeta.Code)
|
|
518
|
+
{
|
|
519
|
+
let tmpCodeSpan = document.createElement('span');
|
|
520
|
+
tmpCodeSpan.className = 'pict-flow-palette-card-code';
|
|
521
|
+
tmpCodeSpan.textContent = tmpMeta.Code;
|
|
522
|
+
tmpCardEl.appendChild(tmpCodeSpan);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
tmpCardsDiv.appendChild(tmpCardEl);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
tmpCategoryDiv.appendChild(tmpCardsDiv);
|
|
529
|
+
tmpBody.appendChild(tmpCategoryDiv);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Toggle the palette open/closed.
|
|
535
|
+
*/
|
|
536
|
+
_togglePalette()
|
|
537
|
+
{
|
|
538
|
+
this._PaletteOpen = !this._PaletteOpen;
|
|
539
|
+
|
|
540
|
+
let tmpFlowViewIdentifier = this.options.FlowViewIdentifier;
|
|
541
|
+
|
|
542
|
+
let tmpBody = this.pict.ContentAssignment.getElement(`#Flow-Palette-Body-${tmpFlowViewIdentifier}`);
|
|
543
|
+
if (tmpBody.length > 0)
|
|
544
|
+
{
|
|
545
|
+
if (this._PaletteOpen)
|
|
546
|
+
{
|
|
547
|
+
tmpBody[0].classList.add('open');
|
|
548
|
+
}
|
|
549
|
+
else
|
|
550
|
+
{
|
|
551
|
+
tmpBody[0].classList.remove('open');
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
let tmpArrow = this.pict.ContentAssignment.getElement(`#Flow-Palette-Arrow-${tmpFlowViewIdentifier}`);
|
|
556
|
+
if (tmpArrow.length > 0)
|
|
557
|
+
{
|
|
558
|
+
if (this._PaletteOpen)
|
|
559
|
+
{
|
|
560
|
+
tmpArrow[0].classList.add('open');
|
|
561
|
+
}
|
|
562
|
+
else
|
|
563
|
+
{
|
|
564
|
+
tmpArrow[0].classList.remove('open');
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Add a node from a palette card click.
|
|
571
|
+
* @param {string} pCardType - The card type hash
|
|
572
|
+
*/
|
|
573
|
+
_addCardFromPalette(pCardType)
|
|
574
|
+
{
|
|
575
|
+
if (!this._FlowView) return;
|
|
576
|
+
|
|
577
|
+
let tmpVS = this._FlowView.viewState;
|
|
578
|
+
let tmpX = (-tmpVS.PanX + 200) / tmpVS.Zoom;
|
|
579
|
+
let tmpY = (-tmpVS.PanY + 200) / tmpVS.Zoom;
|
|
580
|
+
|
|
581
|
+
// Offset to avoid overlap
|
|
582
|
+
let tmpNodeCount = this._FlowView.flowData.Nodes.length;
|
|
583
|
+
tmpX += (tmpNodeCount % 5) * 40;
|
|
584
|
+
tmpY += (tmpNodeCount % 5) * 40;
|
|
585
|
+
|
|
586
|
+
this._FlowView.addNode(pCardType, tmpX, tmpY);
|
|
587
|
+
}
|
|
588
|
+
|
|
158
589
|
/**
|
|
159
590
|
* Handle a toolbar action
|
|
160
591
|
* @param {string} pAction
|
|
@@ -211,6 +642,61 @@ class PictViewFlowToolbar extends libPictView
|
|
|
211
642
|
this._FlowView.autoLayout();
|
|
212
643
|
break;
|
|
213
644
|
|
|
645
|
+
case 'save-layout':
|
|
646
|
+
{
|
|
647
|
+
let tmpName = window.prompt('Enter a name for this layout:');
|
|
648
|
+
if (tmpName !== null && tmpName.trim() !== '')
|
|
649
|
+
{
|
|
650
|
+
this._FlowView._LayoutProvider.saveLayout(tmpName.trim());
|
|
651
|
+
this._populateLayoutDropdown();
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
break;
|
|
655
|
+
|
|
656
|
+
case 'restore-layout':
|
|
657
|
+
{
|
|
658
|
+
let tmpSelectElements = this.pict.ContentAssignment.getElement(
|
|
659
|
+
`#Flow-Toolbar-LayoutSelect-${tmpFlowViewIdentifier}`
|
|
660
|
+
);
|
|
661
|
+
if (tmpSelectElements.length > 0)
|
|
662
|
+
{
|
|
663
|
+
let tmpLayoutHash = tmpSelectElements[0].value;
|
|
664
|
+
if (tmpLayoutHash)
|
|
665
|
+
{
|
|
666
|
+
this._FlowView._LayoutProvider.restoreLayout(tmpLayoutHash);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
break;
|
|
671
|
+
|
|
672
|
+
case 'delete-layout':
|
|
673
|
+
{
|
|
674
|
+
let tmpSelectElements = this.pict.ContentAssignment.getElement(
|
|
675
|
+
`#Flow-Toolbar-LayoutSelect-${tmpFlowViewIdentifier}`
|
|
676
|
+
);
|
|
677
|
+
if (tmpSelectElements.length > 0)
|
|
678
|
+
{
|
|
679
|
+
let tmpLayoutHash = tmpSelectElements[0].value;
|
|
680
|
+
if (tmpLayoutHash)
|
|
681
|
+
{
|
|
682
|
+
this._FlowView._LayoutProvider.deleteLayout(tmpLayoutHash);
|
|
683
|
+
this._populateLayoutDropdown();
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
break;
|
|
688
|
+
|
|
689
|
+
case 'fullscreen':
|
|
690
|
+
{
|
|
691
|
+
let tmpIsFullscreen = this._FlowView.toggleFullscreen();
|
|
692
|
+
let tmpBtnElements = this.pict.ContentAssignment.getElement(`#Flow-Toolbar-Fullscreen-${tmpFlowViewIdentifier}`);
|
|
693
|
+
if (tmpBtnElements.length > 0)
|
|
694
|
+
{
|
|
695
|
+
tmpBtnElements[0].innerHTML = tmpIsFullscreen ? '✖ Exit Fullscreen' : '⛶ Fullscreen';
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
break;
|
|
699
|
+
|
|
214
700
|
default:
|
|
215
701
|
this.log.warn(`PictViewFlowToolbar: unknown action '${pAction}'`);
|
|
216
702
|
break;
|