提交 be56be09 编写于 作者: B Benjamin Pasero

dialog service - offer new input() method

上级 5352c43a
......@@ -27,7 +27,7 @@ import { CommandsRegistry, ICommandEvent, ICommandHandler, ICommandService } fro
import { IConfigurationChangeEvent, IConfigurationData, IConfigurationOverrides, IConfigurationService, IConfigurationModel, IConfigurationValue, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { Configuration, ConfigurationModel, DefaultConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
import { IContextKeyService, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
import { IConfirmation, IConfirmationResult, IDialogOptions, IDialogService, IShowResult } from 'vs/platform/dialogs/common/dialogs';
import { IConfirmation, IConfirmationResult, IDialogOptions, IDialogService, IInputResult, IShowResult } from 'vs/platform/dialogs/common/dialogs';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { AbstractKeybindingService } from 'vs/platform/keybinding/common/abstractKeybindingService';
import { IKeybindingEvent, IKeyboardEvent, KeybindingSource, KeybindingsSchemaContribution } from 'vs/platform/keybinding/common/keybinding';
......@@ -207,6 +207,10 @@ export class SimpleDialogService implements IDialogService {
return Promise.resolve({ choice: 0 });
}
public input(): Promise<IInputResult> {
return Promise.resolve({ choice: 0 }); // unsupported
}
public about(): Promise<void> {
return Promise.resolve(undefined);
}
......
......@@ -17,6 +17,11 @@ export interface FileFilter {
export type DialogType = 'none' | 'info' | 'error' | 'question' | 'warning';
export interface ICheckbox {
label: string;
checked?: boolean;
}
export interface IConfirmation {
title?: string;
type?: DialogType;
......@@ -24,10 +29,7 @@ export interface IConfirmation {
detail?: string;
primaryButton?: string;
secondaryButton?: string;
checkbox?: {
label: string;
checked?: boolean;
};
checkbox?: ICheckbox;
}
export interface IConfirmationResult {
......@@ -61,6 +63,15 @@ export interface IShowResult {
checkboxChecked?: boolean;
}
export interface IInputResult extends IShowResult {
/**
* Values for the input fields as provided by the user
* or `undefined` if none.
*/
values?: string[];
}
export interface IPickAndOpenOptions {
forceNewWindow?: boolean;
defaultUri?: URI;
......@@ -146,10 +157,13 @@ export const IDialogService = createDecorator<IDialogService>('dialogService');
export interface IDialogOptions {
cancelId?: number;
detail?: string;
checkbox?: {
label: string;
checked?: boolean;
};
checkbox?: ICheckbox;
}
export interface IInput {
placeholder?: string;
type?: 'text' | 'password'
value?: string;
}
/**
......@@ -176,6 +190,16 @@ export interface IDialogService {
*/
show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): Promise<IShowResult>;
/**
* Present a modal dialog to the user asking for input.
*
* @returns A promise with the selected choice index. If the user refused to choose,
* then a promise with index of `cancelId` option is returned. If there is no such
* option then promise with index `0` is returned. In addition, the values for the
* inputs are returned as well.
*/
input(type: DialogType, message: string, buttons: string[], inputs: IInput[], options?: IDialogOptions): Promise<IInputResult>;
/**
* Present the about dialog to the user.
*/
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import Severity from 'vs/base/common/severity';
import { IConfirmation, IConfirmationResult, IDialogService, IDialogOptions, IShowResult } from 'vs/platform/dialogs/common/dialogs';
import { IConfirmation, IConfirmationResult, IDialogService, IDialogOptions, IShowResult, IInputResult } from 'vs/platform/dialogs/common/dialogs';
export class TestDialogService implements IDialogService {
......@@ -12,5 +12,6 @@ export class TestDialogService implements IDialogService {
confirm(_confirmation: IConfirmation): Promise<IConfirmationResult> { return Promise.resolve({ confirmed: false }); }
show(_severity: Severity, _message: string, _buttons: string[], _options?: IDialogOptions): Promise<IShowResult> { return Promise.resolve({ choice: 0 }); }
input(): Promise<IInputResult> { { return Promise.resolve({ choice: 0, values: [] }); } }
about(): Promise<void> { return Promise.resolve(); }
}
......@@ -4,11 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { IDialogService, IDialogOptions, IConfirmation, IConfirmationResult, DialogType, IShowResult } from 'vs/platform/dialogs/common/dialogs';
import { IDialogService, IDialogOptions, IConfirmation, IConfirmationResult, DialogType, IShowResult, IInputResult, ICheckbox, IInput } from 'vs/platform/dialogs/common/dialogs';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import { ILogService } from 'vs/platform/log/common/log';
import Severity from 'vs/base/common/severity';
import { Dialog } from 'vs/base/browser/ui/dialog/dialog';
import { Dialog, IDialogResult } from 'vs/base/browser/ui/dialog/dialog';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachDialogStyler } from 'vs/platform/theme/common/styler';
import { DisposableStore } from 'vs/base/common/lifecycle';
......@@ -24,7 +24,14 @@ export class DialogService implements IDialogService {
declare readonly _serviceBrand: undefined;
private allowableCommands = ['copy', 'cut', 'editor.action.clipboardCopyAction', 'editor.action.clipboardCutAction'];
private static readonly ALLOWABLE_COMMANDS = [
'copy',
'cut',
'editor.action.selectAll',
'editor.action.clipboardCopyAction',
'editor.action.clipboardCutAction',
'editor.action.clipboardPasteAction'
];
constructor(
@ILogService private readonly logService: ILogService,
......@@ -51,32 +58,7 @@ export class DialogService implements IDialogService {
buttons.push(nls.localize('cancelButton', "Cancel"));
}
const dialogDisposables = new DisposableStore();
const dialog = new Dialog(
this.layoutService.container,
confirmation.message,
buttons,
{
detail: confirmation.detail,
cancelId: 1,
type: confirmation.type,
keyEventProcessor: (event: StandardKeyboardEvent) => {
const resolved = this.keybindingService.softDispatch(event, this.layoutService.container);
if (resolved && resolved.commandId) {
if (this.allowableCommands.indexOf(resolved.commandId) === -1) {
EventHelper.stop(event, true);
}
}
},
checkboxChecked: confirmation.checkbox ? confirmation.checkbox.checked : undefined,
checkboxLabel: confirmation.checkbox ? confirmation.checkbox.label : undefined
});
dialogDisposables.add(dialog);
dialogDisposables.add(attachDialogStyler(dialog, this.themeService));
const result = await dialog.show();
dialogDisposables.dispose();
const result = await this.doShow(confirmation.type, confirmation.message, buttons, confirmation.detail, 1, confirmation.checkbox);
return { confirmed: result.button === 0, checkboxChecked: result.checkboxChecked };
}
......@@ -88,25 +70,35 @@ export class DialogService implements IDialogService {
async show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): Promise<IShowResult> {
this.logService.trace('DialogService#show', message);
const result = await this.doShow(this.getDialogType(severity), message, buttons, options?.detail, options?.cancelId, options?.checkbox);
return {
choice: result.button,
checkboxChecked: result.checkboxChecked
};
}
private async doShow(type: 'none' | 'info' | 'error' | 'question' | 'warning' | 'pending' | undefined, message: string, buttons: string[], detail?: string, cancelId?: number, checkbox?: ICheckbox, inputs?: IInput[]): Promise<IDialogResult> {
const dialogDisposables = new DisposableStore();
const dialog = new Dialog(
this.layoutService.container,
message,
buttons,
{
detail: options ? options.detail : undefined,
cancelId: options ? options.cancelId : undefined,
type: this.getDialogType(severity),
detail,
cancelId,
type,
keyEventProcessor: (event: StandardKeyboardEvent) => {
const resolved = this.keybindingService.softDispatch(event, this.layoutService.container);
if (resolved && resolved.commandId) {
if (this.allowableCommands.indexOf(resolved.commandId) === -1) {
if (DialogService.ALLOWABLE_COMMANDS.indexOf(resolved.commandId) === -1) {
EventHelper.stop(event, true);
}
}
},
checkboxLabel: options && options.checkbox ? options.checkbox.label : undefined,
checkboxChecked: options && options.checkbox ? options.checkbox.checked : undefined
checkboxLabel: checkbox?.label,
checkboxChecked: checkbox?.checked,
inputs
});
dialogDisposables.add(dialog);
......@@ -115,9 +107,18 @@ export class DialogService implements IDialogService {
const result = await dialog.show();
dialogDisposables.dispose();
return result;
}
async input(type: DialogType, message: string, buttons: string[], inputs: IInput[], options?: IDialogOptions): Promise<IInputResult> {
this.logService.trace('DialogService#input', message);
const result = await this.doShow(type, message, buttons, options?.detail, options?.cancelId, options?.checkbox, inputs);
return {
choice: result.button,
checkboxChecked: result.checkboxChecked
checkboxChecked: result.checkboxChecked,
values: result.values
};
}
......
......@@ -7,7 +7,7 @@ import * as nls from 'vs/nls';
import Severity from 'vs/base/common/severity';
import { isLinux, isWindows } from 'vs/base/common/platform';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { IDialogService, IConfirmation, IConfirmationResult, IDialogOptions, IShowResult } from 'vs/platform/dialogs/common/dialogs';
import { IDialogService, IConfirmation, IConfirmationResult, IDialogOptions, IShowResult, IInputResult, DialogType, IInput } from 'vs/platform/dialogs/common/dialogs';
import { DialogService as HTMLDialogService } from 'vs/workbench/services/dialogs/browser/dialogService';
import { ILogService } from 'vs/platform/log/common/log';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
......@@ -70,7 +70,7 @@ export class DialogService implements IDialogService {
return this.nativeImpl.confirm(confirmation);
}
show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions | undefined): Promise<IShowResult> {
show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): Promise<IShowResult> {
if (this.useCustomDialog) {
return this.customImpl.show(severity, message, buttons, options);
}
......@@ -78,6 +78,10 @@ export class DialogService implements IDialogService {
return this.nativeImpl.show(severity, message, buttons, options);
}
input(type: DialogType, message: string, buttons: string[], inputs: IInput[], options?: IDialogOptions): Promise<IInputResult> {
return this.customImpl.input(type, message, buttons, inputs, options);
}
about(): Promise<void> {
return this.nativeImpl.about();
}
......@@ -205,6 +209,10 @@ class NativeDialogService implements IDialogService {
return { options, buttonIndexMap };
}
input(): never {
throw new Error('Unsupported'); // we have no native API for password dialogs in Electron
}
async about(): Promise<void> {
let version = this.productService.version;
if (this.productService.target) {
......
......@@ -25,6 +25,10 @@ const emptyDialogService = new class implements IDialogService {
about(): never {
throw new Error('not implemented');
}
input(): never {
throw new Error('not implemented');
}
};
const emptyCommandService: ICommandService = {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册