UNPKG

devexpress-richedit

Version:

DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.

460 lines (459 loc) 30.8 kB
import { MapCreator } from '../../../utils/map-creator'; import { Errors } from '@devexpress/utils/lib/errors'; import { IntervalAlgorithms } from '@devexpress/utils/lib/intervals/algorithms'; import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed'; import { ListUtils } from '@devexpress/utils/lib/utils/list'; import { SearchUtils } from '@devexpress/utils/lib/utils/search'; import { MaskedCharacterPropertiesBundle } from '../../../rich-utils/properties-bundle'; import { Chunk } from '../../chunk'; import { DocumentModel } from '../../document-model'; import { Field } from '../../fields/field'; import { AbstractNumberingList, NumberingList } from '../../numbering-lists/numbering-list'; import { Paragraph } from '../../paragraph/paragraph'; import { RichUtils } from '../../rich-utils'; import { RunType } from '../../runs/run-type'; import { ParagraphRun, SectionRun } from '../../runs/simple-runs'; import { Section } from '../../section/section'; import { SubDocumentInterval, SubDocumentPosition } from '../../sub-document'; import { Table } from '../../tables/main-structures/table'; import { TableCell } from '../../tables/main-structures/table-cell'; import { TableRow } from '../../tables/main-structures/table-row'; import { TableWidthUnit, TableWidthUnitType } from '../../tables/secondary-structures/table-units'; import { TableCellUtils } from '../../tables/table-utils'; import { BookmarksManipulator } from '../bookmarks-manipulator'; import { TablesManipulator } from '../tables/tables-manipulator'; import { isDefined } from '@devexpress/utils/lib/utils/common'; import { SubDocumentInserterOptions } from '../document/sub-document-inserter'; export class CreateRangeCopyOperation { get documentModel() { return this.subDocument.documentModel; } constructor(subDocument, abstractNumberingListCache, numberingListCache) { this.newOffsetAtStartChunk = 0; this.additionalParagraphRunPositions = {}; this.subDocument = subDocument; this.numberingListCache = numberingListCache; this.abstractNumberingListCache = abstractNumberingListCache; } copyStyles(newDocumentModel) { newDocumentModel.characterStyles = ListUtils.deepCopy(this.documentModel.characterStyles); newDocumentModel.paragraphStyles = ListUtils.deepCopy(this.documentModel.paragraphStyles); newDocumentModel.numberingListStyles = ListUtils.deepCopy(this.documentModel.numberingListStyles); newDocumentModel.tableStyles = ListUtils.deepCopy(this.documentModel.tableStyles); newDocumentModel.tableCellStyles = ListUtils.deepCopy(this.documentModel.tableCellStyles); } execute(intervals) { const newDocumentModel = this.initNewDocumentModel(); const newSubDocument = newDocumentModel.mainSubDocument; this.copyStyles(newDocumentModel); if (ListUtils.allOf(intervals, curr => curr.length == 0)) throw new Error(Errors.InternalException); let currIntervalOffset = 0; for (let interval of intervals) { this.copyMainContent(interval, newDocumentModel, currIntervalOffset); currIntervalOffset += interval.length; } BookmarksManipulator.copyBookmarksFromSubDocumentTo(this.subDocument, newSubDocument, intervals); newSubDocument.getLastChunk().isLast = true; this.copyTables(newSubDocument, intervals); const addedUselessParagraphMarkInEnd = this.tryAppendAdditionalParagraphRunInTheEnd(newSubDocument, false); return new RangeCopy(newDocumentModel, addedUselessParagraphMarkInEnd, this.abstractNumberingListCache, this.numberingListCache); } copyMainContent(interval, newDocumentModel, currIntervalOffset) { const newSubDocument = newDocumentModel.mainSubDocument; const constRunIterator = this.subDocument.getConstRunIterator(interval); this.oldFieldStartIndex = -1; while (constRunIterator.moveNext()) { var oldCurrentRun = constRunIterator.currentRun; if (this.oldCurrentSection != constRunIterator.currentSection) { this.oldCurrentSection = constRunIterator.currentSection; this.newCurrentSection = this.appendNewSection(newSubDocument); } if (this.oldCurrentParagraph != oldCurrentRun.paragraph) { this.oldCurrentParagraph = oldCurrentRun.paragraph; this.newCurrentParagraph = this.appendNewParagraph(newSubDocument); } if (this.oldCurrentChunk != constRunIterator.currentChunk) { this.oldCurrentChunk = constRunIterator.currentChunk; this.newCurrentChunk = this.appendNewChunk(newSubDocument); this.newOffsetAtStartChunk = 0; } this.newCurrentParagraph.length += oldCurrentRun.getLength(); this.newCurrentSection.setLength(newSubDocument, this.newCurrentSection.getLength() + oldCurrentRun.getLength()); this.newCurrentChunk.textBuffer += this.oldCurrentChunk.getTextInChunk(oldCurrentRun.startOffset, oldCurrentRun.getLength()); if (oldCurrentRun.getType() == RunType.FieldCodeStartRun) this.appendField(newSubDocument, oldCurrentRun, interval.start - currIntervalOffset); else if (oldCurrentRun.getType() == RunType.AnchoredTextBoxRun) { const newTexBoxSubDoc = this.documentModel.subDocuments[oldCurrentRun.subDocId].clone(newDocumentModel); const sourceTextBoxSubDocParagraphs = this.documentModel.subDocuments[oldCurrentRun.subDocId].paragraphs; ListUtils.forEach(newTexBoxSubDoc.paragraphs, (paragraph, index) => { paragraph.numberingListIndex = CreateRangeCopyOperation.getNewNumberingListIndex(this.documentModel, sourceTextBoxSubDocParagraphs[index].numberingListIndex, newTexBoxSubDoc, this.abstractNumberingListCache, this.numberingListCache); }); } this.newCurrentChunk.textRuns.push(oldCurrentRun.createSimularity(this.newOffsetAtStartChunk, oldCurrentRun.getLength(), this.newCurrentParagraph, newDocumentModel.stylesManager.addCharacterStyle(oldCurrentRun.characterStyle), newDocumentModel.cache.maskedCharacterPropertiesCache.getItem(oldCurrentRun.maskedCharacterProperties))); this.newOffsetAtStartChunk += oldCurrentRun.getLength(); } } appendField(newSubDocument, oldCurrentRun, globalOffset) { let oldFieldStartIndex = this.oldFieldStartIndex; const oldSubDocument = this.subDocument; if (oldFieldStartIndex < 0) { const oldFieldStartCodeRunOffset = this.oldCurrentChunk.startLogPosition.value + oldCurrentRun.startOffset; oldFieldStartIndex = Field.normedBinaryIndexOf(oldSubDocument.fields, oldFieldStartCodeRunOffset + 1); } else oldFieldStartIndex++; const oldField = oldSubDocument.fields[oldFieldStartIndex]; const newField = new Field(newSubDocument.positionManager, newSubDocument.fields.length, oldField.getFieldStartPosition() - globalOffset, oldField.getSeparatorPosition() - globalOffset, oldField.getFieldEndPosition() - globalOffset, oldField.showCode, oldField.getHyperlinkInfo() ? oldField.getHyperlinkInfo().clone() : undefined); newSubDocument.fields.push(newField); newField.initParent(newSubDocument.fields); this.oldFieldStartIndex = oldFieldStartIndex; } appendParagraphMarkInTheEnd(newSubDocument, position, sectionEnd) { this.newCurrentParagraph.length += 1; this.newCurrentSection.setLength(newSubDocument, this.newCurrentSection.getLength() + 1); let text = sectionEnd ? RichUtils.specialCharacters.SectionMark : RichUtils.specialCharacters.ParagraphMark; let runType = sectionEnd ? SectionRun : ParagraphRun; this.newCurrentChunk.textBuffer += text; this.newCurrentChunk.textRuns.push(new runType(position, this.newCurrentParagraph, new MaskedCharacterPropertiesBundle(newSubDocument.getLastRun().maskedCharacterProperties, newSubDocument.getLastRun().characterStyle))); this.newOffsetAtStartChunk++; } appendNewChunk(newSubDocument) { let newCurrentChunkAbsolutePosition = newSubDocument.chunks.length ? newSubDocument.getLastChunk().getEndPosition() : 0, newCurrentChunkPosition = newSubDocument.positionManager.registerPosition(newCurrentChunkAbsolutePosition), newCurrentChunk = new Chunk(newCurrentChunkPosition, "", false); newSubDocument.chunks.push(newCurrentChunk); return newCurrentChunk; } appendNewSection(newSubDocument) { this.tryAppendAdditionalParagraphRunInTheEnd(newSubDocument, true); let lastSection = newSubDocument.documentModel.sections[newSubDocument.documentModel.sections.length - 1]; let newCurrentSectionAbsolutePosition = lastSection ? lastSection.getEndPosition() : 0, newCurrentSectionPosition = newSubDocument.positionManager.registerPosition(newCurrentSectionAbsolutePosition); let newCurrentSection = new Section(newSubDocument.documentModel, newCurrentSectionPosition, 0, this.oldCurrentSection.sectionProperties.clone()); newSubDocument.documentModel.sections.push(newCurrentSection); return newCurrentSection; } copyToCore(targetStyle, oldStyle, newSubDocument) { targetStyle.maskedCharacterProperties = oldStyle.maskedCharacterProperties.clone(); targetStyle.maskedParagraphProperties = oldStyle.maskedParagraphProperties.clone(); targetStyle.tabs = oldStyle.tabs.clone(); if (oldStyle.isInOwnList()) { targetStyle.numberingListIndex = CreateRangeCopyOperation.getNewNumberingListIndex(this.documentModel, oldStyle.numberingListIndex, newSubDocument, this.abstractNumberingListCache, this.numberingListCache); } else if (oldStyle.numberingListIndex == AbstractNumberingList.NoNumberingListIndex) { targetStyle.numberingListIndex = AbstractNumberingList.NoNumberingListIndex; } } copyPropertiesTo(targetStyle, oldStyle, newSubDocument) { this.copyToCore(targetStyle, oldStyle, newSubDocument); if (oldStyle.parent) { targetStyle.parent = newSubDocument.documentModel.stylesManager.addParagraphStyle(targetStyle.parent); this.copyPropertiesTo(targetStyle.parent, oldStyle.parent, newSubDocument); } if (oldStyle.nextParagraphStyle != null) targetStyle.nextParagraphStyle = newSubDocument.documentModel.stylesManager.addParagraphStyle(targetStyle.nextParagraphStyle); } appendNewParagraph(newSubDocument) { this.tryAppendAdditionalParagraphRunInTheEnd(newSubDocument, false); const oldCurrentParagraph = this.oldCurrentParagraph; const oldDocumentModel = oldCurrentParagraph.subDocument.documentModel; const lastParagraph = newSubDocument.paragraphs[newSubDocument.paragraphs.length - 1]; const newCurrentParagraphAbsolutePosition = lastParagraph ? lastParagraph.getEndPosition() : 0; const newCurrentParagraphPosition = newSubDocument.positionManager.registerPosition(newCurrentParagraphAbsolutePosition); const newCurrentParagraphStyle = newSubDocument.documentModel.stylesManager.addParagraphStyle(oldCurrentParagraph.paragraphStyle); this.copyPropertiesTo(newCurrentParagraphStyle, oldCurrentParagraph.paragraphStyle, newSubDocument); const newCurrentMaskedParagraphProperties = newSubDocument.documentModel.cache.maskedParagraphPropertiesCache.getItem(oldCurrentParagraph.maskedParagraphProperties); const newCurrentParagraph = new Paragraph(newSubDocument, newCurrentParagraphPosition, 0, newCurrentParagraphStyle, newCurrentMaskedParagraphProperties); newCurrentParagraph.listLevelIndex = oldCurrentParagraph.listLevelIndex; newCurrentParagraph.numberingListIndex = CreateRangeCopyOperation.getNewNumberingListIndex(oldDocumentModel, oldCurrentParagraph.numberingListIndex, newSubDocument, this.abstractNumberingListCache, this.numberingListCache); newCurrentParagraph.tabs = oldCurrentParagraph.tabs.clone(); newSubDocument.paragraphs.push(newCurrentParagraph); return newCurrentParagraph; } static getNewNumberingListIndex(oldmodel, oldNumberingListIndex, newSubDocument, abstractNumberingListCache = {}, numberingListCache = {}) { let newCurrentParagraphNumberingListIndex = -1; let newAbstractNumberingListIndex = -1; if (oldNumberingListIndex >= 0) { const oldNumberingList = oldmodel.numberingLists[oldNumberingListIndex]; newCurrentParagraphNumberingListIndex = numberingListCache[oldNumberingList.getId()]; if (newCurrentParagraphNumberingListIndex === undefined) { const oldAbstractNumberingList = oldmodel.abstractNumberingLists[oldNumberingList.abstractNumberingListIndex]; newAbstractNumberingListIndex = abstractNumberingListCache[oldAbstractNumberingList.getId()]; if (newAbstractNumberingListIndex === undefined) { const newAbstractNumberingList = new AbstractNumberingList(newSubDocument.documentModel); newAbstractNumberingList.copyFrom(oldAbstractNumberingList); newAbstractNumberingListIndex = newSubDocument.documentModel.abstractNumberingLists.push(newAbstractNumberingList) - 1; abstractNumberingListCache[oldAbstractNumberingList.getId()] = newAbstractNumberingListIndex; } const newNumberingList = new NumberingList(newSubDocument.documentModel, newAbstractNumberingListIndex); newNumberingList.copyFrom(oldNumberingList); newCurrentParagraphNumberingListIndex = newSubDocument.documentModel.numberingLists.push(newNumberingList) - 1; numberingListCache[oldNumberingList.getId()] = newCurrentParagraphNumberingListIndex; } } return newCurrentParagraphNumberingListIndex; } tryAppendAdditionalParagraphRunInTheEnd(newSubDocument, sectionEnd) { let lastChunk = newSubDocument.getLastChunk(); if (!lastChunk) return false; let lastRun = lastChunk.textRuns[lastChunk.textRuns.length - 1]; if (!lastRun) return false; if (!lastRun.isParagraphOrSectionRun()) { this.appendParagraphMarkInTheEnd(newSubDocument, lastRun.startOffset + lastRun.getLength(), sectionEnd); this.additionalParagraphRunPositions[lastChunk.getEndPosition() - 1] = true; return true; } return false; } initNewDocumentModel() { const newDocumentModel = new DocumentModel(this.documentModel.modelOptions, 0); newDocumentModel.defaultCharacterProperties = newDocumentModel.cache.maskedCharacterPropertiesCache.getItem(this.documentModel.defaultCharacterProperties); newDocumentModel.defaultParagraphProperties = newDocumentModel.cache.maskedParagraphPropertiesCache.getItem(this.documentModel.defaultParagraphProperties); newDocumentModel.defaultTableProperties = this.documentModel.defaultTableProperties.clone(); newDocumentModel.defaultTableRowProperties = newDocumentModel.cache.tableRowPropertiesCache.getItem(this.documentModel.defaultTableRowProperties); newDocumentModel.defaultTableCellProperties = newDocumentModel.cache.tableCellPropertiesCache.getItem(this.documentModel.defaultTableCellProperties); newDocumentModel.colorProvider.officeTheme.copyFrom(this.documentModel.colorProvider.officeTheme); newDocumentModel.cache.imageCache = this.documentModel.cache.imageCache; return newDocumentModel; } getNestedLevel(newSubDocument, sourceTable, nestedLevel) { if (sourceTable.nestedLevel > nestedLevel) return nestedLevel + 1; if (!sourceTable.parentCell) return 0; const newParentTableIndex = this.mapSourceTableIndexToTarget[sourceTable.getParentTable().index]; return isDefined(newParentTableIndex) ? newSubDocument.tables[newParentTableIndex].nestedLevel + 1 : -1; } copyTables(newSubDocument, intervals) { const tables = this.subDocument.tables; this.mapSourceTableIndexToTarget = new MapCreator().get(); if (!tables.length) return; const pos = intervals[0].start; let startTableIndex = Math.max(0, SearchUtils.normedInterpolationIndexOf(tables, t => t.getStartPosition(), pos)); startTableIndex = Table.correctBoundTable(tables, startTableIndex, pos, (index) => --index).index; let nestedLevel = -1; let endSelectionPosition = intervals[0].end; let prevLength = 0; for (let i = startTableIndex, table; table = this.subDocument.tables[i]; i++) { if (table.nestedLevel != nestedLevel) nestedLevel = this.getNestedLevel(newSubDocument, table, nestedLevel); const tableStartPosition = table.getStartPosition(); const tableInterval = table.interval; while (intervals.length > 0 && tableStartPosition >= intervals[0].end) { if (this.additionalParagraphRunPositions[intervals[0].end]) prevLength++; prevLength += intervals[0].length; intervals.shift(); } if (!intervals.length) break; if (IntervalAlgorithms.getIntersectionNonNullLength(table.interval, intervals[0])) { if (intervals[0].containsInterval(tableInterval)) { this.appendWholeTable(newSubDocument, table, intervals[0].start - prevLength, nestedLevel); } else { let selectedCellInfos = this.getSelectedCells(table, intervals.slice(0), prevLength); if (this.canCopyParticallyTable(selectedCellInfos)) this.appendParticallyTable(newSubDocument, selectedCellInfos, nestedLevel); else nestedLevel = -1; } } else if (tableStartPosition >= endSelectionPosition) break; } } appendWholeTable(newSubDocument, table, positionDelta, newNestedLevel) { let newTable = this.createTable(newSubDocument, table, newNestedLevel, positionDelta); newTable.preferredWidth = table.preferredWidth.clone(); newTable.lookTypes = table.lookTypes; for (let i = 0, row; row = table.rows[i]; i++) { let newRow = new TableRow(newTable, newSubDocument.documentModel.cache.tableRowPropertiesCache.getItem(row.properties.clone())); newTable.rows.push(newRow); newRow.height = row.height.clone(); if (row.tablePropertiesException) newRow.tablePropertiesException = row.tablePropertiesException.clone(); newRow.gridBefore = row.gridBefore; newRow.gridAfter = row.gridAfter; newRow.widthAfter = row.widthAfter.clone(); newRow.widthBefore = row.widthBefore.clone(); for (let j = 0, cell; cell = row.cells[j]; j++) { let newCell = this.cloneTableCell(newSubDocument, newRow, cell); newCell.verticalMerging = cell.verticalMerging; newCell.startParagraphPosition = newSubDocument.positionManager.registerPosition(cell.startParagraphPosition.value - positionDelta); newCell.endParagrapPosition = newSubDocument.positionManager.registerPosition(cell.endParagrapPosition.value - positionDelta); newRow.cells.push(newCell); } } } appendParticallyTable(newSubDocument, selectedCellInfos, newNestedLevel) { let minLeftColumnIndex = Number.MAX_VALUE; let maxRightColumnIndex = 0; let table = selectedCellInfos[0][0].cell.parentRow.parentTable; for (let i = 0, horCells; horCells = selectedCellInfos[i]; i++) { let leftColumnIndex = TableCellUtils.getStartColumnIndex(horCells[0].cell); let rightColumnIndex = TableCellUtils.getEndColumnIndex(horCells[horCells.length - 1].cell); minLeftColumnIndex = Math.min(minLeftColumnIndex, leftColumnIndex); maxRightColumnIndex = Math.max(maxRightColumnIndex, rightColumnIndex); } let newStartPosition = selectedCellInfos[0][0].cell.startParagraphPosition.value - selectedCellInfos[0][0].positionDelta; let newTable = this.createTable(newSubDocument, table, newNestedLevel, newStartPosition); newTable.preferredWidth = TableWidthUnit.create(0, TableWidthUnitType.Auto); for (let i = 0, horCellInfos; horCellInfos = selectedCellInfos[i]; i++) { let leftColumnIndex = TableCellUtils.getStartColumnIndex(horCellInfos[0].cell); let rightColumnIndex = TableCellUtils.getEndColumnIndex(horCellInfos[horCellInfos.length - 1].cell); let row = horCellInfos[0].cell.parentRow; let newRow = new TableRow(newTable, newSubDocument.documentModel.cache.tableRowPropertiesCache.getItem(row.properties.clone())); newTable.rows.push(newRow); newRow.height = row.height.clone(); newRow.gridBefore = leftColumnIndex - minLeftColumnIndex; newRow.gridAfter = maxRightColumnIndex - rightColumnIndex; for (let j = 0, cellInfo; cellInfo = horCellInfos[j]; j++) { let newCell = this.cloneTableCell(newSubDocument, newRow, cellInfo.cell); newCell.startParagraphPosition = newSubDocument.positionManager.registerPosition(cellInfo.cell.startParagraphPosition.value - cellInfo.positionDelta); newCell.endParagrapPosition = newSubDocument.positionManager.registerPosition(cellInfo.cell.endParagrapPosition.value - cellInfo.positionDelta); newRow.cells.push(newCell); } } TablesManipulator.normalizeCellColumnSpansWithoutHistory(newTable, true); } canCopyParticallyTable(selectedCellInfos) { if (selectedCellInfos.length === 0) return false; let prevRowEndPosition = selectedCellInfos[0][0].cell.parentRow.getEndPosition(); let prevLeftColumnIndex = TableCellUtils.getStartColumnIndex(selectedCellInfos[0][0].cell); let prevRightColumnIndex = TableCellUtils.getEndColumnIndex(selectedCellInfos[0][selectedCellInfos[0].length - 1].cell); for (let i = 0, horCells; horCells = selectedCellInfos[i]; i++) { let prevCellEndPosition = horCells[0].cell.endParagrapPosition.value; for (let j = 1, cellInfo; cellInfo = horCells[j]; j++) { if (cellInfo.cell.startParagraphPosition.value !== prevCellEndPosition) return false; prevCellEndPosition = cellInfo.cell.endParagrapPosition.value; } if (i > 0) { if (horCells[0].cell.parentRow.getStartPosition() !== prevRowEndPosition) return false; let leftColumnIndex = TableCellUtils.getStartColumnIndex(horCells[0].cell); let rightColumnIndex = TableCellUtils.getEndColumnIndex(horCells[horCells.length - 1].cell); if (rightColumnIndex < prevLeftColumnIndex || leftColumnIndex > prevRightColumnIndex) return false; prevRowEndPosition = horCells[0].cell.parentRow.getEndPosition(); } } return true; } cloneTableCell(newSubDocument, newRow, sourceCell) { let newCell = new TableCell(newRow, newSubDocument.documentModel.cache.tableCellPropertiesCache.getItem(sourceCell.properties.clone())); newCell.columnSpan = sourceCell.columnSpan; newCell.conditionalFormatting = sourceCell.conditionalFormatting; newCell.preferredWidth = sourceCell.preferredWidth.clone(); newCell.style = sourceCell.style; return newCell; } createTable(newSubDocument, oldTable, newNestedLevel, newDocumentStartPosition) { let newTableStyle = newSubDocument.documentModel.stylesManager.addTableStyle(oldTable.style); let newTable = new Table(oldTable.properties.clone(), newTableStyle); newTable.nestedLevel = newNestedLevel; if (newNestedLevel > 0) { let newStartPosition = oldTable.getStartPosition() - newDocumentStartPosition; newTable.parentCell = Table.getTableCellByPosition(newSubDocument.tables, newStartPosition); } newTable.index = newSubDocument.tables.push(newTable) - 1; this.mapSourceTableIndexToTarget[oldTable.index] = newTable.index; (newSubDocument.tablesByLevels[newNestedLevel] || (newSubDocument.tablesByLevels[newNestedLevel] = [])).push(newTable); return newTable; } getSelectedCells(table, intervals, prevLength) { let currentIntervalIndex = 0; let maxIntervalIndex = intervals.length - 1; let selectedCellInfos = []; for (let rowIndex = 0, row; row = table.rows[rowIndex]; rowIndex++) { let horCells = []; for (let cellIndex = 0, cell; cell = row.cells[cellIndex]; cellIndex++) { while (currentIntervalIndex <= maxIntervalIndex && intervals[currentIntervalIndex].end < cell.endParagrapPosition.value) { if (this.additionalParagraphRunPositions[intervals[currentIntervalIndex].end]) prevLength++; prevLength += intervals[currentIntervalIndex].length; currentIntervalIndex++; } if (currentIntervalIndex > maxIntervalIndex) break; if (intervals[currentIntervalIndex].containsInterval(cell.interval)) { horCells.push(new TableCellInfo(cell, intervals[currentIntervalIndex].start - prevLength)); } } if (horCells.length) selectedCellInfos.push(horCells); if (currentIntervalIndex > maxIntervalIndex) break; } return selectedCellInfos; } } export class RangeCopy { constructor(model, addedUselessParagraphMarkInEnd, abstractNumberingListCache = {}, numberingListCache = {}, pictureSizeUpdater) { this.model = model; this.addedUselessParagraphMarkInEnd = addedUselessParagraphMarkInEnd; this.abstractNumberingListCache = abstractNumberingListCache; this.numberingListCache = numberingListCache; this.pictureSizeUpdater = pictureSizeUpdater; } insertTo(modelManipulator, subDocPosition, overlapTableCellContent = false) { const sourceInterval = new FixedInterval(0, this.model.mainSubDocument.getDocumentEndPosition() - (this.addedUselessParagraphMarkInEnd ? 1 : 0)); const insertOptions = new SubDocumentInserterOptions(); insertOptions.overlapTableCellContent = overlapTableCellContent; insertOptions.abstractNumberingListCache = this.abstractNumberingListCache; insertOptions.numberingListCache = this.numberingListCache; insertOptions.pictureSizeUpdater = this.pictureSizeUpdater; return modelManipulator.subDocument.insertSubDocument(subDocPosition, new SubDocumentInterval(this.model.mainSubDocument, sourceInterval), insertOptions) .insetedInterval; } insertToTable(modelManipulator, insertPosition, targetTableInfo) { const sourceTable = this.model.mainSubDocument.tables[0]; if (!sourceTable) return this.insertTo(modelManipulator, insertPosition); return this.overlapTableContent(modelManipulator, sourceTable, targetTableInfo); } overlapTableContent(modelManipulator, sourceTable, targetTableInfo) { let firstCellIndex = targetTableInfo.rawData.firstCellInfo.cellIndex; let lastCellIndex = targetTableInfo.rawData.lastCellInfo.cellIndex; let firstRowIndex = targetTableInfo.rawData.firstRowInfo.rowIndex; let lastRowIndex = targetTableInfo.rawData.lastRowInfo.rowIndex; if (firstCellIndex == lastCellIndex) { lastCellIndex = firstCellIndex + sourceTable.rows[0].cells.length - 1; if (firstRowIndex == lastRowIndex) lastRowIndex = firstRowIndex + sourceTable.rows.length - 1; } for (let i = firstRowIndex; i <= lastRowIndex; i++) { for (let j = firstCellIndex; j <= lastCellIndex; j++) { if (i >= targetTableInfo.table.rows.length) return targetTableInfo.table.interval; this.overlapTableCellContent(modelManipulator, sourceTable, targetTableInfo, i, j); } } return targetTableInfo.table.interval; } overlapTableCellContent(modelManipulator, sourceTable, targetTableInfo, rowIndex, columnIndex) { const targetCell = targetTableInfo.table.rows[rowIndex].cells[columnIndex]; if (!targetCell) return; const i = (rowIndex - targetTableInfo.rawData.firstRowInfo.rowIndex) % sourceTable.rows.length; const j = (columnIndex - targetTableInfo.rawData.firstCellInfo.cellIndex) % sourceTable.rows[i].cells.length; const sourceCell = sourceTable.rows[i].cells[j]; const copyOperation = new CreateRangeCopyOperation(this.model.mainSubDocument, this.abstractNumberingListCache, this.numberingListCache); const rangeCopy = copyOperation.execute([sourceCell.interval]); modelManipulator.range.removeInterval(new SubDocumentInterval(modelManipulator.model.mainSubDocument, targetCell.interval), false, true); rangeCopy.insertTo(modelManipulator, new SubDocumentPosition(modelManipulator.model.mainSubDocument, targetCell.interval.start), true); } static create(subDocIntervals) { return new CreateRangeCopyOperation(subDocIntervals.subDocument, {}, {}).execute(subDocIntervals.intervals); } } class TableCellInfo { constructor(cell, positionDelta) { this.cell = cell; this.positionDelta = positionDelta; } }