@eclipse-glsp/client 0.10.0-next.e5fcffe.169 → 1.1.0-next.fe0b297.182
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/decoration.css +5 -1
- package/css/glsp-sprotty.css +39 -0
- package/css/tool-palette.css +2 -2
- package/lib/base/container-modules.d.ts.map +1 -1
- package/lib/base/container-modules.js +10 -9
- package/lib/base/container-modules.js.map +1 -1
- package/lib/base/editor-context-service.d.ts +2 -3
- package/lib/base/editor-context-service.d.ts.map +1 -1
- package/lib/base/editor-context-service.js +11 -12
- package/lib/base/editor-context-service.js.map +1 -1
- package/lib/base/model/update-model-command.d.ts +14 -7
- package/lib/base/model/update-model-command.d.ts.map +1 -1
- package/lib/base/model/update-model-command.js +31 -41
- package/lib/base/model/update-model-command.js.map +1 -1
- package/lib/base/source-uri-aware.d.ts +2 -17
- package/lib/base/source-uri-aware.d.ts.map +1 -1
- package/lib/base/source-uri-aware.js +4 -6
- package/lib/base/source-uri-aware.js.map +1 -1
- package/lib/features/change-bounds/movement-restrictor.d.ts +36 -6
- package/lib/features/change-bounds/movement-restrictor.d.ts.map +1 -1
- package/lib/features/change-bounds/movement-restrictor.js +54 -39
- package/lib/features/change-bounds/movement-restrictor.js.map +1 -1
- package/lib/features/change-bounds/snap.d.ts +20 -5
- package/lib/features/change-bounds/snap.d.ts.map +1 -1
- package/lib/features/change-bounds/snap.js +19 -8
- package/lib/features/change-bounds/snap.js.map +1 -1
- package/lib/features/context-menu/selection-service-aware-context-menu-mouse-listener.d.ts +5 -7
- package/lib/features/context-menu/selection-service-aware-context-menu-mouse-listener.d.ts.map +1 -1
- package/lib/features/context-menu/selection-service-aware-context-menu-mouse-listener.js +7 -14
- package/lib/features/context-menu/selection-service-aware-context-menu-mouse-listener.js.map +1 -1
- package/lib/features/hover/hover.d.ts +1 -2
- package/lib/features/hover/hover.d.ts.map +1 -1
- package/lib/features/hover/hover.js +2 -15
- package/lib/features/hover/hover.js.map +1 -1
- package/lib/features/layout/di.config.d.ts +2 -2
- package/lib/features/layout/di.config.d.ts.map +1 -1
- package/lib/features/layout/di.config.js +6 -5
- package/lib/features/layout/di.config.js.map +1 -1
- package/lib/features/layout/{layout-commands.d.ts → layout-elements-action.d.ts} +75 -57
- package/lib/features/layout/layout-elements-action.d.ts.map +1 -0
- package/lib/features/layout/{layout-commands.js → layout-elements-action.js} +153 -197
- package/lib/features/layout/layout-elements-action.js.map +1 -0
- package/lib/features/layout/layout-elements-action.spec.d.ts +3 -0
- package/lib/features/layout/layout-elements-action.spec.d.ts.map +1 -0
- package/lib/features/layout/{layout-commands.spec.js → layout-elements-action.spec.js} +63 -56
- package/lib/features/layout/layout-elements-action.spec.js.map +1 -0
- package/lib/features/mouse-tool/mouse-tool.d.ts +0 -1
- package/lib/features/mouse-tool/mouse-tool.d.ts.map +1 -1
- package/lib/features/mouse-tool/mouse-tool.js +9 -5
- package/lib/features/mouse-tool/mouse-tool.js.map +1 -1
- package/lib/features/select/select-mouse-listener.d.ts +3 -1
- package/lib/features/select/select-mouse-listener.d.ts.map +1 -1
- package/lib/features/select/select-mouse-listener.js +62 -0
- package/lib/features/select/select-mouse-listener.js.map +1 -1
- package/lib/features/select/selection-service.d.ts +12 -3
- package/lib/features/select/selection-service.d.ts.map +1 -1
- package/lib/features/select/selection-service.js +31 -45
- package/lib/features/select/selection-service.js.map +1 -1
- package/lib/features/select/selection-service.spec.js +1 -1
- package/lib/features/select/selection-service.spec.js.map +1 -1
- package/lib/features/source-model-watcher/di.config.d.ts +4 -0
- package/lib/features/{model-source-watcher → source-model-watcher}/di.config.d.ts.map +1 -1
- package/lib/features/{model-source-watcher → source-model-watcher}/di.config.js +4 -4
- package/lib/features/{model-source-watcher → source-model-watcher}/di.config.js.map +1 -1
- package/lib/features/{model-source-watcher/model-source-changed-action-handler.d.ts → source-model-watcher/source-model-changed-action-handler.d.ts} +9 -9
- package/lib/features/{model-source-watcher/model-source-changed-action-handler.d.ts.map → source-model-watcher/source-model-changed-action-handler.d.ts.map} +1 -1
- package/lib/features/{model-source-watcher/model-source-changed-action-handler.js → source-model-watcher/source-model-changed-action-handler.js} +19 -19
- package/lib/features/{model-source-watcher/model-source-changed-action-handler.js.map → source-model-watcher/source-model-changed-action-handler.js.map} +1 -1
- package/lib/features/tool-feedback/change-bounds-tool-feedback.js +1 -1
- package/lib/features/tool-feedback/change-bounds-tool-feedback.js.map +1 -1
- package/lib/features/tool-feedback/edge-edit-tool-feedback.d.ts +3 -2
- package/lib/features/tool-feedback/edge-edit-tool-feedback.d.ts.map +1 -1
- package/lib/features/tool-feedback/edge-edit-tool-feedback.js +13 -6
- package/lib/features/tool-feedback/edge-edit-tool-feedback.js.map +1 -1
- package/lib/features/tools/di.config.d.ts +9 -2
- package/lib/features/tools/di.config.d.ts.map +1 -1
- package/lib/features/tools/di.config.js +14 -3
- package/lib/features/tools/di.config.js.map +1 -1
- package/lib/features/tools/enable-default-tools-on-focus-loss.d.ts +26 -0
- package/lib/features/tools/enable-default-tools-on-focus-loss.d.ts.map +1 -0
- package/lib/features/tools/enable-default-tools-on-focus-loss.js +29 -0
- package/lib/features/tools/enable-default-tools-on-focus-loss.js.map +1 -0
- package/lib/features/validation/di.config.d.ts +0 -15
- package/lib/features/validation/di.config.d.ts.map +1 -1
- package/lib/features/validation/di.config.js +6 -4
- package/lib/features/validation/di.config.js.map +1 -1
- package/lib/features/validation/issue-marker.d.ts +11 -5
- package/lib/features/validation/issue-marker.d.ts.map +1 -1
- package/lib/features/validation/issue-marker.js +25 -5
- package/lib/features/validation/issue-marker.js.map +1 -1
- package/lib/features/validation/marker-navigator.d.ts +11 -17
- package/lib/features/validation/marker-navigator.d.ts.map +1 -1
- package/lib/features/validation/marker-navigator.js +32 -61
- package/lib/features/validation/marker-navigator.js.map +1 -1
- package/lib/features/validation/validate.d.ts +8 -19
- package/lib/features/validation/validate.d.ts.map +1 -1
- package/lib/features/validation/validate.js +29 -55
- package/lib/features/validation/validate.js.map +1 -1
- package/lib/index.d.ts +6 -6
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +16 -15
- package/lib/index.js.map +1 -1
- package/lib/lib/model.d.ts +1 -1
- package/lib/lib/model.d.ts.map +1 -1
- package/lib/lib/model.js +3 -3
- package/lib/lib/model.js.map +1 -1
- package/lib/model-source/glsp-diagram-server.d.ts +1 -1
- package/lib/model-source/glsp-diagram-server.d.ts.map +1 -1
- package/lib/model-source/glsp-diagram-server.js +1 -1
- package/lib/model-source/glsp-diagram-server.js.map +1 -1
- package/lib/utils/layout-utils.d.ts +4 -20
- package/lib/utils/layout-utils.d.ts.map +1 -1
- package/lib/utils/layout-utils.js +1 -1
- package/lib/utils/layout-utils.js.map +1 -1
- package/lib/views/base-view-module.d.ts.map +1 -1
- package/lib/views/base-view-module.js +3 -1
- package/lib/views/base-view-module.js.map +1 -1
- package/lib/views/glsp-projection-view.d.ts +30 -0
- package/lib/views/glsp-projection-view.d.ts.map +1 -0
- package/lib/views/glsp-projection-view.js +142 -0
- package/lib/views/glsp-projection-view.js.map +1 -0
- package/lib/views/index.d.ts +1 -0
- package/lib/views/index.d.ts.map +1 -1
- package/lib/views/index.js +1 -0
- package/lib/views/index.js.map +1 -1
- package/package.json +4 -4
- package/src/base/container-modules.ts +6 -5
- package/src/base/editor-context-service.ts +15 -7
- package/src/base/model/update-model-command.ts +48 -34
- package/src/base/source-uri-aware.ts +5 -4
- package/src/features/change-bounds/movement-restrictor.ts +73 -43
- package/src/features/change-bounds/snap.ts +15 -12
- package/src/features/context-menu/selection-service-aware-context-menu-mouse-listener.ts +19 -25
- package/src/features/hover/hover.ts +2 -24
- package/src/features/layout/di.config.ts +12 -6
- package/src/features/layout/{layout-commands.spec.ts → layout-elements-action.spec.ts} +56 -48
- package/src/features/layout/{layout-commands.ts → layout-elements-action.ts} +195 -207
- package/src/features/mouse-tool/mouse-tool.ts +8 -6
- package/src/features/select/select-mouse-listener.ts +81 -1
- package/src/features/select/selection-service.spec.ts +1 -1
- package/src/features/select/selection-service.ts +37 -50
- package/src/features/{model-source-watcher → source-model-watcher}/di.config.ts +5 -5
- package/src/features/{model-source-watcher/model-source-changed-action-handler.ts → source-model-watcher/source-model-changed-action-handler.ts} +12 -12
- package/src/features/tool-feedback/change-bounds-tool-feedback.ts +1 -1
- package/src/features/tool-feedback/edge-edit-tool-feedback.ts +14 -6
- package/src/features/tools/di.config.ts +13 -2
- package/src/features/tools/enable-default-tools-on-focus-loss.ts +33 -0
- package/src/features/validation/di.config.ts +10 -7
- package/src/features/validation/issue-marker.ts +34 -12
- package/src/features/validation/marker-navigator.ts +29 -66
- package/src/features/validation/validate.ts +36 -71
- package/src/index.ts +8 -7
- package/src/lib/model.ts +1 -1
- package/src/model-source/glsp-diagram-server.ts +1 -1
- package/src/utils/layout-utils.ts +7 -27
- package/src/views/base-view-module.ts +5 -1
- package/src/views/glsp-projection-view.tsx +166 -0
- package/src/views/index.ts +2 -0
- package/lib/features/layout/layout-commands.d.ts.map +0 -1
- package/lib/features/layout/layout-commands.js.map +0 -1
- package/lib/features/layout/layout-commands.spec.d.ts +0 -3
- package/lib/features/layout/layout-commands.spec.d.ts.map +0 -1
- package/lib/features/layout/layout-commands.spec.js.map +0 -1
- package/lib/features/model-source-watcher/di.config.d.ts +0 -4
|
@@ -13,7 +13,21 @@
|
|
|
13
13
|
*
|
|
14
14
|
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
********************************************************************************/
|
|
16
|
-
import {
|
|
16
|
+
import { Action, SelectAction } from '@eclipse-glsp/protocol';
|
|
17
|
+
import {
|
|
18
|
+
BringToFrontAction,
|
|
19
|
+
findParentByFeature,
|
|
20
|
+
isCtrlOrCmd,
|
|
21
|
+
isSelectable,
|
|
22
|
+
SButton,
|
|
23
|
+
SelectMouseListener,
|
|
24
|
+
SModelElement,
|
|
25
|
+
SModelRoot,
|
|
26
|
+
SRoutableElement,
|
|
27
|
+
SRoutingHandle,
|
|
28
|
+
SwitchEditModeAction
|
|
29
|
+
} from 'sprotty';
|
|
30
|
+
import { toArray } from 'sprotty/lib/utils/iterable';
|
|
17
31
|
import { DEFAULT_RANK, Ranked } from '../rank/model';
|
|
18
32
|
|
|
19
33
|
/**
|
|
@@ -22,4 +36,70 @@ import { DEFAULT_RANK, Ranked } from '../rank/model';
|
|
|
22
36
|
*/
|
|
23
37
|
export class RankedSelectMouseListener extends SelectMouseListener implements Ranked {
|
|
24
38
|
rank: number = DEFAULT_RANK - 1; /* we want to be executed before all default mouse listeners */
|
|
39
|
+
|
|
40
|
+
override mouseDown(target: SModelElement, event: MouseEvent): Action[] {
|
|
41
|
+
const result: Action[] = [];
|
|
42
|
+
if (this.buttonHandlerRegistry !== undefined && target instanceof SButton && target.enabled) {
|
|
43
|
+
const buttonHandler = this.buttonHandlerRegistry.get(target.type);
|
|
44
|
+
if (buttonHandler !== undefined) {
|
|
45
|
+
return buttonHandler.buttonPressed(target);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const selectableTarget = findParentByFeature(target, isSelectable);
|
|
49
|
+
if (selectableTarget !== undefined || target instanceof SModelRoot) {
|
|
50
|
+
this.hasDragged = false;
|
|
51
|
+
let deselect: SModelElement[] = [];
|
|
52
|
+
// multi-selection?
|
|
53
|
+
if (!isCtrlOrCmd(event)) {
|
|
54
|
+
deselect = toArray(
|
|
55
|
+
target.root.index
|
|
56
|
+
.all()
|
|
57
|
+
.filter(
|
|
58
|
+
element =>
|
|
59
|
+
isSelectable(element) &&
|
|
60
|
+
element.selected &&
|
|
61
|
+
!(selectableTarget instanceof SRoutingHandle && element === (selectableTarget.parent as SModelElement))
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (selectableTarget !== undefined) {
|
|
66
|
+
if (!selectableTarget.selected) {
|
|
67
|
+
this.wasSelected = false;
|
|
68
|
+
result.push(
|
|
69
|
+
SelectAction.create({
|
|
70
|
+
selectedElementsIDs: [selectableTarget.id],
|
|
71
|
+
deselectedElementsIDs: deselect.map(e => e.id)
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
result.push(BringToFrontAction.create([selectableTarget.id]));
|
|
75
|
+
const routableDeselect = deselect.filter(e => e instanceof SRoutableElement).map(e => e.id);
|
|
76
|
+
if (selectableTarget instanceof SRoutableElement) {
|
|
77
|
+
result.push(
|
|
78
|
+
SwitchEditModeAction.create({
|
|
79
|
+
elementsToActivate: [selectableTarget.id],
|
|
80
|
+
elementsToDeactivate: routableDeselect
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
} else if (routableDeselect.length > 0) {
|
|
84
|
+
result.push(SwitchEditModeAction.create({ elementsToDeactivate: routableDeselect }));
|
|
85
|
+
}
|
|
86
|
+
} else if (isCtrlOrCmd(event)) {
|
|
87
|
+
this.wasSelected = false;
|
|
88
|
+
result.push(SelectAction.create({ deselectedElementsIDs: [selectableTarget.id] }));
|
|
89
|
+
if (selectableTarget instanceof SRoutableElement) {
|
|
90
|
+
result.push(SwitchEditModeAction.create({ elementsToDeactivate: [selectableTarget.id] }));
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
this.wasSelected = true;
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
result.push(SelectAction.create({ deselectedElementsIDs: deselect.map(e => e.id) }));
|
|
97
|
+
const routableDeselect = deselect.filter(e => e instanceof SRoutableElement).map(e => e.id);
|
|
98
|
+
if (routableDeselect.length > 0) {
|
|
99
|
+
result.push(SwitchEditModeAction.create({ elementsToDeactivate: routableDeselect }));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
25
105
|
}
|
|
@@ -347,7 +347,7 @@ describe('SelectionService', () => {
|
|
|
347
347
|
expect(selectionService.hasSelectedElements()).to.equal(expectedSelection.length > 0);
|
|
348
348
|
expect(selectionService.getSelectedElementIDs()).to.have.lengthOf(expectedSelection.length);
|
|
349
349
|
if (expectedSelection.length > 0) {
|
|
350
|
-
expect(selectionService.getSelectedElementIDs()).to.have.
|
|
350
|
+
expect(selectionService.getSelectedElementIDs()).to.have.ordered.members(expectedSelection);
|
|
351
351
|
}
|
|
352
352
|
}
|
|
353
353
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*
|
|
14
14
|
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
********************************************************************************/
|
|
16
|
-
import { Action, distinctAdd, remove, SelectAction, SelectAllAction } from '@eclipse-glsp/protocol';
|
|
16
|
+
import { Action, distinctAdd, pluck, remove, SelectAction, SelectAllAction } from '@eclipse-glsp/protocol';
|
|
17
17
|
import { inject, injectable, multiInject, optional } from 'inversify';
|
|
18
18
|
import {
|
|
19
19
|
Command,
|
|
@@ -25,12 +25,11 @@ import {
|
|
|
25
25
|
SelectAllCommand as SprottySelectAllCommand,
|
|
26
26
|
SelectCommand as SprottySelectCommand,
|
|
27
27
|
SModelElement,
|
|
28
|
-
SModelRoot
|
|
29
|
-
SParentElement
|
|
28
|
+
SModelRoot
|
|
30
29
|
} from 'sprotty';
|
|
31
30
|
import { SModelRootListener } from '../../base/model/update-model-command';
|
|
32
31
|
import { TYPES } from '../../base/types';
|
|
33
|
-
import { getElements } from '../../utils/smodel-util';
|
|
32
|
+
import { getElements, getMatchingElements } from '../../utils/smodel-util';
|
|
34
33
|
import { IFeedbackActionDispatcher } from '../tool-feedback/feedback-action-dispatcher';
|
|
35
34
|
import { SelectFeedbackAction } from './select-feedback-action';
|
|
36
35
|
|
|
@@ -135,8 +134,8 @@ export class SelectionService implements SModelRootListener {
|
|
|
135
134
|
* QUERY METHODS
|
|
136
135
|
*/
|
|
137
136
|
|
|
138
|
-
getSelectedElementIDs():
|
|
139
|
-
return this.selectedElementIDs;
|
|
137
|
+
getSelectedElementIDs(): string[] {
|
|
138
|
+
return [...this.selectedElementIDs];
|
|
140
139
|
}
|
|
141
140
|
|
|
142
141
|
hasSelectedElements(): boolean {
|
|
@@ -152,6 +151,11 @@ export class SelectionService implements SModelRootListener {
|
|
|
152
151
|
}
|
|
153
152
|
}
|
|
154
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Handles a {@link SelectAction} and propagates the new selection to the {@link SelectionService}.
|
|
156
|
+
* Other tools might be selection-sensitive which means {@link SelectAction}s must be processed as fast as possible.
|
|
157
|
+
* Handling the action with a command ensures that the action is processed before the next render tick.
|
|
158
|
+
*/
|
|
155
159
|
@injectable()
|
|
156
160
|
export class SelectCommand extends Command {
|
|
157
161
|
static readonly KIND = SprottySelectCommand.KIND;
|
|
@@ -168,36 +172,30 @@ export class SelectCommand extends Command {
|
|
|
168
172
|
|
|
169
173
|
execute(context: CommandExecutionContext): SModelRoot {
|
|
170
174
|
const model = context.root;
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
this.action.deselectedElementsIDs.forEach(id => {
|
|
178
|
-
const element = model.index.getById(id);
|
|
179
|
-
if (element instanceof SChildElement && isSelectable(element)) {
|
|
180
|
-
this.deselected.push(element);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
return this.redo(context);
|
|
175
|
+
const selectionGuard = (element: any): element is SModelElement => element instanceof SChildElement && isSelectable(element);
|
|
176
|
+
const selectedElements = getElements(model.index, this.action.selectedElementsIDs, selectionGuard);
|
|
177
|
+
const deselectedElements = getElements(model.index, this.action.deselectedElementsIDs, selectionGuard);
|
|
178
|
+
|
|
179
|
+
this.selectionService.updateSelection(model, pluck(selectedElements, 'id'), pluck(deselectedElements, 'id'));
|
|
180
|
+
return model;
|
|
184
181
|
}
|
|
185
182
|
|
|
183
|
+
// Basically no-op since client-side undo is not supported in GLSP.
|
|
186
184
|
undo(context: CommandExecutionContext): SModelRoot {
|
|
187
|
-
const select = this.deselected.map(element => element.id);
|
|
188
|
-
const deselect = this.selected.map(element => element.id);
|
|
189
|
-
this.selectionService.updateSelection(context.root, select, deselect);
|
|
190
185
|
return context.root;
|
|
191
186
|
}
|
|
192
187
|
|
|
188
|
+
// Basically no-op since client-side redo is not supported in GLSP.
|
|
193
189
|
redo(context: CommandExecutionContext): SModelRoot {
|
|
194
|
-
const select = this.selected.map(element => element.id);
|
|
195
|
-
const deselect = this.deselected.map(element => element.id);
|
|
196
|
-
this.selectionService.updateSelection(context.root, select, deselect);
|
|
197
190
|
return context.root;
|
|
198
191
|
}
|
|
199
192
|
}
|
|
200
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Handles a {@link SelectAllAction} and propagates the new selection to the {@link SelectionService}.
|
|
196
|
+
* Other tools might be selection-sensitive which means {@link SelectionAllAction}s must be processed as fast as possible.
|
|
197
|
+
* Handling the action with a command ensures that the action is processed before the next render tick.
|
|
198
|
+
*/
|
|
201
199
|
@injectable()
|
|
202
200
|
export class SelectAllCommand extends Command {
|
|
203
201
|
static readonly KIND = SprottySelectAllCommand.KIND;
|
|
@@ -211,38 +209,27 @@ export class SelectAllCommand extends Command {
|
|
|
211
209
|
}
|
|
212
210
|
|
|
213
211
|
execute(context: CommandExecutionContext): SModelRoot {
|
|
214
|
-
|
|
212
|
+
const model = context.root;
|
|
213
|
+
const selectionGuard = (element: any): element is SModelElement => element instanceof SChildElement && isSelectable(element);
|
|
214
|
+
|
|
215
|
+
const selectables = getMatchingElements(model.index, selectionGuard);
|
|
216
|
+
const selectableIds = pluck(selectables, 'id');
|
|
217
|
+
if (this.action.select) {
|
|
218
|
+
this.selectionService.updateSelection(model, selectableIds, []);
|
|
219
|
+
} else {
|
|
220
|
+
this.selectionService.updateSelection(model, [], selectableIds);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return model;
|
|
215
224
|
}
|
|
216
225
|
|
|
226
|
+
// Basically no-op since client-side undo is not supported in GLSP.
|
|
217
227
|
undo(context: CommandExecutionContext): SModelRoot {
|
|
218
|
-
const index = context.root.index;
|
|
219
|
-
for (const previousState of this.previousSelection) {
|
|
220
|
-
const element = index.getById(previousState[0]);
|
|
221
|
-
if (element !== undefined && isSelectable(element)) {
|
|
222
|
-
element.selected = previousState[1];
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
228
|
return context.root;
|
|
226
229
|
}
|
|
227
230
|
|
|
231
|
+
// Basically no-op since client-side redo is not supported in GLSP.
|
|
228
232
|
redo(context: CommandExecutionContext): SModelRoot {
|
|
229
|
-
const selectables: string[] = [];
|
|
230
|
-
this.selectAll(context.root, this.action.select, selectables);
|
|
231
|
-
if (this.action.select) {
|
|
232
|
-
this.selectionService.updateSelection(context.root, selectables, []);
|
|
233
|
-
} else {
|
|
234
|
-
this.selectionService.updateSelection(context.root, [], selectables);
|
|
235
|
-
}
|
|
236
233
|
return context.root;
|
|
237
234
|
}
|
|
238
|
-
|
|
239
|
-
protected selectAll(element: SParentElement, newState: boolean, selected: string[]): void {
|
|
240
|
-
if (isSelectable(element)) {
|
|
241
|
-
this.previousSelection.set(element.id, element.selected);
|
|
242
|
-
selected.push(element.id);
|
|
243
|
-
}
|
|
244
|
-
for (const child of element.children) {
|
|
245
|
-
this.selectAll(child, newState, selected);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
235
|
}
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
*
|
|
14
14
|
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
********************************************************************************/
|
|
16
|
-
import {
|
|
16
|
+
import { SourceModelChangedAction } from '@eclipse-glsp/protocol';
|
|
17
17
|
import { ContainerModule } from 'inversify';
|
|
18
18
|
import { configureActionHandler } from 'sprotty';
|
|
19
|
-
import {
|
|
19
|
+
import { SourceModelChangedActionHandler } from './source-model-changed-action-handler';
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
configureActionHandler({ bind, isBound },
|
|
21
|
+
const sourceModelWatcherModule = new ContainerModule((bind, _unbind, isBound) => {
|
|
22
|
+
configureActionHandler({ bind, isBound }, SourceModelChangedAction.KIND, SourceModelChangedActionHandler);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
export default
|
|
25
|
+
export default sourceModelWatcherModule;
|
|
@@ -13,43 +13,43 @@
|
|
|
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, ServerMessageAction, ServerStatusAction, SourceModelChangedAction } from '@eclipse-glsp/protocol';
|
|
17
17
|
import { inject, injectable, optional } from 'inversify';
|
|
18
18
|
import { IActionDispatcher, IActionHandler, ViewerOptions } from 'sprotty';
|
|
19
19
|
import { TYPES } from '../../base/types';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* An external handler of the model
|
|
22
|
+
* An external handler of the source model change event.
|
|
23
23
|
*
|
|
24
24
|
* This allows external applications to react specifically to this event, e.g. by bringing up the diagram,
|
|
25
25
|
* check their dirty state, show a dialog, etc.
|
|
26
26
|
*/
|
|
27
27
|
@injectable()
|
|
28
|
-
export abstract class
|
|
28
|
+
export abstract class ExternalSourceModelChangedHandler {
|
|
29
29
|
/**
|
|
30
|
-
* Notifies about a change of the model
|
|
30
|
+
* Notifies about a change of the source model.
|
|
31
31
|
* @returns actions to be dispatched after the notification.
|
|
32
32
|
*/
|
|
33
|
-
abstract
|
|
33
|
+
abstract notifySourceModelChange(sourceModelName: string, options: ViewerOptions): Promise<Action[]>;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
@injectable()
|
|
37
|
-
export class
|
|
37
|
+
export class SourceModelChangedActionHandler implements IActionHandler {
|
|
38
38
|
@inject(TYPES.IActionDispatcher)
|
|
39
39
|
protected dispatcher: IActionDispatcher;
|
|
40
40
|
|
|
41
41
|
@inject(TYPES.ViewerOptions)
|
|
42
42
|
protected options: ViewerOptions;
|
|
43
43
|
|
|
44
|
-
@inject(
|
|
44
|
+
@inject(ExternalSourceModelChangedHandler)
|
|
45
45
|
@optional()
|
|
46
|
-
protected externalModelSourceChangedHandler?:
|
|
46
|
+
protected externalModelSourceChangedHandler?: ExternalSourceModelChangedHandler;
|
|
47
47
|
|
|
48
48
|
handle(action: Action): void {
|
|
49
|
-
if (
|
|
49
|
+
if (SourceModelChangedAction.is(action)) {
|
|
50
50
|
if (this.externalModelSourceChangedHandler) {
|
|
51
51
|
this.externalModelSourceChangedHandler
|
|
52
|
-
.
|
|
52
|
+
.notifySourceModelChange(action.sourceModelName, this.options)
|
|
53
53
|
.then(actions => this.dispatcher.dispatchAll(actions));
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
@@ -57,8 +57,8 @@ export class ModelSourceChangedActionHandler implements IActionHandler {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
protected showSimpleNotification(action:
|
|
61
|
-
const message = `The model
|
|
60
|
+
protected showSimpleNotification(action: SourceModelChangedAction): void {
|
|
61
|
+
const message = `The source model ${action.sourceModelName} has changed. You might want to consider reloading.`;
|
|
62
62
|
const timeout = 0;
|
|
63
63
|
const severity = 'WARNING';
|
|
64
64
|
this.dispatcher.dispatchAll([
|
|
@@ -224,7 +224,7 @@ export class FeedbackMoveMouseListener extends MouseListener {
|
|
|
224
224
|
protected validateMove(startPostion: Point, toPosition: Point, element: SModelElement, isFinished: boolean): Point {
|
|
225
225
|
let newPosition = toPosition;
|
|
226
226
|
if (this.tool.movementRestrictor) {
|
|
227
|
-
const valid = this.tool.movementRestrictor.validate(
|
|
227
|
+
const valid = this.tool.movementRestrictor.validate(element, toPosition);
|
|
228
228
|
let action;
|
|
229
229
|
if (!valid) {
|
|
230
230
|
action = createMovementRestrictionFeedback(element, this.tool.movementRestrictor);
|
|
@@ -265,20 +265,20 @@ export class FeedbackEdgeRouteMovingMouseListener extends MouseListener {
|
|
|
265
265
|
}
|
|
266
266
|
const positionUpdate = this.pointPositionUpdater.updatePosition(target, { x: event.pageX, y: event.pageY }, !event.altKey);
|
|
267
267
|
if (positionUpdate) {
|
|
268
|
-
const moveActions = this.handleMoveOnClient(target, positionUpdate);
|
|
268
|
+
const moveActions = this.handleMoveOnClient(target, positionUpdate, !event.altKey);
|
|
269
269
|
result.push(...moveActions);
|
|
270
270
|
}
|
|
271
271
|
return result;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
-
protected handleMoveOnClient(target: SModelElement, positionUpdate: Point): Action[] {
|
|
274
|
+
protected handleMoveOnClient(target: SModelElement, positionUpdate: Point, isSnap: boolean): Action[] {
|
|
275
275
|
const handleMoves: ElementMove[] = [];
|
|
276
276
|
target.root.index
|
|
277
277
|
.all()
|
|
278
278
|
.filter(element => isSelected(element))
|
|
279
279
|
.forEach(element => {
|
|
280
280
|
if (isRoutingHandle(element)) {
|
|
281
|
-
const elementMove = this.toElementMove(element, positionUpdate);
|
|
281
|
+
const elementMove = this.toElementMove(element, positionUpdate, isSnap);
|
|
282
282
|
if (elementMove) {
|
|
283
283
|
handleMoves.push(elementMove);
|
|
284
284
|
}
|
|
@@ -290,21 +290,29 @@ export class FeedbackEdgeRouteMovingMouseListener extends MouseListener {
|
|
|
290
290
|
return [];
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
protected toElementMove(element: SRoutingHandle, positionDelta: Point): ElementMove | undefined {
|
|
293
|
+
protected toElementMove(element: SRoutingHandle, positionDelta: Point, isSnap: boolean): ElementMove | undefined {
|
|
294
294
|
const point = this.getHandlePosition(element);
|
|
295
295
|
if (point !== undefined) {
|
|
296
|
+
const snappedPoint = this.getSnappedHandlePosition(element, point, isSnap);
|
|
296
297
|
return {
|
|
297
298
|
elementId: element.id,
|
|
298
299
|
fromPosition: point,
|
|
299
300
|
toPosition: {
|
|
300
|
-
x:
|
|
301
|
-
y:
|
|
301
|
+
x: snappedPoint.x + positionDelta.x,
|
|
302
|
+
y: snappedPoint.y + positionDelta.y
|
|
302
303
|
}
|
|
303
304
|
};
|
|
304
305
|
}
|
|
305
306
|
return undefined;
|
|
306
307
|
}
|
|
307
308
|
|
|
309
|
+
protected getSnappedHandlePosition(element: SRoutingHandle, point: Point, isSnap: boolean): Point {
|
|
310
|
+
if (this.snapper && isSnap) {
|
|
311
|
+
return this.snapper.snap(point, element);
|
|
312
|
+
}
|
|
313
|
+
return point;
|
|
314
|
+
}
|
|
315
|
+
|
|
308
316
|
protected getHandlePosition(handle: SRoutingHandle): Point | undefined {
|
|
309
317
|
if (this.edgeRouterRegistry) {
|
|
310
318
|
const parent = handle.parent;
|
|
@@ -16,19 +16,25 @@
|
|
|
16
16
|
import { TriggerEdgeCreationAction, TriggerNodeCreationAction } from '@eclipse-glsp/protocol';
|
|
17
17
|
import { ContainerModule, interfaces } from 'inversify';
|
|
18
18
|
import { configureActionHandler, configureModelElement } from 'sprotty';
|
|
19
|
+
import { FocusStateChangedAction } from '../../base/actions/focus-change-action';
|
|
19
20
|
import { TYPES } from '../../base/types';
|
|
20
21
|
import { MARQUEE } from '../tool-feedback/marquee-tool-feedback';
|
|
21
22
|
import { ChangeBoundsTool } from './change-bounds-tool';
|
|
22
23
|
import { DelKeyDeleteTool, MouseDeleteTool } from './delete-tool';
|
|
23
24
|
import { EdgeCreationTool } from './edge-creation-tool';
|
|
24
25
|
import { EdgeEditTool } from './edge-edit-tool';
|
|
26
|
+
import { EnableDefaultToolsOnFocusLossHandler } from './enable-default-tools-on-focus-loss';
|
|
25
27
|
import { MarqueeMouseTool } from './marquee-mouse-tool';
|
|
26
28
|
import { MarqueeTool } from './marquee-tool';
|
|
27
29
|
import { MarqueeNode } from './model';
|
|
28
30
|
import { NodeCreationTool } from './node-creation-tool';
|
|
29
31
|
import { MarqueeView } from './view';
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Registers the default tools of GLSP (node and edge creation, changing bounds, edge editing, deletion)
|
|
35
|
+
* and adds the marquee selection tool.
|
|
36
|
+
*/
|
|
37
|
+
export const toolsModule = new ContainerModule((bind, _unbind, isBound) => {
|
|
32
38
|
// Register default tools
|
|
33
39
|
bind(TYPES.IDefaultTool).to(ChangeBoundsTool);
|
|
34
40
|
bind(TYPES.IDefaultTool).to(EdgeEditTool);
|
|
@@ -52,4 +58,9 @@ export function configureMarqueeTool(context: { bind: interfaces.Bind; isBound:
|
|
|
52
58
|
context.bind(TYPES.ITool).to(MarqueeMouseTool);
|
|
53
59
|
}
|
|
54
60
|
|
|
55
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Enables the default tools in the tool manager if the diagram looses focus.
|
|
63
|
+
*/
|
|
64
|
+
export const enableDefaultToolsOnFocusLossModule = new ContainerModule((bind, _unbind, isBound) => {
|
|
65
|
+
configureActionHandler({ bind, isBound }, FocusStateChangedAction.KIND, EnableDefaultToolsOnFocusLossHandler);
|
|
66
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2022 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
|
+
import { Action } from '@eclipse-glsp/protocol';
|
|
17
|
+
import { injectable } from 'inversify';
|
|
18
|
+
import { EnableDefaultToolsAction, IActionHandler, ICommand } from 'sprotty';
|
|
19
|
+
import { FocusStateChangedAction } from '../../base/actions/focus-change-action';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Action handler that enables the default tools when the diagram lost focus.
|
|
23
|
+
* @see FocusTracker
|
|
24
|
+
* @see FocusStateChangedAction
|
|
25
|
+
*/
|
|
26
|
+
@injectable()
|
|
27
|
+
export class EnableDefaultToolsOnFocusLossHandler implements IActionHandler {
|
|
28
|
+
handle(action: Action): void | Action | ICommand {
|
|
29
|
+
if (FocusStateChangedAction.is(action) && !action.hasFocus) {
|
|
30
|
+
return EnableDefaultToolsAction.create();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -13,30 +13,33 @@
|
|
|
13
13
|
*
|
|
14
14
|
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
********************************************************************************/
|
|
16
|
+
import { SetMarkersAction } from '@eclipse-glsp/protocol';
|
|
16
17
|
import { ContainerModule } from 'inversify';
|
|
17
|
-
import { configureCommand } from 'sprotty';
|
|
18
|
+
import { configureActionHandler, configureCommand } from 'sprotty';
|
|
18
19
|
import { TYPES } from '../../base/types';
|
|
19
20
|
import {
|
|
20
21
|
LeftToRightTopToBottomComparator,
|
|
21
22
|
MarkerNavigator,
|
|
22
23
|
MarkerNavigatorContextMenuItemProvider,
|
|
23
24
|
MarkerNavigatorKeyListener,
|
|
24
|
-
|
|
25
|
+
NavigateToMarkerAction,
|
|
26
|
+
NavigateToMarkerActionHandler,
|
|
25
27
|
SModelElementComparator
|
|
26
28
|
} from './marker-navigator';
|
|
27
|
-
import { ApplyMarkersCommand, DeleteMarkersCommand,
|
|
29
|
+
import { ApplyMarkersCommand, DeleteMarkersCommand, SetMarkersActionHandler, ValidationFeedbackEmitter } from './validate';
|
|
28
30
|
|
|
29
31
|
export const validationModule = new ContainerModule((bind, _unbind, isBound) => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
configureCommand(
|
|
32
|
+
const context = { bind, isBound };
|
|
33
|
+
configureActionHandler(context, SetMarkersAction.KIND, SetMarkersActionHandler);
|
|
34
|
+
configureCommand(context, ApplyMarkersCommand);
|
|
35
|
+
configureCommand(context, DeleteMarkersCommand);
|
|
33
36
|
bind(ValidationFeedbackEmitter).toSelf().inSingletonScope();
|
|
34
37
|
});
|
|
35
38
|
|
|
36
39
|
export const markerNavigatorModule = new ContainerModule((bind, _unbind, isBound) => {
|
|
37
40
|
bind(SModelElementComparator).to(LeftToRightTopToBottomComparator).inSingletonScope();
|
|
38
41
|
bind(MarkerNavigator).toSelf().inSingletonScope();
|
|
39
|
-
|
|
42
|
+
configureActionHandler({ bind, isBound }, NavigateToMarkerAction.KIND, NavigateToMarkerActionHandler);
|
|
40
43
|
});
|
|
41
44
|
|
|
42
45
|
/**
|
|
@@ -13,14 +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 { Marker, MarkerKind } from '@eclipse-glsp/protocol';
|
|
17
|
-
import { SDecoration, SIssue, SIssueMarker, SParentElement } from 'sprotty';
|
|
16
|
+
import { Bounds, Marker, MarkerKind } from '@eclipse-glsp/protocol';
|
|
17
|
+
import { isBoundsAware, Projectable, SDecoration, SIssue, SIssueMarker, SIssueSeverity, SParentElement } from 'sprotty';
|
|
18
18
|
|
|
19
|
-
export class GIssueMarker extends SIssueMarker {
|
|
19
|
+
export class GIssueMarker extends SIssueMarker implements Projectable {
|
|
20
20
|
constructor() {
|
|
21
21
|
super();
|
|
22
22
|
this.features = new Set<symbol>(SDecoration.DEFAULT_FEATURES);
|
|
23
23
|
}
|
|
24
|
+
projectionCssClasses: string[];
|
|
25
|
+
projectedBounds?: Bounds;
|
|
26
|
+
override issues: SIssue[] = [];
|
|
27
|
+
override type = 'marker';
|
|
28
|
+
|
|
29
|
+
computeProjectionCssClasses(): void {
|
|
30
|
+
const severityCss = getSeverity(this);
|
|
31
|
+
this.projectionCssClasses = ['sprotty-issue', 'sprotty-' + severityCss];
|
|
32
|
+
}
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
/**
|
|
@@ -31,14 +40,15 @@ export class GIssueMarker extends SIssueMarker {
|
|
|
31
40
|
* @returns the child `SIssueMarker` or a new `SIssueMarker` if no such child exists.
|
|
32
41
|
*/
|
|
33
42
|
export function getOrCreateSIssueMarker(modelElement: SParentElement): SIssueMarker {
|
|
34
|
-
let issueMarker:
|
|
43
|
+
let issueMarker: GIssueMarker | undefined;
|
|
35
44
|
|
|
36
45
|
issueMarker = getSIssueMarker(modelElement);
|
|
37
46
|
|
|
38
47
|
if (issueMarker === undefined) {
|
|
39
48
|
issueMarker = new GIssueMarker();
|
|
40
|
-
|
|
41
|
-
|
|
49
|
+
if (isBoundsAware(modelElement)) {
|
|
50
|
+
issueMarker.projectedBounds = modelElement.parentToLocal(modelElement.bounds);
|
|
51
|
+
}
|
|
42
52
|
modelElement.add(issueMarker);
|
|
43
53
|
}
|
|
44
54
|
|
|
@@ -51,11 +61,11 @@ export function getOrCreateSIssueMarker(modelElement: SParentElement): SIssueMar
|
|
|
51
61
|
* @param modelElement for which the `SIssueMarker` should be retrieved.
|
|
52
62
|
* @returns the child `SIssueMarker` or `undefined` if no such child exists.
|
|
53
63
|
*/
|
|
54
|
-
export function getSIssueMarker(modelElement: SParentElement):
|
|
55
|
-
let issueMarker:
|
|
64
|
+
export function getSIssueMarker(modelElement: SParentElement): GIssueMarker | undefined {
|
|
65
|
+
let issueMarker: GIssueMarker | undefined;
|
|
56
66
|
|
|
57
67
|
for (const child of modelElement.children) {
|
|
58
|
-
if (child instanceof
|
|
68
|
+
if (child instanceof GIssueMarker) {
|
|
59
69
|
issueMarker = child;
|
|
60
70
|
}
|
|
61
71
|
}
|
|
@@ -69,8 +79,8 @@ export function getSIssueMarker(modelElement: SParentElement): SIssueMarker | un
|
|
|
69
79
|
* @param marker `Marker` for that an `SIssue` should be created.
|
|
70
80
|
* @returns the created `SIssue`.
|
|
71
81
|
*/
|
|
72
|
-
export function createSIssue(marker: Marker): SIssue {
|
|
73
|
-
const issue
|
|
82
|
+
export function createSIssue(marker: Marker, parent?: SParentElement): SIssue {
|
|
83
|
+
const issue = new SIssue();
|
|
74
84
|
issue.message = marker.description;
|
|
75
85
|
|
|
76
86
|
switch (marker.kind) {
|
|
@@ -87,6 +97,18 @@ export function createSIssue(marker: Marker): SIssue {
|
|
|
87
97
|
break;
|
|
88
98
|
}
|
|
89
99
|
}
|
|
90
|
-
|
|
91
100
|
return issue;
|
|
92
101
|
}
|
|
102
|
+
|
|
103
|
+
export function getSeverity(marker: SIssueMarker): SIssueSeverity {
|
|
104
|
+
let currentSeverity: SIssueSeverity = 'info';
|
|
105
|
+
for (const severity of marker.issues.map(s => s.severity)) {
|
|
106
|
+
if (severity === 'error') {
|
|
107
|
+
return severity;
|
|
108
|
+
}
|
|
109
|
+
if (severity === 'warning' && currentSeverity === 'info') {
|
|
110
|
+
currentSeverity = severity;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return currentSeverity;
|
|
114
|
+
}
|