devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
104 lines (103 loc) • 5.15 kB
JavaScript
import { CompatibilityMode } from '../../model/document-model';
import { Errors } from '@devexpress/utils/lib/errors';
import { Polygon } from '@devexpress/utils/lib/geometry/polygon';
import { Rectangle } from '@devexpress/utils/lib/geometry/rectangle';
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 { NumberMapUtils } from '@devexpress/utils/lib/utils/map/number';
import { AnchoredObjectLevelType } from '../../layout/main-structures/layout-boxes/layout-anchored-object-box';
import { AnchorObjectTextWrapSide, AnchorObjectTextWrapType } from '../../model/floating-objects/enums';
export class RectangleRowBoundsCalculatorInfo extends Rectangle {
}
export class AnchorObjectBoundsInfo {
constructor(bounds, cell) {
this.bounds = bounds;
this.cell = cell;
this.canPutTextAtRight = false;
this.canPutTextAtLeft = false;
}
}
export class LayoutRowBoundsCalculator {
getRectangleBounds(manager) {
const tableFormatter = manager.activeFormatter.tableFormatter;
if (!tableFormatter) {
const ignoreFloatingObjectsInHeaderFooter = manager.model.compatibilitySettings.compatibilityMode < CompatibilityMode.Word2013;
if (manager.activeFormatter.subDocument.isHeaderFooter() && ignoreFloatingObjectsInHeaderFooter)
return [];
else
return this.rectangleBounds;
}
const posInfo = manager.layout.anchorObjectsPositionInfo;
const tableEndPos = tableFormatter.tableInfo.table.getEndPosition();
return ListUtils.reducedMap(this.rectangleBounds, (b, i) => posInfo.getPosition(this.ancObjectsId[i]) < tableEndPos ? b : null);
}
addTableInTextObject(obj, horizOuterBounds) {
this.addAnchoredObject(obj, horizOuterBounds);
}
resetByColumn(objects, horizOuterBounds, ignoreFo) {
this.rectangleBounds = [];
this.ancObjectsId = [];
if (!ignoreFo) {
const inTextObjects = NumberMapUtils.reducedMap(objects, (obj) => obj.levelType == AnchoredObjectLevelType.InText ? obj : null);
NumberMapUtils.forEach(inTextObjects, (obj) => this.addAnchoredObject(obj, horizOuterBounds));
}
}
removeAnchorObjectId(id) {
this.ancObjectsId.splice(id, 1);
this.rectangleBounds.splice(id, 1);
}
addAnchoredObject(obj, horizOuterBounds) {
const anchorInfo = obj.anchorInfo;
const extBounds = obj.getExtendedBounds();
const center = extBounds.center;
const polygon = Polygon.fromRectangle(extBounds);
polygon.rotateAround(center, obj.rotationInRadians, false, true);
const bounds = polygon.bounds;
switch (anchorInfo.wrapType) {
case AnchorObjectTextWrapType.Tight:
case AnchorObjectTextWrapType.Through:
case AnchorObjectTextWrapType.Square: {
const info = this.createAnchorObjectBoundsInfo(anchorInfo, bounds, obj.parentCell);
LayoutRowBoundsCalculator.applySquareWrapSide(anchorInfo.wrapSide, info, horizOuterBounds);
this.rectangleBounds.push(info);
break;
}
case AnchorObjectTextWrapType.TopAndBottom: {
const info = this.createAnchorObjectBoundsInfo(anchorInfo, bounds, obj.parentCell);
info.canPutTextAtLeft = false;
info.canPutTextAtRight = false;
this.rectangleBounds.push(info);
break;
}
default: throw new Error(Errors.InternalException);
}
this.ancObjectsId.push(obj.objectId);
}
createAnchorObjectBoundsInfo(anchorInfo, bounds, cell) {
bounds.applyOffsetsOutside(anchorInfo.getDistanceMargins());
return new AnchorObjectBoundsInfo(bounds, cell);
}
static applySquareWrapSide(wrapSide, boundsInfo, horizOuterBounds) {
const bounds = boundsInfo.bounds;
const intersection = IntervalAlgorithms.getIntersectionNonNullLength(new FixedInterval(bounds.x, bounds.width), horizOuterBounds);
if (!intersection)
return;
switch (wrapSide) {
case AnchorObjectTextWrapSide.Right:
boundsInfo.canPutTextAtRight = true;
break;
case AnchorObjectTextWrapSide.Left:
boundsInfo.canPutTextAtLeft = true;
break;
case AnchorObjectTextWrapSide.Largest:
boundsInfo.canPutTextAtLeft = intersection.start - horizOuterBounds.start >= horizOuterBounds.end - intersection.end;
boundsInfo.canPutTextAtRight = !boundsInfo.canPutTextAtLeft;
break;
case AnchorObjectTextWrapSide.Both:
boundsInfo.canPutTextAtRight = true;
boundsInfo.canPutTextAtLeft = true;
break;
}
}
}