mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-11 10:38:31 -05:00
Merge VS Code 1.23.1 (#1520)
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import product from 'vs/platform/node/product';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { isLinux, isWindows } from 'vs/base/common/platform';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
||||
import { IDialogService, IConfirmation, IConfirmationResult, IDialogOptions } from 'vs/platform/dialogs/common/dialogs';
|
||||
|
||||
interface IMassagedMessageBoxOptions {
|
||||
|
||||
/**
|
||||
* OS massaged message box options.
|
||||
*/
|
||||
options: Electron.MessageBoxOptions;
|
||||
|
||||
/**
|
||||
* Since the massaged result of the message box options potentially
|
||||
* changes the order of buttons, we have to keep a map of these
|
||||
* changes so that we can still return the correct index to the caller.
|
||||
*/
|
||||
buttonIndexMap: number[];
|
||||
}
|
||||
|
||||
export class DialogService implements IDialogService {
|
||||
|
||||
public _serviceBrand: any;
|
||||
|
||||
constructor(
|
||||
@IWindowService private windowService: IWindowService
|
||||
) {
|
||||
}
|
||||
|
||||
public confirm(confirmation: IConfirmation): TPromise<IConfirmationResult> {
|
||||
const { options, buttonIndexMap } = this.massageMessageBoxOptions(this.getConfirmOptions(confirmation));
|
||||
|
||||
return this.windowService.showMessageBox(options).then(result => {
|
||||
return {
|
||||
confirmed: buttonIndexMap[result.button] === 0 ? true : false,
|
||||
checkboxChecked: result.checkboxChecked
|
||||
} as IConfirmationResult;
|
||||
});
|
||||
}
|
||||
|
||||
private getConfirmOptions(confirmation: IConfirmation): Electron.MessageBoxOptions {
|
||||
const buttons: string[] = [];
|
||||
if (confirmation.primaryButton) {
|
||||
buttons.push(confirmation.primaryButton);
|
||||
} else {
|
||||
buttons.push(nls.localize({ key: 'yesButton', comment: ['&& denotes a mnemonic'] }, "&&Yes"));
|
||||
}
|
||||
|
||||
if (confirmation.secondaryButton) {
|
||||
buttons.push(confirmation.secondaryButton);
|
||||
} else if (typeof confirmation.secondaryButton === 'undefined') {
|
||||
buttons.push(nls.localize('cancelButton', "Cancel"));
|
||||
}
|
||||
|
||||
const opts: Electron.MessageBoxOptions = {
|
||||
title: confirmation.title,
|
||||
message: confirmation.message,
|
||||
buttons,
|
||||
cancelId: 1
|
||||
};
|
||||
|
||||
if (confirmation.detail) {
|
||||
opts.detail = confirmation.detail;
|
||||
}
|
||||
|
||||
if (confirmation.type) {
|
||||
opts.type = confirmation.type;
|
||||
}
|
||||
|
||||
if (confirmation.checkbox) {
|
||||
opts.checkboxLabel = confirmation.checkbox.label;
|
||||
opts.checkboxChecked = confirmation.checkbox.checked;
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
public show(severity: Severity, message: string, buttons: string[], dialogOptions?: IDialogOptions): TPromise<number> {
|
||||
const { options, buttonIndexMap } = this.massageMessageBoxOptions({
|
||||
message,
|
||||
buttons,
|
||||
type: (severity === Severity.Info) ? 'question' : (severity === Severity.Error) ? 'error' : (severity === Severity.Warning) ? 'warning' : 'none',
|
||||
cancelId: dialogOptions ? dialogOptions.cancelId : void 0,
|
||||
detail: dialogOptions ? dialogOptions.detail : void 0
|
||||
});
|
||||
|
||||
return this.windowService.showMessageBox(options).then(result => buttonIndexMap[result.button]);
|
||||
}
|
||||
|
||||
private massageMessageBoxOptions(options: Electron.MessageBoxOptions): IMassagedMessageBoxOptions {
|
||||
let buttonIndexMap = options.buttons.map((button, index) => index);
|
||||
let buttons = options.buttons.map(button => mnemonicButtonLabel(button));
|
||||
let cancelId = options.cancelId;
|
||||
|
||||
// Linux: order of buttons is reverse
|
||||
// macOS: also reverse, but the OS handles this for us!
|
||||
if (isLinux) {
|
||||
buttons = buttons.reverse();
|
||||
buttonIndexMap = buttonIndexMap.reverse();
|
||||
}
|
||||
|
||||
// Default Button (always first one)
|
||||
options.defaultId = buttonIndexMap[0];
|
||||
|
||||
// Cancel Button
|
||||
if (typeof cancelId === 'number') {
|
||||
|
||||
// Ensure the cancelId is the correct one from our mapping
|
||||
cancelId = buttonIndexMap[cancelId];
|
||||
|
||||
// macOS/Linux: the cancel button should always be to the left of the primary action
|
||||
// if we see more than 2 buttons, move the cancel one to the left of the primary
|
||||
if (!isWindows && buttons.length > 2 && cancelId !== 1) {
|
||||
const cancelButton = buttons[cancelId];
|
||||
buttons.splice(cancelId, 1);
|
||||
buttons.splice(1, 0, cancelButton);
|
||||
|
||||
const cancelButtonIndex = buttonIndexMap[cancelId];
|
||||
buttonIndexMap.splice(cancelId, 1);
|
||||
buttonIndexMap.splice(1, 0, cancelButtonIndex);
|
||||
|
||||
cancelId = 1;
|
||||
}
|
||||
}
|
||||
|
||||
options.buttons = buttons;
|
||||
options.cancelId = cancelId;
|
||||
options.noLink = true;
|
||||
options.title = options.title || product.nameLong;
|
||||
|
||||
return { options, buttonIndexMap };
|
||||
}
|
||||
}
|
||||
@@ -1,241 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import nls = require('vs/nls');
|
||||
import product from 'vs/platform/node/product';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
||||
import { IConfirmationService, IChoiceService, IConfirmation, IConfirmationResult, Choice } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { INotificationService, INotificationHandle, INotificationActions } from 'vs/platform/notification/common/notification';
|
||||
import { once } from 'vs/base/common/event';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { basename } from 'vs/base/common/paths';
|
||||
|
||||
interface IMassagedMessageBoxOptions {
|
||||
|
||||
/**
|
||||
* OS massaged message box options.
|
||||
*/
|
||||
options: Electron.MessageBoxOptions;
|
||||
|
||||
/**
|
||||
* Since the massaged result of the message box options potentially
|
||||
* changes the order of buttons, we have to keep a map of these
|
||||
* changes so that we can still return the correct index to the caller.
|
||||
*/
|
||||
buttonIndexMap: number[];
|
||||
}
|
||||
|
||||
export class DialogService implements IChoiceService, IConfirmationService {
|
||||
|
||||
public _serviceBrand: any;
|
||||
|
||||
constructor(
|
||||
@IWindowService private windowService: IWindowService,
|
||||
@INotificationService private notificationService: INotificationService
|
||||
) {
|
||||
}
|
||||
|
||||
public confirmWithCheckbox(confirmation: IConfirmation): TPromise<IConfirmationResult> {
|
||||
const { options, buttonIndexMap } = this.massageMessageBoxOptions(this.getConfirmOptions(confirmation));
|
||||
|
||||
return this.windowService.showMessageBox(options).then(result => {
|
||||
return {
|
||||
confirmed: buttonIndexMap[result.button] === 0 ? true : false,
|
||||
checkboxChecked: result.checkboxChecked
|
||||
} as IConfirmationResult;
|
||||
});
|
||||
}
|
||||
|
||||
public confirm(confirmation: IConfirmation): TPromise<boolean> {
|
||||
const { options, buttonIndexMap } = this.massageMessageBoxOptions(this.getConfirmOptions(confirmation));
|
||||
|
||||
return this.windowService.showMessageBox(options).then(result => buttonIndexMap[result.button] === 0 ? true : false);
|
||||
}
|
||||
|
||||
private getConfirmOptions(confirmation: IConfirmation): Electron.MessageBoxOptions {
|
||||
const buttons: string[] = [];
|
||||
if (confirmation.primaryButton) {
|
||||
buttons.push(confirmation.primaryButton);
|
||||
} else {
|
||||
buttons.push(nls.localize({ key: 'yesButton', comment: ['&& denotes a mnemonic'] }, "&&Yes"));
|
||||
}
|
||||
|
||||
if (confirmation.secondaryButton) {
|
||||
buttons.push(confirmation.secondaryButton);
|
||||
} else if (typeof confirmation.secondaryButton === 'undefined') {
|
||||
buttons.push(nls.localize('cancelButton', "Cancel"));
|
||||
}
|
||||
|
||||
const opts: Electron.MessageBoxOptions = {
|
||||
title: confirmation.title,
|
||||
message: confirmation.message,
|
||||
buttons,
|
||||
defaultId: 0,
|
||||
cancelId: 1
|
||||
};
|
||||
|
||||
if (confirmation.detail) {
|
||||
opts.detail = confirmation.detail;
|
||||
}
|
||||
|
||||
if (confirmation.type) {
|
||||
opts.type = confirmation.type;
|
||||
}
|
||||
|
||||
if (confirmation.checkbox) {
|
||||
opts.checkboxLabel = confirmation.checkbox.label;
|
||||
opts.checkboxChecked = confirmation.checkbox.checked;
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
public choose(severity: Severity, message: string, choices: Choice[], cancelId?: number, modal: boolean = false): TPromise<number> {
|
||||
if (modal) {
|
||||
return this.doChooseWithDialog(severity, message, choices, cancelId);
|
||||
}
|
||||
|
||||
return this.doChooseWithNotification(severity, message, choices);
|
||||
}
|
||||
|
||||
private doChooseWithDialog(severity: Severity, message: string, choices: Choice[], cancelId?: number): TPromise<number> {
|
||||
const type: 'none' | 'info' | 'error' | 'question' | 'warning' = severity === Severity.Info ? 'question' : severity === Severity.Error ? 'error' : severity === Severity.Warning ? 'warning' : 'none';
|
||||
|
||||
const stringChoices: string[] = [];
|
||||
choices.forEach(choice => {
|
||||
if (typeof choice === 'string') {
|
||||
stringChoices.push(choice);
|
||||
} else {
|
||||
stringChoices.push(choice.label);
|
||||
}
|
||||
});
|
||||
|
||||
const { options, buttonIndexMap } = this.massageMessageBoxOptions({ message, buttons: stringChoices, type, cancelId });
|
||||
|
||||
return this.windowService.showMessageBox(options).then(result => buttonIndexMap[result.button]);
|
||||
}
|
||||
|
||||
private doChooseWithNotification(severity: Severity, message: string, choices: Choice[]): TPromise<number> {
|
||||
let handle: INotificationHandle;
|
||||
|
||||
const promise = new TPromise<number>((c, e) => {
|
||||
|
||||
// Complete promise with index of action that was picked
|
||||
const callback = (index: number, closeNotification: boolean) => () => {
|
||||
c(index);
|
||||
|
||||
if (closeNotification) {
|
||||
handle.close();
|
||||
}
|
||||
|
||||
return TPromise.as(void 0);
|
||||
};
|
||||
|
||||
// Convert choices into primary/secondary actions
|
||||
const actions: INotificationActions = {
|
||||
primary: [],
|
||||
secondary: []
|
||||
};
|
||||
|
||||
choices.forEach((choice, index) => {
|
||||
let isPrimary = true;
|
||||
let label: string;
|
||||
let closeNotification = false;
|
||||
|
||||
if (typeof choice === 'string') {
|
||||
label = choice;
|
||||
} else {
|
||||
isPrimary = false;
|
||||
label = choice.label;
|
||||
closeNotification = !choice.keepOpen;
|
||||
}
|
||||
|
||||
const action = new Action(`workbench.dialog.choice.${index}`, label, null, true, callback(index, closeNotification));
|
||||
if (isPrimary) {
|
||||
actions.primary.push(action);
|
||||
} else {
|
||||
actions.secondary.push(action);
|
||||
}
|
||||
});
|
||||
|
||||
// Show notification with actions
|
||||
handle = this.notificationService.notify({ severity, message, actions });
|
||||
|
||||
// Cancel promise when notification gets disposed
|
||||
once(handle.onDidClose)(() => promise.cancel());
|
||||
|
||||
}, () => handle.close());
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
private massageMessageBoxOptions(options: Electron.MessageBoxOptions): IMassagedMessageBoxOptions {
|
||||
let buttonIndexMap = options.buttons.map((button, index) => index);
|
||||
|
||||
options.buttons = options.buttons.map(button => mnemonicButtonLabel(button));
|
||||
|
||||
// Linux: order of buttons is reverse
|
||||
// macOS: also reverse, but the OS handles this for us!
|
||||
if (isLinux) {
|
||||
options.buttons = options.buttons.reverse();
|
||||
buttonIndexMap = buttonIndexMap.reverse();
|
||||
}
|
||||
|
||||
// Default Button
|
||||
if (options.defaultId !== void 0) {
|
||||
options.defaultId = buttonIndexMap[options.defaultId];
|
||||
} else if (isLinux) {
|
||||
options.defaultId = buttonIndexMap[0];
|
||||
}
|
||||
|
||||
// Cancel Button
|
||||
if (options.cancelId !== void 0) {
|
||||
|
||||
// macOS: the cancel button should always be to the left of the primary action
|
||||
// if we see more than 2 buttons, move the cancel one to the left of the primary
|
||||
if (isMacintosh && options.buttons.length > 2 && options.cancelId !== 1) {
|
||||
const cancelButton = options.buttons[options.cancelId];
|
||||
options.buttons.splice(options.cancelId, 1);
|
||||
options.buttons.splice(1, 0, cancelButton);
|
||||
|
||||
const cancelButtonIndex = buttonIndexMap[options.cancelId];
|
||||
buttonIndexMap.splice(cancelButtonIndex, 1);
|
||||
buttonIndexMap.splice(1, 0, cancelButtonIndex);
|
||||
}
|
||||
|
||||
options.cancelId = buttonIndexMap[options.cancelId];
|
||||
}
|
||||
|
||||
options.noLink = true;
|
||||
options.title = options.title || product.nameLong;
|
||||
|
||||
return { options, buttonIndexMap };
|
||||
}
|
||||
}
|
||||
|
||||
const MAX_CONFIRM_FILES = 10;
|
||||
export function getConfirmMessage(start: string, resourcesToConfirm: URI[]): string {
|
||||
const message = [start];
|
||||
message.push('');
|
||||
message.push(...resourcesToConfirm.slice(0, MAX_CONFIRM_FILES).map(r => basename(r.fsPath)));
|
||||
|
||||
if (resourcesToConfirm.length > MAX_CONFIRM_FILES) {
|
||||
if (resourcesToConfirm.length - MAX_CONFIRM_FILES === 1) {
|
||||
message.push(nls.localize('moreFile', "...1 additional file not shown"));
|
||||
} else {
|
||||
message.push(nls.localize('moreFiles', "...{0} additional files not shown", resourcesToConfirm.length - MAX_CONFIRM_FILES));
|
||||
}
|
||||
}
|
||||
|
||||
message.push('');
|
||||
return message.join('\n');
|
||||
}
|
||||
Reference in New Issue
Block a user