@aurigma/design-atoms
Version:
Design Atoms is a part of Customer's Canvas SDK which allows for manipulating individual design elements through your code.
324 lines • 17.9 kB
JavaScript
import { BaseProductCommand } from "./BaseProductCommand";
import { maybe } from "tsmonad";
import { PlaceholderItemHandler, GroupItemHandler, BaseTextItemHandler } from "../../ItemHandlers";
import { fitRectangleToRectangle, getOriginCoordinate } from "../../Utils/Math";
import { Product, PrintArea, Surface } from "@aurigma/design-atoms-model/Product";
import { Item, ImageItem } from "@aurigma/design-atoms-model/Product/Items";
import { RectangleF, Matrix, EqualsOfFloatNumbers } from "@aurigma/design-atoms-model/Math";
import { Exception, ArgumentException, NotImplementedException } from "@aurigma/design-atoms-model/Exception";
import { ItemsCommand, OriginPointType, ResizeRectangleType } from "@aurigma/design-atoms-interfaces";
import { isEmpty } from "@aurigma/design-atoms-model";
export class ResizeCommand extends BaseProductCommand {
constructor(historyArgs, product, args, _productHandler, _commandManager, _canvas) {
super(product, historyArgs, args);
this._productHandler = _productHandler;
this._commandManager = _commandManager;
this._canvas = _canvas;
this._executeCommandBody = async () => {
if (this._canvas != null)
this._canvas.pauseRedraw();
try {
const target = this._convertedArgs.target;
const itemHandlers = this._items.map(this._productHandler.getHandler);
if (this._canvas != null) {
const canvasItemHandlers = this._canvas.getAllItemHandlers();
await Promise.all(itemHandlers.filter(handler => handler instanceof BaseTextItemHandler && !canvasItemHandlers.includes(handler)).map(h => {
h.updateForExternalCanvas(this._canvas);
return h.waitUpdate();
}));
}
itemHandlers.forEach((handler) => {
handler.startTransform();
handler.beginUpdate();
});
if (target instanceof Product) {
this._resizeProduct(target);
if (this._canvas != null) {
this._canvas.viewer._onResize(this, false);
}
}
else if (target instanceof PrintArea) {
this._resizePrintArea(target);
}
else if (Array.isArray(target)) {
if (target[0] instanceof Surface) {
target.forEach((s) => this._resizeSurface(s));
}
else if (target[0] instanceof Item) {
this._resizeItems(target);
}
}
this._items.map(this._productHandler.getHandler).forEach((handler) => {
handler.endTransform(true, true);
handler.endUpdate();
});
}
finally {
if (this._canvas != null) {
await this._canvas.waitUpdate();
this._canvas.updateSelection();
this._canvas.continueRedraw();
this._canvas.updateTexts();
}
}
};
this._resizeProduct = (product) => {
product.surfaces.forEach(s => this._resizeSurface(s));
};
this._resizeSurface = (surface) => {
var _a, _b;
const surfaceRect = new RectangleF(0, 0, surface.width, surface.height);
const originX = (_a = this._getResizeOptions().originX) !== null && _a !== void 0 ? _a : OriginPointType.Left;
const originY = (_b = this._getResizeOptions().originY) !== null && _b !== void 0 ? _b : OriginPointType.Top;
const matrix = this._getTransformMatrix(surfaceRect, originX, originY);
surface.mockup.allContainers.forEach((c) => this._resizeMockupContainer(c, matrix, surface));
surface.printAreas.forEach((p) => this._resizePrintAreaBounds(p, matrix));
surface.containers.forEach((c) => this._resizeContainer(c, matrix, surface));
matrix.updateObjectByMatrix(surface, "width", "height");
};
this._resizeMockupContainer = (container, matrix, surface) => {
if (container.size != null)
container.size.updateByMatrix(matrix);
this._resizeContainer(container, matrix, surface);
};
/*send printArea argument for resize items within printArea only. Other items will moved*/
this._resizeContainer = (container, matrix, surface, printArea = null) => {
if (container.region != null)
container.region.updateByMatrix(matrix);
const isItemInPrintArea = (item) => {
return printArea.bounds.intersectsWith(this._productHandler.getHandler(item).bounds);
};
const items = container.items.toArray().filter(i => printArea == null || isItemInPrintArea(i));
const resizeType = this._getResizeOptions(container).resize;
const itemMatrix = this._getItemsMatrix(items, resizeType, matrix, surface);
const resetPlaceholderContent = this._getResizeOptions(container).resetPlaceholderContent;
container.items.forEach((i) => {
let targetMatrix = printArea != null ?
this._getTranslateMatrixRelativeToPrintArea(printArea.bounds, this._productHandler.getHandler(i).bounds, isItemInPrintArea(i) ? itemMatrix : matrix) :
itemMatrix;
this._resizeItem(i, targetMatrix, resetPlaceholderContent);
});
};
this._resizeItems = (items) => {
var _a, _b;
const resize = this._getResizeOptions().resize;
if (resize === ResizeRectangleType.Original)
throw new Exception("Original type not supported when resizing items.");
let overallBounds;
if (items.length === 1) {
var rect = this._productHandler.getHandler(items[0]).rectangle;
rect.angle = 0;
overallBounds = rect.bounds;
}
else {
overallBounds = this._getItemsBounds(items);
}
const originX = (_a = this._getResizeOptions().originX) !== null && _a !== void 0 ? _a : OriginPointType.Center;
const originY = (_b = this._getResizeOptions().originY) !== null && _b !== void 0 ? _b : OriginPointType.Center;
const originMatrix = this._getTransformMatrix(overallBounds, originX, originY);
const matrix = this._getItemsMatrix(items, this._getResizeOptions().resize, originMatrix, null);
items.forEach((i) => { var _a; return this._resizeItem(i, matrix, (_a = this._defaultResizeOptions.resetPlaceholderContent) !== null && _a !== void 0 ? _a : true); });
};
this._resizeItem = (item, matrix, resetPlaceholderContent) => {
const updateHandler = (handler) => {
var _a;
handler.transformByMatrix(matrix, false);
const item = handler.item;
if (item instanceof ImageItem) {
(_a = item.values) === null || _a === void 0 ? void 0 : _a.filter(i => (i === null || i === void 0 ? void 0 : i.transformedRectangle) != null).forEach(v => {
v.transformedRectangle = v.transformedRectangle.transformByMatrix(matrix);
});
}
};
const resetPlaceholderHandler = (handler) => {
if (resetPlaceholderContent && handler.content != null) {
handler.content.updateRectangle(false, handler.item.contentResizeMode, handler);
}
};
const itemHandler = this._productHandler.getHandler(item);
updateHandler(itemHandler);
if (itemHandler instanceof PlaceholderItemHandler) {
itemHandler.updateContentAndFrames(updateHandler);
resetPlaceholderHandler(itemHandler);
}
if (itemHandler instanceof GroupItemHandler)
itemHandler.itemHandlers.toArray().filter(i => i instanceof PlaceholderItemHandler).forEach(resetPlaceholderHandler);
};
this._resizePrintAreaBounds = (printArea, matrix) => {
printArea.bounds = printArea.bounds.clone().updateByMatrix(matrix);
};
this._resizePrintArea = (printArea) => {
const surface = this._product.surfaces.toArray().find(s => s.printAreas.contains(printArea));
const matrix = this._getMatrixForPrintArea(printArea);
surface.containers.forEach((c) => this._resizeContainer(c, matrix, surface, printArea));
surface.printAreas.forEach(p => {
if (p !== printArea)
this._resizePrintAreaBounds(p, this._getTranslateMatrixRelativeToPrintArea(printArea.bounds, p.bounds, matrix));
});
this._resizePrintAreaBounds(printArea, matrix);
this._resizeSurfaceByPrintArea(surface);
};
this._resizeSurfaceByPrintArea = (surface) => {
const overallBounds = RectangleF.getOverallBounds(surface.printAreas.toArray().map(p => p.bounds));
const surfaceRect = new RectangleF(0, 0, surface.width, surface.height);
if (surfaceRect.containsRectangle(overallBounds))
return;
surface.width = Math.max(surface.width, overallBounds.right);
surface.height = Math.max(surface.height, overallBounds.bottom);
if (overallBounds.left >= 0 || overallBounds.top >= 0)
return;
this._commandManager.execute(ItemsCommand.translateItems, {
items: surface.getAllItems().toArray(),
translateX: -Math.min(0, overallBounds.left),
translateY: -Math.min(0, overallBounds.top)
});
};
this._getTransformMatrix = (initialRect, originX, originY) => {
const origin = getOriginCoordinate(initialRect, originX, originY);
const matrix = new Matrix();
matrix.scaleRelativeToPoint(this._getScaleMultiplier(this._args.width, initialRect.width), this._getScaleMultiplier(this._args.height, initialRect.height), origin);
return matrix;
};
this._getScaleMultiplier = (value, parentSize) => {
if (typeof value === "string") {
if (/%$/.test(value)) {
const percent = Number(value.split(/%/)[0]);
return percent / 100;
}
else {
const parsedValue = parseFloat(value);
if (isNaN(parsedValue))
throw new ArgumentException(`ResizeCommand: Wrong string format: ${value}`);
else
value = parsedValue;
}
}
if (value <= 0)
throw new ArgumentException(`ResizeCommand: Wrong value: ${value}`);
if (parentSize <= 0)
throw new ArgumentException(`ResizeCommand: Wrong parentSize: ${parentSize}`);
return value / parentSize;
};
this._convertedArgs = this._args.target != null ?
this._args :
this._convertExternalConfig(this._args);
}
get _items() {
const target = this._convertedArgs.target;
if (target instanceof Product)
return target.getAllItems();
if (target instanceof PrintArea) {
const surface = this._product.surfaces.firstOrDefault(s => s.printAreas.contains(target));
if (surface == null)
return [];
return surface.getAllItems().toArray();
}
if (!Array.isArray(target))
return [];
if (target[0] instanceof Item)
return target;
if (target[0] instanceof Surface)
return target.map((s) => s.getAllItems().toArray()).flat();
return [];
}
_getTranslateMatrixRelativeToPrintArea(printAreaBounds, bounds, originalMatrix) {
const result = new Matrix();
const isItemInLeftOrTopPart = bounds.bottom <= printAreaBounds.top ||
bounds.right <= printAreaBounds.left;
if (isItemInLeftOrTopPart)
return result;
if (printAreaBounds.intersectsWith(bounds))
return originalMatrix;
let newPrintAreaBounds = printAreaBounds.clone().updateByMatrix(originalMatrix);
result.translate(bounds.left > printAreaBounds.right || EqualsOfFloatNumbers(printAreaBounds.right - bounds.left, 0) ? newPrintAreaBounds.right - printAreaBounds.right : 0, bounds.top > printAreaBounds.bottom || EqualsOfFloatNumbers(printAreaBounds.bottom - bounds.top, 0) ? newPrintAreaBounds.bottom - printAreaBounds.bottom : 0);
return result;
}
_getItemsMatrix(items, resizeType, originMatrix, originSurface) {
var _a, _b;
let itemsRectMatrix;
if (resizeType !== ResizeRectangleType.Original) {
const initialItemsRect = this._getItemsBounds(items);
const targetItemRect = initialItemsRect.clone().updateByMatrix(originMatrix);
const forceFit = resizeType === ResizeRectangleType.Arbitrary && items.some(i => i.transform.angle % 90 !== 0);
const targetFittedRect = fitRectangleToRectangle(initialItemsRect, targetItemRect, forceFit ? ResizeRectangleType.Fit : resizeType);
itemsRectMatrix = RectangleF.getMatrix(initialItemsRect, targetFittedRect);
}
else {
const originX = (_a = this._getResizeOptions().originX) !== null && _a !== void 0 ? _a : OriginPointType.Center;
const originY = (_b = this._getResizeOptions().originY) !== null && _b !== void 0 ? _b : OriginPointType.Center;
itemsRectMatrix = this._getTranslateMatrixForOriginalMode(originMatrix, originSurface, originX, originY);
}
return itemsRectMatrix;
}
_getTranslateMatrixForOriginalMode(originMatrix, originSurface, originX, originY) {
const initialRect = new RectangleF(0, 0, originSurface.width, originSurface.height);
const initialOrigin = getOriginCoordinate(initialRect, originX, originY);
const finalRect = initialRect.updateByMatrix(originMatrix);
const finalOrigin = getOriginCoordinate(finalRect, originX, originY);
const matrix = new Matrix();
matrix.translate(finalOrigin.x - initialOrigin.x, finalOrigin.y - initialOrigin.y);
return matrix;
}
_getResizeOptions(container) {
return maybe(this._args.containerOptions)
.bind(options => maybe(container).map(c => options[c.name]))
.caseOf({
just: opt => (Object.assign(Object.assign({}, this._defaultResizeOptions), opt)),
nothing: () => this._defaultResizeOptions
});
}
get _defaultResizeOptions() {
return Object.assign({ resize: ResizeRectangleType.Fit, resetPlaceholderContent: true }, (this._args.defaultOptions || {}));
}
_getItemsBounds(items) {
if (items.length === 0)
return RectangleF.empty;
return RectangleF.getOverallBounds(items.map((i) => this._productHandler.getHandler(i).bounds));
}
_getMatrixForPrintArea(printArea) {
var _a, _b;
const originX = (_a = this._getResizeOptions().originX) !== null && _a !== void 0 ? _a : OriginPointType.Left;
const originY = (_b = this._getResizeOptions().originY) !== null && _b !== void 0 ? _b : OriginPointType.Top;
return this._getTransformMatrix(printArea.bounds, originX, originY);
}
_convertExternalConfig(externalConfig) {
let target;
switch (externalConfig.targetType) {
case "surfaces":
if (isEmpty(externalConfig.targetIds))
throw new ArgumentException("ResizeCommand: target Ids cannot be empty");
target = this._product.surfaces.toArray().filter(s => externalConfig.targetIds.includes(s.id));
break;
case "items":
if (isEmpty(externalConfig.targetIds))
throw new ArgumentException("ResizeCommand: target Ids cannot be empty");
target = this._productHandler.currentSurface
.getAllItems({ ignoreMockups: false, flatGroupItems: true })
.toArray()
.filter(s => externalConfig.targetIds.includes(s.id));
break;
case "printArea":
if (isEmpty(externalConfig.targetIds))
throw new ArgumentException("ResizeCommand: target Ids cannot be empty");
target = this._product.surfaces.toArray().map(s => s.printAreas.toArray()).flat().find(p => externalConfig.targetIds.includes(p.id));
break;
default:
target = this._product;
break;
}
return {
target: target,
width: externalConfig.width,
height: externalConfig.height,
containerOptions: externalConfig.containerOptions,
defaultOptions: externalConfig.defaultOptions
};
}
redo() {
throw new NotImplementedException();
}
undo() {
throw new NotImplementedException();
}
}
//# sourceMappingURL=ResizeCommand.js.map