This commit is contained in:
João Moreno 2021-06-25 16:00:24 +02:00
parent 6c3defb810
commit bf495694c7
No known key found for this signature in database
GPG key ID: 896B853774D1A575
5 changed files with 33 additions and 32 deletions

View file

@ -109,6 +109,7 @@ class TraitRenderer<T> implements IListRenderer<T, ITraitTemplateData>
class Trait<T> implements ISpliceable<boolean>, IDisposable {
private length = 0;
private indexes: number[] = [];
private sortedIndexes: number[] = [];
@ -125,16 +126,26 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable {
constructor(private _trait: string) { }
splice(start: number, deleteCount: number, elements: boolean[]): void {
deleteCount = Math.max(0, Math.min(deleteCount, this.length - start));
const diff = elements.length - deleteCount;
const end = start + deleteCount;
const indexes = [
const sortedIndexes = [
...this.sortedIndexes.filter(i => i < start),
...elements.map((hasTrait, i) => hasTrait ? i + start : -1).filter(i => i !== -1),
...this.sortedIndexes.filter(i => i >= end).map(i => i + diff)
];
const length = this.length + diff;
if (this.sortedIndexes.length > 0 && sortedIndexes.length === 0) {
const first = this.sortedIndexes.find(index => index >= start) ?? length - 1;
sortedIndexes.push(Math.min(first, length - 1));
}
this.renderer.splice(start, deleteCount, elements.length);
this._set(indexes, indexes);
this._set(sortedIndexes, sortedIndexes);
this.length = length;
}
renderIndex(index: number, container: HTMLElement): void {
@ -1472,6 +1483,11 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
return firstOrDefault(this.anchor.get(), undefined);
}
getAnchorElement(): T | undefined {
const anchor = this.getAnchor();
return typeof anchor === 'undefined' ? undefined : this.element(anchor);
}
setFocus(indexes: number[], browserEvent?: UIEvent): void {
for (const index of indexes) {
if (index < 0 || index >= this.length) {

View file

@ -1001,7 +1001,10 @@ class Trait<T> {
return this._nodeSet;
}
constructor(private identityProvider?: IIdentityProvider<T>) { }
constructor(
private getFirstViewElementWithTrait: () => ITreeNode<T, any> | undefined,
private identityProvider?: IIdentityProvider<T>
) { }
set(nodes: ITreeNode<T, any>[], browserEvent?: UIEvent): void {
if (!(browserEvent as any)?.__forceEvent && equals(this.nodes, nodes)) {
@ -1072,6 +1075,14 @@ class Trait<T> {
}
}
if (this.nodes.length > 0 && nodes.length === 0) {
const node = this.getFirstViewElementWithTrait();
if (node) {
nodes.push(node);
}
}
this._set(nodes, true);
}
@ -1321,9 +1332,9 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
this.disposables.add(filter);
}
this.focus = new Trait(_options.identityProvider);
this.selection = new Trait(_options.identityProvider);
this.anchor = new Trait(_options.identityProvider);
this.focus = new Trait(() => this.view.getFocusedElements()[0], _options.identityProvider);
this.selection = new Trait(() => this.view.getSelectedElements()[0], _options.identityProvider);
this.anchor = new Trait(() => this.view.getAnchorElement(), _options.identityProvider);
this.view = new TreeNodeList(user, container, treeDelegate, this.renderers, this.focus, this.selection, this.anchor, { ...asListOptions(() => this.model, _options), tree: this });
this.model = this.createModel(user, this.view, _options);

View file

@ -347,7 +347,6 @@ export class ExplorerService implements IExplorerService {
const parent = element.parent;
// Remove Element from Parent (Model)
parent.removeChild(element);
this.view?.focusNeighbourIfItemFocused(element);
// Refresh Parent (View)
await this.view?.refresh(false, parent);
}

View file

@ -55,7 +55,6 @@ export interface IExplorerView {
setTreeInput(): Promise<void>;
itemsCopied(tats: ExplorerItem[], cut: boolean, previousCut: ExplorerItem[] | undefined): void;
setEditable(stat: ExplorerItem, isEditing: boolean): Promise<void>;
focusNeighbourIfItemFocused(item: ExplorerItem): void;
isItemVisible(item: ExplorerItem): boolean;
hasFocus(): boolean;
}

View file

@ -611,30 +611,6 @@ export class ExplorerView extends ViewPane {
});
}
focusNeighbourIfItemFocused(item: ExplorerItem): void {
const focus = this.tree.getFocus();
if (focus.length !== 1) {
return;
}
const compressedController = this.renderer.getCompressedNavigationController(focus[0]) || this.renderer.getCompressedNavigationController(item);
const indexOfItem = compressedController?.items.indexOf(item) || -1;
const itemsCompressedTogether = compressedController && (compressedController.items.indexOf(focus[0]) >= 0) && (indexOfItem >= 0);
if (focus[0] === item || itemsCompressedTogether) {
if (itemsCompressedTogether && indexOfItem > 0 && item.parent) {
// In case of compact items just focus the parent if it is part of the compact item. So the focus stays
this.tree.setFocus([item.parent]);
} else {
this.tree.focusNext();
const newFocus = this.tree.getFocus();
if (newFocus.length === 1 && newFocus[0] === item) {
// There was no next item to focus, focus the previous one
this.tree.focusPrevious();
}
}
}
}
override getOptimalWidth(): number {
const parentNode = this.tree.getHTMLElement();
const childNodes = ([] as HTMLElement[]).slice.call(parentNode.querySelectorAll('.explorer-item .label-name')); // select all file labels