提交 1c6050ce 编写于 作者: J Joao Moreno

add tree sorter

fixes #63148
上级 3fc2c908
......@@ -179,6 +179,7 @@ function asTreeContextMenuEvent<T>(event: IListContextMenuEvent<ITreeNode<T, any
}
export interface IAbstractTreeOptions<T, TFilterData = void> extends IListOptions<T> {
collapseByDefault?: boolean; // defaults to false
filter?: ITreeFilter<T, TFilterData>;
}
......
......@@ -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 } from 'vs/base/browser/ui/tree/tree';
import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter } 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';
......@@ -157,6 +157,11 @@ function asObjectTreeOptions<T, TFilterData>(options?: IAsyncDataTreeOptions<T,
getKeyboardNavigationLabel(e) {
return options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(e.element!);
}
},
sorter: options.sorter && {
compare(a, b) {
return options.sorter!.compare(a.element!, b.element!);
}
}
};
}
......@@ -170,6 +175,7 @@ function asTreeElement<T>(node: IAsyncDataTreeNode<T>): ITreeElement<IAsyncDataT
export interface IAsyncDataTreeOptions<T, TFilterData = void> extends IAbstractTreeOptions<T, TFilterData> {
identityProvider?: IIdentityProvider<T>;
sorter?: ITreeSorter<T>;
}
export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> implements IDisposable {
......
......@@ -11,9 +11,7 @@ import { IndexTreeModel } from 'vs/base/browser/ui/tree/indexTreeModel';
import { ITreeElement, ITreeModel, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree';
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
export interface IIndexTreeOptions<T, TFilterData = void> extends IAbstractTreeOptions<T, TFilterData> {
collapseByDefault?: boolean; // defaults to false
}
export interface IIndexTreeOptions<T, TFilterData = void> extends IAbstractTreeOptions<T, TFilterData> { }
export class IndexTree<T, TFilterData = void> extends AbstractTree<T, TFilterData, number[]> {
......
......@@ -6,12 +6,12 @@
import { Iterator, ISequence } from 'vs/base/common/iterator';
import { AbstractTree, IAbstractTreeOptions } from 'vs/base/browser/ui/tree/abstractTree';
import { ISpliceable } from 'vs/base/common/sequence';
import { ITreeNode, ITreeModel, ITreeElement, ITreeRenderer } from 'vs/base/browser/ui/tree/tree';
import { ITreeNode, ITreeModel, ITreeElement, ITreeRenderer, ITreeSorter } from 'vs/base/browser/ui/tree/tree';
import { ObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel';
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
export interface IObjectTreeOptions<T, TFilterData = void> extends IAbstractTreeOptions<T, TFilterData> {
collapseByDefault?: boolean; // defaults to false
sorter?: ITreeSorter<T>;
}
export class ObjectTree<T extends NonNullable<any>, TFilterData = void> extends AbstractTree<T | null, TFilterData, T | null> {
......
......@@ -7,9 +7,11 @@ 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 } from 'vs/base/browser/ui/tree/tree';
import { ITreeModel, ITreeNode, ITreeElement, ITreeSorter } from 'vs/base/browser/ui/tree/tree';
export interface IObjectTreeModelOptions<T, TFilterData> extends IIndexTreeModelOptions<T, TFilterData> { }
export interface IObjectTreeModelOptions<T, TFilterData> extends IIndexTreeModelOptions<T, TFilterData> {
sorter?: ITreeSorter<T>;
}
export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends NonNullable<any> = void> implements ITreeModel<T | null, TFilterData, T | null> {
......@@ -17,6 +19,7 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
private model: IndexTreeModel<T | null, TFilterData>;
private nodes = new Map<T | null, ITreeNode<T, TFilterData>>();
private sorter?: ITreeSorter<ITreeElement<T>>;
readonly onDidChangeCollapseState: Event<ITreeNode<T, TFilterData>>;
readonly onDidChangeRenderNodeCount: Event<ITreeNode<T, TFilterData>>;
......@@ -27,6 +30,14 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
this.model = new IndexTreeModel(list, null, options);
this.onDidChangeCollapseState = this.model.onDidChangeCollapseState as Event<ITreeNode<T, TFilterData>>;
this.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount as Event<ITreeNode<T, TFilterData>>;
if (options.sorter) {
this.sorter = {
compare(a, b) {
return options.sorter!.compare(a.element, b.element);
}
};
}
}
setChildren(
......@@ -67,7 +78,11 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
}
private preserveCollapseState(elements: ISequence<ITreeElement<T | null>> | undefined): ISequence<ITreeElement<T | null>> {
const iterator = elements ? getSequenceIterator(elements) : Iterator.empty<ITreeElement<T>>();
let iterator = elements ? getSequenceIterator(elements) : Iterator.empty<ITreeElement<T>>();
if (this.sorter) {
iterator = Iterator.fromArray(Iterator.collect(iterator).sort(this.sorter.compare.bind(this.sorter)));
}
return Iterator.map(iterator, treeElement => {
const node = this.nodes.get(treeElement.element);
......
......@@ -67,6 +67,10 @@ export interface ITreeFilter<T, TFilterData = void> {
filter(element: T, parentVisibility: TreeVisibility): TreeFilterResult<TFilterData>;
}
export interface ITreeSorter<T> {
compare(element: T, otherElement: T): number;
}
export interface ITreeElement<T> {
readonly element: T;
readonly children?: Iterator<ITreeElement<T>> | ITreeElement<T>[];
......
......@@ -138,6 +138,16 @@
}
};
const sorter = new class {
compare(a, b) {
if (a.collapsible === b.collapsible) {
return a.name < b.name ? -1 : 1;
}
return a.collapsible ? -1 : 1;
}
};
const dataSource = new class {
hasChildren(element) {
return element === null || element.element.type === 'dir';
......@@ -154,11 +164,7 @@
collapsible: element.type === 'dir'
}));
if (element) {
setTimeout(() => c(els), 2500);
} else {
c(els);
}
c(els);
}
};
});
......@@ -171,7 +177,7 @@
}
};
const tree = new AsyncDataTree(container, delegate, [renderer], dataSource, { filter: treeFilter, identityProvider });
const tree = new AsyncDataTree(container, delegate, [renderer], dataSource, { filter: treeFilter, sorter, identityProvider });
return { tree, treeFilter };
}
......
......@@ -46,14 +46,6 @@ async function readdir(relativePath) {
}
}
result.sort((a, b) => {
if (a.type === b.type) {
return a.name < b.name ? -1 : 1;
}
return a.type === 'dir' ? -1 : 1;
});
return result;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册