devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
151 lines (150 loc) • 12 kB
JavaScript
import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed';
import { ParagraphPropertiesHistoryItem } from '../../history/items/paragraph-properties-history-items';
import { TableCellBordersHistoryItem, TableCellColumnSpanHistoryItem, TableCellPreferredWidthHistoryItem, TableCellShadingInfoHistoryItem, TableCellVerticalAlignmentHistoryItem, TableCellVerticalMergingHistoryItem } from '../../history/items/tables/table-cell-properties-history-items';
import { SubDocumentInterval, SubDocumentPosition } from '../../sub-document';
import { TablePosition } from '../../tables/main-structures/table';
import { TableCellPropertiesMask } from '../../tables/properties/table-cell-properties';
import { TableCellMergingState } from '../../tables/secondary-structures/table-base-structures';
import { TableWidthUnit } from '../../tables/secondary-structures/table-units';
import { TableCellUtils } from '../../tables/table-utils';
import { InsertParagraphManipulatorParams } from '../paragraph-manipulator/insert-paragraph-manipulator-params';
export class MergeTableCellsOperationBase {
get modelManipulator() { return this.modelManager.modelManipulator; }
constructor(modelManager, subDocument) {
this.needDeleteNextTableCell = false;
this.modelManager = modelManager;
this.subDocument = subDocument;
}
execute(position, suppressNormalizeTableRows, inpPos) {
let nextCellPosition = this.calculateNextCell(position);
this.updateCellsProperties(position, nextCellPosition);
let nextCell = nextCellPosition.cell;
let cell = position.cell;
let isEmptyCell = this.isEmptyCell(cell);
let isEmptyNextCell = this.isEmptyCell(nextCell);
if (!isEmptyNextCell) {
let insertPosition = cell.endParagrapPosition.value - 1;
let nextCellLastParagraph = this.subDocument.paragraphs[this.getCellLastParagraphIndex(nextCell)];
if (!isEmptyCell) {
this.modelManager.modelManipulator.paragraph.insertParagraphViaHistory(InsertParagraphManipulatorParams.makeParamsByPosition(new SubDocumentPosition(this.subDocument, insertPosition), inpPos));
insertPosition++;
}
this.applyParagraphProperties(this.getCellLastParagraphIndex(cell), nextCellLastParagraph);
this.modelManager.modelManipulator.range.copyIntervalTo(this.subDocument, FixedInterval.fromPositions(nextCell.startParagraphPosition.value, nextCell.endParagrapPosition.value - 1), insertPosition);
}
this.deleteTableCellWithContent(nextCellPosition);
this.modelManipulator.table.normalizeCellColumnSpans(this.subDocument, position.table, true);
if (!suppressNormalizeTableRows)
this.modelManipulator.table.normalizeRows(this.subDocument, cell.parentRow.parentTable);
}
getCellLastParagraphIndex(cell) {
return this.subDocument.getParagraphIndexByPosition(cell.endParagrapPosition.value - 1);
}
applyParagraphProperties(targetIndex, source) {
let target = this.subDocument.paragraphs[targetIndex];
if (!target.maskedParagraphProperties.equals(source.maskedParagraphProperties) || target.numberingListIndex !== source.numberingListIndex || target.listLevelIndex !== source.listLevelIndex || target.tabs.equals(source.tabs) || target.paragraphStyle !== source.paragraphStyle)
this.modelManager.history.addAndRedo(new ParagraphPropertiesHistoryItem(this.modelManager.modelManipulator, this.subDocument, targetIndex, source.maskedParagraphProperties, source.paragraphStyle, source.numberingListIndex, source.listLevelIndex, source.tabs));
}
deleteTableCellWithContent(nextCellPosition) {
if (this.needDeleteNextTableCell)
this.modelManipulator.table.removeTableCellWithContent(this.subDocument, nextCellPosition.table, nextCellPosition.rowIndex, nextCellPosition.cellIndex);
else {
let nextCell = nextCellPosition.cell;
this.modelManager.modelManipulator.range.removeInterval(new SubDocumentInterval(this.subDocument, FixedInterval.fromPositions(nextCell.startParagraphPosition.value, nextCell.endParagrapPosition.value - 1)), true, false);
}
}
isEmptyCell(cell) {
return cell.endParagrapPosition.value - cell.startParagraphPosition.value === 1;
}
}
export class MergeTwoTableCellsHorizontallyOperation extends MergeTableCellsOperationBase {
constructor() {
super(...arguments);
this.needDeleteNextTableCell = true;
}
calculateNextCell(position) {
let nextCellIndex = position.cellIndex + 1;
return TablePosition.createAndInit(position.table, position.rowIndex, nextCellIndex);
}
updateCellsProperties(patternCellPosition, nextCellPosition) {
let patternCell = patternCellPosition.cell;
let nextCell = nextCellPosition.cell;
this.modelManager.history.addAndRedo(new TableCellColumnSpanHistoryItem(this.modelManager.modelManipulator, this.subDocument, patternCellPosition.table.index, patternCellPosition.rowIndex, patternCellPosition.cellIndex, patternCell.columnSpan + nextCell.columnSpan));
let patternCellPreferredWidth = patternCell.preferredWidth;
let nextCellPreferredWidth = nextCell.preferredWidth;
if (patternCellPreferredWidth && nextCellPreferredWidth && nextCellPreferredWidth.type === patternCellPreferredWidth.type) {
let newPreferredWidth = TableWidthUnit.create(patternCellPreferredWidth.value + nextCellPreferredWidth.value, patternCellPreferredWidth.type);
this.modelManager.history.addAndRedo(new TableCellPreferredWidthHistoryItem(this.modelManager.modelManipulator, this.subDocument, patternCellPosition.table.index, patternCellPosition.rowIndex, patternCellPosition.cellIndex, newPreferredWidth));
}
}
}
export class MergeTwoTableCellsVerticallyOperation extends MergeTableCellsOperationBase {
calculateNextCell(position) {
let nextRowIndex = position.rowIndex + 1;
let nextRow = position.table.rows[nextRowIndex];
let columnIndex = TableCellUtils.getStartColumnIndex(position.cell);
return TablePosition.createAndInit(position.table, nextRowIndex, TableCellUtils.getCellIndexByColumnIndex(nextRow, columnIndex));
}
updateCellsProperties(patternCellPosition, nextCellPosition) {
this.modelManager.history.addAndRedo(new TableCellVerticalMergingHistoryItem(this.modelManager.modelManipulator, this.subDocument, patternCellPosition.table.index, patternCellPosition.rowIndex, patternCellPosition.cellIndex, TableCellMergingState.Restart));
this.modelManager.history.addAndRedo(new TableCellVerticalMergingHistoryItem(this.modelManager.modelManipulator, this.subDocument, nextCellPosition.table.index, nextCellPosition.rowIndex, nextCellPosition.cellIndex, TableCellMergingState.Continue));
}
}
export class InsertTableCellWithShiftToTheDownOperation extends MergeTableCellsOperationBase {
calculateNextCell(position) {
return TablePosition.createAndInit(position.table, position.rowIndex - 1, position.cellIndex);
}
updateCellsProperties(patternCellPosition, nextCellPosition) {
let manipulator = this.modelManager.modelManipulator;
let subDocument = this.subDocument;
this.modelManager.history.addAndRedo(new TableCellBordersHistoryItem(manipulator, subDocument, patternCellPosition.table.index, patternCellPosition.rowIndex, patternCellPosition.cellIndex, [
nextCellPosition.cell.properties.borders.top.clone(),
nextCellPosition.cell.properties.borders.right.clone(),
nextCellPosition.cell.properties.borders.bottom.clone(),
nextCellPosition.cell.properties.borders.left.clone(),
nextCellPosition.cell.properties.borders.topLeftDiagonal.clone(),
nextCellPosition.cell.properties.borders.topRightDiagonal.clone()
], [nextCellPosition.cell.properties.getUseValue(TableCellPropertiesMask.UseTopBorder),
nextCellPosition.cell.properties.getUseValue(TableCellPropertiesMask.UseRightBorder),
nextCellPosition.cell.properties.getUseValue(TableCellPropertiesMask.UseBottomBorder),
nextCellPosition.cell.properties.getUseValue(TableCellPropertiesMask.UseLeftBorder),
nextCellPosition.cell.properties.getUseValue(TableCellPropertiesMask.UseTopLeftDiagonalBorder),
nextCellPosition.cell.properties.getUseValue(TableCellPropertiesMask.UseTopRightDiagonalBorder)]));
this.modelManager.history.addAndRedo(new TableCellShadingInfoHistoryItem(manipulator, subDocument, patternCellPosition.table.index, patternCellPosition.rowIndex, patternCellPosition.cellIndex, nextCellPosition.cell.properties.shadingInfo, true));
this.modelManager.history.addAndRedo(new TableCellVerticalAlignmentHistoryItem(manipulator, subDocument, patternCellPosition.table.index, patternCellPosition.rowIndex, patternCellPosition.cellIndex, nextCellPosition.cell.properties.verticalAlignment, true));
}
deleteTableCellWithContent(nextCellPosition) {
let nextCell = nextCellPosition.cell;
if (nextCell.endParagrapPosition.value - nextCell.startParagraphPosition.value > 1)
this.modelManager.modelManipulator.range.removeInterval(new SubDocumentInterval(this.subDocument, FixedInterval.fromPositions(nextCell.startParagraphPosition.value, nextCell.endParagrapPosition.value - 1)), true, false);
}
}
export class DeleteOneTableCellWithShiftToTheUpOperation extends MergeTwoTableCellsVerticallyOperation {
execute(position, suppressNormalizeTableRows, inpPos) {
if (position.rowIndex === position.table.rows.length - 1)
this.deleteContentFromCell(position.cell);
else {
this.deleteContentFromCell(position.cell);
super.execute(position, suppressNormalizeTableRows, inpPos);
}
}
updateCellsProperties(patternCellPosition, nextCellPosition) {
if (patternCellPosition.cell.verticalMerging === TableCellMergingState.Restart) {
this.modelManager.history.addAndRedo(new TableCellVerticalMergingHistoryItem(this.modelManager.modelManipulator, this.subDocument, patternCellPosition.table.index, patternCellPosition.rowIndex, patternCellPosition.cellIndex, TableCellMergingState.None));
if (nextCellPosition.rowIndex === nextCellPosition.table.rows.length - 1)
this.modelManager.history.addAndRedo(new TableCellVerticalMergingHistoryItem(this.modelManager.modelManipulator, this.subDocument, nextCellPosition.table.index, nextCellPosition.rowIndex, nextCellPosition.cellIndex, TableCellMergingState.None));
else {
let afterNextCellPosition = this.calculateNextCell(nextCellPosition);
if (afterNextCellPosition.cell && afterNextCellPosition.cell.verticalMerging === TableCellMergingState.Continue)
this.modelManager.history.addAndRedo(new TableCellVerticalMergingHistoryItem(this.modelManager.modelManipulator, this.subDocument, nextCellPosition.table.index, nextCellPosition.rowIndex, nextCellPosition.cellIndex, TableCellMergingState.Restart));
else
this.modelManager.history.addAndRedo(new TableCellVerticalMergingHistoryItem(this.modelManager.modelManipulator, this.subDocument, nextCellPosition.table.index, nextCellPosition.rowIndex, nextCellPosition.cellIndex, TableCellMergingState.None));
}
}
}
deleteContentFromCell(cell) {
let cellInterval = cell.interval;
if (--cellInterval.length > 0)
this.modelManager.modelManipulator.range.removeInterval(new SubDocumentInterval(this.subDocument, cellInterval), true, false);
}
}