@babylonjs/shared-ui-components 5.28.0 → 5.30.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 (249) hide show
  1. package/colorPicker/colorComponentEntry.d.ts +18 -18
  2. package/colorPicker/colorComponentEntry.js +36 -36
  3. package/colorPicker/colorPicker.d.ts +43 -43
  4. package/colorPicker/colorPicker.js +136 -136
  5. package/colorPicker/hexColor.d.ts +20 -20
  6. package/colorPicker/hexColor.js +42 -42
  7. package/components/Button.d.ts +10 -10
  8. package/components/Button.js +6 -6
  9. package/components/Icon.d.ts +6 -6
  10. package/components/Icon.js +6 -6
  11. package/components/Label.d.ts +7 -7
  12. package/components/Label.js +6 -6
  13. package/components/MessageDialog.d.ts +7 -7
  14. package/components/MessageDialog.js +22 -22
  15. package/components/Toggle.d.ts +8 -8
  16. package/components/Toggle.js +15 -15
  17. package/components/bars/CommandBarComponent.d.ts +16 -16
  18. package/components/bars/CommandBarComponent.js +68 -68
  19. package/components/bars/CommandBarComponent.js.map +1 -1
  20. package/components/bars/CommandButtonComponent.d.ts +11 -11
  21. package/components/bars/CommandButtonComponent.js +6 -6
  22. package/components/bars/CommandDropdownComponent.d.ts +26 -26
  23. package/components/bars/CommandDropdownComponent.js +48 -48
  24. package/components/classNames.d.ts +2 -2
  25. package/components/classNames.js +18 -18
  26. package/components/colorPicker/ColorComponentEntry.d.ts +18 -18
  27. package/components/colorPicker/ColorComponentEntry.js +37 -37
  28. package/components/colorPicker/ColorPicker.d.ts +43 -43
  29. package/components/colorPicker/ColorPicker.js +137 -137
  30. package/components/colorPicker/HexColor.d.ts +20 -20
  31. package/components/colorPicker/HexColor.js +45 -45
  32. package/components/layout/DraggableIcon.d.ts +23 -0
  33. package/components/layout/DraggableIcon.js +18 -0
  34. package/components/layout/DraggableIcon.js.map +1 -0
  35. package/components/layout/FlexibleColumn.d.ts +17 -0
  36. package/components/layout/FlexibleColumn.js +12 -0
  37. package/components/layout/FlexibleColumn.js.map +1 -0
  38. package/components/layout/FlexibleDragHandler.d.ts +18 -0
  39. package/components/layout/FlexibleDragHandler.js +88 -0
  40. package/components/layout/FlexibleDragHandler.js.map +1 -0
  41. package/components/layout/FlexibleDropZone.d.ts +19 -0
  42. package/components/layout/FlexibleDropZone.js +12 -0
  43. package/components/layout/FlexibleDropZone.js.map +1 -0
  44. package/components/layout/FlexibleGridContainer.d.ts +10 -0
  45. package/components/layout/FlexibleGridContainer.js +23 -0
  46. package/components/layout/FlexibleGridContainer.js.map +1 -0
  47. package/components/layout/FlexibleGridLayout.d.ts +16 -0
  48. package/components/layout/FlexibleGridLayout.js +24 -0
  49. package/components/layout/FlexibleGridLayout.js.map +1 -0
  50. package/components/layout/FlexibleResizeBar.d.ts +40 -0
  51. package/components/layout/FlexibleResizeBar.js +21 -0
  52. package/components/layout/FlexibleResizeBar.js.map +1 -0
  53. package/components/layout/FlexibleTab.d.ts +34 -0
  54. package/components/layout/FlexibleTab.js +36 -0
  55. package/components/layout/FlexibleTab.js.map +1 -0
  56. package/components/layout/FlexibleTabsContainer.d.ts +28 -0
  57. package/components/layout/FlexibleTabsContainer.js +54 -0
  58. package/components/layout/FlexibleTabsContainer.js.map +1 -0
  59. package/components/layout/LayoutContext.d.ts +12 -0
  60. package/components/layout/LayoutContext.js +3 -0
  61. package/components/layout/LayoutContext.js.map +1 -0
  62. package/components/layout/types.d.ts +82 -0
  63. package/components/layout/types.js +13 -0
  64. package/components/layout/types.js.map +1 -0
  65. package/components/layout/utils.d.ts +25 -0
  66. package/components/layout/utils.js +68 -0
  67. package/components/layout/utils.js.map +1 -0
  68. package/components/lines/ColorLineComponent.d.ts +40 -40
  69. package/components/lines/ColorLineComponent.js +145 -145
  70. package/components/lines/ColorPickerLineComponent.d.ts +33 -33
  71. package/components/lines/ColorPickerLineComponent.js +61 -61
  72. package/components/lines/FileButtonLineComponent.d.ts +16 -16
  73. package/components/lines/FileButtonLineComponent.js +21 -21
  74. package/components/lines/NumericInputComponent.d.ts +31 -31
  75. package/components/lines/NumericInputComponent.js +86 -86
  76. package/lines/booleanLineComponent.d.ts +11 -11
  77. package/lines/booleanLineComponent.js +14 -14
  78. package/lines/buttonLineComponent.d.ts +12 -12
  79. package/lines/buttonLineComponent.js +10 -10
  80. package/lines/checkBoxLineComponent.d.ts +36 -36
  81. package/lines/checkBoxLineComponent.js +88 -88
  82. package/lines/color3LineComponent.d.ts +18 -18
  83. package/lines/color3LineComponent.js +9 -9
  84. package/lines/color4LineComponent.d.ts +18 -18
  85. package/lines/color4LineComponent.js +9 -9
  86. package/lines/colorLineComponent.d.ts +40 -40
  87. package/lines/colorLineComponent.js +144 -144
  88. package/lines/colorPickerComponent.d.ts +31 -31
  89. package/lines/colorPickerComponent.js +60 -60
  90. package/lines/draggableLineComponent.d.ts +9 -9
  91. package/lines/draggableLineComponent.js +12 -12
  92. package/lines/fileButtonLineComponent.d.ts +17 -17
  93. package/lines/fileButtonLineComponent.js +20 -20
  94. package/lines/fileMultipleButtonLineComponent.d.ts +17 -17
  95. package/lines/fileMultipleButtonLineComponent.js +20 -20
  96. package/lines/floatLineComponent.d.ts +50 -50
  97. package/lines/floatLineComponent.js +175 -175
  98. package/lines/hexLineComponent.d.ts +40 -40
  99. package/lines/hexLineComponent.js +121 -121
  100. package/lines/iSelectedLineContainer.d.ts +4 -4
  101. package/lines/iSelectedLineContainer.js +1 -1
  102. package/lines/iconButtonLineComponent.d.ts +11 -11
  103. package/lines/iconButtonLineComponent.js +10 -10
  104. package/lines/iconComponent.d.ts +9 -9
  105. package/lines/iconComponent.js +7 -7
  106. package/lines/indentedTextLineComponent.d.ts +16 -16
  107. package/lines/indentedTextLineComponent.js +26 -26
  108. package/lines/inputArrowsComponent.d.ts +13 -13
  109. package/lines/inputArrowsComponent.js +37 -37
  110. package/lines/lineContainerComponent.d.ts +19 -19
  111. package/lines/lineContainerComponent.js +49 -49
  112. package/lines/linkButtonComponent.d.ts +16 -16
  113. package/lines/linkButtonComponent.js +20 -20
  114. package/lines/matrixLineComponent.d.ts +36 -36
  115. package/lines/matrixLineComponent.js +102 -102
  116. package/lines/messageLineComponent.d.ts +12 -12
  117. package/lines/messageLineComponent.js +14 -14
  118. package/lines/numericInputComponent.d.ts +31 -31
  119. package/lines/numericInputComponent.js +85 -85
  120. package/lines/optionsLineComponent.d.ts +48 -48
  121. package/lines/optionsLineComponent.js +118 -118
  122. package/lines/popup.d.ts +4 -4
  123. package/lines/popup.js +67 -67
  124. package/lines/radioLineComponent.d.ts +21 -21
  125. package/lines/radioLineComponent.js +26 -26
  126. package/lines/sliderLineComponent.d.ts +37 -37
  127. package/lines/sliderLineComponent.js +89 -89
  128. package/lines/targetsProxy.d.ts +11 -11
  129. package/lines/targetsProxy.js +42 -42
  130. package/lines/textInputLineComponent.d.ts +47 -47
  131. package/lines/textInputLineComponent.js +154 -154
  132. package/lines/textLineComponent.d.ts +21 -21
  133. package/lines/textLineComponent.js +30 -30
  134. package/lines/unitButton.d.ts +8 -8
  135. package/lines/unitButton.js +7 -7
  136. package/lines/valueLineComponent.d.ts +15 -15
  137. package/lines/valueLineComponent.js +12 -12
  138. package/lines/vector2LineComponent.d.ts +36 -36
  139. package/lines/vector2LineComponent.js +63 -63
  140. package/lines/vector3LineComponent.d.ts +41 -41
  141. package/lines/vector3LineComponent.js +74 -74
  142. package/lines/vector4LineComponent.d.ts +42 -42
  143. package/lines/vector4LineComponent.js +81 -81
  144. package/nodeGraphSystem/displayLedger.d.ts +5 -5
  145. package/nodeGraphSystem/displayLedger.js +3 -3
  146. package/nodeGraphSystem/frameNodePort.d.ts +25 -25
  147. package/nodeGraphSystem/frameNodePort.js +59 -59
  148. package/nodeGraphSystem/graphCanvas.d.ts +117 -111
  149. package/nodeGraphSystem/graphCanvas.js +1137 -1131
  150. package/nodeGraphSystem/graphCanvas.js.map +1 -1
  151. package/nodeGraphSystem/graphFrame.d.ts +153 -153
  152. package/nodeGraphSystem/graphFrame.js +1328 -1328
  153. package/nodeGraphSystem/graphNode.d.ts +81 -79
  154. package/nodeGraphSystem/graphNode.js +465 -459
  155. package/nodeGraphSystem/graphNode.js.map +1 -1
  156. package/nodeGraphSystem/interfaces/displayManager.d.ts +13 -13
  157. package/nodeGraphSystem/interfaces/displayManager.js +1 -1
  158. package/nodeGraphSystem/interfaces/nodeContainer.d.ts +6 -6
  159. package/nodeGraphSystem/interfaces/nodeContainer.js +1 -1
  160. package/nodeGraphSystem/interfaces/nodeData.d.ts +15 -15
  161. package/nodeGraphSystem/interfaces/nodeData.js +1 -1
  162. package/nodeGraphSystem/interfaces/nodeLocationInfo.d.ts +26 -26
  163. package/nodeGraphSystem/interfaces/nodeLocationInfo.js +1 -1
  164. package/nodeGraphSystem/interfaces/portData.d.ts +28 -28
  165. package/nodeGraphSystem/interfaces/portData.js +7 -7
  166. package/nodeGraphSystem/interfaces/propertyComponentProps.d.ts +6 -6
  167. package/nodeGraphSystem/interfaces/propertyComponentProps.js +1 -1
  168. package/nodeGraphSystem/interfaces/selectionChangedOptions.d.ts +11 -11
  169. package/nodeGraphSystem/interfaces/selectionChangedOptions.js +1 -1
  170. package/nodeGraphSystem/nodeLink.d.ts +31 -31
  171. package/nodeGraphSystem/nodeLink.js +182 -182
  172. package/nodeGraphSystem/nodePort.d.ts +35 -35
  173. package/nodeGraphSystem/nodePort.js +128 -128
  174. package/nodeGraphSystem/propertyLedger.d.ts +8 -8
  175. package/nodeGraphSystem/propertyLedger.js +3 -3
  176. package/nodeGraphSystem/stateManager.d.ts +45 -45
  177. package/nodeGraphSystem/stateManager.js +18 -18
  178. package/nodeGraphSystem/tools.d.ts +5 -5
  179. package/nodeGraphSystem/tools.js +36 -36
  180. package/nodeGraphSystem/typeLedger.d.ts +8 -8
  181. package/nodeGraphSystem/typeLedger.js +2 -2
  182. package/nodeGraphSystem/types/framePortData.d.ts +7 -7
  183. package/nodeGraphSystem/types/framePortData.js +1 -1
  184. package/package.json +4 -3
  185. package/propertyChangedEvent.d.ts +7 -7
  186. package/propertyChangedEvent.js +2 -2
  187. package/stories/Button.stories.d.ts +10 -10
  188. package/stories/Button.stories.js +19 -19
  189. package/stories/Icon.stories.d.ts +9 -9
  190. package/stories/Icon.stories.js +16 -16
  191. package/stories/Label.stories.d.ts +8 -8
  192. package/stories/Label.stories.js +10 -10
  193. package/stories/MessageDialog.stories.d.ts +9 -9
  194. package/stories/MessageDialog.stories.js +19 -19
  195. package/stories/Toggle.stories.d.ts +9 -9
  196. package/stories/Toggle.stories.js +17 -17
  197. package/stories/bars/CommandBarComponent.stories.d.ts +11 -11
  198. package/stories/bars/CommandBarComponent.stories.js +12 -12
  199. package/stories/bars/CommandButtonComponent.stories.d.ts +6 -6
  200. package/stories/bars/CommandButtonComponent.stories.js +6 -6
  201. package/stories/colorPicker/ColorPicker.stories.d.ts +11 -11
  202. package/stories/colorPicker/ColorPicker.stories.js +4 -4
  203. package/stories/layout/FlexibleGridLayout.stories.d.ts +46 -0
  204. package/stories/layout/FlexibleGridLayout.stories.js +48 -0
  205. package/stories/layout/FlexibleGridLayout.stories.js.map +1 -0
  206. package/stories/lines/ColorLineComponent.stories.d.ts +21 -21
  207. package/stories/lines/ColorLineComponent.stories.js +9 -9
  208. package/stories/lines/ColorPickerLineComponent.stories.d.ts +14 -14
  209. package/stories/lines/ColorPickerLineComponent.stories.js +10 -10
  210. package/stories/lines/FileButtonLineComponent.stories.d.ts +6 -6
  211. package/stories/lines/FileButtonLineComponent.stories.js +5 -5
  212. package/stories/lines/NumericInputComponent.stories.d.ts +11 -11
  213. package/stories/lines/NumericInputComponent.stories.js +5 -5
  214. package/stringTools.d.ts +11 -11
  215. package/stringTools.js +88 -88
  216. package/tabs/propertyGrids/gui/checkboxPropertyGridComponent.d.ts +15 -15
  217. package/tabs/propertyGrids/gui/checkboxPropertyGridComponent.js +15 -15
  218. package/tabs/propertyGrids/gui/colorPickerPropertyGridComponent.d.ts +15 -15
  219. package/tabs/propertyGrids/gui/colorPickerPropertyGridComponent.js +14 -14
  220. package/tabs/propertyGrids/gui/commonControlPropertyGridComponent.d.ts +17 -17
  221. package/tabs/propertyGrids/gui/commonControlPropertyGridComponent.js +55 -55
  222. package/tabs/propertyGrids/gui/controlPropertyGridComponent.d.ts +15 -15
  223. package/tabs/propertyGrids/gui/controlPropertyGridComponent.js +12 -12
  224. package/tabs/propertyGrids/gui/ellipsePropertyGridComponent.d.ts +15 -15
  225. package/tabs/propertyGrids/gui/ellipsePropertyGridComponent.js +15 -15
  226. package/tabs/propertyGrids/gui/gridPropertyGridComponent.d.ts +17 -17
  227. package/tabs/propertyGrids/gui/gridPropertyGridComponent.js +38 -38
  228. package/tabs/propertyGrids/gui/imageBasedSliderPropertyGridComponent.d.ts +15 -15
  229. package/tabs/propertyGrids/gui/imageBasedSliderPropertyGridComponent.js +16 -16
  230. package/tabs/propertyGrids/gui/imagePropertyGridComponent.d.ts +15 -15
  231. package/tabs/propertyGrids/gui/imagePropertyGridComponent.js +25 -25
  232. package/tabs/propertyGrids/gui/inputTextPropertyGridComponent.d.ts +15 -15
  233. package/tabs/propertyGrids/gui/inputTextPropertyGridComponent.js +17 -17
  234. package/tabs/propertyGrids/gui/linePropertyGridComponent.d.ts +16 -16
  235. package/tabs/propertyGrids/gui/linePropertyGridComponent.js +27 -27
  236. package/tabs/propertyGrids/gui/radioButtonPropertyGridComponent.d.ts +15 -15
  237. package/tabs/propertyGrids/gui/radioButtonPropertyGridComponent.js +17 -17
  238. package/tabs/propertyGrids/gui/rectanglePropertyGridComponent.d.ts +15 -15
  239. package/tabs/propertyGrids/gui/rectanglePropertyGridComponent.js +15 -15
  240. package/tabs/propertyGrids/gui/scrollViewerPropertyGridComponent.d.ts +15 -15
  241. package/tabs/propertyGrids/gui/scrollViewerPropertyGridComponent.js +15 -15
  242. package/tabs/propertyGrids/gui/sliderPropertyGridComponent.d.ts +15 -15
  243. package/tabs/propertyGrids/gui/sliderPropertyGridComponent.js +16 -16
  244. package/tabs/propertyGrids/gui/stackPanelPropertyGridComponent.d.ts +15 -15
  245. package/tabs/propertyGrids/gui/stackPanelPropertyGridComponent.js +14 -14
  246. package/tabs/propertyGrids/gui/textBlockPropertyGridComponent.d.ts +15 -15
  247. package/tabs/propertyGrids/gui/textBlockPropertyGridComponent.js +34 -34
  248. package/tabs/propertyGrids/lockObject.d.ts +9 -9
  249. package/tabs/propertyGrids/lockObject.js +11 -11
@@ -1,1132 +1,1138 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import * as React from "react";
3
- import { GraphNode } from "./graphNode.js";
4
- import * as dagre from "dagre";
5
- import { NodeLink } from "./nodeLink.js";
6
- import { NodePort } from "./nodePort.js";
7
- import { Vector2 } from "@babylonjs/core/Maths/math.vector.js";
8
- import { DataStorage } from "@babylonjs/core/Misc/dataStorage.js";
9
- import { GraphFrame } from "./graphFrame.js";
10
- import { FrameNodePort } from "./frameNodePort.js";
11
- import { PortDataDirection } from "./interfaces/portData.js";
12
- import styles from "./graphCanvas.modules.scss";
13
- import commonStyles from "./common.modules.scss";
14
- import { TypeLedger } from "./typeLedger.js";
15
- import { RefreshNode } from "./tools.js";
16
- export class GraphCanvasComponent extends React.Component {
17
- constructor(props) {
18
- super(props);
19
- this._minZoom = 0.1;
20
- this._maxZoom = 4;
21
- this._nodes = [];
22
- this._links = [];
23
- this._mouseStartPointX = null;
24
- this._mouseStartPointY = null;
25
- this._dropPointX = 0;
26
- this._dropPointY = 0;
27
- this._selectionStartX = 0;
28
- this._selectionStartY = 0;
29
- this._candidateLinkedHasMoved = false;
30
- this._x = 0;
31
- this._y = 0;
32
- this._zoom = 1;
33
- this._selectedNodes = [];
34
- this._selectedLink = null;
35
- this._selectedPort = null;
36
- this._candidateLink = null;
37
- this._candidatePort = null;
38
- this._gridSize = 20;
39
- this._selectionBox = null;
40
- this._selectedFrames = [];
41
- this._frameCandidate = null;
42
- this._frames = [];
43
- this._nodeDataContentList = new Array();
44
- this._altKeyIsPressed = false;
45
- this._multiKeyIsPressed = false;
46
- this._oldY = -1;
47
- this._frameIsMoving = false;
48
- this._isLoading = false;
49
- this._targetLinkCandidate = null;
50
- this._copiedNodes = [];
51
- this._copiedFrames = [];
52
- props.stateManager.onSelectionChangedObservable.add((options) => {
53
- const { selection, forceKeepSelection, marqueeSelection = false } = options || {};
54
- if (!selection) {
55
- this._selectedNodes = [];
56
- this._selectedLink = null;
57
- this._selectedFrames = [];
58
- this._selectedPort = null;
59
- }
60
- else {
61
- if (selection instanceof NodeLink) {
62
- this._selectedNodes = [];
63
- this._selectedFrames = [];
64
- this._selectedLink = selection;
65
- this._selectedPort = null;
66
- }
67
- else if (selection instanceof NodePort) {
68
- this._selectedNodes = [];
69
- this._selectedFrames = [];
70
- this._selectedLink = null;
71
- this._selectedPort = selection;
72
- }
73
- else if (selection instanceof FrameNodePort) {
74
- this._selectedNodes = [];
75
- this._selectedFrames = [];
76
- this._selectedLink = null;
77
- this._selectedPort = selection;
78
- }
79
- else if (selection instanceof GraphNode || selection instanceof GraphFrame) {
80
- // If in marquee selection mode, always prioritize selecting nodes. Otherwise, always prioritize selecting the type of
81
- // the selected element
82
- if (marqueeSelection) {
83
- if (selection instanceof GraphFrame && !this._selectedFrames.includes(selection)) {
84
- this._selectedFrames.push(selection);
85
- }
86
- else if (selection instanceof GraphNode && !this._selectedNodes.includes(selection)) {
87
- this._selectedNodes.push(selection);
88
- }
89
- if (this._selectedFrameAndNodesConflict(this.selectedFrames, this.selectedNodes)) {
90
- const framesToRemove = new Set();
91
- for (const selectedNode of this._selectedNodes) {
92
- for (const selectedFrame of this._selectedFrames) {
93
- if (selectedFrame.nodes.includes(selectedNode)) {
94
- framesToRemove.add(selectedFrame);
95
- }
96
- }
97
- }
98
- this._selectedFrames = this._selectedFrames.filter((f) => !framesToRemove.has(f));
99
- }
100
- }
101
- else {
102
- if (selection instanceof GraphFrame) {
103
- if (this._multiKeyIsPressed || forceKeepSelection) {
104
- if (!this._selectedFrameAndNodesConflict([selection], this._selectedNodes) && !this._selectedFrames.includes(selection)) {
105
- this._selectedFrames.push(selection);
106
- }
107
- }
108
- else {
109
- this._selectedFrames = [selection];
110
- this._selectedNodes = [];
111
- this._selectedLink = null;
112
- this._selectedPort = null;
113
- }
114
- }
115
- else if (selection instanceof GraphNode) {
116
- if (this._multiKeyIsPressed || forceKeepSelection) {
117
- if (!this._selectedFrameAndNodesConflict(this._selectedFrames, [selection]) && !this._selectedNodes.includes(selection)) {
118
- this._selectedNodes.push(selection);
119
- }
120
- }
121
- else {
122
- this._selectedFrames = [];
123
- this._selectedNodes = [selection];
124
- this._selectedLink = null;
125
- this._selectedPort = null;
126
- }
127
- }
128
- }
129
- }
130
- }
131
- });
132
- props.stateManager.onCandidatePortSelectedObservable.add((port) => {
133
- this._candidatePort = port;
134
- });
135
- props.stateManager.onGridSizeChanged.add(() => {
136
- this.gridSize = DataStorage.ReadNumber("GridSize", 20);
137
- });
138
- this.props.stateManager.hostDocument.addEventListener("keyup", () => this.onKeyUp(), false);
139
- this.props.stateManager.hostDocument.addEventListener("keydown", (evt) => {
140
- this._altKeyIsPressed = evt.altKey;
141
- this._multiKeyIsPressed = evt.ctrlKey || evt.metaKey;
142
- }, false);
143
- this.props.stateManager.hostDocument.defaultView.addEventListener("blur", () => {
144
- this._altKeyIsPressed = false;
145
- this._multiKeyIsPressed = false;
146
- }, false);
147
- // Store additional data to serialization object
148
- this.props.stateManager.storeEditorData = (editorData, graphFrame) => {
149
- editorData.frames = [];
150
- if (graphFrame) {
151
- editorData.frames.push(graphFrame.serialize(false));
152
- }
153
- else {
154
- editorData.x = this.x;
155
- editorData.y = this.y;
156
- editorData.zoom = this.zoom;
157
- for (const frame of this._frames) {
158
- editorData.frames.push(frame.serialize(true));
159
- }
160
- }
161
- };
162
- }
163
- get gridSize() {
164
- return this._gridSize;
165
- }
166
- set gridSize(value) {
167
- this._gridSize = value;
168
- this.updateTransform();
169
- }
170
- get stateManager() {
171
- return this.props.stateManager;
172
- }
173
- get nodes() {
174
- return this._nodes;
175
- }
176
- get links() {
177
- return this._links;
178
- }
179
- get frames() {
180
- return this._frames;
181
- }
182
- get zoom() {
183
- return this._zoom;
184
- }
185
- set zoom(value) {
186
- if (this._zoom === value) {
187
- return;
188
- }
189
- this._zoom = value;
190
- this.updateTransform();
191
- }
192
- get x() {
193
- return this._x;
194
- }
195
- set x(value) {
196
- this._x = value;
197
- this.updateTransform();
198
- }
199
- get y() {
200
- return this._y;
201
- }
202
- set y(value) {
203
- this._y = value;
204
- this.updateTransform();
205
- }
206
- get selectedNodes() {
207
- return this._selectedNodes;
208
- }
209
- get selectedLink() {
210
- return this._selectedLink;
211
- }
212
- get selectedFrames() {
213
- return this._selectedFrames;
214
- }
215
- get selectedPort() {
216
- return this._selectedPort;
217
- }
218
- get canvasContainer() {
219
- return this._graphCanvas;
220
- }
221
- get hostCanvas() {
222
- return this._hostCanvas;
223
- }
224
- get svgCanvas() {
225
- return this._svgCanvas;
226
- }
227
- get selectionContainer() {
228
- return this._selectionContainer;
229
- }
230
- get frameContainer() {
231
- return this._frameContainer;
232
- }
233
- // There is a selection conflict between nodes and frames if any selected node is inside any selected frame
234
- _selectedFrameAndNodesConflict(frameSelection, nodeSelection) {
235
- for (const frame of frameSelection) {
236
- for (const node of nodeSelection) {
237
- if (frame.nodes.includes(node)) {
238
- return true;
239
- }
240
- }
241
- }
242
- return false;
243
- }
244
- populateConnectedEntriesBeforeRemoval(item, items, inputs, outputs) {
245
- inputs.push(...item.content.inputs.filter((i) => i.isConnected && items.every((selected) => { var _a; return selected.content.data !== ((_a = i.connectedPort) === null || _a === void 0 ? void 0 : _a.ownerData); })).map((i) => i.connectedPort));
246
- outputs.push(...item.content.outputs
247
- .filter((i) => i.isConnected)
248
- .map((i) => i.endpoints)
249
- .flat()
250
- .filter((i) => i && items.every((selected) => selected.content.data !== i.ownerData)));
251
- }
252
- automaticRewire(inputs, outputs, firstOnly = false) {
253
- let oneConnectionFound = false;
254
- if (outputs.length && inputs.length) {
255
- inputs.forEach((input) => {
256
- if (oneConnectionFound) {
257
- return;
258
- }
259
- if (!input) {
260
- return;
261
- }
262
- const output = outputs[0];
263
- if (output && input.canConnectTo(output)) {
264
- const nodeInput = this.findNodeFromData(input.ownerData);
265
- const nodeOutput = this.findNodeFromData(output.ownerData);
266
- this.connectNodes(nodeInput, input, nodeOutput, output);
267
- outputs.shift();
268
- if (firstOnly) {
269
- oneConnectionFound = true;
270
- return;
271
- }
272
- }
273
- });
274
- }
275
- }
276
- handleKeyDown(evt, onRemove, mouseLocationX, mouseLocationY, dataGenerator, rootElement) {
277
- if ((evt.keyCode === 46 || evt.keyCode === 8) && !this.props.stateManager.lockObject.lock) {
278
- // Delete
279
- const selectedItems = this.selectedNodes;
280
- const inputs = [];
281
- const outputs = [];
282
- if (selectedItems.length > 0) {
283
- for (const selectedItem of selectedItems) {
284
- if (evt.altKey) {
285
- this.populateConnectedEntriesBeforeRemoval(selectedItem, selectedItems, inputs, outputs);
286
- }
287
- selectedItem.dispose();
288
- onRemove(selectedItem.content);
289
- this.removeDataFromCache(selectedItem.content.data);
290
- }
291
- }
292
- if (this.selectedLink) {
293
- this.selectedLink.dispose();
294
- }
295
- if (this.selectedFrames.length) {
296
- for (const frame of this.selectedFrames) {
297
- if (frame.isCollapsed) {
298
- while (frame.nodes.length > 0) {
299
- onRemove(frame.nodes[0].content);
300
- this.removeDataFromCache(frame.nodes[0].content.data);
301
- frame.nodes[0].dispose();
302
- }
303
- frame.isCollapsed = false;
304
- }
305
- else {
306
- frame.nodes.forEach((node) => {
307
- node.enclosingFrameId = -1;
308
- });
309
- }
310
- frame.dispose();
311
- }
312
- }
313
- // Reconnect if required
314
- this.automaticRewire(inputs, outputs);
315
- this.props.stateManager.onSelectionChangedObservable.notifyObservers(null);
316
- this.props.stateManager.onRebuildRequiredObservable.notifyObservers(false);
317
- return;
318
- }
319
- if ((!evt.ctrlKey && !evt.metaKey) || this.props.stateManager.lockObject.lock) {
320
- return;
321
- }
322
- if (evt.key === "c" || evt.key === "C") {
323
- // Copy
324
- this._copiedNodes = [];
325
- this._copiedFrames = [];
326
- if (this.selectedFrames.length) {
327
- for (const frame of this.selectedFrames) {
328
- frame.serialize(true);
329
- this._copiedFrames.push(frame);
330
- }
331
- return;
332
- }
333
- const selectedItems = this.selectedNodes;
334
- if (!selectedItems.length) {
335
- return;
336
- }
337
- const selectedItem = selectedItems[0];
338
- if (!selectedItem.content.data) {
339
- return;
340
- }
341
- this._copiedNodes = selectedItems.slice(0);
342
- }
343
- else if (evt.key === "v" || evt.key === "V") {
344
- // Paste
345
- const zoomLevel = this.zoom;
346
- let currentY = (mouseLocationY - rootElement.offsetTop - this.y - 20) / zoomLevel;
347
- if (this._copiedFrames.length) {
348
- for (const frame of this._copiedFrames) {
349
- // New frame
350
- const newFrame = new GraphFrame(null, this, true);
351
- this.frames.push(newFrame);
352
- newFrame.width = frame.width;
353
- newFrame.height = frame.height;
354
- newFrame.width / 2;
355
- newFrame.name = frame.name;
356
- newFrame.color = frame.color;
357
- let currentX = (mouseLocationX - rootElement.offsetLeft - this.x) / zoomLevel;
358
- newFrame.x = currentX - newFrame.width / 2;
359
- newFrame.y = currentY;
360
- // Paste nodes
361
- if (frame.nodes.length) {
362
- currentX = newFrame.x + frame.nodes[0].x - frame.x;
363
- currentY = newFrame.y + frame.nodes[0].y - frame.y;
364
- this._frameIsMoving = true;
365
- const newNodes = this.pasteSelection(frame.nodes, currentX, currentY, dataGenerator);
366
- if (newNodes) {
367
- for (const node of newNodes) {
368
- newFrame.syncNode(node);
369
- }
370
- }
371
- this._frameIsMoving = false;
372
- }
373
- newFrame.adjustPorts();
374
- if (frame.isCollapsed) {
375
- newFrame.isCollapsed = true;
376
- }
377
- // Select
378
- this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: newFrame, forceKeepSelection: true });
379
- return;
380
- }
381
- }
382
- if (!this._copiedNodes.length) {
383
- return;
384
- }
385
- const currentX = (mouseLocationX - rootElement.offsetLeft - this.x - GraphCanvasComponent.NodeWidth) / zoomLevel;
386
- this.pasteSelection(this._copiedNodes, currentX, currentY, dataGenerator, true);
387
- }
388
- }
389
- pasteSelection(copiedNodes, currentX, currentY, dataGenerator, selectNew = false) {
390
- let originalNode = null;
391
- const newNodes = [];
392
- // Copy to prevent recursive side effects while creating nodes.
393
- copiedNodes = copiedNodes.slice();
394
- // Cancel selection
395
- this.props.stateManager.onSelectionChangedObservable.notifyObservers(null);
396
- // Create new nodes
397
- for (const node of copiedNodes) {
398
- const data = node.content.data;
399
- if (!data) {
400
- continue;
401
- }
402
- const newNode = dataGenerator(node.content);
403
- let x = 0;
404
- let y = 0;
405
- if (originalNode) {
406
- x = currentX + node.x - originalNode.x;
407
- y = currentY + node.y - originalNode.y;
408
- }
409
- else {
410
- originalNode = node;
411
- x = currentX;
412
- y = currentY;
413
- }
414
- newNode.x = x;
415
- newNode.y = y;
416
- newNode.cleanAccumulation();
417
- newNodes.push(newNode);
418
- if (selectNew) {
419
- this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: newNode, forceKeepSelection: true });
420
- }
421
- }
422
- // Relink
423
- const done = new Array(newNodes.length);
424
- for (let index = 0; index < newNodes.length; index++) {
425
- this.reconnectNewNodes(index, newNodes, copiedNodes, done);
426
- }
427
- return newNodes;
428
- }
429
- reconnectNewNodes(nodeIndex, newNodes, sourceNodes, done) {
430
- if (done[nodeIndex]) {
431
- return;
432
- }
433
- const currentNode = newNodes[nodeIndex];
434
- const sourceNode = sourceNodes[nodeIndex];
435
- for (let inputIndex = 0; inputIndex < sourceNode.content.inputs.length; inputIndex++) {
436
- const sourceInput = sourceNode.content.inputs[inputIndex];
437
- const currentInput = currentNode.content.inputs[inputIndex];
438
- if (!sourceInput.isConnected) {
439
- continue;
440
- }
441
- const sourceContent = this.findNodeFromData(sourceInput.connectedPort.ownerData).content;
442
- const activeNodes = sourceNodes.filter((s) => s.content === sourceContent);
443
- if (activeNodes.length > 0) {
444
- const activeNode = activeNodes[0];
445
- const indexInList = sourceNodes.indexOf(activeNode);
446
- // First make sure to connect the other one
447
- this.reconnectNewNodes(indexInList, newNodes, sourceNodes, done);
448
- // Then reconnect
449
- const outputIndex = sourceContent.outputs.indexOf(sourceInput.connectedPort);
450
- const newOutput = newNodes[indexInList].content.data.outputs[outputIndex];
451
- newOutput.connectTo(currentInput.data);
452
- }
453
- else {
454
- // Connect with outside nodes
455
- sourceInput.connectedPort.connectTo(currentInput);
456
- }
457
- this.connectPorts(currentInput.connectedPort, currentInput);
458
- }
459
- currentNode.refresh();
460
- done[nodeIndex] = true;
461
- }
462
- getCachedData() {
463
- return this._nodeDataContentList;
464
- }
465
- removeDataFromCache(data) {
466
- const dataIndex = this._nodeDataContentList.indexOf(data);
467
- if (dataIndex > -1) {
468
- this._nodeDataContentList.splice(dataIndex, 1);
469
- }
470
- }
471
- createNodeFromObject(nodeData, onNodeCreated, recursion = true) {
472
- if (this._nodeDataContentList.indexOf(nodeData.data) !== -1) {
473
- // Links
474
- if (nodeData.inputs.length && recursion) {
475
- for (const input of nodeData.inputs) {
476
- if (input.isConnected) {
477
- this.connectPorts(input.connectedPort, input);
478
- }
479
- }
480
- }
481
- return this.nodes.filter((n) => n.content.data === nodeData.data)[0];
482
- }
483
- onNodeCreated(nodeData.data);
484
- // Connections
485
- if (nodeData.inputs.length) {
486
- for (const input of nodeData.inputs) {
487
- if (input.connectedPort && recursion) {
488
- this.createNodeFromObject(TypeLedger.NodeDataBuilder(input.connectedPort.ownerData, this), onNodeCreated);
489
- }
490
- }
491
- }
492
- // Graph
493
- const node = this.appendNode(nodeData);
494
- // Links
495
- if (nodeData.inputs.length && recursion) {
496
- for (const input of nodeData.inputs) {
497
- if (input.isConnected) {
498
- this.connectPorts(input.connectedPort, input);
499
- }
500
- }
501
- }
502
- return node;
503
- }
504
- getGridPosition(position, useCeil = false) {
505
- const gridSize = this.gridSize;
506
- if (gridSize === 0) {
507
- return position;
508
- }
509
- if (useCeil) {
510
- return gridSize * Math.ceil(position / gridSize);
511
- }
512
- return gridSize * Math.floor(position / gridSize);
513
- }
514
- getGridPositionCeil(position) {
515
- const gridSize = this.gridSize;
516
- if (gridSize === 0) {
517
- return position;
518
- }
519
- return gridSize * Math.ceil(position / gridSize);
520
- }
521
- updateTransform() {
522
- this._rootContainer.style.transform = `translate(${this._x}px, ${this._y}px) scale(${this._zoom})`;
523
- if (DataStorage.ReadBoolean("ShowGrid", true)) {
524
- this._hostCanvas.style.backgroundSize = `${this._gridSize * this._zoom}px ${this._gridSize * this._zoom}px`;
525
- this._hostCanvas.style.backgroundPosition = `${this._x}px ${this._y}px`;
526
- }
527
- else {
528
- this._hostCanvas.style.backgroundSize = `0`;
529
- }
530
- }
531
- onKeyUp() {
532
- this._altKeyIsPressed = false;
533
- this._multiKeyIsPressed = false;
534
- this._oldY = -1;
535
- }
536
- findNodeFromData(data) {
537
- return this.nodes.filter((n) => n.content.data === data)[0];
538
- }
539
- reset() {
540
- this._nodeDataContentList = [];
541
- for (const node of this._nodes) {
542
- node.dispose();
543
- }
544
- const frames = this._frames.splice(0);
545
- for (const frame of frames) {
546
- frame.dispose();
547
- }
548
- this._nodes = [];
549
- this._frames = [];
550
- this._links = [];
551
- this._graphCanvas.innerHTML = "";
552
- this._svgCanvas.innerHTML = "";
553
- }
554
- connectPorts(pointA, pointB) {
555
- if (!pointA || !pointB) {
556
- return;
557
- }
558
- const ownerDataA = pointA.ownerData;
559
- const ownerDataB = pointB.ownerData;
560
- const nodeA = this.findNodeFromData(ownerDataA);
561
- const nodeB = this.findNodeFromData(ownerDataB);
562
- if (!nodeA || !nodeB) {
563
- return;
564
- }
565
- const portA = nodeA.getPortForPortData(pointA);
566
- const portB = nodeB.getPortForPortData(pointB);
567
- if (!portA || !portB) {
568
- return;
569
- }
570
- for (const currentLink of this._links) {
571
- if (currentLink.portA === portA && currentLink.portB === portB) {
572
- return;
573
- }
574
- if (currentLink.portA === portB && currentLink.portB === portA) {
575
- return;
576
- }
577
- }
578
- const link = new NodeLink(this, portA, nodeA, portB, nodeB);
579
- this._links.push(link);
580
- nodeA.links.push(link);
581
- nodeB.links.push(link);
582
- }
583
- removeLink(link) {
584
- const index = this._links.indexOf(link);
585
- if (index > -1) {
586
- this._links.splice(index, 1);
587
- }
588
- link.dispose();
589
- }
590
- appendNode(nodeData) {
591
- const newNode = new GraphNode(nodeData, this.props.stateManager);
592
- newNode.appendVisual(this._graphCanvas, this);
593
- this._nodes.push(newNode);
594
- this._nodeDataContentList.push(nodeData.data);
595
- return newNode;
596
- }
597
- distributeGraph() {
598
- this.x = 0;
599
- this.y = 0;
600
- this.zoom = 1;
601
- const graph = new dagre.graphlib.Graph();
602
- graph.setGraph({});
603
- graph.setDefaultEdgeLabel(() => ({}));
604
- graph.graph().rankdir = "LR";
605
- // Build dagre graph
606
- this._nodes.forEach((node) => {
607
- if (this._frames.some((f) => f.nodes.indexOf(node) !== -1)) {
608
- return;
609
- }
610
- graph.setNode(node.id.toString(), {
611
- id: node.id,
612
- type: "node",
613
- width: node.width,
614
- height: node.height,
615
- });
616
- });
617
- this._frames.forEach((frame) => {
618
- graph.setNode(frame.id.toString(), {
619
- id: frame.id,
620
- type: "frame",
621
- width: frame.element.clientWidth,
622
- height: frame.element.clientHeight,
623
- });
624
- });
625
- this._nodes.forEach((node) => {
626
- node.content.outputs.forEach((output) => {
627
- if (!output.hasEndpoints) {
628
- return;
629
- }
630
- output.endpoints.forEach((endpoint) => {
631
- const sourceFrames = this._frames.filter((f) => f.nodes.indexOf(node) !== -1);
632
- const targetFrames = this._frames.filter((f) => f.nodes.some((n) => n.content.data === endpoint.ownerData));
633
- const sourceId = sourceFrames.length > 0 ? sourceFrames[0].id : node.id;
634
- const targetId = targetFrames.length > 0 ? targetFrames[0].id : endpoint.ownerData.uniqueId;
635
- graph.setEdge(sourceId.toString(), targetId.toString());
636
- });
637
- });
638
- });
639
- // Distribute
640
- dagre.layout(graph);
641
- // Update graph
642
- const dagreNodes = graph.nodes().map((node) => graph.node(node));
643
- dagreNodes.forEach((dagreNode) => {
644
- if (!dagreNode) {
645
- return;
646
- }
647
- if (dagreNode.type === "node") {
648
- for (const node of this._nodes) {
649
- if (node.id === dagreNode.id) {
650
- node.x = dagreNode.x - dagreNode.width / 2;
651
- node.y = dagreNode.y - dagreNode.height / 2;
652
- node.cleanAccumulation();
653
- return;
654
- }
655
- }
656
- return;
657
- }
658
- for (const frame of this._frames) {
659
- if (frame.id === dagreNode.id) {
660
- this._frameIsMoving = true;
661
- frame.move(dagreNode.x - dagreNode.width / 2, dagreNode.y - dagreNode.height / 2, false);
662
- frame.cleanAccumulation();
663
- this._frameIsMoving = false;
664
- return;
665
- }
666
- }
667
- });
668
- }
669
- componentDidMount() {
670
- this._hostCanvas = this.props.stateManager.hostDocument.getElementById("graph-canvas");
671
- this._rootContainer = this.props.stateManager.hostDocument.getElementById("graph-container");
672
- this._graphCanvas = this.props.stateManager.hostDocument.getElementById("graph-canvas-container");
673
- this._svgCanvas = this.props.stateManager.hostDocument.getElementById("graph-svg-container");
674
- this._selectionContainer = this.props.stateManager.hostDocument.getElementById("selection-container");
675
- this._frameContainer = this.props.stateManager.hostDocument.getElementById("frame-container");
676
- this.gridSize = DataStorage.ReadNumber("GridSize", 20);
677
- this.updateTransform();
678
- }
679
- onMove(evt) {
680
- // Selection box
681
- if (this._selectionBox) {
682
- const rootRect = this.canvasContainer.getBoundingClientRect();
683
- const localX = evt.pageX - rootRect.left;
684
- const localY = evt.pageY - rootRect.top;
685
- if (localX > this._selectionStartX) {
686
- this._selectionBox.style.left = `${this._selectionStartX / this.zoom}px`;
687
- this._selectionBox.style.width = `${(localX - this._selectionStartX) / this.zoom}px`;
688
- }
689
- else {
690
- this._selectionBox.style.left = `${localX / this.zoom}px`;
691
- this._selectionBox.style.width = `${(this._selectionStartX - localX) / this.zoom}px`;
692
- }
693
- if (localY > this._selectionStartY) {
694
- this._selectionBox.style.top = `${this._selectionStartY / this.zoom}px`;
695
- this._selectionBox.style.height = `${(localY - this._selectionStartY) / this.zoom}px`;
696
- }
697
- else {
698
- this._selectionBox.style.top = `${localY / this.zoom}px`;
699
- this._selectionBox.style.height = `${(this._selectionStartY - localY) / this.zoom}px`;
700
- }
701
- this.props.stateManager.onSelectionBoxMoved.notifyObservers(this._selectionBox.getBoundingClientRect());
702
- return;
703
- }
704
- // Candidate frame box
705
- if (this._frameCandidate) {
706
- const rootRect = this.canvasContainer.getBoundingClientRect();
707
- const localX = evt.pageX - rootRect.left;
708
- const localY = evt.pageY - rootRect.top;
709
- if (localX > this._selectionStartX) {
710
- this._frameCandidate.style.left = `${this._selectionStartX / this.zoom}px`;
711
- this._frameCandidate.style.width = `${(localX - this._selectionStartX) / this.zoom}px`;
712
- }
713
- else {
714
- this._frameCandidate.style.left = `${localX / this.zoom}px`;
715
- this._frameCandidate.style.width = `${(this._selectionStartX - localX) / this.zoom}px`;
716
- }
717
- if (localY > this._selectionStartY) {
718
- this._frameCandidate.style.top = `${this._selectionStartY / this.zoom}px`;
719
- this._frameCandidate.style.height = `${(localY - this._selectionStartY) / this.zoom}px`;
720
- }
721
- else {
722
- this._frameCandidate.style.top = `${localY / this.zoom}px`;
723
- this._frameCandidate.style.height = `${(this._selectionStartY - localY) / this.zoom}px`;
724
- }
725
- return;
726
- }
727
- // Candidate link
728
- if (this._candidateLink) {
729
- const rootRect = this.canvasContainer.getBoundingClientRect();
730
- this._candidatePort = null;
731
- this.props.stateManager.onCandidateLinkMoved.notifyObservers(new Vector2(evt.pageX, evt.pageY));
732
- this._dropPointX = (evt.pageX - rootRect.left) / this.zoom;
733
- this._dropPointY = (evt.pageY - rootRect.top) / this.zoom;
734
- this._candidateLink.update(this._dropPointX, this._dropPointY, true);
735
- this._candidateLinkedHasMoved = true;
736
- return;
737
- }
738
- // Zoom with mouse + alt
739
- if (this._altKeyIsPressed && evt.buttons === 1) {
740
- if (this._oldY < 0) {
741
- this._oldY = evt.pageY;
742
- }
743
- const zoomDelta = (evt.pageY - this._oldY) / 10;
744
- if (Math.abs(zoomDelta) > 5) {
745
- const oldZoom = this.zoom;
746
- this.zoom = Math.max(Math.min(this._maxZoom, this.zoom + zoomDelta / 100), this._minZoom);
747
- const boundingRect = evt.currentTarget.getBoundingClientRect();
748
- const clientWidth = boundingRect.width;
749
- const widthDiff = clientWidth * this.zoom - clientWidth * oldZoom;
750
- const clientX = evt.clientX - boundingRect.left;
751
- const xFactor = (clientX - this.x) / oldZoom / clientWidth;
752
- this.x = this.x - widthDiff * xFactor;
753
- this._oldY = evt.pageY;
754
- }
755
- return;
756
- }
757
- // Move canvas
758
- this._rootContainer.style.cursor = "move";
759
- if (this._mouseStartPointX === null || this._mouseStartPointY === null) {
760
- return;
761
- }
762
- this.x += evt.clientX - this._mouseStartPointX;
763
- this.y += evt.clientY - this._mouseStartPointY;
764
- this._mouseStartPointX = evt.clientX;
765
- this._mouseStartPointY = evt.clientY;
766
- }
767
- onDown(evt) {
768
- this._rootContainer.setPointerCapture(evt.pointerId);
769
- // Port dragging
770
- if (evt.nativeEvent.srcElement && evt.nativeEvent.srcElement.nodeName === "IMG") {
771
- if (!this._candidateLink) {
772
- const portElement = evt.nativeEvent.srcElement.parentElement.port;
773
- if (this._altKeyIsPressed && (portElement.portData.isConnected || portElement.portData.hasEndpoints)) {
774
- const node = portElement.node;
775
- // Delete connection
776
- const links = node.getLinksForPortData(portElement.portData);
777
- links.forEach((link) => {
778
- link.dispose(false);
779
- });
780
- // Pick the first one as target port
781
- const targetNode = links[0].nodeA === node ? links[0].nodeB : links[0].nodeA;
782
- const targetPort = links[0].nodeA === node ? links[0].portB : links[0].portA;
783
- // Start a new one
784
- this._candidateLink = new NodeLink(this, targetPort, targetNode);
785
- }
786
- else if (this._multiKeyIsPressed && (portElement.portData.isConnected || portElement.portData.hasEndpoints)) {
787
- const node = portElement.node;
788
- const links = node.getLinksForPortData(portElement.portData);
789
- // Pick the first one as target port
790
- const linkToConsider = this._selectedLink || links[0];
791
- const targetNode = linkToConsider.nodeA === node ? linkToConsider.nodeB : linkToConsider.nodeA;
792
- const targetPort = linkToConsider.nodeA === node ? linkToConsider.portB : linkToConsider.portA;
793
- // Start a new one
794
- this._candidateLink = new NodeLink(this, targetPort, targetNode);
795
- }
796
- else {
797
- this._candidateLink = new NodeLink(this, portElement, portElement.node);
798
- }
799
- this._candidateLinkedHasMoved = false;
800
- }
801
- return;
802
- }
803
- // Selection?
804
- if (evt.currentTarget === this._hostCanvas && this._multiKeyIsPressed) {
805
- this._selectionBox = this.props.stateManager.hostDocument.createElement("div");
806
- this._selectionBox.classList.add(styles["selection-box"]);
807
- this._selectionContainer.appendChild(this._selectionBox);
808
- const rootRect = this.canvasContainer.getBoundingClientRect();
809
- this._selectionStartX = evt.pageX - rootRect.left;
810
- this._selectionStartY = evt.pageY - rootRect.top;
811
- this._selectionBox.style.left = `${this._selectionStartX / this.zoom}px`;
812
- this._selectionBox.style.top = `${this._selectionStartY / this.zoom}px`;
813
- this._selectionBox.style.width = "0px";
814
- this._selectionBox.style.height = "0px";
815
- return;
816
- }
817
- // Frame?
818
- if (evt.currentTarget === this._hostCanvas && evt.shiftKey) {
819
- this._frameCandidate = this.props.stateManager.hostDocument.createElement("div");
820
- this._frameCandidate.classList.add(commonStyles["frame-box"]);
821
- this._frameContainer.appendChild(this._frameCandidate);
822
- const rootRect = this.canvasContainer.getBoundingClientRect();
823
- this._selectionStartX = evt.pageX - rootRect.left;
824
- this._selectionStartY = evt.pageY - rootRect.top;
825
- this._frameCandidate.style.left = `${this._selectionStartX / this.zoom}px`;
826
- this._frameCandidate.style.top = `${this._selectionStartY / this.zoom}px`;
827
- this._frameCandidate.style.width = "0px";
828
- this._frameCandidate.style.height = "0px";
829
- return;
830
- }
831
- this.props.stateManager.onSelectionChangedObservable.notifyObservers(null);
832
- this._mouseStartPointX = evt.clientX;
833
- this._mouseStartPointY = evt.clientY;
834
- }
835
- onUp(evt) {
836
- this._mouseStartPointX = null;
837
- this._mouseStartPointY = null;
838
- this._rootContainer.releasePointerCapture(evt.pointerId);
839
- this._oldY = -1;
840
- if (this._candidateLink) {
841
- if (this._candidateLinkedHasMoved) {
842
- this.processCandidatePort();
843
- this.props.stateManager.onCandidateLinkMoved.notifyObservers(null);
844
- }
845
- else {
846
- // is a click event on NodePort
847
- if (this._candidateLink.portA instanceof FrameNodePort) {
848
- //only on Frame Node Ports
849
- const port = this._candidateLink.portA;
850
- const frame = this.frames.find((frame) => frame.id === port.parentFrameId);
851
- if (frame) {
852
- const data = {
853
- frame,
854
- port,
855
- };
856
- this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: data });
857
- }
858
- }
859
- else if (this._candidateLink.portA instanceof NodePort) {
860
- this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: this._candidateLink.portA });
861
- }
862
- }
863
- this._candidateLink.dispose();
864
- this._candidateLink = null;
865
- this._candidatePort = null;
866
- }
867
- if (this._selectionBox) {
868
- this._selectionBox.parentElement.removeChild(this._selectionBox);
869
- this._selectionBox = null;
870
- }
871
- if (this._frameCandidate) {
872
- const newFrame = new GraphFrame(this._frameCandidate, this);
873
- this._frames.push(newFrame);
874
- this._frameCandidate.parentElement.removeChild(this._frameCandidate);
875
- this._frameCandidate = null;
876
- this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: newFrame });
877
- }
878
- }
879
- onWheel(evt) {
880
- const delta = evt.deltaY < 0 ? 0.1 : -0.1;
881
- const oldZoom = this.zoom;
882
- this.zoom = Math.min(Math.max(this._minZoom, this.zoom + delta * this.zoom), this._maxZoom);
883
- const boundingRect = evt.currentTarget.getBoundingClientRect();
884
- const clientWidth = boundingRect.width;
885
- const clientHeight = boundingRect.height;
886
- const widthDiff = clientWidth * this.zoom - clientWidth * oldZoom;
887
- const heightDiff = clientHeight * this.zoom - clientHeight * oldZoom;
888
- const clientX = evt.clientX - boundingRect.left;
889
- const clientY = evt.clientY - boundingRect.top;
890
- const xFactor = (clientX - this.x) / oldZoom / clientWidth;
891
- const yFactor = (clientY - this.y) / oldZoom / clientHeight;
892
- this.x = this.x - widthDiff * xFactor;
893
- this.y = this.y - heightDiff * yFactor;
894
- }
895
- zoomToFit() {
896
- // Get negative offset
897
- let minX = 0;
898
- let minY = 0;
899
- this._nodes.forEach((node) => {
900
- if (this._frames.some((f) => f.nodes.indexOf(node) !== -1)) {
901
- return;
902
- }
903
- if (node.x < minX) {
904
- minX = node.x;
905
- }
906
- if (node.y < minY) {
907
- minY = node.y;
908
- }
909
- });
910
- this._frames.forEach((frame) => {
911
- if (frame.x < minX) {
912
- minX = frame.x;
913
- }
914
- if (frame.y < minY) {
915
- minY = frame.y;
916
- }
917
- });
918
- // Restore to 0
919
- this._frames.forEach((frame) => {
920
- frame.x += -minX;
921
- frame.y += -minY;
922
- frame.cleanAccumulation();
923
- });
924
- this._nodes.forEach((node) => {
925
- node.x += -minX;
926
- node.y += -minY;
927
- node.cleanAccumulation();
928
- });
929
- // Get correct zoom
930
- const xFactor = this._rootContainer.clientWidth / this._rootContainer.scrollWidth;
931
- const yFactor = this._rootContainer.clientHeight / this._rootContainer.scrollHeight;
932
- const zoomFactor = xFactor < yFactor ? xFactor : yFactor;
933
- this.zoom = zoomFactor;
934
- this.x = 0;
935
- this.y = 0;
936
- }
937
- processCandidatePort() {
938
- let pointB = this._candidateLink.portA.portData;
939
- let nodeB = this._candidateLink.portA.node;
940
- let pointA;
941
- let nodeA;
942
- if (this._candidatePort) {
943
- pointA = this._candidatePort.portData;
944
- nodeA = this._candidatePort.node;
945
- }
946
- else {
947
- if (pointB.direction === PortDataDirection.Output) {
948
- return;
949
- }
950
- // No destination so let's spin a new input node
951
- const newDefaultInput = this.props.stateManager.createDefaultInputData(this.props.stateManager.data, this._candidateLink.portA.portData, this);
952
- if (!newDefaultInput) {
953
- return;
954
- }
955
- const pointName = newDefaultInput.name;
956
- const emittedNodeData = newDefaultInput.data;
957
- pointA = emittedNodeData.getPortByName(pointName);
958
- if (!emittedNodeData.isInput) {
959
- nodeA = this.props.onEmitNewNode(emittedNodeData);
960
- }
961
- else {
962
- nodeA = this.appendNode(emittedNodeData);
963
- }
964
- nodeA.x = this._dropPointX - 200;
965
- nodeA.y = this._dropPointY - 50;
966
- const x = nodeA.x - 250;
967
- let y = nodeA.y;
968
- emittedNodeData.inputs.forEach((portData) => {
969
- if (portData.connectedPort) {
970
- const existingNodes = this.nodes.filter((n) => {
971
- var _a;
972
- return n.content.data === ((_a = portData.connectedPort) === null || _a === void 0 ? void 0 : _a.ownerData);
973
- });
974
- const connectedNode = existingNodes[0];
975
- if (connectedNode.x === 0 && connectedNode.y === 0) {
976
- connectedNode.x = x;
977
- connectedNode.y = y;
978
- connectedNode.cleanAccumulation();
979
- y += 80;
980
- }
981
- }
982
- });
983
- }
984
- if (pointA.direction === PortDataDirection.Input) {
985
- const temp = pointB;
986
- pointB = pointA;
987
- pointA = temp;
988
- const tempNode = nodeA;
989
- nodeA = nodeB;
990
- nodeB = tempNode;
991
- }
992
- if (pointB.connectedPort === pointA) {
993
- return;
994
- }
995
- if (pointB === pointA) {
996
- return;
997
- }
998
- if (pointB.direction === pointA.direction) {
999
- return;
1000
- }
1001
- if (pointB.ownerData === pointA.ownerData) {
1002
- return;
1003
- }
1004
- // Check compatibility
1005
- let compatibilityState = pointA.checkCompatibilityState(pointB);
1006
- if ((pointA.needDualDirectionValidation || pointB.needDualDirectionValidation) && !compatibilityState) {
1007
- compatibilityState = pointB.checkCompatibilityState(pointA);
1008
- }
1009
- const message = pointA.getCompatibilityIssueMessage(compatibilityState, nodeB, pointB);
1010
- if (message) {
1011
- this.props.stateManager.onErrorMessageDialogRequiredObservable.notifyObservers(message);
1012
- return;
1013
- }
1014
- let linksToNotifyForDispose = null;
1015
- if (pointB.isConnected) {
1016
- const links = nodeB.getLinksForPortData(pointB);
1017
- linksToNotifyForDispose = links.slice();
1018
- links.forEach((link) => {
1019
- link.dispose(false);
1020
- });
1021
- }
1022
- if (pointB.ownerData.inputsAreExclusive) {
1023
- // Disconnect all inputs if node has exclusive inputs
1024
- pointB.ownerData.inputs.forEach((i) => {
1025
- const links = nodeB.getLinksForPortData(i);
1026
- if (!linksToNotifyForDispose) {
1027
- linksToNotifyForDispose = links.slice();
1028
- }
1029
- else {
1030
- linksToNotifyForDispose.push(...links.slice());
1031
- }
1032
- links.forEach((link) => {
1033
- link.dispose(false);
1034
- });
1035
- });
1036
- }
1037
- this.connectNodes(nodeA, pointA, nodeB, pointB);
1038
- linksToNotifyForDispose === null || linksToNotifyForDispose === void 0 ? void 0 : linksToNotifyForDispose.forEach((link) => {
1039
- link.onDisposedObservable.notifyObservers(link);
1040
- link.onDisposedObservable.clear();
1041
- });
1042
- this.props.stateManager.onRebuildRequiredObservable.notifyObservers(true);
1043
- }
1044
- connectNodes(nodeA, pointA, nodeB, pointB) {
1045
- pointA.connectTo(pointB);
1046
- this.connectPorts(pointA, pointB);
1047
- // Need to potentially propagate the type of pointA to other ports of nodes connected to owner of pointB
1048
- // We also need to check if we want to display the promotion warning
1049
- const visitedNodes = new Set([nodeA]);
1050
- const visitedLinks = new Set([nodeB.links[nodeB.links.length - 1]]);
1051
- RefreshNode(nodeB, visitedNodes, visitedLinks);
1052
- }
1053
- drop(newNode, targetX, targetY, offsetX, offsetY) {
1054
- let x = targetX - this.x - offsetX * this.zoom;
1055
- let y = targetY - this.y - offsetY * this.zoom;
1056
- newNode.x = x / this.zoom;
1057
- newNode.y = y / this.zoom;
1058
- newNode.cleanAccumulation();
1059
- this.props.stateManager.onNewNodeCreatedObservable.notifyObservers(newNode);
1060
- this.props.stateManager.onSelectionChangedObservable.notifyObservers(null);
1061
- this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: newNode });
1062
- x -= GraphCanvasComponent.NodeWidth + 150;
1063
- newNode.content.inputs.forEach((portData) => {
1064
- if (portData.connectedPort) {
1065
- const existingNodes = this.nodes.filter((n) => {
1066
- var _a;
1067
- return n.content.data === ((_a = portData.connectedPort) === null || _a === void 0 ? void 0 : _a.ownerData);
1068
- });
1069
- const connectedNode = existingNodes[0];
1070
- if (connectedNode.x === 0 && connectedNode.y === 0) {
1071
- connectedNode.x = x / this.zoom;
1072
- connectedNode.y = y / this.zoom;
1073
- connectedNode.cleanAccumulation();
1074
- y += 80;
1075
- }
1076
- }
1077
- });
1078
- }
1079
- processEditorData(editorData) {
1080
- const frames = this._frames.splice(0);
1081
- for (const frame of frames) {
1082
- frame.dispose();
1083
- }
1084
- this._frames = [];
1085
- this.x = editorData.x || 0;
1086
- this.y = editorData.y || 0;
1087
- this.zoom = editorData.zoom || 1;
1088
- // Frames
1089
- if (editorData.frames) {
1090
- for (const frameData of editorData.frames) {
1091
- const frame = GraphFrame.Parse(frameData, this, editorData.map);
1092
- this._frames.push(frame);
1093
- }
1094
- }
1095
- }
1096
- reOrganize(editorData = null, isImportingAFrame = false) {
1097
- if (!editorData || !editorData.locations) {
1098
- this.distributeGraph();
1099
- }
1100
- else {
1101
- // Locations
1102
- for (const location of editorData.locations) {
1103
- for (const node of this.nodes) {
1104
- const data = node.content.data;
1105
- if (data && data.uniqueId === location.blockId) {
1106
- node.x = location.x;
1107
- node.y = location.y;
1108
- node.cleanAccumulation();
1109
- break;
1110
- }
1111
- }
1112
- }
1113
- if (!isImportingAFrame) {
1114
- this.processEditorData(editorData);
1115
- }
1116
- }
1117
- this._isLoading = false;
1118
- for (const node of this.nodes) {
1119
- node._refreshLinks();
1120
- }
1121
- }
1122
- addFrame(frameData) {
1123
- const frame = GraphFrame.Parse(frameData, this, this.props.stateManager.getEditorDataMap());
1124
- this._frames.push(frame);
1125
- this.stateManager.onSelectionChangedObservable.notifyObservers({ selection: frame });
1126
- }
1127
- render() {
1128
- return (_jsx("div", { id: "graph-canvas", className: styles["graph-canvas"], onWheel: (evt) => this.onWheel(evt), onPointerMove: (evt) => this.onMove(evt), onPointerDown: (evt) => this.onDown(evt), onPointerUp: (evt) => this.onUp(evt), children: _jsxs("div", { id: "graph-container", className: styles["graph-container"], children: [_jsx("div", { id: "graph-canvas-container", className: styles["graph-canvas-container"] }), _jsx("div", { id: "frame-container", className: styles["frame-container"] }), _jsx("svg", { id: "graph-svg-container", className: styles["graph-svg-container"] }), _jsx("div", { id: "selection-container", className: styles["selection-container"] })] }) }));
1129
- }
1130
- }
1131
- GraphCanvasComponent.NodeWidth = 100;
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { GraphNode } from "./graphNode.js";
4
+ import * as dagre from "dagre";
5
+ import { NodeLink } from "./nodeLink.js";
6
+ import { NodePort } from "./nodePort.js";
7
+ import { Vector2 } from "@babylonjs/core/Maths/math.vector.js";
8
+ import { DataStorage } from "@babylonjs/core/Misc/dataStorage.js";
9
+ import { GraphFrame } from "./graphFrame.js";
10
+ import { FrameNodePort } from "./frameNodePort.js";
11
+ import { PortDataDirection } from "./interfaces/portData.js";
12
+ import styles from "./graphCanvas.modules.scss";
13
+ import commonStyles from "./common.modules.scss";
14
+ import { TypeLedger } from "./typeLedger.js";
15
+ import { RefreshNode } from "./tools.js";
16
+ export class GraphCanvasComponent extends React.Component {
17
+ constructor(props) {
18
+ super(props);
19
+ this._minZoom = 0.1;
20
+ this._maxZoom = 4;
21
+ this._hostCanvasRef = React.createRef();
22
+ this._graphCanvasRef = React.createRef();
23
+ this._selectionContainerRef = React.createRef();
24
+ this._frameContainerRef = React.createRef();
25
+ this._svgCanvasRef = React.createRef();
26
+ this._rootContainerRef = React.createRef();
27
+ this._nodes = [];
28
+ this._links = [];
29
+ this._mouseStartPointX = null;
30
+ this._mouseStartPointY = null;
31
+ this._dropPointX = 0;
32
+ this._dropPointY = 0;
33
+ this._selectionStartX = 0;
34
+ this._selectionStartY = 0;
35
+ this._candidateLinkedHasMoved = false;
36
+ this._x = 0;
37
+ this._y = 0;
38
+ this._zoom = 1;
39
+ this._selectedNodes = [];
40
+ this._selectedLink = null;
41
+ this._selectedPort = null;
42
+ this._candidateLink = null;
43
+ this._candidatePort = null;
44
+ this._gridSize = 20;
45
+ this._selectionBox = null;
46
+ this._selectedFrames = [];
47
+ this._frameCandidate = null;
48
+ this._frames = [];
49
+ this._nodeDataContentList = new Array();
50
+ this._altKeyIsPressed = false;
51
+ this._multiKeyIsPressed = false;
52
+ this._oldY = -1;
53
+ this._frameIsMoving = false;
54
+ this._isLoading = false;
55
+ this._targetLinkCandidate = null;
56
+ this._copiedNodes = [];
57
+ this._copiedFrames = [];
58
+ props.stateManager.onSelectionChangedObservable.add((options) => {
59
+ const { selection, forceKeepSelection, marqueeSelection = false } = options || {};
60
+ if (!selection) {
61
+ this._selectedNodes = [];
62
+ this._selectedLink = null;
63
+ this._selectedFrames = [];
64
+ this._selectedPort = null;
65
+ }
66
+ else {
67
+ if (selection instanceof NodeLink) {
68
+ this._selectedNodes = [];
69
+ this._selectedFrames = [];
70
+ this._selectedLink = selection;
71
+ this._selectedPort = null;
72
+ }
73
+ else if (selection instanceof NodePort) {
74
+ this._selectedNodes = [];
75
+ this._selectedFrames = [];
76
+ this._selectedLink = null;
77
+ this._selectedPort = selection;
78
+ }
79
+ else if (selection instanceof FrameNodePort) {
80
+ this._selectedNodes = [];
81
+ this._selectedFrames = [];
82
+ this._selectedLink = null;
83
+ this._selectedPort = selection;
84
+ }
85
+ else if (selection instanceof GraphNode || selection instanceof GraphFrame) {
86
+ // If in marquee selection mode, always prioritize selecting nodes. Otherwise, always prioritize selecting the type of
87
+ // the selected element
88
+ if (marqueeSelection) {
89
+ if (selection instanceof GraphFrame && !this._selectedFrames.includes(selection)) {
90
+ this._selectedFrames.push(selection);
91
+ }
92
+ else if (selection instanceof GraphNode && !this._selectedNodes.includes(selection)) {
93
+ this._selectedNodes.push(selection);
94
+ }
95
+ if (this._selectedFrameAndNodesConflict(this.selectedFrames, this.selectedNodes)) {
96
+ const framesToRemove = new Set();
97
+ for (const selectedNode of this._selectedNodes) {
98
+ for (const selectedFrame of this._selectedFrames) {
99
+ if (selectedFrame.nodes.includes(selectedNode)) {
100
+ framesToRemove.add(selectedFrame);
101
+ }
102
+ }
103
+ }
104
+ this._selectedFrames = this._selectedFrames.filter((f) => !framesToRemove.has(f));
105
+ }
106
+ }
107
+ else {
108
+ if (selection instanceof GraphFrame) {
109
+ if (this._multiKeyIsPressed || forceKeepSelection) {
110
+ if (!this._selectedFrameAndNodesConflict([selection], this._selectedNodes) && !this._selectedFrames.includes(selection)) {
111
+ this._selectedFrames.push(selection);
112
+ }
113
+ }
114
+ else {
115
+ this._selectedFrames = [selection];
116
+ this._selectedNodes = [];
117
+ this._selectedLink = null;
118
+ this._selectedPort = null;
119
+ }
120
+ }
121
+ else if (selection instanceof GraphNode) {
122
+ if (this._multiKeyIsPressed || forceKeepSelection) {
123
+ if (!this._selectedFrameAndNodesConflict(this._selectedFrames, [selection]) && !this._selectedNodes.includes(selection)) {
124
+ this._selectedNodes.push(selection);
125
+ }
126
+ }
127
+ else {
128
+ this._selectedFrames = [];
129
+ this._selectedNodes = [selection];
130
+ this._selectedLink = null;
131
+ this._selectedPort = null;
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+ });
138
+ props.stateManager.onCandidatePortSelectedObservable.add((port) => {
139
+ this._candidatePort = port;
140
+ });
141
+ props.stateManager.onGridSizeChanged.add(() => {
142
+ this.gridSize = DataStorage.ReadNumber("GridSize", 20);
143
+ });
144
+ this.props.stateManager.hostDocument.addEventListener("keyup", () => this.onKeyUp(), false);
145
+ this.props.stateManager.hostDocument.addEventListener("keydown", (evt) => {
146
+ this._altKeyIsPressed = evt.altKey;
147
+ this._multiKeyIsPressed = evt.ctrlKey || evt.metaKey;
148
+ }, false);
149
+ this.props.stateManager.hostDocument.defaultView.addEventListener("blur", () => {
150
+ this._altKeyIsPressed = false;
151
+ this._multiKeyIsPressed = false;
152
+ }, false);
153
+ // Store additional data to serialization object
154
+ this.props.stateManager.storeEditorData = (editorData, graphFrame) => {
155
+ editorData.frames = [];
156
+ if (graphFrame) {
157
+ editorData.frames.push(graphFrame.serialize(false));
158
+ }
159
+ else {
160
+ editorData.x = this.x;
161
+ editorData.y = this.y;
162
+ editorData.zoom = this.zoom;
163
+ for (const frame of this._frames) {
164
+ editorData.frames.push(frame.serialize(true));
165
+ }
166
+ }
167
+ };
168
+ }
169
+ get gridSize() {
170
+ return this._gridSize;
171
+ }
172
+ set gridSize(value) {
173
+ this._gridSize = value;
174
+ this.updateTransform();
175
+ }
176
+ get stateManager() {
177
+ return this.props.stateManager;
178
+ }
179
+ get nodes() {
180
+ return this._nodes;
181
+ }
182
+ get links() {
183
+ return this._links;
184
+ }
185
+ get frames() {
186
+ return this._frames;
187
+ }
188
+ get zoom() {
189
+ return this._zoom;
190
+ }
191
+ set zoom(value) {
192
+ if (this._zoom === value) {
193
+ return;
194
+ }
195
+ this._zoom = value;
196
+ this.updateTransform();
197
+ }
198
+ get x() {
199
+ return this._x;
200
+ }
201
+ set x(value) {
202
+ this._x = value;
203
+ this.updateTransform();
204
+ }
205
+ get y() {
206
+ return this._y;
207
+ }
208
+ set y(value) {
209
+ this._y = value;
210
+ this.updateTransform();
211
+ }
212
+ get selectedNodes() {
213
+ return this._selectedNodes;
214
+ }
215
+ get selectedLink() {
216
+ return this._selectedLink;
217
+ }
218
+ get selectedFrames() {
219
+ return this._selectedFrames;
220
+ }
221
+ get selectedPort() {
222
+ return this._selectedPort;
223
+ }
224
+ get canvasContainer() {
225
+ return this._graphCanvas;
226
+ }
227
+ get hostCanvas() {
228
+ return this._hostCanvas;
229
+ }
230
+ get svgCanvas() {
231
+ return this._svgCanvas;
232
+ }
233
+ get selectionContainer() {
234
+ return this._selectionContainer;
235
+ }
236
+ get frameContainer() {
237
+ return this._frameContainer;
238
+ }
239
+ // There is a selection conflict between nodes and frames if any selected node is inside any selected frame
240
+ _selectedFrameAndNodesConflict(frameSelection, nodeSelection) {
241
+ for (const frame of frameSelection) {
242
+ for (const node of nodeSelection) {
243
+ if (frame.nodes.includes(node)) {
244
+ return true;
245
+ }
246
+ }
247
+ }
248
+ return false;
249
+ }
250
+ populateConnectedEntriesBeforeRemoval(item, items, inputs, outputs) {
251
+ inputs.push(...item.content.inputs.filter((i) => i.isConnected && items.every((selected) => { var _a; return selected.content.data !== ((_a = i.connectedPort) === null || _a === void 0 ? void 0 : _a.ownerData); })).map((i) => i.connectedPort));
252
+ outputs.push(...item.content.outputs
253
+ .filter((i) => i.isConnected)
254
+ .map((i) => i.endpoints)
255
+ .flat()
256
+ .filter((i) => i && items.every((selected) => selected.content.data !== i.ownerData)));
257
+ }
258
+ automaticRewire(inputs, outputs, firstOnly = false) {
259
+ let oneConnectionFound = false;
260
+ if (outputs.length && inputs.length) {
261
+ inputs.forEach((input) => {
262
+ if (oneConnectionFound) {
263
+ return;
264
+ }
265
+ if (!input) {
266
+ return;
267
+ }
268
+ const output = outputs[0];
269
+ if (output && input.canConnectTo(output)) {
270
+ const nodeInput = this.findNodeFromData(input.ownerData);
271
+ const nodeOutput = this.findNodeFromData(output.ownerData);
272
+ this.connectNodes(nodeInput, input, nodeOutput, output);
273
+ outputs.shift();
274
+ if (firstOnly) {
275
+ oneConnectionFound = true;
276
+ return;
277
+ }
278
+ }
279
+ });
280
+ }
281
+ }
282
+ handleKeyDown(evt, onRemove, mouseLocationX, mouseLocationY, dataGenerator, rootElement) {
283
+ if ((evt.keyCode === 46 || evt.keyCode === 8) && !this.props.stateManager.lockObject.lock) {
284
+ // Delete
285
+ const selectedItems = this.selectedNodes;
286
+ const inputs = [];
287
+ const outputs = [];
288
+ if (selectedItems.length > 0) {
289
+ for (const selectedItem of selectedItems) {
290
+ if (evt.altKey) {
291
+ this.populateConnectedEntriesBeforeRemoval(selectedItem, selectedItems, inputs, outputs);
292
+ }
293
+ selectedItem.dispose();
294
+ onRemove(selectedItem.content);
295
+ this.removeDataFromCache(selectedItem.content.data);
296
+ }
297
+ }
298
+ if (this.selectedLink) {
299
+ this.selectedLink.dispose();
300
+ }
301
+ if (this.selectedFrames.length) {
302
+ for (const frame of this.selectedFrames) {
303
+ if (frame.isCollapsed) {
304
+ while (frame.nodes.length > 0) {
305
+ onRemove(frame.nodes[0].content);
306
+ this.removeDataFromCache(frame.nodes[0].content.data);
307
+ frame.nodes[0].dispose();
308
+ }
309
+ frame.isCollapsed = false;
310
+ }
311
+ else {
312
+ frame.nodes.forEach((node) => {
313
+ node.enclosingFrameId = -1;
314
+ });
315
+ }
316
+ frame.dispose();
317
+ }
318
+ }
319
+ // Reconnect if required
320
+ this.automaticRewire(inputs, outputs);
321
+ this.props.stateManager.onSelectionChangedObservable.notifyObservers(null);
322
+ this.props.stateManager.onRebuildRequiredObservable.notifyObservers(false);
323
+ return;
324
+ }
325
+ if ((!evt.ctrlKey && !evt.metaKey) || this.props.stateManager.lockObject.lock) {
326
+ return;
327
+ }
328
+ if (evt.key === "c" || evt.key === "C") {
329
+ // Copy
330
+ this._copiedNodes = [];
331
+ this._copiedFrames = [];
332
+ if (this.selectedFrames.length) {
333
+ for (const frame of this.selectedFrames) {
334
+ frame.serialize(true);
335
+ this._copiedFrames.push(frame);
336
+ }
337
+ return;
338
+ }
339
+ const selectedItems = this.selectedNodes;
340
+ if (!selectedItems.length) {
341
+ return;
342
+ }
343
+ const selectedItem = selectedItems[0];
344
+ if (!selectedItem.content.data) {
345
+ return;
346
+ }
347
+ this._copiedNodes = selectedItems.slice(0);
348
+ }
349
+ else if (evt.key === "v" || evt.key === "V") {
350
+ // Paste
351
+ const zoomLevel = this.zoom;
352
+ let currentY = (mouseLocationY - rootElement.offsetTop - this.y - 20) / zoomLevel;
353
+ if (this._copiedFrames.length) {
354
+ for (const frame of this._copiedFrames) {
355
+ // New frame
356
+ const newFrame = new GraphFrame(null, this, true);
357
+ this.frames.push(newFrame);
358
+ newFrame.width = frame.width;
359
+ newFrame.height = frame.height;
360
+ newFrame.width / 2;
361
+ newFrame.name = frame.name;
362
+ newFrame.color = frame.color;
363
+ let currentX = (mouseLocationX - rootElement.offsetLeft - this.x) / zoomLevel;
364
+ newFrame.x = currentX - newFrame.width / 2;
365
+ newFrame.y = currentY;
366
+ // Paste nodes
367
+ if (frame.nodes.length) {
368
+ currentX = newFrame.x + frame.nodes[0].x - frame.x;
369
+ currentY = newFrame.y + frame.nodes[0].y - frame.y;
370
+ this._frameIsMoving = true;
371
+ const newNodes = this.pasteSelection(frame.nodes, currentX, currentY, dataGenerator);
372
+ if (newNodes) {
373
+ for (const node of newNodes) {
374
+ newFrame.syncNode(node);
375
+ }
376
+ }
377
+ this._frameIsMoving = false;
378
+ }
379
+ newFrame.adjustPorts();
380
+ if (frame.isCollapsed) {
381
+ newFrame.isCollapsed = true;
382
+ }
383
+ // Select
384
+ this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: newFrame, forceKeepSelection: true });
385
+ return;
386
+ }
387
+ }
388
+ if (!this._copiedNodes.length) {
389
+ return;
390
+ }
391
+ const currentX = (mouseLocationX - rootElement.offsetLeft - this.x - GraphCanvasComponent.NodeWidth) / zoomLevel;
392
+ this.pasteSelection(this._copiedNodes, currentX, currentY, dataGenerator, true);
393
+ }
394
+ }
395
+ pasteSelection(copiedNodes, currentX, currentY, dataGenerator, selectNew = false) {
396
+ let originalNode = null;
397
+ const newNodes = [];
398
+ // Copy to prevent recursive side effects while creating nodes.
399
+ copiedNodes = copiedNodes.slice();
400
+ // Cancel selection
401
+ this.props.stateManager.onSelectionChangedObservable.notifyObservers(null);
402
+ // Create new nodes
403
+ for (const node of copiedNodes) {
404
+ const data = node.content.data;
405
+ if (!data) {
406
+ continue;
407
+ }
408
+ const newNode = dataGenerator(node.content);
409
+ let x = 0;
410
+ let y = 0;
411
+ if (originalNode) {
412
+ x = currentX + node.x - originalNode.x;
413
+ y = currentY + node.y - originalNode.y;
414
+ }
415
+ else {
416
+ originalNode = node;
417
+ x = currentX;
418
+ y = currentY;
419
+ }
420
+ newNode.x = x;
421
+ newNode.y = y;
422
+ newNode.cleanAccumulation();
423
+ newNodes.push(newNode);
424
+ if (selectNew) {
425
+ this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: newNode, forceKeepSelection: true });
426
+ }
427
+ }
428
+ // Relink
429
+ const done = new Array(newNodes.length);
430
+ for (let index = 0; index < newNodes.length; index++) {
431
+ this.reconnectNewNodes(index, newNodes, copiedNodes, done);
432
+ }
433
+ return newNodes;
434
+ }
435
+ reconnectNewNodes(nodeIndex, newNodes, sourceNodes, done) {
436
+ if (done[nodeIndex]) {
437
+ return;
438
+ }
439
+ const currentNode = newNodes[nodeIndex];
440
+ const sourceNode = sourceNodes[nodeIndex];
441
+ for (let inputIndex = 0; inputIndex < sourceNode.content.inputs.length; inputIndex++) {
442
+ const sourceInput = sourceNode.content.inputs[inputIndex];
443
+ const currentInput = currentNode.content.inputs[inputIndex];
444
+ if (!sourceInput.isConnected) {
445
+ continue;
446
+ }
447
+ const sourceContent = this.findNodeFromData(sourceInput.connectedPort.ownerData).content;
448
+ const activeNodes = sourceNodes.filter((s) => s.content === sourceContent);
449
+ if (activeNodes.length > 0) {
450
+ const activeNode = activeNodes[0];
451
+ const indexInList = sourceNodes.indexOf(activeNode);
452
+ // First make sure to connect the other one
453
+ this.reconnectNewNodes(indexInList, newNodes, sourceNodes, done);
454
+ // Then reconnect
455
+ const outputIndex = sourceContent.outputs.indexOf(sourceInput.connectedPort);
456
+ const newOutput = newNodes[indexInList].content.data.outputs[outputIndex];
457
+ newOutput.connectTo(currentInput.data);
458
+ }
459
+ else {
460
+ // Connect with outside nodes
461
+ sourceInput.connectedPort.connectTo(currentInput);
462
+ }
463
+ this.connectPorts(currentInput.connectedPort, currentInput);
464
+ }
465
+ currentNode.refresh();
466
+ done[nodeIndex] = true;
467
+ }
468
+ getCachedData() {
469
+ return this._nodeDataContentList;
470
+ }
471
+ removeDataFromCache(data) {
472
+ const dataIndex = this._nodeDataContentList.indexOf(data);
473
+ if (dataIndex > -1) {
474
+ this._nodeDataContentList.splice(dataIndex, 1);
475
+ }
476
+ }
477
+ createNodeFromObject(nodeData, onNodeCreated, recursion = true) {
478
+ if (this._nodeDataContentList.indexOf(nodeData.data) !== -1) {
479
+ // Links
480
+ if (nodeData.inputs.length && recursion) {
481
+ for (const input of nodeData.inputs) {
482
+ if (input.isConnected) {
483
+ this.connectPorts(input.connectedPort, input);
484
+ }
485
+ }
486
+ }
487
+ return this.nodes.filter((n) => n.content.data === nodeData.data)[0];
488
+ }
489
+ onNodeCreated(nodeData.data);
490
+ // Connections
491
+ if (nodeData.inputs.length) {
492
+ for (const input of nodeData.inputs) {
493
+ if (input.connectedPort && recursion) {
494
+ this.createNodeFromObject(TypeLedger.NodeDataBuilder(input.connectedPort.ownerData, this), onNodeCreated);
495
+ }
496
+ }
497
+ }
498
+ // Graph
499
+ const node = this.appendNode(nodeData);
500
+ // Links
501
+ if (nodeData.inputs.length && recursion) {
502
+ for (const input of nodeData.inputs) {
503
+ if (input.isConnected) {
504
+ this.connectPorts(input.connectedPort, input);
505
+ }
506
+ }
507
+ }
508
+ return node;
509
+ }
510
+ getGridPosition(position, useCeil = false) {
511
+ const gridSize = this.gridSize;
512
+ if (gridSize === 0) {
513
+ return position;
514
+ }
515
+ if (useCeil) {
516
+ return gridSize * Math.ceil(position / gridSize);
517
+ }
518
+ return gridSize * Math.floor(position / gridSize);
519
+ }
520
+ getGridPositionCeil(position) {
521
+ const gridSize = this.gridSize;
522
+ if (gridSize === 0) {
523
+ return position;
524
+ }
525
+ return gridSize * Math.ceil(position / gridSize);
526
+ }
527
+ updateTransform() {
528
+ this._rootContainer.style.transform = `translate(${this._x}px, ${this._y}px) scale(${this._zoom})`;
529
+ if (DataStorage.ReadBoolean("ShowGrid", true)) {
530
+ this._hostCanvas.style.backgroundSize = `${this._gridSize * this._zoom}px ${this._gridSize * this._zoom}px`;
531
+ this._hostCanvas.style.backgroundPosition = `${this._x}px ${this._y}px`;
532
+ }
533
+ else {
534
+ this._hostCanvas.style.backgroundSize = `0`;
535
+ }
536
+ }
537
+ onKeyUp() {
538
+ this._altKeyIsPressed = false;
539
+ this._multiKeyIsPressed = false;
540
+ this._oldY = -1;
541
+ }
542
+ findNodeFromData(data) {
543
+ return this.nodes.filter((n) => n.content.data === data)[0];
544
+ }
545
+ reset() {
546
+ this._nodeDataContentList = [];
547
+ for (const node of this._nodes) {
548
+ node.dispose();
549
+ }
550
+ const frames = this._frames.splice(0);
551
+ for (const frame of frames) {
552
+ frame.dispose();
553
+ }
554
+ this._nodes = [];
555
+ this._frames = [];
556
+ this._links = [];
557
+ this._graphCanvas.innerHTML = "";
558
+ this._svgCanvas.innerHTML = "";
559
+ }
560
+ connectPorts(pointA, pointB) {
561
+ if (!pointA || !pointB) {
562
+ return;
563
+ }
564
+ const ownerDataA = pointA.ownerData;
565
+ const ownerDataB = pointB.ownerData;
566
+ const nodeA = this.findNodeFromData(ownerDataA);
567
+ const nodeB = this.findNodeFromData(ownerDataB);
568
+ if (!nodeA || !nodeB) {
569
+ return;
570
+ }
571
+ const portA = nodeA.getPortForPortData(pointA);
572
+ const portB = nodeB.getPortForPortData(pointB);
573
+ if (!portA || !portB) {
574
+ return;
575
+ }
576
+ for (const currentLink of this._links) {
577
+ if (currentLink.portA === portA && currentLink.portB === portB) {
578
+ return;
579
+ }
580
+ if (currentLink.portA === portB && currentLink.portB === portA) {
581
+ return;
582
+ }
583
+ }
584
+ const link = new NodeLink(this, portA, nodeA, portB, nodeB);
585
+ this._links.push(link);
586
+ nodeA.links.push(link);
587
+ nodeB.links.push(link);
588
+ }
589
+ removeLink(link) {
590
+ const index = this._links.indexOf(link);
591
+ if (index > -1) {
592
+ this._links.splice(index, 1);
593
+ }
594
+ link.dispose();
595
+ }
596
+ appendNode(nodeData) {
597
+ const newNode = new GraphNode(nodeData, this.props.stateManager);
598
+ newNode.appendVisual(this._graphCanvas, this);
599
+ this._nodes.push(newNode);
600
+ this._nodeDataContentList.push(nodeData.data);
601
+ return newNode;
602
+ }
603
+ distributeGraph() {
604
+ this.x = 0;
605
+ this.y = 0;
606
+ this.zoom = 1;
607
+ const graph = new dagre.graphlib.Graph();
608
+ graph.setGraph({});
609
+ graph.setDefaultEdgeLabel(() => ({}));
610
+ graph.graph().rankdir = "LR";
611
+ // Build dagre graph
612
+ this._nodes.forEach((node) => {
613
+ if (this._frames.some((f) => f.nodes.indexOf(node) !== -1)) {
614
+ return;
615
+ }
616
+ graph.setNode(node.id.toString(), {
617
+ id: node.id,
618
+ type: "node",
619
+ width: node.width,
620
+ height: node.height,
621
+ });
622
+ });
623
+ this._frames.forEach((frame) => {
624
+ graph.setNode(frame.id.toString(), {
625
+ id: frame.id,
626
+ type: "frame",
627
+ width: frame.element.clientWidth,
628
+ height: frame.element.clientHeight,
629
+ });
630
+ });
631
+ this._nodes.forEach((node) => {
632
+ node.content.outputs.forEach((output) => {
633
+ if (!output.hasEndpoints) {
634
+ return;
635
+ }
636
+ output.endpoints.forEach((endpoint) => {
637
+ const sourceFrames = this._frames.filter((f) => f.nodes.indexOf(node) !== -1);
638
+ const targetFrames = this._frames.filter((f) => f.nodes.some((n) => n.content.data === endpoint.ownerData));
639
+ const sourceId = sourceFrames.length > 0 ? sourceFrames[0].id : node.id;
640
+ const targetId = targetFrames.length > 0 ? targetFrames[0].id : endpoint.ownerData.uniqueId;
641
+ graph.setEdge(sourceId.toString(), targetId.toString());
642
+ });
643
+ });
644
+ });
645
+ // Distribute
646
+ dagre.layout(graph);
647
+ // Update graph
648
+ const dagreNodes = graph.nodes().map((node) => graph.node(node));
649
+ dagreNodes.forEach((dagreNode) => {
650
+ if (!dagreNode) {
651
+ return;
652
+ }
653
+ if (dagreNode.type === "node") {
654
+ for (const node of this._nodes) {
655
+ if (node.id === dagreNode.id) {
656
+ node.x = dagreNode.x - dagreNode.width / 2;
657
+ node.y = dagreNode.y - dagreNode.height / 2;
658
+ node.cleanAccumulation();
659
+ return;
660
+ }
661
+ }
662
+ return;
663
+ }
664
+ for (const frame of this._frames) {
665
+ if (frame.id === dagreNode.id) {
666
+ this._frameIsMoving = true;
667
+ frame.move(dagreNode.x - dagreNode.width / 2, dagreNode.y - dagreNode.height / 2, false);
668
+ frame.cleanAccumulation();
669
+ this._frameIsMoving = false;
670
+ return;
671
+ }
672
+ }
673
+ });
674
+ }
675
+ componentDidMount() {
676
+ this._hostCanvas = this._hostCanvasRef.current;
677
+ this._rootContainer = this._rootContainerRef.current;
678
+ this._graphCanvas = this._graphCanvasRef.current;
679
+ this._svgCanvas = this._svgCanvasRef.current;
680
+ this._selectionContainer = this._selectionContainerRef.current;
681
+ this._frameContainer = this._frameContainerRef.current;
682
+ this.gridSize = DataStorage.ReadNumber("GridSize", 20);
683
+ this.updateTransform();
684
+ }
685
+ onMove(evt) {
686
+ // Selection box
687
+ if (this._selectionBox) {
688
+ const rootRect = this.canvasContainer.getBoundingClientRect();
689
+ const localX = evt.pageX - rootRect.left;
690
+ const localY = evt.pageY - rootRect.top;
691
+ if (localX > this._selectionStartX) {
692
+ this._selectionBox.style.left = `${this._selectionStartX / this.zoom}px`;
693
+ this._selectionBox.style.width = `${(localX - this._selectionStartX) / this.zoom}px`;
694
+ }
695
+ else {
696
+ this._selectionBox.style.left = `${localX / this.zoom}px`;
697
+ this._selectionBox.style.width = `${(this._selectionStartX - localX) / this.zoom}px`;
698
+ }
699
+ if (localY > this._selectionStartY) {
700
+ this._selectionBox.style.top = `${this._selectionStartY / this.zoom}px`;
701
+ this._selectionBox.style.height = `${(localY - this._selectionStartY) / this.zoom}px`;
702
+ }
703
+ else {
704
+ this._selectionBox.style.top = `${localY / this.zoom}px`;
705
+ this._selectionBox.style.height = `${(this._selectionStartY - localY) / this.zoom}px`;
706
+ }
707
+ this.props.stateManager.onSelectionBoxMoved.notifyObservers(this._selectionBox.getBoundingClientRect());
708
+ return;
709
+ }
710
+ // Candidate frame box
711
+ if (this._frameCandidate) {
712
+ const rootRect = this.canvasContainer.getBoundingClientRect();
713
+ const localX = evt.pageX - rootRect.left;
714
+ const localY = evt.pageY - rootRect.top;
715
+ if (localX > this._selectionStartX) {
716
+ this._frameCandidate.style.left = `${this._selectionStartX / this.zoom}px`;
717
+ this._frameCandidate.style.width = `${(localX - this._selectionStartX) / this.zoom}px`;
718
+ }
719
+ else {
720
+ this._frameCandidate.style.left = `${localX / this.zoom}px`;
721
+ this._frameCandidate.style.width = `${(this._selectionStartX - localX) / this.zoom}px`;
722
+ }
723
+ if (localY > this._selectionStartY) {
724
+ this._frameCandidate.style.top = `${this._selectionStartY / this.zoom}px`;
725
+ this._frameCandidate.style.height = `${(localY - this._selectionStartY) / this.zoom}px`;
726
+ }
727
+ else {
728
+ this._frameCandidate.style.top = `${localY / this.zoom}px`;
729
+ this._frameCandidate.style.height = `${(this._selectionStartY - localY) / this.zoom}px`;
730
+ }
731
+ return;
732
+ }
733
+ // Candidate link
734
+ if (this._candidateLink) {
735
+ const rootRect = this.canvasContainer.getBoundingClientRect();
736
+ this._candidatePort = null;
737
+ this.props.stateManager.onCandidateLinkMoved.notifyObservers(new Vector2(evt.pageX, evt.pageY));
738
+ this._dropPointX = (evt.pageX - rootRect.left) / this.zoom;
739
+ this._dropPointY = (evt.pageY - rootRect.top) / this.zoom;
740
+ this._candidateLink.update(this._dropPointX, this._dropPointY, true);
741
+ this._candidateLinkedHasMoved = true;
742
+ return;
743
+ }
744
+ // Zoom with mouse + alt
745
+ if (this._altKeyIsPressed && evt.buttons === 1) {
746
+ if (this._oldY < 0) {
747
+ this._oldY = evt.pageY;
748
+ }
749
+ const zoomDelta = (evt.pageY - this._oldY) / 10;
750
+ if (Math.abs(zoomDelta) > 5) {
751
+ const oldZoom = this.zoom;
752
+ this.zoom = Math.max(Math.min(this._maxZoom, this.zoom + zoomDelta / 100), this._minZoom);
753
+ const boundingRect = evt.currentTarget.getBoundingClientRect();
754
+ const clientWidth = boundingRect.width;
755
+ const widthDiff = clientWidth * this.zoom - clientWidth * oldZoom;
756
+ const clientX = evt.clientX - boundingRect.left;
757
+ const xFactor = (clientX - this.x) / oldZoom / clientWidth;
758
+ this.x = this.x - widthDiff * xFactor;
759
+ this._oldY = evt.pageY;
760
+ }
761
+ return;
762
+ }
763
+ // Move canvas
764
+ this._rootContainer.style.cursor = "move";
765
+ if (this._mouseStartPointX === null || this._mouseStartPointY === null) {
766
+ return;
767
+ }
768
+ this.x += evt.clientX - this._mouseStartPointX;
769
+ this.y += evt.clientY - this._mouseStartPointY;
770
+ this._mouseStartPointX = evt.clientX;
771
+ this._mouseStartPointY = evt.clientY;
772
+ }
773
+ onDown(evt) {
774
+ this._rootContainer.setPointerCapture(evt.pointerId);
775
+ // Port dragging
776
+ if (evt.nativeEvent.srcElement && evt.nativeEvent.srcElement.nodeName === "IMG") {
777
+ if (!this._candidateLink) {
778
+ const portElement = evt.nativeEvent.srcElement.parentElement.port;
779
+ if (this._altKeyIsPressed && (portElement.portData.isConnected || portElement.portData.hasEndpoints)) {
780
+ const node = portElement.node;
781
+ // Delete connection
782
+ const links = node.getLinksForPortData(portElement.portData);
783
+ links.forEach((link) => {
784
+ link.dispose(false);
785
+ });
786
+ // Pick the first one as target port
787
+ const targetNode = links[0].nodeA === node ? links[0].nodeB : links[0].nodeA;
788
+ const targetPort = links[0].nodeA === node ? links[0].portB : links[0].portA;
789
+ // Start a new one
790
+ this._candidateLink = new NodeLink(this, targetPort, targetNode);
791
+ }
792
+ else if (this._multiKeyIsPressed && (portElement.portData.isConnected || portElement.portData.hasEndpoints)) {
793
+ const node = portElement.node;
794
+ const links = node.getLinksForPortData(portElement.portData);
795
+ // Pick the first one as target port
796
+ const linkToConsider = this._selectedLink || links[0];
797
+ const targetNode = linkToConsider.nodeA === node ? linkToConsider.nodeB : linkToConsider.nodeA;
798
+ const targetPort = linkToConsider.nodeA === node ? linkToConsider.portB : linkToConsider.portA;
799
+ // Start a new one
800
+ this._candidateLink = new NodeLink(this, targetPort, targetNode);
801
+ }
802
+ else {
803
+ this._candidateLink = new NodeLink(this, portElement, portElement.node);
804
+ }
805
+ this._candidateLinkedHasMoved = false;
806
+ }
807
+ return;
808
+ }
809
+ // Selection?
810
+ if (evt.currentTarget === this._hostCanvas && this._multiKeyIsPressed) {
811
+ this._selectionBox = this.props.stateManager.hostDocument.createElement("div");
812
+ this._selectionBox.classList.add(styles["selection-box"]);
813
+ this._selectionContainer.appendChild(this._selectionBox);
814
+ const rootRect = this.canvasContainer.getBoundingClientRect();
815
+ this._selectionStartX = evt.pageX - rootRect.left;
816
+ this._selectionStartY = evt.pageY - rootRect.top;
817
+ this._selectionBox.style.left = `${this._selectionStartX / this.zoom}px`;
818
+ this._selectionBox.style.top = `${this._selectionStartY / this.zoom}px`;
819
+ this._selectionBox.style.width = "0px";
820
+ this._selectionBox.style.height = "0px";
821
+ return;
822
+ }
823
+ // Frame?
824
+ if (evt.currentTarget === this._hostCanvas && evt.shiftKey) {
825
+ this._frameCandidate = this.props.stateManager.hostDocument.createElement("div");
826
+ this._frameCandidate.classList.add(commonStyles["frame-box"]);
827
+ this._frameContainer.appendChild(this._frameCandidate);
828
+ const rootRect = this.canvasContainer.getBoundingClientRect();
829
+ this._selectionStartX = evt.pageX - rootRect.left;
830
+ this._selectionStartY = evt.pageY - rootRect.top;
831
+ this._frameCandidate.style.left = `${this._selectionStartX / this.zoom}px`;
832
+ this._frameCandidate.style.top = `${this._selectionStartY / this.zoom}px`;
833
+ this._frameCandidate.style.width = "0px";
834
+ this._frameCandidate.style.height = "0px";
835
+ return;
836
+ }
837
+ this.props.stateManager.onSelectionChangedObservable.notifyObservers(null);
838
+ this._mouseStartPointX = evt.clientX;
839
+ this._mouseStartPointY = evt.clientY;
840
+ }
841
+ onUp(evt) {
842
+ this._mouseStartPointX = null;
843
+ this._mouseStartPointY = null;
844
+ this._rootContainer.releasePointerCapture(evt.pointerId);
845
+ this._oldY = -1;
846
+ if (this._candidateLink) {
847
+ if (this._candidateLinkedHasMoved) {
848
+ this.processCandidatePort();
849
+ this.props.stateManager.onCandidateLinkMoved.notifyObservers(null);
850
+ }
851
+ else {
852
+ // is a click event on NodePort
853
+ if (this._candidateLink.portA instanceof FrameNodePort) {
854
+ //only on Frame Node Ports
855
+ const port = this._candidateLink.portA;
856
+ const frame = this.frames.find((frame) => frame.id === port.parentFrameId);
857
+ if (frame) {
858
+ const data = {
859
+ frame,
860
+ port,
861
+ };
862
+ this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: data });
863
+ }
864
+ }
865
+ else if (this._candidateLink.portA instanceof NodePort) {
866
+ this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: this._candidateLink.portA });
867
+ }
868
+ }
869
+ this._candidateLink.dispose();
870
+ this._candidateLink = null;
871
+ this._candidatePort = null;
872
+ }
873
+ if (this._selectionBox) {
874
+ this._selectionBox.parentElement.removeChild(this._selectionBox);
875
+ this._selectionBox = null;
876
+ }
877
+ if (this._frameCandidate) {
878
+ const newFrame = new GraphFrame(this._frameCandidate, this);
879
+ this._frames.push(newFrame);
880
+ this._frameCandidate.parentElement.removeChild(this._frameCandidate);
881
+ this._frameCandidate = null;
882
+ this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: newFrame });
883
+ }
884
+ }
885
+ onWheel(evt) {
886
+ const delta = evt.deltaY < 0 ? 0.1 : -0.1;
887
+ const oldZoom = this.zoom;
888
+ this.zoom = Math.min(Math.max(this._minZoom, this.zoom + delta * this.zoom), this._maxZoom);
889
+ const boundingRect = evt.currentTarget.getBoundingClientRect();
890
+ const clientWidth = boundingRect.width;
891
+ const clientHeight = boundingRect.height;
892
+ const widthDiff = clientWidth * this.zoom - clientWidth * oldZoom;
893
+ const heightDiff = clientHeight * this.zoom - clientHeight * oldZoom;
894
+ const clientX = evt.clientX - boundingRect.left;
895
+ const clientY = evt.clientY - boundingRect.top;
896
+ const xFactor = (clientX - this.x) / oldZoom / clientWidth;
897
+ const yFactor = (clientY - this.y) / oldZoom / clientHeight;
898
+ this.x = this.x - widthDiff * xFactor;
899
+ this.y = this.y - heightDiff * yFactor;
900
+ }
901
+ zoomToFit() {
902
+ // Get negative offset
903
+ let minX = 0;
904
+ let minY = 0;
905
+ this._nodes.forEach((node) => {
906
+ if (this._frames.some((f) => f.nodes.indexOf(node) !== -1)) {
907
+ return;
908
+ }
909
+ if (node.x < minX) {
910
+ minX = node.x;
911
+ }
912
+ if (node.y < minY) {
913
+ minY = node.y;
914
+ }
915
+ });
916
+ this._frames.forEach((frame) => {
917
+ if (frame.x < minX) {
918
+ minX = frame.x;
919
+ }
920
+ if (frame.y < minY) {
921
+ minY = frame.y;
922
+ }
923
+ });
924
+ // Restore to 0
925
+ this._frames.forEach((frame) => {
926
+ frame.x += -minX;
927
+ frame.y += -minY;
928
+ frame.cleanAccumulation();
929
+ });
930
+ this._nodes.forEach((node) => {
931
+ node.x += -minX;
932
+ node.y += -minY;
933
+ node.cleanAccumulation();
934
+ });
935
+ // Get correct zoom
936
+ const xFactor = this._rootContainer.clientWidth / this._rootContainer.scrollWidth;
937
+ const yFactor = this._rootContainer.clientHeight / this._rootContainer.scrollHeight;
938
+ const zoomFactor = xFactor < yFactor ? xFactor : yFactor;
939
+ this.zoom = zoomFactor;
940
+ this.x = 0;
941
+ this.y = 0;
942
+ }
943
+ processCandidatePort() {
944
+ let pointB = this._candidateLink.portA.portData;
945
+ let nodeB = this._candidateLink.portA.node;
946
+ let pointA;
947
+ let nodeA;
948
+ if (this._candidatePort) {
949
+ pointA = this._candidatePort.portData;
950
+ nodeA = this._candidatePort.node;
951
+ }
952
+ else {
953
+ if (pointB.direction === PortDataDirection.Output) {
954
+ return;
955
+ }
956
+ // No destination so let's spin a new input node
957
+ const newDefaultInput = this.props.stateManager.createDefaultInputData(this.props.stateManager.data, this._candidateLink.portA.portData, this);
958
+ if (!newDefaultInput) {
959
+ return;
960
+ }
961
+ const pointName = newDefaultInput.name;
962
+ const emittedNodeData = newDefaultInput.data;
963
+ pointA = emittedNodeData.getPortByName(pointName);
964
+ if (!emittedNodeData.isInput) {
965
+ nodeA = this.props.onEmitNewNode(emittedNodeData);
966
+ }
967
+ else {
968
+ nodeA = this.appendNode(emittedNodeData);
969
+ }
970
+ nodeA.x = this._dropPointX - 200;
971
+ nodeA.y = this._dropPointY - 50;
972
+ const x = nodeA.x - 250;
973
+ let y = nodeA.y;
974
+ emittedNodeData.inputs.forEach((portData) => {
975
+ if (portData.connectedPort) {
976
+ const existingNodes = this.nodes.filter((n) => {
977
+ var _a;
978
+ return n.content.data === ((_a = portData.connectedPort) === null || _a === void 0 ? void 0 : _a.ownerData);
979
+ });
980
+ const connectedNode = existingNodes[0];
981
+ if (connectedNode.x === 0 && connectedNode.y === 0) {
982
+ connectedNode.x = x;
983
+ connectedNode.y = y;
984
+ connectedNode.cleanAccumulation();
985
+ y += 80;
986
+ }
987
+ }
988
+ });
989
+ }
990
+ if (pointA.direction === PortDataDirection.Input) {
991
+ const temp = pointB;
992
+ pointB = pointA;
993
+ pointA = temp;
994
+ const tempNode = nodeA;
995
+ nodeA = nodeB;
996
+ nodeB = tempNode;
997
+ }
998
+ if (pointB.connectedPort === pointA) {
999
+ return;
1000
+ }
1001
+ if (pointB === pointA) {
1002
+ return;
1003
+ }
1004
+ if (pointB.direction === pointA.direction) {
1005
+ return;
1006
+ }
1007
+ if (pointB.ownerData === pointA.ownerData) {
1008
+ return;
1009
+ }
1010
+ // Check compatibility
1011
+ let compatibilityState = pointA.checkCompatibilityState(pointB);
1012
+ if ((pointA.needDualDirectionValidation || pointB.needDualDirectionValidation) && !compatibilityState) {
1013
+ compatibilityState = pointB.checkCompatibilityState(pointA);
1014
+ }
1015
+ const message = pointA.getCompatibilityIssueMessage(compatibilityState, nodeB, pointB);
1016
+ if (message) {
1017
+ this.props.stateManager.onErrorMessageDialogRequiredObservable.notifyObservers(message);
1018
+ return;
1019
+ }
1020
+ let linksToNotifyForDispose = null;
1021
+ if (pointB.isConnected) {
1022
+ const links = nodeB.getLinksForPortData(pointB);
1023
+ linksToNotifyForDispose = links.slice();
1024
+ links.forEach((link) => {
1025
+ link.dispose(false);
1026
+ });
1027
+ }
1028
+ if (pointB.ownerData.inputsAreExclusive) {
1029
+ // Disconnect all inputs if node has exclusive inputs
1030
+ pointB.ownerData.inputs.forEach((i) => {
1031
+ const links = nodeB.getLinksForPortData(i);
1032
+ if (!linksToNotifyForDispose) {
1033
+ linksToNotifyForDispose = links.slice();
1034
+ }
1035
+ else {
1036
+ linksToNotifyForDispose.push(...links.slice());
1037
+ }
1038
+ links.forEach((link) => {
1039
+ link.dispose(false);
1040
+ });
1041
+ });
1042
+ }
1043
+ this.connectNodes(nodeA, pointA, nodeB, pointB);
1044
+ linksToNotifyForDispose === null || linksToNotifyForDispose === void 0 ? void 0 : linksToNotifyForDispose.forEach((link) => {
1045
+ link.onDisposedObservable.notifyObservers(link);
1046
+ link.onDisposedObservable.clear();
1047
+ });
1048
+ this.props.stateManager.onRebuildRequiredObservable.notifyObservers(true);
1049
+ }
1050
+ connectNodes(nodeA, pointA, nodeB, pointB) {
1051
+ pointA.connectTo(pointB);
1052
+ this.connectPorts(pointA, pointB);
1053
+ // Need to potentially propagate the type of pointA to other ports of nodes connected to owner of pointB
1054
+ // We also need to check if we want to display the promotion warning
1055
+ const visitedNodes = new Set([nodeA]);
1056
+ const visitedLinks = new Set([nodeB.links[nodeB.links.length - 1]]);
1057
+ RefreshNode(nodeB, visitedNodes, visitedLinks);
1058
+ }
1059
+ drop(newNode, targetX, targetY, offsetX, offsetY) {
1060
+ let x = targetX - this.x - offsetX * this.zoom;
1061
+ let y = targetY - this.y - offsetY * this.zoom;
1062
+ newNode.x = x / this.zoom;
1063
+ newNode.y = y / this.zoom;
1064
+ newNode.cleanAccumulation();
1065
+ this.props.stateManager.onNewNodeCreatedObservable.notifyObservers(newNode);
1066
+ this.props.stateManager.onSelectionChangedObservable.notifyObservers(null);
1067
+ this.props.stateManager.onSelectionChangedObservable.notifyObservers({ selection: newNode });
1068
+ x -= GraphCanvasComponent.NodeWidth + 150;
1069
+ newNode.content.inputs.forEach((portData) => {
1070
+ if (portData.connectedPort) {
1071
+ const existingNodes = this.nodes.filter((n) => {
1072
+ var _a;
1073
+ return n.content.data === ((_a = portData.connectedPort) === null || _a === void 0 ? void 0 : _a.ownerData);
1074
+ });
1075
+ const connectedNode = existingNodes[0];
1076
+ if (connectedNode.x === 0 && connectedNode.y === 0) {
1077
+ connectedNode.x = x / this.zoom;
1078
+ connectedNode.y = y / this.zoom;
1079
+ connectedNode.cleanAccumulation();
1080
+ y += 80;
1081
+ }
1082
+ }
1083
+ });
1084
+ }
1085
+ processEditorData(editorData) {
1086
+ const frames = this._frames.splice(0);
1087
+ for (const frame of frames) {
1088
+ frame.dispose();
1089
+ }
1090
+ this._frames = [];
1091
+ this.x = editorData.x || 0;
1092
+ this.y = editorData.y || 0;
1093
+ this.zoom = editorData.zoom || 1;
1094
+ // Frames
1095
+ if (editorData.frames) {
1096
+ for (const frameData of editorData.frames) {
1097
+ const frame = GraphFrame.Parse(frameData, this, editorData.map);
1098
+ this._frames.push(frame);
1099
+ }
1100
+ }
1101
+ }
1102
+ reOrganize(editorData = null, isImportingAFrame = false) {
1103
+ if (!editorData || !editorData.locations) {
1104
+ this.distributeGraph();
1105
+ }
1106
+ else {
1107
+ // Locations
1108
+ for (const location of editorData.locations) {
1109
+ for (const node of this.nodes) {
1110
+ const data = node.content.data;
1111
+ if (data && data.uniqueId === location.blockId) {
1112
+ node.x = location.x;
1113
+ node.y = location.y;
1114
+ node.cleanAccumulation();
1115
+ break;
1116
+ }
1117
+ }
1118
+ }
1119
+ if (!isImportingAFrame) {
1120
+ this.processEditorData(editorData);
1121
+ }
1122
+ }
1123
+ this._isLoading = false;
1124
+ for (const node of this.nodes) {
1125
+ node._refreshLinks();
1126
+ }
1127
+ }
1128
+ addFrame(frameData) {
1129
+ const frame = GraphFrame.Parse(frameData, this, this.props.stateManager.getEditorDataMap());
1130
+ this._frames.push(frame);
1131
+ this.stateManager.onSelectionChangedObservable.notifyObservers({ selection: frame });
1132
+ }
1133
+ render() {
1134
+ return (_jsx("div", { ref: this._hostCanvasRef, id: "graph-canvas", className: styles["graph-canvas"], onWheel: (evt) => this.onWheel(evt), onPointerMove: (evt) => this.onMove(evt), onPointerDown: (evt) => this.onDown(evt), onPointerUp: (evt) => this.onUp(evt), children: _jsxs("div", { id: "graph-container", className: styles["graph-container"], ref: this._rootContainerRef, children: [_jsx("div", { id: "graph-canvas-container", className: styles["graph-canvas-container"], ref: this._graphCanvasRef }), _jsx("div", { id: "frame-container", className: styles["frame-container"], ref: this._frameContainerRef }), _jsx("svg", { id: "graph-svg-container", className: styles["graph-svg-container"], ref: this._svgCanvasRef }), _jsx("div", { id: "selection-container", className: styles["selection-container"], ref: this._selectionContainerRef })] }) }));
1135
+ }
1136
+ }
1137
+ GraphCanvasComponent.NodeWidth = 100;
1132
1138
  //# sourceMappingURL=graphCanvas.js.map