@theia/core 1.76.0-next.28 → 1.76.0-next.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/catalog.json +92 -80
- package/lib/browser/frontend-application-module.d.ts.map +1 -1
- package/lib/browser/frontend-application-module.js +2 -0
- package/lib/browser/frontend-application-module.js.map +1 -1
- package/lib/browser/index.d.ts +1 -0
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +1 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/resource-context-key.d.ts +25 -0
- package/lib/browser/resource-context-key.d.ts.map +1 -1
- package/lib/browser/resource-context-key.js +41 -16
- package/lib/browser/resource-context-key.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts +7 -5
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js +13 -12
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts +11 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js +38 -3
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts +2 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +4 -2
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js +123 -2
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.d.ts +12 -4
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.js +2 -2
- package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.js.map +1 -1
- package/lib/browser/view-container.d.ts.map +1 -1
- package/lib/browser/view-container.js +2 -2
- package/lib/browser/view-container.js.map +1 -1
- package/lib/browser/widget-context-key-contribution.d.ts +17 -0
- package/lib/browser/widget-context-key-contribution.d.ts.map +1 -0
- package/lib/browser/widget-context-key-contribution.js +20 -0
- package/lib/browser/widget-context-key-contribution.js.map +1 -0
- package/package.json +4 -4
- package/src/browser/frontend-application-module.ts +2 -0
- package/src/browser/index.ts +1 -0
- package/src/browser/resource-context-key.ts +61 -16
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.tsx +13 -12
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +36 -4
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.ts +150 -3
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.tsx +6 -3
- package/src/browser/shell/tab-bar-toolbar/tab-toolbar-item.tsx +13 -5
- package/src/browser/view-container.ts +3 -3
- package/src/browser/widget-context-key-contribution.ts +34 -0
|
@@ -18,13 +18,18 @@ import { enableJSDOM } from '../../test/jsdom';
|
|
|
18
18
|
|
|
19
19
|
let disableJSDOM = enableJSDOM();
|
|
20
20
|
import { expect } from 'chai';
|
|
21
|
+
import { renderToStaticMarkup } from 'react-dom/server';
|
|
21
22
|
import {
|
|
22
23
|
CommandMenu, CommandRegistry, CompoundMenuNode, Group, GroupImpl, MenuAction, MenuModelRegistry, MenuNode, MenuNodeFactory, MutableCompoundMenuNode,
|
|
23
24
|
Submenu, SubmenuImpl, SubMenuLink
|
|
24
25
|
} from '../../../common';
|
|
25
|
-
import { ContextKeyServiceDummyImpl } from '../../context-key-service';
|
|
26
|
+
import { ContextKeyServiceDummyImpl, ContextMatcher } from '../../context-key-service';
|
|
26
27
|
import { ContextMenuRenderer } from '../../context-menu-renderer';
|
|
27
28
|
import { Widget } from '../../widgets';
|
|
29
|
+
import URI from '../../../common/uri';
|
|
30
|
+
import { ResourceContextKey } from '../../resource-context-key';
|
|
31
|
+
import { WidgetContextKeyContribution } from '../../widget-context-key-contribution';
|
|
32
|
+
import { TabBarToolbar } from './tab-bar-toolbar';
|
|
28
33
|
import { TOOLBAR_WRAPPER_ID_SUFFIX } from './tab-bar-toolbar-menu-adapters';
|
|
29
34
|
import { TabBarToolbarRegistry } from './tab-bar-toolbar-registry';
|
|
30
35
|
import { TAB_BAR_TOOLBAR_CONTEXT_MENU, TabBarToolbarAction } from './tab-bar-toolbar-types';
|
|
@@ -135,6 +140,106 @@ describe('tab-bar-toolbar', () => {
|
|
|
135
140
|
testWidget.dispose();
|
|
136
141
|
});
|
|
137
142
|
|
|
143
|
+
it('evaluates delegated items against the resource of the widget that owns the toolbar', () => {
|
|
144
|
+
const testWidget = new TestToolbarWidget(new URI('probe:/a.probe'));
|
|
145
|
+
const commands = createCommandRegistry();
|
|
146
|
+
commands.registerCommand({ id: TEST_COMMAND, label: 'Test Command' }, { execute: () => { } });
|
|
147
|
+
const menuRegistry = createMenuRegistry(commands);
|
|
148
|
+
menuRegistry.registerMenuAction([...TEST_MENU_PATH, 'other'], { commandId: TEST_COMMAND, when: 'resourceScheme == probe' });
|
|
149
|
+
const registry = createToolbarRegistry(commands, menuRegistry, new TestContextKeyService());
|
|
150
|
+
registry.registerMenuDelegate(TEST_MENU_PATH, TestToolbarWidget.is);
|
|
151
|
+
|
|
152
|
+
const commandItem = registry.visibleItems(testWidget).find(item => item.id === `${TEST_COMMAND}${TOOLBAR_WRAPPER_ID_SUFFIX}`);
|
|
153
|
+
|
|
154
|
+
const otherWidget = new TestToolbarWidget(new URI('file:/a.txt'));
|
|
155
|
+
|
|
156
|
+
expect(commandItem).to.exist;
|
|
157
|
+
expect(registry.visibleItems(otherWidget)).to.be.empty;
|
|
158
|
+
testWidget.dispose();
|
|
159
|
+
otherWidget.dispose();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('evaluates registered items against the keys contributed for the widget that owns the toolbar', () => {
|
|
163
|
+
const testWidget = new TestToolbarWidget(new URI('probe:/a.probe'));
|
|
164
|
+
const otherWidget = new TestToolbarWidget(new URI('probe:/b.probe'));
|
|
165
|
+
const commands = createCommandRegistry();
|
|
166
|
+
commands.registerCommand({ id: TEST_COMMAND, label: 'Test Command' }, { execute: () => { } });
|
|
167
|
+
const menuRegistry = createMenuRegistry(commands);
|
|
168
|
+
const contribution: WidgetContextKeyContribution = {
|
|
169
|
+
getContextKeyValues: widget => [['activeCustomEditorId', widget === testWidget ? 'test.probeEditor' : '']]
|
|
170
|
+
};
|
|
171
|
+
const registry = createToolbarRegistry(commands, menuRegistry, new TestContextKeyService(), [contribution]);
|
|
172
|
+
registry.registerItem({ id: 'test-item', command: TEST_COMMAND, when: 'activeCustomEditorId == test.probeEditor' });
|
|
173
|
+
|
|
174
|
+
expect(registry.visibleItems(testWidget).map(item => item.id)).to.deep.equal(['test-item']);
|
|
175
|
+
expect(registry.visibleItems(otherWidget)).to.be.empty;
|
|
176
|
+
testWidget.dispose();
|
|
177
|
+
otherWidget.dispose();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('renders the submenu chevron against the widget that owns the toolbar', () => {
|
|
181
|
+
const testWidget = new TestToolbarWidget();
|
|
182
|
+
const otherWidget = new TestToolbarWidget();
|
|
183
|
+
const commands = createCommandRegistry();
|
|
184
|
+
commands.registerCommand({ id: TEST_SUBMENU_COMMAND, label: 'Test Submenu Command' }, { execute: () => { } });
|
|
185
|
+
const menuRegistry = createMenuRegistry(commands);
|
|
186
|
+
menuRegistry.registerSubmenu([...TEST_MENU_PATH, 'other', 'test-submenu'], 'Test Submenu');
|
|
187
|
+
menuRegistry.registerMenuAction([...TEST_MENU_PATH, 'other', 'test-submenu'],
|
|
188
|
+
{ commandId: TEST_SUBMENU_COMMAND, when: 'activeCustomEditorId == test.probeEditor' });
|
|
189
|
+
const contribution: WidgetContextKeyContribution = {
|
|
190
|
+
getContextKeyValues: widget => [['activeCustomEditorId', widget === testWidget ? 'test.probeEditor' : '']]
|
|
191
|
+
};
|
|
192
|
+
const registry = createToolbarRegistry(commands, menuRegistry, new TestContextKeyService(), [contribution]);
|
|
193
|
+
registry.registerMenuDelegate(TEST_MENU_PATH, TestToolbarWidget.is);
|
|
194
|
+
const submenuItem = registry.visibleItems(testWidget).find(item => item.id === `test-submenu${TOOLBAR_WRAPPER_ID_SUFFIX}`);
|
|
195
|
+
|
|
196
|
+
expect(submenuItem).to.exist;
|
|
197
|
+
expect(renderToStaticMarkup(submenuItem!.render(testWidget, registry.contextMatcherFor(testWidget)))).to.contain('chevron');
|
|
198
|
+
expect(renderToStaticMarkup(submenuItem!.render(testWidget, registry.contextMatcherFor(otherWidget)))).to.not.contain('chevron');
|
|
199
|
+
testWidget.dispose();
|
|
200
|
+
otherWidget.dispose();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('opens the More Actions menu against the widget that owns the toolbar', () => {
|
|
204
|
+
const testWidget = new TestToolbarWidget();
|
|
205
|
+
const otherWidget = new TestToolbarWidget();
|
|
206
|
+
const commands = createCommandRegistry();
|
|
207
|
+
commands.registerCommand({ id: TEST_SUBMENU_COMMAND, label: 'Test Submenu Command' }, { execute: () => { } });
|
|
208
|
+
const menuRegistry = createMenuRegistry(commands);
|
|
209
|
+
menuRegistry.registerSubmenu([...TEST_MENU_PATH, 'other', 'test-submenu'], 'Test Submenu');
|
|
210
|
+
menuRegistry.registerMenuAction([...TEST_MENU_PATH, 'other', 'test-submenu'],
|
|
211
|
+
{ commandId: TEST_SUBMENU_COMMAND, when: 'activeCustomEditorId == test.probeEditor' });
|
|
212
|
+
const contribution: WidgetContextKeyContribution = {
|
|
213
|
+
getContextKeyValues: widget => [['activeCustomEditorId', widget === testWidget ? 'test.probeEditor' : '']]
|
|
214
|
+
};
|
|
215
|
+
const ambient = new TestContextKeyService();
|
|
216
|
+
const registry = createToolbarRegistry(commands, menuRegistry, ambient, [contribution]);
|
|
217
|
+
registry.registerMenuDelegate(TEST_MENU_PATH, TestToolbarWidget.is);
|
|
218
|
+
|
|
219
|
+
let rendered: { contextKeyService?: ContextMatcher } | undefined;
|
|
220
|
+
const toolbar = new TabBarToolbar();
|
|
221
|
+
Reflect.set(toolbar, 'contextKeyService', ambient);
|
|
222
|
+
Reflect.set(toolbar, 'toolbarRegistry', registry);
|
|
223
|
+
Reflect.set(toolbar, 'contextMenuRenderer', {
|
|
224
|
+
render: (options: { contextKeyService?: ContextMatcher }) => {
|
|
225
|
+
rendered = options;
|
|
226
|
+
return { dispose: () => { } };
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
const setCurrent = Reflect.get(toolbar, 'setCurrent') as (widget: Widget) => void;
|
|
230
|
+
|
|
231
|
+
setCurrent.call(toolbar, testWidget);
|
|
232
|
+
toolbar.renderMoreContextMenu({ x: 0, y: 0 });
|
|
233
|
+
expect(rendered?.contextKeyService?.match('activeCustomEditorId == test.probeEditor')).to.be.true;
|
|
234
|
+
|
|
235
|
+
setCurrent.call(toolbar, otherWidget);
|
|
236
|
+
toolbar.renderMoreContextMenu({ x: 0, y: 0 });
|
|
237
|
+
expect(rendered?.contextKeyService?.match('activeCustomEditorId == test.probeEditor')).to.be.false;
|
|
238
|
+
|
|
239
|
+
testWidget.dispose();
|
|
240
|
+
otherWidget.dispose();
|
|
241
|
+
});
|
|
242
|
+
|
|
138
243
|
it('preserves the widget for wrapped submenu emptiness checks', () => {
|
|
139
244
|
const testWidget = new TestToolbarWidget();
|
|
140
245
|
const commands = createCommandRegistry();
|
|
@@ -166,6 +271,38 @@ class TestToolbarWidget extends Widget {
|
|
|
166
271
|
static is(candidate?: Widget): candidate is TestToolbarWidget {
|
|
167
272
|
return candidate instanceof TestToolbarWidget;
|
|
168
273
|
}
|
|
274
|
+
|
|
275
|
+
constructor(protected readonly resourceUri?: URI) {
|
|
276
|
+
super();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
getResourceUri(): URI | undefined {
|
|
280
|
+
return this.resourceUri;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
createMoveToUri(resourceUri: URI): URI | undefined {
|
|
284
|
+
return resourceUri;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Evaluates `key == value` clauses against the overlay alone, so that a visible item can only come from the
|
|
290
|
+
* values the registry attributed to the widget.
|
|
291
|
+
*/
|
|
292
|
+
class TestContextKeyService extends ContextKeyServiceDummyImpl {
|
|
293
|
+
override match(expression: string): boolean {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
override createOverlay(overlay: Iterable<[string, unknown]>): ContextMatcher {
|
|
298
|
+
const values = new Map(overlay);
|
|
299
|
+
return {
|
|
300
|
+
match: (expression: string) => {
|
|
301
|
+
const [key, value] = expression.split(' == ');
|
|
302
|
+
return values.get(key) === value;
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
}
|
|
169
306
|
}
|
|
170
307
|
|
|
171
308
|
class TestMenuNodeFactory implements MenuNodeFactory {
|
|
@@ -187,7 +324,8 @@ class TestMenuNodeFactory implements MenuNodeFactory {
|
|
|
187
324
|
|
|
188
325
|
createCommandMenu(item: MenuAction): CommandMenu {
|
|
189
326
|
return {
|
|
190
|
-
isVisible: (_path,
|
|
327
|
+
isVisible: (_path, contextMatcher, context, ...args) =>
|
|
328
|
+
(!item.when || contextMatcher.match(item.when, context)) && this.commands.isVisible(item.commandId, ...args),
|
|
191
329
|
isEnabled: (_path, ...args) => this.commands.isEnabled(item.commandId, ...args),
|
|
192
330
|
isToggled: (_path, ...args) => this.commands.isToggled(item.commandId, ...args),
|
|
193
331
|
id: item.commandId,
|
|
@@ -208,7 +346,12 @@ function createMenuRegistry(commands: CommandRegistry): MenuModelRegistry {
|
|
|
208
346
|
return new MenuModelRegistry({ getContributions: () => [] }, commands, new TestMenuNodeFactory(commands));
|
|
209
347
|
}
|
|
210
348
|
|
|
211
|
-
function createToolbarRegistry(
|
|
349
|
+
function createToolbarRegistry(
|
|
350
|
+
commands: CommandRegistry,
|
|
351
|
+
menuRegistry: MenuModelRegistry,
|
|
352
|
+
contextKeyService: ContextKeyServiceDummyImpl,
|
|
353
|
+
contextKeyContributions: WidgetContextKeyContribution[] = []
|
|
354
|
+
): TabBarToolbarRegistry {
|
|
212
355
|
const registry = new TabBarToolbarRegistry();
|
|
213
356
|
Reflect.set(registry, 'commandRegistry', commands);
|
|
214
357
|
Reflect.set(registry, 'contextKeyService', contextKeyService);
|
|
@@ -216,5 +359,9 @@ function createToolbarRegistry(commands: CommandRegistry, menuRegistry: MenuMode
|
|
|
216
359
|
Reflect.set(registry, 'keybindingRegistry', {});
|
|
217
360
|
Reflect.set(registry, 'labelParser', {});
|
|
218
361
|
Reflect.set(registry, 'contextMenuRenderer', { render: () => undefined } as unknown as ContextMenuRenderer);
|
|
362
|
+
const resourceContextKey = new ResourceContextKey();
|
|
363
|
+
Reflect.set(resourceContextKey, 'languages', { languages: [] });
|
|
364
|
+
Reflect.set(registry, 'resourceContextKey', resourceContextKey);
|
|
365
|
+
Reflect.set(registry, 'contextKeyContributionProvider', { getContributions: () => contextKeyContributions });
|
|
219
366
|
return registry;
|
|
220
367
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import { inject, injectable, postConstruct } from 'inversify';
|
|
18
18
|
import * as React from 'react';
|
|
19
19
|
import { buttonKeyboardProps, isActivationKey } from '../../keyboard/keyboard-utils';
|
|
20
|
-
import { ContextKeyService } from '../../context-key-service';
|
|
20
|
+
import { ContextKeyService, ContextMatcher } from '../../context-key-service';
|
|
21
21
|
import { CommandRegistry, Disposable, DisposableCollection, nls } from '../../../common';
|
|
22
22
|
import { Anchor, ContextMenuAccess, ContextMenuRenderer } from '../../context-menu-renderer';
|
|
23
23
|
import { LabelParser } from '../../label-parser';
|
|
@@ -48,6 +48,7 @@ export function toAnchor(event: React.MouseEvent): Anchor {
|
|
|
48
48
|
export class TabBarToolbar extends ReactWidget {
|
|
49
49
|
|
|
50
50
|
protected current: Widget | undefined;
|
|
51
|
+
protected contextMatcher: ContextMatcher;
|
|
51
52
|
protected inline = new Map<string, TabBarToolbarItem>();
|
|
52
53
|
protected more = new Map<string, TabBarToolbarItem>();
|
|
53
54
|
|
|
@@ -73,6 +74,7 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
73
74
|
|
|
74
75
|
@postConstruct()
|
|
75
76
|
protected init(): void {
|
|
77
|
+
this.contextMatcher = this.contextKeyService;
|
|
76
78
|
this.toDispose.pushAll([
|
|
77
79
|
this.keybindings.onKeybindingsChanged(() => this.maybeUpdate()),
|
|
78
80
|
this.contextKeyService.onDidChange(e => {
|
|
@@ -129,6 +131,7 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
129
131
|
this.toDisposeOnSetCurrent.dispose();
|
|
130
132
|
this.toDispose.push(this.toDisposeOnSetCurrent);
|
|
131
133
|
this.current = current;
|
|
134
|
+
this.contextMatcher = current ? this.toolbarRegistry.contextMatcherFor(current) : this.contextKeyService;
|
|
132
135
|
if (current) {
|
|
133
136
|
const resetCurrent = () => {
|
|
134
137
|
this.setCurrent(undefined);
|
|
@@ -145,7 +148,7 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
145
148
|
this.keybindingContextKeys.clear();
|
|
146
149
|
return <React.Fragment>
|
|
147
150
|
{this.renderMore()}
|
|
148
|
-
{[...this.inline.values()].map(item => item.render(this.current))}
|
|
151
|
+
{[...this.inline.values()].map(item => item.render(this.current, this.contextMatcher))}
|
|
149
152
|
</React.Fragment>;
|
|
150
153
|
}
|
|
151
154
|
|
|
@@ -199,7 +202,7 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
199
202
|
args: [this.current],
|
|
200
203
|
anchor,
|
|
201
204
|
context: this.current?.node || this.node,
|
|
202
|
-
contextKeyService: this.
|
|
205
|
+
contextKeyService: this.contextMatcher,
|
|
203
206
|
includeAnchorArg: false,
|
|
204
207
|
onHide: () => toDisposeOnHide.dispose()
|
|
205
208
|
});
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { ContextKeyService } from '../../context-key-service';
|
|
17
|
+
import { ContextKeyService, ContextMatcher } from '../../context-key-service';
|
|
18
18
|
import { ReactTabBarToolbarAction, RenderedToolbarAction, TabBarToolbarActionBase } from './tab-bar-toolbar-types';
|
|
19
19
|
import { Widget } from '@lumino/widgets';
|
|
20
20
|
import { LabelIcon, LabelParser } from '../../label-parser';
|
|
@@ -29,10 +29,18 @@ import { ActionMenuNode, GroupImpl, MenuNode } from '../../../common/menu';
|
|
|
29
29
|
export interface TabBarToolbarItem {
|
|
30
30
|
id: string;
|
|
31
31
|
when?: string;
|
|
32
|
-
|
|
32
|
+
/**
|
|
33
|
+
* @param contextMatcher evaluates `when` clauses with the values that describe the given widget. Keys
|
|
34
|
+
* scoped to a DOM node keep resolving against the focused element, as no context node is passed here.
|
|
35
|
+
*/
|
|
36
|
+
isVisible(widget: Widget, contextMatcher: ContextMatcher): boolean;
|
|
33
37
|
isEnabled(widget: Widget): boolean;
|
|
34
38
|
isToggled(widget: Widget): boolean;
|
|
35
|
-
|
|
39
|
+
/**
|
|
40
|
+
* @param contextMatcher evaluates `when` clauses with the values that describe the given widget. Defaults
|
|
41
|
+
* to the ambient context, for toolbars that render items with no owning widget.
|
|
42
|
+
*/
|
|
43
|
+
render(widget?: Widget, contextMatcher?: ContextMatcher): React.ReactNode;
|
|
36
44
|
onDidChange?: Event<void>;
|
|
37
45
|
group?: string;
|
|
38
46
|
priority?: number;
|
|
@@ -68,12 +76,12 @@ class AbstractToolbarItemImpl<T extends TabBarToolbarActionBase> {
|
|
|
68
76
|
return this.action.onDidChange;
|
|
69
77
|
}
|
|
70
78
|
|
|
71
|
-
isVisible(widget: Widget): boolean {
|
|
79
|
+
isVisible(widget: Widget, contextMatcher: ContextMatcher): boolean {
|
|
72
80
|
if (this.action.isVisible) {
|
|
73
81
|
return this.action.isVisible(widget);
|
|
74
82
|
}
|
|
75
83
|
const actionVisible = !this.action.command || this.commandRegistry.isVisible(this.action.command, widget);
|
|
76
|
-
const contextMatches = !this.action.when ||
|
|
84
|
+
const contextMatches = !this.action.when || contextMatcher.match(this.action.when);
|
|
77
85
|
|
|
78
86
|
return actionVisible && contextMatches;
|
|
79
87
|
}
|
|
@@ -38,7 +38,7 @@ import { Drag } from '@lumino/dragdrop';
|
|
|
38
38
|
import { MimeData } from '@lumino/coreutils';
|
|
39
39
|
import { ElementExt } from '@lumino/domutils';
|
|
40
40
|
import { TabBarDecoratorService } from './shell/tab-bar-decorator';
|
|
41
|
-
import { ContextKeyService } from './context-key-service';
|
|
41
|
+
import { ContextKeyService, ContextMatcher } from './context-key-service';
|
|
42
42
|
import { KeybindingRegistry } from './keybinding';
|
|
43
43
|
import { SubmenuAsToolbarItemWrapper } from './shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters';
|
|
44
44
|
import { TheiaSplitPanel } from './shell/theia-split-panel';
|
|
@@ -109,8 +109,8 @@ class PartsMenuToolbarItem extends SubmenuAsToolbarItemWrapper {
|
|
|
109
109
|
super(effectiveMenuPath, commandRegistry, menuRegistry, contextKeyService, contextMenuRenderer, menuNode, group);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
override isVisible(widget: Widget): boolean {
|
|
113
|
-
return widget === this.target() && super.isVisible(widget);
|
|
112
|
+
override isVisible(widget: Widget, contextMatcher: ContextMatcher): boolean {
|
|
113
|
+
return widget === this.target() && super.isVisible(widget, contextMatcher);
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 JuliaHub, Inc. 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-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { Widget } from '@lumino/widgets';
|
|
18
|
+
|
|
19
|
+
export const WidgetContextKeyContribution = Symbol('WidgetContextKeyContribution');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Contributes the context key values that describe a particular widget, so that `when` clauses about
|
|
23
|
+
* that widget - such as the ones of its tab bar toolbar items - can be evaluated without consulting the
|
|
24
|
+
* ambient context, which describes whichever widget currently has focus.
|
|
25
|
+
*/
|
|
26
|
+
export interface WidgetContextKeyContribution {
|
|
27
|
+
/**
|
|
28
|
+
* @param widget the widget to describe.
|
|
29
|
+
* @returns the values to overlay over the ambient context, or `undefined` if this contribution does not
|
|
30
|
+
* describe the given widget. A contribution owning a key should return an explicit "unset" value for the
|
|
31
|
+
* widgets the key does not apply to, so that the ambient value of another widget cannot leak in.
|
|
32
|
+
*/
|
|
33
|
+
getContextKeyValues(widget: Widget): Iterable<[string, unknown]> | undefined;
|
|
34
|
+
}
|