views.ts 10.3 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 { Command } from 'vs/editor/common/modes';
S
Sandeep Somavarapu 已提交
7
import { UriComponents } from 'vs/base/common/uri';
M
Matt Bierner 已提交
8
import { Event, Emitter } from 'vs/base/common/event';
S
Sandeep Somavarapu 已提交
9 10 11 12
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ITreeViewDataProvider } from 'vs/workbench/common/views';
import { localize } from 'vs/nls';
import { IViewlet } from 'vs/workbench/common/viewlet';
S
Sandeep Somavarapu 已提交
13
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
14
import { IDisposable } from 'vs/base/common/lifecycle';
S
Sandeep Somavarapu 已提交
15
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
S
Sandeep Somavarapu 已提交
16
import { values } from 'vs/base/common/map';
S
Sandeep Somavarapu 已提交
17
import { Registry } from 'vs/platform/registry/common/platform';
S
Sandeep Somavarapu 已提交
18
import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
19
import { IAction } from 'vs/base/common/actions';
20
import { IMarkdownString } from 'vs/base/common/htmlContent';
21
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
S
Sandeep Somavarapu 已提交
22

23
export const TEST_VIEW_CONTAINER_ID = 'workbench.view.extension.test';
S
Sandeep Somavarapu 已提交
24

S
Sandeep Somavarapu 已提交
25 26 27
export namespace Extensions {
	export const ViewContainersRegistry = 'workbench.registry.view.containers';
}
S
Sandeep Somavarapu 已提交
28

S
Sandeep Somavarapu 已提交
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
export interface IViewContainersRegistry {
	/**
	 * An event that is triggerred when a view container is registered.
	 */
	readonly onDidRegister: Event<ViewContainer>;

	/**
	 * All registered view containers
	 */
	readonly all: ViewContainer[];

	/**
	 * Registers a view container with given id
	 * No op if a view container is already registered with the given id.
	 *
	 * @param id of the view container.
	 *
	 * @returns the registered ViewContainer.
	 */
48
	registerViewContainer(id: string, extensionId?: ExtensionIdentifier): ViewContainer;
S
Sandeep Somavarapu 已提交
49 50 51 52 53 54

	/**
	 * Returns the view container with given id.
	 *
	 * @returns the view container with given id.
	 */
55
	get(id: string): ViewContainer | undefined;
S
Sandeep Somavarapu 已提交
56
}
57

S
Sandeep Somavarapu 已提交
58
export class ViewContainer {
59
	protected constructor(readonly id: string, readonly extensionId: ExtensionIdentifier) { }
S
Sandeep Somavarapu 已提交
60 61 62 63
}

class ViewContainersRegistryImpl implements IViewContainersRegistry {

64
	private readonly _onDidRegister = new Emitter<ViewContainer>();
S
Sandeep Somavarapu 已提交
65
	readonly onDidRegister: Event<ViewContainer> = this._onDidRegister.event;
66

S
Sandeep Somavarapu 已提交
67 68 69 70 71 72
	private viewContainers: Map<string, ViewContainer> = new Map<string, ViewContainer>();

	get all(): ViewContainer[] {
		return values(this.viewContainers);
	}

73
	registerViewContainer(id: string, extensionId: ExtensionIdentifier): ViewContainer {
74 75 76
		const existing = this.viewContainers.get(id);
		if (existing) {
			return existing;
S
Sandeep Somavarapu 已提交
77
		}
78 79 80 81 82 83 84 85 86

		const viewContainer = new class extends ViewContainer {
			constructor() {
				super(id, extensionId);
			}
		};
		this.viewContainers.set(id, viewContainer);
		this._onDidRegister.fire(viewContainer);
		return viewContainer;
S
Sandeep Somavarapu 已提交
87 88
	}

89
	get(id: string): ViewContainer | undefined {
S
Sandeep Somavarapu 已提交
90 91
		return this.viewContainers.get(id);
	}
S
Sandeep Somavarapu 已提交
92 93
}

S
Sandeep Somavarapu 已提交
94 95
Registry.add(Extensions.ViewContainersRegistry, new ViewContainersRegistryImpl());

S
Sandeep Somavarapu 已提交
96 97 98 99 100 101
export interface IViewDescriptor {

	readonly id: string;

	readonly name: string;

B
Benjamin Pasero 已提交
102
	// TODO@Sandeep do we really need this?!
S
Sandeep Somavarapu 已提交
103 104 105 106 107 108 109 110 111 112 113
	readonly ctor: any;

	readonly when?: ContextKeyExpr;

	readonly order?: number;

	readonly weight?: number;

	readonly collapsed?: boolean;

	readonly canToggleVisibility?: boolean;
114

115
	// Applies only to newly created views
116
	readonly hideByDefault?: boolean;
S
Sandeep Somavarapu 已提交
117 118

	readonly focusCommand?: { id: string, keybindings?: IKeybindings };
S
Sandeep Somavarapu 已提交
119 120
}

121
export interface IViewDescriptorCollection {
S
Sandeep Somavarapu 已提交
122 123
	readonly onDidChangeActiveViews: Event<{ added: IViewDescriptor[], removed: IViewDescriptor[] }>;
	readonly activeViewDescriptors: IViewDescriptor[];
S
Sandeep Somavarapu 已提交
124
	readonly allViewDescriptors: IViewDescriptor[];
125 126
}

S
Sandeep Somavarapu 已提交
127 128
export interface IViewsRegistry {

129
	readonly onViewsRegistered: Event<{ views: IViewDescriptor[], viewContainer: ViewContainer }>;
S
Sandeep Somavarapu 已提交
130

131
	readonly onViewsDeregistered: Event<{ views: IViewDescriptor[], viewContainer: ViewContainer }>;
S
Sandeep Somavarapu 已提交
132

133 134
	readonly onDidChangeContainer: Event<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }>;

135
	registerViews(views: IViewDescriptor[], viewContainer: ViewContainer): void;
S
Sandeep Somavarapu 已提交
136

137
	deregisterViews(ids: string[], viewContainer: ViewContainer): void;
S
Sandeep Somavarapu 已提交
138

139 140
	moveViews(ids: string[], viewContainer: ViewContainer): void;

141
	getViews(viewContainer: ViewContainer): IViewDescriptor[];
S
Sandeep Somavarapu 已提交
142

M
Matt Bierner 已提交
143
	getView(id: string): IViewDescriptor | null;
S
Sandeep Somavarapu 已提交
144

145
	getViewContainer(id: string): ViewContainer | null;
S
Sandeep Somavarapu 已提交
146 147 148 149
}

export const ViewsRegistry: IViewsRegistry = new class implements IViewsRegistry {

150 151
	private readonly _onViewsRegistered: Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = new Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }>();
	readonly onViewsRegistered: Event<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = this._onViewsRegistered.event;
S
Sandeep Somavarapu 已提交
152

153 154
	private readonly _onViewsDeregistered: Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = new Emitter<{ views: IViewDescriptor[], viewContainer: ViewContainer }>();
	readonly onViewsDeregistered: Event<{ views: IViewDescriptor[], viewContainer: ViewContainer }> = this._onViewsDeregistered.event;
S
Sandeep Somavarapu 已提交
155

156 157 158
	private readonly _onDidChangeContainer: Emitter<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }> = new Emitter<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }>();
	readonly onDidChangeContainer: Event<{ views: IViewDescriptor[], from: ViewContainer, to: ViewContainer }> = this._onDidChangeContainer.event;

159
	private _viewContainers: ViewContainer[] = [];
S
Sandeep Somavarapu 已提交
160
	private _views: Map<ViewContainer, IViewDescriptor[]> = new Map<ViewContainer, IViewDescriptor[]>();
S
Sandeep Somavarapu 已提交
161

162
	registerViews(viewDescriptors: IViewDescriptor[], viewContainer: ViewContainer): void {
S
Sandeep Somavarapu 已提交
163
		if (viewDescriptors.length) {
164 165 166 167 168 169
			let views = this._views.get(viewContainer);
			if (!views) {
				views = [];
				this._views.set(viewContainer, views);
				this._viewContainers.push(viewContainer);
			}
S
Sandeep Somavarapu 已提交
170 171
			for (const viewDescriptor of viewDescriptors) {
				if (views.some(v => v.id === viewDescriptor.id)) {
172
					throw new Error(localize('duplicateId', "A view with id '{0}' is already registered in the container '{1}'", viewDescriptor.id, viewContainer.id));
S
Sandeep Somavarapu 已提交
173 174 175
				}
				views.push(viewDescriptor);
			}
176
			this._onViewsRegistered.fire({ views: viewDescriptors, viewContainer });
S
Sandeep Somavarapu 已提交
177 178 179
		}
	}

180 181
	deregisterViews(ids: string[], viewContainer: ViewContainer): void {
		const views = this._views.get(viewContainer);
S
Sandeep Somavarapu 已提交
182 183 184 185 186 187 188 189

		if (!views) {
			return;
		}

		const viewsToDeregister = views.filter(view => ids.indexOf(view.id) !== -1);

		if (viewsToDeregister.length) {
S
Sandeep Somavarapu 已提交
190 191
			const remaningViews = views.filter(view => ids.indexOf(view.id) === -1);
			if (remaningViews.length) {
192
				this._views.set(viewContainer, remaningViews);
S
Sandeep Somavarapu 已提交
193
			} else {
194 195
				this._views.delete(viewContainer);
				this._viewContainers.splice(this._viewContainers.indexOf(viewContainer), 1);
S
Sandeep Somavarapu 已提交
196
			}
197
			this._onViewsDeregistered.fire({ views: viewsToDeregister, viewContainer });
S
Sandeep Somavarapu 已提交
198 199 200 201
		}

	}

202 203 204 205 206 207 208 209 210 211 212
	moveViews(ids: string[], viewContainer: ViewContainer): void {
		this._views.forEach((views, container) => {
			if (container !== viewContainer) {
				const movedViews = views.filter(view => ids.indexOf(view.id) !== -1);
				if (movedViews.length) {
					this._onDidChangeContainer.fire({ views: movedViews, from: container, to: viewContainer });
				}
			}
		});
	}

S
Sandeep Somavarapu 已提交
213
	getViews(loc: ViewContainer): IViewDescriptor[] {
S
Sandeep Somavarapu 已提交
214 215 216
		return this._views.get(loc) || [];
	}

M
Matt Bierner 已提交
217
	getView(id: string): IViewDescriptor | null {
218
		for (const viewContainer of this._viewContainers) {
S
Sandeep Somavarapu 已提交
219
			const viewDescriptor = (this._views.get(viewContainer) || []).filter(v => v.id === id)[0];
S
Sandeep Somavarapu 已提交
220 221 222 223 224
			if (viewDescriptor) {
				return viewDescriptor;
			}
		}
		return null;
S
Sandeep Somavarapu 已提交
225
	}
S
Sandeep Somavarapu 已提交
226

227 228 229 230 231 232 233 234
	getViewContainer(viewId: string): ViewContainer | null {
		for (const viewContainer of this._viewContainers) {
			const viewDescriptor = (this._views.get(viewContainer) || []).filter(v => v.id === viewId)[0];
			if (viewDescriptor) {
				return viewContainer;
			}
		}
		return null;
S
Sandeep Somavarapu 已提交
235
	}
S
Sandeep Somavarapu 已提交
236 237
};

S
Sandeep Somavarapu 已提交
238 239 240 241 242 243
export interface IView {

	readonly id: string;

}

S
Sandeep Somavarapu 已提交
244 245
export interface IViewsViewlet extends IViewlet {

I
isidor 已提交
246
	openView(id: string, focus?: boolean): IView;
S
Sandeep Somavarapu 已提交
247 248 249

}

250 251 252 253 254
export const IViewsService = createDecorator<IViewsService>('viewsService');

export interface IViewsService {
	_serviceBrand: any;

M
Matt Bierner 已提交
255
	openView(id: string, focus?: boolean): Promise<IView | null>;
256 257

	getViewDescriptors(container: ViewContainer): IViewDescriptorCollection;
258 259
}

S
Sandeep Somavarapu 已提交
260 261
// Custom views

S
rename  
Sandeep Somavarapu 已提交
262
export interface ITreeView extends IDisposable {
263

264
	dataProvider: ITreeViewDataProvider;
S
Sandeep Somavarapu 已提交
265

266 267
	showCollapseAllAction: boolean;

268 269
	message: string | IMarkdownString;

270 271
	readonly visible: boolean;

272 273 274 275
	readonly onDidExpandItem: Event<ITreeItem>;

	readonly onDidCollapseItem: Event<ITreeItem>;

276 277
	readonly onDidChangeSelection: Event<ITreeItem[]>;

278 279
	readonly onDidChangeVisibility: Event<boolean>;

280
	readonly onDidChangeActions: Event<void>;
S
Sandeep Somavarapu 已提交
281

282
	refresh(treeItems?: ITreeItem[]): Promise<void>;
S
Sandeep Somavarapu 已提交
283

284
	setVisibility(visible: boolean): void;
S
Sandeep Somavarapu 已提交
285

286 287 288 289
	focus(): void;

	layout(height: number): void;

S
Sandeep Somavarapu 已提交
290
	show(container: HTMLElement);
291 292

	getOptimalWidth(): number;
S
Sandeep Somavarapu 已提交
293

J
Johannes Rieken 已提交
294
	reveal(item: ITreeItem): Promise<void>;
295

J
Johannes Rieken 已提交
296
	expand(itemOrItems: ITreeItem | ITreeItem[]): Promise<void>;
297 298 299 300

	setSelection(items: ITreeItem[]): void;

	setFocus(item: ITreeItem): void;
301 302 303 304

	getPrimaryActions(): IAction[];

	getSecondaryActions(): IAction[];
S
Sandeep Somavarapu 已提交
305 306
}

307 308 309 310 311 312 313 314 315 316
export interface IRevealOptions {

	select?: boolean;

	focus?: boolean;

	expand?: boolean | number;

}

317
export interface ITreeViewDescriptor extends IViewDescriptor {
S
Sandeep Somavarapu 已提交
318

S
rename  
Sandeep Somavarapu 已提交
319
	readonly treeView: ITreeView;
320

S
Sandeep Somavarapu 已提交
321
}
S
Sandeep Somavarapu 已提交
322 323 324

export type TreeViewItemHandleArg = {
	$treeViewId: string,
S
Sandeep Somavarapu 已提交
325
	$treeItemHandle: string
S
Sandeep Somavarapu 已提交
326 327 328 329 330 331 332 333
};

export enum TreeItemCollapsibleState {
	None = 0,
	Collapsed = 1,
	Expanded = 2
}

S
Sandeep Somavarapu 已提交
334 335 336 337
export interface ITreeItemLabel {

	label: string;

338
	highlights?: [number, number][];
S
Sandeep Somavarapu 已提交
339 340 341

}

S
Sandeep Somavarapu 已提交
342 343
export interface ITreeItem {

S
Sandeep Somavarapu 已提交
344
	handle: string;
S
Sandeep Somavarapu 已提交
345

S
Sandeep Somavarapu 已提交
346 347
	parentHandle: string;

S
Sandeep Somavarapu 已提交
348 349
	collapsibleState: TreeItemCollapsibleState;

S
Sandeep Somavarapu 已提交
350
	label?: ITreeItemLabel;
S
Sandeep Somavarapu 已提交
351

352 353
	description?: string | boolean;

354
	icon?: UriComponents;
S
Sandeep Somavarapu 已提交
355

356
	iconDark?: UriComponents;
S
Sandeep Somavarapu 已提交
357

S
Sandeep Somavarapu 已提交
358
	themeIcon?: ThemeIcon;
S
Sandeep Somavarapu 已提交
359

S
Sandeep Somavarapu 已提交
360 361
	resourceUri?: UriComponents;

S
Sandeep Somavarapu 已提交
362 363
	tooltip?: string;

S
Sandeep Somavarapu 已提交
364 365 366 367 368 369 370 371 372
	contextValue?: string;

	command?: Command;

	children?: ITreeItem[];
}

export interface ITreeViewDataProvider {

373
	getChildren(element?: ITreeItem): Promise<ITreeItem[]>;
S
Sandeep Somavarapu 已提交
374

I
isidor 已提交
375
}