e389ec8ac22db1854f880d21cf3d63f83447214bd90db1690270d4188dd1799031553199cedeac9874439bcef8af4f55e55b5de667d3df0a730f091d292589 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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 './currentLineHighlight.css';
  6. import { DynamicViewOverlay } from '../../view/dynamicViewOverlay.js';
  7. import { editorLineHighlight, editorLineHighlightBorder } from '../../../common/core/editorColorRegistry.js';
  8. import * as arrays from '../../../../base/common/arrays.js';
  9. import { registerThemingParticipant } from '../../../../platform/theme/common/themeService.js';
  10. import { Selection } from '../../../common/core/selection.js';
  11. import { isHighContrast } from '../../../../platform/theme/common/theme.js';
  12. export class AbstractLineHighlightOverlay extends DynamicViewOverlay {
  13. constructor(context) {
  14. super();
  15. this._context = context;
  16. const options = this._context.configuration.options;
  17. const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);
  18. this._lineHeight = options.get(61 /* EditorOption.lineHeight */);
  19. this._renderLineHighlight = options.get(87 /* EditorOption.renderLineHighlight */);
  20. this._renderLineHighlightOnlyWhenFocus = options.get(88 /* EditorOption.renderLineHighlightOnlyWhenFocus */);
  21. this._contentLeft = layoutInfo.contentLeft;
  22. this._contentWidth = layoutInfo.contentWidth;
  23. this._selectionIsEmpty = true;
  24. this._focused = false;
  25. this._cursorLineNumbers = [1];
  26. this._selections = [new Selection(1, 1, 1, 1)];
  27. this._renderData = null;
  28. this._context.addEventHandler(this);
  29. }
  30. dispose() {
  31. this._context.removeEventHandler(this);
  32. super.dispose();
  33. }
  34. _readFromSelections() {
  35. let hasChanged = false;
  36. const cursorsLineNumbers = this._selections.map(s => s.positionLineNumber);
  37. cursorsLineNumbers.sort((a, b) => a - b);
  38. if (!arrays.equals(this._cursorLineNumbers, cursorsLineNumbers)) {
  39. this._cursorLineNumbers = cursorsLineNumbers;
  40. hasChanged = true;
  41. }
  42. const selectionIsEmpty = this._selections.every(s => s.isEmpty());
  43. if (this._selectionIsEmpty !== selectionIsEmpty) {
  44. this._selectionIsEmpty = selectionIsEmpty;
  45. hasChanged = true;
  46. }
  47. return hasChanged;
  48. }
  49. // --- begin event handlers
  50. onThemeChanged(e) {
  51. return this._readFromSelections();
  52. }
  53. onConfigurationChanged(e) {
  54. const options = this._context.configuration.options;
  55. const layoutInfo = options.get(133 /* EditorOption.layoutInfo */);
  56. this._lineHeight = options.get(61 /* EditorOption.lineHeight */);
  57. this._renderLineHighlight = options.get(87 /* EditorOption.renderLineHighlight */);
  58. this._renderLineHighlightOnlyWhenFocus = options.get(88 /* EditorOption.renderLineHighlightOnlyWhenFocus */);
  59. this._contentLeft = layoutInfo.contentLeft;
  60. this._contentWidth = layoutInfo.contentWidth;
  61. return true;
  62. }
  63. onCursorStateChanged(e) {
  64. this._selections = e.selections;
  65. return this._readFromSelections();
  66. }
  67. onFlushed(e) {
  68. return true;
  69. }
  70. onLinesDeleted(e) {
  71. return true;
  72. }
  73. onLinesInserted(e) {
  74. return true;
  75. }
  76. onScrollChanged(e) {
  77. return e.scrollWidthChanged || e.scrollTopChanged;
  78. }
  79. onZonesChanged(e) {
  80. return true;
  81. }
  82. onFocusChanged(e) {
  83. if (!this._renderLineHighlightOnlyWhenFocus) {
  84. return false;
  85. }
  86. this._focused = e.isFocused;
  87. return true;
  88. }
  89. // --- end event handlers
  90. prepareRender(ctx) {
  91. if (!this._shouldRenderThis()) {
  92. this._renderData = null;
  93. return;
  94. }
  95. const renderedLine = this._renderOne(ctx);
  96. const visibleStartLineNumber = ctx.visibleRange.startLineNumber;
  97. const visibleEndLineNumber = ctx.visibleRange.endLineNumber;
  98. const len = this._cursorLineNumbers.length;
  99. let index = 0;
  100. const renderData = [];
  101. for (let lineNumber = visibleStartLineNumber; lineNumber <= visibleEndLineNumber; lineNumber++) {
  102. const lineIndex = lineNumber - visibleStartLineNumber;
  103. while (index < len && this._cursorLineNumbers[index] < lineNumber) {
  104. index++;
  105. }
  106. if (index < len && this._cursorLineNumbers[index] === lineNumber) {
  107. renderData[lineIndex] = renderedLine;
  108. }
  109. else {
  110. renderData[lineIndex] = '';
  111. }
  112. }
  113. this._renderData = renderData;
  114. }
  115. render(startLineNumber, lineNumber) {
  116. if (!this._renderData) {
  117. return '';
  118. }
  119. const lineIndex = lineNumber - startLineNumber;
  120. if (lineIndex >= this._renderData.length) {
  121. return '';
  122. }
  123. return this._renderData[lineIndex];
  124. }
  125. _shouldRenderInMargin() {
  126. return ((this._renderLineHighlight === 'gutter' || this._renderLineHighlight === 'all')
  127. && (!this._renderLineHighlightOnlyWhenFocus || this._focused));
  128. }
  129. _shouldRenderInContent() {
  130. return ((this._renderLineHighlight === 'line' || this._renderLineHighlight === 'all')
  131. && this._selectionIsEmpty
  132. && (!this._renderLineHighlightOnlyWhenFocus || this._focused));
  133. }
  134. }
  135. export class CurrentLineHighlightOverlay extends AbstractLineHighlightOverlay {
  136. _renderOne(ctx) {
  137. const className = 'current-line' + (this._shouldRenderOther() ? ' current-line-both' : '');
  138. return `<div class="${className}" style="width:${Math.max(ctx.scrollWidth, this._contentWidth)}px; height:${this._lineHeight}px;"></div>`;
  139. }
  140. _shouldRenderThis() {
  141. return this._shouldRenderInContent();
  142. }
  143. _shouldRenderOther() {
  144. return this._shouldRenderInMargin();
  145. }
  146. }
  147. export class CurrentLineMarginHighlightOverlay extends AbstractLineHighlightOverlay {
  148. _renderOne(ctx) {
  149. const className = 'current-line' + (this._shouldRenderInMargin() ? ' current-line-margin' : '') + (this._shouldRenderOther() ? ' current-line-margin-both' : '');
  150. return `<div class="${className}" style="width:${this._contentLeft}px; height:${this._lineHeight}px;"></div>`;
  151. }
  152. _shouldRenderThis() {
  153. return true;
  154. }
  155. _shouldRenderOther() {
  156. return this._shouldRenderInContent();
  157. }
  158. }
  159. registerThemingParticipant((theme, collector) => {
  160. const lineHighlight = theme.getColor(editorLineHighlight);
  161. if (lineHighlight) {
  162. collector.addRule(`.monaco-editor .view-overlays .current-line { background-color: ${lineHighlight}; }`);
  163. collector.addRule(`.monaco-editor .margin-view-overlays .current-line-margin { background-color: ${lineHighlight}; border: none; }`);
  164. }
  165. if (!lineHighlight || lineHighlight.isTransparent() || theme.defines(editorLineHighlightBorder)) {
  166. const lineHighlightBorder = theme.getColor(editorLineHighlightBorder);
  167. if (lineHighlightBorder) {
  168. collector.addRule(`.monaco-editor .view-overlays .current-line { border: 2px solid ${lineHighlightBorder}; }`);
  169. collector.addRule(`.monaco-editor .margin-view-overlays .current-line-margin { border: 2px solid ${lineHighlightBorder}; }`);
  170. if (isHighContrast(theme.type)) {
  171. collector.addRule(`.monaco-editor .view-overlays .current-line { border-width: 1px; }`);
  172. collector.addRule(`.monaco-editor .margin-view-overlays .current-line-margin { border-width: 1px; }`);
  173. }
  174. }
  175. }
  176. });