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.

805 lines 30.9 kB
import { Utils } from "../Utils/Common"; import { WebServiceCallType } from "../Utils/Common"; import { EventWithSenderArg, EventObject } from "@aurigma/design-atoms-model/EventObject"; import { Permission } from "../Permission"; import { RectangleF, RotatedRectangleF } from "@aurigma/design-atoms-model/Math"; import { ItemHandlerData } from "./ItemHandlerData"; import { BlendMode, ManipulationPermissions, VisualizationPermissions, ItemPermissions, PlaceholderPermissions } from "@aurigma/design-atoms-model/Product/Items"; import { JsonProductSerializer } from "../Serialization/JsonProductSerializer"; import { Exception, NotImplementedException } from "@aurigma/design-atoms-model/Exception"; import { RenderingType } from "@aurigma/design-atoms-model/Product"; import { Graphics } from "../Graphics"; import { RenderState } from "./RenderState"; import { Deferred } from "../Utils/Deferred"; import Environment from "@aurigma/design-atoms-model/Utils/Environment"; import { throttle } from "@aurigma/design-atoms-model"; import { clamp } from "../Utils/Math"; const BLEND_MODES = { [BlendMode.Normal]: "normal", [BlendMode.Multiply]: "multiply", [BlendMode.Screen]: "screen", [BlendMode.Overlay]: "overlay", [BlendMode.Darken]: "darken", [BlendMode.Lighten]: "lighten", [BlendMode.ColorDodge]: "color-dodge", [BlendMode.ColorBurn]: "color-burn", [BlendMode.HardLight]: "hard-light", [BlendMode.SoftLight]: "soft-light", [BlendMode.Difference]: "difference", [BlendMode.Exclusion]: "exclusion", [BlendMode.None]: "none" }; export class ItemHandler { constructor(item) { this._afterUpdateCallbacks = []; this._modelItem = null; this._skipPropertyChanged = false; this._skippedPropertyName = null; this._visible = true; this._locked = false; this._updating = false; this._isCurrentWebServiceCallForAll = null; this._changeItemOnUpdate = true; /** * Fires when v-object's ready property sets to true. */ this._readyEvent = new EventWithSenderArg(); /** * Fires when v-object was modified (after the end of an operation). */ this._changedEvent = new EventObject(); /** * Fires before v-object is being modified (before the start of an operation). */ this._changingEvent = new EventObject(); this._itemPropertyChangedEvent = new EventWithSenderArg(); this._isDisposed = false; this._tag = null; this._baseOnItemPropertyChanged = (sender, propertyName) => { if (this._skipPropertyChanged) { this._skippedPropertyName = propertyName; return; } this._onItemPropertyChanged(sender, propertyName); }; this._setItem(item); this._controlPoints = []; this._layer = null; this._tag = null; //use current time to generate unique id //use this id for matching between server and cliebt objects this._uniqueId = this._createUniqueID(); this._callbacks = []; this._renderState = RenderState.Hidden; this._throttleSizeChanging = throttle(() => this.raiseChanging(), 100); } set item(item) { this._setItem(item); } get item() { return this._modelItem; } get ready() { return this._isReady(); } get isLoadingImage() { return this._isLoadingImage(); } set isLoadingImage(value) { if (this.isLoadingImage === value) return; this._setIsLoadingImage(value); } get uniqueId() { return this._uniqueId; } set uniqueId(v) { // Do nothing! uniqueId should not be changed } get renderState() { return this._renderState; } set renderState(v) { this._renderState = v; } get parentGroupItemHandler() { if (this.item.parentGroupItem != null && this.canvas != null) return this.canvas.getItemHandler(this.item.parentGroupItem); return null; } get blendMode() { return this.item.blendMode; } get controlPoints() { return this._controlPoints; } set controlPoints(v) { this._controlPoints = v; this.raiseChanged(); } get tag() { return this._tag; } set tag(v) { this._tag = v; this.raiseChanged(); } get canvas() { return this._canvas; } set canvas(value) { if (value === this._canvas) return; const oldCanvas = this._canvas; this._canvas = value; if (this._canvas != null) this._onAddedOnCanvas(value); else this._onRemovedFromCanvas(oldCanvas); } get layer() { return this._getLayer(); } set layer(v) { this._layer = v; this.quickUpdate(); } _getLayer() { return this._layer; } get index() { return (this._layer != null) ? this._layer.flatItemHandlers.indexOf(this) : -1; } get bounds() { return new RectangleF(0, 0, 0, 0); } get name() { return this.item.name; } set name(v) { this.item.name = v; } get visible() { return this._isIgnorePermissionsMode() ? this._visible : this.item.visible; } set visible(v) { if (this._visible !== v) { this._visible = v; this._refreshState(); if (v) this.update(); } } get locked() { return this._isIgnorePermissionsMode() ? this._locked : this.item.locked; } set locked(v) { if (this._locked !== v) { this._locked = v; this._refreshState(); } } get isNormalRenderingType() { if (this.layer == null) { return true; } return this.layer.renderingType === RenderingType.Normal; } get isUpdating() { return this._updating; } get changeItemOnUpdate() { return this._changeItemOnUpdate; } set changeItemOnUpdate(value) { this._changeItemOnUpdate = value; } get _colorSettings() { var _a, _b, _c, _d, _e, _f, _g, _h; return { rgbColorProfileName: (_b = (_a = this.canvas) === null || _a === void 0 ? void 0 : _a.renderingConfigProvider.getRgbColorProfileName()) !== null && _b !== void 0 ? _b : '', cmykColorProfileName: (_d = (_c = this.canvas) === null || _c === void 0 ? void 0 : _c.renderingConfigProvider.getCmykColorProfileName()) !== null && _d !== void 0 ? _d : '', grayscaleColorProfileName: (_f = (_e = this.canvas) === null || _e === void 0 ? void 0 : _e.renderingConfigProvider.getGrayscaleColorProfileName()) !== null && _f !== void 0 ? _f : '', hiResDestinationColorProfileName: (_h = (_g = this.canvas) === null || _g === void 0 ? void 0 : _g.renderingConfigProvider.getHiResDestinationColorProfileName()) !== null && _h !== void 0 ? _h : '' }; } get hasLayoutAncestor() { let current = this; while (current && current.parentGroupItemHandler) { if (current.parentGroupItemHandler.getTypeName() === "LayoutItemHandler") { return true; } current = current.parentGroupItemHandler; } return false; } ; static isGroupHandler(itemHandler) { return itemHandler._isGroupHandler(); } isHighlightNeeded() { return false; } hasBlendMode() { return this.item.blendMode != null && this.item.blendMode != BlendMode.None && this.item.blendMode != BlendMode.Normal; } getPermissions() { if (this._permissions == null) { this._permissions = this._createItemHandlerPermissions(); } return this._permissions; } resetPermissions() { this._permissions = null; } getTypeName() { return this["constructor"].typeName; } getData(type) { var data = this._createDataInstance(this); return type === "asObject" ? data : JSON.stringify(data); } updateItem(item) { this._skippedPropertyName = null; // Can be buggy if several properties changed. See #7700 this._modifyItem((i) => { i.update(item); }); if (this._skippedPropertyName != null) { this._onItemPropertyChanged(this.item, this._skippedPropertyName); if (this.canvas != null) this.canvas.updateSelection(); } } setData(v) { //raise changed event in applyState method if (v && v !== "") { var data; if (typeof v == "string") data = JSON.parse(v); else data = v; this._createDataInstance().applyState(data, this); } } isVisible() { const invisibleByParentGroup = (item) => { var _a; const parentGroupItem = item.parentGroupItem; if (parentGroupItem == null) return false; if (!parentGroupItem.visible || parentGroupItem.visualizationPermissions.noShow) return true; const parentGroupHandler = (_a = this.canvas) === null || _a === void 0 ? void 0 : _a.getItemHandler(parentGroupItem); if (parentGroupHandler && !parentGroupHandler.isVisible()) return true; if (parentGroupHandler && ItemHandler.isGroupHandler(parentGroupHandler) && !parentGroupHandler.isChildVisible(this)) return true; return invisibleByParentGroup(parentGroupItem); }; return this.visible && !this.getPermissions().noShow && (this.layer == null || this.layer.visible) && !invisibleByParentGroup(this.item); } isEmpty() { return false; } isLocked() { return this.locked || this.layer != null && this.layer.locked; } processEvent(e) { } hitTest(point) { throw new Error("Not implemented"); } draw(itemHandlerCtx, clippingPath, textureCanvas, textureCanvasCtx, memoryCanvas, memoryCanvasCtx, canvasRenderer, isMasked) { if (itemHandlerCtx == null || this.canvas == null || this.layer == null) return; const sourceBlendMode = itemHandlerCtx.globalCompositeOperation; const destBlendMode = this.hasBlendMode() ? this._convertBlendModeToGlobalOperation(this.blendMode) : sourceBlendMode; itemHandlerCtx.globalAlpha = isMasked ? 0.2 : 1; if (this.isNormalRenderingType) { if (clippingPath != null) { itemHandlerCtx.save(); Graphics.clipPath(itemHandlerCtx, clippingPath); } if (this.hasBlendMode()) // @ts-ignore itemHandlerCtx.globalCompositeOperation = destBlendMode; this.drawItemHandler(itemHandlerCtx); if (this.hasBlendMode()) itemHandlerCtx.globalCompositeOperation = sourceBlendMode; } else { this._drawTexture(itemHandlerCtx, textureCanvas, textureCanvasCtx, memoryCanvas, memoryCanvasCtx, canvasRenderer, isMasked, clippingPath); } if (clippingPath == null) return; itemHandlerCtx.restore(); } _drawTexture(itemHandlerCtx, textureCanvas, textureCanvasCtx, memoryCanvas, memoryCanvasCtx, canvasRenderer, isMasked, clippingPath) { var _a, _b, _c, _d, _e, _f; const scaleX = Environment.screenDpi * this.canvas.zoom / 72; const scaleY = Environment.screenDpi * this.canvas.zoom / 72; const width = itemHandlerCtx.canvas.width; const height = itemHandlerCtx.canvas.height; const textureImage = this.layer.textureImage; if (textureImage == null) { this.canvas.drawWaitClock(itemHandlerCtx, this.bounds.center); return; } const canvasRect = new RotatedRectangleF(this.canvas.workspaceWidth / 2, this.canvas.workspaceHeight / 2, this.canvas.workspaceWidth, this.canvas.workspaceHeight); Graphics.drawImage(textureCanvasCtx, textureImage, canvasRect, scaleX, scaleY, this.canvas.disableSmoothing); if (clippingPath != null) { memoryCanvasCtx.save(); Graphics.clipPath(memoryCanvasCtx, clippingPath); } this.drawItemHandler(memoryCanvasCtx, itemHandlerCtx); textureCanvasCtx.restore(); textureCanvasCtx.globalCompositeOperation = "destination-in"; textureCanvasCtx.drawImage(memoryCanvas, 0, 0, width, height); let opacity = 1; const transparencyEnabled = (_c = (_b = (_a = this._canvas) === null || _a === void 0 ? void 0 : _a.viewerConfiguration) === null || _b === void 0 ? void 0 : _b.inactiveContainerTransparencyEnabled) !== null && _c !== void 0 ? _c : ItemHandler.DEFAULT_CONTAINER_TRANSPARENCY_ENABLED; const transparency = (_f = (_e = (_d = this._canvas) === null || _d === void 0 ? void 0 : _d.viewerConfiguration) === null || _e === void 0 ? void 0 : _e.inactiveContainerTransparencyLevel) !== null && _f !== void 0 ? _f : ItemHandler.DEFAULT_CONTAINER_TRANSPARENCY_LEVEL; if (transparencyEnabled && typeof transparency == "number") { opacity = 1 - clamp(transparency, 0, 1); } itemHandlerCtx.restore(); itemHandlerCtx.globalAlpha = isMasked && transparencyEnabled ? opacity : 1; itemHandlerCtx.drawImage(textureCanvas, 0, 0, width, height); canvasRenderer.applyContextScale(itemHandlerCtx, this._canvas.workspace, this._canvas.offset); } drawItemHandler(itemHandlerCtx, originalCtx) { } quickUpdate() { //do nothing by default } update(beforeUpdate, afterUpdate) { this._updateImpl(beforeUpdate, afterUpdate); } async updateAsync(beforeUpdate, afterUpdate) { await this._updateImpl(beforeUpdate, afterUpdate); } updateForExternalCanvas(canvas) { this._serverSideUpdate(null, null, null, canvas); } async updateActiveColorWebServiceCall(callPromise, updateForAll) { if (this._activeWebServiceCall != null) await this._activeWebServiceCall; if (this._activeColorWebServiceCall != null) { this._activeColorWebServiceCall.cancel(); if (this._isCurrentWebServiceCallForAll && !updateForAll) { callPromise.cancel(); this._isCurrentWebServiceCallForAll = updateForAll; this._activeColorWebServiceCall = null; return; } } if (this._handlerUpdated == null) this._handlerUpdated = new Deferred(); this._activeColorWebServiceCall = callPromise; this._isCurrentWebServiceCallForAll = updateForAll; } startTransform() { this._cancelWebServiceCall(); } endTransform(changed, resized, supressOnChanged = false) { } async waitUpdate() { if (this._handlerUpdated != null) await this._handlerUpdated.promise; } beginUpdate() { this._updating = true; } endUpdate() { this._updating = false; this.updated(); var modified = false; while (this._callbacks.length > 0) { var callback = this._callbacks.shift(); if (typeof callback == "function") { callback(); modified = true; } } if (modified) this.update(); } updated() { this.raiseChanged(); } addReady(handler) { this._readyEvent.add(handler); } removeReady(handler) { this._readyEvent.remove(handler); } addChanging(handler) { this._changingEvent.add(handler); } removeChanging(handler) { this._changingEvent.remove(handler); } raiseChanging(param) { var _a; param = param != null ? param : this.item; this._changingEvent.notify(param); this.item.getItemChangingEvent().notify(this.item); (_a = this._canvas) === null || _a === void 0 ? void 0 : _a.redraw(); } getChangingEvent() { return this._changingEvent; } addChanged(handler) { this._changedEvent.add(handler); } removeChanged(handler) { this._changedEvent.remove(handler); } raiseChanged() { if (!this.isUpdating) { this._changedEvent.notify(this); } } getChangedEvent() { return this._changedEvent; } addItemPropertyChanged(handler) { this._itemPropertyChangedEvent.add(handler); } removeItemPropertyChanged(handler) { this._itemPropertyChangedEvent.remove(handler); } initialize() { } onSuccessResponse(activeCall = WebServiceCallType.Item) { if (activeCall == WebServiceCallType.Item) this._activeWebServiceCall = null; else if (activeCall == WebServiceCallType.Color) { this._activeColorWebServiceCall = null; } if (this._activeWebServiceCall == null && this._activeColorWebServiceCall == null && this._handlerUpdated != null) { this._handlerUpdated.resolve(); this._handlerUpdated = null; } } onErrorResponse(error, activeCall = WebServiceCallType.Item) { if (activeCall == WebServiceCallType.Item) this._activeWebServiceCall = null; else if (activeCall == WebServiceCallType.Color) this._activeColorWebServiceCall = null; this._afterUpdateCallbacks = []; if (this._activeWebServiceCall == null && this._activeColorWebServiceCall == null && this._handlerUpdated != null) { this._handlerUpdated.reject(error); this._handlerUpdated = null; } } validateActiveColorWebServiceCall() { if (this._activeColorWebServiceCall == null) { if (this._activeWebServiceCall == null) this._handlerUpdated = null; return; } this._activeColorWebServiceCall = null; if (this._activeWebServiceCall == null) this._handlerUpdated = null; } getColors() { return this._getColors().filter(x => x !== null); } dispose() { var _a; this._unsubscribeItemEvents(); this._cancelWebServiceCall(); (_a = this._activeColorWebServiceCall) === null || _a === void 0 ? void 0 : _a.cancel(); this._activeColorWebServiceCall = null; this._isDisposed = true; } _isReady() { return true; } _getColors() { return []; } async _updateImpl(beforeUpdate, afterUpdate) { // To be overridden } transformChanged() { this.raiseChanged(); } _createDataInstance(itemHandler) { return new ItemHandlerData(itemHandler); } _getDataItem() { var serializer = new JsonProductSerializer(); var serializedItem = serializer.serializeModelComponent(this.item); return serializedItem; } _applyDataItem(item, itemHandlerData) { const serializer = new JsonProductSerializer(); const itemObj = serializer.productParser.parseItem(item); this._modifyItem(() => { this._setDataItem(itemObj, itemHandlerData); }); } _setDataItem(item, itemHandlerData) { this.item.transform = item.transform.clone(); this.setData(itemHandlerData); } async _modifyItem(modify) { if (typeof modify !== "function") return; this._skipPropertyChanged = true; try { await modify(this.item); } finally { this._skipPropertyChanged = false; } } _refreshState() { } _onAddedOnCanvas(canvas, supressUpdate) { if (canvas != null) { canvas.updateTexts(); if (!supressUpdate) this.update(); } } _onRemovedFromCanvas(canvas) { this._canvas = null; } _validateBeforeCallService() { return true; } _update(additionalArgs, beforeUpdate, afterUpdate) { this._serverSideUpdate(additionalArgs, beforeUpdate, afterUpdate, null); } _callService(methodName, data, success, failure, externalCanvas) { const canvas = externalCanvas != null ? externalCanvas : this.canvas; if (canvas == null || !canvas.isInitialized || canvas.initialization) { this._handlerUpdated = null; return; } const layerId = (!this.isNormalRenderingType && this.layer != null) ? this.layer.uniqueId : null; const callPromise = this._getCallService(methodName, data, success, failure, layerId, canvas); this._updateActiveWebServiceCall(callPromise); } async _updateActiveWebServiceCall(callPromise) { this._cancelWebServiceCall(); this._activeWebServiceCall = callPromise; if (this._activeColorWebServiceCall == null) return; this._activeColorWebServiceCall.cancel(); this._activeColorWebServiceCall = null; await this._handlerUpdated.promise; } _getDefaultPermissions() { return { manipulation: new ManipulationPermissions(), visualization: new VisualizationPermissions(), item: new ItemPermissions(), placeholder: new PlaceholderPermissions() }; } _getItemPermissions() { return { manipulation: this.item.manipulationPermissions, visualization: this.item.visualizationPermissions, item: this.item.itemPermissions, placeholder: new PlaceholderPermissions() }; } _isIgnorePermissionsMode() { var _a, _b; return (_b = (_a = this.canvas) === null || _a === void 0 ? void 0 : _a.ignorePermissionsMode) !== null && _b !== void 0 ? _b : false; } _isLoadingImage() { return false; } _setIsLoadingImage(value) { throw new NotImplementedException(); } _dispatchReadyEvent() { if (this.ready) { this._readyEvent.notify(this); } } _updateVisibility() { //do nothing by default } _subscribeItemEvents() { if (this._modelItem == null) return; this._modelItem.addPropertyChanged(this._baseOnItemPropertyChanged); } _unsubscribeItemEvents() { if (this._modelItem == null) return; this._modelItem.removePropertyChanged(this._baseOnItemPropertyChanged); } _onItemPropertyChanged(sender, propertyName) { switch (propertyName) { case "locked": case "opacity": case "blendMode": if (this.canvas != null) { this.canvas.updateSelection(); this.canvas.redraw(); } this.raiseChanged(); break; case "transform": if (this.canvas != null) { this.canvas.updateSelection(); this.canvas.redraw(); } this.transformChanged(); break; case "visible": this._onItemVisibilityChanged(); break; case "manipulationPermissions": case "visualizationPermissions": case "itemPermissions": case "permissions": this._permissions = null; this.quickUpdate(); if (this.canvas) this.canvas.redraw(); this.raiseChanged(); this._updateVisibility(); break; default: } this._itemPropertyChangedEvent.notify(this, propertyName); } _onItemVisibilityChanged() { this.quickUpdate(); if (this.canvas != null) { this.canvas.updateSelection(); this.canvas.redraw(); } this.raiseChanged(); // ? } _getItem() { return this._modelItem; } _setItem(item) { this._unsubscribeItemEvents(); this._modelItem = item; this._subscribeItemEvents(); } _onValidateBeforeCallServiceFailed() { this._handlerUpdated.resolve(); this._handlerUpdated = null; } _isGroupHandler() { return true; } _serverSideUpdate(additionalArgs, beforeUpdate, afterUpdate, canvas) { var success = (data) => { if (this.item == null) return; var item = null; if (typeof data == "object") { item = data.item; data = data.itemHandlerData; } if (item != null && this.changeItemOnUpdate) { this._applyDataItem(item, data); } this.setData(data); if (this._afterUpdateCallbacks.length === 0) { this.quickUpdate(); } else { this._afterUpdateCallbacks.forEach(callback => callback.apply(this)); this._afterUpdateCallbacks = []; this.quickUpdate(); this.raiseChanged(); } this.onSuccessResponse(); this.item.getItemChangedEvent().notify(); }; var failure = (error) => { this.onErrorResponse(error); }; if (this.isUpdating) { this._callbacks.push(beforeUpdate); return; } if (typeof beforeUpdate == "function") beforeUpdate(); if (afterUpdate != null) this._afterUpdateCallbacks.push(afterUpdate); const itemHandlerData = this._createDataInstance(this); let data = [JSON.stringify(itemHandlerData), JSON.parse(this._getDataItem()), this._colorSettings]; if (additionalArgs != null) data = data.concat(additionalArgs); if (this._handlerUpdated == null) this._handlerUpdated = new Deferred(); if (this._validateBeforeCallService()) { this._callService(`Update${this.getTypeName()}`, data, success, failure, canvas); } else { this._onValidateBeforeCallServiceFailed(); } } _convertBlendModeToGlobalOperation(blendMode) { const value = BLEND_MODES[blendMode]; return (value != null ? value : "none"); } _cancelWebServiceCall() { if (this._activeWebServiceCall == null) return; this._activeWebServiceCall.cancel(); this._activeWebServiceCall = null; } _createItemHandlerPermissions() { const permissions = !this._isIgnorePermissionsMode() ? this._getItemPermissions() : this._getDefaultPermissions(); var permissionOptions = { "AllowDelete": permissions.manipulation.allowDelete, "AllowMoveHorizontal": permissions.manipulation.allowMoveHorizontal, "AllowMoveVertical": permissions.manipulation.allowMoveVertical, "AllowRotate": permissions.manipulation.allowRotate, "ResizeGrips": permissions.manipulation.resizeGrips != null ? { "Edge": permissions.manipulation.resizeGrips.edge, "Corner": permissions.manipulation.resizeGrips.corner } : null, "AllowDragAndDrop": permissions.manipulation.allowDragAndDrop, "NoPrint": permissions.visualization.noPrint, "NoShow": permissions.visualization.noShow, "ShowDeleteToolbarButton": permissions.item.itemToolbarPermissions.showDeleteButton, "ShowEditToolbarButton": permissions.item.itemToolbarPermissions.showEditButton, "ShowHandleToolbarButton": permissions.item.itemToolbarPermissions.showHandleButton, "ShowSelectToolbarButton": permissions.item.itemToolbarPermissions.showSelectButton, "AllowEditContent": permissions.placeholder.allowEditContent, "ShowSelectButton": permissions.placeholder.showSelectButton, "ShowHandleButton": permissions.placeholder.showHandleButton }; var permission = new Permission(permissionOptions, true); return permission; } _createUniqueID() { return (`vo${new Date().getTime()}`) + Math.round(Math.random() * 1000); } _getCallService(methodName, data, success, failure, layerId = null, canvas) { const callPromise = Utils.makeCancelable(new Promise(function (resolve, reject) { const canvasData = JSON.stringify(canvas.getData(true, layerId)); let args = [canvasData]; if (data != null) args = args.concat(data); args = args.concat(resolve, function (error, userContext, methodName) { reject({ error: error, userContext: userContext, methodName: methodName }); }); canvas.service[methodName](...args); })); callPromise.promise .then(function (responseData) { if (typeof success == "function") success(responseData); }) .catch(function (responseData) { if (responseData instanceof Exception) { console.error(`Exception of type ${responseData.name}: ${responseData.message}`); return; } if (responseData.isCanceled) return; const error = responseData.error; if (typeof failure == "function") failure(error); }); return callPromise; } } ItemHandler.DEFAULT_CONTAINER_TRANSPARENCY_ENABLED = true; ItemHandler.DEFAULT_CONTAINER_TRANSPARENCY_LEVEL = 0.8; ItemHandler.typeName = "ItemHandler"; //# sourceMappingURL=ItemHandler.js.map