| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- import { $, append, clearNode, createStyleSheet, h, hasParentWithClass } from '../../dom.js';
- import { DomEmitter } from '../../event.js';
- import { StandardKeyboardEvent } from '../../keyboardEvent.js';
- import { ActionBar } from '../actionbar/actionbar.js';
- import { FindInput } from '../findinput/findInput.js';
- import { ElementsDragAndDropData } from '../list/listView.js';
- import { isButton, isInputElement, isMonacoEditor, List, MouseController } from '../list/listWidget.js';
- import { Toggle } from '../toggle/toggle.js';
- import { getVisibleState, isFilterResult } from './indexTreeModel.js';
- import { TreeMouseEventTarget } from './tree.js';
- import { Action } from '../../../common/actions.js';
- import { distinct, equals, range } from '../../../common/arrays.js';
- import { disposableTimeout, timeout } from '../../../common/async.js';
- import { Codicon } from '../../../common/codicons.js';
- import { SetMap } from '../../../common/collections.js';
- import { Emitter, Event, EventBufferer, Relay } from '../../../common/event.js';
- import { fuzzyScore, FuzzyScore } from '../../../common/filters.js';
- import { Disposable, DisposableStore, dispose, toDisposable } from '../../../common/lifecycle.js';
- import { clamp } from '../../../common/numbers.js';
- import { isNumber } from '../../../common/types.js';
- import './media/tree.css';
- import { localize } from '../../../../nls.js';
- class TreeElementsDragAndDropData extends ElementsDragAndDropData {
- constructor(data) {
- super(data.elements.map(node => node.element));
- this.data = data;
- }
- }
- function asTreeDragAndDropData(data) {
- if (data instanceof ElementsDragAndDropData) {
- return new TreeElementsDragAndDropData(data);
- }
- return data;
- }
- class TreeNodeListDragAndDrop {
- constructor(modelProvider, dnd) {
- this.modelProvider = modelProvider;
- this.dnd = dnd;
- this.autoExpandDisposable = Disposable.None;
- }
- getDragURI(node) {
- return this.dnd.getDragURI(node.element);
- }
- getDragLabel(nodes, originalEvent) {
- if (this.dnd.getDragLabel) {
- return this.dnd.getDragLabel(nodes.map(node => node.element), originalEvent);
- }
- return undefined;
- }
- onDragStart(data, originalEvent) {
- var _a, _b;
- (_b = (_a = this.dnd).onDragStart) === null || _b === void 0 ? void 0 : _b.call(_a, asTreeDragAndDropData(data), originalEvent);
- }
- onDragOver(data, targetNode, targetIndex, originalEvent, raw = true) {
- const result = this.dnd.onDragOver(asTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);
- const didChangeAutoExpandNode = this.autoExpandNode !== targetNode;
- if (didChangeAutoExpandNode) {
- this.autoExpandDisposable.dispose();
- this.autoExpandNode = targetNode;
- }
- if (typeof targetNode === 'undefined') {
- return result;
- }
- if (didChangeAutoExpandNode && typeof result !== 'boolean' && result.autoExpand) {
- this.autoExpandDisposable = disposableTimeout(() => {
- const model = this.modelProvider();
- const ref = model.getNodeLocation(targetNode);
- if (model.isCollapsed(ref)) {
- model.setCollapsed(ref, false);
- }
- this.autoExpandNode = undefined;
- }, 500);
- }
- if (typeof result === 'boolean' || !result.accept || typeof result.bubble === 'undefined' || result.feedback) {
- if (!raw) {
- const accept = typeof result === 'boolean' ? result : result.accept;
- const effect = typeof result === 'boolean' ? undefined : result.effect;
- return { accept, effect, feedback: [targetIndex] };
- }
- return result;
- }
- if (result.bubble === 1 /* TreeDragOverBubble.Up */) {
- const model = this.modelProvider();
- const ref = model.getNodeLocation(targetNode);
- const parentRef = model.getParentNodeLocation(ref);
- const parentNode = model.getNode(parentRef);
- const parentIndex = parentRef && model.getListIndex(parentRef);
- return this.onDragOver(data, parentNode, parentIndex, originalEvent, false);
- }
- const model = this.modelProvider();
- const ref = model.getNodeLocation(targetNode);
- const start = model.getListIndex(ref);
- const length = model.getListRenderCount(ref);
- return Object.assign(Object.assign({}, result), { feedback: range(start, start + length) });
- }
- drop(data, targetNode, targetIndex, originalEvent) {
- this.autoExpandDisposable.dispose();
- this.autoExpandNode = undefined;
- this.dnd.drop(asTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);
- }
- onDragEnd(originalEvent) {
- var _a, _b;
- (_b = (_a = this.dnd).onDragEnd) === null || _b === void 0 ? void 0 : _b.call(_a, originalEvent);
- }
- }
- function asListOptions(modelProvider, options) {
- return options && Object.assign(Object.assign({}, options), { identityProvider: options.identityProvider && {
- getId(el) {
- return options.identityProvider.getId(el.element);
- }
- }, dnd: options.dnd && new TreeNodeListDragAndDrop(modelProvider, options.dnd), multipleSelectionController: options.multipleSelectionController && {
- isSelectionSingleChangeEvent(e) {
- return options.multipleSelectionController.isSelectionSingleChangeEvent(Object.assign(Object.assign({}, e), { element: e.element }));
- },
- isSelectionRangeChangeEvent(e) {
- return options.multipleSelectionController.isSelectionRangeChangeEvent(Object.assign(Object.assign({}, e), { element: e.element }));
- }
- }, accessibilityProvider: options.accessibilityProvider && Object.assign(Object.assign({}, options.accessibilityProvider), { getSetSize(node) {
- const model = modelProvider();
- const ref = model.getNodeLocation(node);
- const parentRef = model.getParentNodeLocation(ref);
- const parentNode = model.getNode(parentRef);
- return parentNode.visibleChildrenCount;
- },
- getPosInSet(node) {
- return node.visibleChildIndex + 1;
- }, isChecked: options.accessibilityProvider && options.accessibilityProvider.isChecked ? (node) => {
- return options.accessibilityProvider.isChecked(node.element);
- } : undefined, getRole: options.accessibilityProvider && options.accessibilityProvider.getRole ? (node) => {
- return options.accessibilityProvider.getRole(node.element);
- } : () => 'treeitem', getAriaLabel(e) {
- return options.accessibilityProvider.getAriaLabel(e.element);
- },
- getWidgetAriaLabel() {
- return options.accessibilityProvider.getWidgetAriaLabel();
- }, getWidgetRole: options.accessibilityProvider && options.accessibilityProvider.getWidgetRole ? () => options.accessibilityProvider.getWidgetRole() : () => 'tree', getAriaLevel: options.accessibilityProvider && options.accessibilityProvider.getAriaLevel ? (node) => options.accessibilityProvider.getAriaLevel(node.element) : (node) => {
- return node.depth;
- }, getActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && (node => {
- return options.accessibilityProvider.getActiveDescendantId(node.element);
- }) }), keyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && Object.assign(Object.assign({}, options.keyboardNavigationLabelProvider), { getKeyboardNavigationLabel(node) {
- return options.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(node.element);
- } }) });
- }
- export class ComposedTreeDelegate {
- constructor(delegate) {
- this.delegate = delegate;
- }
- getHeight(element) {
- return this.delegate.getHeight(element.element);
- }
- getTemplateId(element) {
- return this.delegate.getTemplateId(element.element);
- }
- hasDynamicHeight(element) {
- return !!this.delegate.hasDynamicHeight && this.delegate.hasDynamicHeight(element.element);
- }
- setDynamicHeight(element, height) {
- var _a, _b;
- (_b = (_a = this.delegate).setDynamicHeight) === null || _b === void 0 ? void 0 : _b.call(_a, element.element, height);
- }
- }
- export var RenderIndentGuides;
- (function (RenderIndentGuides) {
- RenderIndentGuides["None"] = "none";
- RenderIndentGuides["OnHover"] = "onHover";
- RenderIndentGuides["Always"] = "always";
- })(RenderIndentGuides || (RenderIndentGuides = {}));
- class EventCollection {
- constructor(onDidChange, _elements = []) {
- this._elements = _elements;
- this.disposables = new DisposableStore();
- this.onDidChange = Event.forEach(onDidChange, elements => this._elements = elements, this.disposables);
- }
- get elements() {
- return this._elements;
- }
- dispose() {
- this.disposables.dispose();
- }
- }
- class TreeRenderer {
- constructor(renderer, modelProvider, onDidChangeCollapseState, activeNodes, options = {}) {
- var _a;
- this.renderer = renderer;
- this.modelProvider = modelProvider;
- this.activeNodes = activeNodes;
- this.renderedElements = new Map();
- this.renderedNodes = new Map();
- this.indent = TreeRenderer.DefaultIndent;
- this.hideTwistiesOfChildlessElements = false;
- this.shouldRenderIndentGuides = false;
- this.renderedIndentGuides = new SetMap();
- this.activeIndentNodes = new Set();
- this.indentGuidesDisposable = Disposable.None;
- this.disposables = new DisposableStore();
- this.templateId = renderer.templateId;
- this.updateOptions(options);
- Event.map(onDidChangeCollapseState, e => e.node)(this.onDidChangeNodeTwistieState, this, this.disposables);
- (_a = renderer.onDidChangeTwistieState) === null || _a === void 0 ? void 0 : _a.call(renderer, this.onDidChangeTwistieState, this, this.disposables);
- }
- updateOptions(options = {}) {
- if (typeof options.indent !== 'undefined') {
- this.indent = clamp(options.indent, 0, 40);
- }
- if (typeof options.renderIndentGuides !== 'undefined') {
- const shouldRenderIndentGuides = options.renderIndentGuides !== RenderIndentGuides.None;
- if (shouldRenderIndentGuides !== this.shouldRenderIndentGuides) {
- this.shouldRenderIndentGuides = shouldRenderIndentGuides;
- this.indentGuidesDisposable.dispose();
- if (shouldRenderIndentGuides) {
- const disposables = new DisposableStore();
- this.activeNodes.onDidChange(this._onDidChangeActiveNodes, this, disposables);
- this.indentGuidesDisposable = disposables;
- this._onDidChangeActiveNodes(this.activeNodes.elements);
- }
- }
- }
- if (typeof options.hideTwistiesOfChildlessElements !== 'undefined') {
- this.hideTwistiesOfChildlessElements = options.hideTwistiesOfChildlessElements;
- }
- }
- renderTemplate(container) {
- const el = append(container, $('.monaco-tl-row'));
- const indent = append(el, $('.monaco-tl-indent'));
- const twistie = append(el, $('.monaco-tl-twistie'));
- const contents = append(el, $('.monaco-tl-contents'));
- const templateData = this.renderer.renderTemplate(contents);
- return { container, indent, twistie, indentGuidesDisposable: Disposable.None, templateData };
- }
- renderElement(node, index, templateData, height) {
- if (typeof height === 'number') {
- this.renderedNodes.set(node, { templateData, height });
- this.renderedElements.set(node.element, node);
- }
- const indent = TreeRenderer.DefaultIndent + (node.depth - 1) * this.indent;
- templateData.twistie.style.paddingLeft = `${indent}px`;
- templateData.indent.style.width = `${indent + this.indent - 16}px`;
- this.renderTwistie(node, templateData);
- if (typeof height === 'number') {
- this.renderIndentGuides(node, templateData);
- }
- this.renderer.renderElement(node, index, templateData.templateData, height);
- }
- disposeElement(node, index, templateData, height) {
- var _a, _b;
- templateData.indentGuidesDisposable.dispose();
- (_b = (_a = this.renderer).disposeElement) === null || _b === void 0 ? void 0 : _b.call(_a, node, index, templateData.templateData, height);
- if (typeof height === 'number') {
- this.renderedNodes.delete(node);
- this.renderedElements.delete(node.element);
- }
- }
- disposeTemplate(templateData) {
- this.renderer.disposeTemplate(templateData.templateData);
- }
- onDidChangeTwistieState(element) {
- const node = this.renderedElements.get(element);
- if (!node) {
- return;
- }
- this.onDidChangeNodeTwistieState(node);
- }
- onDidChangeNodeTwistieState(node) {
- const data = this.renderedNodes.get(node);
- if (!data) {
- return;
- }
- this.renderTwistie(node, data.templateData);
- this._onDidChangeActiveNodes(this.activeNodes.elements);
- this.renderIndentGuides(node, data.templateData);
- }
- renderTwistie(node, templateData) {
- templateData.twistie.classList.remove(...Codicon.treeItemExpanded.classNamesArray);
- let twistieRendered = false;
- if (this.renderer.renderTwistie) {
- twistieRendered = this.renderer.renderTwistie(node.element, templateData.twistie);
- }
- if (node.collapsible && (!this.hideTwistiesOfChildlessElements || node.visibleChildrenCount > 0)) {
- if (!twistieRendered) {
- templateData.twistie.classList.add(...Codicon.treeItemExpanded.classNamesArray);
- }
- templateData.twistie.classList.add('collapsible');
- templateData.twistie.classList.toggle('collapsed', node.collapsed);
- }
- else {
- templateData.twistie.classList.remove('collapsible', 'collapsed');
- }
- if (node.collapsible) {
- templateData.container.setAttribute('aria-expanded', String(!node.collapsed));
- }
- else {
- templateData.container.removeAttribute('aria-expanded');
- }
- }
- renderIndentGuides(target, templateData) {
- clearNode(templateData.indent);
- templateData.indentGuidesDisposable.dispose();
- if (!this.shouldRenderIndentGuides) {
- return;
- }
- const disposableStore = new DisposableStore();
- const model = this.modelProvider();
- let node = target;
- while (true) {
- const ref = model.getNodeLocation(node);
- const parentRef = model.getParentNodeLocation(ref);
- if (!parentRef) {
- break;
- }
- const parent = model.getNode(parentRef);
- const guide = $('.indent-guide', { style: `width: ${this.indent}px` });
- if (this.activeIndentNodes.has(parent)) {
- guide.classList.add('active');
- }
- if (templateData.indent.childElementCount === 0) {
- templateData.indent.appendChild(guide);
- }
- else {
- templateData.indent.insertBefore(guide, templateData.indent.firstElementChild);
- }
- this.renderedIndentGuides.add(parent, guide);
- disposableStore.add(toDisposable(() => this.renderedIndentGuides.delete(parent, guide)));
- node = parent;
- }
- templateData.indentGuidesDisposable = disposableStore;
- }
- _onDidChangeActiveNodes(nodes) {
- if (!this.shouldRenderIndentGuides) {
- return;
- }
- const set = new Set();
- const model = this.modelProvider();
- nodes.forEach(node => {
- const ref = model.getNodeLocation(node);
- try {
- const parentRef = model.getParentNodeLocation(ref);
- if (node.collapsible && node.children.length > 0 && !node.collapsed) {
- set.add(node);
- }
- else if (parentRef) {
- set.add(model.getNode(parentRef));
- }
- }
- catch (_a) {
- // noop
- }
- });
- this.activeIndentNodes.forEach(node => {
- if (!set.has(node)) {
- this.renderedIndentGuides.forEach(node, line => line.classList.remove('active'));
- }
- });
- set.forEach(node => {
- if (!this.activeIndentNodes.has(node)) {
- this.renderedIndentGuides.forEach(node, line => line.classList.add('active'));
- }
- });
- this.activeIndentNodes = set;
- }
- dispose() {
- this.renderedNodes.clear();
- this.renderedElements.clear();
- this.indentGuidesDisposable.dispose();
- dispose(this.disposables);
- }
- }
- TreeRenderer.DefaultIndent = 8;
- class FindFilter {
- constructor(tree, keyboardNavigationLabelProvider, _filter) {
- this.tree = tree;
- this.keyboardNavigationLabelProvider = keyboardNavigationLabelProvider;
- this._filter = _filter;
- this._totalCount = 0;
- this._matchCount = 0;
- this._pattern = '';
- this._lowercasePattern = '';
- this.disposables = new DisposableStore();
- tree.onWillRefilter(this.reset, this, this.disposables);
- }
- get totalCount() { return this._totalCount; }
- get matchCount() { return this._matchCount; }
- filter(element, parentVisibility) {
- let visibility = 1 /* TreeVisibility.Visible */;
- if (this._filter) {
- const result = this._filter.filter(element, parentVisibility);
- if (typeof result === 'boolean') {
- visibility = result ? 1 /* TreeVisibility.Visible */ : 0 /* TreeVisibility.Hidden */;
- }
- else if (isFilterResult(result)) {
- visibility = getVisibleState(result.visibility);
- }
- else {
- visibility = result;
- }
- if (visibility === 0 /* TreeVisibility.Hidden */) {
- return false;
- }
- }
- this._totalCount++;
- if (!this._pattern) {
- this._matchCount++;
- return { data: FuzzyScore.Default, visibility };
- }
- const label = this.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(element);
- const labels = Array.isArray(label) ? label : [label];
- for (const l of labels) {
- const labelStr = l && l.toString();
- if (typeof labelStr === 'undefined') {
- return { data: FuzzyScore.Default, visibility };
- }
- const score = fuzzyScore(this._pattern, this._lowercasePattern, 0, labelStr, labelStr.toLowerCase(), 0, { firstMatchCanBeWeak: true, boostFullMatch: true });
- if (score) {
- this._matchCount++;
- return labels.length === 1 ?
- { data: score, visibility } :
- { data: { label: labelStr, score: score }, visibility };
- }
- }
- if (this.tree.findMode === TreeFindMode.Filter) {
- return 2 /* TreeVisibility.Recurse */;
- }
- else {
- return { data: FuzzyScore.Default, visibility };
- }
- }
- reset() {
- this._totalCount = 0;
- this._matchCount = 0;
- }
- dispose() {
- dispose(this.disposables);
- }
- }
- export class ModeToggle extends Toggle {
- constructor(opts) {
- var _a;
- super({
- icon: Codicon.filter,
- title: localize('filter', "Filter"),
- isChecked: (_a = opts === null || opts === void 0 ? void 0 : opts.isChecked) !== null && _a !== void 0 ? _a : false,
- inputActiveOptionBorder: opts === null || opts === void 0 ? void 0 : opts.inputActiveOptionBorder,
- inputActiveOptionForeground: opts === null || opts === void 0 ? void 0 : opts.inputActiveOptionForeground,
- inputActiveOptionBackground: opts === null || opts === void 0 ? void 0 : opts.inputActiveOptionBackground
- });
- }
- }
- export var TreeFindMode;
- (function (TreeFindMode) {
- TreeFindMode[TreeFindMode["Highlight"] = 0] = "Highlight";
- TreeFindMode[TreeFindMode["Filter"] = 1] = "Filter";
- })(TreeFindMode || (TreeFindMode = {}));
- class FindWidget extends Disposable {
- constructor(container, tree, contextViewProvider, mode, options) {
- super();
- this.tree = tree;
- this.elements = h('.monaco-tree-type-filter', [
- h('.monaco-tree-type-filter-grab.codicon.codicon-debug-gripper@grab', { tabIndex: 0 }),
- h('.monaco-tree-type-filter-input@findInput'),
- h('.monaco-tree-type-filter-actionbar@actionbar'),
- ]);
- this.width = 0;
- this.right = 0;
- this._onDidDisable = new Emitter();
- container.appendChild(this.elements.root);
- this._register(toDisposable(() => container.removeChild(this.elements.root)));
- this.modeToggle = this._register(new ModeToggle(Object.assign(Object.assign({}, options), { isChecked: mode === TreeFindMode.Filter })));
- this.onDidChangeMode = Event.map(this.modeToggle.onChange, () => this.modeToggle.checked ? TreeFindMode.Filter : TreeFindMode.Highlight, this._store);
- this.findInput = this._register(new FindInput(this.elements.findInput, contextViewProvider, false, {
- label: localize('type to search', "Type to search"),
- additionalToggles: [this.modeToggle]
- }));
- this.actionbar = this._register(new ActionBar(this.elements.actionbar));
- this.mode = mode;
- const emitter = this._register(new DomEmitter(this.findInput.inputBox.inputElement, 'keydown'));
- const onKeyDown = this._register(Event.chain(emitter.event))
- .map(e => new StandardKeyboardEvent(e))
- .event;
- this._register(onKeyDown((e) => {
- switch (e.keyCode) {
- case 18 /* KeyCode.DownArrow */:
- e.preventDefault();
- e.stopPropagation();
- this.tree.domFocus();
- return;
- }
- }));
- const closeAction = this._register(new Action('close', localize('close', "Close"), 'codicon codicon-close', true, () => this.dispose()));
- this.actionbar.push(closeAction, { icon: true, label: false });
- const onGrabMouseDown = this._register(new DomEmitter(this.elements.grab, 'mousedown'));
- this._register(onGrabMouseDown.event(e => {
- const disposables = new DisposableStore();
- const onWindowMouseMove = disposables.add(new DomEmitter(window, 'mousemove'));
- const onWindowMouseUp = disposables.add(new DomEmitter(window, 'mouseup'));
- const startRight = this.right;
- const startX = e.pageX;
- this.elements.grab.classList.add('grabbing');
- const update = (e) => {
- const deltaX = e.pageX - startX;
- this.right = startRight - deltaX;
- this.layout();
- };
- disposables.add(onWindowMouseMove.event(update));
- disposables.add(onWindowMouseUp.event(e => {
- update(e);
- this.elements.grab.classList.remove('grabbing');
- disposables.dispose();
- }));
- }));
- const onGrabKeyDown = this._register(Event.chain(this._register(new DomEmitter(this.elements.grab, 'keydown')).event))
- .map(e => new StandardKeyboardEvent(e))
- .event;
- this._register(onGrabKeyDown((e) => {
- let right;
- if (e.keyCode === 15 /* KeyCode.LeftArrow */) {
- right = Number.POSITIVE_INFINITY;
- }
- else if (e.keyCode === 17 /* KeyCode.RightArrow */) {
- right = 0;
- }
- else if (e.keyCode === 10 /* KeyCode.Space */) {
- right = this.right === 0 ? Number.POSITIVE_INFINITY : 0;
- }
- if (right !== undefined) {
- e.preventDefault();
- e.stopPropagation();
- this.right = right;
- this.layout();
- }
- }));
- this.onDidChangeValue = this.findInput.onDidChange;
- this.style(options !== null && options !== void 0 ? options : {});
- }
- set mode(mode) {
- this.modeToggle.checked = mode === TreeFindMode.Filter;
- this.findInput.inputBox.setPlaceHolder(mode === TreeFindMode.Filter ? localize('type to filter', "Type to filter") : localize('type to search', "Type to search"));
- }
- style(styles) {
- this.findInput.style(styles);
- if (styles.listFilterWidgetBackground) {
- this.elements.root.style.backgroundColor = styles.listFilterWidgetBackground.toString();
- }
- if (styles.listFilterWidgetShadow) {
- this.elements.root.style.boxShadow = `0 0 8px 2px ${styles.listFilterWidgetShadow}`;
- }
- }
- layout(width = this.width) {
- this.width = width;
- this.right = clamp(this.right, 0, Math.max(0, width - 212));
- this.elements.root.style.right = `${this.right}px`;
- }
- showMessage(message) {
- this.findInput.showMessage(message);
- }
- clearMessage() {
- this.findInput.clearMessage();
- }
- dispose() {
- const _super = Object.create(null, {
- dispose: { get: () => super.dispose }
- });
- return __awaiter(this, void 0, void 0, function* () {
- this._onDidDisable.fire();
- this.elements.root.classList.add('disabled');
- yield timeout(300);
- _super.dispose.call(this);
- });
- }
- }
- class FindController {
- constructor(tree, model, view, filter, contextViewProvider) {
- var _a;
- this.tree = tree;
- this.view = view;
- this.filter = filter;
- this.contextViewProvider = contextViewProvider;
- this._pattern = '';
- this.width = 0;
- this._onDidChangeMode = new Emitter();
- this.onDidChangeMode = this._onDidChangeMode.event;
- this._onDidChangePattern = new Emitter();
- this._onDidChangeOpenState = new Emitter();
- this.onDidChangeOpenState = this._onDidChangeOpenState.event;
- this.enabledDisposables = new DisposableStore();
- this.disposables = new DisposableStore();
- this._mode = (_a = tree.options.defaultFindMode) !== null && _a !== void 0 ? _a : TreeFindMode.Highlight;
- model.onDidSplice(this.onDidSpliceModel, this, this.disposables);
- }
- get pattern() { return this._pattern; }
- get mode() { return this._mode; }
- set mode(mode) {
- if (mode === this._mode) {
- return;
- }
- this._mode = mode;
- if (this.widget) {
- this.widget.mode = this._mode;
- }
- this.tree.refilter();
- this.render();
- this._onDidChangeMode.fire(mode);
- }
- onDidSpliceModel() {
- if (!this.widget || this.pattern.length === 0) {
- return;
- }
- this.tree.refilter();
- this.render();
- }
- render() {
- var _a, _b;
- const noMatches = this.filter.totalCount > 0 && this.filter.matchCount === 0;
- if (this.pattern && noMatches) {
- (_a = this.widget) === null || _a === void 0 ? void 0 : _a.showMessage({ type: 2 /* MessageType.WARNING */, content: localize('not found', "No elements found.") });
- }
- else {
- (_b = this.widget) === null || _b === void 0 ? void 0 : _b.clearMessage();
- }
- }
- shouldAllowFocus(node) {
- if (!this.widget || !this.pattern || this._mode === TreeFindMode.Filter) {
- return true;
- }
- if (this.filter.totalCount > 0 && this.filter.matchCount <= 1) {
- return true;
- }
- return !FuzzyScore.isDefault(node.filterData);
- }
- style(styles) {
- var _a;
- this.styles = styles;
- (_a = this.widget) === null || _a === void 0 ? void 0 : _a.style(styles);
- }
- layout(width) {
- var _a;
- this.width = width;
- (_a = this.widget) === null || _a === void 0 ? void 0 : _a.layout(width);
- }
- dispose() {
- this._onDidChangePattern.dispose();
- this.enabledDisposables.dispose();
- this.disposables.dispose();
- }
- }
- function asTreeMouseEvent(event) {
- let target = TreeMouseEventTarget.Unknown;
- if (hasParentWithClass(event.browserEvent.target, 'monaco-tl-twistie', 'monaco-tl-row')) {
- target = TreeMouseEventTarget.Twistie;
- }
- else if (hasParentWithClass(event.browserEvent.target, 'monaco-tl-contents', 'monaco-tl-row')) {
- target = TreeMouseEventTarget.Element;
- }
- else if (hasParentWithClass(event.browserEvent.target, 'monaco-tree-type-filter', 'monaco-list')) {
- target = TreeMouseEventTarget.Filter;
- }
- return {
- browserEvent: event.browserEvent,
- element: event.element ? event.element.element : null,
- target
- };
- }
- function dfs(node, fn) {
- fn(node);
- node.children.forEach(child => dfs(child, fn));
- }
- /**
- * The trait concept needs to exist at the tree level, because collapsed
- * tree nodes will not be known by the list.
- */
- class Trait {
- constructor(getFirstViewElementWithTrait, identityProvider) {
- this.getFirstViewElementWithTrait = getFirstViewElementWithTrait;
- this.identityProvider = identityProvider;
- this.nodes = [];
- this._onDidChange = new Emitter();
- this.onDidChange = this._onDidChange.event;
- }
- get nodeSet() {
- if (!this._nodeSet) {
- this._nodeSet = this.createNodeSet();
- }
- return this._nodeSet;
- }
- set(nodes, browserEvent) {
- if (!(browserEvent === null || browserEvent === void 0 ? void 0 : browserEvent.__forceEvent) && equals(this.nodes, nodes)) {
- return;
- }
- this._set(nodes, false, browserEvent);
- }
- _set(nodes, silent, browserEvent) {
- this.nodes = [...nodes];
- this.elements = undefined;
- this._nodeSet = undefined;
- if (!silent) {
- const that = this;
- this._onDidChange.fire({ get elements() { return that.get(); }, browserEvent });
- }
- }
- get() {
- if (!this.elements) {
- this.elements = this.nodes.map(node => node.element);
- }
- return [...this.elements];
- }
- getNodes() {
- return this.nodes;
- }
- has(node) {
- return this.nodeSet.has(node);
- }
- onDidModelSplice({ insertedNodes, deletedNodes }) {
- if (!this.identityProvider) {
- const set = this.createNodeSet();
- const visit = (node) => set.delete(node);
- deletedNodes.forEach(node => dfs(node, visit));
- this.set([...set.values()]);
- return;
- }
- const deletedNodesIdSet = new Set();
- const deletedNodesVisitor = (node) => deletedNodesIdSet.add(this.identityProvider.getId(node.element).toString());
- deletedNodes.forEach(node => dfs(node, deletedNodesVisitor));
- const insertedNodesMap = new Map();
- const insertedNodesVisitor = (node) => insertedNodesMap.set(this.identityProvider.getId(node.element).toString(), node);
- insertedNodes.forEach(node => dfs(node, insertedNodesVisitor));
- const nodes = [];
- for (const node of this.nodes) {
- const id = this.identityProvider.getId(node.element).toString();
- const wasDeleted = deletedNodesIdSet.has(id);
- if (!wasDeleted) {
- nodes.push(node);
- }
- else {
- const insertedNode = insertedNodesMap.get(id);
- if (insertedNode) {
- nodes.push(insertedNode);
- }
- }
- }
- if (this.nodes.length > 0 && nodes.length === 0) {
- const node = this.getFirstViewElementWithTrait();
- if (node) {
- nodes.push(node);
- }
- }
- this._set(nodes, true);
- }
- createNodeSet() {
- const set = new Set();
- for (const node of this.nodes) {
- set.add(node);
- }
- return set;
- }
- }
- class TreeNodeListMouseController extends MouseController {
- constructor(list, tree) {
- super(list);
- this.tree = tree;
- }
- onViewPointer(e) {
- if (isButton(e.browserEvent.target) ||
- isInputElement(e.browserEvent.target) ||
- isMonacoEditor(e.browserEvent.target)) {
- return;
- }
- const node = e.element;
- if (!node) {
- return super.onViewPointer(e);
- }
- if (this.isSelectionRangeChangeEvent(e) || this.isSelectionSingleChangeEvent(e)) {
- return super.onViewPointer(e);
- }
- const target = e.browserEvent.target;
- const onTwistie = target.classList.contains('monaco-tl-twistie')
- || (target.classList.contains('monaco-icon-label') && target.classList.contains('folder-icon') && e.browserEvent.offsetX < 16);
- let expandOnlyOnTwistieClick = false;
- if (typeof this.tree.expandOnlyOnTwistieClick === 'function') {
- expandOnlyOnTwistieClick = this.tree.expandOnlyOnTwistieClick(node.element);
- }
- else {
- expandOnlyOnTwistieClick = !!this.tree.expandOnlyOnTwistieClick;
- }
- if (expandOnlyOnTwistieClick && !onTwistie && e.browserEvent.detail !== 2) {
- return super.onViewPointer(e);
- }
- if (!this.tree.expandOnDoubleClick && e.browserEvent.detail === 2) {
- return super.onViewPointer(e);
- }
- if (node.collapsible) {
- const model = this.tree.model; // internal
- const location = model.getNodeLocation(node);
- const recursive = e.browserEvent.altKey;
- this.tree.setFocus([location]);
- model.setCollapsed(location, undefined, recursive);
- if (expandOnlyOnTwistieClick && onTwistie) {
- return;
- }
- }
- super.onViewPointer(e);
- }
- onDoubleClick(e) {
- const onTwistie = e.browserEvent.target.classList.contains('monaco-tl-twistie');
- if (onTwistie || !this.tree.expandOnDoubleClick) {
- return;
- }
- super.onDoubleClick(e);
- }
- }
- /**
- * We use this List subclass to restore selection and focus as nodes
- * get rendered in the list, possibly due to a node expand() call.
- */
- class TreeNodeList extends List {
- constructor(user, container, virtualDelegate, renderers, focusTrait, selectionTrait, anchorTrait, options) {
- super(user, container, virtualDelegate, renderers, options);
- this.focusTrait = focusTrait;
- this.selectionTrait = selectionTrait;
- this.anchorTrait = anchorTrait;
- }
- createMouseController(options) {
- return new TreeNodeListMouseController(this, options.tree);
- }
- splice(start, deleteCount, elements = []) {
- super.splice(start, deleteCount, elements);
- if (elements.length === 0) {
- return;
- }
- const additionalFocus = [];
- const additionalSelection = [];
- let anchor;
- elements.forEach((node, index) => {
- if (this.focusTrait.has(node)) {
- additionalFocus.push(start + index);
- }
- if (this.selectionTrait.has(node)) {
- additionalSelection.push(start + index);
- }
- if (this.anchorTrait.has(node)) {
- anchor = start + index;
- }
- });
- if (additionalFocus.length > 0) {
- super.setFocus(distinct([...super.getFocus(), ...additionalFocus]));
- }
- if (additionalSelection.length > 0) {
- super.setSelection(distinct([...super.getSelection(), ...additionalSelection]));
- }
- if (typeof anchor === 'number') {
- super.setAnchor(anchor);
- }
- }
- setFocus(indexes, browserEvent, fromAPI = false) {
- super.setFocus(indexes, browserEvent);
- if (!fromAPI) {
- this.focusTrait.set(indexes.map(i => this.element(i)), browserEvent);
- }
- }
- setSelection(indexes, browserEvent, fromAPI = false) {
- super.setSelection(indexes, browserEvent);
- if (!fromAPI) {
- this.selectionTrait.set(indexes.map(i => this.element(i)), browserEvent);
- }
- }
- setAnchor(index, fromAPI = false) {
- super.setAnchor(index);
- if (!fromAPI) {
- if (typeof index === 'undefined') {
- this.anchorTrait.set([]);
- }
- else {
- this.anchorTrait.set([this.element(index)]);
- }
- }
- }
- }
- export class AbstractTree {
- constructor(_user, container, delegate, renderers, _options = {}) {
- var _a;
- this._user = _user;
- this._options = _options;
- this.eventBufferer = new EventBufferer();
- this.onDidChangeFindOpenState = Event.None;
- this.disposables = new DisposableStore();
- this._onWillRefilter = new Emitter();
- this.onWillRefilter = this._onWillRefilter.event;
- this._onDidUpdateOptions = new Emitter();
- const treeDelegate = new ComposedTreeDelegate(delegate);
- const onDidChangeCollapseStateRelay = new Relay();
- const onDidChangeActiveNodes = new Relay();
- const activeNodes = this.disposables.add(new EventCollection(onDidChangeActiveNodes.event));
- this.renderers = renderers.map(r => new TreeRenderer(r, () => this.model, onDidChangeCollapseStateRelay.event, activeNodes, _options));
- for (const r of this.renderers) {
- this.disposables.add(r);
- }
- let filter;
- if (_options.keyboardNavigationLabelProvider) {
- filter = new FindFilter(this, _options.keyboardNavigationLabelProvider, _options.filter);
- _options = Object.assign(Object.assign({}, _options), { filter: filter }); // TODO need typescript help here
- this.disposables.add(filter);
- }
- 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, Object.assign(Object.assign({}, asListOptions(() => this.model, _options)), { tree: this }));
- this.model = this.createModel(_user, this.view, _options);
- onDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState;
- const onDidModelSplice = Event.forEach(this.model.onDidSplice, e => {
- this.eventBufferer.bufferEvents(() => {
- this.focus.onDidModelSplice(e);
- this.selection.onDidModelSplice(e);
- });
- }, this.disposables);
- // Make sure the `forEach` always runs
- onDidModelSplice(() => null, null, this.disposables);
- // Active nodes can change when the model changes or when focus or selection change.
- // We debounce it with 0 delay since these events may fire in the same stack and we only
- // want to run this once. It also doesn't matter if it runs on the next tick since it's only
- // a nice to have UI feature.
- onDidChangeActiveNodes.input = Event.chain(Event.any(onDidModelSplice, this.focus.onDidChange, this.selection.onDidChange))
- .debounce(() => null, 0)
- .map(() => {
- const set = new Set();
- for (const node of this.focus.getNodes()) {
- set.add(node);
- }
- for (const node of this.selection.getNodes()) {
- set.add(node);
- }
- return [...set.values()];
- }).event;
- if (_options.keyboardSupport !== false) {
- const onKeyDown = Event.chain(this.view.onKeyDown)
- .filter(e => !isInputElement(e.target))
- .map(e => new StandardKeyboardEvent(e));
- onKeyDown.filter(e => e.keyCode === 15 /* KeyCode.LeftArrow */).on(this.onLeftArrow, this, this.disposables);
- onKeyDown.filter(e => e.keyCode === 17 /* KeyCode.RightArrow */).on(this.onRightArrow, this, this.disposables);
- onKeyDown.filter(e => e.keyCode === 10 /* KeyCode.Space */).on(this.onSpace, this, this.disposables);
- }
- if (((_a = _options.findWidgetEnabled) !== null && _a !== void 0 ? _a : true) && _options.keyboardNavigationLabelProvider && _options.contextViewProvider) {
- this.findController = new FindController(this, this.model, this.view, filter, _options.contextViewProvider);
- this.focusNavigationFilter = node => this.findController.shouldAllowFocus(node);
- this.onDidChangeFindOpenState = this.findController.onDidChangeOpenState;
- this.disposables.add(this.findController);
- this.onDidChangeFindMode = this.findController.onDidChangeMode;
- }
- else {
- this.onDidChangeFindMode = Event.None;
- }
- this.styleElement = createStyleSheet(this.view.getHTMLElement());
- this.getHTMLElement().classList.toggle('always', this._options.renderIndentGuides === RenderIndentGuides.Always);
- }
- get onDidChangeFocus() { return this.eventBufferer.wrapEvent(this.focus.onDidChange); }
- get onDidChangeSelection() { return this.eventBufferer.wrapEvent(this.selection.onDidChange); }
- get onMouseDblClick() { return Event.filter(Event.map(this.view.onMouseDblClick, asTreeMouseEvent), e => e.target !== TreeMouseEventTarget.Filter); }
- get onPointer() { return Event.map(this.view.onPointer, asTreeMouseEvent); }
- get onDidFocus() { return this.view.onDidFocus; }
- get onDidChangeModel() { return Event.signal(this.model.onDidSplice); }
- get onDidChangeCollapseState() { return this.model.onDidChangeCollapseState; }
- get findMode() { var _a, _b; return (_b = (_a = this.findController) === null || _a === void 0 ? void 0 : _a.mode) !== null && _b !== void 0 ? _b : TreeFindMode.Highlight; }
- set findMode(findMode) { if (this.findController) {
- this.findController.mode = findMode;
- } }
- get expandOnDoubleClick() { return typeof this._options.expandOnDoubleClick === 'undefined' ? true : this._options.expandOnDoubleClick; }
- get expandOnlyOnTwistieClick() { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? true : this._options.expandOnlyOnTwistieClick; }
- get onDidDispose() { return this.view.onDidDispose; }
- updateOptions(optionsUpdate = {}) {
- this._options = Object.assign(Object.assign({}, this._options), optionsUpdate);
- for (const renderer of this.renderers) {
- renderer.updateOptions(optionsUpdate);
- }
- this.view.updateOptions(this._options);
- this._onDidUpdateOptions.fire(this._options);
- this.getHTMLElement().classList.toggle('always', this._options.renderIndentGuides === RenderIndentGuides.Always);
- }
- get options() {
- return this._options;
- }
- // Widget
- getHTMLElement() {
- return this.view.getHTMLElement();
- }
- get scrollTop() {
- return this.view.scrollTop;
- }
- set scrollTop(scrollTop) {
- this.view.scrollTop = scrollTop;
- }
- domFocus() {
- this.view.domFocus();
- }
- layout(height, width) {
- var _a;
- this.view.layout(height, width);
- if (isNumber(width)) {
- (_a = this.findController) === null || _a === void 0 ? void 0 : _a.layout(width);
- }
- }
- style(styles) {
- var _a;
- const suffix = `.${this.view.domId}`;
- const content = [];
- if (styles.treeIndentGuidesStroke) {
- content.push(`.monaco-list${suffix}:hover .monaco-tl-indent > .indent-guide, .monaco-list${suffix}.always .monaco-tl-indent > .indent-guide { border-color: ${styles.treeIndentGuidesStroke.transparent(0.4)}; }`);
- content.push(`.monaco-list${suffix} .monaco-tl-indent > .indent-guide.active { border-color: ${styles.treeIndentGuidesStroke}; }`);
- }
- this.styleElement.textContent = content.join('\n');
- (_a = this.findController) === null || _a === void 0 ? void 0 : _a.style(styles);
- this.view.style(styles);
- }
- // Tree navigation
- getParentElement(location) {
- const parentRef = this.model.getParentNodeLocation(location);
- const parentNode = this.model.getNode(parentRef);
- return parentNode.element;
- }
- getFirstElementChild(location) {
- return this.model.getFirstElementChild(location);
- }
- // Tree
- getNode(location) {
- return this.model.getNode(location);
- }
- collapse(location, recursive = false) {
- return this.model.setCollapsed(location, true, recursive);
- }
- expand(location, recursive = false) {
- return this.model.setCollapsed(location, false, recursive);
- }
- isCollapsible(location) {
- return this.model.isCollapsible(location);
- }
- setCollapsible(location, collapsible) {
- return this.model.setCollapsible(location, collapsible);
- }
- isCollapsed(location) {
- return this.model.isCollapsed(location);
- }
- refilter() {
- this._onWillRefilter.fire(undefined);
- this.model.refilter();
- }
- setSelection(elements, browserEvent) {
- const nodes = elements.map(e => this.model.getNode(e));
- this.selection.set(nodes, browserEvent);
- const indexes = elements.map(e => this.model.getListIndex(e)).filter(i => i > -1);
- this.view.setSelection(indexes, browserEvent, true);
- }
- getSelection() {
- return this.selection.get();
- }
- setFocus(elements, browserEvent) {
- const nodes = elements.map(e => this.model.getNode(e));
- this.focus.set(nodes, browserEvent);
- const indexes = elements.map(e => this.model.getListIndex(e)).filter(i => i > -1);
- this.view.setFocus(indexes, browserEvent, true);
- }
- getFocus() {
- return this.focus.get();
- }
- reveal(location, relativeTop) {
- this.model.expandTo(location);
- const index = this.model.getListIndex(location);
- if (index === -1) {
- return;
- }
- this.view.reveal(index, relativeTop);
- }
- // List
- onLeftArrow(e) {
- e.preventDefault();
- e.stopPropagation();
- const nodes = this.view.getFocusedElements();
- if (nodes.length === 0) {
- return;
- }
- const node = nodes[0];
- const location = this.model.getNodeLocation(node);
- const didChange = this.model.setCollapsed(location, true);
- if (!didChange) {
- const parentLocation = this.model.getParentNodeLocation(location);
- if (!parentLocation) {
- return;
- }
- const parentListIndex = this.model.getListIndex(parentLocation);
- this.view.reveal(parentListIndex);
- this.view.setFocus([parentListIndex]);
- }
- }
- onRightArrow(e) {
- e.preventDefault();
- e.stopPropagation();
- const nodes = this.view.getFocusedElements();
- if (nodes.length === 0) {
- return;
- }
- const node = nodes[0];
- const location = this.model.getNodeLocation(node);
- const didChange = this.model.setCollapsed(location, false);
- if (!didChange) {
- if (!node.children.some(child => child.visible)) {
- return;
- }
- const [focusedIndex] = this.view.getFocus();
- const firstChildIndex = focusedIndex + 1;
- this.view.reveal(firstChildIndex);
- this.view.setFocus([firstChildIndex]);
- }
- }
- onSpace(e) {
- e.preventDefault();
- e.stopPropagation();
- const nodes = this.view.getFocusedElements();
- if (nodes.length === 0) {
- return;
- }
- const node = nodes[0];
- const location = this.model.getNodeLocation(node);
- const recursive = e.browserEvent.altKey;
- this.model.setCollapsed(location, undefined, recursive);
- }
- dispose() {
- dispose(this.disposables);
- this.view.dispose();
- }
- }
|