diff --git a/src/sql/platform/dialog/customDialogService.ts b/src/sql/platform/dialog/customDialogService.ts index 684673c2a5..a44a3ec02f 100644 --- a/src/sql/platform/dialog/customDialogService.ts +++ b/src/sql/platform/dialog/customDialogService.ts @@ -12,7 +12,7 @@ import { Dialog } 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: true }; +const defaultOptions: IModalOptions = { hasBackButton: true, isWide: false }; export class CustomDialogService { constructor( @IInstantiationService private _instantiationService: IInstantiationService) { } diff --git a/src/sql/platform/dialog/dialogModal.ts b/src/sql/platform/dialog/dialogModal.ts index a5eec9a9f5..98d9514608 100644 --- a/src/sql/platform/dialog/dialogModal.ts +++ b/src/sql/platform/dialog/dialogModal.ts @@ -8,7 +8,7 @@ import 'vs/css!./media/dialogModal'; import { Modal, IModalOptions } from 'sql/base/browser/ui/modal/modal'; import { attachModalDialogStyler } from 'sql/common/theme/styler'; -import { Dialog } from 'sql/platform/dialog/dialogTypes'; +import { Dialog, DialogButton } from 'sql/platform/dialog/dialogTypes'; import { DialogPane } from 'sql/platform/dialog/dialogPane'; import { IBootstrapService } from 'sql/services/bootstrap/bootstrapService'; import { Builder } from 'vs/base/browser/builder'; @@ -23,9 +23,6 @@ import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { localize } from 'vs/nls'; export class DialogModal extends Modal { - private static readonly DONE_BUTTON_LABEL = localize('dialogModalDoneButtonLabel', 'Done'); - private static readonly CANCEL_BUTTON_LABEL = localize('dialogModalCancelButtonLabel', 'Cancel'); - private _dialogPane: DialogPane; // Wizard HTML elements @@ -61,12 +58,28 @@ export class DialogModal extends Modal { attachButtonStyler(this.backButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND }); } - this._cancelButton = this.addFooterButton(DialogModal.CANCEL_BUTTON_LABEL, () => this.cancel()); - this._doneButton = this.addFooterButton(DialogModal.DONE_BUTTON_LABEL, () => this.done()); + if (this._dialog.customButtons) { + this._dialog.customButtons.forEach(button => { + let buttonElement = this.addDialogButton(button); + buttonElement.enabled = button.enabled; + attachButtonStyler(buttonElement, this._themeService); + }); + } + + this._cancelButton = this.addDialogButton(this._dialog.cancelButton, () => this.cancel()); + this._cancelButton.enabled = this._dialog.cancelButton.enabled; + this._doneButton = this.addDialogButton(this._dialog.okButton, () => this.done()); + this._doneButton.enabled = this._dialog.okButton.enabled; attachButtonStyler(this._cancelButton, this._themeService); attachButtonStyler(this._doneButton, this._themeService); } + private addDialogButton(button: DialogButton, onSelect: () => void = () => undefined): Button { + let buttonElement = this.addFooterButton(button.label, onSelect); + button.registerClickEvent(buttonElement.onDidClick); + return buttonElement; + } + protected renderBody(container: HTMLElement): void { new Builder(container).div({ class: 'dialogModal-body' }, (bodyBuilder) => { this._body = bodyBuilder.getHTMLElement(); diff --git a/src/sql/platform/dialog/dialogTypes.ts b/src/sql/platform/dialog/dialogTypes.ts index d58e229b0a..b256952ef8 100644 --- a/src/sql/platform/dialog/dialogTypes.ts +++ b/src/sql/platform/dialog/dialogTypes.ts @@ -6,6 +6,7 @@ 'use strict'; import * as sqlops from 'sqlops'; +import { localize } from 'vs/nls'; import Event, { Emitter } from 'vs/base/common/event'; export class DialogTab implements sqlops.window.modelviewdialog.DialogTab { @@ -21,15 +22,13 @@ export class DialogTab implements sqlops.window.modelviewdialog.DialogTab { } export class Dialog implements sqlops.window.modelviewdialog.Dialog { - public content: string | DialogTab[]; - public okTitle: string; - public cancelTitle: string; - public customButtons: DialogButton[]; + private static readonly DONE_BUTTON_LABEL = localize('dialogModalDoneButtonLabel', 'Done'); + private static readonly CANCEL_BUTTON_LABEL = localize('dialogModalCancelButtonLabel', 'Cancel'); - private _onOk: Emitter = new Emitter(); - public readonly onOk: Event = this._onOk.event; - private _onCancel: Emitter = new Emitter(); - public readonly onCancel: Event = this._onCancel.event; + public content: string | DialogTab[]; + public okButton: DialogButton = new DialogButton(Dialog.DONE_BUTTON_LABEL, true); + public cancelButton: DialogButton = new DialogButton(Dialog.CANCEL_BUTTON_LABEL, true); + public customButtons: DialogButton[]; constructor(public title: string, content?: string | DialogTab[]) { if (content) { @@ -52,4 +51,11 @@ export class DialogButton implements sqlops.window.modelviewdialog.Button { this.label = label; this.enabled = enabled; } + + /** + * Register an event that notifies the button that it has been clicked + */ + public registerClickEvent(clickEvent: Event): void { + clickEvent(() => this._onClick.fire()); + } } \ No newline at end of file diff --git a/src/sql/sqlops.proposed.d.ts b/src/sql/sqlops.proposed.d.ts index 64d778a744..13e93af70e 100644 --- a/src/sql/sqlops.proposed.d.ts +++ b/src/sql/sqlops.proposed.d.ts @@ -257,14 +257,14 @@ declare module 'sqlops' { content: string | DialogTab[], /** - * The caption of the OK button + * The ok button */ - okTitle: string; + okButton: Button; /** - * The caption of the Cancel button + * The cancel button */ - cancelTitle: string; + cancelButton: Button; /** * Any additional buttons that should be displayed @@ -285,16 +285,6 @@ declare module 'sqlops' { * Updates the dialog on screen to reflect changes to the buttons or content */ updateContent(): void; - - /** - * Raised when dialog's ok button is pressed - */ - readonly onOk: vscode.Event; - - /** - * Raised when dialog is canceled - */ - readonly onCancel: vscode.Event; } export interface DialogTab { diff --git a/src/sql/workbench/api/common/sqlExtHostTypes.ts b/src/sql/workbench/api/common/sqlExtHostTypes.ts index 6167463fc8..9fc4ab3bbe 100644 --- a/src/sql/workbench/api/common/sqlExtHostTypes.ts +++ b/src/sql/workbench/api/common/sqlExtHostTypes.ts @@ -94,3 +94,21 @@ export interface IComponentEventArgs { eventType: ComponentEventType; args: any; } + +export interface IModelViewDialogDetails { + title: string; + content: string | number[]; + okButton: number; + cancelButton: number; + customButtons: number[]; +} + +export interface IModelViewTabDetails { + title: string; + content: string; +} + +export interface IModelViewButtonDetails { + label: string; + enabled: boolean; +} diff --git a/src/sql/workbench/api/node/extHostModelViewDialog.ts b/src/sql/workbench/api/node/extHostModelViewDialog.ts new file mode 100644 index 0000000000..552e7ecf9b --- /dev/null +++ b/src/sql/workbench/api/node/extHostModelViewDialog.ts @@ -0,0 +1,218 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { IMainContext } from 'vs/workbench/api/node/extHost.protocol'; +import Event, { Emitter } from 'vs/base/common/event'; +import { deepClone } from 'vs/base/common/objects'; +import * as nls from 'vs/nls'; + +import * as vscode from 'vscode'; +import * as sqlops from 'sqlops'; + +import { SqlMainContext, ExtHostModelViewDialogShape, MainThreadModelViewDialogShape } from 'sql/workbench/api/node/sqlExtHost.protocol'; +import { IItemConfig, ModelComponentTypes, IComponentShape } from 'sql/workbench/api/common/sqlExtHostTypes'; + +class DialogImpl implements sqlops.window.modelviewdialog.Dialog { + public title: string; + public content: string | sqlops.window.modelviewdialog.DialogTab[]; + public okButton: sqlops.window.modelviewdialog.Button; + public cancelButton: sqlops.window.modelviewdialog.Button; + public customButtons: sqlops.window.modelviewdialog.Button[]; + + constructor(private _extHostModelViewDialog: ExtHostModelViewDialog) { + this.okButton = this._extHostModelViewDialog.createButton(nls.localize('dialogOkLabel', 'Done')); + this.cancelButton = this._extHostModelViewDialog.createButton(nls.localize('dialogCancelLabel', 'Cancel')); + } + + public open(): void { + this._extHostModelViewDialog.open(this); + } + + public close(): void { + this._extHostModelViewDialog.close(this); + } + + public updateContent(): void { + this._extHostModelViewDialog.updateDialogContent(this); + } +} + +class TabImpl implements sqlops.window.modelviewdialog.DialogTab { + public title: string; + public content: string; + + constructor(private _extHostModelViewDialog: ExtHostModelViewDialog) { } + + public updateContent(): void { + this._extHostModelViewDialog.updateTabContent(this); + } +} + +class ButtonImpl implements sqlops.window.modelviewdialog.Button { + private _label: string; + private _enabled: boolean; + + private _onClick = new Emitter(); + public onClick = this._onClick.event; + + constructor(private _extHostModelViewDialog: ExtHostModelViewDialog) { + this._enabled = true; + } + + public get label(): string { + return this._label; + } + + public set label(label: string) { + this._label = label; + this._extHostModelViewDialog.updateButton(this); + } + + public get enabled(): boolean { + return this._enabled; + } + + public set enabled(enabled: boolean) { + this._enabled = enabled; + this._extHostModelViewDialog.updateButton(this); + } + + public getOnClickCallback(): () => void { + return () => this._onClick.fire(); + } +} + +export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape { + private static _currentHandle = 0; + + private readonly _proxy: MainThreadModelViewDialogShape; + + private readonly _dialogHandles = new Map(); + private readonly _tabHandles = new Map(); + private readonly _buttonHandles = new Map(); + + private readonly _onClickCallbacks = new Map void>(); + + constructor( + mainContext: IMainContext + ) { + this._proxy = mainContext.getProxy(SqlMainContext.MainThreadModelViewDialog); + } + + private static getNewHandle() { + let handle = ExtHostModelViewDialog._currentHandle; + ExtHostModelViewDialog._currentHandle += 1; + 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); + } + return handle; + } + + public $onButtonClick(handle: number): void { + this._onClickCallbacks.get(handle)(); + } + + public open(dialog: sqlops.window.modelviewdialog.Dialog): void { + let handle = this.getDialogHandle(dialog); + this.updateDialogContent(dialog); + this._proxy.$open(handle); + } + + public close(dialog: sqlops.window.modelviewdialog.Dialog): void { + let handle = this.getDialogHandle(dialog); + this._proxy.$close(handle); + } + + public updateDialogContent(dialog: sqlops.window.modelviewdialog.Dialog): void { + let handle = this.getDialogHandle(dialog); + let tabs = dialog.content; + if (tabs && typeof tabs !== 'string') { + tabs.forEach(tab => tab.updateContent()); + } + if (dialog.customButtons) { + dialog.customButtons.forEach(button => this.updateButton(button)); + } + this.updateButton(dialog.okButton); + 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 + }); + } + + public updateTabContent(tab: sqlops.window.modelviewdialog.DialogTab): void { + let handle = this.getTabHandle(tab); + this._proxy.$setTabDetails(handle, { + title: tab.title, + content: tab.content + }); + } + + public updateButton(button: sqlops.window.modelviewdialog.Button): void { + let handle = this.getButtonHandle(button); + this._proxy.$setButtonDetails(handle, { + label: button.label, + enabled: button.enabled + }); + } + + public registerOnClickCallback(button: sqlops.window.modelviewdialog.Button, callback: () => void) { + let handle = this.getButtonHandle(button); + this._onClickCallbacks.set(handle, callback); + } + + public createDialog(title: string): sqlops.window.modelviewdialog.Dialog { + let dialog = new DialogImpl(this); + dialog.title = title; + let handle = ExtHostModelViewDialog.getNewHandle(); + this._dialogHandles.set(dialog, handle); + return dialog; + } + + public createTab(title: string): sqlops.window.modelviewdialog.DialogTab { + let tab = new TabImpl(this); + tab.title = title; + let handle = ExtHostModelViewDialog.getNewHandle(); + this._tabHandles.set(tab, handle); + return tab; + } + + public createButton(label: string): sqlops.window.modelviewdialog.Button { + let button = new ButtonImpl(this); + button.label = label; + let handle = ExtHostModelViewDialog.getNewHandle(); + this._buttonHandles.set(button, handle); + this.registerOnClickCallback(button, button.getOnClickCallback()); + return button; + } +} \ No newline at end of file diff --git a/src/sql/workbench/api/node/mainThreadModelViewDialog.ts b/src/sql/workbench/api/node/mainThreadModelViewDialog.ts new file mode 100644 index 0000000000..7d3c7eba45 --- /dev/null +++ b/src/sql/workbench/api/node/mainThreadModelViewDialog.ts @@ -0,0 +1,131 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { MainThreadModelViewDialogShape, SqlMainContext, ExtHostModelViewDialogShape, SqlExtHostContext } from 'sql/workbench/api/node/sqlExtHost.protocol'; +import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; +import { Dialog, DialogTab, DialogButton } from 'sql/platform/dialog/dialogTypes'; +import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol'; +import { CustomDialogService } from 'sql/platform/dialog/customDialogService'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails } from 'sql/workbench/api/common/sqlExtHostTypes'; + +@extHostNamedCustomer(SqlMainContext.MainThreadModelViewDialog) +export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape { + private readonly _proxy: ExtHostModelViewDialogShape; + private readonly _dialogs = new Map(); + private readonly _tabs = new Map(); + private readonly _buttons = new Map(); + private _dialogService: CustomDialogService; + + constructor( + context: IExtHostContext, + @IInstantiationService instatiationService: IInstantiationService + ) { + this._proxy = context.getProxy(SqlExtHostContext.ExtHostModelViewDialog); + this._dialogService = new CustomDialogService(instatiationService); + } + + public dispose(): void { + throw new Error('Method not implemented.'); + } + + public $open(handle: number): Thenable { + let dialog = this.getDialog(handle); + this._dialogService.showDialog(dialog); + return Promise.resolve(); + } + + public $close(handle: number): Thenable { + let dialog = this.getDialog(handle); + dialog.close(); + return Promise.resolve(); + } + + public $setDialogDetails(handle: number, details: IModelViewDialogDetails): Thenable { + let dialog = this._dialogs.get(handle); + if (!dialog) { + dialog = new Dialog(details.title); + let okButton = this.getButton(details.okButton); + let cancelButton = this.getButton(details.cancelButton); + dialog.okButton = okButton; + dialog.cancelButton = cancelButton; + this._dialogs.set(handle, dialog); + } + + dialog.title = details.title; + if (details.content && typeof details.content !== 'string') { + dialog.content = details.content.map(tabHandle => this.getTab(tabHandle)); + } else { + dialog.content = details.content as string; + } + + if (details.customButtons) { + dialog.customButtons = details.customButtons.map(buttonHandle => this.getButton(buttonHandle)); + } + + dialog.updateContent(); + return Promise.resolve(); + } + + public $setTabDetails(handle: number, details: IModelViewTabDetails): Thenable { + let tab = this._tabs.get(handle); + if (!tab) { + tab = new DialogTab(details.title); + this._tabs.set(handle, tab); + } + + tab.title = details.title; + tab.content = details.content; + + tab.updateContent(); + return Promise.resolve(); + } + + public $setButtonDetails(handle: number, details: IModelViewButtonDetails): Thenable { + let button = this._buttons.get(handle); + if (!button) { + button = new DialogButton(details.label, details.enabled); + button.onClick(() => this.onButtonClick(handle)); + this._buttons.set(handle, button); + } else { + button.label = details.label; + button.enabled = details.enabled; + } + + 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; + } + + private getTab(handle: number): DialogTab { + let tab = this._tabs.get(handle); + if (!tab) { + throw new Error('No tab matching the given handle'); + } + + return tab; + } + + private getButton(handle: number): DialogButton { + let button = this._buttons.get(handle); + if (!button) { + throw new Error('No button matching the given handle'); + } + + return button; + } + + private onButtonClick(handle: number): void { + this._proxy.$onButtonClick(handle); + } +} \ No newline at end of file diff --git a/src/sql/workbench/api/node/sqlExtHost.api.impl.ts b/src/sql/workbench/api/node/sqlExtHost.api.impl.ts index 25f92d91e3..4f14c4bec9 100644 --- a/src/sql/workbench/api/node/sqlExtHost.api.impl.ts +++ b/src/sql/workbench/api/node/sqlExtHost.api.impl.ts @@ -32,6 +32,7 @@ import { ExtHostConnectionManagement } from 'sql/workbench/api/node/extHostConne import { ExtHostDashboard } from 'sql/workbench/api/node/extHostDashboard'; import { ExtHostObjectExplorer } from 'sql/workbench/api/node/extHostObjectExplorer'; import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; +import { ExtHostModelViewDialog } from 'sql/workbench/api/node/extHostModelViewDialog'; import { ExtHostQueryEditor } from 'sql/workbench/api/node/extHostQueryEditor'; export interface ISqlExtensionApiFactory { @@ -65,6 +66,7 @@ export function createApiFactory( const extHostWebviewWidgets = rpcProtocol.set(SqlExtHostContext.ExtHostDashboardWebviews, new ExtHostDashboardWebviews(rpcProtocol)); const extHostModelView = rpcProtocol.set(SqlExtHostContext.ExtHostModelView, new ExtHostModelView(rpcProtocol)); const extHostDashboard = rpcProtocol.set(SqlExtHostContext.ExtHostDashboard, new ExtHostDashboard(rpcProtocol)); + const extHostModelViewDialog = rpcProtocol.set(SqlExtHostContext.ExtHostModelViewDialog, new ExtHostModelViewDialog(rpcProtocol)); const extHostQueryEditor = rpcProtocol.set(SqlExtHostContext.ExtHostQueryEditor, new ExtHostQueryEditor(rpcProtocol)); @@ -283,10 +285,15 @@ export function createApiFactory( }; const modelViewDialog: typeof sqlops.window.modelviewdialog = { - // TODO mairvine 4/18/18: Implement the extension layer for custom dialogs - createDialog(title: string): sqlops.window.modelviewdialog.Dialog { return undefined; }, - createTab(title: string): sqlops.window.modelviewdialog.DialogTab { return undefined; }, - createButton(label: string): sqlops.window.modelviewdialog.Button { return undefined; } + createDialog(title: string): sqlops.window.modelviewdialog.Dialog { + return extHostModelViewDialog.createDialog(title); + }, + createTab(title: string): sqlops.window.modelviewdialog.DialogTab { + return extHostModelViewDialog.createTab(title); + }, + createButton(label: string): sqlops.window.modelviewdialog.Button { + return extHostModelViewDialog.createButton(label); + } }; const window: typeof sqlops.window = { diff --git a/src/sql/workbench/api/node/sqlExtHost.contribution.ts b/src/sql/workbench/api/node/sqlExtHost.contribution.ts index c3bd405990..8b3b656887 100644 --- a/src/sql/workbench/api/node/sqlExtHost.contribution.ts +++ b/src/sql/workbench/api/node/sqlExtHost.contribution.ts @@ -21,6 +21,7 @@ import 'sql/workbench/api/electron-browser/mainThreadDashboard'; import 'sql/workbench/api/node/mainThreadDashboardWebview'; import 'sql/workbench/api/node/mainThreadQueryEditor'; import 'sql/workbench/api/node/mainThreadModelView'; +import 'sql/workbench/api/node/mainThreadModelViewDialog'; import './mainThreadAccountManagement'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; diff --git a/src/sql/workbench/api/node/sqlExtHost.protocol.ts b/src/sql/workbench/api/node/sqlExtHost.protocol.ts index e43087e9b1..53f9c0372f 100644 --- a/src/sql/workbench/api/node/sqlExtHost.protocol.ts +++ b/src/sql/workbench/api/node/sqlExtHost.protocol.ts @@ -16,7 +16,7 @@ import * as sqlops from 'sqlops'; import * as vscode from 'vscode'; import { ITaskHandlerDescription } from 'sql/platform/tasks/common/tasks'; -import { IItemConfig, ModelComponentTypes, IComponentShape } from 'sql/workbench/api/common/sqlExtHostTypes'; +import { IItemConfig, ModelComponentTypes, IComponentShape, IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails } from 'sql/workbench/api/common/sqlExtHostTypes'; import Event, { Emitter } from 'vs/base/common/event'; export abstract class ExtHostAccountManagementShape { @@ -448,6 +448,7 @@ export const SqlMainContext = { MainThreadDashboardWebview: createMainId('MainThreadDashboardWebview'), MainThreadModelView: createMainId('MainThreadModelView'), MainThreadDashboard: createMainId('MainThreadDashboard'), + MainThreadModelViewDialog: createMainId('MainThreadModelViewDialog'), MainThreadQueryEditor: createMainId('MainThreadQueryEditor'), }; @@ -464,6 +465,7 @@ export const SqlExtHostContext = { ExtHostDashboardWebviews: createExtId('ExtHostDashboardWebviews'), ExtHostModelView: createExtId('ExtHostModelView'), ExtHostDashboard: createExtId('ExtHostDashboard'), + ExtHostModelViewDialog: createExtId('ExtHostModelViewDialog'), ExtHostQueryEditor: createExtId('ExtHostQueryEditor') }; @@ -543,10 +545,21 @@ export interface MainThreadObjectExplorerShape extends IDisposable { $findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable; } +export interface ExtHostModelViewDialogShape { + $onButtonClick(handle: number): void; +} + +export interface MainThreadModelViewDialogShape extends IDisposable { + $open(handle: number): Thenable; + $close(handle: number): Thenable; + $setDialogDetails(handle: number, details: IModelViewDialogDetails): Thenable; + $setTabDetails(handle: number, details: IModelViewTabDetails): Thenable; + $setButtonDetails(handle: number, details: IModelViewButtonDetails): Thenable; +} export interface ExtHostQueryEditorShape { } export interface MainThreadQueryEditorShape extends IDisposable { $connect(fileUri: string, connectionId: string): Thenable; $runQuery(fileUri: string): void; -} \ No newline at end of file +}