@eclipse-glsp-examples/workflow-glsp 0.9.0-next.9ac2fc1e
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/LICENSE +277 -0
- package/README.md +14 -0
- package/css/diagram.css +203 -0
- package/lib/di.config.d.ts +21 -0
- package/lib/di.config.d.ts.map +1 -0
- package/lib/di.config.js +59 -0
- package/lib/di.config.js.map +1 -0
- package/lib/direct-task-editing/di.config.d.ts +18 -0
- package/lib/direct-task-editing/di.config.d.ts.map +1 -0
- package/lib/direct-task-editing/di.config.js +26 -0
- package/lib/direct-task-editing/di.config.js.map +1 -0
- package/lib/direct-task-editing/direct-task-editor.d.ts +53 -0
- package/lib/direct-task-editing/direct-task-editor.d.ts.map +1 -0
- package/lib/direct-task-editing/direct-task-editor.js +142 -0
- package/lib/direct-task-editing/direct-task-editor.js.map +1 -0
- package/lib/index.d.ts +21 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +34 -0
- package/lib/index.js.map +1 -0
- package/lib/model.d.ts +59 -0
- package/lib/model.d.ts.map +1 -0
- package/lib/model.js +92 -0
- package/lib/model.js.map +1 -0
- package/lib/workflow-views.d.ts +26 -0
- package/lib/workflow-views.d.ts.map +1 -0
- package/lib/workflow-views.js +59 -0
- package/lib/workflow-views.js.map +1 -0
- package/package.json +56 -0
- package/scripts/download.ts +32 -0
- package/src/di.config.ts +152 -0
- package/src/direct-task-editing/di.config.ts +24 -0
- package/src/direct-task-editing/direct-task-editor.ts +162 -0
- package/src/index.ts +21 -0
- package/src/model.ts +111 -0
- package/src/workflow-views.tsx +70 -0
package/src/di.config.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2019-2021 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 '../css/diagram.css';
|
|
17
|
+
import 'balloon-css/balloon.min.css';
|
|
18
|
+
import 'sprotty/css/edit-label.css';
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
boundsModule,
|
|
22
|
+
buttonModule,
|
|
23
|
+
configureDefaultModelElements,
|
|
24
|
+
configureModelElement,
|
|
25
|
+
ConsoleLogger,
|
|
26
|
+
defaultGLSPModule,
|
|
27
|
+
defaultModule,
|
|
28
|
+
DefaultTypes,
|
|
29
|
+
DeleteElementContextMenuItemProvider,
|
|
30
|
+
DiamondNodeView,
|
|
31
|
+
edgeIntersectionModule,
|
|
32
|
+
edgeLayoutModule,
|
|
33
|
+
editLabelFeature,
|
|
34
|
+
expandModule,
|
|
35
|
+
exportModule,
|
|
36
|
+
fadeModule,
|
|
37
|
+
GLSP_TYPES,
|
|
38
|
+
glspCommandPaletteModule,
|
|
39
|
+
glspContextMenuModule,
|
|
40
|
+
glspDecorationModule,
|
|
41
|
+
glspEditLabelModule,
|
|
42
|
+
glspHoverModule,
|
|
43
|
+
glspMouseToolModule,
|
|
44
|
+
glspSelectModule,
|
|
45
|
+
glspServerCopyPasteModule,
|
|
46
|
+
glspViewportModule,
|
|
47
|
+
GridSnapper,
|
|
48
|
+
labelEditUiModule,
|
|
49
|
+
layoutCommandsModule,
|
|
50
|
+
LogLevel,
|
|
51
|
+
markerNavigatorModule,
|
|
52
|
+
modelHintsModule,
|
|
53
|
+
modelSourceModule,
|
|
54
|
+
modelSourceWatcherModule,
|
|
55
|
+
navigationModule,
|
|
56
|
+
NoOverlapMovmentRestrictor,
|
|
57
|
+
openModule,
|
|
58
|
+
overrideViewerOptions,
|
|
59
|
+
paletteModule,
|
|
60
|
+
RectangularNodeView,
|
|
61
|
+
RevealNamedElementActionProvider,
|
|
62
|
+
RoundedCornerNodeView,
|
|
63
|
+
routingModule,
|
|
64
|
+
SCompartment,
|
|
65
|
+
SCompartmentView,
|
|
66
|
+
SEdge,
|
|
67
|
+
SLabel,
|
|
68
|
+
SLabelView,
|
|
69
|
+
toolFeedbackModule,
|
|
70
|
+
toolsModule,
|
|
71
|
+
TYPES,
|
|
72
|
+
validationModule,
|
|
73
|
+
zorderModule
|
|
74
|
+
} from '@eclipse-glsp/client';
|
|
75
|
+
import { Container, ContainerModule } from 'inversify';
|
|
76
|
+
|
|
77
|
+
import { directTaskEditor } from './direct-task-editing/di.config';
|
|
78
|
+
import { ActivityNode, Icon, TaskNode, WeightedEdge } from './model';
|
|
79
|
+
import { IconView, WorkflowEdgeView } from './workflow-views';
|
|
80
|
+
|
|
81
|
+
const workflowDiagramModule = new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
82
|
+
rebind(TYPES.ILogger).to(ConsoleLogger).inSingletonScope();
|
|
83
|
+
rebind(TYPES.LogLevel).toConstantValue(LogLevel.warn);
|
|
84
|
+
bind(GLSP_TYPES.IMovementRestrictor).to(NoOverlapMovmentRestrictor).inSingletonScope();
|
|
85
|
+
bind(TYPES.ISnapper).to(GridSnapper);
|
|
86
|
+
bind(TYPES.ICommandPaletteActionProvider).to(RevealNamedElementActionProvider);
|
|
87
|
+
bind(TYPES.IContextMenuItemProvider).to(DeleteElementContextMenuItemProvider);
|
|
88
|
+
const context = { bind, unbind, isBound, rebind };
|
|
89
|
+
|
|
90
|
+
configureDefaultModelElements(context);
|
|
91
|
+
configureModelElement(context, 'task:automated', TaskNode, RoundedCornerNodeView);
|
|
92
|
+
configureModelElement(context, 'task:manual', TaskNode, RoundedCornerNodeView);
|
|
93
|
+
configureModelElement(context, 'label:heading', SLabel, SLabelView, { enable: [editLabelFeature] });
|
|
94
|
+
configureModelElement(context, 'comp:comp', SCompartment, SCompartmentView);
|
|
95
|
+
configureModelElement(context, 'comp:header', SCompartment, SCompartmentView);
|
|
96
|
+
configureModelElement(context, 'label:icon', SLabel, SLabelView);
|
|
97
|
+
configureModelElement(context, DefaultTypes.EDGE, SEdge, WorkflowEdgeView);
|
|
98
|
+
configureModelElement(context, 'edge:weighted', WeightedEdge, WorkflowEdgeView);
|
|
99
|
+
configureModelElement(context, 'icon', Icon, IconView);
|
|
100
|
+
configureModelElement(context, 'activityNode:merge', ActivityNode, DiamondNodeView);
|
|
101
|
+
configureModelElement(context, 'activityNode:decision', ActivityNode, DiamondNodeView);
|
|
102
|
+
configureModelElement(context, 'activityNode:fork', ActivityNode, RectangularNodeView);
|
|
103
|
+
configureModelElement(context, 'activityNode:join', ActivityNode, RectangularNodeView);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
export default function createContainer(widgetId: string): Container {
|
|
107
|
+
const container = new Container();
|
|
108
|
+
|
|
109
|
+
container.load(
|
|
110
|
+
defaultModule,
|
|
111
|
+
defaultGLSPModule,
|
|
112
|
+
glspMouseToolModule,
|
|
113
|
+
validationModule,
|
|
114
|
+
glspSelectModule,
|
|
115
|
+
boundsModule,
|
|
116
|
+
glspViewportModule,
|
|
117
|
+
toolsModule,
|
|
118
|
+
glspHoverModule,
|
|
119
|
+
fadeModule,
|
|
120
|
+
exportModule,
|
|
121
|
+
expandModule,
|
|
122
|
+
openModule,
|
|
123
|
+
buttonModule,
|
|
124
|
+
modelSourceModule,
|
|
125
|
+
labelEditUiModule,
|
|
126
|
+
glspEditLabelModule,
|
|
127
|
+
workflowDiagramModule,
|
|
128
|
+
toolFeedbackModule,
|
|
129
|
+
modelHintsModule,
|
|
130
|
+
glspContextMenuModule,
|
|
131
|
+
glspServerCopyPasteModule,
|
|
132
|
+
modelSourceWatcherModule,
|
|
133
|
+
glspCommandPaletteModule,
|
|
134
|
+
paletteModule,
|
|
135
|
+
routingModule,
|
|
136
|
+
glspDecorationModule,
|
|
137
|
+
edgeLayoutModule,
|
|
138
|
+
zorderModule,
|
|
139
|
+
edgeIntersectionModule,
|
|
140
|
+
layoutCommandsModule,
|
|
141
|
+
directTaskEditor,
|
|
142
|
+
navigationModule,
|
|
143
|
+
markerNavigatorModule
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
overrideViewerOptions(container, {
|
|
147
|
+
baseDiv: widgetId,
|
|
148
|
+
hiddenDiv: widgetId + '_hidden'
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
return container;
|
|
152
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2020 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 { ContainerModule } from 'inversify';
|
|
17
|
+
import { TYPES } from 'sprotty';
|
|
18
|
+
|
|
19
|
+
import { TaskEditor } from './direct-task-editor';
|
|
20
|
+
|
|
21
|
+
export const directTaskEditor = new ContainerModule((bind, _unbind, isBound) => {
|
|
22
|
+
bind(TaskEditor).toSelf().inSingletonScope();
|
|
23
|
+
bind(TYPES.IUIExtension).toService(TaskEditor);
|
|
24
|
+
});
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2020-2021 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 {
|
|
17
|
+
AbstractUIExtension,
|
|
18
|
+
Action,
|
|
19
|
+
AutoCompleteWidget,
|
|
20
|
+
EditorContextService,
|
|
21
|
+
getAbsoluteClientBounds,
|
|
22
|
+
GLSPActionDispatcher,
|
|
23
|
+
ILogger,
|
|
24
|
+
isSetContextActionsAction,
|
|
25
|
+
isSetEditValidationResultAction,
|
|
26
|
+
LabeledAction,
|
|
27
|
+
RequestContextActions,
|
|
28
|
+
RequestEditValidationAction,
|
|
29
|
+
SModelElement,
|
|
30
|
+
SModelRoot,
|
|
31
|
+
toActionArray,
|
|
32
|
+
ValidationDecorator,
|
|
33
|
+
ValidationStatus,
|
|
34
|
+
ViewerOptions
|
|
35
|
+
} from '@eclipse-glsp/client';
|
|
36
|
+
import { inject, injectable } from 'inversify';
|
|
37
|
+
import { TYPES } from 'sprotty/lib';
|
|
38
|
+
import { DOMHelper } from 'sprotty/lib/base/views/dom-helper';
|
|
39
|
+
|
|
40
|
+
import { isTaskNode, TaskNode } from '../model';
|
|
41
|
+
|
|
42
|
+
export class ApplyTaskEditOperation implements Action {
|
|
43
|
+
static readonly KIND = 'applyTaskEdit';
|
|
44
|
+
readonly kind = ApplyTaskEditOperation.KIND;
|
|
45
|
+
constructor(readonly taskId: string, readonly expression: string) {}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@injectable()
|
|
49
|
+
export class TaskEditor extends AbstractUIExtension {
|
|
50
|
+
static readonly ID = 'task-editor';
|
|
51
|
+
readonly autoSuggestionSettings = {
|
|
52
|
+
noSuggestionsMessage: 'No suggestions available',
|
|
53
|
+
suggestionsClass: 'command-palette-suggestions',
|
|
54
|
+
debounceWaitMs: 50,
|
|
55
|
+
showOnFocus: true
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
@inject(TYPES.IActionDispatcher)
|
|
59
|
+
protected actionDispatcher: GLSPActionDispatcher;
|
|
60
|
+
|
|
61
|
+
@inject(EditorContextService)
|
|
62
|
+
protected editorContextService: EditorContextService;
|
|
63
|
+
|
|
64
|
+
@inject(TYPES.ViewerOptions)
|
|
65
|
+
protected viewerOptions: ViewerOptions;
|
|
66
|
+
|
|
67
|
+
@inject(TYPES.DOMHelper)
|
|
68
|
+
protected domHelper: DOMHelper;
|
|
69
|
+
|
|
70
|
+
@inject(TYPES.ILogger)
|
|
71
|
+
protected logger: ILogger;
|
|
72
|
+
|
|
73
|
+
protected task: TaskNode;
|
|
74
|
+
protected autoSuggestion: AutoCompleteWidget;
|
|
75
|
+
|
|
76
|
+
id(): string {
|
|
77
|
+
return TaskEditor.ID;
|
|
78
|
+
}
|
|
79
|
+
containerClass(): string {
|
|
80
|
+
return 'command-palette';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
protected initializeContents(containerElement: HTMLElement): void {
|
|
84
|
+
this.autoSuggestion = new AutoCompleteWidget(
|
|
85
|
+
this.autoSuggestionSettings,
|
|
86
|
+
{ provideSuggestions: input => this.retrieveSuggestions(input) },
|
|
87
|
+
{ executeFromSuggestion: input => this.executeFromSuggestion(input) },
|
|
88
|
+
() => this.hide(),
|
|
89
|
+
this.logger
|
|
90
|
+
);
|
|
91
|
+
this.autoSuggestion.configureValidation(
|
|
92
|
+
{ validate: input => this.validateInput(input) },
|
|
93
|
+
new ValidationDecorator(containerElement)
|
|
94
|
+
);
|
|
95
|
+
this.autoSuggestion.configureTextSubmitHandler({
|
|
96
|
+
executeFromTextOnlyInput: (input: string) => this.executeFromTextOnlyInput(input)
|
|
97
|
+
});
|
|
98
|
+
this.autoSuggestion.initialize(containerElement);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
show(root: Readonly<SModelRoot>, ...contextElementIds: string[]): void {
|
|
102
|
+
super.show(root, ...contextElementIds);
|
|
103
|
+
this.autoSuggestion.open(root);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
protected onBeforeShow(containerElement: HTMLElement, root: Readonly<SModelRoot>, ...contextElementIds: string[]): void {
|
|
107
|
+
this.task = getTask(contextElementIds, root)[0];
|
|
108
|
+
this.autoSuggestion.inputField.value = '';
|
|
109
|
+
this.setPosition(containerElement);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
protected setPosition(containerElement: HTMLElement): void {
|
|
113
|
+
let x = 0;
|
|
114
|
+
let y = 0;
|
|
115
|
+
|
|
116
|
+
if (this.task) {
|
|
117
|
+
const bounds = getAbsoluteClientBounds(this.task, this.domHelper, this.viewerOptions);
|
|
118
|
+
x = bounds.x + 5;
|
|
119
|
+
y = bounds.y + 5;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
containerElement.style.left = `${x}px`;
|
|
123
|
+
containerElement.style.top = `${y}px`;
|
|
124
|
+
containerElement.style.width = '200px';
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
protected async retrieveSuggestions(input: string): Promise<LabeledAction[]> {
|
|
128
|
+
const response = await this.actionDispatcher.request(
|
|
129
|
+
new RequestContextActions(TaskEditor.ID, this.editorContextService.get({ ['text']: input }))
|
|
130
|
+
);
|
|
131
|
+
if (isSetContextActionsAction(response)) {
|
|
132
|
+
return response.actions;
|
|
133
|
+
}
|
|
134
|
+
return Promise.reject();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
protected async validateInput(input: string): Promise<ValidationStatus> {
|
|
138
|
+
const response = await this.actionDispatcher.request(new RequestEditValidationAction(TaskEditor.ID, this.task.id, input));
|
|
139
|
+
if (isSetEditValidationResultAction(response)) {
|
|
140
|
+
return response.status;
|
|
141
|
+
}
|
|
142
|
+
return Promise.reject();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
protected executeFromSuggestion(input: LabeledAction | Action[] | Action): void {
|
|
146
|
+
this.actionDispatcher.dispatchAll(toActionArray(input));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
protected executeFromTextOnlyInput(input: string): void {
|
|
150
|
+
const action = new ApplyTaskEditOperation(this.task.id, input);
|
|
151
|
+
this.actionDispatcher.dispatch(action);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
hide(): void {
|
|
155
|
+
this.autoSuggestion.dispose();
|
|
156
|
+
super.hide();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function getTask(ids: string[], element: SModelElement): TaskNode[] {
|
|
161
|
+
return ids.map(id => element.index.getById(id)).filter(isTaskNode);
|
|
162
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2019-2021 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 createWorkflowDiagramContainer from './di.config';
|
|
17
|
+
|
|
18
|
+
export * from './model';
|
|
19
|
+
export * from './workflow-views';
|
|
20
|
+
export * from './direct-task-editing/direct-task-editor';
|
|
21
|
+
export { createWorkflowDiagramContainer };
|
package/src/model.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2020-2021 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 {
|
|
17
|
+
boundsFeature,
|
|
18
|
+
connectableFeature,
|
|
19
|
+
deletableFeature,
|
|
20
|
+
DiamondNode,
|
|
21
|
+
EditableLabel,
|
|
22
|
+
fadeFeature,
|
|
23
|
+
hoverFeedbackFeature,
|
|
24
|
+
isEditableLabel,
|
|
25
|
+
layoutableChildFeature,
|
|
26
|
+
LayoutContainer,
|
|
27
|
+
layoutContainerFeature,
|
|
28
|
+
moveFeature,
|
|
29
|
+
Nameable,
|
|
30
|
+
nameFeature,
|
|
31
|
+
popupFeature,
|
|
32
|
+
RectangularNode,
|
|
33
|
+
SChildElement,
|
|
34
|
+
SEdge,
|
|
35
|
+
selectFeature,
|
|
36
|
+
SModelElement,
|
|
37
|
+
SShapeElement,
|
|
38
|
+
WithEditableLabel,
|
|
39
|
+
withEditLabelFeature
|
|
40
|
+
} from '@eclipse-glsp/client';
|
|
41
|
+
|
|
42
|
+
export class TaskNode extends RectangularNode implements Nameable, WithEditableLabel {
|
|
43
|
+
static readonly DEFAULT_FEATURES = [
|
|
44
|
+
connectableFeature,
|
|
45
|
+
deletableFeature,
|
|
46
|
+
selectFeature,
|
|
47
|
+
boundsFeature,
|
|
48
|
+
moveFeature,
|
|
49
|
+
layoutContainerFeature,
|
|
50
|
+
fadeFeature,
|
|
51
|
+
hoverFeedbackFeature,
|
|
52
|
+
popupFeature,
|
|
53
|
+
nameFeature,
|
|
54
|
+
withEditLabelFeature
|
|
55
|
+
];
|
|
56
|
+
name = '';
|
|
57
|
+
duration?: number;
|
|
58
|
+
taskType?: string;
|
|
59
|
+
reference?: string;
|
|
60
|
+
|
|
61
|
+
get editableLabel(): (SChildElement & EditableLabel) | undefined {
|
|
62
|
+
const headerComp = this.children.find(element => element.type === 'comp:header');
|
|
63
|
+
if (headerComp) {
|
|
64
|
+
const label = headerComp.children.find(element => element.type === 'label:heading');
|
|
65
|
+
if (label && isEditableLabel(label)) {
|
|
66
|
+
return label;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function isTaskNode(element: SModelElement): element is TaskNode {
|
|
74
|
+
return element instanceof TaskNode || false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export class WeightedEdge extends SEdge {
|
|
78
|
+
probability?: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export class ActivityNode extends DiamondNode {
|
|
82
|
+
nodeType: string = ActivityNode.Type.UNDEFINED;
|
|
83
|
+
size = {
|
|
84
|
+
width: 32,
|
|
85
|
+
height: 32
|
|
86
|
+
};
|
|
87
|
+
strokeWidth = 1;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export namespace ActivityNode {
|
|
91
|
+
export namespace Type {
|
|
92
|
+
export const INITIAL = 'initalNode';
|
|
93
|
+
export const FINAL = 'finalNode';
|
|
94
|
+
export const DECISION = 'decisionNode';
|
|
95
|
+
export const MERGE = 'mergeNode';
|
|
96
|
+
export const JOIN = 'joinNode';
|
|
97
|
+
export const FORK = 'forkNode';
|
|
98
|
+
export const UNDEFINED = 'undefined';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export class Icon extends SShapeElement implements LayoutContainer {
|
|
103
|
+
static readonly DEFAULT_FEATURES = [boundsFeature, layoutContainerFeature, layoutableChildFeature, fadeFeature];
|
|
104
|
+
|
|
105
|
+
layout: string;
|
|
106
|
+
layoutOptions?: { [key: string]: string | number | boolean };
|
|
107
|
+
size = {
|
|
108
|
+
width: 32,
|
|
109
|
+
height: 32
|
|
110
|
+
};
|
|
111
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2019-2021 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 {
|
|
17
|
+
angleOfPoint,
|
|
18
|
+
IView,
|
|
19
|
+
Point,
|
|
20
|
+
PolylineEdgeViewWithGapsOnIntersections,
|
|
21
|
+
RenderingContext,
|
|
22
|
+
SEdge,
|
|
23
|
+
toDegrees
|
|
24
|
+
} from '@eclipse-glsp/client';
|
|
25
|
+
import { injectable } from 'inversify';
|
|
26
|
+
import { VNode } from 'snabbdom';
|
|
27
|
+
import { svg } from 'sprotty';
|
|
28
|
+
|
|
29
|
+
import { Icon } from './model';
|
|
30
|
+
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
32
|
+
const JSX = { createElement: svg };
|
|
33
|
+
|
|
34
|
+
@injectable()
|
|
35
|
+
export class WorkflowEdgeView extends PolylineEdgeViewWithGapsOnIntersections {
|
|
36
|
+
protected renderAdditionals(edge: SEdge, segments: Point[], context: RenderingContext): VNode[] {
|
|
37
|
+
const additionals = super.renderAdditionals(edge, segments, context);
|
|
38
|
+
const p1 = segments[segments.length - 2];
|
|
39
|
+
const p2 = segments[segments.length - 1];
|
|
40
|
+
const arrow = (
|
|
41
|
+
<path
|
|
42
|
+
class-sprotty-edge={true}
|
|
43
|
+
class-arrow={true}
|
|
44
|
+
d='M 1.5,0 L 10,-4 L 10,4 Z'
|
|
45
|
+
transform={`rotate(${toDegrees(angleOfPoint({ x: p1.x - p2.x, y: p1.y - p2.y }))} ${p2.x} ${p2.y}) translate(${p2.x} ${
|
|
46
|
+
p2.y
|
|
47
|
+
})`}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
additionals.push(arrow);
|
|
51
|
+
return additionals;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@injectable()
|
|
56
|
+
export class IconView implements IView {
|
|
57
|
+
render(element: Icon, context: RenderingContext): VNode {
|
|
58
|
+
const radius = this.getRadius();
|
|
59
|
+
return (
|
|
60
|
+
<g>
|
|
61
|
+
<circle class-sprotty-icon={true} r={radius} cx={radius} cy={radius}></circle>
|
|
62
|
+
{context.renderChildren(element)}
|
|
63
|
+
</g>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
getRadius(): number {
|
|
68
|
+
return 16;
|
|
69
|
+
}
|
|
70
|
+
}
|