mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Clean up modal/options dialog disposable use (#9739)
* Fix duplicate options and clean up disposable use * Remove unneeded import * Undo options fix - separating out in different PR
This commit is contained in:
@@ -7,7 +7,7 @@ import { attachButtonStyler } from 'vs/platform/theme/common/styler';
|
|||||||
import { Color } from 'vs/base/common/color';
|
import { Color } from 'vs/base/common/color';
|
||||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||||
import { mixin } from 'vs/base/common/objects';
|
import { mixin } from 'vs/base/common/objects';
|
||||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||||
import * as DOM from 'vs/base/browser/dom';
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
@@ -83,6 +83,7 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
protected _useDefaultMessageBoxLocation: boolean = true;
|
protected _useDefaultMessageBoxLocation: boolean = true;
|
||||||
protected _messageElement: HTMLElement;
|
protected _messageElement: HTMLElement;
|
||||||
protected _modalOptions: IModalOptions;
|
protected _modalOptions: IModalOptions;
|
||||||
|
protected readonly disposableStore = this._register(new DisposableStore());
|
||||||
private _detailsButtonContainer: HTMLElement;
|
private _detailsButtonContainer: HTMLElement;
|
||||||
private _messageIcon: HTMLElement;
|
private _messageIcon: HTMLElement;
|
||||||
private _messageSeverity: HTMLElement;
|
private _messageSeverity: HTMLElement;
|
||||||
@@ -117,10 +118,6 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
private _leftFooter: HTMLElement;
|
private _leftFooter: HTMLElement;
|
||||||
private _rightFooter: HTMLElement;
|
private _rightFooter: HTMLElement;
|
||||||
private _footerButtons: Button[];
|
private _footerButtons: Button[];
|
||||||
|
|
||||||
private _keydownListener: IDisposable;
|
|
||||||
private _resizeListener: IDisposable;
|
|
||||||
|
|
||||||
private _backButton: Button;
|
private _backButton: Button;
|
||||||
|
|
||||||
private _modalShowingContext: IContextKey<Array<string>>;
|
private _modalShowingContext: IContextKey<Array<string>>;
|
||||||
@@ -359,7 +356,7 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
DOM.append(this.layoutService.container, this._bodyContainer);
|
DOM.append(this.layoutService.container, this._bodyContainer);
|
||||||
this.setInitialFocusedElement();
|
this.setInitialFocusedElement();
|
||||||
|
|
||||||
this._keydownListener = DOM.addDisposableListener(document, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
|
this.disposableStore.add(DOM.addDisposableListener(document, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
|
||||||
let context = this._modalShowingContext.get()!;
|
let context = this._modalShowingContext.get()!;
|
||||||
if (context[context.length - 1] === this._staticKey) {
|
if (context[context.length - 1] === this._staticKey) {
|
||||||
let event = new StandardKeyboardEvent(e);
|
let event = new StandardKeyboardEvent(e);
|
||||||
@@ -373,10 +370,10 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
this.handleForwardTab(e);
|
this.handleForwardTab(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
this._resizeListener = DOM.addDisposableListener(window, DOM.EventType.RESIZE, (e: Event) => {
|
this.disposableStore.add(DOM.addDisposableListener(window, DOM.EventType.RESIZE, (e: Event) => {
|
||||||
this.layout(DOM.getTotalHeight(this._modalBodySection));
|
this.layout(DOM.getTotalHeight(this._modalBodySection));
|
||||||
});
|
}));
|
||||||
|
|
||||||
this.layout(DOM.getTotalHeight(this._modalBodySection));
|
this.layout(DOM.getTotalHeight(this._modalBodySection));
|
||||||
this._telemetryService.createActionEvent(TelemetryKeys.TelemetryView.Shell, TelemetryKeys.ModalDialogOpened)
|
this._telemetryService.createActionEvent(TelemetryKeys.TelemetryView.Shell, TelemetryKeys.ModalDialogOpened)
|
||||||
@@ -395,8 +392,7 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
protected hide() {
|
protected hide() {
|
||||||
this._modalShowingContext.get()!.pop();
|
this._modalShowingContext.get()!.pop();
|
||||||
this._bodyContainer.remove();
|
this._bodyContainer.remove();
|
||||||
this._keydownListener.dispose();
|
this.disposableStore.clear();
|
||||||
this._resizeListener.dispose();
|
|
||||||
this._telemetryService.createActionEvent(TelemetryKeys.TelemetryView.Shell, TelemetryKeys.ModalDialogClosed)
|
this._telemetryService.createActionEvent(TelemetryKeys.TelemetryView.Shell, TelemetryKeys.ModalDialogClosed)
|
||||||
.withAdditionalProperties({ name: this._name })
|
.withAdditionalProperties({ name: this._name })
|
||||||
.send();
|
.send();
|
||||||
@@ -416,7 +412,7 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
*/
|
*/
|
||||||
protected addFooterButton(label: string, onSelect: () => void, orientation: 'left' | 'right' = 'right'): Button {
|
protected addFooterButton(label: string, onSelect: () => void, orientation: 'left' | 'right' = 'right'): Button {
|
||||||
let footerButton = DOM.$('.footer-button');
|
let footerButton = DOM.$('.footer-button');
|
||||||
let button = new Button(footerButton);
|
let button = this._register(new Button(footerButton));
|
||||||
button.label = label;
|
button.label = label;
|
||||||
button.onDidClick(() => onSelect()); // @todo this should be registered to dispose but that brakes some dialogs
|
button.onDidClick(() => onSelect()); // @todo this should be registered to dispose but that brakes some dialogs
|
||||||
if (orientation === 'left') {
|
if (orientation === 'left') {
|
||||||
@@ -618,7 +614,6 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
this._keydownListener.dispose();
|
|
||||||
this._footerButtons = [];
|
this._footerButtons = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,8 @@ export class OptionsDialog extends Modal {
|
|||||||
for (let i = 0; i < options.length; i++) {
|
for (let i = 0; i < options.length; i++) {
|
||||||
let option: azdata.ServiceOption = options[i];
|
let option: azdata.ServiceOption = options[i];
|
||||||
let rowContainer = DialogHelper.appendRow(container, option.displayName, 'optionsDialog-label', 'optionsDialog-input');
|
let rowContainer = DialogHelper.appendRow(container, option.displayName, 'optionsDialog-label', 'optionsDialog-input');
|
||||||
OptionsDialogHelper.createOptionElement(option, rowContainer, this._optionValues, this._optionElements, this._contextViewService, (name) => this.onOptionLinkClicked(name));
|
const optionElement = OptionsDialogHelper.createOptionElement(option, rowContainer, this._optionValues, this._optionElements, this._contextViewService, (name) => this.onOptionLinkClicked(name));
|
||||||
|
this.disposableStore.add(optionElement.optionWidget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,12 +176,12 @@ export class OptionsDialog extends Modal {
|
|||||||
switch (option.valueType) {
|
switch (option.valueType) {
|
||||||
case ServiceOptionType.category:
|
case ServiceOptionType.category:
|
||||||
case ServiceOptionType.boolean:
|
case ServiceOptionType.boolean:
|
||||||
this._register(styler.attachSelectBoxStyler(<SelectBox>widget, this._themeService));
|
this.disposableStore.add(styler.attachSelectBoxStyler(<SelectBox>widget, this._themeService));
|
||||||
break;
|
break;
|
||||||
case ServiceOptionType.string:
|
case ServiceOptionType.string:
|
||||||
case ServiceOptionType.password:
|
case ServiceOptionType.password:
|
||||||
case ServiceOptionType.number:
|
case ServiceOptionType.number:
|
||||||
this._register(styler.attachInputBoxStyler(<InputBox>widget, this._themeService));
|
this.disposableStore.add(styler.attachInputBoxStyler(<InputBox>widget, this._themeService));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,8 +225,8 @@ export class OptionsDialog extends Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public close() {
|
public close() {
|
||||||
this.dispose();
|
|
||||||
this.hide();
|
this.hide();
|
||||||
|
this._optionElements = {};
|
||||||
this._onCloseEvent.fire();
|
this._onCloseEvent.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,10 +261,6 @@ export class OptionsDialog extends Modal {
|
|||||||
|
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
for (let optionName in this._optionElements) {
|
this._optionElements = {};
|
||||||
let widget: Widget = this._optionElements[optionName].optionWidget;
|
|
||||||
widget.dispose();
|
|
||||||
delete this._optionElements[optionName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export interface IOptionElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createOptionElement(option: azdata.ServiceOption, rowContainer: HTMLElement, options: { [name: string]: any },
|
export function createOptionElement(option: azdata.ServiceOption, rowContainer: HTMLElement, options: { [name: string]: any },
|
||||||
optionsMap: { [optionName: string]: IOptionElement }, contextViewService: IContextViewService, onFocus: (name) => void): void {
|
optionsMap: { [optionName: string]: IOptionElement }, contextViewService: IContextViewService, onFocus: (name) => void): IOptionElement {
|
||||||
let possibleInputs: string[] = [];
|
let possibleInputs: string[] = [];
|
||||||
let optionValue = getOptionValueAndCategoryValues(option, options, possibleInputs);
|
let optionValue = getOptionValueAndCategoryValues(option, options, possibleInputs);
|
||||||
let optionWidget: any;
|
let optionWidget: any;
|
||||||
@@ -63,8 +63,10 @@ export function createOptionElement(option: azdata.ServiceOption, rowContainer:
|
|||||||
}
|
}
|
||||||
inputElement = findElement(rowContainer, 'input');
|
inputElement = findElement(rowContainer, 'input');
|
||||||
}
|
}
|
||||||
optionsMap[option.name] = { optionWidget: optionWidget, option: option, optionValue: optionValue };
|
const optionElement = { optionWidget: optionWidget, option: option, optionValue: optionValue };
|
||||||
|
optionsMap[option.name] = optionElement;
|
||||||
inputElement.onfocus = () => onFocus(option.name);
|
inputElement.onfocus = () => onFocus(option.name);
|
||||||
|
return optionElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOptionValueAndCategoryValues(option: azdata.ServiceOption, options: { [optionName: string]: any }, possibleInputs: string[]): any {
|
export function getOptionValueAndCategoryValues(option: azdata.ServiceOption, options: { [optionName: string]: any }, possibleInputs: string[]): any {
|
||||||
|
|||||||
Reference in New Issue
Block a user