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.

214 lines 11.4 kB
import { PlainTextItem } from "@aurigma/design-atoms-model/Product/Items"; import { NewBaseTextItemHandler } from "./NewBaseTextItemHandler"; import { EqualsOfFloatNumbers, RectangleF, RotatedRectangleF } from "@aurigma/design-atoms-model/Math"; import { TextFrameType } from "@aurigma/design-atoms-text/TextEditor/Enums/TextFrameType"; import { rectangleEquals } from "../Utils/Math"; import { ListStyleSheetManagerFactory } from "@aurigma/design-atoms-text/TextEditor/Services"; import { GmXmlParser } from "@aurigma/design-atoms-text/Serialization/GmXmlParser"; import { GmXmlSerializer } from "@aurigma/design-atoms-text/Serialization/GmXmlSerializer"; import { ColorPalette } from "@aurigma/design-atoms-text/Serialization/Model/ColorPalette"; import { ItemUtils } from "../Utils/ItemUtils"; import { Paragraph, Span } from "@aurigma/design-atoms-text/Model"; export class NewPlainTextItemHandler extends NewBaseTextItemHandler { constructor(fontRegistry, textEditorControllerFactory, item, textWhizz = null, apiClient, colorPreviewServce, colorParser) { super(fontRegistry, textEditorControllerFactory, item, textWhizz, apiClient, colorPreviewServce, colorParser); } get item() { return this._getItem(); } set item(item) { super._setItem(item); } getFramesData() { let data = []; data.push(this.item.baselineLocation.clone()); return { type: TextFrameType.pointTextFrame, frames: data }; } ; setTextWhizzWrappingPath(handler) { } getWrappingPathData() { return {}; } //TODO: to del updateTextWhizzFrames(handler) { handler.replaceFrame(this._createTextWhizzFrame(), 0); } //TODO: to del _addTextWhizzFrames(handler) { handler.addFrame(this._createTextWhizzFrame()); } async _onItemPropertyChanged(sender, propertyName) { switch (propertyName) { case "baselineLocation": this.update(null, null, "frame"); break; case "isVertical": this.update(); case "alignment": const originalRectangle = this._calculateTransformedRect(); this.update(); await this._correctBaselineLocation(originalRectangle); default: } super._onItemPropertyChanged(sender, propertyName); } async waitInitFrontEndRendering() { await super.waitInitFrontEndRendering(); await this._resetPreviewScale(this.item); } _getDefaultPermissions() { const permissions = super._getDefaultPermissions(); permissions.manipulation.resizeGrips.setCornerArbitrary(false); permissions.manipulation.resizeGrips.edge = false; return permissions; } _getEndTransformTrigger(resized) { return resized ? null : "frame"; } async _applyTransform(item, transform, center) { var _a, _b; if (!(item instanceof PlainTextItem)) return; const point = item.baselineLocation.clone(); point.transform(transform, center); item.baselineLocation = point; const limits = this._getPreviewScaleLimits(); let targetScale = transform.scaleY; targetScale = Math.min((_a = limits.max) !== null && _a !== void 0 ? _a : Number.MAX_VALUE, targetScale); targetScale = Math.max((_b = limits.min) !== null && _b !== void 0 ? _b : Number.MIN_VALUE, targetScale); await this._scaleFontSizes(item, targetScale); await this._updateRectangleAfterTextScale(item, transform); this.textEditorController.updateText("frame", true); } async _updateRectangleAfterTextScale(item, transform) { await this.textEditorController.waitUpdate(); const textBounds = item.sourceRectangle; textBounds.updateByMatrix(transform.toMatrix()); const rectangle = new RectangleF(textBounds.left, textBounds.top, textBounds.width, textBounds.height); this.updateRectangle(rectangle, false); } _getPreviewScaleLimits() { var _a, _b; const baseLimits = super._getPreviewScaleLimits(); if (this.item.leading > 0) { if (this.canvas.maxLeading != null && !isNaN(this.canvas.maxLeading)) baseLimits.max = Math.min((_a = baseLimits.max) !== null && _a !== void 0 ? _a : Number.MAX_VALUE, this.canvas.maxLeading / this.item.leading); if (this.canvas.minLeading != null && !isNaN(this.canvas.minLeading)) baseLimits.min = Math.max((_b = baseLimits.min) !== null && _b !== void 0 ? _b : Number.MIN_VALUE, this.canvas.minLeading / this.item.leading); } return baseLimits; } _calculateTransformedRect() { const transformedRectangle = RotatedRectangleF.fromRectangleF(this.item.sourceRectangle); const transform = this.item.transform; transformedRectangle.setTransform(transform); return transformedRectangle.toRectangleF(); } async _correctBaselineLocation(originalRectangle) { await this._textEditorController.waitUpdate(); const currentBaseline = this.item.baselineLocation.clone(); const currentRectangle = this.item.sourceRectangle; const horizontalShift = originalRectangle.left - currentRectangle.left; currentBaseline.x += horizontalShift; this.item.baselineLocation = currentBaseline; } async _resetPreviewScale(item) { const scale = this.item.previewScale; const eps = 0.0000001; if (Math.abs(scale - 1) > eps) { this.item.previewScale = 1; await this._scaleFontSizes(item, scale); } } async _scaleFontSizes(item, scaleFactor) { await this._scaleFontSizesInItem(item, scaleFactor); await this._scaleFontSizesInMarkup(item, scaleFactor); await this.textEditorController.waitUpdate(); } async _scaleFontSizesInMarkup(item, scaleFactor) { const textParser = new GmXmlParser(this._colorParser); const textSerializer = new GmXmlSerializer(this._colorParser); const listStyleSheetManagerFactory = new ListStyleSheetManagerFactory(); let listStyleSheetManager = listStyleSheetManagerFactory.create(); listStyleSheetManager.initialize(); const colorPalette = new ColorPalette(await ItemUtils.getColorPalette(item, this._colorPreviewService)); const textModel = textParser.parse(item.text, colorPalette, item.font.size, listStyleSheetManager); this._scaleTextModelStyles(textModel, scaleFactor); const updatedText = textSerializer.serialize(textModel, colorPalette); item.text = updatedText; } async _scaleFontSizesInItem(item, scaleFactor) { item.font.size *= scaleFactor; item.leading *= scaleFactor; } _scaleTextModelStyles(textModel, scaleFactor) { textModel.blocks.forEach(block => { if (block instanceof Paragraph) { block.inlineElements.forEach(inlineElement => { if (inlineElement instanceof Span) { const spanStyle = inlineElement.style; if (spanStyle === null || spanStyle === void 0 ? void 0 : spanStyle.fontSize) { spanStyle.fontSize.value *= scaleFactor; } if ((spanStyle === null || spanStyle === void 0 ? void 0 : spanStyle.leading) && spanStyle.leading.unit === "pt") { spanStyle.leading.value *= scaleFactor; } } }); } }); } //TODO: to del _createTextWhizzFrame() { const baselineLocation = this.item.baselineLocation.clone(); const scale = this.item.previewScale; if (!EqualsOfFloatNumbers(scale, 1)) baselineLocation.scale(1 / scale, 1 / scale); const frame = new this._textWhizz.PointTextFrame(); frame.point = baselineLocation; frame.textOrientation = this.item.isVertical ? this._textWhizz.TextOrientation.vertical : this._textWhizz.TextOrientation.horizontal; return frame; } async updateRectangle(rectangle, updateFromTextEdit) { if (!updateFromTextEdit) return super.updateRectangle(rectangle, updateFromTextEdit); const inRect = rectangle.clone(); const textRect = RotatedRectangleF.fromRectangleF(rectangle); const angle = this.item.transform.angle; const oldCenter = this.rectangle.center; const newCenter = rectangle.clone().center; const oldBaselineLocation = this.item.baselineLocation.clone(); // поворачиваем обратно в 0 (приводим в нормализованную систему координат) oldBaselineLocation.rotateAt(angle, oldCenter); textRect.rotateAt(angle, oldCenter); // сдвигаем систему к новому центру. Теперь вычисляется, где будет новый центр в повернутой системе координат newCenter.rotateAt(this.item.transform.angle, oldCenter); // Второй поворот (возвращаем обратно). Всё обратно поворачивается, но уже относительно нового центра // Это нужно, чтобы сохранить правильное положение текста, даже если блок изменил форму или размеры oldBaselineLocation.rotateAt(-angle, newCenter); textRect.rotateAt(-angle, newCenter); this.item.setBaselineLocation(oldBaselineLocation, true); rectangle = textRect.toRectangleF(); super.updateRectangle(rectangle, updateFromTextEdit); if (this.hasLayoutAncestor) return; // Не знаю для чего нужен код ниже, updateText("frame") всеравно будет вызван // в BaseTextItemHandler. С помощью чего и применятся новые координаты ректангла на текст. // Может это какая-то мера предосторожности при наличии большого кол-ва текствовых элементов. // Кроме того при наличии autoLayout с alignment, он параллельно этому коду двигает ректангл в // cоответствии выбранного alignment-а, что и вызывает бесконечный вызов этой функции const rectangleChanged = !rectangleEquals(inRect, rectangle); if (rectangleChanged && this.textEditor == null) { await this.textEditorController.waitUpdate(); this.textEditorController.updateText("text", true); } } } NewPlainTextItemHandler.typeName = "NewPlainTextItemHandler"; //# sourceMappingURL=NewPlainTextItemHandler.js.map