devexpress-richedit 25.2.8 → 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 (80) 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 +6559 -5654
  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 +4 -27
  18. package/lib/client/default-localization.js +19 -0
  19. package/lib/client/dialogs/alert-dialog.d.ts +1 -1
  20. package/lib/client/dialogs/bookmark-dialog.d.ts +1 -1
  21. package/lib/client/dialogs/delete-table-cells-dialog.d.ts +1 -1
  22. package/lib/client/dialogs/dialog-base.d.ts +1 -1
  23. package/lib/client/dialogs/find-replace-dialog.d.ts +1 -1
  24. package/lib/client/dialogs/finish-and-merge-dialog.d.ts +1 -1
  25. package/lib/client/dialogs/font-dialog.d.ts +1 -1
  26. package/lib/client/dialogs/hyperlink-dialog.d.ts +1 -1
  27. package/lib/client/dialogs/insert-merge-field-dialog.d.ts +1 -1
  28. package/lib/client/dialogs/insert-table-cells-dialog.d.ts +1 -1
  29. package/lib/client/dialogs/insert-table-dialog.d.ts +1 -1
  30. package/lib/client/dialogs/page-setup-dialog.d.ts +1 -1
  31. package/lib/client/dialogs/paragraph-dialog.d.ts +1 -1
  32. package/lib/client/dialogs/split-table-cells-dialog.d.ts +1 -1
  33. package/lib/client/dialogs/tabs-dialog.d.ts +1 -1
  34. package/lib/client/public/rich-edit.js +2 -0
  35. package/lib/common/canvas/canvas-manager.d.ts +1 -1
  36. package/lib/common/canvas/canvas-manager.js +7 -3
  37. package/lib/common/canvas/double-tap-detector.d.ts +10 -0
  38. package/lib/common/canvas/double-tap-detector.js +28 -0
  39. package/lib/common/canvas/renderer-class-names.d.ts +2 -0
  40. package/lib/common/canvas/renderer-class-names.js +2 -0
  41. package/lib/common/canvas/renderes/common/document-renderer.d.ts +20 -7
  42. package/lib/common/canvas/renderes/common/document-renderer.js +236 -47
  43. package/lib/common/canvas/renderes/common/simple-view-renderer.d.ts +3 -1
  44. package/lib/common/canvas/renderes/common/simple-view-renderer.js +35 -2
  45. package/lib/common/canvas/renderes/view-manager.d.ts +3 -0
  46. package/lib/common/canvas/renderes/view-manager.js +34 -7
  47. package/lib/common/commands/command-manager.d.ts +2 -0
  48. package/lib/common/commands/command-manager.js +6 -0
  49. package/lib/common/commands/dialogs/dialog-custom-numbering-list-command.js +1 -1
  50. package/lib/common/commands/layout/switch-view-command.js +2 -1
  51. package/lib/common/commands/selection/go-to-next-word-command.d.ts +3 -4
  52. package/lib/common/commands/selection/go-to-next-word-command.js +2 -9
  53. package/lib/common/commands/selection/go-to-prev-word-command.d.ts +3 -2
  54. package/lib/common/commands/selection/go-to-prev-word-command.js +2 -2
  55. package/lib/common/commands/selection/select-all-document-command.d.ts +2 -0
  56. package/lib/common/commands/selection/select-all-document-command.js +6 -0
  57. package/lib/common/commands/selection/selection-command-base.d.ts +2 -0
  58. package/lib/common/commands/selection/selection-command-base.js +8 -0
  59. package/lib/common/event-manager.js +6 -12
  60. package/lib/common/formats/txt/txt-exporter.js +1 -1
  61. package/lib/common/input-controller.js +2 -0
  62. package/lib/common/interfaces/i-rich-edit-core.d.ts +2 -0
  63. package/lib/common/layout/main-structures/layout-boxes/layout-box.js +1 -1
  64. package/lib/common/layout/main-structures/layout-column.d.ts +1 -0
  65. package/lib/common/layout/main-structures/layout-column.js +3 -0
  66. package/lib/common/layout/selection/layout-selection-items.d.ts +3 -0
  67. package/lib/common/layout/selection/layout-selection-items.js +5 -0
  68. package/lib/common/layout-engine/selection/selection-formatter.js +7 -3
  69. package/lib/common/layout-formatter/box/generator/box-infos-generator.js +8 -4
  70. package/lib/common/model/sub-document.d.ts +18 -0
  71. package/lib/common/model/sub-document.js +71 -22
  72. package/lib/common/rich-edit-core.d.ts +3 -0
  73. package/lib/common/rich-edit-core.js +18 -0
  74. package/lib/common/screen-reader-manager.d.ts +48 -0
  75. package/lib/common/screen-reader-manager.js +326 -0
  76. package/lib/common/string-resources.d.ts +23 -0
  77. package/lib/common/string-resources.js +43 -0
  78. package/lib/common/utils/interval-utils.d.ts +4 -0
  79. package/lib/common/utils/interval-utils.js +25 -0
  80. package/package.json +3 -3
@@ -29,9 +29,12 @@ import { RichEditClientCommand } from '../../commands/client-command';
29
29
  import { ZoomLevelChange } from '../../model/changes/model/zoom-level';
30
30
  import { ModelChangeType } from '../../model/changes/enums';
31
31
  import { MixedSize } from '../../../common/utils/mixed-size';
32
+ import { IntervalAlgorithms } from '@devexpress/utils/lib/intervals/algorithms';
33
+ import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed';
32
34
  export class ViewManager {
33
35
  get renderer() { return this.renderers[this.innerClientProperties.viewsSettings.viewType]; }
34
36
  get printLayoutRenderer() { return this.renderers[ViewType.PrintLayout]; }
37
+ get isSimpleView() { return this.innerClientProperties.viewsSettings.isSimpleView; }
35
38
  get canvasListener() { return this.canvasListeners[this.innerClientProperties.viewsSettings.viewType]; }
36
39
  constructor(control, canvas, eventManager, stringResources, horizontalRuler, inputController, innerClientProperties, readOnlyPropertyHolder, layoutFormatterManagerHolder, internalApi, fieldOptions) {
37
40
  this.cache = [];
@@ -79,11 +82,11 @@ export class ViewManager {
79
82
  }
80
83
  adjust(force) {
81
84
  if ((force || !this.sizes.isInitialized()) && this.cache.length > 0) {
82
- const firstRenderedPageIndex = Math.min(this.cache.length, Math.max(0, ListUtils.indexBy(this.layout.pages, (page) => page.flags.get(LayoutPageFlags.ContentRendered))));
85
+ const firstRenderedPageIndex = Math.min(this.cache.length - 1, Math.max(0, this.layout.pages.findIndex((page) => page.flags.get(LayoutPageFlags.ContentRendered))));
83
86
  this.sizes.initialize(this.cache[firstRenderedPageIndex].page, this.canvas);
84
87
  const oldPageIndo = this.innerClientProperties.viewsSettings.pageVerticalInfo.clone();
85
88
  this.innerClientProperties.viewsSettings.pageVerticalInfo.copyFrom(this.sizes.pageVerticalInfo);
86
- if (this.innerClientProperties.viewsSettings.isSimpleView && !this.innerClientProperties.viewsSettings.pageVerticalInfo.equals(oldPageIndo)) {
89
+ if (this.isSimpleView && !this.innerClientProperties.viewsSettings.pageVerticalInfo.equals(oldPageIndo)) {
87
90
  const page = this.layout.pages[firstRenderedPageIndex];
88
91
  if (this.layoutFormatterManagerHolder.layoutFormatterManager && page)
89
92
  this.layoutFormatterManagerHolder.layoutFormatterManager.invalidator.onChangedAllLayout();
@@ -104,11 +107,18 @@ export class ViewManager {
104
107
  NotifySelectionLayoutChanged() {
105
108
  const layoutSelection = this.selection.layoutSelection;
106
109
  this.changeActiveSubDocumentRenderer.update(layoutSelection);
107
- Log.print(LogSource.CanvasManager, "onSelectionLayoutChanged\n", LogListHelper.level_1(Log.w(2, Log.flip(LogObjToStrLayout.pageSelectionChange, 0, 1))(""), this.selection.layoutSelection.selectionInfo.changes, "", "\n"));
108
- if (this.innerClientProperties.viewsSettings.isSimpleView)
110
+ Log.print(LogSource.CanvasManager, "onSelectionLayoutChanged\n", LogListHelper.level_1(Log.w(2, Log.flip(LogObjToStrLayout.pageSelectionChange, 0, 1))(""), layoutSelection.selectionInfo.changes, "", "\n"));
111
+ const shouldUpdateSelectedContent = this.renderer.updateForcedColorsModeState();
112
+ if (shouldUpdateSelectedContent) {
113
+ const intervals = this.getSelectionIntervalsForPageChange();
114
+ this.updateSelectedContent(layoutSelection.selectionInfo, intervals, layoutSelection.subDocumentInfo.isMain);
115
+ }
116
+ if (this.isSimpleView) {
109
117
  this.selection.renderAllPageSelection(this.layout, 0, true);
110
- else
118
+ }
119
+ else {
111
120
  this.selection.applySelectionChanges(this.layout);
121
+ }
112
122
  const pageIndex = ListUtils.reverseIndexBy(layoutSelection.selectionInfo.pageInfos, pageInfo => pageInfo.oldItems.length > 0);
113
123
  if (pageIndex > -1) {
114
124
  const pageInfo = layoutSelection.selectionInfo.pageInfos[pageIndex];
@@ -128,18 +138,35 @@ export class ViewManager {
128
138
  }
129
139
  NotifyMisspelledSelectionLayoutChanged() {
130
140
  Log.print(LogSource.CanvasManager, "onMisspelledSelectionLayoutChanged\n", LogListHelper.level_1(Log.w(2, Log.flip(LogObjToStrLayout.pageSelectionChange, 0, 1))(""), this.selection.layoutSelection.misspelledInfo.changes, "", "\n"));
131
- if (this.innerClientProperties.viewsSettings.isSimpleView)
141
+ if (this.isSimpleView)
132
142
  this.misspelledSelection.renderAllPageSelection(this.layout, 0, true);
133
143
  else
134
144
  this.misspelledSelection.applySelectionChanges(this.layout);
135
145
  }
136
146
  NotifyRangePermissionLayoutChanged() {
137
147
  Log.print(LogSource.CanvasManager, "onRangePermissionsLayoutChanged\n", LogListHelper.level_1(Log.w(2, Log.flip(LogObjToStrLayout.pageSelectionChange, 0, 1))(""), this.selection.layoutSelection.rangePermissionInfo.changes, "", "\n"));
138
- if (this.innerClientProperties.viewsSettings.isSimpleView)
148
+ if (this.isSimpleView)
139
149
  this.rangePermission.renderAllPageSelection(this.layout, 0, true);
140
150
  else
141
151
  this.rangePermission.applySelectionChanges(this.layout);
142
152
  }
153
+ updateSelectedContent(selectionInfo, intervals, isMain) {
154
+ const pageIndexes = this.isSimpleView ? [0] : selectionInfo.changes.map((pageChange) => pageChange.index);
155
+ pageIndexes.forEach((pageIndex) => this.renderer.updateSelectedIntervalsPageChanges(this.layout.pages[pageIndex], pageIndex, intervals, isMain));
156
+ }
157
+ getSelectionIntervalsForPageChange() {
158
+ const selection = this.control.selection;
159
+ if (!selection)
160
+ return [];
161
+ const affectedIntervals = [];
162
+ for (const state of [selection.prevState, selection.currState]) {
163
+ state.intervalsInfo.intervals.forEach((interval) => {
164
+ if (interval.length > 0)
165
+ affectedIntervals.push(new FixedInterval(interval.start, interval.length));
166
+ });
167
+ }
168
+ return IntervalAlgorithms.getMergedIntervals(affectedIntervals, true);
169
+ }
143
170
  addTopLevelContainers() {
144
171
  this.pagesContainer = DocumentRenderer.renderContainer(RendererClassNames.PAGES);
145
172
  this.pagesContainer.style.zoom = this.zoomLevel.toString();
@@ -22,6 +22,8 @@ export declare abstract class CommandManager implements ISelectionChangesListene
22
22
  dispose(): void;
23
23
  abortClipboardCommandExecution(): void;
24
24
  getCommand(key: RichEditClientCommand): ICommand;
25
+ getExecutingCommandsChainDebug(): string[];
26
+ getLastCommandsChainDebug(): string[];
25
27
  beforeExecuting(command: ICommand): void;
26
28
  afterExecuting(): void;
27
29
  assertLastExecutedCommandsChain(checkLength: boolean, ...types: Function[]): boolean;
@@ -579,6 +579,12 @@ export class CommandManager {
579
579
  getCommand(key) {
580
580
  return this.commands[key];
581
581
  }
582
+ getExecutingCommandsChainDebug() {
583
+ return this.executingCommandsChain.map(command => command?.constructor?.name || 'UnknownCommand');
584
+ }
585
+ getLastCommandsChainDebug() {
586
+ return this.lastCommandsChain.map(command => command?.constructor?.name || 'UnknownCommand');
587
+ }
582
588
  beforeExecuting(command) {
583
589
  this.executingCommandsChain.push(command);
584
590
  this.executingCommandCounter++;
@@ -280,7 +280,7 @@ export class NumberingListFormPreviewHelper {
280
280
  layoutRow.width = layoutNumberingListBox.textBox.width + layoutTextBox.width;
281
281
  layoutRow.x = isMultiLevel ? UnitConverter.twipsToPixels(paragraphProperties.leftIndent - paragraphProperties.firstLineIndent) + margin : margin;
282
282
  layoutRow.y = index * layoutRow.height + margin;
283
- return this.richEdit.viewManager.renderer.renderRow(layoutRow, 0);
283
+ return this.richEdit.viewManager.renderer.renderRow(layoutRow, 0, 0);
284
284
  }
285
285
  getNumberingListBoxText(levelIndex, majorIndex) {
286
286
  const items = [];
@@ -16,7 +16,8 @@ export class ChangeViewTypeCommand extends CommandBase {
16
16
  return true;
17
17
  }
18
18
  executeCore(_state, options) {
19
- if (this.control.innerClientProperties.viewsSettings.viewType != options.param) {
19
+ const currentViewType = this.control.innerClientProperties.viewsSettings.viewType;
20
+ if (currentViewType != options.param) {
20
21
  if (this.selection.activeSubDocument.isHeaderFooter())
21
22
  this.control.commandManager.getCommand(RichEditClientCommand.ChangeActiveSubDocumentToMain)
22
23
  .execute(this.control.commandManager.isPublicApiCall, new CommandOptions(this.control));
@@ -1,9 +1,8 @@
1
- import { CommandBase, ICommandOptions } from '../command-base';
1
+ import { ICommandOptions } from '../command-base';
2
2
  import { SimpleCommandState } from '../command-states';
3
- export declare class GoToNextWordCommandBase extends CommandBase<SimpleCommandState> {
4
- getState(): SimpleCommandState;
3
+ import { SelectionCommandBase } from './selection-command-base';
4
+ export declare class GoToNextWordCommandBase extends SelectionCommandBase {
5
5
  getStartPosition(): number;
6
- isEnabledInReadOnlyMode(): boolean;
7
6
  }
8
7
  export declare class GoToNextWordCommand extends GoToNextWordCommandBase {
9
8
  executeCore(_state: SimpleCommandState, _options: ICommandOptions): boolean;
@@ -1,18 +1,11 @@
1
1
  import { LayoutWordBounds } from '../../word-bounds-engine/layout-word-bounds';
2
- import { CommandBase } from '../command-base';
3
- import { SimpleCommandState } from '../command-states';
4
2
  import { ExtendGoToNextCharacterCommand } from './go-to-next-character-command';
5
- export class GoToNextWordCommandBase extends CommandBase {
6
- getState() {
7
- return new SimpleCommandState(this.isEnabled());
8
- }
3
+ import { SelectionCommandBase } from './selection-command-base';
4
+ export class GoToNextWordCommandBase extends SelectionCommandBase {
9
5
  getStartPosition() {
10
6
  var selection = this.selection;
11
7
  return selection.forwardDirection ? selection.lastSelectedInterval.end : selection.lastSelectedInterval.start;
12
8
  }
13
- isEnabledInReadOnlyMode() {
14
- return true;
15
- }
16
9
  }
17
10
  export class GoToNextWordCommand extends GoToNextWordCommandBase {
18
11
  executeCore(_state, _options) {
@@ -1,6 +1,7 @@
1
- import { CommandBase, ICommandOptions } from '../command-base';
1
+ import { ICommandOptions } from '../command-base';
2
2
  import { SimpleCommandState } from '../command-states';
3
- export declare abstract class GoToPrevWordCommandBase extends CommandBase<SimpleCommandState> {
3
+ import { SelectionCommandBase } from './selection-command-base';
4
+ export declare abstract class GoToPrevWordCommandBase extends SelectionCommandBase {
4
5
  getState(): SimpleCommandState;
5
6
  getStartPosition(): number;
6
7
  isEnabledInReadOnlyMode(): boolean;
@@ -1,10 +1,10 @@
1
1
  import { LayoutPositionCreatorConflictFlags, LayoutPositionMainSubDocumentCreator, LayoutPositionOtherSubDocumentCreator } from '../../layout-engine/layout-position-creator';
2
2
  import { DocumentLayoutDetailsLevel } from '../../layout/document-layout-details-level';
3
3
  import { LayoutWordBounds } from '../../word-bounds-engine/layout-word-bounds';
4
- import { CommandBase } from '../command-base';
5
4
  import { SimpleCommandState } from '../command-states';
6
5
  import { ExtendGoToPrevCharacterCommand } from './go-to-prev-character-command';
7
- export class GoToPrevWordCommandBase extends CommandBase {
6
+ import { SelectionCommandBase } from './selection-command-base';
7
+ export class GoToPrevWordCommandBase extends SelectionCommandBase {
8
8
  getState() {
9
9
  return new SimpleCommandState(this.isEnabled());
10
10
  }
@@ -3,5 +3,7 @@ import { SimpleCommandState } from '../command-states';
3
3
  export declare class SelectAllDocumentCommand extends CommandBase<SimpleCommandState> {
4
4
  getState(): SimpleCommandState;
5
5
  executeCore(_state: SimpleCommandState, _options: ICommandOptions): boolean;
6
+ protected beforeExecute(): void;
7
+ protected afterExecute(): void;
6
8
  isEnabledInReadOnlyMode(): boolean;
7
9
  }
@@ -12,6 +12,12 @@ export class SelectAllDocumentCommand extends CommandBase {
12
12
  this.control.focusManager.captureFocus();
13
13
  return true;
14
14
  }
15
+ beforeExecute() {
16
+ this.control.screenReaderManager.beginExecute(this.commandId);
17
+ }
18
+ afterExecute() {
19
+ this.control.screenReaderManager.endExecute();
20
+ }
15
21
  isEnabledInReadOnlyMode() {
16
22
  return true;
17
23
  }
@@ -8,4 +8,6 @@ export declare class SelectionCommandBase extends CommandBase<SimpleCommandState
8
8
  protected shouldCollapseSingleCellTableSelection(entryDirection: TableNavDirection, shrinkDirection: TableNavDirection): boolean;
9
9
  protected collapseSingleCellTableSelectionToCaret(): boolean;
10
10
  protected collapseTableCellSelectionSpatialFocus(direction: TableNavDirection): boolean;
11
+ beforeExecute(): void;
12
+ afterExecute(): void;
11
13
  }
@@ -98,4 +98,12 @@ export class SelectionCommandBase extends CommandBase {
98
98
  selection.deprecatedSetSelection(pos, pos, false, -1, true);
99
99
  return true;
100
100
  }
101
+ beforeExecute() {
102
+ super.beforeExecute();
103
+ this.control.screenReaderManager.beginExecute(this.commandId);
104
+ }
105
+ afterExecute() {
106
+ super.afterExecute();
107
+ this.control.screenReaderManager.endExecute();
108
+ }
101
109
  }
@@ -54,18 +54,12 @@ export class EventManager {
54
54
  clearTimeout(this.onMouseUpTimerId);
55
55
  }
56
56
  onShortcut(shortcutCode) {
57
- this.control.beginUpdate();
58
- try {
59
- if (this.accumulatedText.length)
60
- this.insertFunc();
61
- this.control.shortcutManager.processShortcut(shortcutCode);
62
- this.mouseHandler.onShortcut(shortcutCode);
63
- if (EnumUtils.isAnyOf(shortcutCode, KeyCode.Enter, KeyCode.Tab, KeyCode.Space) && this.control.selection.lastSelectedInterval.start > 0)
64
- this.control.autoCorrectService.performAutoCorrect();
65
- }
66
- finally {
67
- this.control.endUpdate();
68
- }
57
+ if (this.accumulatedText.length)
58
+ this.insertFunc();
59
+ this.control.shortcutManager.processShortcut(shortcutCode);
60
+ this.mouseHandler.onShortcut(shortcutCode);
61
+ if (EnumUtils.isAnyOf(shortcutCode, KeyCode.Enter, KeyCode.Tab, KeyCode.Space) && this.control.selection.lastSelectedInterval.start > 0)
62
+ this.control.autoCorrectService.performAutoCorrect();
69
63
  }
70
64
  onMouseDown(evt) {
71
65
  Log.print(LogSource.EventManager, "onMouseDown", LogObjToStrCanvas.richMouseEvent(evt));
@@ -22,7 +22,7 @@ export class TxtExporter {
22
22
  this.model.mainSubDocument.paragraphs.forEach((p, index) => {
23
23
  if (index > 0)
24
24
  text += '\r\n';
25
- text += this.model.mainSubDocument.getSimpleText(new FixedInterval(p.startLogPosition.value, p.length));
25
+ text += this.model.mainSubDocument.getSimpleText(new FixedInterval(p.startLogPosition.value, p.length - 1));
26
26
  });
27
27
  callback(new Blob([text], { type: PlainTextMimeType }));
28
28
  });
@@ -91,6 +91,7 @@ export class InputEditorBase {
91
91
  createHierarchy(parent) {
92
92
  this.inputElement = this.createInputElement();
93
93
  this.inputElement.classList.add(INPUT_CLASS_NAME);
94
+ this.inputElement.setAttribute('aria-hidden', 'true');
94
95
  parent.appendChild(this.inputElement);
95
96
  this.createHierarchyCore();
96
97
  this.inputElement.addEventListener("load", () => this.recreateIfNeeded(), true);
@@ -585,6 +586,7 @@ export class IFrameInputEditor extends InputEditorBase {
585
586
  }
586
587
  createInputElement() {
587
588
  const element = document.createElement("IFRAME");
589
+ element.setAttribute("aria-hidden", "true");
588
590
  element.src = "about:blank";
589
591
  if (Browser.Safari) {
590
592
  element.style.width = "100%";
@@ -38,6 +38,7 @@ import { SearchManager } from '../ui/search-manager';
38
38
  import { IControlOwner } from './i-control-owner';
39
39
  import { IExportModelOptions } from '../formats/i-document-exporter';
40
40
  import { ModelScrollManager } from '../scroll/model-scroll-manager';
41
+ import { ScreenReaderManager } from '../screen-reader-manager';
41
42
  export interface IBarListener extends IEventListener {
42
43
  NotifyBarCommandExecuted(commandID: RichEditClientCommand, parameter: any): any;
43
44
  NotifyBarUpdateRequested(): any;
@@ -86,6 +87,7 @@ export interface IRichEditControl extends IBatchUpdatableObject, IDisposable, IR
86
87
  owner: IControlOwner;
87
88
  selectionModelChangesListener: SelectionModelChangesListener;
88
89
  pdfHelperFrame: PdfHelperFrame;
90
+ screenReaderManager: ScreenReaderManager;
89
91
  getExportModelOptions(initOptions?: Partial<IExportModelOptions>): IExportModelOptions;
90
92
  isClientMode(): boolean;
91
93
  createFieldRequestManager(): FieldRequestManager;
@@ -42,7 +42,7 @@ export class LayoutBox extends Rectangle {
42
42
  this.colorInfo.equals(obj.colorInfo) &&
43
43
  this.rowOffset == obj.rowOffset &&
44
44
  this.hyperlinkTip == obj.hyperlinkTip &&
45
- this.fieldLevel == this.fieldLevel;
45
+ this.fieldLevel == obj.fieldLevel;
46
46
  }
47
47
  copyFrom(obj) {
48
48
  super.copyFrom(obj);
@@ -8,6 +8,7 @@ export declare class LayoutColumn extends Rectangle {
8
8
  paragraphFrames: ParagraphFrame[];
9
9
  tablesInfo: LayoutTableColumnInfo[];
10
10
  constructor();
11
+ getStartPosition(): number;
11
12
  getEndPosition(): number;
12
13
  getLastRow(): LayoutRow;
13
14
  static findSectionColumnWithMinimumWidth(columnBounds: Rectangle[]): number;
@@ -7,6 +7,9 @@ export class LayoutColumn extends Rectangle {
7
7
  this.paragraphFrames = [];
8
8
  this.tablesInfo = [];
9
9
  }
10
+ getStartPosition() {
11
+ return this.pageAreaOffset + this.rows[0].getStartPosition();
12
+ }
10
13
  getEndPosition() {
11
14
  return this.pageAreaOffset + ListUtils.last(this.rows).getEndPosition();
12
15
  }
@@ -36,3 +36,6 @@ export declare class LayoutSelectionFloatingObjectItem extends LayoutSelectionIt
36
36
  get zIndexClassType(): zIndexCssClassType;
37
37
  get baseClassName(): string;
38
38
  }
39
+ export declare class LayoutSelectionPictureItem extends LayoutSelectionItem {
40
+ get baseClassName(): string;
41
+ }
@@ -73,3 +73,8 @@ export class LayoutSelectionFloatingObjectItem extends LayoutSelectionItem {
73
73
  return [RendererClassNames.SELECTION_ROW, RendererClassNames.SELECTION_FLOATING_OBJECTS].join(" ");
74
74
  }
75
75
  }
76
+ export class LayoutSelectionPictureItem extends LayoutSelectionItem {
77
+ get baseClassName() {
78
+ return [RendererClassNames.SELECTION_ROW, RendererClassNames.SELECTION_PICTURE_ROW].join(" ");
79
+ }
80
+ }
@@ -7,7 +7,7 @@ import { LayoutChangeType } from '../../layout-formatter/changes/changes/layout-
7
7
  import { LayoutPageSelectionChange } from '../../layout-formatter/changes/changes/selection/layout-page-selection-change';
8
8
  import { DocumentLayoutDetailsLevel } from '../../layout/document-layout-details-level';
9
9
  import { LayoutBoxType } from '../../layout/main-structures/layout-boxes/layout-box';
10
- import { LayoutRangePermissionItem, LayoutSelectionCursorItem, LayoutSelectionFloatingObjectItem, LayoutSelectionItem, LayoutSelectionMisspelledItem, LayoutSelectionSearchItem } from '../../layout/selection/layout-selection-items';
10
+ import { LayoutRangePermissionItem, LayoutSelectionCursorItem, LayoutSelectionFloatingObjectItem, LayoutSelectionItem, LayoutSelectionMisspelledItem, LayoutSelectionPictureItem, LayoutSelectionSearchItem } from '../../layout/selection/layout-selection-items';
11
11
  import { TableCellBoundFlags } from '../../layout/table/layout-table-cell-info';
12
12
  import { ModelChangeType } from '../../model/changes/enums';
13
13
  import { CharacterFormattingScript } from '../../model/character/enums';
@@ -285,6 +285,7 @@ export class SelectionFormatter extends BatchUpdatableObject {
285
285
  throw new Error(Errors.InternalException);
286
286
  let currentLayoutRow = null;
287
287
  let currSelectionItem = null;
288
+ let wasPreviousBoxPicture = false;
288
289
  const selectedCellsCollector = new SelectedCellsCollector();
289
290
  let currPageIndex = -1;
290
291
  for (let isFirstBox = true; iterator.moveNext(new LayoutPositionCreatorConflictFlags().setDefault(!isFirstBox), new LayoutPositionCreatorConflictFlags().setDefault(true)); isFirstBox = false) {
@@ -324,15 +325,18 @@ export class SelectionFormatter extends BatchUpdatableObject {
324
325
  const absRowOffsetX = currPosition.pageArea.x + currPosition.column.x + currPosition.row.x;
325
326
  const absBoxOffsetX = currPosition.box.x + currentBoxLeftOffsetX + absRowOffsetX;
326
327
  const thereIsGap = !!currSelectionItem && !MathUtils.numberCloseTo(absBoxOffsetX, currSelectionItem.x + currSelectionItem.width);
327
- const isNeedCreateNewSelectionRow = row !== currentLayoutRow || thereIsGap;
328
+ const isPictureBox = currPosition.box.getType() === LayoutBoxType.Picture;
329
+ const isNeedCreateNewSelectionRow = row !== currentLayoutRow || thereIsGap || isPictureBox || wasPreviousBoxPicture;
328
330
  if (isNeedCreateNewSelectionRow) {
329
331
  currentLayoutRow = row;
330
332
  const floatingObjectId = SelectionFormatter.getFloatingObjId(activeSubDocument, currPosition.page);
331
- currSelectionItem = LayoutSelectionItem.create(currPosition, new Size(0, row.height), floatingObjectId, LayoutSelectionItem);
333
+ const itemCtor = isPictureBox ? LayoutSelectionPictureItem : LayoutSelectionItem;
334
+ currSelectionItem = LayoutSelectionItem.create(currPosition, new Size(0, row.height), floatingObjectId, itemCtor);
332
335
  currSelectionItem.x += currPosition.box.x + currentBoxLeftOffsetX;
333
336
  layoutSelectionInfo.registerItem(currPosition.pageIndex, currSelectionItem);
334
337
  }
335
338
  currSelectionItem.width += currentBoxRightOffsetX - currentBoxLeftOffsetX;
339
+ wasPreviousBoxPicture = isPictureBox;
336
340
  }
337
341
  }
338
342
  static isCellFullySelected(cell, allIntervals) {
@@ -405,10 +405,14 @@ export class BoxGenerator {
405
405
  const word = this.modelIterator.getRunText(currRunTextStart, currBoxLength);
406
406
  currRunTextStart += currBoxLength;
407
407
  const charProps = this.getActualCharacterProperties();
408
- if (this.currBoxInfoType == LayoutBoxType.Text)
409
- this.addNewBoxInfo(new LayoutTextBox(charProps, charProps.getLayoutColorInfo(this.colorProvider), word), currRunTextStart);
410
- else
411
- this.addNewBoxInfo(new LayoutDashBox(charProps, charProps.getLayoutColorInfo(this.colorProvider), word), currRunTextStart);
408
+ if (this.currBoxInfoType == LayoutBoxType.Text) {
409
+ const newBox = new LayoutTextBox(charProps, charProps.getLayoutColorInfo(this.colorProvider), word);
410
+ this.addNewBoxInfo(newBox, currRunTextStart);
411
+ }
412
+ else {
413
+ const newBox = new LayoutDashBox(charProps, charProps.getLayoutColorInfo(this.colorProvider), word);
414
+ this.addNewBoxInfo(newBox, currRunTextStart);
415
+ }
412
416
  } while (currRunTextStart < this.modelIterator.charOffset);
413
417
  }
414
418
  this.currBoxInfoType = LayoutBoxType.Text;
@@ -44,6 +44,9 @@ export declare class SubDocument {
44
44
  getFirstParagraph(): Paragraph;
45
45
  getText(interval?: FixedInterval): string;
46
46
  getSimpleText(interval: ConstInterval): string;
47
+ getVisibleText(interval: ConstInterval, options?: IGetTextOptions): string;
48
+ private resolveChar;
49
+ private isPositionVisible;
47
50
  splitRun(position: number): void;
48
51
  getLastRun(): RunBase;
49
52
  getFirstRun(): RunBase;
@@ -123,3 +126,18 @@ export declare class SubDocumentIntervals implements ISubDocumentIntervals {
123
126
  equals(obj: SubDocumentIntervals): boolean;
124
127
  static fromPosition(subDocument: SubDocument, pos: number): SubDocumentIntervals;
125
128
  }
129
+ export declare enum TransformAction {
130
+ InsertBefore = 0,
131
+ Replace = 1,
132
+ InsertAfter = 2
133
+ }
134
+ export interface IGetTextOptions {
135
+ charMap?: Record<string, string>;
136
+ includeNumberedListMarks?: boolean;
137
+ forceFieldResultText?: boolean;
138
+ transform?: (info: FullChunkAndRunInfo, fieldIndexes: number[]) => ITransformResult | string | null;
139
+ }
140
+ export interface ITransformResult {
141
+ text?: string | null;
142
+ action: TransformAction;
143
+ }
@@ -5,13 +5,14 @@ import { SearchUtils } from '@devexpress/utils/lib/utils/search';
5
5
  import { SpellCheckerIntervalsManager } from '../spelling/intervals-manager';
6
6
  import { RunIterator } from './character/run-iterator';
7
7
  import { ResetFormattingCacheType } from './document-model';
8
- import { Field } from './fields/field';
9
8
  import { FullChunkAndRunInfo } from './full-chunk-and-run-info';
10
9
  import { BookmarksManipulator } from './manipulators/bookmarks-manipulator';
11
10
  import { ModelIterator } from './model-iterator';
12
11
  import { PositionManager } from './position/position-manager';
13
12
  import { RichUtils } from './rich-utils';
14
13
  import { RunType } from './runs/run-type';
14
+ import { ParagraphIterator } from '../layout-formatter/box/generator/one-dimension-itertors';
15
+ import { FieldIterator } from '../layout-formatter/box/generator/recursive-objects-iterators';
15
16
  export class SubDocument {
16
17
  static { this.AUTOGENERATE_ID = -1; }
17
18
  static { this.MAIN_SUBDOCUMENT_ID = 0; }
@@ -63,36 +64,78 @@ export class SubDocument {
63
64
  return buffer;
64
65
  }
65
66
  getSimpleText(interval) {
66
- let result = "";
67
+ return this.getVisibleText(interval, {
68
+ forceFieldResultText: true,
69
+ charMap: {
70
+ [RichUtils.specialCharacters.LineBreak]: ' ',
71
+ [RichUtils.specialCharacters.SectionMark]: '\r\n',
72
+ [RichUtils.specialCharacters.ParagraphMark]: '\r\n'
73
+ }
74
+ });
75
+ }
76
+ getVisibleText(interval, options = {}) {
77
+ let result = [];
67
78
  let pos = interval.start;
68
- let nested = 0;
69
- const fieldIndex = Field.normedBinaryIndexOf(this.fields, pos);
70
- if (fieldIndex > -1) {
71
- let field = this.fields[fieldIndex];
72
- while (field.parent)
73
- field = field.parent;
74
- pos = field.getFieldStartPosition();
75
- }
79
+ const { charMap = {}, forceFieldResultText = false, includeNumberedListMarks = false, transform } = options;
76
80
  const iterator = new ModelIterator(this, true);
77
81
  iterator.setPosition(pos);
82
+ const fieldIterator = new FieldIterator(this.fields);
83
+ fieldIterator.init(pos);
84
+ const paragraphIterator = new ParagraphIterator(this.paragraphs);
85
+ paragraphIterator.init(pos);
78
86
  while (pos < interval.end) {
79
- switch (iterator.run.getType()) {
80
- case RunType.FieldCodeStartRun:
81
- nested++;
82
- break;
83
- case RunType.FieldCodeEndRun:
84
- nested--;
85
- break;
86
- case RunType.TextRun:
87
- if (pos >= interval.start && nested == 0)
88
- result += iterator.getCurrentChar();
87
+ if (this.isPositionVisible(pos, fieldIterator.indexes, forceFieldResultText)) {
88
+ const paragraph = this.paragraphs[paragraphIterator.index];
89
+ if (includeNumberedListMarks && pos === paragraph.startLogPosition.value && paragraph.isInList())
90
+ result.push(paragraph.getNumberingListText() + paragraph.getNumberingListSeparatorChar());
91
+ const transformResult = transform?.(iterator, fieldIterator.indexes);
92
+ if (transformResult != null) {
93
+ if (typeof transformResult === "string")
94
+ result.push(transformResult);
95
+ else if (transformResult.text != null) {
96
+ if (transformResult.action === TransformAction.InsertAfter)
97
+ this.resolveChar(iterator, result, charMap);
98
+ result.push(transformResult.text);
99
+ if (transformResult.action === TransformAction.InsertBefore)
100
+ this.resolveChar(iterator, result, charMap);
101
+ }
102
+ }
103
+ else
104
+ this.resolveChar(iterator, result, charMap);
105
+ if (!iterator.moveToNextChar())
89
106
  break;
90
107
  }
91
- if (!iterator.moveToNextChar())
108
+ else if (!iterator.moveToNextRun())
92
109
  break;
93
110
  pos = iterator.getAbsolutePosition();
111
+ paragraphIterator.update(pos);
112
+ fieldIterator.update(pos);
113
+ }
114
+ return result.join("");
115
+ }
116
+ resolveChar(iterator, result, charMap) {
117
+ switch (iterator.run.getType()) {
118
+ case RunType.SectionRun:
119
+ case RunType.ParagraphRun:
120
+ case RunType.FieldCodeStartRun:
121
+ case RunType.FieldCodeEndRun:
122
+ case RunType.TextRun:
123
+ const char = iterator.getCurrentChar();
124
+ result.push(charMap[char] ?? char);
125
+ break;
126
+ }
127
+ }
128
+ isPositionVisible(pos, fieldIndexes, forceFieldResultText) {
129
+ for (const index of fieldIndexes) {
130
+ const field = this.fields[index];
131
+ const isCodeView = !forceFieldResultText && field.showCode;
132
+ const invisibleInterval = isCodeView
133
+ ? field.getResultIntervalWithBorders()
134
+ : field.getCodeIntervalWithBorders();
135
+ if (invisibleInterval.contains(pos))
136
+ return false;
94
137
  }
95
- return result.replace(RichUtils.specialCharacters.LineBreak, " ");
138
+ return true;
96
139
  }
97
140
  splitRun(position) {
98
141
  var info = this.getRunAndIndexesByPosition(position);
@@ -466,6 +509,12 @@ export class SubDocumentIntervals {
466
509
  return new SubDocumentIntervals(subDocument, [new FixedInterval(pos, 0)]);
467
510
  }
468
511
  }
512
+ export var TransformAction;
513
+ (function (TransformAction) {
514
+ TransformAction[TransformAction["InsertBefore"] = 0] = "InsertBefore";
515
+ TransformAction[TransformAction["Replace"] = 1] = "Replace";
516
+ TransformAction[TransformAction["InsertAfter"] = 2] = "InsertAfter";
517
+ })(TransformAction || (TransformAction = {}));
469
518
  function internalValidateInterval(subDocument, interval) {
470
519
  const documentEndPosition = subDocument.getDocumentEndPosition();
471
520
  if (interval.start == 0 && interval.end == documentEndPosition)
@@ -38,6 +38,7 @@ import { RulerSettings } from './ui/ruler/settings';
38
38
  import { SearchManager } from './ui/search-manager';
39
39
  import { IExportModelOptions } from './formats/i-document-exporter';
40
40
  import { ModelScrollManager } from './scroll/model-scroll-manager';
41
+ import { ScreenReaderManager } from './screen-reader-manager';
41
42
  export declare abstract class RichEditCore implements IRichEditControl {
42
43
  modelManager: IModelManager;
43
44
  barHolder: IBarHolder;
@@ -71,6 +72,7 @@ export declare abstract class RichEditCore implements IRichEditControl {
71
72
  owner: IControlOwner;
72
73
  selectionModelChangesListener: SelectionModelChangesListener;
73
74
  readonly pdfHelperFrame: PdfHelperFrame;
75
+ screenReaderManager: ScreenReaderManager;
74
76
  private closed;
75
77
  sessionGuid: string;
76
78
  private clientGuid;
@@ -119,6 +121,7 @@ export declare abstract class RichEditCore implements IRichEditControl {
119
121
  getExportModelOptions(initOptions?: Partial<IExportModelOptions>): IExportModelOptions;
120
122
  ensureDocumentIsFullyFormatted(): void;
121
123
  protected abstract createSpellChecker(): any;
124
+ protected createAriaLiveElement(element: HTMLElement): HTMLDivElement;
122
125
  protected createViewElement(id: string, element: HTMLElement): HTMLDivElement;
123
126
  private isUsedInnerClipboard;
124
127
  getExportDocumentFormat(): DocumentFormat;