@eclipse-glsp/client 2.2.0-next.333 → 2.2.0-next.334
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/change-bounds.css +36 -2
- package/css/glsp-sprotty.css +18 -2
- package/css/helper-lines.css +3 -3
- package/lib/base/default.module.d.ts.map +1 -1
- package/lib/base/default.module.js +3 -0
- package/lib/base/default.module.js.map +1 -1
- package/lib/base/feedback/css-feedback.d.ts +7 -2
- package/lib/base/feedback/css-feedback.d.ts.map +1 -1
- package/lib/base/feedback/css-feedback.js +10 -2
- package/lib/base/feedback/css-feedback.js.map +1 -1
- package/lib/base/feedback/feeback-emitter.d.ts +2 -2
- package/lib/base/feedback/feeback-emitter.d.ts.map +1 -1
- package/lib/base/feedback/feeback-emitter.js +5 -2
- package/lib/base/feedback/feeback-emitter.js.map +1 -1
- package/lib/base/index.d.ts +1 -0
- package/lib/base/index.d.ts.map +1 -1
- package/lib/base/index.js +1 -0
- package/lib/base/index.js.map +1 -1
- package/lib/base/mouse-position-tracker.d.ts +22 -0
- package/lib/base/mouse-position-tracker.d.ts.map +1 -0
- package/lib/base/mouse-position-tracker.js +40 -0
- package/lib/base/mouse-position-tracker.js.map +1 -0
- package/lib/features/accessibility/view-key-tools/movement-key-tool.d.ts +2 -0
- package/lib/features/accessibility/view-key-tools/movement-key-tool.d.ts.map +1 -1
- package/lib/features/accessibility/view-key-tools/movement-key-tool.js +15 -7
- package/lib/features/accessibility/view-key-tools/movement-key-tool.js.map +1 -1
- package/lib/features/bounds/bounds-module.d.ts.map +1 -1
- package/lib/features/bounds/bounds-module.js +2 -0
- package/lib/features/bounds/bounds-module.js.map +1 -1
- package/lib/features/bounds/freeform-layout.d.ts +17 -1
- package/lib/features/bounds/freeform-layout.d.ts.map +1 -1
- package/lib/features/bounds/freeform-layout.js +14 -5
- package/lib/features/bounds/freeform-layout.js.map +1 -1
- package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts +5 -4
- package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts.map +1 -1
- package/lib/features/bounds/glsp-hidden-bounds-updater.js +51 -39
- package/lib/features/bounds/glsp-hidden-bounds-updater.js.map +1 -1
- package/lib/features/bounds/hbox-layout.d.ts +18 -2
- package/lib/features/bounds/hbox-layout.d.ts.map +1 -1
- package/lib/features/bounds/hbox-layout.js +14 -5
- package/lib/features/bounds/hbox-layout.js.map +1 -1
- package/lib/features/bounds/index.d.ts +1 -0
- package/lib/features/bounds/index.d.ts.map +1 -1
- package/lib/features/bounds/index.js +1 -0
- package/lib/features/bounds/index.js.map +1 -1
- package/lib/features/bounds/layout-data.d.ts +27 -0
- package/lib/features/bounds/layout-data.d.ts.map +1 -0
- package/lib/features/bounds/layout-data.js +48 -0
- package/lib/features/bounds/layout-data.js.map +1 -0
- package/lib/features/bounds/local-bounds.d.ts +3 -1
- package/lib/features/bounds/local-bounds.d.ts.map +1 -1
- package/lib/features/bounds/local-bounds.js +14 -0
- package/lib/features/bounds/local-bounds.js.map +1 -1
- package/lib/features/bounds/vbox-layout.d.ts +18 -2
- package/lib/features/bounds/vbox-layout.d.ts.map +1 -1
- package/lib/features/bounds/vbox-layout.js +14 -5
- package/lib/features/bounds/vbox-layout.js.map +1 -1
- package/lib/features/change-bounds/index.d.ts +1 -0
- package/lib/features/change-bounds/index.d.ts.map +1 -1
- package/lib/features/change-bounds/index.js +1 -0
- package/lib/features/change-bounds/index.js.map +1 -1
- package/lib/features/change-bounds/model.d.ts +19 -3
- package/lib/features/change-bounds/model.d.ts.map +1 -1
- package/lib/features/change-bounds/model.js +92 -4
- package/lib/features/change-bounds/model.js.map +1 -1
- package/lib/features/change-bounds/movement-restrictor.d.ts +1 -0
- package/lib/features/change-bounds/movement-restrictor.d.ts.map +1 -1
- package/lib/features/change-bounds/movement-restrictor.js +7 -1
- package/lib/features/change-bounds/movement-restrictor.js.map +1 -1
- package/lib/features/change-bounds/point-position-updater.d.ts +3 -0
- package/lib/features/change-bounds/point-position-updater.d.ts.map +1 -1
- package/lib/features/change-bounds/point-position-updater.js +7 -2
- package/lib/features/change-bounds/point-position-updater.js.map +1 -1
- package/lib/features/change-bounds/position-snapper.d.ts +4 -0
- package/lib/features/change-bounds/position-snapper.d.ts.map +1 -1
- package/lib/features/change-bounds/position-snapper.js +4 -0
- package/lib/features/change-bounds/position-snapper.js.map +1 -1
- package/lib/features/change-bounds/snap.d.ts +6 -0
- package/lib/features/change-bounds/snap.d.ts.map +1 -1
- package/lib/features/change-bounds/snap.js +6 -0
- package/lib/features/change-bounds/snap.js.map +1 -1
- package/lib/features/change-bounds/tracker.d.ts +32 -0
- package/lib/features/change-bounds/tracker.d.ts.map +1 -0
- package/lib/features/change-bounds/tracker.js +60 -0
- package/lib/features/change-bounds/tracker.js.map +1 -0
- package/lib/features/debug/debug-bounds-decorator.d.ts +4 -1
- package/lib/features/debug/debug-bounds-decorator.d.ts.map +1 -1
- package/lib/features/debug/debug-bounds-decorator.js +14 -7
- package/lib/features/debug/debug-bounds-decorator.js.map +1 -1
- package/lib/features/element-template/mouse-tracking-element-position-listener.d.ts +9 -22
- package/lib/features/element-template/mouse-tracking-element-position-listener.d.ts.map +1 -1
- package/lib/features/element-template/mouse-tracking-element-position-listener.js +30 -46
- package/lib/features/element-template/mouse-tracking-element-position-listener.js.map +1 -1
- package/lib/features/helper-lines/helper-line-feedback.d.ts +2 -2
- package/lib/features/helper-lines/helper-line-feedback.d.ts.map +1 -1
- package/lib/features/helper-lines/helper-line-feedback.js +1 -1
- package/lib/features/helper-lines/helper-line-feedback.js.map +1 -1
- package/lib/features/helper-lines/helper-line-manager-default.d.ts +2 -1
- package/lib/features/helper-lines/helper-line-manager-default.d.ts.map +1 -1
- package/lib/features/helper-lines/helper-line-manager-default.js +23 -0
- package/lib/features/helper-lines/helper-line-manager-default.js.map +1 -1
- package/lib/features/helper-lines/helper-line-manager.d.ts +10 -2
- package/lib/features/helper-lines/helper-line-manager.d.ts.map +1 -1
- package/lib/features/routing/edge-router.d.ts +4 -0
- package/lib/features/routing/edge-router.d.ts.map +1 -1
- package/lib/features/routing/edge-router.js +37 -0
- package/lib/features/routing/edge-router.js.map +1 -1
- package/lib/features/select/select-mouse-listener.d.ts +3 -0
- package/lib/features/select/select-mouse-listener.d.ts.map +1 -1
- package/lib/features/select/select-mouse-listener.js +30 -2
- package/lib/features/select/select-mouse-listener.js.map +1 -1
- package/lib/features/tools/base-tools.d.ts +24 -15
- package/lib/features/tools/base-tools.d.ts.map +1 -1
- package/lib/features/tools/base-tools.js +0 -18
- package/lib/features/tools/base-tools.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-manager.d.ts +42 -0
- package/lib/features/tools/change-bounds/change-bounds-manager.d.ts.map +1 -0
- package/lib/features/tools/change-bounds/change-bounds-manager.js +136 -0
- package/lib/features/tools/change-bounds/change-bounds-manager.js.map +1 -0
- package/lib/features/tools/change-bounds/change-bounds-tool-feedback.d.ts +6 -0
- package/lib/features/tools/change-bounds/change-bounds-tool-feedback.d.ts.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool-feedback.js +14 -8
- package/lib/features/tools/change-bounds/change-bounds-tool-feedback.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool-module.d.ts.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool-module.js +2 -0
- package/lib/features/tools/change-bounds/change-bounds-tool-module.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.d.ts +6 -15
- package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.d.ts.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.js +24 -72
- package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool.d.ts +14 -25
- package/lib/features/tools/change-bounds/change-bounds-tool.d.ts.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool.js +63 -109
- package/lib/features/tools/change-bounds/change-bounds-tool.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tracker.d.ts +136 -0
- package/lib/features/tools/change-bounds/change-bounds-tracker.d.ts.map +1 -0
- package/lib/features/tools/change-bounds/change-bounds-tracker.js +301 -0
- package/lib/features/tools/change-bounds/change-bounds-tracker.js.map +1 -0
- package/lib/features/tools/change-bounds/index.d.ts +2 -0
- package/lib/features/tools/change-bounds/index.d.ts.map +1 -1
- package/lib/features/tools/change-bounds/index.js +2 -0
- package/lib/features/tools/change-bounds/index.js.map +1 -1
- package/lib/features/tools/change-bounds/view.d.ts.map +1 -1
- package/lib/features/tools/change-bounds/view.js +1 -16
- package/lib/features/tools/change-bounds/view.js.map +1 -1
- package/lib/features/tools/edge-edit/edge-edit-tool-feedback.d.ts +7 -9
- package/lib/features/tools/edge-edit/edge-edit-tool-feedback.d.ts.map +1 -1
- package/lib/features/tools/edge-edit/edge-edit-tool-feedback.js +27 -47
- package/lib/features/tools/edge-edit/edge-edit-tool-feedback.js.map +1 -1
- package/lib/features/tools/edge-edit/edge-edit-tool.d.ts +2 -2
- package/lib/features/tools/edge-edit/edge-edit-tool.d.ts.map +1 -1
- package/lib/features/tools/edge-edit/edge-edit-tool.js +5 -5
- package/lib/features/tools/edge-edit/edge-edit-tool.js.map +1 -1
- package/lib/features/tools/marquee-selection/marquee-mouse-tool.d.ts +1 -0
- package/lib/features/tools/marquee-selection/marquee-mouse-tool.d.ts.map +1 -1
- package/lib/features/tools/marquee-selection/marquee-mouse-tool.js +3 -0
- package/lib/features/tools/marquee-selection/marquee-mouse-tool.js.map +1 -1
- package/lib/features/tools/node-creation/node-creation-tool.d.ts +2 -4
- package/lib/features/tools/node-creation/node-creation-tool.d.ts.map +1 -1
- package/lib/features/tools/node-creation/node-creation-tool.js +8 -11
- package/lib/features/tools/node-creation/node-creation-tool.js.map +1 -1
- package/lib/utils/gmodel-util.d.ts +20 -1
- package/lib/utils/gmodel-util.d.ts.map +1 -1
- package/lib/utils/gmodel-util.js +38 -16
- package/lib/utils/gmodel-util.js.map +1 -1
- package/lib/utils/layout-utils.d.ts +1 -0
- package/lib/utils/layout-utils.d.ts.map +1 -1
- package/lib/utils/layout-utils.js +5 -1
- package/lib/utils/layout-utils.js.map +1 -1
- package/package.json +3 -3
- package/src/base/default.module.ts +4 -1
- package/src/base/feedback/css-feedback.ts +10 -2
- package/src/base/feedback/feeback-emitter.ts +6 -3
- package/src/base/index.ts +1 -0
- package/src/base/mouse-position-tracker.ts +25 -0
- package/src/features/accessibility/view-key-tools/movement-key-tool.ts +12 -7
- package/src/features/bounds/bounds-module.ts +2 -0
- package/src/features/bounds/freeform-layout.ts +16 -6
- package/src/features/bounds/glsp-hidden-bounds-updater.ts +63 -46
- package/src/features/bounds/hbox-layout.ts +18 -9
- package/src/features/bounds/index.ts +1 -0
- package/src/features/bounds/layout-data.ts +48 -0
- package/src/features/bounds/local-bounds.ts +20 -4
- package/src/features/bounds/vbox-layout.ts +18 -10
- package/src/features/change-bounds/index.ts +1 -0
- package/src/features/change-bounds/model.ts +104 -4
- package/src/features/change-bounds/movement-restrictor.ts +10 -0
- package/src/features/change-bounds/point-position-updater.spec.ts +2 -0
- package/src/features/change-bounds/point-position-updater.ts +6 -0
- package/src/features/change-bounds/position-snapper.ts +4 -0
- package/src/features/change-bounds/snap.ts +6 -0
- package/src/features/change-bounds/tracker.ts +63 -0
- package/src/features/debug/debug-bounds-decorator.tsx +17 -7
- package/src/features/element-template/mouse-tracking-element-position-listener.ts +49 -71
- package/src/features/helper-lines/helper-line-feedback.ts +2 -1
- package/src/features/helper-lines/helper-line-manager-default.ts +37 -2
- package/src/features/helper-lines/helper-line-manager.ts +11 -2
- package/src/features/routing/edge-router.ts +42 -0
- package/src/features/select/select-mouse-listener.ts +15 -1
- package/src/features/tools/base-tools.ts +31 -19
- package/src/features/tools/change-bounds/change-bounds-manager.ts +145 -0
- package/src/features/tools/change-bounds/change-bounds-tool-feedback.ts +17 -6
- package/src/features/tools/change-bounds/change-bounds-tool-module.ts +2 -0
- package/src/features/tools/change-bounds/change-bounds-tool-move-feedback.ts +31 -81
- package/src/features/tools/change-bounds/change-bounds-tool.ts +89 -148
- package/src/features/tools/change-bounds/change-bounds-tracker.ts +455 -0
- package/src/features/tools/change-bounds/index.ts +2 -0
- package/src/features/tools/change-bounds/view.tsx +2 -14
- package/src/features/tools/edge-edit/edge-edit-tool-feedback.ts +34 -52
- package/src/features/tools/edge-edit/edge-edit-tool.ts +4 -3
- package/src/features/tools/marquee-selection/marquee-mouse-tool.ts +4 -0
- package/src/features/tools/node-creation/node-creation-tool.ts +7 -7
- package/src/utils/gmodel-util.ts +41 -5
- 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 {
|
|
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
|
-
|
|
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
|
|
257
|
+
protected tracker: ChangeBoundsTracker;
|
|
259
258
|
|
|
260
259
|
constructor(
|
|
261
|
-
protected
|
|
260
|
+
protected changeBoundsManager: ChangeBoundsManager,
|
|
262
261
|
protected edgeRouterRegistry?: EdgeRouterRegistry
|
|
263
262
|
) {
|
|
264
263
|
super();
|
|
265
|
-
this.
|
|
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.
|
|
273
|
+
this.tracker.startTracking();
|
|
275
274
|
} else {
|
|
276
|
-
this.
|
|
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
|
-
|
|
282
|
+
super.mouseMove(target, event);
|
|
284
283
|
if (event.buttons === 0) {
|
|
285
284
|
return this.mouseUp(target, event);
|
|
286
|
-
}
|
|
287
|
-
|
|
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
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
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
|
-
|
|
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
|
|
331
|
-
|
|
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.
|
|
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(
|
|
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.
|
|
77
|
+
this.feedbackMovingListener = new FeedbackEdgeRouteMovingMouseListener(this.changeBoundsManager, this.edgeRouterRegistry);
|
|
77
78
|
|
|
78
79
|
this.toDisposeOnDisable.push(
|
|
79
80
|
this.edgeEditListener,
|