UNPKG

@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
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