mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-25 00:44:05 +01:00
Add support for visibility and focus
This commit is contained in:
Vendored
+31
-10
@@ -6160,14 +6160,23 @@ declare module 'vscode' {
|
||||
}
|
||||
|
||||
/**
|
||||
* The event that is fired when there is a change in [tree view's selections](#TreeView.selections)
|
||||
* The event that is fired when there is a change in [tree view's selection](#TreeView.selection)
|
||||
*/
|
||||
export interface TreeViewSelectionChangeEvent<T> {
|
||||
|
||||
/**
|
||||
* Selected elements.
|
||||
*/
|
||||
selections: T[];
|
||||
selection: T[];
|
||||
|
||||
}
|
||||
|
||||
export interface TreeViewVisibilityChangeEvent {
|
||||
|
||||
/**
|
||||
* `true` if the [tree view](#TreeView) is visible otherwise `false`.
|
||||
*/
|
||||
visible: boolean;
|
||||
|
||||
}
|
||||
|
||||
@@ -6186,27 +6195,39 @@ declare module 'vscode' {
|
||||
*/
|
||||
readonly onDidCollapseElement: Event<TreeViewExpansionEvent<T>>;
|
||||
|
||||
/**
|
||||
* Event that is fired when the selection has changed
|
||||
*/
|
||||
readonly onDidChangeSelection: Event<TreeViewSelectionChangeEvent<T>>;
|
||||
|
||||
/**
|
||||
* Currently selected elements.
|
||||
*/
|
||||
readonly selection: ReadonlyArray<T>;
|
||||
|
||||
/**
|
||||
* Reveal an element. By default revealed element is selected.
|
||||
* Event that is fired when the [selection](#TreeView.selection) has changed
|
||||
*/
|
||||
readonly onDidChangeSelection: Event<TreeViewSelectionChangeEvent<T>>;
|
||||
|
||||
/**
|
||||
* `true` if the [tree view](#TreeView) is visible otherwise `false`.
|
||||
*/
|
||||
readonly visible: boolean;
|
||||
|
||||
/**
|
||||
* Event that is fired when [visibility](TreeView.visible) has changed
|
||||
*/
|
||||
readonly onDidChangeVisibility: Event<TreeViewVisibilityChangeEvent>;
|
||||
|
||||
/**
|
||||
* Reveals the given element in the tree view.
|
||||
* If the tree view is not visible then the element is revealed after the tree view is shown.
|
||||
*
|
||||
* By default revealed element is selected and not focused.
|
||||
* In order to not to select, set the option `select` to `false`.
|
||||
* In order to focus, set the option `focus` to `true`.
|
||||
*
|
||||
* **NOTE:** [TreeDataProvider](#TreeDataProvider) is required to implement [getParent](#TreeDataProvider.getParent) method to access this API.
|
||||
*/
|
||||
reveal(element: T, options?: { select?: boolean }): Thenable<void>;
|
||||
reveal(element: T, options?: { select?: boolean, focus?: boolean }): Thenable<void>;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A data provider that provides tree data
|
||||
*/
|
||||
|
||||
@@ -39,8 +39,8 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
|
||||
}
|
||||
}
|
||||
|
||||
$reveal(treeViewId: string, item: ITreeItem, parentChain: ITreeItem[], options?: { select?: boolean }): TPromise<void> {
|
||||
return this.viewsService.openView(treeViewId)
|
||||
$reveal(treeViewId: string, item: ITreeItem, parentChain: ITreeItem[], options: { select: boolean, focus: boolean }): TPromise<void> {
|
||||
return this.viewsService.openView(treeViewId, options.focus)
|
||||
.then(() => {
|
||||
const viewer = this.getTreeViewer(treeViewId);
|
||||
return viewer ? viewer.reveal(item, parentChain, options) : null;
|
||||
@@ -61,6 +61,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
|
||||
this._register(treeViewer.onDidExpandItem(item => this._proxy.$setExpanded(treeViewId, item.handle, true)));
|
||||
this._register(treeViewer.onDidCollapseItem(item => this._proxy.$setExpanded(treeViewId, item.handle, false)));
|
||||
this._register(treeViewer.onDidChangeSelection(items => this._proxy.$setSelection(treeViewId, items.map(({ handle }) => handle))));
|
||||
this._register(treeViewer.onDidChangeVisibility(isVisible => this._proxy.$setVisible(treeViewId, isVisible)));
|
||||
}
|
||||
|
||||
private getTreeViewer(treeViewId: string): ITreeViewer {
|
||||
|
||||
@@ -216,7 +216,7 @@ export interface MainThreadTextEditorsShape extends IDisposable {
|
||||
export interface MainThreadTreeViewsShape extends IDisposable {
|
||||
$registerTreeViewDataProvider(treeViewId: string): void;
|
||||
$refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem }): TPromise<void>;
|
||||
$reveal(treeViewId: string, treeItem: ITreeItem, parentChain: ITreeItem[], options?: { select?: boolean }): TPromise<void>;
|
||||
$reveal(treeViewId: string, treeItem: ITreeItem, parentChain: ITreeItem[], options: { select: boolean, focus: boolean }): TPromise<void>;
|
||||
}
|
||||
|
||||
export interface MainThreadErrorsShape extends IDisposable {
|
||||
@@ -666,6 +666,7 @@ export interface ExtHostTreeViewsShape {
|
||||
$getChildren(treeViewId: string, treeItemHandle?: string): TPromise<ITreeItem[]>;
|
||||
$setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void;
|
||||
$setSelection(treeViewId: string, treeItemHandles: string[]): void;
|
||||
$setVisible(treeViewId: string, visible: boolean): void;
|
||||
}
|
||||
|
||||
export interface ExtHostWorkspaceShape {
|
||||
|
||||
@@ -52,9 +52,11 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
return {
|
||||
get onDidCollapseElement() { return treeView.onDidCollapseElement; },
|
||||
get onDidExpandElement() { return treeView.onDidExpandElement; },
|
||||
get onDidChangeSelection() { return treeView.onDidChangeSelection; },
|
||||
get selection() { return treeView.selectedElements; },
|
||||
reveal: (element: T, options?: { select?: boolean }): Thenable<void> => {
|
||||
get onDidChangeSelection() { return treeView.onDidChangeSelection; },
|
||||
get visible() { return treeView.visible; },
|
||||
get onDidChangeVisibility() { return treeView.onDidChangeVisibility; },
|
||||
reveal: (element: T, options?: { select?: boolean, focus?: boolean }): Thenable<void> => {
|
||||
return treeView.reveal(element, options);
|
||||
},
|
||||
dispose: () => {
|
||||
@@ -88,6 +90,14 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
treeView.setSelection(treeItemHandles);
|
||||
}
|
||||
|
||||
$setVisible(treeViewId: string, isVisible: boolean): void {
|
||||
const treeView = this.treeViews.get(treeViewId);
|
||||
if (!treeView) {
|
||||
throw new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId));
|
||||
}
|
||||
treeView.setVisible(isVisible);
|
||||
}
|
||||
|
||||
private createExtHostTreeViewer<T>(id: string, dataProvider: vscode.TreeDataProvider<T>): ExtHostTreeView<T> {
|
||||
const treeView = new ExtHostTreeView<T>(id, dataProvider, this._proxy, this.commands.converter);
|
||||
this.treeViews.set(id, treeView);
|
||||
@@ -115,6 +125,9 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
private elements: Map<TreeItemHandle, T> = new Map<TreeItemHandle, T>();
|
||||
private nodes: Map<T, TreeNode> = new Map<T, TreeNode>();
|
||||
|
||||
private _visible: boolean = true;
|
||||
get visible(): boolean { return this._visible; }
|
||||
|
||||
private _selectedHandles: TreeItemHandle[] = [];
|
||||
get selectedElements(): T[] { return this._selectedHandles.map(handle => this.getExtensionElement(handle)).filter(element => !isUndefinedOrNull(element)); }
|
||||
|
||||
@@ -127,6 +140,9 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
private _onDidChangeSelection: Emitter<vscode.TreeViewSelectionChangeEvent<T>> = this._register(new Emitter<vscode.TreeViewSelectionChangeEvent<T>>());
|
||||
readonly onDidChangeSelection: Event<vscode.TreeViewSelectionChangeEvent<T>> = this._onDidChangeSelection.event;
|
||||
|
||||
private _onDidChangeVisibility: Emitter<vscode.TreeViewVisibilityChangeEvent> = this._register(new Emitter<vscode.TreeViewVisibilityChangeEvent>());
|
||||
readonly onDidChangeVisibility: Event<vscode.TreeViewVisibilityChangeEvent> = this._onDidChangeVisibility.event;
|
||||
|
||||
private refreshPromise: TPromise<void> = TPromise.as(null);
|
||||
|
||||
constructor(private viewId: string, private dataProvider: vscode.TreeDataProvider<T>, private proxy: MainThreadTreeViewsShape, private commands: CommandsConverter) {
|
||||
@@ -165,14 +181,18 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
return this.elements.get(treeItemHandle);
|
||||
}
|
||||
|
||||
reveal(element: T, options?: { select?: boolean }): TPromise<void> {
|
||||
reveal(element: T, options?: { select?: boolean, focus?: boolean }): TPromise<void> {
|
||||
options = options ? options : { select: true, focus: false };
|
||||
const select = isUndefinedOrNull(options.select) ? true : options.select;
|
||||
const focus = isUndefinedOrNull(options.focus) ? false : options.focus;
|
||||
|
||||
if (typeof this.dataProvider.getParent !== 'function') {
|
||||
return TPromise.wrapError(new Error(`Required registered TreeDataProvider to implement 'getParent' method to access 'reveal' method`));
|
||||
}
|
||||
return this.refreshPromise
|
||||
.then(() => this.resolveUnknownParentChain(element))
|
||||
.then(parentChain => this.resolveTreeNode(element, parentChain[parentChain.length - 1])
|
||||
.then(treeNode => this.proxy.$reveal(this.viewId, treeNode.item, parentChain.map(p => p.item), options)));
|
||||
.then(treeNode => this.proxy.$reveal(this.viewId, treeNode.item, parentChain.map(p => p.item), { select, focus })));
|
||||
}
|
||||
|
||||
setExpanded(treeItemHandle: TreeItemHandle, expanded: boolean): void {
|
||||
@@ -189,7 +209,14 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
setSelection(treeItemHandles: TreeItemHandle[]): void {
|
||||
if (!equals(this._selectedHandles, treeItemHandles)) {
|
||||
this._selectedHandles = treeItemHandles;
|
||||
this._onDidChangeSelection.fire({ selections: this.selectedElements });
|
||||
this._onDidChangeSelection.fire({ selection: this.selectedElements });
|
||||
}
|
||||
}
|
||||
|
||||
setVisible(visible: boolean): void {
|
||||
if (visible !== this._visible) {
|
||||
this._visible = visible;
|
||||
this._onDidChangeVisibility.fire({ visible: this._visible });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -193,6 +193,9 @@ export class CustomTreeViewer extends Disposable implements ITreeViewer {
|
||||
private _onDidChangeSelection: Emitter<ITreeItem[]> = this._register(new Emitter<ITreeItem[]>());
|
||||
readonly onDidChangeSelection: Event<ITreeItem[]> = this._onDidChangeSelection.event;
|
||||
|
||||
private _onDidChangeVisibility: Emitter<boolean> = this._register(new Emitter<boolean>());
|
||||
readonly onDidChangeVisibility: Event<boolean> = this._onDidChangeVisibility.event;
|
||||
|
||||
constructor(
|
||||
private id: string,
|
||||
private container: ViewContainer,
|
||||
@@ -267,6 +270,8 @@ export class CustomTreeViewer extends Disposable implements ITreeViewer {
|
||||
this.elementsToRefresh = [];
|
||||
}
|
||||
}
|
||||
|
||||
this._onDidChangeVisibility.fire(this.isVisible);
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
@@ -337,13 +342,15 @@ export class CustomTreeViewer extends Disposable implements ITreeViewer {
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
reveal(item: ITreeItem, parentChain: ITreeItem[], options?: { select?: boolean }): TPromise<void> {
|
||||
reveal(item: ITreeItem, parentChain: ITreeItem[], options?: { select?: boolean, focus?: boolean }): TPromise<void> {
|
||||
if (this.tree && this.isVisible) {
|
||||
options = options ? options : { select: true };
|
||||
options = options ? options : { select: false, focus: false };
|
||||
const select = isUndefinedOrNull(options.select) ? false : options.select;
|
||||
const focus = isUndefinedOrNull(options.focus) ? false : options.focus;
|
||||
|
||||
const root: Root = this.tree.getInput();
|
||||
const promise = root.children ? TPromise.as(null) : this.refresh(); // Refresh if root is not populated
|
||||
return promise.then(() => {
|
||||
const select = isUndefinedOrNull(options.select) ? true : options.select;
|
||||
var result = TPromise.as(null);
|
||||
parentChain.forEach((e) => {
|
||||
result = result.then(() => this.tree.expand(e));
|
||||
@@ -353,6 +360,10 @@ export class CustomTreeViewer extends Disposable implements ITreeViewer {
|
||||
if (select) {
|
||||
this.tree.setSelection([item], { source: 'api' });
|
||||
}
|
||||
if (focus) {
|
||||
this.focus();
|
||||
this.tree.setFocus(item);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -208,7 +208,9 @@ export abstract class ViewContainerViewlet extends PanelViewlet implements IView
|
||||
}
|
||||
view = this.getView(id);
|
||||
view.setExpanded(true);
|
||||
view.focus();
|
||||
if (focus) {
|
||||
view.focus();
|
||||
}
|
||||
return TPromise.as(view);
|
||||
}
|
||||
|
||||
|
||||
@@ -227,6 +227,8 @@ export interface ITreeViewer extends IDisposable {
|
||||
|
||||
readonly onDidChangeSelection: Event<ITreeItem[]>;
|
||||
|
||||
readonly onDidChangeVisibility: Event<boolean>;
|
||||
|
||||
refresh(treeItems?: ITreeItem[]): TPromise<void>;
|
||||
|
||||
setVisibility(visible: boolean): void;
|
||||
|
||||
Reference in New Issue
Block a user