@eclipse-glsp/client 2.1.0-next.295 → 2.1.0-next.297
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/ghost-element.css +25 -0
- package/css/glsp-sprotty.css +5 -0
- package/lib/base/args-feature.d.ts +2 -1
- package/lib/base/args-feature.d.ts.map +1 -1
- package/lib/base/args-feature.js +12 -2
- package/lib/base/args-feature.js.map +1 -1
- package/lib/base/command-stack.d.ts +22 -3
- package/lib/base/command-stack.d.ts.map +1 -1
- package/lib/base/command-stack.js +2 -2
- package/lib/base/command-stack.js.map +1 -1
- package/lib/base/default.module.d.ts +1 -1
- package/lib/base/default.module.d.ts.map +1 -1
- package/lib/base/default.module.js +2 -2
- package/lib/base/default.module.js.map +1 -1
- package/lib/base/feedback/css-feedback.d.ts +17 -0
- package/lib/base/feedback/css-feedback.d.ts.map +1 -1
- package/lib/base/feedback/css-feedback.js +4 -2
- package/lib/base/feedback/css-feedback.js.map +1 -1
- package/lib/base/selection-service.d.ts +18 -3
- package/lib/base/selection-service.d.ts.map +1 -1
- package/lib/base/selection-service.js +1 -1
- package/lib/base/selection-service.js.map +1 -1
- package/lib/default-modules.d.ts +1 -1
- package/lib/default-modules.d.ts.map +1 -1
- package/lib/default-modules.js +2 -0
- package/lib/default-modules.js.map +1 -1
- package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette-module.d.ts.map +1 -1
- package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette-module.js +4 -2
- package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette-module.js.map +1 -1
- package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.d.ts +16 -1
- package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.d.ts.map +1 -1
- package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.js +9 -10
- package/lib/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.js.map +1 -1
- package/lib/features/bounds/bounds-module.d.ts.map +1 -1
- package/lib/features/bounds/bounds-module.js +4 -0
- package/lib/features/bounds/bounds-module.js.map +1 -1
- package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts +2 -2
- package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts.map +1 -1
- package/lib/features/bounds/glsp-hidden-bounds-updater.js +7 -3
- package/lib/features/bounds/glsp-hidden-bounds-updater.js.map +1 -1
- package/lib/features/bounds/local-bounds.d.ts +34 -0
- package/lib/features/bounds/local-bounds.d.ts.map +1 -0
- package/lib/features/bounds/local-bounds.js +99 -0
- package/lib/features/bounds/local-bounds.js.map +1 -0
- package/lib/features/bounds/set-bounds-feedback-command.d.ts +33 -0
- package/lib/features/bounds/set-bounds-feedback-command.d.ts.map +1 -0
- package/lib/features/bounds/set-bounds-feedback-command.js +74 -0
- package/lib/features/bounds/set-bounds-feedback-command.js.map +1 -0
- package/lib/features/change-bounds/model.d.ts +1 -1
- package/lib/features/change-bounds/model.d.ts.map +1 -1
- package/lib/features/change-bounds/model.js +0 -1
- package/lib/features/change-bounds/model.js.map +1 -1
- package/lib/features/decoration/decoration-placer.d.ts +16 -1
- package/lib/features/decoration/decoration-placer.d.ts.map +1 -1
- package/lib/features/decoration/decoration-placer.js +3 -3
- package/lib/features/decoration/decoration-placer.js.map +1 -1
- package/lib/features/element-template/add-template-element.d.ts +39 -0
- package/lib/features/element-template/add-template-element.d.ts.map +1 -0
- package/lib/features/element-template/add-template-element.js +107 -0
- package/lib/features/element-template/add-template-element.js.map +1 -0
- package/lib/features/element-template/element-template-module.d.ts +18 -0
- package/lib/features/element-template/element-template-module.d.ts.map +1 -0
- package/lib/features/element-template/element-template-module.js +27 -0
- package/lib/features/element-template/element-template-module.js.map +1 -0
- package/lib/features/element-template/mouse-tracking-element-position-listener.d.ts +38 -0
- package/lib/features/element-template/mouse-tracking-element-position-listener.d.ts.map +1 -0
- package/lib/features/element-template/mouse-tracking-element-position-listener.js +102 -0
- package/lib/features/element-template/mouse-tracking-element-position-listener.js.map +1 -0
- package/lib/features/element-template/remove-template-element.d.ts +32 -0
- package/lib/features/element-template/remove-template-element.d.ts.map +1 -0
- package/lib/features/element-template/remove-template-element.js +66 -0
- package/lib/features/element-template/remove-template-element.js.map +1 -0
- package/lib/features/tool-palette/tool-palette-module.d.ts.map +1 -1
- package/lib/features/tool-palette/tool-palette-module.js +2 -0
- package/lib/features/tool-palette/tool-palette-module.js.map +1 -1
- package/lib/features/tool-palette/tool-palette.d.ts +22 -4
- package/lib/features/tool-palette/tool-palette.d.ts.map +1 -1
- package/lib/features/tool-palette/tool-palette.js +35 -11
- package/lib/features/tool-palette/tool-palette.js.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool.d.ts +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool.d.ts.map +1 -1
- package/lib/features/tools/change-bounds/change-bounds-tool.js +6 -5
- package/lib/features/tools/change-bounds/change-bounds-tool.js.map +1 -1
- package/lib/features/tools/change-bounds/view.d.ts +16 -1
- package/lib/features/tools/change-bounds/view.d.ts.map +1 -1
- package/lib/features/tools/change-bounds/view.js +1 -1
- package/lib/features/tools/change-bounds/view.js.map +1 -1
- package/lib/features/tools/node-creation/node-creation-module.d.ts.map +1 -1
- package/lib/features/tools/node-creation/node-creation-module.js +2 -1
- package/lib/features/tools/node-creation/node-creation-module.js.map +1 -1
- package/lib/features/tools/node-creation/node-creation-tool.d.ts +24 -3
- package/lib/features/tools/node-creation/node-creation-tool.d.ts.map +1 -1
- package/lib/features/tools/node-creation/node-creation-tool.js +41 -11
- package/lib/features/tools/node-creation/node-creation-tool.js.map +1 -1
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/base/args-feature.ts +12 -2
- package/src/base/command-stack.ts +10 -5
- package/src/base/default.module.ts +2 -2
- package/src/base/feedback/css-feedback.ts +4 -1
- package/src/base/selection-service.ts +12 -6
- package/src/default-modules.ts +2 -0
- package/src/features/accessibility/keyboard-tool-palette/keyboard-tool-palette-module.ts +13 -3
- package/src/features/accessibility/keyboard-tool-palette/keyboard-tool-palette.ts +15 -16
- package/src/features/bounds/bounds-module.ts +6 -0
- package/src/features/bounds/glsp-hidden-bounds-updater.ts +11 -7
- package/src/features/bounds/local-bounds.ts +91 -0
- package/src/features/bounds/set-bounds-feedback-command.ts +70 -0
- package/src/features/change-bounds/model.ts +2 -3
- package/src/features/decoration/decoration-placer.ts +3 -3
- package/src/features/element-template/add-template-element.ts +109 -0
- package/src/features/element-template/element-template-module.ts +24 -0
- package/src/features/element-template/mouse-tracking-element-position-listener.ts +110 -0
- package/src/features/element-template/remove-template-element.ts +56 -0
- package/src/features/tool-palette/tool-palette-module.ts +3 -1
- package/src/features/tool-palette/tool-palette.ts +42 -14
- package/src/features/tools/change-bounds/change-bounds-tool.ts +12 -10
- package/src/features/tools/change-bounds/view.tsx +1 -1
- package/src/features/tools/node-creation/node-creation-module.ts +9 -5
- package/src/features/tools/node-creation/node-creation-tool.ts +51 -13
- package/src/index.ts +4 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2023 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
|
+
Action,
|
|
19
|
+
CommandExecutionContext,
|
|
20
|
+
CommandResult,
|
|
21
|
+
ElementTemplate,
|
|
22
|
+
GChildElement,
|
|
23
|
+
GModelElementSchema,
|
|
24
|
+
TYPES,
|
|
25
|
+
distinctAdd,
|
|
26
|
+
remove
|
|
27
|
+
} from '@eclipse-glsp/sprotty';
|
|
28
|
+
import { inject, injectable } from 'inversify';
|
|
29
|
+
import { GLSPActionDispatcher } from '../../base/action-dispatcher';
|
|
30
|
+
import { FeedbackCommand } from '../../base/feedback/feedback-command';
|
|
31
|
+
import { isNotUndefined } from '../../utils/gmodel-util';
|
|
32
|
+
import { LocalRequestBoundsAction } from '../bounds/local-bounds';
|
|
33
|
+
|
|
34
|
+
export interface AddTemplateElementsAction extends Action {
|
|
35
|
+
kind: typeof AddTemplateElementsAction.KIND;
|
|
36
|
+
templates: ElementTemplate[];
|
|
37
|
+
addClasses?: string[];
|
|
38
|
+
removeClasses?: string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export namespace AddTemplateElementsAction {
|
|
42
|
+
export const KIND = 'addTemplateElements';
|
|
43
|
+
|
|
44
|
+
export function create(options: Omit<AddTemplateElementsAction, 'kind'>): AddTemplateElementsAction {
|
|
45
|
+
return {
|
|
46
|
+
kind: KIND,
|
|
47
|
+
...options
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function getTemplateElementId(template: ElementTemplate): string {
|
|
53
|
+
return typeof template === 'string' ? `${template}_feedback` : template.id;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@injectable()
|
|
57
|
+
export class AddTemplateElementsFeedbackCommand extends FeedbackCommand {
|
|
58
|
+
static readonly KIND = AddTemplateElementsAction.KIND;
|
|
59
|
+
|
|
60
|
+
@inject(TYPES.IActionDispatcher) protected actionDispatcher: GLSPActionDispatcher;
|
|
61
|
+
|
|
62
|
+
constructor(@inject(TYPES.Action) readonly action: AddTemplateElementsAction) {
|
|
63
|
+
super();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
override execute(context: CommandExecutionContext): CommandResult {
|
|
67
|
+
this.action.templates
|
|
68
|
+
.map(template => templateToSchema(template, context))
|
|
69
|
+
.filter(isNotUndefined)
|
|
70
|
+
.map(schema => context.modelFactory.createElement(schema))
|
|
71
|
+
.map(element => this.applyRootCssClasses(element, this.action.addClasses, this.action.removeClasses))
|
|
72
|
+
.forEach(templateElement => context.root.add(templateElement));
|
|
73
|
+
return LocalRequestBoundsAction.fromCommand(context, this.actionDispatcher, this.action);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
protected applyRootCssClasses(element: GChildElement, addClasses?: string[], removeClasses?: string[]): GChildElement {
|
|
77
|
+
element.cssClasses = modifyCssClasses(element.cssClasses, addClasses, removeClasses);
|
|
78
|
+
return element;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function templateToSchema(template: ElementTemplate, context: CommandExecutionContext): GModelElementSchema | undefined {
|
|
83
|
+
if (typeof template === 'string') {
|
|
84
|
+
const element = context.root.index.getById(template);
|
|
85
|
+
const schema = element ? context.modelFactory.createSchema(element) : undefined;
|
|
86
|
+
if (schema) {
|
|
87
|
+
adaptSchemaIds(schema);
|
|
88
|
+
}
|
|
89
|
+
return schema;
|
|
90
|
+
}
|
|
91
|
+
return template;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function adaptSchemaIds(schema: GModelElementSchema): GModelElementSchema {
|
|
95
|
+
schema.id = getTemplateElementId(schema.id);
|
|
96
|
+
schema.children?.forEach(child => adaptSchemaIds(child));
|
|
97
|
+
return schema;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function modifyCssClasses(source?: string[], toAdd?: string[], toRemove?: string[]): string[] {
|
|
101
|
+
const classes = source ?? [];
|
|
102
|
+
if (toAdd) {
|
|
103
|
+
distinctAdd(classes, ...toAdd);
|
|
104
|
+
}
|
|
105
|
+
if (toRemove) {
|
|
106
|
+
remove(classes, ...toRemove);
|
|
107
|
+
}
|
|
108
|
+
return classes;
|
|
109
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2019-2023 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 { FeatureModule, configureCommand } from '@eclipse-glsp/sprotty';
|
|
17
|
+
import { AddTemplateElementsFeedbackCommand } from './add-template-element';
|
|
18
|
+
import { RemoveTemplateElementsFeedbackCommand } from './remove-template-element';
|
|
19
|
+
|
|
20
|
+
export const elementTemplateModule = new FeatureModule((bind, unbind, isBound, rebind) => {
|
|
21
|
+
const context = { bind, unbind, isBound, rebind };
|
|
22
|
+
configureCommand(context, AddTemplateElementsFeedbackCommand);
|
|
23
|
+
configureCommand(context, RemoveTemplateElementsFeedbackCommand);
|
|
24
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2023 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 { Action, Disposable, GModelElement, ISnapper, MoveAction, Point, isBoundsAware, isMoveable } from '@eclipse-glsp/sprotty';
|
|
18
|
+
import { injectable } from 'inversify';
|
|
19
|
+
import { DragAwareMouseListener } from '../../base/drag-aware-mouse-listener';
|
|
20
|
+
import { CSS_HIDDEN, ModifyCSSFeedbackAction } from '../../base/feedback/css-feedback';
|
|
21
|
+
import { IFeedbackEmitter } from '../../base/feedback/feedback-action-dispatcher';
|
|
22
|
+
import { Tool } from '../../base/tool-manager/tool';
|
|
23
|
+
import { getAbsolutePosition } from '../../utils/viewpoint-util';
|
|
24
|
+
import {
|
|
25
|
+
IMovementRestrictor,
|
|
26
|
+
createMovementRestrictionFeedback,
|
|
27
|
+
removeMovementRestrictionFeedback
|
|
28
|
+
} from '../change-bounds/movement-restrictor';
|
|
29
|
+
|
|
30
|
+
export interface PositioningTool extends Tool {
|
|
31
|
+
readonly snapper?: ISnapper;
|
|
32
|
+
readonly movementRestrictor?: IMovementRestrictor;
|
|
33
|
+
|
|
34
|
+
registerFeedback(feedbackActions: Action[], feedbackEmitter?: IFeedbackEmitter, cleanupActions?: Action[]): Disposable;
|
|
35
|
+
deregisterFeedback(feedbackEmitter?: IFeedbackEmitter, cleanupActions?: Action[]): void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@injectable()
|
|
39
|
+
export class MouseTrackingElementPositionListener extends DragAwareMouseListener {
|
|
40
|
+
element?: GModelElement;
|
|
41
|
+
currentPosition?: Point;
|
|
42
|
+
|
|
43
|
+
constructor(
|
|
44
|
+
protected elementId: string,
|
|
45
|
+
protected tool: PositioningTool,
|
|
46
|
+
protected cursorPosition: 'top-left' | 'middle' = 'top-left'
|
|
47
|
+
) {
|
|
48
|
+
super();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override mouseMove(target: GModelElement, event: MouseEvent): Action[] {
|
|
52
|
+
super.mouseMove(target, event);
|
|
53
|
+
const element = target.root.index.getById(this.elementId);
|
|
54
|
+
this.element = element;
|
|
55
|
+
if (!element) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let newPosition = getAbsolutePosition(target, event);
|
|
60
|
+
if (this.cursorPosition === 'middle' && isBoundsAware(element)) {
|
|
61
|
+
newPosition = Point.subtract(newPosition, { x: element.bounds.width / 2, y: element.bounds.height / 2 });
|
|
62
|
+
}
|
|
63
|
+
newPosition = this.snap(newPosition, element);
|
|
64
|
+
|
|
65
|
+
const finished = false;
|
|
66
|
+
if (isMoveable(element)) {
|
|
67
|
+
newPosition = this.validateMove(this.currentPosition ?? newPosition, newPosition, element, finished);
|
|
68
|
+
}
|
|
69
|
+
this.currentPosition = newPosition;
|
|
70
|
+
const moveGhostElement = MoveAction.create(
|
|
71
|
+
[
|
|
72
|
+
{
|
|
73
|
+
elementId: element.id,
|
|
74
|
+
toPosition: newPosition
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
{ animate: false, finished }
|
|
78
|
+
);
|
|
79
|
+
this.tool.registerFeedback([moveGhostElement], this);
|
|
80
|
+
return element.cssClasses?.includes(CSS_HIDDEN)
|
|
81
|
+
? [ModifyCSSFeedbackAction.create({ elements: [element.id], remove: [CSS_HIDDEN] })]
|
|
82
|
+
: [];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
protected snap(position: Point, element: GModelElement, isSnap = true): Point {
|
|
86
|
+
if (isSnap && this.tool.snapper) {
|
|
87
|
+
return this.tool.snapper.snap(position, element);
|
|
88
|
+
} else {
|
|
89
|
+
return position;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
protected validateMove(startPosition: Point, toPosition: Point, element: GModelElement, isFinished: boolean): Point {
|
|
94
|
+
let newPosition = toPosition;
|
|
95
|
+
if (this.tool.movementRestrictor) {
|
|
96
|
+
const valid = this.tool.movementRestrictor.validate(element, toPosition);
|
|
97
|
+
let action;
|
|
98
|
+
if (!valid) {
|
|
99
|
+
action = createMovementRestrictionFeedback(element, this.tool.movementRestrictor);
|
|
100
|
+
if (isFinished) {
|
|
101
|
+
newPosition = startPosition;
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
action = removeMovementRestrictionFeedback(element, this.tool.movementRestrictor);
|
|
105
|
+
}
|
|
106
|
+
this.tool.registerFeedback([action], this, [removeMovementRestrictionFeedback(element, this.tool.movementRestrictor)]);
|
|
107
|
+
}
|
|
108
|
+
return newPosition;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2023 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 { Action, CommandExecutionContext, CommandReturn, ElementTemplate, GChildElement, TYPES } from '@eclipse-glsp/sprotty';
|
|
18
|
+
import { inject, injectable } from 'inversify';
|
|
19
|
+
import { FeedbackCommand } from '../../base/feedback/feedback-command';
|
|
20
|
+
import { getTemplateElementId } from './add-template-element';
|
|
21
|
+
|
|
22
|
+
export interface RemoveTemplateElementsAction extends Action {
|
|
23
|
+
kind: typeof RemoveTemplateElementsAction.KIND;
|
|
24
|
+
templates: ElementTemplate[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export namespace RemoveTemplateElementsAction {
|
|
28
|
+
export const KIND = 'removeTemplateElements';
|
|
29
|
+
|
|
30
|
+
export function create(options: Omit<RemoveTemplateElementsAction, 'kind'>): RemoveTemplateElementsAction {
|
|
31
|
+
return {
|
|
32
|
+
kind: KIND,
|
|
33
|
+
...options
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@injectable()
|
|
39
|
+
export class RemoveTemplateElementsFeedbackCommand extends FeedbackCommand {
|
|
40
|
+
static readonly KIND = RemoveTemplateElementsAction.KIND;
|
|
41
|
+
|
|
42
|
+
constructor(@inject(TYPES.Action) readonly action: RemoveTemplateElementsAction) {
|
|
43
|
+
super();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
execute(context: CommandExecutionContext): CommandReturn {
|
|
47
|
+
const index = context.root.index;
|
|
48
|
+
for (const template of this.action.templates) {
|
|
49
|
+
const element = index.getById(getTemplateElementId(template));
|
|
50
|
+
if (element && element instanceof GChildElement) {
|
|
51
|
+
element.parent.remove(element);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return context.root;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -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 { bindAsService, configureActionHandler, FeatureModule, TYPES } from '@eclipse-glsp/sprotty';
|
|
16
|
+
import { bindAsService, configureActionHandler, FeatureModule, SetModelAction, TYPES, UpdateModelAction } from '@eclipse-glsp/sprotty';
|
|
17
17
|
import '../../../css/tool-palette.css';
|
|
18
18
|
import { EnableDefaultToolsAction } from '../../base/tool-manager/tool';
|
|
19
19
|
import { ToolPalette } from './tool-palette';
|
|
@@ -22,4 +22,6 @@ export const toolPaletteModule = new FeatureModule((bind, _unbind, isBound, _reb
|
|
|
22
22
|
bindAsService(bind, TYPES.IUIExtension, ToolPalette);
|
|
23
23
|
bind(TYPES.IDiagramStartup).toService(ToolPalette);
|
|
24
24
|
configureActionHandler({ bind, isBound }, EnableDefaultToolsAction.KIND, ToolPalette);
|
|
25
|
+
configureActionHandler({ bind, isBound }, UpdateModelAction.KIND, ToolPalette);
|
|
26
|
+
configureActionHandler({ bind, isBound }, SetModelAction.KIND, ToolPalette);
|
|
25
27
|
});
|
|
@@ -13,22 +13,25 @@
|
|
|
13
13
|
*
|
|
14
14
|
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
********************************************************************************/
|
|
16
|
-
import { inject, injectable, postConstruct } from 'inversify';
|
|
17
16
|
import {
|
|
18
17
|
AbstractUIExtension,
|
|
19
18
|
Action,
|
|
19
|
+
GModelRoot,
|
|
20
20
|
IActionHandler,
|
|
21
21
|
ICommand,
|
|
22
22
|
MarkersReason,
|
|
23
23
|
PaletteItem,
|
|
24
24
|
RequestContextActions,
|
|
25
25
|
RequestMarkersAction,
|
|
26
|
-
GModelRoot,
|
|
27
26
|
SetContextActions,
|
|
27
|
+
SetModelAction,
|
|
28
28
|
SetUIExtensionVisibilityAction,
|
|
29
|
+
TriggerNodeCreationAction,
|
|
30
|
+
UpdateModelAction,
|
|
29
31
|
codiconCSSClasses,
|
|
30
32
|
matchesKeystroke
|
|
31
33
|
} from '@eclipse-glsp/sprotty';
|
|
34
|
+
import { inject, injectable, postConstruct } from 'inversify';
|
|
32
35
|
import { GLSPActionDispatcher } from '../../base/action-dispatcher';
|
|
33
36
|
import { EditorContextService, IEditModeListener } from '../../base/editor-context-service';
|
|
34
37
|
import { FocusTracker } from '../../base/focus/focus-tracker';
|
|
@@ -73,6 +76,7 @@ export class ToolPalette extends AbstractUIExtension implements IActionHandler,
|
|
|
73
76
|
|
|
74
77
|
protected paletteItems: PaletteItem[];
|
|
75
78
|
protected paletteItemsCopy: PaletteItem[] = [];
|
|
79
|
+
protected dynamic = false;
|
|
76
80
|
protected bodyDiv?: HTMLElement;
|
|
77
81
|
protected lastActiveButton?: HTMLElement;
|
|
78
82
|
protected defaultToolsButton: HTMLElement;
|
|
@@ -333,11 +337,15 @@ export class ToolPalette extends AbstractUIExtension implements IActionHandler,
|
|
|
333
337
|
}
|
|
334
338
|
}
|
|
335
339
|
|
|
336
|
-
handle(action:
|
|
340
|
+
handle(action: Action): ICommand | Action | void {
|
|
337
341
|
this.changeActiveButton();
|
|
338
|
-
if (
|
|
339
|
-
|
|
340
|
-
|
|
342
|
+
if (UpdateModelAction.is(action) || SetModelAction.is(action)) {
|
|
343
|
+
this.reloadPaletteBody();
|
|
344
|
+
} else if (EnableDefaultToolsAction.is(action)) {
|
|
345
|
+
if (this.focusTracker.hasFocus) {
|
|
346
|
+
// if focus was deliberately taken do not restore focus to the palette
|
|
347
|
+
this.focusTracker.diagramElement?.focus();
|
|
348
|
+
}
|
|
341
349
|
}
|
|
342
350
|
}
|
|
343
351
|
|
|
@@ -360,11 +368,6 @@ export class ToolPalette extends AbstractUIExtension implements IActionHandler,
|
|
|
360
368
|
}
|
|
361
369
|
}
|
|
362
370
|
|
|
363
|
-
protected handleSetContextActions(action: SetContextActions): void {
|
|
364
|
-
this.paletteItems = action.actions.map(e => e as PaletteItem);
|
|
365
|
-
this.createBody();
|
|
366
|
-
}
|
|
367
|
-
|
|
368
371
|
protected requestFilterUpdate(filter: string): void {
|
|
369
372
|
// Initialize the copy if it's empty
|
|
370
373
|
if (this.paletteItemsCopy.length === 0) {
|
|
@@ -395,6 +398,17 @@ export class ToolPalette extends AbstractUIExtension implements IActionHandler,
|
|
|
395
398
|
}
|
|
396
399
|
|
|
397
400
|
async preRequestModel(): Promise<void> {
|
|
401
|
+
await this.setPaletteItems();
|
|
402
|
+
if (!this.editorContext.isReadonly) {
|
|
403
|
+
this.show(this.editorContext.modelRoot);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
async postRequestModel(): Promise<void> {
|
|
408
|
+
this.reloadPaletteBody();
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
protected async setPaletteItems(): Promise<void> {
|
|
398
412
|
const requestAction = RequestContextActions.create({
|
|
399
413
|
contextId: ToolPalette.ID,
|
|
400
414
|
editorContext: {
|
|
@@ -402,9 +416,23 @@ export class ToolPalette extends AbstractUIExtension implements IActionHandler,
|
|
|
402
416
|
}
|
|
403
417
|
});
|
|
404
418
|
const response = await this.actionDispatcher.request<SetContextActions>(requestAction);
|
|
405
|
-
this.paletteItems = response.actions.map(
|
|
406
|
-
|
|
407
|
-
|
|
419
|
+
this.paletteItems = response.actions.map(action => action as PaletteItem);
|
|
420
|
+
this.dynamic = this.paletteItems.some(item => this.hasDynamicAction(item));
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
protected hasDynamicAction(item: PaletteItem): boolean {
|
|
424
|
+
const dynamic = !!item.actions.find(action => TriggerNodeCreationAction.is(action) && action.ghostElement?.dynamic);
|
|
425
|
+
if (dynamic) {
|
|
426
|
+
return dynamic;
|
|
427
|
+
}
|
|
428
|
+
return item.children?.some(child => this.hasDynamicAction(child)) || false;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
protected async reloadPaletteBody(): Promise<void> {
|
|
432
|
+
if (this.dynamic) {
|
|
433
|
+
await this.setPaletteItems();
|
|
434
|
+
this.paletteItemsCopy = [];
|
|
435
|
+
this.requestFilterUpdate(this.searchField.value);
|
|
408
436
|
}
|
|
409
437
|
}
|
|
410
438
|
}
|
|
@@ -28,15 +28,14 @@ import {
|
|
|
28
28
|
ElementAndBounds,
|
|
29
29
|
ElementAndRoutingPoints,
|
|
30
30
|
GChildElement,
|
|
31
|
-
ISnapper,
|
|
32
|
-
MouseListener,
|
|
33
|
-
Operation,
|
|
34
|
-
Point,
|
|
35
31
|
GConnectableElement,
|
|
36
32
|
GModelElement,
|
|
37
33
|
GModelRoot,
|
|
38
34
|
GParentElement,
|
|
39
|
-
|
|
35
|
+
ISnapper,
|
|
36
|
+
MouseListener,
|
|
37
|
+
Operation,
|
|
38
|
+
Point,
|
|
40
39
|
TYPES,
|
|
41
40
|
findParentByFeature,
|
|
42
41
|
isSelected
|
|
@@ -45,13 +44,14 @@ import { DragAwareMouseListener } from '../../../base/drag-aware-mouse-listener'
|
|
|
45
44
|
import { CursorCSS, applyCssClasses, cursorFeedbackAction, deleteCssClasses } from '../../../base/feedback/css-feedback';
|
|
46
45
|
import { ISelectionListener, SelectionService } from '../../../base/selection-service';
|
|
47
46
|
import { PointPositionUpdater } from '../../../features/change-bounds/snap';
|
|
48
|
-
import { isValidMove, isValidSize } from '../../../utils/layout-utils';
|
|
49
47
|
import {
|
|
50
48
|
calcElementAndRoutingPoints,
|
|
51
49
|
forEachElement,
|
|
52
50
|
isNonRoutableSelectedMovableBoundsAware,
|
|
53
51
|
toElementAndBounds
|
|
54
52
|
} from '../../../utils/gmodel-util';
|
|
53
|
+
import { isValidMove, isValidSize } from '../../../utils/layout-utils';
|
|
54
|
+
import { SetBoundsFeedbackAction } from '../../bounds/set-bounds-feedback-command';
|
|
55
55
|
import { Resizable, ResizeHandleLocation, SResizeHandle, isBoundsAwareMoveable, isResizable } from '../../change-bounds/model';
|
|
56
56
|
import {
|
|
57
57
|
IMovementRestrictor,
|
|
@@ -335,7 +335,7 @@ export class ChangeBoundsListener extends DragAwareMouseListener implements ISel
|
|
|
335
335
|
if (this.initialBounds && this.activeResizeHandle && resetBounds) {
|
|
336
336
|
// we only reset the bounds if an active resize operation was cancelled due to the tool being disabled
|
|
337
337
|
resetFeedback.push(
|
|
338
|
-
|
|
338
|
+
SetBoundsFeedbackAction.create([
|
|
339
339
|
{
|
|
340
340
|
elementId: this.activeResizeElement.id,
|
|
341
341
|
newPosition: this.initialBounds,
|
|
@@ -424,7 +424,9 @@ export class ChangeBoundsListener extends DragAwareMouseListener implements ISel
|
|
|
424
424
|
if (this.tool.movementRestrictor) {
|
|
425
425
|
actions.push(removeMovementRestrictionFeedback(element, this.tool.movementRestrictor));
|
|
426
426
|
}
|
|
427
|
-
actions.push(
|
|
427
|
+
actions.push(
|
|
428
|
+
SetBoundsFeedbackAction.create([{ elementId: element.id, newPosition: this.initialBounds, newSize: this.initialBounds }])
|
|
429
|
+
);
|
|
428
430
|
return actions;
|
|
429
431
|
}
|
|
430
432
|
return [];
|
|
@@ -446,12 +448,12 @@ export class ChangeBoundsListener extends DragAwareMouseListener implements ISel
|
|
|
446
448
|
if (this.tool.movementRestrictor) {
|
|
447
449
|
result.push(removeMovementRestrictionFeedback(element, this.tool.movementRestrictor));
|
|
448
450
|
}
|
|
449
|
-
result.push(
|
|
451
|
+
result.push(SetBoundsFeedbackAction.create([{ elementId: element.id, newPosition, newSize }]));
|
|
450
452
|
} else if (this.isValidSize(element, newSize)) {
|
|
451
453
|
if (this.tool.movementRestrictor) {
|
|
452
454
|
result.push(createMovementRestrictionFeedback(element, this.tool.movementRestrictor));
|
|
453
455
|
}
|
|
454
|
-
result.push(
|
|
456
|
+
result.push(SetBoundsFeedbackAction.create([{ elementId: element.id, newPosition, newSize }]));
|
|
455
457
|
}
|
|
456
458
|
|
|
457
459
|
return result;
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
*
|
|
14
14
|
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
********************************************************************************/
|
|
16
|
+
import { IView, Point, RenderingContext, setAttr, svg } from '@eclipse-glsp/sprotty';
|
|
16
17
|
import { injectable } from 'inversify';
|
|
17
18
|
import { VNode } from 'snabbdom';
|
|
18
|
-
import { IView, Point, RenderingContext, setAttr, svg } from '@eclipse-glsp/sprotty';
|
|
19
19
|
import { ResizeHandleLocation, SResizeHandle, isResizable } from '../../change-bounds/model';
|
|
20
20
|
|
|
21
21
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -14,10 +14,14 @@
|
|
|
14
14
|
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
********************************************************************************/
|
|
16
16
|
import { FeatureModule, TYPES, TriggerNodeCreationAction, bindAsService, configureActionHandler } from '@eclipse-glsp/sprotty';
|
|
17
|
+
import { elementTemplateModule } from '../../element-template/element-template-module';
|
|
17
18
|
import { NodeCreationTool } from './node-creation-tool';
|
|
18
19
|
|
|
19
|
-
export const nodeCreationToolModule = new FeatureModule(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
export const nodeCreationToolModule = new FeatureModule(
|
|
21
|
+
(bind, unbind, isBound, rebind) => {
|
|
22
|
+
const context = { bind, unbind, isBound, rebind };
|
|
23
|
+
bindAsService(context, TYPES.ITool, NodeCreationTool);
|
|
24
|
+
configureActionHandler(context, TriggerNodeCreationAction.KIND, NodeCreationTool);
|
|
25
|
+
},
|
|
26
|
+
{ requires: elementTemplateModule }
|
|
27
|
+
);
|
|
@@ -13,40 +13,61 @@
|
|
|
13
13
|
*
|
|
14
14
|
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
********************************************************************************/
|
|
16
|
-
import { inject, injectable, optional } from 'inversify';
|
|
17
16
|
import {
|
|
18
17
|
Action,
|
|
19
18
|
CreateNodeOperation,
|
|
20
|
-
ISnapper,
|
|
21
19
|
GModelElement,
|
|
22
20
|
GNode,
|
|
21
|
+
ISnapper,
|
|
22
|
+
Point,
|
|
23
23
|
TYPES,
|
|
24
24
|
TriggerNodeCreationAction,
|
|
25
25
|
findParentByFeature,
|
|
26
26
|
isCtrlOrCmd
|
|
27
27
|
} from '@eclipse-glsp/sprotty';
|
|
28
|
+
import { inject, injectable, optional } from 'inversify';
|
|
29
|
+
import '../../../../css/ghost-element.css';
|
|
28
30
|
import { DragAwareMouseListener } from '../../../base/drag-aware-mouse-listener';
|
|
29
|
-
import { CursorCSS, cursorFeedbackAction } from '../../../base/feedback/css-feedback';
|
|
31
|
+
import { CSS_GHOST_ELEMENT, CSS_HIDDEN, CursorCSS, cursorFeedbackAction } from '../../../base/feedback/css-feedback';
|
|
30
32
|
import { EnableDefaultToolsAction } from '../../../base/tool-manager/tool';
|
|
31
33
|
import { getAbsolutePosition } from '../../../utils/viewpoint-util';
|
|
34
|
+
import { IMovementRestrictor } from '../../change-bounds/movement-restrictor';
|
|
35
|
+
import { AddTemplateElementsAction, getTemplateElementId } from '../../element-template/add-template-element';
|
|
36
|
+
import { MouseTrackingElementPositionListener, PositioningTool } from '../../element-template/mouse-tracking-element-position-listener';
|
|
37
|
+
import { RemoveTemplateElementsAction } from '../../element-template/remove-template-element';
|
|
32
38
|
import { Containable, isContainable } from '../../hints/model';
|
|
33
39
|
import { BaseCreationTool } from '../base-tools';
|
|
34
40
|
|
|
35
41
|
@injectable()
|
|
36
|
-
export class NodeCreationTool extends BaseCreationTool<TriggerNodeCreationAction> {
|
|
42
|
+
export class NodeCreationTool extends BaseCreationTool<TriggerNodeCreationAction> implements PositioningTool {
|
|
37
43
|
static ID = 'tool_create_node';
|
|
38
44
|
|
|
39
45
|
protected isTriggerAction = TriggerNodeCreationAction.is;
|
|
40
46
|
|
|
41
47
|
@inject(TYPES.ISnapper) @optional() readonly snapper?: ISnapper;
|
|
48
|
+
@inject(TYPES.IMovementRestrictor) @optional() readonly movementRestrictor?: IMovementRestrictor;
|
|
42
49
|
|
|
43
50
|
get id(): string {
|
|
44
51
|
return NodeCreationTool.ID;
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
doEnable(): void {
|
|
55
|
+
let trackingListener: MouseTrackingElementPositionListener | undefined;
|
|
56
|
+
const ghostElement = this.triggerAction.ghostElement;
|
|
57
|
+
if (ghostElement) {
|
|
58
|
+
trackingListener = new MouseTrackingElementPositionListener(getTemplateElementId(ghostElement.template), this, 'middle');
|
|
59
|
+
this.toDisposeOnDisable.push(
|
|
60
|
+
this.registerFeedback(
|
|
61
|
+
[AddTemplateElementsAction.create({ templates: [ghostElement.template], addClasses: [CSS_HIDDEN, CSS_GHOST_ELEMENT] })],
|
|
62
|
+
ghostElement,
|
|
63
|
+
[RemoveTemplateElementsAction.create({ templates: [ghostElement.template] })]
|
|
64
|
+
),
|
|
65
|
+
this.mouseTool.registerListener(trackingListener)
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
48
69
|
this.toDisposeOnDisable.push(
|
|
49
|
-
this.mouseTool.registerListener(new NodeCreationToolMouseListener(this.triggerAction, this)),
|
|
70
|
+
this.mouseTool.registerListener(new NodeCreationToolMouseListener(this.triggerAction, this, trackingListener)),
|
|
50
71
|
this.registerFeedback([cursorFeedbackAction(CursorCSS.NODE_CREATION)], this, [cursorFeedbackAction()])
|
|
51
72
|
);
|
|
52
73
|
}
|
|
@@ -56,7 +77,11 @@ export class NodeCreationTool extends BaseCreationTool<TriggerNodeCreationAction
|
|
|
56
77
|
export class NodeCreationToolMouseListener extends DragAwareMouseListener {
|
|
57
78
|
protected container?: GModelElement & Containable;
|
|
58
79
|
|
|
59
|
-
constructor(
|
|
80
|
+
constructor(
|
|
81
|
+
protected triggerAction: TriggerNodeCreationAction,
|
|
82
|
+
protected tool: NodeCreationTool,
|
|
83
|
+
protected trackingListener?: MouseTrackingElementPositionListener
|
|
84
|
+
) {
|
|
60
85
|
super();
|
|
61
86
|
}
|
|
62
87
|
|
|
@@ -76,21 +101,34 @@ export class NodeCreationToolMouseListener extends DragAwareMouseListener {
|
|
|
76
101
|
|
|
77
102
|
if (this.creationAllowed(this.elementTypeId)) {
|
|
78
103
|
const containerId = this.container ? this.container.id : undefined;
|
|
79
|
-
|
|
80
|
-
if (this.tool.snapper) {
|
|
81
|
-
// Create a 0-bounds proxy element for snapping
|
|
82
|
-
const elementProxy = new GNode();
|
|
83
|
-
elementProxy.size = { width: 0, height: 0 };
|
|
84
|
-
location = this.tool.snapper.snap(location, elementProxy);
|
|
85
|
-
}
|
|
104
|
+
const location = this.getInsertPosition(target, event);
|
|
86
105
|
result.push(CreateNodeOperation.create(this.elementTypeId, { location, containerId, args: this.triggerAction.args }));
|
|
87
106
|
if (!isCtrlOrCmd(event)) {
|
|
88
107
|
result.push(EnableDefaultToolsAction.create());
|
|
108
|
+
} else {
|
|
109
|
+
this.tool.deregisterFeedback(this);
|
|
89
110
|
}
|
|
90
111
|
}
|
|
91
112
|
return result;
|
|
92
113
|
}
|
|
93
114
|
|
|
115
|
+
protected getInsertPosition(target: GModelElement, event: MouseEvent): Point {
|
|
116
|
+
if (this.trackingListener) {
|
|
117
|
+
const trackedPosition = this.trackingListener.currentPosition;
|
|
118
|
+
if (trackedPosition) {
|
|
119
|
+
return trackedPosition;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
let location = getAbsolutePosition(target, event);
|
|
123
|
+
if (this.tool.snapper) {
|
|
124
|
+
// Create a 0-bounds proxy element for snapping
|
|
125
|
+
const elementProxy = new GNode();
|
|
126
|
+
elementProxy.size = { width: 0, height: 0 };
|
|
127
|
+
location = this.tool.snapper.snap(location, elementProxy);
|
|
128
|
+
}
|
|
129
|
+
return location;
|
|
130
|
+
}
|
|
131
|
+
|
|
94
132
|
override mouseOver(target: GModelElement, event: MouseEvent): Action[] {
|
|
95
133
|
const currentContainer = findParentByFeature(target, isContainable);
|
|
96
134
|
if (!this.container || currentContainer !== this.container) {
|