UNPKG

monaco-editor

Version:
1,037 lines (1,036 loc) • 46.6 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); } return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import './list.css'; import { localize } from '../../../../nls.js'; import { dispose } from '../../../common/lifecycle.js'; import { isNumber } from '../../../common/types.js'; import { range, firstIndex } from '../../../common/arrays.js'; import { memoize } from '../../../common/decorators.js'; import * as DOM from '../../dom.js'; import * as platform from '../../../common/platform.js'; import { Gesture } from '../../touch.js'; import { StandardKeyboardEvent } from '../../keyboardEvent.js'; import { Event, Emitter, EventBufferer, chain, mapEvent, anyEvent } from '../../../common/event.js'; import { domEvent } from '../../event.js'; import { ListView } from './listView.js'; import { Color } from '../../../common/color.js'; import { mixin } from '../../../common/objects.js'; import { CombinedSpliceable } from './splice.js'; import { clamp } from '../../../common/numbers.js'; var TraitRenderer = /** @class */ (function () { function TraitRenderer(trait) { this.trait = trait; this.renderedElements = []; } Object.defineProperty(TraitRenderer.prototype, "templateId", { get: function () { return "template:" + this.trait.trait; }, enumerable: true, configurable: true }); TraitRenderer.prototype.renderTemplate = function (container) { return container; }; TraitRenderer.prototype.renderElement = function (element, index, templateData) { var renderedElementIndex = firstIndex(this.renderedElements, function (el) { return el.templateData === templateData; }); if (renderedElementIndex >= 0) { var rendered = this.renderedElements[renderedElementIndex]; this.trait.unrender(templateData); rendered.index = index; } else { var rendered = { index: index, templateData: templateData }; this.renderedElements.push(rendered); } this.trait.renderIndex(index, templateData); }; TraitRenderer.prototype.disposeElement = function () { // noop }; TraitRenderer.prototype.splice = function (start, deleteCount, insertCount) { var rendered = []; for (var i = 0; i < this.renderedElements.length; i++) { var renderedElement = this.renderedElements[i]; if (renderedElement.index < start) { rendered.push(renderedElement); } else if (renderedElement.index >= start + deleteCount) { rendered.push({ index: renderedElement.index + insertCount - deleteCount, templateData: renderedElement.templateData }); } } this.renderedElements = rendered; }; TraitRenderer.prototype.renderIndexes = function (indexes) { for (var _i = 0, _a = this.renderedElements; _i < _a.length; _i++) { var _b = _a[_i], index = _b.index, templateData = _b.templateData; if (indexes.indexOf(index) > -1) { this.trait.renderIndex(index, templateData); } } }; TraitRenderer.prototype.disposeTemplate = function (templateData) { var index = firstIndex(this.renderedElements, function (el) { return el.templateData === templateData; }); if (index < 0) { return; } this.renderedElements.splice(index, 1); }; return TraitRenderer; }()); var Trait = /** @class */ (function () { function Trait(_trait) { this._trait = _trait; this._onChange = new Emitter(); this.indexes = []; } Object.defineProperty(Trait.prototype, "onChange", { get: function () { return this._onChange.event; }, enumerable: true, configurable: true }); Object.defineProperty(Trait.prototype, "trait", { get: function () { return this._trait; }, enumerable: true, configurable: true }); Object.defineProperty(Trait.prototype, "renderer", { get: function () { return new TraitRenderer(this); }, enumerable: true, configurable: true }); Trait.prototype.splice = function (start, deleteCount, elements) { var diff = elements.length - deleteCount; var end = start + deleteCount; var indexes = this.indexes.filter(function (i) { return i < start; }).concat(elements.map(function (hasTrait, i) { return hasTrait ? i + start : -1; }).filter(function (i) { return i !== -1; }), this.indexes.filter(function (i) { return i >= end; }).map(function (i) { return i + diff; })); this.renderer.splice(start, deleteCount, elements.length); this.set(indexes); }; Trait.prototype.renderIndex = function (index, container) { DOM.toggleClass(container, this._trait, this.contains(index)); }; Trait.prototype.unrender = function (container) { DOM.removeClass(container, this._trait); }; /** * Sets the indexes which should have this trait. * * @param indexes Indexes which should have this trait. * @return The old indexes which had this trait. */ Trait.prototype.set = function (indexes, browserEvent) { var result = this.indexes; this.indexes = indexes; var toRender = disjunction(result, indexes); this.renderer.renderIndexes(toRender); this._onChange.fire({ indexes: indexes, browserEvent: browserEvent }); return result; }; Trait.prototype.get = function () { return this.indexes; }; Trait.prototype.contains = function (index) { return this.indexes.some(function (i) { return i === index; }); }; Trait.prototype.dispose = function () { this.indexes = null; this._onChange = dispose(this._onChange); }; __decorate([ memoize ], Trait.prototype, "renderer", null); return Trait; }()); var FocusTrait = /** @class */ (function (_super) { __extends(FocusTrait, _super); function FocusTrait(getDomId) { var _this = _super.call(this, 'focused') || this; _this.getDomId = getDomId; return _this; } FocusTrait.prototype.renderIndex = function (index, container) { _super.prototype.renderIndex.call(this, index, container); container.setAttribute('role', 'treeitem'); container.setAttribute('id', this.getDomId(index)); if (this.contains(index)) { container.setAttribute('aria-selected', 'true'); } else { container.removeAttribute('aria-selected'); } }; return FocusTrait; }(Trait)); /** * The TraitSpliceable is used as a util class to be able * to preserve traits across splice calls, given an identity * provider. */ var TraitSpliceable = /** @class */ (function () { function TraitSpliceable(trait, view, getId) { this.trait = trait; this.view = view; this.getId = getId; } TraitSpliceable.prototype.splice = function (start, deleteCount, elements) { var _this = this; if (!this.getId) { return this.trait.splice(start, deleteCount, elements.map(function (e) { return false; })); } var pastElementsWithTrait = this.trait.get().map(function (i) { return _this.getId(_this.view.element(i)); }); var elementsWithTrait = elements.map(function (e) { return pastElementsWithTrait.indexOf(_this.getId(e)) > -1; }); this.trait.splice(start, deleteCount, elementsWithTrait); }; return TraitSpliceable; }()); function isInputElement(e) { return e.tagName === 'INPUT' || e.tagName === 'TEXTAREA'; } var KeyboardController = /** @class */ (function () { function KeyboardController(list, view, options) { this.list = list; this.view = view; var multipleSelectionSupport = !(options.multipleSelectionSupport === false); this.disposables = []; this.openController = options.openController || DefaultOpenController; var onKeyDown = chain(domEvent(view.domNode, 'keydown')) .filter(function (e) { return !isInputElement(e.target); }) .map(function (e) { return new StandardKeyboardEvent(e); }); onKeyDown.filter(function (e) { return e.keyCode === 3 /* Enter */; }).on(this.onEnter, this, this.disposables); onKeyDown.filter(function (e) { return e.keyCode === 16 /* UpArrow */; }).on(this.onUpArrow, this, this.disposables); onKeyDown.filter(function (e) { return e.keyCode === 18 /* DownArrow */; }).on(this.onDownArrow, this, this.disposables); onKeyDown.filter(function (e) { return e.keyCode === 11 /* PageUp */; }).on(this.onPageUpArrow, this, this.disposables); onKeyDown.filter(function (e) { return e.keyCode === 12 /* PageDown */; }).on(this.onPageDownArrow, this, this.disposables); onKeyDown.filter(function (e) { return e.keyCode === 9 /* Escape */; }).on(this.onEscape, this, this.disposables); if (multipleSelectionSupport) { onKeyDown.filter(function (e) { return (platform.isMacintosh ? e.metaKey : e.ctrlKey) && e.keyCode === 31 /* KEY_A */; }).on(this.onCtrlA, this, this.disposables); } } KeyboardController.prototype.onEnter = function (e) { e.preventDefault(); e.stopPropagation(); this.list.setSelection(this.list.getFocus(), e.browserEvent); if (this.openController.shouldOpen(e.browserEvent)) { this.list.open(this.list.getFocus(), e.browserEvent); } }; KeyboardController.prototype.onUpArrow = function (e) { e.preventDefault(); e.stopPropagation(); this.list.focusPrevious(1, false, e.browserEvent); this.list.reveal(this.list.getFocus()[0]); this.view.domNode.focus(); }; KeyboardController.prototype.onDownArrow = function (e) { e.preventDefault(); e.stopPropagation(); this.list.focusNext(1, false, e.browserEvent); this.list.reveal(this.list.getFocus()[0]); this.view.domNode.focus(); }; KeyboardController.prototype.onPageUpArrow = function (e) { e.preventDefault(); e.stopPropagation(); this.list.focusPreviousPage(e.browserEvent); this.list.reveal(this.list.getFocus()[0]); this.view.domNode.focus(); }; KeyboardController.prototype.onPageDownArrow = function (e) { e.preventDefault(); e.stopPropagation(); this.list.focusNextPage(e.browserEvent); this.list.reveal(this.list.getFocus()[0]); this.view.domNode.focus(); }; KeyboardController.prototype.onCtrlA = function (e) { e.preventDefault(); e.stopPropagation(); this.list.setSelection(range(this.list.length), e.browserEvent); this.view.domNode.focus(); }; KeyboardController.prototype.onEscape = function (e) { e.preventDefault(); e.stopPropagation(); this.list.setSelection([], e.browserEvent); this.view.domNode.focus(); }; KeyboardController.prototype.dispose = function () { this.disposables = dispose(this.disposables); }; return KeyboardController; }()); var DOMFocusController = /** @class */ (function () { function DOMFocusController(list, view) { this.list = list; this.view = view; this.disposables = []; this.disposables = []; var onKeyDown = chain(domEvent(view.domNode, 'keydown')) .filter(function (e) { return !isInputElement(e.target); }) .map(function (e) { return new StandardKeyboardEvent(e); }); onKeyDown.filter(function (e) { return e.keyCode === 2 /* Tab */ && !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey; }) .on(this.onTab, this, this.disposables); } DOMFocusController.prototype.onTab = function (e) { if (e.target !== this.view.domNode) { return; } var focus = this.list.getFocus(); if (focus.length === 0) { return; } var focusedDomElement = this.view.domElement(focus[0]); var tabIndexElement = focusedDomElement.querySelector('[tabIndex]'); if (!tabIndexElement || !(tabIndexElement instanceof HTMLElement) || tabIndexElement.tabIndex === -1) { return; } var style = window.getComputedStyle(tabIndexElement); if (style.visibility === 'hidden' || style.display === 'none') { return; } e.preventDefault(); e.stopPropagation(); tabIndexElement.focus(); }; DOMFocusController.prototype.dispose = function () { this.disposables = dispose(this.disposables); }; return DOMFocusController; }()); export function isSelectionSingleChangeEvent(event) { return platform.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey; } export function isSelectionRangeChangeEvent(event) { return event.browserEvent.shiftKey; } function isMouseRightClick(event) { return event instanceof MouseEvent && event.button === 2; } var DefaultMultipleSelectionContoller = { isSelectionSingleChangeEvent: isSelectionSingleChangeEvent, isSelectionRangeChangeEvent: isSelectionRangeChangeEvent }; var DefaultOpenController = { shouldOpen: function (event) { if (event instanceof MouseEvent) { return !isMouseRightClick(event); } return true; } }; var MouseController = /** @class */ (function () { function MouseController(list, view, options) { if (options === void 0) { options = {}; } this.list = list; this.view = view; this.options = options; this.didJustPressContextMenuKey = false; this.disposables = []; this.multipleSelectionSupport = !(options.multipleSelectionSupport === false); if (this.multipleSelectionSupport) { this.multipleSelectionController = options.multipleSelectionController || DefaultMultipleSelectionContoller; } this.openController = options.openController || DefaultOpenController; view.onMouseDown(this.onMouseDown, this, this.disposables); view.onMouseClick(this.onPointer, this, this.disposables); view.onMouseDblClick(this.onDoubleClick, this, this.disposables); view.onTouchStart(this.onMouseDown, this, this.disposables); view.onTap(this.onPointer, this, this.disposables); Gesture.addTarget(view.domNode); } Object.defineProperty(MouseController.prototype, "onContextMenu", { get: function () { var _this = this; var fromKeydown = chain(domEvent(this.view.domNode, 'keydown')) .map(function (e) { return new StandardKeyboardEvent(e); }) .filter(function (e) { return _this.didJustPressContextMenuKey = e.keyCode === 58 /* ContextMenu */ || (e.shiftKey && e.keyCode === 68 /* F10 */); }) .filter(function (e) { e.preventDefault(); e.stopPropagation(); return false; }) .map(function (event) { var index = _this.list.getFocus()[0]; var element = _this.view.element(index); var anchor = _this.view.domElement(index); return { index: index, element: element, anchor: anchor, browserEvent: event.browserEvent }; }) .event; var fromKeyup = chain(domEvent(this.view.domNode, 'keyup')) .filter(function () { var didJustPressContextMenuKey = _this.didJustPressContextMenuKey; _this.didJustPressContextMenuKey = false; return didJustPressContextMenuKey; }) .filter(function () { return _this.list.getFocus().length > 0; }) .map(function (browserEvent) { var index = _this.list.getFocus()[0]; var element = _this.view.element(index); var anchor = _this.view.domElement(index); return { index: index, element: element, anchor: anchor, browserEvent: browserEvent }; }) .filter(function (_a) { var anchor = _a.anchor; return !!anchor; }) .event; var fromMouse = chain(this.view.onContextMenu) .filter(function () { return !_this.didJustPressContextMenuKey; }) .map(function (_a) { var element = _a.element, index = _a.index, browserEvent = _a.browserEvent; return ({ element: element, index: index, anchor: { x: browserEvent.clientX + 1, y: browserEvent.clientY }, browserEvent: browserEvent }); }) .event; return anyEvent(fromKeydown, fromKeyup, fromMouse); }, enumerable: true, configurable: true }); MouseController.prototype.isSelectionSingleChangeEvent = function (event) { if (this.multipleSelectionController) { return this.multipleSelectionController.isSelectionSingleChangeEvent(event); } return platform.isMacintosh ? event.browserEvent.metaKey : event.browserEvent.ctrlKey; }; MouseController.prototype.isSelectionRangeChangeEvent = function (event) { if (this.multipleSelectionController) { return this.multipleSelectionController.isSelectionRangeChangeEvent(event); } return event.browserEvent.shiftKey; }; MouseController.prototype.isSelectionChangeEvent = function (event) { return this.isSelectionSingleChangeEvent(event) || this.isSelectionRangeChangeEvent(event); }; MouseController.prototype.onMouseDown = function (e) { if (this.options.focusOnMouseDown === false) { e.browserEvent.preventDefault(); e.browserEvent.stopPropagation(); } else if (document.activeElement !== e.browserEvent.target) { this.view.domNode.focus(); } var reference = this.list.getFocus()[0]; var selection = this.list.getSelection(); reference = reference === undefined ? selection[0] : reference; if (this.multipleSelectionSupport && this.isSelectionRangeChangeEvent(e)) { return this.changeSelection(e, reference); } var focus = e.index; if (selection.every(function (s) { return s !== focus; })) { this.list.setFocus([focus], e.browserEvent); } if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) { return this.changeSelection(e, reference); } if (this.options.selectOnMouseDown && !isMouseRightClick(e.browserEvent)) { this.list.setSelection([focus], e.browserEvent); if (this.openController.shouldOpen(e.browserEvent)) { this.list.open([focus], e.browserEvent); } } }; MouseController.prototype.onPointer = function (e) { if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) { return; } if (!this.options.selectOnMouseDown) { var focus_1 = this.list.getFocus(); this.list.setSelection(focus_1, e.browserEvent); if (this.openController.shouldOpen(e.browserEvent)) { this.list.open(focus_1, e.browserEvent); } } }; MouseController.prototype.onDoubleClick = function (e) { if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) { return; } var focus = this.list.getFocus(); this.list.setSelection(focus, e.browserEvent); this.list.pin(focus); }; MouseController.prototype.changeSelection = function (e, reference) { var focus = e.index; if (this.isSelectionRangeChangeEvent(e) && reference !== undefined) { var min = Math.min(reference, focus); var max = Math.max(reference, focus); var rangeSelection = range(min, max + 1); var selection = this.list.getSelection(); var contiguousRange = getContiguousRangeContaining(disjunction(selection, [reference]), reference); if (contiguousRange.length === 0) { return; } var newSelection = disjunction(rangeSelection, relativeComplement(selection, contiguousRange)); this.list.setSelection(newSelection, e.browserEvent); } else if (this.isSelectionSingleChangeEvent(e)) { var selection = this.list.getSelection(); var newSelection = selection.filter(function (i) { return i !== focus; }); if (selection.length === newSelection.length) { this.list.setSelection(newSelection.concat([focus]), e.browserEvent); } else { this.list.setSelection(newSelection, e.browserEvent); } } }; MouseController.prototype.dispose = function () { this.disposables = dispose(this.disposables); }; __decorate([ memoize ], MouseController.prototype, "onContextMenu", null); return MouseController; }()); var DefaultStyleController = /** @class */ (function () { function DefaultStyleController(styleElement, selectorSuffix) { this.styleElement = styleElement; this.selectorSuffix = selectorSuffix; } DefaultStyleController.prototype.style = function (styles) { var suffix = this.selectorSuffix ? "." + this.selectorSuffix : ''; var content = []; if (styles.listFocusBackground) { content.push(".monaco-list" + suffix + ":focus .monaco-list-row.focused { background-color: " + styles.listFocusBackground + "; }"); content.push(".monaco-list" + suffix + ":focus .monaco-list-row.focused:hover { background-color: " + styles.listFocusBackground + "; }"); // overwrite :hover style in this case! } if (styles.listFocusForeground) { content.push(".monaco-list" + suffix + ":focus .monaco-list-row.focused { color: " + styles.listFocusForeground + "; }"); } if (styles.listActiveSelectionBackground) { content.push(".monaco-list" + suffix + ":focus .monaco-list-row.selected { background-color: " + styles.listActiveSelectionBackground + "; }"); content.push(".monaco-list" + suffix + ":focus .monaco-list-row.selected:hover { background-color: " + styles.listActiveSelectionBackground + "; }"); // overwrite :hover style in this case! } if (styles.listActiveSelectionForeground) { content.push(".monaco-list" + suffix + ":focus .monaco-list-row.selected { color: " + styles.listActiveSelectionForeground + "; }"); } if (styles.listFocusAndSelectionBackground) { content.push(".monaco-list" + suffix + ":focus .monaco-list-row.selected.focused { background-color: " + styles.listFocusAndSelectionBackground + "; }"); } if (styles.listFocusAndSelectionForeground) { content.push(".monaco-list" + suffix + ":focus .monaco-list-row.selected.focused { color: " + styles.listFocusAndSelectionForeground + "; }"); } if (styles.listInactiveFocusBackground) { content.push(".monaco-list" + suffix + " .monaco-list-row.focused { background-color: " + styles.listInactiveFocusBackground + "; }"); content.push(".monaco-list" + suffix + " .monaco-list-row.focused:hover { background-color: " + styles.listInactiveFocusBackground + "; }"); // overwrite :hover style in this case! } if (styles.listInactiveSelectionBackground) { content.push(".monaco-list" + suffix + " .monaco-list-row.selected { background-color: " + styles.listInactiveSelectionBackground + "; }"); content.push(".monaco-list" + suffix + " .monaco-list-row.selected:hover { background-color: " + styles.listInactiveSelectionBackground + "; }"); // overwrite :hover style in this case! } if (styles.listInactiveSelectionForeground) { content.push(".monaco-list" + suffix + " .monaco-list-row.selected { color: " + styles.listInactiveSelectionForeground + "; }"); } if (styles.listHoverBackground) { content.push(".monaco-list" + suffix + " .monaco-list-row:hover { background-color: " + styles.listHoverBackground + "; }"); } if (styles.listHoverForeground) { content.push(".monaco-list" + suffix + " .monaco-list-row:hover { color: " + styles.listHoverForeground + "; }"); } if (styles.listSelectionOutline) { content.push(".monaco-list" + suffix + " .monaco-list-row.selected { outline: 1px dotted " + styles.listSelectionOutline + "; outline-offset: -1px; }"); } if (styles.listFocusOutline) { content.push(".monaco-list" + suffix + ":focus .monaco-list-row.focused { outline: 1px solid " + styles.listFocusOutline + "; outline-offset: -1px; }"); } if (styles.listInactiveFocusOutline) { content.push(".monaco-list" + suffix + " .monaco-list-row.focused { outline: 1px dotted " + styles.listInactiveFocusOutline + "; outline-offset: -1px; }"); } if (styles.listHoverOutline) { content.push(".monaco-list" + suffix + " .monaco-list-row:hover { outline: 1px dashed " + styles.listHoverOutline + "; outline-offset: -1px; }"); } var newStyles = content.join('\n'); if (newStyles !== this.styleElement.innerHTML) { this.styleElement.innerHTML = newStyles; } }; return DefaultStyleController; }()); export { DefaultStyleController }; var defaultStyles = { listFocusBackground: Color.fromHex('#073655'), listActiveSelectionBackground: Color.fromHex('#0E639C'), listActiveSelectionForeground: Color.fromHex('#FFFFFF'), listFocusAndSelectionBackground: Color.fromHex('#094771'), listFocusAndSelectionForeground: Color.fromHex('#FFFFFF'), listInactiveSelectionBackground: Color.fromHex('#3F3F46'), listHoverBackground: Color.fromHex('#2A2D2E'), listDropBackground: Color.fromHex('#383B3D') }; var DefaultOptions = { keyboardSupport: true, mouseSupport: true, multipleSelectionSupport: true }; // TODO@Joao: move these utils into a SortedArray class function getContiguousRangeContaining(range, value) { var index = range.indexOf(value); if (index === -1) { return []; } var result = []; var i = index - 1; while (i >= 0 && range[i] === value - (index - i)) { result.push(range[i--]); } result.reverse(); i = index; while (i < range.length && range[i] === value + (i - index)) { result.push(range[i++]); } return result; } /** * Given two sorted collections of numbers, returns the intersection * betweem them (OR). */ function disjunction(one, other) { var result = []; var i = 0, j = 0; while (i < one.length || j < other.length) { if (i >= one.length) { result.push(other[j++]); } else if (j >= other.length) { result.push(one[i++]); } else if (one[i] === other[j]) { result.push(one[i]); i++; j++; continue; } else if (one[i] < other[j]) { result.push(one[i++]); } else { result.push(other[j++]); } } return result; } /** * Given two sorted collections of numbers, returns the relative * complement between them (XOR). */ function relativeComplement(one, other) { var result = []; var i = 0, j = 0; while (i < one.length || j < other.length) { if (i >= one.length) { result.push(other[j++]); } else if (j >= other.length) { result.push(one[i++]); } else if (one[i] === other[j]) { i++; j++; continue; } else if (one[i] < other[j]) { result.push(one[i++]); } else { j++; } } return result; } var numericSort = function (a, b) { return a - b; }; var PipelineRenderer = /** @class */ (function () { function PipelineRenderer(_templateId, renderers) { this._templateId = _templateId; this.renderers = renderers; } Object.defineProperty(PipelineRenderer.prototype, "templateId", { get: function () { return this._templateId; }, enumerable: true, configurable: true }); PipelineRenderer.prototype.renderTemplate = function (container) { return this.renderers.map(function (r) { return r.renderTemplate(container); }); }; PipelineRenderer.prototype.renderElement = function (element, index, templateData) { var i = 0; for (var _i = 0, _a = this.renderers; _i < _a.length; _i++) { var renderer = _a[_i]; renderer.renderElement(element, index, templateData[i++]); } }; PipelineRenderer.prototype.disposeElement = function (element, index, templateData) { var i = 0; for (var _i = 0, _a = this.renderers; _i < _a.length; _i++) { var renderer = _a[_i]; renderer.disposeElement(element, index, templateData[i++]); } }; PipelineRenderer.prototype.disposeTemplate = function (templateData) { var i = 0; for (var _i = 0, _a = this.renderers; _i < _a.length; _i++) { var renderer = _a[_i]; renderer.disposeTemplate(templateData[i++]); } }; return PipelineRenderer; }()); var AccessibiltyRenderer = /** @class */ (function () { function AccessibiltyRenderer(accessibilityProvider) { this.accessibilityProvider = accessibilityProvider; this.templateId = 'a18n'; } AccessibiltyRenderer.prototype.renderTemplate = function (container) { return container; }; AccessibiltyRenderer.prototype.renderElement = function (element, index, container) { var ariaLabel = this.accessibilityProvider.getAriaLabel(element); if (ariaLabel) { container.setAttribute('aria-label', ariaLabel); } else { container.removeAttribute('aria-label'); } }; AccessibiltyRenderer.prototype.disposeElement = function (element, index, container) { // noop }; AccessibiltyRenderer.prototype.disposeTemplate = function (templateData) { // noop }; return AccessibiltyRenderer; }()); var List = /** @class */ (function () { function List(container, virtualDelegate, renderers, options) { if (options === void 0) { options = DefaultOptions; } var _this = this; this.idPrefix = "list_id_" + ++List.InstanceCount; this.eventBufferer = new EventBufferer(); this.onContextMenu = Event.None; this._onOpen = new Emitter(); this._onPin = new Emitter(); this._onDidDispose = new Emitter(); this.focus = new FocusTrait(function (i) { return _this.getElementDomId(i); }); this.selection = new Trait('selected'); mixin(options, defaultStyles, false); var baseRenderers = [this.focus.renderer, this.selection.renderer]; if (options.accessibilityProvider) { baseRenderers.push(new AccessibiltyRenderer(options.accessibilityProvider)); } renderers = renderers.map(function (r) { return new PipelineRenderer(r.templateId, baseRenderers.concat([r])); }); this.view = new ListView(container, virtualDelegate, renderers, options); this.view.domNode.setAttribute('role', 'tree'); DOM.addClass(this.view.domNode, this.idPrefix); this.view.domNode.tabIndex = 0; this.styleElement = DOM.createStyleSheet(this.view.domNode); this.styleController = options.styleController; if (!this.styleController) { this.styleController = new DefaultStyleController(this.styleElement, this.idPrefix); } this.spliceable = new CombinedSpliceable([ new TraitSpliceable(this.focus, this.view, options.identityProvider), new TraitSpliceable(this.selection, this.view, options.identityProvider), this.view ]); this.disposables = [this.focus, this.selection, this.view, this._onDidDispose]; this.onDidFocus = mapEvent(domEvent(this.view.domNode, 'focus', true), function () { return null; }); this.onDidBlur = mapEvent(domEvent(this.view.domNode, 'blur', true), function () { return null; }); this.disposables.push(new DOMFocusController(this, this.view)); if (typeof options.keyboardSupport !== 'boolean' || options.keyboardSupport) { var controller = new KeyboardController(this, this.view, options); this.disposables.push(controller); } if (typeof options.mouseSupport !== 'boolean' || options.mouseSupport) { this.mouseController = new MouseController(this, this.view, options); this.disposables.push(this.mouseController); this.onContextMenu = this.mouseController.onContextMenu; } this.onFocusChange(this._onFocusChange, this, this.disposables); this.onSelectionChange(this._onSelectionChange, this, this.disposables); if (options.ariaLabel) { this.view.domNode.setAttribute('aria-label', localize('aria list', "{0}. Use the navigation keys to navigate.", options.ariaLabel)); } this.style(options); } Object.defineProperty(List.prototype, "onFocusChange", { get: function () { var _this = this; return mapEvent(this.eventBufferer.wrapEvent(this.focus.onChange), function (e) { return _this.toListEvent(e); }); }, enumerable: true, configurable: true }); Object.defineProperty(List.prototype, "onSelectionChange", { get: function () { var _this = this; return mapEvent(this.eventBufferer.wrapEvent(this.selection.onChange), function (e) { return _this.toListEvent(e); }); }, enumerable: true, configurable: true }); Object.defineProperty(List.prototype, "onMouseClick", { get: function () { return this.view.onMouseClick; }, enumerable: true, configurable: true }); Object.defineProperty(List.prototype, "onKeyDown", { get: function () { return domEvent(this.view.domNode, 'keydown'); }, enumerable: true, configurable: true }); Object.defineProperty(List.prototype, "onDidDispose", { get: function () { return this._onDidDispose.event; }, enumerable: true, configurable: true }); List.prototype.splice = function (start, deleteCount, elements) { var _this = this; if (elements === void 0) { elements = []; } if (start < 0 || start > this.view.length) { throw new Error("Invalid start index: " + start); } if (deleteCount < 0) { throw new Error("Invalid delete count: " + deleteCount); } if (deleteCount === 0 && elements.length === 0) { return; } this.eventBufferer.bufferEvents(function () { return _this.spliceable.splice(start, deleteCount, elements); }); }; Object.defineProperty(List.prototype, "length", { get: function () { return this.view.length; }, enumerable: true, configurable: true }); Object.defineProperty(List.prototype, "contentHeight", { get: function () { return this.view.getContentHeight(); }, enumerable: true, configurable: true }); List.prototype.layout = function (height) { this.view.layout(height); }; List.prototype.setSelection = function (indexes, browserEvent) { for (var _i = 0, indexes_1 = indexes; _i < indexes_1.length; _i++) { var index = indexes_1[_i]; if (index < 0 || index >= this.length) { throw new Error("Invalid index " + index); } } indexes = indexes.sort(numericSort); this.selection.set(indexes, browserEvent); }; List.prototype.getSelection = function () { return this.selection.get(); }; List.prototype.setFocus = function (indexes, browserEvent) { for (var _i = 0, indexes_2 = indexes; _i < indexes_2.length; _i++) { var index = indexes_2[_i]; if (index < 0 || index >= this.length) { throw new Error("Invalid index " + index); } } indexes = indexes.sort(numericSort); this.focus.set(indexes, browserEvent); }; List.prototype.focusNext = function (n, loop, browserEvent) { if (n === void 0) { n = 1; } if (loop === void 0) { loop = false; } if (this.length === 0) { return; } var focus = this.focus.get(); var index = focus.length > 0 ? focus[0] + n : 0; this.setFocus(loop ? [index % this.length] : [Math.min(index, this.length - 1)], browserEvent); }; List.prototype.focusPrevious = function (n, loop, browserEvent) { if (n === void 0) { n = 1; } if (loop === void 0) { loop = false; } if (this.length === 0) { return; } var focus = this.focus.get(); var index = focus.length > 0 ? focus[0] - n : 0; if (loop && index < 0) { index = (this.length + (index % this.length)) % this.length; } this.setFocus([Math.max(index, 0)], browserEvent); }; List.prototype.focusNextPage = function (browserEvent) { var _this = this; var lastPageIndex = this.view.indexAt(this.view.getScrollTop() + this.view.renderHeight); lastPageIndex = lastPageIndex === 0 ? 0 : lastPageIndex - 1; var lastPageElement = this.view.element(lastPageIndex); var currentlyFocusedElement = this.getFocusedElements()[0]; if (currentlyFocusedElement !== lastPageElement) { this.setFocus([lastPageIndex], browserEvent); } else { var previousScrollTop = this.view.getScrollTop(); this.view.setScrollTop(previousScrollTop + this.view.renderHeight - this.view.elementHeight(lastPageIndex)); if (this.view.getScrollTop() !== previousScrollTop) { // Let the scroll event listener run setTimeout(function () { return _this.focusNextPage(browserEvent); }, 0); } } }; List.prototype.focusPreviousPage = function (browserEvent) { var _this = this; var firstPageIndex; var scrollTop = this.view.getScrollTop(); if (scrollTop === 0) { firstPageIndex = this.view.indexAt(scrollTop); } else { firstPageIndex = this.view.indexAfter(scrollTop - 1); } var firstPageElement = this.view.element(firstPageIndex); var currentlyFocusedElement = this.getFocusedElements()[0]; if (currentlyFocusedElement !== firstPageElement) { this.setFocus([firstPageIndex], browserEvent); } else { var previousScrollTop = scrollTop; this.view.setScrollTop(scrollTop - this.view.renderHeight); if (this.view.getScrollTop() !== previousScrollTop) { // Let the scroll event listener run setTimeout(function () { return _this.focusPreviousPage(browserEvent); }, 0); } } }; List.prototype.focusLast = function (browserEvent) { if (this.length === 0) { return; } this.setFocus([this.length - 1], browserEvent); }; List.prototype.focusFirst = function (browserEvent) { if (this.length === 0) { return; } this.setFocus([0], browserEvent); }; List.prototype.getFocus = function () { return this.focus.get(); }; List.prototype.getFocusedElements = function () { var _this = this; return this.getFocus().map(function (i) { return _this.view.element(i); }); }; List.prototype.reveal = function (index, relativeTop) { if (index < 0 || index >= this.length) { throw new Error("Invalid index " + index); } var scrollTop = this.view.getScrollTop(); var elementTop = this.view.elementTop(index); var elementHeight = this.view.elementHeight(index); if (isNumber(relativeTop)) { // y = mx + b var m = elementHeight - this.view.renderHeight; this.view.setScrollTop(m * clamp(relativeTop, 0, 1) + elementTop); } else { var viewItemBottom = elementTop + elementHeight; var wrapperBottom = scrollTop + this.view.renderHeight; if (elementTop < scrollTop) { this.view.setScrollTop(elementTop); } else if (viewItemBottom >= wrapperBottom) { this.view.setScrollTop(viewItemBottom - this.view.renderHeight); } } }; List.prototype.getElementDomId = function (index) { return this.idPrefix + "_" + index; }; List.prototype.getHTMLElement = function () { return this.view.domNode; }; List.prototype.open = function (indexes, browserEvent) { var _this = this; for (var _i = 0, indexes_3 = indexes; _i < indexes_3.length; _i++) { var index = indexes_3[_i]; if (index < 0 || index >= this.length) { throw new Error("Invalid index " + index); } } this._onOpen.fire({ indexes: indexes, elements: indexes.map(function (i) { return _this.view.element(i); }), browserEvent: browserEvent }); }; List.prototype.pin = function (indexes) { for (var _i = 0, indexes_4 = indexes; _i < indexes_4.length; _i++) { var index = indexes_4[_i]; if (index < 0 || index >= this.length) { throw new Error("Invalid index " + index); } } this._onPin.fire(indexes); }; List.prototype.style = function (styles) { this.styleController.style(styles); }; List.prototype.toListEvent = function (_a) { var _this = this; var indexes = _a.indexes, browserEvent = _a.browserEvent; return { indexes: indexes, elements: indexes.map(function (i) { return _this.view.element(i); }), browserEvent: browserEvent }; }; List.prototype._onFocusChange = function () { var focus = this.focus.get(); if (focus.length > 0) { this.view.domNode.setAttribute('aria-activedescendant', this.getElementDomId(focus[0])); } else { this.view.domNode.removeAttribute('aria-activedescendant'); } this.view.domNode.setAttribute('role', 'tree'); DOM.toggleClass(this.view.domNode, 'element-focused', focus.length > 0); }; List.prototype._onSelectionChange = function () { var selection = this.selection.get(); DOM.toggleClass(this.view.domNode, 'selection-none', selection.length === 0); DOM.toggleClass(this.view.domNode, 'selection-single', selection.length === 1); DOM.toggleClass(this.view.domNode, 'selection-multiple', selection.length > 1); }; List.prototype.dispose = function () { this._onDidDispose.fire(); this.disposables = dispose(this.disposables); this._onOpen.dispose(); this._onPin.dispose(); this._onDidDispose.dispose(); }; List.InstanceCount = 0; __decorate([ memoize ], List.prototype, "onFocusChange", null); __decorate([ memoize ], List.prototype, "onSelectionChange", null); return List; }()); export { List };