mirror of
https://github.com/Microsoft/vscode
synced 2024-10-30 03:47:56 +00:00
First cut of quick pick separators as kind
. ref #74967
This commit is contained in:
parent
958a5ad8bb
commit
a41001c482
4 changed files with 113 additions and 78 deletions
7
src/vs/vscode.proposed.d.ts
vendored
7
src/vs/vscode.proposed.d.ts
vendored
|
@ -2762,4 +2762,11 @@ declare module 'vscode' {
|
|||
|
||||
//#endregion
|
||||
|
||||
//#region quickPickItemKind: https://github.com/microsoft/vscode/issues/74967
|
||||
|
||||
export interface QuickPickItem {
|
||||
kind?: string | { label: string; };
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
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 { ExtHostContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, TransferQuickPickItem, MainContext, IExtHostContext, TransferQuickInput, TransferQuickInputButton, IInputBoxOptions, TransferQuickPickItemOrSeparator } 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';
|
||||
|
||||
interface QuickInputSession {
|
||||
input: IQuickInput;
|
||||
handlesToItems: Map<number, TransferQuickPickItems>;
|
||||
handlesToItems: Map<number, TransferQuickPickItem>;
|
||||
}
|
||||
|
||||
function reviveIconPathUris(iconPath: { dark: URI; light?: URI | undefined; }) {
|
||||
|
@ -27,7 +27,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
|
|||
private readonly _proxy: ExtHostQuickOpenShape;
|
||||
private readonly _quickInputService: IQuickInputService;
|
||||
private readonly _items: Record<number, {
|
||||
resolve(items: TransferQuickPickItems[]): void;
|
||||
resolve(items: TransferQuickPickItemOrSeparator[]): void;
|
||||
reject(error: Error): void;
|
||||
}> = {};
|
||||
|
||||
|
@ -42,8 +42,8 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
|
|||
public dispose(): void {
|
||||
}
|
||||
|
||||
$show(instance: number, options: IPickOptions<TransferQuickPickItems>, token: CancellationToken): Promise<number | number[] | undefined> {
|
||||
const contents = new Promise<TransferQuickPickItems[]>((resolve, reject) => {
|
||||
$show(instance: number, options: IPickOptions<TransferQuickPickItem>, token: CancellationToken): Promise<number | number[] | undefined> {
|
||||
const contents = new Promise<TransferQuickPickItemOrSeparator[]>((resolve, reject) => {
|
||||
this._items[instance] = { resolve, reject };
|
||||
});
|
||||
|
||||
|
@ -51,7 +51,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
|
|||
...options,
|
||||
onDidFocus: el => {
|
||||
if (el) {
|
||||
this._proxy.$onItemSelected((<TransferQuickPickItems>el).handle);
|
||||
this._proxy.$onItemSelected((<TransferQuickPickItem>el).handle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -73,7 +73,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
|
|||
}
|
||||
}
|
||||
|
||||
$setItems(instance: number, items: TransferQuickPickItems[]): Promise<void> {
|
||||
$setItems(instance: number, items: TransferQuickPickItemOrSeparator[]): Promise<void> {
|
||||
if (this._items[instance]) {
|
||||
this._items[instance].resolve(items);
|
||||
delete this._items[instance];
|
||||
|
@ -140,13 +140,13 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
|
|||
// 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));
|
||||
this._proxy.$onDidChangeActive(sessionId, items.map(item => (item as TransferQuickPickItem).handle));
|
||||
});
|
||||
quickpick.onDidChangeSelection(items => {
|
||||
this._proxy.$onDidChangeSelection(sessionId, items.map(item => (item as TransferQuickPickItems).handle));
|
||||
this._proxy.$onDidChangeSelection(sessionId, items.map(item => (item as TransferQuickPickItem).handle));
|
||||
});
|
||||
quickpick.onDidTriggerItemButton((e) => {
|
||||
this._proxy.$onDidTriggerItemButton(sessionId, (e.item as TransferQuickPickItems).handle, (e.button as TransferQuickInputButton).handle);
|
||||
this._proxy.$onDidTriggerItemButton(sessionId, (e.item as TransferQuickPickItem).handle, (e.button as TransferQuickInputButton).handle);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,11 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
|
|||
}
|
||||
} else if (param === 'items') {
|
||||
handlesToItems.clear();
|
||||
params[param].forEach((item: TransferQuickPickItems) => {
|
||||
params[param].forEach((item: TransferQuickPickItemOrSeparator) => {
|
||||
if (item.type === 'separator') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.buttons) {
|
||||
item.buttons = item.buttons.map((button: TransferQuickInputButton) => {
|
||||
if (button.iconPath) {
|
||||
|
|
|
@ -510,7 +510,8 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
|
|||
$sendProcessExit(terminalId: number, exitCode: number | undefined): void;
|
||||
}
|
||||
|
||||
export interface TransferQuickPickItems extends quickInput.IQuickPickItem {
|
||||
export type TransferQuickPickItemOrSeparator = TransferQuickPickItem | quickInput.IQuickPickSeparator;
|
||||
export interface TransferQuickPickItem extends quickInput.IQuickPickItem {
|
||||
handle: number;
|
||||
buttons?: TransferQuickInputButton[];
|
||||
}
|
||||
|
@ -548,7 +549,7 @@ export interface TransferQuickPick extends BaseTransferQuickInput {
|
|||
|
||||
buttons?: TransferQuickInputButton[];
|
||||
|
||||
items?: TransferQuickPickItems[];
|
||||
items?: TransferQuickPickItemOrSeparator[];
|
||||
|
||||
activeItems?: number[];
|
||||
|
||||
|
@ -593,8 +594,8 @@ export interface IInputBoxOptions {
|
|||
}
|
||||
|
||||
export interface MainThreadQuickOpenShape extends IDisposable {
|
||||
$show(instance: number, options: quickInput.IPickOptions<TransferQuickPickItems>, token: CancellationToken): Promise<number | number[] | undefined>;
|
||||
$setItems(instance: number, items: TransferQuickPickItems[]): Promise<void>;
|
||||
$show(instance: number, options: quickInput.IPickOptions<TransferQuickPickItem>, token: CancellationToken): Promise<number | number[] | undefined>;
|
||||
$setItems(instance: number, items: TransferQuickPickItemOrSeparator[]): Promise<void>;
|
||||
$setError(instance: number, error: Error): Promise<void>;
|
||||
$input(options: IInputBoxOptions | undefined, validateInput: boolean, token: CancellationToken): Promise<string | undefined>;
|
||||
$createOrUpdate(params: TransferQuickInput): Promise<void>;
|
||||
|
|
|
@ -10,7 +10,7 @@ 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, QuickPickItemButtonEvent, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
|
||||
import { ExtHostQuickOpenShape, IMainContext, MainContext, TransferQuickPickItems, TransferQuickInput, TransferQuickInputButton } from './extHost.protocol';
|
||||
import { ExtHostQuickOpenShape, IMainContext, MainContext, TransferQuickInput, TransferQuickInputButton, TransferQuickPickItemOrSeparator } from './extHost.protocol';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ThemeIcon, QuickInputButtons } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
|
@ -59,7 +59,7 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
|
|||
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, enableProposedApi: boolean, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Promise<QuickPickItem[] | undefined>;
|
||||
showQuickPick(itemsOrItemsPromise: string[] | Promise<string[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Promise<string | undefined>;
|
||||
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Promise<QuickPickItem | undefined>;
|
||||
showQuickPick(itemsOrItemsPromise: Item[] | Promise<Item[]>, enableProposedApi: boolean, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Promise<Item | Item[] | undefined> {
|
||||
async showQuickPick(itemsOrItemsPromise: Item[] | Promise<Item[]>, enableProposedApi: boolean, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Promise<Item | Item[] | undefined> {
|
||||
|
||||
// clear state from last invocation
|
||||
this._onDidSelectItem = undefined;
|
||||
|
@ -80,70 +80,81 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
|
|||
const widgetClosedMarker = {};
|
||||
const widgetClosedPromise = quickPickWidget.then(() => widgetClosedMarker);
|
||||
|
||||
return Promise.race([widgetClosedPromise, itemsPromise]).then(result => {
|
||||
if (result === widgetClosedMarker) {
|
||||
return undefined;
|
||||
const result = await Promise.race([widgetClosedPromise, itemsPromise]);
|
||||
if (result === widgetClosedMarker) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const items = await itemsPromise;
|
||||
|
||||
const pickItems: TransferQuickPickItemOrSeparator[] = [];
|
||||
let lastKind: string | { label: string; } | undefined = undefined;
|
||||
for (let handle = 0; handle < items.length; handle++) {
|
||||
const item = items[handle];
|
||||
let label: string;
|
||||
let description: string | undefined;
|
||||
let detail: string | undefined;
|
||||
let picked: boolean | undefined;
|
||||
let alwaysShow: boolean | undefined;
|
||||
|
||||
if (typeof item === 'string') {
|
||||
// 'string' items have a kind of undefined so
|
||||
// if the previous item had a kind, that is considered a
|
||||
// change and would cause the addition of a separator.
|
||||
if (lastKind) {
|
||||
pickItems.push({ type: 'separator' });
|
||||
lastKind = undefined;
|
||||
}
|
||||
label = item;
|
||||
} else {
|
||||
if (lastKind !== item.kind) {
|
||||
const label: string | undefined = typeof item.kind === 'string' ? item.kind : item.kind?.label;
|
||||
pickItems.push({ type: 'separator', label });
|
||||
lastKind = item.kind;
|
||||
}
|
||||
label = item.label;
|
||||
description = item.description;
|
||||
detail = item.detail;
|
||||
picked = item.picked;
|
||||
alwaysShow = item.alwaysShow;
|
||||
}
|
||||
|
||||
return itemsPromise.then(items => {
|
||||
|
||||
const pickItems: TransferQuickPickItems[] = [];
|
||||
for (let handle = 0; handle < items.length; handle++) {
|
||||
|
||||
const item = items[handle];
|
||||
let label: string;
|
||||
let description: string | undefined;
|
||||
let detail: string | undefined;
|
||||
let picked: boolean | undefined;
|
||||
let alwaysShow: boolean | undefined;
|
||||
|
||||
if (typeof item === 'string') {
|
||||
label = item;
|
||||
} else {
|
||||
label = item.label;
|
||||
description = item.description;
|
||||
detail = item.detail;
|
||||
picked = item.picked;
|
||||
alwaysShow = item.alwaysShow;
|
||||
}
|
||||
pickItems.push({
|
||||
label,
|
||||
description,
|
||||
handle,
|
||||
detail,
|
||||
picked,
|
||||
alwaysShow
|
||||
});
|
||||
}
|
||||
|
||||
// handle selection changes
|
||||
if (options && typeof options.onDidSelectItem === 'function') {
|
||||
this._onDidSelectItem = (handle) => {
|
||||
options.onDidSelectItem!(items[handle]);
|
||||
};
|
||||
}
|
||||
|
||||
// show items
|
||||
proxy.$setItems(instance, pickItems);
|
||||
|
||||
return quickPickWidget.then(handle => {
|
||||
if (typeof handle === 'number') {
|
||||
return items[handle];
|
||||
} else if (Array.isArray(handle)) {
|
||||
return handle.map(h => items[h]);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
pickItems.push({
|
||||
label,
|
||||
description,
|
||||
handle,
|
||||
detail,
|
||||
picked,
|
||||
alwaysShow
|
||||
});
|
||||
}).then(undefined, err => {
|
||||
}
|
||||
|
||||
// handle selection changes
|
||||
if (options && typeof options.onDidSelectItem === 'function') {
|
||||
this._onDidSelectItem = (handle) => {
|
||||
options.onDidSelectItem!(items[handle]);
|
||||
};
|
||||
}
|
||||
|
||||
// show items
|
||||
proxy.$setItems(instance, pickItems);
|
||||
|
||||
try {
|
||||
return quickPickWidget.then(handle => {
|
||||
if (typeof handle === 'number') {
|
||||
return items[handle];
|
||||
} else if (Array.isArray(handle)) {
|
||||
return handle.map(h => items[h]);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
} catch (err) {
|
||||
if (isPromiseCanceledError(err)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
proxy.$setError(instance, err);
|
||||
|
||||
return Promise.reject(err);
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
$onItemSelected(handle: number): void {
|
||||
|
@ -553,8 +564,16 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
|
|||
this._handlesToItems.set(i, item);
|
||||
this._itemsToHandles.set(item, i);
|
||||
});
|
||||
this.update({
|
||||
items: items.map((item, i) => ({
|
||||
const itemsItems: Array<TransferQuickPickItemOrSeparator> = [];
|
||||
let lastKind: string | { label: string; } | undefined = undefined;
|
||||
items.forEach((item, i) => {
|
||||
|
||||
if (lastKind !== item.kind) {
|
||||
const label: string | undefined = typeof item.kind === 'string' ? item.kind : item.kind?.label;
|
||||
itemsItems.push({ type: 'separator', label });
|
||||
lastKind = item.kind;
|
||||
}
|
||||
itemsItems.push({
|
||||
label: item.label,
|
||||
description: item.description,
|
||||
handle: i,
|
||||
|
@ -567,8 +586,12 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx
|
|||
tooltip: button.tooltip,
|
||||
handle: i
|
||||
};
|
||||
}),
|
||||
}))
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
this.update({
|
||||
items: itemsItems
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue