Skip to content

Commit 23a9cf4

Browse files
fix: modernize diagram context menu, simplify visibility logic and solve lint errors
1 parent 714ee0f commit 23a9cf4

File tree

11 files changed

+114
-326
lines changed

11 files changed

+114
-326
lines changed

packages/composite-editor/src/browser/composite-editor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,4 +436,4 @@ export class CompositeEditor
436436
this.getPrimaryWidget()?.restoreState(oldState.primaryWidget);
437437
this.getCodeWidget()?.restoreState(oldState.codeWidget);
438438
}
439-
}
439+
}

packages/glsp-client/src/browser/crossmodel-diagram-module.ts

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,32 @@
44

55
import { GRID, ShowPropertiesAction } from '@crossmodel/protocol';
66
import {
7-
ConsoleLogger,
8-
GLSPHiddenBoundsUpdater,
9-
GLSPMousePositionTracker,
10-
GModelElement,
11-
GlspCommandPalette,
12-
LogLevel,
13-
MetadataPlacer,
14-
MouseDeleteTool,
15-
TYPES,
16-
ToolManager,
17-
ToolPalette,
18-
bindAsService,
19-
bindOrRebind,
20-
configureActionHandler,
21-
isRoutable,
22-
toElementAndRoutingPoints
7+
ConsoleLogger,
8+
GLSPHiddenBoundsUpdater,
9+
GLSPMousePositionTracker,
10+
GModelElement,
11+
GlspCommandPalette,
12+
LogLevel,
13+
MetadataPlacer,
14+
MouseDeleteTool,
15+
TYPES,
16+
ToolManager,
17+
ToolPalette,
18+
bindAsService,
19+
bindOrRebind,
20+
configureActionHandler,
21+
isRoutable,
22+
toElementAndRoutingPoints
2323
} from '@eclipse-glsp/client';
2424
import { GlspSelectionDataService } from '@eclipse-glsp/theia-integration';
2525
import { ContainerModule, injectable, interfaces } from '@theia/core/shared/inversify';
2626
import { VNode } from 'snabbdom';
2727
import { CmMetadataPlacer } from './cm-metadata-placer';
2828
import {
29-
CrossModelCommandPalette,
30-
CrossModelMousePositionTracker,
31-
EntityCommandPalette,
32-
RelationshipCommandPalette
29+
CrossModelCommandPalette,
30+
CrossModelMousePositionTracker,
31+
EntityCommandPalette,
32+
RelationshipCommandPalette
3333
} from './cross-model-command-palette';
3434
import { CrossModelMouseDeleteTool } from './cross-model-delete-tool';
3535
import { CrossModelDiagramStartup } from './cross-model-diagram-startup';
@@ -53,20 +53,21 @@ export function createCrossModelDiagramModule(registry: interfaces.ContainerModu
5353
registry(bind, unbind, isBound, rebind, unbindAsync, onActivation, onDeactivation);
5454
bind(CrossModelCommandPalette).toSelf().inSingletonScope();
5555
rebind(GlspCommandPalette).toService(CrossModelCommandPalette);
56-
bindAsService(bind, TYPES.IUIExtension, EntityCommandPalette);
57-
bindAsService(bind, TYPES.IUIExtension, RelationshipCommandPalette);
56+
bindAsService(context, TYPES.IUIExtension, EntityCommandPalette);
57+
bindAsService(context, TYPES.IUIExtension, RelationshipCommandPalette);
5858

5959
bind(CrossModelMousePositionTracker).toSelf().inSingletonScope();
6060
bindOrRebind(context, GLSPMousePositionTracker).toService(CrossModelMousePositionTracker);
6161

6262
bind(CrossModelToolManager).toSelf().inSingletonScope();
6363
bindOrRebind(context, TYPES.IToolManager).toService(CrossModelToolManager);
6464

65-
bindAsService(bind, TYPES.IUIExtension, CrossModelErrorExtension);
65+
bindAsService(context, TYPES.IUIExtension, CrossModelErrorExtension);
6666
rebind(MetadataPlacer).to(CmMetadataPlacer).inSingletonScope();
6767

6868
bind(CrossModelHiddenBoundsUpdater).toSelf().inSingletonScope();
6969
rebind(GLSPHiddenBoundsUpdater).to(CrossModelHiddenBoundsUpdater).inSingletonScope();
70+
rebind(GLSPHiddenBoundsUpdater).to(CrossModelHiddenBoundsUpdater).inSingletonScope();
7071

7172
configureActionHandler(context, ShowPropertiesAction.KIND, ShowPropertiesActionHandler);
7273
});

packages/glsp-client/src/browser/system-diagram/context-menu/context-menu-action-handlers.ts

Lines changed: 42 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,25 @@
44

55
import { ModelService } from '@crossmodel/model-service/lib/common';
66
import {
7-
ENTITY_NODE_TYPE,
8-
INHERITANCE_EDGE_TYPE,
9-
RELATIONSHIP_EDGE_TYPE,
10-
RelationshipType,
11-
findNextUnique,
12-
identity
7+
ENTITY_NODE_TYPE,
8+
INHERITANCE_EDGE_TYPE,
9+
RELATIONSHIP_EDGE_TYPE,
10+
RelationshipType,
11+
findNextUnique,
12+
identity
1313
} from '@crossmodel/protocol';
1414
import {
15-
Action,
16-
CommandExecutionContext,
17-
CommandReturn,
18-
CreateNodeOperation,
19-
GModelElement,
20-
IActionDispatcher,
21-
IActionHandler,
22-
ICommand,
23-
IDiagramOptions,
24-
Point,
25-
SetUIExtensionVisibilityAction,
26-
TYPES,
27-
TriggerEdgeCreationAction
15+
Action,
16+
CreateNodeOperation,
17+
GModelElement,
18+
IActionDispatcher,
19+
IActionHandler,
20+
ICommand,
21+
IDiagramOptions,
22+
Point,
23+
SetUIExtensionVisibilityAction,
24+
TYPES,
25+
TriggerEdgeCreationAction
2826
} from '@eclipse-glsp/client';
2927
import { GLSPDiagramWidget } from '@eclipse-glsp/theia-integration';
3028
import { URI } from '@theia/core';
@@ -33,15 +31,13 @@ import { inject, injectable } from '@theia/core/shared/inversify';
3331
import { EditorManager } from '@theia/editor/lib/browser';
3432
import { EntityCommandPalette, RelationshipCommandPalette } from '../../cross-model-command-palette';
3533
import {
36-
CreateEntityAction,
37-
CreateInheritanceAction,
38-
CreateRelationshipAction,
39-
HideElementAction,
40-
OpenInCodeEditorAction,
41-
OpenInFormEditorAction,
42-
ShowAllElementsAction,
43-
ShowEntityAction,
44-
ShowRelationshipAction
34+
CreateEntityAction,
35+
CreateInheritanceAction,
36+
CreateRelationshipAction,
37+
OpenInCodeEditorAction,
38+
OpenInFormEditorAction,
39+
ShowEntityAction,
40+
ShowRelationshipAction
4541
} from './context-menu-actions';
4642

4743
/**
@@ -114,7 +110,7 @@ export class OpenInFormEditorActionHandler extends SemanticUriActionHandler {
114110

115111
const widgetUri = glspWidget ? (glspWidget as any).options?.uri?.toString() : undefined;
116112
const modelId = glspWidget?.modelSource?.model?.id || 'N/A';
117-
113+
118114
if (glspWidget && (widgetUri === action.rootId || modelId === action.rootId)) {
119115
diagramWidget = glspWidget;
120116
break;
@@ -125,8 +121,11 @@ export class OpenInFormEditorActionHandler extends SemanticUriActionHandler {
125121
return;
126122
}
127123

128-
const rootElement = (diagramWidget as any).model || (diagramWidget as any).modelSource?.model || (diagramWidget as any).modelSource?.modelRoot || (diagramWidget as any).editorContext?.modelRoot;
129-
124+
const rootElement = (diagramWidget as any).model
125+
|| (diagramWidget as any).modelSource?.model
126+
|| (diagramWidget as any).modelSource?.modelRoot
127+
|| (diagramWidget as any).editorContext?.modelRoot;
128+
130129
if (!rootElement) {
131130
return;
132131
}
@@ -136,7 +135,7 @@ export class OpenInFormEditorActionHandler extends SemanticUriActionHandler {
136135
if (!semanticUri) {
137136
return;
138137
}
139-
138+
140139
(async () => {
141140
try {
142141
const opener = await this.openerService.getOpener(new URI(semanticUri));
@@ -146,7 +145,8 @@ export class OpenInFormEditorActionHandler extends SemanticUriActionHandler {
146145
let compositeEditor: any = widget;
147146
if (!(typeof compositeEditor.getPrimaryWidget === 'function' && typeof compositeEditor.revealCodeTab === 'function')) {
148147
const widgetAny = widget as any;
149-
if (widgetAny.parent && typeof widgetAny.parent.getPrimaryWidget === 'function' && typeof widgetAny.parent.revealCodeTab === 'function') {
148+
if (widgetAny.parent && typeof widgetAny.parent.getPrimaryWidget === 'function'
149+
&& typeof widgetAny.parent.revealCodeTab === 'function') {
150150
compositeEditor = widgetAny.parent;
151151
} else {
152152
compositeEditor = undefined;
@@ -200,7 +200,7 @@ export class OpenInCodeEditorActionHandler extends SemanticUriActionHandler {
200200

201201
const widgetUri = glspWidget ? (glspWidget as any).options?.uri?.toString() : undefined;
202202
const modelId = glspWidget?.modelSource?.model?.id || 'N/A';
203-
203+
204204
if (glspWidget && (widgetUri === action.rootId || modelId === action.rootId)) {
205205
diagramWidget = glspWidget;
206206
break;
@@ -211,8 +211,11 @@ export class OpenInCodeEditorActionHandler extends SemanticUriActionHandler {
211211
return;
212212
}
213213

214-
const rootElement = (diagramWidget as any).model || (diagramWidget as any).modelSource?.model || (diagramWidget as any).modelSource?.modelRoot || (diagramWidget as any).editorContext?.modelRoot;
215-
214+
const rootElement = (diagramWidget as any).model
215+
|| (diagramWidget as any).modelSource?.model
216+
|| (diagramWidget as any).modelSource?.modelRoot
217+
|| (diagramWidget as any).editorContext?.modelRoot;
218+
216219
if (!rootElement) {
217220
return;
218221
}
@@ -222,7 +225,7 @@ export class OpenInCodeEditorActionHandler extends SemanticUriActionHandler {
222225
if (!semanticUri) {
223226
return;
224227
}
225-
228+
226229
(async () => {
227230
try {
228231
const opener = await this.openerService.getOpener(new URI(semanticUri));
@@ -232,7 +235,8 @@ export class OpenInCodeEditorActionHandler extends SemanticUriActionHandler {
232235
let compositeEditor: any = widget;
233236
if (!(typeof compositeEditor.getPrimaryWidget === 'function' && typeof compositeEditor.revealCodeTab === 'function')) {
234237
const widgetAny = widget as any;
235-
if (widgetAny.parent && typeof widgetAny.parent.getPrimaryWidget === 'function' && typeof widgetAny.parent.revealCodeTab === 'function') {
238+
if (widgetAny.parent && typeof widgetAny.parent.getPrimaryWidget === 'function'
239+
&& typeof widgetAny.parent.revealCodeTab === 'function') {
236240
compositeEditor = widgetAny.parent;
237241
} else {
238242
compositeEditor = undefined;
@@ -250,66 +254,6 @@ export class OpenInCodeEditorActionHandler extends SemanticUriActionHandler {
250254
}
251255
}
252256

253-
/**
254-
* Action handler for hiding elements from the diagram (visual-only, temporary).
255-
*/
256-
@injectable()
257-
export class HideElementActionHandler implements IActionHandler {
258-
@inject(TYPES.IActionDispatcher) protected readonly actionDispatcher: IActionDispatcher;
259-
260-
handle(action: Action): void | Action | ICommand {
261-
if (!HideElementAction.is(action)) {
262-
return;
263-
}
264-
265-
return new HideElementCommand(action.elementId);
266-
}
267-
}
268-
269-
/**
270-
* Command to hide an element from the diagram.
271-
*/
272-
export class HideElementCommand implements ICommand {
273-
static readonly KIND = 'hideElementCommand';
274-
275-
constructor(protected readonly elementId: string) {}
276-
277-
execute(context: CommandExecutionContext): CommandReturn {
278-
const element = context.root.index.getById(this.elementId);
279-
if (!element) {
280-
console.warn('[HideElementCommand] Element not found:', this.elementId);
281-
return context.root;
282-
}
283-
284-
if (!element.cssClasses) {
285-
element.cssClasses = [];
286-
}
287-
if (!element.cssClasses.includes('hidden')) {
288-
element.cssClasses.push('hidden');
289-
}
290-
291-
console.log('[HideElementCommand] Hidden element:', this.elementId);
292-
return context.root;
293-
}
294-
295-
undo(context: CommandExecutionContext): CommandReturn {
296-
const element = context.root.index.getById(this.elementId);
297-
if (!element) {
298-
return context.root;
299-
}
300-
301-
if (element.cssClasses) {
302-
element.cssClasses = element.cssClasses.filter(cls => cls !== 'hidden');
303-
}
304-
305-
return context.root;
306-
}
307-
308-
redo(context: CommandExecutionContext): CommandReturn {
309-
return this.execute(context);
310-
}
311-
}
312-
313257
/**
314258
* Action handler for creating a new entity.
315259
*/
@@ -460,59 +404,3 @@ class EntityNameInputDialog extends SingleTextInputDialog {
460404
}
461405
}
462406
}
463-
464-
/**
465-
* Action handler for showing all hidden elements in the diagram.
466-
*/
467-
@injectable()
468-
export class ShowAllElementsActionHandler implements IActionHandler {
469-
@inject(TYPES.IActionDispatcher) protected readonly actionDispatcher: IActionDispatcher;
470-
471-
handle(action: Action): void | Action | ICommand {
472-
if (!ShowAllElementsAction.is(action)) {
473-
return;
474-
}
475-
476-
return new ShowAllElementsCommand();
477-
}
478-
}
479-
480-
/**
481-
* Command to show all hidden elements in the diagram.
482-
*/
483-
export class ShowAllElementsCommand implements ICommand {
484-
static readonly KIND = 'showAllElementsCommand';
485-
486-
protected hiddenElementIds: string[] = [];
487-
488-
execute(context: CommandExecutionContext): CommandReturn {
489-
this.hiddenElementIds = [];
490-
for (const element of context.root.index.all()) {
491-
if (element.cssClasses && element.cssClasses.includes('hidden')) {
492-
element.cssClasses = element.cssClasses.filter(cls => cls !== 'hidden');
493-
this.hiddenElementIds.push(element.id);
494-
}
495-
}
496-
497-
return context.root;
498-
}
499-
500-
undo(context: CommandExecutionContext): CommandReturn {
501-
for (const id of this.hiddenElementIds) {
502-
const element = context.root.index.getById(id);
503-
if (element) {
504-
if (!element.cssClasses) {
505-
element.cssClasses = [];
506-
}
507-
if (!element.cssClasses.includes('hidden')) {
508-
element.cssClasses.push('hidden');
509-
}
510-
}
511-
}
512-
return context.root;
513-
}
514-
515-
redo(context: CommandExecutionContext): CommandReturn {
516-
return this.execute(context);
517-
}
518-
}

0 commit comments

Comments
 (0)