Properly save and restore dynamic tab state (#6185)

* WIP

* WIP 2

* WIP 3

* Rework state capture implementation

* Break loop after setting
This commit is contained in:
Karl Burtram
2019-06-27 16:14:28 -07:00
committed by GitHub
parent f5d647f05c
commit 4ef25ecf37
4 changed files with 57 additions and 9 deletions

View File

@@ -22,7 +22,7 @@ const PREVIOUS_LABEL = nls.localize('dialogPreviousLabel', 'Previous');
class ModelViewPanelImpl implements azdata.window.ModelViewPanel { class ModelViewPanelImpl implements azdata.window.ModelViewPanel {
private _modelView: azdata.ModelView; private _modelView: azdata.ModelView;
private _handle: number; private static _handle: number;
protected _modelViewId: string; protected _modelViewId: string;
protected _valid: boolean = true; protected _valid: boolean = true;
protected _onValidityChanged: vscode.Event<boolean>; protected _onValidityChanged: vscode.Event<boolean>;
@@ -37,7 +37,7 @@ class ModelViewPanelImpl implements azdata.window.ModelViewPanel {
public registerContent(handler: (view: azdata.ModelView) => Thenable<void>): void { public registerContent(handler: (view: azdata.ModelView) => Thenable<void>): void {
if (!this._modelViewId) { if (!this._modelViewId) {
let viewId = this._viewType + this._handle; let viewId = this._viewType + ModelViewPanelImpl._handle;
this.setModelViewId(viewId); this.setModelViewId(viewId);
this._extHostModelView.$registerProvider(viewId, modelView => { this._extHostModelView.$registerProvider(viewId, modelView => {
this._modelView = modelView; this._modelView = modelView;
@@ -47,7 +47,7 @@ class ModelViewPanelImpl implements azdata.window.ModelViewPanel {
} }
public set handle(value: number) { public set handle(value: number) {
this._handle = value; ModelViewPanelImpl._handle = value;
} }
public setModelViewId(value: string) { public setModelViewId(value: string) {

View File

@@ -240,13 +240,20 @@ export class QueryResultsView extends Disposable {
} }
// restore query model view tabs // restore query model view tabs
this.dynamicModelViewTabs.forEach(tab => {
if (this._panelView.contains(tab)) {
this._panelView.removeTab(tab.identifier);
}
});
this.dynamicModelViewTabs = [];
this.input.state.visibleTabs.forEach(tabId => { this.input.state.visibleTabs.forEach(tabId => {
if (tabId.startsWith('querymodelview;')) { if (tabId.startsWith('querymodelview;')) {
// tab id format is 'tab type;title;model view id' // tab id format is 'tab type;title;model view id'
let parts = tabId.split(';'); let parts = tabId.split(';');
if (parts.length === 3) { if (parts.length === 3) {
let tab = this._register(new QueryModelViewTab(parts[1], this.instantiationService)); let tab = this._register(new QueryModelViewTab(parts[1], this.instantiationService));
tab.view._componentId = parts[2]; tab.view.componentId = parts[2];
this.dynamicModelViewTabs.push(tab); this.dynamicModelViewTabs.push(tab);
if (!this._panelView.contains(tab)) { if (!this._panelView.contains(tab)) {
this._panelView.pushTab(tab, undefined, true); this._panelView.pushTab(tab, undefined, true);
@@ -275,12 +282,16 @@ export class QueryResultsView extends Disposable {
this.runnerDisposables = []; this.runnerDisposables = [];
[this.resultsTab, this.messagesTab, this.qpTab, this.topOperationsTab, this.chartTab].forEach(t => t.clear()); [this.resultsTab, this.messagesTab, this.qpTab, this.topOperationsTab, this.chartTab].forEach(t => t.clear());
this.dynamicModelViewTabs.forEach(t => t.clear());
this.resultsTab.view.state = this.input.state.gridPanelState; this.resultsTab.view.state = this.input.state.gridPanelState;
this.messagesTab.view.state = this.input.state.messagePanelState; this.messagesTab.view.state = this.input.state.messagePanelState;
this.qpTab.view.state = this.input.state.queryPlanState; this.qpTab.view.state = this.input.state.queryPlanState;
this.topOperationsTab.view.state = this.input.state.topOperationsState; this.topOperationsTab.view.state = this.input.state.topOperationsState;
this.chartTab.view.state = this.input.state.chartState; this.chartTab.view.state = this.input.state.chartState;
this.dynamicModelViewTabs.forEach((dynamicTab: QueryModelViewTab) => {
dynamicTab.captureState(this.input.state.dynamicModelViewTabsState);
});
let info = this.queryModelService._getQueryInfo(input.uri); let info = this.queryModelService._getQueryInfo(input.uri);
if (info) { if (info) {
@@ -306,6 +317,7 @@ export class QueryResultsView extends Disposable {
this.qpTab.clear(); this.qpTab.clear();
this.topOperationsTab.clear(); this.topOperationsTab.clear();
this.chartTab.clear(); this.chartTab.clear();
this.dynamicModelViewTabs.forEach(t => t.clear());
} }
public get input(): QueryResultsInput { public get input(): QueryResultsInput {
@@ -388,12 +400,14 @@ export class QueryResultsView extends Disposable {
public registerQueryModelViewTab(title: string, componentId: string): void { public registerQueryModelViewTab(title: string, componentId: string): void {
let tab = this._register(new QueryModelViewTab(title, this.instantiationService)); let tab = this._register(new QueryModelViewTab(title, this.instantiationService));
tab.view._componentId = componentId; tab.view.componentId = componentId;
this.dynamicModelViewTabs.push(tab); this.dynamicModelViewTabs.push(tab);
this.input.state.visibleTabs.add('querymodelview;' + title + ';' + componentId); this.input.state.visibleTabs.add('querymodelview;' + title + ';' + componentId);
if (!this._panelView.contains(tab)) { if (!this._panelView.contains(tab)) {
this._panelView.pushTab(tab, undefined, true); this._panelView.pushTab(tab, undefined, true);
} }
tab.putState(this.input.state.dynamicModelViewTabsState);
} }
} }

View File

@@ -12,6 +12,7 @@ import { MessagePanelState } from 'sql/workbench/parts/query/browser/messagePane
import { QueryPlanState } from 'sql/workbench/parts/queryPlan/electron-browser/queryPlan'; import { QueryPlanState } from 'sql/workbench/parts/queryPlan/electron-browser/queryPlan';
import { ChartState } from 'sql/workbench/parts/charts/browser/chartView'; import { ChartState } from 'sql/workbench/parts/charts/browser/chartView';
import { TopOperationsState } from 'sql/workbench/parts/queryPlan/browser/topOperations'; import { TopOperationsState } from 'sql/workbench/parts/queryPlan/browser/topOperations';
import { QueryModelViewState, QueryModelViewTab } from 'sql/workbench/parts/query/modelViewTab/queryModelViewTab';
export class ResultsViewState { export class ResultsViewState {
public gridPanelState: GridPanelState = new GridPanelState(); public gridPanelState: GridPanelState = new GridPanelState();
@@ -19,6 +20,8 @@ export class ResultsViewState {
public chartState: ChartState = new ChartState(); public chartState: ChartState = new ChartState();
public queryPlanState: QueryPlanState = new QueryPlanState(); public queryPlanState: QueryPlanState = new QueryPlanState();
public topOperationsState = new TopOperationsState(); public topOperationsState = new TopOperationsState();
public dynamicModelViewTabsState: Map<string, QueryModelViewState> = new Map<string, QueryModelViewState>();
public activeTab: string; public activeTab: string;
public visibleTabs: Set<string> = new Set<string>(); public visibleTabs: Set<string> = new Set<string>();
@@ -27,6 +30,10 @@ export class ResultsViewState {
this.messagePanelState.dispose(); this.messagePanelState.dispose();
this.chartState.dispose(); this.chartState.dispose();
this.queryPlanState.dispose(); this.queryPlanState.dispose();
this.dynamicModelViewTabsState.forEach((state: QueryModelViewState, identifier: string) => {
state.dispose();
});
this.dynamicModelViewTabsState.clear();
} }
} }

View File

@@ -9,6 +9,7 @@ import { IPanelView, IPanelTab } from 'sql/base/browser/ui/panel/panel';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { bootstrapAngular } from 'sql/platform/bootstrap/node/bootstrapService'; import { bootstrapAngular } from 'sql/platform/bootstrap/node/bootstrapService';
import { QueryModelViewTabModule } from 'sql/workbench/parts/query/modelViewTab/queryModelViewTab.module'; import { QueryModelViewTabModule } from 'sql/workbench/parts/query/modelViewTab/queryModelViewTab.module';
import { ResultsViewState } from 'sql/workbench/parts/query/common/queryResultsInput';
export class QueryModelViewTab implements IPanelTab { export class QueryModelViewTab implements IPanelTab {
public identifier = 'QueryModelViewTab_'; public identifier = 'QueryModelViewTab_';
@@ -19,6 +20,20 @@ export class QueryModelViewTab implements IPanelTab {
this.view = instantiationService.createInstance(QueryModelViewTabView); this.view = instantiationService.createInstance(QueryModelViewTabView);
} }
public putState(dynamicModelViewTabsState: Map<string, QueryModelViewState>): void {
dynamicModelViewTabsState.set(this.view.componentId, this.view.state);
}
public captureState(dynamicModelViewTabsState: Map<string, QueryModelViewState>): void {
for (let i = 0; i < dynamicModelViewTabsState.keys.length; ++i) {
let currentIdentifier = dynamicModelViewTabsState[dynamicModelViewTabsState.keys[i]];
if (currentIdentifier === this.view.componentId) {
this.view.state = dynamicModelViewTabsState[dynamicModelViewTabsState.keys[i]];
break;
}
}
}
public dispose() { public dispose() {
dispose(this.view); dispose(this.view);
} }
@@ -28,9 +43,14 @@ export class QueryModelViewTab implements IPanelTab {
} }
} }
export class QueryModelViewTabView implements IPanelView { export class QueryModelViewState {
public componentId: string;
public dispose() {
}
}
public _componentId: string; export class QueryModelViewTabView implements IPanelView {
public state: QueryModelViewState = new QueryModelViewState();
constructor( constructor(
@IInstantiationService private _instantiationService: IInstantiationService) { @IInstantiationService private _instantiationService: IInstantiationService) {
@@ -40,7 +60,7 @@ export class QueryModelViewTabView implements IPanelView {
this.bootstrapAngular(container); this.bootstrapAngular(container);
} }
dispose() { public dispose() {
} }
public clear() { public clear() {
@@ -50,7 +70,14 @@ export class QueryModelViewTabView implements IPanelView {
} }
public focus(): void { public focus(): void {
}
public get componentId(): string {
return this.state.componentId;
}
public set componentId(value: string) {
this.state.componentId = value;
} }
/** /**
@@ -61,7 +88,7 @@ export class QueryModelViewTabView implements IPanelView {
QueryModelViewTabModule, QueryModelViewTabModule,
container, container,
'querytab-modelview-container', 'querytab-modelview-container',
{ modelViewId: this._componentId }); { modelViewId: this.state.componentId });
return uniqueSelector; return uniqueSelector;
} }
} }