diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 9e852eca701..6ba87f6803a 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -4975,10 +4975,11 @@ declare module 'vscode' { color: string | ThemeColor | undefined; /** - * The identifier of a command to run on click. The command must be - * [known](#commands.getCommands). + * [`Command`](#Command) or identifier of a command to run on click. + * + * The command must be [known](#commands.getCommands). */ - command: string | undefined; + command: string | Command | undefined; /** * Shows the entry in the status bar. diff --git a/src/vs/workbench/api/browser/mainThreadStatusBar.ts b/src/vs/workbench/api/browser/mainThreadStatusBar.ts index 91a9ba1419f..fb733a38228 100644 --- a/src/vs/workbench/api/browser/mainThreadStatusBar.ts +++ b/src/vs/workbench/api/browser/mainThreadStatusBar.ts @@ -8,6 +8,7 @@ import { MainThreadStatusBarShape, MainContext, IExtHostContext } from '../commo import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { dispose } from 'vs/base/common/lifecycle'; +import { Command } from 'vs/editor/common/modes'; @extHostNamedCustomer(MainContext.MainThreadStatusBar) export class MainThreadStatusBar implements MainThreadStatusBarShape { @@ -24,7 +25,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { this.entries.clear(); } - $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: string | undefined, color: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined): void { + $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined): void { const entry: IStatusbarEntry = { text, tooltip, command, color }; if (typeof priority === 'undefined') { diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 143bc3bdf77..39f0534293c 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -143,7 +143,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I const extHostClipboard = new ExtHostClipboard(rpcProtocol); const extHostMessageService = new ExtHostMessageService(rpcProtocol, extHostLogService); const extHostDialogs = new ExtHostDialogs(rpcProtocol); - const extHostStatusBar = new ExtHostStatusBar(rpcProtocol); + const extHostStatusBar = new ExtHostStatusBar(rpcProtocol, extHostCommands.converter); const extHostLanguages = new ExtHostLanguages(rpcProtocol, extHostDocuments); // Register API-ish commands diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index a21449c9036..ec69c297aa0 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -533,7 +533,7 @@ export interface MainThreadQuickOpenShape extends IDisposable { } export interface MainThreadStatusBarShape extends IDisposable { - $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: string | undefined, color: string | ThemeColor | undefined, alignment: statusbar.StatusbarAlignment, priority: number | undefined): void; + $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: ICommandDto | undefined, color: string | ThemeColor | undefined, alignment: statusbar.StatusbarAlignment, priority: number | undefined): void; $dispose(id: number): void; } diff --git a/src/vs/workbench/api/common/extHostStatusBar.ts b/src/vs/workbench/api/common/extHostStatusBar.ts index 02c89a6e89e..d26ee3d7c86 100644 --- a/src/vs/workbench/api/common/extHostStatusBar.ts +++ b/src/vs/workbench/api/common/extHostStatusBar.ts @@ -5,11 +5,13 @@ import { StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/workbench/services/statusbar/common/statusbar'; import { StatusBarAlignment as ExtHostStatusBarAlignment, Disposable, ThemeColor } from './extHostTypes'; -import { StatusBarItem, StatusBarAlignment } from 'vscode'; -import { MainContext, MainThreadStatusBarShape, IMainContext } from './extHost.protocol'; +import type * as vscode from 'vscode'; +import { MainContext, MainThreadStatusBarShape, IMainContext, ICommandDto } from './extHost.protocol'; import { localize } from 'vs/nls'; +import { CommandsConverter } from 'vs/workbench/api/common/extHostCommands'; +import { DisposableStore } from 'vs/base/common/lifecycle'; -export class ExtHostStatusBarEntry implements StatusBarItem { +export class ExtHostStatusBarEntry implements vscode.StatusBarItem { private static ID_GEN = 0; private _id: number; @@ -24,14 +26,20 @@ export class ExtHostStatusBarEntry implements StatusBarItem { private _text: string = ''; private _tooltip?: string; private _color?: string | ThemeColor; - private _command?: string; + private readonly _internalCommandRegistration = new DisposableStore(); + private _command?: { + readonly fromApi: string | vscode.Command, + readonly internal: ICommandDto, + }; private _timeoutHandle: any; private _proxy: MainThreadStatusBarShape; + private _commands: CommandsConverter; - constructor(proxy: MainThreadStatusBarShape, id: string, name: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number) { + constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, id: string, name: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number) { this._id = ExtHostStatusBarEntry.ID_GEN++; this._proxy = proxy; + this._commands = commands; this._statusId = id; this._statusName = name; this._alignment = alignment; @@ -42,7 +50,7 @@ export class ExtHostStatusBarEntry implements StatusBarItem { return this._id; } - public get alignment(): StatusBarAlignment { + public get alignment(): vscode.StatusBarAlignment { return this._alignment; } @@ -62,8 +70,8 @@ export class ExtHostStatusBarEntry implements StatusBarItem { return this._color; } - public get command(): string | undefined { - return this._command; + public get command(): string | vscode.Command | undefined { + return this._command?.fromApi; } public set text(text: string) { @@ -81,8 +89,25 @@ export class ExtHostStatusBarEntry implements StatusBarItem { this.update(); } - public set command(command: string | undefined) { - this._command = command; + public set command(command: string | vscode.Command | undefined) { + if (this._command?.fromApi === command) { + return; + } + + this._internalCommandRegistration.clear(); + if (typeof command === 'string') { + this._command = { + fromApi: command, + internal: this._commands.toInternal({ title: '', command }, this._internalCommandRegistration), + }; + } else if (command) { + this._command = { + fromApi: command, + internal: this._commands.toInternal(command, this._internalCommandRegistration), + }; + } else { + this._command = undefined; + } this.update(); } @@ -109,7 +134,7 @@ export class ExtHostStatusBarEntry implements StatusBarItem { this._timeoutHandle = undefined; // Set to status bar - this._proxy.$setEntry(this.id, this._statusId, this._statusName, this.text, this.tooltip, this.command, this.color, + this._proxy.$setEntry(this.id, this._statusId, this._statusName, this.text, this.tooltip, this._command?.internal, this.color, this._alignment === ExtHostStatusBarAlignment.Left ? MainThreadStatusBarAlignment.LEFT : MainThreadStatusBarAlignment.RIGHT, this._priority); }, 0); @@ -123,7 +148,7 @@ export class ExtHostStatusBarEntry implements StatusBarItem { class StatusBarMessage { - private _item: StatusBarItem; + private _item: vscode.StatusBarItem; private _messages: { message: string }[] = []; constructor(statusBar: ExtHostStatusBar) { @@ -161,16 +186,18 @@ class StatusBarMessage { export class ExtHostStatusBar { - private _proxy: MainThreadStatusBarShape; + private readonly _proxy: MainThreadStatusBarShape; + private readonly _commands: CommandsConverter; private _statusMessage: StatusBarMessage; - constructor(mainContext: IMainContext) { + constructor(mainContext: IMainContext, commands: CommandsConverter) { this._proxy = mainContext.getProxy(MainContext.MainThreadStatusBar); + this._commands = commands; this._statusMessage = new StatusBarMessage(this); } - createStatusBarEntry(id: string, name: string, alignment?: ExtHostStatusBarAlignment, priority?: number): StatusBarItem { - return new ExtHostStatusBarEntry(this._proxy, id, name, alignment, priority); + createStatusBarEntry(id: string, name: string, alignment?: ExtHostStatusBarAlignment, priority?: number): vscode.StatusBarItem { + return new ExtHostStatusBarEntry(this._proxy, this._commands, id, name, alignment, priority); } setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable): Disposable { diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 4d140afcf29..b3a0df2c36b 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -34,6 +34,7 @@ import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { values } from 'vs/base/common/map'; import { assertIsDefined } from 'vs/base/common/types'; import { Emitter, Event } from 'vs/base/common/event'; +import { Command } from 'vs/editor/common/modes'; interface IPendingStatusbarEntry { id: string; @@ -702,7 +703,7 @@ class StatusbarEntryItem extends Disposable { const command = entry.command; if (command) { - this.commandListener.value = addDisposableListener(this.labelContainer, EventType.CLICK, () => this.executeCommand(command, entry.arguments)); + this.commandListener.value = addDisposableListener(this.labelContainer, EventType.CLICK, () => this.executeCommand(command)); removeClass(this.labelContainer, 'disabled'); } else { @@ -738,8 +739,9 @@ class StatusbarEntryItem extends Disposable { this.entry = entry; } - private async executeCommand(id: string, args?: unknown[]): Promise { - args = args || []; + private async executeCommand(command: string | Command): Promise { + const id = typeof command === 'string' ? command : command.id; + const args = typeof command === 'string' ? [] : command.arguments ?? []; // Maintain old behaviour of always focusing the editor here const activeTextEditorControl = this.editorService.activeTextEditorControl; diff --git a/src/vs/workbench/contrib/scm/browser/activity.ts b/src/vs/workbench/contrib/scm/browser/activity.ts index 150e3b562e7..13ed604bd7f 100644 --- a/src/vs/workbench/contrib/scm/browser/activity.ts +++ b/src/vs/workbench/contrib/scm/browser/activity.ts @@ -159,8 +159,7 @@ export class SCMStatusController implements IWorkbenchContribution { disposables.add(this.statusbarService.addEntry({ text: c.title, tooltip: `${label} - ${c.tooltip}`, - command: c.id, - arguments: c.arguments + command: c }, 'status.scm', localize('status.scm', "Source Control"), MainThreadStatusBarAlignment.LEFT, 10000)); } diff --git a/src/vs/workbench/services/statusbar/common/statusbar.ts b/src/vs/workbench/services/statusbar/common/statusbar.ts index 31f46524c9c..130101a530b 100644 --- a/src/vs/workbench/services/statusbar/common/statusbar.ts +++ b/src/vs/workbench/services/statusbar/common/statusbar.ts @@ -7,6 +7,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' import { IDisposable } from 'vs/base/common/lifecycle'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { Event } from 'vs/base/common/event'; +import { Command } from 'vs/editor/common/modes'; export const IStatusbarService = createDecorator('statusbarService'); @@ -45,12 +46,7 @@ export interface IStatusbarEntry { /** * An optional id of a command that is known to the workbench to execute on click */ - readonly command?: string; - - /** - * Optional arguments for the command. - */ - readonly arguments?: unknown[]; + readonly command?: string | Command; /** * Whether to show a beak above the status bar entry.