mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-14 17:22:20 -05:00
Expose custom dialog extension APIs (#1206)
This commit is contained in:
218
src/sql/workbench/api/node/extHostModelViewDialog.ts
Normal file
218
src/sql/workbench/api/node/extHostModelViewDialog.ts
Normal file
@@ -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<void>();
|
||||
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<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 _onClickCallbacks = new Map<number, () => 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;
|
||||
}
|
||||
}
|
||||
131
src/sql/workbench/api/node/mainThreadModelViewDialog.ts
Normal file
131
src/sql/workbench/api/node/mainThreadModelViewDialog.ts
Normal file
@@ -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<number, Dialog>();
|
||||
private readonly _tabs = new Map<number, DialogTab>();
|
||||
private readonly _buttons = new Map<number, DialogButton>();
|
||||
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<void> {
|
||||
let dialog = this.getDialog(handle);
|
||||
this._dialogService.showDialog(dialog);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $close(handle: number): Thenable<void> {
|
||||
let dialog = this.getDialog(handle);
|
||||
dialog.close();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $setDialogDetails(handle: number, details: IModelViewDialogDetails): Thenable<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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<MainThreadDashboardWebviewShape>('MainThreadDashboardWebview'),
|
||||
MainThreadModelView: createMainId<MainThreadModelViewShape>('MainThreadModelView'),
|
||||
MainThreadDashboard: createMainId<MainThreadDashboardShape>('MainThreadDashboard'),
|
||||
MainThreadModelViewDialog: createMainId<MainThreadModelViewDialogShape>('MainThreadModelViewDialog'),
|
||||
MainThreadQueryEditor: createMainId<MainThreadQueryEditorShape>('MainThreadQueryEditor'),
|
||||
};
|
||||
|
||||
@@ -464,6 +465,7 @@ export const SqlExtHostContext = {
|
||||
ExtHostDashboardWebviews: createExtId<ExtHostDashboardWebviewsShape>('ExtHostDashboardWebviews'),
|
||||
ExtHostModelView: createExtId<ExtHostModelViewShape>('ExtHostModelView'),
|
||||
ExtHostDashboard: createExtId<ExtHostDashboardShape>('ExtHostDashboard'),
|
||||
ExtHostModelViewDialog: createExtId<ExtHostModelViewDialogShape>('ExtHostModelViewDialog'),
|
||||
ExtHostQueryEditor: createExtId<ExtHostQueryEditorShape>('ExtHostQueryEditor')
|
||||
};
|
||||
|
||||
@@ -543,10 +545,21 @@ export interface MainThreadObjectExplorerShape extends IDisposable {
|
||||
$findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]>;
|
||||
}
|
||||
|
||||
export interface ExtHostModelViewDialogShape {
|
||||
$onButtonClick(handle: number): void;
|
||||
}
|
||||
|
||||
export interface MainThreadModelViewDialogShape extends IDisposable {
|
||||
$open(handle: number): Thenable<void>;
|
||||
$close(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>;
|
||||
}
|
||||
export interface ExtHostQueryEditorShape {
|
||||
}
|
||||
|
||||
export interface MainThreadQueryEditorShape extends IDisposable {
|
||||
$connect(fileUri: string, connectionId: string): Thenable<void>;
|
||||
$runQuery(fileUri: string): void;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user