提交 0affcfd8 编写于 作者: J Joao Moreno

avoid data tree expansion in recursive expand

上级 1c6050ce
......@@ -11,7 +11,7 @@ import { append, $, toggleClass } from 'vs/base/browser/dom';
import { Event, Relay } from 'vs/base/common/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { ITreeModel, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeFilter, ITreeNavigator } from 'vs/base/browser/ui/tree/tree';
import { ITreeModel, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeFilter, ITreeNavigator, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree';
import { ISpliceable } from 'vs/base/common/sequence';
function asListOptions<T, TFilterData>(options?: IAbstractTreeOptions<T, TFilterData>): IListOptions<ITreeNode<T, TFilterData>> | undefined {
......@@ -74,11 +74,11 @@ class TreeRenderer<T, TFilterData, TTemplateData> implements IListRenderer<ITree
constructor(
private renderer: ITreeRenderer<T, TFilterData, TTemplateData>,
onDidChangeCollapseState: Event<ITreeNode<T, TFilterData>>
onDidChangeCollapseState: Event<ICollapseStateChangeEvent<T, TFilterData>>
) {
this.templateId = renderer.templateId;
onDidChangeCollapseState(this.onDidChangeNodeTwistieState, this, this.disposables);
Event.map(onDidChangeCollapseState, e => e.node)(this.onDidChangeNodeTwistieState, this, this.disposables);
if (renderer.onDidChangeTwistieState) {
renderer.onDidChangeTwistieState(this.onDidChangeTwistieState, this, this.disposables);
......@@ -204,7 +204,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
get onDidFocus(): Event<void> { return this.view.onDidFocus; }
get onDidBlur(): Event<void> { return this.view.onDidBlur; }
get onDidChangeCollapseState(): Event<ITreeNode<T, TFilterData>> { return this.model.onDidChangeCollapseState; }
get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<T, TFilterData>> { return this.model.onDidChangeCollapseState; }
get onDidChangeRenderNodeCount(): Event<ITreeNode<T, TFilterData>> { return this.model.onDidChangeRenderNodeCount; }
get onDidDispose(): Event<void> { return this.view.onDidDispose; }
......@@ -217,7 +217,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
) {
const treeDelegate = new ComposedTreeDelegate<T, ITreeNode<T, TFilterData>>(delegate);
const onDidChangeCollapseStateRelay = new Relay<ITreeNode<T, TFilterData>>();
const onDidChangeCollapseStateRelay = new Relay<ICollapseStateChangeEvent<T, TFilterData>>();
const treeRenderers = renderers.map(r => new TreeRenderer<T, TFilterData, any>(r, onDidChangeCollapseStateRelay.event));
this.disposables.push(...treeRenderers);
......
......@@ -6,7 +6,7 @@
import { ComposedTreeDelegate, IAbstractTreeOptions } from 'vs/base/browser/ui/tree/abstractTree';
import { ObjectTree, IObjectTreeOptions } from 'vs/base/browser/ui/tree/objectTree';
import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list';
import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter } from 'vs/base/browser/ui/tree/tree';
import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event';
import { timeout, always } from 'vs/base/common/async';
......@@ -193,7 +193,6 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
get onDidChangeFocus(): Event<ITreeEvent<T>> { return Event.map(this.tree.onDidChangeFocus, asTreeEvent); }
get onDidChangeSelection(): Event<ITreeEvent<T>> { return Event.map(this.tree.onDidChangeSelection, asTreeEvent); }
get onDidOpen(): Event<ITreeEvent<T>> { return Event.map(this.tree.onDidOpen, asTreeEvent); }
get onDidChangeCollapseState(): Event<T> { return Event.map(this.tree.onDidChangeCollapseState, e => e.element!.element!); }
private readonly _onDidResolveChildren = new Emitter<IChildrenResolutionEvent<T>>();
readonly onDidResolveChildren: Event<IChildrenResolutionEvent<T>> = this._onDidResolveChildren.event;
......@@ -496,9 +495,13 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
}
}
private _onDidChangeCollapseState(treeNode: ITreeNode<IAsyncDataTreeNode<T>, any>): void {
if (!treeNode.collapsed && treeNode.element.state === AsyncDataTreeNodeState.Uninitialized) {
this.refreshNode(treeNode.element, false, ChildrenResolutionReason.Expand);
private _onDidChangeCollapseState({ node, deep }: ICollapseStateChangeEvent<IAsyncDataTreeNode<T>, any>): void {
if (!node.collapsed && node.element.state === AsyncDataTreeNodeState.Uninitialized) {
if (deep) {
this.collapse(node.element.element!);
} else {
this.refreshNode(node.element, false, ChildrenResolutionReason.Expand);
}
}
}
......
......@@ -7,7 +7,7 @@ import { ISpliceable } from 'vs/base/common/sequence';
import { Iterator, ISequence } from 'vs/base/common/iterator';
import { Emitter, Event, EventBufferer } from 'vs/base/common/event';
import { tail2 } from 'vs/base/common/arrays';
import { ITreeFilterDataResult, TreeVisibility, ITreeFilter, ITreeModel, ITreeNode, ITreeElement } from 'vs/base/browser/ui/tree/tree';
import { ITreeFilterDataResult, TreeVisibility, ITreeFilter, ITreeModel, ITreeNode, ITreeElement, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree';
interface IMutableTreeNode<T, TFilterData> extends ITreeNode<T, TFilterData> {
readonly parent: IMutableTreeNode<T, TFilterData> | undefined;
......@@ -48,10 +48,10 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
readonly rootRef = [];
private root: IMutableTreeNode<T, TFilterData>;
private eventBufferer = new EventBufferer(); // TODO@joao is this really necessary
private eventBufferer = new EventBufferer();
private _onDidChangeCollapseState = new Emitter<ITreeNode<T, TFilterData>>();
readonly onDidChangeCollapseState: Event<ITreeNode<T, TFilterData>> = this.eventBufferer.wrapEvent(this._onDidChangeCollapseState.event);
private _onDidChangeCollapseState = new Emitter<ICollapseStateChangeEvent<T, TFilterData>>();
readonly onDidChangeCollapseState: Event<ICollapseStateChangeEvent<T, TFilterData>> = this.eventBufferer.wrapEvent(this._onDidChangeCollapseState.event);
private _onDidChangeRenderNodeCount = new Emitter<ITreeNode<T, TFilterData>>();
readonly onDidChangeRenderNodeCount: Event<ITreeNode<T, TFilterData>> = this.eventBufferer.wrapEvent(this._onDidChangeRenderNodeCount.event);
......@@ -63,6 +63,8 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
this.collapseByDefault = typeof options.collapseByDefault === 'undefined' ? false : options.collapseByDefault;
this.filter = options.filter;
// this.onDidChangeCollapseState(node => console.log(node.collapsed, node));
this.root = {
parent: undefined,
element: rootElement,
......@@ -140,11 +142,13 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
collapsed = !node.collapsed;
}
return this._setCollapsed(node, listIndex, revealed, collapsed, recursive || false);
return this.eventBufferer.bufferEvents(() => {
return this._setCollapsed(node, listIndex, revealed, collapsed!, recursive || false);
});
}
private _setCollapsed(node: IMutableTreeNode<T, TFilterData>, listIndex: number, revealed: boolean, collapsed: boolean, recursive: boolean): boolean {
const result = this._setNodeCollapsed(node, collapsed, recursive);
const result = this._setNodeCollapsed(node, collapsed, recursive, false);
if (!revealed || !node.visible) {
return result;
......@@ -152,25 +156,26 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
const previousRenderNodeCount = node.renderNodeCount;
const toInsert = this.updateNodeAfterCollapseChange(node);
const deleteCount = previousRenderNodeCount - (listIndex === -1 ? 0 : 1);
this.list.splice(listIndex + 1, deleteCount, toInsert.slice(1));
this._onDidChangeCollapseState.fire(node);
return result;
}
private _setNodeCollapsed(node: IMutableTreeNode<T, TFilterData>, collapsed: boolean, recursive: boolean): boolean {
private _setNodeCollapsed(node: IMutableTreeNode<T, TFilterData>, collapsed: boolean, recursive: boolean, deep: boolean): boolean {
let result = node.collapsible && node.collapsed !== collapsed;
if (node.collapsible) {
node.collapsed = collapsed;
if (result) {
this._onDidChangeCollapseState.fire({ node, deep });
}
}
if (recursive) {
for (const child of node.children) {
result = this._setNodeCollapsed(child, collapsed, true) || result;
result = this._setNodeCollapsed(child, collapsed, true, true) || result;
}
}
......
......@@ -7,7 +7,7 @@ import { ISpliceable } from 'vs/base/common/sequence';
import { Iterator, ISequence, getSequenceIterator } from 'vs/base/common/iterator';
import { IndexTreeModel, IIndexTreeModelOptions } from 'vs/base/browser/ui/tree/indexTreeModel';
import { Event } from 'vs/base/common/event';
import { ITreeModel, ITreeNode, ITreeElement, ITreeSorter } from 'vs/base/browser/ui/tree/tree';
import { ITreeModel, ITreeNode, ITreeElement, ITreeSorter, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree';
export interface IObjectTreeModelOptions<T, TFilterData> extends IIndexTreeModelOptions<T, TFilterData> {
sorter?: ITreeSorter<T>;
......@@ -21,14 +21,14 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
private nodes = new Map<T | null, ITreeNode<T, TFilterData>>();
private sorter?: ITreeSorter<ITreeElement<T>>;
readonly onDidChangeCollapseState: Event<ITreeNode<T, TFilterData>>;
readonly onDidChangeCollapseState: Event<ICollapseStateChangeEvent<T, TFilterData>>;
readonly onDidChangeRenderNodeCount: Event<ITreeNode<T, TFilterData>>;
get size(): number { return this.nodes.size; }
constructor(list: ISpliceable<ITreeNode<T, TFilterData>>, options: IObjectTreeModelOptions<T, TFilterData> = {}) {
this.model = new IndexTreeModel(list, null, options);
this.onDidChangeCollapseState = this.model.onDidChangeCollapseState as Event<ITreeNode<T, TFilterData>>;
this.onDidChangeCollapseState = this.model.onDidChangeCollapseState as Event<ICollapseStateChangeEvent<T, TFilterData>>;
this.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount as Event<ITreeNode<T, TFilterData>>;
if (options.sorter) {
......
......@@ -89,9 +89,14 @@ export interface ITreeNode<T, TFilterData = void> {
readonly filterData: TFilterData | undefined;
}
export interface ICollapseStateChangeEvent<T, TFilterData> {
node: ITreeNode<T, TFilterData>;
deep: boolean;
}
export interface ITreeModel<T, TFilterData, TRef> {
readonly rootRef: TRef;
readonly onDidChangeCollapseState: Event<ITreeNode<T, TFilterData>>;
readonly onDidChangeCollapseState: Event<ICollapseStateChangeEvent<T, TFilterData>>;
readonly onDidChangeRenderNodeCount: Event<ITreeNode<T, TFilterData>>;
getListIndex(location: TRef): number;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册