diff --git a/extensions/dacpac/src/wizard/pages/dacFxSummaryPage.ts b/extensions/dacpac/src/wizard/pages/dacFxSummaryPage.ts index 0194e53e83..1cf20735e5 100644 --- a/extensions/dacpac/src/wizard/pages/dacFxSummaryPage.ts +++ b/extensions/dacpac/src/wizard/pages/dacFxSummaryPage.ts @@ -54,6 +54,9 @@ export class DacFxSummaryPage extends BasePage { if (this.model.upgradeExisting && this.instance.selectedOperation === Operation.deploy) { this.instance.wizard.generateScriptButton.hidden = false; } + + this.instance.wizard.doneButton.focused = true; + return true; } diff --git a/src/sql/azdata.d.ts b/src/sql/azdata.d.ts index ecc368a0a4..460036cb67 100644 --- a/src/sql/azdata.d.ts +++ b/src/sql/azdata.d.ts @@ -3624,6 +3624,11 @@ declare module 'azdata' { */ hidden: boolean; + /** + * Whether the button is focused + */ + focused?: boolean; + /** * Raised when the button is clicked */ diff --git a/src/sql/platform/dialog/browser/wizardModal.ts b/src/sql/platform/dialog/browser/wizardModal.ts index e0476341e0..8658fdb7bb 100644 --- a/src/sql/platform/dialog/browser/wizardModal.ts +++ b/src/sql/platform/dialog/browser/wizardModal.ts @@ -119,6 +119,11 @@ export class WizardModal extends Modal { buttonElement.label = dialogButton.label; buttonElement.enabled = requirePageValid ? dialogButton.enabled && this._wizard.pages[this._wizard.currentPage].valid : dialogButton.enabled; dialogButton.hidden ? buttonElement.element.parentElement.classList.add('dialogModal-hidden') : buttonElement.element.parentElement.classList.remove('dialogModal-hidden'); + + if (dialogButton.focused) { + buttonElement.focus(); + } + this.setButtonsForPage(this._wizard.currentPage); } diff --git a/src/sql/platform/dialog/common/dialogTypes.ts b/src/sql/platform/dialog/common/dialogTypes.ts index 9236b3df4b..f11709c86a 100644 --- a/src/sql/platform/dialog/common/dialogTypes.ts +++ b/src/sql/platform/dialog/common/dialogTypes.ts @@ -83,6 +83,7 @@ export class DialogButton implements azdata.window.Button { private _label: string; private _enabled: boolean; private _hidden: boolean; + private _focused: boolean; private _onClick: Emitter = new Emitter(); public readonly onClick: Event = this._onClick.event; private _onUpdate: Emitter = new Emitter(); @@ -121,6 +122,15 @@ export class DialogButton implements azdata.window.Button { this._onUpdate.fire(); } + public get focused(): boolean { + return this._focused; + } + + public set focused(focused: boolean) { + this._focused = focused; + this._onUpdate.fire(); + } + /** * Register an event that notifies the button that it has been clicked */ @@ -255,4 +265,4 @@ export class Wizard { this._message = value; this._onMessageChange.fire(this._message); } -} \ No newline at end of file +} diff --git a/src/sql/workbench/api/common/extHostModelViewDialog.ts b/src/sql/workbench/api/common/extHostModelViewDialog.ts index 434566e059..27240ef8f0 100644 --- a/src/sql/workbench/api/common/extHostModelViewDialog.ts +++ b/src/sql/workbench/api/common/extHostModelViewDialog.ts @@ -207,6 +207,7 @@ class ButtonImpl implements azdata.window.Button { private _label: string; private _enabled: boolean; private _hidden: boolean; + private _focused: boolean; private _onClick = new Emitter(); public onClick = this._onClick.event; @@ -243,6 +244,23 @@ class ButtonImpl implements azdata.window.Button { this._extHostModelViewDialog.updateButton(this); } + public get focused(): boolean { + return this._focused; + } + + /** + * Focuses the button when set to "true", then the internal value is immediately reset to 'undefined'. + * + * @remarks + * Because communication between ADS and extensions is unidirectional, a focus change by the user is not + * communicated to the extension. The internal value is reset to avoid inconsistent models of where focus is. + */ + public set focused(focused: boolean) { + this._focused = focused; + this._extHostModelViewDialog.updateButton(this); + this._focused = undefined; + } + public getOnClickCallback(): () => void { return () => this._onClick.fire(); } @@ -568,7 +586,8 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape { this._proxy.$setButtonDetails(handle, { label: button.label, enabled: button.enabled, - hidden: button.hidden + hidden: button.hidden, + focused: button.focused }); } diff --git a/src/sql/workbench/api/common/sqlExtHostTypes.ts b/src/sql/workbench/api/common/sqlExtHostTypes.ts index 99f3eef8e1..45bdabfd4c 100644 --- a/src/sql/workbench/api/common/sqlExtHostTypes.ts +++ b/src/sql/workbench/api/common/sqlExtHostTypes.ts @@ -251,6 +251,7 @@ export interface IModelViewButtonDetails { label: string; enabled: boolean; hidden: boolean; + focused?: boolean; } export interface IModelViewWizardPageDetails { diff --git a/src/sql/workbench/api/electron-browser/mainThreadModelViewDialog.ts b/src/sql/workbench/api/electron-browser/mainThreadModelViewDialog.ts index 7c7218b8e3..68cdfef763 100644 --- a/src/sql/workbench/api/electron-browser/mainThreadModelViewDialog.ts +++ b/src/sql/workbench/api/electron-browser/mainThreadModelViewDialog.ts @@ -133,6 +133,7 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape button.label = details.label; button.enabled = details.enabled; button.hidden = details.hidden; + button.focused = details.focused; } return Promise.resolve();