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,95 @@
|
|
|
1
|
+
# marshalToView / marshalFromView
|
|
2
|
+
|
|
3
|
+
Two-way data binding between the flow view and Pict's `AppData` store. Requires the `FlowDataAddress` configuration option to be set.
|
|
4
|
+
|
|
5
|
+
## Signatures
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
flowView.marshalToView();
|
|
9
|
+
flowView.marshalFromView();
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## marshalToView
|
|
13
|
+
|
|
14
|
+
Load flow data from the AppData address specified in `FlowDataAddress` into the view and render it.
|
|
15
|
+
|
|
16
|
+
This is the "pull" direction: AppData → Flow View.
|
|
17
|
+
|
|
18
|
+
## marshalFromView
|
|
19
|
+
|
|
20
|
+
Write the current flow data back to the AppData address specified in `FlowDataAddress`.
|
|
21
|
+
|
|
22
|
+
This is the "push" direction: Flow View → AppData.
|
|
23
|
+
|
|
24
|
+
## Configuration
|
|
25
|
+
|
|
26
|
+
Set `FlowDataAddress` when registering the view:
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
_Pict.addView('MyFlow',
|
|
30
|
+
{
|
|
31
|
+
FlowDataAddress: 'AppData.Workflows.MainFlow'
|
|
32
|
+
},
|
|
33
|
+
libPictSectionFlow);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Examples
|
|
37
|
+
|
|
38
|
+
### Load from AppData on initialization
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
// Set up initial data in AppData
|
|
42
|
+
_Pict.AppData.Workflows =
|
|
43
|
+
{
|
|
44
|
+
MainFlow:
|
|
45
|
+
{
|
|
46
|
+
Nodes:
|
|
47
|
+
[
|
|
48
|
+
{
|
|
49
|
+
Hash: 'node-1',
|
|
50
|
+
Type: 'start',
|
|
51
|
+
X: 50, Y: 100,
|
|
52
|
+
Width: 140, Height: 80,
|
|
53
|
+
Title: 'Entry',
|
|
54
|
+
Ports:
|
|
55
|
+
[
|
|
56
|
+
{ Hash: 'port-1', Direction: 'output', Side: 'right', Label: 'Out' }
|
|
57
|
+
],
|
|
58
|
+
Data: {}
|
|
59
|
+
}
|
|
60
|
+
],
|
|
61
|
+
Connections: [],
|
|
62
|
+
OpenPanels: [],
|
|
63
|
+
SavedLayouts: [],
|
|
64
|
+
ViewState: { PanX: 0, PanY: 0, Zoom: 1 }
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// The flow view pulls this data on render
|
|
69
|
+
let tmpFlowView = _Pict.views.MyFlow;
|
|
70
|
+
tmpFlowView.marshalToView();
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Push changes back to AppData
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
// After the user edits the flow, persist to AppData
|
|
77
|
+
tmpFlowView.marshalFromView();
|
|
78
|
+
|
|
79
|
+
// Now AppData.Workflows.MainFlow reflects the current flow state
|
|
80
|
+
console.log(_Pict.AppData.Workflows.MainFlow.Nodes.length);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Auto-sync on flow changes
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
tmpFlowView._EventHandlerProvider.registerHandler('onFlowChanged',
|
|
87
|
+
() =>
|
|
88
|
+
{
|
|
89
|
+
tmpFlowView.marshalFromView();
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## See Also
|
|
94
|
+
|
|
95
|
+
- [getFlowData / setFlowData](getFlowData.md) — Direct get/set without AppData
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# openPanel / closePanel / closePanelForNode / togglePanel / updatePanelPosition
|
|
2
|
+
|
|
3
|
+
Manage the lifecycle and positioning of properties panels. Panels are floating UI elements tethered to nodes by a line. They display when a node is double-clicked or opened programmatically.
|
|
4
|
+
|
|
5
|
+
## Signatures
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
flowView.openPanel(pNodeHash);
|
|
9
|
+
flowView.closePanel(pPanelHash);
|
|
10
|
+
flowView.closePanelForNode(pNodeHash);
|
|
11
|
+
flowView.togglePanel(pNodeHash);
|
|
12
|
+
flowView.updatePanelPosition(pPanelHash, pX, pY);
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## openPanel
|
|
16
|
+
|
|
17
|
+
Open a properties panel for a node. The panel type and configuration come from the node type's `PropertiesPanel` definition.
|
|
18
|
+
|
|
19
|
+
| Parameter | Type | Description |
|
|
20
|
+
|-----------|------|-------------|
|
|
21
|
+
| `pNodeHash` | string | Hash of the node to open a panel for |
|
|
22
|
+
|
|
23
|
+
**Returns:** Panel data object, or `false` if the node type has no panel configuration.
|
|
24
|
+
|
|
25
|
+
**Events Fired:** `onPanelOpened`
|
|
26
|
+
|
|
27
|
+
## closePanel
|
|
28
|
+
|
|
29
|
+
Close a panel by its hash.
|
|
30
|
+
|
|
31
|
+
| Parameter | Type | Description |
|
|
32
|
+
|-----------|------|-------------|
|
|
33
|
+
| `pPanelHash` | string | Hash of the panel to close |
|
|
34
|
+
|
|
35
|
+
**Returns:** `boolean`
|
|
36
|
+
|
|
37
|
+
**Events Fired:** `onPanelClosed`
|
|
38
|
+
|
|
39
|
+
## closePanelForNode
|
|
40
|
+
|
|
41
|
+
Close all panels associated with a node.
|
|
42
|
+
|
|
43
|
+
| Parameter | Type | Description |
|
|
44
|
+
|-----------|------|-------------|
|
|
45
|
+
| `pNodeHash` | string | Hash of the node whose panels to close |
|
|
46
|
+
|
|
47
|
+
**Returns:** `boolean`
|
|
48
|
+
|
|
49
|
+
## togglePanel
|
|
50
|
+
|
|
51
|
+
Toggle a node's panel. Opens it if closed, closes it if open.
|
|
52
|
+
|
|
53
|
+
| Parameter | Type | Description |
|
|
54
|
+
|-----------|------|-------------|
|
|
55
|
+
| `pNodeHash` | string | Hash of the node |
|
|
56
|
+
|
|
57
|
+
**Returns:** Panel data object if opened, `false` if closed.
|
|
58
|
+
|
|
59
|
+
## updatePanelPosition
|
|
60
|
+
|
|
61
|
+
Move a panel to new coordinates.
|
|
62
|
+
|
|
63
|
+
| Parameter | Type | Description |
|
|
64
|
+
|-----------|------|-------------|
|
|
65
|
+
| `pPanelHash` | string | Hash of the panel |
|
|
66
|
+
| `pX` | number | New X coordinate |
|
|
67
|
+
| `pY` | number | New Y coordinate |
|
|
68
|
+
|
|
69
|
+
**Events Fired:** `onPanelMoved`
|
|
70
|
+
|
|
71
|
+
## Examples
|
|
72
|
+
|
|
73
|
+
### Open a panel programmatically
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
let tmpNode = flowView.addNode('FREAD', 200, 150, 'Read Config');
|
|
77
|
+
let tmpPanel = flowView.openPanel(tmpNode.Hash);
|
|
78
|
+
|
|
79
|
+
if (tmpPanel)
|
|
80
|
+
{
|
|
81
|
+
console.log('Panel opened:', tmpPanel.Hash);
|
|
82
|
+
console.log('Panel type:', tmpPanel.PanelType);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Toggle on button click
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
document.getElementById('toggle-props').addEventListener('click', () =>
|
|
90
|
+
{
|
|
91
|
+
let tmpFlowData = flowView.getFlowData();
|
|
92
|
+
if (tmpFlowData.ViewState.SelectedNodeHash)
|
|
93
|
+
{
|
|
94
|
+
flowView.togglePanel(tmpFlowData.ViewState.SelectedNodeHash);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Close all open panels
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
let tmpFlowData = flowView.getFlowData();
|
|
103
|
+
tmpFlowData.OpenPanels.forEach((pPanel) =>
|
|
104
|
+
{
|
|
105
|
+
flowView.closePanel(pPanel.Hash);
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Listen for panel events
|
|
110
|
+
|
|
111
|
+
```javascript
|
|
112
|
+
flowView._EventHandlerProvider.registerHandler('onPanelOpened',
|
|
113
|
+
(pPanelData) =>
|
|
114
|
+
{
|
|
115
|
+
console.log('Panel opened for node:', pPanelData.NodeHash);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
flowView._EventHandlerProvider.registerHandler('onPanelClosed',
|
|
119
|
+
(pPanelData) =>
|
|
120
|
+
{
|
|
121
|
+
console.log('Panel closed:', pPanelData.Hash);
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## See Also
|
|
126
|
+
|
|
127
|
+
- [PictFlowCard](PictFlowCard.md) — Define PropertiesPanel configuration on card types
|
|
128
|
+
- [PictFlowCardPropertiesPanel](PictFlowCardPropertiesPanel.md) — Custom panel base class
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# registerHandler / removeHandler / fireEvent
|
|
2
|
+
|
|
3
|
+
The event system for hooking into flow diagram lifecycle events. Register callbacks to react to user actions, data changes, and state transitions without modifying core code.
|
|
4
|
+
|
|
5
|
+
## Signatures
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
let tmpHash = flowView._EventHandlerProvider.registerHandler(pEventName, pHandler, pHandlerHash);
|
|
9
|
+
flowView._EventHandlerProvider.removeHandler(pEventName, pHandlerHash);
|
|
10
|
+
flowView._EventHandlerProvider.fireEvent(pEventName, pData);
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## registerHandler
|
|
14
|
+
|
|
15
|
+
Register a callback for a named event.
|
|
16
|
+
|
|
17
|
+
| Parameter | Type | Required | Description |
|
|
18
|
+
|-----------|------|----------|-------------|
|
|
19
|
+
| `pEventName` | string | Yes | Event name from the supported events list |
|
|
20
|
+
| `pHandler` | function | Yes | Callback function receiving event data |
|
|
21
|
+
| `pHandlerHash` | string | No | Optional unique ID for later removal |
|
|
22
|
+
|
|
23
|
+
**Returns:** Handler hash (string). Auto-generated if not provided.
|
|
24
|
+
|
|
25
|
+
## removeHandler
|
|
26
|
+
|
|
27
|
+
Unregister a previously registered handler.
|
|
28
|
+
|
|
29
|
+
| Parameter | Type | Required | Description |
|
|
30
|
+
|-----------|------|----------|-------------|
|
|
31
|
+
| `pEventName` | string | Yes | Event name |
|
|
32
|
+
| `pHandlerHash` | string | Yes | Hash returned from `registerHandler` |
|
|
33
|
+
|
|
34
|
+
**Returns:** `boolean`
|
|
35
|
+
|
|
36
|
+
## fireEvent
|
|
37
|
+
|
|
38
|
+
Manually fire all handlers for a named event. Typically used internally by services, but available for custom events.
|
|
39
|
+
|
|
40
|
+
| Parameter | Type | Required | Description |
|
|
41
|
+
|-----------|------|----------|-------------|
|
|
42
|
+
| `pEventName` | string | Yes | Event name |
|
|
43
|
+
| `pData` | any | No | Data passed to each handler |
|
|
44
|
+
|
|
45
|
+
## Supported Events
|
|
46
|
+
|
|
47
|
+
| Event | Payload | Description |
|
|
48
|
+
|-------|---------|-------------|
|
|
49
|
+
| `onNodeSelected` | Node object or null | A node is selected or deselected |
|
|
50
|
+
| `onNodeAdded` | Node object | A node is created |
|
|
51
|
+
| `onNodeRemoved` | Node object | A node is deleted |
|
|
52
|
+
| `onNodeMoved` | Node object | A node's position changes |
|
|
53
|
+
| `onConnectionSelected` | Connection object or null | A connection is selected |
|
|
54
|
+
| `onConnectionCreated` | Connection object | A connection is created |
|
|
55
|
+
| `onConnectionRemoved` | Connection object | A connection is deleted |
|
|
56
|
+
| `onConnectionHandleMoved` | Connection object | A bezier handle is dragged |
|
|
57
|
+
| `onConnectionModeChanged` | Connection object | Line mode switches |
|
|
58
|
+
| `onPanelOpened` | Panel data | A properties panel opens |
|
|
59
|
+
| `onPanelClosed` | Panel data | A properties panel closes |
|
|
60
|
+
| `onPanelMoved` | Panel data | A panel is repositioned |
|
|
61
|
+
| `onTetherSelected` | Panel data | A tether line is selected |
|
|
62
|
+
| `onTetherHandleMoved` | Panel data | A tether handle is dragged |
|
|
63
|
+
| `onTetherModeChanged` | Panel data | Tether mode switches |
|
|
64
|
+
| `onLayoutSaved` | Layout data | A layout is saved |
|
|
65
|
+
| `onLayoutRestored` | Layout data | A layout is restored |
|
|
66
|
+
| `onLayoutDeleted` | Layout data | A layout is deleted |
|
|
67
|
+
| `onFlowChanged` | Flow data | Any structural change |
|
|
68
|
+
| `onThemeChanged` | Theme key (string) | The active theme changes |
|
|
69
|
+
|
|
70
|
+
## Examples
|
|
71
|
+
|
|
72
|
+
### Track all changes for undo/redo
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
let tmpHistory = [];
|
|
76
|
+
let tmpHistoryIndex = -1;
|
|
77
|
+
|
|
78
|
+
flowView._EventHandlerProvider.registerHandler('onFlowChanged',
|
|
79
|
+
(pFlowData) =>
|
|
80
|
+
{
|
|
81
|
+
// Trim future states if we've undone
|
|
82
|
+
tmpHistory = tmpHistory.slice(0, tmpHistoryIndex + 1);
|
|
83
|
+
tmpHistory.push(JSON.parse(JSON.stringify(pFlowData)));
|
|
84
|
+
tmpHistoryIndex = tmpHistory.length - 1;
|
|
85
|
+
},
|
|
86
|
+
'undo-redo-tracker');
|
|
87
|
+
|
|
88
|
+
function undo()
|
|
89
|
+
{
|
|
90
|
+
if (tmpHistoryIndex > 0)
|
|
91
|
+
{
|
|
92
|
+
tmpHistoryIndex--;
|
|
93
|
+
flowView.setFlowData(tmpHistory[tmpHistoryIndex]);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function redo()
|
|
98
|
+
{
|
|
99
|
+
if (tmpHistoryIndex < tmpHistory.length - 1)
|
|
100
|
+
{
|
|
101
|
+
tmpHistoryIndex++;
|
|
102
|
+
flowView.setFlowData(tmpHistory[tmpHistoryIndex]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Sync to server on every change
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
flowView._EventHandlerProvider.registerHandler('onFlowChanged',
|
|
111
|
+
(pFlowData) =>
|
|
112
|
+
{
|
|
113
|
+
fetch('/api/flows/my-flow',
|
|
114
|
+
{
|
|
115
|
+
method: 'PUT',
|
|
116
|
+
headers: { 'Content-Type': 'application/json' },
|
|
117
|
+
body: JSON.stringify(pFlowData)
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
'server-sync');
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Update a sidebar when selection changes
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
flowView._EventHandlerProvider.registerHandler('onNodeSelected',
|
|
127
|
+
(pNode) =>
|
|
128
|
+
{
|
|
129
|
+
let tmpSidebar = document.getElementById('sidebar');
|
|
130
|
+
|
|
131
|
+
if (!pNode)
|
|
132
|
+
{
|
|
133
|
+
tmpSidebar.innerHTML = '<p>Select a node to view details</p>';
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
tmpSidebar.innerHTML =
|
|
138
|
+
'<h3>' + pNode.Title + '</h3>' +
|
|
139
|
+
'<p>Type: ' + pNode.Type + '</p>' +
|
|
140
|
+
'<p>Ports: ' + pNode.Ports.length + '</p>';
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Remove a handler
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
let tmpHandlerHash = flowView._EventHandlerProvider.registerHandler('onNodeAdded',
|
|
148
|
+
(pNode) =>
|
|
149
|
+
{
|
|
150
|
+
console.log('Node added:', pNode.Title);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Later, unregister it
|
|
154
|
+
flowView._EventHandlerProvider.removeHandler('onNodeAdded', tmpHandlerHash);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Multiple handlers for the same event
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
// Both handlers fire when a node is added
|
|
161
|
+
flowView._EventHandlerProvider.registerHandler('onNodeAdded',
|
|
162
|
+
(pNode) => { console.log('Handler 1:', pNode.Title); },
|
|
163
|
+
'logger');
|
|
164
|
+
|
|
165
|
+
flowView._EventHandlerProvider.registerHandler('onNodeAdded',
|
|
166
|
+
(pNode) => { updateNodeCount(); },
|
|
167
|
+
'counter');
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## See Also
|
|
171
|
+
|
|
172
|
+
- [addNode](addNode.md) — Triggers `onNodeAdded` and `onFlowChanged`
|
|
173
|
+
- [selectNode](selectNode.md) — Triggers `onNodeSelected`
|
|
174
|
+
- [setTheme](setTheme.md) — Triggers `onThemeChanged`
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# registerNodeType / removeNodeType / getNodeType
|
|
2
|
+
|
|
3
|
+
Register, remove, and query node types in the flow diagram's type registry. Most developers will use `PictFlowCard.registerWithFlowView()` instead, but these methods provide direct access for dynamic or programmatic type management.
|
|
4
|
+
|
|
5
|
+
## Signatures
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
flowView._NodeTypeProvider.registerNodeType(pNodeTypeConfig);
|
|
9
|
+
flowView._NodeTypeProvider.removeNodeType(pTypeHash);
|
|
10
|
+
flowView._NodeTypeProvider.getNodeType(pTypeHash);
|
|
11
|
+
flowView._NodeTypeProvider.getNodeTypes();
|
|
12
|
+
flowView._NodeTypeProvider.getNodeTypeList();
|
|
13
|
+
flowView._NodeTypeProvider.getEnabledCards();
|
|
14
|
+
flowView._NodeTypeProvider.getCardsByCategory();
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## registerNodeType
|
|
18
|
+
|
|
19
|
+
Register a node type configuration directly.
|
|
20
|
+
|
|
21
|
+
| Parameter | Type | Description |
|
|
22
|
+
|-----------|------|-------------|
|
|
23
|
+
| `pNodeTypeConfig` | object | Node type configuration |
|
|
24
|
+
|
|
25
|
+
**Returns:** `boolean`
|
|
26
|
+
|
|
27
|
+
### Configuration Shape
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
{
|
|
31
|
+
Hash: 'FREAD',
|
|
32
|
+
Label: 'File Read',
|
|
33
|
+
DefaultWidth: 160,
|
|
34
|
+
DefaultHeight: 70,
|
|
35
|
+
TitleBarColor: '#2980b9',
|
|
36
|
+
DefaultPorts:
|
|
37
|
+
[
|
|
38
|
+
{ Hash: null, Direction: 'input', Side: 'left', Label: 'Path', PortType: 'value' },
|
|
39
|
+
{ Hash: null, Direction: 'output', Side: 'right', Label: 'Data', PortType: 'value' },
|
|
40
|
+
{ Hash: null, Direction: 'output', Side: 'bottom', Label: 'Error', PortType: 'error' }
|
|
41
|
+
],
|
|
42
|
+
CardMetadata:
|
|
43
|
+
{
|
|
44
|
+
Name: 'File Read',
|
|
45
|
+
Code: 'FREAD',
|
|
46
|
+
Description: 'Read contents from a file path',
|
|
47
|
+
Category: 'File I/O',
|
|
48
|
+
Enabled: true
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## removeNodeType
|
|
54
|
+
|
|
55
|
+
Unregister a node type by hash.
|
|
56
|
+
|
|
57
|
+
**Returns:** `boolean`
|
|
58
|
+
|
|
59
|
+
## getNodeType
|
|
60
|
+
|
|
61
|
+
Retrieve a node type configuration by hash. Returns the default type if the hash is not found.
|
|
62
|
+
|
|
63
|
+
**Returns:** Node type configuration object.
|
|
64
|
+
|
|
65
|
+
## getNodeTypes
|
|
66
|
+
|
|
67
|
+
**Returns:** Map of all registered node types (hash → config).
|
|
68
|
+
|
|
69
|
+
## getNodeTypeList
|
|
70
|
+
|
|
71
|
+
**Returns:** Array of registered type hash strings.
|
|
72
|
+
|
|
73
|
+
## getEnabledCards
|
|
74
|
+
|
|
75
|
+
**Returns:** Array of card configurations where `CardMetadata.Enabled` is `true`.
|
|
76
|
+
|
|
77
|
+
## getCardsByCategory
|
|
78
|
+
|
|
79
|
+
**Returns:** Object mapping category names to arrays of card configurations. Useful for building palette UIs.
|
|
80
|
+
|
|
81
|
+
## Examples
|
|
82
|
+
|
|
83
|
+
### Register a type directly
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
flowView._NodeTypeProvider.registerNodeType(
|
|
87
|
+
{
|
|
88
|
+
Hash: 'FILTER',
|
|
89
|
+
Label: 'Filter',
|
|
90
|
+
DefaultWidth: 140,
|
|
91
|
+
DefaultHeight: 60,
|
|
92
|
+
TitleBarColor: '#9b59b6',
|
|
93
|
+
DefaultPorts:
|
|
94
|
+
[
|
|
95
|
+
{ Hash: null, Direction: 'input', Side: 'left', Label: 'In' },
|
|
96
|
+
{ Hash: null, Direction: 'output', Side: 'right', Label: 'Pass' },
|
|
97
|
+
{ Hash: null, Direction: 'output', Side: 'bottom', Label: 'Reject' }
|
|
98
|
+
],
|
|
99
|
+
CardMetadata:
|
|
100
|
+
{
|
|
101
|
+
Code: 'FILTER',
|
|
102
|
+
Category: 'Data',
|
|
103
|
+
Enabled: true
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### List all categories
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
let tmpCategories = flowView._NodeTypeProvider.getCardsByCategory();
|
|
112
|
+
|
|
113
|
+
Object.keys(tmpCategories).forEach((pCategory) =>
|
|
114
|
+
{
|
|
115
|
+
console.log(pCategory + ':');
|
|
116
|
+
tmpCategories[pCategory].forEach((pCard) =>
|
|
117
|
+
{
|
|
118
|
+
console.log(' -', pCard.Label, '(' + pCard.Hash + ')');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Check if a type exists
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
let tmpType = flowView._NodeTypeProvider.getNodeType('FREAD');
|
|
127
|
+
if (tmpType.Hash === 'FREAD')
|
|
128
|
+
{
|
|
129
|
+
console.log('File Read type is registered');
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Remove a type at runtime
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
flowView._NodeTypeProvider.removeNodeType('FREAD');
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## See Also
|
|
140
|
+
|
|
141
|
+
- [PictFlowCard](PictFlowCard.md) — Higher-level card class (recommended approach)
|
|
142
|
+
- [addNode](addNode.md) — Create nodes from registered types
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# removeConnection
|
|
2
|
+
|
|
3
|
+
Delete a connection from the flow canvas.
|
|
4
|
+
|
|
5
|
+
## Signature
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
flowView.removeConnection(pConnectionHash)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Parameters
|
|
12
|
+
|
|
13
|
+
| Parameter | Type | Required | Description |
|
|
14
|
+
|-----------|------|----------|-------------|
|
|
15
|
+
| `pConnectionHash` | string | Yes | Hash of the connection to remove |
|
|
16
|
+
|
|
17
|
+
## Returns
|
|
18
|
+
|
|
19
|
+
`boolean` — `true` if the connection was found and removed, `false` otherwise.
|
|
20
|
+
|
|
21
|
+
## Events Fired
|
|
22
|
+
|
|
23
|
+
- `onConnectionRemoved` — with the removed connection object
|
|
24
|
+
- `onFlowChanged` — with the updated flow data
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### Basic removal
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
let tmpConn = flowView.addConnection(
|
|
32
|
+
tmpA.Hash, tmpOutPort.Hash,
|
|
33
|
+
tmpB.Hash, tmpInPort.Hash
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
flowView.removeConnection(tmpConn.Hash);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Remove all connections for a specific node
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
let tmpFlowData = flowView.getFlowData();
|
|
43
|
+
let tmpTargetHash = myNode.Hash;
|
|
44
|
+
|
|
45
|
+
tmpFlowData.Connections.forEach((pConn) =>
|
|
46
|
+
{
|
|
47
|
+
if (pConn.SourceNodeHash === tmpTargetHash || pConn.TargetNodeHash === tmpTargetHash)
|
|
48
|
+
{
|
|
49
|
+
flowView.removeConnection(pConn.Hash);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## See Also
|
|
55
|
+
|
|
56
|
+
- [addConnection](addConnection.md) — Create a connection
|
|
57
|
+
- [removeNode](removeNode.md) — Remove a node (cascades connections)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# removeNode
|
|
2
|
+
|
|
3
|
+
Delete a node from the flow canvas. All connections attached to the node are also removed. Any open properties panel for the node is closed. The canvas is re-rendered.
|
|
4
|
+
|
|
5
|
+
## Signature
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
flowView.removeNode(pNodeHash)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Parameters
|
|
12
|
+
|
|
13
|
+
| Parameter | Type | Required | Description |
|
|
14
|
+
|-----------|------|----------|-------------|
|
|
15
|
+
| `pNodeHash` | string | Yes | Hash of the node to remove |
|
|
16
|
+
|
|
17
|
+
## Returns
|
|
18
|
+
|
|
19
|
+
`boolean` — `true` if the node was found and removed, `false` otherwise.
|
|
20
|
+
|
|
21
|
+
## Events Fired
|
|
22
|
+
|
|
23
|
+
- `onNodeRemoved` — with the removed node object
|
|
24
|
+
- `onConnectionRemoved` — for each connection that was cascaded
|
|
25
|
+
- `onFlowChanged` — with the updated flow data
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
### Basic removal
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
let tmpNode = flowView.addNode('default', 100, 100, 'Temporary');
|
|
33
|
+
|
|
34
|
+
// Later, remove it
|
|
35
|
+
let tmpRemoved = flowView.removeNode(tmpNode.Hash);
|
|
36
|
+
console.log(tmpRemoved); // true
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Remove with cascading connections
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
let tmpA = flowView.addNode('start', 50, 100, 'A');
|
|
43
|
+
let tmpB = flowView.addNode('default', 250, 100, 'B');
|
|
44
|
+
let tmpC = flowView.addNode('end', 450, 100, 'C');
|
|
45
|
+
|
|
46
|
+
// Connect A -> B -> C
|
|
47
|
+
flowView.addConnection(tmpA.Hash, tmpA.Ports[0].Hash, tmpB.Hash, tmpB.Ports[0].Hash);
|
|
48
|
+
flowView.addConnection(tmpB.Hash, tmpB.Ports[1].Hash, tmpC.Hash, tmpC.Ports[0].Hash);
|
|
49
|
+
|
|
50
|
+
// Removing B also removes both connections
|
|
51
|
+
flowView.removeNode(tmpB.Hash);
|
|
52
|
+
|
|
53
|
+
let tmpFlowData = flowView.getFlowData();
|
|
54
|
+
console.log(tmpFlowData.Connections.length); // 0
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Conditional removal with event tracking
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
flowView._EventHandlerProvider.registerHandler('onNodeRemoved',
|
|
61
|
+
(pNode) =>
|
|
62
|
+
{
|
|
63
|
+
console.log('Removed:', pNode.Title);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Only remove nodes of a certain type
|
|
67
|
+
let tmpFlowData = flowView.getFlowData();
|
|
68
|
+
tmpFlowData.Nodes.forEach((pNode) =>
|
|
69
|
+
{
|
|
70
|
+
if (pNode.Type === 'default')
|
|
71
|
+
{
|
|
72
|
+
flowView.removeNode(pNode.Hash);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## See Also
|
|
78
|
+
|
|
79
|
+
- [addNode](addNode.md) — Create a node
|
|
80
|
+
- [deleteSelected](selectNode.md) — Delete the currently selected element
|