Skip to content

Commit eb23ff3

Browse files
authored
GLSP-1568: Refactor MenuItem API (#450)
- Refactor `MenuItem` API - Split into `ClientMenuItem` and `ServerMenuItem` (serializable) - Deprecate original `MenuItem` - Refactor `ServerContextMenuItemProvider` to properly map `ServerMenuItem`s to the client version - Replace deprecates usage of `MenuItem` with `ClientMenuItem` Also - Fix issue in `ToolManager` that prevented proper reactivation of default tools when switching back from readonly to edit mode - Ensure that the `Delete` context menu is deactivated if the editor is readonly - Add missing i18n messages for context menu labels and sort messages.json alphabetically - Fix copy right headers and regenerate index Part of: eclipse-glsp/glsp#1586
1 parent 1b63a9e commit eb23ff3

File tree

15 files changed

+185
-139
lines changed

15 files changed

+185
-139
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"build": "yarn compile && yarn bundle",
1212
"bundle": "yarn standalone bundle",
1313
"check:headers": "glsp checkHeaders . -t lastCommit",
14-
"check:pr": "yarn all && yarn check:format && yarn check:headers",
14+
"check:pr": "yarn all && yarn format:check && yarn check:headers",
1515
"clean": "lerna run clean && rimraf coverage .nyc_output",
1616
"compile": "tsc -b",
1717
"format": "prettier --write .",
Lines changed: 68 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,98 @@
11
{
2-
"navigation": {
3-
"default_navigation_mode_activated": "Navigation On: Use arrow keys to select preceding (←) or succeding (→) elements. Use the up (↑) and down (↓) arrows to navigate paths. Press 'N' to exit.",
4-
"default_navigation_mode_deactivated": "Navigation Off: Press 'N' for default navigation, 'ALT+N' for position based navigation.",
5-
"local_navigation_mode_activated": "Position based Nav On: Navigate nearest elements using arrow keys: (↑) for above, (↓) for below, (←) for previous, (→) for next element. Press 'ALT+N' to exit.",
6-
"local_navigation_mode_deactivated": "Position based Nav Off: Press 'N' for default navigation, 'ALT+N' for position based navigation.",
7-
"shortcut_local_mode": "Activate local navigation mode",
8-
"shortcut_global_mode": "Activate global navigation mode"
2+
"autocomplete": {
3+
"no_suggestions": "No suggestions available"
4+
},
5+
"context_menu": {
6+
"copy": "Copy",
7+
"cut": "Cut",
8+
"delete": "Delete",
9+
"marker": {
10+
"navigation": "Go to",
11+
"next": "Next marker",
12+
"previous": "Previous marker"
13+
},
14+
"paste": "Paste"
15+
},
16+
"diagram": {
17+
"label": "Diagram"
918
},
1019
"focus": {
1120
"focus_not_set": "Focus not set",
12-
"focus_on": "Currently focused: ",
1321
"focus_off": "Currently no element is focused.",
22+
"focus_on": "Currently focused: ",
1423
"focus_within": "Within",
15-
"shortcut_focus_palette": "Focus on tool palette",
16-
"shortcut_focus_graph": "Focus on graph"
24+
"shortcut_focus_graph": "Focus on graph",
25+
"shortcut_focus_palette": "Focus on tool palette"
26+
},
27+
"grid": {
28+
"shortcut_zoom_in": "Zoom in via grid",
29+
"zoom_in_grid": "Select a digit from 1-9 to zoom in on the respective box."
30+
},
31+
"issue_marker": {
32+
"severity_error": "ERROR",
33+
"severity_info": "INFO",
34+
"severity_warning": "WARNING"
35+
},
36+
"move": {
37+
"shortcut_move": "Move element"
38+
},
39+
"navigation": {
40+
"default_navigation_mode_activated": "Navigation On: Use arrow keys to select preceding (←) or succeding (→) elements. Use the up (↑) and down (↓) arrows to navigate paths. Press 'N' to exit.",
41+
"default_navigation_mode_deactivated": "Navigation Off: Press 'N' for default navigation, 'ALT+N' for position based navigation.",
42+
"local_navigation_mode_activated": "Position based Nav On: Navigate nearest elements using arrow keys: (↑) for above, (↓) for below, (←) for previous, (→) for next element. Press 'ALT+N' to exit.",
43+
"local_navigation_mode_deactivated": "Position based Nav Off: Press 'N' for default navigation, 'ALT+N' for position based navigation.",
44+
"shortcut_global_mode": "Activate global navigation mode",
45+
"shortcut_local_mode": "Activate local navigation mode"
1746
},
1847
"resize": {
1948
"resize_mode_activated": "Resize On: Use plus(+) and minus(-) to resize, 'CTRL'+'0' for default size. Press 'ESC' to exit.",
2049
"resize_mode_deactivated": "Resize Off: Press 'ALT'+'A' for resize mode.",
2150
"shortcut_activate": "Activate resize mode for selected element",
2251
"shortcut_deactivate": "Deactivate resize handler",
23-
"shortcut_increase": "Increase size of element",
2452
"shortcut_decrease": "Decrease size of element",
53+
"shortcut_increase": "Increase size of element",
2554
"shortcut_reset": "Set element size to default"
2655
},
27-
"move": {
28-
"shortcut_move": "Move element"
29-
},
30-
"grid": {
31-
"zoom_in_grid": "Select a digit from 1-9 to zoom in on the respective box.",
32-
"shortcut_zoom_in": "Zoom in via grid"
33-
},
3456
"search": {
35-
"shortcut_activate": "Activate search for elements",
57+
"label": "Search Field",
3658
"placeholder": "Search for elements...",
37-
"label": "Search Field"
59+
"shortcut_activate": "Activate search for elements"
60+
},
61+
"shortcut": {
62+
"group_focus": "Focus",
63+
"group_graph": "Graph",
64+
"group_grid": "Grid",
65+
"group_move": "Move",
66+
"group_navigation": "Navigation",
67+
"group_resize": "Resize",
68+
"group_search": "Search",
69+
"group_tool_palette": "Tool Palette",
70+
"group_viewport": "Viewport",
71+
"group_zoom": "Zoom",
72+
"header_command": "Command",
73+
"header_shortcut": "Keybinding",
74+
"menu_title": "Shortcut Menu",
75+
"title": "Keyboard Shortcuts"
3876
},
3977
"tool_palette": {
40-
"label": "Tool Palette",
78+
"debug_mode_button": "Debug Mode",
4179
"delete_button": "Enable deletion tool",
80+
"label": "Tool Palette",
4281
"marquee_button": "Enable marquee tool",
4382
"marquee_message": "Currently marquee tool is only usable with mouse.",
44-
"search_placeholder": "Search...",
83+
"maximize": "Maximize palette",
84+
"minimize": "Minimize palette",
85+
"no_items": "No results found.",
86+
"reset_viewport_button": "Reset Viewport",
4587
"search_button": "Filter palette entries",
88+
"search_placeholder": "Search...",
4689
"selection_button": "Enable selection tool",
47-
"validate_button": "Validate model",
48-
"reset_viewport_button": "Reset Viewport",
4990
"toggle_grid_button": "Toggle Grid",
50-
"debug_mode_button": "Debug Mode",
51-
"minimize": "Minimize palette",
52-
"maximize": "Maximize palette",
53-
"no_items": "No results found."
91+
"validate_button": "Validate model"
5492
},
5593
"viewport": {
5694
"shortcut_move_viewport": "Move viewport",
57-
"shortcut_zoom_viewport": "Zoom viewport",
58-
"shortcut_zoom_element": "Zoom element"
59-
},
60-
"shortcut": {
61-
"title": "Keyboard Shortcuts",
62-
"header_command": "Command",
63-
"header_shortcut": "Keybinding",
64-
"menu_title": "Shortcut Menu",
65-
"group_move": "Move",
66-
"group_graph": "Graph",
67-
"group_resize": "Resize",
68-
"group_focus": "Focus",
69-
"group_zoom": "Zoom",
70-
"group_navigation": "Navigation",
71-
"group_grid": "Grid",
72-
"group_search": "Search",
73-
"group_tool_palette": "Tool Palette",
74-
"group_viewport": "Viewport"
75-
},
76-
"diagram": {
77-
"label": "Diagram"
78-
},
79-
"autocomplete": {
80-
"no_suggestions": "No suggestions available"
81-
},
82-
"issue_marker": {
83-
"severity_error": "ERROR",
84-
"severity_warning": "WARNING",
85-
"severity_info": "INFO"
95+
"shortcut_zoom_element": "Zoom element",
96+
"shortcut_zoom_viewport": "Zoom viewport"
8697
}
8798
}

packages/client/src/base/tool-manager/tool-manager.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2019-2024 EclipseSource and others.
2+
* Copyright (c) 2019-2025 EclipseSource and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -133,8 +133,8 @@ export class ToolManager implements IToolManager, IDiagramStartup, IEditModeList
133133
this.actives.splice(0, this.actives.length);
134134
}
135135

136-
enableDefaultTools(): void {
137-
if (this.defaultToolsEnabled) {
136+
enableDefaultTools(force = false): void {
137+
if (this.defaultToolsEnabled && !force) {
138138
return;
139139
}
140140
this.enable(pluck(this.defaultTools, 'id'));
@@ -171,7 +171,7 @@ export class ToolManager implements IToolManager, IDiagramStartup, IEditModeList
171171
if (newValue === EditMode.READONLY) {
172172
this.disableEditTools();
173173
} else if (newValue === EditMode.EDITABLE) {
174-
this.enableDefaultTools();
174+
this.enableDefaultTools(true);
175175
}
176176
}
177177
}

packages/client/src/features/accessibility/edge-autocomplete/edge-autocomplete-palette.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2023-2024 Business Informatics Group (TU Wien) and others.
2+
* Copyright (c) 2023-2025 Business Informatics Group (TU Wien) and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at

packages/client/src/features/accessibility/keyboard-grid/keyboard-grid-search-palette.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2023 Business Informatics Group (TU Wien) and others.
2+
* Copyright (c) 2023-2025 Business Informatics Group (TU Wien) and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at

packages/client/src/features/accessibility/keyboard-grid/keyboard-node-grid.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2023-2024 Business Informatics Group (TU Wien) and others.
2+
* Copyright (c) 2023-2025 Business Informatics Group (TU Wien) and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at

packages/client/src/features/accessibility/keyboard/keyboard-module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2023-2024 Business Informatics Group (TU Wien) and others.
2+
* Copyright (c) 2023-2025 Business Informatics Group (TU Wien) and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at

packages/client/src/features/context-menu/delete-element-context-menu.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2019-2024 EclipseSource and others.
2+
* Copyright (c) 2019-2025 EclipseSource and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -13,9 +13,10 @@
1313
*
1414
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
********************************************************************************/
16-
import { DeleteElementOperation, GModelRoot, IContextMenuItemProvider, MenuItem, Point, TYPES } from '@eclipse-glsp/sprotty';
16+
import { ClientMenuItem, DeleteElementOperation, GModelRoot, IContextMenuItemProvider, Point, TYPES } from '@eclipse-glsp/sprotty';
1717
import { inject, injectable } from 'inversify';
1818
import { EditorContextService, EditorContextServiceProvider } from '../../base/editor-context-service';
19+
import { messages } from '../../base/messages';
1920

2021
@injectable()
2122
export class DeleteElementContextMenuItemProvider implements IContextMenuItemProvider {
@@ -26,14 +27,17 @@ export class DeleteElementContextMenuItemProvider implements IContextMenuItemPro
2627
@inject(EditorContextService)
2728
protected editorContext: EditorContextService;
2829

29-
async getItems(_root: Readonly<GModelRoot>, _lastMousePosition?: Point): Promise<MenuItem[]> {
30+
async getItems(_root: Readonly<GModelRoot>, _lastMousePosition?: Point): Promise<ClientMenuItem[]> {
31+
if (this.editorContext.isReadonly) {
32+
return [];
33+
}
3034
return [this.createDeleteMenuItem()];
3135
}
3236

33-
protected createDeleteMenuItem(): MenuItem {
37+
protected createDeleteMenuItem(): ClientMenuItem {
3438
return {
3539
id: 'delete',
36-
label: 'Delete',
40+
label: messages.context_menu.delete,
3741
sortString: 'd',
3842
group: 'edit',
3943
actions: [DeleteElementOperation.create(this.editorContext.selectedElements.map(e => e.id))],

packages/client/src/features/context-menu/server-context-menu-provider.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2019-2024 EclipseSource and others.
2+
* Copyright (c) 2019-2025 EclipseSource and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -14,11 +14,11 @@
1414
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
********************************************************************************/
1616
import {
17-
Action,
17+
ClientMenuItem,
1818
GModelElement,
1919
IActionDispatcher,
2020
IContextMenuItemProvider,
21-
LabeledAction,
21+
MenuItem,
2222
Point,
2323
RequestContextActions,
2424
SetContextActions,
@@ -37,7 +37,7 @@ export class ServerContextMenuItemProvider implements IContextMenuItemProvider {
3737
@inject(TYPES.IActionDispatcher) protected actionDispatcher: IActionDispatcher;
3838
@inject(EditorContextService) protected editorContext: EditorContextService;
3939

40-
async getItems(root: Readonly<GModelElement>, _lastMousePosition?: Point): Promise<LabeledAction[]> {
40+
async getItems(root: Readonly<GModelElement>, _lastMousePosition?: Point): Promise<ClientMenuItem[]> {
4141
const selectedElementIds = Array.from(
4242
root.index
4343
.all()
@@ -50,10 +50,9 @@ export class ServerContextMenuItemProvider implements IContextMenuItemProvider {
5050
return response ? this.getContextActionsFromResponse(response) : [];
5151
}
5252

53-
getContextActionsFromResponse(action: Action): LabeledAction[] {
54-
if (SetContextActions.is(action)) {
55-
return action.actions;
56-
}
57-
return [];
53+
getContextActionsFromResponse(action: SetContextActions): ClientMenuItem[] {
54+
return action.actions
55+
.filter(item => MenuItem.is(item)) //
56+
.map(item => ClientMenuItem.convert(item));
5857
}
5958
}

packages/client/src/features/copy-paste/copy-paste-context-menu.ts

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2020-2023 EclipseSource and others.
2+
* Copyright (c) 2020-2025 EclipseSource and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -14,21 +14,23 @@
1414
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
********************************************************************************/
1616
/* eslint-disable deprecation/deprecation */
17-
import { inject, injectable } from 'inversify';
1817
import {
1918
Action,
19+
ClientMenuItem,
20+
GModelRoot,
2021
IActionDispatcher,
2122
IActionHandler,
2223
IContextMenuItemProvider,
23-
MenuItem,
24-
Point,
25-
GModelRoot,
2624
MessageAction,
25+
Point,
2726
StatusAction,
2827
TYPES,
2928
hasStringProp,
3029
isSelected
3130
} from '@eclipse-glsp/sprotty';
31+
import { inject, injectable } from 'inversify';
32+
import { EditorContextService } from '../../base/editor-context-service';
33+
import { messages } from '../../base/messages';
3234

3335
/**
3436
* An `InvokeCopyPasteAction` is dispatched by the client to initiate a cut, copy or paste operation.
@@ -89,39 +91,41 @@ export class InvokeCopyPasteActionHandler implements IActionHandler {
8991

9092
@injectable()
9193
export class CopyPasteContextMenuItemProvider implements IContextMenuItemProvider {
92-
getItems(root: Readonly<GModelRoot>, _lastMousePosition?: Point): Promise<MenuItem[]> {
94+
@inject(EditorContextService)
95+
protected editorContext: EditorContextService;
96+
97+
async getItems(root: Readonly<GModelRoot>, _lastMousePosition?: Point): Promise<ClientMenuItem[]> {
98+
if (this.editorContext.isReadonly) {
99+
return [];
100+
}
93101
const hasSelectedElements = Array.from(root.index.all().filter(isSelected)).length > 0;
94-
return Promise.resolve([
95-
this.createCopyMenuItem(hasSelectedElements),
96-
this.createCutMenuItem(hasSelectedElements),
97-
this.createPasteMenuItem()
98-
]);
102+
return [this.createCopyMenuItem(hasSelectedElements), this.createCutMenuItem(hasSelectedElements), this.createPasteMenuItem()];
99103
}
100104

101-
protected createPasteMenuItem(): MenuItem {
105+
protected createPasteMenuItem(): ClientMenuItem {
102106
return {
103107
id: 'paste',
104-
label: 'Paste',
108+
label: messages.context_menu.paste,
105109
group: 'copy-paste',
106110
actions: [InvokeCopyPasteAction.create('paste')],
107111
isEnabled: () => true
108112
};
109113
}
110114

111-
protected createCutMenuItem(hasSelectedElements: boolean): MenuItem {
115+
protected createCutMenuItem(hasSelectedElements: boolean): ClientMenuItem {
112116
return {
113117
id: 'cut',
114-
label: 'Cut',
118+
label: messages.context_menu.cut,
115119
group: 'copy-paste',
116120
actions: [InvokeCopyPasteAction.create('cut')],
117121
isEnabled: () => hasSelectedElements
118122
};
119123
}
120124

121-
protected createCopyMenuItem(hasSelectedElements: boolean): MenuItem {
125+
protected createCopyMenuItem(hasSelectedElements: boolean): ClientMenuItem {
122126
return {
123127
id: 'copy',
124-
label: 'Copy',
128+
label: messages.context_menu.copy,
125129
group: 'copy-paste',
126130
actions: [InvokeCopyPasteAction.create('copy')],
127131
isEnabled: () => hasSelectedElements

0 commit comments

Comments
 (0)