61dba0fe09b1a534671dff99ad69b40a01619d2a6ad577ac4718a36403b05ca639143e18008af041e4201fc5375231402d6249d3947f6c4ea734e9ed0e99a1 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  6. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  7. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  8. 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;
  9. return c > 3 && r && Object.defineProperty(target, key, r), r;
  10. };
  11. import { isFirefox } from '../../browser.js';
  12. import { DataTransfers, StaticDND } from '../../dnd.js';
  13. import { $, addDisposableListener, animate, getContentHeight, getContentWidth, getTopLeftOffset, scheduleAtNextAnimationFrame } from '../../dom.js';
  14. import { DomEmitter } from '../../event.js';
  15. import { EventType as TouchEventType, Gesture } from '../../touch.js';
  16. import { SmoothScrollableElement } from '../scrollbar/scrollableElement.js';
  17. import { distinct, equals } from '../../../common/arrays.js';
  18. import { Delayer, disposableTimeout } from '../../../common/async.js';
  19. import { memoize } from '../../../common/decorators.js';
  20. import { Emitter, Event } from '../../../common/event.js';
  21. import { Disposable, DisposableStore, dispose, toDisposable } from '../../../common/lifecycle.js';
  22. import { Range } from '../../../common/range.js';
  23. import { Scrollable } from '../../../common/scrollable.js';
  24. import { RangeMap, shift } from './rangeMap.js';
  25. import { RowCache } from './rowCache.js';
  26. const DefaultOptions = {
  27. useShadows: true,
  28. verticalScrollMode: 1 /* ScrollbarVisibility.Auto */,
  29. setRowLineHeight: true,
  30. setRowHeight: true,
  31. supportDynamicHeights: false,
  32. dnd: {
  33. getDragElements(e) { return [e]; },
  34. getDragURI() { return null; },
  35. onDragStart() { },
  36. onDragOver() { return false; },
  37. drop() { }
  38. },
  39. horizontalScrolling: false,
  40. transformOptimization: true,
  41. alwaysConsumeMouseWheel: true,
  42. };
  43. export class ElementsDragAndDropData {
  44. constructor(elements) {
  45. this.elements = elements;
  46. }
  47. update() { }
  48. getData() {
  49. return this.elements;
  50. }
  51. }
  52. export class ExternalElementsDragAndDropData {
  53. constructor(elements) {
  54. this.elements = elements;
  55. }
  56. update() { }
  57. getData() {
  58. return this.elements;
  59. }
  60. }
  61. export class NativeDragAndDropData {
  62. constructor() {
  63. this.types = [];
  64. this.files = [];
  65. }
  66. update(dataTransfer) {
  67. if (dataTransfer.types) {
  68. this.types.splice(0, this.types.length, ...dataTransfer.types);
  69. }
  70. if (dataTransfer.files) {
  71. this.files.splice(0, this.files.length);
  72. for (let i = 0; i < dataTransfer.files.length; i++) {
  73. const file = dataTransfer.files.item(i);
  74. if (file && (file.size || file.type)) {
  75. this.files.push(file);
  76. }
  77. }
  78. }
  79. }
  80. getData() {
  81. return {
  82. types: this.types,
  83. files: this.files
  84. };
  85. }
  86. }
  87. function equalsDragFeedback(f1, f2) {
  88. if (Array.isArray(f1) && Array.isArray(f2)) {
  89. return equals(f1, f2);
  90. }
  91. return f1 === f2;
  92. }
  93. class ListViewAccessibilityProvider {
  94. constructor(accessibilityProvider) {
  95. if (accessibilityProvider === null || accessibilityProvider === void 0 ? void 0 : accessibilityProvider.getSetSize) {
  96. this.getSetSize = accessibilityProvider.getSetSize.bind(accessibilityProvider);
  97. }
  98. else {
  99. this.getSetSize = (e, i, l) => l;
  100. }
  101. if (accessibilityProvider === null || accessibilityProvider === void 0 ? void 0 : accessibilityProvider.getPosInSet) {
  102. this.getPosInSet = accessibilityProvider.getPosInSet.bind(accessibilityProvider);
  103. }
  104. else {
  105. this.getPosInSet = (e, i) => i + 1;
  106. }
  107. if (accessibilityProvider === null || accessibilityProvider === void 0 ? void 0 : accessibilityProvider.getRole) {
  108. this.getRole = accessibilityProvider.getRole.bind(accessibilityProvider);
  109. }
  110. else {
  111. this.getRole = _ => 'listitem';
  112. }
  113. if (accessibilityProvider === null || accessibilityProvider === void 0 ? void 0 : accessibilityProvider.isChecked) {
  114. this.isChecked = accessibilityProvider.isChecked.bind(accessibilityProvider);
  115. }
  116. else {
  117. this.isChecked = _ => undefined;
  118. }
  119. }
  120. }
  121. /**
  122. * The {@link ListView} is a virtual scrolling engine.
  123. *
  124. * Given that it only renders elements within its viewport, it can hold large
  125. * collections of elements and stay very performant. The performance bottleneck
  126. * usually lies within the user's rendering code for each element.
  127. *
  128. * @remarks It is a low-level widget, not meant to be used directly. Refer to the
  129. * List widget instead.
  130. */
  131. export class ListView {
  132. constructor(container, virtualDelegate, renderers, options = DefaultOptions) {
  133. var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
  134. this.virtualDelegate = virtualDelegate;
  135. this.domId = `list_id_${++ListView.InstanceCount}`;
  136. this.renderers = new Map();
  137. this.renderWidth = 0;
  138. this._scrollHeight = 0;
  139. this.scrollableElementUpdateDisposable = null;
  140. this.scrollableElementWidthDelayer = new Delayer(50);
  141. this.splicing = false;
  142. this.dragOverAnimationStopDisposable = Disposable.None;
  143. this.dragOverMouseY = 0;
  144. this.canDrop = false;
  145. this.currentDragFeedbackDisposable = Disposable.None;
  146. this.onDragLeaveTimeout = Disposable.None;
  147. this.disposables = new DisposableStore();
  148. this._onDidChangeContentHeight = new Emitter();
  149. this._horizontalScrolling = false;
  150. if (options.horizontalScrolling && options.supportDynamicHeights) {
  151. throw new Error('Horizontal scrolling and dynamic heights not supported simultaneously');
  152. }
  153. this.items = [];
  154. this.itemId = 0;
  155. this.rangeMap = new RangeMap();
  156. for (const renderer of renderers) {
  157. this.renderers.set(renderer.templateId, renderer);
  158. }
  159. this.cache = this.disposables.add(new RowCache(this.renderers));
  160. this.lastRenderTop = 0;
  161. this.lastRenderHeight = 0;
  162. this.domNode = document.createElement('div');
  163. this.domNode.className = 'monaco-list';
  164. this.domNode.classList.add(this.domId);
  165. this.domNode.tabIndex = 0;
  166. this.domNode.classList.toggle('mouse-support', typeof options.mouseSupport === 'boolean' ? options.mouseSupport : true);
  167. this._horizontalScrolling = (_a = options.horizontalScrolling) !== null && _a !== void 0 ? _a : DefaultOptions.horizontalScrolling;
  168. this.domNode.classList.toggle('horizontal-scrolling', this._horizontalScrolling);
  169. this.additionalScrollHeight = typeof options.additionalScrollHeight === 'undefined' ? 0 : options.additionalScrollHeight;
  170. this.accessibilityProvider = new ListViewAccessibilityProvider(options.accessibilityProvider);
  171. this.rowsContainer = document.createElement('div');
  172. this.rowsContainer.className = 'monaco-list-rows';
  173. const transformOptimization = (_b = options.transformOptimization) !== null && _b !== void 0 ? _b : DefaultOptions.transformOptimization;
  174. if (transformOptimization) {
  175. this.rowsContainer.style.transform = 'translate3d(0px, 0px, 0px)';
  176. }
  177. this.disposables.add(Gesture.addTarget(this.rowsContainer));
  178. this.scrollable = new Scrollable({
  179. forceIntegerValues: true,
  180. smoothScrollDuration: ((_c = options.smoothScrolling) !== null && _c !== void 0 ? _c : false) ? 125 : 0,
  181. scheduleAtNextAnimationFrame: cb => scheduleAtNextAnimationFrame(cb)
  182. });
  183. this.scrollableElement = this.disposables.add(new SmoothScrollableElement(this.rowsContainer, {
  184. alwaysConsumeMouseWheel: (_d = options.alwaysConsumeMouseWheel) !== null && _d !== void 0 ? _d : DefaultOptions.alwaysConsumeMouseWheel,
  185. horizontal: 1 /* ScrollbarVisibility.Auto */,
  186. vertical: (_e = options.verticalScrollMode) !== null && _e !== void 0 ? _e : DefaultOptions.verticalScrollMode,
  187. useShadows: (_f = options.useShadows) !== null && _f !== void 0 ? _f : DefaultOptions.useShadows,
  188. mouseWheelScrollSensitivity: options.mouseWheelScrollSensitivity,
  189. fastScrollSensitivity: options.fastScrollSensitivity
  190. }, this.scrollable));
  191. this.domNode.appendChild(this.scrollableElement.getDomNode());
  192. container.appendChild(this.domNode);
  193. this.scrollableElement.onScroll(this.onScroll, this, this.disposables);
  194. this.disposables.add(addDisposableListener(this.rowsContainer, TouchEventType.Change, e => this.onTouchChange(e)));
  195. // Prevent the monaco-scrollable-element from scrolling
  196. // https://github.com/microsoft/vscode/issues/44181
  197. this.disposables.add(addDisposableListener(this.scrollableElement.getDomNode(), 'scroll', e => e.target.scrollTop = 0));
  198. this.disposables.add(addDisposableListener(this.domNode, 'dragover', e => this.onDragOver(this.toDragEvent(e))));
  199. this.disposables.add(addDisposableListener(this.domNode, 'drop', e => this.onDrop(this.toDragEvent(e))));
  200. this.disposables.add(addDisposableListener(this.domNode, 'dragleave', e => this.onDragLeave(this.toDragEvent(e))));
  201. this.disposables.add(addDisposableListener(this.domNode, 'dragend', e => this.onDragEnd(e)));
  202. this.setRowLineHeight = (_g = options.setRowLineHeight) !== null && _g !== void 0 ? _g : DefaultOptions.setRowLineHeight;
  203. this.setRowHeight = (_h = options.setRowHeight) !== null && _h !== void 0 ? _h : DefaultOptions.setRowHeight;
  204. this.supportDynamicHeights = (_j = options.supportDynamicHeights) !== null && _j !== void 0 ? _j : DefaultOptions.supportDynamicHeights;
  205. this.dnd = (_k = options.dnd) !== null && _k !== void 0 ? _k : DefaultOptions.dnd;
  206. this.layout();
  207. }
  208. get contentHeight() { return this.rangeMap.size; }
  209. get horizontalScrolling() { return this._horizontalScrolling; }
  210. set horizontalScrolling(value) {
  211. if (value === this._horizontalScrolling) {
  212. return;
  213. }
  214. if (value && this.supportDynamicHeights) {
  215. throw new Error('Horizontal scrolling and dynamic heights not supported simultaneously');
  216. }
  217. this._horizontalScrolling = value;
  218. this.domNode.classList.toggle('horizontal-scrolling', this._horizontalScrolling);
  219. if (this._horizontalScrolling) {
  220. for (const item of this.items) {
  221. this.measureItemWidth(item);
  222. }
  223. this.updateScrollWidth();
  224. this.scrollableElement.setScrollDimensions({ width: getContentWidth(this.domNode) });
  225. this.rowsContainer.style.width = `${Math.max(this.scrollWidth || 0, this.renderWidth)}px`;
  226. }
  227. else {
  228. this.scrollableElementWidthDelayer.cancel();
  229. this.scrollableElement.setScrollDimensions({ width: this.renderWidth, scrollWidth: this.renderWidth });
  230. this.rowsContainer.style.width = '';
  231. }
  232. }
  233. updateOptions(options) {
  234. if (options.additionalScrollHeight !== undefined) {
  235. this.additionalScrollHeight = options.additionalScrollHeight;
  236. this.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });
  237. }
  238. if (options.smoothScrolling !== undefined) {
  239. this.scrollable.setSmoothScrollDuration(options.smoothScrolling ? 125 : 0);
  240. }
  241. if (options.horizontalScrolling !== undefined) {
  242. this.horizontalScrolling = options.horizontalScrolling;
  243. }
  244. if (options.mouseWheelScrollSensitivity !== undefined) {
  245. this.scrollableElement.updateOptions({ mouseWheelScrollSensitivity: options.mouseWheelScrollSensitivity });
  246. }
  247. if (options.fastScrollSensitivity !== undefined) {
  248. this.scrollableElement.updateOptions({ fastScrollSensitivity: options.fastScrollSensitivity });
  249. }
  250. }
  251. splice(start, deleteCount, elements = []) {
  252. if (this.splicing) {
  253. throw new Error('Can\'t run recursive splices.');
  254. }
  255. this.splicing = true;
  256. try {
  257. return this._splice(start, deleteCount, elements);
  258. }
  259. finally {
  260. this.splicing = false;
  261. this._onDidChangeContentHeight.fire(this.contentHeight);
  262. }
  263. }
  264. _splice(start, deleteCount, elements = []) {
  265. const previousRenderRange = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight);
  266. const deleteRange = { start, end: start + deleteCount };
  267. const removeRange = Range.intersect(previousRenderRange, deleteRange);
  268. // try to reuse rows, avoid removing them from DOM
  269. const rowsToDispose = new Map();
  270. for (let i = removeRange.end - 1; i >= removeRange.start; i--) {
  271. const item = this.items[i];
  272. item.dragStartDisposable.dispose();
  273. item.checkedDisposable.dispose();
  274. if (item.row) {
  275. let rows = rowsToDispose.get(item.templateId);
  276. if (!rows) {
  277. rows = [];
  278. rowsToDispose.set(item.templateId, rows);
  279. }
  280. const renderer = this.renderers.get(item.templateId);
  281. if (renderer && renderer.disposeElement) {
  282. renderer.disposeElement(item.element, i, item.row.templateData, item.size);
  283. }
  284. rows.push(item.row);
  285. }
  286. item.row = null;
  287. }
  288. const previousRestRange = { start: start + deleteCount, end: this.items.length };
  289. const previousRenderedRestRange = Range.intersect(previousRestRange, previousRenderRange);
  290. const previousUnrenderedRestRanges = Range.relativeComplement(previousRestRange, previousRenderRange);
  291. const inserted = elements.map(element => ({
  292. id: String(this.itemId++),
  293. element,
  294. templateId: this.virtualDelegate.getTemplateId(element),
  295. size: this.virtualDelegate.getHeight(element),
  296. width: undefined,
  297. hasDynamicHeight: !!this.virtualDelegate.hasDynamicHeight && this.virtualDelegate.hasDynamicHeight(element),
  298. lastDynamicHeightWidth: undefined,
  299. row: null,
  300. uri: undefined,
  301. dropTarget: false,
  302. dragStartDisposable: Disposable.None,
  303. checkedDisposable: Disposable.None
  304. }));
  305. let deleted;
  306. // TODO@joao: improve this optimization to catch even more cases
  307. if (start === 0 && deleteCount >= this.items.length) {
  308. this.rangeMap = new RangeMap();
  309. this.rangeMap.splice(0, 0, inserted);
  310. deleted = this.items;
  311. this.items = inserted;
  312. }
  313. else {
  314. this.rangeMap.splice(start, deleteCount, inserted);
  315. deleted = this.items.splice(start, deleteCount, ...inserted);
  316. }
  317. const delta = elements.length - deleteCount;
  318. const renderRange = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight);
  319. const renderedRestRange = shift(previousRenderedRestRange, delta);
  320. const updateRange = Range.intersect(renderRange, renderedRestRange);
  321. for (let i = updateRange.start; i < updateRange.end; i++) {
  322. this.updateItemInDOM(this.items[i], i);
  323. }
  324. const removeRanges = Range.relativeComplement(renderedRestRange, renderRange);
  325. for (const range of removeRanges) {
  326. for (let i = range.start; i < range.end; i++) {
  327. this.removeItemFromDOM(i);
  328. }
  329. }
  330. const unrenderedRestRanges = previousUnrenderedRestRanges.map(r => shift(r, delta));
  331. const elementsRange = { start, end: start + elements.length };
  332. const insertRanges = [elementsRange, ...unrenderedRestRanges].map(r => Range.intersect(renderRange, r));
  333. const beforeElement = this.getNextToLastElement(insertRanges);
  334. for (const range of insertRanges) {
  335. for (let i = range.start; i < range.end; i++) {
  336. const item = this.items[i];
  337. const rows = rowsToDispose.get(item.templateId);
  338. const row = rows === null || rows === void 0 ? void 0 : rows.pop();
  339. this.insertItemInDOM(i, beforeElement, row);
  340. }
  341. }
  342. for (const rows of rowsToDispose.values()) {
  343. for (const row of rows) {
  344. this.cache.release(row);
  345. }
  346. }
  347. this.eventuallyUpdateScrollDimensions();
  348. if (this.supportDynamicHeights) {
  349. this._rerender(this.scrollTop, this.renderHeight);
  350. }
  351. return deleted.map(i => i.element);
  352. }
  353. eventuallyUpdateScrollDimensions() {
  354. this._scrollHeight = this.contentHeight;
  355. this.rowsContainer.style.height = `${this._scrollHeight}px`;
  356. if (!this.scrollableElementUpdateDisposable) {
  357. this.scrollableElementUpdateDisposable = scheduleAtNextAnimationFrame(() => {
  358. this.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });
  359. this.updateScrollWidth();
  360. this.scrollableElementUpdateDisposable = null;
  361. });
  362. }
  363. }
  364. eventuallyUpdateScrollWidth() {
  365. if (!this.horizontalScrolling) {
  366. this.scrollableElementWidthDelayer.cancel();
  367. return;
  368. }
  369. this.scrollableElementWidthDelayer.trigger(() => this.updateScrollWidth());
  370. }
  371. updateScrollWidth() {
  372. if (!this.horizontalScrolling) {
  373. return;
  374. }
  375. let scrollWidth = 0;
  376. for (const item of this.items) {
  377. if (typeof item.width !== 'undefined') {
  378. scrollWidth = Math.max(scrollWidth, item.width);
  379. }
  380. }
  381. this.scrollWidth = scrollWidth;
  382. this.scrollableElement.setScrollDimensions({ scrollWidth: scrollWidth === 0 ? 0 : (scrollWidth + 10) });
  383. }
  384. rerender() {
  385. if (!this.supportDynamicHeights) {
  386. return;
  387. }
  388. for (const item of this.items) {
  389. item.lastDynamicHeightWidth = undefined;
  390. }
  391. this._rerender(this.lastRenderTop, this.lastRenderHeight);
  392. }
  393. get length() {
  394. return this.items.length;
  395. }
  396. get renderHeight() {
  397. const scrollDimensions = this.scrollableElement.getScrollDimensions();
  398. return scrollDimensions.height;
  399. }
  400. element(index) {
  401. return this.items[index].element;
  402. }
  403. domElement(index) {
  404. const row = this.items[index].row;
  405. return row && row.domNode;
  406. }
  407. elementHeight(index) {
  408. return this.items[index].size;
  409. }
  410. elementTop(index) {
  411. return this.rangeMap.positionAt(index);
  412. }
  413. indexAt(position) {
  414. return this.rangeMap.indexAt(position);
  415. }
  416. indexAfter(position) {
  417. return this.rangeMap.indexAfter(position);
  418. }
  419. layout(height, width) {
  420. const scrollDimensions = {
  421. height: typeof height === 'number' ? height : getContentHeight(this.domNode)
  422. };
  423. if (this.scrollableElementUpdateDisposable) {
  424. this.scrollableElementUpdateDisposable.dispose();
  425. this.scrollableElementUpdateDisposable = null;
  426. scrollDimensions.scrollHeight = this.scrollHeight;
  427. }
  428. this.scrollableElement.setScrollDimensions(scrollDimensions);
  429. if (typeof width !== 'undefined') {
  430. this.renderWidth = width;
  431. if (this.supportDynamicHeights) {
  432. this._rerender(this.scrollTop, this.renderHeight);
  433. }
  434. }
  435. if (this.horizontalScrolling) {
  436. this.scrollableElement.setScrollDimensions({
  437. width: typeof width === 'number' ? width : getContentWidth(this.domNode)
  438. });
  439. }
  440. }
  441. // Render
  442. render(previousRenderRange, renderTop, renderHeight, renderLeft, scrollWidth, updateItemsInDOM = false) {
  443. const renderRange = this.getRenderRange(renderTop, renderHeight);
  444. const rangesToInsert = Range.relativeComplement(renderRange, previousRenderRange);
  445. const rangesToRemove = Range.relativeComplement(previousRenderRange, renderRange);
  446. const beforeElement = this.getNextToLastElement(rangesToInsert);
  447. if (updateItemsInDOM) {
  448. const rangesToUpdate = Range.intersect(previousRenderRange, renderRange);
  449. for (let i = rangesToUpdate.start; i < rangesToUpdate.end; i++) {
  450. this.updateItemInDOM(this.items[i], i);
  451. }
  452. }
  453. for (const range of rangesToInsert) {
  454. for (let i = range.start; i < range.end; i++) {
  455. this.insertItemInDOM(i, beforeElement);
  456. }
  457. }
  458. for (const range of rangesToRemove) {
  459. for (let i = range.start; i < range.end; i++) {
  460. this.removeItemFromDOM(i);
  461. }
  462. }
  463. if (renderLeft !== undefined) {
  464. this.rowsContainer.style.left = `-${renderLeft}px`;
  465. }
  466. this.rowsContainer.style.top = `-${renderTop}px`;
  467. if (this.horizontalScrolling && scrollWidth !== undefined) {
  468. this.rowsContainer.style.width = `${Math.max(scrollWidth, this.renderWidth)}px`;
  469. }
  470. this.lastRenderTop = renderTop;
  471. this.lastRenderHeight = renderHeight;
  472. }
  473. // DOM operations
  474. insertItemInDOM(index, beforeElement, row) {
  475. const item = this.items[index];
  476. if (!item.row) {
  477. item.row = row !== null && row !== void 0 ? row : this.cache.alloc(item.templateId);
  478. }
  479. const role = this.accessibilityProvider.getRole(item.element) || 'listitem';
  480. item.row.domNode.setAttribute('role', role);
  481. const checked = this.accessibilityProvider.isChecked(item.element);
  482. if (typeof checked === 'boolean') {
  483. item.row.domNode.setAttribute('aria-checked', String(!!checked));
  484. }
  485. else if (checked) {
  486. const update = (checked) => item.row.domNode.setAttribute('aria-checked', String(!!checked));
  487. update(checked.value);
  488. item.checkedDisposable = checked.onDidChange(update);
  489. }
  490. if (!item.row.domNode.parentElement) {
  491. if (beforeElement) {
  492. this.rowsContainer.insertBefore(item.row.domNode, beforeElement);
  493. }
  494. else {
  495. this.rowsContainer.appendChild(item.row.domNode);
  496. }
  497. }
  498. this.updateItemInDOM(item, index);
  499. const renderer = this.renderers.get(item.templateId);
  500. if (!renderer) {
  501. throw new Error(`No renderer found for template id ${item.templateId}`);
  502. }
  503. renderer === null || renderer === void 0 ? void 0 : renderer.renderElement(item.element, index, item.row.templateData, item.size);
  504. const uri = this.dnd.getDragURI(item.element);
  505. item.dragStartDisposable.dispose();
  506. item.row.domNode.draggable = !!uri;
  507. if (uri) {
  508. item.dragStartDisposable = addDisposableListener(item.row.domNode, 'dragstart', event => this.onDragStart(item.element, uri, event));
  509. }
  510. if (this.horizontalScrolling) {
  511. this.measureItemWidth(item);
  512. this.eventuallyUpdateScrollWidth();
  513. }
  514. }
  515. measureItemWidth(item) {
  516. if (!item.row || !item.row.domNode) {
  517. return;
  518. }
  519. item.row.domNode.style.width = isFirefox ? '-moz-fit-content' : 'fit-content';
  520. item.width = getContentWidth(item.row.domNode);
  521. const style = window.getComputedStyle(item.row.domNode);
  522. if (style.paddingLeft) {
  523. item.width += parseFloat(style.paddingLeft);
  524. }
  525. if (style.paddingRight) {
  526. item.width += parseFloat(style.paddingRight);
  527. }
  528. item.row.domNode.style.width = '';
  529. }
  530. updateItemInDOM(item, index) {
  531. item.row.domNode.style.top = `${this.elementTop(index)}px`;
  532. if (this.setRowHeight) {
  533. item.row.domNode.style.height = `${item.size}px`;
  534. }
  535. if (this.setRowLineHeight) {
  536. item.row.domNode.style.lineHeight = `${item.size}px`;
  537. }
  538. item.row.domNode.setAttribute('data-index', `${index}`);
  539. item.row.domNode.setAttribute('data-last-element', index === this.length - 1 ? 'true' : 'false');
  540. item.row.domNode.setAttribute('data-parity', index % 2 === 0 ? 'even' : 'odd');
  541. item.row.domNode.setAttribute('aria-setsize', String(this.accessibilityProvider.getSetSize(item.element, index, this.length)));
  542. item.row.domNode.setAttribute('aria-posinset', String(this.accessibilityProvider.getPosInSet(item.element, index)));
  543. item.row.domNode.setAttribute('id', this.getElementDomId(index));
  544. item.row.domNode.classList.toggle('drop-target', item.dropTarget);
  545. }
  546. removeItemFromDOM(index) {
  547. const item = this.items[index];
  548. item.dragStartDisposable.dispose();
  549. item.checkedDisposable.dispose();
  550. if (item.row) {
  551. const renderer = this.renderers.get(item.templateId);
  552. if (renderer && renderer.disposeElement) {
  553. renderer.disposeElement(item.element, index, item.row.templateData, item.size);
  554. }
  555. this.cache.release(item.row);
  556. item.row = null;
  557. }
  558. if (this.horizontalScrolling) {
  559. this.eventuallyUpdateScrollWidth();
  560. }
  561. }
  562. getScrollTop() {
  563. const scrollPosition = this.scrollableElement.getScrollPosition();
  564. return scrollPosition.scrollTop;
  565. }
  566. setScrollTop(scrollTop, reuseAnimation) {
  567. if (this.scrollableElementUpdateDisposable) {
  568. this.scrollableElementUpdateDisposable.dispose();
  569. this.scrollableElementUpdateDisposable = null;
  570. this.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });
  571. }
  572. this.scrollableElement.setScrollPosition({ scrollTop, reuseAnimation });
  573. }
  574. get scrollTop() {
  575. return this.getScrollTop();
  576. }
  577. set scrollTop(scrollTop) {
  578. this.setScrollTop(scrollTop);
  579. }
  580. get scrollHeight() {
  581. return this._scrollHeight + (this.horizontalScrolling ? 10 : 0) + this.additionalScrollHeight;
  582. }
  583. // Events
  584. get onMouseClick() { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'click')).event, e => this.toMouseEvent(e), this.disposables); }
  585. get onMouseDblClick() { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'dblclick')).event, e => this.toMouseEvent(e), this.disposables); }
  586. get onMouseMiddleClick() { return Event.filter(Event.map(this.disposables.add(new DomEmitter(this.domNode, 'auxclick')).event, e => this.toMouseEvent(e), this.disposables), e => e.browserEvent.button === 1, this.disposables); }
  587. get onMouseDown() { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mousedown')).event, e => this.toMouseEvent(e), this.disposables); }
  588. get onMouseOver() { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mouseover')).event, e => this.toMouseEvent(e), this.disposables); }
  589. get onContextMenu() { return Event.any(Event.map(this.disposables.add(new DomEmitter(this.domNode, 'contextmenu')).event, e => this.toMouseEvent(e), this.disposables), Event.map(this.disposables.add(new DomEmitter(this.domNode, TouchEventType.Contextmenu)).event, e => this.toGestureEvent(e), this.disposables)); }
  590. get onTouchStart() { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'touchstart')).event, e => this.toTouchEvent(e), this.disposables); }
  591. get onTap() { return Event.map(this.disposables.add(new DomEmitter(this.rowsContainer, TouchEventType.Tap)).event, e => this.toGestureEvent(e), this.disposables); }
  592. toMouseEvent(browserEvent) {
  593. const index = this.getItemIndexFromEventTarget(browserEvent.target || null);
  594. const item = typeof index === 'undefined' ? undefined : this.items[index];
  595. const element = item && item.element;
  596. return { browserEvent, index, element };
  597. }
  598. toTouchEvent(browserEvent) {
  599. const index = this.getItemIndexFromEventTarget(browserEvent.target || null);
  600. const item = typeof index === 'undefined' ? undefined : this.items[index];
  601. const element = item && item.element;
  602. return { browserEvent, index, element };
  603. }
  604. toGestureEvent(browserEvent) {
  605. const index = this.getItemIndexFromEventTarget(browserEvent.initialTarget || null);
  606. const item = typeof index === 'undefined' ? undefined : this.items[index];
  607. const element = item && item.element;
  608. return { browserEvent, index, element };
  609. }
  610. toDragEvent(browserEvent) {
  611. const index = this.getItemIndexFromEventTarget(browserEvent.target || null);
  612. const item = typeof index === 'undefined' ? undefined : this.items[index];
  613. const element = item && item.element;
  614. return { browserEvent, index, element };
  615. }
  616. onScroll(e) {
  617. try {
  618. const previousRenderRange = this.getRenderRange(this.lastRenderTop, this.lastRenderHeight);
  619. this.render(previousRenderRange, e.scrollTop, e.height, e.scrollLeft, e.scrollWidth);
  620. if (this.supportDynamicHeights) {
  621. this._rerender(e.scrollTop, e.height, e.inSmoothScrolling);
  622. }
  623. }
  624. catch (err) {
  625. console.error('Got bad scroll event:', e);
  626. throw err;
  627. }
  628. }
  629. onTouchChange(event) {
  630. event.preventDefault();
  631. event.stopPropagation();
  632. this.scrollTop -= event.translationY;
  633. }
  634. // DND
  635. onDragStart(element, uri, event) {
  636. var _a, _b;
  637. if (!event.dataTransfer) {
  638. return;
  639. }
  640. const elements = this.dnd.getDragElements(element);
  641. event.dataTransfer.effectAllowed = 'copyMove';
  642. event.dataTransfer.setData(DataTransfers.TEXT, uri);
  643. if (event.dataTransfer.setDragImage) {
  644. let label;
  645. if (this.dnd.getDragLabel) {
  646. label = this.dnd.getDragLabel(elements, event);
  647. }
  648. if (typeof label === 'undefined') {
  649. label = String(elements.length);
  650. }
  651. const dragImage = $('.monaco-drag-image');
  652. dragImage.textContent = label;
  653. document.body.appendChild(dragImage);
  654. event.dataTransfer.setDragImage(dragImage, -10, -10);
  655. setTimeout(() => document.body.removeChild(dragImage), 0);
  656. }
  657. this.currentDragData = new ElementsDragAndDropData(elements);
  658. StaticDND.CurrentDragAndDropData = new ExternalElementsDragAndDropData(elements);
  659. (_b = (_a = this.dnd).onDragStart) === null || _b === void 0 ? void 0 : _b.call(_a, this.currentDragData, event);
  660. }
  661. onDragOver(event) {
  662. var _a;
  663. event.browserEvent.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
  664. this.onDragLeaveTimeout.dispose();
  665. if (StaticDND.CurrentDragAndDropData && StaticDND.CurrentDragAndDropData.getData() === 'vscode-ui') {
  666. return false;
  667. }
  668. this.setupDragAndDropScrollTopAnimation(event.browserEvent);
  669. if (!event.browserEvent.dataTransfer) {
  670. return false;
  671. }
  672. // Drag over from outside
  673. if (!this.currentDragData) {
  674. if (StaticDND.CurrentDragAndDropData) {
  675. // Drag over from another list
  676. this.currentDragData = StaticDND.CurrentDragAndDropData;
  677. }
  678. else {
  679. // Drag over from the desktop
  680. if (!event.browserEvent.dataTransfer.types) {
  681. return false;
  682. }
  683. this.currentDragData = new NativeDragAndDropData();
  684. }
  685. }
  686. const result = this.dnd.onDragOver(this.currentDragData, event.element, event.index, event.browserEvent);
  687. this.canDrop = typeof result === 'boolean' ? result : result.accept;
  688. if (!this.canDrop) {
  689. this.currentDragFeedback = undefined;
  690. this.currentDragFeedbackDisposable.dispose();
  691. return false;
  692. }
  693. event.browserEvent.dataTransfer.dropEffect = (typeof result !== 'boolean' && result.effect === 0 /* ListDragOverEffect.Copy */) ? 'copy' : 'move';
  694. let feedback;
  695. if (typeof result !== 'boolean' && result.feedback) {
  696. feedback = result.feedback;
  697. }
  698. else {
  699. if (typeof event.index === 'undefined') {
  700. feedback = [-1];
  701. }
  702. else {
  703. feedback = [event.index];
  704. }
  705. }
  706. // sanitize feedback list
  707. feedback = distinct(feedback).filter(i => i >= -1 && i < this.length).sort((a, b) => a - b);
  708. feedback = feedback[0] === -1 ? [-1] : feedback;
  709. if (equalsDragFeedback(this.currentDragFeedback, feedback)) {
  710. return true;
  711. }
  712. this.currentDragFeedback = feedback;
  713. this.currentDragFeedbackDisposable.dispose();
  714. if (feedback[0] === -1) { // entire list feedback
  715. this.domNode.classList.add('drop-target');
  716. this.rowsContainer.classList.add('drop-target');
  717. this.currentDragFeedbackDisposable = toDisposable(() => {
  718. this.domNode.classList.remove('drop-target');
  719. this.rowsContainer.classList.remove('drop-target');
  720. });
  721. }
  722. else {
  723. for (const index of feedback) {
  724. const item = this.items[index];
  725. item.dropTarget = true;
  726. (_a = item.row) === null || _a === void 0 ? void 0 : _a.domNode.classList.add('drop-target');
  727. }
  728. this.currentDragFeedbackDisposable = toDisposable(() => {
  729. var _a;
  730. for (const index of feedback) {
  731. const item = this.items[index];
  732. item.dropTarget = false;
  733. (_a = item.row) === null || _a === void 0 ? void 0 : _a.domNode.classList.remove('drop-target');
  734. }
  735. });
  736. }
  737. return true;
  738. }
  739. onDragLeave(event) {
  740. var _a, _b;
  741. this.onDragLeaveTimeout.dispose();
  742. this.onDragLeaveTimeout = disposableTimeout(() => this.clearDragOverFeedback(), 100);
  743. if (this.currentDragData) {
  744. (_b = (_a = this.dnd).onDragLeave) === null || _b === void 0 ? void 0 : _b.call(_a, this.currentDragData, event.element, event.index, event.browserEvent);
  745. }
  746. }
  747. onDrop(event) {
  748. if (!this.canDrop) {
  749. return;
  750. }
  751. const dragData = this.currentDragData;
  752. this.teardownDragAndDropScrollTopAnimation();
  753. this.clearDragOverFeedback();
  754. this.currentDragData = undefined;
  755. StaticDND.CurrentDragAndDropData = undefined;
  756. if (!dragData || !event.browserEvent.dataTransfer) {
  757. return;
  758. }
  759. event.browserEvent.preventDefault();
  760. dragData.update(event.browserEvent.dataTransfer);
  761. this.dnd.drop(dragData, event.element, event.index, event.browserEvent);
  762. }
  763. onDragEnd(event) {
  764. var _a, _b;
  765. this.canDrop = false;
  766. this.teardownDragAndDropScrollTopAnimation();
  767. this.clearDragOverFeedback();
  768. this.currentDragData = undefined;
  769. StaticDND.CurrentDragAndDropData = undefined;
  770. (_b = (_a = this.dnd).onDragEnd) === null || _b === void 0 ? void 0 : _b.call(_a, event);
  771. }
  772. clearDragOverFeedback() {
  773. this.currentDragFeedback = undefined;
  774. this.currentDragFeedbackDisposable.dispose();
  775. this.currentDragFeedbackDisposable = Disposable.None;
  776. }
  777. // DND scroll top animation
  778. setupDragAndDropScrollTopAnimation(event) {
  779. if (!this.dragOverAnimationDisposable) {
  780. const viewTop = getTopLeftOffset(this.domNode).top;
  781. this.dragOverAnimationDisposable = animate(this.animateDragAndDropScrollTop.bind(this, viewTop));
  782. }
  783. this.dragOverAnimationStopDisposable.dispose();
  784. this.dragOverAnimationStopDisposable = disposableTimeout(() => {
  785. if (this.dragOverAnimationDisposable) {
  786. this.dragOverAnimationDisposable.dispose();
  787. this.dragOverAnimationDisposable = undefined;
  788. }
  789. }, 1000);
  790. this.dragOverMouseY = event.pageY;
  791. }
  792. animateDragAndDropScrollTop(viewTop) {
  793. if (this.dragOverMouseY === undefined) {
  794. return;
  795. }
  796. const diff = this.dragOverMouseY - viewTop;
  797. const upperLimit = this.renderHeight - 35;
  798. if (diff < 35) {
  799. this.scrollTop += Math.max(-14, Math.floor(0.3 * (diff - 35)));
  800. }
  801. else if (diff > upperLimit) {
  802. this.scrollTop += Math.min(14, Math.floor(0.3 * (diff - upperLimit)));
  803. }
  804. }
  805. teardownDragAndDropScrollTopAnimation() {
  806. this.dragOverAnimationStopDisposable.dispose();
  807. if (this.dragOverAnimationDisposable) {
  808. this.dragOverAnimationDisposable.dispose();
  809. this.dragOverAnimationDisposable = undefined;
  810. }
  811. }
  812. // Util
  813. getItemIndexFromEventTarget(target) {
  814. const scrollableElement = this.scrollableElement.getDomNode();
  815. let element = target;
  816. while (element instanceof HTMLElement && element !== this.rowsContainer && scrollableElement.contains(element)) {
  817. const rawIndex = element.getAttribute('data-index');
  818. if (rawIndex) {
  819. const index = Number(rawIndex);
  820. if (!isNaN(index)) {
  821. return index;
  822. }
  823. }
  824. element = element.parentElement;
  825. }
  826. return undefined;
  827. }
  828. getRenderRange(renderTop, renderHeight) {
  829. return {
  830. start: this.rangeMap.indexAt(renderTop),
  831. end: this.rangeMap.indexAfter(renderTop + renderHeight - 1)
  832. };
  833. }
  834. /**
  835. * Given a stable rendered state, checks every rendered element whether it needs
  836. * to be probed for dynamic height. Adjusts scroll height and top if necessary.
  837. */
  838. _rerender(renderTop, renderHeight, inSmoothScrolling) {
  839. const previousRenderRange = this.getRenderRange(renderTop, renderHeight);
  840. // Let's remember the second element's position, this helps in scrolling up
  841. // and preserving a linear upwards scroll movement
  842. let anchorElementIndex;
  843. let anchorElementTopDelta;
  844. if (renderTop === this.elementTop(previousRenderRange.start)) {
  845. anchorElementIndex = previousRenderRange.start;
  846. anchorElementTopDelta = 0;
  847. }
  848. else if (previousRenderRange.end - previousRenderRange.start > 1) {
  849. anchorElementIndex = previousRenderRange.start + 1;
  850. anchorElementTopDelta = this.elementTop(anchorElementIndex) - renderTop;
  851. }
  852. let heightDiff = 0;
  853. while (true) {
  854. const renderRange = this.getRenderRange(renderTop, renderHeight);
  855. let didChange = false;
  856. for (let i = renderRange.start; i < renderRange.end; i++) {
  857. const diff = this.probeDynamicHeight(i);
  858. if (diff !== 0) {
  859. this.rangeMap.splice(i, 1, [this.items[i]]);
  860. }
  861. heightDiff += diff;
  862. didChange = didChange || diff !== 0;
  863. }
  864. if (!didChange) {
  865. if (heightDiff !== 0) {
  866. this.eventuallyUpdateScrollDimensions();
  867. }
  868. const unrenderRanges = Range.relativeComplement(previousRenderRange, renderRange);
  869. for (const range of unrenderRanges) {
  870. for (let i = range.start; i < range.end; i++) {
  871. if (this.items[i].row) {
  872. this.removeItemFromDOM(i);
  873. }
  874. }
  875. }
  876. const renderRanges = Range.relativeComplement(renderRange, previousRenderRange);
  877. for (const range of renderRanges) {
  878. for (let i = range.start; i < range.end; i++) {
  879. const afterIndex = i + 1;
  880. const beforeRow = afterIndex < this.items.length ? this.items[afterIndex].row : null;
  881. const beforeElement = beforeRow ? beforeRow.domNode : null;
  882. this.insertItemInDOM(i, beforeElement);
  883. }
  884. }
  885. for (let i = renderRange.start; i < renderRange.end; i++) {
  886. if (this.items[i].row) {
  887. this.updateItemInDOM(this.items[i], i);
  888. }
  889. }
  890. if (typeof anchorElementIndex === 'number') {
  891. // To compute a destination scroll top, we need to take into account the current smooth scrolling
  892. // animation, and then reuse it with a new target (to avoid prolonging the scroll)
  893. // See https://github.com/microsoft/vscode/issues/104144
  894. // See https://github.com/microsoft/vscode/pull/104284
  895. // See https://github.com/microsoft/vscode/issues/107704
  896. const deltaScrollTop = this.scrollable.getFutureScrollPosition().scrollTop - renderTop;
  897. const newScrollTop = this.elementTop(anchorElementIndex) - anchorElementTopDelta + deltaScrollTop;
  898. this.setScrollTop(newScrollTop, inSmoothScrolling);
  899. }
  900. this._onDidChangeContentHeight.fire(this.contentHeight);
  901. return;
  902. }
  903. }
  904. }
  905. probeDynamicHeight(index) {
  906. var _a, _b, _c;
  907. const item = this.items[index];
  908. if (!!this.virtualDelegate.getDynamicHeight) {
  909. const newSize = this.virtualDelegate.getDynamicHeight(item.element);
  910. if (newSize !== null) {
  911. const size = item.size;
  912. item.size = newSize;
  913. item.lastDynamicHeightWidth = this.renderWidth;
  914. return newSize - size;
  915. }
  916. }
  917. if (!item.hasDynamicHeight || item.lastDynamicHeightWidth === this.renderWidth) {
  918. return 0;
  919. }
  920. if (!!this.virtualDelegate.hasDynamicHeight && !this.virtualDelegate.hasDynamicHeight(item.element)) {
  921. return 0;
  922. }
  923. const size = item.size;
  924. if (!this.setRowHeight && item.row) {
  925. const newSize = item.row.domNode.offsetHeight;
  926. item.size = newSize;
  927. item.lastDynamicHeightWidth = this.renderWidth;
  928. return newSize - size;
  929. }
  930. const row = this.cache.alloc(item.templateId);
  931. row.domNode.style.height = '';
  932. this.rowsContainer.appendChild(row.domNode);
  933. const renderer = this.renderers.get(item.templateId);
  934. if (renderer) {
  935. renderer.renderElement(item.element, index, row.templateData, undefined);
  936. (_a = renderer.disposeElement) === null || _a === void 0 ? void 0 : _a.call(renderer, item.element, index, row.templateData, undefined);
  937. }
  938. item.size = row.domNode.offsetHeight;
  939. (_c = (_b = this.virtualDelegate).setDynamicHeight) === null || _c === void 0 ? void 0 : _c.call(_b, item.element, item.size);
  940. item.lastDynamicHeightWidth = this.renderWidth;
  941. this.rowsContainer.removeChild(row.domNode);
  942. this.cache.release(row);
  943. return item.size - size;
  944. }
  945. getNextToLastElement(ranges) {
  946. const lastRange = ranges[ranges.length - 1];
  947. if (!lastRange) {
  948. return null;
  949. }
  950. const nextToLastItem = this.items[lastRange.end];
  951. if (!nextToLastItem) {
  952. return null;
  953. }
  954. if (!nextToLastItem.row) {
  955. return null;
  956. }
  957. return nextToLastItem.row.domNode;
  958. }
  959. getElementDomId(index) {
  960. return `${this.domId}_${index}`;
  961. }
  962. // Dispose
  963. dispose() {
  964. var _a;
  965. if (this.items) {
  966. for (const item of this.items) {
  967. if (item.row) {
  968. const renderer = this.renderers.get(item.row.templateId);
  969. if (renderer) {
  970. (_a = renderer.disposeElement) === null || _a === void 0 ? void 0 : _a.call(renderer, item.element, -1, item.row.templateData, undefined);
  971. renderer.disposeTemplate(item.row.templateData);
  972. }
  973. }
  974. }
  975. this.items = [];
  976. }
  977. if (this.domNode && this.domNode.parentNode) {
  978. this.domNode.parentNode.removeChild(this.domNode);
  979. }
  980. dispose(this.disposables);
  981. }
  982. }
  983. ListView.InstanceCount = 0;
  984. __decorate([
  985. memoize
  986. ], ListView.prototype, "onMouseClick", null);
  987. __decorate([
  988. memoize
  989. ], ListView.prototype, "onMouseDblClick", null);
  990. __decorate([
  991. memoize
  992. ], ListView.prototype, "onMouseMiddleClick", null);
  993. __decorate([
  994. memoize
  995. ], ListView.prototype, "onMouseDown", null);
  996. __decorate([
  997. memoize
  998. ], ListView.prototype, "onMouseOver", null);
  999. __decorate([
  1000. memoize
  1001. ], ListView.prototype, "onContextMenu", null);
  1002. __decorate([
  1003. memoize
  1004. ], ListView.prototype, "onTouchStart", null);
  1005. __decorate([
  1006. memoize
  1007. ], ListView.prototype, "onTap", null);