devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
469 lines (468 loc) • 30.6 kB
JavaScript
import { FixedInterval } from '@devexpress/utils/lib/intervals/fixed';
import { EnumUtils } from '@devexpress/utils/lib/utils/enum';
import { SearchUtils } from '@devexpress/utils/lib/utils/search';
import { SectionMergedSubDocumentChange } from '../../changes/model/section-merged';
import { AnchorObjectRemovedSubDocumentChange } from '../../changes/sub-document/text/anchor-object-removed';
import { IntervalRemovedSubDocumentChange } from '../../changes/sub-document/text/interval-removed';
import { ParagraphMergedSubDocumentChange } from '../../changes/sub-document/text/paragraph-merged';
import { HistoryRun, HistoryRunAnchoredPicture, HistoryRunAnchoredTextBox, HistoryRunFieldCodeEnd, HistoryRunFieldCodeStart, HistoryRunFieldResultEnd, HistoryRunInlinePicture, HistoryRunParagraph, HistoryRunSection } from '../../character/history-runs';
import { Field } from '../../fields/field';
import { AnchoredPictureRun } from '../../runs/anchored-picture-run';
import { AnchoredTextBoxRun } from '../../runs/anchored-text-box-run';
import { InlinePictureRun } from '../../runs/inline-picture-run';
import { RunType } from '../../runs/run-type';
import { RunsBaseManipulator } from '../runs-base-manipulator';
import { BaseTextBoxInfo } from '../text-box-manipulator';
export class RemoveIntervalOperation {
constructor(manipulator, subDocument) {
this.currentCellIndex = 0;
this.modelManipulator = manipulator;
this.subDocument = subDocument;
}
execute(interval, applyPropertiesToLeft, needHistory) {
this.cellsIterator = new SelectedCellsIterator(this.subDocument, interval);
const result = new RemoveIntervalOperationResult(this.cellsIterator);
result.bookmarkItems = this.modelManipulator.bookmark.deleteBookmarks(this.subDocument, interval);
result.rangePermssionsItems = this.modelManipulator.rangePermission.deleteRangePermissions(this.subDocument, interval);
if (this.tryPackSelectionInOneRun(interval, result))
return result;
var iterator = this.subDocument.getRunIterator(interval);
if (needHistory)
this.fillResult(interval, result);
this.initializeStartPositions(interval.start);
this.executeCore(applyPropertiesToLeft, interval.start, iterator, result);
this.correctTablesStart();
return result;
}
correctTablesStart() {
for (let tbl of this.subDocument.tables) {
const tblPos = tbl.getStartPosition();
const parPos = this.subDocument.getParagraphByPosition(tblPos).startLogPosition.value;
if (tblPos != parPos)
this.modelManipulator.table.changeTableStartPosition(this.subDocument, tbl, parPos);
}
}
initializeStartPositions(intervalStart) {
this.position = intervalStart;
this.currentChunkIndex = SearchUtils.normedInterpolationIndexOf(this.subDocument.chunks, (c) => c.startLogPosition.value, intervalStart);
this.currentSectionIndex = SearchUtils.normedInterpolationIndexOf(this.subDocument.documentModel.sections, s => s.startLogPosition.value, intervalStart);
this.currentParagraphIndex = SearchUtils.normedInterpolationIndexOf(this.subDocument.paragraphs, p => p.startLogPosition.value, intervalStart);
this.fieldIndexThatNeedDelete = -1;
}
executeCore(applyPropertiesToLeft, startPosition, iterator, result) {
var subDocument = this.subDocument;
var accumulatedInterval = new FixedInterval(this.position, 0);
let removedTextList = [];
while (iterator.moveNext()) {
if (EnumUtils.isAnyOf(iterator.currentRun.getType(), RunType.AnchoredPictureRun, RunType.AnchoredTextBoxRun)) {
const currentRun = iterator.currentRun;
const position = iterator.currentInterval().start;
const change = new AnchorObjectRemovedSubDocumentChange(this.subDocument.id, currentRun.anchoredObjectID, position);
if (currentRun instanceof AnchoredTextBoxRun)
this.modelManipulator.model.subDocumentsCollection.replace(currentRun.subDocId, subDocument.id);
this.modelManipulator.notifyModelChanged(change);
}
if (iterator.currentChunk !== subDocument.chunks[this.currentChunkIndex]) {
this.removeAccumulatedInterval(accumulatedInterval, this.position, 0, removedTextList);
this.currentChunkIndex++;
}
if (subDocument.documentModel.sections[this.currentSectionIndex] !== iterator.currentSection)
this.currentSectionIndex++;
var runIndex = SearchUtils.normedInterpolationIndexOf(subDocument.chunks[this.currentChunkIndex].textRuns, r => r.startOffset, iterator.currentRun.startOffset);
if (iterator.currentRun.getType() == RunType.FieldCodeStartRun)
this.removeField(startPosition);
if (iterator.currentRun.getType() == RunType.ParagraphRun) {
if (subDocument.paragraphs.length === 1) {
result.removeLastParagraphRun();
continue;
}
}
iterator.currentRun.paragraph.length -= iterator.currentRun.getLength();
this.modifySectionLength(iterator.currentSection, -iterator.currentRun.getLength());
const strategy = this.getStrategy(iterator, accumulatedInterval);
strategy.call(this, accumulatedInterval, removedTextList, runIndex);
}
this.removeAccumulatedInterval(accumulatedInterval, -1, 0, removedTextList);
if (this.shouldMergeParagraphs)
this.tryMergeStartEndParagraphs(startPosition, applyPropertiesToLeft);
this.cellsIterator.reset();
}
modifySectionLength(section, delta) {
section.setLength(this.subDocument, section.getLength() + delta);
}
getStrategy(iterator, accumulatedInterval) {
if (!this.canRemoveRun(iterator.currentRun, iterator.currentRun.startOffset + iterator.currentChunk.startLogPosition.value + accumulatedInterval.length, iterator.currentRun.paragraph.length === 0))
return this.skipRunAndMoveToNextParagraph;
else if (iterator.currentRun.getType() === RunType.SectionRun && iterator.currentSection.getLength() == 0)
return this.removeWholeSection;
else if (iterator.currentRun.getType() === RunType.ParagraphRun && iterator.currentRun.paragraph.length === 0)
return this.removeWholeParagraph;
else if (iterator.currentRun.getType() === RunType.SectionRun && this.shouldMergeParagraphs && iterator.currentRun.paragraph.length === 0)
return this.mergePreviousParagraph;
else if (!iterator.currentRun.isParagraphOrSectionRun())
return this.removeTextRun;
else
return this.skipParagraphRunAndMergeParagraphsAtTheEnd;
}
removeTextRun(accumulatedInterval, removedTextList, runIndex) {
accumulatedInterval.length += this.subDocument.chunks[this.currentChunkIndex].textRuns[runIndex].getLength();
removedTextList.push(this.removeRunInternal(this.subDocument, runIndex));
}
skipParagraphRunAndMergeParagraphsAtTheEnd(accumulatedInterval, removedTextList, runIndex) {
this.skipRunAndMoveToNextParagraph(accumulatedInterval, removedTextList, runIndex);
this.shouldMergeParagraphs = true;
}
skipRunAndMoveToNextParagraph(accumulatedInterval, removedTextList, _runIndex) {
this.subDocument.paragraphs[this.currentParagraphIndex].length++;
this.modifySectionLength(this.subDocument.documentModel.sections[this.currentSectionIndex], 1);
this.position++;
this.removeAccumulatedInterval(accumulatedInterval, this.position, 0, removedTextList);
this.currentParagraphIndex++;
}
mergePreviousParagraph(accumulatedInterval, removedTextList, runIndex) {
if (runIndex === 0)
this.currentChunkIndex--;
var paragraphIndex = this.currentParagraphIndex;
const par = this.subDocument.paragraphs[paragraphIndex];
const remodedParagraphMarkPos = par.getEndPosition() - 1;
par.length++;
this.removeAccumulatedInterval(accumulatedInterval, this.position, 0, removedTextList);
this.mergeParagraphsInternal(this.subDocument, paragraphIndex - 1, false);
this.modelManipulator.notifyModelChanged(new ParagraphMergedSubDocumentChange(this.subDocument.id, new FixedInterval(remodedParagraphMarkPos, 1), this.subDocument.paragraphs[paragraphIndex - 1].getEndPosition() - 1, false));
}
removeWholeSection(accumulatedInterval, removedTextList, runIndex) {
var subDocument = this.subDocument;
var currentSection = subDocument.documentModel.sections[this.currentSectionIndex];
this.removeAccumulatedInterval(accumulatedInterval, this.position, -1, removedTextList);
if (subDocument.documentModel.sections.length > 1) {
const deletedSectionMarkPosition = currentSection.getEndPosition();
subDocument.positionManager.unregisterPosition(currentSection.startLogPosition);
subDocument.documentModel.sections.splice(this.currentSectionIndex, 1);
subDocument.positionManager.unregisterPosition(subDocument.paragraphs[this.currentParagraphIndex].startLogPosition);
subDocument.paragraphs.splice(this.currentParagraphIndex, 1);
this.removeRunInternal(subDocument, runIndex);
this.currentSectionIndex--;
this.modelManipulator.notifyModelChanged(new SectionMergedSubDocumentChange(this.currentSectionIndex + 1, new FixedInterval(deletedSectionMarkPosition, 1), false));
}
}
removeWholeParagraph(accumulatedInterval, removedTextList, runIndex) {
var subDocument = this.subDocument;
this.removeAccumulatedInterval(accumulatedInterval, this.position, -1, removedTextList);
if (subDocument.paragraphs.length > 1) {
const pos = subDocument.paragraphs[this.currentParagraphIndex].startLogPosition;
const removedParagraphMarkPos = pos.value;
subDocument.positionManager.unregisterPosition(pos);
subDocument.paragraphs.splice(this.currentParagraphIndex, 1);
this.removeRunInternal(subDocument, runIndex);
this.modelManipulator.notifyModelChanged(new ParagraphMergedSubDocumentChange(subDocument.id, new FixedInterval(removedParagraphMarkPos, 1), this.position, false));
}
}
tryMergeStartEndParagraphs(startPosition, applyPropertiesToLeft) {
var subDocument = this.subDocument;
var firstParagraphIndex = subDocument.getParagraphIndexByPosition(startPosition), firstParagraph = subDocument.paragraphs[firstParagraphIndex], lastParagraph = subDocument.paragraphs[firstParagraphIndex + 1];
var firstSectionIndex = SearchUtils.normedInterpolationIndexOf(subDocument.documentModel.sections, s => s.startLogPosition.value, firstParagraph.startLogPosition.value), firstSection = subDocument.documentModel.sections[firstSectionIndex];
if (lastParagraph) {
this.modifySectionLength(firstSection, -1);
if (this.subDocument.isMain() && firstSection.getEndPosition() === firstParagraph.getEndPosition() - 1 && firstSectionIndex < subDocument.documentModel.sections.length - 1) {
const lastSection = subDocument.documentModel.sections[firstSectionIndex + 1];
const deletedSectionMarkPos = firstSection.getEndPosition();
subDocument.positionManager.unregisterPosition(lastSection.startLogPosition);
lastSection.startLogPosition = subDocument.positionManager.registerPosition(firstSection.startLogPosition.value);
this.modifySectionLength(lastSection, firstSection.getLength());
subDocument.positionManager.unregisterPosition(firstSection.startLogPosition);
subDocument.documentModel.sections.splice(firstSectionIndex, 1);
this.mergeParagraphsInternal(subDocument, firstParagraphIndex, applyPropertiesToLeft);
this.modelManipulator.notifyModelChanged(new SectionMergedSubDocumentChange(firstSectionIndex, new FixedInterval(deletedSectionMarkPos, 1), !!applyPropertiesToLeft));
}
else {
const deletedParagraphMarkPos = lastParagraph.startLogPosition.value - 1;
this.mergeParagraphsInternal(subDocument, firstParagraphIndex, applyPropertiesToLeft);
this.modelManipulator.notifyModelChanged(new ParagraphMergedSubDocumentChange(subDocument.id, new FixedInterval(deletedParagraphMarkPos, 1), lastParagraph.startLogPosition.value - 1, !!applyPropertiesToLeft));
}
}
}
removeField(startPosition) {
if (this.fieldIndexThatNeedDelete < 0) {
this.fieldIndexThatNeedDelete = Field.normedBinaryIndexOf(this.subDocument.fields, startPosition + 1);
if (this.fieldIndexThatNeedDelete < 0 || startPosition > this.subDocument.fields[this.fieldIndexThatNeedDelete].getFieldStartPosition())
this.fieldIndexThatNeedDelete++;
}
Field.deleteFieldByIndex(this.subDocument, this.fieldIndexThatNeedDelete, this.modelManipulator);
}
tryPackSelectionInOneRun(interval, result) {
const runInfo = this.subDocument.getRunAndIndexesByPosition(interval.start);
const runStartPosition = runInfo.chunk.startLogPosition.value + runInfo.run.startOffset;
const runEndPosition = runStartPosition + runInfo.run.getLength();
const selectionEndPosition = interval.end;
const selectionStartPosition = interval.start;
if ((runStartPosition < selectionStartPosition) && (selectionEndPosition < runEndPosition)) {
const chunkStartPosition = runInfo.chunk.startLogPosition.value;
const offsetStartSelectionAtChunk = selectionStartPosition - chunkStartPosition;
const offsetEndSelectionAtChunk = selectionEndPosition - chunkStartPosition;
const removedText = runInfo.chunk.getTextInChunk(offsetStartSelectionAtChunk, interval.length);
result.registerItem(new HistoryRun(runInfo.run.getType(), runInfo.run.getCharPropsBundle(this.modelManipulator.model), selectionStartPosition, removedText));
runInfo.run.incLength(-interval.length);
runInfo.chunk.textBuffer = [runInfo.chunk.textBuffer.substr(0, offsetStartSelectionAtChunk), runInfo.chunk.textBuffer.substr(offsetEndSelectionAtChunk)].join('');
const paragraphIndex = SearchUtils.normedInterpolationIndexOf(this.subDocument.paragraphs, (p) => p.startLogPosition.value, selectionStartPosition);
this.subDocument.paragraphs[paragraphIndex].length -= interval.length;
const sectionIndex = SearchUtils.normedInterpolationIndexOf(this.subDocument.documentModel.sections, (s) => s.startLogPosition.value, selectionStartPosition);
this.modifySectionLength(this.subDocument.documentModel.sections[sectionIndex], -interval.length);
RunsBaseManipulator.moveRunsInChunk(runInfo.chunk, runInfo.runIndex + 1, -interval.length);
this.subDocument.positionManager.advance(selectionStartPosition, -interval.length);
this.modelManipulator.notifyModelChanged(new IntervalRemovedSubDocumentChange(this.subDocument.id, interval, removedText));
return true;
}
return false;
}
canRemoveRun(run, absolutePosition, isLastRunInParagraph) {
if (run.getType() === RunType.ParagraphRun) {
this.cellsIterator.moveTo(absolutePosition);
let currentCell = this.cellsIterator.getCurrent();
if (currentCell && absolutePosition === currentCell.endParagrapPosition.value - 1)
return false;
let nextCell = this.cellsIterator.getNext();
if (nextCell && nextCell.startParagraphPosition.value === absolutePosition + 1) {
if (!isLastRunInParagraph)
return false;
let prevCell = this.cellsIterator.getPrev();
if (prevCell && prevCell.parentRow.parentTable.getLastCell() === prevCell)
return false;
}
}
return true;
}
fillResult(interval, result) {
var iterator = this.subDocument.getRunIterator(interval);
var isInsertPropertiesAndStyleIndexToCurrentParagraph = undefined;
var lastParagraphRemovingLength = 0;
while (iterator.moveNext()) {
var currentRun = iterator.currentRun;
var currentChunk = iterator.currentChunk;
var currentInterval = iterator.currentInterval();
lastParagraphRemovingLength += currentInterval.length;
if (!this.canRemoveRun(currentRun, currentInterval.start, iterator.currentRun.paragraph.length === lastParagraphRemovingLength)) {
if (currentRun.isParagraphOrSectionRun())
lastParagraphRemovingLength = 0;
continue;
}
switch (currentRun.getType()) {
case RunType.TextRun:
result.registerItem(new HistoryRun(currentRun.getType(), currentRun.getCharPropsBundle(this.modelManipulator.model), currentInterval.start, currentChunk.getRunText(currentRun)));
break;
case RunType.ParagraphRun:
case RunType.SectionRun:
if (isInsertPropertiesAndStyleIndexToCurrentParagraph === undefined)
isInsertPropertiesAndStyleIndexToCurrentParagraph = currentRun.paragraph.startLogPosition.value == interval.start;
var paragraph;
if (isInsertPropertiesAndStyleIndexToCurrentParagraph)
paragraph = currentRun.paragraph;
else {
var nextParagraphIndex = SearchUtils.normedInterpolationIndexOf(this.subDocument.paragraphs, (p) => p.startLogPosition.value, currentRun.paragraph.startLogPosition.value) + 1;
paragraph = this.subDocument.paragraphs[nextParagraphIndex];
}
if (currentRun.getType() == RunType.ParagraphRun) {
result.registerItem(new HistoryRunParagraph(currentRun.getType(), currentRun.getCharPropsBundle(this.modelManipulator.model), paragraph.getParagraphBundleFull(this.modelManipulator.model), currentInterval.start, currentChunk.getRunText(currentRun), isInsertPropertiesAndStyleIndexToCurrentParagraph));
}
else {
result.registerItem(new HistoryRunSection(currentRun.getCharPropsBundle(this.modelManipulator.model), paragraph.getParagraphBundleFull(this.modelManipulator.model), iterator.currentSection, currentInterval.start, isInsertPropertiesAndStyleIndexToCurrentParagraph));
}
lastParagraphRemovingLength = 0;
break;
case RunType.InlinePictureRun:
var currentPictureRun = currentRun;
if (!(currentPictureRun instanceof InlinePictureRun))
throw new Error("In TexManipulator.getHistoryRunsFromInterval currentPictureRun not have type InlinePictureRun");
result.registerItem(new HistoryRunInlinePicture(currentInterval.start, currentRun.getCharPropsBundle(this.modelManipulator.model), currentPictureRun.info.clone()));
break;
case RunType.FieldCodeStartRun:
var globalOffset = currentInterval.start;
var fieldIndex = Field.normedBinaryIndexOf(this.subDocument.fields, globalOffset + 1);
var field = this.subDocument.fields[fieldIndex];
result.registerItem(new HistoryRunFieldCodeStart(currentRun.getType(), currentRun.getCharPropsBundle(this.modelManipulator.model), globalOffset, currentChunk.getRunText(currentRun), field.showCode, field.getFieldStartPosition(), field.getSeparatorPosition(), field.getFieldEndPosition(), field.getHyperlinkInfo() ? field.getHyperlinkInfo().clone() : undefined));
break;
case RunType.FieldCodeEndRun:
result.registerItem(new HistoryRunFieldCodeEnd(currentRun.getType(), currentRun.getCharPropsBundle(this.modelManipulator.model), currentInterval.start, currentChunk.getRunText(currentRun)));
break;
case RunType.FieldResultEndRun:
result.registerItem(new HistoryRunFieldResultEnd(currentRun.getType(), currentRun.getCharPropsBundle(this.modelManipulator.model), currentInterval.start, currentChunk.getRunText(currentRun)));
break;
case RunType.AnchoredPictureRun:
var currentAnchoredRun = currentRun;
if (!(currentAnchoredRun instanceof AnchoredPictureRun))
throw new Error("In TextManipulator.getHistoryRunsFromInterval currentAnchoredRun is not of type AnchoredPictureRun");
result.registerItem(new HistoryRunAnchoredPicture(currentRun.getCharPropsBundle(this.modelManipulator.model), currentAnchoredRun.info.clone(), currentInterval.start));
break;
case RunType.AnchoredTextBoxRun:
const currentAnchoredTextBoxRun = currentRun;
if (!(currentAnchoredTextBoxRun instanceof AnchoredTextBoxRun))
throw new Error("In TextManipulator.getHistoryRunsFromInterval currentAnchoredTextBoxRun is not of type AnchoredTextBoxRun");
result.registerItem(new HistoryRunAnchoredTextBox(currentRun.getCharPropsBundle(this.modelManipulator.model), new BaseTextBoxInfo(this.modelManipulator.model.subDocuments[currentAnchoredTextBoxRun.subDocId], currentAnchoredTextBoxRun.size.clone(), currentAnchoredTextBoxRun.shape.clone(), currentAnchoredTextBoxRun.anchorInfo.clone(), currentAnchoredTextBoxRun.textBoxProperties.clone(), currentAnchoredTextBoxRun.containerProperties.clone()), currentInterval.start));
break;
}
}
iterator.reset();
this.cellsIterator.reset();
}
removeAccumulatedInterval(removingInterval, newPosition, advanceDelta, removedTextList) {
advanceDelta -= removingInterval.length;
if (Math.abs(advanceDelta) > 0)
this.subDocument.positionManager.advance(removingInterval.start, advanceDelta);
if (removingInterval.length) {
const removedText = removedTextList.join('');
this.modelManipulator.notifyModelChanged(new IntervalRemovedSubDocumentChange(this.subDocument.id, removingInterval.clone(), removedText));
removedTextList.splice(0);
}
removingInterval.start = newPosition;
removingInterval.length = 0;
}
mergeParagraphsInternal(subDocument, paragraphIndex, setPropertiesSecondParagraph) {
var firstParagraph = subDocument.paragraphs[paragraphIndex];
var lastParagraph = subDocument.paragraphs[paragraphIndex + 1];
var runInfo = subDocument.getRunAndIndexesByPosition(lastParagraph.startLogPosition.value - 1);
if (setPropertiesSecondParagraph)
firstParagraph.copyFrom(lastParagraph);
var runs = subDocument.getRunsByInterval(new FixedInterval(lastParagraph.startLogPosition.value, lastParagraph.length));
var chunkIndexDelta = this.currentChunkIndex - runInfo.chunkIndex;
this.currentChunkIndex = runInfo.chunkIndex;
this.removeRunInternal(subDocument, runInfo.runIndex);
this.currentChunkIndex += chunkIndexDelta;
firstParagraph.length--;
for (var i = 0, run; run = runs[i]; i++) {
run.paragraph = firstParagraph;
run.onCharacterPropertiesChanged();
firstParagraph.length += run.getLength();
}
subDocument.positionManager.advance(lastParagraph.startLogPosition.value, -1, -1);
subDocument.positionManager.unregisterPosition(lastParagraph.startLogPosition);
subDocument.paragraphs.splice(paragraphIndex + 1, 1);
}
removeRunInternal(subDocument, runIndex) {
const currentChunk = subDocument.chunks[this.currentChunkIndex];
const currentRun = currentChunk.textRuns[runIndex];
const removedText = currentChunk.textBuffer.substr(currentRun.startOffset, currentRun.getLength());
currentChunk.textBuffer = currentChunk.textBuffer.substr(0, currentRun.startOffset) + currentChunk.textBuffer.substr(currentRun.startOffset + currentRun.getLength());
currentChunk.textRuns.splice(runIndex, 1);
RunsBaseManipulator.moveRunsInChunk(currentChunk, runIndex, -currentRun.getLength());
if (currentChunk.textRuns.length === 0) {
subDocument.positionManager.unregisterPosition(currentChunk.startLogPosition);
subDocument.chunks.splice(this.currentChunkIndex--, 1);
}
return removedText;
}
}
export class RemoveIntervalOperationResult {
constructor(cellsIterator) {
this.historyRuns = [];
this.nestingLevels = [];
this.bookmarkItems = [];
this.rangePermssionsItems = [];
this.cellsIterator = cellsIterator;
}
registerItem(historyRun) {
this.cellsIterator.moveTo(historyRun.offsetAtStartDocument);
var cell = this.cellsIterator.getCurrent();
this.registerItemCore(historyRun, cell ? cell.parentRow.parentTable.nestedLevel : -1);
}
registerItemCore(historyRun, nestingLevel) {
this.historyRuns.push(historyRun);
this.nestingLevels.push(nestingLevel);
}
removeLastParagraphRun() {
var lastIndex = this.historyRuns.length - 1;
var lastHistoryRun = this.historyRuns[lastIndex];
if (lastHistoryRun && lastHistoryRun.type == RunType.ParagraphRun) {
this.historyRuns.splice(lastIndex, 1);
this.nestingLevels.splice(lastIndex, 1);
}
}
getIterator() {
return new RemoveIntervalOperationResultIterator(this.historyRuns, this.nestingLevels);
}
}
export class SelectedCellsIterator {
constructor(subDocument, interval) {
this.current = 0;
this.cells = SelectedCellsIterator.getCellsByInterval(subDocument, interval);
}
moveTo(position) {
if (position < this.position)
this.reset();
this.position = position;
let cell;
while (cell = this.cells[this.current]) {
if (position >= cell.endParagrapPosition.value)
this.current++;
else
return true;
}
return false;
}
getCurrent() {
let cell = this.cells[this.current];
return cell ? SelectedCellsIterator.correctCurrent(this.position, cell) : null;
}
getPrev() {
let cell = this.cells[this.current];
if (cell && this.position >= cell.endParagrapPosition.value)
return cell;
return this.cells[this.current - 1] || null;
}
getNext() {
let cell = this.cells[this.current];
if (cell && this.position < cell.startParagraphPosition.value)
return cell;
return this.cells[this.current + 1] || null;
}
reset() {
this.current = 0;
this.position = 0;
}
static getCellsByInterval(subDocument, interval) {
if (subDocument.tables.length === 0)
return [];
let table = subDocument.tablesByLevels[0][Math.max(0, SearchUtils.normedInterpolationIndexOf(subDocument.tablesByLevels[0], t => t.getStartPosition(), interval.start))];
let intervalEnd = interval.end;
if (intervalEnd < table.getStartPosition())
return [];
let result = [];
this.collectCellsByIntervalCore(subDocument, result, table, interval.start, intervalEnd);
return result.sort((c1, c2) => c1.endParagrapPosition.value - c2.endParagrapPosition.value);
}
static collectCellsByIntervalCore(subDocument, result, table, intervalStart, intervalEnd) {
let nextTable = subDocument.tables[table.index + 1];
if (nextTable && nextTable.getStartPosition() <= intervalEnd)
this.collectCellsByIntervalCore(subDocument, result, nextTable, intervalStart, intervalEnd);
for (let rowIndex = 0, row; row = table.rows[rowIndex]; rowIndex++) {
for (let cellIndex = 0, cell; cell = row.cells[cellIndex]; cellIndex++) {
if (intervalStart < cell.endParagrapPosition.value && intervalEnd > cell.startParagraphPosition.value)
result.push(cell);
else if (intervalStart === cell.endParagrapPosition.value && cell.parentRow.parentTable.getLastCell() === cell)
result.push(cell);
else if (cell.parentRow.parentTable.getFirstCell() === cell && cell.startParagraphPosition.value === intervalEnd)
result.push(cell);
else if (cell.startParagraphPosition.value > intervalEnd)
return;
}
}
}
static correctCurrent(position, cell) {
if (position >= cell.startParagraphPosition.value && position < cell.endParagrapPosition.value)
return cell;
if (position < cell.startParagraphPosition.value && cell.parentRow.parentTable.parentCell)
return this.correctCurrent(position, cell.parentRow.parentTable.parentCell);
return null;
}
}
export class RemoveIntervalOperationResultIterator {
constructor(historyRuns, nestingLevels) {
this.position = -1;
this.historyRuns = historyRuns;
this.nestingLevels = nestingLevels;
}
moveNext() {
this.position++;
this.currentHistoryRun = this.historyRuns[this.position];
this.currentNestingLevel = this.nestingLevels[this.position];
return !!this.currentHistoryRun;
}
}