editorGroup.ts 17.3 KB
Newer Older
B
Benjamin Pasero 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

J
Joao Moreno 已提交
6
import { Event, Emitter } from 'vs/base/common/event';
7
import { Extensions, IEditorInputFactoryRegistry, EditorInput, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, CloseDirection, IEditorInput, SideBySideEditorInput } from 'vs/workbench/common/editor';
J
Johannes Rieken 已提交
8
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
9
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
10
import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
11
import { Registry } from 'vs/platform/registry/common/platform';
M
Matt Bierner 已提交
12
import { coalesce } from 'vs/base/common/arrays';
B
Benjamin Pasero 已提交
13

B
Benjamin Pasero 已提交
14 15 16 17 18 19 20
const EditorOpenPositioning = {
	LEFT: 'left',
	RIGHT: 'right',
	FIRST: 'first',
	LAST: 'last'
};

B
Benjamin Pasero 已提交
21
export interface EditorCloseEvent extends IEditorCloseEvent {
22 23 24
	editor: EditorInput;
}

25
export interface EditorIdentifier extends IEditorIdentifier {
I
isidor 已提交
26
	groupId: GroupIdentifier;
27
	editor: EditorInput;
28 29
}

B
Benjamin Pasero 已提交
30 31 32
export interface IEditorOpenOptions {
	pinned?: boolean;
	active?: boolean;
B
Benjamin Pasero 已提交
33
	index?: number;
B
Benjamin Pasero 已提交
34 35
}

36
export interface ISerializedEditorInput {
37 38 39 40
	id: string;
	value: string;
}

41
export interface ISerializedEditorGroup {
42
	id: number;
43 44
	editors: ISerializedEditorInput[];
	mru: number[];
M
Matt Bierner 已提交
45
	preview?: number;
46 47
}

48
export function isSerializedEditorGroup(obj?: any): obj is ISerializedEditorGroup {
49
	const group: ISerializedEditorGroup = obj;
50 51 52 53

	return obj && typeof obj === 'object' && Array.isArray(group.editors) && Array.isArray(group.mru);
}

B
Benjamin Pasero 已提交
54
export class EditorGroup extends Disposable {
55 56 57

	private static IDS = 0;

58 59 60
	//#region events

	private readonly _onDidEditorActivate = this._register(new Emitter<EditorInput>());
61
	readonly onDidEditorActivate = this._onDidEditorActivate.event;
62 63

	private readonly _onDidEditorOpen = this._register(new Emitter<EditorInput>());
64
	readonly onDidEditorOpen = this._onDidEditorOpen.event;
65 66

	private readonly _onDidEditorClose = this._register(new Emitter<EditorCloseEvent>());
67
	readonly onDidEditorClose = this._onDidEditorClose.event;
68 69

	private readonly _onDidEditorDispose = this._register(new Emitter<EditorInput>());
70
	readonly onDidEditorDispose = this._onDidEditorDispose.event;
71 72

	private readonly _onDidEditorBecomeDirty = this._register(new Emitter<EditorInput>());
73
	readonly onDidEditorBecomeDirty = this._onDidEditorBecomeDirty.event;
74 75

	private readonly _onDidEditorLabelChange = this._register(new Emitter<EditorInput>());
76
	readonly onDidEditorLabelChange = this._onDidEditorLabelChange.event;
77 78

	private readonly _onDidEditorMove = this._register(new Emitter<EditorInput>());
79
	readonly onDidEditorMove = this._onDidEditorMove.event;
80 81

	private readonly _onDidEditorPin = this._register(new Emitter<EditorInput>());
82
	readonly onDidEditorPin = this._onDidEditorPin.event;
83 84

	private readonly _onDidEditorUnpin = this._register(new Emitter<EditorInput>());
85
	readonly onDidEditorUnpin = this._onDidEditorUnpin.event;
86 87

	//#endregion
B
Benjamin Pasero 已提交
88

B
Benjamin Pasero 已提交
89
	private _id: GroupIdentifier;
B
Benjamin Pasero 已提交
90
	get id(): GroupIdentifier { return this._id; }
91

92 93
	private editors: EditorInput[] = [];
	private mru: EditorInput[] = [];
94

B
Benjamin Pasero 已提交
95 96
	private preview: EditorInput | null = null; // editor in preview state
	private active: EditorInput | null = null;  // editor in active state
97

B
Benjamin Pasero 已提交
98 99
	private editorOpenPositioning: ('left' | 'right' | 'first' | 'last') | undefined;
	private focusRecentEditorAfterClose: boolean | undefined;
100

101
	constructor(
102
		labelOrSerializedGroup: ISerializedEditorGroup | undefined,
103 104
		@IInstantiationService private readonly instantiationService: IInstantiationService,
		@IConfigurationService private readonly configurationService: IConfigurationService
105
	) {
106 107
		super();

108
		if (isSerializedEditorGroup(labelOrSerializedGroup)) {
B
Benjamin Pasero 已提交
109
			this._id = this.deserialize(labelOrSerializedGroup);
110
		} else {
111
			this._id = EditorGroup.IDS++;
112
		}
113

114
		this.onConfigurationUpdated();
115 116 117 118
		this.registerListeners();
	}

	private registerListeners(): void {
119
		this._register(this.configurationService.onDidChangeConfiguration(e => this.onConfigurationUpdated(e)));
120 121
	}

122
	private onConfigurationUpdated(event?: IConfigurationChangeEvent): void {
123
		this.editorOpenPositioning = this.configurationService.getValue('workbench.editor.openPositioning');
124
		this.focusRecentEditorAfterClose = this.configurationService.getValue('workbench.editor.focusRecentEditorAfterClose');
B
Benjamin Pasero 已提交
125 126
	}

127
	get count(): number {
128 129 130
		return this.editors.length;
	}

131
	getEditors(mru?: boolean): EditorInput[] {
B
Benjamin Pasero 已提交
132
		return mru ? this.mru.slice(0) : this.editors.slice(0);
B
Benjamin Pasero 已提交
133 134
	}

B
Benjamin Pasero 已提交
135 136
	getEditorByIndex(index: number): EditorInput | undefined {
		return this.editors[index];
137 138
	}

M
Matt Bierner 已提交
139
	get activeEditor(): EditorInput | null {
B
Benjamin Pasero 已提交
140 141 142
		return this.active;
	}

143
	isActive(editor: EditorInput): boolean {
B
Benjamin Pasero 已提交
144
		return this.matches(this.active, editor);
B
Benjamin Pasero 已提交
145 146
	}

M
Matt Bierner 已提交
147
	get previewEditor(): EditorInput | null {
B
Benjamin Pasero 已提交
148 149 150
		return this.preview;
	}

151
	isPreview(editor: EditorInput): boolean {
B
Benjamin Pasero 已提交
152
		return this.matches(this.preview, editor);
B
Benjamin Pasero 已提交
153 154
	}

155
	openEditor(editor: EditorInput, options?: IEditorOpenOptions): void {
B
Benjamin Pasero 已提交
156 157
		const index = this.indexOf(editor);

B
Benjamin Pasero 已提交
158 159
		const makePinned = options?.pinned;
		const makeActive = options?.active || !this.activeEditor || (!makePinned && this.matches(this.preview, this.activeEditor));
B
Benjamin Pasero 已提交
160 161 162

		// New editor
		if (index === -1) {
163 164
			let targetIndex: number;
			const indexOfActive = this.indexOf(this.active);
B
Benjamin Pasero 已提交
165

166 167 168 169
			// Insert into specific position
			if (options && typeof options.index === 'number') {
				targetIndex = options.index;
			}
B
Benjamin Pasero 已提交
170

171
			// Insert to the BEGINNING
172
			else if (this.editorOpenPositioning === EditorOpenPositioning.FIRST) {
173 174 175 176
				targetIndex = 0;
			}

			// Insert to the END
177
			else if (this.editorOpenPositioning === EditorOpenPositioning.LAST) {
178
				targetIndex = this.editors.length;
179
			}
B
Benjamin Pasero 已提交
180

181
			// Insert to the LEFT of active editor
182
			else if (this.editorOpenPositioning === EditorOpenPositioning.LEFT) {
183 184 185
				if (indexOfActive === 0 || !this.editors.length) {
					targetIndex = 0; // to the left becoming first editor in list
				} else {
186
					targetIndex = indexOfActive; // to the left of active editor
B
Benjamin Pasero 已提交
187
				}
188
			}
B
Benjamin Pasero 已提交
189

190 191 192 193 194
			// Insert to the RIGHT of active editor
			else {
				targetIndex = indexOfActive + 1;
			}

195 196 197
			// Insert into our list of editors if pinned or we have no preview editor
			if (makePinned || !this.preview) {
				this.splice(targetIndex, false, editor);
B
Benjamin Pasero 已提交
198 199
			}

200 201
			// Handle preview
			if (!makePinned) {
B
Benjamin Pasero 已提交
202 203

				// Replace existing preview with this editor if we have a preview
204 205
				if (this.preview) {
					const indexOfPreview = this.indexOf(this.preview);
206 207
					if (targetIndex > indexOfPreview) {
						targetIndex--; // accomodate for the fact that the preview editor closes
208 209
					}

210
					this.replaceEditor(this.preview, editor, targetIndex, !makeActive);
211
				}
B
Benjamin Pasero 已提交
212

B
Benjamin Pasero 已提交
213 214 215
				this.preview = editor;
			}

216
			// Listeners
B
Benjamin Pasero 已提交
217
			this.registerEditorListeners(editor);
218

B
Benjamin Pasero 已提交
219
			// Event
220
			this._onDidEditorOpen.fire(editor);
B
Benjamin Pasero 已提交
221

222
			// Handle active
B
Benjamin Pasero 已提交
223
			if (makeActive) {
B
Benjamin Pasero 已提交
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
				this.setActive(editor);
			}
		}

		// Existing editor
		else {

			// Pin it
			if (makePinned) {
				this.pin(editor);
			}

			// Activate it
			if (makeActive) {
				this.setActive(editor);
			}
B
Benjamin Pasero 已提交
240 241 242 243 244

			// Respect index
			if (options && typeof options.index === 'number') {
				this.moveEditor(editor, options.index);
			}
B
Benjamin Pasero 已提交
245 246 247
		}
	}

B
Benjamin Pasero 已提交
248
	private registerEditorListeners(editor: EditorInput): void {
249
		const listeners = new DisposableStore();
250 251

		// Re-emit disposal of editor input as our own event
J
Joao Moreno 已提交
252
		const onceDispose = Event.once(editor.onDispose);
253
		listeners.add(onceDispose(() => {
254
			if (this.indexOf(editor) >= 0) {
255
				this._onDidEditorDispose.fire(editor);
256
			}
257 258 259
		}));

		// Re-Emit dirty state changes
260
		listeners.add(editor.onDidChangeDirty(() => {
261
			this._onDidEditorBecomeDirty.fire(editor);
262
		}));
263

B
Benjamin Pasero 已提交
264
		// Re-Emit label changes
265
		listeners.add(editor.onDidChangeLabel(() => {
266
			this._onDidEditorLabelChange.fire(editor);
B
Benjamin Pasero 已提交
267 268
		}));

269
		// Clean up dispose listeners once the editor gets closed
270
		listeners.add(this.onDidEditorClose(event => {
271
			if (event.editor.matches(editor)) {
272
				dispose(listeners);
273
			}
274
		}));
275 276
	}

B
Benjamin Pasero 已提交
277
	private replaceEditor(toReplace: EditorInput, replaceWith: EditorInput, replaceIndex: number, openNext = true): void {
278
		const event = this.doCloseEditor(toReplace, openNext, true); // optimization to prevent multiple setActive() in one call
279 280 281 282

		// We want to first add the new editor into our model before emitting the close event because
		// firing the close event can trigger a dispose on the same editor that is now being added.
		// This can lead into opening a disposed editor which is not what we want.
B
Benjamin Pasero 已提交
283
		this.splice(replaceIndex, false, replaceWith);
284 285

		if (event) {
286
			this._onDidEditorClose.fire(event);
287 288 289
		}
	}

M
Matt Bierner 已提交
290
	closeEditor(editor: EditorInput, openNext = true): number | undefined {
291
		const event = this.doCloseEditor(editor, openNext, false);
292 293

		if (event) {
294
			this._onDidEditorClose.fire(event);
295 296

			return event.index;
297
		}
298

R
Rob Lourens 已提交
299
		return undefined;
300 301
	}

M
Matt Bierner 已提交
302
	private doCloseEditor(editor: EditorInput, openNext: boolean, replaced: boolean): EditorCloseEvent | null {
B
Benjamin Pasero 已提交
303 304
		const index = this.indexOf(editor);
		if (index === -1) {
305
			return null; // not found
B
Benjamin Pasero 已提交
306 307 308
		}

		// Active Editor closed
B
Benjamin Pasero 已提交
309
		if (openNext && this.matches(this.active, editor)) {
B
Benjamin Pasero 已提交
310 311

			// More than one editor
B
Benjamin Pasero 已提交
312
			if (this.mru.length > 1) {
313
				let newActive: EditorInput;
314
				if (this.focusRecentEditorAfterClose) {
315
					newActive = this.mru[1]; // active editor is always first in MRU, so pick second editor after as new active
B
Benjamin Pasero 已提交
316
				} else {
317 318
					if (index === this.editors.length - 1) {
						newActive = this.editors[index - 1]; // last editor is closed, pick previous as new active
B
Benjamin Pasero 已提交
319
					} else {
320 321 322
						newActive = this.editors[index + 1]; // pick next editor as new active
					}
				}
B
Benjamin Pasero 已提交
323

324
				this.setActive(newActive);
B
Benjamin Pasero 已提交
325 326 327 328 329 330 331 332 333
			}

			// One Editor
			else {
				this.active = null;
			}
		}

		// Preview Editor closed
B
Benjamin Pasero 已提交
334
		if (this.matches(this.preview, editor)) {
B
Benjamin Pasero 已提交
335 336 337
			this.preview = null;
		}

B
Benjamin Pasero 已提交
338
		// Remove from arrays
B
Benjamin Pasero 已提交
339
		this.splice(index, true);
B
Benjamin Pasero 已提交
340 341

		// Event
I
isidor 已提交
342
		return { editor, replaced, index, groupId: this.id };
B
Benjamin Pasero 已提交
343 344
	}

B
Benjamin Pasero 已提交
345
	closeEditors(except: EditorInput, direction?: CloseDirection): void {
B
Benjamin Pasero 已提交
346 347 348 349 350 351
		const index = this.indexOf(except);
		if (index === -1) {
			return; // not found
		}

		// Close to the left
B
Benjamin Pasero 已提交
352
		if (direction === CloseDirection.LEFT) {
B
Benjamin Pasero 已提交
353 354 355 356 357 358
			for (let i = index - 1; i >= 0; i--) {
				this.closeEditor(this.editors[i]);
			}
		}

		// Close to the right
B
Benjamin Pasero 已提交
359
		else if (direction === CloseDirection.RIGHT) {
B
Benjamin Pasero 已提交
360 361 362 363 364 365 366
			for (let i = this.editors.length - 1; i > index; i--) {
				this.closeEditor(this.editors[i]);
			}
		}

		// Both directions
		else {
B
Benjamin Pasero 已提交
367
			this.mru.filter(e => !this.matches(e, except)).forEach(e => this.closeEditor(e));
B
Benjamin Pasero 已提交
368 369 370
		}
	}

371
	closeAllEditors(): void {
372 373

		// Optimize: close all non active editors first to produce less upstream work
B
Benjamin Pasero 已提交
374
		this.mru.filter(e => !this.matches(e, this.active)).forEach(e => this.closeEditor(e));
M
Matt Bierner 已提交
375 376 377
		if (this.active) {
			this.closeEditor(this.active);
		}
378 379
	}

380
	moveEditor(editor: EditorInput, toIndex: number): void {
B
Benjamin Pasero 已提交
381 382 383 384 385 386 387 388 389 390
		const index = this.indexOf(editor);
		if (index < 0) {
			return;
		}

		// Move
		this.editors.splice(index, 1);
		this.editors.splice(toIndex, 0, editor);

		// Event
391
		this._onDidEditorMove.fire(editor);
B
Benjamin Pasero 已提交
392 393
	}

394
	setActive(editor: EditorInput): void {
B
Benjamin Pasero 已提交
395 396 397 398 399
		const index = this.indexOf(editor);
		if (index === -1) {
			return; // not found
		}

B
Benjamin Pasero 已提交
400
		if (this.matches(this.active, editor)) {
B
Benjamin Pasero 已提交
401 402 403 404 405
			return; // already active
		}

		this.active = editor;

B
Benjamin Pasero 已提交
406
		// Bring to front in MRU list
B
Benjamin Pasero 已提交
407 408
		this.setMostRecentlyUsed(editor);

B
Benjamin Pasero 已提交
409
		// Event
410
		this._onDidEditorActivate.fire(editor);
B
Benjamin Pasero 已提交
411 412
	}

413
	pin(editor: EditorInput): void {
414 415 416 417 418
		const index = this.indexOf(editor);
		if (index === -1) {
			return; // not found
		}

B
Benjamin Pasero 已提交
419 420
		if (!this.isPreview(editor)) {
			return; // can only pin a preview editor
B
Benjamin Pasero 已提交
421 422 423 424 425 426
		}

		// Convert the preview editor to be a pinned editor
		this.preview = null;

		// Event
427
		this._onDidEditorPin.fire(editor);
B
Benjamin Pasero 已提交
428 429
	}

430
	unpin(editor: EditorInput): void {
431 432 433 434
		const index = this.indexOf(editor);
		if (index === -1) {
			return; // not found
		}
435

B
Benjamin Pasero 已提交
436 437 438 439 440 441 442 443 444
		if (!this.isPinned(editor)) {
			return; // can only unpin a pinned editor
		}

		// Set new
		const oldPreview = this.preview;
		this.preview = editor;

		// Event
445
		this._onDidEditorUnpin.fire(editor);
B
Benjamin Pasero 已提交
446 447

		// Close old preview editor if any
M
Matt Bierner 已提交
448 449 450
		if (oldPreview) {
			this.closeEditor(oldPreview);
		}
B
Benjamin Pasero 已提交
451 452
	}

453 454 455
	isPinned(editor: EditorInput): boolean;
	isPinned(index: number): boolean;
	isPinned(arg1: EditorInput | number): boolean {
456 457 458 459 460 461 462 463 464 465 466
		let editor: EditorInput;
		let index: number;
		if (typeof arg1 === 'number') {
			editor = this.editors[arg1];
			index = arg1;
		} else {
			editor = arg1;
			index = this.indexOf(editor);
		}

		if (index === -1 || !editor) {
B
Benjamin Pasero 已提交
467 468 469 470 471 472 473
			return false; // editor not found
		}

		if (!this.preview) {
			return true; // no preview editor
		}

B
Benjamin Pasero 已提交
474
		return !this.matches(this.preview, editor);
B
Benjamin Pasero 已提交
475 476
	}

B
Benjamin Pasero 已提交
477
	private splice(index: number, del: boolean, editor?: EditorInput): void {
478
		const editorToDeleteOrReplace = this.editors[index];
B
Benjamin Pasero 已提交
479

480
		// Perform on editors array
481
		if (editor) {
482 483 484
			this.editors.splice(index, del ? 1 : 0, editor);
		} else {
			this.editors.splice(index, del ? 1 : 0);
485
		}
B
Benjamin Pasero 已提交
486

487
		// Add
B
Benjamin Pasero 已提交
488
		if (!del && editor) {
489 490 491 492 493 494 495 496 497 498 499 500 501
			if (this.mru.length === 0) {
				// the list of most recent editors is empty
				// so this editor can only be the most recent
				this.mru.push(editor);
			} else {
				// we have most recent editors. as such we
				// put this newly opened editor right after
				// the current most recent one because it cannot
				// be the most recently active one unless
				// it becomes active. but it is still more
				// active then any other editor in the list.
				this.mru.splice(1, 0, editor);
			}
B
Benjamin Pasero 已提交
502 503
		}

B
Benjamin Pasero 已提交
504
		// Remove / Replace
B
Benjamin Pasero 已提交
505
		else {
B
Benjamin Pasero 已提交
506 507
			const indexInMRU = this.indexOf(editorToDeleteOrReplace, this.mru);

508
			// Remove
B
Benjamin Pasero 已提交
509
			if (del && !editor) {
510
				this.mru.splice(indexInMRU, 1); // remove from MRU
B
Benjamin Pasero 已提交
511 512
			}

513
			// Replace
B
Benjamin Pasero 已提交
514
			else if (del && editor) {
515
				this.mru.splice(indexInMRU, 1, editor); // replace MRU at location
B
Benjamin Pasero 已提交
516
			}
517 518
		}
	}
B
Benjamin Pasero 已提交
519

520
	indexOf(candidate: IEditorInput | null, editors = this.editors): number {
B
Benjamin Pasero 已提交
521 522
		if (!candidate) {
			return -1;
B
Benjamin Pasero 已提交
523 524
		}

B
Benjamin Pasero 已提交
525
		for (let i = 0; i < editors.length; i++) {
B
Benjamin Pasero 已提交
526
			if (this.matches(editors[i], candidate)) {
B
Benjamin Pasero 已提交
527 528 529 530 531 532
				return i;
			}
		}

		return -1;
	}
B
Benjamin Pasero 已提交
533

534 535 536 537 538
	contains(candidate: EditorInput, searchInSideBySideEditors?: boolean): boolean {
		for (const editor of this.editors) {
			if (this.matches(editor, candidate)) {
				return true;
			}
539

540 541 542 543 544
			if (searchInSideBySideEditors && editor instanceof SideBySideEditorInput) {
				if (this.matches(editor.master, candidate) || this.matches(editor.details, candidate)) {
					return true;
				}
			}
545 546 547 548 549
		}

		return false;
	}

B
Benjamin Pasero 已提交
550 551 552 553 554 555 556 557 558
	private setMostRecentlyUsed(editor: EditorInput): void {
		const index = this.indexOf(editor);
		if (index === -1) {
			return; // editor not found
		}

		const mruIndex = this.indexOf(editor, this.mru);

		// Remove old index
B
Benjamin Pasero 已提交
559
		this.mru.splice(mruIndex, 1);
B
Benjamin Pasero 已提交
560

561
		// Set editor as most recent one (first)
B
Benjamin Pasero 已提交
562 563
		this.mru.unshift(editor);
	}
B
Benjamin Pasero 已提交
564

565
	private matches(editorA: IEditorInput | null, editorB: IEditorInput | null): boolean {
B
Benjamin Pasero 已提交
566 567
		return !!editorA && !!editorB && editorA.matches(editorB);
	}
568

569
	clone(): EditorGroup {
R
Rob Lourens 已提交
570
		const group = this.instantiationService.createInstance(EditorGroup, undefined);
571 572 573 574 575 576 577 578 579 580
		group.editors = this.editors.slice(0);
		group.mru = this.mru.slice(0);
		group.preview = this.preview;
		group.active = this.active;
		group.editorOpenPositioning = this.editorOpenPositioning;

		return group;
	}

	serialize(): ISerializedEditorGroup {
581
		const registry = Registry.as<IEditorInputFactoryRegistry>(Extensions.EditorInputFactories);
582 583 584 585 586 587

		// Serialize all editor inputs so that we can store them.
		// Editors that cannot be serialized need to be ignored
		// from mru, active and preview if any.
		let serializableEditors: EditorInput[] = [];
		let serializedEditors: ISerializedEditorInput[] = [];
M
Matt Bierner 已提交
588
		let serializablePreviewIndex: number | undefined;
589
		this.editors.forEach(e => {
590
			const factory = registry.getEditorInputFactory(e.getTypeId());
591
			if (factory) {
592
				const value = factory.serialize(e);
593
				if (typeof value === 'string') {
594
					serializedEditors.push({ id: e.getTypeId(), value });
595
					serializableEditors.push(e);
B
Benjamin Pasero 已提交
596 597 598 599

					if (this.preview === e) {
						serializablePreviewIndex = serializableEditors.length - 1;
					}
600 601 602 603
				}
			}
		});

B
Benjamin Pasero 已提交
604
		const serializableMru = this.mru.map(e => this.indexOf(e, serializableEditors)).filter(i => i >= 0);
605 606

		return {
607
			id: this.id,
608 609
			editors: serializedEditors,
			mru: serializableMru,
B
Benjamin Pasero 已提交
610
			preview: serializablePreviewIndex,
611 612 613
		};
	}

B
Benjamin Pasero 已提交
614
	private deserialize(data: ISerializedEditorGroup): number {
615
		const registry = Registry.as<IEditorInputFactoryRegistry>(Extensions.EditorInputFactories);
616

617 618 619 620 621 622 623 624
		if (typeof data.id === 'number') {
			this._id = data.id;

			EditorGroup.IDS = Math.max(data.id + 1, EditorGroup.IDS); // make sure our ID generator is always larger
		} else {
			this._id = EditorGroup.IDS++; // backwards compatibility
		}

M
Matt Bierner 已提交
625
		this.editors = coalesce(data.editors.map(e => {
B
Benjamin Pasero 已提交
626 627
			const factory = registry.getEditorInputFactory(e.id);
			if (factory) {
B
Benjamin Pasero 已提交
628 629 630 631
				const editor = factory.deserialize(this.instantiationService, e.value);
				if (editor) {
					this.registerEditorListeners(editor);
				}
632

B
Benjamin Pasero 已提交
633 634 635 636
				return editor;
			}

			return null;
M
Matt Bierner 已提交
637
		}));
B
Benjamin Pasero 已提交
638

639
		this.mru = data.mru.map(i => this.editors[i]);
B
Benjamin Pasero 已提交
640

641
		this.active = this.mru[0];
B
Benjamin Pasero 已提交
642

M
Matt Bierner 已提交
643 644 645
		if (typeof data.preview === 'number') {
			this.preview = this.editors[data.preview];
		}
B
Benjamin Pasero 已提交
646 647

		return this._id;
648 649
	}
}