From d08794bb530827201215a22ec9480667536b5af5 Mon Sep 17 00:00:00 2001 From: Mark Sujew Date: Tue, 1 Oct 2024 19:32:21 +0200 Subject: [PATCH] Improve widget specific status bar handling --- .../browser/frontend-application-module.ts | 5 + packages/core/src/browser/index.ts | 1 + .../src/browser/widget-status-bar-service.ts | 84 +++++++++++++ .../editor/src/browser/editor-contribution.ts | 59 +++++---- .../src/browser/editor-frontend-module.ts | 11 +- .../getting-started-frontend-module.ts | 3 +- .../src/browser/keymaps-frontend-module.ts | 3 +- .../src/browser/monaco-frontend-module.ts | 5 +- .../browser/monaco-status-bar-contribution.ts | 117 +++++++++--------- .../notebook-status-bar-contribution.ts | 57 ++++----- .../src/browser/notebook-frontend-module.ts | 6 +- .../browser/plugin-ext-frontend-module.ts | 5 +- .../src/browser/preference-frontend-module.ts | 5 +- .../browser/vsx-registry-frontend-module.ts | 5 +- 14 files changed, 234 insertions(+), 132 deletions(-) create mode 100644 packages/core/src/browser/widget-status-bar-service.ts diff --git a/packages/core/src/browser/frontend-application-module.ts b/packages/core/src/browser/frontend-application-module.ts index 51131f9b1ce93..ea29eff0ebf87 100644 --- a/packages/core/src/browser/frontend-application-module.ts +++ b/packages/core/src/browser/frontend-application-module.ts @@ -144,6 +144,7 @@ import { bindTreePreferences } from './tree'; import { OpenWithService } from './open-with-service'; import { ViewColumnService } from './shell/view-column-service'; import { DomInputUndoRedoHandler, UndoRedoHandler, UndoRedoHandlerService } from './undo-redo-handler'; +import { WidgetStatusBarContribution, WidgetStatusBarService } from './widget-status-bar-service'; export { bindResourceProvider, bindMessageService, bindPreferenceService }; @@ -471,4 +472,8 @@ export const frontendApplicationModule = new ContainerModule((bind, _unbind, _is bindContributionProvider(bind, UndoRedoHandler); bind(DomInputUndoRedoHandler).toSelf().inSingletonScope(); bind(UndoRedoHandler).toService(DomInputUndoRedoHandler); + + bind(WidgetStatusBarService).toSelf().inSingletonScope(); + bind(FrontendApplicationContribution).toService(WidgetStatusBarService); + bindContributionProvider(bind, WidgetStatusBarContribution); }); diff --git a/packages/core/src/browser/index.ts b/packages/core/src/browser/index.ts index ecc1ccc4da2f8..02cae0fbdf1f4 100644 --- a/packages/core/src/browser/index.ts +++ b/packages/core/src/browser/index.ts @@ -48,3 +48,4 @@ export * from './styling-service'; export * from './hover-service'; export * from './saveable-service'; export * from './undo-redo-handler'; +export * from './widget-status-bar-service'; diff --git a/packages/core/src/browser/widget-status-bar-service.ts b/packages/core/src/browser/widget-status-bar-service.ts new file mode 100644 index 0000000000000..d705880d90546 --- /dev/null +++ b/packages/core/src/browser/widget-status-bar-service.ts @@ -0,0 +1,84 @@ +// ***************************************************************************** +// Copyright (C) 2024 TypeFox 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-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { inject, injectable, named } from 'inversify'; +import { Widget } from './widgets'; +import { StatusBar } from './status-bar'; +import { FrontendApplicationContribution } from './frontend-application-contribution'; +import { ContributionProvider } from '../common'; +import { FrontendApplication } from './frontend-application'; + +export const WidgetStatusBarContribution = Symbol('WidgetStatusBarContribution'); + +export interface WidgetStatusBarContribution { + canHandle(widget: Widget): widget is T; + activate(statusBar: StatusBar, widget: T): void; + deactivate(statusBar: StatusBar): void; +} + +/** + * Creates an empty {@link WidgetStatusBarContribution} that does nothing. + * Useful for widgets that are not handled by any other contribution, for example: + * * Settings widget + * * Welcome widget + * * Webview widget + * + * @param prototype Prototype to identify the kind of the widget. + * @returns An empty {@link WidgetStatusBarContribution}. + */ +export function noopWidgetStatusBarContribution(prototype: Function): WidgetStatusBarContribution { + return { + canHandle(widget: Widget): widget is Widget { + return widget instanceof prototype; + }, + activate: () => { }, + deactivate: () => { } + }; +} + +@injectable() +export class WidgetStatusBarService implements FrontendApplicationContribution { + + @inject(ContributionProvider) @named(WidgetStatusBarContribution) + protected readonly contributionProvider: ContributionProvider>; + + @inject(StatusBar) + protected readonly statusBar: StatusBar; + + onStart(app: FrontendApplication): void { + app.shell.onDidChangeCurrentWidget(event => { + if (event.newValue) { + this.show(event.newValue); + } + }); + } + + protected show(widget: Widget): void { + const contributions = this.contributionProvider.getContributions(); + // If any contribution can handle the widget, activate it + // If none can, keep everything as is + if (contributions.some(contribution => contribution.canHandle(widget))) { + for (const contribution of contributions) { + // Deactivate all contributions + contribution.deactivate(this.statusBar); + if (contribution.canHandle(widget)) { + // Selectively re-activate them + contribution.activate(this.statusBar, widget); + } + } + } + } +} diff --git a/packages/editor/src/browser/editor-contribution.ts b/packages/editor/src/browser/editor-contribution.ts index a51191531fdf4..00dca84019da8 100644 --- a/packages/editor/src/browser/editor-contribution.ts +++ b/packages/editor/src/browser/editor-contribution.ts @@ -20,7 +20,9 @@ import { injectable, inject, optional } from '@theia/core/shared/inversify'; import { StatusBarAlignment, StatusBar } from '@theia/core/lib/browser/status-bar/status-bar'; import { FrontendApplicationContribution, DiffUris, DockLayout, - QuickInputService, KeybindingRegistry, KeybindingContribution, SHELL_TABBAR_CONTEXT_SPLIT, ApplicationShell + QuickInputService, KeybindingRegistry, KeybindingContribution, SHELL_TABBAR_CONTEXT_SPLIT, ApplicationShell, + WidgetStatusBarContribution, + Widget } from '@theia/core/lib/browser'; import { ContextKeyService } from '@theia/core/lib/browser/context-key-service'; import { CommandHandler, DisposableCollection, MenuContribution, MenuModelRegistry } from '@theia/core'; @@ -33,9 +35,9 @@ import { EditorWidget } from './editor-widget'; import { EditorLanguageStatusService } from './language-status/editor-language-status-service'; @injectable() -export class EditorContribution implements FrontendApplicationContribution, CommandContribution, KeybindingContribution, MenuContribution { +export class EditorContribution implements FrontendApplicationContribution, + CommandContribution, KeybindingContribution, MenuContribution, WidgetStatusBarContribution { - @inject(StatusBar) protected readonly statusBar: StatusBar; @inject(EditorManager) protected readonly editorManager: EditorManager; @inject(EditorLanguageStatusService) protected readonly languageStatusService: EditorLanguageStatusService; @inject(ApplicationShell) protected readonly shell: ApplicationShell; @@ -48,9 +50,6 @@ export class EditorContribution implements FrontendApplicationContribution, Comm onStart(): void { this.initEditorContextKeys(); - - this.updateStatusBar(); - this.editorManager.onCurrentEditorChanged(() => this.updateStatusBar()); } protected initEditorContextKeys(): void { @@ -72,33 +71,41 @@ export class EditorContribution implements FrontendApplicationContribution, Comm } protected readonly toDisposeOnCurrentEditorChanged = new DisposableCollection(); - protected updateStatusBar(): void { + + canHandle(widget: Widget): widget is EditorWidget { + return widget instanceof EditorWidget; + } + + activate(statusBar: StatusBar, widget: EditorWidget): void { this.toDisposeOnCurrentEditorChanged.dispose(); + const editor = widget.editor; + this.updateLanguageStatus(statusBar, editor); + this.updateEncodingStatus(statusBar, editor); + this.setCursorPositionStatus(statusBar, editor); + this.toDisposeOnCurrentEditorChanged.pushAll([ + editor.onLanguageChanged(() => this.updateLanguageStatus(statusBar, editor)), + editor.onEncodingChanged(() => this.updateEncodingStatus(statusBar, editor)), + editor.onCursorPositionChanged(() => this.setCursorPositionStatus(statusBar, editor)) + ]); + } - const widget = this.editorManager.currentEditor; - const editor = widget && widget.editor; - this.updateLanguageStatus(editor); - this.updateEncodingStatus(editor); - this.setCursorPositionStatus(editor); - if (editor) { - this.toDisposeOnCurrentEditorChanged.pushAll([ - editor.onLanguageChanged(() => this.updateLanguageStatus(editor)), - editor.onEncodingChanged(() => this.updateEncodingStatus(editor)), - editor.onCursorPositionChanged(() => this.setCursorPositionStatus(editor)) - ]); - } + deactivate(statusBar: StatusBar): void { + this.toDisposeOnCurrentEditorChanged.dispose(); + this.updateLanguageStatus(statusBar, undefined); + this.updateEncodingStatus(statusBar, undefined); + this.setCursorPositionStatus(statusBar, undefined); } - protected updateLanguageStatus(editor: TextEditor | undefined): void { + protected updateLanguageStatus(statusBar: StatusBar, editor: TextEditor | undefined): void { this.languageStatusService.updateLanguageStatus(editor); } - protected updateEncodingStatus(editor: TextEditor | undefined): void { + protected updateEncodingStatus(statusBar: StatusBar, editor: TextEditor | undefined): void { if (!editor) { - this.statusBar.removeElement('editor-status-encoding'); + statusBar.removeElement('editor-status-encoding'); return; } - this.statusBar.setElement('editor-status-encoding', { + statusBar.setElement('editor-status-encoding', { text: SUPPORTED_ENCODINGS[editor.getEncoding()].labelShort, alignment: StatusBarAlignment.RIGHT, priority: 10, @@ -107,13 +114,13 @@ export class EditorContribution implements FrontendApplicationContribution, Comm }); } - protected setCursorPositionStatus(editor: TextEditor | undefined): void { + protected setCursorPositionStatus(statusBar: StatusBar, editor: TextEditor | undefined): void { if (!editor) { - this.statusBar.removeElement('editor-status-cursor-position'); + statusBar.removeElement('editor-status-cursor-position'); return; } const { cursor } = editor; - this.statusBar.setElement('editor-status-cursor-position', { + statusBar.setElement('editor-status-cursor-position', { text: nls.localizeByDefault('Ln {0}, Col {1}', cursor.line + 1, editor.getVisibleColumn(cursor)), alignment: StatusBarAlignment.RIGHT, priority: 100, diff --git a/packages/editor/src/browser/editor-frontend-module.ts b/packages/editor/src/browser/editor-frontend-module.ts index e4a089ae90b2a..d5142fa29fa9e 100644 --- a/packages/editor/src/browser/editor-frontend-module.ts +++ b/packages/editor/src/browser/editor-frontend-module.ts @@ -19,7 +19,7 @@ import '../../src/browser/language-status/editor-language-status.css'; import { ContainerModule } from '@theia/core/shared/inversify'; import { CommandContribution, MenuContribution } from '@theia/core/lib/common'; -import { OpenHandler, WidgetFactory, FrontendApplicationContribution, KeybindingContribution } from '@theia/core/lib/browser'; +import { OpenHandler, WidgetFactory, FrontendApplicationContribution, KeybindingContribution, WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { VariableContribution } from '@theia/variable-resolver/lib/browser'; import { EditorManager, EditorAccess, ActiveEditorAccess, CurrentEditorAccess } from './editor-manager'; import { EditorContribution } from './editor-contribution'; @@ -59,7 +59,6 @@ export default new ContainerModule(bind => { bind(KeybindingContribution).toService(EditorKeybindingContribution); bind(EditorContribution).toSelf().inSingletonScope(); - bind(FrontendApplicationContribution).toService(EditorContribution); bind(EditorLanguageStatusService).toSelf().inSingletonScope(); bind(EditorLineNumberContribution).toSelf().inSingletonScope(); @@ -73,7 +72,13 @@ export default new ContainerModule(bind => { bind(VariableContribution).to(EditorVariableContribution).inSingletonScope(); - [CommandContribution, KeybindingContribution, MenuContribution].forEach(serviceIdentifier => { + [ + FrontendApplicationContribution, + WidgetStatusBarContribution, + CommandContribution, + KeybindingContribution, + MenuContribution + ].forEach(serviceIdentifier => { bind(serviceIdentifier).toService(EditorContribution); }); bind(QuickEditorService).toSelf().inSingletonScope(); diff --git a/packages/getting-started/src/browser/getting-started-frontend-module.ts b/packages/getting-started/src/browser/getting-started-frontend-module.ts index fbcc828646f02..d029dd7a2236c 100644 --- a/packages/getting-started/src/browser/getting-started-frontend-module.ts +++ b/packages/getting-started/src/browser/getting-started-frontend-module.ts @@ -17,13 +17,14 @@ import { GettingStartedContribution } from './getting-started-contribution'; import { ContainerModule, interfaces } from '@theia/core/shared/inversify'; import { GettingStartedWidget } from './getting-started-widget'; -import { WidgetFactory, FrontendApplicationContribution, bindViewContribution } from '@theia/core/lib/browser'; +import { WidgetFactory, FrontendApplicationContribution, bindViewContribution, noopWidgetStatusBarContribution, WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { bindGettingStartedPreferences } from './getting-started-preferences'; import '../../src/browser/style/index.css'; export default new ContainerModule((bind: interfaces.Bind) => { bindViewContribution(bind, GettingStartedContribution); bind(FrontendApplicationContribution).toService(GettingStartedContribution); + bind(WidgetStatusBarContribution).toConstantValue(noopWidgetStatusBarContribution(GettingStartedWidget)); bind(GettingStartedWidget).toSelf(); bind(WidgetFactory).toDynamicValue(context => ({ id: GettingStartedWidget.ID, diff --git a/packages/keymaps/src/browser/keymaps-frontend-module.ts b/packages/keymaps/src/browser/keymaps-frontend-module.ts index 2056444246231..5a2c1476bc357 100644 --- a/packages/keymaps/src/browser/keymaps-frontend-module.ts +++ b/packages/keymaps/src/browser/keymaps-frontend-module.ts @@ -22,7 +22,7 @@ import { KeymapsFrontendContribution } from './keymaps-frontend-contribution'; import { CommandContribution, MenuContribution } from '@theia/core/lib/common'; import { KeybindingContribution } from '@theia/core/lib/browser/keybinding'; import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; -import { WidgetFactory } from '@theia/core/lib/browser'; +import { noopWidgetStatusBarContribution, WidgetFactory, WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { KeybindingWidget } from './keybindings-widget'; import { KeybindingSchemaUpdater } from './keybinding-schema-updater'; import { JsonSchemaContribution } from '@theia/core/lib/browser/json-schema-store'; @@ -41,4 +41,5 @@ export default new ContainerModule(bind => { })).inSingletonScope(); bind(KeybindingSchemaUpdater).toSelf().inSingletonScope(); bind(JsonSchemaContribution).toService(KeybindingSchemaUpdater); + bind(WidgetStatusBarContribution).toConstantValue(noopWidgetStatusBarContribution(KeybindingWidget)); }); diff --git a/packages/monaco/src/browser/monaco-frontend-module.ts b/packages/monaco/src/browser/monaco-frontend-module.ts index 0bd3a74f2500c..e7d727453bb07 100644 --- a/packages/monaco/src/browser/monaco-frontend-module.ts +++ b/packages/monaco/src/browser/monaco-frontend-module.ts @@ -21,7 +21,8 @@ import { FrontendApplicationContribution, KeybindingContribution, PreferenceService, PreferenceSchemaProvider, createPreferenceProxy, PreferenceScope, PreferenceChange, OVERRIDE_PROPERTY_PATTERN, QuickInputService, StylingParticipant, WebSocketConnectionProvider, - UndoRedoHandler + UndoRedoHandler, + WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { TextEditorProvider, DiffNavigatorProvider, TextEditor } from '@theia/editor/lib/browser'; import { MonacoEditorProvider, MonacoEditorFactory } from './monaco-editor-provider'; @@ -135,7 +136,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(FrontendApplicationContribution).toService(MonacoFormattingConflictsContribution); bind(MonacoStatusBarContribution).toSelf().inSingletonScope(); - bind(FrontendApplicationContribution).toService(MonacoStatusBarContribution); + bind(WidgetStatusBarContribution).toService(MonacoStatusBarContribution); bind(MonacoCommandRegistry).toSelf().inSingletonScope(); bind(MonacoEditorCommandHandlers).toSelf().inSingletonScope(); diff --git a/packages/monaco/src/browser/monaco-status-bar-contribution.ts b/packages/monaco/src/browser/monaco-status-bar-contribution.ts index fae85805e9f1a..c7ac733d29987 100644 --- a/packages/monaco/src/browser/monaco-status-bar-contribution.ts +++ b/packages/monaco/src/browser/monaco-status-bar-contribution.ts @@ -14,93 +14,90 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { injectable, inject } from '@theia/core/shared/inversify'; +import { injectable } from '@theia/core/shared/inversify'; import { DisposableCollection, nls } from '@theia/core'; -import { FrontendApplicationContribution, FrontendApplication, StatusBar, StatusBarAlignment } from '@theia/core/lib/browser'; -import { EditorCommands, EditorManager, EditorWidget } from '@theia/editor/lib/browser'; +import { StatusBar, StatusBarAlignment, Widget, WidgetStatusBarContribution } from '@theia/core/lib/browser'; +import { EditorCommands, EditorWidget } from '@theia/editor/lib/browser'; import { MonacoEditor } from './monaco-editor'; import * as monaco from '@theia/monaco-editor-core'; +export const EDITOR_STATUS_TABBING_CONFIG = 'editor-status-tabbing-config'; +export const EDITOR_STATUS_EOL = 'editor-status-eol'; + @injectable() -export class MonacoStatusBarContribution implements FrontendApplicationContribution { +export class MonacoStatusBarContribution implements WidgetStatusBarContribution { protected readonly toDispose = new DisposableCollection(); - constructor( - @inject(EditorManager) protected readonly editorManager: EditorManager, - @inject(StatusBar) protected readonly statusBar: StatusBar - ) { } - - onStart(app: FrontendApplication): void { - this.updateStatusBar(); - this.editorManager.onCurrentEditorChanged(() => this.updateStatusBar()); + canHandle(widget: Widget): widget is EditorWidget { + if (widget instanceof EditorWidget) { + return Boolean(this.getModel(widget)); + } + return false; } - protected updateStatusBar(): void { - const editor = this.editorManager.currentEditor; + activate(statusBar: StatusBar, editor: EditorWidget): void { + this.toDispose.dispose(); const editorModel = this.getModel(editor); - if (editor && editorModel) { - this.setConfigTabSizeWidget(); - this.setLineEndingWidget(); - - this.toDispose.dispose(); + if (editorModel) { + this.setConfigTabSizeWidget(statusBar, editorModel); + this.setLineEndingWidget(statusBar, editorModel); this.toDispose.push(editorModel.onDidChangeOptions(() => { - this.setConfigTabSizeWidget(); - this.setLineEndingWidget(); + this.setConfigTabSizeWidget(statusBar, editorModel); + this.setLineEndingWidget(statusBar, editorModel); })); let previous = editorModel.getEOL(); this.toDispose.push(editorModel.onDidChangeContent(e => { if (previous !== e.eol) { previous = e.eol; - this.setLineEndingWidget(); + this.setLineEndingWidget(statusBar, editorModel); } })); } else { - this.removeConfigTabSizeWidget(); - this.removeLineEndingWidget(); + this.deactivate(statusBar); } } - protected setConfigTabSizeWidget(): void { - const editor = this.editorManager.currentEditor; - const editorModel = this.getModel(editor); - if (editor && editorModel) { - const modelOptions = editorModel.getOptions(); - const tabSize = modelOptions.tabSize; - const indentSize = modelOptions.indentSize; - const spaceOrTabSizeMessage = modelOptions.insertSpaces - ? nls.localizeByDefault('Spaces: {0}', indentSize) - : nls.localizeByDefault('Tab Size: {0}', tabSize); - this.statusBar.setElement('editor-status-tabbing-config', { - text: spaceOrTabSizeMessage, - alignment: StatusBarAlignment.RIGHT, - priority: 10, - command: EditorCommands.CONFIG_INDENTATION.id, - tooltip: nls.localizeByDefault('Select Indentation') - }); - } + deactivate(statusBar: StatusBar): void { + this.toDispose.dispose(); + this.removeConfigTabSizeWidget(statusBar); + this.removeLineEndingWidget(statusBar); } - protected removeConfigTabSizeWidget(): void { - this.statusBar.removeElement('editor-status-tabbing-config'); + + protected setConfigTabSizeWidget(statusBar: StatusBar, model: monaco.editor.ITextModel): void { + const modelOptions = model.getOptions(); + const tabSize = modelOptions.tabSize; + const indentSize = modelOptions.indentSize; + const spaceOrTabSizeMessage = modelOptions.insertSpaces + ? nls.localizeByDefault('Spaces: {0}', indentSize) + : nls.localizeByDefault('Tab Size: {0}', tabSize); + statusBar.setElement(EDITOR_STATUS_TABBING_CONFIG, { + text: spaceOrTabSizeMessage, + alignment: StatusBarAlignment.RIGHT, + priority: 10, + command: EditorCommands.CONFIG_INDENTATION.id, + tooltip: nls.localizeByDefault('Select Indentation') + }); } - protected setLineEndingWidget(): void { - const editor = this.editorManager.currentEditor; - const editorModel = this.getModel(editor); - if (editor && editorModel) { - const eol = editorModel.getEOL(); - const text = eol === '\n' ? 'LF' : 'CRLF'; - this.statusBar.setElement('editor-status-eol', { - text: `${text}`, - alignment: StatusBarAlignment.RIGHT, - priority: 11, - command: EditorCommands.CONFIG_EOL.id, - tooltip: nls.localizeByDefault('Select End of Line Sequence') - }); - } + protected removeConfigTabSizeWidget(statusBar: StatusBar): void { + statusBar.removeElement(EDITOR_STATUS_TABBING_CONFIG); } - protected removeLineEndingWidget(): void { - this.statusBar.removeElement('editor-status-eol'); + + protected setLineEndingWidget(statusBar: StatusBar, model: monaco.editor.ITextModel): void { + const eol = model.getEOL(); + const text = eol === '\n' ? 'LF' : 'CRLF'; + statusBar.setElement(EDITOR_STATUS_EOL, { + text: `${text}`, + alignment: StatusBarAlignment.RIGHT, + priority: 11, + command: EditorCommands.CONFIG_EOL.id, + tooltip: nls.localizeByDefault('Select End of Line Sequence') + }); + } + + protected removeLineEndingWidget(statusBar: StatusBar): void { + statusBar.removeElement(EDITOR_STATUS_EOL); } protected getModel(editor: EditorWidget | undefined): monaco.editor.ITextModel | undefined { diff --git a/packages/notebook/src/browser/contributions/notebook-status-bar-contribution.ts b/packages/notebook/src/browser/contributions/notebook-status-bar-contribution.ts index 05ded847b5bb3..740970baf76ca 100644 --- a/packages/notebook/src/browser/contributions/notebook-status-bar-contribution.ts +++ b/packages/notebook/src/browser/contributions/notebook-status-bar-contribution.ts @@ -14,10 +14,9 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { inject, injectable } from '@theia/core/shared/inversify'; -import { FrontendApplicationContribution, StatusBar, StatusBarAlignment } from '@theia/core/lib/browser'; +import { injectable } from '@theia/core/shared/inversify'; +import { StatusBar, StatusBarAlignment, Widget, WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { Disposable } from '@theia/core/lib/common'; -import { NotebookEditorWidgetService } from '../service/notebook-editor-widget-service'; import { NotebookEditorWidget } from '../notebook-editor-widget'; import { nls } from '@theia/core'; import { NotebookCommands } from './notebook-actions-contribution'; @@ -25,53 +24,43 @@ import { NotebookCommands } from './notebook-actions-contribution'; export const NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID = 'notebook-cell-selection-position'; @injectable() -export class NotebookStatusBarContribution implements FrontendApplicationContribution { +export class NotebookStatusBarContribution implements WidgetStatusBarContribution { - @inject(StatusBar) protected readonly statusBar: StatusBar; - @inject(NotebookEditorWidgetService) protected readonly editorWidgetService: NotebookEditorWidgetService; + protected onDeactivate: Disposable | undefined; - protected currentCellSelectionListener: Disposable | undefined; - protected lastFocusedEditor: NotebookEditorWidget | undefined; + canHandle(widget: Widget): widget is NotebookEditorWidget { + return widget instanceof NotebookEditorWidget; + } - onStart(): void { - this.editorWidgetService.onDidChangeFocusedEditor(editor => { - this.currentCellSelectionListener?.dispose(); - this.currentCellSelectionListener = editor?.model?.onDidChangeSelectedCell(() => - this.updateStatusbar(editor) - ); - editor?.onDidDispose(() => { - this.lastFocusedEditor = undefined; - this.updateStatusbar(); + activate(statusBar: StatusBar, widget: NotebookEditorWidget): void { + widget.ready.then(model => { + this.onDeactivate = model.onDidChangeSelectedCell(() => { + this.updateStatusbar(statusBar, widget); }); - this.updateStatusbar(editor); - this.lastFocusedEditor = editor; }); - if (this.editorWidgetService.focusedEditor) { - this.updateStatusbar(); - } + this.updateStatusbar(statusBar, widget); } - protected async updateStatusbar(editor?: NotebookEditorWidget): Promise { - if ((!editor && !this.lastFocusedEditor?.isVisible) || editor?.model?.cells.length === 0) { - this.statusBar.removeElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID); - return; - } + deactivate(statusBar: StatusBar): void { + this.onDeactivate?.dispose(); + this.updateStatusbar(statusBar); + } - await editor?.ready; - if (!editor?.model) { + protected async updateStatusbar(statusBar: StatusBar, editor?: NotebookEditorWidget): Promise { + const model = await editor?.ready; + if (!model || model.cells.length === 0 || !model.selectedCell) { + statusBar.removeElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID); return; } - const selectedCellIndex = editor.model.selectedCell ? editor.model.cells.indexOf(editor.model.selectedCell) + 1 : ''; + const selectedCellIndex = model.cells.indexOf(model.selectedCell) + 1; - this.statusBar.setElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID, { - text: nls.localizeByDefault('Cell {0} of {1}', selectedCellIndex, editor.model.cells.length), + statusBar.setElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID, { + text: nls.localizeByDefault('Cell {0} of {1}', selectedCellIndex, model.cells.length), alignment: StatusBarAlignment.RIGHT, priority: 100, command: NotebookCommands.CENTER_ACTIVE_CELL.id, arguments: [editor] }); - } - } diff --git a/packages/notebook/src/browser/notebook-frontend-module.ts b/packages/notebook/src/browser/notebook-frontend-module.ts index 839d16908a17d..b5158315668b2 100644 --- a/packages/notebook/src/browser/notebook-frontend-module.ts +++ b/packages/notebook/src/browser/notebook-frontend-module.ts @@ -16,7 +16,9 @@ import '../../src/browser/style/index.css'; import { ContainerModule } from '@theia/core/shared/inversify'; -import { FrontendApplicationContribution, KeybindingContribution, LabelProviderContribution, OpenHandler, UndoRedoHandler, WidgetFactory } from '@theia/core/lib/browser'; +import { + FrontendApplicationContribution, KeybindingContribution, LabelProviderContribution, OpenHandler, UndoRedoHandler, WidgetFactory, WidgetStatusBarContribution +} from '@theia/core/lib/browser'; import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; import { NotebookOpenHandler } from './notebook-open-handler'; import { CommandContribution, MenuContribution, ResourceResolver, } from '@theia/core'; @@ -117,5 +119,5 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(UndoRedoHandler).toService(NotebookUndoRedoHandler); bind(NotebookStatusBarContribution).toSelf().inSingletonScope(); - bind(FrontendApplicationContribution).toService(NotebookStatusBarContribution); + bind(WidgetStatusBarContribution).toService(NotebookStatusBarContribution); }); diff --git a/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts b/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts index a8510268870f3..5e592c30c397b 100644 --- a/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts +++ b/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts @@ -22,7 +22,9 @@ import { ContainerModule } from '@theia/core/shared/inversify'; import { FrontendApplicationContribution, WidgetFactory, bindViewContribution, ViewContainerIdentifier, ViewContainer, createTreeContainer, TreeWidget, LabelProviderContribution, LabelProvider, - UndoRedoHandler, DiffUris, Navigatable, SplitWidget + UndoRedoHandler, DiffUris, Navigatable, SplitWidget, + noopWidgetStatusBarContribution, + WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { MaybePromise, CommandContribution, ResourceResolver, bindContributionProvider, URI, generateUuid } from '@theia/core/lib/common'; import { WebSocketConnectionProvider } from '@theia/core/lib/browser/messaging'; @@ -191,6 +193,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(WebviewSecondaryWindowSupport).toSelf().inSingletonScope(); bind(FrontendApplicationContribution).toService(WebviewSecondaryWindowSupport); bind(FrontendApplicationContribution).toService(WebviewContextKeys); + bind(WidgetStatusBarContribution).toConstantValue(noopWidgetStatusBarContribution(WebviewWidget)); bind(PluginCustomEditorRegistry).toSelf().inSingletonScope(); bind(CustomEditorService).toSelf().inSingletonScope(); diff --git a/packages/preferences/src/browser/preference-frontend-module.ts b/packages/preferences/src/browser/preference-frontend-module.ts index ef7d553bcee84..d55f47e63d60b 100644 --- a/packages/preferences/src/browser/preference-frontend-module.ts +++ b/packages/preferences/src/browser/preference-frontend-module.ts @@ -17,7 +17,7 @@ import '../../src/browser/style/index.css'; import './preferences-monaco-contribution'; import { ContainerModule, interfaces } from '@theia/core/shared/inversify'; -import { bindViewContribution, FrontendApplicationContribution, OpenHandler } from '@theia/core/lib/browser'; +import { bindViewContribution, FrontendApplicationContribution, noopWidgetStatusBarContribution, OpenHandler, WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; import { PreferenceTreeGenerator } from './util/preference-tree-generator'; import { bindPreferenceProviders } from './preference-bindings'; @@ -33,6 +33,7 @@ import { CliPreferences, CliPreferencesPath } from '../common/cli-preferences'; import { ServiceConnectionProvider } from '@theia/core/lib/browser/messaging/service-connection-provider'; import { PreferenceFrontendContribution } from './preference-frontend-contribution'; import { PreferenceLayoutProvider } from './util/preference-layout'; +import { PreferencesWidget } from './views/preference-widget'; export function bindPreferences(bind: interfaces.Bind, unbind: interfaces.Unbind): void { bindPreferenceProviders(bind, unbind); @@ -59,6 +60,8 @@ export function bindPreferences(bind: interfaces.Bind, unbind: interfaces.Unbind bind(CliPreferences).toDynamicValue(ctx => ServiceConnectionProvider.createProxy(ctx.container, CliPreferencesPath)).inSingletonScope(); bind(PreferenceFrontendContribution).toSelf().inSingletonScope(); bind(FrontendApplicationContribution).toService(PreferenceFrontendContribution); + + bind(WidgetStatusBarContribution).toConstantValue(noopWidgetStatusBarContribution(PreferencesWidget)); } export default new ContainerModule((bind, unbind, isBound, rebind) => { diff --git a/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts b/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts index 2bb0b34eec0c9..19736daf75b62 100644 --- a/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts +++ b/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts @@ -18,7 +18,9 @@ import '../../src/browser/style/index.css'; import { ContainerModule } from '@theia/core/shared/inversify'; import { - WidgetFactory, bindViewContribution, FrontendApplicationContribution, ViewContainerIdentifier, OpenHandler, WidgetManager, WebSocketConnectionProvider + WidgetFactory, bindViewContribution, FrontendApplicationContribution, ViewContainerIdentifier, OpenHandler, WidgetManager, WebSocketConnectionProvider, + WidgetStatusBarContribution, + noopWidgetStatusBarContribution } from '@theia/core/lib/browser'; import { VSXExtensionsViewContainer } from './vsx-extensions-view-container'; import { VSXExtensionsContribution } from './vsx-extensions-contribution'; @@ -64,6 +66,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { })).inSingletonScope(); bind(VSXExtensionEditorManager).toSelf().inSingletonScope(); bind(OpenHandler).toService(VSXExtensionEditorManager); + bind(WidgetStatusBarContribution).toConstantValue(noopWidgetStatusBarContribution(VSXExtensionEditor)); bind(WidgetFactory).toDynamicValue(({ container }) => ({ id: VSXExtensionsWidget.ID,