mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-17 17:22:42 -05:00
Enable basic wizard API (#1450)
This commit is contained in:
@@ -50,8 +50,7 @@ export class ModelViewEditor extends BaseEditor {
|
||||
|
||||
if (!this._modelViewMap.get(input.modelViewId)) {
|
||||
let modelViewContainer = DOM.$('div.model-view-container');
|
||||
let dialog = new Dialog(input.title, input.modelViewId);
|
||||
let dialogPane = new DialogPane(dialog, this._bootstrapService);
|
||||
let dialogPane = new DialogPane(input.title, input.modelViewId, () => undefined, this._bootstrapService);
|
||||
dialogPane.createBody(modelViewContainer);
|
||||
this._modelViewMap.set(input.modelViewId, modelViewContainer);
|
||||
}
|
||||
|
||||
@@ -8,14 +8,17 @@
|
||||
import * as sqlops from 'sqlops';
|
||||
import { OptionsDialog } from 'sql/base/browser/ui/modal/optionsDialog';
|
||||
import { DialogModal } from 'sql/platform/dialog/dialogModal';
|
||||
import { Dialog } from 'sql/platform/dialog/dialogTypes';
|
||||
import { WizardModal } from 'sql/platform/dialog/wizardModal';
|
||||
import { Dialog, Wizard, DialogTab } from 'sql/platform/dialog/dialogTypes';
|
||||
import { IModalOptions } from 'sql/base/browser/ui/modal/modal';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
const defaultOptions: IModalOptions = { hasBackButton: true, isWide: false };
|
||||
const defaultOptions: IModalOptions = { hasBackButton: false, isWide: false };
|
||||
const defaultWizardOptions: IModalOptions = { hasBackButton: false, isWide: true };
|
||||
|
||||
export class CustomDialogService {
|
||||
private _dialogModals = new Map<Dialog, DialogModal>();
|
||||
private _wizardModals = new Map<Wizard, WizardModal>();
|
||||
|
||||
constructor( @IInstantiationService private _instantiationService: IInstantiationService) { }
|
||||
|
||||
@@ -26,10 +29,24 @@ export class CustomDialogService {
|
||||
dialogModal.open();
|
||||
}
|
||||
|
||||
public showWizard(wizard: Wizard, options?: IModalOptions): void {
|
||||
let wizardModal = this._instantiationService.createInstance(WizardModal, wizard, 'WizardPage', options || defaultWizardOptions);
|
||||
this._wizardModals.set(wizard, wizardModal);
|
||||
wizardModal.render();
|
||||
wizardModal.open();
|
||||
}
|
||||
|
||||
public closeDialog(dialog: Dialog): void {
|
||||
let dialogModal = this._dialogModals.get(dialog);
|
||||
if (dialogModal) {
|
||||
dialogModal.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public closeWizard(wizard: Wizard): void {
|
||||
let wizardModal = this._wizardModals.get(wizard);
|
||||
if (wizardModal) {
|
||||
wizardModal.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,8 @@ export class DialogModal extends Modal {
|
||||
body = bodyBuilder.getHTMLElement();
|
||||
});
|
||||
|
||||
this._dialogPane = new DialogPane(this._dialog, this._bootstrapService);
|
||||
this._dialogPane = new DialogPane(this._dialog.title, this._dialog.content,
|
||||
valid => this._dialog.notifyValidityChanged(valid), this._bootstrapService);
|
||||
this._dialogPane.createBody(body);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import 'vs/css!./media/dialogModal';
|
||||
import { NgModuleRef } from '@angular/core';
|
||||
import { IModalDialogStyles } from 'sql/base/browser/ui/modal/modal';
|
||||
import { Dialog } from 'sql/platform/dialog/dialogTypes';
|
||||
import { Dialog, DialogTab } from 'sql/platform/dialog/dialogTypes';
|
||||
import { TabbedPanel, IPanelTab, IPanelView } from 'sql/base/browser/ui/panel/panel';
|
||||
import { IBootstrapService } from 'sql/services/bootstrap/bootstrapService';
|
||||
import { DialogModule } from 'sql/platform/dialog/dialog.module';
|
||||
@@ -32,7 +32,9 @@ export class DialogPane extends Disposable implements IThemable {
|
||||
private _tabContent: HTMLElement[];
|
||||
|
||||
constructor(
|
||||
private _dialog: Dialog,
|
||||
private _title: string,
|
||||
private _content: string | DialogTab[],
|
||||
private _validityChangedCallback: (valid: boolean) => void,
|
||||
private _bootstrapService: IBootstrapService
|
||||
) {
|
||||
super();
|
||||
@@ -43,19 +45,19 @@ export class DialogPane extends Disposable implements IThemable {
|
||||
public createBody(container: HTMLElement): HTMLElement {
|
||||
new Builder(container).div({ class: 'dialogModal-pane' }, (bodyBuilder) => {
|
||||
this._body = bodyBuilder.getHTMLElement();
|
||||
if (typeof this._dialog.content === 'string' || this._dialog.content.length < 2) {
|
||||
let modelViewId = typeof this._dialog.content === 'string' ? this._dialog.content : this._dialog.content[0].content;
|
||||
if (typeof this._content === 'string' || this._content.length < 2) {
|
||||
let modelViewId = typeof this._content === 'string' ? this._content : this._content[0].content;
|
||||
this.initializeModelViewContainer(this._body, modelViewId);
|
||||
} else {
|
||||
this._tabbedPanel = new TabbedPanel(this._body);
|
||||
this._dialog.content.forEach((tab, tabIndex) => {
|
||||
this._content.forEach((tab, tabIndex) => {
|
||||
let tabContainer = document.createElement('div');
|
||||
tabContainer.style.display = 'none';
|
||||
this._body.appendChild(tabContainer);
|
||||
this.initializeModelViewContainer(tabContainer, tab.content);
|
||||
this.initializeModelViewContainer(tabContainer, tab.content, tab);
|
||||
this._tabbedPanel.pushTab({
|
||||
title: tab.title,
|
||||
identifier: 'dialogPane.' + this._dialog.title + '.' + tabIndex,
|
||||
identifier: 'dialogPane.' + this._title + '.' + tabIndex,
|
||||
view: {
|
||||
render: (container) => {
|
||||
if (tabContainer.parentElement === this._body) {
|
||||
@@ -77,14 +79,19 @@ export class DialogPane extends Disposable implements IThemable {
|
||||
/**
|
||||
* Bootstrap angular for the dialog's model view controller with the given model view ID
|
||||
*/
|
||||
private initializeModelViewContainer(bodyContainer: HTMLElement, modelViewId: string) {
|
||||
private initializeModelViewContainer(bodyContainer: HTMLElement, modelViewId: string, tab?: DialogTab) {
|
||||
this._bootstrapService.bootstrap(
|
||||
DialogModule,
|
||||
bodyContainer,
|
||||
'dialog-modelview-container',
|
||||
{
|
||||
modelViewId: modelViewId,
|
||||
validityChangedCallback: (valid: boolean) => this._setValidity(modelViewId, valid)
|
||||
validityChangedCallback: (valid: boolean) => {
|
||||
this._setValidity(modelViewId, valid);
|
||||
if (tab) {
|
||||
tab.notifyValidityChanged(valid);
|
||||
}
|
||||
}
|
||||
} as DialogComponentParams,
|
||||
undefined,
|
||||
(moduleRef) => this._moduleRefs.push(moduleRef));
|
||||
@@ -111,7 +118,7 @@ export class DialogPane extends Disposable implements IThemable {
|
||||
this._modelViewValidityMap.set(modelViewId, valid);
|
||||
let newValidity = this.isValid();
|
||||
if (newValidity !== oldValidity) {
|
||||
this._dialog.notifyValidityChanged(newValidity);
|
||||
this._validityChangedCallback(newValidity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +130,7 @@ export class DialogPane extends Disposable implements IThemable {
|
||||
|
||||
public dispose() {
|
||||
super.dispose();
|
||||
this._body.remove();
|
||||
this._moduleRefs.forEach(moduleRef => moduleRef.destroy());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,17 +9,35 @@ import * as sqlops from 'sqlops';
|
||||
import { localize } from 'vs/nls';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
|
||||
export class DialogTab {
|
||||
export class ModelViewPane {
|
||||
private _valid: boolean = true;
|
||||
private _validityChangedEmitter = new Emitter<boolean>();
|
||||
public readonly onValidityChanged = this._validityChangedEmitter.event;
|
||||
|
||||
public get valid(): boolean {
|
||||
return this._valid;
|
||||
}
|
||||
|
||||
public notifyValidityChanged(valid: boolean) {
|
||||
if (this._valid !== valid) {
|
||||
this._valid = valid;
|
||||
this._validityChangedEmitter.fire(this._valid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class DialogTab extends ModelViewPane {
|
||||
public content: string;
|
||||
|
||||
constructor(public title: string, content?: string) {
|
||||
super();
|
||||
if (content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Dialog {
|
||||
export class Dialog extends ModelViewPane {
|
||||
private static readonly DONE_BUTTON_LABEL = localize('dialogModalDoneButtonLabel', 'Done');
|
||||
private static readonly CANCEL_BUTTON_LABEL = localize('dialogModalCancelButtonLabel', 'Cancel');
|
||||
|
||||
@@ -28,24 +46,12 @@ export class Dialog {
|
||||
public cancelButton: DialogButton = new DialogButton(Dialog.CANCEL_BUTTON_LABEL, true);
|
||||
public customButtons: DialogButton[];
|
||||
|
||||
private _valid: boolean = true;
|
||||
private _validityChangedEmitter = new Emitter<boolean>();
|
||||
public readonly onValidityChanged = this._validityChangedEmitter.event;
|
||||
|
||||
constructor(public title: string, content?: string | DialogTab[]) {
|
||||
super();
|
||||
if (content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
|
||||
public get valid(): boolean {
|
||||
return this._valid;
|
||||
}
|
||||
|
||||
public notifyValidityChanged(valid: boolean) {
|
||||
this._valid = valid;
|
||||
this._validityChangedEmitter.fire(valid);
|
||||
}
|
||||
}
|
||||
|
||||
export class DialogButton implements sqlops.window.modelviewdialog.Button {
|
||||
@@ -96,4 +102,93 @@ export class DialogButton implements sqlops.window.modelviewdialog.Button {
|
||||
public registerClickEvent(clickEvent: Event<void>): void {
|
||||
clickEvent(() => this._onClick.fire());
|
||||
}
|
||||
}
|
||||
|
||||
export class WizardPage extends DialogTab {
|
||||
public customButtons: DialogButton[];
|
||||
private _enabled: boolean;
|
||||
private _onUpdate: Emitter<void> = new Emitter<void>();
|
||||
public readonly onUpdate: Event<void> = this._onUpdate.event;
|
||||
|
||||
constructor(public title: string, content?: string) {
|
||||
super(title, content);
|
||||
}
|
||||
|
||||
public get enabled(): boolean {
|
||||
return this._enabled;
|
||||
}
|
||||
|
||||
public set enabled(enabled: boolean) {
|
||||
this._enabled = enabled;
|
||||
this._onUpdate.fire();
|
||||
}
|
||||
}
|
||||
|
||||
export class Wizard {
|
||||
public pages: WizardPage[];
|
||||
public nextButton: DialogButton;
|
||||
public backButton: DialogButton;
|
||||
public generateScriptButton: DialogButton;
|
||||
public doneButton: DialogButton;
|
||||
public cancelButton: DialogButton;
|
||||
public customButtons: DialogButton[];
|
||||
private _currentPage: number;
|
||||
private _pageChangedEmitter = new Emitter<sqlops.window.modelviewdialog.WizardPageChangeInfo>();
|
||||
public readonly onPageChanged = this._pageChangedEmitter.event;
|
||||
private _pageAddedEmitter = new Emitter<WizardPage>();
|
||||
public readonly onPageAdded = this._pageAddedEmitter.event;
|
||||
private _pageRemovedEmitter = new Emitter<WizardPage>();
|
||||
public readonly onPageRemoved = this._pageRemovedEmitter.event;
|
||||
|
||||
constructor(public title: string) { }
|
||||
|
||||
public get currentPage(): number {
|
||||
return this._currentPage;
|
||||
}
|
||||
|
||||
public setCurrentPage(index: number): void {
|
||||
if (index === undefined || index < 0 || index >= this.pages.length) {
|
||||
throw new Error('Index is out of bounds');
|
||||
}
|
||||
let lastPage = this._currentPage;
|
||||
this._currentPage = index;
|
||||
if (lastPage !== undefined && this._currentPage !== undefined && lastPage !== this._currentPage) {
|
||||
this._pageChangedEmitter.fire({
|
||||
lastPage: lastPage,
|
||||
newPage: this._currentPage
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public addPage(page: WizardPage, index?: number): void {
|
||||
if (index !== undefined && (index < 0 || index > this.pages.length)) {
|
||||
throw new Error('Index is out of bounds');
|
||||
}
|
||||
if (index !== undefined && this.currentPage !== undefined && index <= this.currentPage) {
|
||||
++this._currentPage;
|
||||
}
|
||||
if (index === undefined) {
|
||||
this.pages.push(page);
|
||||
} else {
|
||||
this.pages = this.pages.slice(0, index).concat([page], this.pages.slice(index));
|
||||
}
|
||||
this._pageAddedEmitter.fire(page);
|
||||
}
|
||||
|
||||
public removePage(index: number): void {
|
||||
if (index === undefined || index < 0 || index >= this.pages.length) {
|
||||
throw new Error('Index is out of bounds');
|
||||
}
|
||||
if (index === this.currentPage) {
|
||||
// Switch to the new page before deleting the current page
|
||||
let newPage = this._currentPage > 0 ? this._currentPage - 1 : this._currentPage + 1;
|
||||
this.setCurrentPage(newPage);
|
||||
}
|
||||
if (this.currentPage !== undefined && index < this.currentPage) {
|
||||
--this._currentPage;
|
||||
}
|
||||
let removedPage = this.pages[index];
|
||||
this.pages.splice(index, 1);
|
||||
this._pageRemovedEmitter.fire(removedPage);
|
||||
}
|
||||
}
|
||||
@@ -26,3 +26,7 @@
|
||||
.dialogModal-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.footer-button.dialogModal-hidden {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
209
src/sql/platform/dialog/wizardModal.ts
Normal file
209
src/sql/platform/dialog/wizardModal.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'vs/css!./media/dialogModal';
|
||||
import { Modal, IModalOptions } from 'sql/base/browser/ui/modal/modal';
|
||||
import { attachModalDialogStyler } from 'sql/common/theme/styler';
|
||||
import { Wizard, Dialog, DialogButton, WizardPage } from 'sql/platform/dialog/dialogTypes';
|
||||
import { DialogPane } from 'sql/platform/dialog/dialogPane';
|
||||
import { IBootstrapService } from 'sql/services/bootstrap/bootstrapService';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { Builder } from 'vs/base/browser/builder';
|
||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { attachButtonStyler } from 'vs/platform/theme/common/styler';
|
||||
import { localize } from 'vs/nls';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
export class WizardModal extends Modal {
|
||||
private _dialogPanes = new Map<WizardPage, DialogPane>();
|
||||
private _onDone = new Emitter<void>();
|
||||
private _onCancel = new Emitter<void>();
|
||||
|
||||
// Wizard HTML elements
|
||||
private _body: HTMLElement;
|
||||
|
||||
// Buttons
|
||||
private _previousButton: Button;
|
||||
private _nextButton: Button;
|
||||
private _generateScriptButton: Button;
|
||||
private _doneButton: Button;
|
||||
private _cancelButton: Button;
|
||||
|
||||
constructor(
|
||||
private _wizard: Wizard,
|
||||
name: string,
|
||||
options: IModalOptions,
|
||||
@IPartService partService: IPartService,
|
||||
@IWorkbenchThemeService private _themeService: IWorkbenchThemeService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IBootstrapService private _bootstrapService: IBootstrapService
|
||||
) {
|
||||
super(_wizard.title, name, partService, telemetryService, contextKeyService, options);
|
||||
}
|
||||
|
||||
public layout(): void {
|
||||
|
||||
}
|
||||
|
||||
public render() {
|
||||
super.render();
|
||||
attachModalDialogStyler(this, this._themeService);
|
||||
|
||||
if (this.backButton) {
|
||||
this.backButton.onDidClick(() => this.cancel());
|
||||
attachButtonStyler(this.backButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND });
|
||||
}
|
||||
|
||||
this._previousButton = this.addDialogButton(this._wizard.backButton, () => this.showPage(this.getCurrentPage() - 1));
|
||||
this._nextButton = this.addDialogButton(this._wizard.nextButton, () => this.showPage(this.getCurrentPage() + 1));
|
||||
this._generateScriptButton = this.addDialogButton(this._wizard.generateScriptButton, () => undefined);
|
||||
this._doneButton = this.addDialogButton(this._wizard.doneButton, () => this.done(), false);
|
||||
this._wizard.doneButton.registerClickEvent(this._onDone.event);
|
||||
this._cancelButton = this.addDialogButton(this._wizard.cancelButton, () => this.cancel(), false);
|
||||
this._wizard.cancelButton.registerClickEvent(this._onCancel.event);
|
||||
}
|
||||
|
||||
private addDialogButton(button: DialogButton, onSelect: () => void = () => undefined, registerClickEvent: boolean = true): Button {
|
||||
let buttonElement = this.addFooterButton(button.label, onSelect);
|
||||
buttonElement.enabled = button.enabled;
|
||||
if (registerClickEvent) {
|
||||
button.registerClickEvent(buttonElement.onDidClick);
|
||||
}
|
||||
button.onUpdate(() => {
|
||||
this.updateButtonElement(buttonElement, button);
|
||||
});
|
||||
attachButtonStyler(buttonElement, this._themeService);
|
||||
this.updateButtonElement(buttonElement, button);
|
||||
return buttonElement;
|
||||
}
|
||||
|
||||
private updateButtonElement(buttonElement: Button, dialogButton: DialogButton) {
|
||||
buttonElement.label = dialogButton.label;
|
||||
buttonElement.enabled = dialogButton.enabled;
|
||||
dialogButton.hidden ? buttonElement.element.classList.add('dialogModal-hidden') : buttonElement.element.classList.remove('dialogModal-hidden');
|
||||
}
|
||||
|
||||
protected renderBody(container: HTMLElement): void {
|
||||
new Builder(container).div({ class: 'dialogModal-body' }, (bodyBuilder) => {
|
||||
this._body = bodyBuilder.getHTMLElement();
|
||||
});
|
||||
|
||||
let builder = new Builder(this._body);
|
||||
this._wizard.pages.forEach(page => {
|
||||
this.registerPage(page);
|
||||
});
|
||||
this._wizard.onPageAdded(page => {
|
||||
this.registerPage(page);
|
||||
this.showPage(this.getCurrentPage());
|
||||
});
|
||||
this._wizard.onPageRemoved(page => {
|
||||
let dialogPane = this._dialogPanes.get(page);
|
||||
this._dialogPanes.delete(page);
|
||||
this.showPage(this.getCurrentPage());
|
||||
dialogPane.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
private registerPage(page: WizardPage): void {
|
||||
let dialogPane = new DialogPane(page.title, page.content, valid => page.notifyValidityChanged(valid), this._bootstrapService);
|
||||
dialogPane.createBody(this._body);
|
||||
this._dialogPanes.set(page, dialogPane);
|
||||
page.onUpdate(() => this.setButtonsForPage(this._wizard.currentPage));
|
||||
}
|
||||
|
||||
private showPage(index: number): void {
|
||||
let pageToShow = this._wizard.pages[index];
|
||||
if (!pageToShow) {
|
||||
this.done();
|
||||
return;
|
||||
}
|
||||
this._dialogPanes.forEach((dialogPane, page) => {
|
||||
if (page === pageToShow) {
|
||||
dialogPane.show();
|
||||
} else {
|
||||
dialogPane.hide();
|
||||
}
|
||||
});
|
||||
this.setButtonsForPage(index);
|
||||
this._wizard.setCurrentPage(index);
|
||||
}
|
||||
|
||||
private setButtonsForPage(index: number) {
|
||||
if (this._wizard.pages[index - 1]) {
|
||||
this._previousButton.element.parentElement.classList.remove('dialogModal-hidden');
|
||||
this._previousButton.enabled = this._wizard.pages[index - 1].enabled;
|
||||
} else {
|
||||
this._previousButton.element.parentElement.classList.add('dialogModal-hidden');
|
||||
}
|
||||
|
||||
if (this._wizard.pages[index + 1]) {
|
||||
this._nextButton.element.parentElement.classList.remove('dialogModal-hidden');
|
||||
this._nextButton.enabled = this._wizard.pages[index + 1].enabled;
|
||||
this._doneButton.element.parentElement.classList.add('dialogModal-hidden');
|
||||
} else {
|
||||
this._nextButton.element.parentElement.classList.add('dialogModal-hidden');
|
||||
this._doneButton.element.parentElement.classList.remove('dialogModal-hidden');
|
||||
}
|
||||
}
|
||||
|
||||
private getCurrentPage(): number {
|
||||
return this._wizard.currentPage;
|
||||
}
|
||||
|
||||
public open(): void {
|
||||
this.showPage(0);
|
||||
this.show();
|
||||
}
|
||||
|
||||
public done(): void {
|
||||
if (this._wizard.doneButton.enabled) {
|
||||
this._onDone.fire();
|
||||
this.dispose();
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
public cancel(): void {
|
||||
this._onCancel.fire();
|
||||
this.dispose();
|
||||
this.hide();
|
||||
}
|
||||
|
||||
protected hide(): void {
|
||||
super.hide();
|
||||
}
|
||||
|
||||
protected show(): void {
|
||||
super.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridable to change behavior of escape key
|
||||
*/
|
||||
protected onClose(e: StandardKeyboardEvent) {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridable to change behavior of enter key
|
||||
*/
|
||||
protected onAccept(e: StandardKeyboardEvent) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
super.dispose();
|
||||
this._dialogPanes.forEach(dialogPane => dialogPane.dispose());
|
||||
}
|
||||
}
|
||||
154
src/sql/sqlops.proposed.d.ts
vendored
154
src/sql/sqlops.proposed.d.ts
vendored
@@ -396,6 +396,18 @@ declare module 'sqlops' {
|
||||
*/
|
||||
export function closeDialog(dialog: Dialog): void;
|
||||
|
||||
/**
|
||||
* Create a wizard page with the given title, for inclusion in a wizard
|
||||
* @param title The title of the page
|
||||
*/
|
||||
export function createWizardPage(title: string): WizardPage;
|
||||
|
||||
/**
|
||||
* Create a wizard with the given title and pages
|
||||
* @param title The title of the wizard
|
||||
*/
|
||||
export function createWizard(title: string): Wizard;
|
||||
|
||||
export interface ModelViewPanel {
|
||||
/**
|
||||
* Register model view content for the dialog.
|
||||
@@ -407,6 +419,16 @@ declare module 'sqlops' {
|
||||
* Returns the model view content if registered. Returns undefined if model review is not registered
|
||||
*/
|
||||
readonly modelView: ModelView;
|
||||
|
||||
/**
|
||||
* Whether the panel's content is valid
|
||||
*/
|
||||
readonly valid: boolean;
|
||||
|
||||
/**
|
||||
* Fired whenever the panel's valid property changes
|
||||
*/
|
||||
readonly onValidityChanged: vscode.Event<boolean>;
|
||||
}
|
||||
|
||||
// Model view dialog classes
|
||||
@@ -436,16 +458,6 @@ declare module 'sqlops' {
|
||||
* Any additional buttons that should be displayed
|
||||
*/
|
||||
customButtons: Button[];
|
||||
|
||||
/**
|
||||
* Whether the dialog's content is valid
|
||||
*/
|
||||
readonly valid: boolean;
|
||||
|
||||
/**
|
||||
* Fired whenever the dialog's valid property changes
|
||||
*/
|
||||
readonly onValidityChanged: vscode.Event<boolean>;
|
||||
}
|
||||
|
||||
export interface DialogTab extends ModelViewPanel {
|
||||
@@ -481,6 +493,128 @@ declare module 'sqlops' {
|
||||
*/
|
||||
readonly onClick: vscode.Event<void>;
|
||||
}
|
||||
|
||||
export interface WizardPageChangeInfo {
|
||||
/**
|
||||
* The page number that the wizard changed from
|
||||
*/
|
||||
lastPage: number,
|
||||
|
||||
/**
|
||||
* The new page number
|
||||
*/
|
||||
newPage: number
|
||||
}
|
||||
|
||||
export interface WizardPage extends ModelViewPanel {
|
||||
/**
|
||||
* The title of the page
|
||||
*/
|
||||
title: string;
|
||||
|
||||
/**
|
||||
* A string giving the ID of the page's model view content
|
||||
*/
|
||||
content: string;
|
||||
|
||||
/**
|
||||
* Any additional buttons that should be displayed while the page is open
|
||||
*/
|
||||
customButtons: Button[];
|
||||
|
||||
/**
|
||||
* Whether the page is enabled. If the page is not enabled, the user will not be
|
||||
* able to advance to it. Defaults to true.
|
||||
*/
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface Wizard {
|
||||
/**
|
||||
* The title of the wizard
|
||||
*/
|
||||
title: string,
|
||||
|
||||
/**
|
||||
* The wizard's pages. Pages can be added/removed while the dialog is open by using
|
||||
* the addPage and removePage methods
|
||||
*/
|
||||
pages: WizardPage[];
|
||||
|
||||
/**
|
||||
* The index in the pages array of the active page, or undefined if the wizard is
|
||||
* not currently visible
|
||||
*/
|
||||
readonly currentPage: number;
|
||||
|
||||
/**
|
||||
* The done button
|
||||
*/
|
||||
doneButton: Button;
|
||||
|
||||
/**
|
||||
* The cancel button
|
||||
*/
|
||||
cancelButton: Button;
|
||||
|
||||
/**
|
||||
* The generate script button
|
||||
*/
|
||||
generateScriptButton: Button;
|
||||
|
||||
/**
|
||||
* The next button
|
||||
*/
|
||||
nextButton: Button;
|
||||
|
||||
/**
|
||||
* The back button
|
||||
*/
|
||||
backButton: Button;
|
||||
|
||||
/**
|
||||
* Any additional buttons that should be displayed for all pages of the dialog. If
|
||||
* buttons are needed for specific pages they can be added using the customButtons
|
||||
* property on each page.
|
||||
*/
|
||||
customButtons: Button[];
|
||||
|
||||
/**
|
||||
* Event fired when the wizard's page changes, containing information about the
|
||||
* previous page and the new page
|
||||
*/
|
||||
onPageChanged: vscode.Event<WizardPageChangeInfo>;
|
||||
|
||||
/**
|
||||
* Add a page to the wizard at the given index
|
||||
* @param page The page to add
|
||||
* @param index The index in the pages array to add the page at, or undefined to
|
||||
* add it at the end
|
||||
*/
|
||||
addPage(page: WizardPage, index?: number): Thenable<void>;
|
||||
|
||||
/**
|
||||
* Remove the page at the given index from the wizard
|
||||
* @param index The index in the pages array to remove
|
||||
*/
|
||||
removePage(index: number): Thenable<void>;
|
||||
|
||||
/**
|
||||
* Go to the page at the given index in the pages array.
|
||||
* @param index The index of the page to go to
|
||||
*/
|
||||
setCurrentPage(index: number): Thenable<void>;
|
||||
|
||||
/**
|
||||
* Open the wizard. Does nothing if the wizard is already open.
|
||||
*/
|
||||
open(): Thenable<void>;
|
||||
|
||||
/**
|
||||
* Close the wizard. Does nothing if the wizard is not open.
|
||||
*/
|
||||
close(): Thenable<void>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,25 @@ export interface IModelViewButtonDetails {
|
||||
hidden: boolean;
|
||||
}
|
||||
|
||||
export interface IModelViewWizardPageDetails {
|
||||
title: string;
|
||||
content: string;
|
||||
enabled: boolean;
|
||||
customButtons: number[];
|
||||
}
|
||||
|
||||
export interface IModelViewWizardDetails {
|
||||
title: string;
|
||||
pages: number[];
|
||||
currentPage: number;
|
||||
doneButton: number;
|
||||
cancelButton: number;
|
||||
generateScriptButton: number;
|
||||
nextButton: number;
|
||||
backButton: number;
|
||||
customButtons: number[];
|
||||
}
|
||||
|
||||
/// Card-related APIs that need to be here to avoid early load issues
|
||||
// with enums causing requiring of sqlops API to fail.
|
||||
export enum StatusIndicator {
|
||||
|
||||
@@ -15,13 +15,24 @@ import * as sqlops from 'sqlops';
|
||||
import { SqlMainContext, ExtHostModelViewDialogShape, MainThreadModelViewDialogShape, ExtHostModelViewShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||
import { IItemConfig, ModelComponentTypes, IComponentShape } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
|
||||
const DONE_LABEL = nls.localize('dialogDoneLabel', 'Done');
|
||||
const CANCEL_LABEL = nls.localize('dialogCancelLabel', 'Cancel');
|
||||
const GENERATE_SCRIPT_LABEL = nls.localize('generateScriptLabel', 'Generate script');
|
||||
const NEXT_LABEL = nls.localize('dialogNextLabel', 'Next');
|
||||
const PREVIOUS_LABEL = nls.localize('dialogPreviousLabel', 'Previous');
|
||||
|
||||
class ModelViewPanelImpl implements sqlops.window.modelviewdialog.ModelViewPanel {
|
||||
private _modelView: sqlops.ModelView;
|
||||
private _handle: number;
|
||||
protected _modelViewId: string;
|
||||
protected _valid: boolean = true;
|
||||
protected _onValidityChanged: vscode.Event<boolean>;
|
||||
|
||||
constructor(private _viewType: string,
|
||||
protected _extHostModelViewDialog: ExtHostModelViewDialog,
|
||||
protected _extHostModelView: ExtHostModelViewShape) {
|
||||
this._onValidityChanged = this._extHostModelViewDialog.getValidityChangedEvent(this);
|
||||
this._onValidityChanged(valid => this._valid = valid);
|
||||
}
|
||||
|
||||
public registerContent(handler: (view: sqlops.ModelView) => void): void {
|
||||
@@ -50,15 +61,24 @@ class ModelViewPanelImpl implements sqlops.window.modelviewdialog.ModelViewPanel
|
||||
public set modelView(value: sqlops.ModelView) {
|
||||
this._modelView = value;
|
||||
}
|
||||
|
||||
public get valid(): boolean {
|
||||
return this._valid;
|
||||
}
|
||||
|
||||
public get onValidityChanged(): Event<boolean> {
|
||||
return this._onValidityChanged;
|
||||
}
|
||||
}
|
||||
|
||||
class ModelViewEditorImpl extends ModelViewPanelImpl implements sqlops.workspace.ModelViewEditor {
|
||||
constructor(
|
||||
extHostModelViewDialog: ExtHostModelViewDialog,
|
||||
extHostModelView: ExtHostModelViewShape,
|
||||
private _proxy: MainThreadModelViewDialogShape,
|
||||
private _title: string
|
||||
) {
|
||||
super('modelViewEditor', extHostModelView);
|
||||
super('modelViewEditor', extHostModelViewDialog, extHostModelView);
|
||||
}
|
||||
|
||||
public openEditor(position?: vscode.ViewColumn): Thenable<void> {
|
||||
@@ -72,21 +92,12 @@ class DialogImpl extends ModelViewPanelImpl implements sqlops.window.modelviewdi
|
||||
public okButton: sqlops.window.modelviewdialog.Button;
|
||||
public cancelButton: sqlops.window.modelviewdialog.Button;
|
||||
public customButtons: sqlops.window.modelviewdialog.Button[];
|
||||
public readonly onValidityChanged: vscode.Event<boolean>;
|
||||
private _valid: boolean = true;
|
||||
|
||||
|
||||
constructor(private _extHostModelViewDialog: ExtHostModelViewDialog,
|
||||
constructor(extHostModelViewDialog: ExtHostModelViewDialog,
|
||||
extHostModelView: ExtHostModelViewShape) {
|
||||
super('modelViewDialog', extHostModelView);
|
||||
this.okButton = this._extHostModelViewDialog.createButton(nls.localize('dialogOkLabel', 'Done'));
|
||||
this.cancelButton = this._extHostModelViewDialog.createButton(nls.localize('dialogCancelLabel', 'Cancel'));
|
||||
this.onValidityChanged = this._extHostModelViewDialog.getValidityChangedEvent(this);
|
||||
this.onValidityChanged(valid => this._valid = valid);
|
||||
}
|
||||
|
||||
public get valid(): boolean {
|
||||
return this._valid;
|
||||
super('modelViewDialog', extHostModelViewDialog, extHostModelView);
|
||||
this.okButton = this._extHostModelViewDialog.createButton(DONE_LABEL);
|
||||
this.cancelButton = this._extHostModelViewDialog.createButton(CANCEL_LABEL);
|
||||
}
|
||||
|
||||
public setModelViewId(value: string) {
|
||||
@@ -97,9 +108,9 @@ class DialogImpl extends ModelViewPanelImpl implements sqlops.window.modelviewdi
|
||||
|
||||
class TabImpl extends ModelViewPanelImpl implements sqlops.window.modelviewdialog.DialogTab {
|
||||
constructor(
|
||||
private _extHostModelViewDialog: ExtHostModelViewDialog,
|
||||
extHostModelViewDialog: ExtHostModelViewDialog,
|
||||
extHostModelView: ExtHostModelViewShape) {
|
||||
super('modelViewDialogTab', extHostModelView);
|
||||
super('modelViewDialogTab', extHostModelViewDialog, extHostModelView);
|
||||
}
|
||||
|
||||
public title: string;
|
||||
@@ -157,17 +168,110 @@ class ButtonImpl implements sqlops.window.modelviewdialog.Button {
|
||||
}
|
||||
}
|
||||
|
||||
class WizardPageImpl extends ModelViewPanelImpl implements sqlops.window.modelviewdialog.WizardPage {
|
||||
public customButtons: sqlops.window.modelviewdialog.Button[];
|
||||
private _enabled: boolean = true;
|
||||
|
||||
constructor(public title: string, _extHostModelViewDialog: ExtHostModelViewDialog, _extHostModelView: ExtHostModelViewShape) {
|
||||
super('modelViewWizardPage', _extHostModelViewDialog, _extHostModelView);
|
||||
}
|
||||
|
||||
public get enabled(): boolean {
|
||||
return this._enabled;
|
||||
}
|
||||
|
||||
public set enabled(enabled: boolean) {
|
||||
this._enabled = enabled;
|
||||
this._extHostModelViewDialog.updateWizardPage(this);
|
||||
}
|
||||
|
||||
public get content(): string {
|
||||
return this._modelViewId;
|
||||
}
|
||||
|
||||
public set content(content: string) {
|
||||
this._modelViewId = content;
|
||||
}
|
||||
}
|
||||
|
||||
export enum WizardPageInfoEventType {
|
||||
PageChanged,
|
||||
PageAddedOrRemoved
|
||||
}
|
||||
|
||||
export interface WizardPageEventInfo {
|
||||
eventType: WizardPageInfoEventType;
|
||||
pageChangeInfo: sqlops.window.modelviewdialog.WizardPageChangeInfo;
|
||||
pages?: sqlops.window.modelviewdialog.WizardPage[];
|
||||
}
|
||||
|
||||
class WizardImpl implements sqlops.window.modelviewdialog.Wizard {
|
||||
private _currentPage: number = undefined;
|
||||
public pages: sqlops.window.modelviewdialog.WizardPage[] = [];
|
||||
public doneButton: sqlops.window.modelviewdialog.Button;
|
||||
public cancelButton: sqlops.window.modelviewdialog.Button;
|
||||
public generateScriptButton: sqlops.window.modelviewdialog.Button;
|
||||
public nextButton: sqlops.window.modelviewdialog.Button;
|
||||
public backButton: sqlops.window.modelviewdialog.Button;
|
||||
public customButtons: sqlops.window.modelviewdialog.Button[];
|
||||
private _pageChangedEmitter = new Emitter<sqlops.window.modelviewdialog.WizardPageChangeInfo>();
|
||||
public readonly onPageChanged = this._pageChangedEmitter.event;
|
||||
|
||||
constructor(public title: string, private _extHostModelViewDialog: ExtHostModelViewDialog) {
|
||||
this.doneButton = this._extHostModelViewDialog.createButton(DONE_LABEL);
|
||||
this.cancelButton = this._extHostModelViewDialog.createButton(CANCEL_LABEL);
|
||||
this.generateScriptButton = this._extHostModelViewDialog.createButton(GENERATE_SCRIPT_LABEL);
|
||||
this.nextButton = this._extHostModelViewDialog.createButton(NEXT_LABEL);
|
||||
this.backButton = this._extHostModelViewDialog.createButton(PREVIOUS_LABEL);
|
||||
this._extHostModelViewDialog.registerWizardPageInfoChangedCallback(this, info => this.handlePageInfoChanged(info));
|
||||
this.onPageChanged(info => this._currentPage = info.newPage);
|
||||
}
|
||||
|
||||
public get currentPage(): number {
|
||||
return this._currentPage;
|
||||
}
|
||||
|
||||
public addPage(page: sqlops.window.modelviewdialog.WizardPage, index?: number): Thenable<void> {
|
||||
return this._extHostModelViewDialog.updateWizardPage(page).then(() => {
|
||||
this._extHostModelViewDialog.addPage(this, page, index);
|
||||
});
|
||||
}
|
||||
|
||||
public removePage(index: number): Thenable<void> {
|
||||
return this._extHostModelViewDialog.removePage(this, index);
|
||||
}
|
||||
|
||||
public setCurrentPage(index: number): Thenable<void> {
|
||||
return this._extHostModelViewDialog.setWizardPage(this, index);
|
||||
}
|
||||
|
||||
public open(): Thenable<void> {
|
||||
return this._extHostModelViewDialog.openWizard(this);
|
||||
}
|
||||
|
||||
public close(): Thenable<void> {
|
||||
return this._extHostModelViewDialog.closeWizard(this);
|
||||
}
|
||||
|
||||
private handlePageInfoChanged(info: WizardPageEventInfo): void {
|
||||
this._currentPage = info.pageChangeInfo.newPage;
|
||||
if (info.eventType === WizardPageInfoEventType.PageAddedOrRemoved) {
|
||||
this.pages = info.pages;
|
||||
} else if (info.eventType === WizardPageInfoEventType.PageChanged) {
|
||||
this._pageChangedEmitter.fire(info.pageChangeInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
||||
private static _currentHandle = 0;
|
||||
|
||||
private readonly _proxy: MainThreadModelViewDialogShape;
|
||||
|
||||
private readonly _dialogHandles = new Map<sqlops.window.modelviewdialog.Dialog, number>();
|
||||
private readonly _tabHandles = new Map<sqlops.window.modelviewdialog.DialogTab, number>();
|
||||
private readonly _buttonHandles = new Map<sqlops.window.modelviewdialog.Button, number>();
|
||||
private readonly _editorHandles = new Map<sqlops.workspace.ModelViewEditor, number>();
|
||||
|
||||
private readonly _objectHandles = new Map<object, number>();
|
||||
private readonly _objectsByHandle = new Map<number, object>();
|
||||
private readonly _validityEmitters = new Map<number, Emitter<boolean>>();
|
||||
private readonly _pageInfoChangedCallbacks = new Map<number, (info: WizardPageEventInfo) => void>();
|
||||
private readonly _onClickCallbacks = new Map<number, () => void>();
|
||||
|
||||
constructor(
|
||||
@@ -183,38 +287,13 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
||||
return handle;
|
||||
}
|
||||
|
||||
private getEditorHandle(editor: sqlops.workspace.ModelViewEditor) {
|
||||
let handle = this._editorHandles.get(editor);
|
||||
private getHandle(item: sqlops.window.modelviewdialog.Button | sqlops.window.modelviewdialog.Dialog | sqlops.window.modelviewdialog.DialogTab
|
||||
| sqlops.window.modelviewdialog.ModelViewPanel | sqlops.window.modelviewdialog.Wizard | sqlops.window.modelviewdialog.WizardPage | sqlops.workspace.ModelViewEditor) {
|
||||
let handle = this._objectHandles.get(item);
|
||||
if (handle === undefined) {
|
||||
handle = ExtHostModelViewDialog.getNewHandle();
|
||||
this._editorHandles.set(editor, handle);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
private getDialogHandle(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||
let handle = this._dialogHandles.get(dialog);
|
||||
if (handle === undefined) {
|
||||
handle = ExtHostModelViewDialog.getNewHandle();
|
||||
this._dialogHandles.set(dialog, handle);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
private getTabHandle(tab: sqlops.window.modelviewdialog.DialogTab) {
|
||||
let handle = this._tabHandles.get(tab);
|
||||
if (handle === undefined) {
|
||||
handle = ExtHostModelViewDialog.getNewHandle();
|
||||
this._tabHandles.set(tab, handle);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
private getButtonHandle(button: sqlops.window.modelviewdialog.Button) {
|
||||
let handle = this._buttonHandles.get(button);
|
||||
if (handle === undefined) {
|
||||
handle = ExtHostModelViewDialog.getNewHandle();
|
||||
this._buttonHandles.set(button, handle);
|
||||
this._objectHandles.set(item, handle);
|
||||
this._objectsByHandle.set(handle, item);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
@@ -223,32 +302,57 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
||||
this._onClickCallbacks.get(handle)();
|
||||
}
|
||||
|
||||
public $onDialogValidityChanged(handle: number, valid: boolean): void {
|
||||
public $onPanelValidityChanged(handle: number, valid: boolean): void {
|
||||
let emitter = this._validityEmitters.get(handle);
|
||||
if (emitter) {
|
||||
emitter.fire(valid);
|
||||
}
|
||||
}
|
||||
|
||||
public open(dialog: sqlops.window.modelviewdialog.Dialog): void {
|
||||
let handle = this.getDialogHandle(dialog);
|
||||
this.updateDialogContent(dialog);
|
||||
this._proxy.$open(handle);
|
||||
public $onWizardPageChanged(handle: number, info: sqlops.window.modelviewdialog.WizardPageChangeInfo): void {
|
||||
let callback = this._pageInfoChangedCallbacks.get(handle);
|
||||
if (callback) {
|
||||
callback({
|
||||
eventType: WizardPageInfoEventType.PageChanged,
|
||||
pageChangeInfo: info
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public close(dialog: sqlops.window.modelviewdialog.Dialog): void {
|
||||
let handle = this.getDialogHandle(dialog);
|
||||
this._proxy.$close(handle);
|
||||
public $updateWizardPageInfo(handle: number, pageHandles: number[], currentPageIndex: number): void {
|
||||
let callback = this._pageInfoChangedCallbacks.get(handle);
|
||||
if (callback) {
|
||||
let pages = pageHandles.map(pageHandle => this._objectsByHandle.get(handle) as sqlops.window.modelviewdialog.WizardPage);
|
||||
callback({
|
||||
eventType: WizardPageInfoEventType.PageAddedOrRemoved,
|
||||
pageChangeInfo: {
|
||||
lastPage: undefined,
|
||||
newPage: currentPageIndex
|
||||
},
|
||||
pages: pages
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public openDialog(dialog: sqlops.window.modelviewdialog.Dialog): void {
|
||||
let handle = this.getHandle(dialog);
|
||||
this.updateDialogContent(dialog);
|
||||
this._proxy.$openDialog(handle);
|
||||
}
|
||||
|
||||
public closeDialog(dialog: sqlops.window.modelviewdialog.Dialog): void {
|
||||
let handle = this.getHandle(dialog);
|
||||
this._proxy.$closeDialog(handle);
|
||||
}
|
||||
|
||||
public createModelViewEditor(title: string): sqlops.workspace.ModelViewEditor {
|
||||
let editor = new ModelViewEditorImpl(this._extHostModelView, this._proxy, title);
|
||||
editor.handle = this.getEditorHandle(editor);
|
||||
let editor = new ModelViewEditorImpl(this, this._extHostModelView, this._proxy, title);
|
||||
editor.handle = this.getHandle(editor);
|
||||
return editor;
|
||||
}
|
||||
|
||||
public updateDialogContent(dialog: sqlops.window.modelviewdialog.Dialog): void {
|
||||
let handle = this.getDialogHandle(dialog);
|
||||
let handle = this.getHandle(dialog);
|
||||
let tabs = dialog.content;
|
||||
if (tabs && typeof tabs !== 'string') {
|
||||
tabs.forEach(tab => this.updateTabContent(tab));
|
||||
@@ -260,15 +364,15 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
||||
this.updateButton(dialog.cancelButton);
|
||||
this._proxy.$setDialogDetails(handle, {
|
||||
title: dialog.title,
|
||||
okButton: this.getButtonHandle(dialog.okButton),
|
||||
cancelButton: this.getButtonHandle(dialog.cancelButton),
|
||||
content: dialog.content && typeof dialog.content !== 'string' ? dialog.content.map(tab => this.getTabHandle(tab)) : dialog.content as string,
|
||||
customButtons: dialog.customButtons ? dialog.customButtons.map(button => this.getButtonHandle(button)) : undefined
|
||||
okButton: this.getHandle(dialog.okButton),
|
||||
cancelButton: this.getHandle(dialog.cancelButton),
|
||||
content: dialog.content && typeof dialog.content !== 'string' ? dialog.content.map(tab => this.getHandle(tab)) : dialog.content as string,
|
||||
customButtons: dialog.customButtons ? dialog.customButtons.map(button => this.getHandle(button)) : undefined
|
||||
});
|
||||
}
|
||||
|
||||
public updateTabContent(tab: sqlops.window.modelviewdialog.DialogTab): void {
|
||||
let handle = this.getTabHandle(tab);
|
||||
let handle = this.getHandle(tab);
|
||||
this._proxy.$setTabDetails(handle, {
|
||||
title: tab.title,
|
||||
content: tab.content
|
||||
@@ -276,7 +380,7 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
||||
}
|
||||
|
||||
public updateButton(button: sqlops.window.modelviewdialog.Button): void {
|
||||
let handle = this.getButtonHandle(button);
|
||||
let handle = this.getHandle(button);
|
||||
this._proxy.$setButtonDetails(handle, {
|
||||
label: button.label,
|
||||
enabled: button.enabled,
|
||||
@@ -285,34 +389,34 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
||||
}
|
||||
|
||||
public registerOnClickCallback(button: sqlops.window.modelviewdialog.Button, callback: () => void) {
|
||||
let handle = this.getButtonHandle(button);
|
||||
let handle = this.getHandle(button);
|
||||
this._onClickCallbacks.set(handle, callback);
|
||||
}
|
||||
|
||||
public createDialog(title: string): sqlops.window.modelviewdialog.Dialog {
|
||||
let dialog = new DialogImpl(this, this._extHostModelView);
|
||||
dialog.title = title;
|
||||
dialog.handle = this.getDialogHandle(dialog);
|
||||
dialog.handle = this.getHandle(dialog);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public createTab(title: string): sqlops.window.modelviewdialog.DialogTab {
|
||||
let tab = new TabImpl(this, this._extHostModelView);
|
||||
tab.title = title;
|
||||
tab.handle = this.getTabHandle(tab);
|
||||
tab.handle = this.getHandle(tab);
|
||||
return tab;
|
||||
}
|
||||
|
||||
public createButton(label: string): sqlops.window.modelviewdialog.Button {
|
||||
let button = new ButtonImpl(this);
|
||||
this.getButtonHandle(button);
|
||||
this.getHandle(button);
|
||||
this.registerOnClickCallback(button, button.getOnClickCallback());
|
||||
button.label = label;
|
||||
return button;
|
||||
}
|
||||
|
||||
public getValidityChangedEvent(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||
let handle = this.getDialogHandle(dialog);
|
||||
public getValidityChangedEvent(panel: sqlops.window.modelviewdialog.ModelViewPanel) {
|
||||
let handle = this.getHandle(panel);
|
||||
let emitter = this._validityEmitters.get(handle);
|
||||
if (!emitter) {
|
||||
emitter = new Emitter<boolean>();
|
||||
@@ -320,4 +424,81 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
||||
}
|
||||
return emitter.event;
|
||||
}
|
||||
|
||||
public registerWizardPageInfoChangedCallback(wizard: sqlops.window.modelviewdialog.Wizard, callback: (info: WizardPageEventInfo) => void): void {
|
||||
let handle = this.getHandle(wizard);
|
||||
this._pageInfoChangedCallbacks.set(handle, callback);
|
||||
}
|
||||
|
||||
public createWizardPage(title: string): sqlops.window.modelviewdialog.WizardPage {
|
||||
let page = new WizardPageImpl(title, this, this._extHostModelView);
|
||||
page.handle = this.getHandle(page);
|
||||
return page;
|
||||
}
|
||||
|
||||
public createWizard(title: string): sqlops.window.modelviewdialog.Wizard {
|
||||
let wizard = new WizardImpl(title, this);
|
||||
this.getHandle(wizard);
|
||||
return wizard;
|
||||
}
|
||||
|
||||
public updateWizardPage(page: sqlops.window.modelviewdialog.WizardPage): Thenable<void> {
|
||||
let handle = this.getHandle(page);
|
||||
if (page.customButtons) {
|
||||
page.customButtons.forEach(button => this.updateButton(button));
|
||||
}
|
||||
return this._proxy.$setWizardPageDetails(handle, {
|
||||
content: page.content,
|
||||
customButtons: page.customButtons ? page.customButtons.map(button => this.getHandle(button)) : undefined,
|
||||
enabled: page.enabled,
|
||||
title: page.title
|
||||
});
|
||||
}
|
||||
|
||||
public updateWizard(wizard: sqlops.window.modelviewdialog.Wizard): Thenable<void> {
|
||||
let handle = this.getHandle(wizard);
|
||||
wizard.pages.forEach(page => this.updateWizardPage(page));
|
||||
this.updateButton(wizard.backButton);
|
||||
this.updateButton(wizard.cancelButton);
|
||||
this.updateButton(wizard.generateScriptButton);
|
||||
this.updateButton(wizard.doneButton);
|
||||
this.updateButton(wizard.nextButton);
|
||||
if (wizard.customButtons) {
|
||||
wizard.customButtons.forEach(button => this.updateButton(button));
|
||||
}
|
||||
return this._proxy.$setWizardDetails(handle, {
|
||||
title: wizard.title,
|
||||
pages: wizard.pages.map(page => this.getHandle(page)),
|
||||
currentPage: wizard.currentPage,
|
||||
backButton: this.getHandle(wizard.backButton),
|
||||
cancelButton: this.getHandle(wizard.cancelButton),
|
||||
generateScriptButton: this.getHandle(wizard.generateScriptButton),
|
||||
doneButton: this.getHandle(wizard.doneButton),
|
||||
nextButton: this.getHandle(wizard.nextButton),
|
||||
customButtons: wizard.customButtons ? wizard.customButtons.map(button => this.getHandle(button)) : undefined
|
||||
});
|
||||
}
|
||||
|
||||
public addPage(wizard: sqlops.window.modelviewdialog.Wizard, page: sqlops.window.modelviewdialog.WizardPage, pageIndex?: number): Thenable<void> {
|
||||
return this._proxy.$addWizardPage(this.getHandle(wizard), this.getHandle(page), pageIndex);
|
||||
}
|
||||
|
||||
public removePage(wizard: sqlops.window.modelviewdialog.Wizard, pageIndex: number): Thenable<void> {
|
||||
return this._proxy.$removeWizardPage(this.getHandle(wizard), pageIndex);
|
||||
}
|
||||
|
||||
public setWizardPage(wizard: sqlops.window.modelviewdialog.Wizard, pageIndex: number): Thenable<void> {
|
||||
return this._proxy.$setWizardPage(this.getHandle(wizard), pageIndex);
|
||||
}
|
||||
|
||||
public openWizard(wizard: sqlops.window.modelviewdialog.Wizard): Thenable<void> {
|
||||
let handle = this.getHandle(wizard);
|
||||
this.updateWizard(wizard);
|
||||
return this._proxy.$openWizard(handle);
|
||||
}
|
||||
|
||||
public closeWizard(wizard: sqlops.window.modelviewdialog.Wizard): Thenable<void> {
|
||||
let handle = this.getHandle(wizard);
|
||||
return this._proxy.$closeWizard(handle);
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,9 @@ import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
import { MainThreadModelViewDialogShape, SqlMainContext, ExtHostModelViewDialogShape, SqlExtHostContext } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||
import { Dialog, DialogTab, DialogButton } from 'sql/platform/dialog/dialogTypes';
|
||||
import { Dialog, DialogTab, DialogButton, WizardPage, Wizard } from 'sql/platform/dialog/dialogTypes';
|
||||
import { CustomDialogService } from 'sql/platform/dialog/customDialogService';
|
||||
import { IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
import { IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails, IModelViewWizardPageDetails, IModelViewWizardDetails } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
import { ModelViewInput } from 'sql/parts/modelComponents/modelEditor/modelViewInput';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
@@ -24,6 +24,9 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
||||
private readonly _dialogs = new Map<number, Dialog>();
|
||||
private readonly _tabs = new Map<number, DialogTab>();
|
||||
private readonly _buttons = new Map<number, DialogButton>();
|
||||
private readonly _wizardPages = new Map<number, WizardPage>();
|
||||
private readonly _wizardPageHandles = new Map<WizardPage, number>();
|
||||
private readonly _wizards = new Map<number, Wizard>();
|
||||
private _dialogService: CustomDialogService;
|
||||
|
||||
constructor(
|
||||
@@ -55,13 +58,13 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
||||
});
|
||||
}
|
||||
|
||||
public $open(handle: number): Thenable<void> {
|
||||
public $openDialog(handle: number): Thenable<void> {
|
||||
let dialog = this.getDialog(handle);
|
||||
this._dialogService.showDialog(dialog);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $close(handle: number): Thenable<void> {
|
||||
public $closeDialog(handle: number): Thenable<void> {
|
||||
let dialog = this.getDialog(handle);
|
||||
this._dialogService.closeDialog(dialog);
|
||||
return Promise.resolve();
|
||||
@@ -75,7 +78,7 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
||||
let cancelButton = this.getButton(details.cancelButton);
|
||||
dialog.okButton = okButton;
|
||||
dialog.cancelButton = cancelButton;
|
||||
dialog.onValidityChanged(valid => this._proxy.$onDialogValidityChanged(handle, valid));
|
||||
dialog.onValidityChanged(valid => this._proxy.$onPanelValidityChanged(handle, valid));
|
||||
this._dialogs.set(handle, dialog);
|
||||
}
|
||||
|
||||
@@ -97,6 +100,7 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
||||
let tab = this._tabs.get(handle);
|
||||
if (!tab) {
|
||||
tab = new DialogTab(details.title);
|
||||
tab.onValidityChanged(valid => this._proxy.$onPanelValidityChanged(handle, valid));
|
||||
this._tabs.set(handle, tab);
|
||||
}
|
||||
|
||||
@@ -121,12 +125,91 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $setWizardPageDetails(handle: number, details: IModelViewWizardPageDetails): Thenable<void> {
|
||||
let page = this._wizardPages.get(handle);
|
||||
if (!page) {
|
||||
page = new WizardPage(details.title, details.content);
|
||||
page.onValidityChanged(valid => this._proxy.$onPanelValidityChanged(handle, valid));
|
||||
this._wizardPages.set(handle, page);
|
||||
this._wizardPageHandles.set(page, handle);
|
||||
}
|
||||
|
||||
page.title = details.title;
|
||||
page.content = details.content;
|
||||
page.enabled = details.enabled;
|
||||
if (details.customButtons !== undefined) {
|
||||
page.customButtons = details.customButtons.map(buttonHandle => this.getButton(buttonHandle));
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $setWizardDetails(handle: number, details: IModelViewWizardDetails): Thenable<void> {
|
||||
let wizard = this._wizards.get(handle);
|
||||
if (!wizard) {
|
||||
wizard = new Wizard(details.title);
|
||||
wizard.backButton = this.getButton(details.backButton);
|
||||
wizard.cancelButton = this.getButton(details.cancelButton);
|
||||
wizard.generateScriptButton = this.getButton(details.generateScriptButton);
|
||||
wizard.doneButton = this.getButton(details.doneButton);
|
||||
wizard.nextButton = this.getButton(details.nextButton);
|
||||
wizard.onPageChanged(info => this._proxy.$onWizardPageChanged(handle, info));
|
||||
wizard.onPageAdded(() => this.handleWizardPageAddedOrRemoved(handle));
|
||||
wizard.onPageRemoved(() => this.handleWizardPageAddedOrRemoved(handle));
|
||||
this._wizards.set(handle, wizard);
|
||||
}
|
||||
|
||||
wizard.title = details.title;
|
||||
wizard.pages = details.pages.map(handle => this.getWizardPage(handle));
|
||||
if (details.currentPage !== undefined) {
|
||||
wizard.setCurrentPage(details.currentPage);
|
||||
}
|
||||
if (details.customButtons !== undefined) {
|
||||
wizard.customButtons = details.customButtons.map(buttonHandle => this.getButton(buttonHandle));
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $addWizardPage(wizardHandle: number, pageHandle: number, pageIndex?: number): Thenable<void> {
|
||||
if (pageIndex === null) {
|
||||
pageIndex = undefined;
|
||||
}
|
||||
let wizard = this.getWizard(wizardHandle);
|
||||
let page = this.getWizardPage(pageHandle);
|
||||
wizard.addPage(page, pageIndex);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $removeWizardPage(wizardHandle: number, pageIndex: number): Thenable<void> {
|
||||
let wizard = this.getWizard(wizardHandle);
|
||||
wizard.removePage(pageIndex);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $setWizardPage(wizardHandle: number, pageIndex: number): Thenable<void> {
|
||||
let wizard = this.getWizard(wizardHandle);
|
||||
wizard.setCurrentPage(pageIndex);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $openWizard(handle: number): Thenable<void> {
|
||||
let wizard = this.getWizard(handle);
|
||||
this._dialogService.showWizard(wizard);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $closeWizard(handle: number): Thenable<void> {
|
||||
let wizard = this.getWizard(handle);
|
||||
this._dialogService.closeWizard(wizard);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
private getDialog(handle: number): Dialog {
|
||||
let dialog = this._dialogs.get(handle);
|
||||
if (!dialog) {
|
||||
throw new Error('No dialog matching the given handle');
|
||||
}
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@@ -135,7 +218,6 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
||||
if (!tab) {
|
||||
throw new Error('No tab matching the given handle');
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
@@ -144,11 +226,31 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
||||
if (!button) {
|
||||
throw new Error('No button matching the given handle');
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
private onButtonClick(handle: number): void {
|
||||
this._proxy.$onButtonClick(handle);
|
||||
}
|
||||
|
||||
private getWizardPage(handle: number): WizardPage {
|
||||
let page = this._wizardPages.get(handle);
|
||||
if (!page) {
|
||||
throw new Error('No page matching the given handle');
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
private getWizard(handle: number): Wizard {
|
||||
let wizard = this._wizards.get(handle);
|
||||
if (!wizard) {
|
||||
throw new Error('No wizard matching the given handle');
|
||||
}
|
||||
return wizard;
|
||||
}
|
||||
|
||||
private handleWizardPageAddedOrRemoved(handle: number): void {
|
||||
let wizard = this._wizards.get(handle);
|
||||
this._proxy.$updateWizardPageInfo(handle, wizard.pages.map(page => this._wizardPageHandles.get(page)), wizard.currentPage);
|
||||
}
|
||||
}
|
||||
@@ -295,10 +295,16 @@ export function createApiFactory(
|
||||
return extHostModelViewDialog.createButton(label);
|
||||
},
|
||||
openDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||
return extHostModelViewDialog.open(dialog);
|
||||
return extHostModelViewDialog.openDialog(dialog);
|
||||
},
|
||||
closeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||
return extHostModelViewDialog.close(dialog);
|
||||
return extHostModelViewDialog.closeDialog(dialog);
|
||||
},
|
||||
createWizardPage(title: string): sqlops.window.modelviewdialog.WizardPage {
|
||||
return extHostModelViewDialog.createWizardPage(title);
|
||||
},
|
||||
createWizard(title: string): sqlops.window.modelviewdialog.Wizard {
|
||||
return extHostModelViewDialog.createWizard(title);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
import {
|
||||
createMainContextProxyIdentifier as createMainId,
|
||||
createExtHostContextProxyIdentifier as createExtId,
|
||||
ProxyIdentifier, IRPCProtocol } from 'vs/workbench/services/extensions/node/proxyIdentifier';
|
||||
ProxyIdentifier, IRPCProtocol
|
||||
} from 'vs/workbench/services/extensions/node/proxyIdentifier';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -16,7 +17,10 @@ import * as sqlops from 'sqlops';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { ITaskHandlerDescription } from 'sql/platform/tasks/common/tasks';
|
||||
import { IItemConfig, ModelComponentTypes, IComponentShape, IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
import {
|
||||
IItemConfig, ModelComponentTypes, IComponentShape, IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails,
|
||||
IModelViewWizardDetails, IModelViewWizardPageDetails
|
||||
} from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
|
||||
export abstract class ExtHostAccountManagementShape {
|
||||
@@ -313,17 +317,17 @@ export abstract class ExtHostDataProtocolShape {
|
||||
/**
|
||||
* Get Agent Job list
|
||||
*/
|
||||
$getJobs(handle: number, ownerUri: string): Thenable<sqlops.AgentJobsResult>{ throw ni(); }
|
||||
$getJobs(handle: number, ownerUri: string): Thenable<sqlops.AgentJobsResult> { throw ni(); }
|
||||
|
||||
/**
|
||||
* Get a Agent Job's history
|
||||
*/
|
||||
$getJobHistory(handle: number, ownerUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult>{ throw ni(); }
|
||||
$getJobHistory(handle: number, ownerUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult> { throw ni(); }
|
||||
|
||||
/**
|
||||
* Run an action on a Job
|
||||
*/
|
||||
$jobAction(handle: number, ownerUri: string, jobName: string, action: string): Thenable<sqlops.AgentJobActionResult>{ throw ni(); }
|
||||
$jobAction(handle: number, ownerUri: string, jobName: string, action: string): Thenable<sqlops.AgentJobActionResult> { throw ni(); }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -530,7 +534,7 @@ export interface MainThreadModelViewShape extends IDisposable {
|
||||
$addToContainer(handle: number, containerId: string, item: IItemConfig): Thenable<void>;
|
||||
$setLayout(handle: number, componentId: string, layout: any): Thenable<void>;
|
||||
$setProperties(handle: number, componentId: string, properties: { [key: string]: any }): Thenable<void>;
|
||||
$registerEvent(handle: number, componentId: string): Thenable<void>;
|
||||
$registerEvent(handle: number, componentId: string): Thenable<void>;
|
||||
$validate(handle: number, componentId: string): Thenable<boolean>;
|
||||
}
|
||||
|
||||
@@ -539,7 +543,7 @@ export interface ExtHostObjectExplorerShape {
|
||||
|
||||
export interface MainThreadObjectExplorerShape extends IDisposable {
|
||||
$getNode(connectionId: string, nodePath?: string): Thenable<sqlops.NodeInfo>;
|
||||
$getActiveConnectionNodes(): Thenable<{ nodeInfo: sqlops.NodeInfo, connectionId: string}[]>;
|
||||
$getActiveConnectionNodes(): Thenable<{ nodeInfo: sqlops.NodeInfo, connectionId: string }[]>;
|
||||
$setExpandedState(connectionId: string, nodePath: string, expandedState: vscode.TreeItemCollapsibleState): Thenable<void>;
|
||||
$setSelected(connectionId: string, nodePath: string, selected: boolean, clearOtherSelections?: boolean): Thenable<void>;
|
||||
$getChildren(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo[]>;
|
||||
@@ -549,16 +553,25 @@ export interface MainThreadObjectExplorerShape extends IDisposable {
|
||||
|
||||
export interface ExtHostModelViewDialogShape {
|
||||
$onButtonClick(handle: number): void;
|
||||
$onDialogValidityChanged(handle: number, valid: boolean): void;
|
||||
$onPanelValidityChanged(handle: number, valid: boolean): void;
|
||||
$onWizardPageChanged(handle: number, info: sqlops.window.modelviewdialog.WizardPageChangeInfo): void;
|
||||
$updateWizardPageInfo(handle: number, pageHandles: number[], currentPageIndex: number): void;
|
||||
}
|
||||
|
||||
export interface MainThreadModelViewDialogShape extends IDisposable {
|
||||
$openEditor(modelViewId: string, title: string, position?: vscode.ViewColumn): Thenable<void>;
|
||||
$open(handle: number): Thenable<void>;
|
||||
$close(handle: number): Thenable<void>;
|
||||
$openDialog(handle: number): Thenable<void>;
|
||||
$closeDialog(handle: number): Thenable<void>;
|
||||
$setDialogDetails(handle: number, details: IModelViewDialogDetails): Thenable<void>;
|
||||
$setTabDetails(handle: number, details: IModelViewTabDetails): Thenable<void>;
|
||||
$setButtonDetails(handle: number, details: IModelViewButtonDetails): Thenable<void>;
|
||||
$openWizard(handle: number): Thenable<void>;
|
||||
$closeWizard(handle: number): Thenable<void>;
|
||||
$setWizardPageDetails(handle: number, details: IModelViewWizardPageDetails): Thenable<void>;
|
||||
$setWizardDetails(handle: number, details: IModelViewWizardDetails): Thenable<void>;
|
||||
$addWizardPage(wizardHandle: number, pageHandle: number, pageIndex: number): Thenable<void>;
|
||||
$removeWizardPage(wizardHandle: number, pageIndex: number): Thenable<void>;
|
||||
$setWizardPage(wizardHandle: number, pageIndex: number): Thenable<void>;
|
||||
}
|
||||
export interface ExtHostQueryEditorShape {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user