devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
125 lines (124 loc) • 5.38 kB
JavaScript
import { ColumnChange } from '../changes/column-change';
import { LayoutChangeType, ParagraphFrameChange, RowChange, TableChange } from '../changes/layout-change-base';
import { PageAreaChange } from '../changes/page-area-change';
import { PageChange } from '../changes/page-change';
export class ChangesMerger {
merge(changes) {
this.resultChanges = [];
this.infos = [];
this.fillTo(0);
for (var change of changes)
switch (change.changeType) {
case LayoutChangeType.Inserted:
this.handleInsertedChange(change);
break;
case LayoutChangeType.Deleted:
this.handleDeletedChange(change);
break;
case LayoutChangeType.Replaced:
this.handleReplacedChange(change, ChangesMergerInfoType.Replaced);
break;
case LayoutChangeType.Updated:
this.handleReplacedChange(change, ChangesMergerInfoType.Updated);
break;
}
this.collectFinalChanges();
return this.resultChanges;
}
fillTo(lastIndex) {
while (this.infos.length <= lastIndex)
this.infos.push(new ChangesMergerInfo(ChangesMergerInfoType.None, null, 0));
}
handleDeletedChange(change) {
this.fillTo(change.index);
const delPageInfo = this.infos.splice(change.index + 1, 1)[0];
this.infos[change.index].numElemsDeletedAfterThis += 1 + (delPageInfo ? delPageInfo.numElemsDeletedAfterThis : 0);
}
handleInsertedChange(change) {
this.fillTo(change.index);
const prevPageInfo = this.infos[change.index];
this.infos.splice(change.index + 1, 0, prevPageInfo.numElemsDeletedAfterThis ?
new ChangesMergerInfo(ChangesMergerInfoType.Replaced, this.changeConstructor(change.index, LayoutChangeType.Replaced), prevPageInfo.numElemsDeletedAfterThis - 1) :
new ChangesMergerInfo(ChangesMergerInfoType.Inserted, change, 0));
prevPageInfo.numElemsDeletedAfterThis = 0;
}
handleReplacedChange(change, infoType) {
this.fillTo(change.index + 1);
const info = this.infos[change.index + 1];
switch (info.type) {
case ChangesMergerInfoType.Inserted:
case ChangesMergerInfoType.Replaced:
break;
case ChangesMergerInfoType.None:
case ChangesMergerInfoType.Updated:
if (infoType == ChangesMergerInfoType.Updated && info.type == ChangesMergerInfoType.Updated) {
info.change.summarizeChanges(change);
}
else {
info.type = infoType;
info.change = change;
}
break;
}
}
collectFinalChanges() {
for (let infoIndex = 0, info; info = this.infos[infoIndex]; infoIndex++) {
switch (info.type) {
case ChangesMergerInfoType.Inserted:
case ChangesMergerInfoType.Replaced:
case ChangesMergerInfoType.Updated:
info.change.index = infoIndex - 1;
this.resultChanges.push(info.change);
break;
case ChangesMergerInfoType.None:
break;
}
for (; info.numElemsDeletedAfterThis; info.numElemsDeletedAfterThis--)
this.resultChanges.push(this.changeConstructor(infoIndex, LayoutChangeType.Deleted));
}
}
}
export class LayoutPageChangesMerger extends ChangesMerger {
changeConstructor(index, changeType) {
return new PageChange(index, changeType, [], []);
}
}
export class LayoutPageAreaChangesMerger extends ChangesMerger {
changeConstructor(index, changeType) {
return new PageAreaChange(index, changeType, []);
}
}
export class LayoutColumnChangesMerger extends ChangesMerger {
changeConstructor(index, changeType) {
return new ColumnChange(index, changeType, [], [], []);
}
}
export class LayoutRowChangesMerger extends ChangesMerger {
changeConstructor(index, changeType) {
return new RowChange(index, changeType);
}
}
export class LayoutTableChangesMerger extends ChangesMerger {
changeConstructor(index, changeType) {
return new TableChange(index, changeType);
}
}
export class LayoutParagraphFrameChangesMerger extends ChangesMerger {
changeConstructor(index, changeType) {
return new ParagraphFrameChange(index, changeType);
}
}
class ChangesMergerInfo {
constructor(type, change, numElemsDeletedAfterThis) {
this.type = type;
this.change = change;
this.numElemsDeletedAfterThis = numElemsDeletedAfterThis;
}
}
var ChangesMergerInfoType;
(function (ChangesMergerInfoType) {
ChangesMergerInfoType[ChangesMergerInfoType["Replaced"] = 0] = "Replaced";
ChangesMergerInfoType[ChangesMergerInfoType["Inserted"] = 1] = "Inserted";
ChangesMergerInfoType[ChangesMergerInfoType["Updated"] = 2] = "Updated";
ChangesMergerInfoType[ChangesMergerInfoType["None"] = 3] = "None";
})(ChangesMergerInfoType || (ChangesMergerInfoType = {}));