@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.
- 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
|
@@ -41,6 +41,13 @@ export abstract class GLSPAbstractEdgeRouter extends AbstractEdgeRouter {
|
|
|
41
41
|
const anchor = super.getTranslatedAnchor(connectable, refPoint, refContainer, edge, anchorCorrection);
|
|
42
42
|
return Point.isValid(anchor) ? anchor : refPoint;
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
override cleanupRoutingPoints(edge: GRoutableElement, routingPoints: Point[], updateHandles: boolean, addRoutingPoints: boolean): void {
|
|
46
|
+
// sometimes it might happen that the source or target has the bounds not properly set when using the feedback edge
|
|
47
|
+
if (ensureBounds(edge.source) && ensureBounds(edge.target)) {
|
|
48
|
+
super.cleanupRoutingPoints(edge, routingPoints, updateHandles, addRoutingPoints);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
@injectable()
|
|
@@ -56,6 +63,13 @@ export class GLSPPolylineEdgeRouter extends PolylineEdgeRouter {
|
|
|
56
63
|
const anchor = super.getTranslatedAnchor(connectable, refPoint, refContainer, edge, anchorCorrection);
|
|
57
64
|
return Point.isValid(anchor) ? anchor : refPoint;
|
|
58
65
|
}
|
|
66
|
+
|
|
67
|
+
override cleanupRoutingPoints(edge: GRoutableElement, routingPoints: Point[], updateHandles: boolean, addRoutingPoints: boolean): void {
|
|
68
|
+
// sometimes it might happen that the source or target has the bounds not properly set when using the feedback edge
|
|
69
|
+
if (ensureBounds(edge.source) && ensureBounds(edge.target)) {
|
|
70
|
+
super.cleanupRoutingPoints(edge, routingPoints, updateHandles, addRoutingPoints);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
59
73
|
}
|
|
60
74
|
|
|
61
75
|
@injectable()
|
|
@@ -111,6 +125,13 @@ export class GLSPManhattanEdgeRouter extends ManhattanEdgeRouter {
|
|
|
111
125
|
}
|
|
112
126
|
});
|
|
113
127
|
}
|
|
128
|
+
|
|
129
|
+
override cleanupRoutingPoints(edge: GRoutableElement, routingPoints: Point[], updateHandles: boolean, addRoutingPoints: boolean): void {
|
|
130
|
+
// sometimes it might happen that the source or target has the bounds not properly set when using the feedback edge
|
|
131
|
+
if (ensureBounds(edge.source) && ensureBounds(edge.target)) {
|
|
132
|
+
super.cleanupRoutingPoints(edge, routingPoints, updateHandles, addRoutingPoints);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
114
135
|
}
|
|
115
136
|
|
|
116
137
|
@injectable()
|
|
@@ -126,4 +147,25 @@ export class GLSPBezierEdgeRouter extends BezierEdgeRouter {
|
|
|
126
147
|
const anchor = super.getTranslatedAnchor(connectable, refPoint, refContainer, edge, anchorCorrection);
|
|
127
148
|
return Point.isValid(anchor) ? anchor : refPoint;
|
|
128
149
|
}
|
|
150
|
+
|
|
151
|
+
override cleanupRoutingPoints(edge: GRoutableElement, routingPoints: Point[], updateHandles: boolean, addRoutingPoints: boolean): void {
|
|
152
|
+
// sometimes it might happen that the source or target has the bounds not properly set when using the feedback edge
|
|
153
|
+
if (ensureBounds(edge.source) && ensureBounds(edge.target)) {
|
|
154
|
+
super.cleanupRoutingPoints(edge, routingPoints, updateHandles, addRoutingPoints);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function ensureBounds(element?: GConnectableElement): boolean {
|
|
160
|
+
if (!element) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
if (element.bounds) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
if (element.position && element.size) {
|
|
167
|
+
element.bounds = { ...element.position, ...element.size };
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
return false;
|
|
129
171
|
}
|
|
@@ -13,17 +13,23 @@
|
|
|
13
13
|
*
|
|
14
14
|
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
********************************************************************************/
|
|
16
|
-
import { Action, BringToFrontAction, GModelElement, SelectAction, SelectMouseListener } from '@eclipse-glsp/sprotty';
|
|
16
|
+
import { Action, BringToFrontAction, GModelElement, SelectAction, SelectMouseListener, TYPES } from '@eclipse-glsp/sprotty';
|
|
17
|
+
import { inject, injectable, optional } from 'inversify';
|
|
17
18
|
import { Ranked } from '../../base/ranked';
|
|
18
19
|
import { SelectableElement } from '../../utils';
|
|
20
|
+
import { SResizeHandle } from '../change-bounds';
|
|
21
|
+
import { ChangeBoundsManager } from '../tools';
|
|
19
22
|
|
|
20
23
|
/**
|
|
21
24
|
* Ranked select mouse listener that is executed before default mouse listeners when using the RankedMouseTool.
|
|
22
25
|
* This ensures that default mouse listeners are working on a model that has selection changes already applied.
|
|
23
26
|
*/
|
|
27
|
+
@injectable()
|
|
24
28
|
export class RankedSelectMouseListener extends SelectMouseListener implements Ranked {
|
|
25
29
|
rank: number = Ranked.DEFAULT_RANK - 100; /* we want to be executed before all default mouse listeners */
|
|
26
30
|
|
|
31
|
+
@inject(TYPES.IChangeBoundsManager) @optional() readonly changeBoundsManager?: ChangeBoundsManager;
|
|
32
|
+
|
|
27
33
|
protected override handleSelectTarget(
|
|
28
34
|
selectableTarget: SelectableElement,
|
|
29
35
|
deselectedElements: GModelElement[],
|
|
@@ -52,4 +58,12 @@ export class RankedSelectMouseListener extends SelectMouseListener implements Ra
|
|
|
52
58
|
result.push(SelectAction.create({ selectedElementsIDs: [], deselectedElementsIDs: deselectedElements.map(e => e.id) }));
|
|
53
59
|
return result;
|
|
54
60
|
}
|
|
61
|
+
|
|
62
|
+
protected override handleButton(target: GModelElement, event: MouseEvent): (Action | Promise<Action>)[] | undefined {
|
|
63
|
+
if (target instanceof SResizeHandle && this.changeBoundsManager?.useSymmetricResize(event)) {
|
|
64
|
+
// avoid de-selecting elements when resizing with a modifier key
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
return super.handleButton(target, event);
|
|
68
|
+
}
|
|
55
69
|
}
|
|
@@ -23,11 +23,41 @@ import { EnableToolsAction, Tool } from '../../base/tool-manager/tool';
|
|
|
23
23
|
import { GLSPKeyTool } from '../../base/view/key-tool';
|
|
24
24
|
import { GLSPMouseTool } from '../../base/view/mouse-tool';
|
|
25
25
|
|
|
26
|
+
export interface FeedbackAwareTool extends Tool {
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new feedback emitter helper object. While anything can serve as a feedback emitter,
|
|
29
|
+
* this method ensures that the emitter is stable and does not change between model updates.
|
|
30
|
+
*/
|
|
31
|
+
createFeedbackEmitter(): FeedbackEmitter;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Registers `actions` to be sent out as feedback, i.e., changes that are re-established whenever the `GModelRoot`
|
|
35
|
+
* has been set or updated.
|
|
36
|
+
*
|
|
37
|
+
* @param feedbackActions the actions to be sent out.
|
|
38
|
+
* @param feedbackEmitter the emitter sending out feedback actions (this tool by default).
|
|
39
|
+
* @param cleanupActions the actions to be sent out when the feedback is de-registered through the returned Disposable.
|
|
40
|
+
* @returns A 'Disposable' that de-registers the feedback and cleans up any pending feedback with the given `cleanupActions`.
|
|
41
|
+
* @deprecated It is recommended to create a {@link createFeedbackEmitter dedicated emitter} per feedback instead of using the tool.
|
|
42
|
+
*/
|
|
43
|
+
registerFeedback(feedbackActions: Action[], feedbackEmitter?: IFeedbackEmitter, cleanupActions?: MaybeActions): Disposable;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* De-registers all feedback from the given `feedbackEmitter` (this tool by default) and cleans up any pending feedback with the
|
|
47
|
+
* given `cleanupActions`.
|
|
48
|
+
*
|
|
49
|
+
* @param feedbackEmitter the emitter to be deregistered (this tool by default).
|
|
50
|
+
* @param cleanupActions the actions to be dispatched right after the deregistration to clean up any pending feedback.
|
|
51
|
+
* @deprecated It is recommended to create a {@link createFeedbackEmitter dedicated emitter} per feedback and dispose it like that.
|
|
52
|
+
*/
|
|
53
|
+
deregisterFeedback(feedbackEmitter?: IFeedbackEmitter, cleanupActions?: MaybeActions): void;
|
|
54
|
+
}
|
|
55
|
+
|
|
26
56
|
/**
|
|
27
57
|
* A reusable base implementation for edit {@link Tool}s.
|
|
28
58
|
*/
|
|
29
59
|
@injectable()
|
|
30
|
-
export abstract class BaseEditTool implements
|
|
60
|
+
export abstract class BaseEditTool implements FeedbackAwareTool {
|
|
31
61
|
@inject(TYPES.IFeedbackActionDispatcher) protected feedbackDispatcher: IFeedbackActionDispatcher;
|
|
32
62
|
@inject(TYPES.IActionDispatcher) protected actionDispatcher: GLSPActionDispatcher;
|
|
33
63
|
@inject(GLSPMouseTool) protected mouseTool: GLSPMouseTool;
|
|
@@ -56,28 +86,10 @@ export abstract class BaseEditTool implements Tool {
|
|
|
56
86
|
return this.feedbackDispatcher.createEmitter();
|
|
57
87
|
}
|
|
58
88
|
|
|
59
|
-
/**
|
|
60
|
-
* Registers `actions` to be sent out as feedback, i.e., changes that are re-established whenever the `GModelRoot`
|
|
61
|
-
* has been set or updated.
|
|
62
|
-
*
|
|
63
|
-
* @param feedbackActions the actions to be sent out.
|
|
64
|
-
* @param feedbackEmitter the emitter sending out feedback actions (this tool by default).
|
|
65
|
-
* @param cleanupActions the actions to be sent out when the feedback is de-registered through the returned Disposable.
|
|
66
|
-
* @returns A 'Disposable' that de-registers the feedback and cleans up any pending feedback with the given `cleanupActions`.
|
|
67
|
-
* @deprecated It is recommended to create a {@link createFeedbackEmitter dedicated emitter} per feedback instead of using the tool.
|
|
68
|
-
*/
|
|
69
89
|
registerFeedback(feedbackActions: Action[], feedbackEmitter: IFeedbackEmitter = this, cleanupActions?: MaybeActions): Disposable {
|
|
70
90
|
return this.feedbackDispatcher.registerFeedback(feedbackEmitter, feedbackActions, cleanupActions);
|
|
71
91
|
}
|
|
72
92
|
|
|
73
|
-
/**
|
|
74
|
-
* De-registers all feedback from the given `feedbackEmitter` (this tool by default) and cleans up any pending feedback with the
|
|
75
|
-
* given `cleanupActions`.
|
|
76
|
-
*
|
|
77
|
-
* @param feedbackEmitter the emitter to be deregistered (this tool by default).
|
|
78
|
-
* @param cleanupActions the actions to be dispatched right after the deregistration to clean up any pending feedback.
|
|
79
|
-
* @deprecated It is recommended to create a {@link createFeedbackEmitter dedicated emitter} per feedback and dispose it like that.
|
|
80
|
-
*/
|
|
81
93
|
deregisterFeedback(feedbackEmitter: IFeedbackEmitter = this, cleanupActions?: MaybeActions): void {
|
|
82
94
|
this.feedbackDispatcher.deregisterFeedback(feedbackEmitter, cleanupActions);
|
|
83
95
|
}
|
|
@@ -0,0 +1,145 @@
|
|
|
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
|
+
|
|
17
|
+
import {
|
|
18
|
+
Dimension,
|
|
19
|
+
GModelElement,
|
|
20
|
+
ISnapper,
|
|
21
|
+
KeyboardModifier,
|
|
22
|
+
MousePositionTracker,
|
|
23
|
+
Movement,
|
|
24
|
+
Point,
|
|
25
|
+
TYPES,
|
|
26
|
+
Vector,
|
|
27
|
+
isBoundsAware,
|
|
28
|
+
isLocateable
|
|
29
|
+
} from '@eclipse-glsp/sprotty';
|
|
30
|
+
import { inject, injectable, optional } from 'inversify';
|
|
31
|
+
import { FeedbackEmitter } from '../../../base';
|
|
32
|
+
import { isValidMove, minDimensions } from '../../../utils';
|
|
33
|
+
import { LayoutAware } from '../../bounds/layout-data';
|
|
34
|
+
import {
|
|
35
|
+
IMovementRestrictor,
|
|
36
|
+
ResizeHandleLocation,
|
|
37
|
+
movementRestrictionFeedback,
|
|
38
|
+
removeMovementRestrictionFeedback
|
|
39
|
+
} from '../../change-bounds';
|
|
40
|
+
import { IHelperLineManager } from '../../helper-lines';
|
|
41
|
+
import { ChangeBoundsTracker, TrackedElementMove } from './change-bounds-tracker';
|
|
42
|
+
|
|
43
|
+
export const CSS_RESIZE_MODE = 'resize-mode';
|
|
44
|
+
|
|
45
|
+
@injectable()
|
|
46
|
+
export class ChangeBoundsManager {
|
|
47
|
+
constructor(
|
|
48
|
+
@inject(MousePositionTracker) readonly positionTracker: MousePositionTracker,
|
|
49
|
+
@optional() @inject(TYPES.IMovementRestrictor) readonly movementRestrictor?: IMovementRestrictor,
|
|
50
|
+
@optional() @inject(TYPES.ISnapper) readonly snapper?: ISnapper,
|
|
51
|
+
@optional() @inject(TYPES.IHelperLineManager) readonly helperLineManager?: IHelperLineManager
|
|
52
|
+
) {}
|
|
53
|
+
|
|
54
|
+
unsnapModifier(): KeyboardModifier | undefined {
|
|
55
|
+
return 'shift';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
usePositionSnap(arg: MouseEvent | KeyboardEvent | any): boolean {
|
|
59
|
+
return typeof arg === 'boolean' ? arg : !(arg as MouseEvent | KeyboardEvent).shiftKey;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
snapPosition(element: GModelElement, position: Point): Point {
|
|
63
|
+
return this.snapper?.snap(position, element) ?? position;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
isValid(element: GModelElement): boolean {
|
|
67
|
+
return this.hasValidPosition(element) && this.hasValidSize(element);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
hasValidPosition(element: GModelElement, position?: Point): boolean {
|
|
71
|
+
return !isLocateable(element) || isValidMove(element, position ?? element.position, this.movementRestrictor);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
hasValidSize(element: GModelElement, size?: Dimension): boolean {
|
|
75
|
+
if (!isBoundsAware(element)) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
const dimension: Dimension = size ?? element.bounds;
|
|
79
|
+
const minimum = this.getMinimumSize(element);
|
|
80
|
+
if (dimension.width < minimum.width || dimension.height < minimum.height) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getMinimumSize(element: GModelElement): Dimension {
|
|
87
|
+
if (!isBoundsAware(element)) {
|
|
88
|
+
return Dimension.EMPTY;
|
|
89
|
+
}
|
|
90
|
+
const definedMinimum = minDimensions(element);
|
|
91
|
+
const computedMinimum = LayoutAware.getComputedDimensions(element);
|
|
92
|
+
return computedMinimum
|
|
93
|
+
? {
|
|
94
|
+
width: Math.max(definedMinimum.width, computedMinimum.width),
|
|
95
|
+
height: Math.max(definedMinimum.height, computedMinimum.height)
|
|
96
|
+
}
|
|
97
|
+
: definedMinimum;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
useMovementRestriction(arg: MouseEvent | KeyboardEvent | any): boolean {
|
|
101
|
+
return this.usePositionSnap(arg);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
restrictMovement(element: GModelElement, movement: Movement): Movement {
|
|
105
|
+
const minimumMovement = this.helperLineManager?.getMinimumMoveVector(element, true, movement.direction);
|
|
106
|
+
if (!minimumMovement) {
|
|
107
|
+
return movement;
|
|
108
|
+
}
|
|
109
|
+
// minimum is given in absolute coordinates
|
|
110
|
+
// if minimum is not reached, reset to original position for that coordinate
|
|
111
|
+
const absVector = Vector.abs(movement.vector);
|
|
112
|
+
const targetPosition: Point = {
|
|
113
|
+
x: absVector.x < minimumMovement.x ? movement.from.x : movement.to.x,
|
|
114
|
+
y: absVector.y < minimumMovement.y ? movement.from.y : movement.to.y
|
|
115
|
+
};
|
|
116
|
+
return Point.move(movement.from, targetPosition);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
addRestrictionFeedback(feedback: FeedbackEmitter, move: TrackedElementMove): FeedbackEmitter {
|
|
120
|
+
if (this.movementRestrictor) {
|
|
121
|
+
feedback.add(
|
|
122
|
+
movementRestrictionFeedback(move.element, this.movementRestrictor!, move.valid),
|
|
123
|
+
removeMovementRestrictionFeedback(move.element, this.movementRestrictor!)
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return feedback;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
defaultResizeLocations(): ResizeHandleLocation[] {
|
|
130
|
+
return [
|
|
131
|
+
ResizeHandleLocation.TopLeft,
|
|
132
|
+
ResizeHandleLocation.TopRight,
|
|
133
|
+
ResizeHandleLocation.BottomRight,
|
|
134
|
+
ResizeHandleLocation.BottomLeft
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
useSymmetricResize(arg: MouseEvent | KeyboardEvent | any): boolean {
|
|
139
|
+
return typeof arg === 'boolean' ? arg : (arg as MouseEvent | KeyboardEvent).ctrlKey;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
createTracker(): ChangeBoundsTracker {
|
|
143
|
+
return new ChangeBoundsTracker(this);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -19,12 +19,14 @@ import { inject, injectable } from 'inversify';
|
|
|
19
19
|
import { FeedbackCommand } from '../../../base/feedback/feedback-command';
|
|
20
20
|
import { OptionalAction } from '../../../base/model/glsp-model-source';
|
|
21
21
|
import { forEachElement } from '../../../utils/gmodel-util';
|
|
22
|
-
import { addResizeHandles, isResizable, removeResizeHandles } from '../../change-bounds/model';
|
|
22
|
+
import { ResizeHandleLocation, addResizeHandles, isResizable, removeResizeHandles } from '../../change-bounds/model';
|
|
23
|
+
import { ChangeBoundsManager } from './change-bounds-manager';
|
|
23
24
|
|
|
24
25
|
export interface ShowChangeBoundsToolResizeFeedbackAction extends Action {
|
|
25
26
|
kind: typeof ShowChangeBoundsToolResizeFeedbackAction.KIND;
|
|
26
27
|
|
|
27
28
|
elementId: string;
|
|
29
|
+
resizeLocations?: ResizeHandleLocation[];
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export namespace ShowChangeBoundsToolResizeFeedbackAction {
|
|
@@ -34,10 +36,16 @@ export namespace ShowChangeBoundsToolResizeFeedbackAction {
|
|
|
34
36
|
return Action.hasKind(object, KIND) && hasStringProp(object, 'elementId');
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
/** @deprecated Use the create method with the options object parameter instead and set the 'elementId' parameter. */
|
|
40
|
+
export function create(elementId: string): ShowChangeBoundsToolResizeFeedbackAction;
|
|
41
|
+
export function create(options: Omit<ShowChangeBoundsToolResizeFeedbackAction, 'kind'>): ShowChangeBoundsToolResizeFeedbackAction;
|
|
42
|
+
export function create(
|
|
43
|
+
options: Omit<ShowChangeBoundsToolResizeFeedbackAction, 'kind'> | string
|
|
44
|
+
): ShowChangeBoundsToolResizeFeedbackAction {
|
|
45
|
+
const opts = typeof options === 'string' ? { elementId: options } : options;
|
|
38
46
|
return {
|
|
39
47
|
kind: KIND,
|
|
40
|
-
|
|
48
|
+
...opts
|
|
41
49
|
};
|
|
42
50
|
}
|
|
43
51
|
}
|
|
@@ -63,15 +71,18 @@ export class ShowChangeBoundsToolResizeFeedbackCommand extends FeedbackCommand {
|
|
|
63
71
|
static readonly KIND = ShowChangeBoundsToolResizeFeedbackAction.KIND;
|
|
64
72
|
|
|
65
73
|
@inject(TYPES.Action) protected action: ShowChangeBoundsToolResizeFeedbackAction;
|
|
74
|
+
@inject(TYPES.IChangeBoundsManager) protected changeBoundsManager: ChangeBoundsManager;
|
|
66
75
|
|
|
67
76
|
execute(context: CommandExecutionContext): CommandReturn {
|
|
68
77
|
const index = context.root.index;
|
|
69
78
|
|
|
70
79
|
forEachElement(index, isResizable, element => element.id !== this.action.elementId && removeResizeHandles(element));
|
|
71
80
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
if (this.action.elementId) {
|
|
82
|
+
const resizeElement = index.getById(this.action.elementId);
|
|
83
|
+
if (resizeElement && isResizable(resizeElement)) {
|
|
84
|
+
addResizeHandles(resizeElement, this.action.resizeLocations ?? this.changeBoundsManager.defaultResizeLocations());
|
|
85
|
+
}
|
|
75
86
|
}
|
|
76
87
|
return context.root;
|
|
77
88
|
}
|
|
@@ -16,12 +16,14 @@
|
|
|
16
16
|
import { FeatureModule, TYPES, bindAsService, configureCommand, configureView } from '@eclipse-glsp/sprotty';
|
|
17
17
|
import '../../../../css/change-bounds.css';
|
|
18
18
|
import { SResizeHandle } from '../../change-bounds/model';
|
|
19
|
+
import { ChangeBoundsManager } from './change-bounds-manager';
|
|
19
20
|
import { ChangeBoundsTool } from './change-bounds-tool';
|
|
20
21
|
import { HideChangeBoundsToolResizeFeedbackCommand, ShowChangeBoundsToolResizeFeedbackCommand } from './change-bounds-tool-feedback';
|
|
21
22
|
import { SResizeHandleView } from './view';
|
|
22
23
|
|
|
23
24
|
export const changeBoundsToolModule = new FeatureModule((bind, unbind, isBound, rebind) => {
|
|
24
25
|
const context = { bind, unbind, isBound, rebind };
|
|
26
|
+
bindAsService(context, TYPES.IChangeBoundsManager, ChangeBoundsManager);
|
|
25
27
|
bindAsService(context, TYPES.IDefaultTool, ChangeBoundsTool);
|
|
26
28
|
configureCommand(context, ShowChangeBoundsToolResizeFeedbackCommand);
|
|
27
29
|
configureCommand(context, HideChangeBoundsToolResizeFeedbackCommand);
|
|
@@ -13,29 +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,
|
|
16
|
+
import { Action, ElementMove, GModelElement, GModelRoot, MoveAction, Point, findParentByFeature } from '@eclipse-glsp/sprotty';
|
|
17
17
|
|
|
18
18
|
import { DebouncedFunc, debounce } from 'lodash';
|
|
19
|
+
import { ChangeBoundsTracker, TrackedMove } from '.';
|
|
19
20
|
import { DragAwareMouseListener } from '../../../base/drag-aware-mouse-listener';
|
|
20
21
|
import { CursorCSS, cursorFeedbackAction } from '../../../base/feedback/css-feedback';
|
|
21
22
|
import { FeedbackEmitter } from '../../../base/feedback/feeback-emitter';
|
|
22
23
|
import { MoveableElement, filter, getElements, isNonRoutableSelectedMovableBoundsAware, removeDescendants } from '../../../utils';
|
|
23
|
-
import { PointPositionUpdater } from '../../change-bounds';
|
|
24
24
|
import { SResizeHandle } from '../../change-bounds/model';
|
|
25
|
-
import { createMovementRestrictionFeedback, removeMovementRestrictionFeedback } from '../../change-bounds/movement-restrictor';
|
|
26
25
|
import { ChangeBoundsTool } from './change-bounds-tool';
|
|
27
26
|
import { MoveFinishedEventAction, MoveInitializedEventAction } from './change-bounds-tool-feedback';
|
|
28
27
|
|
|
29
|
-
export interface ValidatedElementMove extends ElementMove {
|
|
30
|
-
valid: boolean;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export namespace ValidatedElementMove {
|
|
34
|
-
export function isValid(move: ElementMove): boolean {
|
|
35
|
-
return (move as ValidatedElementMove).valid ?? true;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
28
|
/**
|
|
40
29
|
* This mouse listener provides visual feedback for moving by sending client-side
|
|
41
30
|
* `MoveAction`s while elements are selected and dragged. This will also update
|
|
@@ -43,9 +32,9 @@ export namespace ValidatedElementMove {
|
|
|
43
32
|
* the visual feedback but also the basis for sending the change to the server
|
|
44
33
|
* (see also `tools/MoveTool`).
|
|
45
34
|
*/
|
|
46
|
-
export class FeedbackMoveMouseListener extends DragAwareMouseListener
|
|
35
|
+
export class FeedbackMoveMouseListener extends DragAwareMouseListener {
|
|
47
36
|
protected rootElement?: GModelRoot;
|
|
48
|
-
protected
|
|
37
|
+
protected tracker: ChangeBoundsTracker;
|
|
49
38
|
protected elementId2startPos = new Map<string, Point>();
|
|
50
39
|
|
|
51
40
|
protected pendingMoveInitialized?: DebouncedFunc<() => void>;
|
|
@@ -55,7 +44,7 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
|
|
|
55
44
|
|
|
56
45
|
constructor(protected tool: ChangeBoundsTool) {
|
|
57
46
|
super();
|
|
58
|
-
this.
|
|
47
|
+
this.tracker = tool.createChangeBoundsTracker();
|
|
59
48
|
this.moveInitializedFeedback = tool.createFeedbackEmitter();
|
|
60
49
|
this.moveFeedback = tool.createFeedbackEmitter();
|
|
61
50
|
}
|
|
@@ -66,7 +55,7 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
|
|
|
66
55
|
this.initializeMove(target, event);
|
|
67
56
|
return [];
|
|
68
57
|
}
|
|
69
|
-
this.
|
|
58
|
+
this.tracker.stopTracking();
|
|
70
59
|
return [];
|
|
71
60
|
}
|
|
72
61
|
|
|
@@ -77,10 +66,10 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
|
|
|
77
66
|
}
|
|
78
67
|
const moveable = findParentByFeature(target, this.isValidMoveable);
|
|
79
68
|
if (moveable !== undefined) {
|
|
80
|
-
this.
|
|
69
|
+
this.tracker.startTracking();
|
|
81
70
|
this.scheduleMoveInitialized();
|
|
82
71
|
} else {
|
|
83
|
-
this.
|
|
72
|
+
this.tracker.stopTracking();
|
|
84
73
|
}
|
|
85
74
|
}
|
|
86
75
|
|
|
@@ -113,7 +102,7 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
|
|
|
113
102
|
override nonDraggingMouseUp(element: GModelElement, event: MouseEvent): Action[] {
|
|
114
103
|
// should reset everything that may have happend on mouse down
|
|
115
104
|
this.moveInitializedFeedback.dispose();
|
|
116
|
-
this.
|
|
105
|
+
this.tracker.stopTracking();
|
|
117
106
|
return [];
|
|
118
107
|
}
|
|
119
108
|
|
|
@@ -121,7 +110,7 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
|
|
|
121
110
|
super.mouseMove(target, event);
|
|
122
111
|
if (event.buttons === 0) {
|
|
123
112
|
return this.mouseUp(target, event);
|
|
124
|
-
} else if (
|
|
113
|
+
} else if (this.tracker.isTracking()) {
|
|
125
114
|
return this.moveElements(target, event);
|
|
126
115
|
}
|
|
127
116
|
return [];
|
|
@@ -131,35 +120,34 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
|
|
|
131
120
|
if (this.elementId2startPos.size === 0) {
|
|
132
121
|
this.initializeElementsToMove(target.root);
|
|
133
122
|
}
|
|
134
|
-
const
|
|
135
|
-
|
|
123
|
+
const elementsToMove = this.getElementsToMove(target);
|
|
124
|
+
const move = this.tracker.moveElements(elementsToMove, { snap: event, restrict: event });
|
|
125
|
+
if (move.elementMoves.length === 0) {
|
|
136
126
|
return [];
|
|
137
127
|
}
|
|
138
128
|
// cancel any pending move
|
|
139
129
|
this.pendingMoveInitialized?.cancel();
|
|
140
|
-
this.moveFeedback.add(
|
|
141
|
-
this.addMovementFeedback(
|
|
130
|
+
this.moveFeedback.add(this.createMoveAction(move), () => this.resetElementPositions(target));
|
|
131
|
+
this.addMovementFeedback(move, target, event);
|
|
132
|
+
this.tracker.updateTrackingPosition(move);
|
|
142
133
|
this.moveFeedback.submit();
|
|
143
134
|
return [];
|
|
144
135
|
}
|
|
145
136
|
|
|
146
|
-
protected
|
|
137
|
+
protected createMoveAction(trackedMove: TrackedMove): Action {
|
|
138
|
+
// we never want to animate the move action as this interferes with the move feedback
|
|
139
|
+
return MoveAction.create(
|
|
140
|
+
trackedMove.elementMoves.map(move => ({ elementId: move.element.id, toPosition: move.toPosition })),
|
|
141
|
+
{ animate: false }
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
protected addMovementFeedback(trackedMove: TrackedMove, ctx: GModelElement, event: MouseEvent): void {
|
|
147
146
|
// cursor feedback
|
|
148
147
|
this.moveFeedback.add(cursorFeedbackAction(CursorCSS.MOVE), cursorFeedbackAction(CursorCSS.DEFAULT));
|
|
149
148
|
|
|
150
149
|
// restriction feedback
|
|
151
|
-
|
|
152
|
-
const element = ctx.root.index.getById(move.elementId);
|
|
153
|
-
if (element && this.tool.movementRestrictor) {
|
|
154
|
-
if (!ValidatedElementMove.isValid(move)) {
|
|
155
|
-
this.moveFeedback.add(createMovementRestrictionFeedback(element, this.tool.movementRestrictor), () =>
|
|
156
|
-
removeMovementRestrictionFeedback(element, this.tool.movementRestrictor!)
|
|
157
|
-
);
|
|
158
|
-
} else {
|
|
159
|
-
this.moveFeedback.add(removeMovementRestrictionFeedback(element, this.tool.movementRestrictor));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
});
|
|
150
|
+
trackedMove.elementMoves.forEach(move => this.tool.changeBoundsManager.addRestrictionFeedback(this.moveFeedback, move));
|
|
163
151
|
}
|
|
164
152
|
|
|
165
153
|
protected initializeElementsToMove(root: GModelRoot): void {
|
|
@@ -177,45 +165,6 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
|
|
|
177
165
|
return getElements(context.root.index, Array.from(this.elementId2startPos.keys()), this.isValidMoveable);
|
|
178
166
|
}
|
|
179
167
|
|
|
180
|
-
protected getElementMoves(target: GModelElement, event: MouseEvent, finished: boolean): MoveAction | undefined {
|
|
181
|
-
const delta = this.positionUpdater.updatePosition(target, event);
|
|
182
|
-
if (!delta) {
|
|
183
|
-
return undefined;
|
|
184
|
-
}
|
|
185
|
-
const elementMoves: ElementMove[] = this.getElementMovesForDelta(target, delta, finished).filter(move =>
|
|
186
|
-
this.filterElementMove(move)
|
|
187
|
-
);
|
|
188
|
-
if (elementMoves.length > 0) {
|
|
189
|
-
// we never want to animate the move action as this interferes with the move feedback
|
|
190
|
-
return MoveAction.create(elementMoves, { animate: false, finished });
|
|
191
|
-
} else {
|
|
192
|
-
return undefined;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
protected filterElementMove(elementMove: ValidatedElementMove): boolean {
|
|
197
|
-
return !!elementMove.fromPosition && !Point.equals(elementMove.fromPosition, elementMove.toPosition);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
protected getElementMovesForDelta(target: GModelElement, delta: Point, finished: boolean): ValidatedElementMove[] {
|
|
201
|
-
return this.getElementsToMove(target).flatMap<ValidatedElementMove>(element => {
|
|
202
|
-
const startPosition = this.elementId2startPos.get(element.id);
|
|
203
|
-
if (!startPosition) {
|
|
204
|
-
return [];
|
|
205
|
-
}
|
|
206
|
-
const targetPosition = Point.add(element.position, delta);
|
|
207
|
-
const valid = this.tool.movementRestrictor?.validate(element, targetPosition) ?? true;
|
|
208
|
-
return [this.createElementMove(element, targetPosition, valid, finished)];
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
protected createElementMove(element: MoveableElement, toPosition: Point, valid: boolean, finished: boolean): ValidatedElementMove {
|
|
213
|
-
// if we are finished and have an invalid move, we want to move the element back to its start position
|
|
214
|
-
return !valid && finished
|
|
215
|
-
? { elementId: element.id, fromPosition: element.position, toPosition: element.position, valid }
|
|
216
|
-
: { elementId: element.id, fromPosition: element.position, toPosition, valid };
|
|
217
|
-
}
|
|
218
|
-
|
|
219
168
|
protected resetElementPositions(context: GModelElement): MoveAction | undefined {
|
|
220
169
|
const elementMoves: ElementMove[] = this.revertElementMoves(context);
|
|
221
170
|
return MoveAction.create(elementMoves, { animate: false, finished: true });
|
|
@@ -233,12 +182,13 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
|
|
|
233
182
|
}
|
|
234
183
|
|
|
235
184
|
override draggingMouseUp(target: GModelElement, event: MouseEvent): Action[] {
|
|
236
|
-
if (this.
|
|
185
|
+
if (!this.tracker.isTracking()) {
|
|
237
186
|
return [];
|
|
238
187
|
}
|
|
239
188
|
// only reset the move of invalid elements, the others will be handled by the change bounds tool itself
|
|
240
|
-
|
|
241
|
-
|
|
189
|
+
this.getElementsToMove(target)
|
|
190
|
+
.filter(element => this.tool.changeBoundsManager.isValid(element))
|
|
191
|
+
.forEach(element => this.elementId2startPos.delete(element.id));
|
|
242
192
|
this.dispose();
|
|
243
193
|
return [];
|
|
244
194
|
}
|
|
@@ -247,7 +197,7 @@ export class FeedbackMoveMouseListener extends DragAwareMouseListener implements
|
|
|
247
197
|
this.pendingMoveInitialized?.cancel();
|
|
248
198
|
this.moveInitializedFeedback.dispose();
|
|
249
199
|
this.moveFeedback.dispose();
|
|
250
|
-
this.
|
|
200
|
+
this.tracker.dispose();
|
|
251
201
|
this.elementId2startPos.clear();
|
|
252
202
|
super.dispose();
|
|
253
203
|
}
|