@eclipse-glsp/client 2.2.0-next.333 → 2.2.0-next.335

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 (214) hide show
  1. package/css/change-bounds.css +36 -2
  2. package/css/glsp-sprotty.css +18 -2
  3. package/css/helper-lines.css +3 -3
  4. package/lib/base/default.module.d.ts.map +1 -1
  5. package/lib/base/default.module.js +3 -0
  6. package/lib/base/default.module.js.map +1 -1
  7. package/lib/base/feedback/css-feedback.d.ts +7 -2
  8. package/lib/base/feedback/css-feedback.d.ts.map +1 -1
  9. package/lib/base/feedback/css-feedback.js +10 -2
  10. package/lib/base/feedback/css-feedback.js.map +1 -1
  11. package/lib/base/feedback/feeback-emitter.d.ts +2 -2
  12. package/lib/base/feedback/feeback-emitter.d.ts.map +1 -1
  13. package/lib/base/feedback/feeback-emitter.js +5 -2
  14. package/lib/base/feedback/feeback-emitter.js.map +1 -1
  15. package/lib/base/index.d.ts +1 -0
  16. package/lib/base/index.d.ts.map +1 -1
  17. package/lib/base/index.js +1 -0
  18. package/lib/base/index.js.map +1 -1
  19. package/lib/base/mouse-position-tracker.d.ts +22 -0
  20. package/lib/base/mouse-position-tracker.d.ts.map +1 -0
  21. package/lib/base/mouse-position-tracker.js +40 -0
  22. package/lib/base/mouse-position-tracker.js.map +1 -0
  23. package/lib/features/accessibility/view-key-tools/movement-key-tool.d.ts +2 -0
  24. package/lib/features/accessibility/view-key-tools/movement-key-tool.d.ts.map +1 -1
  25. package/lib/features/accessibility/view-key-tools/movement-key-tool.js +15 -7
  26. package/lib/features/accessibility/view-key-tools/movement-key-tool.js.map +1 -1
  27. package/lib/features/bounds/bounds-module.d.ts.map +1 -1
  28. package/lib/features/bounds/bounds-module.js +2 -0
  29. package/lib/features/bounds/bounds-module.js.map +1 -1
  30. package/lib/features/bounds/freeform-layout.d.ts +17 -1
  31. package/lib/features/bounds/freeform-layout.d.ts.map +1 -1
  32. package/lib/features/bounds/freeform-layout.js +14 -5
  33. package/lib/features/bounds/freeform-layout.js.map +1 -1
  34. package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts +5 -4
  35. package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts.map +1 -1
  36. package/lib/features/bounds/glsp-hidden-bounds-updater.js +51 -39
  37. package/lib/features/bounds/glsp-hidden-bounds-updater.js.map +1 -1
  38. package/lib/features/bounds/hbox-layout.d.ts +18 -2
  39. package/lib/features/bounds/hbox-layout.d.ts.map +1 -1
  40. package/lib/features/bounds/hbox-layout.js +14 -5
  41. package/lib/features/bounds/hbox-layout.js.map +1 -1
  42. package/lib/features/bounds/index.d.ts +1 -0
  43. package/lib/features/bounds/index.d.ts.map +1 -1
  44. package/lib/features/bounds/index.js +1 -0
  45. package/lib/features/bounds/index.js.map +1 -1
  46. package/lib/features/bounds/layout-data.d.ts +27 -0
  47. package/lib/features/bounds/layout-data.d.ts.map +1 -0
  48. package/lib/features/bounds/layout-data.js +48 -0
  49. package/lib/features/bounds/layout-data.js.map +1 -0
  50. package/lib/features/bounds/local-bounds.d.ts +3 -1
  51. package/lib/features/bounds/local-bounds.d.ts.map +1 -1
  52. package/lib/features/bounds/local-bounds.js +14 -0
  53. package/lib/features/bounds/local-bounds.js.map +1 -1
  54. package/lib/features/bounds/vbox-layout.d.ts +18 -2
  55. package/lib/features/bounds/vbox-layout.d.ts.map +1 -1
  56. package/lib/features/bounds/vbox-layout.js +14 -5
  57. package/lib/features/bounds/vbox-layout.js.map +1 -1
  58. package/lib/features/change-bounds/index.d.ts +1 -0
  59. package/lib/features/change-bounds/index.d.ts.map +1 -1
  60. package/lib/features/change-bounds/index.js +1 -0
  61. package/lib/features/change-bounds/index.js.map +1 -1
  62. package/lib/features/change-bounds/model.d.ts +19 -3
  63. package/lib/features/change-bounds/model.d.ts.map +1 -1
  64. package/lib/features/change-bounds/model.js +92 -4
  65. package/lib/features/change-bounds/model.js.map +1 -1
  66. package/lib/features/change-bounds/movement-restrictor.d.ts +1 -0
  67. package/lib/features/change-bounds/movement-restrictor.d.ts.map +1 -1
  68. package/lib/features/change-bounds/movement-restrictor.js +7 -1
  69. package/lib/features/change-bounds/movement-restrictor.js.map +1 -1
  70. package/lib/features/change-bounds/point-position-updater.d.ts +3 -0
  71. package/lib/features/change-bounds/point-position-updater.d.ts.map +1 -1
  72. package/lib/features/change-bounds/point-position-updater.js +7 -2
  73. package/lib/features/change-bounds/point-position-updater.js.map +1 -1
  74. package/lib/features/change-bounds/position-snapper.d.ts +4 -0
  75. package/lib/features/change-bounds/position-snapper.d.ts.map +1 -1
  76. package/lib/features/change-bounds/position-snapper.js +4 -0
  77. package/lib/features/change-bounds/position-snapper.js.map +1 -1
  78. package/lib/features/change-bounds/snap.d.ts +6 -0
  79. package/lib/features/change-bounds/snap.d.ts.map +1 -1
  80. package/lib/features/change-bounds/snap.js +6 -0
  81. package/lib/features/change-bounds/snap.js.map +1 -1
  82. package/lib/features/change-bounds/tracker.d.ts +32 -0
  83. package/lib/features/change-bounds/tracker.d.ts.map +1 -0
  84. package/lib/features/change-bounds/tracker.js +60 -0
  85. package/lib/features/change-bounds/tracker.js.map +1 -0
  86. package/lib/features/debug/debug-bounds-decorator.d.ts +4 -1
  87. package/lib/features/debug/debug-bounds-decorator.d.ts.map +1 -1
  88. package/lib/features/debug/debug-bounds-decorator.js +14 -7
  89. package/lib/features/debug/debug-bounds-decorator.js.map +1 -1
  90. package/lib/features/element-template/mouse-tracking-element-position-listener.d.ts +9 -22
  91. package/lib/features/element-template/mouse-tracking-element-position-listener.d.ts.map +1 -1
  92. package/lib/features/element-template/mouse-tracking-element-position-listener.js +30 -46
  93. package/lib/features/element-template/mouse-tracking-element-position-listener.js.map +1 -1
  94. package/lib/features/helper-lines/helper-line-feedback.d.ts +2 -2
  95. package/lib/features/helper-lines/helper-line-feedback.d.ts.map +1 -1
  96. package/lib/features/helper-lines/helper-line-feedback.js +1 -1
  97. package/lib/features/helper-lines/helper-line-feedback.js.map +1 -1
  98. package/lib/features/helper-lines/helper-line-manager-default.d.ts +2 -1
  99. package/lib/features/helper-lines/helper-line-manager-default.d.ts.map +1 -1
  100. package/lib/features/helper-lines/helper-line-manager-default.js +23 -0
  101. package/lib/features/helper-lines/helper-line-manager-default.js.map +1 -1
  102. package/lib/features/helper-lines/helper-line-manager.d.ts +10 -2
  103. package/lib/features/helper-lines/helper-line-manager.d.ts.map +1 -1
  104. package/lib/features/routing/edge-router.d.ts +4 -0
  105. package/lib/features/routing/edge-router.d.ts.map +1 -1
  106. package/lib/features/routing/edge-router.js +37 -0
  107. package/lib/features/routing/edge-router.js.map +1 -1
  108. package/lib/features/select/select-mouse-listener.d.ts +3 -0
  109. package/lib/features/select/select-mouse-listener.d.ts.map +1 -1
  110. package/lib/features/select/select-mouse-listener.js +30 -2
  111. package/lib/features/select/select-mouse-listener.js.map +1 -1
  112. package/lib/features/tools/base-tools.d.ts +24 -15
  113. package/lib/features/tools/base-tools.d.ts.map +1 -1
  114. package/lib/features/tools/base-tools.js +0 -18
  115. package/lib/features/tools/base-tools.js.map +1 -1
  116. package/lib/features/tools/change-bounds/change-bounds-manager.d.ts +42 -0
  117. package/lib/features/tools/change-bounds/change-bounds-manager.d.ts.map +1 -0
  118. package/lib/features/tools/change-bounds/change-bounds-manager.js +136 -0
  119. package/lib/features/tools/change-bounds/change-bounds-manager.js.map +1 -0
  120. package/lib/features/tools/change-bounds/change-bounds-tool-feedback.d.ts +6 -0
  121. package/lib/features/tools/change-bounds/change-bounds-tool-feedback.d.ts.map +1 -1
  122. package/lib/features/tools/change-bounds/change-bounds-tool-feedback.js +14 -8
  123. package/lib/features/tools/change-bounds/change-bounds-tool-feedback.js.map +1 -1
  124. package/lib/features/tools/change-bounds/change-bounds-tool-module.d.ts.map +1 -1
  125. package/lib/features/tools/change-bounds/change-bounds-tool-module.js +2 -0
  126. package/lib/features/tools/change-bounds/change-bounds-tool-module.js.map +1 -1
  127. package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.d.ts +6 -15
  128. package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.d.ts.map +1 -1
  129. package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.js +24 -72
  130. package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.js.map +1 -1
  131. package/lib/features/tools/change-bounds/change-bounds-tool.d.ts +14 -25
  132. package/lib/features/tools/change-bounds/change-bounds-tool.d.ts.map +1 -1
  133. package/lib/features/tools/change-bounds/change-bounds-tool.js +63 -109
  134. package/lib/features/tools/change-bounds/change-bounds-tool.js.map +1 -1
  135. package/lib/features/tools/change-bounds/change-bounds-tracker.d.ts +136 -0
  136. package/lib/features/tools/change-bounds/change-bounds-tracker.d.ts.map +1 -0
  137. package/lib/features/tools/change-bounds/change-bounds-tracker.js +301 -0
  138. package/lib/features/tools/change-bounds/change-bounds-tracker.js.map +1 -0
  139. package/lib/features/tools/change-bounds/index.d.ts +2 -0
  140. package/lib/features/tools/change-bounds/index.d.ts.map +1 -1
  141. package/lib/features/tools/change-bounds/index.js +2 -0
  142. package/lib/features/tools/change-bounds/index.js.map +1 -1
  143. package/lib/features/tools/change-bounds/view.d.ts.map +1 -1
  144. package/lib/features/tools/change-bounds/view.js +1 -16
  145. package/lib/features/tools/change-bounds/view.js.map +1 -1
  146. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.d.ts +7 -9
  147. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.d.ts.map +1 -1
  148. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.js +27 -47
  149. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.js.map +1 -1
  150. package/lib/features/tools/edge-edit/edge-edit-tool.d.ts +2 -2
  151. package/lib/features/tools/edge-edit/edge-edit-tool.d.ts.map +1 -1
  152. package/lib/features/tools/edge-edit/edge-edit-tool.js +5 -5
  153. package/lib/features/tools/edge-edit/edge-edit-tool.js.map +1 -1
  154. package/lib/features/tools/marquee-selection/marquee-mouse-tool.d.ts +1 -0
  155. package/lib/features/tools/marquee-selection/marquee-mouse-tool.d.ts.map +1 -1
  156. package/lib/features/tools/marquee-selection/marquee-mouse-tool.js +3 -0
  157. package/lib/features/tools/marquee-selection/marquee-mouse-tool.js.map +1 -1
  158. package/lib/features/tools/node-creation/node-creation-tool.d.ts +2 -4
  159. package/lib/features/tools/node-creation/node-creation-tool.d.ts.map +1 -1
  160. package/lib/features/tools/node-creation/node-creation-tool.js +8 -11
  161. package/lib/features/tools/node-creation/node-creation-tool.js.map +1 -1
  162. package/lib/utils/gmodel-util.d.ts +20 -1
  163. package/lib/utils/gmodel-util.d.ts.map +1 -1
  164. package/lib/utils/gmodel-util.js +38 -16
  165. package/lib/utils/gmodel-util.js.map +1 -1
  166. package/lib/utils/layout-utils.d.ts +1 -0
  167. package/lib/utils/layout-utils.d.ts.map +1 -1
  168. package/lib/utils/layout-utils.js +5 -1
  169. package/lib/utils/layout-utils.js.map +1 -1
  170. package/package.json +3 -3
  171. package/src/base/default.module.ts +4 -1
  172. package/src/base/feedback/css-feedback.ts +10 -2
  173. package/src/base/feedback/feeback-emitter.ts +6 -3
  174. package/src/base/index.ts +1 -0
  175. package/src/base/mouse-position-tracker.ts +25 -0
  176. package/src/features/accessibility/view-key-tools/movement-key-tool.ts +12 -7
  177. package/src/features/bounds/bounds-module.ts +2 -0
  178. package/src/features/bounds/freeform-layout.ts +16 -6
  179. package/src/features/bounds/glsp-hidden-bounds-updater.ts +63 -46
  180. package/src/features/bounds/hbox-layout.ts +18 -9
  181. package/src/features/bounds/index.ts +1 -0
  182. package/src/features/bounds/layout-data.ts +48 -0
  183. package/src/features/bounds/local-bounds.ts +20 -4
  184. package/src/features/bounds/vbox-layout.ts +18 -10
  185. package/src/features/change-bounds/index.ts +1 -0
  186. package/src/features/change-bounds/model.ts +104 -4
  187. package/src/features/change-bounds/movement-restrictor.ts +10 -0
  188. package/src/features/change-bounds/point-position-updater.spec.ts +2 -0
  189. package/src/features/change-bounds/point-position-updater.ts +6 -0
  190. package/src/features/change-bounds/position-snapper.ts +4 -0
  191. package/src/features/change-bounds/snap.ts +6 -0
  192. package/src/features/change-bounds/tracker.ts +63 -0
  193. package/src/features/debug/debug-bounds-decorator.tsx +17 -7
  194. package/src/features/element-template/mouse-tracking-element-position-listener.ts +49 -71
  195. package/src/features/helper-lines/helper-line-feedback.ts +2 -1
  196. package/src/features/helper-lines/helper-line-manager-default.ts +37 -2
  197. package/src/features/helper-lines/helper-line-manager.ts +11 -2
  198. package/src/features/routing/edge-router.ts +42 -0
  199. package/src/features/select/select-mouse-listener.ts +15 -1
  200. package/src/features/tools/base-tools.ts +31 -19
  201. package/src/features/tools/change-bounds/change-bounds-manager.ts +145 -0
  202. package/src/features/tools/change-bounds/change-bounds-tool-feedback.ts +17 -6
  203. package/src/features/tools/change-bounds/change-bounds-tool-module.ts +2 -0
  204. package/src/features/tools/change-bounds/change-bounds-tool-move-feedback.ts +31 -81
  205. package/src/features/tools/change-bounds/change-bounds-tool.ts +89 -148
  206. package/src/features/tools/change-bounds/change-bounds-tracker.ts +455 -0
  207. package/src/features/tools/change-bounds/index.ts +2 -0
  208. package/src/features/tools/change-bounds/view.tsx +2 -14
  209. package/src/features/tools/edge-edit/edge-edit-tool-feedback.ts +34 -52
  210. package/src/features/tools/edge-edit/edge-edit-tool.ts +4 -3
  211. package/src/features/tools/marquee-selection/marquee-mouse-tool.ts +4 -0
  212. package/src/features/tools/node-creation/node-creation-tool.ts +7 -7
  213. package/src/utils/gmodel-util.ts +41 -5
  214. package/src/utils/layout-utils.ts +4 -0
@@ -0,0 +1,455 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2024 EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import {
18
+ Bounds,
19
+ Dimension,
20
+ GModelElement,
21
+ GRoutingHandle,
22
+ Locateable,
23
+ Movement,
24
+ Point,
25
+ ResolvedElementMove,
26
+ TypeGuard,
27
+ Vector,
28
+ Writable,
29
+ hasBooleanProp,
30
+ isMoveable
31
+ } from '@eclipse-glsp/sprotty';
32
+ import { ChangeBoundsManager } from '..';
33
+ import { BoundsAwareModelElement, MoveableElement, ResizableModelElement, getElements } from '../../../utils';
34
+ import { DiagramMovementCalculator, ResizeHandleLocation, SResizeHandle } from '../../change-bounds';
35
+
36
+ export interface ElementTrackingOptions {
37
+ /** Snap position. Default: true. */
38
+ snap: boolean | MouseEvent | KeyboardEvent | any;
39
+ /** Restrict position. Default: true */
40
+ restrict: boolean | MouseEvent | KeyboardEvent | any;
41
+ /** Validate operation. Default: true */
42
+ validate: boolean;
43
+
44
+ /** Skip operations that do not trigger change. Default: true */
45
+ skipStatic: boolean;
46
+ }
47
+
48
+ export interface MoveOptions extends ElementTrackingOptions {
49
+ /** Skip operations are invalid. Default: false */
50
+ skipInvalid: boolean;
51
+ }
52
+
53
+ export const DEFAULT_MOVE_OPTIONS: MoveOptions = {
54
+ snap: true,
55
+ restrict: true,
56
+ validate: true,
57
+
58
+ skipStatic: true,
59
+ skipInvalid: false
60
+ };
61
+
62
+ export type MoveableElements =
63
+ | MoveableElement[]
64
+ | {
65
+ ctx: GModelElement;
66
+ elementIDs: string[];
67
+ guard?: TypeGuard<MoveableElement>;
68
+ };
69
+
70
+ export interface TrackedElementMove extends ResolvedElementMove {
71
+ moveVector: Vector;
72
+ sourceVector: Vector;
73
+ valid: boolean;
74
+ }
75
+
76
+ export type TypedElementMove<T extends MoveableElement> = TrackedElementMove & { element: T };
77
+
78
+ export interface TrackedMove extends Movement {
79
+ elementMoves: TrackedElementMove[];
80
+ valid: boolean;
81
+ options: MoveOptions;
82
+ }
83
+
84
+ export namespace TrackedMove {
85
+ export function is(obj: any): obj is TrackedMove {
86
+ return Movement.is(obj) && hasBooleanProp(obj, 'valid');
87
+ }
88
+ }
89
+
90
+ export interface ResizeOptions extends ElementTrackingOptions {
91
+ /** Skip resizes that do not actually change the dimension of the element. Default: true. */
92
+ skipStatic: boolean;
93
+
94
+ /** Perform symmetric resize on the opposite side. Default: false. */
95
+ symmetric: boolean | MouseEvent | KeyboardEvent | any;
96
+
97
+ /**
98
+ * Avoids resizes smaller than the minimum size which will result in invalid sizes.
99
+ * Please note that the snapping will be applied before the constraining so an element may still be resized to an unsnapped size.
100
+ *
101
+ * Default: true.
102
+ */
103
+ constrainResize: boolean;
104
+
105
+ /** Skip resizes that produce an invalid size. Default: false. */
106
+ skipInvalidSize: boolean;
107
+
108
+ /** Skip resizes that produce an invalid move. Default: false. */
109
+ skipInvalidMove: boolean;
110
+ }
111
+
112
+ export const DEFAULT_RESIZE_OPTIONS: ResizeOptions = {
113
+ snap: true,
114
+ restrict: true,
115
+ validate: true,
116
+ symmetric: true,
117
+
118
+ constrainResize: true,
119
+
120
+ skipStatic: true,
121
+ skipInvalidSize: false,
122
+ skipInvalidMove: false
123
+ };
124
+
125
+ export interface TrackedHandleMove extends TypedElementMove<MoveableResizeHandle> {}
126
+
127
+ export interface TrackedElementResize {
128
+ element: BoundsAwareModelElement;
129
+ fromBounds: Bounds;
130
+ toBounds: Bounds;
131
+ valid: {
132
+ size: boolean;
133
+ move: boolean;
134
+ };
135
+ }
136
+
137
+ export interface TrackedResize extends Movement {
138
+ handleMove: TrackedHandleMove;
139
+ elementResizes: TrackedElementResize[];
140
+ valid: {
141
+ size: boolean;
142
+ move: boolean;
143
+ };
144
+ options: ResizeOptions;
145
+ }
146
+
147
+ export class ChangeBoundsTracker {
148
+ protected diagramMovement: DiagramMovementCalculator;
149
+
150
+ constructor(readonly manager: ChangeBoundsManager) {
151
+ this.diagramMovement = new DiagramMovementCalculator(manager.positionTracker);
152
+ }
153
+
154
+ startTracking(): this {
155
+ this.diagramMovement.init();
156
+ return this;
157
+ }
158
+
159
+ updateTrackingPosition(param: Vector | Movement | TrackedMove): void {
160
+ const update = TrackedMove.is(param) ? Vector.max(...param.elementMoves.map(move => move.moveVector)) : param;
161
+ this.diagramMovement.updatePosition(update);
162
+ }
163
+
164
+ isTracking(): boolean {
165
+ return this.diagramMovement.hasPosition;
166
+ }
167
+
168
+ stopTracking(): this {
169
+ this.diagramMovement.dispose();
170
+ return this;
171
+ }
172
+
173
+ //
174
+ // MOVE
175
+ //
176
+
177
+ moveElements(elements: MoveableElements, opts?: Partial<MoveOptions>): TrackedMove {
178
+ const options = this.resolveMoveOptions(opts);
179
+ const update = this.calculateDiagramMovement();
180
+ const move: TrackedMove = { ...update, elementMoves: [], valid: true, options };
181
+
182
+ if (Vector.isZero(update.vector)) {
183
+ // no movement detected so elements won't be moved, exit early
184
+ return move;
185
+ }
186
+
187
+ // calculate move for each element
188
+ const elementsToMove = this.getMoveableElements(elements, options);
189
+ for (const element of elementsToMove) {
190
+ const elementMove = this.calculateElementMove(element, update.vector, options);
191
+ if (!this.skipElementMove(elementMove, options)) {
192
+ move.elementMoves.push(elementMove);
193
+ move.valid &&= elementMove.valid;
194
+ }
195
+ }
196
+ return move;
197
+ }
198
+
199
+ protected resolveMoveOptions(opts?: Partial<MoveOptions>): MoveOptions {
200
+ return {
201
+ ...DEFAULT_MOVE_OPTIONS,
202
+ ...opts,
203
+ snap: this.manager.usePositionSnap(opts?.snap ?? DEFAULT_MOVE_OPTIONS.snap),
204
+ restrict: this.manager.useMovementRestriction(opts?.restrict ?? DEFAULT_MOVE_OPTIONS.restrict)
205
+ };
206
+ }
207
+
208
+ protected calculateDiagramMovement(): Movement {
209
+ return this.diagramMovement.calculateMoveToCurrent();
210
+ }
211
+
212
+ protected getMoveableElements(elements: MoveableElements, options: MoveOptions): MoveableElement[] {
213
+ return Array.isArray(elements) ? elements : getElements(elements.ctx.index, elements.elementIDs, elements.guard ?? isMoveable);
214
+ }
215
+
216
+ protected skipElementMove(elementMove: TrackedElementMove, options: MoveOptions): boolean {
217
+ return (options.skipInvalid && !elementMove.valid) || (options.skipStatic && Vector.isZero(elementMove.moveVector));
218
+ }
219
+
220
+ protected calculateElementMove<T extends MoveableElement>(element: T, vector: Vector, options: MoveOptions): TypedElementMove<T> {
221
+ const fromPosition = element.position;
222
+ const toPosition = Point.add(fromPosition, vector);
223
+ const move: TypedElementMove<T> = { element, fromPosition, toPosition, valid: true, moveVector: vector, sourceVector: vector };
224
+
225
+ if (options.snap) {
226
+ move.toPosition = this.snapPosition(move, options);
227
+ }
228
+
229
+ if (options.restrict) {
230
+ move.toPosition = this.restrictMovement(move, options);
231
+ }
232
+
233
+ if (options.validate) {
234
+ move.valid = this.validateElementMove(move, options);
235
+ }
236
+
237
+ move.moveVector = Point.vector(move.fromPosition, move.toPosition);
238
+ return move;
239
+ }
240
+
241
+ protected snapPosition(elementMove: TrackedElementMove, opts: MoveOptions): Point {
242
+ return this.manager.snapPosition(elementMove.element, elementMove.toPosition);
243
+ }
244
+
245
+ protected restrictMovement(elementMove: TrackedElementMove, opts: MoveOptions): Point {
246
+ const movement = Point.move(elementMove.fromPosition, elementMove.toPosition);
247
+ return this.manager.restrictMovement(elementMove.element, movement).to;
248
+ }
249
+
250
+ protected validateElementMove(elementMove: TrackedElementMove, opts: MoveOptions): boolean {
251
+ return this.manager.hasValidPosition(elementMove.element, elementMove.toPosition);
252
+ }
253
+
254
+ //
255
+ // RESIZE
256
+ //
257
+
258
+ resizeElements(handle: SResizeHandle, opts?: Partial<ResizeOptions>): TrackedResize {
259
+ const options = this.resolveResizeOptions(opts);
260
+ const update = this.calculateDiagramMovement();
261
+ const handleMove = this.calculateHandleMove(new MoveableResizeHandle(handle), update.vector, options);
262
+ const resize: TrackedResize = { ...update, valid: { move: true, size: true }, options, handleMove, elementResizes: [] };
263
+ if (Vector.isZero(handleMove.moveVector)) {
264
+ // no movement detected so elements won't be moved, exit early
265
+ return resize;
266
+ }
267
+
268
+ // calculate resize for each element (typically only one element is resized at a time but customizations are possible)
269
+ const elementsToResize = this.getResizeableElements(handle, options);
270
+ for (const element of elementsToResize) {
271
+ const elementResize = this.calculateElementResize(element, handleMove, options);
272
+ if (!this.skipElementResize(elementResize, options)) {
273
+ resize.elementResizes.push(elementResize);
274
+ resize.valid.move = resize.valid.move && elementResize.valid.move;
275
+ resize.valid.size = resize.valid.size && elementResize.valid.size;
276
+ }
277
+ }
278
+ return resize;
279
+ }
280
+
281
+ protected resolveResizeOptions(opts?: Partial<ResizeOptions>): ResizeOptions {
282
+ return {
283
+ ...DEFAULT_RESIZE_OPTIONS,
284
+ ...opts,
285
+ snap: this.manager.usePositionSnap(opts?.snap ?? DEFAULT_RESIZE_OPTIONS.snap),
286
+ restrict: this.manager.useMovementRestriction(opts?.restrict ?? DEFAULT_RESIZE_OPTIONS.restrict),
287
+ symmetric: this.manager.useSymmetricResize(opts?.symmetric ?? DEFAULT_RESIZE_OPTIONS.symmetric)
288
+ };
289
+ }
290
+
291
+ protected calculateHandleMove(handle: MoveableResizeHandle, diagramMovement: Vector, opts?: Partial<ResizeOptions>): TrackedHandleMove {
292
+ const moveOptions = this.resolveMoveOptions({ ...opts, validate: false });
293
+ return this.calculateElementMove(handle, diagramMovement, moveOptions);
294
+ }
295
+
296
+ protected getResizeableElements(handle: SResizeHandle, options: ResizeOptions): ResizableModelElement[] {
297
+ return [handle.parent];
298
+ }
299
+
300
+ protected skipElementResize(elementResize: TrackedElementResize, options: ResizeOptions): boolean {
301
+ return (
302
+ (options.skipInvalidMove && !elementResize.valid.move) ||
303
+ (options.skipInvalidSize && !elementResize.valid.size) ||
304
+ (options.skipStatic && Dimension.equals(elementResize.fromBounds, elementResize.toBounds))
305
+ );
306
+ }
307
+
308
+ protected calculateElementResize(
309
+ element: ResizableModelElement,
310
+ handleMove: TrackedHandleMove,
311
+ options: ResizeOptions
312
+ ): TrackedElementResize {
313
+ const fromBounds = element.bounds;
314
+ const toBounds = this.calculateElementBounds(element, handleMove, options);
315
+ const resize: TrackedElementResize = { element, fromBounds, toBounds, valid: { size: true, move: true } };
316
+
317
+ if (options.validate) {
318
+ resize.valid.size = this.manager.hasValidSize(resize.element, resize.toBounds);
319
+ resize.valid.move = handleMove.valid && this.manager.hasValidPosition(resize.element, resize.toBounds);
320
+ }
321
+
322
+ return resize;
323
+ }
324
+
325
+ protected calculateElementBounds(element: ResizableModelElement, handleMove: TrackedHandleMove, options: ResizeOptions): Bounds {
326
+ let toBounds = this.calculateBounds(element.bounds, handleMove);
327
+ if (options.symmetric) {
328
+ const symmetricHandleMove = this.calculateSymmetricHandleMove(handleMove, options);
329
+ toBounds = this.calculateBounds(toBounds, symmetricHandleMove);
330
+ }
331
+ if (!options.constrainResize || this.manager.hasValidSize(element, toBounds)) {
332
+ return toBounds;
333
+ }
334
+
335
+ // we need to adjust to the minimum size but it is not enough to simply set the size
336
+ // we need to make sure that the element is still at the expected position
337
+ // we therefore constrain the movement vector to actually avoid going below the minimum size
338
+ const minimum = this.manager.getMinimumSize(element);
339
+ handleMove.moveVector = this.constrainResizeVector(element.bounds, handleMove, minimum);
340
+ if (options.symmetric) {
341
+ // if we have symmetric resize we want to distribute the constrained movement vector to both sides
342
+ // but only for the dimension that was actually resized beyond the minimum
343
+ handleMove.moveVector.x = element.bounds.width > minimum.width ? handleMove.moveVector.x / 2 : handleMove.moveVector.x;
344
+ handleMove.moveVector.y = element.bounds.height > minimum.height ? handleMove.moveVector.y / 2 : handleMove.moveVector.y;
345
+ }
346
+ toBounds = this.calculateBounds(element.bounds, handleMove);
347
+ if (options.symmetric) {
348
+ // since we already distributed the available movement vector, we do not want to snap the symmetric handle move
349
+ const symmetricHandleMove = this.calculateSymmetricHandleMove(handleMove, { ...options, snap: false });
350
+ toBounds = this.calculateBounds(toBounds, symmetricHandleMove);
351
+ }
352
+ return toBounds;
353
+ }
354
+
355
+ protected calculateSymmetricHandleMove(handleMove: TrackedHandleMove, options: ResizeOptions): TrackedHandleMove {
356
+ const moveOptions = this.resolveMoveOptions({ ...options, validate: false, restrict: false });
357
+ return this.calculateElementMove(handleMove.element.opposite(), Vector.reverse(handleMove.moveVector), moveOptions);
358
+ }
359
+
360
+ protected calculateBounds(src: Readonly<Bounds>, handleMove?: TrackedHandleMove): Bounds {
361
+ if (!handleMove || Vector.isZero(handleMove.moveVector)) {
362
+ return src;
363
+ }
364
+ return this.doCalculateBounds(src, handleMove.moveVector, handleMove.element.location);
365
+ }
366
+
367
+ protected doCalculateBounds(src: Readonly<Bounds>, vector: Vector, location: ResizeHandleLocation): Bounds {
368
+ switch (location) {
369
+ case ResizeHandleLocation.TopLeft:
370
+ return { x: src.x + vector.x, y: src.y + vector.y, width: src.width - vector.x, height: src.height - vector.y };
371
+ case ResizeHandleLocation.Top:
372
+ return { ...src, y: src.y + vector.y, height: src.height - vector.y };
373
+ case ResizeHandleLocation.TopRight:
374
+ return { ...src, y: src.y + vector.y, width: src.width + vector.x, height: src.height - vector.y };
375
+ case ResizeHandleLocation.Right:
376
+ return { ...src, width: src.width + vector.x };
377
+ case ResizeHandleLocation.BottomRight:
378
+ return { ...src, width: src.width + vector.x, height: src.height + vector.y };
379
+ case ResizeHandleLocation.Bottom:
380
+ return { ...src, height: src.height + vector.y };
381
+ case ResizeHandleLocation.BottomLeft:
382
+ return { ...src, x: src.x + vector.x, width: src.width - vector.x, height: src.height + vector.y };
383
+ case ResizeHandleLocation.Left:
384
+ return { ...src, x: src.x + vector.x, width: src.width - vector.x };
385
+ }
386
+ }
387
+
388
+ protected constrainResizeVector(src: Readonly<Bounds>, handleMove: TrackedHandleMove, minimum: Dimension): Vector {
389
+ const vector = handleMove.moveVector as Writable<Vector>;
390
+ switch (handleMove.element.location) {
391
+ case ResizeHandleLocation.TopLeft:
392
+ vector.x = src.width - vector.x < minimum.width ? src.width - minimum.width : vector.x;
393
+ vector.y = src.height - vector.y < minimum.height ? src.height - minimum.height : vector.y;
394
+ break;
395
+ case ResizeHandleLocation.Top:
396
+ vector.y = src.height - vector.y < minimum.height ? src.height - minimum.height : vector.y;
397
+ break;
398
+ case ResizeHandleLocation.TopRight:
399
+ vector.x = src.width + vector.x < minimum.width ? minimum.width - src.width : vector.x;
400
+ vector.y = src.height - vector.y < minimum.height ? src.height - minimum.height : vector.y;
401
+ break;
402
+ case ResizeHandleLocation.Right:
403
+ vector.x = src.width + vector.x < minimum.width ? minimum.width - src.width : vector.x;
404
+ break;
405
+ case ResizeHandleLocation.BottomRight:
406
+ vector.x = src.width + vector.x < minimum.width ? minimum.width - src.width : vector.x;
407
+ vector.y = src.height + vector.y < minimum.height ? minimum.height - src.height : vector.y;
408
+ break;
409
+ case ResizeHandleLocation.Bottom:
410
+ vector.y = src.height + vector.y < minimum.height ? minimum.height - src.height : vector.y;
411
+ break;
412
+ case ResizeHandleLocation.BottomLeft:
413
+ vector.x = src.width - vector.x < minimum.width ? src.width - minimum.width : vector.x;
414
+ vector.y = src.height + vector.y < minimum.height ? minimum.height - src.height : vector.y;
415
+ break;
416
+ case ResizeHandleLocation.Left:
417
+ vector.x = src.width - vector.x < minimum.width ? src.width - minimum.width : vector.x;
418
+ break;
419
+ }
420
+ return vector;
421
+ }
422
+
423
+ dispose(): void {
424
+ this.stopTracking();
425
+ }
426
+ }
427
+
428
+ export class MoveableResizeHandle extends SResizeHandle implements Locateable {
429
+ constructor(
430
+ protected handle: SResizeHandle,
431
+ override location: ResizeHandleLocation = handle.location,
432
+ readonly position = SResizeHandle.getHandlePosition(handle.parent, location)
433
+ ) {
434
+ super(location, handle.type, handle.hoverFeedback);
435
+ this.id = handle.id;
436
+ // this only acts as a wrapper so we do not actually add this to the parent but still want the parent reference
437
+ (this as any).parent = handle.parent;
438
+ }
439
+
440
+ opposite(): MoveableResizeHandle {
441
+ return new MoveableResizeHandle(this.handle, ResizeHandleLocation.opposite(this.location));
442
+ }
443
+ }
444
+
445
+ export class MoveableRoutingHandle extends GRoutingHandle implements Locateable {
446
+ constructor(
447
+ protected handle: GRoutingHandle,
448
+ readonly position: Point
449
+ ) {
450
+ super();
451
+ this.id = handle.id;
452
+ // this only acts as a wrapper so we do not actually add this to the parent but still want the parent reference
453
+ (this as any).parent = handle.parent;
454
+ }
455
+ }
@@ -13,8 +13,10 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
+ export * from './change-bounds-manager';
16
17
  export * from './change-bounds-tool';
17
18
  export * from './change-bounds-tool-feedback';
18
19
  export * from './change-bounds-tool-module';
19
20
  export * from './change-bounds-tool-move-feedback';
21
+ export * from './change-bounds-tracker';
20
22
  export * from './view';
@@ -16,7 +16,7 @@
16
16
  import { IView, Point, RenderingContext, setAttr, svg } from '@eclipse-glsp/sprotty';
17
17
  import { injectable } from 'inversify';
18
18
  import { VNode } from 'snabbdom';
19
- import { ResizeHandleLocation, SResizeHandle, isResizable } from '../../change-bounds/model';
19
+ import { SResizeHandle } from '../../change-bounds/model';
20
20
 
21
21
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
22
22
  const JSX = { createElement: svg };
@@ -46,19 +46,7 @@ export class SResizeHandleView implements IView {
46
46
  }
47
47
 
48
48
  protected getPosition(handle: SResizeHandle): Point | undefined {
49
- const parent = handle.parent;
50
- if (isResizable(parent)) {
51
- if (handle.location === ResizeHandleLocation.TopLeft) {
52
- return { x: 0, y: 0 };
53
- } else if (handle.location === ResizeHandleLocation.TopRight) {
54
- return { x: parent.bounds.width, y: 0 };
55
- } else if (handle.location === ResizeHandleLocation.BottomLeft) {
56
- return { x: 0, y: parent.bounds.height };
57
- } else if (handle.location === ResizeHandleLocation.BottomRight) {
58
- return { x: parent.bounds.width, y: parent.bounds.height };
59
- }
60
- }
61
- return undefined;
49
+ return Point.subtract(SResizeHandle.getHandlePosition(handle), handle.parent.bounds);
62
50
  }
63
51
 
64
52
  getRadius(): number {
@@ -21,7 +21,6 @@ import {
21
21
  CommandReturn,
22
22
  Disposable,
23
23
  EdgeRouterRegistry,
24
- ElementMove,
25
24
  GConnectableElement,
26
25
  GModelElement,
27
26
  GRoutingHandle,
@@ -37,17 +36,17 @@ import {
37
36
  hasStringProp,
38
37
  isBoundsAware,
39
38
  isConnectable,
40
- isSelected
39
+ isSelected,
40
+ toTypeGuard,
41
+ typeGuard
41
42
  } from '@eclipse-glsp/sprotty';
42
43
  import { inject, injectable } from 'inversify';
44
+ import { ChangeBoundsManager, ChangeBoundsTracker, MoveableRoutingHandle } from '..';
43
45
  import { FeedbackEmitter } from '../../../base';
44
46
  import { IFeedbackActionDispatcher } from '../../../base/feedback/feedback-action-dispatcher';
45
47
  import { FeedbackCommand } from '../../../base/feedback/feedback-command';
46
- import { forEachElement, isRoutable, isRoutingHandle } from '../../../utils/gmodel-util';
48
+ import { forEachElement, getMatchingElements, isRoutable, isRoutingHandle } from '../../../utils/gmodel-util';
47
49
  import { getAbsolutePosition, toAbsoluteBounds } from '../../../utils/viewpoint-util';
48
- import { PointPositionUpdater } from '../../change-bounds/point-position-updater';
49
- import { PositionSnapper } from '../../change-bounds/position-snapper';
50
- import { useSnap } from '../../change-bounds/snap';
51
50
  import { addReconnectHandles, removeReconnectHandles } from '../../reconnect/model';
52
51
  import { FeedbackEdgeEnd, feedbackEdgeEndId, feedbackEdgeId } from '../edge-creation/dangling-edge-feedback';
53
52
  import { FeedbackEdgeEndMovingMouseListener } from '../edge-creation/edge-creation-tool-feedback';
@@ -255,14 +254,14 @@ export class FeedbackEdgeSourceMovingMouseListener extends MouseListener impleme
255
254
  }
256
255
 
257
256
  export class FeedbackEdgeRouteMovingMouseListener extends MouseListener {
258
- protected pointPositionUpdater: PointPositionUpdater;
257
+ protected tracker: ChangeBoundsTracker;
259
258
 
260
259
  constructor(
261
- protected positionSnapper: PositionSnapper,
260
+ protected changeBoundsManager: ChangeBoundsManager,
262
261
  protected edgeRouterRegistry?: EdgeRouterRegistry
263
262
  ) {
264
263
  super();
265
- this.pointPositionUpdater = new PointPositionUpdater(positionSnapper);
264
+ this.tracker = this.changeBoundsManager.createTracker();
266
265
  }
267
266
 
268
267
  override mouseDown(target: GModelElement, event: MouseEvent): Action[] {
@@ -271,64 +270,47 @@ export class FeedbackEdgeRouteMovingMouseListener extends MouseListener {
271
270
  const routingHandle = findParentByFeature(target, isRoutingHandle);
272
271
  if (routingHandle !== undefined) {
273
272
  result.push(SwitchRoutingModeAction.create({ elementsToActivate: [target.id] }));
274
- this.pointPositionUpdater.updateLastDragPosition(event);
273
+ this.tracker.startTracking();
275
274
  } else {
276
- this.pointPositionUpdater.resetPosition();
275
+ this.tracker.dispose();
277
276
  }
278
277
  }
279
278
  return result;
280
279
  }
281
280
 
282
281
  override mouseMove(target: GModelElement, event: MouseEvent): Action[] {
283
- const result: Action[] = [];
282
+ super.mouseMove(target, event);
284
283
  if (event.buttons === 0) {
285
284
  return this.mouseUp(target, event);
286
- }
287
- const positionUpdate = this.pointPositionUpdater.updatePosition(target, event);
288
- if (positionUpdate) {
289
- const moveActions = this.handleMoveOnClient(target, positionUpdate, useSnap(event));
290
- result.push(...moveActions);
291
- }
292
- return result;
293
- }
294
-
295
- protected handleMoveOnClient(target: GModelElement, positionUpdate: Point, isSnap: boolean): Action[] {
296
- const handleMoves: ElementMove[] = [];
297
- target.root.index
298
- .all()
299
- .filter(element => isSelected(element))
300
- .forEach(element => {
301
- if (isRoutingHandle(element)) {
302
- const elementMove = this.toElementMove(element, positionUpdate, isSnap);
303
- if (elementMove) {
304
- handleMoves.push(elementMove);
305
- }
306
- }
307
- });
308
- if (handleMoves.length > 0) {
309
- return [MoveAction.create(handleMoves, { animate: false })];
285
+ } else if (this.tracker.isTracking()) {
286
+ return this.moveRoutingHandles(target, event);
310
287
  }
311
288
  return [];
312
289
  }
313
290
 
314
- protected toElementMove(element: GRoutingHandle, positionDelta: Point, isSnap: boolean): ElementMove | undefined {
315
- const point = this.getHandlePosition(element);
316
- if (point !== undefined) {
317
- const snappedPoint = this.getSnappedHandlePosition(element, point, isSnap);
318
- return {
319
- elementId: element.id,
320
- fromPosition: point,
321
- toPosition: {
322
- x: snappedPoint.x + positionDelta.x,
323
- y: snappedPoint.y + positionDelta.y
324
- }
325
- };
291
+ protected moveRoutingHandles(target: GModelElement, event: MouseEvent): Action[] {
292
+ const routingHandlesToMove = this.getRoutingHandlesToMove(target);
293
+ const move = this.tracker.moveElements(routingHandlesToMove, { snap: event, restrict: event });
294
+ if (move.elementMoves.length === 0) {
295
+ return [];
326
296
  }
327
- return undefined;
297
+ this.tracker.updateTrackingPosition(move);
298
+ return [
299
+ MoveAction.create(
300
+ move.elementMoves.map(elementMove => ({ elementId: elementMove.element.id, toPosition: elementMove.toPosition })),
301
+ { animate: false }
302
+ )
303
+ ];
328
304
  }
329
305
 
330
- protected getSnappedHandlePosition(element: GRoutingHandle, point: Point, isSnap: boolean): Point {
331
- return this.positionSnapper?.snapPosition(point, element, isSnap);
306
+ protected getRoutingHandlesToMove(context: GModelElement): MoveableRoutingHandle[] {
307
+ const selectedRoutingHandles = getMatchingElements(context.root.index, typeGuard(isRoutingHandle, isSelected));
308
+ return selectedRoutingHandles
309
+ .map(handle => {
310
+ const position = this.getHandlePosition(handle);
311
+ return position ? new MoveableRoutingHandle(handle, position) : undefined;
312
+ })
313
+ .filter(toTypeGuard(MoveableRoutingHandle));
332
314
  }
333
315
 
334
316
  protected getHandlePosition(handle: GRoutingHandle): Point | undefined {
@@ -345,7 +327,7 @@ export class FeedbackEdgeRouteMovingMouseListener extends MouseListener {
345
327
  }
346
328
 
347
329
  override mouseUp(_target: GModelElement, _event: MouseEvent): Action[] {
348
- this.pointPositionUpdater.resetPosition();
330
+ this.tracker.dispose();
349
331
  return [];
350
332
  }
351
333
  }
@@ -24,18 +24,19 @@ import {
24
24
  GRoutableElement,
25
25
  GRoutingHandle,
26
26
  ReconnectEdgeOperation,
27
+ TYPES,
27
28
  canEditRouting,
28
29
  findParentByFeature,
29
30
  isConnectable,
30
31
  isSelected
31
32
  } from '@eclipse-glsp/sprotty';
32
33
  import { inject, injectable, optional } from 'inversify';
34
+ import { ChangeBoundsManager } from '..';
33
35
  import { FeedbackEmitter } from '../../../base';
34
36
  import { DragAwareMouseListener } from '../../../base/drag-aware-mouse-listener';
35
37
  import { CursorCSS, cursorFeedbackAction } from '../../../base/feedback/css-feedback';
36
38
  import { ISelectionListener, SelectionService } from '../../../base/selection-service';
37
39
  import { calcElementAndRoutingPoints, isRoutable, isRoutingHandle } from '../../../utils/gmodel-util';
38
- import { PositionSnapper } from '../../change-bounds/position-snapper';
39
40
  import { GReconnectHandle, isReconnectHandle, isReconnectable, isSourceRoutingHandle, isTargetRoutingHandle } from '../../reconnect/model';
40
41
  import { BaseEditTool } from '../base-tools';
41
42
  import { DrawFeedbackEdgeAction, RemoveFeedbackEdgeAction, feedbackEdgeId } from '../edge-creation/dangling-edge-feedback';
@@ -56,7 +57,7 @@ export class EdgeEditTool extends BaseEditTool {
56
57
  @inject(SelectionService) protected selectionService: SelectionService;
57
58
  @inject(AnchorComputerRegistry) protected anchorRegistry: AnchorComputerRegistry;
58
59
  @inject(EdgeRouterRegistry) @optional() readonly edgeRouterRegistry?: EdgeRouterRegistry;
59
- @inject(PositionSnapper) readonly positionSnapper: PositionSnapper;
60
+ @inject(TYPES.IChangeBoundsManager) readonly changeBoundsManager: ChangeBoundsManager;
60
61
 
61
62
  protected feedbackEdgeSourceMovingListener: FeedbackEdgeSourceMovingMouseListener;
62
63
  protected feedbackEdgeTargetMovingListener: FeedbackEdgeTargetMovingMouseListener;
@@ -73,7 +74,7 @@ export class EdgeEditTool extends BaseEditTool {
73
74
  // install feedback move mouse listener for client-side move updates
74
75
  this.feedbackEdgeSourceMovingListener = new FeedbackEdgeSourceMovingMouseListener(this.anchorRegistry, this.feedbackDispatcher);
75
76
  this.feedbackEdgeTargetMovingListener = new FeedbackEdgeTargetMovingMouseListener(this.anchorRegistry, this.feedbackDispatcher);
76
- this.feedbackMovingListener = new FeedbackEdgeRouteMovingMouseListener(this.positionSnapper, this.edgeRouterRegistry);
77
+ this.feedbackMovingListener = new FeedbackEdgeRouteMovingMouseListener(this.changeBoundsManager, this.edgeRouterRegistry);
77
78
 
78
79
  this.toDisposeOnDisable.push(
79
80
  this.edgeEditListener,