devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
424 lines (423 loc) • 20.4 kB
JavaScript
import { ListUtils } from '@devexpress/utils/lib/utils/list';
import { NumberMapUtils } from '@devexpress/utils/lib/utils/map/number';
import { SearchUtils } from '@devexpress/utils/lib/utils/search';
export class ParentLinkTableCell {
constructor() {
this.parentCell = null;
this.parentLink = null;
this.layoutRowIndexInParentCell = -1;
}
createParentLink() {
return this.createParentLinkInternal(this);
}
createParentLinkInternal(link) {
if (link.parentLink)
return this.createParentLinkInternal(link.parentLink);
var newLink = new ParentLinkTableCell();
link.parentLink = newLink;
return newLink;
}
}
export class TableCellIterator {
get tableCellInfo() {
return this.tableCellInfoInternal;
}
get isInTable() {
return this.layoutRowIndexInCell > -1;
}
constructor(position, layout, measurer) {
this.tableIndex = -1;
this.tableRowIndex = -1;
this.tableCellIndex = -1;
this.layoutRowIndexInCell = -1;
this.layoutRowIndexInLayout = -1;
this.layoutRowIndexInLayoutInitial = -1;
this.pageIndex = 0;
this.pageAreaIndex = 0;
this.columnIndex = 0;
this.skipCalculateCellIndex = false;
this.canCalculateLastCellIndex = false;
this.position = position;
this.layout = layout;
this.measurer = measurer;
this.setPositionProperties();
if (this.readTables(this.position.column.tablesInfo)) {
for (let tableIndex = 0, table; table = this.position.column.tablesInfo[tableIndex]; tableIndex++)
if (table == this.tableInfo) {
this.tableIndex = tableIndex;
break;
}
}
}
readTables(tables, parentCell = null, layountIndex = -1) {
for (let tableIndex = 0, table; table = tables[tableIndex]; tableIndex++) {
for (let rowIndex = 0, row; row = table.tableRows[rowIndex]; rowIndex++) {
for (let cellIndex = 0, cell; cell = table.tableRows[rowIndex].rowCells[cellIndex]; cellIndex++) {
for (var layountRowIndex in cell.internalTables) {
if (this.readTables(this.getConvertedObjectToArray(cell.internalTables), cell, parseInt(layountRowIndex))) {
var link = this.parentLink.createParentLink();
link.parentCell = parentCell;
link.layoutRowIndexInParentCell = layountIndex;
return true;
}
}
var index = SearchUtils.binaryIndexOf(cell.layoutRows, (row) => row.indexInColumn - this.position.rowIndex);
if (index >= 0) {
this.tableInfo = table;
this.tableRowIndex = rowIndex;
this.tableRowInfo = row;
this.tableCellIndex = cellIndex;
this.tableCellInfoInternal = cell;
this.layoutRowIndexInCell = index;
this.layoutRowIndexInLayout = cell.layoutRows[index].indexInColumn;
this.layoutRowIndexInLayoutInitial = this.layoutRowIndexInLayout;
this.parentLink = new ParentLinkTableCell();
this.parentLink.parentCell = parentCell;
this.parentLink.layoutRowIndexInParentCell = layountIndex;
return true;
}
}
}
}
return false;
}
getConvertedObjectToArray(obj) {
return NumberMapUtils.toList(obj);
}
setPositionProperties() {
this.pageIndex = this.position.pageIndex;
this.pageAreaIndex = this.position.pageAreaIndex;
this.columnIndex = this.position.columnIndex;
}
isMainSubDocument() {
return this.position.pageArea.subDocument.isMain();
}
getSelectedInterval() {
return this.tableInfo.logicInfo.grid.table.rows[this.tableRowIndex].cells[this.tableCellInfoInternal.cellGridIndex].interval;
}
getModifyPosition() {
var newPosition = this.position.clone();
if (this.isMainSubDocument()) {
newPosition.pageIndex = this.pageIndex;
newPosition.pageAreaIndex = this.pageAreaIndex;
newPosition.columnIndex = this.columnIndex;
newPosition.page = this.layout.pages[newPosition.pageIndex];
newPosition.pageArea = newPosition.page.mainSubDocumentPageAreas[newPosition.pageAreaIndex];
newPosition.column = newPosition.pageArea.columns[newPosition.columnIndex];
}
newPosition.rowIndex = this.layoutRowIndexInLayout;
newPosition.row = newPosition.column.rows[newPosition.rowIndex];
return newPosition;
}
tryAdvanceToRightCell() {
this.skipCalculateCellIndex = true;
this.tableCellIndex++;
if (this.tableCellIndex >= this.tableRowInfo.rowCells.length) {
this.tableCellIndex = 0;
return this.tryAdvanceToBelowRowInternal();
}
return this.updateTableInfosIfAdvanceToBelowRow();
}
tryAdvanceToLeftCell() {
this.skipCalculateCellIndex = true;
this.tableCellIndex--;
if (this.tableCellIndex < 0) {
this.canCalculateLastCellIndex = true;
return this.tryAdvanceToAboveRowInternal();
}
return this.updateTableInfosIfAdvanceToAboveRow();
}
tryAdvanceToBelowRow() {
if (!this.canAdvanceToBelowRow())
return false;
return this.tryAdvanceToBelowRowInternal();
}
tryAdvanceToBelowRowInternal() {
this.isDownDirection = true;
this.tableRowIndex++;
if (this.tableRowIndex >= this.tableInfo.tableRows.length) {
this.tableRowIndex = 0;
this.tableIndex = 0;
if (!this.isMainSubDocument())
return this.tryAdvanceToLayoutRowBelowTable();
this.columnIndex++;
if (this.columnIndex >= this.position.pageArea.columns.length) {
this.columnIndex = 0;
this.pageAreaIndex++;
if (this.pageAreaIndex >= this.position.page.mainSubDocumentPageAreas.length) {
this.pageAreaIndex = 0;
this.pageIndex++;
if (this.pageIndex >= this.layout.validPageCount)
return this.tryAdvanceToLayoutRowBelowTable();
}
}
}
if (this.updateTableInfosIfAdvanceToBelowRow())
return true;
return this.tryAdvanceToLayoutRowBelowTable();
}
updateTableInfosIfAdvanceToBelowRow() {
var tables = this.getTables();
if (tables.length > 0 && this.isEqualTables(tables[this.tableIndex], this.tableInfo)) {
this.tableInfo = tables[this.tableIndex];
this.tableRowInfo = this.tableInfo.tableRows[this.tableRowIndex];
if (!this.skipCalculateCellIndex)
this.tableCellIndex = this.findNextCellIndex(this.tableRowInfo);
this.tableCellInfoInternal = this.tableRowInfo.rowCells[this.tableCellIndex];
while (!this.tableCellInfoInternal.layoutRows.length) {
this.tableInfo = this.tableCellInfoInternal.internalTables[0];
this.tableRowIndex = 0;
this.tableRowInfo = this.tableInfo.tableRows[this.tableRowIndex];
this.tableCellIndex = 0;
this.tableCellInfoInternal = this.tableRowInfo.rowCells[this.tableCellIndex];
}
this.layoutRowIndexInLayout = this.tableCellInfoInternal.layoutRows[0].indexInColumn;
this.goToInternalTableIfExistInFirstBelowRow();
return true;
}
return false;
}
tryAdvanceToAboveRow() {
if (!this.canAdvanceToAboveRow())
return false;
return this.tryAdvanceToAboveRowInternal();
}
getLayoutTablesAssociatedWithLogicGrid() {
var list = [];
this.setPositionProperties();
list.push(this.tableInfo);
while (this.tryAdvanceToAboveTable())
list.push(this.tableInfo);
return list;
}
tryAdvanceToAboveTable() {
var columnIndexReset = false;
var pageAreaIndexReset = false;
this.columnIndex--;
if (this.columnIndex < 0) {
columnIndexReset = true;
this.pageAreaIndex--;
if (this.pageAreaIndex < 0)
pageAreaIndexReset = true;
this.pageIndex--;
if (this.pageIndex < 0)
return false;
}
if (pageAreaIndexReset)
this.pageAreaIndex = this.layout.pages[this.pageIndex].mainSubDocumentPageAreas.length - 1;
if (columnIndexReset)
this.columnIndex = this.layout.pages[this.pageIndex].mainSubDocumentPageAreas[this.pageAreaIndex].columns.length - 1;
var tables = this.layout.pages[this.pageIndex].mainSubDocumentPageAreas[this.pageAreaIndex].columns[this.columnIndex].tablesInfo;
for (let t, i = 0; t = tables[i]; i++) {
if (t.logicInfo.grid == this.tableInfo.logicInfo.grid) {
this.tableInfo = t;
return true;
}
}
return false;
}
tryAdvanceToAboveRowInternal() {
var rowIndexReset = false, columnIndexReset = false, pageAreaIndexReset = false;
this.isDownDirection = false;
if (this.tableCellInfoInternal.layoutRows.length == 1 && this.tableCellInfoInternal.internalTables[this.layoutRowIndexInCell])
if (this.goToInternalTableIfExistInLastAboveRow())
return true;
var tables = [];
this.tableRowIndex--;
if (this.tableRowIndex < 0) {
if (!this.isMainSubDocument())
return this.tryAdvanceToLayoutRowAboveTable();
rowIndexReset = true;
this.columnIndex--;
if (this.columnIndex < 0) {
columnIndexReset = true;
this.pageAreaIndex--;
if (this.pageAreaIndex < 0) {
pageAreaIndexReset = true;
this.pageIndex--;
if (this.pageIndex < 0)
return this.tryAdvanceToLayoutRowAboveTable();
}
}
if (pageAreaIndexReset)
this.pageAreaIndex = this.layout.pages[this.pageIndex].mainSubDocumentPageAreas.length - 1;
if (columnIndexReset)
this.columnIndex = this.layout.pages[this.pageIndex].mainSubDocumentPageAreas[this.pageAreaIndex].columns.length - 1;
if (rowIndexReset) {
tables = this.getTables();
if (tables.length == 0)
return false;
this.tableIndex = tables.length - 1;
this.tableRowIndex = tables[this.tableIndex].tableRows.length - 1;
}
}
if (this.updateTableInfosIfAdvanceToAboveRow())
return true;
return this.tryAdvanceToLayoutRowAboveTable();
}
updateTableInfosIfAdvanceToAboveRow() {
var tables = this.getTables();
if (tables.length > 0 && this.isEqualTables(tables[this.tableIndex], this.tableInfo)) {
this.tableInfo = tables[this.tableIndex];
this.tableRowInfo = this.tableInfo.tableRows[this.tableRowIndex];
if (!this.skipCalculateCellIndex) {
this.tableCellIndex = this.findNextCellIndex(this.tableRowInfo);
this.tableRowInfo = this.tableInfo.tableRows[this.tableRowIndex];
}
if (this.canCalculateLastCellIndex)
this.tableCellIndex = this.tableRowInfo.rowCells.length - 1;
this.tableCellInfoInternal = this.tableRowInfo.rowCells[this.tableCellIndex];
this.layoutRowIndexInLayout = this.tableCellInfoInternal.layoutRows[this.tableCellInfoInternal.layoutRows.length - 1].indexInColumn;
this.goToInternalTableIfExistInLastAboveRow();
return true;
}
return false;
}
tryAdvanceToLayoutRowBelowTable() {
this.setPositionProperties();
var row = ListUtils.last(ListUtils.last(ListUtils.last(this.tableInfo.tableRows).rowCells).layoutRows);
var column = this.layout.pages[this.pageIndex].mainSubDocumentPageAreas[this.pageAreaIndex].columns[this.columnIndex];
this.layoutRowIndexInLayout = row.indexInColumn + 1;
if (this.layoutRowIndexInLayout >= column.rows.length) {
this.columnIndex++;
if (this.columnIndex >= this.position.pageArea.columns.length) {
this.columnIndex = 0;
this.pageAreaIndex++;
if (this.pageAreaIndex >= this.position.page.mainSubDocumentPageAreas.length) {
this.pageAreaIndex = 0;
this.pageIndex++;
if (this.pageIndex >= this.layout.validPageCount) {
this.setPositionProperties();
this.resetLayoutRowIndex();
return true;
}
}
}
this.layoutRowIndexInLayout = 0;
}
return true;
}
isAboveLayoutRowOuterTable() {
return this.parentLink && this.parentLink.parentCell && this.parentLink.layoutRowIndexInParentCell == 0;
}
tryAdvanceToLayoutRowOuterTable(parentLink) {
var parentRow = parentLink.parentCell.parentRow;
var parentTable = parentRow.parentTable;
if (parentRow.rowIndex == 0 && parentLink.parentLink.parentCell)
return this.tryAdvanceToLayoutRowOuterTable(parentLink.parentLink);
if (parentRow.rowIndex > 0) {
var index = this.findNextCellIndex(parentTable.tableRows[parentRow.rowIndex - 1], true);
this.layoutRowIndexInLayout = ListUtils.last(parentTable.tableRows[parentRow.rowIndex - 1].rowCells[index].layoutRows).indexInColumn;
return true;
}
return false;
}
tryAdvanceToLayoutRowAboveTable() {
this.setPositionProperties();
if (this.isAboveLayoutRowOuterTable())
return this.tryAdvanceToLayoutRowOuterTable(this.parentLink);
var columnIndexReset = false, pageAreaIndexReset = false;
var row = this.tableInfo.tableRows[0].rowCells[0].layoutRows[0];
this.layoutRowIndexInLayout = row.indexInColumn - 1;
if (this.layoutRowIndexInLayout < 0) {
this.columnIndex--;
if (this.columnIndex < 0) {
columnIndexReset = true;
this.pageAreaIndex--;
if (this.pageAreaIndex < 0) {
pageAreaIndexReset = true;
this.pageIndex--;
if (this.pageIndex < 0) {
this.setPositionProperties();
this.resetLayoutRowIndex();
return true;
}
}
}
if (pageAreaIndexReset)
this.pageAreaIndex = this.layout.pages[this.pageIndex].mainSubDocumentPageAreas.length - 1;
if (columnIndexReset)
this.columnIndex = this.layout.pages[this.pageIndex].mainSubDocumentPageAreas[this.pageAreaIndex].columns.length - 1;
var rows = this.layout.pages[this.pageIndex].mainSubDocumentPageAreas[this.pageAreaIndex].columns[this.columnIndex].rows;
this.layoutRowIndexInLayout = rows.length - 1;
}
return true;
}
goToInternalTableIfExistInFirstBelowRow() {
if (this.tableCellInfoInternal.internalTables && this.tableCellInfoInternal.internalTables[0]) {
var internalTable = this.tableCellInfoInternal.internalTables[0];
this.tableCellInfoInternal = internalTable.tableRows[0].rowCells[this.findNextCellIndex(internalTable.tableRows[0])];
if (this.goToInternalTableIfExistInFirstBelowRow())
return true;
this.layoutRowIndexInLayout = this.tableCellInfoInternal.layoutRows[0].indexInColumn;
return true;
}
return false;
}
goToInternalTableIfExistInLastAboveRow() {
var lastLayoutRowIndexInInternalTable = this.tableCellInfoInternal.layoutRows.length - 1;
if (this.tableCellInfoInternal.internalTables && this.tableCellInfoInternal.internalTables[lastLayoutRowIndexInInternalTable]) {
var internalTable = this.tableCellInfoInternal.internalTables[lastLayoutRowIndexInInternalTable];
var lastTableRowIndex = internalTable.tableRows.length - 1;
var cellIndexInInternalTable = this.findNextCellIndex2(internalTable.tableRows[lastTableRowIndex]);
var lastLayoutRowIndex = internalTable.tableRows[lastTableRowIndex].rowCells[cellIndexInInternalTable].layoutRows.length - 1;
this.layoutRowIndexInLayout = internalTable.tableRows[lastTableRowIndex].rowCells[cellIndexInInternalTable].layoutRows[lastLayoutRowIndex].indexInColumn;
return true;
}
return false;
}
canAdvanceToBelowRow() {
return this.isInTable && this.layoutRowIndexInCell == this.tableCellInfoInternal.layoutRows.length - 1;
}
canAdvanceToAboveRow() {
return this.isInTable && this.layoutRowIndexInCell == 0;
}
resetLayoutRowIndex() {
this.layoutRowIndexInLayout = this.layoutRowIndexInLayoutInitial;
}
isEqualTables(table1, table2) {
return table1.logicInfo.grid == table2.logicInfo.grid;
}
getTables() {
if (this.isMainSubDocument())
return this.layout.pages[this.pageIndex].mainSubDocumentPageAreas[this.pageAreaIndex].columns[this.columnIndex].tablesInfo;
return this.position.column.tablesInfo;
}
findNextCellIndex(newRow, skipSearchCellInAllTable = false) {
var x = this.position.box.getCharOffsetXInPixels(this.measurer, this.position.charOffset) + this.position.box.x + this.position.row.x;
if (!this.isDownDirection && !skipSearchCellInAllTable) {
for (let tableRowInfoIndex = this.tableRowIndex; tableRowInfoIndex >= 0; tableRowInfoIndex--) {
const tableRowInfo = this.tableInfo.tableRows[tableRowInfoIndex];
const tableCellInfoIndex = Math.max(0, SearchUtils.normedInterpolationIndexOf(tableRowInfo.rowCells, (c) => c.x, x));
var tableCellInfo = tableRowInfo.rowCells[tableCellInfoIndex];
if (x >= tableCellInfo.x && x <= (tableCellInfo.x + tableCellInfo.width)) {
this.tableRowIndex = tableRowInfoIndex;
return tableCellInfoIndex;
}
}
}
for (var i = 0; i < newRow.rowCells.length; i++) {
var cell = newRow.rowCells[i];
if (x >= cell.x && x <= cell.right)
return i;
}
return 0;
}
findNextCellIndex2(newRow) {
var x = this.position.box.getCharOffsetXInPixels(this.measurer, this.position.charOffset) + this.position.box.x + this.position.row.x;
if (!this.isDownDirection) {
const tableCellInfoIndex = Math.max(0, SearchUtils.normedInterpolationIndexOf(newRow.rowCells, (c) => c.x, x));
var tableCellInfo = newRow.rowCells[tableCellInfoIndex];
if (x >= tableCellInfo.x && x <= (tableCellInfo.right)) {
this.tableRowIndex = newRow.rowIndex;
return tableCellInfoIndex;
}
}
for (var i = 0; i < newRow.rowCells.length; i++) {
var cell = newRow.rowCells[i];
if (x >= cell.x && x <= cell.right)
return i;
}
return 0;
}
}