From d21049171a62932a3fc38dff2533c12cb6bdb423 Mon Sep 17 00:00:00 2001 From: Colin Grant Date: Mon, 18 Jan 2021 22:46:34 +0100 Subject: [PATCH 1/2] update on did change Signed-off-by: Colin Grant --- packages/core/src/browser/view-container.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/core/src/browser/view-container.ts b/packages/core/src/browser/view-container.ts index 97d4fb257be26..5817ede069c91 100644 --- a/packages/core/src/browser/view-container.ts +++ b/packages/core/src/browser/view-container.ts @@ -915,6 +915,7 @@ export class ViewContainerPart extends BaseWidget { const toolbar = this.toolbarFactory(); toolbar.addClass('theia-view-container-part-title'); this.toHideToolbar.push(toolbar); + this.toHideToolbar.push(this.toolbarRegistry.onDidChange(() => this.updateToolbar())); Widget.attach(toolbar, this.header); this.toHideToolbar.push(Disposable.create(() => Widget.detach(toolbar))); @@ -922,7 +923,13 @@ export class ViewContainerPart extends BaseWidget { this.toolbar = toolbar; this.toHideToolbar.push(Disposable.create(() => this.toolbar = undefined)); - this.toolbar.updateTarget(this.wrapped); + this.updateToolbar(); + } + + protected updateToolbar(): void { + if (this.toolbar) { + this.toolbar.updateTarget(this.wrapped); + } } get toolbarHidden(): boolean { From 09af5d535bb34f7950e4a192f6a9cb2797624d21 Mon Sep 17 00:00:00 2001 From: Colin Grant Date: Tue, 20 Apr 2021 19:25:46 +0200 Subject: [PATCH 2/2] add sample view container part with conditional toolbar icons Signed-off-by: Colin Grant --- examples/api-samples/compile.tsconfig.json | 3 + examples/api-samples/package.json | 5 +- .../browser/api-samples-frontend-module.ts | 2 + ...sample-view-container-part-contribution.ts | 100 ++++++++++++++++++ .../view/sample-view-container-part.ts | 65 ++++++++++++ 5 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 examples/api-samples/src/browser/view/sample-view-container-part-contribution.ts create mode 100644 examples/api-samples/src/browser/view/sample-view-container-part.ts diff --git a/examples/api-samples/compile.tsconfig.json b/examples/api-samples/compile.tsconfig.json index 8c8d2a2b5febe..cf68c31c2988c 100644 --- a/examples/api-samples/compile.tsconfig.json +++ b/examples/api-samples/compile.tsconfig.json @@ -23,6 +23,9 @@ }, { "path": "../../packages/workspace/compile.tsconfig.json" + }, + { + "path": "../../packages/navigator/compile.tsconfig.json" } ] } diff --git a/examples/api-samples/package.json b/examples/api-samples/package.json index c20f4d0b76469..03025ae028d66 100644 --- a/examples/api-samples/package.json +++ b/examples/api-samples/package.json @@ -7,8 +7,9 @@ "@theia/core": "1.16.0", "@theia/filesystem": "1.16.0", "@theia/output": "1.16.0", - "@theia/vsx-registry": "1.16.0", - "@theia/workspace": "1.16.0" + "@theia/workspace": "1.16.0", + "@theia/navigator": "1.16.0", + "@theia/vsx-registry": "1.16.0" }, "theiaExtensions": [ { diff --git a/examples/api-samples/src/browser/api-samples-frontend-module.ts b/examples/api-samples/src/browser/api-samples-frontend-module.ts index 10a3ba15d7ecc..1ab4a3f52c461 100644 --- a/examples/api-samples/src/browser/api-samples-frontend-module.ts +++ b/examples/api-samples/src/browser/api-samples-frontend-module.ts @@ -24,6 +24,7 @@ import { bindSampleFileWatching } from './file-watching/sample-file-watching-con import { bindVSXCommand } from './vsx/sample-vsx-command-contribution'; import '../../src/browser/style/branding.css'; +import { bindSampleViewContainerPart } from './view/sample-view-container-part-contribution'; export default new ContainerModule(bind => { bindDynamicLabelProvider(bind); @@ -33,4 +34,5 @@ export default new ContainerModule(bind => { bindSampleFileWatching(bind); bindVSXCommand(bind); bindSampleFilteredCommandContribution(bind); + bindSampleViewContainerPart(bind); }); diff --git a/examples/api-samples/src/browser/view/sample-view-container-part-contribution.ts b/examples/api-samples/src/browser/view/sample-view-container-part-contribution.ts new file mode 100644 index 0000000000000..3347b8391880c --- /dev/null +++ b/examples/api-samples/src/browser/view/sample-view-container-part-contribution.ts @@ -0,0 +1,100 @@ +/******************************************************************************** + * Copyright (C) 2021 Ericsson and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { ViewContainer, WidgetFactory, WidgetManager } from '@theia/core/lib/browser'; +import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; +import { CommandContribution, CommandRegistry, Emitter } from '@theia/core/lib/common'; +import { inject, injectable, interfaces, postConstruct } from '@theia/core/shared/inversify'; +import { EXPLORER_VIEW_CONTAINER_ID } from '@theia/navigator/lib/browser'; +import { SampleViewContainerPart } from './sample-view-container-part'; + +const CHANGE_TO_MINUS_COMMAND = { + id: 'sample-view-container-part-to-minus', + label: 'Change the command displayed in the Sample View Container Part toolbar to a minus sign.', + iconClass: 'fa fa-plus' +}; + +const CHANGE_TO_PLUS_COMMAND = { + id: 'sample-view-container-part-to-plus', + label: 'Change the command displayed in the Sample View Container Part toolbar to a plus sign.', + iconClass: 'fa fa-minus' +}; + +@injectable() +export class SampleViewContainerPartContribution implements CommandContribution, TabBarToolbarContribution { + protected readonly onChangeEmitter = new Emitter(); + readonly onChange = this.onChangeEmitter.event; + + @inject(WidgetManager) protected readonly widgetManager: WidgetManager; + + @postConstruct() + protected async init(): Promise { + const widget = await this.widgetManager.getOrCreateWidget(SampleViewContainerPart.ID); + widget.onIconDisplayChanged(() => this.onChangeEmitter.fire()); + } + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(CHANGE_TO_PLUS_COMMAND, + { + isVisible: widget => widget instanceof SampleViewContainerPart && !widget.shouldShowPlus, + isEnabled: widget => widget instanceof SampleViewContainerPart && !widget.shouldShowPlus, + execute: (widget: SampleViewContainerPart) => { + widget.changeDisplay(); + } + }); + registry.registerCommand(CHANGE_TO_MINUS_COMMAND, + { + isVisible: widget => widget instanceof SampleViewContainerPart && widget.shouldShowPlus, + isEnabled: widget => widget instanceof SampleViewContainerPart && widget.shouldShowPlus, + execute: (widget: SampleViewContainerPart) => { + widget.changeDisplay(); + } + }); + } + + registerToolbarItems(registry: TabBarToolbarRegistry): void { + registry.registerItem({ + command: CHANGE_TO_PLUS_COMMAND.id, + id: CHANGE_TO_PLUS_COMMAND.id, + tooltip: CHANGE_TO_PLUS_COMMAND.label, + onDidChange: this.onChange, + }); + registry.registerItem({ + command: CHANGE_TO_MINUS_COMMAND.id, + id: CHANGE_TO_MINUS_COMMAND.id, + tooltip: CHANGE_TO_MINUS_COMMAND.label, + onDidChange: this.onChange, + }); + } +} + +export const bindSampleViewContainerPart = (bind: interfaces.Bind): void => { + bind(SampleViewContainerPart).toSelf().inSingletonScope(); + bind(SampleViewContainerPartContribution).toSelf().inSingletonScope(); + bind(CommandContribution).toService(SampleViewContainerPartContribution); + bind(TabBarToolbarContribution).toService(SampleViewContainerPartContribution); + bind(WidgetFactory).toDynamicValue(({ container }) => ({ + id: SampleViewContainerPart.ID, + createWidget: async () => { + const widgetManager = container.get(WidgetManager); + const viewContainer = await widgetManager.getOrCreateWidget(EXPLORER_VIEW_CONTAINER_ID); + const viewContainerPart = container.get(SampleViewContainerPart); + viewContainer.addWidget(viewContainerPart); + return viewContainerPart; + } + })).inSingletonScope(); +}; + diff --git a/examples/api-samples/src/browser/view/sample-view-container-part.ts b/examples/api-samples/src/browser/view/sample-view-container-part.ts new file mode 100644 index 0000000000000..480e059fe1826 --- /dev/null +++ b/examples/api-samples/src/browser/view/sample-view-container-part.ts @@ -0,0 +1,65 @@ +/******************************************************************************** + * Copyright (C) 2021 Ericsson and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { BaseWidget } from '@theia/core/lib/browser'; +import { injectable, postConstruct } from '@theia/core/shared/inversify'; +import { Emitter } from '@theia/core/lib/common'; + +@injectable() +export class SampleViewContainerPart extends BaseWidget { + static ID = 'sample-view-container-part'; + + protected readonly iconDisplayChangedEmitter = new Emitter(); + readonly onIconDisplayChanged = this.iconDisplayChangedEmitter.event; + + protected _shouldShowPlus = true; + protected message: HTMLDivElement; + + get shouldShowPlus(): boolean { + return this._shouldShowPlus; + } + + @postConstruct() + protected init(): void { + this.toDispose.push(this.iconDisplayChangedEmitter); + this.title.label = 'Sample View Container Part'; + this.addClass(SampleViewContainerPart.ID); + this.id = SampleViewContainerPart.ID; + this.node.style.padding = 'var(--theia-ui-padding)'; + this.node.style.textAlign = 'center'; + this.message = document.createElement('div'); + this.message.classList.add(`${SampleViewContainerPart.ID}-message`); + this.message.textContent = this.getMessage(this.shouldShowPlus); + const button = document.createElement('button'); + button.classList.add('theia-button'); + button.onclick = this.changeDisplay.bind(this); + button.textContent = 'Change Icon'; + button.style.marginBlockStart = 'calc(var(--theia-ui-padding) * 2)'; + button.style.marginBlockEnd = 'calc(var(--theia-ui-padding) * 2)'; + this.node.appendChild(this.message); + this.node.appendChild(button); + } + + protected getMessage(shouldShowPlus: boolean): string { + return `You should see a ${shouldShowPlus ? 'plus' : 'minus'} sign icon when you hover over this widget.`; + } + + changeDisplay(): void { + this._shouldShowPlus = !this.shouldShowPlus; + this.message.textContent = this.getMessage(this.shouldShowPlus); + this.iconDisplayChangedEmitter.fire(); + } +}