@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
@@ -14,15 +14,18 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
  import {
17
+ Bounds,
17
18
  GChildElement,
18
19
  GModelElement,
19
20
  GParentElement,
20
21
  Hoverable,
22
+ Point,
21
23
  hoverFeedbackFeature,
22
24
  isBoundsAware,
23
25
  isMoveable,
24
26
  isSelectable
25
27
  } from '@eclipse-glsp/sprotty';
28
+ import { CursorCSS } from '../../base';
26
29
  import { BoundsAwareModelElement, MoveableElement, ResizableModelElement } from '../../utils';
27
30
 
28
31
  export const resizeFeature = Symbol('resizeFeature');
@@ -34,9 +37,36 @@ export function isResizable(element: GModelElement): element is ResizableModelEl
34
37
  // eslint-disable-next-line no-shadow
35
38
  export enum ResizeHandleLocation {
36
39
  TopLeft = 'top-left',
40
+ Top = 'top',
37
41
  TopRight = 'top-right',
42
+ Right = 'right',
43
+ BottomRight = 'bottom-right',
44
+ Bottom = 'bottom',
38
45
  BottomLeft = 'bottom-left',
39
- BottomRight = 'bottom-right'
46
+ Left = 'left'
47
+ }
48
+
49
+ export namespace ResizeHandleLocation {
50
+ export function opposite(location: ResizeHandleLocation): ResizeHandleLocation {
51
+ switch (location) {
52
+ case ResizeHandleLocation.TopLeft:
53
+ return ResizeHandleLocation.BottomRight;
54
+ case ResizeHandleLocation.Top:
55
+ return ResizeHandleLocation.Bottom;
56
+ case ResizeHandleLocation.TopRight:
57
+ return ResizeHandleLocation.BottomLeft;
58
+ case ResizeHandleLocation.Right:
59
+ return ResizeHandleLocation.Left;
60
+ case ResizeHandleLocation.BottomRight:
61
+ return ResizeHandleLocation.TopLeft;
62
+ case ResizeHandleLocation.Bottom:
63
+ return ResizeHandleLocation.Top;
64
+ case ResizeHandleLocation.BottomLeft:
65
+ return ResizeHandleLocation.TopRight;
66
+ case ResizeHandleLocation.Left:
67
+ return ResizeHandleLocation.Right;
68
+ }
69
+ }
40
70
  }
41
71
 
42
72
  export function isBoundsAwareMoveable(element: GModelElement): element is BoundsAwareModelElement & MoveableElement {
@@ -64,18 +94,34 @@ export class SResizeHandle extends GChildElement implements Hoverable {
64
94
  return this.location === ResizeHandleLocation.TopLeft;
65
95
  }
66
96
 
67
- isSeResize(): boolean {
68
- return this.location === ResizeHandleLocation.BottomRight;
97
+ isNResize(): boolean {
98
+ return this.location === ResizeHandleLocation.Top;
69
99
  }
70
100
 
71
101
  isNeResize(): boolean {
72
102
  return this.location === ResizeHandleLocation.TopRight;
73
103
  }
74
104
 
105
+ isEResize(): boolean {
106
+ return this.location === ResizeHandleLocation.Right;
107
+ }
108
+
109
+ isSeResize(): boolean {
110
+ return this.location === ResizeHandleLocation.BottomRight;
111
+ }
112
+
113
+ isSResize(): boolean {
114
+ return this.location === ResizeHandleLocation.Bottom;
115
+ }
116
+
75
117
  isSwResize(): boolean {
76
118
  return this.location === ResizeHandleLocation.BottomLeft;
77
119
  }
78
120
 
121
+ isWResize(): boolean {
122
+ return this.location === ResizeHandleLocation.Left;
123
+ }
124
+
79
125
  isNwSeResize(): boolean {
80
126
  return this.isNwResize() || this.isSeResize();
81
127
  }
@@ -83,18 +129,72 @@ export class SResizeHandle extends GChildElement implements Hoverable {
83
129
  isNeSwResize(): boolean {
84
130
  return this.isNeResize() || this.isSwResize();
85
131
  }
132
+
133
+ static getHandlePosition(handle: SResizeHandle): Point;
134
+ static getHandlePosition(parent: ResizableModelElement, location: ResizeHandleLocation): Point;
135
+ static getHandlePosition(bounds: Bounds, location: ResizeHandleLocation): Point;
136
+ static getHandlePosition(first: ResizableModelElement | SResizeHandle | Bounds, second?: ResizeHandleLocation): Point {
137
+ const bounds = SResizeHandle.is(first) ? first.parent.bounds : first instanceof GModelElement ? first.bounds : first;
138
+ const location = SResizeHandle.is(first) ? first.location : second!;
139
+ switch (location) {
140
+ case ResizeHandleLocation.TopLeft:
141
+ return Bounds.topLeft(bounds);
142
+ case ResizeHandleLocation.Top:
143
+ return Bounds.topCenter(bounds);
144
+ case ResizeHandleLocation.TopRight:
145
+ return Bounds.topRight(bounds);
146
+ case ResizeHandleLocation.Right:
147
+ return Bounds.middleRight(bounds);
148
+ case ResizeHandleLocation.BottomRight:
149
+ return Bounds.bottomRight(bounds);
150
+ case ResizeHandleLocation.Bottom:
151
+ return Bounds.bottomCenter(bounds);
152
+ case ResizeHandleLocation.BottomLeft:
153
+ return Bounds.bottomLeft(bounds);
154
+ case ResizeHandleLocation.Left:
155
+ return Bounds.middleLeft(bounds);
156
+ }
157
+ }
158
+
159
+ static getCursorCss(handle: SResizeHandle): string {
160
+ switch (handle.location) {
161
+ case ResizeHandleLocation.TopLeft:
162
+ return CursorCSS.RESIZE_NW;
163
+ case ResizeHandleLocation.Top:
164
+ return CursorCSS.RESIZE_N;
165
+ case ResizeHandleLocation.TopRight:
166
+ return CursorCSS.RESIZE_NE;
167
+ case ResizeHandleLocation.Right:
168
+ return CursorCSS.RESIZE_E;
169
+ case ResizeHandleLocation.BottomRight:
170
+ return CursorCSS.RESIZE_SE;
171
+ case ResizeHandleLocation.Bottom:
172
+ return CursorCSS.RESIZE_S;
173
+ case ResizeHandleLocation.BottomLeft:
174
+ return CursorCSS.RESIZE_SW;
175
+ case ResizeHandleLocation.Left:
176
+ return CursorCSS.RESIZE_W;
177
+ }
178
+ }
179
+
180
+ static is(handle: unknown): handle is SResizeHandle {
181
+ return typeof handle === 'object' && !!handle && 'type' in handle && handle.type === SResizeHandle.TYPE;
182
+ }
86
183
  }
87
184
 
88
185
  export function addResizeHandles(
89
186
  element: ResizableModelElement,
90
187
  locations: ResizeHandleLocation[] = [
91
188
  ResizeHandleLocation.TopLeft,
92
- ResizeHandleLocation.TopRight,
189
+ ResizeHandleLocation.Top,
93
190
  ResizeHandleLocation.BottomLeft,
94
191
  ResizeHandleLocation.BottomRight
95
192
  ]
96
193
  ): void {
97
194
  for (const location of Object.values(ResizeHandleLocation)) {
195
+ if (typeof location === 'function') {
196
+ continue;
197
+ }
98
198
  const existing = element.children.find(child => child instanceof SResizeHandle && child.location === location);
99
199
  if (locations.includes(location) && !existing) {
100
200
  // add missing handle
@@ -108,3 +108,13 @@ export function removeMovementRestrictionFeedback(
108
108
 
109
109
  return ModifyCSSFeedbackAction.create({ elements, remove: movementRestrictor.cssClasses });
110
110
  }
111
+
112
+ export function movementRestrictionFeedback(
113
+ element: GModelElement,
114
+ movementRestrictor: IMovementRestrictor,
115
+ valid: boolean
116
+ ): ModifyCSSFeedbackAction {
117
+ return valid
118
+ ? removeMovementRestrictionFeedback(element, movementRestrictor)
119
+ : createMovementRestrictionFeedback(element, movementRestrictor);
120
+ }
@@ -13,6 +13,8 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
+ /* eslint-disable import/no-deprecated */
17
+ /* eslint-disable deprecation/deprecation */
16
18
 
17
19
  import { GModelElement } from '@eclipse-glsp/sprotty';
18
20
  import { expect } from 'chai';
@@ -14,6 +14,9 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
  /* eslint-disable @typescript-eslint/no-shadow */
17
+ /* eslint-disable import/no-deprecated */
18
+ /* eslint-disable deprecation/deprecation */
19
+
17
20
  import { GModelElement, ISnapper, Point, Writable } from '@eclipse-glsp/sprotty';
18
21
  import { calculateDeltaBetweenPoints } from '../../utils/gmodel-util';
19
22
  import { isMouseEvent } from '../../utils/html-utils';
@@ -29,6 +32,9 @@ import { useSnap } from './snap';
29
32
  *
30
33
  * You can initialize a this class with a optional {@link ISnapper}. If a
31
34
  * snapper is present, the positions will be snapped to the defined grid.
35
+ *
36
+ * @deprecated The use of this class is discouraged. Use the {@link ChangeBoundsManager.createTracker}
37
+ * instead which centralized a few aspects of the tracking.
32
38
  */
33
39
  export class PointPositionUpdater {
34
40
  protected positionSnapper: PositionSnapper;
@@ -18,6 +18,10 @@ import { inject, injectable, optional } from 'inversify';
18
18
  import { IHelperLineManager } from '../helper-lines/helper-line-manager';
19
19
  import { Direction, HelperLine, isHelperLine } from '../helper-lines/model';
20
20
 
21
+ /**
22
+ * @deprecated The use of this class is discouraged. Use the {@link ChangeBoundsManager.createTracker}
23
+ * instead which centralized a few aspects of the tracking.
24
+ */
21
25
  @injectable()
22
26
  export class PositionSnapper {
23
27
  constructor(
@@ -16,10 +16,16 @@
16
16
  /* eslint-disable @typescript-eslint/no-shadow */
17
17
  import { KeyboardModifier } from '@eclipse-glsp/sprotty';
18
18
 
19
+ /**
20
+ * @deprecated Use {@link ChangeBoundsManager.useSnap} instead which may be customized.
21
+ */
19
22
  export function useSnap(event: MouseEvent | KeyboardEvent): boolean {
20
23
  return !event.shiftKey;
21
24
  }
22
25
 
26
+ /**
27
+ * @deprecated Use {@link ChangeBoundsManager.unsnapModifier} instead which may be customized.
28
+ */
23
29
  export function unsnapModifier(): KeyboardModifier {
24
30
  return 'shift';
25
31
  }
@@ -0,0 +1,63 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2024 Axon Ivy AG 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
+ import { Disposable, MousePositionTracker, Movement, Point, Vector } from '@eclipse-glsp/sprotty';
17
+
18
+ export class MovementCalculator implements Disposable {
19
+ protected position?: Point;
20
+
21
+ setPosition(position: Point): void {
22
+ this.position = { ...position };
23
+ }
24
+
25
+ updatePosition(param: Vector | Movement): void {
26
+ const vector = Vector.is(param) ? param : param.vector;
27
+ this.setPosition(Point.add(this.position ?? Point.ORIGIN, vector));
28
+ }
29
+
30
+ get hasPosition(): boolean {
31
+ return this.position !== undefined;
32
+ }
33
+
34
+ calculateMoveTo(targetPosition: Point): Movement {
35
+ return !this.position ? Movement.ZERO : Point.move(this.position, targetPosition);
36
+ }
37
+
38
+ dispose(): void {
39
+ this.position = undefined;
40
+ }
41
+ }
42
+
43
+ export class DiagramMovementCalculator extends MovementCalculator {
44
+ constructor(readonly positionTracker: MousePositionTracker) {
45
+ super();
46
+ }
47
+
48
+ init(): void {
49
+ const position = this.positionTracker.lastPositionOnDiagram;
50
+ if (position) {
51
+ this.setPosition(position);
52
+ }
53
+ }
54
+
55
+ calculateMoveToCurrent(): Movement {
56
+ const targetPosition = this.positionTracker.lastPositionOnDiagram;
57
+ return targetPosition ? this.calculateMoveTo(targetPosition) : Movement.ZERO;
58
+ }
59
+
60
+ reset(): void {
61
+ this.dispose();
62
+ }
63
+ }
@@ -15,7 +15,7 @@
15
15
  ********************************************************************************/
16
16
  /* eslint-disable max-len */
17
17
 
18
- import { Bounds, GModelElement, IVNodePostprocessor, Point, TYPES, isBoundsAware, setClass, svg } from '@eclipse-glsp/sprotty';
18
+ import { Bounds, GModelElement, IVNodePostprocessor, Point, TYPES, isDecoration, isSizeable, setClass, svg } from '@eclipse-glsp/sprotty';
19
19
  import { inject, injectable, optional } from 'inversify';
20
20
  import { VNode } from 'snabbdom';
21
21
  import { GGraph } from '../../model';
@@ -25,6 +25,8 @@ import { DebugManager } from './debug-manager';
25
25
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
26
  const JSX = { createElement: svg };
27
27
 
28
+ export const CSS_DEBUG_BOUNDS = 'debug-bounds';
29
+
28
30
  @injectable()
29
31
  export class DebugBoundsDecorator implements IVNodePostprocessor {
30
32
  @inject(TYPES.IDebugManager) @optional() protected debugManager?: DebugManager;
@@ -33,10 +35,10 @@ export class DebugBoundsDecorator implements IVNodePostprocessor {
33
35
  if (!this.debugManager?.isDebugEnabled) {
34
36
  return vnode;
35
37
  }
36
- if (isBoundsAware(element)) {
37
- this.decorateBoundsAware(vnode, element);
38
+ if (isSizeable(element) && this.shouldDecorateSizeable(element)) {
39
+ this.decorateSizeable(vnode, element);
38
40
  }
39
- if (element instanceof GGraph) {
41
+ if (element instanceof GGraph && this.shouldDecorateGraph(element)) {
40
42
  this.decorateGraph(vnode, element);
41
43
  }
42
44
  return vnode;
@@ -48,8 +50,12 @@ export class DebugBoundsDecorator implements IVNodePostprocessor {
48
50
  return 5;
49
51
  }
50
52
 
53
+ protected shouldDecorateGraph(graph: GGraph): boolean {
54
+ return true;
55
+ }
56
+
51
57
  protected decorateGraph(vnode: VNode, graph: GGraph): void {
52
- setClass(vnode, 'debug-bounds', true);
58
+ setClass(vnode, CSS_DEBUG_BOUNDS, true);
53
59
  const svgChild = vnode.children?.find(child => typeof child !== 'string' && child.sel === 'svg') as VNode | undefined;
54
60
  const group = svgChild?.children?.find(child => typeof child !== 'string' && child.sel === 'g') as VNode | undefined;
55
61
  group?.children?.push(this.renderOrigin(graph));
@@ -67,8 +73,12 @@ export class DebugBoundsDecorator implements IVNodePostprocessor {
67
73
  );
68
74
  }
69
75
 
70
- protected decorateBoundsAware(vnode: VNode, element: BoundsAwareModelElement): void {
71
- setClass(vnode, 'debug-bounds', true);
76
+ protected shouldDecorateSizeable(element: BoundsAwareModelElement): boolean {
77
+ return !isDecoration(element);
78
+ }
79
+
80
+ protected decorateSizeable(vnode: VNode, element: BoundsAwareModelElement): void {
81
+ setClass(vnode, CSS_DEBUG_BOUNDS, true);
72
82
  vnode.children?.push(this.renderTopLeftCorner(element));
73
83
  vnode.children?.push(this.renderTopRightCorner(element));
74
84
  vnode.children?.push(this.renderBottomLeftCorner(element));
@@ -14,55 +14,27 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
 
17
- import {
18
- Action,
19
- Dimension,
20
- Disposable,
21
- ElementMove,
22
- GModelElement,
23
- MoveAction,
24
- Point,
25
- isBoundsAware,
26
- isMoveable
27
- } from '@eclipse-glsp/sprotty';
28
- import { injectable } from 'inversify';
17
+ import { Action, Dimension, GModelElement, MoveAction, Point, isBoundsAware, isMoveable } from '@eclipse-glsp/sprotty';
29
18
  import { DragAwareMouseListener } from '../../base/drag-aware-mouse-listener';
30
19
  import { CSS_HIDDEN, ModifyCSSFeedbackAction } from '../../base/feedback/css-feedback';
31
20
  import { FeedbackEmitter } from '../../base/feedback/feeback-emitter';
32
- import { IFeedbackEmitter } from '../../base/feedback/feedback-action-dispatcher';
33
- import { Tool } from '../../base/tool-manager/tool';
34
- import { MoveableElement } from '../../utils';
35
- import { getAbsolutePosition } from '../../utils/viewpoint-util';
21
+ import { MoveableElement, getAbsolutePosition } from '../../utils';
36
22
  import {
37
- IMovementRestrictor,
38
- createMovementRestrictionFeedback,
39
- removeMovementRestrictionFeedback
40
- } from '../change-bounds/movement-restrictor';
41
- import { PointPositionUpdater } from '../change-bounds/point-position-updater';
42
- import { PositionSnapper } from '../change-bounds/position-snapper';
43
- import { useSnap } from '../change-bounds/snap';
44
- import { MoveFinishedEventAction } from '../tools';
45
-
46
- export interface PositioningTool extends Tool {
47
- readonly positionSnapper: PositionSnapper;
48
- readonly movementRestrictor?: IMovementRestrictor;
23
+ CSS_RESIZE_MODE,
24
+ ChangeBoundsManager,
25
+ ChangeBoundsTracker,
26
+ FeedbackAwareTool,
27
+ MoveFinishedEventAction,
28
+ TrackedElementMove
29
+ } from '../tools';
49
30
 
50
- createFeedbackEmitter(): FeedbackEmitter;
51
- /**
52
- * @deprecated It is recommended to create a {@link createFeedbackEmitter dedicated emitter} per feedback instead of using the tool.
53
- */
54
- registerFeedback(feedbackActions: Action[], feedbackEmitter?: IFeedbackEmitter, cleanupActions?: Action[]): Disposable;
55
- /**
56
- * @deprecated It is recommended to create a {@link createFeedbackEmitter dedicated emitter} per feedback and dispose it like that.
57
- */
58
- deregisterFeedback(feedbackEmitter?: IFeedbackEmitter, cleanupActions?: Action[]): void;
31
+ export interface PositioningTool extends FeedbackAwareTool {
32
+ readonly changeBoundsManager: ChangeBoundsManager;
59
33
  }
60
34
 
61
- @injectable()
62
35
  export class MouseTrackingElementPositionListener extends DragAwareMouseListener {
63
- protected positionUpdater: PointPositionUpdater;
64
36
  protected moveGhostFeedback: FeedbackEmitter;
65
- protected currentPosition?: Point;
37
+ protected tracker: ChangeBoundsTracker;
66
38
 
67
39
  constructor(
68
40
  protected elementId: string,
@@ -70,54 +42,60 @@ export class MouseTrackingElementPositionListener extends DragAwareMouseListener
70
42
  protected cursorPosition: 'top-left' | 'middle' = 'top-left'
71
43
  ) {
72
44
  super();
73
- this.positionUpdater = new PointPositionUpdater(this.tool.positionSnapper);
45
+ this.tracker = this.tool.changeBoundsManager.createTracker();
74
46
  this.moveGhostFeedback = this.tool.createFeedbackEmitter();
75
47
  }
76
48
 
49
+ protected getTrackedElement(target: GModelElement, event: MouseEvent): MoveableElement | undefined {
50
+ const element = target.root.index.getById(this.elementId);
51
+ return !element || !isMoveable(element) ? undefined : element;
52
+ }
53
+
77
54
  override mouseMove(target: GModelElement, event: MouseEvent): Action[] {
78
55
  super.mouseMove(target, event);
79
- const element = target.root.index.getById(this.elementId);
80
- if (!element || !isMoveable(element)) {
56
+ const element = this.getTrackedElement(target, event);
57
+ if (!element) {
81
58
  return [];
82
59
  }
83
- if (this.positionUpdater.isLastDragPositionUndefined()) {
84
- this.positionUpdater.updateLastDragPosition(element.position);
60
+ if (!this.tracker.isTracking()) {
61
+ this.initialize(element, target, event);
85
62
  }
86
- const mousePosition = getAbsolutePosition(target, event);
87
- const delta = this.positionUpdater.updatePosition(element, mousePosition, useSnap(event));
88
- if (!delta) {
63
+ const move = this.tracker.moveElements([element], { snap: event, restrict: event, validate: true });
64
+ const elementMove = move.elementMoves[0];
65
+ if (!elementMove) {
89
66
  return [];
90
67
  }
91
- const toPosition = this.getElementTargetPosition(mousePosition, element, event);
92
- const elementMove = { elementId: element.id, toPosition: toPosition };
93
- this.addMoveFeeback(element, elementMove);
94
- this.currentPosition = toPosition;
95
68
  // since we are moving a ghost element that is feedback-only and will be removed anyway,
96
69
  // we just send a MoveFinishedEventAction instead of reseting the position with a MoveAction and the finished flag set to true.
97
- this.moveGhostFeedback.add(MoveAction.create([elementMove], { animate: false }), MoveFinishedEventAction.create()).submit();
70
+ this.moveGhostFeedback.add(
71
+ MoveAction.create([{ elementId: this.elementId, toPosition: elementMove.toPosition }], { animate: false }),
72
+ MoveFinishedEventAction.create()
73
+ );
74
+ this.addMoveFeeback(elementMove);
75
+ this.moveGhostFeedback.submit();
76
+ this.tracker.updateTrackingPosition(elementMove.moveVector);
98
77
  return [];
99
78
  }
100
79
 
101
- protected getElementTargetPosition(mousePosition: Point, element: MoveableElement, event: MouseEvent): Point {
102
- const unsnappedPosition =
103
- this.cursorPosition === 'middle' && isBoundsAware(element)
104
- ? Point.subtract(mousePosition, Dimension.center(element.bounds))
105
- : mousePosition;
106
- return this.tool.positionSnapper.snapPosition(unsnappedPosition, element, useSnap(event));
80
+ protected initialize(element: MoveableElement, target: GModelElement, event: MouseEvent): void {
81
+ this.tracker.startTracking();
82
+ element.position = this.initializeElementPosition(element, target, event);
107
83
  }
108
84
 
109
- protected addMoveFeeback(element: MoveableElement, elementMove: ElementMove): void {
110
- if (this.tool.movementRestrictor) {
111
- if (!this.tool.movementRestrictor.validate(element, elementMove.toPosition)) {
112
- this.moveGhostFeedback.add(
113
- createMovementRestrictionFeedback(element, this.tool.movementRestrictor),
114
- removeMovementRestrictionFeedback(element, this.tool.movementRestrictor)
115
- );
116
- } else {
117
- this.moveGhostFeedback.add(removeMovementRestrictionFeedback(element, this.tool.movementRestrictor));
118
- }
119
- }
120
- this.moveGhostFeedback.add(ModifyCSSFeedbackAction.create({ elements: [element.id], remove: [CSS_HIDDEN] }));
85
+ protected initializeElementPosition(element: MoveableElement, target: GModelElement, event: MouseEvent): Point {
86
+ const mousePosition = getAbsolutePosition(target, event);
87
+ return this.cursorPosition === 'middle' && isBoundsAware(element)
88
+ ? Point.subtract(mousePosition, Dimension.center(element.bounds))
89
+ : mousePosition;
90
+ }
91
+
92
+ protected addMoveFeeback(move: TrackedElementMove): void {
93
+ this.tool.changeBoundsManager.addRestrictionFeedback(this.moveGhostFeedback, move);
94
+ this.moveGhostFeedback.add(ModifyCSSFeedbackAction.create({ elements: [move.element.id], remove: [CSS_HIDDEN] }));
95
+ this.moveGhostFeedback.add(
96
+ ModifyCSSFeedbackAction.create({ add: [CSS_RESIZE_MODE] }),
97
+ ModifyCSSFeedbackAction.create({ remove: [CSS_RESIZE_MODE] })
98
+ );
121
99
  }
122
100
 
123
101
  override dispose(): void {
@@ -27,6 +27,7 @@ import {
27
27
  Point,
28
28
  TYPES,
29
29
  Viewport,
30
+ equalUpTo,
30
31
  findParentByFeature,
31
32
  isBoundsAware,
32
33
  isDecoration,
@@ -293,7 +294,7 @@ export class DrawHelperLinesFeedbackCommand extends FeedbackCommand {
293
294
  }
294
295
 
295
296
  protected isMatch(leftCoordinate: number, rightCoordinate: number, epsilon: number): boolean {
296
- return Math.abs(leftCoordinate - rightCoordinate) <= epsilon;
297
+ return equalUpTo(leftCoordinate, rightCoordinate, epsilon);
297
298
  }
298
299
 
299
300
  protected log(message: string, ...params: any[]): void {
@@ -13,7 +13,18 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
- import { Action, GModelElement, GModelRoot, IActionHandler, MoveAction, Point, SetBoundsAction, TYPES } from '@eclipse-glsp/sprotty';
16
+ import {
17
+ Action,
18
+ GModelElement,
19
+ GModelRoot,
20
+ IActionHandler,
21
+ MoveAction,
22
+ Point,
23
+ SetBoundsAction,
24
+ TYPES,
25
+ Vector,
26
+ Writable
27
+ } from '@eclipse-glsp/sprotty';
17
28
  import { inject, injectable, optional, postConstruct } from 'inversify';
18
29
  import { FeedbackEmitter } from '../../base';
19
30
  import { IFeedbackActionDispatcher } from '../../base/feedback/feedback-action-dispatcher';
@@ -33,7 +44,7 @@ import {
33
44
  ViewportLineType
34
45
  } from './helper-line-feedback';
35
46
  import { IHelperLineManager } from './helper-line-manager';
36
- import { Direction, HelperLineType } from './model';
47
+ import { Direction, HelperLine, HelperLineType, isHelperLine } from './model';
37
48
 
38
49
  export interface IHelperLineOptions {
39
50
  /**
@@ -158,4 +169,28 @@ export class HelperLineManager implements IActionHandler, ISelectionListener, IH
158
169
  ? this.options.minimumMoveDelta.x
159
170
  : this.options.minimumMoveDelta.y;
160
171
  }
172
+
173
+ getMinimumMoveVector(element: GModelElement, isSnap: boolean, directions: Direction[]): Vector | undefined {
174
+ if (!isSnap) {
175
+ return undefined;
176
+ }
177
+
178
+ const helperLines = element.root.children.filter(child => isHelperLine(child)) as HelperLine[];
179
+ if (helperLines.length === 0) {
180
+ return undefined;
181
+ }
182
+
183
+ const minimum: Writable<Vector> = { ...Vector.ZERO };
184
+ if (directions.includes(Direction.Left) && helperLines.some(line => line.isLeft || line.isCenter)) {
185
+ minimum.x = this.getMinimumMoveDelta(element, isSnap, Direction.Left);
186
+ } else if (directions.includes(Direction.Right) && helperLines.some(line => line.isRight || line.isCenter)) {
187
+ minimum.x = this.getMinimumMoveDelta(element, isSnap, Direction.Right);
188
+ }
189
+ if (directions.includes(Direction.Up) && helperLines.some(line => line.isTop || line.isMiddle)) {
190
+ minimum.y = this.getMinimumMoveDelta(element, isSnap, Direction.Up);
191
+ } else if (directions.includes(Direction.Down) && helperLines.some(line => line.isBottom || line.isMiddle)) {
192
+ minimum.y = this.getMinimumMoveDelta(element, isSnap, Direction.Down);
193
+ }
194
+ return Vector.isZero(minimum) ? undefined : minimum;
195
+ }
161
196
  }
@@ -13,16 +13,25 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
- import { GModelElement } from '@eclipse-glsp/sprotty';
16
+ import { GModelElement, Vector } from '@eclipse-glsp/sprotty';
17
17
  import { Direction } from './model';
18
18
 
19
19
  export interface IHelperLineManager {
20
20
  /**
21
- * Calculates the minimum move delta that is necessary to break through a helper line.
21
+ * Calculates the minimum move delta on one axis that is necessary to break through a helper line.
22
22
  *
23
23
  * @param element element that is being moved
24
24
  * @param isSnap whether snapping is active or not
25
25
  * @param direction direction in which the target element is moving
26
26
  */
27
27
  getMinimumMoveDelta(element: GModelElement, isSnap: boolean, direction: Direction): number;
28
+
29
+ /**
30
+ * Calculates the minimum move vector that is necessary to break through a helper line.
31
+ *
32
+ * @param element element that is being moved
33
+ * @param isSnap whether snapping is active or not
34
+ * @param directions directions in which the target element is moving
35
+ */
36
+ getMinimumMoveVector(element: GModelElement, isSnap: boolean, directions: Direction[]): Vector | undefined;
28
37
  }