提交 4b3c04ec 编写于 作者: J Joao Moreno

tree: expand/collapse on click

上级 323bbc57
...@@ -4,19 +4,13 @@ ...@@ -4,19 +4,13 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import 'vs/css!./tree'; import 'vs/css!./tree';
import { IDisposable } from 'vs/base/common/lifecycle'; import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IListOptions, List, IIdentityProvider, IMultipleSelectionController } from 'vs/base/browser/ui/list/listWidget'; import { IListOptions, List, IIdentityProvider, IMultipleSelectionController } from 'vs/base/browser/ui/list/listWidget';
import { TreeModel, ITreeNode, ITreeElement } from 'vs/base/browser/ui/tree/treeModel'; import { TreeModel, ITreeNode, ITreeElement } from 'vs/base/browser/ui/tree/treeModel';
import { IIterator, empty } from 'vs/base/common/iterator'; import { IIterator, empty } from 'vs/base/common/iterator';
import { IDelegate, IRenderer } from 'vs/base/browser/ui/list/list'; import { IDelegate, IRenderer, IListMouseEvent } from 'vs/base/browser/ui/list/list';
import { append, $ } from 'vs/base/browser/dom'; import { append, $ } from 'vs/base/browser/dom';
/**
* Remove ITreeNode and just use ITreeNode instead.
* We need ITreeNode live objects to associate them with the respective rendered
* HTMLElement. That way we can find the right node when DOM events happen, eg click.
*/
function toTreeListOptions<T>(options?: IListOptions<T>): IListOptions<ITreeNode<T>> { function toTreeListOptions<T>(options?: IListOptions<T>): IListOptions<ITreeNode<T>> {
if (!options) { if (!options) {
return undefined; return undefined;
...@@ -95,10 +89,22 @@ class TreeRenderer<T, TTemplateData> implements IRenderer<ITreeNode<T>, ITreeLis ...@@ -95,10 +89,22 @@ class TreeRenderer<T, TTemplateData> implements IRenderer<ITreeNode<T>, ITreeLis
} }
} }
function getLocation<T>(node: ITreeNode<T>): number[] {
const location = [];
while (node.parent) {
location.push(node.parent.children.indexOf(node));
node = node.parent;
}
return location.reverse();
}
export class Tree<T> implements IDisposable { export class Tree<T> implements IDisposable {
private view: List<ITreeNode<T>>; private view: List<ITreeNode<T>>;
private model: TreeModel<T>; private model: TreeModel<T>;
private disposables: IDisposable[] = [];
constructor( constructor(
container: HTMLElement, container: HTMLElement,
...@@ -112,13 +118,24 @@ export class Tree<T> implements IDisposable { ...@@ -112,13 +118,24 @@ export class Tree<T> implements IDisposable {
this.view = new List(container, treeDelegate, treeRenderers, treeOptions); this.view = new List(container, treeDelegate, treeRenderers, treeOptions);
this.model = new TreeModel<T>(this.view); this.model = new TreeModel<T>(this.view);
this.view.onMouseClick(this.onMouseClick, this, this.disposables);
} }
splice(location: number[], deleteCount: number, toInsert: IIterator<ITreeElement<T>> = empty()): IIterator<ITreeElement<T>> { splice(location: number[], deleteCount: number, toInsert: IIterator<ITreeElement<T>> = empty()): IIterator<ITreeElement<T>> {
return this.model.splice(location, deleteCount, toInsert); return this.model.splice(location, deleteCount, toInsert);
} }
private onMouseClick(e: IListMouseEvent<ITreeNode<T>>): void {
const node = e.element;
const location = getLocation(node);
this.model.toggleCollapsed(location);
}
dispose(): void { dispose(): void {
this.disposables = dispose(this.disposables);
this.view.dispose(); this.view.dispose();
this.view = null;
this.model = null;
} }
} }
\ No newline at end of file
...@@ -16,7 +16,7 @@ export interface ITreeElement<T> { ...@@ -16,7 +16,7 @@ export interface ITreeElement<T> {
} }
export interface ITreeNode<T> { export interface ITreeNode<T> {
readonly parent: IMutableTreeNode<T>; readonly parent: IMutableTreeNode<T> | undefined;
readonly element: T; readonly element: T;
readonly children: IMutableTreeNode<T>[]; readonly children: IMutableTreeNode<T>[];
readonly depth: number; readonly depth: number;
...@@ -52,7 +52,7 @@ function getVisibleNodes<T>(nodes: IMutableTreeNode<T>[], result: ITreeNode<T>[] ...@@ -52,7 +52,7 @@ function getVisibleNodes<T>(nodes: IMutableTreeNode<T>[], result: ITreeNode<T>[]
function treeElementToNode<T>(treeElement: ITreeElement<T>, parent: IMutableTreeNode<T>, visible: boolean, treeListElements: ITreeNode<T>[]): IMutableTreeNode<T> { function treeElementToNode<T>(treeElement: ITreeElement<T>, parent: IMutableTreeNode<T>, visible: boolean, treeListElements: ITreeNode<T>[]): IMutableTreeNode<T> {
const depth = parent.depth + 1; const depth = parent.depth + 1;
const { element, collapsed } = treeElement; const { element, collapsed } = treeElement;
const node = { parent: undefined, element, children: [], depth, collapsed, visibleCount: 0 }; const node = { parent, element, children: [], depth, collapsed, visibleCount: 0 };
if (visible) { if (visible) {
treeListElements.push(node); treeListElements.push(node);
...@@ -105,8 +105,20 @@ export class TreeModel<T> { ...@@ -105,8 +105,20 @@ export class TreeModel<T> {
} }
setCollapsed(location: number[], collapsed: boolean): void { setCollapsed(location: number[], collapsed: boolean): void {
this._setCollapsed(location, collapsed);
}
toggleCollapsed(location: number[]): void {
this._setCollapsed(location);
}
private _setCollapsed(location: number[], collapsed?: boolean | undefined): void {
const { node, listIndex, visible } = this.findNode(location); const { node, listIndex, visible } = this.findNode(location);
if (typeof collapsed === 'undefined') {
collapsed = !node.collapsed;
}
if (node.collapsed === collapsed) { if (node.collapsed === collapsed) {
return; return;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册