editorGroupsService.ts 12.8 KB
Newer Older
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

8
import { Event } from 'vs/base/common/event';
9
import { createDecorator, ServiceIdentifier, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
10
import { IEditorInput, IEditor, GroupIdentifier, IEditorInputWithOptions, CloseDirection } from 'vs/workbench/common/editor';
B
Benjamin Pasero 已提交
11
import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor';
12
import { TPromise } from 'vs/base/common/winjs.base';
B
Benjamin Pasero 已提交
13
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
14

15
export const IEditorGroupsService = createDecorator<IEditorGroupsService>('editorGroupsService');
16

17
export enum GroupDirection {
18 19 20 21 22 23
	UP,
	DOWN,
	LEFT,
	RIGHT
}

B
Benjamin Pasero 已提交
24 25 26 27 28 29 30 31 32 33 34 35
export function preferredGroupDirection(configurationService: IConfigurationService): GroupDirection {
	const openSideBySideDirection = configurationService.getValue<'left' | 'right' | 'up' | 'down'>('workbench.editor.openSideBySideDirection');

	switch (openSideBySideDirection) {
		case 'left': return GroupDirection.LEFT;
		case 'right': return GroupDirection.RIGHT;
		case 'up': return GroupDirection.UP;
		case 'down': return GroupDirection.DOWN;
		default: return GroupDirection.RIGHT;
	}
}

36 37 38 39 40
export enum GroupOrientation {
	HORIZONTAL,
	VERTICAL
}

41 42 43 44 45 46 47 48 49 50 51 52
export enum GroupLocation {
	FIRST,
	LAST,
	NEXT,
	PREVIOUS
}

export interface IFindGroupScope {
	direction?: GroupDirection;
	location?: GroupLocation;
}

53 54 55 56 57 58 59 60 61 62 63 64 65 66
export enum GroupsArrangement {

	/**
	 * Make the current active group consume the maximum
	 * amount of space possible.
	 */
	MINIMIZE_OTHERS,

	/**
	 * Size all groups evenly.
	 */
	EVEN
}

B
Benjamin Pasero 已提交
67 68 69 70 71 72
export interface IMoveEditorOptions {
	index?: number;
	inactive?: boolean;
	preserveFocus?: boolean;
}

73 74
export interface ICopyEditorOptions extends IMoveEditorOptions { }

75 76 77 78
export interface IAddGroupOptions {
	activate?: boolean;
}

79 80
export enum MergeGroupMode {
	COPY_EDITORS,
81
	MOVE_EDITORS
82 83 84 85 86
}

export interface IMergeGroupOptions {
	mode?: MergeGroupMode;
}
B
Benjamin Pasero 已提交
87

88 89
export type ICloseEditorsFilter = {
	except?: IEditorInput,
B
Benjamin Pasero 已提交
90
	direction?: CloseDirection,
91 92 93
	savedOnly?: boolean
};

94 95 96
export interface IEditorReplacement {
	editor: IEditorInput;
	replacement: IEditorInput;
B
Benjamin Pasero 已提交
97
	options?: IEditorOptions | ITextEditorOptions;
98 99
}

100
export enum GroupsOrder {
101 102 103 104 105 106 107 108 109

	/**
	 * Groups sorted by creation order (oldest one first)
	 */
	CREATION_TIME,

	/**
	 * Groups sorted by most recent activity (most recent active first)
	 */
110
	MOST_RECENTLY_ACTIVE,
111 112

	/**
B
Benjamin Pasero 已提交
113
	 * Groups sorted by grid widget order
114 115
	 */
	GRID_APPEARANCE
116 117
}

B
Benjamin Pasero 已提交
118 119 120 121 122 123 124 125
export enum EditorsOrder {

	/**
	 * Editors sorted by most recent activity (most recent active first)
	 */
	MOST_RECENTLY_ACTIVE,

	/**
126
	 * Editors sorted by sequential order
B
Benjamin Pasero 已提交
127
	 */
128
	SEQUENTIAL
B
Benjamin Pasero 已提交
129 130
}

131
export interface IEditorGroupsService {
B
Benjamin Pasero 已提交
132 133 134 135 136 137 138

	_serviceBrand: ServiceIdentifier<any>;

	/**
	 * An event for when the active editor group changes. The active editor
	 * group is the default location for new editors to open.
	 */
139
	readonly onDidActiveGroupChange: Event<IEditorGroup>;
B
Benjamin Pasero 已提交
140 141 142 143

	/**
	 * An event for when a new group was added.
	 */
144
	readonly onDidAddGroup: Event<IEditorGroup>;
B
Benjamin Pasero 已提交
145 146 147 148

	/**
	 * An event for when a group was removed.
	 */
149
	readonly onDidRemoveGroup: Event<IEditorGroup>;
B
Benjamin Pasero 已提交
150

B
Benjamin Pasero 已提交
151 152 153
	/**
	 * An event for when a group was moved.
	 */
154
	readonly onDidMoveGroup: Event<IEditorGroup>;
B
Benjamin Pasero 已提交
155

B
Benjamin Pasero 已提交
156 157 158
	/**
	 * An active group is the default location for new editors to open.
	 */
159
	readonly activeGroup: IEditorGroup;
B
Benjamin Pasero 已提交
160 161

	/**
162 163
	 * All groups that are currently visible in the editor area in the
	 * order of their creation (oldest first).
B
Benjamin Pasero 已提交
164
	 */
165
	readonly groups: ReadonlyArray<IEditorGroup>;
B
Benjamin Pasero 已提交
166 167 168 169 170 171

	/**
	 * The number of editor groups that are currently opened.
	 */
	readonly count: number;

172 173 174 175 176
	/**
	 * The current layout orientation of the root group.
	 */
	readonly orientation: GroupOrientation;

177 178 179
	/**
	 * A promise that resolves when groups have been restored.
	 */
180
	readonly whenRestored: TPromise<void>;
181

B
Benjamin Pasero 已提交
182 183
	/**
	 * Get all groups that are currently visible in the editor area optionally
184 185
	 * sorted by being most recent active or grid order. Will sort by creation
	 * time by default (oldest group first).
B
Benjamin Pasero 已提交
186
	 */
187
	getGroups(order?: GroupsOrder): ReadonlyArray<IEditorGroup>;
B
Benjamin Pasero 已提交
188 189 190 191

	/**
	 * Allows to convert a group identifier to a group.
	 */
192
	getGroup(identifier: GroupIdentifier): IEditorGroup;
B
Benjamin Pasero 已提交
193 194 195 196

	/**
	 * Set a group as active. An active group is the default location for new editors to open.
	 */
197
	activateGroup(group: IEditorGroup | GroupIdentifier): IEditorGroup;
B
Benjamin Pasero 已提交
198

199
	/**
200
	 * Returns the size of a group.
201
	 */
202 203 204 205 206 207
	getSize(group: IEditorGroup | GroupIdentifier): number;

	/**
	 * Sets the size of a group.
	 */
	setSize(group: IEditorGroup | GroupIdentifier, size: number): void;
208

209 210 211 212 213
	/**
	 * Arrange all groups according to the provided arrangement.
	 */
	arrangeGroups(arrangement: GroupsArrangement): void;

214 215 216 217 218
	/**
	 * Sets the orientation of the root group to be either vertical or horizontal.
	 */
	setGroupOrientation(orientation: GroupOrientation): void;

219
	/**
220 221 222 223 224
	 * Find a groupd in a specific scope:
	 * * `GroupLocation.FIRST`: the first group
	 * * `GroupLocation.LAST`: the last group
	 * * `GroupLocation.NEXT`: the next group from either the active one or `source`
	 * * `GroupLocation.PREVIOUS`: the previous group from either the active one or `source`
225 226
	 * * `GroupDirection.UP`: the next group above the active one or `source`
	 * * `GroupDirection.DOWN`: the next group below the active one or `source`
227 228
	 * * `GroupDirection.LEFT`: the next group to the left of the active one or `source`
	 * * `GroupDirection.RIGHT`: the next group to the right of the active one or `source`
229
	 *
230 231
	 * @param scope the scope of the group to search in
	 * @param source optional source to search from
232
	 */
233
	findGroup(scope: IFindGroupScope, source?: IEditorGroup | GroupIdentifier): IEditorGroup;
234

B
Benjamin Pasero 已提交
235
	/**
B
Benjamin Pasero 已提交
236 237
	 * Add a new group to the editor area. A new group is added by splitting a provided one in
	 * one of the four directions.
B
Benjamin Pasero 已提交
238
	 *
B
Benjamin Pasero 已提交
239
	 * @param location the group from which to split to add a new group
B
Benjamin Pasero 已提交
240
	 * @param direction the direction of where to split to
241
	 * @param options configure the newly group with options
B
Benjamin Pasero 已提交
242
	 */
243
	addGroup(location: IEditorGroup | GroupIdentifier, direction: GroupDirection, options?: IAddGroupOptions): IEditorGroup;
B
Benjamin Pasero 已提交
244 245 246 247

	/**
	 * Remove a group from the editor area.
	 */
248
	removeGroup(group: IEditorGroup | GroupIdentifier): void;
B
Benjamin Pasero 已提交
249 250 251 252 253 254 255 256

	/**
	 * Move a group to a new group in the editor area.
	 *
	 * @param group the group to move
	 * @param location the group from which to split to add the moved group
	 * @param direction the direction of where to split to
	 */
257
	moveGroup(group: IEditorGroup | GroupIdentifier, location: IEditorGroup | GroupIdentifier, direction: GroupDirection): IEditorGroup;
B
Benjamin Pasero 已提交
258

B
Benjamin Pasero 已提交
259
	/**
260 261 262
	 * Merge the editors of a group into a target group. By default, all editors will
	 * move and the source group will close. This behaviour can be configured via the
	 * `IMergeGroupOptions` options.
B
Benjamin Pasero 已提交
263 264 265
	 *
	 * @param group the group to merge
	 * @param target the target group to merge into
266 267 268 269
	 * @param options controls how the merge should be performed. by default all editors
	 * will be moved over to the target and the source group will close. Configure to
	 * `MOVE_EDITORS_KEEP_GROUP` to prevent the source group from closing. Set to
	 * `COPY_EDITORS` to copy the editors into the target instead of moding them.
B
Benjamin Pasero 已提交
270
	 */
271
	mergeGroup(group: IEditorGroup | GroupIdentifier, target: IEditorGroup | GroupIdentifier, options?: IMergeGroupOptions): IEditorGroup;
B
Benjamin Pasero 已提交
272

B
Benjamin Pasero 已提交
273 274 275 276 277 278 279
	/**
	 * Copy a group to a new group in the editor area.
	 *
	 * @param group the group to copy
	 * @param location the group from which to split to add the copied group
	 * @param direction the direction of where to split to
	 */
280
	copyGroup(group: IEditorGroup | GroupIdentifier, location: IEditorGroup | GroupIdentifier, direction: GroupDirection): IEditorGroup;
B
Benjamin Pasero 已提交
281 282
}

283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
export enum GroupChangeKind {

	/* Group Changes */
	GROUP_ACTIVE,
	GROUP_LABEL,

	/* Editor Changes */
	EDITOR_OPEN,
	EDITOR_CLOSE,
	EDITOR_MOVE,
	EDITOR_ACTIVE,
	EDITOR_LABEL,
	EDITOR_PIN,
	EDITOR_DIRTY
}

export interface IGroupChangeEvent {
	kind: GroupChangeKind;
	editor?: IEditorInput;
302
	editorIndex?: number;
303 304
}

305
export interface IEditorGroup {
306

307 308 309 310 311
	/**
	 * An aggregated event for when the group changes in any way.
	 */
	readonly onDidGroupChange: Event<IGroupChangeEvent>;

312 313 314 315
	/**
	 * A unique identifier of this group that remains identical even if the
	 * group is moved to different locations.
	 */
316
	readonly id: GroupIdentifier;
B
Benjamin Pasero 已提交
317

318 319 320
	/**
	 * A human readable label for the group. This label can change depending
	 * on the layout of all editor groups. Clients should listen on the
321
	 * `onDidGroupChange` event to react to that.
322 323 324
	 */
	readonly label: string;

325 326 327
	/**
	 * The active control is the currently visible control of the group.
	 */
328
	readonly activeControl: IEditor;
329 330 331 332 333

	/**
	 * The active editor is the currently visible editor of the group
	 * within the current active control.
	 */
334
	readonly activeEditor: IEditorInput;
335

336 337 338 339 340 341
	/**
	 * The editor in the group that is in preview mode if any. There can
	 * only ever be one editor in preview mode.
	 */
	readonly previewEditor: IEditorInput;

342 343 344 345 346 347 348 349
	/**
	 * The number of opend editors in this group.
	 */
	readonly count: number;

	/**
	 * All opened editors in the group. There can only be one editor active.
	 */
B
Benjamin Pasero 已提交
350
	readonly editors: ReadonlyArray<IEditorInput>;
B
Benjamin Pasero 已提交
351

352 353 354 355 356
	/**
	 * Returns the editor at a specific index of the group.
	 */
	getEditor(index: number): IEditorInput;

B
Benjamin Pasero 已提交
357 358 359 360 361 362 363
	/**
	 * Get all editors that are currently opened in the group optionally
	 * sorted by being most recent active. Will sort by sequential appearance
	 * by default (from left to right).
	 */
	getEditors(order?: EditorsOrder): ReadonlyArray<IEditorInput>;

364 365 366 367 368
	/**
	 * Returns the index of the editor in the group or -1 if not opened.
	 */
	getIndexOfEditor(editor: IEditorInput): number;

369
	/**
370 371 372 373
	 * Open an editor in this group.
	 *
	 * @returns a promise that is resolved when the active editor (if any)
	 * has finished loading
374
	 */
B
Benjamin Pasero 已提交
375
	openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions): TPromise<void>;
376

377
	/**
378 379 380 381
	 * Opens editors in this group.
	 *
	 * @returns a promise that is resolved when the active editor (if any)
	 * has finished loading
382
	 */
383
	openEditors(editors: IEditorInputWithOptions[]): TPromise<void>;
384

385
	/**
386 387 388
	 * Find out if the provided editor is opened in the group.
	 *
	 * Note: An editor can be opened but not actively visible.
389 390 391
	 */
	isOpened(editor: IEditorInput): boolean;

392 393 394 395 396 397 398 399 400 401
	/**
	 * Find out if the provided editor is pinned in the group.
	 */
	isPinned(editor: IEditorInput): boolean;

	/**
	 * Find out if the provided editor is active in the group.
	 */
	isActive(editor: IEditorInput): boolean;

B
Benjamin Pasero 已提交
402 403 404
	/**
	 * Move an editor from this group either within this group or to another group.
	 */
405
	moveEditor(editor: IEditorInput, target: IEditorGroup, options?: IMoveEditorOptions): void;
B
Benjamin Pasero 已提交
406

B
Benjamin Pasero 已提交
407 408 409 410 411
	/**
	 * Copy an editor from this group to another group.
	 *
	 * Note: It is currently not supported to show the same editor more than once in the same group.
	 */
412
	copyEditor(editor: IEditorInput, target: IEditorGroup, options?: ICopyEditorOptions): void;
B
Benjamin Pasero 已提交
413

414 415 416 417 418 419 420 421 422
	/**
	 * Close an editor from the group. This may trigger a confirmation dialog if
	 * the editor is dirty and thus returns a promise as value.
	 *
	 * @param editor the editor to close, or the currently active editor
	 * if unspecified.
	 *
	 * @returns a promise when the editor is closed.
	 */
423
	closeEditor(editor?: IEditorInput): TPromise<void>;
424

425 426 427 428 429 430
	/**
	 * Closes specific editors in this group. This may trigger a confirmation dialog if
	 * there are dirty editors and thus returns a promise as value.
	 *
	 * @returns a promise when all editors are closed.
	 */
431
	closeEditors(editors: IEditorInput[] | ICloseEditorsFilter): TPromise<void>;
432 433 434 435 436 437 438

	/**
	 * Closes all editors from the group. This may trigger a confirmation dialog if
	 * there are dirty editors and thus returns a promise as value.
	 *
	 * @returns a promise when all editors are closed.
	 */
439
	closeAllEditors(): TPromise<void>;
440

441 442 443 444 445 446 447 448
	/**
	 * Replaces editors in this group with the provided replacement.
	 *
	 * @param editors the editors to replace
	 *
	 * @returns a promise that is resolved when the replaced active
	 * editor (if any) has finished loading.
	 */
449
	replaceEditors(editors: IEditorReplacement[]): TPromise<void>;
450

451 452 453
	/**
	 * Set an editor to be pinned. A pinned editor is not replaced
	 * when another editor opens at the same location.
454
	 *
455
	 * @param editor the editor to pin, or the currently active editor
456
	 * if unspecified.
457 458
	 */
	pinEditor(editor?: IEditorInput): void;
459 460 461 462 463

	/**
	 * Move keyboard focus into the group.
	 */
	focus(): void;
464 465 466 467 468

	/**
	 * Invoke a function in the context of the services of this group.
	 */
	invokeWithinContext<T>(fn: (accessor: ServicesAccessor) => T): T;
469
}