Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/common/views.ts
3292 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Command } from '../../editor/common/languages.js';
7
import { UriComponents, URI } from '../../base/common/uri.js';
8
import { Event, Emitter } from '../../base/common/event.js';
9
import { ContextKeyExpression } from '../../platform/contextkey/common/contextkey.js';
10
import { localize } from '../../nls.js';
11
import { createDecorator } from '../../platform/instantiation/common/instantiation.js';
12
import { IDisposable, Disposable, toDisposable } from '../../base/common/lifecycle.js';
13
import { ThemeIcon } from '../../base/common/themables.js';
14
import { getOrSet, SetMap } from '../../base/common/map.js';
15
import { Registry } from '../../platform/registry/common/platform.js';
16
import { IKeybindings } from '../../platform/keybinding/common/keybindingsRegistry.js';
17
import { ExtensionIdentifier } from '../../platform/extensions/common/extensions.js';
18
import { SyncDescriptor } from '../../platform/instantiation/common/descriptors.js';
19
import { IProgressIndicator } from '../../platform/progress/common/progress.js';
20
import Severity from '../../base/common/severity.js';
21
import { IAccessibilityInformation } from '../../platform/accessibility/common/accessibility.js';
22
import { IMarkdownString, MarkdownString } from '../../base/common/htmlContent.js';
23
import { mixin } from '../../base/common/objects.js';
24
import { Codicon } from '../../base/common/codicons.js';
25
import { registerIcon } from '../../platform/theme/common/iconRegistry.js';
26
import { CancellationToken } from '../../base/common/cancellation.js';
27
import { VSDataTransfer } from '../../base/common/dataTransfer.js';
28
import { ILocalizedString } from '../../platform/action/common/action.js';
29
30
export const VIEWS_LOG_ID = 'views';
31
export const VIEWS_LOG_NAME = localize('views log', "Views");
32
export const defaultViewIcon = registerIcon('default-view-icon', Codicon.window, localize('defaultViewIcon', 'Default view icon.'));
33
34
export namespace Extensions {
35
export const ViewContainersRegistry = 'workbench.registry.view.containers';
36
export const ViewsRegistry = 'workbench.registry.view';
37
}
38
39
export const enum ViewContainerLocation {
40
Sidebar,
41
Panel,
42
AuxiliaryBar
43
}
44
45
export const ViewContainerLocations = [ViewContainerLocation.Sidebar, ViewContainerLocation.Panel, ViewContainerLocation.AuxiliaryBar];
46
47
export function ViewContainerLocationToString(viewContainerLocation: ViewContainerLocation) {
48
switch (viewContainerLocation) {
49
case ViewContainerLocation.Sidebar: return 'sidebar';
50
case ViewContainerLocation.Panel: return 'panel';
51
case ViewContainerLocation.AuxiliaryBar: return 'auxiliarybar';
52
}
53
}
54
55
type OpenCommandActionDescriptor = {
56
readonly id: string;
57
readonly title?: ILocalizedString | string;
58
readonly mnemonicTitle?: string;
59
readonly order?: number;
60
readonly keybindings?: IKeybindings & { when?: ContextKeyExpression };
61
};
62
63
/**
64
* View Container Contexts
65
*/
66
67
export interface IViewContainerDescriptor {
68
69
/**
70
* The id of the view container
71
*/
72
readonly id: string;
73
74
/**
75
* The title of the view container
76
*/
77
readonly title: ILocalizedString;
78
79
/**
80
* Icon representation of the View container
81
*/
82
readonly icon?: ThemeIcon | URI;
83
84
/**
85
* Order of the view container.
86
*/
87
readonly order?: number;
88
89
/**
90
* IViewPaneContainer Ctor to instantiate
91
*/
92
readonly ctorDescriptor: SyncDescriptor<IViewPaneContainer>;
93
94
/**
95
* Descriptor for open view container command
96
* If not provided, view container info (id, title) is used.
97
*
98
* Note: To prevent registering open command, use `doNotRegisterOpenCommand` flag while registering the view container
99
*/
100
readonly openCommandActionDescriptor?: OpenCommandActionDescriptor;
101
102
/**
103
* Storage id to use to store the view container state.
104
* If not provided, it will be derived.
105
*/
106
readonly storageId?: string;
107
108
/**
109
* If enabled, view container is not shown if it has no active views.
110
*/
111
readonly hideIfEmpty?: boolean;
112
113
/**
114
* Id of the extension that contributed the view container
115
*/
116
readonly extensionId?: ExtensionIdentifier;
117
118
readonly alwaysUseContainerInfo?: boolean;
119
120
readonly viewOrderDelegate?: ViewOrderDelegate;
121
122
readonly rejectAddedViews?: boolean;
123
124
requestedIndex?: number;
125
}
126
127
export interface IViewContainersRegistry {
128
/**
129
* An event that is triggered when a view container is registered.
130
*/
131
readonly onDidRegister: Event<{ viewContainer: ViewContainer; viewContainerLocation: ViewContainerLocation }>;
132
133
/**
134
* An event that is triggered when a view container is deregistered.
135
*/
136
readonly onDidDeregister: Event<{ viewContainer: ViewContainer; viewContainerLocation: ViewContainerLocation }>;
137
138
/**
139
* All registered view containers
140
*/
141
readonly all: ViewContainer[];
142
143
/**
144
* Registers a view container to given location.
145
* No op if a view container is already registered.
146
*
147
* @param viewContainerDescriptor descriptor of view container
148
* @param location location of the view container
149
*
150
* @returns the registered ViewContainer.
151
*/
152
registerViewContainer(viewContainerDescriptor: IViewContainerDescriptor, location: ViewContainerLocation, options?: { isDefault?: boolean; doNotRegisterOpenCommand?: boolean }): ViewContainer;
153
154
/**
155
* Deregisters the given view container
156
* No op if the view container is not registered
157
*/
158
deregisterViewContainer(viewContainer: ViewContainer): void;
159
160
/**
161
* Returns the view container with given id.
162
*
163
* @returns the view container with given id.
164
*/
165
get(id: string): ViewContainer | undefined;
166
167
/**
168
* Returns all view containers in the given location
169
*/
170
getViewContainers(location: ViewContainerLocation): ViewContainer[];
171
172
/**
173
* Returns the view container location
174
*/
175
getViewContainerLocation(container: ViewContainer): ViewContainerLocation;
176
177
/**
178
* Return the default view container from the given location
179
*/
180
getDefaultViewContainer(location: ViewContainerLocation): ViewContainer | undefined;
181
}
182
183
interface ViewOrderDelegate {
184
getOrder(group?: string): number | undefined;
185
}
186
187
export interface ViewContainer extends IViewContainerDescriptor { }
188
189
interface RelaxedViewContainer extends ViewContainer {
190
191
openCommandActionDescriptor?: OpenCommandActionDescriptor;
192
}
193
194
class ViewContainersRegistryImpl extends Disposable implements IViewContainersRegistry {
195
196
private readonly _onDidRegister = this._register(new Emitter<{ viewContainer: ViewContainer; viewContainerLocation: ViewContainerLocation }>());
197
readonly onDidRegister: Event<{ viewContainer: ViewContainer; viewContainerLocation: ViewContainerLocation }> = this._onDidRegister.event;
198
199
private readonly _onDidDeregister = this._register(new Emitter<{ viewContainer: ViewContainer; viewContainerLocation: ViewContainerLocation }>());
200
readonly onDidDeregister: Event<{ viewContainer: ViewContainer; viewContainerLocation: ViewContainerLocation }> = this._onDidDeregister.event;
201
202
private readonly viewContainers: Map<ViewContainerLocation, ViewContainer[]> = new Map<ViewContainerLocation, ViewContainer[]>();
203
private readonly defaultViewContainers: ViewContainer[] = [];
204
205
get all(): ViewContainer[] {
206
return [...this.viewContainers.values()].flat();
207
}
208
209
registerViewContainer(viewContainerDescriptor: IViewContainerDescriptor, viewContainerLocation: ViewContainerLocation, options?: { isDefault?: boolean; doNotRegisterOpenCommand?: boolean }): ViewContainer {
210
const existing = this.get(viewContainerDescriptor.id);
211
if (existing) {
212
return existing;
213
}
214
215
const viewContainer: RelaxedViewContainer = viewContainerDescriptor;
216
viewContainer.openCommandActionDescriptor = options?.doNotRegisterOpenCommand ? undefined : (viewContainer.openCommandActionDescriptor ?? { id: viewContainer.id });
217
const viewContainers = getOrSet(this.viewContainers, viewContainerLocation, []);
218
viewContainers.push(viewContainer);
219
if (options?.isDefault) {
220
this.defaultViewContainers.push(viewContainer);
221
}
222
this._onDidRegister.fire({ viewContainer, viewContainerLocation });
223
return viewContainer;
224
}
225
226
deregisterViewContainer(viewContainer: ViewContainer): void {
227
for (const viewContainerLocation of this.viewContainers.keys()) {
228
const viewContainers = this.viewContainers.get(viewContainerLocation)!;
229
const index = viewContainers?.indexOf(viewContainer);
230
if (index !== -1) {
231
viewContainers?.splice(index, 1);
232
if (viewContainers.length === 0) {
233
this.viewContainers.delete(viewContainerLocation);
234
}
235
this._onDidDeregister.fire({ viewContainer, viewContainerLocation });
236
return;
237
}
238
}
239
}
240
241
get(id: string): ViewContainer | undefined {
242
return this.all.filter(viewContainer => viewContainer.id === id)[0];
243
}
244
245
getViewContainers(location: ViewContainerLocation): ViewContainer[] {
246
return [...(this.viewContainers.get(location) || [])];
247
}
248
249
getViewContainerLocation(container: ViewContainer): ViewContainerLocation {
250
return [...this.viewContainers.keys()].filter(location => this.getViewContainers(location).filter(viewContainer => viewContainer?.id === container.id).length > 0)[0];
251
}
252
253
getDefaultViewContainer(location: ViewContainerLocation): ViewContainer | undefined {
254
return this.defaultViewContainers.find(viewContainer => this.getViewContainerLocation(viewContainer) === location);
255
}
256
}
257
258
Registry.add(Extensions.ViewContainersRegistry, new ViewContainersRegistryImpl());
259
260
export interface IViewDescriptor {
261
262
readonly type?: string;
263
264
readonly id: string;
265
266
readonly name: ILocalizedString;
267
268
readonly ctorDescriptor: SyncDescriptor<IView>;
269
270
readonly when?: ContextKeyExpression;
271
272
readonly order?: number;
273
274
readonly weight?: number;
275
276
readonly collapsed?: boolean;
277
278
readonly canToggleVisibility?: boolean;
279
280
readonly canMoveView?: boolean;
281
282
readonly containerIcon?: ThemeIcon | URI;
283
284
readonly containerTitle?: string;
285
286
readonly singleViewPaneContainerTitle?: string;
287
288
// Applies only to newly created views
289
readonly hideByDefault?: boolean;
290
291
readonly workspace?: boolean;
292
293
readonly focusCommand?: { id: string; keybindings?: IKeybindings };
294
295
// For contributed remote explorer views
296
readonly group?: string;
297
298
readonly remoteAuthority?: string | string[];
299
readonly virtualWorkspace?: string;
300
301
readonly openCommandActionDescriptor?: OpenCommandActionDescriptor;
302
303
readonly accessibilityHelpContent?: MarkdownString;
304
}
305
306
export interface ICustomViewDescriptor extends IViewDescriptor {
307
readonly extensionId: ExtensionIdentifier;
308
readonly originalContainerId: string;
309
readonly treeView?: ITreeView;
310
}
311
312
export interface IViewDescriptorRef {
313
viewDescriptor: IViewDescriptor;
314
index: number;
315
}
316
317
export interface IAddedViewDescriptorRef extends IViewDescriptorRef {
318
collapsed: boolean;
319
size?: number;
320
}
321
322
export interface IAddedViewDescriptorState {
323
viewDescriptor: IViewDescriptor;
324
collapsed?: boolean;
325
visible?: boolean;
326
}
327
328
export interface IViewContainerModel {
329
330
readonly viewContainer: ViewContainer;
331
332
readonly title: string;
333
readonly icon: ThemeIcon | URI | undefined;
334
readonly keybindingId: string | undefined;
335
readonly onDidChangeContainerInfo: Event<{ title?: boolean; icon?: boolean; keybindingId?: boolean; badgeEnablement?: boolean }>;
336
337
readonly allViewDescriptors: ReadonlyArray<IViewDescriptor>;
338
readonly onDidChangeAllViewDescriptors: Event<{ added: ReadonlyArray<IViewDescriptor>; removed: ReadonlyArray<IViewDescriptor> }>;
339
340
readonly activeViewDescriptors: ReadonlyArray<IViewDescriptor>;
341
readonly onDidChangeActiveViewDescriptors: Event<{ added: ReadonlyArray<IViewDescriptor>; removed: ReadonlyArray<IViewDescriptor> }>;
342
343
readonly visibleViewDescriptors: ReadonlyArray<IViewDescriptor>;
344
readonly onDidAddVisibleViewDescriptors: Event<IAddedViewDescriptorRef[]>;
345
readonly onDidRemoveVisibleViewDescriptors: Event<IViewDescriptorRef[]>;
346
readonly onDidMoveVisibleViewDescriptors: Event<{ from: IViewDescriptorRef; to: IViewDescriptorRef }>;
347
348
isVisible(id: string): boolean;
349
setVisible(id: string, visible: boolean): void;
350
351
isCollapsed(id: string): boolean;
352
setCollapsed(id: string, collapsed: boolean): void;
353
354
getSize(id: string): number | undefined;
355
setSizes(newSizes: readonly { id: string; size: number }[]): void;
356
357
move(from: string, to: string): void;
358
}
359
360
export enum ViewContentGroups {
361
Open = '2_open',
362
Debug = '4_debug',
363
SCM = '5_scm',
364
More = '9_more'
365
}
366
367
export interface IViewContentDescriptor {
368
readonly content: string;
369
/**
370
* Whether to render all but the first button as secondary
371
* if there are buttons in the `content` property.
372
*/
373
readonly renderSecondaryButtons?: boolean;
374
readonly when?: ContextKeyExpression | 'default';
375
readonly group?: string;
376
readonly order?: number;
377
readonly precondition?: ContextKeyExpression | undefined;
378
}
379
380
export interface IViewsRegistry {
381
382
readonly onViewsRegistered: Event<{ views: IViewDescriptor[]; viewContainer: ViewContainer }[]>;
383
384
readonly onViewsDeregistered: Event<{ views: IViewDescriptor[]; viewContainer: ViewContainer }>;
385
386
readonly onDidChangeContainer: Event<{ views: IViewDescriptor[]; from: ViewContainer; to: ViewContainer }>;
387
388
registerViews(views: IViewDescriptor[], viewContainer: ViewContainer): void;
389
390
registerViews2(views: { views: IViewDescriptor[]; viewContainer: ViewContainer }[]): void;
391
392
deregisterViews(views: IViewDescriptor[], viewContainer: ViewContainer): void;
393
394
moveViews(views: IViewDescriptor[], viewContainer: ViewContainer): void;
395
396
getViews(viewContainer: ViewContainer): IViewDescriptor[];
397
398
getView(id: string): IViewDescriptor | null;
399
400
getViewContainer(id: string): ViewContainer | null;
401
402
readonly onDidChangeViewWelcomeContent: Event<string>;
403
registerViewWelcomeContent(id: string, viewContent: IViewContentDescriptor): IDisposable;
404
registerViewWelcomeContent2<TKey>(id: string, viewContentMap: Map<TKey, IViewContentDescriptor>): Map<TKey, IDisposable>;
405
getViewWelcomeContent(id: string): IViewContentDescriptor[];
406
}
407
408
function compareViewContentDescriptors(a: IViewContentDescriptor, b: IViewContentDescriptor): number {
409
const aGroup = a.group ?? ViewContentGroups.More;
410
const bGroup = b.group ?? ViewContentGroups.More;
411
if (aGroup !== bGroup) {
412
return aGroup.localeCompare(bGroup);
413
}
414
return (a.order ?? 5) - (b.order ?? 5);
415
}
416
417
class ViewsRegistry extends Disposable implements IViewsRegistry {
418
419
private readonly _onViewsRegistered = this._register(new Emitter<{ views: IViewDescriptor[]; viewContainer: ViewContainer }[]>());
420
readonly onViewsRegistered = this._onViewsRegistered.event;
421
422
private readonly _onViewsDeregistered: Emitter<{ views: IViewDescriptor[]; viewContainer: ViewContainer }> = this._register(new Emitter<{ views: IViewDescriptor[]; viewContainer: ViewContainer }>());
423
readonly onViewsDeregistered: Event<{ views: IViewDescriptor[]; viewContainer: ViewContainer }> = this._onViewsDeregistered.event;
424
425
private readonly _onDidChangeContainer: Emitter<{ views: IViewDescriptor[]; from: ViewContainer; to: ViewContainer }> = this._register(new Emitter<{ views: IViewDescriptor[]; from: ViewContainer; to: ViewContainer }>());
426
readonly onDidChangeContainer: Event<{ views: IViewDescriptor[]; from: ViewContainer; to: ViewContainer }> = this._onDidChangeContainer.event;
427
428
private readonly _onDidChangeViewWelcomeContent: Emitter<string> = this._register(new Emitter<string>());
429
readonly onDidChangeViewWelcomeContent: Event<string> = this._onDidChangeViewWelcomeContent.event;
430
431
private _viewContainers: ViewContainer[] = [];
432
private _views: Map<ViewContainer, IViewDescriptor[]> = new Map<ViewContainer, IViewDescriptor[]>();
433
private _viewWelcomeContents = new SetMap<string, IViewContentDescriptor>();
434
435
registerViews(views: IViewDescriptor[], viewContainer: ViewContainer): void {
436
this.registerViews2([{ views, viewContainer }]);
437
}
438
439
registerViews2(views: { views: IViewDescriptor[]; viewContainer: ViewContainer }[]): void {
440
views.forEach(({ views, viewContainer }) => this.addViews(views, viewContainer));
441
this._onViewsRegistered.fire(views);
442
}
443
444
deregisterViews(viewDescriptors: IViewDescriptor[], viewContainer: ViewContainer): void {
445
const views = this.removeViews(viewDescriptors, viewContainer);
446
if (views.length) {
447
this._onViewsDeregistered.fire({ views, viewContainer });
448
}
449
}
450
451
moveViews(viewsToMove: IViewDescriptor[], viewContainer: ViewContainer): void {
452
for (const container of this._views.keys()) {
453
if (container !== viewContainer) {
454
const views = this.removeViews(viewsToMove, container);
455
if (views.length) {
456
this.addViews(views, viewContainer);
457
this._onDidChangeContainer.fire({ views, from: container, to: viewContainer });
458
}
459
}
460
}
461
}
462
463
getViews(loc: ViewContainer): IViewDescriptor[] {
464
return this._views.get(loc) || [];
465
}
466
467
getView(id: string): IViewDescriptor | null {
468
for (const viewContainer of this._viewContainers) {
469
const viewDescriptor = (this._views.get(viewContainer) || []).filter(v => v.id === id)[0];
470
if (viewDescriptor) {
471
return viewDescriptor;
472
}
473
}
474
return null;
475
}
476
477
getViewContainer(viewId: string): ViewContainer | null {
478
for (const viewContainer of this._viewContainers) {
479
const viewDescriptor = (this._views.get(viewContainer) || []).filter(v => v.id === viewId)[0];
480
if (viewDescriptor) {
481
return viewContainer;
482
}
483
}
484
return null;
485
}
486
487
registerViewWelcomeContent(id: string, viewContent: IViewContentDescriptor): IDisposable {
488
this._viewWelcomeContents.add(id, viewContent);
489
this._onDidChangeViewWelcomeContent.fire(id);
490
491
return toDisposable(() => {
492
this._viewWelcomeContents.delete(id, viewContent);
493
this._onDidChangeViewWelcomeContent.fire(id);
494
});
495
}
496
497
registerViewWelcomeContent2<TKey>(id: string, viewContentMap: Map<TKey, IViewContentDescriptor>): Map<TKey, IDisposable> {
498
const disposables = new Map<TKey, IDisposable>();
499
500
for (const [key, content] of viewContentMap) {
501
this._viewWelcomeContents.add(id, content);
502
503
disposables.set(key, toDisposable(() => {
504
this._viewWelcomeContents.delete(id, content);
505
this._onDidChangeViewWelcomeContent.fire(id);
506
}));
507
}
508
this._onDidChangeViewWelcomeContent.fire(id);
509
510
return disposables;
511
}
512
513
getViewWelcomeContent(id: string): IViewContentDescriptor[] {
514
const result: IViewContentDescriptor[] = [];
515
this._viewWelcomeContents.forEach(id, descriptor => result.push(descriptor));
516
return result.sort(compareViewContentDescriptors);
517
}
518
519
private addViews(viewDescriptors: IViewDescriptor[], viewContainer: ViewContainer): void {
520
let views = this._views.get(viewContainer);
521
if (!views) {
522
views = [];
523
this._views.set(viewContainer, views);
524
this._viewContainers.push(viewContainer);
525
}
526
for (const viewDescriptor of viewDescriptors) {
527
if (this.getView(viewDescriptor.id) !== null) {
528
throw new Error(localize('duplicateId', "A view with id '{0}' is already registered", viewDescriptor.id));
529
}
530
views.push(viewDescriptor);
531
}
532
}
533
534
private removeViews(viewDescriptors: IViewDescriptor[], viewContainer: ViewContainer): IViewDescriptor[] {
535
const views = this._views.get(viewContainer);
536
if (!views) {
537
return [];
538
}
539
const viewsToDeregister: IViewDescriptor[] = [];
540
const remaningViews: IViewDescriptor[] = [];
541
for (const view of views) {
542
if (!viewDescriptors.includes(view)) {
543
remaningViews.push(view);
544
} else {
545
viewsToDeregister.push(view);
546
}
547
}
548
if (viewsToDeregister.length) {
549
if (remaningViews.length) {
550
this._views.set(viewContainer, remaningViews);
551
} else {
552
this._views.delete(viewContainer);
553
this._viewContainers.splice(this._viewContainers.indexOf(viewContainer), 1);
554
}
555
}
556
return viewsToDeregister;
557
}
558
}
559
560
Registry.add(Extensions.ViewsRegistry, new ViewsRegistry());
561
562
export interface IView {
563
564
readonly id: string;
565
566
focus(): void;
567
568
isVisible(): boolean;
569
570
isBodyVisible(): boolean;
571
572
setExpanded(expanded: boolean): boolean;
573
574
getProgressIndicator(): IProgressIndicator | undefined;
575
}
576
577
export const IViewDescriptorService = createDecorator<IViewDescriptorService>('viewDescriptorService');
578
579
export enum ViewVisibilityState {
580
Default = 0,
581
Expand = 1
582
}
583
584
export interface IViewDescriptorService {
585
586
readonly _serviceBrand: undefined;
587
588
// ViewContainers
589
readonly viewContainers: ReadonlyArray<ViewContainer>;
590
readonly onDidChangeViewContainers: Event<{ added: ReadonlyArray<{ container: ViewContainer; location: ViewContainerLocation }>; removed: ReadonlyArray<{ container: ViewContainer; location: ViewContainerLocation }> }>;
591
592
getDefaultViewContainer(location: ViewContainerLocation): ViewContainer | undefined;
593
getViewContainerById(id: string): ViewContainer | null;
594
isViewContainerRemovedPermanently(id: string): boolean;
595
getDefaultViewContainerLocation(viewContainer: ViewContainer): ViewContainerLocation | null;
596
getViewContainerLocation(viewContainer: ViewContainer): ViewContainerLocation | null;
597
getViewContainersByLocation(location: ViewContainerLocation): ViewContainer[];
598
getViewContainerModel(viewContainer: ViewContainer): IViewContainerModel;
599
600
readonly onDidChangeContainerLocation: Event<{ viewContainer: ViewContainer; from: ViewContainerLocation; to: ViewContainerLocation }>;
601
moveViewContainerToLocation(viewContainer: ViewContainer, location: ViewContainerLocation, requestedIndex?: number, reason?: string): void;
602
603
getViewContainerBadgeEnablementState(id: string): boolean;
604
setViewContainerBadgeEnablementState(id: string, badgesEnabled: boolean): void;
605
606
// Views
607
getViewDescriptorById(id: string): IViewDescriptor | null;
608
getViewContainerByViewId(id: string): ViewContainer | null;
609
getDefaultContainerById(id: string): ViewContainer | null;
610
getViewLocationById(id: string): ViewContainerLocation | null;
611
612
readonly onDidChangeContainer: Event<{ views: IViewDescriptor[]; from: ViewContainer; to: ViewContainer }>;
613
moveViewsToContainer(views: IViewDescriptor[], viewContainer: ViewContainer, visibilityState?: ViewVisibilityState, reason?: string): void;
614
615
readonly onDidChangeLocation: Event<{ views: IViewDescriptor[]; from: ViewContainerLocation; to: ViewContainerLocation }>;
616
moveViewToLocation(view: IViewDescriptor, location: ViewContainerLocation, reason?: string): void;
617
618
reset(): void;
619
}
620
621
// Custom views
622
623
export interface ITreeView extends IDisposable {
624
625
dataProvider: ITreeViewDataProvider | undefined;
626
627
dragAndDropController?: ITreeViewDragAndDropController;
628
629
showCollapseAllAction: boolean;
630
631
canSelectMany: boolean;
632
633
manuallyManageCheckboxes: boolean;
634
635
message?: string | IMarkdownString;
636
637
title: string;
638
639
description: string | undefined;
640
641
badge: IViewBadge | undefined;
642
643
readonly visible: boolean;
644
645
readonly onDidExpandItem: Event<ITreeItem>;
646
647
readonly onDidCollapseItem: Event<ITreeItem>;
648
649
readonly onDidChangeSelectionAndFocus: Event<{ selection: readonly ITreeItem[]; focus: ITreeItem }>;
650
651
readonly onDidChangeVisibility: Event<boolean>;
652
653
readonly onDidChangeActions: Event<void>;
654
655
readonly onDidChangeTitle: Event<string>;
656
657
readonly onDidChangeDescription: Event<string | undefined>;
658
659
readonly onDidChangeWelcomeState: Event<void>;
660
661
readonly onDidChangeCheckboxState: Event<readonly ITreeItem[]>;
662
663
readonly container: any | undefined;
664
665
// checkboxesChanged is a subset of treeItems
666
refresh(treeItems?: readonly ITreeItem[], checkboxesChanged?: readonly ITreeItem[]): Promise<void>;
667
668
setVisibility(visible: boolean): void;
669
670
focus(): void;
671
672
layout(height: number, width: number): void;
673
674
getOptimalWidth(): number;
675
676
reveal(item: ITreeItem): Promise<void>;
677
678
expand(itemOrItems: ITreeItem | ITreeItem[]): Promise<void>;
679
680
isCollapsed(item: ITreeItem): boolean;
681
682
setSelection(items: ITreeItem[]): void;
683
684
getSelection(): ITreeItem[];
685
686
setFocus(item?: ITreeItem): void;
687
688
show(container: any): void;
689
}
690
691
export interface IRevealOptions {
692
693
select?: boolean;
694
695
focus?: boolean;
696
697
expand?: boolean | number;
698
699
}
700
701
export interface ITreeViewDescriptor extends IViewDescriptor {
702
treeView: ITreeView;
703
}
704
705
export type TreeViewPaneHandleArg = {
706
$treeViewId: string;
707
$selectedTreeItems?: boolean;
708
$focusedTreeItem?: boolean;
709
};
710
711
export type TreeViewItemHandleArg = {
712
$treeViewId: string;
713
$treeItemHandle: string;
714
};
715
716
export enum TreeItemCollapsibleState {
717
None = 0,
718
Collapsed = 1,
719
Expanded = 2
720
}
721
722
export interface ITreeItemLabel {
723
724
label: string;
725
726
highlights?: [number, number][];
727
728
strikethrough?: boolean;
729
730
}
731
732
export type TreeCommand = Command & { originalId?: string };
733
734
export interface ITreeItemCheckboxState {
735
isChecked: boolean;
736
tooltip?: string;
737
accessibilityInformation?: IAccessibilityInformation;
738
}
739
740
export interface ITreeItem {
741
742
handle: string;
743
744
parentHandle?: string;
745
746
collapsibleState: TreeItemCollapsibleState;
747
748
label?: ITreeItemLabel;
749
750
description?: string | boolean;
751
752
icon?: UriComponents;
753
754
iconDark?: UriComponents;
755
756
themeIcon?: ThemeIcon;
757
758
resourceUri?: UriComponents;
759
760
tooltip?: string | IMarkdownString;
761
762
contextValue?: string;
763
764
command?: TreeCommand;
765
766
children?: ITreeItem[];
767
768
parent?: ITreeItem;
769
770
accessibilityInformation?: IAccessibilityInformation;
771
772
checkbox?: ITreeItemCheckboxState;
773
}
774
775
export class ResolvableTreeItem implements ITreeItem {
776
handle!: string;
777
parentHandle?: string;
778
collapsibleState!: TreeItemCollapsibleState;
779
label?: ITreeItemLabel;
780
description?: string | boolean;
781
icon?: UriComponents;
782
iconDark?: UriComponents;
783
themeIcon?: ThemeIcon;
784
resourceUri?: UriComponents;
785
tooltip?: string | IMarkdownString;
786
contextValue?: string;
787
command?: Command & { originalId?: string };
788
children?: ITreeItem[];
789
accessibilityInformation?: IAccessibilityInformation;
790
resolve: (token: CancellationToken) => Promise<void>;
791
private resolved: boolean = false;
792
private _hasResolve: boolean = false;
793
constructor(treeItem: ITreeItem, resolve?: ((token: CancellationToken) => Promise<ITreeItem | undefined>)) {
794
mixin(this, treeItem);
795
this._hasResolve = !!resolve;
796
this.resolve = async (token: CancellationToken) => {
797
if (resolve && !this.resolved) {
798
const resolvedItem = await resolve(token);
799
if (resolvedItem) {
800
// Resolvable elements. Currently tooltip and command.
801
this.tooltip = this.tooltip ?? resolvedItem.tooltip;
802
this.command = this.command ?? resolvedItem.command;
803
}
804
}
805
if (!token.isCancellationRequested) {
806
this.resolved = true;
807
}
808
};
809
}
810
get hasResolve(): boolean {
811
return this._hasResolve;
812
}
813
public resetResolve() {
814
this.resolved = false;
815
}
816
public asTreeItem(): ITreeItem {
817
return {
818
handle: this.handle,
819
parentHandle: this.parentHandle,
820
collapsibleState: this.collapsibleState,
821
label: this.label,
822
description: this.description,
823
icon: this.icon,
824
iconDark: this.iconDark,
825
themeIcon: this.themeIcon,
826
resourceUri: this.resourceUri,
827
tooltip: this.tooltip,
828
contextValue: this.contextValue,
829
command: this.command,
830
children: this.children,
831
accessibilityInformation: this.accessibilityInformation
832
};
833
}
834
}
835
836
export class NoTreeViewError extends Error {
837
override readonly name = 'NoTreeViewError';
838
constructor(treeViewId: string) {
839
super(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId));
840
}
841
static is(err: unknown): err is NoTreeViewError {
842
return !!err && (err as Error).name === 'NoTreeViewError';
843
}
844
}
845
846
export interface ITreeViewDataProvider {
847
readonly isTreeEmpty?: boolean;
848
onDidChangeEmpty?: Event<void>;
849
getChildren(element?: ITreeItem): Promise<ITreeItem[] | undefined>;
850
getChildrenBatch?(element?: ITreeItem[]): Promise<ITreeItem[][] | undefined>;
851
}
852
853
export interface ITreeViewDragAndDropController {
854
readonly dropMimeTypes: string[];
855
readonly dragMimeTypes: string[];
856
handleDrag(sourceTreeItemHandles: string[], operationUuid: string, token: CancellationToken): Promise<VSDataTransfer | undefined>;
857
handleDrop(elements: VSDataTransfer, target: ITreeItem | undefined, token: CancellationToken, operationUuid?: string, sourceTreeId?: string, sourceTreeItemHandles?: string[]): Promise<void>;
858
}
859
860
export interface IEditableData {
861
validationMessage: (value: string) => { content: string; severity: Severity } | null;
862
placeholder?: string | null;
863
startingValue?: string | null;
864
onFinish: (value: string, success: boolean) => Promise<void>;
865
}
866
867
export interface IViewPaneContainer {
868
onDidAddViews: Event<IView[]>;
869
onDidRemoveViews: Event<IView[]>;
870
onDidChangeViewVisibility: Event<IView>;
871
872
readonly views: IView[];
873
874
setVisible(visible: boolean): void;
875
isVisible(): boolean;
876
focus(): void;
877
getActionsContext(): unknown;
878
getView(viewId: string): IView | undefined;
879
toggleViewVisibility(viewId: string): void;
880
}
881
882
export interface IViewBadge {
883
readonly tooltip: string;
884
readonly value: number;
885
}
886
887