mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Use native tree filter and sorter (#224536)
* Use native tree filter and sorter So much cleaner using what's available * revert playground * revert playground part 2
This commit is contained in:
committed by
GitHub
parent
fd5f15a2b3
commit
3b27f1f74b
@@ -7,7 +7,7 @@ import * as dom from 'vs/base/browser/dom';
|
||||
import { Emitter, Event, EventBufferer, IValueWithChangeEvent } from 'vs/base/common/event';
|
||||
import { IHoverDelegate } from 'vs/base/browser/ui/hover/hoverDelegate';
|
||||
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { IObjectTreeElement, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree';
|
||||
import { IObjectTreeElement, ITreeNode, ITreeRenderer, TreeVisibility } from 'vs/base/browser/ui/tree/tree';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { WorkbenchObjectTree } from 'vs/platform/list/browser/listService';
|
||||
@@ -38,7 +38,7 @@ import { ThrottledDelayer } from 'vs/base/common/async';
|
||||
import { isCancellationError } from 'vs/base/common/errors';
|
||||
import type { IHoverWidget, IManagedHoverTooltipMarkdownString } from 'vs/base/browser/ui/hover/hover';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { observableValue, observableValueOpts } from 'vs/base/common/observable';
|
||||
import { observableValue, observableValueOpts, transaction } from 'vs/base/common/observable';
|
||||
import { equals } from 'vs/base/common/arrays';
|
||||
|
||||
const $ = dom.$;
|
||||
@@ -553,6 +553,12 @@ class QuickPickSeparatorElementRenderer extends BaseQuickInputListRenderer<Quick
|
||||
return this._visibleSeparatorsFrequency.has(separator);
|
||||
}
|
||||
|
||||
override renderTemplate(container: HTMLElement): IQuickInputItemTemplateData {
|
||||
const data = super.renderTemplate(container);
|
||||
data.checkbox.style.display = 'none';
|
||||
return data;
|
||||
}
|
||||
|
||||
override renderElement(node: ITreeNode<QuickPickSeparatorElement, void>, index: number, data: IQuickInputItemTemplateData): void {
|
||||
const element = node.element;
|
||||
data.element = element;
|
||||
@@ -706,6 +712,7 @@ export class QuickInputTree extends Disposable {
|
||||
// Elements that apply to the current set of elements
|
||||
private readonly _elementDisposable = this._register(new DisposableStore());
|
||||
private _lastHover: IHoverWidget | undefined;
|
||||
private _lastQueryString: string | undefined;
|
||||
|
||||
constructor(
|
||||
private parent: HTMLElement,
|
||||
@@ -726,6 +733,24 @@ export class QuickInputTree extends Disposable {
|
||||
new QuickInputItemDelegate(),
|
||||
[this._itemRenderer, this._separatorRenderer],
|
||||
{
|
||||
filter: {
|
||||
filter(element) {
|
||||
return element.hidden
|
||||
? TreeVisibility.Hidden
|
||||
: element instanceof QuickPickSeparatorElement
|
||||
? TreeVisibility.Recurse
|
||||
: TreeVisibility.Visible;
|
||||
},
|
||||
},
|
||||
sorter: {
|
||||
compare: (element, otherElement) => {
|
||||
if (!this.sortByLabel || !this._lastQueryString) {
|
||||
return 0;
|
||||
}
|
||||
const normalizedSearchValue = this._lastQueryString.toLowerCase();
|
||||
return compareEntries(element, otherElement, normalizedSearchValue);
|
||||
},
|
||||
},
|
||||
accessibilityProvider: new QuickInputAccessibilityProvider(),
|
||||
setRowLineHeight: false,
|
||||
multipleSelectionSupport: false,
|
||||
@@ -1055,6 +1080,7 @@ export class QuickInputTree extends Disposable {
|
||||
|
||||
setElements(inputElements: QuickPickItem[]): void {
|
||||
this._elementDisposable.clear();
|
||||
this._lastQueryString = undefined;
|
||||
this._inputElements = inputElements;
|
||||
this._hasCheckboxes = this.parent.classList.contains('show-checkboxes');
|
||||
let currentSeparatorElement: QuickPickSeparatorElement | undefined;
|
||||
@@ -1362,6 +1388,7 @@ export class QuickInputTree extends Disposable {
|
||||
}
|
||||
|
||||
filter(query: string): boolean {
|
||||
this._lastQueryString = query;
|
||||
if (!(this._sortByLabel || this._matchOnLabel || this._matchOnDescription || this._matchOnDetail)) {
|
||||
this._tree.layout();
|
||||
return false;
|
||||
@@ -1387,7 +1414,7 @@ export class QuickInputTree extends Disposable {
|
||||
// Filter by value (since we support icons in labels, use $(..) aware fuzzy matching)
|
||||
else {
|
||||
let currentSeparator: IQuickPickSeparator | undefined;
|
||||
this._elementTree.forEach(element => {
|
||||
this._itemElements.forEach(element => {
|
||||
let labelHighlights: IMatch[] | undefined;
|
||||
if (this.matchOnLabelMode === 'fuzzy') {
|
||||
labelHighlights = this.matchOnLabel ? matchesFuzzyIconAware(query, parseLabelWithIcons(element.saneLabel)) ?? undefined : undefined;
|
||||
@@ -1418,8 +1445,10 @@ export class QuickInputTree extends Disposable {
|
||||
|
||||
// we can show the separator unless the list gets sorted by match
|
||||
if (!this.sortByLabel) {
|
||||
const previous = element.index && this._inputElements[element.index - 1];
|
||||
currentSeparator = previous && previous.type === 'separator' ? previous : currentSeparator;
|
||||
const previous = element.index && this._inputElements[element.index - 1] || undefined;
|
||||
if (previous?.type === 'separator' && !previous.buttons) {
|
||||
currentSeparator = previous;
|
||||
}
|
||||
if (currentSeparator && !element.hidden) {
|
||||
element.separator = currentSeparator;
|
||||
currentSeparator = undefined;
|
||||
@@ -1428,33 +1457,12 @@ export class QuickInputTree extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
const shownElements = this._elementTree.filter(element => !element.hidden);
|
||||
|
||||
// Sort by value
|
||||
if (this.sortByLabel && query) {
|
||||
const normalizedSearchValue = query.toLowerCase();
|
||||
shownElements.sort((a, b) => {
|
||||
return compareEntries(a, b, normalizedSearchValue);
|
||||
});
|
||||
}
|
||||
|
||||
let currentSeparator: QuickPickSeparatorElement | undefined;
|
||||
const finalElements = shownElements.reduce((result, element, index) => {
|
||||
if (element instanceof QuickPickItemElement) {
|
||||
if (currentSeparator) {
|
||||
currentSeparator.children.push(element);
|
||||
} else {
|
||||
result.push(element);
|
||||
}
|
||||
} else if (element instanceof QuickPickSeparatorElement) {
|
||||
element.children = [];
|
||||
currentSeparator = element;
|
||||
result.push(element);
|
||||
}
|
||||
return result;
|
||||
}, new Array<IQuickPickElement>());
|
||||
|
||||
this._setElementsToTree(finalElements);
|
||||
this._setElementsToTree(this._sortByLabel && query
|
||||
// We don't render any separators if we're sorting so just render the elements
|
||||
? this._itemElements
|
||||
// Render the full tree
|
||||
: this._elementTree
|
||||
);
|
||||
this._tree.layout();
|
||||
return true;
|
||||
}
|
||||
@@ -1546,10 +1554,12 @@ export class QuickInputTree extends Disposable {
|
||||
}
|
||||
|
||||
private _updateCheckedObservables() {
|
||||
this._allVisibleCheckedObservable.set(this._allVisibleChecked(this._itemElements, false), undefined);
|
||||
const checkedCount = this._itemElements.filter(element => element.checked).length;
|
||||
this._checkedCountObservable.set(checkedCount, undefined);
|
||||
this._checkedElementsObservable.set(this.getCheckedElements(), undefined);
|
||||
transaction((tx) => {
|
||||
this._allVisibleCheckedObservable.set(this._allVisibleChecked(this._itemElements, false), tx);
|
||||
const checkedCount = this._itemElements.filter(element => element.checked).length;
|
||||
this._checkedCountObservable.set(checkedCount, tx);
|
||||
this._checkedElementsObservable.set(this.getCheckedElements(), tx);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user