c17cd3f3c5e12631661cf6011dd2cff32e83f3aa09fa86694aaa722d5e957114d9cad46bac250ea40c88b1f32f6d51bf94593c71051feca111c3ff11030a91 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. import { $, append, clearNode, createStyleSheet } from '../../dom.js';
  6. import { List } from '../list/listWidget.js';
  7. import { SplitView } from '../splitview/splitview.js';
  8. import { Emitter, Event } from '../../../common/event.js';
  9. import { DisposableStore } from '../../../common/lifecycle.js';
  10. import './table.css';
  11. class TableListRenderer {
  12. constructor(columns, renderers, getColumnSize) {
  13. this.columns = columns;
  14. this.getColumnSize = getColumnSize;
  15. this.templateId = TableListRenderer.TemplateId;
  16. this.renderedTemplates = new Set();
  17. const rendererMap = new Map(renderers.map(r => [r.templateId, r]));
  18. this.renderers = [];
  19. for (const column of columns) {
  20. const renderer = rendererMap.get(column.templateId);
  21. if (!renderer) {
  22. throw new Error(`Table cell renderer for template id ${column.templateId} not found.`);
  23. }
  24. this.renderers.push(renderer);
  25. }
  26. }
  27. renderTemplate(container) {
  28. const rowContainer = append(container, $('.monaco-table-tr'));
  29. const cellContainers = [];
  30. const cellTemplateData = [];
  31. for (let i = 0; i < this.columns.length; i++) {
  32. const renderer = this.renderers[i];
  33. const cellContainer = append(rowContainer, $('.monaco-table-td', { 'data-col-index': i }));
  34. cellContainer.style.width = `${this.getColumnSize(i)}px`;
  35. cellContainers.push(cellContainer);
  36. cellTemplateData.push(renderer.renderTemplate(cellContainer));
  37. }
  38. const result = { container, cellContainers, cellTemplateData };
  39. this.renderedTemplates.add(result);
  40. return result;
  41. }
  42. renderElement(element, index, templateData, height) {
  43. for (let i = 0; i < this.columns.length; i++) {
  44. const column = this.columns[i];
  45. const cell = column.project(element);
  46. const renderer = this.renderers[i];
  47. renderer.renderElement(cell, index, templateData.cellTemplateData[i], height);
  48. }
  49. }
  50. disposeElement(element, index, templateData, height) {
  51. for (let i = 0; i < this.columns.length; i++) {
  52. const renderer = this.renderers[i];
  53. if (renderer.disposeElement) {
  54. const column = this.columns[i];
  55. const cell = column.project(element);
  56. renderer.disposeElement(cell, index, templateData.cellTemplateData[i], height);
  57. }
  58. }
  59. }
  60. disposeTemplate(templateData) {
  61. for (let i = 0; i < this.columns.length; i++) {
  62. const renderer = this.renderers[i];
  63. renderer.disposeTemplate(templateData.cellTemplateData[i]);
  64. }
  65. clearNode(templateData.container);
  66. this.renderedTemplates.delete(templateData);
  67. }
  68. layoutColumn(index, size) {
  69. for (const { cellContainers } of this.renderedTemplates) {
  70. cellContainers[index].style.width = `${size}px`;
  71. }
  72. }
  73. }
  74. TableListRenderer.TemplateId = 'row';
  75. function asListVirtualDelegate(delegate) {
  76. return {
  77. getHeight(row) { return delegate.getHeight(row); },
  78. getTemplateId() { return TableListRenderer.TemplateId; },
  79. };
  80. }
  81. class ColumnHeader {
  82. constructor(column, index) {
  83. this.column = column;
  84. this.index = index;
  85. this._onDidLayout = new Emitter();
  86. this.onDidLayout = this._onDidLayout.event;
  87. this.element = $('.monaco-table-th', { 'data-col-index': index, title: column.tooltip }, column.label);
  88. }
  89. get minimumSize() { var _a; return (_a = this.column.minimumWidth) !== null && _a !== void 0 ? _a : 120; }
  90. get maximumSize() { var _a; return (_a = this.column.maximumWidth) !== null && _a !== void 0 ? _a : Number.POSITIVE_INFINITY; }
  91. get onDidChange() { var _a; return (_a = this.column.onDidChangeWidthConstraints) !== null && _a !== void 0 ? _a : Event.None; }
  92. layout(size) {
  93. this._onDidLayout.fire([this.index, size]);
  94. }
  95. }
  96. export class Table {
  97. constructor(user, container, virtualDelegate, columns, renderers, _options) {
  98. this.virtualDelegate = virtualDelegate;
  99. this.domId = `table_id_${++Table.InstanceCount}`;
  100. this.disposables = new DisposableStore();
  101. this.cachedWidth = 0;
  102. this.cachedHeight = 0;
  103. this.domNode = append(container, $(`.monaco-table.${this.domId}`));
  104. const headers = columns.map((c, i) => new ColumnHeader(c, i));
  105. const descriptor = {
  106. size: headers.reduce((a, b) => a + b.column.weight, 0),
  107. views: headers.map(view => ({ size: view.column.weight, view }))
  108. };
  109. this.splitview = this.disposables.add(new SplitView(this.domNode, {
  110. orientation: 1 /* Orientation.HORIZONTAL */,
  111. scrollbarVisibility: 2 /* ScrollbarVisibility.Hidden */,
  112. getSashOrthogonalSize: () => this.cachedHeight,
  113. descriptor
  114. }));
  115. this.splitview.el.style.height = `${virtualDelegate.headerRowHeight}px`;
  116. this.splitview.el.style.lineHeight = `${virtualDelegate.headerRowHeight}px`;
  117. const renderer = new TableListRenderer(columns, renderers, i => this.splitview.getViewSize(i));
  118. this.list = this.disposables.add(new List(user, this.domNode, asListVirtualDelegate(virtualDelegate), [renderer], _options));
  119. Event.any(...headers.map(h => h.onDidLayout))(([index, size]) => renderer.layoutColumn(index, size), null, this.disposables);
  120. this.splitview.onDidSashReset(index => {
  121. const totalWeight = columns.reduce((r, c) => r + c.weight, 0);
  122. const size = columns[index].weight / totalWeight * this.cachedWidth;
  123. this.splitview.resizeView(index, size);
  124. }, null, this.disposables);
  125. this.styleElement = createStyleSheet(this.domNode);
  126. this.style({});
  127. }
  128. get onDidChangeFocus() { return this.list.onDidChangeFocus; }
  129. get onDidChangeSelection() { return this.list.onDidChangeSelection; }
  130. get onMouseDblClick() { return this.list.onMouseDblClick; }
  131. get onPointer() { return this.list.onPointer; }
  132. get onDidFocus() { return this.list.onDidFocus; }
  133. get onDidDispose() { return this.list.onDidDispose; }
  134. updateOptions(options) {
  135. this.list.updateOptions(options);
  136. }
  137. splice(start, deleteCount, elements = []) {
  138. this.list.splice(start, deleteCount, elements);
  139. }
  140. getHTMLElement() {
  141. return this.domNode;
  142. }
  143. style(styles) {
  144. const content = [];
  145. content.push(`.monaco-table.${this.domId} > .monaco-split-view2 .monaco-sash.vertical::before {
  146. top: ${this.virtualDelegate.headerRowHeight + 1}px;
  147. height: calc(100% - ${this.virtualDelegate.headerRowHeight}px);
  148. }`);
  149. this.styleElement.textContent = content.join('\n');
  150. this.list.style(styles);
  151. }
  152. getSelectedElements() {
  153. return this.list.getSelectedElements();
  154. }
  155. getSelection() {
  156. return this.list.getSelection();
  157. }
  158. getFocus() {
  159. return this.list.getFocus();
  160. }
  161. dispose() {
  162. this.disposables.dispose();
  163. }
  164. }
  165. Table.InstanceCount = 0;