devexpress-richedit 26.1.2-beta → 26.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/bin/gulpfile.js +1 -1
  2. package/bin/index-custom.js +1 -1
  3. package/bin/localization-builder.js +1 -1
  4. package/bin/nspell-index.js +1 -1
  5. package/bin/nspell.webpack.config.js +1 -1
  6. package/bin/webpack-externals.js +1 -1
  7. package/bin/webpack.config.js +1 -1
  8. package/dist/dx.richedit.css +26 -0
  9. package/dist/dx.richedit.d.ts +1 -1
  10. package/dist/dx.richedit.js +6016 -5627
  11. package/dist/dx.richedit.min.js +3 -3
  12. package/dist/pdfkit.js +21908 -22350
  13. package/dist/pdfkit.min.js +1 -1
  14. package/index.d.ts +1 -1
  15. package/index.js +1 -1
  16. package/lib/client/client-rich-edit.d.ts +0 -1
  17. package/lib/client/client-rich-edit.js +2 -25
  18. package/lib/client/default-localization.js +1 -0
  19. package/lib/common/canvas/canvas-manager.d.ts +1 -1
  20. package/lib/common/canvas/canvas-manager.js +7 -3
  21. package/lib/common/canvas/double-tap-detector.d.ts +10 -0
  22. package/lib/common/canvas/double-tap-detector.js +28 -0
  23. package/lib/common/canvas/renderer-class-names.d.ts +2 -0
  24. package/lib/common/canvas/renderer-class-names.js +2 -0
  25. package/lib/common/canvas/renderes/common/document-renderer.d.ts +20 -7
  26. package/lib/common/canvas/renderes/common/document-renderer.js +236 -47
  27. package/lib/common/canvas/renderes/common/simple-view-renderer.d.ts +3 -1
  28. package/lib/common/canvas/renderes/common/simple-view-renderer.js +35 -2
  29. package/lib/common/canvas/renderes/view-manager.d.ts +3 -0
  30. package/lib/common/canvas/renderes/view-manager.js +34 -7
  31. package/lib/common/commands/border-command-options.d.ts +7 -0
  32. package/lib/common/commands/border-command-options.js +8 -0
  33. package/lib/common/commands/dialogs/dialog-border-shading-command.js +13 -6
  34. package/lib/common/commands/dialogs/dialog-custom-numbering-list-command.js +1 -1
  35. package/lib/common/commands/tables/toggle-table-cells-border-command.d.ts +1 -1
  36. package/lib/common/commands/tables/toggle-table-cells-border-command.js +10 -3
  37. package/lib/common/event-manager.js +2 -0
  38. package/lib/common/layout/main-structures/layout-boxes/layout-box.js +1 -1
  39. package/lib/common/layout/main-structures/layout-column.d.ts +1 -0
  40. package/lib/common/layout/main-structures/layout-column.js +3 -0
  41. package/lib/common/layout/selection/layout-selection-items.d.ts +3 -0
  42. package/lib/common/layout/selection/layout-selection-items.js +5 -0
  43. package/lib/common/layout-engine/selection/selection-formatter.js +7 -3
  44. package/lib/common/layout-formatter/box/generator/box-infos-generator.js +8 -4
  45. package/lib/common/layout-formatter/row/result.d.ts +1 -0
  46. package/lib/common/layout-formatter/row/result.js +11 -1
  47. package/lib/common/layout-formatter/row/size-engine/row-formatting-info.d.ts +2 -1
  48. package/lib/common/layout-formatter/row/size-engine/row-formatting-info.js +7 -4
  49. package/lib/common/model/sub-document.d.ts +12 -5
  50. package/lib/common/model/sub-document.js +36 -31
  51. package/lib/common/rich-edit-core.js +1 -1
  52. package/lib/common/screen-reader-manager.d.ts +6 -3
  53. package/lib/common/screen-reader-manager.js +66 -49
  54. package/lib/common/string-resources.d.ts +23 -0
  55. package/lib/common/string-resources.js +43 -0
  56. package/package.json +3 -3
@@ -1,9 +1,13 @@
1
1
  import { MapCreator } from '../../../utils/map-creator';
2
2
  import { RendererClassNames } from '../../renderer-class-names';
3
3
  import { zIndexCssClassType, ZIndexHelper } from '../z-index-helper';
4
- import { LayoutChangeType } from '../../../layout-formatter/changes/changes/layout-change-base';
4
+ import { ColumnChange } from '../../../layout-formatter/changes/changes/column-change';
5
+ import { LayoutChangeType, RowChange } from '../../../layout-formatter/changes/changes/layout-change-base';
6
+ import { PageAreaChange } from '../../../layout-formatter/changes/changes/page-area-change';
7
+ import { PageChange } from '../../../layout-formatter/changes/changes/page-change';
5
8
  import { LayoutBookmarkBoxType } from '../../../layout/main-structures/layout-boxes/bookmark-box';
6
9
  import { LayoutBoxType } from '../../../layout/main-structures/layout-boxes/layout-box';
10
+ import { LayoutTextBox } from '../../../layout/main-structures/layout-boxes/layout-text-box';
7
11
  import { LayoutPageFlags } from '../../../layout/main-structures/layout-page';
8
12
  import { BorderLineStyle } from '../../../model/borders/enums';
9
13
  import { CharacterFormattingScript, StrikeoutType, UnderlineType } from '../../../model/character/enums';
@@ -18,6 +22,7 @@ import { Errors } from '@devexpress/utils/lib/errors';
18
22
  import { Point } from '@devexpress/utils/lib/geometry/point';
19
23
  import { Rectangle } from '@devexpress/utils/lib/geometry/rectangle';
20
24
  import { Size } from '@devexpress/utils/lib/geometry/size';
25
+ import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed';
21
26
  import { ColorUtils } from '@devexpress/utils/lib/utils/color';
22
27
  import { DomUtils } from '@devexpress/utils/lib/utils/dom';
23
28
  import { ListUtils } from '@devexpress/utils/lib/utils/list';
@@ -96,6 +101,9 @@ export class SimpleViewCanvasSizeManager {
96
101
  export class DocumentRenderer {
97
102
  get cache() { return this.viewManager.cache; }
98
103
  constructor(viewManager) {
104
+ this.isForcedColorsModeActive = false;
105
+ this.selectionSegmentBoxesCache = new SelectionSegmentBoxesCache();
106
+ this.isSelectionChangeCacheEnabled = false;
99
107
  this.viewManager = viewManager;
100
108
  if (this.viewManager.innerClientProperties.viewsSettings.isSimpleView)
101
109
  DomUtils.addClassName(this.viewManager.canvas, RendererClassNames.SIMPLE_VIEW);
@@ -111,6 +119,8 @@ export class DocumentRenderer {
111
119
  }
112
120
  }
113
121
  applyPageChange(layoutPage, pageChange) {
122
+ if (this.isForcedColorsModeActive && !this.isSelectionChangeCacheEnabled)
123
+ this.selectionSegmentBoxesCache.clear();
114
124
  Log.print(LogSource.DocumentRenderer, "applyPageChanges", `pageIndex ${pageChange.index}`);
115
125
  const pageFromCache = this.cache[pageChange.index];
116
126
  for (let pageAreaChange of pageChange.mainPageAreaChanges)
@@ -120,6 +130,76 @@ export class DocumentRenderer {
120
130
  for (let anchoredPictureChange of pageChange.anchoredPictureChanges)
121
131
  this.applyAnchorPictureChange(pageFromCache, layoutPage, anchoredPictureChange);
122
132
  }
133
+ updateSelectedIntervalsPageChanges(layoutPage, pageIndex, intervals = [], isMain = true) {
134
+ if (!intervals.length)
135
+ return;
136
+ const mainPageAreaChanges = [];
137
+ const otherPageAreaChanges = [];
138
+ if (isMain) {
139
+ layoutPage.mainSubDocumentPageAreas.forEach((pageArea, areaIndex) => {
140
+ const pageAreaModelOffset = layoutPage.getPosition() + pageArea.pageOffset;
141
+ this.addSelectedPageAreaChange(mainPageAreaChanges, pageArea, areaIndex, pageAreaModelOffset, intervals);
142
+ });
143
+ }
144
+ else {
145
+ NumberMapUtils.forEach(layoutPage.otherPageAreas, (pageArea, subDocId) => {
146
+ this.addSelectedPageAreaChange(otherPageAreaChanges, pageArea, subDocId, pageArea.pageOffset, intervals);
147
+ });
148
+ }
149
+ if (!mainPageAreaChanges.length && !otherPageAreaChanges.length)
150
+ return;
151
+ this.isSelectionChangeCacheEnabled = true;
152
+ this.applyPageChange(layoutPage, new PageChange(pageIndex, LayoutChangeType.Updated, mainPageAreaChanges, otherPageAreaChanges));
153
+ this.isSelectionChangeCacheEnabled = false;
154
+ }
155
+ addSelectedPageAreaChange(pageAreaChanges, pageArea, pageAreaIndex, pageAreaModelOffset, intervals) {
156
+ const columnChanges = [];
157
+ for (let interval of intervals) {
158
+ const firstColumnIndex = this.findIntersectingLayoutElement(pageArea.columns, pageAreaModelOffset, interval.start, true);
159
+ if (firstColumnIndex < 0)
160
+ continue;
161
+ const lastColumnIndex = this.findIntersectingLayoutElement(pageArea.columns, pageAreaModelOffset, interval.end, false);
162
+ for (let columnIndex = firstColumnIndex; columnIndex <= lastColumnIndex; columnIndex++) {
163
+ const column = pageArea.columns[columnIndex];
164
+ const columnModelOffset = pageAreaModelOffset + column.pageAreaOffset;
165
+ const firstRowIndex = this.findIntersectingLayoutElement(column.rows, columnModelOffset, interval.start, true);
166
+ if (firstRowIndex < 0)
167
+ continue;
168
+ const lastRowIndex = this.findIntersectingLayoutElement(column.rows, columnModelOffset, interval.end, false);
169
+ const rowChanges = [];
170
+ for (let rowIndex = firstRowIndex; rowIndex <= lastRowIndex; rowIndex++)
171
+ rowChanges.push(new RowChange(rowIndex, LayoutChangeType.Replaced));
172
+ columnChanges.push(new ColumnChange(columnIndex, LayoutChangeType.Updated, rowChanges));
173
+ }
174
+ }
175
+ if (columnChanges.length)
176
+ pageAreaChanges.push(new PageAreaChange(pageAreaIndex, LayoutChangeType.Updated, columnChanges));
177
+ }
178
+ findIntersectingLayoutElement(layoutElements, modelOffset, intervalBoundary, findFirst) {
179
+ let low = 0;
180
+ let high = layoutElements.length - 1;
181
+ let result = -1;
182
+ while (low <= high) {
183
+ const mid = (low + high) >> 1;
184
+ const elementPosition = findFirst ? layoutElements[mid].getEndPosition() : layoutElements[mid].getStartPosition();
185
+ const elementModelPosition = modelOffset + elementPosition;
186
+ const isIntersecting = findFirst ? elementModelPosition > intervalBoundary : elementModelPosition < intervalBoundary;
187
+ if (isIntersecting) {
188
+ result = mid;
189
+ if (findFirst)
190
+ high = mid - 1;
191
+ else
192
+ low = mid + 1;
193
+ }
194
+ else {
195
+ if (findFirst)
196
+ low = mid + 1;
197
+ else
198
+ high = mid - 1;
199
+ }
200
+ }
201
+ return result;
202
+ }
123
203
  applyAnchorPictureChange(cache, layoutPage, ancPicChange) {
124
204
  const objId = ancPicChange.index;
125
205
  switch (ancPicChange.changeType) {
@@ -149,13 +229,14 @@ export class DocumentRenderer {
149
229
  DocumentRenderer.removeFromContainerByIndex(pageCache.page, pageAreaChange.canvasIndex, DocumentRenderer.getMainPageAreaContainerCore);
150
230
  break;
151
231
  case LayoutChangeType.Replaced:
152
- DocumentRenderer.replaceInContainer(pageCache.page, pageAreaChange.canvasIndex, this.renderPageArea(layoutPage.renderLevelCalculator, pageCache, layoutPage.mainSubDocumentPageAreas[pageAreaChange.layoutIndex], null), DocumentRenderer.getMainPageAreaContainerCore);
232
+ DocumentRenderer.replaceInContainer(pageCache.page, pageAreaChange.canvasIndex, this.renderPageArea(layoutPage.renderLevelCalculator, pageCache, layoutPage.mainSubDocumentPageAreas[pageAreaChange.layoutIndex], null, layoutPage.getPosition()), DocumentRenderer.getMainPageAreaContainerCore);
153
233
  break;
154
234
  case LayoutChangeType.Updated: {
155
235
  const layoutPageArea = layoutPage.mainSubDocumentPageAreas[pageAreaChange.layoutIndex];
236
+ const pageAreaModelOffset = (layoutPageArea.subDocument.isMain() ? layoutPage.getPosition() : 0) + layoutPageArea.pageOffset;
156
237
  const pageAreaElement = DocumentRenderer.getMainPageAreaContainerCore(pageCache.page).childNodes[pageAreaChange.canvasIndex];
157
238
  for (let columnChange of pageAreaChange.columnChanges)
158
- this.applyColumnChange(pageAreaElement, layoutPageArea, columnChange, layoutPage.renderLevelCalculator.renderMainPageAreaLevel);
239
+ this.applyColumnChange(pageAreaElement, layoutPageArea, columnChange, layoutPage.renderLevelCalculator.renderMainPageAreaLevel, pageAreaModelOffset);
159
240
  break;
160
241
  }
161
242
  default: throw new Error(Errors.InternalException);
@@ -171,7 +252,9 @@ export class DocumentRenderer {
171
252
  break;
172
253
  }
173
254
  case LayoutChangeType.Replaced: {
174
- DocumentRenderer.replaceFromContainerByObject(subDocId, DocumentRenderer.getOtherPageAreaContainerCore(cache.page), cache.otherAreas, this.renderPageArea(layoutPage.renderLevelCalculator, cache, pageArea, pageArea.subDocument.isTextBox() ? layoutPage.anchoredObjectHolder.getTextBoxByInternalSubDocId(subDocId) : null));
255
+ const textBox = pageArea.subDocument.isTextBox() ? layoutPage.anchoredObjectHolder.getTextBoxByInternalSubDocId(subDocId) : null;
256
+ const pageAreaElement = this.renderPageArea(layoutPage.renderLevelCalculator, cache, pageArea, textBox, layoutPage.getPosition());
257
+ DocumentRenderer.replaceFromContainerByObject(subDocId, DocumentRenderer.getOtherPageAreaContainerCore(cache.page), cache.otherAreas, pageAreaElement);
175
258
  break;
176
259
  }
177
260
  case LayoutChangeType.Updated: {
@@ -179,32 +262,36 @@ export class DocumentRenderer {
179
262
  const level = pageArea.subDocument.isTextBox() ?
180
263
  layoutPage.renderLevelCalculator.getRenderLevel(layoutPage.anchoredObjectHolder.getTextBoxByInternalSubDocId(subDocId).rendererLevel) :
181
264
  layoutPage.renderLevelCalculator.renderHeaderFooterPageAreasLevel;
265
+ const pageAreaModelOffset = (pageArea.subDocument.isMain() ? layoutPage.getPosition() : 0) + pageArea.pageOffset;
182
266
  for (let columnChange of pageAreaChange.columnChanges)
183
- this.applyColumnChange(pageAreaElement, pageArea, columnChange, level);
267
+ this.applyColumnChange(pageAreaElement, pageArea, columnChange, level, pageAreaModelOffset);
184
268
  break;
185
269
  }
186
270
  case LayoutChangeType.Inserted: {
187
- DocumentRenderer.insertToContainerByObject(subDocId, DocumentRenderer.getOtherPageAreaContainerCore(cache.page), cache.otherAreas, this.renderPageArea(layoutPage.renderLevelCalculator, cache, pageArea, pageArea.subDocument.isTextBox() ? layoutPage.anchoredObjectHolder.getTextBoxByInternalSubDocId(subDocId) : null));
271
+ const textBox = pageArea.subDocument.isTextBox() ? layoutPage.anchoredObjectHolder.getTextBoxByInternalSubDocId(subDocId) : null;
272
+ const pageAreaElement = this.renderPageArea(layoutPage.renderLevelCalculator, cache, pageArea, textBox, layoutPage.getPosition());
273
+ DocumentRenderer.insertToContainerByObject(subDocId, DocumentRenderer.getOtherPageAreaContainerCore(cache.page), cache.otherAreas, pageAreaElement);
188
274
  break;
189
275
  }
190
276
  default: throw new Error(Errors.InternalException);
191
277
  }
192
278
  }
193
- applyColumnChange(pageAreaElement, layoutPageArea, columnChange, level) {
279
+ applyColumnChange(pageAreaElement, layoutPageArea, columnChange, level, pageAreaModelOffset) {
194
280
  switch (columnChange.changeType) {
195
281
  case LayoutChangeType.Deleted:
196
282
  DocumentRenderer.removeFromContainerByIndex(pageAreaElement, columnChange.canvasIndex, DocumentRenderer.getColumnsContainerCore);
197
283
  break;
198
284
  case LayoutChangeType.Replaced: {
199
- const renderedColumn = this.renderColumn(layoutPageArea.columns[columnChange.layoutIndex], level, layoutPageArea.subDocument.isMain());
285
+ const renderedColumn = this.renderColumn(layoutPageArea.columns[columnChange.layoutIndex], level, pageAreaModelOffset, layoutPageArea.subDocument.isMain());
200
286
  DocumentRenderer.replaceInContainer(pageAreaElement, columnChange.canvasIndex, renderedColumn, DocumentRenderer.getColumnsContainerCore);
201
287
  break;
202
288
  }
203
289
  case LayoutChangeType.Updated: {
204
290
  const layoutColumn = layoutPageArea.columns[columnChange.layoutIndex];
291
+ const columnModelOffset = pageAreaModelOffset + layoutColumn.pageAreaOffset;
205
292
  const columnElement = DocumentRenderer.getColumnsContainerCore(pageAreaElement).childNodes[columnChange.canvasIndex];
206
293
  for (var rowChange of columnChange.rowChanges)
207
- DocumentRenderer.applyChange(columnElement, rowChange, DocumentRenderer.getRowsContainerCore, () => this.renderRow(layoutColumn.rows[rowChange.layoutIndex], level));
294
+ DocumentRenderer.applyChange(columnElement, rowChange, DocumentRenderer.getRowsContainerCore, () => this.renderRow(layoutColumn.rows[rowChange.layoutIndex], level, columnModelOffset));
208
295
  for (var tableChange of columnChange.tableChanges)
209
296
  DocumentRenderer.applyChange(columnElement, tableChange, DocumentRenderer.getTablesContainerCore, () => DocumentRenderer.renderTable(layoutColumn.tablesInfo[tableChange.layoutIndex], level, this.viewManager.innerClientProperties.showTableGridLines));
210
297
  for (var paragraphFrameChange of columnChange.paragraphFrameChanges)
@@ -212,7 +299,7 @@ export class DocumentRenderer {
212
299
  break;
213
300
  }
214
301
  case LayoutChangeType.Inserted: {
215
- const renderedColumn = this.renderColumn(layoutPageArea.columns[columnChange.layoutIndex], level, layoutPageArea.subDocument.isMain());
302
+ const renderedColumn = this.renderColumn(layoutPageArea.columns[columnChange.layoutIndex], level, pageAreaModelOffset, layoutPageArea.subDocument.isMain());
216
303
  DocumentRenderer.insertInContainer(pageAreaElement, columnChange.canvasIndex, renderedColumn, DocumentRenderer.getColumnsContainerCore);
217
304
  break;
218
305
  }
@@ -310,17 +397,18 @@ export class DocumentRenderer {
310
397
  renderPageContent(page, pageIndex) {
311
398
  const pageCache = this.cache[pageIndex];
312
399
  const [mainPageAreasContainer, otherPageAreasContainer, floatingObjectsContainer] = this.renderPageContainers(pageCache);
313
- ListUtils.forEach(page.mainSubDocumentPageAreas, (area) => mainPageAreasContainer.appendChild(this.renderPageArea(page.renderLevelCalculator, pageCache, area, null)));
400
+ ListUtils.forEach(page.mainSubDocumentPageAreas, (area) => mainPageAreasContainer.appendChild(this.renderPageArea(page.renderLevelCalculator, pageCache, area, null, page.getPosition())));
314
401
  if (!this.viewManager.innerClientProperties.viewsSettings.isSimpleView)
315
402
  NumberMapUtils.forEach(page.otherPageAreas, (pageArea, subDocId) => {
316
403
  if (!pageArea.subDocument.isTextBox())
317
- DocumentRenderer.insertToContainerByObject(subDocId, otherPageAreasContainer, pageCache.otherAreas, this.renderPageArea(page.renderLevelCalculator, pageCache, pageArea, null));
404
+ DocumentRenderer.insertToContainerByObject(subDocId, otherPageAreasContainer, pageCache.otherAreas, this.renderPageArea(page.renderLevelCalculator, pageCache, pageArea, null, page.getPosition()));
318
405
  });
319
406
  for (let ancObjProps of this.renderPageContentGetFloatingObjects(page)) {
320
407
  switch (ancObjProps.getType()) {
321
408
  case LayoutBoxType.AnchorTextBox:
322
409
  const internalSubDocId = ancObjProps.internalSubDocId;
323
- DocumentRenderer.insertToContainerByObject(internalSubDocId, otherPageAreasContainer, pageCache.otherAreas, this.renderPageArea(page.renderLevelCalculator, pageCache, page.otherPageAreas[internalSubDocId], ancObjProps));
410
+ const pageAreaElement = this.renderPageArea(page.renderLevelCalculator, pageCache, page.otherPageAreas[internalSubDocId], ancObjProps, page.getPosition());
411
+ DocumentRenderer.insertToContainerByObject(internalSubDocId, otherPageAreasContainer, pageCache.otherAreas, pageAreaElement);
324
412
  break;
325
413
  case LayoutBoxType.AnchorPicture:
326
414
  DocumentRenderer.insertToContainerByObject(ancObjProps.objectId, floatingObjectsContainer, pageCache.anchoredPicture, this.renderFloatingPicture(ancObjProps, page.renderLevelCalculator));
@@ -344,7 +432,7 @@ export class DocumentRenderer {
344
432
  }
345
433
  throw new Error(Errors.InternalException);
346
434
  }
347
- renderPageArea(renderLevelCalculator, pageCache, area, textBox, renderContent = true) {
435
+ renderPageArea(renderLevelCalculator, pageCache, area, textBox, pageStartPosition = 0) {
348
436
  const element = DocumentRenderer.renderContainer(DocumentRenderer.getPageAreaClassname(area));
349
437
  if (area.subDocument.isTextBox())
350
438
  element.style.overflow = "hidden";
@@ -383,42 +471,39 @@ export class DocumentRenderer {
383
471
  ColorUtils.LIGHT_COLOR : this.viewManager.layout.pageColor;
384
472
  DocumentRenderer.updatePageColor(element, color);
385
473
  }
386
- if (renderContent)
387
- for (let column of area.columns)
388
- element.appendChild(this.renderColumn(column, level, area.subDocument.isMain()));
474
+ const isMainPageArea = area.subDocument.isMain();
475
+ const pageAreaModelOffset = (area.subDocument.isMain() ? pageStartPosition : 0) + area.pageOffset;
476
+ for (let column of area.columns)
477
+ element.appendChild(this.renderColumn(column, level, pageAreaModelOffset, isMainPageArea));
389
478
  return element;
390
479
  }
391
- renderColumn(column, level, _isMainPageArea) {
480
+ renderColumn(column, level, pageAreaModelOffset, _isMainPageArea) {
392
481
  const columnElement = DocumentRenderer.renderContainer(RendererClassNames.COLUMN);
393
482
  DomUtils.setStyleSizeAndPosition(columnElement.style, column);
483
+ const columnModelOffset = pageAreaModelOffset + column.pageAreaOffset;
394
484
  const rowsContainer = columnElement.appendChild(DocumentRenderer.renderContainer(RendererClassNames.ROWS_CONTAINER));
395
485
  const paragraphFramesContainer = columnElement.appendChild(DocumentRenderer.renderContainer(RendererClassNames.PARAGRAPHFRAMES_CONTAINER));
396
486
  const tablesContainer = columnElement.appendChild(DocumentRenderer.renderContainer(RendererClassNames.TABLES_CONTAINER));
397
487
  for (let row of column.rows)
398
- rowsContainer.appendChild(this.renderRow(row, level));
488
+ rowsContainer.appendChild(this.renderRow(row, level, columnModelOffset));
399
489
  for (let frame of column.paragraphFrames)
400
490
  paragraphFramesContainer.appendChild(DocumentRenderer.renderParagraphFrame(frame, level));
401
491
  for (let tableColumn of column.tablesInfo)
402
492
  tablesContainer.appendChild(DocumentRenderer.renderTable(tableColumn, level, this.viewManager.innerClientProperties.showTableGridLines));
403
493
  return columnElement;
404
494
  }
405
- renderRow(row, level) {
495
+ renderRow(row, level, columnModelOffset = 0) {
406
496
  const lastBoxIndexWhatCanStrikeoutAndUnderline = row.getLastBoxIndexWhatCanStrikeoutAndUnderline();
497
+ const rowModelOffset = columnModelOffset + row.columnOffset;
407
498
  const rowElement = DocumentRenderer.renderContainer(RendererClassNames.ROW);
408
499
  rowElement.innerHTML = "";
409
500
  if (row.numberingListBox) {
410
501
  const skipUnderlineAndStrikeout = 0 > lastBoxIndexWhatCanStrikeoutAndUnderline;
411
- let box = this.renderBox(row, row.numberingListBox.textBox, level, skipUnderlineAndStrikeout).html;
412
- if (typeof box === 'string')
413
- rowElement.innerHTML += box;
414
- else
415
- rowElement.appendChild(box);
502
+ let box = this.renderBox(row, row.numberingListBox.textBox, level, skipUnderlineAndStrikeout, rowModelOffset, true).html;
503
+ rowElement.appendChild(box);
416
504
  if (row.numberingListBox.separatorBox) {
417
- let box = this.renderBox(row, row.numberingListBox.separatorBox, level, skipUnderlineAndStrikeout).html;
418
- if (typeof box === 'string')
419
- rowElement.innerHTML += box;
420
- else
421
- rowElement.appendChild(box);
505
+ let box = this.renderBox(row, row.numberingListBox.separatorBox, level, skipUnderlineAndStrikeout, rowModelOffset, true).html;
506
+ rowElement.appendChild(box);
422
507
  }
423
508
  }
424
509
  let increaseRowHeight = false;
@@ -431,12 +516,9 @@ export class DocumentRenderer {
431
516
  nextBoxHasNormalScriptedUnderline = this.boxHasNormalScriptedUnderline(row.boxes[boxIndex + 1]);
432
517
  const skipUnderlineAndStrikeout = boxIndex > lastBoxIndexWhatCanStrikeoutAndUnderline;
433
518
  const skipUnderlineScript = prevBoxHasNormalScriptedUnderline || nextBoxHasNormalScriptedUnderline;
434
- const boxRenderResult = this.renderBox(row, box, level, skipUnderlineAndStrikeout, skipUnderlineScript);
519
+ const boxRenderResult = this.renderBox(row, box, level, skipUnderlineAndStrikeout, rowModelOffset, skipUnderlineScript);
435
520
  const boxRenderResultHtml = boxRenderResult.html;
436
- if (typeof boxRenderResultHtml === 'string')
437
- rowElement.innerHTML += boxRenderResultHtml;
438
- else
439
- rowElement.appendChild(boxRenderResultHtml);
521
+ rowElement.appendChild(boxRenderResultHtml);
440
522
  increaseRowHeight = increaseRowHeight || boxRenderResult.increaseRowHeight;
441
523
  prevBoxHasNormalScriptedUnderline = this.boxHasNormalScriptedUnderline(box, skipUnderlineScript);
442
524
  }
@@ -450,7 +532,30 @@ export class DocumentRenderer {
450
532
  && box.characterProperties.fontUnderlineType != UnderlineType.None
451
533
  && (box.characterProperties.script === CharacterFormattingScript.Normal || forceNormalScript);
452
534
  }
453
- renderBox(row, box, level, skipUnderlineAndStrikeout, skipUnderlineScript = true) {
535
+ renderBox(row, box, level, skipUnderlineAndStrikeout, rowModelOffset, skipUnderlineScript = true) {
536
+ if (!this.isForcedColorsModeActive)
537
+ return this.renderSingleBox(row, box, level, skipUnderlineAndStrikeout, skipUnderlineScript, false);
538
+ const selectedIntervals = this.getSelectedIntervalsForBox(rowModelOffset, box);
539
+ if (selectedIntervals.length == 0)
540
+ return this.renderSingleBox(row, box, level, skipUnderlineAndStrikeout, skipUnderlineScript, false);
541
+ if (box instanceof LayoutTextBox) {
542
+ const result = document.createDocumentFragment();
543
+ let increaseRowHeight = false;
544
+ for (const segment of this.getSelectionSegmentBoxes(box, selectedIntervals)) {
545
+ const segmentRenderResult = this.renderSingleBox(row, segment.box, level, skipUnderlineAndStrikeout, skipUnderlineScript, segment.isSelected);
546
+ increaseRowHeight = increaseRowHeight || segmentRenderResult.increaseRowHeight;
547
+ result.appendChild(segmentRenderResult.html);
548
+ }
549
+ return new BoxRenderResult(result, increaseRowHeight);
550
+ }
551
+ return this.renderSingleBox(row, box, level, skipUnderlineAndStrikeout, skipUnderlineScript, true);
552
+ }
553
+ updateForcedColorsModeState() {
554
+ this.isForcedColorsModeActive = typeof window !== 'undefined' && typeof window.matchMedia === 'function' &&
555
+ window.matchMedia('(forced-colors: active)').matches;
556
+ return this.isForcedColorsModeActive;
557
+ }
558
+ renderSingleBox(row, box, level, skipUnderlineAndStrikeout, skipUnderlineScript = true, isSelected = false) {
454
559
  let content = box.renderGetContent(this);
455
560
  let top = box.getTop(row);
456
561
  const left = box.x;
@@ -522,9 +627,11 @@ export class DocumentRenderer {
522
627
  default:
523
628
  boxClass = RendererClassNames.BOX_SPACE + " " + ZIndexHelper.getClassName(level, zIndexCssClassType.BoxSpace);
524
629
  }
630
+ if (isSelected)
631
+ boxClass += " " + RendererClassNames.BOX_SELECTED;
525
632
  if (charProps.hidden && this.viewManager.innerClientProperties.showHiddenSymbols)
526
633
  boxClass += ' ' + RendererClassNames.HIDDEN_BOX;
527
- const result = new DocumentFragment();
634
+ const result = document.createDocumentFragment();
528
635
  const contentSpan = document.createElement('span');
529
636
  contentSpan.style.cssText = boxStyles.join(";");
530
637
  contentSpan.setAttribute('class', boxClass);
@@ -573,6 +680,53 @@ export class DocumentRenderer {
573
680
  }
574
681
  return new BoxRenderResult(result, charProps.hidden);
575
682
  }
683
+ getSelectedIntervalsForBox(rowModelOffset, box) {
684
+ const selection = this.viewManager.control.selection;
685
+ if (!selection || selection.isCollapsed())
686
+ return [];
687
+ const boxStart = rowModelOffset + box.rowOffset;
688
+ const boxEnd = boxStart + box.getLength();
689
+ const intersections = [];
690
+ for (const selectionInterval of selection.intervals) {
691
+ const start = Math.max(boxStart, selectionInterval.start);
692
+ const end = Math.min(boxEnd, selectionInterval.end);
693
+ if (end > start)
694
+ intersections.push(new FixedInterval(start - boxStart, end - start));
695
+ }
696
+ return intersections;
697
+ }
698
+ getSelectionSegmentBoxes(box, selectedIntervals) {
699
+ this.selectionSegmentBoxesCache.clearIfIntervalsChanged(box, selectedIntervals);
700
+ if (!selectedIntervals.length)
701
+ return [{ box, isSelected: false }];
702
+ const segmentBoxes = [];
703
+ let textPosition = 0;
704
+ for (const interval of selectedIntervals) {
705
+ if (interval.start > textPosition)
706
+ segmentBoxes.push({ box: this.getOrCreateSelectionSegmentBox(box, textPosition, interval.start), isSelected: false });
707
+ segmentBoxes.push({ box: this.getOrCreateSelectionSegmentBox(box, interval.start, interval.end), isSelected: true });
708
+ textPosition = interval.end;
709
+ }
710
+ if (textPosition < box.text.length)
711
+ segmentBoxes.push({ box: this.getOrCreateSelectionSegmentBox(box, textPosition, box.text.length), isSelected: false });
712
+ return segmentBoxes;
713
+ }
714
+ getOrCreateSelectionSegmentBox(box, start, end) {
715
+ return this.selectionSegmentBoxesCache.get(box, start, end) ?? this.createSelectionSegmentBox(box, start, end);
716
+ }
717
+ createSelectionSegmentBox(box, start, end) {
718
+ const measurer = this.viewManager.control.measurer;
719
+ const left = box.getCharOffsetXInPixels(measurer, start);
720
+ const right = box.getCharOffsetXInPixels(measurer, end);
721
+ const segmentBox = box.clone();
722
+ segmentBox.text = box.text.substring(start, end);
723
+ segmentBox.x = box.x + left;
724
+ segmentBox.width = right - left;
725
+ segmentBox.rowOffset = box.rowOffset + start;
726
+ if (this.isSelectionChangeCacheEnabled)
727
+ this.selectionSegmentBoxesCache.set(box, start, end, segmentBox);
728
+ return segmentBox;
729
+ }
576
730
  renderVerticalAlignContainer(content, commonStyles, script) {
577
731
  const cssText = commonStyles.join(";") + ";vertical-align: " + (script === CharacterFormattingScript.Subscript ? "sub" : "super") + ";";
578
732
  return this.renderContainerWithCssText(content, cssText);
@@ -906,17 +1060,52 @@ export class BoxRenderResult {
906
1060
  this.increaseRowHeight = increaseRowHeight;
907
1061
  }
908
1062
  toString() {
909
- if (typeof this.html === 'string')
910
- return this.html;
911
- else {
912
- const result = [];
913
- if (this.html) {
914
- const length = this.html.children.length;
915
- for (let i = 0; i < length; i++) {
916
- result.push(this.html.children.item(i).outerHTML);
917
- }
1063
+ const result = [];
1064
+ if (this.html) {
1065
+ const length = this.html.children.length;
1066
+ for (let i = 0; i < length; i++) {
1067
+ result.push(this.html.children.item(i).outerHTML);
918
1068
  }
919
- return result.join('');
920
1069
  }
1070
+ return result.join('');
1071
+ }
1072
+ }
1073
+ class SelectionSegmentBoxesCache {
1074
+ constructor() {
1075
+ this.cache = new WeakMap();
1076
+ this.intervalsSignatureByBox = new WeakMap();
1077
+ }
1078
+ clear() {
1079
+ this.cache = new WeakMap();
1080
+ this.intervalsSignatureByBox = new WeakMap();
1081
+ }
1082
+ clearIfIntervalsChanged(box, intervals) {
1083
+ const currentSignature = this.getIntervalsSignature(intervals);
1084
+ const prevSignature = this.intervalsSignatureByBox.get(box);
1085
+ if (prevSignature !== currentSignature)
1086
+ this.cache.delete(box);
1087
+ this.intervalsSignatureByBox.set(box, currentSignature);
1088
+ }
1089
+ get(box, start, end) {
1090
+ const segmentsCache = this.cache.get(box);
1091
+ if (!segmentsCache)
1092
+ return null;
1093
+ const cacheKey = this.getCacheKey(start, end);
1094
+ return segmentsCache.get(cacheKey) || null;
1095
+ }
1096
+ set(box, start, end, segmentBox) {
1097
+ let segmentsCache = this.cache.get(box);
1098
+ if (!segmentsCache) {
1099
+ segmentsCache = new Map();
1100
+ this.cache.set(box, segmentsCache);
1101
+ }
1102
+ const cacheKey = this.getCacheKey(start, end);
1103
+ segmentsCache.set(cacheKey, segmentBox);
1104
+ }
1105
+ getCacheKey(start, end) {
1106
+ return `${start}_${end}`;
1107
+ }
1108
+ getIntervalsSignature(intervals) {
1109
+ return intervals.map(interval => `${interval.start}_${interval.end}`).join('|');
921
1110
  }
922
1111
  }
@@ -7,6 +7,7 @@ import { LayoutColumn } from '../../../layout/main-structures/layout-column';
7
7
  import { LayoutPage } from '../../../layout/main-structures/layout-page';
8
8
  import { BoundaryInterval } from '@devexpress/utils/lib/intervals/boundary';
9
9
  import { ConstInterval } from '@devexpress/utils/lib/intervals/const';
10
+ import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed';
10
11
  import { VisibleCanvasObjectsInfo } from '../canvas-listener/simple-view-canvas-listener';
11
12
  import { DocumentRenderer } from './document-renderer';
12
13
  export declare class SimpleViewRenderer extends DocumentRenderer {
@@ -15,6 +16,7 @@ export declare class SimpleViewRenderer extends DocumentRenderer {
15
16
  protected tableIndexInterval: BoundaryInterval;
16
17
  protected updateDataChunk: VisibleCanvasObjectsInfo;
17
18
  pageInserted(layoutPage: LayoutPage, updateDataChunk: VisibleCanvasObjectsInfo): void;
19
+ updateSelectedIntervalsPageChanges(layoutPage: LayoutPage, pageIndex?: number, intervals?: FixedInterval[], _isMain?: boolean): void;
18
20
  protected renderPageContentGetFloatingObjects(page: LayoutPage): LayoutAnchoredObjectBox[];
19
21
  collectScrollChanges<ResultChangesT extends LayoutChangeBase>(oldInterval: ConstInterval, newInterval: ConstInterval, isAddUpdateChange: boolean, getConstructor: new (layoutIndex: number, canvasIndex: number, changeType: LayoutChangeType) => ResultChangesT): ResultChangesT[];
20
22
  collectScrollChangesMap<ObjectT extends LayoutAnchoredPictureBox | LayoutAnchoredTextBox, ResultChangesT extends LayoutChangeBase>(oldObjects: Record<number, ObjectT>, newObjects: Record<number, ObjectT>, isAddUpdateChange: boolean, isTextBoxes: boolean, getConstructor: new (layoutIndex: number, changeType: LayoutChangeType) => ResultChangesT): ResultChangesT[];
@@ -24,6 +26,6 @@ export declare class SimpleViewRenderer extends DocumentRenderer {
24
26
  private applyFormatterChangesMap;
25
27
  private makePageChange;
26
28
  pageUpdated(pageChange: PageChange, newUpdateDataChunk: VisibleCanvasObjectsInfo): void;
27
- protected renderColumn(column: LayoutColumn, level: number, isMainPageArea: boolean): HTMLElement;
29
+ protected renderColumn(column: LayoutColumn, level: number, pageAreaModelOffset: number, isMainPageArea: boolean): HTMLElement;
28
30
  protected updatePageSize(page: LayoutPage, pageElement: HTMLElement): void;
29
31
  }
@@ -29,6 +29,36 @@ export class SimpleViewRenderer extends DocumentRenderer {
29
29
  this.updateDataChunk = updateDataChunk;
30
30
  this.renderPage(layoutPage, 0, true);
31
31
  }
32
+ updateSelectedIntervalsPageChanges(layoutPage, pageIndex = 0, intervals = [], _isMain = true) {
33
+ if (!intervals.length)
34
+ return;
35
+ const pageArea = layoutPage.mainSubDocumentPageAreas[0];
36
+ const column = pageArea?.columns?.[0];
37
+ if (!column)
38
+ return;
39
+ const visibleRows = this.updateDataChunk.rows;
40
+ const visibleStart = Math.max(0, visibleRows.start);
41
+ const visibleEnd = Math.min(visibleRows.end, column.rows.length);
42
+ if (visibleStart >= visibleEnd)
43
+ return;
44
+ const pageModelOffset = layoutPage.getPosition() + pageArea.pageOffset + column.pageAreaOffset;
45
+ const rowChanges = [];
46
+ for (let rowLayoutIndex = visibleStart; rowLayoutIndex < visibleEnd; rowLayoutIndex++) {
47
+ const row = column.rows[rowLayoutIndex];
48
+ const rowStart = pageModelOffset + row.getStartPosition();
49
+ const rowEnd = pageModelOffset + row.getEndPosition();
50
+ if (rowEnd <= rowStart)
51
+ continue;
52
+ const hasIntersection = intervals.some((interval) => rowStart < interval.end && rowEnd > interval.start);
53
+ if (hasIntersection)
54
+ rowChanges.push(new RowChangeSV(rowLayoutIndex, rowLayoutIndex - visibleStart, LayoutChangeType.Replaced));
55
+ }
56
+ if (!rowChanges.length)
57
+ return;
58
+ const columnChange = new ColumnChange(0, LayoutChangeType.Updated, rowChanges);
59
+ const pageAreaChange = new PageAreaChange(0, LayoutChangeType.Updated, [columnChange]);
60
+ this.applyPageChange(layoutPage, new PageChange(pageIndex, LayoutChangeType.Updated, [pageAreaChange], []));
61
+ }
32
62
  renderPageContentGetFloatingObjects(page) {
33
63
  const foMap = NumberMapUtils.shallowCopy(this.updateDataChunk.ancPictureObjs);
34
64
  NumberMapUtils.forEach(this.updateDataChunk.ancTextBoxObjs, (tb, key) => foMap[key] = tb);
@@ -93,6 +123,8 @@ export class SimpleViewRenderer extends DocumentRenderer {
93
123
  if (!scrollChanges.length || !formatterChanges.length)
94
124
  return;
95
125
  const mm = ListUtils.minMaxExtended(scrollChanges, (v) => v.layoutIndex);
126
+ if (!mm)
127
+ return;
96
128
  const visibleObjectsInterval = new BoundaryInterval(mm.minValue, mm.maxValue + 1);
97
129
  const isObjectMustBeReplaced = ListUtils.accumulate(formatterChanges, {}, (acc, c) => {
98
130
  if (c.changeType == LayoutChangeType.Replaced && visibleObjectsInterval.contains(c.layoutIndex))
@@ -139,16 +171,17 @@ export class SimpleViewRenderer extends DocumentRenderer {
139
171
  this.applyPageChange(this.viewManager.layout.pages[0], pc);
140
172
  this.updateDataChunk = newUpdateDataChunk;
141
173
  }
142
- renderColumn(column, level, isMainPageArea) {
174
+ renderColumn(column, level, pageAreaModelOffset, isMainPageArea) {
143
175
  const columnElement = DocumentRenderer.renderContainer(RendererClassNames.COLUMN);
144
176
  DomUtils.setStyleSizeAndPosition(columnElement.style, column);
177
+ const columnModelOffset = pageAreaModelOffset + column.pageAreaOffset;
145
178
  const rowsContainer = columnElement.appendChild(DocumentRenderer.renderContainer(RendererClassNames.ROWS_CONTAINER));
146
179
  const paragraphFramesContainer = columnElement.appendChild(DocumentRenderer.renderContainer(RendererClassNames.PARAGRAPHFRAMES_CONTAINER));
147
180
  const tablesContainer = columnElement.appendChild(DocumentRenderer.renderContainer(RendererClassNames.TABLES_CONTAINER));
148
181
  const bounds = isMainPageArea ?
149
182
  this.updateDataChunk :
150
183
  new SimpleViewChangesDataBase(new BoundaryInterval(0, column.rows.length), new BoundaryInterval(0, column.tablesInfo.length), new BoundaryInterval(0, column.paragraphFrames.length));
151
- ListUtils.forEach(column.rows, (row) => rowsContainer.appendChild(this.renderRow(row, level)), bounds.rows.start, bounds.rows.end);
184
+ ListUtils.forEach(column.rows, (row) => rowsContainer.appendChild(this.renderRow(row, level, columnModelOffset)), bounds.rows.start, bounds.rows.end);
152
185
  ListUtils.forEach(column.paragraphFrames, (pf) => paragraphFramesContainer.appendChild(DocumentRenderer.renderParagraphFrame(pf, level)), bounds.parFrames.start, bounds.parFrames.end);
153
186
  ListUtils.forEach(column.tablesInfo, (t) => tablesContainer.appendChild(DocumentRenderer.renderTable(t, level, this.viewManager.innerClientProperties.showTableGridLines)), bounds.tables.start, bounds.tables.end);
154
187
  return columnElement;
@@ -31,6 +31,7 @@ export declare class ViewManager implements ILayoutChangesListener, IZoomLevelHo
31
31
  private renderers;
32
32
  get renderer(): DocumentRenderer;
33
33
  get printLayoutRenderer(): DocumentRenderer;
34
+ get isSimpleView(): boolean;
34
35
  lastUsedRendererType: ViewType;
35
36
  canvasListeners: Record<number, CanvasListener<DocumentRenderer>>;
36
37
  get canvasListener(): CanvasListener<DocumentRenderer>;
@@ -67,6 +68,8 @@ export declare class ViewManager implements ILayoutChangesListener, IZoomLevelHo
67
68
  NotifySearchSelectionLayoutChanged(): void;
68
69
  NotifyMisspelledSelectionLayoutChanged(): void;
69
70
  NotifyRangePermissionLayoutChanged(): void;
71
+ private updateSelectedContent;
72
+ private getSelectionIntervalsForPageChange;
70
73
  private addTopLevelContainers;
71
74
  setWorkSession(layout: DocumentLayout, layoutSelection: LayoutSelection, imageCache: ImageCache): void;
72
75
  closeDocument(): void;