@eclipse-glsp/client 2.6.0-next.435 → 2.6.0-next.5

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.
Files changed (121) hide show
  1. package/css/command-palette.css +2 -0
  2. package/css/navigation.css +2 -2
  3. package/css/search.css +12 -3
  4. package/lib/base/auto-complete/auto-complete-widget.d.ts +2 -2
  5. package/lib/base/auto-complete/auto-complete-widget.d.ts.map +1 -1
  6. package/lib/base/auto-complete/auto-complete-widget.js +5 -2
  7. package/lib/base/auto-complete/auto-complete-widget.js.map +1 -1
  8. package/lib/base/auto-complete/autocomplete-suggestion-provider.d.ts +56 -0
  9. package/lib/base/auto-complete/autocomplete-suggestion-provider.d.ts.map +1 -0
  10. package/lib/base/auto-complete/autocomplete-suggestion-provider.js +56 -0
  11. package/lib/base/auto-complete/autocomplete-suggestion-provider.js.map +1 -0
  12. package/lib/base/auto-complete/base-autocomplete-palette.d.ts +4 -9
  13. package/lib/base/auto-complete/base-autocomplete-palette.d.ts.map +1 -1
  14. package/lib/base/auto-complete/base-autocomplete-palette.js +2 -2
  15. package/lib/base/auto-complete/base-autocomplete-palette.js.map +1 -1
  16. package/lib/base/default.module.d.ts.map +1 -1
  17. package/lib/base/default.module.js +4 -0
  18. package/lib/base/default.module.js.map +1 -1
  19. package/lib/default-modules.d.ts +1 -1
  20. package/lib/default-modules.d.ts.map +1 -1
  21. package/lib/default-modules.js +4 -1
  22. package/lib/default-modules.js.map +1 -1
  23. package/lib/features/accessibility/accessibility-module.d.ts.map +1 -1
  24. package/lib/features/accessibility/accessibility-module.js +2 -4
  25. package/lib/features/accessibility/accessibility-module.js.map +1 -1
  26. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-palette.d.ts +20 -14
  27. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-palette.d.ts.map +1 -1
  28. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-palette.js +58 -44
  29. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-palette.js.map +1 -1
  30. package/lib/features/accessibility/element-navigation/diagram-navigation-tool.d.ts.map +1 -1
  31. package/lib/features/accessibility/element-navigation/diagram-navigation-tool.js +2 -3
  32. package/lib/features/accessibility/element-navigation/diagram-navigation-tool.js.map +1 -1
  33. package/lib/features/accessibility/{keyboard-pointer/keyboard-pointer-module.d.ts → keyboard/keyboard-module.d.ts} +1 -1
  34. package/lib/features/accessibility/keyboard/keyboard-module.d.ts.map +1 -0
  35. package/lib/features/accessibility/{keyboard-pointer/keyboard-pointer-module.js → keyboard/keyboard-module.js} +6 -3
  36. package/lib/features/accessibility/keyboard/keyboard-module.js.map +1 -0
  37. package/lib/features/accessibility/keyboard-grid/keyboard-grid-search-palette.d.ts +14 -11
  38. package/lib/features/accessibility/keyboard-grid/keyboard-grid-search-palette.d.ts.map +1 -1
  39. package/lib/features/accessibility/keyboard-grid/keyboard-grid-search-palette.js +39 -21
  40. package/lib/features/accessibility/keyboard-grid/keyboard-grid-search-palette.js.map +1 -1
  41. package/lib/features/accessibility/keyboard-grid/keyboard-node-grid.js +1 -1
  42. package/lib/features/accessibility/keyboard-grid/keyboard-node-grid.js.map +1 -1
  43. package/lib/features/command-palette/command-palette.d.ts +3 -1
  44. package/lib/features/command-palette/command-palette.d.ts.map +1 -1
  45. package/lib/features/command-palette/command-palette.js +37 -0
  46. package/lib/features/command-palette/command-palette.js.map +1 -1
  47. package/{src/features/accessibility/edge-autocomplete/edge-autocomplete-context.ts → lib/features/search-palette/search-palette-key-listener.d.ts} +5 -9
  48. package/lib/features/search-palette/search-palette-key-listener.d.ts.map +1 -0
  49. package/lib/features/search-palette/search-palette-key-listener.js +45 -0
  50. package/lib/features/search-palette/search-palette-key-listener.js.map +1 -0
  51. package/lib/features/{accessibility/search → search-palette}/search-palette-module.d.ts +4 -3
  52. package/lib/features/search-palette/search-palette-module.d.ts.map +1 -0
  53. package/lib/features/search-palette/search-palette-module.js +39 -0
  54. package/lib/features/search-palette/search-palette-module.js.map +1 -0
  55. package/lib/features/search-palette/search-palette.d.ts +51 -0
  56. package/lib/features/search-palette/search-palette.d.ts.map +1 -0
  57. package/lib/features/search-palette/search-palette.js +141 -0
  58. package/lib/features/search-palette/search-palette.js.map +1 -0
  59. package/{src/base/auto-complete/autocomplete-suggestion-providers.ts → lib/features/search-palette/suggestions/edge-element-suggestions.d.ts} +11 -22
  60. package/lib/features/search-palette/suggestions/edge-element-suggestions.d.ts.map +1 -0
  61. package/lib/features/search-palette/suggestions/edge-element-suggestions.js +72 -0
  62. package/lib/features/search-palette/suggestions/edge-element-suggestions.js.map +1 -0
  63. package/lib/features/search-palette/suggestions/named-element-suggestions.d.ts +30 -0
  64. package/lib/features/search-palette/suggestions/named-element-suggestions.d.ts.map +1 -0
  65. package/lib/features/search-palette/suggestions/named-element-suggestions.js +83 -0
  66. package/lib/features/search-palette/suggestions/named-element-suggestions.js.map +1 -0
  67. package/lib/features/viewport/reposition.d.ts.map +1 -1
  68. package/lib/features/viewport/reposition.js +1 -5
  69. package/lib/features/viewport/reposition.js.map +1 -1
  70. package/lib/index.d.ts +5 -6
  71. package/lib/index.d.ts.map +1 -1
  72. package/lib/index.js +5 -6
  73. package/lib/index.js.map +1 -1
  74. package/lib/standalone-modules.d.ts +1 -1
  75. package/lib/standalone-modules.d.ts.map +1 -1
  76. package/lib/standalone-modules.js +2 -0
  77. package/lib/standalone-modules.js.map +1 -1
  78. package/package.json +4 -4
  79. package/src/base/auto-complete/auto-complete-widget.ts +7 -4
  80. package/src/base/auto-complete/autocomplete-suggestion-provider.ts +86 -0
  81. package/src/base/auto-complete/base-autocomplete-palette.ts +6 -6
  82. package/src/base/default.module.ts +5 -0
  83. package/src/default-modules.ts +4 -1
  84. package/src/features/accessibility/accessibility-module.ts +1 -3
  85. package/src/features/accessibility/edge-autocomplete/edge-autocomplete-palette.ts +74 -51
  86. package/src/features/accessibility/element-navigation/diagram-navigation-tool.ts +2 -4
  87. package/src/features/accessibility/{keyboard-pointer/keyboard-pointer-module.ts → keyboard/keyboard-module.ts} +11 -4
  88. package/src/features/accessibility/keyboard-grid/keyboard-grid-search-palette.ts +35 -21
  89. package/src/features/accessibility/keyboard-grid/keyboard-node-grid.ts +2 -2
  90. package/src/features/command-palette/command-palette.ts +41 -1
  91. package/src/features/{accessibility/search/search-palette-module.ts → search-palette/search-palette-key-listener.ts} +15 -14
  92. package/src/features/search-palette/search-palette-module.ts +48 -0
  93. package/src/features/search-palette/search-palette.ts +164 -0
  94. package/src/features/search-palette/suggestions/edge-element-suggestions.ts +71 -0
  95. package/src/features/search-palette/suggestions/named-element-suggestions.ts +88 -0
  96. package/src/features/viewport/reposition.ts +1 -7
  97. package/src/index.ts +5 -6
  98. package/src/standalone-modules.ts +2 -0
  99. package/lib/base/auto-complete/autocomplete-suggestion-providers.d.ts +0 -35
  100. package/lib/base/auto-complete/autocomplete-suggestion-providers.d.ts.map +0 -1
  101. package/lib/base/auto-complete/autocomplete-suggestion-providers.js +0 -18
  102. package/lib/base/auto-complete/autocomplete-suggestion-providers.js.map +0 -1
  103. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-context.d.ts +0 -23
  104. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-context.d.ts.map +0 -1
  105. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-context.js +0 -18
  106. package/lib/features/accessibility/edge-autocomplete/edge-autocomplete-context.js.map +0 -1
  107. package/lib/features/accessibility/keyboard-pointer/keyboard-pointer-module.d.ts.map +0 -1
  108. package/lib/features/accessibility/keyboard-pointer/keyboard-pointer-module.js.map +0 -1
  109. package/lib/features/accessibility/search/search-palette-module.d.ts.map +0 -1
  110. package/lib/features/accessibility/search/search-palette-module.js +0 -32
  111. package/lib/features/accessibility/search/search-palette-module.js.map +0 -1
  112. package/lib/features/accessibility/search/search-palette.d.ts +0 -51
  113. package/lib/features/accessibility/search/search-palette.d.ts.map +0 -1
  114. package/lib/features/accessibility/search/search-palette.js +0 -186
  115. package/lib/features/accessibility/search/search-palette.js.map +0 -1
  116. package/lib/features/accessibility/search/search-tool.d.ts +0 -33
  117. package/lib/features/accessibility/search/search-tool.d.ts.map +0 -1
  118. package/lib/features/accessibility/search/search-tool.js +0 -84
  119. package/lib/features/accessibility/search/search-tool.js.map +0 -1
  120. package/src/features/accessibility/search/search-palette.ts +0 -218
  121. package/src/features/accessibility/search/search-tool.ts +0 -74
@@ -38,7 +38,6 @@ import { GEdge } from '../../../model';
38
38
  import { SelectableBoundsAware } from '../../../utils/gmodel-util';
39
39
  import { BaseTool } from '../../tools/base-tools';
40
40
  import { RepositionAction } from '../../viewport/reposition';
41
- import { SearchAutocompletePaletteTool } from '../search/search-tool';
42
41
  import { ShowToastMessageAction } from '../toast/toast-handler';
43
42
  import { ElementNavigator } from './element-navigator';
44
43
 
@@ -144,7 +143,7 @@ export class ElementNavigatorKeyListener extends KeyListener {
144
143
  if (this.mode !== NavigationMode.POSITION) {
145
144
  this.clean();
146
145
  this.tool.dispatchActions([
147
- EnableToolsAction.create([ElementNavigatorTool.ID, SearchAutocompletePaletteTool.ID, AvailableShortcutsTool.ID]),
146
+ EnableToolsAction.create([ElementNavigatorTool.ID, AvailableShortcutsTool.ID]),
148
147
  ShowToastMessageAction.create({
149
148
  id: Symbol.for(ElementNavigatorKeyListener.name),
150
149
  message: messages.navigation.local_navigation_mode_activated
@@ -180,9 +179,8 @@ export class ElementNavigatorKeyListener extends KeyListener {
180
179
  if (this.matchesActivateDefaultNavigation(event)) {
181
180
  if (this.mode !== NavigationMode.DEFAULT) {
182
181
  this.clean();
183
-
184
182
  this.tool.dispatchActions([
185
- EnableToolsAction.create([ElementNavigatorTool.ID, SearchAutocompletePaletteTool.ID, AvailableShortcutsTool.ID]),
183
+ EnableToolsAction.create([ElementNavigatorTool.ID, AvailableShortcutsTool.ID]),
186
184
  ShowToastMessageAction.create({
187
185
  id: Symbol.for(ElementNavigatorKeyListener.name),
188
186
  message: messages.navigation.default_navigation_mode_activated
@@ -23,15 +23,19 @@ import {
23
23
  configureActionHandler
24
24
  } from '@eclipse-glsp/sprotty';
25
25
  import { SetEdgeTargetSelectionAction } from '../edge-autocomplete/action';
26
- import { EdgeAutocompletePalette } from '../edge-autocomplete/edge-autocomplete-palette';
26
+ import { EdgeAutocompletePalette, SetEdgeTargetGridSuggestionProvider } from '../edge-autocomplete/edge-autocomplete-palette';
27
27
  import { EdgeAutocompletePaletteTool } from '../edge-autocomplete/edge-autocomplete-tool';
28
28
  import { GlobalKeyListenerTool } from '../global-keylistener-tool';
29
29
  import { EnableKeyboardGridAction, KeyboardGridCellSelectedAction } from '../keyboard-grid/action';
30
30
  import { KeyboardGrid } from '../keyboard-grid/keyboard-grid';
31
- import { GridSearchPalette } from '../keyboard-grid/keyboard-grid-search-palette';
31
+ import {
32
+ GridSearchPalette,
33
+ RevealGridEdgeSuggestionProvider,
34
+ RevealGridNamedElementSuggestionProvider
35
+ } from '../keyboard-grid/keyboard-grid-search-palette';
32
36
  import { KeyboardNodeGrid } from '../keyboard-grid/keyboard-node-grid';
33
- import { SetKeyboardPointerRenderPositionAction } from './actions';
34
- import { KeyboardPointer } from './keyboard-pointer';
37
+ import { SetKeyboardPointerRenderPositionAction } from '../keyboard-pointer/actions';
38
+ import { KeyboardPointer } from '../keyboard-pointer/keyboard-pointer';
35
39
 
36
40
  /**
37
41
  * Handles the pointer used via grid to position new elements.
@@ -55,6 +59,7 @@ export function configureKeyboardControlTools(context: BindingContext): void {
55
59
 
56
60
  bindAsService(context, TYPES.IUIExtension, EdgeAutocompletePalette);
57
61
  bindAsService(context, TYPES.IDefaultTool, EdgeAutocompletePaletteTool);
62
+ bindAsService(context, TYPES.IAutocompleteSuggestionProvider, SetEdgeTargetGridSuggestionProvider);
58
63
 
59
64
  configureActionHandler(context, EnableKeyboardGridAction.KIND, KeyboardGrid);
60
65
  configureActionHandler(context, KeyboardGridCellSelectedAction.KIND, KeyboardPointer);
@@ -63,4 +68,6 @@ export function configureKeyboardControlTools(context: BindingContext): void {
63
68
  configureActionHandler(context, SetEdgeTargetSelectionAction.KIND, EdgeAutocompletePalette);
64
69
 
65
70
  bindAsService(context, TYPES.IUIExtension, GridSearchPalette);
71
+ bindAsService(context, TYPES.IAutocompleteSuggestionProvider, RevealGridEdgeSuggestionProvider);
72
+ bindAsService(context, TYPES.IAutocompleteSuggestionProvider, RevealGridNamedElementSuggestionProvider);
66
73
  }
@@ -15,36 +15,40 @@
15
15
  ********************************************************************************/
16
16
  import '../../../../css/keyboard.css';
17
17
 
18
- import { Action, GModelElement, GModelRoot, SetUIExtensionVisibilityAction } from '@eclipse-glsp/sprotty';
18
+ import { Action, GModelElement, SetUIExtensionVisibilityAction } from '@eclipse-glsp/sprotty';
19
19
  import { injectable } from 'inversify';
20
- import { IAutocompleteSuggestionProvider } from '../../../base/auto-complete/autocomplete-suggestion-providers';
21
- import {
22
- RevealEdgeElementAutocompleteSuggestionProvider,
23
- RevealNamedElementAutocompleteSuggestionProvider,
24
- SearchAutocompletePalette
25
- } from '../search/search-palette';
26
- import { KeyboardGridMetadata } from './constants';
27
20
  import { GEdge } from '../../../model';
28
-
29
- export namespace GridSearchPaletteMetadata {
30
- export const ID = 'grid-search-palette';
31
- }
21
+ import { SearchAutocompletePalette } from '../../search-palette/search-palette';
22
+ import { RevealEdgeElementSuggestionProvider } from '../../search-palette/suggestions/edge-element-suggestions';
23
+ import { RevealNamedElementSuggestionProvider } from '../../search-palette/suggestions/named-element-suggestions';
24
+ import { KeyboardGridMetadata } from './constants';
32
25
 
33
26
  @injectable()
34
27
  export class GridSearchPalette extends SearchAutocompletePalette {
28
+ static override readonly ID: string = 'glsp.grid-search-palette';
29
+
35
30
  override id(): string {
36
- return GridSearchPaletteMetadata.ID;
31
+ return GridSearchPalette.ID;
37
32
  }
38
33
 
39
- protected override getSuggestionProviders(root: Readonly<GModelRoot>, input: string): IAutocompleteSuggestionProvider[] {
40
- return [new GridRevealNamedElementSuggestionProvider(), new GridRevealEdgeSuggestionProvider()];
34
+ override get searchContext(): string[] {
35
+ return [GridSearchPalette.ID];
41
36
  }
42
37
  }
43
38
 
44
- export class GridRevealEdgeSuggestionProvider extends RevealEdgeElementAutocompleteSuggestionProvider {
45
- protected override getActions(edge: GEdge): Action[] {
39
+ @injectable()
40
+ export class RevealGridEdgeSuggestionProvider extends RevealEdgeElementSuggestionProvider {
41
+ override get id(): string {
42
+ return 'glsp.reveal-grid-edge-suggestion';
43
+ }
44
+
45
+ override canHandle(searchContext: string): boolean {
46
+ return searchContext === GridSearchPalette.ID;
47
+ }
48
+
49
+ protected override createActions(edge: GEdge): Action[] {
46
50
  return [
47
- ...super.getActions(edge),
51
+ ...super.createActions(edge),
48
52
  SetUIExtensionVisibilityAction.create({
49
53
  extensionId: KeyboardGridMetadata.ID,
50
54
  visible: true
@@ -52,10 +56,20 @@ export class GridRevealEdgeSuggestionProvider extends RevealEdgeElementAutocompl
52
56
  ];
53
57
  }
54
58
  }
55
- export class GridRevealNamedElementSuggestionProvider extends RevealNamedElementAutocompleteSuggestionProvider {
56
- protected override getActions(nameable: GModelElement): Action[] {
59
+
60
+ @injectable()
61
+ export class RevealGridNamedElementSuggestionProvider extends RevealNamedElementSuggestionProvider {
62
+ override get id(): string {
63
+ return 'glsp.reveal-grid-named-element-suggestion';
64
+ }
65
+
66
+ override canHandle(searchContext: string): boolean {
67
+ return searchContext === GridSearchPalette.ID;
68
+ }
69
+
70
+ protected override createActions(nameable: GModelElement): Action[] {
57
71
  return [
58
- ...super.getActions(nameable),
72
+ ...super.createActions(nameable),
59
73
  SetUIExtensionVisibilityAction.create({
60
74
  extensionId: KeyboardGridMetadata.ID,
61
75
  visible: true
@@ -21,7 +21,7 @@ import { KeyboardPointerMetadata } from '../keyboard-pointer/constants';
21
21
  import { KeyboardPointer } from '../keyboard-pointer/keyboard-pointer';
22
22
  import { KeyboardNodeGridMetadata } from './constants';
23
23
  import { KeyboardGrid } from './keyboard-grid';
24
- import { GridSearchPaletteMetadata } from './keyboard-grid-search-palette';
24
+ import { GridSearchPalette } from './keyboard-grid-search-palette';
25
25
 
26
26
  @injectable()
27
27
  export class KeyboardNodeGrid extends KeyboardGrid {
@@ -52,7 +52,7 @@ export class KeyboardNodeGrid extends KeyboardGrid {
52
52
  event.preventDefault();
53
53
  this.actionDispatcher.dispatch(
54
54
  SetUIExtensionVisibilityAction.create({
55
- extensionId: GridSearchPaletteMetadata.ID,
55
+ extensionId: GridSearchPalette.ID,
56
56
  visible: true
57
57
  })
58
58
  );
@@ -14,14 +14,16 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
 
17
- import { CommandPalette } from '@eclipse-glsp/sprotty';
17
+ import { Bounds, CommandPalette, getWindowScroll, GModelElement, GModelRoot } from '@eclipse-glsp/sprotty';
18
18
  import { injectable } from 'inversify';
19
19
  import { CSS_HIDDEN_EXTENSION_CLASS, CSS_UI_EXTENSION_CLASS } from '../../base/ui-extension/ui-extension';
20
+ import { getElements, isSelectableAndBoundsAware } from '../../utils/gmodel-util';
20
21
 
21
22
  @injectable()
22
23
  export class GlspCommandPalette extends CommandPalette {
23
24
  protected override initializeContents(containerElement: HTMLElement): void {
24
25
  super.initializeContents(containerElement);
26
+ containerElement.style.position = '';
25
27
  containerElement.classList.add(CSS_UI_EXTENSION_CLASS);
26
28
  }
27
29
 
@@ -32,4 +34,42 @@ export class GlspCommandPalette extends CommandPalette {
32
34
  this.containerElement?.classList.add(CSS_HIDDEN_EXTENSION_CLASS);
33
35
  }
34
36
  }
37
+
38
+ protected override onBeforeShow(containerElement: HTMLElement, root: Readonly<GModelRoot>, ...selectedElementIds: string[]): void {
39
+ let x = this.xOffset;
40
+ let y = this.yOffset;
41
+
42
+ const selectedElements = getElements(root.index, selectedElementIds, isSelectableAndBoundsAware);
43
+ if (selectedElements.length === 1) {
44
+ const bounds = this.getAbsoluteBounds(selectedElements[0]);
45
+ x += bounds.x + bounds.width;
46
+ y += bounds.y;
47
+ } else {
48
+ const bounds = this.getAbsoluteBounds(root);
49
+ x += bounds.x;
50
+ y += bounds.y;
51
+ }
52
+ containerElement.style.left = `${x}px`;
53
+ containerElement.style.top = `${y}px`;
54
+ containerElement.style.width = `${this.defaultWidth}px`;
55
+ }
56
+
57
+ protected getAbsoluteBounds(element: Readonly<GModelElement>): Bounds {
58
+ let x = 0;
59
+ let y = 0;
60
+ let width = 0;
61
+ let height = 0;
62
+
63
+ const svgElementId = this.domHelper.createUniqueDOMElementId(element);
64
+ const svgElement = document.getElementById(svgElementId);
65
+ if (svgElement) {
66
+ const rect = svgElement.getBoundingClientRect();
67
+ const scroll = getWindowScroll();
68
+ x = rect.left + scroll.x;
69
+ y = rect.top + scroll.y;
70
+ width = rect.width;
71
+ height = rect.height;
72
+ }
73
+ return { x, y, width, height };
74
+ }
35
75
  }
@@ -14,20 +14,21 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
 
17
- import { bindAsService, BindingContext, FeatureModule, TYPES } from '@eclipse-glsp/sprotty';
18
- import '../../../../css/search.css';
17
+ import { Action, GModelElement, KeyListener, matchesKeystroke, SetUIExtensionVisibilityAction } from '@eclipse-glsp/sprotty';
18
+ import { injectable } from 'inversify';
19
19
  import { SearchAutocompletePalette } from './search-palette';
20
- import { SearchAutocompletePaletteTool } from './search-tool';
21
20
 
22
- export const searchPaletteModule = new FeatureModule(
23
- (bind, _unbind, isBound, rebind) => {
24
- const context = { bind, isBound, rebind };
25
- configureSearchPaletteModule(context);
26
- },
27
- { featureId: Symbol('searchPalette') }
28
- );
29
-
30
- export function configureSearchPaletteModule(context: Pick<BindingContext, 'bind'>): void {
31
- bindAsService(context, TYPES.IUIExtension, SearchAutocompletePalette);
32
- bindAsService(context, TYPES.IDefaultTool, SearchAutocompletePaletteTool);
21
+ @injectable()
22
+ export class SearchPaletteKeyListener extends KeyListener {
23
+ override keyDown(element: GModelElement, event: KeyboardEvent): Action[] {
24
+ if (matchesKeystroke(event, 'KeyF', 'ctrlCmd')) {
25
+ return [
26
+ SetUIExtensionVisibilityAction.create({
27
+ extensionId: SearchAutocompletePalette.ID,
28
+ visible: true
29
+ })
30
+ ];
31
+ }
32
+ return [];
33
+ }
33
34
  }
@@ -0,0 +1,48 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2023-2025 Business Informatics Group (TU Wien) 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 { bindAsService, FeatureModule, TYPES } from '@eclipse-glsp/sprotty';
18
+ import '../../../css/search.css';
19
+ import { SearchAutocompletePalette } from './search-palette';
20
+ import { SearchPaletteKeyListener } from './search-palette-key-listener';
21
+ import { RevealEdgeElementSuggestionProvider } from './suggestions/edge-element-suggestions';
22
+ import { NodesWithoutNameSuggestionProvider, RevealNamedElementSuggestionProvider } from './suggestions/named-element-suggestions';
23
+
24
+ export const searchPaletteModule = new FeatureModule(
25
+ (bind, _unbind, isBound, rebind) => {
26
+ const context = { bind, isBound, rebind };
27
+ bindAsService(context, TYPES.IUIExtension, SearchAutocompletePalette);
28
+ },
29
+ { featureId: Symbol('searchPalette') }
30
+ );
31
+
32
+ export const searchPaletteDefaultSuggestionsModule = new FeatureModule(
33
+ (bind, _unbind, isBound, rebind) => {
34
+ const context = { bind, isBound, rebind };
35
+ bindAsService(context, TYPES.IAutocompleteSuggestionProvider, RevealNamedElementSuggestionProvider);
36
+ bindAsService(context, TYPES.IAutocompleteSuggestionProvider, NodesWithoutNameSuggestionProvider);
37
+ bindAsService(context, TYPES.IAutocompleteSuggestionProvider, RevealEdgeElementSuggestionProvider);
38
+ },
39
+ { featureId: Symbol('searchPaletteDefaultSuggestions'), requires: searchPaletteModule }
40
+ );
41
+
42
+ export const standaloneSearchPaletteModule = new FeatureModule(
43
+ (bind, _unbind, isBound) => {
44
+ const context = { bind, isBound };
45
+ bindAsService(context, TYPES.KeyListener, SearchPaletteKeyListener);
46
+ },
47
+ { featureId: Symbol('standaloneSearchPalette'), requires: searchPaletteModule }
48
+ );
@@ -0,0 +1,164 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2023-2025 Business Informatics Group (TU Wien) 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 { GModelElement, GModelRoot, GNode, LabeledAction, SelectAllAction, toArray, TYPES } from '@eclipse-glsp/sprotty';
18
+ import { inject, injectable } from 'inversify';
19
+ import { debounce, isEqual } from 'lodash';
20
+ import {
21
+ AutocompleteSuggestionProviderContext,
22
+ type AutocompleteSuggestion,
23
+ type AutocompleteSuggestionRegistry
24
+ } from '../../base/auto-complete/autocomplete-suggestion-provider';
25
+ import { BaseAutocompletePalette } from '../../base/auto-complete/base-autocomplete-palette';
26
+ import { applyCssClasses, deleteCssClasses } from '../../base/feedback/css-feedback';
27
+ import { messages } from '../../base/messages';
28
+ import { GEdge } from '../../model';
29
+ import { RepositionAction } from '../viewport/reposition';
30
+
31
+ const CSS_SEARCH_HIDDEN = 'search-hidden';
32
+ const CSS_SEARCH_HIGHLIGHTED = 'search-highlighted';
33
+
34
+ export interface SearchAutocompleteSuggestion extends Required<AutocompleteSuggestion> {}
35
+
36
+ export namespace SearchAutocompleteSuggestion {
37
+ export function is(suggestion: AutocompleteSuggestion): suggestion is SearchAutocompleteSuggestion {
38
+ return suggestion.element !== undefined;
39
+ }
40
+ }
41
+
42
+ @injectable()
43
+ export class SearchAutocompletePalette extends BaseAutocompletePalette {
44
+ static readonly ID: string = 'glsp.search-autocomplete-palette';
45
+
46
+ @inject(TYPES.IAutocompleteSuggestionProviderRegistry)
47
+ protected readonly suggestionRegistry: AutocompleteSuggestionRegistry;
48
+
49
+ /**
50
+ * Cache the suggestions so that we don't have to retrieve them again for CSS manipulation.
51
+ */
52
+ protected cachedSuggestions: SearchAutocompleteSuggestion[] = [];
53
+
54
+ id(): string {
55
+ return SearchAutocompletePalette.ID;
56
+ }
57
+
58
+ /**
59
+ * The search context for the search palette. This is used to filter the suggestions
60
+ */
61
+ get searchContext(): string[] {
62
+ return [AutocompleteSuggestionProviderContext.CANVAS];
63
+ }
64
+
65
+ protected override initializeContents(containerElement: HTMLElement): void {
66
+ super.initializeContents(containerElement);
67
+
68
+ this.autocompleteWidget.inputField.placeholder = messages.search.placeholder;
69
+ containerElement.setAttribute('aria-label', messages.search.label);
70
+ }
71
+
72
+ protected async retrieveSuggestions(root: Readonly<GModelRoot>, input: string): Promise<LabeledAction[]> {
73
+ const suggestions = await this.provideSearchSuggestions(root, input);
74
+ this.cachedSuggestions = suggestions;
75
+ return suggestions.map(s => s.action);
76
+ }
77
+
78
+ protected async provideSearchSuggestions(root: Readonly<GModelRoot>, input: string): Promise<SearchAutocompleteSuggestion[]> {
79
+ return (
80
+ await Promise.all(
81
+ this.suggestionRegistry.providersForContext(this.searchContext).flatMap(provider => provider.getSuggestions(root, input))
82
+ )
83
+ )
84
+ .flat(1)
85
+ .filter(SearchAutocompleteSuggestion.is);
86
+ }
87
+
88
+ protected override async visibleSuggestionsChanged(root: Readonly<GModelRoot>, labeledActions: LabeledAction[]): Promise<void> {
89
+ await this.applyCSS(this.getHiddenElements(root, this.getSuggestionsFromLabeledActions(labeledActions)), CSS_SEARCH_HIDDEN);
90
+ await this.deleteCSS(
91
+ this.getSuggestionsFromLabeledActions(labeledActions)
92
+ .filter(s => s.element)
93
+ .map(s => s.element!),
94
+ CSS_SEARCH_HIDDEN
95
+ );
96
+ }
97
+
98
+ protected override async selectedSuggestionChanged(
99
+ root: Readonly<GModelRoot>,
100
+ labeledAction?: LabeledAction | undefined
101
+ ): Promise<void> {
102
+ await this.handleSuggestionChanged(root, labeledAction);
103
+ }
104
+
105
+ protected readonly handleSuggestionChanged = debounce(this.doHandleSuggestionChanged, 300, { trailing: true });
106
+ protected async doHandleSuggestionChanged(root: Readonly<GModelRoot>, labeledAction?: LabeledAction | undefined): Promise<void> {
107
+ await this.deleteAllCSS(root, CSS_SEARCH_HIGHLIGHTED);
108
+ if (labeledAction !== undefined) {
109
+ const suggestions = this.getSuggestionsFromLabeledActions([labeledAction]);
110
+
111
+ const actions: RepositionAction[] = [];
112
+ suggestions.map(currElem => actions.push(RepositionAction.create([currElem.element.id])));
113
+
114
+ this.actionDispatcher.dispatchAll(actions);
115
+ await this.applyCSS(
116
+ suggestions.map(s => s.element),
117
+ CSS_SEARCH_HIGHLIGHTED
118
+ );
119
+ }
120
+ }
121
+
122
+ override show(root: Readonly<GModelRoot>, ...contextElementIds: string[]): void {
123
+ this.actionDispatcher.dispatch(SelectAllAction.create(false));
124
+
125
+ super.show(root, ...contextElementIds);
126
+ }
127
+
128
+ override hide(): void {
129
+ if (this.root !== undefined) {
130
+ this.deleteAllCSS(this.root, CSS_SEARCH_HIDDEN, CSS_SEARCH_HIGHLIGHTED);
131
+ this.autocompleteWidget.inputField.value = '';
132
+ }
133
+
134
+ super.hide();
135
+ }
136
+
137
+ protected applyCSS(elements: GModelElement[], ...add: string[]): Promise<void> {
138
+ const actions = elements.map(element => applyCssClasses(element, ...add));
139
+ return this.actionDispatcher.dispatchAll(actions);
140
+ }
141
+
142
+ protected deleteCSS(elements: GModelElement[], ...remove: string[]): Promise<void> {
143
+ const actions = elements.map(element => deleteCssClasses(element, ...remove));
144
+ return this.actionDispatcher.dispatchAll(actions);
145
+ }
146
+
147
+ protected deleteAllCSS(root: Readonly<GModelRoot>, ...remove: string[]): Promise<void> {
148
+ const actions = toArray(root.index.all().map(element => deleteCssClasses(element, ...remove)));
149
+ return this.actionDispatcher.dispatchAll(actions);
150
+ }
151
+
152
+ protected getSuggestionsFromLabeledActions(labeledActions: LabeledAction[]): SearchAutocompleteSuggestion[] {
153
+ return this.cachedSuggestions.filter(c => labeledActions.find(s => isEqual(s, c.action)));
154
+ }
155
+
156
+ protected getHiddenElements(root: Readonly<GModelRoot>, suggestions: SearchAutocompleteSuggestion[]): GModelElement[] {
157
+ return toArray(
158
+ root.index
159
+ .all()
160
+ .filter(element => element instanceof GNode || element instanceof GEdge)
161
+ .filter(element => suggestions.find(suggestion => suggestion.element.id === element.id) === undefined)
162
+ );
163
+ }
164
+ }
@@ -0,0 +1,71 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2023-2025 Business Informatics Group (TU Wien) 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, CenterAction, GModelRoot, SelectAction, codiconCSSString, name, toArray } from '@eclipse-glsp/sprotty';
18
+ import { injectable } from 'inversify';
19
+ import {
20
+ AutocompleteSuggestionProviderContext,
21
+ IAutocompleteSuggestionProvider,
22
+ type AutocompleteSuggestion
23
+ } from '../../../base/auto-complete/autocomplete-suggestion-provider';
24
+ import { GEdge } from '../../../model';
25
+
26
+ @injectable()
27
+ export class RevealEdgeElementSuggestionProvider implements IAutocompleteSuggestionProvider {
28
+ get id(): string {
29
+ return 'glsp.reveal-edge-element-suggestion';
30
+ }
31
+
32
+ canHandle(context: string): boolean {
33
+ return context === AutocompleteSuggestionProviderContext.CANVAS;
34
+ }
35
+
36
+ async getSuggestions(root: Readonly<GModelRoot>, text: string): Promise<AutocompleteSuggestion[]> {
37
+ const edges = toArray(root.index.all().filter(element => element instanceof GEdge)) as GEdge[];
38
+ return edges.map(edge => ({
39
+ element: edge,
40
+ action: {
41
+ label: `[${edge.type}] ${this.getEdgeLabel(root, edge)}`,
42
+ actions: this.createActions(edge),
43
+ icon: codiconCSSString('arrow-both')
44
+ }
45
+ }));
46
+ }
47
+
48
+ protected createActions(edge: GEdge): Action[] {
49
+ return [
50
+ SelectAction.create({ selectedElementsIDs: [edge.id] }),
51
+ CenterAction.create([edge.sourceId, edge.targetId], { retainZoom: true })
52
+ ];
53
+ }
54
+
55
+ protected getEdgeLabel(root: Readonly<GModelRoot>, edge: GEdge): string {
56
+ let sourceName = '';
57
+ let targetName = '';
58
+
59
+ const sourceNode = root.index.getById(edge.sourceId);
60
+ const targetNode = root.index.getById(edge.targetId);
61
+
62
+ if (sourceNode !== undefined) {
63
+ sourceName = name(sourceNode) ?? sourceNode.type;
64
+ }
65
+ if (targetNode !== undefined) {
66
+ targetName = name(targetNode) ?? targetNode.type;
67
+ }
68
+
69
+ return sourceName + ' -> ' + targetName;
70
+ }
71
+ }
@@ -0,0 +1,88 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2023-2025 Business Informatics Group (TU Wien) 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
+ CenterAction,
20
+ codiconCSSString,
21
+ GModelElement,
22
+ GModelRoot,
23
+ GNode,
24
+ isNameable,
25
+ name,
26
+ SelectAction,
27
+ toArray
28
+ } from '@eclipse-glsp/sprotty';
29
+ import { injectable } from 'inversify';
30
+ import {
31
+ AutocompleteSuggestionProviderContext,
32
+ IAutocompleteSuggestionProvider,
33
+ type AutocompleteSuggestion
34
+ } from '../../../base/auto-complete/autocomplete-suggestion-provider';
35
+
36
+ @injectable()
37
+ export class RevealNamedElementSuggestionProvider implements IAutocompleteSuggestionProvider {
38
+ get id(): string {
39
+ return 'glsp.reveal-named-element-suggestion';
40
+ }
41
+
42
+ canHandle(context: string): boolean {
43
+ return context === AutocompleteSuggestionProviderContext.CANVAS;
44
+ }
45
+
46
+ async getSuggestions(root: Readonly<GModelRoot>, text: string): Promise<AutocompleteSuggestion[]> {
47
+ const nameables = toArray(root.index.all().filter(element => isNameable(element)));
48
+ return nameables.map(nameable => ({
49
+ element: nameable,
50
+ action: {
51
+ label: `[${nameable.type}] ${name(nameable) ?? '<no-name>'}`,
52
+ actions: this.createActions(nameable),
53
+ icon: codiconCSSString('eye')
54
+ }
55
+ }));
56
+ }
57
+
58
+ protected createActions(nameable: GModelElement): Action[] {
59
+ return [SelectAction.create({ selectedElementsIDs: [nameable.id] }), CenterAction.create([nameable.id], { retainZoom: true })];
60
+ }
61
+ }
62
+
63
+ @injectable()
64
+ export class NodesWithoutNameSuggestionProvider implements IAutocompleteSuggestionProvider {
65
+ get id(): string {
66
+ return 'glsp.reveal-nodes-without-name-suggestion';
67
+ }
68
+
69
+ canHandle(searchContext: string): boolean {
70
+ return searchContext === AutocompleteSuggestionProviderContext.CANVAS;
71
+ }
72
+
73
+ async getSuggestions(root: Readonly<GModelRoot>, text: string): Promise<AutocompleteSuggestion[]> {
74
+ const nodes = toArray(root.index.all().filter(element => !isNameable(element) && element instanceof GNode));
75
+ return nodes.map(node => ({
76
+ element: node,
77
+ action: {
78
+ label: `[${node.type}]`,
79
+ actions: this.createActions(node),
80
+ icon: codiconCSSString('symbol-namespace')
81
+ }
82
+ }));
83
+ }
84
+
85
+ protected createActions(nameable: GModelElement): Action[] {
86
+ return [SelectAction.create({ selectedElementsIDs: [nameable.id] }), CenterAction.create([nameable.id], { retainZoom: true })];
87
+ }
88
+ }
@@ -70,13 +70,7 @@ export class RepositionCommand extends BoundsAwareViewportCommand {
70
70
  if (element instanceof GChildElement && element.parent !== viewport) {
71
71
  return this.boundsInViewport(element.parent, element.parent.localToParent(bounds) as Bounds, viewport);
72
72
  } else if (element instanceof GEdge) {
73
- const edgeBounds = getRouteBounds(calcElementAndRoute(element).newRoutingPoints ?? []);
74
-
75
- if (element instanceof GChildElement && element.parent !== viewport) {
76
- return this.boundsInViewport(element.parent, element.parent.localToParent(edgeBounds), viewport);
77
- }
78
-
79
- return edgeBounds;
73
+ return getRouteBounds(calcElementAndRoute(element).newRoutingPoints ?? []);
80
74
  }
81
75
 
82
76
  return bounds;