@aurigma/design-atoms
Version:
Design Atoms is a part of Customer's Canvas SDK which allows for manipulating individual design elements through your code.
327 lines • 19.8 kB
JavaScript
import { CanvasElementHandler } from "../../CanvasElementHandler";
import Environment from "@aurigma/design-atoms-model/Utils/Environment";
import { RotatedRectangleF, PointF, EqualsOfFloatNumbers } from "@aurigma/design-atoms-model/Math";
import * as _ from "underscore";
import { addClassToElement } from "../../Utils/Dom";
import { ArgumentException } from "@aurigma/design-atoms-model/Exception";
import { alignRectToRect } from "../../Utils/Math";
import { CoordinatesConvertUtils } from "../../Utils/CoordinatesConvertUtils";
import { OriginPointType } from "@aurigma/design-atoms-interfaces";
var FloatingToolbarElementHandler = /** @class */ (function () {
function FloatingToolbarElementHandler(_canvasElementHandler, _viewer, _cssClass, _bigButtonCssClass) {
var _this = this;
this._canvasElementHandler = _canvasElementHandler;
this._viewer = _viewer;
this._cssClass = _cssClass;
this._bigButtonCssClass = _bigButtonCssClass;
this._buttonElements = new Map();
this._toolbarElementId = "floatingItemToolbarDiv";
this._centerPositionBottomOffset = 10;
this._visible = false;
this._stopPropagationFnc = function (e) { e.stopPropagation(); };
this._createButtonFromDescription = function (description) {
var handler = description.handler, cssClass = description.cssClass, defaultText = description.defaultText;
var toolbarButton = document.createElement("button");
toolbarButton.type = "button";
toolbarButton.addEventListener("mousedown", _this._stopPropagationFnc);
toolbarButton.addEventListener("dblclick", _this._stopPropagationFnc);
toolbarButton.addEventListener("touchstart", _this._stopPropagationFnc);
toolbarButton.value = defaultText;
toolbarButton.addEventListener("click", handler);
addClassToElement(cssClass, toolbarButton);
return toolbarButton;
};
}
FloatingToolbarElementHandler.prototype.init = function (buttonDescriptions) {
var _this = this;
if (this._viewer == null)
throw new ArgumentException("FloatingToolbarElementHandler.initFloatingItemToolbar: this._viewer cannot be null!");
if (buttonDescriptions == null || buttonDescriptions.size === 0)
throw new ArgumentException("FloatingToolbarElementHandler.initFloatingItemToolbar: buttonDescriptions cannot be empty!");
if (this._descriptions != null)
throw new ArgumentException("FloatingToolbarElementHandler.initFloatingItemToolbar: toolbar have already initialized!");
this._descriptions = buttonDescriptions;
this._toolbarElement = this._createRootElement();
var parent = this._toolbarElement.querySelector("#" + this._toolbarElementId);
buttonDescriptions.forEach(function (desc, key) {
var buttonElement = _this._createButtonFromDescription(desc);
_this._buttonElements.set(key, buttonElement);
parent.appendChild(buttonElement);
});
this._canvasElementHandler.addChild(this._toolbarElement);
this.update();
};
FloatingToolbarElementHandler.prototype.changeButtonsVisibility = function (params) {
var _this = this;
if (_.isEmpty(params))
throw new ArgumentException("FloatingToolbarElementHandler.changeButtonVisibility: params cannot be empty");
params.forEach(function (p) { return _this._changeButtonVisibility(p.id, p.visible); });
this.update();
};
FloatingToolbarElementHandler.prototype._changeButtonVisibility = function (id, visible) {
if (!this._descriptions.has(id))
throw new ArgumentException("FloatingToolbarElementHandler.changeButtonVisibility: There is no button with id='" + id + "' in descriptors map.");
var descriptor = this._descriptions.get(id);
if (descriptor.visible === visible)
return false;
descriptor.visible = visible;
return true;
};
FloatingToolbarElementHandler.prototype.dispose = function () {
var _this = this;
var _a, _b;
this._descriptions = null;
(_a = this._buttonElements) === null || _a === void 0 ? void 0 : _a.forEach(function (button) {
button.removeEventListener("click", _this._stopPropagationFnc);
button.removeEventListener("mousedown", _this._stopPropagationFnc);
button.removeEventListener("dblclick", _this._stopPropagationFnc);
});
(_b = this._toolbarElement) === null || _b === void 0 ? void 0 : _b.remove();
};
FloatingToolbarElementHandler.prototype.changeVisibility = function (value) {
this._visible = value;
return this._updateVisibility();
};
Object.defineProperty(FloatingToolbarElementHandler.prototype, "visible", {
get: function () {
return this._visible;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FloatingToolbarElementHandler.prototype, "isElementVisible", {
get: function () {
return this._visible && this._isAtLeastOneButtonElementIsVisible;
},
enumerable: true,
configurable: true
});
FloatingToolbarElementHandler.prototype._updateVisibility = function () {
var atLeastOneButtonElementIsVisible = this._isAtLeastOneButtonElementIsVisible;
var visible = this._visible && atLeastOneButtonElementIsVisible;
this.isElementVisible ?
CanvasElementHandler.showElement(this._toolbarElement, !atLeastOneButtonElementIsVisible) :
CanvasElementHandler.hideElement(this._toolbarElement, !atLeastOneButtonElementIsVisible);
return visible;
};
Object.defineProperty(FloatingToolbarElementHandler.prototype, "_isAtLeastOneButtonElementIsVisible", {
get: function () {
return Array.from(this._descriptions.values()).map(function (d) { return d.visible; }).some(function (v) { return v; });
},
enumerable: true,
configurable: true
});
FloatingToolbarElementHandler.prototype.update = function () {
var _this = this;
this._updateVisibility();
this._descriptions.forEach(function (description, key) {
var element = _this._buttonElements.get(key);
element.style.display = description.visible ? "block" : "none";
});
};
FloatingToolbarElementHandler.prototype.hitTest = function (pt) {
var divContentRect = this._viewer.canvas.getButtonGroupRectInGripsDiv(this._toolbarElement);
return divContentRect.contains(pt);
};
FloatingToolbarElementHandler.prototype._createRootElement = function () {
var buttonDiv = document.createElement("div");
buttonDiv.style.position = "absolute";
buttonDiv.id = "buttonDiv";
var floatingItemToolbarDiv = document.createElement("div");
floatingItemToolbarDiv.style.display = "flex";
floatingItemToolbarDiv.id = this._toolbarElementId;
addClassToElement(this._cssClass, floatingItemToolbarDiv);
if (Environment.IsTouchDevice())
addClassToElement(this._bigButtonCssClass, floatingItemToolbarDiv);
buttonDiv.appendChild(floatingItemToolbarDiv);
return buttonDiv;
};
FloatingToolbarElementHandler.prototype.updatePosition = function (rectangle, mode) {
if (mode === void 0) { mode = UpdatePositionMode.Smart; }
return mode === UpdatePositionMode.Smart || this.isToolbarLargerThanRectangle(rectangle) ?
this._smartUpdatePosition(rectangle) :
this._updatePositionOnCenter(rectangle);
};
FloatingToolbarElementHandler.prototype.isToolbarLargerThanRectangle = function (rectangle) {
var w = this._toolbarElement.offsetWidth;
var h = this._toolbarElement.offsetHeight + this._centerPositionBottomOffset;
var itemRect = CoordinatesConvertUtils.workspaceToControlRectangle(rectangle.bounds, this._viewer);
return w > itemRect.width || h > itemRect.height;
};
FloatingToolbarElementHandler.prototype._smartUpdatePosition = function (rectangle) {
var currentAngleRotate = rectangle.angle % 360;
var rotatedRect = CanvasElementHandler.rotateRectangle(rectangle, this._viewer);
var z = this._viewer.zoom;
var hs = this._viewer.screenXDpi / 72 * z;
var vs = this._viewer.screenYDpi / 72 * z;
var rectWidth = Math.floor(rotatedRect.width * hs);
var rectHeight = Math.floor(rotatedRect.height * vs);
var containerWidth = this._toolbarElement.offsetWidth;
var containerHeight = this._toolbarElement.offsetHeight;
var abovePositionMultiplier = 3.5;
var isPositionAboveObject = (containerWidth * abovePositionMultiplier) > rectWidth ||
(containerHeight * abovePositionMultiplier) > rectHeight;
var margin = 8;
var offsetX = (isPositionAboveObject ? -containerWidth / 2 : margin) + containerWidth / 2;
var offsetY = (isPositionAboveObject ? -containerHeight : margin) + containerHeight / 2;
var offsetPoint = new PointF(offsetX, offsetY);
offsetPoint.rotate(rotatedRect.angle);
var containerPosition = CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getUpperRightCorner(), this._viewer);
var futurePositionContainer = new PointF(0, 0);
futurePositionContainer.x = Math.max(0, containerPosition.x);
futurePositionContainer.y = Math.max(0, containerPosition.y);
var rotateAngle = this._viewer.contentAngle;
if (currentAngleRotate >= 0 && currentAngleRotate < 90) {
var corners = [
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getUpperLeftCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getUpperRightCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getBottomRightCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getBottomLeftCorner(), this._viewer)
]; // topLeftCorner, topRightCorner, bottomRightCorner, bottomLeftCorner
futurePositionContainer = this._findBetter(corners, rotateAngle, futurePositionContainer, containerHeight, containerWidth);
}
else if (currentAngleRotate >= 180 && currentAngleRotate < 270) {
var corners = [
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getBottomRightCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getBottomLeftCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getUpperLeftCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getUpperRightCorner(), this._viewer)
]; // topLeftCorner, topRightCorner, bottomRightCorner, bottomLeftCorner
futurePositionContainer = this._findBetter(corners, rotateAngle, futurePositionContainer, containerHeight, containerWidth);
}
else if (currentAngleRotate >= 270) {
var corners = [
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getUpperRightCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getBottomRightCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getBottomLeftCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getUpperLeftCorner(), this._viewer)
]; // topLeftCorner, topRightCorner, bottomRightCorner, bottomLeftCorner
futurePositionContainer = this._findBetter(corners, rotateAngle, futurePositionContainer, containerHeight, containerWidth);
}
else { // 90-180
var corners = [
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getBottomLeftCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getUpperLeftCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getUpperRightCorner(), this._viewer),
CoordinatesConvertUtils.workspaceToControlPoint(rotatedRect.getBottomRightCorner(), this._viewer)
]; // topLeftCorner, topRightCorner, bottomRightCorner, bottomLeftCorner
futurePositionContainer = this._findBetter(corners, rotateAngle, futurePositionContainer, containerHeight, containerWidth);
}
this._toolbarElement.style.left = futurePositionContainer.x - 12 + "px";
this._toolbarElement.style.top = futurePositionContainer.y + "px";
};
FloatingToolbarElementHandler.prototype._findBetter = function (corners, rotateAngle, futurePositionContainer, containerHeight, containerWidth) {
/*
Search better position in the following order: top(1), right(2), left(3), bottom(4).
If found then find the best position in it:
- if the area is top or bottom, then the position is horizontal;
- if the area is to the right or left, then the position is vertical.
If don`t found better position, then top right corner(5).
*/
var _this = this;
switch (rotateAngle) {
case 90:
corners = corners.concat(corners.splice(0, 3));
break;
case 180:
corners = corners.concat(corners.splice(0, 2));
break;
case 270:
corners = corners.concat(corners.splice(0, 1));
break;
default: // 0 degree`s
break;
}
var topCornerPosition = corners[0];
var topRightCornerPosition = corners[1]; // container position old
var bottomCornerPosition = corners[2];
var leftCornerPosition = corners[3];
var stopLineRight = this._viewer.element.offsetWidth - (topRightCornerPosition.x + (containerWidth / 2));
var stopLineBottom = this._viewer.element.offsetHeight - bottomCornerPosition.y;
var yCoordination = topCornerPosition.y - 12;
var rotateCircle = document.querySelector("div#rotate-circle");
var circleRadius = 15;
var rotateCirclePosition = null;
if (rotateCircle) {
var pageRotateCircleOffset = rotateCircle.getBoundingClientRect();
rotateCirclePosition = CoordinatesConvertUtils.pageToControlPoint(new PointF(pageRotateCircleOffset.left, pageRotateCircleOffset.top), this._viewer);
}
var rotateCircleCovered = function () {
return rotateCirclePosition != null
&&
(rotateCirclePosition.y + circleRadius > futurePositionContainer.y && rotateCirclePosition.y - circleRadius < futurePositionContainer.y + containerHeight)
&&
(rotateCirclePosition.x + 2 * circleRadius > futurePositionContainer.x && rotateCirclePosition.x - 2 * circleRadius < futurePositionContainer.x + containerWidth);
};
var calculatedHorizontalPosition = function () {
if (stopLineRight < 0)
futurePositionContainer.x = topRightCornerPosition.x - (containerWidth / 2) - 5 + stopLineRight;
else
futurePositionContainer.x = topRightCornerPosition.x - (containerWidth / 2) - 5;
if (rotateCircleCovered())
if (stopLineRight > 0 && (_this._viewer.element.offsetWidth - (rotateCirclePosition.x + 2 * circleRadius + containerWidth + 5)) > 0)
futurePositionContainer.x = rotateCirclePosition.x + 2 * circleRadius;
else
futurePositionContainer.x = rotateCirclePosition.x - circleRadius - containerWidth;
return futurePositionContainer.x;
};
var calculatedVerticalPosition = function () {
if (topCornerPosition.y - containerHeight > 0)
futurePositionContainer.y = topCornerPosition.y - containerHeight;
else
futurePositionContainer.y = 0;
if (rotateCircleCovered())
futurePositionContainer.y = rotateCirclePosition.y + circleRadius;
return futurePositionContainer.y;
};
if (yCoordination > containerHeight) { // 1
futurePositionContainer.y = topCornerPosition.y - containerHeight - 12;
futurePositionContainer.x = calculatedHorizontalPosition();
}
else {
if (stopLineRight - (containerWidth / 2 + 5) > 0) { // 2
futurePositionContainer.x = topRightCornerPosition.x + 5;
futurePositionContainer.y = calculatedVerticalPosition();
}
else if (stopLineRight - (containerWidth / 2 + 5) < 0) { // 3
if (leftCornerPosition.x - containerWidth - 5 > 5) {
futurePositionContainer.x = leftCornerPosition.x - containerWidth - 5;
futurePositionContainer.y = calculatedVerticalPosition();
}
else { // 4
futurePositionContainer.x = calculatedHorizontalPosition();
if (stopLineBottom > containerHeight) {
futurePositionContainer.y = bottomCornerPosition.y;
}
else { // 5
futurePositionContainer.y = calculatedVerticalPosition();
}
}
}
}
futurePositionContainer.x += this._viewer.element.scrollLeft;
futurePositionContainer.y += this._viewer.element.scrollTop;
return futurePositionContainer;
};
FloatingToolbarElementHandler.prototype._updatePositionOnCenter = function (rectangle) {
if (!(EqualsOfFloatNumbers(rectangle.angle % 90, 0) && !EqualsOfFloatNumbers(rectangle.angle, 360)))
throw new ArgumentException("FloatingToolbarElementHandler._updatePositionOnCenter: mode supports only rectangles without angle");
var controlRectangle = CanvasElementHandler.getControlRectangle(rectangle, this._viewer);
var w = this._toolbarElement.offsetWidth;
var h = this._toolbarElement.offsetHeight;
var angle = rectangle.angle;
var toolbarRectangle = RotatedRectangleF.FromLTRB(0, 0, w, h);
var itemRectangle = RotatedRectangleF.fromRectangleF(RotatedRectangleF.fromRectangleF(controlRectangle, angle).bounds);
var targetRect = alignRectToRect(toolbarRectangle, itemRectangle, OriginPointType.Center, OriginPointType.Bottom).bounds;
this._toolbarElement.style.left = targetRect.left + "px";
this._toolbarElement.style.top = (targetRect.top - this._centerPositionBottomOffset) + "px";
};
return FloatingToolbarElementHandler;
}());
export { FloatingToolbarElementHandler };
export var UpdatePositionMode;
(function (UpdatePositionMode) {
UpdatePositionMode[UpdatePositionMode["Smart"] = 0] = "Smart";
UpdatePositionMode[UpdatePositionMode["Center"] = 1] = "Center";
})(UpdatePositionMode || (UpdatePositionMode = {}));
//# sourceMappingURL=FloatingToolbarElementHandler.js.map