Fix query files not being editable (#5731)

* Initial attempt at fix

* Use two separate containers and just swap between those
This commit is contained in:
Charles Gagnon
2019-05-29 14:21:06 -07:00
committed by GitHub
parent 4b1088edbc
commit 9fc634dfe0

View File

@@ -13,6 +13,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor'; import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
@@ -31,7 +32,8 @@ import { QueryResultsEditor } from 'sql/workbench/parts/query/browser/queryResul
import * as queryContext from 'sql/workbench/parts/query/common/queryContext'; import * as queryContext from 'sql/workbench/parts/query/common/queryContext';
import { Taskbar, ITaskbarContent } from 'sql/base/browser/ui/taskbar/taskbar'; import { Taskbar, ITaskbarContent } from 'sql/base/browser/ui/taskbar/taskbar';
import * as actions from 'sql/workbench/parts/query/browser/queryActions'; import * as actions from 'sql/workbench/parts/query/browser/queryActions';
import { IRange } from 'vs/editor/common/core/range'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
/** /**
* Editor that hosts 2 sub-editors: A TextResourceEditor for SQL file editing, and a QueryResultsEditor * Editor that hosts 2 sub-editors: A TextResourceEditor for SQL file editing, and a QueryResultsEditor
@@ -46,9 +48,13 @@ export class QueryEditor extends BaseEditor {
private resultsEditor: QueryResultsEditor; private resultsEditor: QueryResultsEditor;
private resultsEditorContainer: HTMLElement; private resultsEditorContainer: HTMLElement;
// could be untitled or resource editor
private textEditor: TextResourceEditor; private textResourceEditor: TextResourceEditor;
private textEditorContainer: HTMLElement; private textFileEditor: TextFileEditor;
private currentTextEditor: BaseTextEditor;
private textResourceEditorContainer: HTMLElement;
private textFileEditorContainer: HTMLElement;
private taskbar: Taskbar; private taskbar: Taskbar;
private splitview: SplitView; private splitview: SplitView;
@@ -103,13 +109,21 @@ export class QueryEditor extends BaseEditor {
this.splitview = this._register(new SplitView(splitviewContainer, { orientation: Orientation.VERTICAL })); this.splitview = this._register(new SplitView(splitviewContainer, { orientation: Orientation.VERTICAL }));
this._register(this.splitview.onDidSashReset(() => this.splitview.distributeViewSizes())); this._register(this.splitview.onDidSashReset(() => this.splitview.distributeViewSizes()));
this.textEditorContainer = DOM.$('.text-editor-container'); // We create two separate editors - one for Untitled Documents (ad-hoc queries) and another for queries from
this.textEditor = this._register(this.instantiationService.createInstance(TextResourceEditor)); // files. This is necessary because TextResourceEditor by default makes all non-Untitled inputs to be
this.textEditor.create(this.textEditorContainer); // read-only so we need to use a TextFileEditor for files in order to edit them.
this.textResourceEditor = this._register(this.instantiationService.createInstance(TextResourceEditor));
this.textFileEditor = this._register(this.instantiationService.createInstance(TextFileEditor));
this.textResourceEditorContainer = DOM.$('.text-resource-editor-container');
this.textResourceEditor.create(this.textResourceEditorContainer);
this.textFileEditorContainer = DOM.$('.text-file-editor-container');
this.textFileEditor.create(this.textFileEditorContainer);
this.currentTextEditor = this.textResourceEditor;
this.splitview.addView({ this.splitview.addView({
element: this.textEditorContainer, element: this.textResourceEditorContainer,
layout: size => this.textEditor.layout(new DOM.Dimension(this.dimension.width, size)), layout: size => this.currentTextEditor.layout(new DOM.Dimension(this.dimension.width, size)),
minimumSize: 0, minimumSize: 0,
maximumSize: Number.POSITIVE_INFINITY, maximumSize: Number.POSITIVE_INFINITY,
onDidChange: Event.None onDidChange: Event.None
@@ -228,23 +242,42 @@ export class QueryEditor extends BaseEditor {
this.taskbar.setContent(content); this.taskbar.setContent(content);
} }
public setInput(newInput: QueryInput, options: EditorOptions, token: CancellationToken): Promise<void> { public async setInput(newInput: QueryInput, options: EditorOptions, token: CancellationToken): Promise<void> {
const oldInput = this.input; const oldInput = this.input;
if (newInput.matches(oldInput)) { if (newInput.matches(oldInput)) {
return Promise.resolve(); return Promise.resolve();
} }
return Promise.all([ if (oldInput) {
this.currentTextEditor.clearInput();
}
// If we're switching editor types switch out the views
const newTextEditor = newInput.sql instanceof FileEditorInput ? this.textFileEditor : this.textResourceEditor;
if (newTextEditor !== this.currentTextEditor) {
this.currentTextEditor = newTextEditor;
this.splitview.removeView(0, Sizing.Distribute);
this.splitview.addView({
element: this.currentTextEditor.getContainer(),
layout: size => this.currentTextEditor.layout(new DOM.Dimension(this.dimension.width, size)),
minimumSize: 0,
maximumSize: Number.POSITIVE_INFINITY,
onDidChange: Event.None
}, Sizing.Distribute, 0);
}
await Promise.all([
super.setInput(newInput, options, token), super.setInput(newInput, options, token),
this.textEditor.setInput(newInput.sql, options, token), this.currentTextEditor.setInput(newInput.sql, options, token),
this.resultsEditor.setInput(newInput.results, options) this.resultsEditor.setInput(newInput.results, options)
]).then(() => { ]);
dispose(this.inputDisposables); dispose(this.inputDisposables);
this.inputDisposables = []; this.inputDisposables = [];
this.inputDisposables.push(this.input.state.onChange(c => this.updateState(c))); this.inputDisposables.push(this.input.state.onChange(c => this.updateState(c)));
this.updateState({ connectingChange: true, connectedChange: true, executingChange: true, resultsVisibleChange: true }); this.updateState({ connectingChange: true, connectedChange: true, executingChange: true, resultsVisibleChange: true });
});
} }
public toggleResultsEditorVisibility() { public toggleResultsEditorVisibility() {
@@ -259,7 +292,7 @@ export class QueryEditor extends BaseEditor {
* Sets this editor and the 2 sub-editors to visible. * Sets this editor and the 2 sub-editors to visible.
*/ */
public setEditorVisible(visible: boolean, group: IEditorGroup): void { public setEditorVisible(visible: boolean, group: IEditorGroup): void {
this.textEditor.setVisible(visible, group); this.currentTextEditor.setVisible(visible, group);
this.resultsEditor.setVisible(visible, group); this.resultsEditor.setVisible(visible, group);
super.setEditorVisible(visible, group); super.setEditorVisible(visible, group);
@@ -292,7 +325,7 @@ export class QueryEditor extends BaseEditor {
* input should be freed. * input should be freed.
*/ */
public clearInput(): void { public clearInput(): void {
this.textEditor.clearInput(); this.currentTextEditor.clearInput();
this.resultsEditor.clearInput(); this.resultsEditor.clearInput();
super.clearInput(); super.clearInput();
} }
@@ -301,7 +334,7 @@ export class QueryEditor extends BaseEditor {
* Sets focus on this editor. Specifically, it sets the focus on the hosted text editor. * Sets focus on this editor. Specifically, it sets the focus on the hosted text editor.
*/ */
public focus(): void { public focus(): void {
this.textEditor.focus(); this.currentTextEditor.focus();
} }
/** /**
@@ -317,11 +350,11 @@ export class QueryEditor extends BaseEditor {
* Returns the editor control for the text editor. * Returns the editor control for the text editor.
*/ */
public getControl(): IEditorControl { public getControl(): IEditorControl {
return this.textEditor.getControl(); return this.currentTextEditor.getControl();
} }
public setOptions(options: EditorOptions): void { public setOptions(options: EditorOptions): void {
this.textEditor.setOptions(options); this.currentTextEditor.setOptions(options);
} }
private removeResultsEditor() { private removeResultsEditor() {
@@ -353,8 +386,8 @@ export class QueryEditor extends BaseEditor {
// helper functions // helper functions
public isSelectionEmpty(): boolean { public isSelectionEmpty(): boolean {
if (this.textEditor && this.textEditor.getControl()) { if (this.currentTextEditor && this.currentTextEditor.getControl()) {
let control = this.textEditor.getControl(); let control = this.currentTextEditor.getControl();
let codeEditor: ICodeEditor = <ICodeEditor>control; let codeEditor: ICodeEditor = <ICodeEditor>control;
if (codeEditor) { if (codeEditor) {
@@ -372,8 +405,8 @@ export class QueryEditor extends BaseEditor {
* is no selected text. * is no selected text.
*/ */
public getSelection(checkIfRange: boolean = true): ISelectionData { public getSelection(checkIfRange: boolean = true): ISelectionData {
if (this.textEditor && this.textEditor.getControl()) { if (this.currentTextEditor && this.currentTextEditor.getControl()) {
let vscodeSelection = this.textEditor.getControl().getSelection(); let vscodeSelection = this.currentTextEditor.getControl().getSelection();
// If the selection is a range of characters rather than just a cursor position, return the range // If the selection is a range of characters rather than just a cursor position, return the range
let isRange: boolean = let isRange: boolean =
@@ -395,8 +428,8 @@ export class QueryEditor extends BaseEditor {
} }
public getAllSelection(): ISelectionData { public getAllSelection(): ISelectionData {
if (this.textEditor && this.textEditor.getControl()) { if (this.currentTextEditor && this.currentTextEditor.getControl()) {
let control = this.textEditor.getControl(); let control = this.currentTextEditor.getControl();
let codeEditor: ICodeEditor = <ICodeEditor>control; let codeEditor: ICodeEditor = <ICodeEditor>control;
if (codeEditor) { if (codeEditor) {
let model = codeEditor.getModel(); let model = codeEditor.getModel();
@@ -415,8 +448,8 @@ export class QueryEditor extends BaseEditor {
} }
public getAllText(): string { public getAllText(): string {
if (this.textEditor && this.textEditor.getControl()) { if (this.currentTextEditor && this.currentTextEditor.getControl()) {
let control = this.textEditor.getControl(); let control = this.currentTextEditor.getControl();
let codeEditor: ICodeEditor = <ICodeEditor>control; let codeEditor: ICodeEditor = <ICodeEditor>control;
if (codeEditor) { if (codeEditor) {
let value = codeEditor.getValue(); let value = codeEditor.getValue();
@@ -431,8 +464,8 @@ export class QueryEditor extends BaseEditor {
} }
public getSelectionText(): string { public getSelectionText(): string {
if (this.textEditor && this.textEditor.getControl()) { if (this.currentTextEditor && this.currentTextEditor.getControl()) {
let control = this.textEditor.getControl(); let control = this.currentTextEditor.getControl();
let codeEditor: ICodeEditor = <ICodeEditor>control; let codeEditor: ICodeEditor = <ICodeEditor>control;
let vscodeSelection = control.getSelection(); let vscodeSelection = control.getSelection();