提交 6a5e884c 编写于 作者: J Joao Moreno

ObjectTree.resort

fixes #67876
上级 eccccb64
......@@ -418,6 +418,10 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
await this.refreshAndRenderNode(this.getDataNode(element), recursive, ChildrenResolutionReason.Refresh, viewStateContext);
}
resort(element: TInput | T = this.root.element, recursive = true): void {
this.tree.resort(this.getDataNode(element), recursive);
}
hasNode(element: TInput | T): boolean {
return element === this.root.element || this.nodes.has(element as T);
}
......
......@@ -89,6 +89,10 @@ export class DataTree<TInput, T, TFilterData = void> extends AbstractTree<T | nu
this._refresh(element);
}
resort(element: T | TInput = this.input!, recursive = true): void {
this.model.resort((element === this.input ? null : element) as T, recursive);
}
// View
refresh(element: T): void {
......
......@@ -40,6 +40,10 @@ export class ObjectTree<T extends NonNullable<any>, TFilterData = void> extends
this.model.refresh(element);
}
resort(element: T, recursive = true): void {
this.model.resort(element, recursive);
}
protected createModel(view: ISpliceable<ITreeNode<T, TFilterData>>, options: IObjectTreeOptions<T, TFilterData>): ITreeModel<T | null, TFilterData, T | null> {
return new ObjectTreeModel(view, options);
}
......
......@@ -19,7 +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>>;
private sorter?: ITreeSorter<{ element: T; }>;
readonly onDidSplice: Event<ITreeModelSpliceEvent<T | null, TFilterData>>;
readonly onDidChangeCollapseState: Event<ICollapseStateChangeEvent<T, TFilterData>>;
......@@ -49,6 +49,15 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
onDidDeleteNode?: (node: ITreeNode<T, TFilterData>) => void
): Iterator<ITreeElement<T | null>> {
const location = this.getElementLocation(element);
return this._setChildren(location, this.preserveCollapseState(children), onDidCreateNode, onDidDeleteNode);
}
private _setChildren(
location: number[],
children: ISequence<ITreeElement<T>> | undefined,
onDidCreateNode?: (node: ITreeNode<T, TFilterData>) => void,
onDidDeleteNode?: (node: ITreeNode<T, TFilterData>) => void
): Iterator<ITreeElement<T | null>> {
const insertedElements = new Set<T | null>();
const _onDidCreateNode = (node: ITreeNode<T, TFilterData>) => {
......@@ -73,13 +82,13 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
return this.model.splice(
[...location, 0],
Number.MAX_VALUE,
this.preserveCollapseState(children),
children,
_onDidCreateNode,
_onDidDeleteNode
);
}
private preserveCollapseState(elements: ISequence<ITreeElement<T | null>> | undefined): ISequence<ITreeElement<T | null>> {
private preserveCollapseState(elements: ISequence<ITreeElement<T>> | undefined): ISequence<ITreeElement<T>> {
let iterator = elements ? getSequenceIterator(elements) : Iterator.empty<ITreeElement<T>>();
if (this.sorter) {
......@@ -113,6 +122,32 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
this.model.refresh(location);
}
resort(element: T | null = null, recursive = true): void {
if (!this.sorter) {
return;
}
const location = this.getElementLocation(element);
const node = this.model.getNode(location);
this._setChildren(location, this.resortChildren(node, recursive));
}
private resortChildren(node: ITreeNode<T | null, TFilterData>, recursive: boolean, first = true): ISequence<ITreeElement<T>> {
let childrenNodes = Iterator.fromArray(node.children as ITreeNode<T, TFilterData>[]);
if (recursive || first) {
childrenNodes = Iterator.fromArray(Iterator.collect(childrenNodes).sort(this.sorter!.compare.bind(this.sorter)));
}
return Iterator.map<ITreeNode<T | null, TFilterData>, ITreeElement<T>>(childrenNodes, node => ({
element: node.element as T,
collapsible: node.collapsible,
collapsed: node.collapsed,
children: this.resortChildren(node, recursive, false)
}));
}
getParentElement(ref: T | null = null): T | null {
const location = this.getElementLocation(ref);
return this.model.getParentElement(location);
......
......@@ -183,4 +183,41 @@ suite('ObjectTreeModel', function () {
model.setChildren(null, data);
assert.deepEqual(toArray(list), ['airplanes', 'jet', 'passenger', 'bicycles', 'dutch', 'electric', 'mountain', 'cars', 'compact', 'convertible', 'sedan']);
});
test('resort', () => {
let compare: (a: string, b: string) => number = () => 0;
const list: ITreeNode<string>[] = [];
const model = new ObjectTreeModel<string>(toSpliceable(list), { sorter: { compare(a, b) { return compare(a, b); } } });
const data = [
{ element: 'cars', children: [{ element: 'sedan' }, { element: 'convertible' }, { element: 'compact' }] },
{ element: 'airplanes', children: [{ element: 'passenger' }, { element: 'jet' }] },
{ element: 'bicycles', children: [{ element: 'dutch' }, { element: 'mountain' }, { element: 'electric' }] },
];
model.setChildren(null, data);
assert.deepEqual(toArray(list), ['cars', 'sedan', 'convertible', 'compact', 'airplanes', 'passenger', 'jet', 'bicycles', 'dutch', 'mountain', 'electric']);
// lexicographical
compare = (a, b) => a < b ? -1 : 1;
// non-recursive
model.resort(null, false);
assert.deepEqual(toArray(list), ['airplanes', 'passenger', 'jet', 'bicycles', 'dutch', 'mountain', 'electric', 'cars', 'sedan', 'convertible', 'compact']);
// recursive
model.resort();
assert.deepEqual(toArray(list), ['airplanes', 'jet', 'passenger', 'bicycles', 'dutch', 'electric', 'mountain', 'cars', 'compact', 'convertible', 'sedan']);
// reverse
compare = (a, b) => a < b ? 1 : -1;
// scoped
model.resort('cars');
assert.deepEqual(toArray(list), ['airplanes', 'jet', 'passenger', 'bicycles', 'dutch', 'electric', 'mountain', 'cars', 'sedan', 'convertible', 'compact']);
// recursive
model.resort();
assert.deepEqual(toArray(list), ['cars', 'sedan', 'convertible', 'compact', 'bicycles', 'mountain', 'electric', 'dutch', 'airplanes', 'passenger', 'jet']);
});
});
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册