sideBySideEditor.ts 9.2 KB
Newer Older
S
Sandeep Somavarapu 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import * as DOM from 'vs/base/browser/dom';
7
import { Registry } from 'vs/platform/registry/common/platform';
8
import { EditorInput, EditorOptions, SideBySideEditorInput, IEditorControl, IEditor } from 'vs/workbench/common/editor';
9
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
S
Sandeep Somavarapu 已提交
10 11
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
B
Benjamin Pasero 已提交
12
import { IThemeService } from 'vs/platform/theme/common/themeService';
13
import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry';
14
import { IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
15
import { CancellationToken } from 'vs/base/common/cancellation';
16
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
17
import { SplitView, Sizing, Orientation } from 'vs/base/browser/ui/splitview/splitview';
J
Joao Moreno 已提交
18
import { Event, Relay, Emitter } from 'vs/base/common/event';
B
Benjamin Pasero 已提交
19
import { IStorageService } from 'vs/platform/storage/common/storage';
20
import { assertIsDefined } from 'vs/base/common/types';
S
Sandeep Somavarapu 已提交
21 22 23

export class SideBySideEditor extends BaseEditor {

B
Benjamin Pasero 已提交
24
	static readonly ID: string = 'workbench.editor.sidebysideEditor';
B
Benjamin Pasero 已提交
25
	static MASTER: SideBySideEditor | undefined;
S
Sandeep Somavarapu 已提交
26

B
Benjamin Pasero 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
	get minimumMasterWidth() { return this.masterEditor ? this.masterEditor.minimumWidth : 0; }
	get maximumMasterWidth() { return this.masterEditor ? this.masterEditor.maximumWidth : Number.POSITIVE_INFINITY; }
	get minimumMasterHeight() { return this.masterEditor ? this.masterEditor.minimumHeight : 0; }
	get maximumMasterHeight() { return this.masterEditor ? this.masterEditor.maximumHeight : Number.POSITIVE_INFINITY; }

	get minimumDetailsWidth() { return this.detailsEditor ? this.detailsEditor.minimumWidth : 0; }
	get maximumDetailsWidth() { return this.detailsEditor ? this.detailsEditor.maximumWidth : Number.POSITIVE_INFINITY; }
	get minimumDetailsHeight() { return this.detailsEditor ? this.detailsEditor.minimumHeight : 0; }
	get maximumDetailsHeight() { return this.detailsEditor ? this.detailsEditor.maximumHeight : Number.POSITIVE_INFINITY; }

	// these setters need to exist because this extends from BaseEditor
	set minimumWidth(value: number) { /* noop */ }
	set maximumWidth(value: number) { /* noop */ }
	set minimumHeight(value: number) { /* noop */ }
	set maximumHeight(value: number) { /* noop */ }

	get minimumWidth() { return this.minimumMasterWidth + this.minimumDetailsWidth; }
	get maximumWidth() { return this.maximumMasterWidth + this.maximumDetailsWidth; }
	get minimumHeight() { return this.minimumMasterHeight + this.minimumDetailsHeight; }
	get maximumHeight() { return this.maximumMasterHeight + this.maximumDetailsHeight; }
S
Sandeep Somavarapu 已提交
47

M
Matt Bierner 已提交
48 49
	protected masterEditor?: BaseEditor;
	protected detailsEditor?: BaseEditor;
B
Benjamin Pasero 已提交
50

51 52
	private masterEditorContainer: HTMLElement | undefined;
	private detailsEditorContainer: HTMLElement | undefined;
S
Sandeep Somavarapu 已提交
53

54
	private splitview: SplitView | undefined;
B
Benjamin Pasero 已提交
55
	private dimension: DOM.Dimension = new DOM.Dimension(0, 0);
S
Sandeep Somavarapu 已提交
56

M
Matt Bierner 已提交
57
	private onDidCreateEditors = this._register(new Emitter<{ width: number; height: number; } | undefined>());
B
Benjamin Pasero 已提交
58

M
Matt Bierner 已提交
59
	private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; } | undefined>());
60
	readonly onDidSizeConstraintsChange = Event.any(this.onDidCreateEditors.event, this._onDidSizeConstraintsChange.event);
61

S
Sandeep Somavarapu 已提交
62 63
	constructor(
		@ITelemetryService telemetryService: ITelemetryService,
64
		@IInstantiationService private readonly instantiationService: IInstantiationService,
B
Benjamin Pasero 已提交
65
		@IThemeService themeService: IThemeService,
66
		@IStorageService storageService: IStorageService
S
Sandeep Somavarapu 已提交
67
	) {
68
		super(SideBySideEditor.ID, telemetryService, themeService, storageService);
S
Sandeep Somavarapu 已提交
69 70
	}

71 72
	protected createEditor(parent: HTMLElement): void {
		DOM.addClass(parent, 'side-by-side-editor');
73

74 75
		const splitview = this.splitview = this._register(new SplitView(parent, { orientation: Orientation.HORIZONTAL }));
		this._register(this.splitview.onDidSashReset(() => splitview.distributeViewSizes()));
76 77 78 79

		this.detailsEditorContainer = DOM.$('.details-editor-container');
		this.splitview.addView({
			element: this.detailsEditorContainer,
J
Joao Moreno 已提交
80
			layout: size => this.detailsEditor && this.detailsEditor.layout(new DOM.Dimension(size, this.dimension.height)),
81 82 83 84 85 86 87 88
			minimumSize: 220,
			maximumSize: Number.POSITIVE_INFINITY,
			onDidChange: Event.None
		}, Sizing.Distribute);

		this.masterEditorContainer = DOM.$('.master-editor-container');
		this.splitview.addView({
			element: this.masterEditorContainer,
J
Joao Moreno 已提交
89
			layout: size => this.masterEditor && this.masterEditor.layout(new DOM.Dimension(size, this.dimension.height)),
90 91 92 93 94 95
			minimumSize: 220,
			maximumSize: Number.POSITIVE_INFINITY,
			onDidChange: Event.None
		}, Sizing.Distribute);

		this.updateStyles();
S
Sandeep Somavarapu 已提交
96 97
	}

98
	async setInput(newInput: EditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<void> {
M
Matt Bierner 已提交
99
		const oldInput = this.input as SideBySideEditorInput;
100 101 102
		await super.setInput(newInput, options, token);

		return this.updateInput(oldInput, (newInput as SideBySideEditorInput), options, token);
103 104
	}

105
	setOptions(options: EditorOptions | undefined): void {
106 107 108
		if (this.masterEditor) {
			this.masterEditor.setOptions(options);
		}
S
Sandeep Somavarapu 已提交
109 110
	}

111
	protected setEditorVisible(visible: boolean, group: IEditorGroup | undefined): void {
S
Sandeep Somavarapu 已提交
112
		if (this.masterEditor) {
113
			this.masterEditor.setVisible(visible, group);
S
Sandeep Somavarapu 已提交
114
		}
115

S
Sandeep Somavarapu 已提交
116
		if (this.detailsEditor) {
117
			this.detailsEditor.setVisible(visible, group);
S
Sandeep Somavarapu 已提交
118
		}
119

120
		super.setEditorVisible(visible, group);
B
Benjamin Pasero 已提交
121 122
	}

B
Benjamin Pasero 已提交
123
	clearInput(): void {
B
Benjamin Pasero 已提交
124 125 126
		if (this.masterEditor) {
			this.masterEditor.clearInput();
		}
127

B
Benjamin Pasero 已提交
128 129 130
		if (this.detailsEditor) {
			this.detailsEditor.clearInput();
		}
131

S
Sandeep Somavarapu 已提交
132
		this.disposeEditors();
133

S
Sandeep Somavarapu 已提交
134 135 136
		super.clearInput();
	}

B
Benjamin Pasero 已提交
137
	focus(): void {
S
Sandeep Somavarapu 已提交
138 139 140 141 142
		if (this.masterEditor) {
			this.masterEditor.focus();
		}
	}

B
Benjamin Pasero 已提交
143
	layout(dimension: DOM.Dimension): void {
S
Sandeep Somavarapu 已提交
144
		this.dimension = dimension;
145 146 147

		const splitview = assertIsDefined(this.splitview);
		splitview.layout(dimension.width);
S
Sandeep Somavarapu 已提交
148 149
	}

150
	getControl(): IEditorControl | undefined {
S
Sandeep Somavarapu 已提交
151 152 153
		if (this.masterEditor) {
			return this.masterEditor.getControl();
		}
154

155
		return undefined;
S
Sandeep Somavarapu 已提交
156 157
	}

M
Matt Bierner 已提交
158
	getMasterEditor(): IEditor | undefined {
159 160 161
		return this.masterEditor;
	}

M
Matt Bierner 已提交
162
	getDetailsEditor(): IEditor | undefined {
163 164 165
		return this.detailsEditor;
	}

166
	private async updateInput(oldInput: SideBySideEditorInput, newInput: SideBySideEditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<void> {
S
Sandeep Somavarapu 已提交
167 168 169 170
		if (!newInput.matches(oldInput)) {
			if (oldInput) {
				this.disposeEditors();
			}
171

172
			return this.setNewInput(newInput, options, token);
S
Sandeep Somavarapu 已提交
173
		}
174

M
Matt Bierner 已提交
175
		if (!this.detailsEditor || !this.masterEditor) {
176
			return;
M
Matt Bierner 已提交
177
		}
B
Benjamin Pasero 已提交
178

179
		await Promise.all([
180
			this.detailsEditor.setInput(newInput.details, undefined, token),
181 182
			this.masterEditor.setInput(newInput.master, options, token)
		]);
S
Sandeep Somavarapu 已提交
183 184
	}

185
	private setNewInput(newInput: SideBySideEditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<void> {
186 187
		const detailsEditor = this.doCreateEditor(newInput.details, assertIsDefined(this.detailsEditorContainer));
		const masterEditor = this.doCreateEditor(newInput.master, assertIsDefined(this.masterEditorContainer));
188

189
		return this.onEditorsCreated(detailsEditor, masterEditor, newInput.details, newInput.master, options, token);
S
Sandeep Somavarapu 已提交
190 191
	}

B
Benjamin Pasero 已提交
192
	private doCreateEditor(editorInput: EditorInput, container: HTMLElement): BaseEditor {
S
Sandeep Somavarapu 已提交
193
		const descriptor = Registry.as<IEditorRegistry>(EditorExtensions.Editors).getEditor(editorInput);
M
Matt Bierner 已提交
194 195 196
		if (!descriptor) {
			throw new Error('No descriptor for editor found');
		}
B
Benjamin Pasero 已提交
197

198
		const editor = descriptor.instantiate(this.instantiationService);
199
		editor.create(container);
200
		editor.setVisible(this.isVisible(), this.group);
201 202

		return editor;
S
Sandeep Somavarapu 已提交
203 204
	}

205
	private async onEditorsCreated(details: BaseEditor, master: BaseEditor, detailsInput: EditorInput, masterInput: EditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<void> {
S
Sandeep Somavarapu 已提交
206 207
		this.detailsEditor = details;
		this.masterEditor = master;
208

J
Joao Moreno 已提交
209 210 211
		this._onDidSizeConstraintsChange.input = Event.any(
			Event.map(details.onDidSizeConstraintsChange, () => undefined),
			Event.map(master.onDidSizeConstraintsChange, () => undefined)
212 213
		);

214
		this.onDidCreateEditors.fire(undefined);
215

216
		await Promise.all([
217
			this.detailsEditor.setInput(detailsInput, undefined, token),
218 219
			this.masterEditor.setInput(masterInput, options, token)]
		);
S
Sandeep Somavarapu 已提交
220 221
	}

B
Benjamin Pasero 已提交
222
	updateStyles(): void {
223 224 225
		super.updateStyles();

		if (this.masterEditorContainer) {
226
			this.masterEditorContainer.style.boxShadow = `-6px 0 5px -5px ${this.getColor(scrollbarShadow)}`;
227
		}
S
Sandeep Somavarapu 已提交
228 229
	}

S
Sandeep Somavarapu 已提交
230
	private disposeEditors(): void {
S
Sandeep Somavarapu 已提交
231 232
		if (this.detailsEditor) {
			this.detailsEditor.dispose();
M
Matt Bierner 已提交
233
			this.detailsEditor = undefined;
S
Sandeep Somavarapu 已提交
234
		}
B
Benjamin Pasero 已提交
235

S
Sandeep Somavarapu 已提交
236 237
		if (this.masterEditor) {
			this.masterEditor.dispose();
M
Matt Bierner 已提交
238
			this.masterEditor = undefined;
S
Sandeep Somavarapu 已提交
239
		}
B
Benjamin Pasero 已提交
240

241 242 243 244 245 246 247
		if (this.detailsEditorContainer) {
			DOM.clearNode(this.detailsEditorContainer);
		}

		if (this.masterEditorContainer) {
			DOM.clearNode(this.masterEditorContainer);
		}
S
Sandeep Somavarapu 已提交
248
	}
S
Sandeep Somavarapu 已提交
249

B
Benjamin Pasero 已提交
250
	dispose(): void {
S
Sandeep Somavarapu 已提交
251
		this.disposeEditors();
B
Benjamin Pasero 已提交
252

S
Sandeep Somavarapu 已提交
253 254
		super.dispose();
	}
I
isidor 已提交
255
}