@aurigma/design-atoms
Version:
Design Atoms is a part of Customer's Canvas SDK which allows for manipulating individual design elements through your code.
470 lines • 23.5 kB
JavaScript
import { NotImplementedException } from "@aurigma/design-atoms-model/Exception";
import { BaseItemsCommand } from "./BaseItemsCommand";
import { BaseRectangleItemHandler, LayoutItemHandler, PlaceholderItemHandler } from "../../ItemHandlers";
export class AlignItemsCommand extends BaseItemsCommand {
constructor(productHandler, historyArgs, args, _canvas) {
super(productHandler, historyArgs, args);
this._canvas = _canvas;
this._alignByPrintArea = (items, align, targetPrintArea) => {
const rotateAngle = this._productHandler.currentSurface.rotateAngle;
const itemHandlerForFirstItem = this._itemToItemHandler(items[0]);
const boundsForFirstItem = this._getItemBounds(itemHandlerForFirstItem, align);
const printAreaBounds = this._getPrintArea(boundsForFirstItem, targetPrintArea).bounds;
const changedItems = [];
items.forEach(item => {
const itemHandler = this._itemToItemHandler(item);
const itemBounds = this._getItemBounds(itemHandler, align);
const originalRectangle = itemHandler.rectangle.clone();
let alignedRectangle;
const adjustedAlign = this._adjustAlignParameterByRotateAngle(rotateAngle, align);
const regionExists = itemHandler.layer.region != null;
if (regionExists)
alignedRectangle = this._getRectangleAlignedToRegion(itemBounds, itemHandler, adjustedAlign);
else
alignedRectangle = this._getRectangleAlignedToPrintArea(itemBounds, itemHandler, adjustedAlign, printAreaBounds);
alignedRectangle = this._adjustAlignedRectangleForInteractiveItem(alignedRectangle, originalRectangle, itemBounds, itemHandler, adjustedAlign);
const applyAlignmentToItemHandlerFunc = this._getApplyAlignStrategy(itemHandler, alignedRectangle, originalRectangle);
applyAlignmentToItemHandlerFunc();
const hasChanged = !originalRectangle.equals(alignedRectangle);
if (hasChanged)
changedItems.push(item);
});
return changedItems;
};
this._alignBySelectionBounds = (items, align) => {
const rotateAngle = this._productHandler.currentSurface.rotateAngle;
var baseRect = this._canvas.selection.visibleRectangle;
const changedItems = [];
items.forEach(item => {
const itemHandler = this._itemToItemHandler(item);
const bounds = this._getItemBounds(itemHandler, align);
const originalRectangle = itemHandler.rectangle.clone();
let alignedRectangle;
const adjustedAlign = this._adjustAlignParameterByRotateAngle(rotateAngle, align);
alignedRectangle = this._getRectangleAlignedToBoundBox(baseRect, bounds, itemHandler, adjustedAlign);
itemHandler.setRectangle(alignedRectangle);
const applyAlignmentToItemHandlerFunc = this._getApplyAlignStrategy(itemHandler, alignedRectangle, originalRectangle);
applyAlignmentToItemHandlerFunc();
const hasChanged = !originalRectangle.equals(alignedRectangle);
if (hasChanged)
changedItems.push(item);
});
return changedItems;
};
this._alignBySafeArea = (items, align, targetSafeArea) => {
const rotateAngle = this._productHandler.currentSurface.rotateAngle;
const itemHandlerForFirstItem = this._itemToItemHandler(items[0]);
const boundsForFirstItem = this._getItemBounds(itemHandlerForFirstItem, align);
const safeArea = this._getSafeArea(targetSafeArea, boundsForFirstItem);
const safeAreaMargin = safeArea.getMargin();
const printAreaBounds = this._findPrintAreaBySafeArea(safeArea).bounds;
const changedItems = [];
items.forEach(item => {
const itemHandler = this._itemToItemHandler(item);
const bounds = this._getItemBounds(itemHandler, align);
const originalRectangle = itemHandler.rectangle.clone();
let alignedRectangle;
const adjustedAlign = this._adjustAlignParameterByRotateAngle(rotateAngle, align);
const regionExists = itemHandler.layer.region != null;
if (regionExists)
alignedRectangle = this._getRectangleAlignedToRegion(bounds, itemHandler, adjustedAlign);
else
alignedRectangle = this._getRectangleAlignedToSafeArea(bounds, itemHandler, adjustedAlign, safeAreaMargin, printAreaBounds);
alignedRectangle = this._adjustAlignedRectangleForInteractiveItem(alignedRectangle, originalRectangle, bounds, itemHandler, adjustedAlign);
const applyAlignmentToItemHandlerFunc = this._getApplyAlignStrategy(itemHandler, alignedRectangle, originalRectangle);
applyAlignmentToItemHandlerFunc();
const hasChanged = !originalRectangle.equals(alignedRectangle);
if (hasChanged)
changedItems.push(item);
});
return changedItems;
};
this._alignByGroup = (items, align) => {
const rotateAngle = this._productHandler.currentSurface.rotateAngle;
var baseRect = this._canvas.selection.parentRectangle.toRectangleF();
const changedItems = [];
items.forEach(item => {
const itemHandler = this._itemToItemHandler(item);
const bounds = this._getItemBounds(itemHandler, align);
const originalRectangle = itemHandler.rectangle.clone();
let alignedRectangle;
const adjustedAlign = this._adjustAlignParameterByRotateAngle(rotateAngle, align);
alignedRectangle = this._getRectangleAlignedToGroup(baseRect, bounds, itemHandler, adjustedAlign);
itemHandler.setRectangle(alignedRectangle);
alignedRectangle = this._adjustAlignedRectangleForInteractiveItem(alignedRectangle, originalRectangle, bounds, itemHandler, adjustedAlign);
const applyAlignmentToItemHandlerFunc = this._getApplyAlignStrategy(itemHandler, alignedRectangle, originalRectangle);
applyAlignmentToItemHandlerFunc();
const hasChanged = !originalRectangle.equals(alignedRectangle);
if (hasChanged)
changedItems.push(item);
});
return changedItems;
};
}
async _executeCommandBody() {
if (this._canvas != null)
this._canvas.pauseRedraw();
try {
let alignStrategyFunc = this._getAlignStrategy(this._args);
const changedItems = alignStrategyFunc();
changedItems.forEach(item => item.getItemChangedEvent().fire());
}
finally {
if (this._canvas != null) {
this._canvas.continueRedraw();
this._canvas.updateTexts();
this._canvas.selection.update();
this._canvas.redraw();
}
}
}
_getAlignStrategy(args) {
const items = this._getTargetItems(args.items, args.query, args.queryOptions);
switch (args.target) {
case "auto":
if (items.length == 1) {
if (!items[0].parentGroupItem) {
return this._alignByPrintArea.bind(this, items, args.align, args.targetPrintArea);
}
else {
return this._alignByGroup.bind(this, items, args.align);
}
}
else {
return this._alignBySelectionBounds.bind(this, items, args.align);
}
case "printArea":
return this._alignByPrintArea.bind(this, items, args.align, args.targetPrintArea);
case "safeArea":
return this._alignBySafeArea.bind(this, items, args.align, args.targetSafeArea);
default:
throw "Unsupported alignment context: " + args.target;
}
}
_itemToItemHandler(item) {
var itemHandler = this._productHandler.getHandler(item);
if (!(itemHandler instanceof BaseRectangleItemHandler))
throw "A BaseRectangleItemHandler expected in alignment command.";
return itemHandler;
}
_adjustAlignedRectangleForInteractiveItem(alignedRectangle, originalRectangle, bounds, itemHandler, align) {
const adjustedRectangle = alignedRectangle.clone();
const permissions = itemHandler.getPermissions();
const allowMoveHorizontal = permissions.allowMoveHorizontal;
const allowMoveVertical = permissions.allowMoveVertical;
if (this._itemRequiresFrameConsideration(itemHandler, align)
&& !itemHandler.isLocked()
&& this._isItemInteractive(itemHandler.item)) {
if ((align === "bottom" || align === "top") && allowMoveVertical) {
adjustedRectangle.centerY -= bounds.top + (bounds.height / 2) - originalRectangle.centerY;
}
if ((align === "left" || align === "right") && allowMoveHorizontal) {
adjustedRectangle.centerX -= bounds.left + (bounds.width / 2) - originalRectangle.centerX;
}
}
return adjustedRectangle;
}
_adjustAlignParameterByRotateAngle(angle, align) {
const noRotationMap = new Map([
['left', 'left'],
['horizontalCenter', 'horizontalCenter'],
['right', 'right'],
['top', 'top'],
['verticalCenter', 'verticalCenter'],
['bottom', 'bottom']
]);
const clockwiseRotationMap = new Map([
['left', 'bottom'],
['horizontalCenter', 'verticalCenter'],
['right', 'top'],
['top', 'left'],
['verticalCenter', 'horizontalCenter'],
['bottom', 'right']
]);
const doubleClockwiseRotationMap = new Map([
['left', 'right'],
['horizontalCenter', 'horizontalCenter'],
['right', 'left'],
['top', 'bottom'],
['verticalCenter', 'verticalCenter'],
['bottom', 'top']
]);
const counterClockwiseRotationMap = new Map([
['left', 'top'],
['horizontalCenter', 'verticalCenter'],
['right', 'bottom'],
['top', 'right'],
['verticalCenter', 'horizontalCenter'],
['bottom', 'left']
]);
switch (angle) {
case 0:
return noRotationMap.get(align);
case 90:
return clockwiseRotationMap.get(align);
case 180:
return doubleClockwiseRotationMap.get(align);
case 270:
return counterClockwiseRotationMap.get(align);
default:
throw new Error(`Cannot align when the rotation angle is ${angle}. Use angles aliquot to 90 degrees.`);
}
}
_getRectangleAlignedToBoundBox(baseRect, bounds, itemHandler, align) {
const rectangle = itemHandler.rectangle;
const permissions = itemHandler.getPermissions();
const allowMoveHorizontal = permissions.allowMoveHorizontal;
const allowMoveVertical = permissions.allowMoveVertical;
switch (align) {
case "left":
if (allowMoveHorizontal)
rectangle.centerX = baseRect.location.x + bounds.width / 2;
break;
case "horizontalCenter":
if (allowMoveHorizontal)
rectangle.centerX = baseRect.centerX;
break;
case "right":
if (allowMoveHorizontal)
rectangle.centerX = baseRect.getBottomRightCorner().x - bounds.width / 2;
break;
case "top":
if (allowMoveVertical)
rectangle.centerY = baseRect.location.y + bounds.height / 2;
break;
case "verticalCenter":
if (allowMoveVertical)
rectangle.centerY = baseRect.centerY;
break;
case "bottom":
if (allowMoveVertical)
rectangle.centerY = baseRect.getBottomRightCorner().y - bounds.height / 2;
break;
}
return rectangle;
}
_getRectangleAlignedToRegion(bounds, itemHandler, align) {
const rectangle = itemHandler.rectangle;
const region = itemHandler.layer.region;
const permissions = itemHandler.getPermissions();
const allowMoveHorizontal = permissions.allowMoveHorizontal;
const allowMoveVertical = permissions.allowMoveVertical;
switch (align) {
case "left":
if (allowMoveHorizontal)
rectangle.centerX = region.left + bounds.width / 2;
break;
case "horizontalCenter":
if (allowMoveHorizontal)
rectangle.centerX = region.left + region.width / 2;
break;
case "right":
if (allowMoveHorizontal)
rectangle.centerX = region.left + region.width - bounds.width / 2;
break;
case "top":
if (allowMoveVertical)
rectangle.centerY = region.top + bounds.height / 2;
break;
case "verticalCenter":
if (allowMoveVertical)
rectangle.centerY = region.top + region.height / 2;
break;
case "bottom":
if (allowMoveVertical)
rectangle.centerY = region.top + region.height - bounds.height / 2;
break;
}
return rectangle;
}
_getRectangleAlignedToGroup(baseRect, bounds, itemHandler, align) {
const rectangle = itemHandler.rectangle;
const permissions = itemHandler.getPermissions();
const allowMoveHorizontal = permissions.allowMoveHorizontal;
const allowMoveVertical = permissions.allowMoveVertical;
switch (align) {
case "left":
if (allowMoveHorizontal)
rectangle.centerX = baseRect.left + bounds.width / 2;
break;
case "horizontalCenter":
if (allowMoveHorizontal)
rectangle.centerX = baseRect.left + baseRect.width / 2;
break;
case "right":
if (allowMoveHorizontal)
rectangle.centerX = baseRect.left + baseRect.width - bounds.width / 2;
break;
case "top":
if (allowMoveVertical)
rectangle.centerY = baseRect.top + bounds.height / 2;
break;
case "verticalCenter":
if (allowMoveVertical)
rectangle.centerY = baseRect.top + baseRect.height / 2;
break;
case "bottom":
if (allowMoveVertical)
rectangle.centerY = baseRect.top + baseRect.height - bounds.height / 2;
break;
}
return rectangle;
}
_getRectangleAlignedToPrintArea(bounds, itemHandler, align, printAreaBounds) {
const rectangle = itemHandler.rectangle;
const permissions = itemHandler.getPermissions();
const allowMoveHorizontal = permissions.allowMoveHorizontal;
const allowMoveVertical = permissions.allowMoveVertical;
switch (align) {
case "left":
if (allowMoveHorizontal)
rectangle.centerX = printAreaBounds.left + this._canvas.leftMargin + bounds.width / 2;
break;
case "horizontalCenter":
if (allowMoveHorizontal)
rectangle.centerX = printAreaBounds.left + this._canvas.leftMargin + (printAreaBounds.width - this._canvas.rightMargin - this._canvas.leftMargin) / 2;
break;
case "right":
if (allowMoveHorizontal)
rectangle.centerX = printAreaBounds.right - this._canvas.rightMargin - bounds.width / 2;
break;
case "top":
if (allowMoveVertical)
rectangle.centerY = printAreaBounds.top + this._canvas.topMargin + bounds.height / 2;
break;
case "verticalCenter":
if (allowMoveVertical)
rectangle.centerY = printAreaBounds.top + this._canvas.topMargin + (printAreaBounds.height - this._canvas.bottomMargin - this._canvas.topMargin) / 2;
break;
case "bottom":
if (allowMoveVertical)
rectangle.centerY = printAreaBounds.bottom - this._canvas.bottomMargin - bounds.height / 2;
break;
}
return rectangle;
}
_getRectangleAlignedToSafeArea(bounds, itemHandler, align, safeAreaMargin, printAreaBounds) {
const rectangle = itemHandler.rectangle;
const permissions = itemHandler.getPermissions();
const allowMoveHorizontal = permissions.allowMoveHorizontal;
const allowMoveVertical = permissions.allowMoveVertical;
switch (align) {
case "left":
if (allowMoveHorizontal)
rectangle.centerX = printAreaBounds.left + this._canvas.leftMargin + safeAreaMargin.left + bounds.width / 2;
break;
case "horizontalCenter":
const availableWidth = printAreaBounds.width - safeAreaMargin.left - safeAreaMargin.right;
if (allowMoveHorizontal)
rectangle.centerX = printAreaBounds.left + safeAreaMargin.left + (availableWidth - this._canvas.rightMargin - this._canvas.leftMargin) / 2;
break;
case "right":
if (allowMoveHorizontal)
rectangle.centerX = printAreaBounds.right - this._canvas.rightMargin - safeAreaMargin.right - bounds.width / 2;
break;
case "top":
if (allowMoveVertical)
rectangle.centerY = printAreaBounds.top + safeAreaMargin.top + this._canvas.topMargin + bounds.height / 2;
break;
case "verticalCenter":
const availableHeight = printAreaBounds.height - safeAreaMargin.top - safeAreaMargin.bottom;
if (allowMoveVertical)
rectangle.centerY = printAreaBounds.top + safeAreaMargin.top + (availableHeight - this._canvas.bottomMargin - this._canvas.topMargin) / 2;
break;
case "bottom":
if (allowMoveVertical)
rectangle.centerY = printAreaBounds.bottom - safeAreaMargin.bottom - this._canvas.bottomMargin - bounds.height / 2;
break;
}
return rectangle;
}
_getSafeArea(safeArea, bounds) {
const printArea = this._getPrintArea(bounds);
const defaultSafeArea = printArea.safetyLines.get(0);
return safeArea !== null && safeArea !== void 0 ? safeArea : defaultSafeArea;
}
_getPrintArea(bounds, printArea) {
const printAreas = this._getPrintAreas();
const defaultPrintArea = this._findPrintAreaForItemBounds(bounds, printAreas);
return printArea !== null && printArea !== void 0 ? printArea : defaultPrintArea;
}
_getPrintAreas() {
return this._productHandler.currentSurface.printAreas;
}
_findPrintAreaBySafeArea(safeArea) {
const printAreas = this._getPrintAreas();
for (let printArea of printAreas) {
for (let safetyLine of printArea.safetyLines) {
if (safetyLine.name == safeArea.name) {
return printArea;
}
}
}
return null;
}
_findPrintAreaForItemBounds(bounds, printAreas) {
let bestMatch = null;
let bestDistanceSquared = Infinity;
for (let printArea of printAreas) {
if (printArea.bounds.contains(bounds.center)) {
return printArea;
}
else {
const distanceSquared = bounds.center.distance(printArea.bounds.center);
if (distanceSquared < bestDistanceSquared) {
bestDistanceSquared = distanceSquared;
bestMatch = printArea;
}
}
}
if (bestMatch)
return bestMatch;
else
throw new Error("There are no print areas");
}
_getItemBounds(itemHandler, align) {
if (this._itemRequiresFrameConsideration(itemHandler, align))
return itemHandler.getBoundsIncludingFrames();
return itemHandler.bounds;
}
_itemRequiresFrameConsideration(itemHandler, align) {
return itemHandler instanceof PlaceholderItemHandler
&& !(align === "verticalCenter" || align === "horizontalCenter");
}
_isItemInteractive(item) {
return this._canvas.viewer.productHandler.isInteractive(item);
}
_getApplyAlignStrategy(itemHandler, alignedRectangle, originalRectangle) {
if (itemHandler instanceof PlaceholderItemHandler) {
return this._applyAlignmentToPlaceholderItem.bind(this, itemHandler, alignedRectangle, originalRectangle);
}
else if (itemHandler instanceof LayoutItemHandler) {
return this._applyAlignmentToLayoutItem.bind(this, itemHandler, alignedRectangle);
}
else {
return this._applyAlignmentToDefaultItem.bind(this, itemHandler, alignedRectangle);
}
}
_applyAlignmentToPlaceholderItem(itemHandler, alignedRectangle, originalRectangle) {
itemHandler.setRectangle(alignedRectangle, null, true);
itemHandler.updateContentAndFrames(function (contentHandler) {
var rect = contentHandler.rectangle;
rect.centerX += (alignedRectangle.centerX - originalRectangle.centerX);
rect.centerY += (alignedRectangle.centerY - originalRectangle.centerY);
contentHandler.setRectangle(rect);
});
}
_applyAlignmentToLayoutItem(itemHandler, alignedRectangle) {
itemHandler.setRectangle(alignedRectangle, null, true);
}
_applyAlignmentToDefaultItem(itemHandler, alignedRectangle) {
itemHandler.setRectangle(alignedRectangle);
}
redo() {
throw new NotImplementedException();
}
undo() {
throw new NotImplementedException();
}
}
//# sourceMappingURL=AlignItemsCommand.js.map