@eclipse-glsp/client 1.1.0-next.697cc23.237 → 1.1.0-next.6c2f3cc.244

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 (87) hide show
  1. package/{lib/features/change-bounds/snap.spec.d.ts → css/autocomplete-palette.css} +8 -3
  2. package/css/glsp-sprotty.css +16 -1
  3. package/lib/base/auto-complete/auto-complete-widget.d.ts +8 -2
  4. package/lib/base/auto-complete/auto-complete-widget.d.ts.map +1 -1
  5. package/lib/base/auto-complete/auto-complete-widget.js +25 -6
  6. package/lib/base/auto-complete/auto-complete-widget.js.map +1 -1
  7. package/lib/features/accessibility/di.config.d.ts +21 -0
  8. package/lib/features/accessibility/di.config.d.ts.map +1 -0
  9. package/lib/features/accessibility/di.config.js +28 -0
  10. package/lib/features/accessibility/di.config.js.map +1 -0
  11. package/lib/features/accessibility/search/di.config.d.ts +20 -0
  12. package/lib/features/accessibility/search/di.config.d.ts.map +1 -0
  13. package/lib/features/accessibility/search/di.config.js +33 -0
  14. package/lib/features/accessibility/search/di.config.js.map +1 -0
  15. package/lib/features/accessibility/search/search-palette.d.ts +47 -0
  16. package/lib/features/accessibility/search/search-palette.d.ts.map +1 -0
  17. package/lib/features/accessibility/search/search-palette.js +155 -0
  18. package/lib/features/accessibility/search/search-palette.js.map +1 -0
  19. package/lib/features/accessibility/search/search-tool.d.ts +30 -0
  20. package/lib/features/accessibility/search/search-tool.d.ts.map +1 -0
  21. package/lib/features/accessibility/search/search-tool.js +73 -0
  22. package/lib/features/accessibility/search/search-tool.js.map +1 -0
  23. package/lib/features/autocomplete-palette/autocomplete-suggestion-providers.d.ts +35 -0
  24. package/lib/features/autocomplete-palette/autocomplete-suggestion-providers.d.ts.map +1 -0
  25. package/lib/features/{tools/marquee-behavior.spec.d.ts → autocomplete-palette/autocomplete-suggestion-providers.js} +4 -3
  26. package/lib/features/autocomplete-palette/autocomplete-suggestion-providers.js.map +1 -0
  27. package/lib/features/autocomplete-palette/base-autocomplete-palette.d.ts +41 -0
  28. package/lib/features/autocomplete-palette/base-autocomplete-palette.d.ts.map +1 -0
  29. package/lib/features/autocomplete-palette/base-autocomplete-palette.js +82 -0
  30. package/lib/features/autocomplete-palette/base-autocomplete-palette.js.map +1 -0
  31. package/lib/features/tool-feedback/creation-tool-feedback.d.ts +1 -1
  32. package/lib/features/tool-feedback/creation-tool-feedback.js +1 -1
  33. package/lib/features/tool-feedback/edge-edit-tool-feedback.d.ts +1 -1
  34. package/lib/features/tool-feedback/edge-edit-tool-feedback.js +1 -1
  35. package/lib/index.d.ts +5 -3
  36. package/lib/index.d.ts.map +1 -1
  37. package/lib/index.js +52 -48
  38. package/lib/index.js.map +1 -1
  39. package/package.json +5 -3
  40. package/src/base/auto-complete/auto-complete-widget.ts +31 -7
  41. package/src/features/accessibility/di.config.ts +26 -0
  42. package/src/features/accessibility/search/di.config.ts +31 -0
  43. package/src/features/accessibility/search/search-palette.ts +181 -0
  44. package/src/features/accessibility/search/search-tool.ts +60 -0
  45. package/src/features/autocomplete-palette/autocomplete-suggestion-providers.ts +37 -0
  46. package/src/features/autocomplete-palette/base-autocomplete-palette.ts +88 -0
  47. package/src/features/tool-feedback/creation-tool-feedback.ts +1 -1
  48. package/src/features/tool-feedback/edge-edit-tool-feedback.ts +1 -1
  49. package/src/index.ts +7 -3
  50. package/lib/features/bounds/freeform-layout.spec.d.ts +0 -3
  51. package/lib/features/bounds/freeform-layout.spec.d.ts.map +0 -1
  52. package/lib/features/bounds/freeform-layout.spec.js +0 -201
  53. package/lib/features/bounds/freeform-layout.spec.js.map +0 -1
  54. package/lib/features/bounds/hbox-layout.spec.d.ts +0 -3
  55. package/lib/features/bounds/hbox-layout.spec.d.ts.map +0 -1
  56. package/lib/features/bounds/hbox-layout.spec.js +0 -161
  57. package/lib/features/bounds/hbox-layout.spec.js.map +0 -1
  58. package/lib/features/bounds/layouter-test-util.spec.d.ts +0 -33
  59. package/lib/features/bounds/layouter-test-util.spec.d.ts.map +0 -1
  60. package/lib/features/bounds/layouter-test-util.spec.js +0 -96
  61. package/lib/features/bounds/layouter-test-util.spec.js.map +0 -1
  62. package/lib/features/bounds/vbox-layout.spec.d.ts +0 -3
  63. package/lib/features/bounds/vbox-layout.spec.d.ts.map +0 -1
  64. package/lib/features/bounds/vbox-layout.spec.js +0 -161
  65. package/lib/features/bounds/vbox-layout.spec.js.map +0 -1
  66. package/lib/features/change-bounds/snap.spec.d.ts.map +0 -1
  67. package/lib/features/change-bounds/snap.spec.js +0 -82
  68. package/lib/features/change-bounds/snap.spec.js.map +0 -1
  69. package/lib/features/layout/layout-elements-action.spec.d.ts +0 -3
  70. package/lib/features/layout/layout-elements-action.spec.d.ts.map +0 -1
  71. package/lib/features/layout/layout-elements-action.spec.js +0 -325
  72. package/lib/features/layout/layout-elements-action.spec.js.map +0 -1
  73. package/lib/features/navigation/navigation-target-resolver.spec.d.ts +0 -3
  74. package/lib/features/navigation/navigation-target-resolver.spec.d.ts.map +0 -1
  75. package/lib/features/navigation/navigation-target-resolver.spec.js +0 -54
  76. package/lib/features/navigation/navigation-target-resolver.spec.js.map +0 -1
  77. package/lib/features/select/selection-service.spec.d.ts +0 -2
  78. package/lib/features/select/selection-service.spec.d.ts.map +0 -1
  79. package/lib/features/select/selection-service.spec.js +0 -363
  80. package/lib/features/select/selection-service.spec.js.map +0 -1
  81. package/lib/features/tools/marquee-behavior.spec.d.ts.map +0 -1
  82. package/lib/features/tools/marquee-behavior.spec.js +0 -165
  83. package/lib/features/tools/marquee-behavior.spec.js.map +0 -1
  84. package/lib/features/validation/marker-navigator.spec.d.ts +0 -3
  85. package/lib/features/validation/marker-navigator.spec.d.ts.map +0 -1
  86. package/lib/features/validation/marker-navigator.spec.js +0 -169
  87. package/lib/features/validation/marker-navigator.spec.js.map +0 -1
@@ -28,6 +28,7 @@ export interface AutoCompleteSettings {
28
28
  readonly showOnFocus?: boolean;
29
29
  }
30
30
 
31
+ export type CloseReason = 'submission' | 'blur' | 'escape';
31
32
  export interface InputValidator {
32
33
  validate(input: string): Promise<ValidationStatus>;
33
34
  }
@@ -48,6 +49,11 @@ export interface TextSubmitHandler {
48
49
  executeFromTextOnlyInput(input: string): void;
49
50
  }
50
51
 
52
+ export interface AutoCompleteWidgetOptions {
53
+ visibleSuggestionsChanged?: (suggestions: LabeledAction[]) => void;
54
+ selectedSuggestionChanged?: (suggestion?: LabeledAction) => void;
55
+ }
56
+
51
57
  // eslint-disable-next-line @typescript-eslint/no-var-requires
52
58
  const configureAutocomplete: (settings: AutocompleteSettings<LabeledAction>) => AutocompleteResult = require('autocompleter');
53
59
 
@@ -78,8 +84,9 @@ export class AutoCompleteWidget {
78
84
  public suggestionProvider: SuggestionProvider,
79
85
  public suggestionSubmitHandler: SuggestionSubmitHandler,
80
86
  // eslint-disable-next-line @typescript-eslint/no-empty-function
81
- protected notifyClose: () => void = () => {},
82
- protected logger?: ILogger
87
+ protected notifyClose: (reason: CloseReason) => void = () => {},
88
+ protected logger?: ILogger,
89
+ protected options?: AutoCompleteWidgetOptions
83
90
  ) {}
84
91
 
85
92
  configureValidation(
@@ -109,13 +116,18 @@ export class AutoCompleteWidget {
109
116
  inputElement.autocomplete = 'false';
110
117
  inputElement.style.width = '100%';
111
118
  inputElement.addEventListener('keydown', event => this.handleKeyDown(event));
112
- inputElement.addEventListener('blur', () => window.setTimeout(() => this.notifyClose(), 200));
119
+ inputElement.addEventListener('blur', () => {
120
+ if (this.containerElement.style.visibility !== 'hidden') {
121
+ window.setTimeout(() => this.notifyClose('blur'), 200);
122
+ }
123
+ });
124
+
113
125
  return inputElement;
114
126
  }
115
127
 
116
128
  protected handleKeyDown(event: KeyboardEvent): void {
117
129
  if (matchesKeystroke(event, 'Escape')) {
118
- this.notifyClose();
130
+ this.notifyClose('escape');
119
131
  return;
120
132
  }
121
133
  if (matchesKeystroke(event, 'Enter') && !this.isInputElementChanged() && this.isSuggestionAvailable()) {
@@ -133,7 +145,7 @@ export class AutoCompleteWidget {
133
145
  }
134
146
  if (this.textSubmitHandler) {
135
147
  this.executeFromTextOnlyInput();
136
- this.notifyClose();
148
+ this.notifyClose('submission');
137
149
  }
138
150
  }
139
151
 
@@ -175,6 +187,17 @@ export class AutoCompleteWidget {
175
187
  // move container into our UIExtension container as this is already positioned correctly
176
188
  if (this.containerElement) {
177
189
  this.containerElement.appendChild(container);
190
+
191
+ if (this.options && this.options.selectedSuggestionChanged) {
192
+ const selectedElement = container.querySelector('.selected');
193
+ // eslint-disable-next-line no-null/no-null
194
+ if (selectedElement !== null && selectedElement !== undefined) {
195
+ const index = Array.from(container.children).indexOf(selectedElement);
196
+ this.options.selectedSuggestionChanged(this.contextActions?.[index]);
197
+ } else {
198
+ this.options.selectedSuggestionChanged(undefined);
199
+ }
200
+ }
178
201
  }
179
202
  }
180
203
 
@@ -189,6 +212,7 @@ export class AutoCompleteWidget {
189
212
  .then(actions => {
190
213
  this.contextActions = this.filterActions(text, actions);
191
214
  update(this.contextActions);
215
+ this.options?.visibleSuggestionsChanged?.(this.contextActions);
192
216
  this.onLoaded('success');
193
217
  })
194
218
  .catch(reason => {
@@ -228,7 +252,7 @@ export class AutoCompleteWidget {
228
252
  if (item.icon) {
229
253
  this.renderIcon(itemElement, item.icon);
230
254
  }
231
- itemElement.innerHTML += item.label.replace(regex, match => '<em>' + match + '</em>');
255
+ itemElement.innerHTML += item.label.replace(regex, match => '<em>' + match + '</em>').replace(/ /g, '&nbsp;');
232
256
  return itemElement;
233
257
  }
234
258
 
@@ -257,7 +281,7 @@ export class AutoCompleteWidget {
257
281
  window.setTimeout(() => this.inputElement.dispatchEvent(new Event('keyup')));
258
282
  } else {
259
283
  this.executeFromSuggestion(item);
260
- this.notifyClose();
284
+ this.notifyClose('submission');
261
285
  }
262
286
  }
263
287
 
@@ -0,0 +1,26 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2023 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 { ContainerModule } from 'inversify';
18
+ import { configureSearchPaletteModule } from './search/di.config';
19
+
20
+ /**
21
+ * Enables the accessibility tools for a keyboard-only-usage
22
+ */
23
+ export const glspAccessibilityModule = new ContainerModule((bind, _unbind, isBound, rebind) => {
24
+ const context = { bind, isBound, rebind };
25
+ configureSearchPaletteModule(context);
26
+ });
@@ -0,0 +1,31 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2023 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, BindingContext } from '@eclipse-glsp/protocol';
18
+ import { ContainerModule } from 'inversify';
19
+ import { TYPES } from '../../../base/types';
20
+ import { SearchAutocompletePalette } from './search-palette';
21
+ import { SearchAutocompletePaletteTool } from './search-tool';
22
+
23
+ export const glspSearchPaletteModule = new ContainerModule((bind, _unbind, isBound, rebind) => {
24
+ const context = { bind, isBound, rebind };
25
+ configureSearchPaletteModule(context);
26
+ });
27
+
28
+ export function configureSearchPaletteModule(context: Pick<BindingContext, 'bind'>): void {
29
+ bindAsService(context, TYPES.IUIExtension, SearchAutocompletePalette);
30
+ bindAsService(context, TYPES.IDefaultTool, SearchAutocompletePaletteTool);
31
+ }
@@ -0,0 +1,181 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2023 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, SelectAction, SelectAllAction } from '@eclipse-glsp/protocol';
18
+ import { injectable } from 'inversify';
19
+ import { isEqual } from 'lodash';
20
+ import { codiconCSSString, isNameable, LabeledAction, name, SEdge, SModelElement, SModelRoot, SNode } from 'sprotty';
21
+ import { toArray } from 'sprotty/lib/utils/iterable';
22
+ import { AutocompleteSuggestion, IAutocompleteSuggestionProvider } from '../../autocomplete-palette/autocomplete-suggestion-providers';
23
+ import { BaseAutocompletePalette } from '../../autocomplete-palette/base-autocomplete-palette';
24
+
25
+ import { applyCssClasses, deleteCssClasses } from '../../tool-feedback/css-feedback';
26
+
27
+ const CSS_SEARCH_HIDDEN = 'search-hidden';
28
+ const CSS_SEARCH_HIGHLIGHTED = 'search-highlighted';
29
+
30
+ export class RevealNamedElementAutocompleteSuggestionProvider implements IAutocompleteSuggestionProvider {
31
+ async retrieveSuggestions(root: Readonly<SModelRoot>, text: string): Promise<AutocompleteSuggestion[]> {
32
+ const nameables = toArray(root.index.all().filter(element => isNameable(element)));
33
+ return nameables.map(nameable => ({
34
+ element: nameable,
35
+ action: new LabeledAction(
36
+ `[${nameable.type}] ${name(nameable) ?? '<no-name>'}`,
37
+ this.getActions(nameable),
38
+ codiconCSSString('eye')
39
+ )
40
+ }));
41
+ }
42
+
43
+ protected getActions(nameable: SModelElement): Action[] {
44
+ return [SelectAction.create({ selectedElementsIDs: [nameable.id] }), CenterAction.create([nameable.id], { retainZoom: true })];
45
+ }
46
+ }
47
+
48
+ export class RevealEdgeElementAutocompleteSuggestionProvider implements IAutocompleteSuggestionProvider {
49
+ async retrieveSuggestions(root: Readonly<SModelRoot>, text: string): Promise<AutocompleteSuggestion[]> {
50
+ const edges = toArray(root.index.all().filter(element => element instanceof SEdge)) as SEdge[];
51
+ return edges.map(edge => ({
52
+ element: edge,
53
+ action: new LabeledAction(
54
+ `[${edge.type}] ` + this.getEdgeLabel(root, edge),
55
+ this.getActions(edge),
56
+ codiconCSSString('arrow-both')
57
+ )
58
+ }));
59
+ }
60
+ protected getActions(edge: SEdge): Action[] {
61
+ return [SelectAction.create({ selectedElementsIDs: [edge.id] }), CenterAction.create([edge.sourceId, edge.targetId])];
62
+ }
63
+ protected getEdgeLabel(root: Readonly<SModelRoot>, edge: SEdge): string {
64
+ let sourceName = '';
65
+ let targetName = '';
66
+
67
+ const sourceNode = root.index.getById(edge.sourceId);
68
+ const targetNode = root.index.getById(edge.targetId);
69
+
70
+ if (sourceNode !== undefined) {
71
+ sourceName = name(sourceNode) ?? sourceNode.type;
72
+ }
73
+ if (targetNode !== undefined) {
74
+ targetName = name(targetNode) ?? targetNode.type;
75
+ }
76
+
77
+ return sourceName + ' -> ' + targetName;
78
+ }
79
+ }
80
+ @injectable()
81
+ export class SearchAutocompletePalette extends BaseAutocompletePalette {
82
+ static readonly ID = 'search-autocomplete-palette';
83
+
84
+ protected cachedSuggestions: AutocompleteSuggestion[] = [];
85
+
86
+ id(): string {
87
+ return SearchAutocompletePalette.ID;
88
+ }
89
+
90
+ protected override initializeContents(containerElement: HTMLElement): void {
91
+ super.initializeContents(containerElement);
92
+
93
+ this.autocompleteWidget.inputField.placeholder = 'Search for elements';
94
+ }
95
+ protected getSuggestionProviders(root: Readonly<SModelRoot>, input: string): IAutocompleteSuggestionProvider[] {
96
+ return [new RevealNamedElementAutocompleteSuggestionProvider(), new RevealEdgeElementAutocompleteSuggestionProvider()];
97
+ }
98
+ protected async retrieveSuggestions(root: Readonly<SModelRoot>, input: string): Promise<LabeledAction[]> {
99
+ const providers = this.getSuggestionProviders(root, input);
100
+ const suggestions = (await Promise.all(providers.map(provider => provider.retrieveSuggestions(root, input)))).flat(1);
101
+
102
+ this.cachedSuggestions = suggestions;
103
+
104
+ return suggestions.map(s => s.action);
105
+ }
106
+
107
+ protected override async visibleSuggestionsChanged(root: Readonly<SModelRoot>, labeledActions: LabeledAction[]): Promise<void> {
108
+ await this.applyCSS(this.getHiddenElements(root, this.getSuggestionsFromLabeledActions(labeledActions)), CSS_SEARCH_HIDDEN);
109
+ await this.deleteCSS(
110
+ this.getSuggestionsFromLabeledActions(labeledActions).map(s => s.element),
111
+ CSS_SEARCH_HIDDEN
112
+ );
113
+ }
114
+
115
+ protected override async selectedSuggestionChanged(
116
+ root: Readonly<SModelRoot>,
117
+ labeledAction?: LabeledAction | undefined
118
+ ): Promise<void> {
119
+ await this.deleteAllCSS(root, CSS_SEARCH_HIGHLIGHTED);
120
+ if (labeledAction !== undefined) {
121
+ const suggestions = this.getSuggestionsFromLabeledActions([labeledAction]);
122
+
123
+ const actions: CenterAction[] = [];
124
+ suggestions.map(currElem => actions.push(CenterAction.create([currElem.element.id], { animate: true, retainZoom: true })));
125
+
126
+ this.actionDispatcher.dispatchAll(actions);
127
+ await this.applyCSS(
128
+ suggestions.map(s => s.element),
129
+ CSS_SEARCH_HIGHLIGHTED
130
+ );
131
+ }
132
+ }
133
+
134
+ public override show(root: Readonly<SModelRoot>, ...contextElementIds: string[]): void {
135
+ this.actionDispatcher.dispatch(SelectAllAction.create(false));
136
+
137
+ super.show(root, ...contextElementIds);
138
+ }
139
+
140
+ public override hide(): void {
141
+ if (this.root !== undefined) {
142
+ this.deleteAllCSS(this.root, CSS_SEARCH_HIDDEN);
143
+ this.deleteAllCSS(this.root, CSS_SEARCH_HIGHLIGHTED);
144
+ this.autocompleteWidget.inputField.value = '';
145
+ }
146
+
147
+ super.hide();
148
+ }
149
+
150
+ protected applyCSS(elements: SModelElement[], cssClass: string): Promise<void> {
151
+ const actions = elements.map(element => applyCssClasses(element, cssClass));
152
+ return this.actionDispatcher.dispatchAll(actions);
153
+ }
154
+
155
+ protected deleteCSS(elements: SModelElement[], cssClass: string): Promise<void> {
156
+ const actions = elements.map(element => deleteCssClasses(element, cssClass));
157
+ return this.actionDispatcher.dispatchAll(actions);
158
+ }
159
+
160
+ protected deleteAllCSS(root: Readonly<SModelRoot>, cssClass: string): Promise<void> {
161
+ const actions = toArray(root.index.all().map(element => deleteCssClasses(element, cssClass)));
162
+ return this.actionDispatcher.dispatchAll(actions);
163
+ }
164
+
165
+ protected getSuggestionsFromLabeledActions(labeledActions: LabeledAction[]): AutocompleteSuggestion[] {
166
+ return this.cachedSuggestions.filter(c => labeledActions.find(s => isEqual(s, c.action)));
167
+ }
168
+
169
+ protected getHiddenSuggestionsFromLabeledActions(labeledActions: LabeledAction[]): AutocompleteSuggestion[] {
170
+ return this.cachedSuggestions.filter(c => !labeledActions.find(s => isEqual(s, c.action)));
171
+ }
172
+
173
+ protected getHiddenElements(root: Readonly<SModelRoot>, suggestions: AutocompleteSuggestion[]): SModelElement[] {
174
+ return toArray(
175
+ root.index
176
+ .all()
177
+ .filter(element => element instanceof SNode || element instanceof SEdge)
178
+ .filter(element => suggestions.find(suggestion => suggestion.element.id === element.id) === undefined)
179
+ );
180
+ }
181
+ }
@@ -0,0 +1,60 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2023 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 } from '@eclipse-glsp/protocol';
18
+ import { inject, injectable } from 'inversify';
19
+ import { KeyListener, KeyTool, SetUIExtensionVisibilityAction, SModelElement, Tool } from 'sprotty';
20
+ import { matchesKeystroke } from 'sprotty/lib/utils/keyboard';
21
+ import { SearchAutocompletePalette } from './search-palette';
22
+
23
+ @injectable()
24
+ export class SearchAutocompletePaletteTool implements Tool {
25
+ static readonly ID = 'glsp.search-autocomplete-palette-tool';
26
+
27
+ protected readonly keyListener = new SearchAutocompletePaletteKeyListener();
28
+
29
+ @inject(KeyTool) protected keyTool: KeyTool;
30
+
31
+ get id(): string {
32
+ return SearchAutocompletePaletteTool.ID;
33
+ }
34
+
35
+ enable(): void {
36
+ this.keyTool.register(this.keyListener);
37
+ }
38
+
39
+ disable(): void {
40
+ this.keyTool.deregister(this.keyListener);
41
+ }
42
+ }
43
+
44
+ export class SearchAutocompletePaletteKeyListener extends KeyListener {
45
+ override keyDown(element: SModelElement, event: KeyboardEvent): Action[] {
46
+ if (this.matchesSearchActivateKeystroke(event)) {
47
+ return [
48
+ SetUIExtensionVisibilityAction.create({
49
+ extensionId: SearchAutocompletePalette.ID,
50
+ visible: true
51
+ })
52
+ ];
53
+ }
54
+ return [];
55
+ }
56
+
57
+ protected matchesSearchActivateKeystroke(event: KeyboardEvent): boolean {
58
+ return matchesKeystroke(event, 'KeyF', 'ctrl');
59
+ }
60
+ }
@@ -0,0 +1,37 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2023 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 { LabeledAction, SModelElement, SModelRoot } from 'sprotty';
18
+
19
+ /**
20
+ * Interface for a provider that provides suggestions that can be used to fill the autocomplete
21
+ */
22
+ export interface IAutocompleteSuggestionProvider {
23
+ /**
24
+ * Returns the suggestions based on the provided parameters.
25
+ * @param root: The root model
26
+ * @param text: The text input provided by the user.
27
+ */
28
+ retrieveSuggestions(root: Readonly<SModelRoot>, text: string): Promise<AutocompleteSuggestion[]>;
29
+ }
30
+
31
+ /**
32
+ * Interface for autocomplete suggestions.
33
+ */
34
+ export interface AutocompleteSuggestion {
35
+ element: SModelElement;
36
+ action: LabeledAction;
37
+ }
@@ -0,0 +1,88 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2023 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 } from '@eclipse-glsp/protocol';
18
+ import { inject } from 'inversify';
19
+ import { AbstractUIExtension, LabeledAction, SModelRoot, TYPES } from 'sprotty';
20
+ import '../../../css/autocomplete-palette.css';
21
+ import { GLSPActionDispatcher } from '../../base/action-dispatcher';
22
+ import { AutoCompleteWidget, CloseReason, toActionArray } from '../../base/auto-complete/auto-complete-widget';
23
+
24
+ export abstract class BaseAutocompletePalette extends AbstractUIExtension {
25
+ protected readonly autoSuggestionSettings = {
26
+ noSuggestionsMessage: 'No suggestions available',
27
+ suggestionsClass: 'command-palette-suggestions',
28
+ debounceWaitMs: 50,
29
+ showOnFocus: true
30
+ };
31
+
32
+ protected root?: Readonly<SModelRoot>;
33
+ protected autocompleteWidget: AutoCompleteWidget;
34
+
35
+ @inject(TYPES.IActionDispatcher)
36
+ protected actionDispatcher: GLSPActionDispatcher;
37
+
38
+ containerClass(): string {
39
+ return 'autocomplete-palette';
40
+ }
41
+
42
+ override show(root: Readonly<SModelRoot>, ...contextElementIds: string[]): void {
43
+ super.show(root, ...contextElementIds);
44
+ this.root = root;
45
+ this.autocompleteWidget.open(root);
46
+ }
47
+
48
+ override hide(): void {
49
+ this.autocompleteWidget.dispose();
50
+ this.root = undefined;
51
+ super.hide();
52
+ }
53
+
54
+ protected initializeContents(containerElement: HTMLElement): void {
55
+ containerElement.classList.add('command-palette');
56
+
57
+ this.autocompleteWidget = new AutoCompleteWidget(
58
+ this.autoSuggestionSettings,
59
+ { provideSuggestions: input => this.retrieveSuggestions(this.root!, input) },
60
+ { executeFromSuggestion: input => this.executeSuggestion(input) },
61
+ reason => this.autocompleteHide(reason),
62
+ this.logger,
63
+ {
64
+ visibleSuggestionsChanged: suggestions => this.visibleSuggestionsChanged(this.root!, suggestions),
65
+ selectedSuggestionChanged: suggestion => this.selectedSuggestionChanged(this.root!, suggestion)
66
+ }
67
+ );
68
+ this.autocompleteWidget.initialize(containerElement);
69
+ }
70
+
71
+ protected abstract retrieveSuggestions(root: Readonly<SModelRoot>, input: string): Promise<LabeledAction[]>;
72
+
73
+ protected async visibleSuggestionsChanged(root: Readonly<SModelRoot>, labeledActions: LabeledAction[]): Promise<void> {
74
+ return;
75
+ }
76
+
77
+ protected async selectedSuggestionChanged(root: Readonly<SModelRoot>, labeledAction?: LabeledAction): Promise<void> {
78
+ return;
79
+ }
80
+
81
+ protected autocompleteHide(reason: CloseReason): void {
82
+ this.hide();
83
+ }
84
+
85
+ protected executeSuggestion(input: LabeledAction | Action[] | Action): void {
86
+ this.actionDispatcher.dispatchAll(toActionArray(input));
87
+ }
88
+ }
@@ -1,5 +1,5 @@
1
1
  /********************************************************************************
2
- * Copyright (c) 2019-2022 EclipseSource and others.
2
+ * Copyright (c) 2019-2023 EclipseSource and others.
3
3
  *
4
4
  * This program and the accompanying materials are made available under the
5
5
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -1,5 +1,5 @@
1
1
  /********************************************************************************
2
- * Copyright (c) 2019-2022 EclipseSource and others.
2
+ * Copyright (c) 2019-2023 EclipseSource and others.
3
3
  *
4
4
  * This program and the accompanying materials are made available under the
5
5
  * terms of the Eclipse Public License v. 2.0 which is available at
package/src/index.ts CHANGED
@@ -14,11 +14,12 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
  import defaultGLSPModule from './base/di.config';
17
+ import { glspAccessibilityModule } from './features/accessibility/di.config';
18
+ import { glspSearchPaletteModule } from './features/accessibility/search/di.config';
17
19
  import glspCommandPaletteModule from './features/command-palette/di.config';
18
20
  import glspContextMenuModule from './features/context-menu/di.config';
19
21
  import { copyPasteContextMenuModule, glspServerCopyPasteModule } from './features/copy-paste/di.config';
20
22
  import glspDecorationModule from './features/decoration/di.config';
21
- import svgMetadataModule from './features/svg-metadata/di.config';
22
23
  import glspEditLabelModule from './features/edit-label/di.config';
23
24
  import modelHintsModule from './features/hints/di.config';
24
25
  import glspHoverModule from './features/hover/di.config';
@@ -28,6 +29,7 @@ import navigationModule from './features/navigation/di.config';
28
29
  import saveModule from './features/save/di.config';
29
30
  import glspSelectModule from './features/select/di.config';
30
31
  import sourceModelWatcherModule from './features/source-model-watcher/di.config';
32
+ import svgMetadataModule from './features/svg-metadata/di.config';
31
33
  import toolFeedbackModule from './features/tool-feedback/di.config';
32
34
  import paletteModule from './features/tool-palette/di.config';
33
35
  import { enableDefaultToolsOnFocusLossModule, toolsModule } from './features/tools/di.config';
@@ -74,7 +76,6 @@ export * from './features/context-menu/server-context-menu-provider';
74
76
  export * from './features/copy-paste/copy-paste-context-menu';
75
77
  export * from './features/copy-paste/copy-paste-handler';
76
78
  export * from './features/decoration/decoration-placer';
77
- export * from './features/svg-metadata/metadata-placer';
78
79
  export * from './features/edit-label/edit-label-tool';
79
80
  export * from './features/edit-label/edit-label-validator';
80
81
  export * from './features/export/glsp-svg-exporter';
@@ -93,6 +94,7 @@ export * from './features/select/select-feedback-action';
93
94
  export * from './features/select/select-mouse-listener';
94
95
  export * from './features/select/selection-service';
95
96
  export * from './features/source-model-watcher/source-model-changed-action-handler';
97
+ export * from './features/svg-metadata/metadata-placer';
96
98
  export * from './features/tool-feedback/change-bounds-tool-feedback';
97
99
  export * from './features/tool-feedback/creation-tool-feedback';
98
100
  export * from './features/tool-feedback/css-feedback';
@@ -154,5 +156,7 @@ export {
154
156
  sourceModelWatcherModule,
155
157
  markerNavigatorContextMenuModule,
156
158
  glspViewportModule,
157
- svgMetadataModule
159
+ svgMetadataModule,
160
+ glspSearchPaletteModule,
161
+ glspAccessibilityModule
158
162
  };
@@ -1,3 +0,0 @@
1
- import 'mocha';
2
- import 'reflect-metadata';
3
- //# sourceMappingURL=freeform-layout.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"freeform-layout.spec.d.ts","sourceRoot":"","sources":["../../../src/features/bounds/freeform-layout.spec.ts"],"names":[],"mappings":"AAgBA,OAAO,OAAO,CAAC;AACf,OAAO,kBAAkB,CAAC"}