initial support of QuickPickItemButton API (#130519)

This commit is contained in:
Tyler James Leonhardt 2021-08-11 08:42:29 -07:00 committed by GitHub
parent 0344ecd462
commit 4191923874
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 127 additions and 65 deletions

View file

@ -2796,4 +2796,18 @@ declare module 'vscode' {
}
//#endregion
//#region https://github.com/microsoft/vscode/issues/88716
export interface QuickPickItem {
buttons?: QuickInputButton[];
}
export interface QuickPick<T extends QuickPickItem> extends QuickInput {
readonly onDidTriggerItemButton: Event<QuickPickItemButtonEvent<T>>;
}
export interface QuickPickItemButtonEvent<T extends QuickPickItem> {
button: QuickInputButton;
item: T;
}
//#endregion
}

View file

@ -3,18 +3,24 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IPickOptions, IInputOptions, IQuickInputService, IQuickInput } from 'vs/platform/quickinput/common/quickInput';
import { IPickOptions, IInputOptions, IQuickInputService, IQuickInput, IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { ExtHostContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, TransferQuickPickItems, MainContext, IExtHostContext, TransferQuickInput, TransferQuickInputButton, IInputBoxOptions } from 'vs/workbench/api/common/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { URI } from 'vs/base/common/uri';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
interface QuickInputSession {
input: IQuickInput;
handlesToItems: Map<number, TransferQuickPickItems>;
}
function reviveIconPathUris(iconPath: { dark: URI; light?: URI | undefined; }) {
iconPath.dark = URI.revive(iconPath.dark);
if (iconPath.light) {
iconPath.light = URI.revive(iconPath.light);
}
}
@extHostNamedCustomer(MainContext.MainThreadQuickOpen)
export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
@ -115,49 +121,39 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
const sessionId = params.id;
let session = this.sessions.get(sessionId);
if (!session) {
const input = params.type === 'quickPick' ? this._quickInputService.createQuickPick() : this._quickInputService.createInputBox();
input.onDidAccept(() => {
this._proxy.$onDidAccept(sessionId);
});
input.onDidTriggerButton(button => {
this._proxy.$onDidTriggerButton(sessionId, (button as TransferQuickInputButton).handle);
});
input.onDidChangeValue(value => {
this._proxy.$onDidChangeValue(sessionId, value);
});
input.onDidHide(() => {
this._proxy.$onDidHide(sessionId);
});
if (params.type === 'quickPick') {
const input = this._quickInputService.createQuickPick();
input.onDidAccept(() => {
this._proxy.$onDidAccept(sessionId);
});
input.onDidChangeActive(items => {
// Add extra events specific for quickpick
const quickpick = input as IQuickPick<IQuickPickItem>;
quickpick.onDidChangeActive(items => {
this._proxy.$onDidChangeActive(sessionId, items.map(item => (item as TransferQuickPickItems).handle));
});
input.onDidChangeSelection(items => {
quickpick.onDidChangeSelection(items => {
this._proxy.$onDidChangeSelection(sessionId, items.map(item => (item as TransferQuickPickItems).handle));
});
input.onDidTriggerButton(button => {
this._proxy.$onDidTriggerButton(sessionId, (button as TransferQuickInputButton).handle);
quickpick.onDidTriggerItemButton((e) => {
this._proxy.$onDidTriggerItemButton(sessionId, (e.item as TransferQuickPickItems).handle, (e.button as TransferQuickInputButton).handle);
});
input.onDidChangeValue(value => {
this._proxy.$onDidChangeValue(sessionId, value);
});
input.onDidHide(() => {
this._proxy.$onDidHide(sessionId);
});
session = {
input,
handlesToItems: new Map()
};
} else {
const input = this._quickInputService.createInputBox();
input.onDidAccept(() => {
this._proxy.$onDidAccept(sessionId);
});
input.onDidTriggerButton(button => {
this._proxy.$onDidTriggerButton(sessionId, (button as TransferQuickInputButton).handle);
});
input.onDidChangeValue(value => {
this._proxy.$onDidChangeValue(sessionId, value);
});
input.onDidHide(() => {
this._proxy.$onDidHide(sessionId);
});
session = {
input,
handlesToItems: new Map()
};
}
session = {
input,
handlesToItems: new Map()
};
this.sessions.set(sessionId, session);
}
const { input, handlesToItems } = session;
@ -174,6 +170,15 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
} else if (param === 'items') {
handlesToItems.clear();
params[param].forEach((item: TransferQuickPickItems) => {
if (item.buttons) {
item.buttons = item.buttons.map((button: TransferQuickInputButton) => {
if (button.iconPath) {
reviveIconPathUris(button.iconPath);
}
return button;
});
}
handlesToItems.set(item.handle, item);
});
(input as any)[param] = params[param];
@ -186,23 +191,12 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
if (button.handle === -1) {
return this._quickInputService.backButton;
}
const { iconPath, tooltip, handle } = button;
if ('id' in iconPath) {
return {
iconClass: ThemeIcon.asClassName(iconPath),
tooltip,
handle
};
} else {
return {
iconPath: {
dark: URI.revive(iconPath.dark),
light: iconPath.light && URI.revive(iconPath.light)
},
tooltip,
handle
};
if (button.iconPath) {
reviveIconPathUris(button.iconPath);
}
return button;
});
} else {
(input as any)[param] = params[param];

View file

@ -516,12 +516,11 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
export interface TransferQuickPickItems extends quickInput.IQuickPickItem {
handle: number;
buttons?: TransferQuickInputButton[];
}
export interface TransferQuickInputButton {
export interface TransferQuickInputButton extends quickInput.IQuickInputButton {
handle: number;
iconPath: { dark: URI; light?: URI; } | { id: string; };
tooltip?: string;
}
export type TransferQuickInput = TransferQuickPick | TransferInputBox;
@ -1706,6 +1705,7 @@ export interface ExtHostQuickOpenShape {
$onDidAccept(sessionId: number): void;
$onDidChangeValue(sessionId: number, value: string): void;
$onDidTriggerButton(sessionId: number, handle: number): void;
$onDidTriggerItemButton(sessionId: number, itemHandle: number, buttonHandle: number): void;
$onDidHide(sessionId: number): void;
}

View file

@ -9,7 +9,7 @@ import { Emitter } from 'vs/base/common/event';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { IExtHostWorkspaceProvider } from 'vs/workbench/api/common/extHostWorkspace';
import { InputBox, InputBoxOptions, QuickInput, QuickInputButton, QuickPick, QuickPickItem, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
import { InputBox, InputBoxOptions, QuickInput, QuickInputButton, QuickPick, QuickPickItem, QuickPickItemButtonEvent, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
import { ExtHostQuickOpenShape, IMainContext, MainContext, TransferQuickPickItems, TransferQuickInput, TransferQuickInputButton } from './extHost.protocol';
import { URI } from 'vs/base/common/uri';
import { ThemeIcon, QuickInputButtons } from 'vs/workbench/api/common/extHostTypes';
@ -17,6 +17,7 @@ import { isPromiseCanceledError } from 'vs/base/common/errors';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { coalesce } from 'vs/base/common/arrays';
import Severity from 'vs/base/common/severity';
import { ThemeIcon as ThemeIconUtils } from 'vs/platform/theme/common/themeService';
export type Item = string | QuickPickItem;
@ -238,6 +239,13 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
}
}
$onDidTriggerItemButton(sessionId: number, itemHandle: number, buttonHandle: number): void {
const session = this._sessions.get(sessionId);
if (session instanceof ExtHostQuickPick) {
session._fireDidTriggerItemButton(itemHandle, buttonHandle);
}
}
$onDidHide(sessionId: number): void {
const session = this._sessions.get(sessionId);
if (session) {
@ -369,11 +377,13 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
this._handlesToButtons.set(handle, button);
});
this.update({
buttons: buttons.map<TransferQuickInputButton>((button, i) => ({
iconPath: getIconUris(button.iconPath),
tooltip: button.tooltip,
handle: button === QuickInputButtons.Back ? -1 : i,
}))
buttons: buttons.map<TransferQuickInputButton>((button, i) => {
return {
...getIconPathOrClass(button),
tooltip: button.tooltip,
handle: button === QuickInputButtons.Back ? -1 : i,
};
})
});
}
@ -481,6 +491,22 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
return typeof iconPath === 'object' && 'dark' in iconPath ? iconPath.dark : iconPath;
}
function getIconPathOrClass(button: QuickInputButton) {
const iconPathOrIconClass = getIconUris(button.iconPath);
let iconPath: { dark: URI; light?: URI | undefined; } | undefined;
let iconClass: string | undefined;
if ('id' in iconPathOrIconClass) {
iconClass = ThemeIconUtils.asClassName(iconPathOrIconClass);
} else {
iconPath = iconPathOrIconClass;
}
return {
iconPath,
iconClass
};
}
class ExtHostQuickPick<T extends QuickPickItem> extends ExtHostQuickInput implements QuickPick<T> {
private _items: T[] = [];
@ -494,12 +520,14 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
private readonly _onDidChangeActiveEmitter = new Emitter<T[]>();
private _selectedItems: T[] = [];
private readonly _onDidChangeSelectionEmitter = new Emitter<T[]>();
private readonly _onDidTriggerItemButtonEmitter = new Emitter<QuickPickItemButtonEvent<T>>();
constructor(extensionId: ExtensionIdentifier, enableProposedApi: boolean, onDispose: () => void) {
constructor(extensionId: ExtensionIdentifier, private readonly enableProposedApi: boolean, onDispose: () => void) {
super(extensionId, onDispose);
this._disposables.push(
this._onDidChangeActiveEmitter,
this._onDidChangeSelectionEmitter,
this._onDidTriggerItemButtonEmitter
);
this.update({ type: 'quickPick' });
}
@ -523,7 +551,17 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
handle: i,
detail: item.detail,
picked: item.picked,
alwaysShow: item.alwaysShow
alwaysShow: item.alwaysShow,
// Proposed API only at the moment
buttons: item.buttons && this.enableProposedApi
? item.buttons.map<TransferQuickInputButton>((button, i) => {
return {
...getIconPathOrClass(button),
tooltip: button.tooltip,
handle: i
};
})
: undefined,
}))
});
}
@ -597,6 +635,22 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
this._selectedItems = items;
this._onDidChangeSelectionEmitter.fire(items);
}
onDidTriggerItemButton = this._onDidTriggerItemButtonEmitter.event;
_fireDidTriggerItemButton(itemHandle: number, buttonHandle: number) {
const item = this._handlesToItems.get(itemHandle)!;
if (!item || !item.buttons || !item.buttons.length) {
return;
}
const button = item.buttons[buttonHandle];
if (button) {
this._onDidTriggerItemButtonEmitter.fire({
button,
item
});
}
}
}
class ExtHostInputBox extends ExtHostQuickInput implements InputBox {