a1b7a257c683270c49fc46f993696e32d740ca9f951e6e8703cc9da51c9a05e8877a5b4b747d51a75189e36eb4d44a397fdf46b5eed3fbda9eb6879b667dda 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  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 * as arrays from '../../../base/common/arrays.js';
  6. import { Position } from '../core/position.js';
  7. import { Range } from '../core/range.js';
  8. import { IndentGuide, IndentGuideHorizontalLine } from '../textModelGuides.js';
  9. import { ModelDecorationOptions } from '../model/textModel.js';
  10. import { LineInjectedText } from '../textModelEvents.js';
  11. import * as viewEvents from '../viewEvents.js';
  12. import { createModelLineProjection } from './modelLineProjection.js';
  13. import { ConstantTimePrefixSumComputer } from '../model/prefixSumComputer.js';
  14. import { ViewLineData } from '../viewModel.js';
  15. export class ViewModelLinesFromProjectedModel {
  16. constructor(editorId, model, domLineBreaksComputerFactory, monospaceLineBreaksComputerFactory, fontInfo, tabSize, wrappingStrategy, wrappingColumn, wrappingIndent) {
  17. this._editorId = editorId;
  18. this.model = model;
  19. this._validModelVersionId = -1;
  20. this._domLineBreaksComputerFactory = domLineBreaksComputerFactory;
  21. this._monospaceLineBreaksComputerFactory = monospaceLineBreaksComputerFactory;
  22. this.fontInfo = fontInfo;
  23. this.tabSize = tabSize;
  24. this.wrappingStrategy = wrappingStrategy;
  25. this.wrappingColumn = wrappingColumn;
  26. this.wrappingIndent = wrappingIndent;
  27. this._constructLines(/*resetHiddenAreas*/ true, null);
  28. }
  29. dispose() {
  30. this.hiddenAreasDecorationIds = this.model.deltaDecorations(this.hiddenAreasDecorationIds, []);
  31. }
  32. createCoordinatesConverter() {
  33. return new CoordinatesConverter(this);
  34. }
  35. _constructLines(resetHiddenAreas, previousLineBreaks) {
  36. this.modelLineProjections = [];
  37. if (resetHiddenAreas) {
  38. this.hiddenAreasDecorationIds = this.model.deltaDecorations(this.hiddenAreasDecorationIds, []);
  39. }
  40. const linesContent = this.model.getLinesContent();
  41. const injectedTextDecorations = this.model.getInjectedTextDecorations(this._editorId);
  42. const lineCount = linesContent.length;
  43. const lineBreaksComputer = this.createLineBreaksComputer();
  44. const injectedTextQueue = new arrays.ArrayQueue(LineInjectedText.fromDecorations(injectedTextDecorations));
  45. for (let i = 0; i < lineCount; i++) {
  46. const lineInjectedText = injectedTextQueue.takeWhile(t => t.lineNumber === i + 1);
  47. lineBreaksComputer.addRequest(linesContent[i], lineInjectedText, previousLineBreaks ? previousLineBreaks[i] : null);
  48. }
  49. const linesBreaks = lineBreaksComputer.finalize();
  50. const values = [];
  51. const hiddenAreas = this.hiddenAreasDecorationIds.map((areaId) => this.model.getDecorationRange(areaId)).sort(Range.compareRangesUsingStarts);
  52. let hiddenAreaStart = 1, hiddenAreaEnd = 0;
  53. let hiddenAreaIdx = -1;
  54. let nextLineNumberToUpdateHiddenArea = (hiddenAreaIdx + 1 < hiddenAreas.length) ? hiddenAreaEnd + 1 : lineCount + 2;
  55. for (let i = 0; i < lineCount; i++) {
  56. const lineNumber = i + 1;
  57. if (lineNumber === nextLineNumberToUpdateHiddenArea) {
  58. hiddenAreaIdx++;
  59. hiddenAreaStart = hiddenAreas[hiddenAreaIdx].startLineNumber;
  60. hiddenAreaEnd = hiddenAreas[hiddenAreaIdx].endLineNumber;
  61. nextLineNumberToUpdateHiddenArea = (hiddenAreaIdx + 1 < hiddenAreas.length) ? hiddenAreaEnd + 1 : lineCount + 2;
  62. }
  63. const isInHiddenArea = (lineNumber >= hiddenAreaStart && lineNumber <= hiddenAreaEnd);
  64. const line = createModelLineProjection(linesBreaks[i], !isInHiddenArea);
  65. values[i] = line.getViewLineCount();
  66. this.modelLineProjections[i] = line;
  67. }
  68. this._validModelVersionId = this.model.getVersionId();
  69. this.projectedModelLineLineCounts = new ConstantTimePrefixSumComputer(values);
  70. }
  71. getHiddenAreas() {
  72. return this.hiddenAreasDecorationIds.map((decId) => this.model.getDecorationRange(decId));
  73. }
  74. setHiddenAreas(_ranges) {
  75. const validatedRanges = _ranges.map(r => this.model.validateRange(r));
  76. const newRanges = normalizeLineRanges(validatedRanges);
  77. // TODO@Martin: Please stop calling this method on each model change!
  78. // This checks if there really was a change
  79. const oldRanges = this.hiddenAreasDecorationIds.map((areaId) => this.model.getDecorationRange(areaId)).sort(Range.compareRangesUsingStarts);
  80. if (newRanges.length === oldRanges.length) {
  81. let hasDifference = false;
  82. for (let i = 0; i < newRanges.length; i++) {
  83. if (!newRanges[i].equalsRange(oldRanges[i])) {
  84. hasDifference = true;
  85. break;
  86. }
  87. }
  88. if (!hasDifference) {
  89. return false;
  90. }
  91. }
  92. const newDecorations = newRanges.map((r) => ({
  93. range: r,
  94. options: ModelDecorationOptions.EMPTY,
  95. }));
  96. this.hiddenAreasDecorationIds = this.model.deltaDecorations(this.hiddenAreasDecorationIds, newDecorations);
  97. const hiddenAreas = newRanges;
  98. let hiddenAreaStart = 1, hiddenAreaEnd = 0;
  99. let hiddenAreaIdx = -1;
  100. let nextLineNumberToUpdateHiddenArea = (hiddenAreaIdx + 1 < hiddenAreas.length) ? hiddenAreaEnd + 1 : this.modelLineProjections.length + 2;
  101. let hasVisibleLine = false;
  102. for (let i = 0; i < this.modelLineProjections.length; i++) {
  103. const lineNumber = i + 1;
  104. if (lineNumber === nextLineNumberToUpdateHiddenArea) {
  105. hiddenAreaIdx++;
  106. hiddenAreaStart = hiddenAreas[hiddenAreaIdx].startLineNumber;
  107. hiddenAreaEnd = hiddenAreas[hiddenAreaIdx].endLineNumber;
  108. nextLineNumberToUpdateHiddenArea = (hiddenAreaIdx + 1 < hiddenAreas.length) ? hiddenAreaEnd + 1 : this.modelLineProjections.length + 2;
  109. }
  110. let lineChanged = false;
  111. if (lineNumber >= hiddenAreaStart && lineNumber <= hiddenAreaEnd) {
  112. // Line should be hidden
  113. if (this.modelLineProjections[i].isVisible()) {
  114. this.modelLineProjections[i] = this.modelLineProjections[i].setVisible(false);
  115. lineChanged = true;
  116. }
  117. }
  118. else {
  119. hasVisibleLine = true;
  120. // Line should be visible
  121. if (!this.modelLineProjections[i].isVisible()) {
  122. this.modelLineProjections[i] = this.modelLineProjections[i].setVisible(true);
  123. lineChanged = true;
  124. }
  125. }
  126. if (lineChanged) {
  127. const newOutputLineCount = this.modelLineProjections[i].getViewLineCount();
  128. this.projectedModelLineLineCounts.setValue(i, newOutputLineCount);
  129. }
  130. }
  131. if (!hasVisibleLine) {
  132. // Cannot have everything be hidden => reveal everything!
  133. this.setHiddenAreas([]);
  134. }
  135. return true;
  136. }
  137. modelPositionIsVisible(modelLineNumber, _modelColumn) {
  138. if (modelLineNumber < 1 || modelLineNumber > this.modelLineProjections.length) {
  139. // invalid arguments
  140. return false;
  141. }
  142. return this.modelLineProjections[modelLineNumber - 1].isVisible();
  143. }
  144. getModelLineViewLineCount(modelLineNumber) {
  145. if (modelLineNumber < 1 || modelLineNumber > this.modelLineProjections.length) {
  146. // invalid arguments
  147. return 1;
  148. }
  149. return this.modelLineProjections[modelLineNumber - 1].getViewLineCount();
  150. }
  151. setTabSize(newTabSize) {
  152. if (this.tabSize === newTabSize) {
  153. return false;
  154. }
  155. this.tabSize = newTabSize;
  156. this._constructLines(/*resetHiddenAreas*/ false, null);
  157. return true;
  158. }
  159. setWrappingSettings(fontInfo, wrappingStrategy, wrappingColumn, wrappingIndent) {
  160. const equalFontInfo = this.fontInfo.equals(fontInfo);
  161. const equalWrappingStrategy = (this.wrappingStrategy === wrappingStrategy);
  162. const equalWrappingColumn = (this.wrappingColumn === wrappingColumn);
  163. const equalWrappingIndent = (this.wrappingIndent === wrappingIndent);
  164. if (equalFontInfo && equalWrappingStrategy && equalWrappingColumn && equalWrappingIndent) {
  165. return false;
  166. }
  167. const onlyWrappingColumnChanged = (equalFontInfo && equalWrappingStrategy && !equalWrappingColumn && equalWrappingIndent);
  168. this.fontInfo = fontInfo;
  169. this.wrappingStrategy = wrappingStrategy;
  170. this.wrappingColumn = wrappingColumn;
  171. this.wrappingIndent = wrappingIndent;
  172. let previousLineBreaks = null;
  173. if (onlyWrappingColumnChanged) {
  174. previousLineBreaks = [];
  175. for (let i = 0, len = this.modelLineProjections.length; i < len; i++) {
  176. previousLineBreaks[i] = this.modelLineProjections[i].getProjectionData();
  177. }
  178. }
  179. this._constructLines(/*resetHiddenAreas*/ false, previousLineBreaks);
  180. return true;
  181. }
  182. createLineBreaksComputer() {
  183. const lineBreaksComputerFactory = (this.wrappingStrategy === 'advanced'
  184. ? this._domLineBreaksComputerFactory
  185. : this._monospaceLineBreaksComputerFactory);
  186. return lineBreaksComputerFactory.createLineBreaksComputer(this.fontInfo, this.tabSize, this.wrappingColumn, this.wrappingIndent);
  187. }
  188. onModelFlushed() {
  189. this._constructLines(/*resetHiddenAreas*/ true, null);
  190. }
  191. onModelLinesDeleted(versionId, fromLineNumber, toLineNumber) {
  192. if (!versionId || versionId <= this._validModelVersionId) {
  193. // Here we check for versionId in case the lines were reconstructed in the meantime.
  194. // We don't want to apply stale change events on top of a newer read model state.
  195. return null;
  196. }
  197. const outputFromLineNumber = (fromLineNumber === 1 ? 1 : this.projectedModelLineLineCounts.getPrefixSum(fromLineNumber - 1) + 1);
  198. const outputToLineNumber = this.projectedModelLineLineCounts.getPrefixSum(toLineNumber);
  199. this.modelLineProjections.splice(fromLineNumber - 1, toLineNumber - fromLineNumber + 1);
  200. this.projectedModelLineLineCounts.removeValues(fromLineNumber - 1, toLineNumber - fromLineNumber + 1);
  201. return new viewEvents.ViewLinesDeletedEvent(outputFromLineNumber, outputToLineNumber);
  202. }
  203. onModelLinesInserted(versionId, fromLineNumber, _toLineNumber, lineBreaks) {
  204. if (!versionId || versionId <= this._validModelVersionId) {
  205. // Here we check for versionId in case the lines were reconstructed in the meantime.
  206. // We don't want to apply stale change events on top of a newer read model state.
  207. return null;
  208. }
  209. // cannot use this.getHiddenAreas() because those decorations have already seen the effect of this model change
  210. const isInHiddenArea = (fromLineNumber > 2 && !this.modelLineProjections[fromLineNumber - 2].isVisible());
  211. const outputFromLineNumber = (fromLineNumber === 1 ? 1 : this.projectedModelLineLineCounts.getPrefixSum(fromLineNumber - 1) + 1);
  212. let totalOutputLineCount = 0;
  213. const insertLines = [];
  214. const insertPrefixSumValues = [];
  215. for (let i = 0, len = lineBreaks.length; i < len; i++) {
  216. const line = createModelLineProjection(lineBreaks[i], !isInHiddenArea);
  217. insertLines.push(line);
  218. const outputLineCount = line.getViewLineCount();
  219. totalOutputLineCount += outputLineCount;
  220. insertPrefixSumValues[i] = outputLineCount;
  221. }
  222. // TODO@Alex: use arrays.arrayInsert
  223. this.modelLineProjections =
  224. this.modelLineProjections.slice(0, fromLineNumber - 1)
  225. .concat(insertLines)
  226. .concat(this.modelLineProjections.slice(fromLineNumber - 1));
  227. this.projectedModelLineLineCounts.insertValues(fromLineNumber - 1, insertPrefixSumValues);
  228. return new viewEvents.ViewLinesInsertedEvent(outputFromLineNumber, outputFromLineNumber + totalOutputLineCount - 1);
  229. }
  230. onModelLineChanged(versionId, lineNumber, lineBreakData) {
  231. if (versionId !== null && versionId <= this._validModelVersionId) {
  232. // Here we check for versionId in case the lines were reconstructed in the meantime.
  233. // We don't want to apply stale change events on top of a newer read model state.
  234. return [false, null, null, null];
  235. }
  236. const lineIndex = lineNumber - 1;
  237. const oldOutputLineCount = this.modelLineProjections[lineIndex].getViewLineCount();
  238. const isVisible = this.modelLineProjections[lineIndex].isVisible();
  239. const line = createModelLineProjection(lineBreakData, isVisible);
  240. this.modelLineProjections[lineIndex] = line;
  241. const newOutputLineCount = this.modelLineProjections[lineIndex].getViewLineCount();
  242. let lineMappingChanged = false;
  243. let changeFrom = 0;
  244. let changeTo = -1;
  245. let insertFrom = 0;
  246. let insertTo = -1;
  247. let deleteFrom = 0;
  248. let deleteTo = -1;
  249. if (oldOutputLineCount > newOutputLineCount) {
  250. changeFrom = this.projectedModelLineLineCounts.getPrefixSum(lineNumber - 1) + 1;
  251. changeTo = changeFrom + newOutputLineCount - 1;
  252. deleteFrom = changeTo + 1;
  253. deleteTo = deleteFrom + (oldOutputLineCount - newOutputLineCount) - 1;
  254. lineMappingChanged = true;
  255. }
  256. else if (oldOutputLineCount < newOutputLineCount) {
  257. changeFrom = this.projectedModelLineLineCounts.getPrefixSum(lineNumber - 1) + 1;
  258. changeTo = changeFrom + oldOutputLineCount - 1;
  259. insertFrom = changeTo + 1;
  260. insertTo = insertFrom + (newOutputLineCount - oldOutputLineCount) - 1;
  261. lineMappingChanged = true;
  262. }
  263. else {
  264. changeFrom = this.projectedModelLineLineCounts.getPrefixSum(lineNumber - 1) + 1;
  265. changeTo = changeFrom + newOutputLineCount - 1;
  266. }
  267. this.projectedModelLineLineCounts.setValue(lineIndex, newOutputLineCount);
  268. const viewLinesChangedEvent = (changeFrom <= changeTo ? new viewEvents.ViewLinesChangedEvent(changeFrom, changeTo - changeFrom + 1) : null);
  269. const viewLinesInsertedEvent = (insertFrom <= insertTo ? new viewEvents.ViewLinesInsertedEvent(insertFrom, insertTo) : null);
  270. const viewLinesDeletedEvent = (deleteFrom <= deleteTo ? new viewEvents.ViewLinesDeletedEvent(deleteFrom, deleteTo) : null);
  271. return [lineMappingChanged, viewLinesChangedEvent, viewLinesInsertedEvent, viewLinesDeletedEvent];
  272. }
  273. acceptVersionId(versionId) {
  274. this._validModelVersionId = versionId;
  275. if (this.modelLineProjections.length === 1 && !this.modelLineProjections[0].isVisible()) {
  276. // At least one line must be visible => reset hidden areas
  277. this.setHiddenAreas([]);
  278. }
  279. }
  280. getViewLineCount() {
  281. return this.projectedModelLineLineCounts.getTotalSum();
  282. }
  283. _toValidViewLineNumber(viewLineNumber) {
  284. if (viewLineNumber < 1) {
  285. return 1;
  286. }
  287. const viewLineCount = this.getViewLineCount();
  288. if (viewLineNumber > viewLineCount) {
  289. return viewLineCount;
  290. }
  291. return viewLineNumber | 0;
  292. }
  293. getActiveIndentGuide(viewLineNumber, minLineNumber, maxLineNumber) {
  294. viewLineNumber = this._toValidViewLineNumber(viewLineNumber);
  295. minLineNumber = this._toValidViewLineNumber(minLineNumber);
  296. maxLineNumber = this._toValidViewLineNumber(maxLineNumber);
  297. const modelPosition = this.convertViewPositionToModelPosition(viewLineNumber, this.getViewLineMinColumn(viewLineNumber));
  298. const modelMinPosition = this.convertViewPositionToModelPosition(minLineNumber, this.getViewLineMinColumn(minLineNumber));
  299. const modelMaxPosition = this.convertViewPositionToModelPosition(maxLineNumber, this.getViewLineMinColumn(maxLineNumber));
  300. const result = this.model.guides.getActiveIndentGuide(modelPosition.lineNumber, modelMinPosition.lineNumber, modelMaxPosition.lineNumber);
  301. const viewStartPosition = this.convertModelPositionToViewPosition(result.startLineNumber, 1);
  302. const viewEndPosition = this.convertModelPositionToViewPosition(result.endLineNumber, this.model.getLineMaxColumn(result.endLineNumber));
  303. return {
  304. startLineNumber: viewStartPosition.lineNumber,
  305. endLineNumber: viewEndPosition.lineNumber,
  306. indent: result.indent
  307. };
  308. }
  309. // #region ViewLineInfo
  310. getViewLineInfo(viewLineNumber) {
  311. viewLineNumber = this._toValidViewLineNumber(viewLineNumber);
  312. const r = this.projectedModelLineLineCounts.getIndexOf(viewLineNumber - 1);
  313. const lineIndex = r.index;
  314. const remainder = r.remainder;
  315. return new ViewLineInfo(lineIndex + 1, remainder);
  316. }
  317. getMinColumnOfViewLine(viewLineInfo) {
  318. return this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewLineMinColumn(this.model, viewLineInfo.modelLineNumber, viewLineInfo.modelLineWrappedLineIdx);
  319. }
  320. getMaxColumnOfViewLine(viewLineInfo) {
  321. return this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewLineMaxColumn(this.model, viewLineInfo.modelLineNumber, viewLineInfo.modelLineWrappedLineIdx);
  322. }
  323. getModelStartPositionOfViewLine(viewLineInfo) {
  324. const line = this.modelLineProjections[viewLineInfo.modelLineNumber - 1];
  325. const minViewColumn = line.getViewLineMinColumn(this.model, viewLineInfo.modelLineNumber, viewLineInfo.modelLineWrappedLineIdx);
  326. const column = line.getModelColumnOfViewPosition(viewLineInfo.modelLineWrappedLineIdx, minViewColumn);
  327. return new Position(viewLineInfo.modelLineNumber, column);
  328. }
  329. getModelEndPositionOfViewLine(viewLineInfo) {
  330. const line = this.modelLineProjections[viewLineInfo.modelLineNumber - 1];
  331. const maxViewColumn = line.getViewLineMaxColumn(this.model, viewLineInfo.modelLineNumber, viewLineInfo.modelLineWrappedLineIdx);
  332. const column = line.getModelColumnOfViewPosition(viewLineInfo.modelLineWrappedLineIdx, maxViewColumn);
  333. return new Position(viewLineInfo.modelLineNumber, column);
  334. }
  335. getViewLineInfosGroupedByModelRanges(viewStartLineNumber, viewEndLineNumber) {
  336. const startViewLine = this.getViewLineInfo(viewStartLineNumber);
  337. const endViewLine = this.getViewLineInfo(viewEndLineNumber);
  338. const result = new Array();
  339. let lastVisibleModelPos = this.getModelStartPositionOfViewLine(startViewLine);
  340. let viewLines = new Array();
  341. for (let curModelLine = startViewLine.modelLineNumber; curModelLine <= endViewLine.modelLineNumber; curModelLine++) {
  342. const line = this.modelLineProjections[curModelLine - 1];
  343. if (line.isVisible()) {
  344. const startOffset = curModelLine === startViewLine.modelLineNumber
  345. ? startViewLine.modelLineWrappedLineIdx
  346. : 0;
  347. const endOffset = curModelLine === endViewLine.modelLineNumber
  348. ? endViewLine.modelLineWrappedLineIdx + 1
  349. : line.getViewLineCount();
  350. for (let i = startOffset; i < endOffset; i++) {
  351. viewLines.push(new ViewLineInfo(curModelLine, i));
  352. }
  353. }
  354. if (!line.isVisible() && lastVisibleModelPos) {
  355. const lastVisibleModelPos2 = new Position(curModelLine - 1, this.model.getLineMaxColumn(curModelLine - 1) + 1);
  356. const modelRange = Range.fromPositions(lastVisibleModelPos, lastVisibleModelPos2);
  357. result.push(new ViewLineInfoGroupedByModelRange(modelRange, viewLines));
  358. viewLines = [];
  359. lastVisibleModelPos = null;
  360. }
  361. else if (line.isVisible() && !lastVisibleModelPos) {
  362. lastVisibleModelPos = new Position(curModelLine, 1);
  363. }
  364. }
  365. if (lastVisibleModelPos) {
  366. const modelRange = Range.fromPositions(lastVisibleModelPos, this.getModelEndPositionOfViewLine(endViewLine));
  367. result.push(new ViewLineInfoGroupedByModelRange(modelRange, viewLines));
  368. }
  369. return result;
  370. }
  371. // #endregion
  372. getViewLinesBracketGuides(viewStartLineNumber, viewEndLineNumber, activeViewPosition, options) {
  373. const modelActivePosition = activeViewPosition ? this.convertViewPositionToModelPosition(activeViewPosition.lineNumber, activeViewPosition.column) : null;
  374. const resultPerViewLine = [];
  375. for (const group of this.getViewLineInfosGroupedByModelRanges(viewStartLineNumber, viewEndLineNumber)) {
  376. const modelRangeStartLineNumber = group.modelRange.startLineNumber;
  377. const bracketGuidesPerModelLine = this.model.guides.getLinesBracketGuides(modelRangeStartLineNumber, group.modelRange.endLineNumber, modelActivePosition, options);
  378. for (const viewLineInfo of group.viewLines) {
  379. const bracketGuides = bracketGuidesPerModelLine[viewLineInfo.modelLineNumber - modelRangeStartLineNumber];
  380. // visibleColumns stay as they are (this is a bug and needs to be fixed, but it is not a regression)
  381. // model-columns must be converted to view-model columns.
  382. const result = bracketGuides.map(g => {
  383. if (g.forWrappedLinesAfterColumn !== -1) {
  384. const p = this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewPositionOfModelPosition(0, g.forWrappedLinesAfterColumn);
  385. if (p.lineNumber >= viewLineInfo.modelLineWrappedLineIdx) {
  386. return undefined;
  387. }
  388. }
  389. if (g.forWrappedLinesBeforeOrAtColumn !== -1) {
  390. const p = this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewPositionOfModelPosition(0, g.forWrappedLinesBeforeOrAtColumn);
  391. if (p.lineNumber < viewLineInfo.modelLineWrappedLineIdx) {
  392. return undefined;
  393. }
  394. }
  395. if (!g.horizontalLine) {
  396. return g;
  397. }
  398. let column = -1;
  399. if (g.column !== -1) {
  400. const p = this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewPositionOfModelPosition(0, g.column);
  401. if (p.lineNumber === viewLineInfo.modelLineWrappedLineIdx) {
  402. column = p.column;
  403. }
  404. else if (p.lineNumber < viewLineInfo.modelLineWrappedLineIdx) {
  405. column = this.getMinColumnOfViewLine(viewLineInfo);
  406. }
  407. else if (p.lineNumber > viewLineInfo.modelLineWrappedLineIdx) {
  408. return undefined;
  409. }
  410. }
  411. const viewPosition = this.convertModelPositionToViewPosition(viewLineInfo.modelLineNumber, g.horizontalLine.endColumn);
  412. const p = this.modelLineProjections[viewLineInfo.modelLineNumber - 1].getViewPositionOfModelPosition(0, g.horizontalLine.endColumn);
  413. if (p.lineNumber === viewLineInfo.modelLineWrappedLineIdx) {
  414. return new IndentGuide(g.visibleColumn, column, g.className, new IndentGuideHorizontalLine(g.horizontalLine.top, viewPosition.column), -1, -1);
  415. }
  416. else if (p.lineNumber < viewLineInfo.modelLineWrappedLineIdx) {
  417. return undefined;
  418. }
  419. else {
  420. if (g.visibleColumn !== -1) {
  421. // Don't repeat horizontal lines that use visibleColumn for unrelated lines.
  422. return undefined;
  423. }
  424. return new IndentGuide(g.visibleColumn, column, g.className, new IndentGuideHorizontalLine(g.horizontalLine.top, this.getMaxColumnOfViewLine(viewLineInfo)), -1, -1);
  425. }
  426. });
  427. resultPerViewLine.push(result.filter((r) => !!r));
  428. }
  429. }
  430. return resultPerViewLine;
  431. }
  432. getViewLinesIndentGuides(viewStartLineNumber, viewEndLineNumber) {
  433. // TODO: Use the same code as in `getViewLinesBracketGuides`.
  434. // Future TODO: Merge with `getViewLinesBracketGuides`.
  435. // However, this requires more refactoring of indent guides.
  436. viewStartLineNumber = this._toValidViewLineNumber(viewStartLineNumber);
  437. viewEndLineNumber = this._toValidViewLineNumber(viewEndLineNumber);
  438. const modelStart = this.convertViewPositionToModelPosition(viewStartLineNumber, this.getViewLineMinColumn(viewStartLineNumber));
  439. const modelEnd = this.convertViewPositionToModelPosition(viewEndLineNumber, this.getViewLineMaxColumn(viewEndLineNumber));
  440. let result = [];
  441. const resultRepeatCount = [];
  442. const resultRepeatOption = [];
  443. const modelStartLineIndex = modelStart.lineNumber - 1;
  444. const modelEndLineIndex = modelEnd.lineNumber - 1;
  445. let reqStart = null;
  446. for (let modelLineIndex = modelStartLineIndex; modelLineIndex <= modelEndLineIndex; modelLineIndex++) {
  447. const line = this.modelLineProjections[modelLineIndex];
  448. if (line.isVisible()) {
  449. const viewLineStartIndex = line.getViewLineNumberOfModelPosition(0, modelLineIndex === modelStartLineIndex ? modelStart.column : 1);
  450. const viewLineEndIndex = line.getViewLineNumberOfModelPosition(0, this.model.getLineMaxColumn(modelLineIndex + 1));
  451. const count = viewLineEndIndex - viewLineStartIndex + 1;
  452. let option = 0 /* IndentGuideRepeatOption.BlockNone */;
  453. if (count > 1 && line.getViewLineMinColumn(this.model, modelLineIndex + 1, viewLineEndIndex) === 1) {
  454. // wrapped lines should block indent guides
  455. option = (viewLineStartIndex === 0 ? 1 /* IndentGuideRepeatOption.BlockSubsequent */ : 2 /* IndentGuideRepeatOption.BlockAll */);
  456. }
  457. resultRepeatCount.push(count);
  458. resultRepeatOption.push(option);
  459. // merge into previous request
  460. if (reqStart === null) {
  461. reqStart = new Position(modelLineIndex + 1, 0);
  462. }
  463. }
  464. else {
  465. // hit invisible line => flush request
  466. if (reqStart !== null) {
  467. result = result.concat(this.model.guides.getLinesIndentGuides(reqStart.lineNumber, modelLineIndex));
  468. reqStart = null;
  469. }
  470. }
  471. }
  472. if (reqStart !== null) {
  473. result = result.concat(this.model.guides.getLinesIndentGuides(reqStart.lineNumber, modelEnd.lineNumber));
  474. reqStart = null;
  475. }
  476. const viewLineCount = viewEndLineNumber - viewStartLineNumber + 1;
  477. const viewIndents = new Array(viewLineCount);
  478. let currIndex = 0;
  479. for (let i = 0, len = result.length; i < len; i++) {
  480. let value = result[i];
  481. const count = Math.min(viewLineCount - currIndex, resultRepeatCount[i]);
  482. const option = resultRepeatOption[i];
  483. let blockAtIndex;
  484. if (option === 2 /* IndentGuideRepeatOption.BlockAll */) {
  485. blockAtIndex = 0;
  486. }
  487. else if (option === 1 /* IndentGuideRepeatOption.BlockSubsequent */) {
  488. blockAtIndex = 1;
  489. }
  490. else {
  491. blockAtIndex = count;
  492. }
  493. for (let j = 0; j < count; j++) {
  494. if (j === blockAtIndex) {
  495. value = 0;
  496. }
  497. viewIndents[currIndex++] = value;
  498. }
  499. }
  500. return viewIndents;
  501. }
  502. getViewLineContent(viewLineNumber) {
  503. const info = this.getViewLineInfo(viewLineNumber);
  504. return this.modelLineProjections[info.modelLineNumber - 1].getViewLineContent(this.model, info.modelLineNumber, info.modelLineWrappedLineIdx);
  505. }
  506. getViewLineLength(viewLineNumber) {
  507. const info = this.getViewLineInfo(viewLineNumber);
  508. return this.modelLineProjections[info.modelLineNumber - 1].getViewLineLength(this.model, info.modelLineNumber, info.modelLineWrappedLineIdx);
  509. }
  510. getViewLineMinColumn(viewLineNumber) {
  511. const info = this.getViewLineInfo(viewLineNumber);
  512. return this.modelLineProjections[info.modelLineNumber - 1].getViewLineMinColumn(this.model, info.modelLineNumber, info.modelLineWrappedLineIdx);
  513. }
  514. getViewLineMaxColumn(viewLineNumber) {
  515. const info = this.getViewLineInfo(viewLineNumber);
  516. return this.modelLineProjections[info.modelLineNumber - 1].getViewLineMaxColumn(this.model, info.modelLineNumber, info.modelLineWrappedLineIdx);
  517. }
  518. getViewLineData(viewLineNumber) {
  519. const info = this.getViewLineInfo(viewLineNumber);
  520. return this.modelLineProjections[info.modelLineNumber - 1].getViewLineData(this.model, info.modelLineNumber, info.modelLineWrappedLineIdx);
  521. }
  522. getViewLinesData(viewStartLineNumber, viewEndLineNumber, needed) {
  523. viewStartLineNumber = this._toValidViewLineNumber(viewStartLineNumber);
  524. viewEndLineNumber = this._toValidViewLineNumber(viewEndLineNumber);
  525. const start = this.projectedModelLineLineCounts.getIndexOf(viewStartLineNumber - 1);
  526. let viewLineNumber = viewStartLineNumber;
  527. const startModelLineIndex = start.index;
  528. const startRemainder = start.remainder;
  529. const result = [];
  530. for (let modelLineIndex = startModelLineIndex, len = this.model.getLineCount(); modelLineIndex < len; modelLineIndex++) {
  531. const line = this.modelLineProjections[modelLineIndex];
  532. if (!line.isVisible()) {
  533. continue;
  534. }
  535. const fromViewLineIndex = (modelLineIndex === startModelLineIndex ? startRemainder : 0);
  536. let remainingViewLineCount = line.getViewLineCount() - fromViewLineIndex;
  537. let lastLine = false;
  538. if (viewLineNumber + remainingViewLineCount > viewEndLineNumber) {
  539. lastLine = true;
  540. remainingViewLineCount = viewEndLineNumber - viewLineNumber + 1;
  541. }
  542. line.getViewLinesData(this.model, modelLineIndex + 1, fromViewLineIndex, remainingViewLineCount, viewLineNumber - viewStartLineNumber, needed, result);
  543. viewLineNumber += remainingViewLineCount;
  544. if (lastLine) {
  545. break;
  546. }
  547. }
  548. return result;
  549. }
  550. validateViewPosition(viewLineNumber, viewColumn, expectedModelPosition) {
  551. viewLineNumber = this._toValidViewLineNumber(viewLineNumber);
  552. const r = this.projectedModelLineLineCounts.getIndexOf(viewLineNumber - 1);
  553. const lineIndex = r.index;
  554. const remainder = r.remainder;
  555. const line = this.modelLineProjections[lineIndex];
  556. const minColumn = line.getViewLineMinColumn(this.model, lineIndex + 1, remainder);
  557. const maxColumn = line.getViewLineMaxColumn(this.model, lineIndex + 1, remainder);
  558. if (viewColumn < minColumn) {
  559. viewColumn = minColumn;
  560. }
  561. if (viewColumn > maxColumn) {
  562. viewColumn = maxColumn;
  563. }
  564. const computedModelColumn = line.getModelColumnOfViewPosition(remainder, viewColumn);
  565. const computedModelPosition = this.model.validatePosition(new Position(lineIndex + 1, computedModelColumn));
  566. if (computedModelPosition.equals(expectedModelPosition)) {
  567. return new Position(viewLineNumber, viewColumn);
  568. }
  569. return this.convertModelPositionToViewPosition(expectedModelPosition.lineNumber, expectedModelPosition.column);
  570. }
  571. validateViewRange(viewRange, expectedModelRange) {
  572. const validViewStart = this.validateViewPosition(viewRange.startLineNumber, viewRange.startColumn, expectedModelRange.getStartPosition());
  573. const validViewEnd = this.validateViewPosition(viewRange.endLineNumber, viewRange.endColumn, expectedModelRange.getEndPosition());
  574. return new Range(validViewStart.lineNumber, validViewStart.column, validViewEnd.lineNumber, validViewEnd.column);
  575. }
  576. convertViewPositionToModelPosition(viewLineNumber, viewColumn) {
  577. const info = this.getViewLineInfo(viewLineNumber);
  578. const inputColumn = this.modelLineProjections[info.modelLineNumber - 1].getModelColumnOfViewPosition(info.modelLineWrappedLineIdx, viewColumn);
  579. // console.log('out -> in ' + viewLineNumber + ',' + viewColumn + ' ===> ' + (lineIndex+1) + ',' + inputColumn);
  580. return this.model.validatePosition(new Position(info.modelLineNumber, inputColumn));
  581. }
  582. convertViewRangeToModelRange(viewRange) {
  583. const start = this.convertViewPositionToModelPosition(viewRange.startLineNumber, viewRange.startColumn);
  584. const end = this.convertViewPositionToModelPosition(viewRange.endLineNumber, viewRange.endColumn);
  585. return new Range(start.lineNumber, start.column, end.lineNumber, end.column);
  586. }
  587. convertModelPositionToViewPosition(_modelLineNumber, _modelColumn, affinity = 2 /* PositionAffinity.None */) {
  588. const validPosition = this.model.validatePosition(new Position(_modelLineNumber, _modelColumn));
  589. const inputLineNumber = validPosition.lineNumber;
  590. const inputColumn = validPosition.column;
  591. let lineIndex = inputLineNumber - 1, lineIndexChanged = false;
  592. while (lineIndex > 0 && !this.modelLineProjections[lineIndex].isVisible()) {
  593. lineIndex--;
  594. lineIndexChanged = true;
  595. }
  596. if (lineIndex === 0 && !this.modelLineProjections[lineIndex].isVisible()) {
  597. // Could not reach a real line
  598. // console.log('in -> out ' + inputLineNumber + ',' + inputColumn + ' ===> ' + 1 + ',' + 1);
  599. return new Position(1, 1);
  600. }
  601. const deltaLineNumber = 1 + this.projectedModelLineLineCounts.getPrefixSum(lineIndex);
  602. let r;
  603. if (lineIndexChanged) {
  604. r = this.modelLineProjections[lineIndex].getViewPositionOfModelPosition(deltaLineNumber, this.model.getLineMaxColumn(lineIndex + 1), affinity);
  605. }
  606. else {
  607. r = this.modelLineProjections[inputLineNumber - 1].getViewPositionOfModelPosition(deltaLineNumber, inputColumn, affinity);
  608. }
  609. // console.log('in -> out ' + inputLineNumber + ',' + inputColumn + ' ===> ' + r.lineNumber + ',' + r);
  610. return r;
  611. }
  612. /**
  613. * @param affinity The affinity in case of an empty range. Has no effect for non-empty ranges.
  614. */
  615. convertModelRangeToViewRange(modelRange, affinity = 0 /* PositionAffinity.Left */) {
  616. if (modelRange.isEmpty()) {
  617. const start = this.convertModelPositionToViewPosition(modelRange.startLineNumber, modelRange.startColumn, affinity);
  618. return Range.fromPositions(start);
  619. }
  620. else {
  621. const start = this.convertModelPositionToViewPosition(modelRange.startLineNumber, modelRange.startColumn, 1 /* PositionAffinity.Right */);
  622. const end = this.convertModelPositionToViewPosition(modelRange.endLineNumber, modelRange.endColumn, 0 /* PositionAffinity.Left */);
  623. return new Range(start.lineNumber, start.column, end.lineNumber, end.column);
  624. }
  625. }
  626. getViewLineNumberOfModelPosition(modelLineNumber, modelColumn) {
  627. let lineIndex = modelLineNumber - 1;
  628. if (this.modelLineProjections[lineIndex].isVisible()) {
  629. // this model line is visible
  630. const deltaLineNumber = 1 + this.projectedModelLineLineCounts.getPrefixSum(lineIndex);
  631. return this.modelLineProjections[lineIndex].getViewLineNumberOfModelPosition(deltaLineNumber, modelColumn);
  632. }
  633. // this model line is not visible
  634. while (lineIndex > 0 && !this.modelLineProjections[lineIndex].isVisible()) {
  635. lineIndex--;
  636. }
  637. if (lineIndex === 0 && !this.modelLineProjections[lineIndex].isVisible()) {
  638. // Could not reach a real line
  639. return 1;
  640. }
  641. const deltaLineNumber = 1 + this.projectedModelLineLineCounts.getPrefixSum(lineIndex);
  642. return this.modelLineProjections[lineIndex].getViewLineNumberOfModelPosition(deltaLineNumber, this.model.getLineMaxColumn(lineIndex + 1));
  643. }
  644. getDecorationsInRange(range, ownerId, filterOutValidation) {
  645. const modelStart = this.convertViewPositionToModelPosition(range.startLineNumber, range.startColumn);
  646. const modelEnd = this.convertViewPositionToModelPosition(range.endLineNumber, range.endColumn);
  647. if (modelEnd.lineNumber - modelStart.lineNumber <= range.endLineNumber - range.startLineNumber) {
  648. // most likely there are no hidden lines => fast path
  649. // fetch decorations from column 1 to cover the case of wrapped lines that have whole line decorations at column 1
  650. return this.model.getDecorationsInRange(new Range(modelStart.lineNumber, 1, modelEnd.lineNumber, modelEnd.column), ownerId, filterOutValidation);
  651. }
  652. let result = [];
  653. const modelStartLineIndex = modelStart.lineNumber - 1;
  654. const modelEndLineIndex = modelEnd.lineNumber - 1;
  655. let reqStart = null;
  656. for (let modelLineIndex = modelStartLineIndex; modelLineIndex <= modelEndLineIndex; modelLineIndex++) {
  657. const line = this.modelLineProjections[modelLineIndex];
  658. if (line.isVisible()) {
  659. // merge into previous request
  660. if (reqStart === null) {
  661. reqStart = new Position(modelLineIndex + 1, modelLineIndex === modelStartLineIndex ? modelStart.column : 1);
  662. }
  663. }
  664. else {
  665. // hit invisible line => flush request
  666. if (reqStart !== null) {
  667. const maxLineColumn = this.model.getLineMaxColumn(modelLineIndex);
  668. result = result.concat(this.model.getDecorationsInRange(new Range(reqStart.lineNumber, reqStart.column, modelLineIndex, maxLineColumn), ownerId, filterOutValidation));
  669. reqStart = null;
  670. }
  671. }
  672. }
  673. if (reqStart !== null) {
  674. result = result.concat(this.model.getDecorationsInRange(new Range(reqStart.lineNumber, reqStart.column, modelEnd.lineNumber, modelEnd.column), ownerId, filterOutValidation));
  675. reqStart = null;
  676. }
  677. result.sort((a, b) => {
  678. const res = Range.compareRangesUsingStarts(a.range, b.range);
  679. if (res === 0) {
  680. if (a.id < b.id) {
  681. return -1;
  682. }
  683. if (a.id > b.id) {
  684. return 1;
  685. }
  686. return 0;
  687. }
  688. return res;
  689. });
  690. // Eliminate duplicate decorations that might have intersected our visible ranges multiple times
  691. const finalResult = [];
  692. let finalResultLen = 0;
  693. let prevDecId = null;
  694. for (const dec of result) {
  695. const decId = dec.id;
  696. if (prevDecId === decId) {
  697. // skip
  698. continue;
  699. }
  700. prevDecId = decId;
  701. finalResult[finalResultLen++] = dec;
  702. }
  703. return finalResult;
  704. }
  705. getInjectedTextAt(position) {
  706. const info = this.getViewLineInfo(position.lineNumber);
  707. return this.modelLineProjections[info.modelLineNumber - 1].getInjectedTextAt(info.modelLineWrappedLineIdx, position.column);
  708. }
  709. normalizePosition(position, affinity) {
  710. const info = this.getViewLineInfo(position.lineNumber);
  711. return this.modelLineProjections[info.modelLineNumber - 1].normalizePosition(info.modelLineWrappedLineIdx, position, affinity);
  712. }
  713. getLineIndentColumn(lineNumber) {
  714. const info = this.getViewLineInfo(lineNumber);
  715. if (info.modelLineWrappedLineIdx === 0) {
  716. return this.model.getLineIndentColumn(info.modelLineNumber);
  717. }
  718. // wrapped lines have no indentation.
  719. // We deliberately don't handle the case that indentation is wrapped
  720. // to avoid two view lines reporting indentation for the very same model line.
  721. return 0;
  722. }
  723. }
  724. /**
  725. * Overlapping unsorted ranges:
  726. * [ ) [ ) [ )
  727. * [ ) [ )
  728. * ->
  729. * Non overlapping sorted ranges:
  730. * [ ) [ ) [ )
  731. *
  732. * Note: This function only considers line information! Columns are ignored.
  733. */
  734. function normalizeLineRanges(ranges) {
  735. if (ranges.length === 0) {
  736. return [];
  737. }
  738. const sortedRanges = ranges.slice();
  739. sortedRanges.sort(Range.compareRangesUsingStarts);
  740. const result = [];
  741. let currentRangeStart = sortedRanges[0].startLineNumber;
  742. let currentRangeEnd = sortedRanges[0].endLineNumber;
  743. for (let i = 1, len = sortedRanges.length; i < len; i++) {
  744. const range = sortedRanges[i];
  745. if (range.startLineNumber > currentRangeEnd + 1) {
  746. result.push(new Range(currentRangeStart, 1, currentRangeEnd, 1));
  747. currentRangeStart = range.startLineNumber;
  748. currentRangeEnd = range.endLineNumber;
  749. }
  750. else if (range.endLineNumber > currentRangeEnd) {
  751. currentRangeEnd = range.endLineNumber;
  752. }
  753. }
  754. result.push(new Range(currentRangeStart, 1, currentRangeEnd, 1));
  755. return result;
  756. }
  757. /**
  758. * Represents a view line. Can be used to efficiently query more information about it.
  759. */
  760. class ViewLineInfo {
  761. constructor(modelLineNumber, modelLineWrappedLineIdx) {
  762. this.modelLineNumber = modelLineNumber;
  763. this.modelLineWrappedLineIdx = modelLineWrappedLineIdx;
  764. }
  765. }
  766. /**
  767. * A list of view lines that have a contiguous span in the model.
  768. */
  769. class ViewLineInfoGroupedByModelRange {
  770. constructor(modelRange, viewLines) {
  771. this.modelRange = modelRange;
  772. this.viewLines = viewLines;
  773. }
  774. }
  775. class CoordinatesConverter {
  776. constructor(lines) {
  777. this._lines = lines;
  778. }
  779. // View -> Model conversion and related methods
  780. convertViewPositionToModelPosition(viewPosition) {
  781. return this._lines.convertViewPositionToModelPosition(viewPosition.lineNumber, viewPosition.column);
  782. }
  783. convertViewRangeToModelRange(viewRange) {
  784. return this._lines.convertViewRangeToModelRange(viewRange);
  785. }
  786. validateViewPosition(viewPosition, expectedModelPosition) {
  787. return this._lines.validateViewPosition(viewPosition.lineNumber, viewPosition.column, expectedModelPosition);
  788. }
  789. validateViewRange(viewRange, expectedModelRange) {
  790. return this._lines.validateViewRange(viewRange, expectedModelRange);
  791. }
  792. // Model -> View conversion and related methods
  793. convertModelPositionToViewPosition(modelPosition, affinity) {
  794. return this._lines.convertModelPositionToViewPosition(modelPosition.lineNumber, modelPosition.column, affinity);
  795. }
  796. convertModelRangeToViewRange(modelRange, affinity) {
  797. return this._lines.convertModelRangeToViewRange(modelRange, affinity);
  798. }
  799. modelPositionIsVisible(modelPosition) {
  800. return this._lines.modelPositionIsVisible(modelPosition.lineNumber, modelPosition.column);
  801. }
  802. getModelLineViewLineCount(modelLineNumber) {
  803. return this._lines.getModelLineViewLineCount(modelLineNumber);
  804. }
  805. getViewLineNumberOfModelPosition(modelLineNumber, modelColumn) {
  806. return this._lines.getViewLineNumberOfModelPosition(modelLineNumber, modelColumn);
  807. }
  808. }
  809. export class ViewModelLinesFromModelAsIs {
  810. constructor(model) {
  811. this.model = model;
  812. }
  813. dispose() {
  814. }
  815. createCoordinatesConverter() {
  816. return new IdentityCoordinatesConverter(this);
  817. }
  818. getHiddenAreas() {
  819. return [];
  820. }
  821. setHiddenAreas(_ranges) {
  822. return false;
  823. }
  824. setTabSize(_newTabSize) {
  825. return false;
  826. }
  827. setWrappingSettings(_fontInfo, _wrappingStrategy, _wrappingColumn, _wrappingIndent) {
  828. return false;
  829. }
  830. createLineBreaksComputer() {
  831. const result = [];
  832. return {
  833. addRequest: (lineText, injectedText, previousLineBreakData) => {
  834. result.push(null);
  835. },
  836. finalize: () => {
  837. return result;
  838. }
  839. };
  840. }
  841. onModelFlushed() {
  842. }
  843. onModelLinesDeleted(_versionId, fromLineNumber, toLineNumber) {
  844. return new viewEvents.ViewLinesDeletedEvent(fromLineNumber, toLineNumber);
  845. }
  846. onModelLinesInserted(_versionId, fromLineNumber, toLineNumber, lineBreaks) {
  847. return new viewEvents.ViewLinesInsertedEvent(fromLineNumber, toLineNumber);
  848. }
  849. onModelLineChanged(_versionId, lineNumber, lineBreakData) {
  850. return [false, new viewEvents.ViewLinesChangedEvent(lineNumber, 1), null, null];
  851. }
  852. acceptVersionId(_versionId) {
  853. }
  854. getViewLineCount() {
  855. return this.model.getLineCount();
  856. }
  857. getActiveIndentGuide(viewLineNumber, _minLineNumber, _maxLineNumber) {
  858. return {
  859. startLineNumber: viewLineNumber,
  860. endLineNumber: viewLineNumber,
  861. indent: 0
  862. };
  863. }
  864. getViewLinesBracketGuides(startLineNumber, endLineNumber, activePosition) {
  865. return new Array(endLineNumber - startLineNumber + 1).fill([]);
  866. }
  867. getViewLinesIndentGuides(viewStartLineNumber, viewEndLineNumber) {
  868. const viewLineCount = viewEndLineNumber - viewStartLineNumber + 1;
  869. const result = new Array(viewLineCount);
  870. for (let i = 0; i < viewLineCount; i++) {
  871. result[i] = 0;
  872. }
  873. return result;
  874. }
  875. getViewLineContent(viewLineNumber) {
  876. return this.model.getLineContent(viewLineNumber);
  877. }
  878. getViewLineLength(viewLineNumber) {
  879. return this.model.getLineLength(viewLineNumber);
  880. }
  881. getViewLineMinColumn(viewLineNumber) {
  882. return this.model.getLineMinColumn(viewLineNumber);
  883. }
  884. getViewLineMaxColumn(viewLineNumber) {
  885. return this.model.getLineMaxColumn(viewLineNumber);
  886. }
  887. getViewLineData(viewLineNumber) {
  888. const lineTokens = this.model.tokenization.getLineTokens(viewLineNumber);
  889. const lineContent = lineTokens.getLineContent();
  890. return new ViewLineData(lineContent, false, 1, lineContent.length + 1, 0, lineTokens.inflate(), null);
  891. }
  892. getViewLinesData(viewStartLineNumber, viewEndLineNumber, needed) {
  893. const lineCount = this.model.getLineCount();
  894. viewStartLineNumber = Math.min(Math.max(1, viewStartLineNumber), lineCount);
  895. viewEndLineNumber = Math.min(Math.max(1, viewEndLineNumber), lineCount);
  896. const result = [];
  897. for (let lineNumber = viewStartLineNumber; lineNumber <= viewEndLineNumber; lineNumber++) {
  898. const idx = lineNumber - viewStartLineNumber;
  899. result[idx] = needed[idx] ? this.getViewLineData(lineNumber) : null;
  900. }
  901. return result;
  902. }
  903. getDecorationsInRange(range, ownerId, filterOutValidation) {
  904. return this.model.getDecorationsInRange(range, ownerId, filterOutValidation);
  905. }
  906. normalizePosition(position, affinity) {
  907. return this.model.normalizePosition(position, affinity);
  908. }
  909. getLineIndentColumn(lineNumber) {
  910. return this.model.getLineIndentColumn(lineNumber);
  911. }
  912. getInjectedTextAt(position) {
  913. // Identity lines collection does not support injected text.
  914. return null;
  915. }
  916. }
  917. class IdentityCoordinatesConverter {
  918. constructor(lines) {
  919. this._lines = lines;
  920. }
  921. _validPosition(pos) {
  922. return this._lines.model.validatePosition(pos);
  923. }
  924. _validRange(range) {
  925. return this._lines.model.validateRange(range);
  926. }
  927. // View -> Model conversion and related methods
  928. convertViewPositionToModelPosition(viewPosition) {
  929. return this._validPosition(viewPosition);
  930. }
  931. convertViewRangeToModelRange(viewRange) {
  932. return this._validRange(viewRange);
  933. }
  934. validateViewPosition(_viewPosition, expectedModelPosition) {
  935. return this._validPosition(expectedModelPosition);
  936. }
  937. validateViewRange(_viewRange, expectedModelRange) {
  938. return this._validRange(expectedModelRange);
  939. }
  940. // Model -> View conversion and related methods
  941. convertModelPositionToViewPosition(modelPosition) {
  942. return this._validPosition(modelPosition);
  943. }
  944. convertModelRangeToViewRange(modelRange) {
  945. return this._validRange(modelRange);
  946. }
  947. modelPositionIsVisible(modelPosition) {
  948. const lineCount = this._lines.model.getLineCount();
  949. if (modelPosition.lineNumber < 1 || modelPosition.lineNumber > lineCount) {
  950. // invalid arguments
  951. return false;
  952. }
  953. return true;
  954. }
  955. getModelLineViewLineCount(modelLineNumber) {
  956. return 1;
  957. }
  958. getViewLineNumberOfModelPosition(modelLineNumber, modelColumn) {
  959. return modelLineNumber;
  960. }
  961. }