devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
199 lines (198 loc) • 12.6 kB
JavaScript
import { LayoutBoxIteratorMainSubDocument } from '../../layout-engine/layout-box-iterator/layout-box-iterator-main-sub-document';
import { LayoutBoxIteratorOtherSubDocument } from '../../layout-engine/layout-box-iterator/layout-box-iterator-other-sub-document';
import { LayoutPositionCreatorConflictFlags, LayoutPositionMainSubDocumentCreator, LayoutPositionOtherSubDocumentCreator } from '../../layout-engine/layout-position-creator';
import { DocumentLayoutDetailsLevel } from '../../layout/document-layout-details-level';
import { ModelIterator } from '../../model/model-iterator';
import { ControlOptions } from '../../model/options/control';
import { RunType } from '../../model/runs/run-type';
import { TablePosition } from '../../model/tables/main-structures/table';
import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed';
import { EnumUtils } from '@devexpress/utils/lib/utils/enum';
import { ListUtils } from '@devexpress/utils/lib/utils/list';
import { SetSelectionParams } from '../../selection/set-selection-params';
import { RichEditClientCommand } from '../client-command';
import { CommandBase } from '../command-base';
import { SimpleCommandState } from '../command-states';
import { ChangeIndentCommandBase } from '../paragraph-properties/change-indent-command';
import { ChangeParagraphIndentFromFirstRowCommandBase } from '../paragraph-properties/change-paragraph-indent-from-first-row-command';
export class InsertTabCommandBase extends CommandBase {
getState() {
return new SimpleCommandState(this.isEnabled());
}
setNextObj(iter) {
do {
if (EnumUtils.isAnyOf(iter.run.getType(), RunType.InlinePictureRun, RunType.AnchoredPictureRun, RunType.AnchoredTextBoxRun))
return true;
} while (iter.moveToNextRun());
return false;
}
executeCore(_state, options) {
const specInfo = this.selection.specialRunInfo;
if (specInfo.isSelected() && (!specInfo.isTextBoxSelected() ||
this.selection.activeSubDocument.id == specInfo.getParentSubDocument().id)) {
const iter = new ModelIterator(this.selection.activeSubDocument, true);
iter.setPosition(specInfo.getPosition() + 1);
if (!this.setNextObj(iter)) {
iter.setPosition(0);
this.setNextObj(iter);
}
this.selection.setSelection(new SetSelectionParams().setInterval(new FixedInterval(iter.getAbsolutePosition(), 1)));
return true;
}
var interval = this.selection.lastSelectedInterval.clone();
var startParagraph = this.selection.activeSubDocument.getParagraphByPosition(interval.start);
var documentEndPosition = this.selection.activeSubDocument.getDocumentEndPosition();
if (interval.start >= documentEndPosition)
throw new Error("InsertTabCommandBase interval.start >= documentEndPosition");
if (interval.length > 0 && interval.end > documentEndPosition)
throw new Error("InsertTabCommandBase interval.end > documentEndPosition");
var subDocument = this.selection.activeSubDocument;
var startLayoutPosition = subDocument.isMain()
? LayoutPositionMainSubDocumentCreator.ensureLayoutPosition(this.control.layoutFormatterManager, subDocument, interval.start, DocumentLayoutDetailsLevel.Character, new LayoutPositionCreatorConflictFlags().setDefault(false), new LayoutPositionCreatorConflictFlags().setDefault(false))
: new LayoutPositionOtherSubDocumentCreator(this.control.layout, subDocument, interval.start, this.selection.pageIndex, DocumentLayoutDetailsLevel.Character)
.create(new LayoutPositionCreatorConflictFlags().setDefault(false), new LayoutPositionCreatorConflictFlags().setDefault(false));
if (this.addTableRowIfRequired(startLayoutPosition))
return true;
if (this.performCellIteratorActionIfRequired(startLayoutPosition, interval.start))
return true;
if (!this.control.commandManager.assertLastExecutedCommandsChain(true, InsertTabCommandBase)) {
if (startParagraph.getTabs().positions.length === 0) {
if (this.needProcessFirstParagraphRow(interval, startParagraph, startLayoutPosition)) {
if (startParagraph.isInList())
return this.createIndentNumberingParagraphCommand().execute(this.control.commandManager.isPublicApiCall);
return this.createChangeParagraphIndentFromFirstRowCommand().execute(this.control.commandManager.isPublicApiCall);
}
if (this.needProcessParagraphLeftIndent(interval, startLayoutPosition))
return this.createChangeIndentCommand().execute(this.control.commandManager.isPublicApiCall);
}
}
if (ControlOptions.isEnabled(this.control.modelManager.richOptions.control.tabSymbol))
this.insertTextWithSelection(options.intervalsInfo.subDocInterval, this.control.modelManager.richOptions.control.tabMarker);
return true;
}
addTableRowIfRequired(lp) {
const cellInfo = lp.row.tableCellInfo;
if (!cellInfo)
return false;
const rowInfo = cellInfo.parentRow;
const grid = rowInfo.parentTable.logicInfo.grid;
const info = grid.tableCellGridInfos[rowInfo.rowIndex][cellInfo.cellGridIndex];
const rowInd = info.getEndRowIndex();
const cellInd = info.getCellIndex(info.getNumRowsInCell() - 1);
const lastRow = ListUtils.last(grid.table.rows);
if (rowInd == grid.table.rows.length && cellInd == lastRow.cells.length - 1) {
this.control.commandManager.getCommand(RichEditClientCommand.InsertTableRowBelow)
.execute(this.control.commandManager.isPublicApiCall);
this.selection.setSelection(new SetSelectionParams()
.setPosition(this.selection.intervals[0].start)
.setEndOfLine(false));
return true;
}
return false;
}
needProcessFirstParagraphRow(interval, startParagraph, startLayoutPosition) {
if (this.control.commandManager.assertLastExecutedCommandsChain(false, InsertTabCommandBase, ChangeParagraphIndentFromFirstRowCommandBase) && this.isIntervalStartInParagraphStart(interval, startParagraph))
return true;
return this.isIntervalStartInParagraphStart(interval, startParagraph) && (interval.length === 0 || this.isIntervalEndOnRowEnd(interval, startLayoutPosition));
}
needProcessParagraphLeftIndent(interval, startLayoutPosition) {
if (this.control.commandManager.assertLastExecutedCommandsChain(false, InsertTabCommandBase, ChangeIndentCommandBase))
return true;
var subDocument = this.selection.activeSubDocument;
var endLayoutPosition = (subDocument.isMain()
? new LayoutPositionMainSubDocumentCreator(this.control.layout, subDocument, interval.end, DocumentLayoutDetailsLevel.Character)
: new LayoutPositionOtherSubDocumentCreator(this.control.layout, subDocument, interval.end, this.selection.pageIndex, DocumentLayoutDetailsLevel.Character))
.create(new LayoutPositionCreatorConflictFlags().setDefault(true), new LayoutPositionCreatorConflictFlags().setDefault(false));
return startLayoutPosition && startLayoutPosition.isPositionBeforeFirstBoxInRow() && this.isIntervalIncludesWholeRow(startLayoutPosition, endLayoutPosition);
}
performCellIteratorActionIfRequired(startLayoutPosition, pos) {
const startCellInfo = startLayoutPosition.row.tableCellInfo;
if (!startCellInfo)
return false;
let boxIterator;
const startCellIndexes = this.getTablePos(startCellInfo);
while (true) {
boxIterator = this.getBoxIterator(pos, startCellInfo.parentRow.parentTable.getTopLevelColumn().logicInfo.grid.table.getEndPosition() + 1);
if (boxIterator && boxIterator.isInitialized())
break;
this.control.layoutFormatterManager.forceFormatPage(this.control.layout.validPageCount);
}
while (this.performCellIteratorAction(boxIterator)) {
const currIndexes = this.getTablePos(boxIterator.position.row.tableCellInfo);
if (!startCellIndexes.equals(currIndexes)) {
if (currIndexes &&
(startCellIndexes.table.index == currIndexes.table.index ||
currIndexes.table.nestedLevel > startCellIndexes.table.nestedLevel)) {
const grid = boxIterator.position.row.tableCellInfo.parentRow.parentTable.logicInfo.grid;
const cellStartPos = grid.table.rows[currIndexes.rowIndex].cells[currIndexes.cellIndex].startParagraphPosition.value;
this.selection.setSelection(new SetSelectionParams()
.setInterval(new FixedInterval(cellStartPos, 0))
.setEndOfLine(false));
}
break;
}
}
return true;
}
getTablePos(cellInfo) {
if (!cellInfo)
return null;
const rowInfo = cellInfo.parentRow;
const grid = rowInfo.parentTable.logicInfo.grid;
const info = grid.tableCellGridInfos[rowInfo.rowIndex][cellInfo.cellGridIndex];
return new TablePosition(grid.table, info.getStartRowIndex(), info.getCellIndex(0));
}
isIntervalStartInParagraphStart(interval, paragraph) {
return interval.start === paragraph.startLogPosition.value;
}
isIntervalEndOnRowEnd(interval, layoutPosition) {
if (!layoutPosition)
return false;
return layoutPosition.getRelatedSubDocumentPagePosition() + layoutPosition.pageArea.pageOffset + layoutPosition.column.pageAreaOffset + layoutPosition.row.getEndPosition() === interval.end;
}
isIntervalIncludesWholeRow(startLayoutPosition, endLayoutPosition) {
return !endLayoutPosition || endLayoutPosition.row !== startLayoutPosition.row || endLayoutPosition.isPositionAfterLastBoxInRow();
}
}
export class InsertTabCommand extends InsertTabCommandBase {
createIndentNumberingParagraphCommand() {
return this.control.commandManager.getCommand(RichEditClientCommand.IncrementNumberingIndent);
}
createChangeParagraphIndentFromFirstRowCommand() {
return this.control.commandManager.getCommand(RichEditClientCommand.IncrementParagraphIndentFromFirstRow);
}
createChangeIndentCommand() {
return this.control.commandManager.getCommand(RichEditClientCommand.IncreaseIndent);
}
performCellIteratorAction(boxIterator) {
return boxIterator.moveNext(new LayoutPositionCreatorConflictFlags().setDefault(false), new LayoutPositionCreatorConflictFlags().setDefault(true));
}
getBoxIterator(pos, endPos) {
const subDocument = this.selection.activeSubDocument;
const layout = this.control.layout;
return subDocument.isMain() ?
new LayoutBoxIteratorMainSubDocument(subDocument, layout, pos, endPos) :
new LayoutBoxIteratorOtherSubDocument(subDocument, layout, pos, endPos, this.selection.pageIndex);
}
}
export class InsertShiftTabCommand extends InsertTabCommandBase {
createIndentNumberingParagraphCommand() {
return this.control.commandManager.getCommand(RichEditClientCommand.DecrementNumberingIndent);
}
createChangeParagraphIndentFromFirstRowCommand() {
return this.control.commandManager.getCommand(RichEditClientCommand.DecrementParagraphIndentFromFirstRow);
}
createChangeIndentCommand() {
return this.control.commandManager.getCommand(RichEditClientCommand.DecreaseIndent);
}
performCellIteratorAction(boxIterator) {
return boxIterator.movePrev(new LayoutPositionCreatorConflictFlags().setDefault(true), new LayoutPositionCreatorConflictFlags().setDefault(true));
}
getBoxIterator(pos, _endPos) {
const subDocument = this.selection.activeSubDocument;
const layout = this.control.layout;
return subDocument.isMain() ?
new LayoutBoxIteratorMainSubDocument(subDocument, layout, 0, pos) :
new LayoutBoxIteratorOtherSubDocument(subDocument, layout, 0, pos, this.selection.pageIndex);
}
}