devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
106 lines (105 loc) • 6.72 kB
JavaScript
import { LayoutAnchorObjectFinder } from '../layout-engine/layout-anchor-object-finder';
import { RunType } from '../model/runs/run-type';
import { UnitConverter } from '@devexpress/utils/lib/class/unit-converter';
import { Size } from '@devexpress/utils/lib/geometry/size';
import { RichEditClientCommand } from '../commands/client-command';
import { CommandOptions } from '../commands/command-base';
import { MouseEventSource } from './mouse-event-source';
export class ResizeBoxHelper {
constructor(control, resizeBoxVisualizer) {
this.control = control;
this.resizeBoxVisualizer = resizeBoxVisualizer;
}
start(evt) {
const specialRunInfo = this.control.selection.specialRunInfo;
let pos = specialRunInfo.getPosition();
const run = this.control.selection.activeSubDocument.getRunByPosition(pos);
if (specialRunInfo.isSelectedAnchorObject) {
const parentSubDoc = specialRunInfo.getParentSubDocument();
const finder = new LayoutAnchorObjectFinder(this.control.layout, pos, parentSubDoc.id, parentSubDoc.isHeaderFooter() ? this.control.selection.pageIndex : undefined);
this.startSize = new Size(finder.obj.width, finder.obj.height);
}
else
this.startSize = Size.initByCommonAction(adp => UnitConverter.twipsToPixelsF(adp(run.size.actualSize)));
this.lockAspectRatio = run.size.lockAspectRatio;
this.rotation = UnitConverter.twipsToDegrees(run.size.rotation) * Math.PI / 180;
this.startX = evt.absolutePoint.x;
this.startY = evt.absolutePoint.y;
this.startScrollLeft = evt.scroll.x;
this.startScrollTop = evt.scroll.y;
this.lockH = evt.source == MouseEventSource.ResizeBox_S || evt.source == MouseEventSource.ResizeBox_N;
this.lockV = evt.source == MouseEventSource.ResizeBox_E || evt.source == MouseEventSource.ResizeBox_W;
this.sideH = evt.source == MouseEventSource.ResizeBox_E || evt.source == MouseEventSource.ResizeBox_NE || evt.source == MouseEventSource.ResizeBox_SE;
this.sideV = evt.source == MouseEventSource.ResizeBox_SE || evt.source == MouseEventSource.ResizeBox_S || evt.source == MouseEventSource.ResizeBox_SW;
}
move(evt) {
this.size = this.getSize(evt);
this.positionDelta = this.getPositionDelta(this.size);
this.resizeBoxVisualizer.recalculate(this.size, this.positionDelta, null);
}
end(evt) {
let run = this.control.selection.activeSubDocument.getRunByPosition(this.control.selection.specialRunInfo.getPosition());
if (!this.size) {
this.size = this.getSize(evt);
this.positionDelta = this.getPositionDelta(this.size);
}
if (run.getType() == RunType.InlinePictureRun) {
let changeInlinePictureScaleCommand = this.control.commandManager.getCommand(RichEditClientCommand.ChangeInlinePictureScale);
let originalSize = run.size.originalSize;
let newWidth = UnitConverter.pixelsToTwips(100 * this.size.width / originalSize.width);
let newHeight = UnitConverter.pixelsToTwips(100 * this.size.height / originalSize.height);
changeInlinePictureScaleCommand.execute(this.control.commandManager.isPublicApiCall, [newWidth, newHeight]);
}
else {
let layoutOptionsCommand = this.control.commandManager.getCommand(RichEditClientCommand.ShowLayoutOptionsForm);
let params = layoutOptionsCommand.createParameters(new CommandOptions(this.control));
const initParams = params.clone();
params.useAbsoluteWidth = true;
params.useAbsoluteHeight = true;
params.absoluteWidth = UnitConverter.pixelsToTwips(this.size.width);
params.absoluteHeight = UnitConverter.pixelsToTwips(this.size.height);
params.offsetX = params.offsetX + UnitConverter.pixelsToTwips(this.positionDelta.width);
params.offsetY = params.offsetY + UnitConverter.pixelsToTwips(this.positionDelta.height);
layoutOptionsCommand.applyParameters(layoutOptionsCommand.getState(), params, initParams);
}
}
getSize(evt) {
var absDeltaX = evt.absolutePoint.x - (this.startScrollLeft - evt.scroll.x) - this.startX;
var absDeltaY = evt.absolutePoint.y - (this.startScrollTop - evt.scroll.y) - this.startY;
var deltaX = absDeltaX * Math.cos(this.rotation) - (-absDeltaY) * Math.sin(this.rotation);
var deltaY = -(absDeltaX * Math.sin(this.rotation) + (-absDeltaY) * Math.cos(this.rotation));
var newWidth, newHeight;
deltaY = !this.sideV && deltaY > 0 ? Math.min(this.startSize.height + 1, deltaY) : deltaY;
deltaX = !this.sideH && deltaX > 0 ? Math.min(this.startSize.width + 1, deltaX) : deltaX;
if (!this.lockH && !this.lockV && this.lockAspectRatio) {
if (Math.abs(deltaX) > Math.abs(deltaY)) {
newWidth = this.sideH ? Math.max(1, this.startSize.width + deltaX) : (this.startSize.width - deltaX);
newHeight = this.startSize.height * (newWidth / this.startSize.width);
}
else {
newHeight = this.sideV ? Math.max(1, this.startSize.height + deltaY) : (this.startSize.height - deltaY);
newWidth = this.startSize.width * (newHeight / this.startSize.height);
}
}
else {
deltaX = this.lockH ? 0 : deltaX;
deltaY = this.lockV ? 0 : deltaY;
newWidth = Math.max(1, this.sideH ? (this.startSize.width + deltaX) : (this.startSize.width - deltaX));
newHeight = Math.max(1, this.sideV ? (this.startSize.height + deltaY) : (this.startSize.height - deltaY));
}
return new Size(newWidth, newHeight);
}
getPositionDelta(newSize) {
let deltaWidth = this.startSize.width - newSize.width;
let deltaHeight = this.startSize.height - newSize.height;
let halfDeltaWidth = (!this.lockV && (this.sideH && !this.sideV || !this.sideH && this.sideV) ? -deltaWidth : deltaWidth) / 2;
let halfDeltaHeight = deltaHeight / 2;
let deltaX = halfDeltaWidth * Math.cos(this.rotation) - halfDeltaHeight * Math.sin(this.rotation);
let deltaY = halfDeltaHeight * Math.cos(this.rotation) + halfDeltaWidth * Math.sin(this.rotation);
if ((this.sideH || this.sideV) && !(!this.lockV && this.sideH && !this.sideV)) {
deltaX = -deltaX;
deltaY = -deltaY;
}
return new Size(deltaX + deltaWidth / 2, deltaY + deltaHeight / 2);
}
}