8439 lines
299 KiB
JavaScript
8439 lines
299 KiB
JavaScript
/*
|
|
* (c) Copyright Ascensio System SIA 2010-2023
|
|
*
|
|
* This program is a free software product. You can redistribute it and/or
|
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
* version 3 as published by the Free Software Foundation. In accordance with
|
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
* of any third-party rights.
|
|
*
|
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
*
|
|
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
|
* street, Riga, Latvia, EU, LV-1050.
|
|
*
|
|
* The interactive user interfaces in modified source and object code versions
|
|
* of the Program must display Appropriate Legal Notices, as required under
|
|
* Section 5 of the GNU AGPL version 3.
|
|
*
|
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
* grant you any rights under trademark law for use of our trademarks.
|
|
*
|
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
* well as technical writing content are licensed under the terms of the
|
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
*
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
(function (window) {
|
|
// const IS_DEBUG_DRAWING = true;
|
|
// const IS_ADD_HTML = false;
|
|
AscCommon.IS_GENERATE_SMARTART_AND_TEXT_ON_OPEN = false;
|
|
|
|
const LayoutNode = AscFormat.LayoutNode;
|
|
const Choose = AscFormat.Choose;
|
|
const If = AscFormat.If;
|
|
const Else = AscFormat.Else;
|
|
const Alg = AscFormat.Alg;
|
|
const ForEach = AscFormat.ForEach;
|
|
const Point = AscFormat.Point;
|
|
const ConstrLst = AscFormat.ConstrLst;
|
|
const SShape = AscFormat.SShape;
|
|
const PresOf = AscFormat.PresOf;
|
|
const RuleLst = AscFormat.RuleLst;
|
|
const VarLst = AscFormat.VarLst;
|
|
const LayoutBaseClass = AscFormat.LayoutBaseClass;
|
|
const IteratorLayoutBase = AscFormat.IteratorLayoutBase;
|
|
|
|
const degToRad = Math.PI / 180;
|
|
const radToDeg = 1 / degToRad;
|
|
const algDelta = 1e-10;
|
|
const intDelta = 1e-2;
|
|
|
|
const factRuleState = {
|
|
default: 0,
|
|
enabled: 1,
|
|
disabled: 2
|
|
};
|
|
Math.imul =
|
|
Math.imul ||
|
|
function (a, b) {
|
|
var ah = (a >>> 16) & 0xffff;
|
|
var al = a & 0xffff;
|
|
var bh = (b >>> 16) & 0xffff;
|
|
var bl = b & 0xffff;
|
|
return (al * bl + (((ah * bl + al * bh) << 16) >>> 0)) | 0;
|
|
};
|
|
function cyrb128(str) {
|
|
let h1 = 1779033703, h2 = 3144134277,
|
|
h3 = 1013904242, h4 = 2773480762;
|
|
for (let i = 0, k; i < str.length; i++) {
|
|
k = str.charCodeAt(i);
|
|
h1 = h2 ^ Math.imul(h1 ^ k, 597399067);
|
|
h2 = h3 ^ Math.imul(h2 ^ k, 2869860233);
|
|
h3 = h4 ^ Math.imul(h3 ^ k, 951274213);
|
|
h4 = h1 ^ Math.imul(h4 ^ k, 2716044179);
|
|
}
|
|
h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067);
|
|
h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233);
|
|
h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213);
|
|
h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179);
|
|
h1 ^= (h2 ^ h3 ^ h4), h2 ^= h1, h3 ^= h1, h4 ^= h1;
|
|
return [h1>>>0, h2>>>0, h3>>>0, h4>>>0];
|
|
}
|
|
function sfc32(a, b, c, d) {
|
|
return function() {
|
|
a |= 0; b |= 0; c |= 0; d |= 0;
|
|
let t = (a + b | 0) + d | 0;
|
|
d = d + 1 | 0;
|
|
a = b ^ b >>> 9;
|
|
b = c + (c << 3) | 0;
|
|
c = (c << 21 | c >>> 11);
|
|
c = c + t | 0;
|
|
return (t >>> 0) / 4294967296;
|
|
}
|
|
}
|
|
function CreateTemplateGUID(randomFunc) {
|
|
function s4() {
|
|
return Math.floor((1 + randomFunc()) * 0x10000).toString(16).substring(1);
|
|
}
|
|
|
|
let val = '{' + s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4() + '}';
|
|
val = val.toUpperCase();
|
|
return val;
|
|
}
|
|
function GUIDGenerator(str) {
|
|
this.randomFunc = sfc32.apply(sfc32, cyrb128(str));
|
|
}
|
|
GUIDGenerator.prototype.getGUID = function() {
|
|
return CreateTemplateGUID(this.randomFunc);
|
|
};
|
|
function getDefaultColorsStyleLbl() {
|
|
return AscFormat.ExecuteNoHistory(function () {
|
|
const styleLbl = new AscFormat.ColorDefStyleLbl();
|
|
styleLbl.setName("noName");
|
|
styleLbl.setFillClrLst(new AscFormat.ClrLst());
|
|
styleLbl.fillClrLst.addToLst(0, AscFormat.CreateUniColorRGB(0, 0, 0));
|
|
styleLbl.setLinClrLst(new AscFormat.ClrLst());
|
|
styleLbl.linClrLst.addToLst(0, AscFormat.CreateUniColorRGB(0, 0, 0));
|
|
return styleLbl;
|
|
});
|
|
}
|
|
function isClockwisePoints(centerPoint, edgePoint1, edgePoint2) {
|
|
const rectSum = (centerPoint.x - edgePoint1.x) * (edgePoint2.y - edgePoint1.y) -
|
|
(edgePoint2.x - edgePoint1.x) * (centerPoint.y - edgePoint1.y);
|
|
return rectSum < 0;
|
|
}
|
|
|
|
function checkBounds(firstBounds, secondBounds) {
|
|
if (secondBounds.l < firstBounds.l) {
|
|
firstBounds.l = secondBounds.l;
|
|
}
|
|
if (secondBounds.t < firstBounds.t) {
|
|
firstBounds.t = secondBounds.t;
|
|
}
|
|
if (secondBounds.r > firstBounds.r) {
|
|
firstBounds.r = secondBounds.r;
|
|
}
|
|
if (secondBounds.b > firstBounds.b) {
|
|
firstBounds.b = secondBounds.b;
|
|
}
|
|
}
|
|
|
|
function fAlgDeltaEqual(a, b) {
|
|
return AscFormat.fApproxEqual(a, b, algDelta);
|
|
}
|
|
function fIntervalDeltaEqual(a, b) {
|
|
return AscFormat.fApproxEqual(a, b, intDelta);
|
|
}
|
|
|
|
function CCoordPoint(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
LayoutBaseClass.prototype.executeLayoutAlgorithms = function(smartartAlgorithm) {
|
|
if (this.shape) {
|
|
this.shape.executeAlgorithm(smartartAlgorithm);
|
|
}
|
|
if (this.alg) {
|
|
this.alg.executeAlgorithm(smartartAlgorithm);
|
|
}
|
|
for (let i = 0; i < this.list.length; i++) {
|
|
this.list[i].executeAlgorithm(smartartAlgorithm);
|
|
}
|
|
if (this.presOf) {
|
|
this.presOf.executeAlgorithm(smartartAlgorithm);
|
|
}
|
|
if (this.constrLst) {
|
|
this.constrLst.executeAlgorithm(smartartAlgorithm);
|
|
}
|
|
if (this.ruleLst) {
|
|
this.ruleLst.executeAlgorithm(smartartAlgorithm);
|
|
}
|
|
if (this.varLst) {
|
|
this.varLst.executeAlgorithm(smartartAlgorithm);
|
|
}
|
|
};
|
|
IteratorLayoutBase.prototype.executeLayoutAlgorithms = LayoutBaseClass.prototype.executeLayoutAlgorithms;
|
|
CCoordPoint.prototype.getVector = function (point) {
|
|
return new CVector(point.x - this.x, point.y - this.y);
|
|
}
|
|
function CVector(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
CVector.getVectorByAngle = function (angle) {
|
|
return new CVector(Math.cos(angle), Math.sin(angle));
|
|
};
|
|
CVector.prototype.getDistance = function () {
|
|
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
};
|
|
CVector.prototype.getDiffVector = function (vector) {
|
|
return new CVector(this.x - vector.x, this.y - vector.y);
|
|
};
|
|
CVector.prototype.multiply = function (value) {
|
|
this.x *= value;
|
|
this.y *= value;
|
|
};
|
|
CVector.prototype.getAngle = function () {
|
|
const x = this.x;
|
|
const y = this.y;
|
|
const vectorLength = Math.sqrt(x * x + y * y);
|
|
if (vectorLength !== 0) {
|
|
const angle = Math.acos(x / vectorLength);
|
|
if (y > 0) {
|
|
return angle;
|
|
}
|
|
return AscFormat.normalizeRotate(-angle);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
CVector.prototype.getAngleBetween = function (vector, isAntiClockwise) {
|
|
let currentAngle = this.getAngle();
|
|
let anotherAngle = vector.getAngle();
|
|
|
|
if (isAntiClockwise) {
|
|
if (currentAngle < anotherAngle) {
|
|
currentAngle += Math.PI * 2;
|
|
}
|
|
return currentAngle - anotherAngle;
|
|
} else {
|
|
if (anotherAngle < currentAngle || fAlgDeltaEqual(anotherAngle, currentAngle)) {
|
|
anotherAngle += Math.PI * 2;
|
|
}
|
|
return anotherAngle - currentAngle;
|
|
}
|
|
};
|
|
|
|
VarLst.prototype.executeAlgorithm = function (smartartAlgorithm) {};
|
|
|
|
PresOf.prototype.executeAlgorithm = function (smartartAlgorithm) {
|
|
const currentPresNode = smartartAlgorithm.getCurrentPresNode();
|
|
const nodes = this.getNodesArray(smartartAlgorithm);
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
const node = nodes[i];
|
|
currentPresNode.contentNodes.push(node);
|
|
if (currentPresNode.algorithm instanceof TextAlgorithm) {
|
|
node.presOf.textNode = currentPresNode;
|
|
} else if (currentPresNode.layoutInfo.shape && !currentPresNode.layoutInfo.shape.hideGeom && currentPresNode.layoutInfo.shape.type !== AscFormat.LayoutShapeType_outputShapeType_none) {
|
|
node.presOf.contentNode = currentPresNode;
|
|
}
|
|
}
|
|
|
|
if (nodes.length) {
|
|
currentPresNode.node = nodes[0] || smartartAlgorithm.getCurrentNode();
|
|
}
|
|
};
|
|
LayoutNode.prototype.executeAlgorithm = function (smartartAlgorithm) {
|
|
const parentPresNode = smartartAlgorithm.getCurrentPresNode();
|
|
const curPresNode = smartartAlgorithm.getPresNode(this);
|
|
parentPresNode.addChild(curPresNode);
|
|
smartartAlgorithm.addCurrentPresNode(curPresNode);
|
|
this.executeLayoutAlgorithms(smartartAlgorithm);
|
|
curPresNode.checkMoveWith();
|
|
curPresNode.initPresShape();
|
|
smartartAlgorithm.removeCurrentPresNode(curPresNode);
|
|
}
|
|
LayoutNode.prototype.getForEachMap = function () {
|
|
const forEachMap = {};
|
|
const elements = [this];
|
|
while (elements.length) {
|
|
const element = elements.pop();
|
|
|
|
const list = element.list;
|
|
if (list) {
|
|
elements.push.apply(elements, list);
|
|
}
|
|
if (element instanceof ForEach) {
|
|
forEachMap[element.name] = element;
|
|
}
|
|
}
|
|
return forEachMap;
|
|
}
|
|
|
|
Choose.prototype.executeAlgorithm = function (smartartAlgorithm) {
|
|
for (let i = 0; i < this.if.length; i++) {
|
|
if (this.if[i].executeAlgorithm(smartartAlgorithm)) {
|
|
return;
|
|
}
|
|
}
|
|
this.else.executeAlgorithm(smartartAlgorithm);
|
|
};
|
|
|
|
|
|
If.prototype.executeAlgorithm = function (smartartAlgorithm) {
|
|
if (this.checkCondition(smartartAlgorithm)) {
|
|
this.executeLayoutAlgorithms(smartartAlgorithm);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
If.prototype.checkCondition = function (smartArtAlgorithm) {
|
|
const node = smartArtAlgorithm.getCurrentNode();
|
|
const nodes = this.getNodesArray(smartArtAlgorithm);
|
|
|
|
switch (this.func) {
|
|
case AscFormat.If_func_cnt:
|
|
return this.funcCnt(nodes);
|
|
case AscFormat.If_func_depth:
|
|
return this.funcDepth(node);
|
|
case AscFormat.If_func_maxDepth:
|
|
const depth = node.isParNode() ? node.depth - 1 : node.depth;
|
|
return this.funcMaxDepth(nodes, depth);
|
|
case AscFormat.If_func_pos:
|
|
return this.funcPos(nodes, node);
|
|
case AscFormat.If_func_posEven:
|
|
return this.funcPosEven(nodes, node);
|
|
case AscFormat.If_func_posOdd:
|
|
return this.funcPosOdd(nodes, node);
|
|
case AscFormat.If_func_revPos:
|
|
return this.funcRevPos(nodes, node);
|
|
case AscFormat.If_func_var:
|
|
return this.funcVar(smartArtAlgorithm);
|
|
default:
|
|
return false;
|
|
}
|
|
};
|
|
|
|
If.prototype.check = function (expected, result) {
|
|
switch (this.op) {
|
|
case AscFormat.If_op_equ: {
|
|
return expected === result;
|
|
}
|
|
case AscFormat.If_op_gt: {
|
|
return result > expected;
|
|
}
|
|
case AscFormat.If_op_lt: {
|
|
return result < expected;
|
|
}
|
|
case AscFormat.If_op_gte: {
|
|
return result >= expected;
|
|
}
|
|
case AscFormat.If_op_lte: {
|
|
return result <= expected;
|
|
}
|
|
case AscFormat.If_op_neq: {
|
|
return result !== expected;
|
|
}
|
|
default: {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
If.prototype.funcPosEven = function (nodes, currentNode) {
|
|
const conditionValue = parseInt(this.getConditionValue(), 10);
|
|
for (let i = 0; i < nodes.length; i += 1) {
|
|
if (nodes === currentNode) {
|
|
return this.check(conditionValue, (i + 1) % 2 === 0 ? 1 : 0);
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
If.prototype.funcPosOdd = function (nodes, currentNode) {
|
|
const conditionValue = parseInt(this.getConditionValue(), 10);
|
|
const position = currentNode.getPositionByParent() + 1;
|
|
return this.check(conditionValue, position % 2);
|
|
};
|
|
If.prototype.funcPos = function (nodes, currentNode) {
|
|
const conditionValue = parseInt(this.getConditionValue(), 10);
|
|
const position = currentNode.getPositionByParent() + 1;
|
|
return this.check(conditionValue, position);
|
|
};
|
|
If.prototype.funcRevPos = function (nodes, currentNode) {
|
|
const conditionValue = parseInt(this.getConditionValue(), 10);
|
|
const position = currentNode.getPositionByParent();
|
|
const parentLength = currentNode.getParentChildLength();
|
|
return this.check(conditionValue, parentLength - position);
|
|
};
|
|
If.prototype.funcDepth = function (currentNode) {
|
|
const conditionValue = parseInt(this.getConditionValue(), 10);
|
|
return this.check(conditionValue, currentNode.depth);
|
|
};
|
|
If.prototype.funcMaxDepth = function (nodes, curDepth) {
|
|
const conditionValue = parseInt(this.getConditionValue(), 10);
|
|
let maxDepth = curDepth;
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
const depth = nodes[i].getChildDepth();
|
|
if (depth > maxDepth) {
|
|
maxDepth = depth;
|
|
}
|
|
}
|
|
return this.check(conditionValue, maxDepth - curDepth);
|
|
};
|
|
If.prototype.getVarPoint = function (smartArtAlgorithm) {
|
|
let node;
|
|
switch (this.arg) {
|
|
case AscFormat.If_arg_dir: {
|
|
node = smartArtAlgorithm.getRootPresNode();
|
|
break;
|
|
}
|
|
default:
|
|
node = smartArtAlgorithm.getCurrentPresNode();
|
|
while (node && node.presPoint && !(node.presPoint.prSet && node.presPoint.prSet.presLayoutVars)) {
|
|
if (!(node.parent && node.parent.presPoint)) {
|
|
break;
|
|
}
|
|
node = node.parent;
|
|
}
|
|
break;
|
|
}
|
|
return node && node.presPoint;
|
|
};
|
|
If.prototype.funcVar = function (smartArtAlgorithm) {
|
|
const point = this.getVarPoint(smartArtAlgorithm);
|
|
const nodeVal = point && point.getFuncVarValue(this.arg);
|
|
return this.check(this.getConditionValue(), nodeVal);
|
|
}
|
|
If.prototype.funcCnt = function (nodes) {
|
|
return this.check(parseInt(this.val, 10), nodes.length);
|
|
}
|
|
If.prototype.getConditionValue = function () {
|
|
switch (this.arg) {
|
|
case AscFormat.If_arg_dir: {
|
|
return this.getConditionDirValue();
|
|
}
|
|
case AscFormat.If_arg_hierBranch: {
|
|
return this.getConditionHierBranchValue();
|
|
}
|
|
default:
|
|
return this.val;
|
|
}
|
|
};
|
|
If.prototype.getConditionHierBranchValue = function () {
|
|
switch (this.val) {
|
|
case 'l':
|
|
return AscFormat.HierBranch_val_l;
|
|
case 'r':
|
|
return AscFormat.HierBranch_val_r;
|
|
case 'hang':
|
|
return AscFormat.HierBranch_val_hang;
|
|
case 'init':
|
|
return AscFormat.HierBranch_val_init;
|
|
case 'std':
|
|
return AscFormat.HierBranch_val_std;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
If.prototype.getConditionDirValue = function () {
|
|
switch (this.val) {
|
|
case 'norm':
|
|
return AscFormat.DiagramDirection_val_norm;
|
|
case 'rev':
|
|
return AscFormat.DiagramDirection_val_rev;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
ConstrLst.prototype.executeAlgorithm = function (smartartAlgorithm) {
|
|
smartartAlgorithm.setConstraints(this.list);
|
|
}
|
|
|
|
RuleLst.prototype.executeAlgorithm = function (smartartAlgorithm) {
|
|
smartartAlgorithm.setRules(this.list);
|
|
}
|
|
|
|
Else.prototype.executeAlgorithm = function (smartartAlgorithm) {
|
|
this.executeLayoutAlgorithms(smartartAlgorithm);
|
|
}
|
|
|
|
ForEach.prototype.executeAlgorithm = function (smartartAlgorithm) {
|
|
const refForEach = smartartAlgorithm.getForEach(this.ref);
|
|
if (refForEach) {
|
|
refForEach.executeAlgorithm(smartartAlgorithm);
|
|
return;
|
|
}
|
|
const currentNode = smartartAlgorithm.getCurrentNode();
|
|
|
|
let isHideLastTrans2 = this.getHideLastTrans(0);
|
|
if (!isHideLastTrans2) {
|
|
const parent = currentNode.parent || currentNode;
|
|
const lastChild = parent.childs[parent.childs.length - 1];
|
|
if (lastChild && lastChild.sibNode) {
|
|
lastChild.sibNode.isHideLastTrans = false;
|
|
}
|
|
}
|
|
const nodes = this.getNodesArray(smartartAlgorithm);
|
|
for (let i = 0; i < nodes.length; i += 1) {
|
|
const node = nodes[i];
|
|
smartartAlgorithm.addCurrentNode(node);
|
|
this.executeLayoutAlgorithms(smartartAlgorithm);
|
|
smartartAlgorithm.removeCurrentNode();
|
|
}
|
|
};
|
|
|
|
Alg.prototype.getAlgorithm = function (smartartAlgorithm) {
|
|
let algorithm;
|
|
switch (this.getType()) {
|
|
case AscFormat.Alg_type_snake: {
|
|
algorithm = new SnakeAlgorithm();
|
|
break;
|
|
}
|
|
case AscFormat.Alg_type_tx: {
|
|
algorithm = new TextAlgorithm();
|
|
break;
|
|
}
|
|
case AscFormat.Alg_type_sp: {
|
|
algorithm = new SpaceAlgorithm();
|
|
break;
|
|
}
|
|
case AscFormat.Alg_type_composite: {
|
|
algorithm = new CompositeAlgorithm();
|
|
break;
|
|
}
|
|
case AscFormat.Alg_type_lin: {
|
|
algorithm = new LinearAlgorithm();
|
|
break;
|
|
}
|
|
case AscFormat.Alg_type_conn: {
|
|
algorithm = new ConnectorAlgorithm();
|
|
break;
|
|
}
|
|
case AscFormat.Alg_type_cycle: {
|
|
algorithm = new CycleAlgorithm();
|
|
break;
|
|
}
|
|
case AscFormat.Alg_type_pyra: {
|
|
algorithm = new PyramidAlgorithm();
|
|
break;
|
|
}
|
|
case AscFormat.Alg_type_hierRoot: {
|
|
algorithm = new HierarchyRootAlgorithm();
|
|
break;
|
|
}
|
|
case AscFormat.Alg_type_hierChild: {
|
|
algorithm = new HierarchyChildAlgorithm();
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
if (algorithm) {
|
|
algorithm.setParams(this.param);
|
|
algorithm.setParentNode(smartartAlgorithm.getCurrentPresNode());
|
|
}
|
|
return algorithm;
|
|
};
|
|
|
|
Alg.prototype.executeAlgorithm = function (smartartAlgorithm) {
|
|
const node = smartartAlgorithm.getCurrentPresNode();
|
|
node.setAlgorithm(this.getAlgorithm(smartartAlgorithm));
|
|
}
|
|
Point.prototype.getFuncVarValue = function(arg) {
|
|
const varLst = this.prSet && this.prSet.presLayoutVars;
|
|
switch (arg) {
|
|
case AscFormat.If_arg_dir:
|
|
if (varLst && varLst.dir !== null) {
|
|
return varLst.dir;
|
|
}
|
|
return AscFormat.DiagramDirection_val_norm;
|
|
case AscFormat.If_arg_hierBranch:
|
|
if (varLst && varLst.hierBranch !== null) {
|
|
return varLst.hierBranch;
|
|
}
|
|
return AscFormat.HierBranch_val_std;
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
|
|
SShape.prototype.executeAlgorithm = function (smartartAlgoritm) {
|
|
const presNode = smartartAlgoritm.getCurrentPresNode();
|
|
presNode.layoutInfo.shape = this;
|
|
}
|
|
|
|
function SmartArtAlgorithm(smartart) {
|
|
this.smartart = smartart;
|
|
this.relations = this.smartart.getRelationOfContent2();
|
|
this.dataRoot = null;
|
|
this.presRoot = null;
|
|
this.nodesStack = [];
|
|
this.presNodesStack = [];
|
|
this.presNodesInfoStack = [];
|
|
this.connectorAlgorithmStack = [];
|
|
this.moveShapeSettings = [];
|
|
this.forEachMap = null;
|
|
this.factRuleState = factRuleState.default;
|
|
this.guidGenerator = new GUIDGenerator(this.getModelIdStr());
|
|
this.initDataTree();
|
|
}
|
|
SmartArtAlgorithm.prototype.getModelIdStr = function() {
|
|
const data = this.smartart.getDataModelFromData();
|
|
if (data) {
|
|
const ptLst = data.getPtLst();
|
|
if (ptLst) {
|
|
return ptLst.getModelIdStr();
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
SmartArtAlgorithm.prototype.createPresNode = function (presName, styleLbl, contentNode) {
|
|
presName = presName || "";
|
|
const point = new Point();
|
|
point.setType(AscFormat.Point_type_pres);
|
|
const prSet = new AscFormat.PrSet();
|
|
prSet.setPresName(presName);
|
|
prSet.setPresStyleLbl(styleLbl || "node1");
|
|
|
|
point.setPrSet(prSet);
|
|
point.setModelId(this.getNewGUID());
|
|
return new PresNode(point, contentNode);
|
|
};
|
|
SmartArtAlgorithm.prototype.forEachContentNode = function (callback) {
|
|
const nodes = [this.dataRoot];
|
|
callback(this.dataRoot, 0);
|
|
while (nodes.length) {
|
|
const node = nodes.pop();
|
|
for (let i = 0; i < node.childs.length; i++) {
|
|
const child = node.childs[i];
|
|
callback(child, i);
|
|
nodes.push(child);
|
|
}
|
|
}
|
|
};
|
|
SmartArtAlgorithm.prototype.getDataPointRelations = function () {
|
|
const mapRelations = {};
|
|
this.forEachContentNode(function (node) {
|
|
mapRelations[node.point.getModelId()] = node;
|
|
if (node.sibNode) {
|
|
mapRelations[node.sibNode.point.getModelId()] = node.sibNode;
|
|
}
|
|
if (node.parNode) {
|
|
mapRelations[node.parNode.point.getModelId()] = node.parNode;
|
|
}
|
|
});
|
|
return mapRelations;
|
|
};
|
|
SmartArtAlgorithm.prototype.setFactRuleState = function (pr) {
|
|
this.factRuleState = pr;
|
|
};
|
|
SmartArtAlgorithm.prototype.addSettingsForMove = function (settings) {
|
|
this.moveShapeSettings.push(settings);
|
|
};
|
|
SmartArtAlgorithm.prototype.applySettingsForMove = function () {
|
|
while (this.moveShapeSettings.length) {
|
|
const settings = this.moveShapeSettings.pop();
|
|
const coefficient = settings.coefficient;
|
|
const shape = settings.shape;
|
|
|
|
const presNode = shape.node;
|
|
const prSet = presNode.getPrSet();
|
|
let neighborWidth = null;
|
|
let neighborHeight = null;
|
|
const neighbor = presNode.getNeighbor();
|
|
const neighborShape = neighbor.shape;
|
|
/* if (neighborShape) {
|
|
if (presNode.node.isSibNode()) {
|
|
neighborHeight = neighborShape.cleanParams.height;
|
|
} else {
|
|
neighborWidth = neighborShape.cleanParams.width;
|
|
}
|
|
}*/
|
|
if (prSet) {
|
|
let offX = 0;
|
|
let offY = 0;
|
|
const radialInfo = shape.getCustomRadialInfo();
|
|
if (radialInfo) {
|
|
const custScaleRadius = prSet.custRadScaleRad === null ? 1 : prSet.custRadScaleRad;
|
|
const custScaleAngle = prSet.custRadScaleInc === null ? 0 : prSet.custRadScaleInc;
|
|
if (custScaleRadius !== 1 || custScaleAngle !== 0) {
|
|
const shapeCenterPoint = new CCoordPoint(shape.x + shape.width / 2, shape.y + shape.height / 2);
|
|
const centerPoint = new CCoordPoint(shapeCenterPoint.x - shape.radialVector.x, shapeCenterPoint.y - shape.radialVector.y);
|
|
const customRadius = radialInfo.radius;
|
|
const custAngle = radialInfo.angle;
|
|
const custVector = CVector.getVectorByAngle(custAngle);
|
|
custVector.multiply(customRadius);
|
|
const custCenterPoint = new CCoordPoint(custVector.x + centerPoint.x, custVector.y + centerPoint.y);
|
|
offX = custCenterPoint.x - shape.width / 2 - shape.x;
|
|
offY = custCenterPoint.y - shape.height / 2 - shape.y;
|
|
shape.custCenterPoint = centerPoint;
|
|
}
|
|
}
|
|
|
|
if (prSet.custLinFactNeighborX) {
|
|
const width = neighborWidth !== null ? neighborWidth : shape.cleanParams.width;
|
|
offX += width * prSet.custLinFactNeighborX * coefficient;
|
|
}
|
|
if (prSet.custLinFactX) {
|
|
offX += shape.cleanParams.width * prSet.custLinFactX * coefficient;
|
|
}
|
|
if (prSet.custLinFactNeighborY) {
|
|
const height = neighborHeight !== null ? neighborHeight : shape.cleanParams.height;
|
|
offY += height * prSet.custLinFactNeighborY * coefficient;
|
|
}
|
|
if (prSet.custLinFactY) {
|
|
offY += shape.cleanParams.height * prSet.custLinFactY * coefficient;
|
|
}
|
|
|
|
const smartart = this.smartart;
|
|
const smartartHeight = smartart.spPr.xfrm.extY;
|
|
const smartartWidth = smartart.spPr.xfrm.extX;
|
|
const shapeBounds = shape.getBounds();
|
|
if (shapeBounds.l + offX < 0) {
|
|
offX = -shapeBounds.l;
|
|
} else if (shapeBounds.r + offX > smartartWidth) {
|
|
offX = smartartWidth - shapeBounds.r;
|
|
}
|
|
if (shapeBounds.t + offY < 0) {
|
|
offY = -shapeBounds.t;
|
|
} else if (shapeBounds.b + offY > smartartHeight) {
|
|
offY = smartartHeight - shapeBounds.b;
|
|
}
|
|
if (shape.radialVector) {
|
|
shape.radialVector = new CVector(shape.radialVector.x + offX, shape.radialVector.y + offY);
|
|
}
|
|
shape.moveTo(offX, offY);
|
|
}
|
|
}
|
|
};
|
|
SmartArtAlgorithm.prototype.getForEachMap = function() {
|
|
if (this.forEachMap === null) {
|
|
const layout = this.smartart.getLayoutDef();
|
|
const layoutNode = layout.getLayoutNode();
|
|
this.forEachMap = layoutNode.getForEachMap();
|
|
}
|
|
return this.forEachMap;
|
|
};
|
|
SmartArtAlgorithm.prototype.getForEach = function (ref) {
|
|
const forEachMap = this.getForEachMap();
|
|
return forEachMap[ref];
|
|
};
|
|
SmartArtAlgorithm.prototype.addConnectorAlgorithm = function (algorithm) {
|
|
this.connectorAlgorithmStack.push(algorithm);
|
|
}
|
|
SmartArtAlgorithm.prototype.getParentObjects = function () {
|
|
const smartart = this.smartart;
|
|
return smartart.getParentObjects();
|
|
};
|
|
SmartArtAlgorithm.prototype.getInitObjects = function () {
|
|
const api = Asc.editor;
|
|
if (!api) {
|
|
return null;
|
|
}
|
|
const smartart = this.smartart;
|
|
const initObjects = Object.create(this.getParentObjects());
|
|
initObjects.worksheet = null;
|
|
initObjects.parent = null;
|
|
initObjects.drawingObjects = null;
|
|
initObjects.drawingDocument = api.getDrawingDocument();
|
|
const editorId = api.getEditorId();
|
|
if (editorId === AscCommon.c_oEditorId.Spreadsheet) {
|
|
initObjects.worksheet = smartart.worksheet;
|
|
initObjects.drawingObjects = smartart.drawingObjects;
|
|
} else if (editorId === AscCommon.c_oEditorId.Presentation) {
|
|
initObjects.parent = smartart.parent;
|
|
}
|
|
return initObjects;
|
|
};
|
|
SmartArtAlgorithm.prototype.applyColorsDef = function (shadowShapes) {
|
|
const colorsDef = this.smartart.getColorsDef();
|
|
const stylesDef = this.smartart.getStyleDef();
|
|
const styleLblsByName = stylesDef.styleLbl;
|
|
const colorLblsByName = colorsDef.styleLbl;
|
|
const parentObjects = this.getParentObjects();
|
|
const shapesByStyleLbl = {};
|
|
for (let i = 0; i < shadowShapes.length; i += 1) {
|
|
const shadowShape = shadowShapes[i];
|
|
const node = shadowShape.node;
|
|
const styleLbl = node.getPresStyleLbl();
|
|
if (styleLbl) {
|
|
if (!shapesByStyleLbl[styleLbl]) {
|
|
shapesByStyleLbl[styleLbl] = [];
|
|
}
|
|
shapesByStyleLbl[styleLbl].push(shadowShape.connectorShape || shadowShape);
|
|
}
|
|
}
|
|
for (let styleLbl in shapesByStyleLbl) {
|
|
const colorLbl = colorLblsByName[styleLbl] || getDefaultColorsStyleLbl();
|
|
const shapes = shapesByStyleLbl[styleLbl];
|
|
if (colorLbl) {
|
|
colorLbl.setShapeFill(shapes, parentObjects);
|
|
colorLbl.setShapeLn(shapes, parentObjects);
|
|
}
|
|
const quickStyleLbl = styleLblsByName[styleLbl];
|
|
if (quickStyleLbl) {
|
|
quickStyleLbl.setShapeStyle(shapes);
|
|
}
|
|
}
|
|
};
|
|
|
|
SmartArtAlgorithm.prototype.initDataTree = function () {
|
|
const dataModel = this.smartart.getDataModel().getDataModel();
|
|
const mainSmartArtPoint = dataModel.getMainPoint();
|
|
const treeRoot = new SmartArtDataNode(mainSmartArtPoint, 0);
|
|
this.dataRoot = treeRoot;
|
|
const elements = [treeRoot];
|
|
|
|
while (elements.length) {
|
|
const root = elements.shift();
|
|
const rootChildDepth = root.depth + 1;
|
|
let connectionChildren = this.relations[[AscFormat.Cxn_type_parOf]][root.getModelId()];
|
|
if (connectionChildren) {
|
|
for (let i = 0; i < connectionChildren.length; i += 1) {
|
|
const connectionChild = connectionChildren[i];
|
|
const contentPoint = connectionChild.point;
|
|
const sibPoint = connectionChild.sibPoint;
|
|
const parPoint = connectionChild.parPoint;
|
|
const node = new SmartArtDataNode(contentPoint, rootChildDepth);
|
|
node.setSibNode(new SmartArtSibDataNode(sibPoint, rootChildDepth));
|
|
node.setParNode(new SmartArtParDataNode(parPoint, rootChildDepth));
|
|
root.addChild(node);
|
|
elements.push(node);
|
|
}
|
|
if (connectionChildren.length) {
|
|
const lastNode = elements[elements.length - 1];
|
|
const sibTrans = lastNode.sibNode;
|
|
sibTrans.isHideLastTrans = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SmartArtAlgorithm.prototype.updateData = function() {
|
|
const data = this.smartart.getDataModelFromData();
|
|
const cxnLst = data.getCxnLst();
|
|
const ptLst = data.getPtLst();
|
|
const cxnMap = cxnLst.getCxnMap();
|
|
const ptMap = ptLst.getPtMap();
|
|
const dataRootId = this.dataRoot.point.getModelId();
|
|
delete ptMap[dataRootId];
|
|
this.checkPresOfCxn(this.presRoot, dataRootId, cxnMap, cxnLst);
|
|
this.updatePresParOfData(cxnMap, ptMap);
|
|
this.updatePresOfData(cxnMap);
|
|
this.updateParOfData(cxnMap, ptMap);
|
|
cxnLst.removeChildrenFromMap(cxnMap);
|
|
ptLst.removeChildrenFromMap(ptMap);
|
|
this.relations = this.smartart.getRelationOfContent2();
|
|
};
|
|
SmartArtAlgorithm.prototype.getNewGUID = function() {
|
|
return this.guidGenerator.getGUID();
|
|
};
|
|
SmartArtAlgorithm.prototype.updateParOfData = function(cxnMap, ptMap) {
|
|
const data = this.smartart.getDataModelFromData();
|
|
const ptLst = data.getPtLst();
|
|
const oThis = this;
|
|
this.forEachContentNode(function(node, parentIndex) {
|
|
const parent = node.parent;
|
|
if (parent) {
|
|
const parentModelId = parent.point.getModelId();
|
|
const childModelId = node.point.getModelId();
|
|
if (ptMap[childModelId]) {
|
|
delete ptMap[childModelId];
|
|
} else {
|
|
ptLst.addToLst(ptLst.list.length, node.point);
|
|
}
|
|
let cxn;
|
|
if (cxnMap[parentModelId][childModelId]) {
|
|
cxn = cxnMap[parentModelId][childModelId];
|
|
delete cxnMap[parentModelId][childModelId];
|
|
if (cxn.srcOrd !== parentIndex) {
|
|
cxn.setSrcOrd(parentIndex);
|
|
}
|
|
} else {
|
|
cxn = new AscFormat.Cxn();
|
|
cxn.setModelId(oThis.getNewGUID());
|
|
cxn.setDestOrd(0);
|
|
cxn.setSrcOrd(parentIndex);
|
|
cxn.setSrcId(parentModelId);
|
|
cxn.setDestId(childModelId);
|
|
cxn.setType(AscFormat.Cxn_type_parOf);
|
|
}
|
|
const sibNode = node.sibNode;
|
|
if (sibNode) {
|
|
const sibModelId = sibNode.point.getModelId();
|
|
if (ptMap[sibModelId]) {
|
|
delete ptMap[sibModelId];
|
|
} else {
|
|
ptLst.addToLst(ptLst.list.length, sibNode.point);
|
|
}
|
|
if (cxn.sibTransId !== sibModelId) {
|
|
cxn.setSibTransId(sibModelId);
|
|
}
|
|
}
|
|
const parNode = node.parNode;
|
|
if (parNode) {
|
|
const parModelId = parNode.point.getModelId();
|
|
if (ptMap[parModelId]) {
|
|
delete ptMap[parModelId];
|
|
} else {
|
|
ptLst.addToLst(ptLst.list.length, parNode.point);
|
|
}
|
|
if (cxn.parTransId !== parModelId) {
|
|
cxn.setParTransId(parModelId);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
};
|
|
SmartArtAlgorithm.prototype.checkPresOfCxn = function(presOfNode, contentNodeId, cxnMap, cxnLst) {
|
|
const presPoint = presOfNode.presPoint;
|
|
const modelId = presPoint.getModelId();
|
|
if (cxnMap[contentNodeId][modelId]) {
|
|
delete cxnMap[contentNodeId][modelId];
|
|
} else {
|
|
const newCxn = new AscFormat.Cxn();
|
|
newCxn.setModelId(this.getNewGUID());
|
|
newCxn.setSrcId(contentNodeId);
|
|
newCxn.setDestId(modelId);
|
|
newCxn.setDestOrd(0);
|
|
newCxn.setSrcOrd(0);
|
|
newCxn.setType(AscFormat.Cxn_type_presOf);
|
|
cxnLst.addToLst(cxnLst.list.length, newCxn);
|
|
}
|
|
};
|
|
SmartArtAlgorithm.prototype.checkPresOfData = function(node, cxnMap, cxnLst) {
|
|
if (!node) {
|
|
return;
|
|
}
|
|
const nodeModelId = node.point.getModelId();
|
|
const textNodes = node.getTextNodes();
|
|
const textNode = textNodes.textNode;
|
|
const contentNode = textNodes.contentNode;
|
|
if (textNode) {
|
|
this.checkPresOfCxn(textNode, nodeModelId, cxnMap, cxnLst);
|
|
}
|
|
if (contentNode) {
|
|
this.checkPresOfCxn(contentNode, nodeModelId, cxnMap, cxnLst);
|
|
}
|
|
}
|
|
SmartArtAlgorithm.prototype.updatePresOfData = function(cxnMap) {
|
|
const data = this.smartart.getDataModelFromData();
|
|
const cxnLst = data.getCxnLst();
|
|
const oThis = this;
|
|
this.forEachContentNode(function(node) {
|
|
oThis.checkPresOfData(node, cxnMap, cxnLst);
|
|
oThis.checkPresOfData(node.sibNode, cxnMap, cxnLst);
|
|
oThis.checkPresOfData(node.parNode, cxnMap, cxnLst);
|
|
});
|
|
};
|
|
|
|
SmartArtAlgorithm.prototype.updatePresParOfData = function(cxnMap, ptMap) {
|
|
const data = this.smartart.getDataModelFromData();
|
|
const cxnLst = data.getCxnLst();
|
|
const ptLst = data.getPtLst();
|
|
const oThis = this;
|
|
this.forEachPresFromTop(function(node, parentIndex) {
|
|
const presPoint = node.presPoint;
|
|
const modelId = presPoint.getModelId();
|
|
if (ptMap[modelId] && presPoint === ptMap[modelId]) {
|
|
delete ptMap[modelId];
|
|
} else {
|
|
ptLst.addToLst(ptLst.list.length, presPoint);
|
|
}
|
|
const parentPresPoint = node.parent && node.parent.presPoint;
|
|
if (!parentPresPoint) {
|
|
return;
|
|
}
|
|
|
|
const parentModelId = parentPresPoint.getModelId();
|
|
const cxn = cxnMap[parentModelId] && cxnMap[parentModelId][modelId];
|
|
if (cxn) {
|
|
if (cxn.srcOrd !== parentIndex) {
|
|
cxn.setSrcOrd(parentIndex);
|
|
}
|
|
delete cxnMap[parentModelId][modelId];
|
|
} else {
|
|
const newCxn = new AscFormat.Cxn();
|
|
newCxn.setModelId(oThis.getNewGUID());
|
|
newCxn.setSrcId(parentModelId);
|
|
newCxn.setDestId(modelId);
|
|
newCxn.setType(AscFormat.Cxn_type_presParOf);
|
|
newCxn.setDestOrd(0);
|
|
newCxn.setSrcOrd(parentIndex);
|
|
cxnLst.addToLst(cxnLst.list.length, newCxn);
|
|
}
|
|
});
|
|
};
|
|
SmartArtAlgorithm.prototype.getPresNode = function (layoutNode) {
|
|
const currentNode = this.getCurrentNode();
|
|
const currentPresNode = this.getCurrentPresNode();
|
|
const currentPresNodeInfo = this.getCurrentPresNodeInfo();
|
|
const presRelations = this.relations[AscFormat.Cxn_type_presOf];
|
|
const presParRelations = this.relations[AscFormat.Cxn_type_presParOf];
|
|
let presNode;
|
|
if (currentPresNode && currentPresNode.parent) {
|
|
const children = presParRelations[currentPresNode.getModelId()];
|
|
let child;
|
|
if (children && children[layoutNode.name]) {
|
|
if (currentPresNodeInfo.childrenIndexes[layoutNode.name] === undefined) {
|
|
currentPresNodeInfo.childrenIndexes[layoutNode.name] = -1;
|
|
}
|
|
currentPresNodeInfo.childrenIndexes[layoutNode.name] += 1;
|
|
const element = children[layoutNode.name][currentPresNodeInfo.childrenIndexes[layoutNode.name]];
|
|
child = element && element.point;
|
|
}
|
|
if (child && child.getPresName() === layoutNode.name) {
|
|
presNode = new PresNode(child, currentNode);
|
|
} else {
|
|
presNode = this.createPresNode(layoutNode.name, layoutNode.styleLbl, currentNode);
|
|
}
|
|
} else {
|
|
const nodeModelId = currentNode.getModelId();
|
|
const presPoints = presRelations[nodeModelId];
|
|
const presPoint = presPoints && presPoints[layoutNode.name];
|
|
if (presPoint) {
|
|
presNode = new PresNode(presPoint, currentNode);
|
|
} else {
|
|
presNode = this.createPresNode(layoutNode.name, layoutNode.styleLbl, currentNode);
|
|
}
|
|
}
|
|
presNode.moveWith = layoutNode.moveWith;
|
|
return presNode;
|
|
};
|
|
|
|
SmartArtAlgorithm.prototype.addCurrentPresNode = function (presNode) {
|
|
this.presNodesStack.push(presNode);
|
|
this.presNodesInfoStack.push({childrenIndexes: {}});
|
|
}
|
|
SmartArtAlgorithm.prototype.removeCurrentPresNode = function () {
|
|
this.presNodesStack.pop();
|
|
this.presNodesInfoStack.pop();
|
|
}
|
|
SmartArtAlgorithm.prototype.getCurrentPresNode = function () {
|
|
return this.presNodesStack[this.presNodesStack.length - 1];
|
|
}
|
|
SmartArtAlgorithm.prototype.getCurrentPresNodeInfo = function () {
|
|
return this.presNodesInfoStack[this.presNodesStack.length - 1];
|
|
}
|
|
SmartArtAlgorithm.prototype.getRootPresNode = function () {
|
|
return this.presNodesStack[1];
|
|
}
|
|
SmartArtAlgorithm.prototype.getShapes = function () {
|
|
|
|
const algorithm = this.presRoot.algorithm;
|
|
return algorithm ? algorithm.getShapes(this) : [];
|
|
}
|
|
SmartArtAlgorithm.prototype.connectShapeSmartArtInfo = function () {
|
|
if (!this.presRoot) {
|
|
this.startFromBegin();
|
|
} else {
|
|
this.cleanDrawingShapeInfo();
|
|
}
|
|
|
|
const spTree = this.smartart.drawing.spTree;
|
|
const mapEditorShapes = {};
|
|
for (let i = 0; i < spTree.length; i++) {
|
|
const shape = spTree[i];
|
|
mapEditorShapes[shape.getModelId()] = shape;
|
|
}
|
|
this.forEachPresFromBottom(function (presNode) {
|
|
const point = presNode.presPoint;
|
|
const editorShape = mapEditorShapes[point.getModelId()];
|
|
if (editorShape) {
|
|
const shadowShape = presNode.getShape();
|
|
shadowShape.setShapeSmartArtInfo(editorShape);
|
|
shadowShape.editorShape = editorShape;
|
|
const textNodes = presNode.contentNodes[0] && presNode.contentNodes[0].getTextNodes();
|
|
if (textNodes) {
|
|
if (presNode === textNodes.textNode) {
|
|
presNode.algorithm.applyFontRelations(editorShape);
|
|
} else if (presNode === textNodes.contentNode && textNodes.textNode) {
|
|
textNodes.textNode.algorithm.applyFontRelations(editorShape);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
|
|
SmartArtAlgorithm.prototype.cleanDrawingShapeInfo = function () {
|
|
const smartart = this.smartart;
|
|
const drawing = smartart.drawing;
|
|
for (let i = 0; i < drawing.spTree.length; i++) {
|
|
const shape = drawing.spTree[i];
|
|
shape.setShapeSmartArtInfo(null);
|
|
}
|
|
};
|
|
SmartArtAlgorithm.prototype.checkDataModel = function() {
|
|
this.executeLayoutAlgorithms();
|
|
this.updateData();
|
|
};
|
|
SmartArtAlgorithm.prototype.cleanPresOf = function() {
|
|
this.forEachContentNode(function(node) {
|
|
node.cleanPresOf();
|
|
});
|
|
};
|
|
SmartArtAlgorithm.prototype.executeLayoutAlgorithms = function() {
|
|
this.cleanPresOf();
|
|
this.addCurrentNode(this.dataRoot);
|
|
const mockPresNode = new PresNode();
|
|
this.addCurrentPresNode(mockPresNode);
|
|
|
|
const layout = this.smartart.getLayoutDef();
|
|
const layoutNode = layout.getLayoutNode();
|
|
layoutNode.executeAlgorithm(this);
|
|
this.presRoot = mockPresNode.childs[0];
|
|
this.presRoot.parent = null;
|
|
this.removeCurrentPresNode();
|
|
this.removeCurrentNode();
|
|
}
|
|
SmartArtAlgorithm.prototype.startFromBegin = function () {
|
|
this.cleanDrawingShapeInfo();
|
|
this.executeLayoutAlgorithms();
|
|
this.calculateShadowShapes();
|
|
};
|
|
SmartArtAlgorithm.prototype.calculateShadowShapes = function() {
|
|
this.cleanCalcValues();
|
|
this.calcConstraints();
|
|
this.cleanRules();
|
|
this.calcScaleCoefficients();
|
|
if (this.factRuleState === factRuleState.disabled) {
|
|
this.cleanCalcValues();
|
|
this.calcConstraints();
|
|
this.calcScaleCoefficients();
|
|
}
|
|
this.calcAdaptedConstraints();
|
|
this.executeAlgorithms();
|
|
};
|
|
SmartArtAlgorithm.prototype.cleanCalcValues = function () {
|
|
this.forEachPresFromTop(function (presNode) {
|
|
presNode.cleanRules();
|
|
presNode.cleanConstraints();
|
|
presNode.cleanScales();
|
|
presNode.cleanPosition();
|
|
});
|
|
this.presRoot.initRootConstraints(this.smartart, this);
|
|
};
|
|
|
|
|
|
SmartArtAlgorithm.prototype.calcScaleCoefficients = function () {
|
|
const oThis = this;
|
|
this.forEachPresFromBottom(function (presNode) {
|
|
presNode.startAlgorithm(oThis, true);
|
|
});
|
|
};
|
|
SmartArtAlgorithm.prototype.calcAdaptedConstraints = function () {
|
|
const oThis = this;
|
|
const isNeedSetRules = this.factRuleState !== factRuleState.disabled;
|
|
this.forEachPresFromTop(function (presNode) {
|
|
if (isNeedSetRules) {
|
|
presNode.setRules(oThis);
|
|
}
|
|
presNode.setConstraints(true, oThis);
|
|
});
|
|
};
|
|
SmartArtAlgorithm.prototype.calcConstraints = function () {
|
|
const oThis = this;
|
|
const isNeedSetRules = this.factRuleState !== factRuleState.disabled;
|
|
this.forEachPresFromTop(function (presNode) {
|
|
if (isNeedSetRules) {
|
|
presNode.setRules(oThis);
|
|
}
|
|
presNode.setConstraints(false, oThis);
|
|
});
|
|
};
|
|
SmartArtAlgorithm.prototype.cleanRules = function () {
|
|
this.forEachPresFromTop(function (presNode) {
|
|
presNode.cleanRules();
|
|
});
|
|
};
|
|
SmartArtAlgorithm.prototype.executeAlgorithms = function () {
|
|
const oThis = this;
|
|
this.forEachPresFromBottom(function (presNode) {
|
|
presNode.startAlgorithm(oThis);
|
|
});
|
|
this.applySettingsForMove();
|
|
this.generateConnectors();
|
|
this.applySettingsForMove();
|
|
};
|
|
SmartArtAlgorithm.prototype.generateConnectors = function () {
|
|
while (this.connectorAlgorithmStack.length) {
|
|
const connectorAlgorithm = this.connectorAlgorithmStack.pop();
|
|
connectorAlgorithm.connectShapes(this);
|
|
}
|
|
};
|
|
SmartArtAlgorithm.prototype.forEachPresFromBottom = function (callback) {
|
|
const checkElements = [this.presRoot];
|
|
while (checkElements.length) {
|
|
const elem = checkElements.pop();
|
|
if (elem.childs.length) {
|
|
for (let i = 0; i < elem.childs.length; i += 1) {
|
|
checkElements.push(elem.childs[i]);
|
|
}
|
|
} else {
|
|
const callbackElements = [elem];
|
|
while (callbackElements.length) {
|
|
const elem = callbackElements.pop();
|
|
callback(elem);
|
|
const firstParentChild = elem.parent && elem.parent.childs[0];
|
|
if (firstParentChild === elem) {
|
|
callbackElements.push(elem.parent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
SmartArtAlgorithm.prototype.forEachPresFromTop = function (callback) {
|
|
const elements = [this.presRoot];
|
|
callback(this.presRoot, 0);
|
|
while (elements.length) {
|
|
const element = elements.pop();
|
|
for (let i = 0; i < element.childs.length; i += 1) {
|
|
const child = element.childs[i];
|
|
callback(child, i);
|
|
elements.push(child);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
SmartArtAlgorithm.prototype.getCurrentNode = function () {
|
|
return this.nodesStack[this.nodesStack.length - 1];
|
|
}
|
|
SmartArtAlgorithm.prototype.addCurrentNode = function (node) {
|
|
this.nodesStack.push(node);
|
|
}
|
|
|
|
SmartArtAlgorithm.prototype.removeCurrentNode = function () {
|
|
this.nodesStack.pop();
|
|
}
|
|
|
|
SmartArtAlgorithm.prototype.setConstraints = function (constr) {
|
|
const node = this.getCurrentPresNode();
|
|
node.setLayoutConstraints(constr);
|
|
}
|
|
SmartArtAlgorithm.prototype.setRules = function (rules) {
|
|
const node = this.getCurrentPresNode();
|
|
node.setLayoutRules(rules);
|
|
}
|
|
|
|
function SmartArtDataNodeBase(point, depth) {
|
|
this.point = point;
|
|
this.parent = null;
|
|
this.childs = [];
|
|
this.depth = AscFormat.isRealNumber(depth) ? depth : null;
|
|
this.presOf = {
|
|
contentNode: null,
|
|
textNode: null
|
|
};
|
|
}
|
|
SmartArtDataNodeBase.prototype.cleanPresOf = function() {
|
|
this.presOf = {
|
|
contentNode: null,
|
|
textNode: null
|
|
};
|
|
};
|
|
SmartArtDataNodeBase.prototype.getTextNode = function () {
|
|
const textNodes = this.getTextNodes();
|
|
return textNodes.textNode || textNodes.contentNode;
|
|
};
|
|
SmartArtDataNodeBase.prototype.getContentNode = function () {
|
|
const textNodes = this.getTextNodes();
|
|
return textNodes.contentNode || textNodes.textNode;
|
|
};
|
|
SmartArtDataNodeBase.prototype.getTextNodes = function () {
|
|
return this.presOf;
|
|
};
|
|
SmartArtDataNodeBase.prototype.getPositionByParent = function () {
|
|
return -1;
|
|
};
|
|
SmartArtDataNodeBase.prototype.getPresName = function () {
|
|
const presNode = this.getPresNode();
|
|
return presNode && presNode.getPresName();
|
|
};
|
|
SmartArtDataNodeBase.prototype.getPtType = function () {
|
|
return this.point.type;
|
|
}
|
|
|
|
SmartArtDataNodeBase.prototype.getNodesByAxis = function (nodes, axis, ptType) {
|
|
nodes = nodes || [];
|
|
switch (axis) {
|
|
case AscFormat.AxisType_value_root: {
|
|
this.getNodesByRoot(nodes, ptType);
|
|
break;
|
|
}
|
|
case AscFormat.AxisType_value_ch: {
|
|
this.getNodesByCh(nodes, ptType);
|
|
break;
|
|
}
|
|
case AscFormat.AxisType_value_par: {
|
|
this.getNodesByParent(nodes, ptType);
|
|
break;
|
|
}
|
|
case AscFormat.AxisType_value_self: {
|
|
const needNode = this.getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.AxisType_value_follow: {
|
|
this.getNodesByFollow(nodes, ptType);
|
|
break;
|
|
}
|
|
case AscFormat.AxisType_value_followSib: {
|
|
this.getNodesByFollowSib(nodes, ptType);
|
|
break;
|
|
}
|
|
case AscFormat.AxisType_value_precedSib: {
|
|
this.getNodesByPrecedSib(nodes, ptType);
|
|
break;
|
|
}
|
|
case AscFormat.AxisType_value_des: {
|
|
this.getNodesByDescendant(nodes, ptType);
|
|
break;
|
|
}
|
|
case AscFormat.AxisType_value_desOrSelf: {
|
|
this.getNodesByAxis(nodes, AscFormat.AxisType_value_self, ptType);
|
|
this.getNodesByAxis(nodes, AscFormat.AxisType_value_des, ptType);
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
return nodes;
|
|
}
|
|
SmartArtDataNodeBase.prototype.getParent = function () {
|
|
return this.parent;
|
|
}
|
|
SmartArtDataNodeBase.prototype.getNodesByParent = function (nodes, ptType) {
|
|
const parent = this.getParent();
|
|
const needNode = parent && parent.getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
};
|
|
SmartArtDataNodeBase.prototype.getNodesByRoot = function (nodes, ptType) {
|
|
let curNode = this;
|
|
while (curNode && !curNode.isRoot()) {
|
|
curNode = curNode.parent;
|
|
}
|
|
if (curNode && curNode.isRoot()) {
|
|
const needNode = curNode.getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
}
|
|
}
|
|
SmartArtDataNodeBase.prototype.getNodesByDescendant = function (nodes, ptType) {
|
|
const elements = [].concat(this.childs);
|
|
while (elements.length) {
|
|
const child = elements.shift();
|
|
const needNode = child.getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
for (let i = 0; i < child.childs.length; i++) {
|
|
elements.push(child.childs[i]);
|
|
}
|
|
}
|
|
};
|
|
|
|
SmartArtDataNodeBase.prototype.forEachDes = function (callback) {
|
|
const elements = [this];
|
|
while (elements.length) {
|
|
const element = elements.pop();
|
|
for (let i = 0; i < element.childs.length; i++) {
|
|
elements.push(element.childs[i]);
|
|
callback(element.childs[i]);
|
|
}
|
|
}
|
|
};
|
|
|
|
SmartArtDataNodeBase.prototype.forEachDesOrSelf = function (callback) {
|
|
callback(this);
|
|
this.forEachDes(callback);
|
|
};
|
|
SmartArtDataNodeBase.prototype.getNodesByFollow = function (nodes, ptType) {
|
|
const parent = this.getParent();
|
|
if (parent) {
|
|
let bAdd = false;
|
|
for (let i = 0; i < parent.childs.length; i++) {
|
|
const child = parent.childs[i];
|
|
if (bAdd) {
|
|
child.forEachDesOrSelf(function (node) {
|
|
const needNode = node.getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
});
|
|
} else if (child === this) {
|
|
bAdd = true;
|
|
if (ptType === AscFormat.ElementType_value_sibTrans) {
|
|
child.forEachDesOrSelf(function (node) {
|
|
const needNode = node.getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
});
|
|
}
|
|
} else if (child.sibNode === this) {
|
|
bAdd = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SmartArtDataNodeBase.prototype.getNodesByFollowSib = function (nodes, ptType) {
|
|
const parent = this.getParent();
|
|
if (parent) {
|
|
let bAdd = false;
|
|
for (let i = 0; i < parent.childs.length; i++) {
|
|
const child = parent.childs[i];
|
|
if (bAdd) {
|
|
const needNode = parent.childs[i].getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
} else if (child === this) {
|
|
bAdd = true;
|
|
if (ptType === AscFormat.ElementType_value_sibTrans) {
|
|
const needNode = parent.childs[i].getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
}
|
|
} else if (child.sibNode === this) {
|
|
bAdd = true;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
SmartArtDataNodeBase.prototype.getNodesByPrecedSib = function (nodes, ptType) {
|
|
const parent = this.parent;
|
|
if (parent) {
|
|
for (let i = 0; i < parent.childs.length; i++) {
|
|
if (parent.childs[i] === this) {
|
|
if (ptType === AscFormat.ElementType_value_parTrans) {
|
|
const needNode = parent.childs[i].getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
}
|
|
break;
|
|
} else {
|
|
const needNode = parent.childs[i].getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
SmartArtDataNodeBase.prototype.getNodesByCh = function (nodes, ptType) {
|
|
for (let i = 0; i < this.childs.length; i++) {
|
|
const child = this.childs[i];
|
|
const needNode = child.getNodeByPtType(ptType);
|
|
if (needNode) {
|
|
nodes.push(needNode);
|
|
}
|
|
}
|
|
};
|
|
|
|
SmartArtDataNodeBase.prototype.addChild = function (child, position) {
|
|
position = AscFormat.isRealNumber(position) ? position : this.childs.length;
|
|
this.childs.splice(position, 0, child);
|
|
child.setParent(this);
|
|
};
|
|
SmartArtDataNodeBase.prototype.removeChilds = function (position, count) {
|
|
this.childs.splice(position, count);
|
|
};
|
|
SmartArtDataNodeBase.prototype.setParent = function (parent) {
|
|
this.parent = parent;
|
|
};
|
|
SmartArtDataNodeBase.prototype.getPresNode = function () {
|
|
const textNodes = this.getTextNodes();
|
|
return textNodes.textNode || textNodes.contentNode;
|
|
};
|
|
SmartArtDataNodeBase.prototype.getModelId = function () {
|
|
return this.point.getModelId();
|
|
};
|
|
SmartArtDataNodeBase.prototype.isRoot = function () {
|
|
return this.point.getType() === AscFormat.Point_type_doc;
|
|
};
|
|
SmartArtDataNodeBase.prototype.isNode = function () {
|
|
return this.point.getType() === AscFormat.Point_type_node;
|
|
};
|
|
SmartArtDataNodeBase.prototype.isAsst = function () {
|
|
return this.point.getType() === AscFormat.Point_type_asst;
|
|
};
|
|
SmartArtDataNodeBase.prototype.isContentNode = function () {
|
|
return false;
|
|
};
|
|
SmartArtDataNodeBase.prototype.isSibNode = function () {
|
|
return false;
|
|
};
|
|
SmartArtDataNodeBase.prototype.isParNode = function () {
|
|
return false;
|
|
};
|
|
|
|
function SmartArtSibDataNode(mainPoint, depth) {
|
|
SmartArtDataNodeBase.call(this, mainPoint, depth);
|
|
}
|
|
AscFormat.InitClassWithoutType(SmartArtSibDataNode, SmartArtDataNodeBase);
|
|
SmartArtSibDataNode.prototype.isSibNode = function () {
|
|
return true;
|
|
};
|
|
SmartArtSibDataNode.prototype.getParent = function () {
|
|
return this.parent && this.parent.parent;
|
|
}
|
|
SmartArtSibDataNode.prototype.getNodeByPtType = function (elementTypeValue) {
|
|
switch (elementTypeValue) {
|
|
case AscFormat.ElementType_value_sibTrans:
|
|
return this;
|
|
case AscFormat.ElementType_value_node:
|
|
return this;
|
|
default:
|
|
return this;
|
|
}
|
|
}
|
|
|
|
function SmartArtParDataNode(mainPoint, depth) {
|
|
SmartArtDataNodeBase.call(this, mainPoint, depth);
|
|
}
|
|
AscFormat.InitClassWithoutType(SmartArtParDataNode, SmartArtDataNodeBase);
|
|
SmartArtParDataNode.prototype.isParNode = function () {
|
|
return true;
|
|
};
|
|
SmartArtParDataNode.prototype.getNodeByPtType = function (elementTypeValue) {
|
|
return this;
|
|
}
|
|
SmartArtParDataNode.prototype.getParent = function () {
|
|
return this.parent && this.parent.parent;
|
|
}
|
|
function SmartArtDataNode(mainPoint, depth) {
|
|
SmartArtDataNodeBase.call(this, mainPoint, depth);
|
|
this.sibNode = null;
|
|
this.parNode = null;
|
|
this.childDepth = null;
|
|
}
|
|
AscFormat.InitClassWithoutType(SmartArtDataNode, SmartArtDataNodeBase);
|
|
SmartArtDataNode.prototype.getPointType = function () {
|
|
return this.point.getType();
|
|
}
|
|
SmartArtDataNode.prototype.getParentChildLength = function () {
|
|
const parent = this.getParent();
|
|
return parent.childs.length;
|
|
}
|
|
SmartArtDataNode.prototype.getPositionByParent = function () {
|
|
const parent = this.getParent();
|
|
for (let i = 0; i < parent.childs.length; i++) {
|
|
if (parent.childs[i] === this) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
|
|
SmartArtDataNode.prototype.getChildDepth = function () {
|
|
if (this.childDepth === null) {
|
|
let maxDepth = this.depth;
|
|
const tempNodes = [this];
|
|
while (tempNodes.length) {
|
|
const node = tempNodes.pop();
|
|
if (node.depth > maxDepth) {
|
|
maxDepth = node.depth;
|
|
}
|
|
tempNodes.push.apply(tempNodes, node.childs);
|
|
}
|
|
this.childDepth = maxDepth;
|
|
}
|
|
return this.childDepth;
|
|
};
|
|
SmartArtDataNode.prototype.isContentNode = function () {
|
|
return true;
|
|
};
|
|
|
|
SmartArtDataNode.prototype.setSibNode = function (node) {
|
|
this.sibNode = node;
|
|
node.setParent(this);
|
|
};
|
|
|
|
SmartArtDataNode.prototype.setParNode = function (node) {
|
|
this.parNode = node;
|
|
node.setParent(this);
|
|
};
|
|
|
|
SmartArtDataNode.prototype.getNodeByPtType = function (elementTypeValue) {
|
|
switch (elementTypeValue) {
|
|
case AscFormat.ElementType_value_sibTrans:
|
|
return this.sibNode;
|
|
case AscFormat.ElementType_value_node:
|
|
if (this.isNode() || this.isAsst()) {
|
|
return this;
|
|
}
|
|
break;
|
|
case AscFormat.ElementType_value_parTrans:
|
|
return this.parNode;
|
|
case AscFormat.ElementType_value_all:
|
|
return this;
|
|
case AscFormat.ElementType_value_asst:
|
|
if (this.isAsst()) {
|
|
return this;
|
|
}
|
|
break;
|
|
case AscFormat.ElementType_value_doc:
|
|
if (this.isRoot()) {
|
|
return this;
|
|
}
|
|
break;
|
|
|
|
case AscFormat.ElementType_value_nonAsst:
|
|
if (!this.isAsst()) {
|
|
return this;
|
|
}
|
|
break;
|
|
case AscFormat.ElementType_value_nonNorm:
|
|
break;
|
|
case AscFormat.ElementType_value_norm:
|
|
break;
|
|
case AscFormat.ElementType_value_pres:
|
|
break;
|
|
default:
|
|
return this;
|
|
}
|
|
}
|
|
|
|
SmartArtDataNode.prototype.getSibName = function () {
|
|
return this.sibNode.getPresName();
|
|
};
|
|
SmartArtDataNode.prototype.getParName = function () {
|
|
return this.parNode.getPresName();
|
|
};
|
|
|
|
SmartArtDataNode.prototype.checkName = function (name) {
|
|
switch (name) {
|
|
case this.getPresName():
|
|
return this;
|
|
case this.getSibName():
|
|
return this.sibNode;
|
|
case this.getParName():
|
|
return this.parNode;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
SmartArtDataNode.prototype.getPrSet = function () {
|
|
const presNode = this.getPresNode();
|
|
return presNode && presNode.getPrSet();
|
|
}
|
|
|
|
function Position(node) {
|
|
this.rot = 0;
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.node = node;
|
|
this.cleanParams = {
|
|
x: 0,
|
|
y: 0,
|
|
width: 0,
|
|
height: 0
|
|
};
|
|
}
|
|
Position.prototype.getMatrix = function () {
|
|
const matrix = new AscCommon.CMatrix();
|
|
matrix.RotateAt(this.rot * radToDeg, this.x + this.width / 2, this.y + this.height / 2);
|
|
return matrix;
|
|
};
|
|
Position.prototype.getReverseMatrix = function () {
|
|
const matrix = new AscCommon.CMatrix();
|
|
matrix.RotateAt(-this.rot * radToDeg, this.x + this.width / 2, this.y + this.height / 2);
|
|
return matrix;
|
|
};
|
|
Position.prototype.initFromShape = function () {
|
|
|
|
};
|
|
Position.prototype.moveTo = function (dx, dy) {
|
|
this.node.moveTo(dx, dy, true);
|
|
};
|
|
Position.prototype.checkBounds = function (bounds, isClean) {
|
|
const shapeBounds = this.getBounds(isClean);
|
|
checkBounds(bounds, shapeBounds);
|
|
};
|
|
Position.prototype.getBounds = function (isClean, skipRotate) {
|
|
const res = {
|
|
isEllipse: this.node.layoutInfo.shape.type === AscFormat.LayoutShapeType_shapeType_ellipse
|
|
};
|
|
const pos = isClean ? this.cleanParams : this;
|
|
let minX;
|
|
let maxX;
|
|
let minY;
|
|
let maxY;
|
|
if (skipRotate) {
|
|
minX = pos.x;
|
|
maxX = pos.x + pos.width;
|
|
minY = pos.y;
|
|
maxY = pos.y + pos.height;
|
|
} else {
|
|
const matrix = this.getMatrix();
|
|
const x1 = matrix.TransformPointX(pos.x, pos.y);
|
|
const x2 = matrix.TransformPointX(pos.x + pos.width, pos.y);
|
|
const x3 = matrix.TransformPointX(pos.x, pos.y + pos.height);
|
|
const x4 = matrix.TransformPointX(pos.x + pos.width, pos.y + pos.height);
|
|
const y1 = matrix.TransformPointY(pos.x, pos.y);
|
|
const y2 = matrix.TransformPointY(pos.x + pos.width, pos.y);
|
|
const y3 = matrix.TransformPointY(pos.x, pos.y + pos.height);
|
|
const y4 = matrix.TransformPointY(pos.x + pos.width, pos.y + pos.height);
|
|
|
|
|
|
minX = Math.min(x1, x2, x3, x4);
|
|
maxX = Math.max(x1, x2, x3, x4);
|
|
minY = Math.min(y1, y2, y3, y4);
|
|
maxY = Math.max(y1, y2, y3, y4);
|
|
}
|
|
if (pos.width < 0) {
|
|
res.l = maxX;
|
|
res.r = minX;
|
|
} else {
|
|
res.l = minX;
|
|
res.r = maxX;
|
|
}
|
|
if (pos.height < 0) {
|
|
res.t = maxY;
|
|
res.b = minY;
|
|
} else {
|
|
res.t = minY;
|
|
res.b = maxY;
|
|
}
|
|
return res;
|
|
};
|
|
function ShadowShape(node) {
|
|
Position.call(this, node);
|
|
this.rot = 0;
|
|
this.type = AscFormat.LayoutShapeType_outputShapeType_none;
|
|
this.ln = null;
|
|
this.fill = null;
|
|
this.tailLnArrow = null;
|
|
this.headLnArrow = null;
|
|
this.style = null;
|
|
this.shape = null;
|
|
this.connectorShape = null;
|
|
this.customAdj = null;
|
|
this.customGeom = [];
|
|
this.radialVector = null;
|
|
this.incAngle = null;
|
|
}
|
|
AscFormat.InitClassWithoutType(ShadowShape, Position);
|
|
ShadowShape.prototype.setRadialInfo = function (radialVector, incAngle) {
|
|
const nodes = [this.node];
|
|
while (nodes.length) {
|
|
const node = nodes.pop();
|
|
if (node.algorithm instanceof CompositeAlgorithm) {
|
|
nodes.push.apply(nodes, node.childs);
|
|
} else {
|
|
const shape = node.getShape();
|
|
shape.radialVector = radialVector;
|
|
shape.incAngle = incAngle;
|
|
}
|
|
}
|
|
};
|
|
ShadowShape.prototype.getCustomRadialInfo = function () {
|
|
if (this.radialVector && AscFormat.isRealNumber(this.incAngle)) {
|
|
const prSet = this.node.getPrSet();
|
|
if (prSet) {
|
|
const custScaleRadius = prSet.custRadScaleRad === null ? 1 : prSet.custRadScaleRad;
|
|
const custScaleAngle = prSet.custRadScaleInc === null ? 0 : prSet.custRadScaleInc;
|
|
const defaultRadius = this.radialVector.getDistance();
|
|
const defaultAngle = this.radialVector.getAngle();
|
|
if (custScaleRadius !== 1 || custScaleAngle !== 0) {
|
|
const customRadius = defaultRadius * custScaleRadius;
|
|
const custAngle = AscFormat.normalizeRotate(defaultAngle + custScaleAngle * this.incAngle);
|
|
return {radius: customRadius, angle: custAngle};
|
|
}
|
|
return {radius: defaultRadius, angle: defaultAngle};
|
|
}
|
|
}
|
|
};
|
|
ShadowShape.prototype.moveTo = function (dX, dY) {
|
|
this.node.moveTo(dX, dY, false);
|
|
};
|
|
ShadowShape.prototype.changeSize = function (coefficient, props) {
|
|
props = props || {};
|
|
this.x *= coefficient;
|
|
this.width *= coefficient;
|
|
if (props.changeHeight !== false) {
|
|
this.y *= coefficient;
|
|
this.height *= coefficient;
|
|
}
|
|
}
|
|
ShadowShape.prototype.initSizesFromConstraints = function () {
|
|
|
|
}
|
|
ShadowShape.prototype.initFromShape = function (shape) {
|
|
this.shape = shape;
|
|
if (!(shape.hideGeom && (this.node.algorithm instanceof SpaceAlgorithm))) {
|
|
this.type = shape.type;
|
|
}
|
|
|
|
}
|
|
|
|
ShadowShape.prototype.setFill = function (fill) {
|
|
this.fill = fill;
|
|
};
|
|
|
|
ShadowShape.prototype.setLn = function (ln) {
|
|
this.ln = ln;
|
|
}
|
|
|
|
ShadowShape.prototype.setStyle = function (style) {
|
|
this.style = style;
|
|
}
|
|
|
|
ShadowShape.prototype.getEditorLine = function (initObjects) {
|
|
|
|
const shapeTrack = new AscFormat.NewShapeTrack("", this.x, this.y, initObjects.theme, initObjects.master, initObjects.layout, initObjects.slide, 0, undefined, undefined, undefined, true);
|
|
shapeTrack.track({}, this.x + this.width, this.y + this.height);
|
|
const shape = shapeTrack.getShape(false, initObjects.drawingDocument, initObjects.drawingObjects);
|
|
const spPr = shape.spPr;
|
|
spPr.setFill(null);
|
|
spPr.setLn(null);
|
|
spPr.xfrm.setExtX(this.width);
|
|
spPr.xfrm.setExtY(this.height);
|
|
shape.setBDeleted(false);
|
|
shape.setParent(initObjects.parent);
|
|
shape.setWorksheet(initObjects.worksheet);
|
|
|
|
const geometry = spPr.geometry;
|
|
for (let i = 0; i < this.customGeom.length; i += 1) {
|
|
const custCommand = this.customGeom[i];
|
|
for (let j = 1; j < custCommand.length; j++) {
|
|
custCommand[j] = String(custCommand[j] >> 0);
|
|
}
|
|
geometry.AddPathCommand.apply(geometry, custCommand);
|
|
}
|
|
this.applyPostEditorSettings(shape);
|
|
return shape;
|
|
};
|
|
ShadowShape.prototype.getEditorShape = function (isLine, initObjects) {
|
|
if (this.connectorShape) {
|
|
return this.connectorShape.getEditorShape(this.connectorShape.type === AscFormat.LayoutShapeType_outputShapeType_conn, initObjects);
|
|
}
|
|
|
|
if (isLine) {
|
|
return this.getEditorLine(initObjects);
|
|
} else {
|
|
const shapeType = this.getEditorShapeType();
|
|
if (typeof shapeType !== 'string') {
|
|
return null;
|
|
}
|
|
|
|
const shapeTrack = new AscFormat.NewShapeTrack(this.getEditorShapeType(), this.x, this.y, initObjects.theme, initObjects.master, initObjects.layout, initObjects.slide, 0, undefined, undefined, undefined, true);
|
|
shapeTrack.track({}, this.x + this.width, this.y + this.height);
|
|
const shape = shapeTrack.getShape(false, initObjects.drawingDocument, initObjects.drawingObjects);
|
|
const nvSpPr = new AscFormat.UniNvPr();
|
|
nvSpPr.cNvPr.setId(0);
|
|
shape.setNvSpPr(nvSpPr);
|
|
const spPr = shape.spPr;
|
|
spPr.setFill(null);
|
|
spPr.setLn(null);
|
|
spPr.xfrm.setExtX(this.width);
|
|
spPr.xfrm.setExtY(this.height);
|
|
shape.setBDeleted(false);
|
|
shape.setParent(initObjects.parent);
|
|
shape.setWorksheet(initObjects.worksheet);
|
|
|
|
this.applyAdjLst(shape.spPr.geometry);
|
|
this.applyPostEditorSettings(shape);
|
|
return shape;
|
|
}
|
|
}
|
|
ShadowShape.prototype.getAdjValueWithApplyFactor = function (adj) {
|
|
const val = adj.val;
|
|
const idx = adj.idx;
|
|
switch (this.type) {
|
|
case AscFormat.LayoutShapeType_shapeType_pie:
|
|
case AscFormat.LayoutShapeType_shapeType_arc:
|
|
return AscFormat.normalizeRotate(val * degToRad) * radToDeg * 60000;
|
|
case AscFormat.LayoutShapeType_shapeType_blockArc:
|
|
switch (idx) {
|
|
case 1:
|
|
case 2:
|
|
return AscFormat.normalizeRotate(val * degToRad) * radToDeg * 60000;
|
|
default:
|
|
return val * 100000;
|
|
}
|
|
case AscFormat.LayoutShapeType_shapeType_circularArrow:
|
|
case AscFormat.LayoutShapeType_shapeType_leftCircularArrow:
|
|
switch (idx) {
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
return AscFormat.normalizeRotate(val * degToRad) * radToDeg * 60000;
|
|
default:
|
|
return val * 100000;
|
|
}
|
|
case AscFormat.LayoutShapeType_shapeType_chord:
|
|
return AscFormat.normalizeRotate(val * degToRad) * radToDeg * 60000;
|
|
default:
|
|
return val * 100000;
|
|
}
|
|
};
|
|
function getAdjName(geometry, id) {
|
|
switch (geometry.preset) {
|
|
case "hexagon":
|
|
if (id === 1) {
|
|
return "adj"
|
|
} else if (id === 2) {
|
|
return "vf";
|
|
}
|
|
break;
|
|
default:
|
|
const singleAdjName = "adj";
|
|
const adjName = singleAdjName + id;
|
|
if (geometry.avLst[adjName]) {
|
|
return adjName;
|
|
} else if (geometry.avLst[singleAdjName]) {
|
|
return singleAdjName;
|
|
}
|
|
break;
|
|
}
|
|
return null;
|
|
}
|
|
ShadowShape.prototype.applyAdjLst = function (geometry) {
|
|
const adjLst = this.customAdj || (this.shape && this.shape.adjLst);
|
|
if (adjLst) {
|
|
for (let i = 0; i < adjLst.list.length; i += 1) {
|
|
const adj = adjLst.list[i];
|
|
const adjName = getAdjName(geometry, adj.idx);
|
|
if (adjName) {
|
|
geometry.AddAdj(adjName, 0, this.getAdjValueWithApplyFactor(adj));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
ShadowShape.prototype.setShapeSmartArtInfo = function (editorShape) {
|
|
const shapeSmartArtInfo = new AscFormat.ShapeSmartArtInfo();
|
|
editorShape.setShapeSmartArtInfo(shapeSmartArtInfo);
|
|
|
|
const presNode = this.node;
|
|
shapeSmartArtInfo.setShapePoint(presNode.presPoint);
|
|
editorShape.setModelId(presNode.presPoint.getModelId());
|
|
for (let i = presNode.contentNodes.length - 1; i >= 0; i -= 1) {
|
|
const contentNode = presNode.contentNodes[i];
|
|
shapeSmartArtInfo.addToLstContentPoint(0, contentNode);
|
|
}
|
|
};
|
|
|
|
ShadowShape.prototype.applyPostEditorSettings = function (editorShape) {
|
|
this.setShapeSmartArtInfo(editorShape);
|
|
this.applyShapeSettings(editorShape);
|
|
this.applyTextSettings(editorShape);
|
|
this.applyShapeRot(editorShape);
|
|
};
|
|
|
|
ShadowShape.prototype.applyShapeRot = function (editorShape) {
|
|
const presNode = this.node;
|
|
let sumRot = this.rot + presNode.moveRot;
|
|
const prSet = presNode.getPrSet();
|
|
if (prSet) {
|
|
if (prSet.custAng) {
|
|
sumRot += prSet.custAng;
|
|
}
|
|
}
|
|
editorShape.spPr.xfrm.setRot(AscFormat.normalizeRotate(sumRot));
|
|
};
|
|
|
|
ShadowShape.prototype.applyTextSettings = function (editorShape) {
|
|
const algorithm = this.node.algorithm;
|
|
algorithm.applyTextSettings(editorShape);
|
|
};
|
|
ShadowShape.prototype.applyShapeSettings = function (editorShape) {
|
|
const shapeSmartArtInfo = editorShape.getSmartArtInfo();
|
|
const presPoint = shapeSmartArtInfo.shapePoint;
|
|
const contentPoint = shapeSmartArtInfo.contentPoint[0];
|
|
let skipSettingDefaultSpPr = false;
|
|
if (this.style) {
|
|
editorShape.setStyle(this.style);
|
|
if (this.fill) {
|
|
skipSettingDefaultSpPr = true;
|
|
const fillRef = editorShape.style.fillRef ? editorShape.style.fillRef.createDuplicate() : new AscFormat.StyleRef();
|
|
const color = this.fill.fill.color || null;
|
|
fillRef.setColor(color);
|
|
editorShape.style.setFillRef(fillRef);
|
|
}
|
|
if (this.ln) {
|
|
skipSettingDefaultSpPr = true;
|
|
const lnRef = editorShape.style.lnRef ? editorShape.style.lnRef.createDuplicate() : new AscFormat.StyleRef();
|
|
const color = this.ln.Fill.fill.color || null;
|
|
lnRef.setColor(color);
|
|
editorShape.style.setLnRef(lnRef);
|
|
}
|
|
}
|
|
if (!editorShape.spPr.ln) {
|
|
editorShape.spPr.setLn(new AscFormat.CLn());
|
|
}
|
|
if (this.headLnArrow) {
|
|
editorShape.spPr.ln.setHeadEnd(this.headLnArrow);
|
|
}
|
|
if (this.tailLnArrow) {
|
|
editorShape.spPr.ln.setTailEnd(this.tailLnArrow);
|
|
}
|
|
|
|
|
|
const style = editorShape.style;
|
|
if (contentPoint && contentPoint.point.prSet && contentPoint.point.prSet.style) {
|
|
style.merge(contentPoint.point.prSet.style);
|
|
skipSettingDefaultSpPr = true;
|
|
}
|
|
if (presPoint && presPoint.prSet && presPoint.prSet.style) {
|
|
style.merge(presPoint.prSet.style);
|
|
skipSettingDefaultSpPr = true;
|
|
}
|
|
|
|
const spPr = editorShape.spPr;
|
|
if (!skipSettingDefaultSpPr) {
|
|
if (this.fill) {
|
|
spPr.setFill(this.fill);
|
|
} else {
|
|
spPr.setFill(AscFormat.CreateNoFillUniFill());
|
|
}
|
|
if (this.ln) {
|
|
spPr.setLn(this.ln);
|
|
} else {
|
|
spPr.setLn(AscFormat.CreateNoFillLine());
|
|
}
|
|
}
|
|
|
|
if (contentPoint && contentPoint.point.spPr) {
|
|
spPr.fullMerge(contentPoint.point.spPr);
|
|
}
|
|
if (presPoint && presPoint.spPr) {
|
|
spPr.fullMerge(presPoint.spPr);
|
|
}
|
|
};
|
|
|
|
ShadowShape.prototype.getEditorShapeType = function () {
|
|
if (this.type !== AscFormat.LayoutShapeType_outputShapeType_none && this.type !== AscFormat.LayoutShapeType_outputShapeType_conn) {
|
|
return AscCommon.To_XML_ST_LayoutShapeType(this.type);
|
|
}
|
|
};
|
|
|
|
|
|
function BaseAlgorithm() {
|
|
this.params = {};
|
|
this.parentNode = null;
|
|
this._isHideLastChild = null;
|
|
this.constraintSizes = null;
|
|
this.constrClockwise = null;
|
|
this.calcValues = {};
|
|
}
|
|
BaseAlgorithm.prototype.applyTextSettings = function (editorShape) {};
|
|
BaseAlgorithm.prototype.setConstrClockwise = function (isClockwise) {
|
|
this.constrClockwise = isClockwise;
|
|
}
|
|
BaseAlgorithm.prototype.isClockwise = function () {
|
|
return true;
|
|
};
|
|
BaseAlgorithm.prototype.getConstrClockwise = function () {
|
|
return this.constrClockwise;
|
|
}
|
|
BaseAlgorithm.prototype.getChildAlgorithmAlignBounds = function (isCalculateCoefficients, skipRotate) {
|
|
let childShape = this.parentNode.getShape(isCalculateCoefficients);
|
|
if (childShape.connectorShape) {
|
|
childShape = childShape.connectorShape;
|
|
}
|
|
return childShape.getBounds(false, skipRotate);
|
|
};
|
|
BaseAlgorithm.prototype.getAlgorithmAlignBounds = function (isCalculateCoefficients) {
|
|
const childs = this.parentNode.childs;
|
|
let bounds;
|
|
const isCycleAlgorithm = this instanceof CycleAlgorithm;
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const node = childs[i];
|
|
if (node.isSkipShape(isCalculateCoefficients, isCycleAlgorithm)) {
|
|
continue;
|
|
}
|
|
const childBounds = node.algorithm.getChildAlgorithmAlignBounds(isCalculateCoefficients, isCycleAlgorithm);
|
|
if (bounds) {
|
|
checkBounds(bounds, childBounds);
|
|
} else {
|
|
bounds = childBounds;
|
|
}
|
|
}
|
|
return bounds;
|
|
};
|
|
BaseAlgorithm.prototype.getHorizontalAlgorithmOffset = function (isCalculateCoefficients) {
|
|
if (this.params[AscFormat.Param_type_horzAlign] === AscFormat.ParameterVal_horizontalAlignment_none) {
|
|
return 0;
|
|
}
|
|
|
|
const constrBounds = this.getAlgorithmAlignBounds(isCalculateCoefficients);
|
|
if (!constrBounds) {
|
|
return 0;
|
|
}
|
|
|
|
switch (this.params[AscFormat.Param_type_horzAlign]) {
|
|
case AscFormat.ParameterVal_horizontalAlignment_ctr: {
|
|
const parentWidth = this.parentNode.getConstr(AscFormat.Constr_type_w, !isCalculateCoefficients);
|
|
const boundsWidth = constrBounds.r - constrBounds.l;
|
|
return parentWidth / 2 - (constrBounds.l + boundsWidth / 2);
|
|
}
|
|
case AscFormat.ParameterVal_horizontalAlignment_l: {
|
|
return -constrBounds.l;
|
|
}
|
|
case AscFormat.ParameterVal_horizontalAlignment_r: {
|
|
const parentWidth = this.parentNode.getConstr(AscFormat.Constr_type_w, !isCalculateCoefficients);
|
|
return parentWidth - constrBounds.r;
|
|
}
|
|
default:
|
|
return 0;
|
|
|
|
}
|
|
};
|
|
BaseAlgorithm.prototype.getVerticalAlgorithmOffset = function (isCalculateCoefficients) {
|
|
if (this.params[AscFormat.Param_type_vertAlign] === AscFormat.ParameterVal_horizontalAlignment_none) {
|
|
return 0;
|
|
}
|
|
|
|
const constrBounds = this.getAlgorithmAlignBounds(isCalculateCoefficients);
|
|
if (!constrBounds) {
|
|
return 0;
|
|
}
|
|
|
|
switch (this.params[AscFormat.Param_type_vertAlign]) {
|
|
case AscFormat.ParameterVal_verticalAlignment_mid: {
|
|
const boundsHeight = constrBounds.b - constrBounds.t;
|
|
const parentHeight = this.parentNode.getConstr(AscFormat.Constr_type_h, !isCalculateCoefficients);
|
|
return parentHeight / 2 - (constrBounds.t + boundsHeight / 2);
|
|
}
|
|
case AscFormat.ParameterVal_verticalAlignment_t: {
|
|
return -constrBounds.t;
|
|
}
|
|
case AscFormat.ParameterVal_verticalAlignment_b: {
|
|
const parentHeight = this.parentNode.getConstr(AscFormat.Constr_type_h, !isCalculateCoefficients);
|
|
return parentHeight - constrBounds.b;
|
|
}
|
|
default:
|
|
return 0;
|
|
}
|
|
};
|
|
BaseAlgorithm.prototype.applyAlgorithmAligns = function (isCalculateCoefficients) {
|
|
const offX = this.getHorizontalAlgorithmOffset(isCalculateCoefficients);
|
|
const offY = this.getVerticalAlgorithmOffset(isCalculateCoefficients);
|
|
this.parentNode.forEachChild(function (node) {
|
|
node.moveTo(offX, offY, isCalculateCoefficients, true);
|
|
});
|
|
};
|
|
BaseAlgorithm.prototype.getParentConnectionNode = function () {
|
|
return this.parentNode;
|
|
};
|
|
BaseAlgorithm.prototype.setParentConnection = function (connectorAlgorithm, childNode) {
|
|
const parentConnNode = this.getParentConnectionNode();
|
|
if (connectorAlgorithm && childNode.algorithm && parentConnNode) {
|
|
let srcNode;
|
|
let dstNode;
|
|
if (connectorAlgorithm.params[AscFormat.Param_type_srcNode]) {
|
|
srcNode = parentConnNode.getNamedNode(connectorAlgorithm.params[AscFormat.Param_type_srcNode]);
|
|
} else {
|
|
srcNode = parentConnNode.getDefaultConnectionNode();
|
|
}
|
|
if (connectorAlgorithm.params[AscFormat.Param_type_dstNode]) {
|
|
dstNode = childNode.getNamedNode(connectorAlgorithm.params[AscFormat.Param_type_dstNode]);
|
|
} else {
|
|
dstNode = childNode.getDefaultConnectionNode();
|
|
}
|
|
if (srcNode && dstNode) {
|
|
connectorAlgorithm.setParentAlgorithm(this);
|
|
connectorAlgorithm.setFirstConnectorNode(srcNode);
|
|
connectorAlgorithm.setLastConnectorNode(dstNode);
|
|
}
|
|
}
|
|
};
|
|
BaseAlgorithm.prototype.getBounds = function (isCalculateScaleCoefficients, bounds) {
|
|
const shape = this.parentNode.getShape(isCalculateScaleCoefficients);
|
|
if (!bounds) {
|
|
bounds = shape.getBounds();
|
|
} else {
|
|
shape.checkBounds(bounds);
|
|
}
|
|
return bounds;
|
|
};
|
|
BaseAlgorithm.prototype.getRoot = function () {
|
|
return this.parentNode;
|
|
};
|
|
BaseAlgorithm.prototype.getShapes = function (smartartAlgorithm) {
|
|
const shapes = [];
|
|
const initObjects = smartartAlgorithm.getInitObjects();
|
|
if (!initObjects) {
|
|
return shapes;
|
|
}
|
|
const shadowShapes = this.parentNode.getShadowShapesByZOrder();
|
|
smartartAlgorithm.applyColorsDef(this.parentNode.getDescendantFilteredShapes().sort(function (shape1, shape2) {
|
|
return shape2.shape.zOrderOff - shape1.shape.zOrderOff;
|
|
}));
|
|
for (let i = 0; i < shadowShapes.length; i++) {
|
|
const shadowShape = shadowShapes[i];
|
|
const editorShape = shadowShape.getEditorShape(false, initObjects);
|
|
if (editorShape) {
|
|
shadowShape.editorShape = editorShape;
|
|
shapes.push(editorShape);
|
|
}
|
|
}
|
|
return shapes;
|
|
}
|
|
BaseAlgorithm.prototype.applyPostAlgorithmSettings = function (smartartAlgorithm) {
|
|
this.applyPostAlgorithmSettingsForShape(smartartAlgorithm, this.parentNode.getShape(false));
|
|
};
|
|
BaseAlgorithm.prototype.isHierarchy = function () {return false;};
|
|
BaseAlgorithm.prototype.moveToHierarchyOffsets = function () {};
|
|
BaseAlgorithm.prototype.isRootHierarchy = function () {
|
|
return false;
|
|
};
|
|
BaseAlgorithm.prototype.setConstraintSizes = function (shape) {
|
|
this.constraintSizes = {
|
|
x : shape.x,
|
|
y : shape.y,
|
|
width : shape.width,
|
|
height: shape.height
|
|
}
|
|
}
|
|
BaseAlgorithm.prototype.setSibConnection = function (startNode, endNode, connectorAlgorithm) {
|
|
let srcNode;
|
|
let dstNode;
|
|
const parentNode = this.parentNode;
|
|
if (connectorAlgorithm.params[AscFormat.Param_type_srcNode]) {
|
|
srcNode = startNode.getNamedNode(connectorAlgorithm.params[AscFormat.Param_type_srcNode]);
|
|
if (!srcNode) {
|
|
srcNode = parentNode.getNamedNode(connectorAlgorithm.params[AscFormat.Param_type_srcNode]);
|
|
}
|
|
} else {
|
|
srcNode = startNode.getDefaultConnectionNode();
|
|
}
|
|
if (connectorAlgorithm.params[AscFormat.Param_type_dstNode]) {
|
|
dstNode = endNode.getNamedNode(connectorAlgorithm.params[AscFormat.Param_type_dstNode]);
|
|
if (!dstNode) {
|
|
dstNode = parentNode.getNamedNode(connectorAlgorithm.params[AscFormat.Param_type_dstNode]);
|
|
}
|
|
} else {
|
|
dstNode = endNode.getDefaultConnectionNode();
|
|
}
|
|
if (srcNode && dstNode) {
|
|
connectorAlgorithm.setParentAlgorithm(this);
|
|
connectorAlgorithm.setFirstConnectorNode(srcNode);
|
|
connectorAlgorithm.setLastConnectorNode(dstNode);
|
|
}
|
|
};
|
|
BaseAlgorithm.prototype.setConnections = function() {
|
|
const nodes = this.parentNode.childs;
|
|
let firstNode;
|
|
let sibConnNode;
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
const node = nodes[i];
|
|
const shape = node.shape;
|
|
if (nodes[i].isRealShapeType()) {
|
|
sibConnNode = nodes[i];
|
|
}
|
|
if (shape.type === AscFormat.LayoutShapeType_outputShapeType_conn) {
|
|
const algorithm = node.algorithm;
|
|
if (node.isParNode() && this instanceof CompositeAlgorithm && sibConnNode) {
|
|
this.setParentConnection(algorithm, sibConnNode);
|
|
} else if (node.isParNode() || sibConnNode) {
|
|
if (!firstNode) {
|
|
firstNode = sibConnNode;
|
|
}
|
|
let nextIndex = i + 1;
|
|
while (nextIndex < nodes.length && !nodes[nextIndex].isRealShapeType()) {
|
|
nextIndex += 1;
|
|
}
|
|
const lastNode = nodes[nodes.length - 1].node;
|
|
const nextNode = nextIndex === nodes.length && !lastNode.isHideLastTrans ? firstNode : nodes[nextIndex];
|
|
if (nextNode) {
|
|
if (node.isParNode()) {
|
|
this.setParentConnection(algorithm, nextNode);
|
|
} else {
|
|
this.setSibConnection(sibConnNode, nextNode, algorithm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
BaseAlgorithm.prototype.getRadialConnectionInfo = function () {};
|
|
BaseAlgorithm.prototype.setParentAlgorithm = function (algorithm) {};
|
|
BaseAlgorithm.prototype.isHideLastChild = function () {
|
|
if (this._isHideLastChild !== null) {
|
|
return this._isHideLastChild;
|
|
}
|
|
this._isHideLastChild = false;
|
|
if (this.parentNode.isHideLastTrans) {
|
|
const childs = this.parentNode.childs;
|
|
const lastNode = childs[childs.length - 1];
|
|
if (lastNode && lastNode.isSibNode()) {
|
|
this._isHideLastChild = true;
|
|
}
|
|
}
|
|
return this._isHideLastChild;
|
|
};
|
|
|
|
BaseAlgorithm.prototype.calcScaleCoefficients = function () {};
|
|
BaseAlgorithm.prototype.setConnectionDistance = function (value, isStart) {
|
|
|
|
};
|
|
BaseAlgorithm.prototype.setStemThick = function (value) {
|
|
|
|
};
|
|
BaseAlgorithm.prototype.afterShape = function (smartartAlgorithm) {};
|
|
BaseAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createShadowShape(false, isCalculateScaleCoefficients);
|
|
};
|
|
BaseAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm, isCalculateScaleCoefficients) {
|
|
this.createShadowShape(isCalculateScaleCoefficients);
|
|
};
|
|
BaseAlgorithm.prototype.setParams = function (params) {
|
|
this.initParams(params);
|
|
};
|
|
BaseAlgorithm.prototype.initParams = function (params) {
|
|
for (let i = 0; i < params.length; i++) {
|
|
const param = params[i];
|
|
this.params[param.type] = param.getValEnum();
|
|
}
|
|
};
|
|
BaseAlgorithm.prototype.getAspectRatio = function () {
|
|
return this.params[AscFormat.Param_type_ar] || 0;
|
|
}
|
|
|
|
|
|
BaseAlgorithm.prototype.setParentNode = function (node) {
|
|
this.parentNode = node;
|
|
};
|
|
BaseAlgorithm.prototype.setFirstConnectorNode = function () {
|
|
|
|
};
|
|
BaseAlgorithm.prototype.setLastConnectorNode = function () {
|
|
|
|
};
|
|
BaseAlgorithm.prototype.applyPostAlgorithmSettingsForShape = function (smartartAlgorithm, shape, customCoefficient) {
|
|
const presNode = shape.node;
|
|
const prSet = presNode.getPrSet();
|
|
if (prSet.custLinFactY || prSet.custLinFactX || prSet.custLinFactNeighborY || prSet.custLinFactNeighborX || prSet.custRadScaleInc || prSet.custRadScaleRad) {
|
|
smartartAlgorithm.addSettingsForMove({shape: shape, coefficient: customCoefficient || 1});
|
|
}
|
|
};
|
|
function PositionAlgorithm() {
|
|
BaseAlgorithm.call(this);
|
|
this.connector = null;
|
|
this.shapeContainer = null;
|
|
this.coefficientShapeContainer = null;
|
|
}
|
|
AscFormat.InitClassWithoutType(PositionAlgorithm, BaseAlgorithm);
|
|
PositionAlgorithm.prototype.getParentNodeWidth = function (isAdapt) {
|
|
return this.parentNode.getConstr(AscFormat.Constr_type_w, isAdapt) || this.parentNode.getParentWidth(isAdapt);
|
|
};
|
|
PositionAlgorithm.prototype.getParentNodeHeight = function (isAdapt) {
|
|
return this.parentNode.getConstr(AscFormat.Constr_type_h, isAdapt) || this.parentNode.getParentHeight(isAdapt);
|
|
};
|
|
PositionAlgorithm.prototype.getShapeContainer = function (isCalculateScaleCoefficient) {
|
|
return isCalculateScaleCoefficient ? this.coefficientShapeContainer : this.shapeContainer;
|
|
};
|
|
|
|
PositionAlgorithm.prototype.applyParamOffsets = function (isCalculateScaleCoefficient) {
|
|
switch (this.params[AscFormat.Param_type_off]) {
|
|
case AscFormat.ParameterVal_offset_ctr:
|
|
this.applyCenterAlign(isCalculateScaleCoefficient);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
|
|
PositionAlgorithm.prototype.applyCenterAlign = function (isCalculateScaleCoefficient) {
|
|
const parentHeight = this.parentNode.getConstr(AscFormat.Constr_type_h, !isCalculateScaleCoefficient)/* || this.parentNode.getParentHeight(!isCalculateScaleCoefficient)*/;
|
|
const parentWidth = this.parentNode.getConstr(AscFormat.Constr_type_w, !isCalculateScaleCoefficient)/* || this.parentNode.getParentWidth(!isCalculateScaleCoefficient)*/;
|
|
if (!(parentWidth && parentHeight)) {
|
|
return
|
|
}
|
|
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficient);
|
|
shapeContainer.applyCenterAlign(parentHeight, parentWidth, isCalculateScaleCoefficient, this);
|
|
};
|
|
|
|
PositionAlgorithm.prototype.calcScaleCoefficients = function () {
|
|
|
|
};
|
|
PositionAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm) {
|
|
|
|
};
|
|
|
|
|
|
function SnakeAlgorithm() {
|
|
PositionAlgorithm.call(this);
|
|
this.calcValues = {
|
|
spacing: null
|
|
};
|
|
}
|
|
|
|
AscFormat.InitClassWithoutType(SnakeAlgorithm, PositionAlgorithm);
|
|
SnakeAlgorithm.prototype.initParams = function (params) {
|
|
BaseAlgorithm.prototype.initParams.call(this, params);
|
|
if (this.params[AscFormat.Param_type_flowDir] === undefined) {
|
|
this.params[AscFormat.Param_type_flowDir] = AscFormat.ParameterVal_flowDirection_row;
|
|
}
|
|
if (this.params[AscFormat.Param_type_grDir] === undefined) {
|
|
this.params[AscFormat.Param_type_grDir] = AscFormat.ParameterVal_growDirection_tL;
|
|
}
|
|
if (this.params[AscFormat.Param_type_bkpt] === undefined) {
|
|
this.params[AscFormat.Param_type_bkpt] = AscFormat.ParameterVal_breakpoint_endCnv;
|
|
}
|
|
if (this.params[AscFormat.Param_type_vertAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_vertAlign] = AscFormat.ParameterVal_verticalAlignment_mid;
|
|
}
|
|
if (this.params[AscFormat.Param_type_horzAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_horzAlign] = AscFormat.ParameterVal_horizontalAlignment_ctr;
|
|
}
|
|
if (this.params[AscFormat.Param_type_contDir] === undefined) {
|
|
this.params[AscFormat.Param_type_contDir] = AscFormat.ParameterVal_continueDirection_sameDir;
|
|
}
|
|
};
|
|
SnakeAlgorithm.prototype.applyParamOffsets = function (isCalculateScaleCoefficients) {
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficients);
|
|
shapeContainer.applyCenterAlign(this.params[AscFormat.Param_type_off] === AscFormat.ParameterVal_offset_ctr);
|
|
};
|
|
SnakeAlgorithm.prototype.getStartValues = function (node) {
|
|
const oRes = {coefficient: 1, width: 0, height: 0, prSpace: 0};
|
|
if (node) {
|
|
const shape = node.getShape(true);
|
|
oRes.height = shape.height;
|
|
oRes.width = shape.width;
|
|
|
|
const smWidth = this.parentNode.getConstr(AscFormat.Constr_type_w);
|
|
const smHeight = this.parentNode.getConstr(AscFormat.Constr_type_h);
|
|
|
|
const widthKoef = smWidth / oRes.width;
|
|
const heightKoef = smHeight / oRes.height;
|
|
oRes.coefficient = Math.min(1, widthKoef, heightKoef);
|
|
}
|
|
return oRes;
|
|
};
|
|
|
|
|
|
SnakeAlgorithm.prototype.calculateFixedRowScaleCoefficient = function () {
|
|
const parentNode = this.parentNode;
|
|
const childs = parentNode.childs;
|
|
|
|
const parentWidth = parentNode.getConstr(AscFormat.Constr_type_w);
|
|
const parentHeight = parentNode.getConstr(AscFormat.Constr_type_h);
|
|
const spaceConstr = parentNode.getConstr(AscFormat.Constr_type_sp);
|
|
|
|
const countInRow = this.getBreakpointFixedValue();
|
|
let maxWidth = 0;
|
|
let height = -spaceConstr;
|
|
let rowWidth = 0;
|
|
let maxRowHeight = 0;
|
|
let rowShapeCounter = 0;
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const node = childs[i];
|
|
const shape = node.getShape(true);
|
|
if (!node.node.isSibNode()) {
|
|
if (rowShapeCounter === countInRow) {
|
|
rowShapeCounter = 0;
|
|
if (maxWidth < rowWidth) {
|
|
maxWidth = rowWidth;
|
|
}
|
|
height += maxRowHeight + spaceConstr;
|
|
maxRowHeight = shape.height;
|
|
rowWidth = shape.width;
|
|
} else {
|
|
rowWidth += shape.width;
|
|
if (shape.height > maxRowHeight) {
|
|
maxRowHeight = shape.height;
|
|
}
|
|
}
|
|
rowShapeCounter += 1;
|
|
} else if (rowShapeCounter !== 0 && rowShapeCounter !== countInRow) {
|
|
rowWidth += shape.width;
|
|
}
|
|
}
|
|
if (rowShapeCounter !== 0) {
|
|
if (maxWidth < rowWidth) {
|
|
maxWidth = rowWidth;
|
|
}
|
|
height += maxRowHeight + spaceConstr;
|
|
}
|
|
const coefficient = Math.min(1, parentWidth / maxWidth, parentHeight / height);
|
|
this.setScaleCoefficient(coefficient);
|
|
};
|
|
SnakeAlgorithm.prototype.calculateFixedColumnScaleCoefficient = function () {
|
|
const parentNode = this.parentNode;
|
|
const childs = parentNode.childs;
|
|
|
|
const parentWidth = parentNode.getConstr(AscFormat.Constr_type_w);
|
|
const parentHeight = parentNode.getConstr(AscFormat.Constr_type_h);
|
|
const spaceConstr = parentNode.getConstr(AscFormat.Constr_type_sp);
|
|
|
|
const countInColumn = this.getBreakpointFixedValue();
|
|
|
|
let maxHeight = 0;
|
|
let width = -spaceConstr;
|
|
let columnHeight = 0;
|
|
let maxColumnWidth = 0;
|
|
let columnShapeCounter = 0;
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const node = childs[i];
|
|
const shape = node.getShape(true);
|
|
if (!node.node.isSibNode()) {
|
|
if (columnShapeCounter === countInColumn) {
|
|
columnShapeCounter = 0;
|
|
if (maxHeight < columnHeight) {
|
|
maxHeight = columnHeight;
|
|
}
|
|
width += maxColumnWidth + spaceConstr;
|
|
maxColumnWidth = shape.width;
|
|
columnHeight = shape.height;
|
|
} else {
|
|
columnHeight += shape.height;
|
|
if (shape.width > maxColumnWidth) {
|
|
maxColumnWidth = shape.width;
|
|
}
|
|
}
|
|
columnShapeCounter += 1;
|
|
} else if (columnShapeCounter !== 0 && columnShapeCounter !== countInColumn) {
|
|
columnHeight += shape.height;
|
|
}
|
|
}
|
|
if (columnShapeCounter !== 0) {
|
|
if (maxHeight < columnHeight) {
|
|
maxHeight = columnHeight;
|
|
}
|
|
width += maxColumnWidth + spaceConstr;
|
|
}
|
|
const coefficient = Math.min(1, parentWidth / width, parentHeight / maxHeight);
|
|
this.setScaleCoefficient(coefficient);
|
|
};
|
|
SnakeAlgorithm.prototype.setScaleCoefficient = function (coefficient) {
|
|
this.parentNode.forEachDes(function (node) {
|
|
node.setSizesScale(coefficient, coefficient);
|
|
});
|
|
const space = this.parentNode.getConstr(AscFormat.Constr_type_sp);
|
|
this.calcValues.spacing = coefficient * space;
|
|
}
|
|
SnakeAlgorithm.prototype.calculateCanvasRowScaleCoefficient = function () {
|
|
const parentNode = this.parentNode;
|
|
const childs = parentNode.childs;
|
|
|
|
const parentWidth = parentNode.getConstr(AscFormat.Constr_type_w);
|
|
const parentHeight = parentNode.getConstr(AscFormat.Constr_type_h);
|
|
const spaceConstr = parentNode.getConstr(AscFormat.Constr_type_sp);
|
|
const initValues = this.getStartValues(parentNode.childs[0]);
|
|
let coefficient = initValues.coefficient;
|
|
let i = 1;
|
|
let nNeedRecalc = 0;
|
|
function calculateAdaptCoefficient() {
|
|
let prSpaceWidth = 0;
|
|
let previousRowHeight = 0;
|
|
let columnWidth = initValues.width;
|
|
let rowHeight = initValues.height;
|
|
let previousRowSpace = 0;
|
|
let previousMaxWidthCoefficient = null;
|
|
for (i; i < childs.length; i++) {
|
|
const child = parentNode.childs[i];
|
|
const childShape = child.getShape(true);
|
|
if (child.node.isSibNode()) {
|
|
prSpaceWidth = childShape.width;
|
|
} else {
|
|
const width = childShape.width;
|
|
const height = childShape.height;
|
|
|
|
const sumWidth = columnWidth + width + prSpaceWidth;
|
|
const sumHeight = rowHeight + height + spaceConstr;
|
|
|
|
const updatePreviousRowHeight = previousRowHeight + height + previousRowSpace;
|
|
|
|
|
|
let widthCoefficient = 1;
|
|
let heightCoefficient = 1;
|
|
widthCoefficient = parentWidth / sumWidth;
|
|
heightCoefficient = parentHeight / sumHeight;
|
|
const tempCoefficient = Math.min(coefficient, Math.max(widthCoefficient, heightCoefficient));
|
|
const nodeWidthCoefficient = parentWidth / width;
|
|
const nodeHeightCoefficient = parentHeight / updatePreviousRowHeight;
|
|
let addToWidth = false;
|
|
|
|
|
|
if ((heightCoefficient < 1) && (heightCoefficient > widthCoefficient) && (nodeWidthCoefficient < tempCoefficient)) {
|
|
coefficient = Math.min(coefficient, /*nodeWidthCoefficient,*/ nodeWidthCoefficient);
|
|
addToWidth = true;
|
|
} else if ((updatePreviousRowHeight > rowHeight) && (widthCoefficient < 1) && (widthCoefficient > nodeHeightCoefficient) && (nodeHeightCoefficient < tempCoefficient)) {
|
|
if (previousRowHeight > height || nNeedRecalc >= i) {
|
|
coefficient = Math.min(coefficient, nodeHeightCoefficient);
|
|
} else {
|
|
coefficient = Math.min(coefficient, parentHeight / height);
|
|
return true;
|
|
}
|
|
} else {
|
|
if (previousMaxWidthCoefficient !== null && previousMaxWidthCoefficient < coefficient && tempCoefficient < coefficient && previousMaxWidthCoefficient >= heightCoefficient) {
|
|
coefficient = previousMaxWidthCoefficient;
|
|
return true;
|
|
} else if (widthCoefficient < coefficient && (previousMaxWidthCoefficient === null || previousMaxWidthCoefficient < widthCoefficient)) {
|
|
previousMaxWidthCoefficient = widthCoefficient;
|
|
}
|
|
addToWidth = widthCoefficient >= tempCoefficient;
|
|
coefficient = tempCoefficient;
|
|
|
|
}
|
|
if (addToWidth) {
|
|
columnWidth = sumWidth;
|
|
rowHeight = Math.max(rowHeight, updatePreviousRowHeight);
|
|
// todo need optimize
|
|
if (nNeedRecalc < i) {
|
|
return true
|
|
}
|
|
} else {
|
|
previousRowSpace = spaceConstr;
|
|
previousRowHeight = rowHeight;
|
|
rowHeight = sumHeight;
|
|
columnWidth = width;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
while (calculateAdaptCoefficient()) {
|
|
nNeedRecalc = i;
|
|
i = 1;
|
|
}
|
|
this.setScaleCoefficient(coefficient);
|
|
};
|
|
SnakeAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createShadowShape(false, isCalculateScaleCoefficients);
|
|
};
|
|
SnakeAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm, isCalculateScaleCoefficients) {
|
|
if (isCalculateScaleCoefficients) {
|
|
this.calcScaleCoefficients();
|
|
} else {
|
|
this._calculateShapePositions();
|
|
this.applyParamOffsets();
|
|
this.applyAlgorithmAligns();
|
|
this.applyPostAlgorithmSettings();
|
|
this.setConnections();
|
|
}
|
|
this.createShadowShape(isCalculateScaleCoefficients);
|
|
}
|
|
SnakeAlgorithm.prototype._calculateShapePositions = function () {
|
|
if (this.isColumn()) {
|
|
this.calculateColumnSnakeShapePositions();
|
|
} else {
|
|
this.calculateRowSnakeShapePositions();
|
|
}
|
|
}
|
|
SnakeAlgorithm.prototype.getMainElements = function () {
|
|
const childs = this.parentNode.childs;
|
|
const mainElements = [];
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const node = childs[i];
|
|
if (!node.node.isSibNode()) {
|
|
mainElements.push(node);
|
|
}
|
|
}
|
|
return mainElements;
|
|
};
|
|
SnakeAlgorithm.prototype.getBreakpointFixedValue = function () {
|
|
if (this.params[AscFormat.Param_type_bkPtFixedVal] !== undefined) {
|
|
return this.params[AscFormat.Param_type_bkPtFixedVal];
|
|
}
|
|
const mainElements = this.getMainElements();
|
|
return Math.ceil(Math.sqrt(mainElements.length));
|
|
|
|
};
|
|
SnakeAlgorithm.prototype.calcScaleCoefficients = function () {
|
|
if (this.isColumn()) {
|
|
if (this.params[AscFormat.Param_type_bkpt] !== AscFormat.ParameterVal_breakpoint_endCnv) {
|
|
this.calculateFixedColumnScaleCoefficient();
|
|
}
|
|
} else {
|
|
if (this.params[AscFormat.Param_type_bkpt] === AscFormat.ParameterVal_breakpoint_endCnv) {
|
|
this.calculateCanvasRowScaleCoefficient();
|
|
} else {
|
|
this.calculateFixedRowScaleCoefficient();
|
|
}
|
|
}
|
|
};
|
|
SnakeAlgorithm.prototype.isReverseNextLine = function () {
|
|
return this.params[AscFormat.Param_type_contDir] === AscFormat.ParameterVal_continueDirection_revDir;
|
|
};
|
|
SnakeAlgorithm.prototype.addGridToParentContainer = function (parentContainer, gridContainer, isReverse) {
|
|
if (isReverse) {
|
|
gridContainer.reverse();
|
|
}
|
|
|
|
switch (this.params[AscFormat.Param_type_grDir]) {
|
|
case AscFormat.ParameterVal_growDirection_tL:
|
|
parentContainer.push(gridContainer);
|
|
break;
|
|
case AscFormat.ParameterVal_growDirection_bR:
|
|
parentContainer.unshift(gridContainer);
|
|
break;
|
|
case AscFormat.ParameterVal_growDirection_tR:
|
|
if (this.isColumn()) {
|
|
parentContainer.unshift(gridContainer);
|
|
} else {
|
|
parentContainer.push(gridContainer);
|
|
}
|
|
break;
|
|
case AscFormat.ParameterVal_growDirection_bL:
|
|
if (this.isColumn()) {
|
|
parentContainer.push(gridContainer);
|
|
} else {
|
|
parentContainer.unshift(gridContainer);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
SnakeAlgorithm.prototype.isPushInCurrentLine = function (containerLength) {
|
|
let defaultValue;
|
|
switch (this.params[AscFormat.Param_type_grDir]) {
|
|
case AscFormat.ParameterVal_growDirection_tR:
|
|
defaultValue = this.isColumn();
|
|
break;
|
|
case AscFormat.ParameterVal_growDirection_tL:
|
|
defaultValue = true;
|
|
break;
|
|
case AscFormat.ParameterVal_growDirection_bR:
|
|
defaultValue = false;
|
|
break;
|
|
case AscFormat.ParameterVal_growDirection_bL:
|
|
defaultValue = !this.isColumn();
|
|
break;
|
|
default:
|
|
defaultValue = true;
|
|
break;
|
|
}
|
|
return this.isReverseNextLine() && (containerLength % 2 === 1) ? !defaultValue : defaultValue;
|
|
};
|
|
SnakeAlgorithm.prototype.addShapeToRow = function (row, shape, isPush, offX) {
|
|
row.push(shape);
|
|
if (isPush) {
|
|
shape.moveTo(offX - shape.x, -shape.y);
|
|
return shape.x + shape.width;
|
|
} else {
|
|
shape.moveTo(offX - (shape.x + shape.width), -shape.y);
|
|
return shape.x;
|
|
}
|
|
};
|
|
SnakeAlgorithm.prototype.addShapeToColumn = function (column, shape, isPush, offY) {
|
|
column.push(shape);
|
|
if (isPush) {
|
|
shape.moveTo(-shape.x, offY - shape.y);
|
|
return shape.y + shape.height;
|
|
} else {
|
|
shape.moveTo(-shape.x, offY - (shape.y + shape.height));
|
|
return shape.y;
|
|
}
|
|
};
|
|
SnakeAlgorithm.prototype.calculateRowSnakeShapePositions = function () {
|
|
const childs = this.parentNode.childs;
|
|
const parentWidth = this.parentNode.getConstr(AscFormat.Constr_type_w, true);
|
|
const constrSpace = this.calcValues.spacing;
|
|
const rows = this.getShapeContainer();
|
|
rows.setGap(constrSpace);
|
|
let row = new ShapeContainer();
|
|
let isPushInCurrentLine = this.isPushInCurrentLine(0);
|
|
let sibSpacingShapes = [];
|
|
let sibWidth = 0;
|
|
let offX = 0;
|
|
let startX = 0;
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const child = childs[i];
|
|
const shape = child.getShape(false);
|
|
const newRowWidth = Math.abs(offX - startX) + shape.width + sibWidth;
|
|
if (newRowWidth > parentWidth && !fAlgDeltaEqual(newRowWidth, parentWidth)) {
|
|
this.addGridToParentContainer(rows, row, !isPushInCurrentLine);
|
|
isPushInCurrentLine = this.isPushInCurrentLine(rows.getLength());
|
|
if (isPushInCurrentLine) {
|
|
const positionShape = row.shapes[0];
|
|
offX = positionShape.x;
|
|
startX = offX;
|
|
} else {
|
|
const positionShape = row.shapes[row.shapes.length - 1];
|
|
offX = positionShape.x + positionShape.width;
|
|
startX = offX;
|
|
}
|
|
|
|
row = new ShapeContainer();
|
|
sibSpacingShapes = [];
|
|
sibWidth = 0;
|
|
if (!child.node.isSibNode()) {
|
|
offX = this.addShapeToRow(row, shape, isPushInCurrentLine, offX);
|
|
}
|
|
} else {
|
|
if (!child.node.isSibNode()) {
|
|
for (let j = 0; j < sibSpacingShapes.length; j += 1) {
|
|
offX = this.addShapeToRow(row, sibSpacingShapes[j], isPushInCurrentLine, offX);
|
|
}
|
|
sibSpacingShapes = [];
|
|
sibWidth = 0;
|
|
offX = this.addShapeToRow(row, shape, isPushInCurrentLine, offX);
|
|
} else if (row.shapes.length !== 0) {
|
|
sibSpacingShapes.push(shape);
|
|
sibWidth += shape.width;
|
|
}
|
|
}
|
|
}
|
|
if (row !== rows.rows[rows.rows.length - 1]) {
|
|
this.addGridToParentContainer(rows, row);
|
|
}
|
|
rows.applyVerticalPositions();
|
|
};
|
|
|
|
SnakeAlgorithm.prototype.calculateColumnSnakeShapePositions = function () {
|
|
const childs = this.parentNode.childs;
|
|
const parentHeight = this.parentNode.getConstr(AscFormat.Constr_type_h, true);
|
|
const constrSpace = this.calcValues.spacing;
|
|
const columns = this.getShapeContainer();
|
|
columns.setGap(constrSpace);
|
|
let column = new ShapeContainer();
|
|
let isPushInCurrentLine = this.isPushInCurrentLine(0);
|
|
let sibSpacingShapes = [];
|
|
let sibSpacingHeight = 0;
|
|
let offY = 0;
|
|
let startY = 0;
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const child = childs[i];
|
|
const shape = child.getShape(false);
|
|
const newRowHeight = Math.abs(offY - startY) + shape.height + sibSpacingHeight;
|
|
if (newRowHeight > parentHeight && !fAlgDeltaEqual(newRowHeight, parentHeight)) {
|
|
this.addGridToParentContainer(columns, column, !isPushInCurrentLine);
|
|
isPushInCurrentLine = this.isPushInCurrentLine(columns.getLength());
|
|
if (isPushInCurrentLine) {
|
|
const positionShape = column.shapes[0];
|
|
offY = positionShape.y;
|
|
startY = offY;
|
|
} else {
|
|
const positionShape = column.shapes[column.shapes.length - 1];
|
|
offY = positionShape.y + positionShape.height;
|
|
startY = offY;
|
|
}
|
|
|
|
column = new ShapeContainer();
|
|
sibSpacingShapes = [];
|
|
sibSpacingHeight = 0;
|
|
if (!child.node.isSibNode()) {
|
|
offY = this.addShapeToColumn(column, shape, isPushInCurrentLine, offY);
|
|
}
|
|
} else {
|
|
if (!child.node.isSibNode()) {
|
|
for (let j = 0; j < sibSpacingShapes.length; j += 1) {
|
|
offY = this.addShapeToColumn(column, sibSpacingShapes[j], isPushInCurrentLine, offY);
|
|
}
|
|
sibSpacingShapes = [];
|
|
sibSpacingHeight = 0;
|
|
offY = this.addShapeToColumn(column, shape, isPushInCurrentLine, offY);
|
|
} else if (column.shapes.length !== 0) {
|
|
sibSpacingShapes.push(shape);
|
|
sibSpacingHeight += shape.height;
|
|
}
|
|
}
|
|
}
|
|
if (column !== columns.columns[columns.columns.length - 1]) {
|
|
this.addGridToParentContainer(columns, column);
|
|
}
|
|
columns.applyHorizontalPositions();
|
|
};
|
|
SnakeAlgorithm.prototype.isColumn = function () {
|
|
return this.params[AscFormat.Param_type_flowDir] === AscFormat.ParameterVal_flowDirection_col;
|
|
}
|
|
SnakeAlgorithm.prototype.getShapeContainer = function (isCalculateScaleCoefficient) {
|
|
if (isCalculateScaleCoefficient) {
|
|
if (this.coefficientShapeContainer === null) {
|
|
this.coefficientShapeContainer = this.isColumn() ? new ShapeColumns() : new ShapeRows();
|
|
}
|
|
return this.coefficientShapeContainer;
|
|
}
|
|
if (this.shapeContainer === null) {
|
|
this.shapeContainer = this.isColumn() ? new ShapeColumns() : new ShapeRows();
|
|
}
|
|
return this.shapeContainer;
|
|
};
|
|
|
|
function ContainerBase() {
|
|
|
|
}
|
|
ContainerBase.prototype.forEachShape = function (callback) {
|
|
};
|
|
ContainerBase.prototype.applyCenterAlign = function (parentHeight, parentWidth, isCalculateScaleCoefficients, algorithm) {
|
|
};
|
|
|
|
function ShapeContainer() {
|
|
ContainerBase.call(this);
|
|
this.shapes = [];
|
|
this.bounds = null;
|
|
}
|
|
AscFormat.InitClassWithoutType(ShapeContainer, ContainerBase);
|
|
ShapeContainer.prototype.forEachShape = function (callback) {
|
|
for (let i = 0; i < this.shapes.length; i += 1) {
|
|
callback(this.shapes[i]);
|
|
}
|
|
};
|
|
ShapeContainer.prototype.reverse = function () {
|
|
return this.shapes.reverse();
|
|
};
|
|
ShapeContainer.prototype.push = function (shape) {
|
|
this.shapes.push(shape);
|
|
};
|
|
ShapeContainer.prototype.unshift = function (shape) {
|
|
this.shapes.unshift(shape);
|
|
};
|
|
ShapeContainer.prototype.getBounds = function (isCalculateScaleCoefficient, isClean) {
|
|
if (this.shapes.length) {
|
|
const firstShape = this.shapes[0];
|
|
this.bounds = firstShape.getBounds(isClean);
|
|
for (let i = 1; i < this.shapes.length; i += 1) {
|
|
this.shapes[i].checkBounds(this.bounds, isClean);
|
|
}
|
|
} else {
|
|
this.bounds = {l: 0, r: 0, t: 0, b: 0};
|
|
}
|
|
return this.bounds;
|
|
};
|
|
ShapeContainer.prototype.getOffsets = function (parentHeight, parentWidth, isCalculateScaleCoefficient) {
|
|
const bounds = this.getBounds(isCalculateScaleCoefficient);
|
|
const ctrX = bounds.l + (bounds.r - bounds.l) / 2;
|
|
const ctrY = bounds.t + (bounds.b - bounds.t) / 2;
|
|
const offX = parentWidth / 2 - ctrX;
|
|
const offY = parentHeight / 2 - ctrY;
|
|
return {offX: offX, offY: offY};
|
|
}
|
|
ShapeContainer.prototype.applyCenterAlign = function (parentHeight, parentWidth, isCalculateScaleCoefficient, algorithm) {
|
|
const offsets = this.getOffsets(parentHeight, parentWidth, isCalculateScaleCoefficient);
|
|
algorithm.moveToHierarchyOffsets(offsets.offX, offsets.offY);
|
|
for (let i = 0; i < this.shapes.length; i++) {
|
|
const shape = this.shapes[i];
|
|
const node = shape.node;
|
|
node.moveTo(offsets.offX, offsets.offY, isCalculateScaleCoefficient);
|
|
}
|
|
};
|
|
function PyramidContainer() {
|
|
ShapeContainer.call(this)
|
|
}
|
|
AscFormat.InitClassWithoutType(PyramidContainer, ShapeContainer);
|
|
|
|
function HierarchyChildContainer() {
|
|
ShapeContainer.call(this);
|
|
}
|
|
AscFormat.InitClassWithoutType(HierarchyChildContainer, ShapeContainer);
|
|
HierarchyChildContainer.prototype.getBounds = function (isCalculateScaleCoefficient) {
|
|
let bounds;
|
|
for (let i = 0; i < this.shapes.length; i += 1) {
|
|
const shape = this.shapes[i];
|
|
const algorithm = shape.node.algorithm;
|
|
bounds = algorithm.getBounds(isCalculateScaleCoefficient, bounds);
|
|
}
|
|
if (!bounds) {
|
|
return {l: 0, r: 0, t: 0, b: 0};
|
|
}
|
|
return bounds;
|
|
};
|
|
function HierarchyRootContainer() {
|
|
ShapeContainer.call(this);
|
|
}
|
|
AscFormat.InitClassWithoutType(HierarchyRootContainer, ShapeContainer);
|
|
function CycleContainer() {
|
|
ShapeContainer.call(this);
|
|
}
|
|
AscFormat.InitClassWithoutType(CycleContainer, ShapeContainer);
|
|
CycleContainer.prototype.getBounds = function (isCalculateScaleCoefficient) {
|
|
if (this.shapes.length) {
|
|
const firstShape = this.shapes[0];
|
|
const bounds = {
|
|
l: firstShape.x,
|
|
t: firstShape.y,
|
|
b: firstShape.y + firstShape.height,
|
|
r: firstShape.x + firstShape.width
|
|
};
|
|
this.bounds = bounds;
|
|
for (let i = 0; i < this.shapes.length; i += 1) {
|
|
const shape = this.shapes[i];
|
|
if (shape.x < bounds.l) {
|
|
bounds.l = shape.x;
|
|
}
|
|
if (shape.y < bounds.t) {
|
|
bounds.t = shape.y;
|
|
}
|
|
|
|
const r = shape.x + shape.width;
|
|
if (r > bounds.r) {
|
|
bounds.r = r;
|
|
}
|
|
|
|
const b = shape.y + shape.height;
|
|
if (b > bounds.b) {
|
|
bounds.b = b;
|
|
}
|
|
}
|
|
} else {
|
|
this.bounds = {l: 0, r: 0, b: 0, t: 0};
|
|
}
|
|
return this.bounds;
|
|
};
|
|
|
|
|
|
function ShapeRows() {
|
|
ContainerBase.call(this);
|
|
this.bounds = null;
|
|
this.rows = [];
|
|
this.gap = 0;
|
|
}
|
|
AscFormat.InitClassWithoutType(ShapeRows, ContainerBase);
|
|
ShapeRows.prototype.getLength = function () {
|
|
return this.rows.length;
|
|
};
|
|
ShapeRows.prototype.setGap = function (value) {
|
|
this.gap = value;
|
|
};
|
|
ShapeRows.prototype.applyVerticalPositions = function () {
|
|
for (let i = 1; i < this.rows.length; i += 1) {
|
|
const currentRow = this.rows[i];
|
|
const currentRowBounds = currentRow.getBounds();
|
|
const previousRowBounds = this.rows[i - 1].getBounds();
|
|
|
|
const offY = previousRowBounds.b + this.gap - currentRowBounds.t;
|
|
for (let j = 0; j < currentRow.shapes.length; j += 1) {
|
|
const shape = currentRow.shapes[j];
|
|
shape.moveTo(0, offY);
|
|
}
|
|
}
|
|
};
|
|
ShapeRows.prototype.push = function (elem) {
|
|
this.rows.push(elem);
|
|
}
|
|
ShapeRows.prototype.unshift = function (elem) {
|
|
this.rows.unshift(elem);
|
|
}
|
|
ShapeRows.prototype.getBounds = function (isCalculateScaleCoefficient, isClean) {
|
|
if (this.rows.length) {
|
|
const firstBounds = Object.assign({}, this.rows[0].getBounds(isCalculateScaleCoefficient, isClean));
|
|
for (let i = 0; i < this.rows.length; i++) {
|
|
const row = this.rows[i];
|
|
const bounds = row.getBounds(isCalculateScaleCoefficient, isClean);
|
|
checkBounds(firstBounds, bounds);
|
|
}
|
|
this.bounds = firstBounds;
|
|
} else {
|
|
this.bounds = {l: 0, r: 0, t: 0, b: 0};
|
|
}
|
|
return this.bounds;
|
|
};
|
|
|
|
ShapeRows.prototype.applyCenterAlign = function (isCenteringRows) {
|
|
const bounds = this.getBounds();
|
|
const width = bounds.r - bounds.l;
|
|
|
|
for (let i = 0; i < this.rows.length; i++) {
|
|
const row = this.rows[i];
|
|
const rowBounds = row.getBounds();
|
|
const rowHeight = rowBounds.b - rowBounds.t;
|
|
let offRowX = 0;
|
|
if (isCenteringRows) {
|
|
const rowWidth = rowBounds.r - rowBounds.l;
|
|
offRowX = bounds.l + width / 2 - (rowBounds.l + rowWidth / 2);
|
|
}
|
|
for (let j = 0; j < row.shapes.length; j++) {
|
|
const shape = row.shapes[j];
|
|
const offRowY = rowBounds.t + rowHeight / 2 - (shape.y + shape.height / 2);
|
|
shape.moveTo(offRowX, offRowY);
|
|
}
|
|
}
|
|
};
|
|
ShapeRows.prototype.forEachShape = function (callback) {
|
|
for (let i = 0; i < this.rows.length; i += 1) {
|
|
this.rows[i].forEachShape(callback);
|
|
}
|
|
};
|
|
|
|
function ShapeColumns() {
|
|
ContainerBase.call(this);
|
|
this.bounds = null;
|
|
this.columns = [];
|
|
this.gap = 0;
|
|
}
|
|
AscFormat.InitClassWithoutType(ShapeColumns, ContainerBase);
|
|
|
|
ShapeColumns.prototype.getLength = function () {
|
|
return this.columns.length;
|
|
};
|
|
ShapeColumns.prototype.push = function (elem) {
|
|
this.columns.push(elem);
|
|
}
|
|
ShapeColumns.prototype.unshift = function (elem) {
|
|
this.columns.unshift(elem);
|
|
}
|
|
ShapeColumns.prototype.setGap = function (value) {
|
|
this.gap = value;
|
|
}
|
|
ShapeColumns.prototype.getBounds = function (isCalculateScaleCoefficient, isClean) {
|
|
if (this.columns.length) {
|
|
const firstBounds = Object.assign({}, this.columns[0].getBounds(isCalculateScaleCoefficient, isClean));
|
|
for (let i = 0; i < this.columns.length; i++) {
|
|
const column = this.columns[i];
|
|
const bounds = column.getBounds(isCalculateScaleCoefficient, isClean);
|
|
checkBounds(firstBounds, bounds);
|
|
}
|
|
this.bounds = firstBounds;
|
|
} else {
|
|
this.bounds = {l: 0, r: 0, t: 0, b: 0};
|
|
}
|
|
return this.bounds;
|
|
};
|
|
|
|
ShapeColumns.prototype.applyHorizontalPositions = function () {
|
|
for (let i = 1; i < this.columns.length; i += 1) {
|
|
const currentColumn = this.columns[i];
|
|
const currentColumnBounds = currentColumn.getBounds();
|
|
const previousColumnBounds = this.columns[i - 1].getBounds();
|
|
|
|
const offX = previousColumnBounds.r + this.gap - currentColumnBounds.l;
|
|
for (let j = 0; j < currentColumn.shapes.length; j += 1) {
|
|
const shape = currentColumn.shapes[j];
|
|
shape.moveTo(offX, 0);
|
|
}
|
|
}
|
|
};
|
|
|
|
ShapeColumns.prototype.applyCenterAlign = function (isCenteringColumns) {
|
|
const bounds = this.getBounds();
|
|
const height = bounds.b - bounds.t;
|
|
|
|
for (let i = 0; i < this.columns.length; i++) {
|
|
const column = this.columns[i];
|
|
const columnBounds = column.getBounds();
|
|
const columnWidth = columnBounds.r - columnBounds.l;
|
|
|
|
let offColumnY = 0;
|
|
if (isCenteringColumns) {
|
|
const columnHeight = columnBounds.b - columnBounds.t;
|
|
offColumnY = height / 2 - (columnBounds.t + columnHeight / 2);
|
|
}
|
|
for (let j = 0; j < column.shapes.length; j++) {
|
|
const shape = column.shapes[j];
|
|
const offColumnX = columnBounds.l + columnWidth / 2 - (shape.x + shape.width / 2);
|
|
shape.moveTo(offColumnX, offColumnY);
|
|
}
|
|
}
|
|
};
|
|
ShapeColumns.prototype.forEachShape = function (callback) {
|
|
for (let i = 0; i < this.columns.length; i += 1) {
|
|
this.columns[i].forEachShape(callback);
|
|
}
|
|
};
|
|
|
|
function HierarchyAlgorithm() {
|
|
PositionAlgorithm.call(this);
|
|
this.levelPositions = [];
|
|
this.calcValues = {
|
|
mainChilds: null
|
|
};
|
|
}
|
|
AscFormat.InitClassWithoutType(HierarchyAlgorithm, PositionAlgorithm);
|
|
HierarchyAlgorithm.prototype.moveToHierarchyOffsets = function (dx, dy) {
|
|
for (let i = 0; i < this.levelPositions.length; i += 1) {
|
|
const levelPosition = this.levelPositions[i];
|
|
levelPosition.l += dx;
|
|
levelPosition.r += dx;
|
|
levelPosition.t += dy;
|
|
levelPosition.b += dy;
|
|
}
|
|
};
|
|
HierarchyAlgorithm.prototype.setLevelBounds = function (bounds) {
|
|
this.levelPositions.push(Object.assign({}, bounds));
|
|
};
|
|
HierarchyAlgorithm.prototype.getHorizontalOffset = function (node, isCalculateScaleCoefficient, fromLeft) {
|
|
const algorithm = node.algorithm;
|
|
let maxSpace = 0;
|
|
const shape = node.getShape(isCalculateScaleCoefficient);
|
|
|
|
for (let i = 0; i < this.levelPositions.length; i += 1) {
|
|
const startBounds = this.levelPositions[i];
|
|
for (let j = 0; j < algorithm.levelPositions.length; j += 1) {
|
|
const endBounds = algorithm.levelPositions[j];
|
|
let levelDifference;
|
|
if (fromLeft) {
|
|
levelDifference = startBounds.r - endBounds.l;
|
|
} else {
|
|
levelDifference = endBounds.r - startBounds.l;
|
|
}
|
|
if (levelDifference > maxSpace && !!this.getVerticalIntersection(startBounds, endBounds)) {
|
|
maxSpace = levelDifference;
|
|
}
|
|
}
|
|
const shapeBounds = shape.getBounds();
|
|
let nodeDifference;
|
|
if (fromLeft) {
|
|
nodeDifference = startBounds.r - shapeBounds.l;
|
|
} else {
|
|
nodeDifference = shapeBounds.r - startBounds.l;
|
|
}
|
|
if (nodeDifference > maxSpace && !!this.getVerticalIntersection(shapeBounds, startBounds)) {
|
|
maxSpace = nodeDifference;
|
|
}
|
|
}
|
|
return maxSpace;
|
|
};
|
|
HierarchyAlgorithm.prototype.getHorizontalIntersection = function (bounds1, bounds2) {
|
|
return Math.max(Math.min(bounds1.r, bounds2.r) - Math.max(bounds1.l, bounds2.l), 0);
|
|
};
|
|
HierarchyAlgorithm.prototype.getVerticalIntersection = function (bounds1, bounds2) {
|
|
return Math.max(Math.min(bounds1.b, bounds2.b) - Math.max(bounds1.t, bounds2.t), 0);
|
|
};
|
|
HierarchyAlgorithm.prototype.getVerticalOffset = function (node, isCalculateScaleCoefficient) {
|
|
const algorithm = node.algorithm;
|
|
let maxSpace = 0;
|
|
const shape = node.getShape(isCalculateScaleCoefficient);
|
|
for (let i = 0; i < this.levelPositions.length; i += 1) {
|
|
const startBounds = this.levelPositions[i];
|
|
for (let j = 0; j < algorithm.levelPositions.length; j += 1) {
|
|
const endBounds = algorithm.levelPositions[j];
|
|
const levelDifference = startBounds.b - endBounds.t;
|
|
if (levelDifference > maxSpace && !!this.getHorizontalIntersection(startBounds, endBounds)) {
|
|
maxSpace = levelDifference;
|
|
}
|
|
}
|
|
const shapeBounds = shape.getBounds();
|
|
const nodeDifference = startBounds.b - shapeBounds.t;
|
|
if (nodeDifference > maxSpace && !!this.getHorizontalIntersection(shapeBounds, startBounds)) {
|
|
maxSpace = nodeDifference;
|
|
}
|
|
}
|
|
return maxSpace;
|
|
};
|
|
HierarchyAlgorithm.prototype.isHierarchy = function () {
|
|
return true;
|
|
};
|
|
HierarchyAlgorithm.prototype.getMainChilds = function () {
|
|
if (this.calcValues.mainChilds === null) {
|
|
const childs = [];
|
|
for (let i = 0; i < this.parentNode.childs.length; i += 1) {
|
|
const child = this.parentNode.childs[i];
|
|
if (child.isContentNode()) {
|
|
childs.push(child);
|
|
}
|
|
}
|
|
this.calcValues.mainChilds = childs;
|
|
}
|
|
return this.calcValues.mainChilds;
|
|
};
|
|
HierarchyAlgorithm.prototype._calculateShapePositions = function (isAdapt) {
|
|
|
|
};
|
|
HierarchyAlgorithm.prototype.setScaleCoefficient = function () {
|
|
if (this.parentNode.parent && !(this.parentNode.parent.algorithm instanceof CompositeAlgorithm)) {
|
|
return;
|
|
}
|
|
const childs = this.getMainChilds();
|
|
const parentHeight = this.parentNode.getConstr(AscFormat.Constr_type_h);
|
|
const parentWidth = this.parentNode.getConstr(AscFormat.Constr_type_w);
|
|
if (!(parentHeight && parentWidth)) {
|
|
return;
|
|
}
|
|
const shapeContainer = this.getShapeContainer(true);
|
|
const bounds = shapeContainer.getBounds(true);
|
|
const height = bounds.b - bounds.t;
|
|
const width = bounds.r - bounds.l;
|
|
|
|
const widthCoefficient = Math.min(parentWidth / width, 1);
|
|
const heightCoefficient = Math.min(parentHeight / height, 1);
|
|
const coefficient = Math.min(widthCoefficient, heightCoefficient, 1);
|
|
if (!AscFormat.isRealNumber(coefficient)) {
|
|
return
|
|
}
|
|
|
|
this.parentNode.forEachDes(function (node) {
|
|
node.setSizesScale(coefficient, coefficient);
|
|
});
|
|
};
|
|
|
|
HierarchyAlgorithm.prototype.updateLevelPositions = function (algorithm) {
|
|
if (algorithm.levelPositions) {
|
|
for (let i = 0; i < algorithm.levelPositions.length; i += 1) {
|
|
this.setLevelBounds(algorithm.levelPositions[i]);
|
|
}
|
|
}
|
|
};
|
|
HierarchyAlgorithm.prototype.resetLevelPositions = function () {
|
|
this.levelPositions = [];
|
|
};
|
|
HierarchyAlgorithm.prototype.collectHierarchyPositions = function () {};
|
|
HierarchyAlgorithm.prototype.putShapesToShapeContainer = function (isCalculateScaleCoefficient) {};
|
|
HierarchyAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm, isCalculateScaleCoefficients) {
|
|
this.resetLevelPositions();
|
|
this.putShapesToShapeContainer(isCalculateScaleCoefficients);
|
|
this._calculateShapePositions(isCalculateScaleCoefficients);
|
|
this.applyParamOffsets(isCalculateScaleCoefficients);
|
|
this.collectHierarchyPositions();
|
|
if (isCalculateScaleCoefficients) {
|
|
this.setScaleCoefficient();
|
|
} else {
|
|
this.setConnections();
|
|
}
|
|
this.createShadowShape(isCalculateScaleCoefficients);
|
|
};
|
|
|
|
|
|
function HierarchyChildAlgorithm() {
|
|
HierarchyAlgorithm.call(this);
|
|
}
|
|
AscFormat.InitClassWithoutType(HierarchyChildAlgorithm, HierarchyAlgorithm);
|
|
|
|
HierarchyChildAlgorithm.prototype.getHorizontalSibSp = function (node, isCalculateScaleCoefficient, fromLeft) {
|
|
const sibSp = this.parentNode.getConstr(AscFormat.Constr_type_sibSp, !isCalculateScaleCoefficient);
|
|
const offset = this.getHorizontalOffset(node, isCalculateScaleCoefficient, fromLeft);
|
|
if (fromLeft) {
|
|
return sibSp + offset;
|
|
} else {
|
|
return - offset - sibSp;
|
|
}
|
|
};
|
|
HierarchyChildAlgorithm.prototype.getVerticalSibSp = function (node, isCalculateScaleCoefficient) {
|
|
const sibSp = this.parentNode.getConstr(AscFormat.Constr_type_sibSp, !isCalculateScaleCoefficient);
|
|
const offset = this.getVerticalOffset(node, isCalculateScaleCoefficient);
|
|
return sibSp + offset;
|
|
};
|
|
HierarchyChildAlgorithm.prototype.isHorizontalHierarchy = function () {
|
|
const parent = this.parentNode.parent;
|
|
if (parent && parent.algorithm.isHierarchy()) {
|
|
return parent.algorithm.isHorizontalHierarchy();
|
|
} else {
|
|
switch (this.params[AscFormat.Param_type_chAlign]) {
|
|
case AscFormat.ParameterVal_childAlignment_r:
|
|
case AscFormat.ParameterVal_childAlignment_l:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
};
|
|
HierarchyChildAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createHierarchyChildShadowShape(isCalculateScaleCoefficients);
|
|
};
|
|
HierarchyChildAlgorithm.prototype.setParentConnection = function (connectorAlgorithm, childNode) {
|
|
const parent = this.parentNode.parent;
|
|
if (parent && parent.algorithm.isHierarchy()) {
|
|
const root = parent.algorithm.getRoot();
|
|
root.algorithm.setParentConnection(connectorAlgorithm, childNode.algorithm.getRoot());
|
|
}
|
|
};
|
|
HierarchyChildAlgorithm.prototype.initParams = function (params) {
|
|
HierarchyAlgorithm.prototype.initParams.call(this, params);
|
|
if (this.params[AscFormat.Param_type_linDir] === undefined) {
|
|
this.params[AscFormat.Param_type_linDir] = AscFormat.ParameterVal_linearDirection_fromL;
|
|
}
|
|
if (this.params[AscFormat.Param_type_chAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_chAlign] = AscFormat.ParameterVal_childAlignment_t;
|
|
}
|
|
if (this.params[AscFormat.Param_type_off] === undefined) {
|
|
this.params[AscFormat.Param_type_off] = AscFormat.ParameterVal_offset_ctr;
|
|
}
|
|
}
|
|
|
|
HierarchyChildAlgorithm.prototype.isHang = function () {
|
|
return this.params[AscFormat.Param_type_secLinDir] !== undefined &&
|
|
this.params[AscFormat.Param_type_linDir] !== undefined;
|
|
}
|
|
HierarchyChildAlgorithm.prototype.getCommonChildBounds = function (isCalculateScaleCoefficient) {
|
|
const childs = this.getMainChilds();
|
|
let bounds;
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const child = childs[i];
|
|
bounds = child.algorithm.getBounds(isCalculateScaleCoefficient, bounds);
|
|
}
|
|
return bounds;
|
|
};
|
|
HierarchyChildAlgorithm.prototype.getRootCenteringOffset = function (shape, isCalculateScaleCoefficient) {
|
|
const result = {offX: 0, offY: 0};
|
|
if (this.isHang()) {
|
|
const isHorizontal = this.isHorizontalHierarchy();
|
|
const sibSp = this.parentNode.getConstr(AscFormat.Constr_type_sibSp, !isCalculateScaleCoefficient);
|
|
const bounds = this.getHangStructBounds(isCalculateScaleCoefficient);
|
|
if (!bounds) {
|
|
return result;
|
|
}
|
|
if (isHorizontal) {
|
|
result.offY = shape.y + shape.height / 2 - bounds.b - sibSp / 2;
|
|
} else {
|
|
if (this.params[AscFormat.Param_type_linDir] === AscFormat.ParameterVal_linearDirection_fromR) {
|
|
result.offX = shape.x + shape.width / 2 - bounds.l + sibSp / 2;
|
|
} else {
|
|
result.offX = shape.x + shape.width / 2 - bounds.r - sibSp / 2;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
HierarchyChildAlgorithm.prototype.putShapesToShapeContainer = function (isCalculateScaleCoefficient) {
|
|
const childs = this.getMainChilds();
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficient);
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
shapeContainer.push(childs[i].getShape(isCalculateScaleCoefficient));
|
|
}
|
|
}
|
|
HierarchyChildAlgorithm.prototype.calculateVerticalHierarchyVerticalShapePositions = function (isCalculateScaleCoefficient, fromTop) {
|
|
const childs = fromTop ? this.getMainChilds() : this.getMainChilds().slice().reverse();
|
|
const parentNode = this.parentNode;
|
|
const sibSp = parentNode.getConstr(AscFormat.Constr_type_sibSp, !isCalculateScaleCoefficient);
|
|
const commonBounds = this.getCommonChildBounds(isCalculateScaleCoefficient);
|
|
const firstShape = childs[0].getShape(isCalculateScaleCoefficient);
|
|
const firstBounds = childs[0].algorithm.getBounds(isCalculateScaleCoefficient);
|
|
|
|
const firstChildOffsets = this.getChildAlignOffsets(commonBounds, firstBounds, this.params[AscFormat.Param_type_chAlign]);
|
|
firstShape.moveTo(firstChildOffsets.offX, firstChildOffsets.offY);
|
|
|
|
let offY = firstBounds.b - firstBounds.t + sibSp;
|
|
this.setLevelBounds({l: firstShape.x, t: firstShape.y, b: firstShape.y + firstShape.height, r: firstShape.x + firstShape.width});
|
|
this.updateLevelPositions(childs[0].algorithm);
|
|
let previousShape = firstShape;
|
|
let previousDesHeight = firstBounds.b - firstBounds.t;
|
|
for (let i = 1; i < childs.length; i += 1) {
|
|
const node = childs[i];
|
|
const shape = node.getShape(isCalculateScaleCoefficient);
|
|
const bounds = node.algorithm.getBounds(isCalculateScaleCoefficient);
|
|
const childOffsets = this.getChildAlignOffsets(commonBounds, bounds, this.params[AscFormat.Param_type_chAlign]);
|
|
const offY = previousShape.y + previousDesHeight + sibSp - shape.y;
|
|
shape.moveTo(childOffsets.offX, offY + childOffsets.offY);
|
|
this.setLevelBounds({l: shape.x, t: shape.y, b: shape.y + shape.height, r: shape.x + shape.width});
|
|
this.updateLevelPositions(node.algorithm);
|
|
previousShape = shape;
|
|
previousDesHeight = bounds.b - bounds.t;
|
|
}
|
|
};
|
|
HierarchyChildAlgorithm.prototype.calculateHorizontalHierarchyVerticalShapePositions = function (isCalculateScaleCoefficient, fromTop) {
|
|
const childs = fromTop ? this.getMainChilds() : this.getMainChilds().slice().reverse();
|
|
const commonBounds = this.getCommonChildBounds(isCalculateScaleCoefficient);
|
|
const firstNode = childs[0];
|
|
const firstShape = firstNode.getShape(isCalculateScaleCoefficient);
|
|
const firstBounds = firstNode.algorithm.getBounds(isCalculateScaleCoefficient);
|
|
const firstChildOffsets = this.getChildAlignOffsets(commonBounds, firstBounds, this.params[AscFormat.Param_type_chAlign]);
|
|
firstShape.moveTo(firstChildOffsets.offX, firstChildOffsets.offY);
|
|
|
|
this.updateLevelPositions(firstNode.algorithm);
|
|
let previousShape = firstShape;
|
|
this.setLevelBounds({l: firstShape.x, r: firstShape.x + firstShape.width, t: firstShape.y, b: firstShape.y + firstShape.height});
|
|
for (let i = 1; i < childs.length; i += 1) {
|
|
const node = childs[i];
|
|
const shape = node.getShape(isCalculateScaleCoefficient);
|
|
const bounds = node.algorithm.getBounds(isCalculateScaleCoefficient);
|
|
const offY = previousShape.y + previousShape.height - shape.y;
|
|
const childOffsets = this.getChildAlignOffsets(commonBounds, bounds, this.params[AscFormat.Param_type_chAlign]);
|
|
shape.moveTo(childOffsets.offX, offY + childOffsets.offY);
|
|
const sibSp = this.getVerticalSibSp(node, isCalculateScaleCoefficient);
|
|
shape.moveTo(0, sibSp);
|
|
this.updateLevelPositions(node.algorithm);
|
|
this.setLevelBounds({l: shape.x, r: shape.x + shape.width, t: shape.y, b: shape.y + shape.height});
|
|
previousShape = shape;
|
|
}
|
|
};
|
|
HierarchyChildAlgorithm.prototype.setSibLevelBounds = function () {
|
|
|
|
};
|
|
HierarchyChildAlgorithm.prototype.calculateVerticalHierarchyHorizontalShapePositions = function (isCalculateScaleCoefficient, fromLeft) {
|
|
const childs = this.getMainChilds();
|
|
const commonBounds = this.getCommonChildBounds(isCalculateScaleCoefficient);
|
|
const firstNode = childs[0];
|
|
const firstShape = firstNode.getShape(isCalculateScaleCoefficient);
|
|
const firstBounds = firstNode.algorithm.getBounds(isCalculateScaleCoefficient);
|
|
const firstAlignOffsets = this.getChildAlignOffsets(commonBounds, firstBounds, this.params[AscFormat.Param_type_chAlign]);
|
|
firstNode.moveTo(firstAlignOffsets.offX, firstAlignOffsets.offY, isCalculateScaleCoefficient);
|
|
this.updateLevelPositions(childs[0].algorithm);
|
|
let previousShape = firstShape;
|
|
this.setLevelBounds({l: firstShape.x, t: firstShape.y, b: firstShape.y + firstShape.height, r: firstShape.x + firstShape.width});
|
|
for (let i = 1; i < childs.length; i += 1) {
|
|
const node = childs[i];
|
|
const shape = node.getShape(isCalculateScaleCoefficient);
|
|
|
|
let offX;
|
|
if (fromLeft) {
|
|
offX = previousShape.x + previousShape.width - shape.x;
|
|
} else {
|
|
offX = previousShape.x - (shape.x + shape.width);
|
|
}
|
|
const bounds = node.algorithm.getBounds(isCalculateScaleCoefficient);
|
|
const alignOffsets = this.getChildAlignOffsets(commonBounds, bounds, this.params[AscFormat.Param_type_chAlign]);
|
|
node.moveTo(offX + alignOffsets.offX, alignOffsets.offY, isCalculateScaleCoefficient);
|
|
const offset = this.getHorizontalSibSp(node, isCalculateScaleCoefficient, fromLeft);
|
|
node.moveTo(offset, 0, isCalculateScaleCoefficient);
|
|
previousShape = shape;
|
|
this.updateLevelPositions(node.algorithm);
|
|
this.setLevelBounds({l: shape.x, t: shape.y, b: shape.y + shape.height, r: shape.x + shape.width});
|
|
}
|
|
};
|
|
HierarchyChildAlgorithm.prototype.calculateHorizontalHierarchyHorizontalShapePositions = function (isCalculateScaleCoefficient, fromRight) {
|
|
const childs = fromRight ? this.getMainChilds() : this.getMainChilds().slice().reverse();
|
|
const parentNode = this.parentNode;
|
|
const sibSp = parentNode.getConstr(AscFormat.Constr_type_sibSp, !isCalculateScaleCoefficient);
|
|
const commonBounds = this.getCommonChildBounds(isCalculateScaleCoefficient);
|
|
const firstShape = childs[0].getShape(isCalculateScaleCoefficient);
|
|
const firstBounds = childs[0].algorithm.getBounds(isCalculateScaleCoefficient);
|
|
|
|
const firstChildOffsets = this.getChildAlignOffsets(commonBounds, firstBounds, this.params[AscFormat.Param_type_chAlign]);
|
|
firstShape.moveTo(firstChildOffsets.offX, firstChildOffsets.offY);
|
|
|
|
this.setLevelBounds({l: firstShape.x, t: firstShape.y, b: firstShape.y + firstShape.height, r: firstShape.x + firstShape.width});
|
|
this.updateLevelPositions(childs[0].algorithm);
|
|
let previousShape = firstShape;
|
|
let previousWidth = firstBounds.r - firstBounds.l;
|
|
for (let i = 1; i < childs.length; i += 1) {
|
|
const node = childs[i];
|
|
const shape = node.getShape(isCalculateScaleCoefficient);
|
|
const bounds = node.algorithm.getBounds(isCalculateScaleCoefficient);
|
|
const childOffsets = this.getChildAlignOffsets(commonBounds, bounds, this.params[AscFormat.Param_type_chAlign]);
|
|
const offX = previousShape.x + previousWidth + sibSp;
|
|
shape.moveTo(childOffsets.offX + offX, childOffsets.offY);
|
|
this.setLevelBounds({l: shape.x, t: shape.y, b: shape.y + shape.height, r: shape.x + shape.width});
|
|
this.updateLevelPositions(node.algorithm);
|
|
previousShape = shape;
|
|
previousWidth = bounds.r - bounds.l;
|
|
}
|
|
};
|
|
HierarchyChildAlgorithm.prototype.getShapeContainer = function (isCalculateScaleCoefficient) {
|
|
if (isCalculateScaleCoefficient) {
|
|
if (this.coefficientShapeContainer === null) {
|
|
this.coefficientShapeContainer = new HierarchyChildContainer();
|
|
}
|
|
return this.coefficientShapeContainer;
|
|
}
|
|
if (this.shapeContainer === null) {
|
|
this.shapeContainer = new HierarchyChildContainer();
|
|
}
|
|
return this.shapeContainer;
|
|
}
|
|
HierarchyChildAlgorithm.prototype.calculateShapePositionsHorizontalHang = function (isCalculateScaleCoefficient, fromRight) {
|
|
const childs = this.getMainChilds();
|
|
const sibSp = this.parentNode.getConstr(AscFormat.Constr_type_sibSp, !isCalculateScaleCoefficient);
|
|
|
|
const topRow = [];
|
|
const bottomRow = [];
|
|
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const child = childs[i];
|
|
if (i % 2 === 0) {
|
|
topRow.push(child);
|
|
} else {
|
|
bottomRow.push(child);
|
|
}
|
|
}
|
|
|
|
const topCalcBounds = this.applyMainChildAlign(topRow, isCalculateScaleCoefficient);
|
|
const bottomCalcBounds = this.applyMainChildAlign(bottomRow, isCalculateScaleCoefficient);
|
|
|
|
let bottomOffY = 0;
|
|
if (topCalcBounds.commonBounds && bottomCalcBounds.commonBounds) {
|
|
bottomOffY = topCalcBounds.commonBounds.b - bottomCalcBounds.commonBounds.t + sibSp;
|
|
}
|
|
|
|
let offX = 0;
|
|
for (let i = 0; i < topRow.length; i += 1) {
|
|
const topNode = topRow[i];
|
|
const topShape = topNode.getShape(isCalculateScaleCoefficient);
|
|
const topBounds = topCalcBounds.bounds[i];
|
|
|
|
const commonChildBounds = Object.assign({}, topBounds);
|
|
|
|
const bottomNode = bottomRow[i];
|
|
let bottomShape;
|
|
if (bottomNode) {
|
|
bottomShape = bottomNode.getShape(isCalculateScaleCoefficient);
|
|
const bottomBounds = bottomCalcBounds.bounds[i];
|
|
checkBounds(commonChildBounds, bottomBounds);
|
|
const bottomOffsets = this.getChildAlignOffsets(commonChildBounds, bottomBounds, this.params[AscFormat.Param_type_chAlign]);
|
|
bottomNode.moveTo(bottomOffsets.offX, bottomOffsets.offY, isCalculateScaleCoefficient);
|
|
if (fromRight) {
|
|
bottomShape.moveTo(offX - (bottomShape.x + bottomShape.width), bottomOffY - bottomShape.y);
|
|
} else {
|
|
bottomShape.moveTo(offX - bottomShape.x, bottomOffY - bottomShape.y);
|
|
}
|
|
this.updateLevelPositions(bottomNode.algorithm);
|
|
this.setLevelBounds({
|
|
l: bottomShape.x,
|
|
r: bottomShape.x + bottomShape.width,
|
|
t: bottomShape.y,
|
|
b: bottomShape.y + bottomShape.height
|
|
});
|
|
}
|
|
const topOffsets = this.getChildAlignOffsets(commonChildBounds, topBounds, this.params[AscFormat.Param_type_chAlign]);
|
|
topNode.moveTo(topOffsets.offX, topOffsets.offY, isCalculateScaleCoefficient);
|
|
if (fromRight) {
|
|
topShape.moveTo(offX - (topShape.x + topShape.width), 0);
|
|
} else {
|
|
topShape.moveTo(offX - topShape.x, 0);
|
|
}
|
|
this.updateLevelPositions(topNode.algorithm);
|
|
this.setLevelBounds({
|
|
l: topShape.x,
|
|
r: topShape.x + topShape.width,
|
|
t: topShape.y,
|
|
b: topShape.y + topShape.height
|
|
});
|
|
if (topShape && bottomShape) {
|
|
const bottomBounds = bottomCalcBounds.bounds[i];
|
|
if (fromRight) {
|
|
const topLeft = topShape.x + topShape.width - (topBounds.r - topBounds.l);
|
|
const bottomLeft = bottomShape.x + bottomShape.width - (bottomBounds.r - bottomBounds.l);
|
|
offX = Math.min(topLeft, bottomLeft) - sibSp;
|
|
} else {
|
|
const topRight = topShape.x + (topBounds.r - topBounds.l);
|
|
const bottomRight = bottomShape.x + (bottomBounds.r - bottomBounds.l);
|
|
offX = Math.max(topRight, bottomRight) + sibSp;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
HierarchyChildAlgorithm.prototype.getChildAlignOffsets = function (commonBounds, shapeBounds, childAlign) {
|
|
const offsets = {offX: 0, offY: 0};
|
|
|
|
switch (childAlign) {
|
|
case AscFormat.ParameterVal_childAlignment_l:
|
|
offsets.offX = commonBounds.l - shapeBounds.l;
|
|
break;
|
|
case AscFormat.ParameterVal_childAlignment_t:
|
|
offsets.offY = commonBounds.t - shapeBounds.t;
|
|
break;
|
|
case AscFormat.ParameterVal_childAlignment_r:
|
|
offsets.offX = commonBounds.r - shapeBounds.r;
|
|
break;
|
|
case AscFormat.ParameterVal_childAlignment_b:
|
|
offsets.offY = commonBounds.b - shapeBounds.b;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return offsets;
|
|
};
|
|
HierarchyChildAlgorithm.prototype.calculateShapePositionsVerticalHangFromTop = function (isCalculateScaleCoefficient, fromRight) {
|
|
const childs = this.getMainChilds();
|
|
|
|
let leftCol = [];
|
|
let rightCol = [];
|
|
const sibSp = this.parentNode.getConstr(AscFormat.Constr_type_sibSp, !isCalculateScaleCoefficient);
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const child = childs[i];
|
|
if (i % 2 === 0) {
|
|
leftCol.push(child);
|
|
} else {
|
|
rightCol.push(child);
|
|
}
|
|
}
|
|
if (fromRight) {
|
|
const tempCol = leftCol;
|
|
leftCol = rightCol;
|
|
rightCol = tempCol;
|
|
}
|
|
const leftCalcBounds = this.applyMainChildAlign(leftCol, isCalculateScaleCoefficient);
|
|
const rightCalcBounds = this.applyMainChildAlign(rightCol, isCalculateScaleCoefficient);
|
|
let rightOffX = 0;
|
|
if (leftCalcBounds.commonBounds && rightCalcBounds.commonBounds) {
|
|
rightOffX = leftCalcBounds.commonBounds.r - rightCalcBounds.commonBounds.l + sibSp;
|
|
}
|
|
let offY = 0;
|
|
const columnLength = Math.ceil(childs.length / 2);
|
|
for (let i = 0; i < columnLength; i += 1) {
|
|
const leftNode = leftCol[i];
|
|
if (leftNode) {
|
|
const leftShape = leftNode.getShape(isCalculateScaleCoefficient);
|
|
leftShape.moveTo(0, offY);
|
|
this.updateLevelPositions(leftNode.algorithm);
|
|
this.setLevelBounds({l: leftShape.x, r: leftShape.x + leftShape.width, t: leftShape.y, b: leftShape.y + leftShape.height});
|
|
}
|
|
const rightNode = rightCol[i];
|
|
if (rightNode) {
|
|
const rightShape = rightNode.getShape(isCalculateScaleCoefficient);
|
|
rightShape.moveTo(rightOffX, offY);
|
|
this.updateLevelPositions(rightNode.algorithm);
|
|
this.setLevelBounds({l: rightShape.x, r: rightShape.x + rightShape.width, t: rightShape.y, b: rightShape.y + rightShape.height});
|
|
}
|
|
const leftBounds = leftCalcBounds.bounds[i];
|
|
const rightBounds = rightCalcBounds.bounds[i];
|
|
if (leftBounds && rightBounds) {
|
|
const commonChildBounds = Object.assign({}, leftBounds);
|
|
checkBounds(commonChildBounds, rightBounds);
|
|
/* const leftOffsets = this.getChildAlignOffsets(commonChildBounds, leftBounds, this.params[AscFormat.Param_type_chAlign]);
|
|
const rightOffsets = this.getChildAlignOffsets(commonChildBounds, rightBounds, this.params[AscFormat.Param_type_chAlign]);
|
|
leftNode.moveTo(leftOffsets.offX, leftOffsets.offY, isCalculateScaleCoefficient);
|
|
rightNode.moveTo(rightOffsets.offX, rightOffsets.offY, isCalculateScaleCoefficient);*/
|
|
offY += Math.max(leftBounds.b - leftBounds.t, rightBounds.b - rightBounds.t) + sibSp;
|
|
}
|
|
}
|
|
};
|
|
HierarchyChildAlgorithm.prototype.applyMainChildAlign = function (childs, isCalculateScaleCoefficient) {
|
|
const allBounds = [];
|
|
const result = {
|
|
commonBounds: null,
|
|
bounds: allBounds
|
|
};
|
|
if (!childs.length) {
|
|
return result;
|
|
}
|
|
const commonBounds = {};
|
|
const firstChild = childs[0];
|
|
const firstBounds = firstChild.algorithm.getBounds(isCalculateScaleCoefficient);
|
|
allBounds.push(firstBounds);
|
|
Object.assign(commonBounds, firstBounds);
|
|
for (let i = 1; i < childs.length; i += 1) {
|
|
const child = childs[i];
|
|
const bounds = child.algorithm.getBounds(isCalculateScaleCoefficient);
|
|
checkBounds(commonBounds, bounds);
|
|
allBounds.push(bounds);
|
|
}
|
|
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const child = childs[i];
|
|
const mainOffsets = this.getChildAlignOffsets(commonBounds, allBounds[i], this.params[AscFormat.Param_type_chAlign]);
|
|
const secondaryOffsets = this.getChildAlignOffsets(commonBounds, allBounds[i], this.params[AscFormat.Param_type_secChAlign]);
|
|
child.moveTo(mainOffsets.offX + secondaryOffsets.offX, mainOffsets.offY + secondaryOffsets.offY, isCalculateScaleCoefficient);
|
|
}
|
|
return {commonBounds: commonBounds, bounds: allBounds};
|
|
};
|
|
|
|
HierarchyChildAlgorithm.prototype.calculateShapePositionsVerticalHangFromRight = function (isCalculateScaleCoefficient) {
|
|
|
|
};
|
|
HierarchyChildAlgorithm.prototype._calculateShapePositions = function (isCalculateScaleCoefficient) {
|
|
const childs = this.getMainChilds();
|
|
if (!childs.length) {
|
|
return;
|
|
}
|
|
if (this.isHang()) {
|
|
switch (this.params[AscFormat.Param_type_secLinDir]) {
|
|
case AscFormat.ParameterVal_linearDirection_fromT:
|
|
const fromRight = this.params[AscFormat.Param_type_linDir] === AscFormat.ParameterVal_linearDirection_fromR;
|
|
this.calculateShapePositionsVerticalHangFromTop(isCalculateScaleCoefficient, fromRight);
|
|
break;
|
|
case AscFormat.ParameterVal_linearDirection_fromL:
|
|
this.calculateShapePositionsHorizontalHang(isCalculateScaleCoefficient, false);
|
|
break;
|
|
case AscFormat.ParameterVal_linearDirection_fromR:
|
|
this.calculateShapePositionsHorizontalHang(isCalculateScaleCoefficient, true);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
if (this.isHorizontalHierarchy()) {
|
|
switch (this.params[AscFormat.Param_type_linDir]) {
|
|
case AscFormat.ParameterVal_linearDirection_fromB:
|
|
this.calculateHorizontalHierarchyVerticalShapePositions(isCalculateScaleCoefficient, false);
|
|
break;
|
|
case AscFormat.ParameterVal_linearDirection_fromT:
|
|
this.calculateHorizontalHierarchyVerticalShapePositions(isCalculateScaleCoefficient, true);
|
|
break;
|
|
case AscFormat.ParameterVal_linearDirection_fromR:
|
|
this.calculateHorizontalHierarchyHorizontalShapePositions(isCalculateScaleCoefficient, false);
|
|
break;
|
|
case AscFormat.ParameterVal_linearDirection_fromL:
|
|
this.calculateHorizontalHierarchyHorizontalShapePositions(isCalculateScaleCoefficient, true);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else {
|
|
switch (this.params[AscFormat.Param_type_linDir]) {
|
|
case AscFormat.ParameterVal_linearDirection_fromB:
|
|
this.calculateVerticalHierarchyVerticalShapePositions(isCalculateScaleCoefficient, false);
|
|
break;
|
|
case AscFormat.ParameterVal_linearDirection_fromT:
|
|
this.calculateVerticalHierarchyVerticalShapePositions(isCalculateScaleCoefficient, true);
|
|
break;
|
|
case AscFormat.ParameterVal_linearDirection_fromR:
|
|
this.calculateVerticalHierarchyHorizontalShapePositions(isCalculateScaleCoefficient, false);
|
|
break;
|
|
case AscFormat.ParameterVal_linearDirection_fromL:
|
|
this.calculateVerticalHierarchyHorizontalShapePositions(isCalculateScaleCoefficient, true);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
HierarchyChildAlgorithm.prototype.getChildBounds = function (isCalculateScaleCoefficients) {
|
|
const childs = this.getMainChilds();
|
|
|
|
if (!childs.length) {
|
|
return;
|
|
}
|
|
|
|
const firstChild = childs[0];
|
|
const firstRoot = firstChild.algorithm.getRoot();
|
|
const firstShape = firstRoot.getShape(isCalculateScaleCoefficients);
|
|
const bounds = firstShape.getBounds();
|
|
|
|
for (let i = 1; i < childs.length; i += 1) {
|
|
const child = childs[i];
|
|
const root = child.algorithm.getRoot();
|
|
const shape = root.getShape(isCalculateScaleCoefficients);
|
|
shape.checkBounds(bounds);
|
|
}
|
|
return bounds;
|
|
};
|
|
HierarchyChildAlgorithm.prototype.getHangStructBounds = function (isCalculateScaleCoefficients) {
|
|
const childs = this.getMainChilds();
|
|
if (!childs.length) {
|
|
return;
|
|
}
|
|
const firstChild = childs[0];
|
|
const bounds = firstChild.algorithm.getBounds(isCalculateScaleCoefficients);
|
|
for (let i = 2; i < childs.length; i += 2) {
|
|
const child = childs[i];
|
|
child.algorithm.getBounds(isCalculateScaleCoefficients, bounds);
|
|
}
|
|
return bounds;
|
|
};
|
|
function HierarchyRootAlgorithm() {
|
|
HierarchyAlgorithm.call(this);
|
|
}
|
|
AscFormat.InitClassWithoutType(HierarchyRootAlgorithm, HierarchyAlgorithm);
|
|
HierarchyRootAlgorithm.prototype.isHorizontalHierarchy = function () {
|
|
switch (this.params[AscFormat.Param_type_hierAlign]) {
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lB:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lCtrDes:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lT:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rB:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rCtrDes:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rT:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
};
|
|
HierarchyRootAlgorithm.prototype.putShapesToShapeContainer = function (isCalculateScaleCoefficient) {
|
|
const rootNode = this.getRoot();
|
|
const asstNode = this.getAsstNode();
|
|
const nonAsstNode = this.getNonAsstNode();
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficient);
|
|
shapeContainer.push(rootNode.getShape(isCalculateScaleCoefficient));
|
|
if (asstNode && asstNode.algorithm.getMainChilds().length) {
|
|
shapeContainer.push(asstNode.getShape(isCalculateScaleCoefficient));
|
|
}
|
|
if (nonAsstNode.algorithm.getMainChilds().length) {
|
|
shapeContainer.push(nonAsstNode.getShape(isCalculateScaleCoefficient));
|
|
}
|
|
};
|
|
HierarchyRootAlgorithm.prototype.getBounds = function (isCalculateScaleCoefficients, bounds) {
|
|
const childs = this.getMainChilds();
|
|
const firstChild = childs[0];
|
|
const firstShape = firstChild.getShape(isCalculateScaleCoefficients);
|
|
if (!bounds) {
|
|
bounds = firstShape.getBounds();
|
|
} else {
|
|
firstShape.checkBounds(bounds);
|
|
}
|
|
const asstNode = this.getAsstNode();
|
|
if (asstNode && asstNode.childs.length) {
|
|
const shape = asstNode.getShape(isCalculateScaleCoefficients);
|
|
shape.checkBounds(bounds);
|
|
}
|
|
const nonAsstNode = this.getNonAsstNode();
|
|
if (nonAsstNode.childs.length) {
|
|
const shape = nonAsstNode.getShape(isCalculateScaleCoefficients);
|
|
shape.checkBounds(bounds);
|
|
}
|
|
return bounds;
|
|
};
|
|
HierarchyRootAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createHierarchyRootShadowShape(isCalculateScaleCoefficients);
|
|
};
|
|
HierarchyRootAlgorithm.prototype.getNonAsstNode = function () {
|
|
return this.parentNode.childs[1];
|
|
};
|
|
HierarchyRootAlgorithm.prototype.getAsstNode = function () {
|
|
return this.parentNode.childs[2];
|
|
};
|
|
HierarchyRootAlgorithm.prototype.applyMainTopAlign = function (isCalculateScaleCoefficients) {
|
|
const root = this.getRoot();
|
|
if (!root) {
|
|
return;
|
|
}
|
|
const parentNode = this.parentNode;
|
|
const space = parentNode.getConstr(AscFormat.Constr_type_sp, !isCalculateScaleCoefficients);
|
|
const rootShape = root.getShape(isCalculateScaleCoefficients);
|
|
let offY = rootShape.y + rootShape.height + space;
|
|
|
|
const asstNode = this.getAsstNode();
|
|
if (asstNode && asstNode.algorithm.getMainChilds().length) {
|
|
const asstShape = asstNode.getShape(isCalculateScaleCoefficients);
|
|
asstShape.moveTo(/*todo: asstOffset*/0, offY - asstShape.y);
|
|
offY = asstShape.y + asstShape.height + space;
|
|
}
|
|
|
|
const nonAsstNode = this.getNonAsstNode();
|
|
if (nonAsstNode.algorithm.getMainChilds().length) {
|
|
const nonAsstShape = nonAsstNode.getShape(isCalculateScaleCoefficients);
|
|
nonAsstShape.moveTo(/*todo: nonAsstOffset*/0, offY - nonAsstShape.y);
|
|
}
|
|
};
|
|
|
|
HierarchyRootAlgorithm.prototype.applyMainBottomAlign = function (isCalculateScaleCoefficients) {
|
|
const rootNode = this.getRoot();
|
|
if (!rootNode) {
|
|
return;
|
|
}
|
|
const parentNode = this.parentNode;
|
|
const space = parentNode.getConstr(AscFormat.Constr_type_sp, !isCalculateScaleCoefficients);
|
|
|
|
let offY = 0;
|
|
const nonAsstNode = this.getNonAsstNode();
|
|
if (nonAsstNode.algorithm.getMainChilds().length) {
|
|
const nonAsstShape = nonAsstNode.getShape(isCalculateScaleCoefficients);
|
|
offY += nonAsstShape.y + nonAsstShape.height + space;
|
|
}
|
|
|
|
|
|
const asstNode = this.getAsstNode();
|
|
if (asstNode && asstNode.algorithm.getMainChilds().length) {
|
|
const asstShape = asstNode.getShape(isCalculateScaleCoefficients);
|
|
asstShape.moveTo(/*todo: asstOffset*/0, offY - asstShape.y);
|
|
offY = asstShape.y + asstShape.height + space;
|
|
}
|
|
|
|
const rootShape = rootNode.getShape(isCalculateScaleCoefficients);
|
|
rootShape.moveTo(0, offY - rootShape.y);
|
|
};
|
|
|
|
HierarchyRootAlgorithm.prototype.applyMainLeftAlign = function (isCalculateScaleCoefficients) {
|
|
const rootNode = this.getRoot();
|
|
if (!rootNode) {
|
|
return;
|
|
}
|
|
const space = this.parentNode.getConstr(AscFormat.Constr_type_sp, !isCalculateScaleCoefficients);
|
|
const rootShape = rootNode.getShape(isCalculateScaleCoefficients);
|
|
const bounds = rootShape.getBounds();
|
|
let offX = bounds.r + space;
|
|
|
|
const asstNode = this.getAsstNode();
|
|
if (asstNode && asstNode.algorithm.getMainChilds().length) {
|
|
const asstShape = asstNode.getShape(isCalculateScaleCoefficients);
|
|
asstShape.moveTo(offX - asstShape.x, 0);
|
|
offX = asstShape.x + asstShape.width + space;
|
|
}
|
|
|
|
const nonAsstNode = this.getNonAsstNode();
|
|
if (nonAsstNode.algorithm.getMainChilds().length) {
|
|
const nonAsstShape = nonAsstNode.getShape(isCalculateScaleCoefficients);
|
|
nonAsstShape.moveTo(offX - nonAsstShape.x, 0);
|
|
}
|
|
};
|
|
|
|
HierarchyRootAlgorithm.prototype.applyMainRightAlign = function (isCalculateScaleCoefficients) {
|
|
const rootNode = this.getRoot();
|
|
if (!rootNode) {
|
|
return;
|
|
}
|
|
const space = this.parentNode.getConstr(AscFormat.Constr_type_sp, !isCalculateScaleCoefficients);
|
|
let offX = 0;
|
|
|
|
const nonAsstNode = this.getNonAsstNode();
|
|
if (nonAsstNode.algorithm.getMainChilds().length) {
|
|
const nonAsstShape = nonAsstNode.getShape(isCalculateScaleCoefficients);
|
|
offX = nonAsstShape.x + nonAsstShape.width + space;
|
|
}
|
|
|
|
const asstNode = this.getAsstNode();
|
|
if (asstNode && asstNode.algorithm.getMainChilds().length) {
|
|
const asstShape = asstNode.getShape(isCalculateScaleCoefficients);
|
|
asstShape.moveTo(offX - asstShape.x, 0);
|
|
offX = asstShape.x + asstShape.width + space;
|
|
}
|
|
|
|
const rootShape = rootNode.getShape(isCalculateScaleCoefficients);
|
|
const bounds = rootShape.getBounds();
|
|
rootShape.moveTo(offX - bounds.l, 0);
|
|
};
|
|
|
|
HierarchyRootAlgorithm.prototype.applyMainAlign = function (isCalculateScaleCoefficients) {
|
|
switch (this.params[AscFormat.Param_type_hierAlign]) {
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bCtrDes:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bL:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bR:
|
|
this.applyMainBottomAlign(isCalculateScaleCoefficients);
|
|
break;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lB:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lT:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lCtrDes:
|
|
this.applyMainLeftAlign(isCalculateScaleCoefficients);
|
|
break;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rB:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rT:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rCtrDes:
|
|
this.applyMainRightAlign(isCalculateScaleCoefficients);
|
|
break;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tCtrDes:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tL:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tR:
|
|
this.applyMainTopAlign(isCalculateScaleCoefficients);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
};
|
|
HierarchyRootAlgorithm.prototype.applySecondaryAlign = function (isCalculateScaleCoefficients) {
|
|
const asstNode = this.getAsstNode();
|
|
const nonAsstNode = this.getNonAsstNode();
|
|
|
|
if (asstNode) {
|
|
this.applySecondaryAlignForChild(isCalculateScaleCoefficients, asstNode);
|
|
}
|
|
this.applySecondaryAlignForChild(isCalculateScaleCoefficients, nonAsstNode);
|
|
};
|
|
HierarchyRootAlgorithm.prototype.applySecondaryAlignForChild = function (isCalculateScaleCoefficients, child) {
|
|
const rootNode = this.getRoot();
|
|
const rootShape = rootNode.getShape(isCalculateScaleCoefficients);
|
|
const childShape = child.getShape(isCalculateScaleCoefficients);
|
|
if (child.algorithm.isHang()) {
|
|
const offsets = child.algorithm.getRootCenteringOffset(rootShape, isCalculateScaleCoefficients);
|
|
childShape.moveTo(offsets.offX, offsets.offY);
|
|
return;
|
|
}
|
|
|
|
const appendChildOffset = this.getOffsetAlign(isCalculateScaleCoefficients, child);
|
|
switch (this.params[AscFormat.Param_type_hierAlign]) {
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rCtrCh: {
|
|
const childBounds = child.algorithm.getChildBounds(isCalculateScaleCoefficients);
|
|
if (childBounds) {
|
|
childShape.moveTo(0, (rootShape.y + rootShape.height / 2) - (childBounds.t + (childBounds.b - childBounds.t) / 2) + appendChildOffset);
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tCtrCh: {
|
|
const childBounds = child.algorithm.getChildBounds(isCalculateScaleCoefficients);
|
|
if (childBounds) {
|
|
childShape.moveTo((rootShape.x + rootShape.width / 2) - (childBounds.l + (childBounds.r - childBounds.l) / 2) + appendChildOffset, 0);
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lCtrDes:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rCtrDes:
|
|
childShape.moveTo(0, rootShape.y + rootShape.height / 2 - (childShape.y + childShape.height / 2) + appendChildOffset);
|
|
break;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bCtrDes:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tCtrDes:
|
|
childShape.moveTo(rootShape.x + rootShape.width / 2 - (childShape.x + childShape.width / 2) + appendChildOffset, 0);
|
|
break;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bL:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tL:
|
|
childShape.moveTo(rootShape.x - childShape.x + appendChildOffset, 0);
|
|
break;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bR:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tR:
|
|
childShape.moveTo((rootShape.x + rootShape.width) - (childShape.x + childShape.width) + appendChildOffset, 0);
|
|
break;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lB:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rB:
|
|
childShape.moveTo(0, (rootShape.y + rootShape.height) - (childShape.y + childShape.height) + appendChildOffset);
|
|
break;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lT:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rT:
|
|
childShape.moveTo(0, rootShape.y - childShape.y + appendChildOffset);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
};
|
|
|
|
HierarchyRootAlgorithm.prototype.getOffsetAlign = function (isCalculateScaleCoefficients, child) {
|
|
const offsetFactor = child.algorithm.isHang() ? 0 : this.parentNode.getConstr(AscFormat.Constr_type_alignOff, !isCalculateScaleCoefficients);
|
|
if (!offsetFactor) {
|
|
return 0;
|
|
}
|
|
const rootNode = this.getRoot();
|
|
const rootShape = rootNode.getShape(isCalculateScaleCoefficients);
|
|
switch (this.params[AscFormat.Param_type_hierAlign]) {
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tCtrCh:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bCtrDes:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lCtrDes:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rCtrDes:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tCtrDes:
|
|
return 0;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bL:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tL:
|
|
return rootShape.width * offsetFactor;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_bR:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_tR:
|
|
return -rootShape.width * offsetFactor;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lB:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rB:
|
|
return -rootShape.height * offsetFactor;
|
|
case AscFormat.ParameterVal_hierarchyAlignment_lT:
|
|
case AscFormat.ParameterVal_hierarchyAlignment_rT:
|
|
return rootShape.height * offsetFactor;
|
|
default:
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
HierarchyRootAlgorithm.prototype.initParams = function (params) {
|
|
HierarchyAlgorithm.prototype.initParams.call(this, params);
|
|
if (this.params[AscFormat.Param_type_off] === undefined) {
|
|
this.params[AscFormat.Param_type_off] = AscFormat.ParameterVal_offset_ctr;
|
|
}
|
|
if (this.params[AscFormat.Param_type_hierAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_hierAlign] = AscFormat.ParameterVal_hierarchyAlignment_tCtrCh;
|
|
}
|
|
}
|
|
HierarchyRootAlgorithm.prototype.getRoot = function () {
|
|
const childs = this.getMainChilds();
|
|
if (childs.length) {
|
|
return childs[0];
|
|
}
|
|
};
|
|
HierarchyRootAlgorithm.prototype.getShapeContainer = function (isCalculateScaleCoefficients) {
|
|
if (isCalculateScaleCoefficients) {
|
|
if (this.coefficientShapeContainer === null) {
|
|
this.coefficientShapeContainer = new HierarchyRootContainer();
|
|
}
|
|
return this.coefficientShapeContainer;
|
|
} else {
|
|
if (this.shapeContainer === null) {
|
|
this.shapeContainer = new HierarchyRootContainer();
|
|
}
|
|
return this.shapeContainer;
|
|
}
|
|
};
|
|
HierarchyRootAlgorithm.prototype._collectHierarchyPositions = function (isVertical) {
|
|
const asstNode = this.getAsstNode();
|
|
if (asstNode) {
|
|
const asstAlgorithm = asstNode.algorithm;
|
|
for (let i = 0; i < asstAlgorithm.levelPositions.length; i += 1) {
|
|
this.setLevelBounds(asstAlgorithm.levelPositions[i]);
|
|
}
|
|
}
|
|
const nonAsstNode = this.getNonAsstNode();
|
|
const nonAsstAlgorithm = nonAsstNode.algorithm;
|
|
for (let i = 0; i < nonAsstAlgorithm.levelPositions.length; i += 1) {
|
|
this.setLevelBounds(nonAsstAlgorithm.levelPositions[i]);
|
|
}
|
|
};
|
|
HierarchyRootAlgorithm.prototype.collectHierarchyPositions = function () {
|
|
this._collectHierarchyPositions();
|
|
};
|
|
HierarchyRootAlgorithm.prototype._calculateShapePositions = function (isCalculateScaleCoefficients) {
|
|
this.applyMainAlign(isCalculateScaleCoefficients);
|
|
this.applySecondaryAlign(isCalculateScaleCoefficients);
|
|
};
|
|
|
|
|
|
function PyramidAlgorithm() {
|
|
PositionAlgorithm.call(this);
|
|
this.calcValues = {
|
|
defaultBlockHeight: 0
|
|
};
|
|
}
|
|
AscFormat.InitClassWithoutType(PyramidAlgorithm, PositionAlgorithm);
|
|
PyramidAlgorithm.prototype.initParams = function (params) {
|
|
PositionAlgorithm.prototype.initParams.call(this, params);
|
|
if (this.params[AscFormat.Param_type_pyraAcctPos] === undefined) {
|
|
this.params[AscFormat.Param_type_pyraAcctPos] = AscFormat.ParameterVal_pyramidAccentPosition_aft;
|
|
}
|
|
if (this.params[AscFormat.Param_type_off] === undefined) {
|
|
this.params[AscFormat.Param_type_off] = AscFormat.ParameterVal_offset_ctr;
|
|
}
|
|
|
|
}
|
|
PyramidAlgorithm.prototype.calcScaleCoefficients = function () {
|
|
const parentHeight = this.parentNode.getConstr(AscFormat.Constr_type_h, false);
|
|
const childs = this.parentNode.childs;
|
|
const defaultBlockHeight = parentHeight / childs.length;
|
|
let sumHeight = 0;
|
|
for (let i = 0; i < childs.length; i++) {
|
|
const child = this.getPyramidChildren(childs[i]).pyramid;
|
|
const scaleBlockHeight = child.getHeightScale();
|
|
sumHeight += scaleBlockHeight * defaultBlockHeight;
|
|
}
|
|
this.calcValues.defaultBlockHeight = defaultBlockHeight * (parentHeight / sumHeight);
|
|
};
|
|
PyramidAlgorithm.prototype.getTextNodeCoefficients = function (contentNode, textNode) {
|
|
const resultScales = {width: 1, height: 1};
|
|
const contentWidth = contentNode.getConstr(AscFormat.Constr_type_w, true, true);
|
|
const contentHeight = contentNode.getConstr(AscFormat.Constr_type_h, true, true);
|
|
const textWidth = textNode.getConstr(AscFormat.Constr_type_w, true, true);
|
|
const textHeight = textNode.getConstr(AscFormat.Constr_type_h, true, true);
|
|
if (contentWidth && textWidth) {
|
|
resultScales.width = textWidth / contentWidth;
|
|
}
|
|
if (contentHeight && textHeight) {
|
|
resultScales.height = textHeight / contentHeight;
|
|
}
|
|
return resultScales;
|
|
};
|
|
PyramidAlgorithm.prototype.setPyramidParametersForNode = function (child, x, y, height, width, cleanHeight, cleanWidth, adjValue) {
|
|
const shape = child.getShape(false);
|
|
if (shape) {
|
|
if (width < height) {
|
|
adjValue = adjValue * height / cleanWidth;
|
|
}
|
|
shape.height = height;
|
|
shape.width = width;
|
|
shape.x = x;
|
|
shape.y = y;
|
|
shape.cleanParams.height = cleanHeight;
|
|
shape.cleanParams.width = cleanWidth;
|
|
const adjLst = new AscFormat.AdjLst();
|
|
const adj = new AscFormat.Adj();
|
|
adj.setVal(adjValue);
|
|
adj.setIdx(1);
|
|
adjLst.addToLst(0, adj);
|
|
shape.customAdj = adjLst;
|
|
|
|
const textNodes = child.contentNodes[0] && child.contentNodes[0].getTextNodes();
|
|
if (textNodes && textNodes.contentNode === child && textNodes.textNode) {
|
|
const txNode = textNodes.textNode;
|
|
const coefficients = this.getTextNodeCoefficients(child, txNode);
|
|
const textShape = txNode.getShape();
|
|
textShape.height = shape.height * coefficients.height;
|
|
textShape.width = shape.width * coefficients.width;
|
|
textShape.x = shape.x + (shape.width - textShape.width) / 2;
|
|
textShape.y = shape.y + (shape.height - textShape.height) / 2;
|
|
}
|
|
}
|
|
};
|
|
PyramidAlgorithm.prototype.getPyramidChildren = function (node) {
|
|
const pyramid = node.getNamedNode(this.params[AscFormat.Param_type_pyraLvlNode]);
|
|
const acct = node.getNamedNode(this.params[AscFormat.Param_type_pyraAcctBkgdNode]);
|
|
return {
|
|
pyramid: pyramid,
|
|
acct: acct
|
|
};
|
|
};
|
|
PyramidAlgorithm.prototype.isReversedPyramid = function () {
|
|
return this.params[AscFormat.Param_type_linDir] === AscFormat.ParameterVal_linearDirection_fromT;
|
|
};
|
|
PyramidAlgorithm.prototype.getStartDefaultBlockWidth = function () {
|
|
const acctRatio = this.parentNode.getConstr(AscFormat.Constr_type_pyraAcctRatio, true);
|
|
const parentWidth = this.parentNode.getConstr(AscFormat.Constr_type_w, true);
|
|
return parentWidth * (1 - acctRatio);
|
|
}
|
|
PyramidAlgorithm.prototype.forEachChild = function (callback, startIndex) {
|
|
const childs = this.parentNode.childs;
|
|
if (this.isReversedPyramid()) {
|
|
for (let i = startIndex; i < childs.length; i += 1) {
|
|
callback(childs[i]);
|
|
}
|
|
} else {
|
|
for (let i = childs.length - 1 - startIndex; i >= 0; i -= 1) {
|
|
callback(childs[i]);
|
|
}
|
|
}
|
|
}
|
|
PyramidAlgorithm.prototype.getFirstPyramidComponents = function () {
|
|
const childs = this.parentNode.childs;
|
|
if (this.isReversedPyramid()) {
|
|
return this.getPyramidChildren(childs[0]);
|
|
}
|
|
|
|
return this.getPyramidChildren(childs[childs.length - 1]);
|
|
}
|
|
PyramidAlgorithm.prototype.getShapeContainer = function (isCalculateScaleCoefficient) {
|
|
if (isCalculateScaleCoefficient) {
|
|
if (this.coefficientShapeContainer === null) {
|
|
this.coefficientShapeContainer = new PyramidContainer();
|
|
}
|
|
return this.coefficientShapeContainer;
|
|
}
|
|
if (this.shapeContainer === null) {
|
|
this.shapeContainer = new PyramidContainer();
|
|
}
|
|
return this.shapeContainer;
|
|
};
|
|
PyramidAlgorithm.prototype._calculateShapePositions = function () {
|
|
const parentNode = this.parentNode;
|
|
const shapeContainer = this.getShapeContainer(false);
|
|
const parentHeight = parentNode.getConstr(AscFormat.Constr_type_h, true);
|
|
const parentWidth = parentNode.getConstr(AscFormat.Constr_type_w, true);
|
|
const defaultBlockHeight = this.calcValues.defaultBlockHeight;
|
|
let previousBlockWidth = this.getStartDefaultBlockWidth();
|
|
const defaultAdjValue = (previousBlockWidth / 2) / parentHeight;
|
|
|
|
|
|
const firstPyramidComponents = this.getFirstPyramidComponents();
|
|
const firstChild = firstPyramidComponents.pyramid;
|
|
const firstShape = firstChild.getShape(false);
|
|
const firstHeight = defaultBlockHeight * firstChild.getHeightScale();
|
|
const firstWidth = previousBlockWidth * firstChild.getWidthScale();
|
|
let ctrX = (previousBlockWidth - firstWidth) / 2 + firstWidth / 2;
|
|
if (!this.isAfterAcct()) {
|
|
ctrX = parentWidth - ctrX;
|
|
}
|
|
let previousY;
|
|
if (this.isReversedPyramid()) {
|
|
previousY = 0;
|
|
} else {
|
|
previousY = parentHeight - firstHeight;
|
|
}
|
|
let previousBlockHeight = firstHeight;
|
|
this.setPyramidParametersForNode(firstChild, ctrX - firstWidth / 2, previousY, firstHeight, firstWidth, defaultBlockHeight, previousBlockWidth, defaultAdjValue);
|
|
const firstAcctOffset = defaultAdjValue * previousBlockHeight;
|
|
if (this.isReversedPyramid()) {
|
|
firstShape.rot = Math.PI;
|
|
this.addAcctShape(firstChild, firstPyramidComponents.acct, defaultAdjValue, firstAcctOffset);
|
|
shapeContainer.push(firstShape);
|
|
} else {
|
|
shapeContainer.push(firstShape);
|
|
this.addAcctShape(firstChild, firstPyramidComponents.acct, defaultAdjValue, firstAcctOffset);
|
|
}
|
|
const oThis = this;
|
|
this.forEachChild(function (node) {
|
|
const pyramidComponents = oThis.getPyramidChildren(node);
|
|
const child = pyramidComponents.pyramid;
|
|
const shape = child.getShape(false);
|
|
const blockHeightFactor = child.getHeightScale();
|
|
const blockWidthFactor = child.getWidthScale();
|
|
const scaledBlockHeight = blockHeightFactor * defaultBlockHeight;
|
|
const curBlockWidth = previousBlockWidth - 2 * defaultAdjValue * previousBlockHeight;
|
|
const scaledBlockWidth = curBlockWidth * blockWidthFactor;
|
|
const x = ctrX - scaledBlockWidth / 2;
|
|
let y;
|
|
if (oThis.isReversedPyramid()) {
|
|
y = previousY + previousBlockHeight;
|
|
} else {
|
|
y = previousY - scaledBlockHeight;
|
|
}
|
|
const acctOffset = defaultAdjValue * scaledBlockHeight;
|
|
oThis.setPyramidParametersForNode(child, x, y, scaledBlockHeight, scaledBlockWidth, defaultBlockHeight, curBlockWidth, defaultAdjValue);
|
|
if (oThis.isReversedPyramid()) {
|
|
shape.rot = Math.PI;
|
|
oThis.addAcctShape(child, pyramidComponents.acct, defaultAdjValue, acctOffset);
|
|
shapeContainer.push(shape);
|
|
} else {
|
|
shapeContainer.push(shape);
|
|
oThis.addAcctShape(child, pyramidComponents.acct, defaultAdjValue, acctOffset);
|
|
}
|
|
previousBlockWidth = curBlockWidth;
|
|
previousBlockHeight = scaledBlockHeight;
|
|
previousY = y;
|
|
}, 1);
|
|
if (!this.isReversedPyramid()) {
|
|
shapeContainer.reverse();
|
|
}
|
|
};
|
|
PyramidAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm, isCalculateScaleCoefficients) {
|
|
const parentNode = this.parentNode;
|
|
const childs = parentNode.childs;
|
|
if (!childs.length) {
|
|
return;
|
|
}
|
|
if (isCalculateScaleCoefficients) {
|
|
this.calcScaleCoefficients(smartartAlgorithm);
|
|
} else {
|
|
this._calculateShapePositions();
|
|
this.applyParamOffsets();
|
|
this.applyPostAlgorithmSettings();
|
|
this.createShadowShape(false);
|
|
}
|
|
};
|
|
PyramidAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createShadowShape(true, isCalculateScaleCoefficients);
|
|
};
|
|
PyramidAlgorithm.prototype.getTemplateAdjAcctLst = function (firstAdj, secondAdj) {
|
|
const adjLst = new AscFormat.AdjLst();
|
|
const adj1 = new AscFormat.Adj();
|
|
adjLst.addToLst(0, adj1);
|
|
adj1.setIdx(1);
|
|
|
|
const adj2 = new AscFormat.Adj();
|
|
adj2.setIdx(2);
|
|
adjLst.addToLst(1, adj2);
|
|
|
|
adj1.setVal(firstAdj);
|
|
adj2.setVal(secondAdj);
|
|
return adjLst;
|
|
};
|
|
PyramidAlgorithm.prototype.isAfterAcct = function () {
|
|
return this.params[AscFormat.Param_type_pyraAcctPos] === AscFormat.ParameterVal_pyramidAccentPosition_aft;
|
|
}
|
|
PyramidAlgorithm.prototype.addAcctShape = function (mainNode, acctNode, defaultAdjValue, acctHelper) {
|
|
if (!(mainNode && acctNode)) {
|
|
return;
|
|
}
|
|
const shapeContainer = this.getShapeContainer();
|
|
const parentWidth = this.parentNode.getConstr(AscFormat.Constr_type_w, true);
|
|
const mainShape = mainNode.getShape(false);
|
|
const acctShape = acctNode.getShape(false);
|
|
|
|
const heightScale = acctNode.getHeightScale();
|
|
const widthScale = acctNode.getWidthScale();
|
|
let defaultWidth;
|
|
if (this.isAfterAcct()) {
|
|
defaultWidth = parentWidth - (mainShape.x + mainShape.width - acctHelper);
|
|
} else {
|
|
defaultWidth = mainShape.x + acctHelper;
|
|
}
|
|
const defaultHeight = mainShape.height;
|
|
acctShape.cleanParams.width = defaultWidth;
|
|
acctShape.cleanParams.height = defaultHeight;
|
|
acctShape.width = defaultWidth * widthScale;
|
|
acctShape.height = defaultHeight * heightScale;
|
|
if (defaultWidth < defaultHeight) {
|
|
defaultAdjValue = defaultAdjValue * defaultHeight / defaultWidth;
|
|
}
|
|
|
|
if (this.isAfterAcct()) {
|
|
acctShape.x = mainShape.x + mainShape.width - acctHelper + (defaultWidth - acctShape.width) / 2;
|
|
if (this.isReversedPyramid()) {
|
|
acctShape.customAdj = this.getTemplateAdjAcctLst(defaultAdjValue, 0);
|
|
} else {
|
|
acctShape.customAdj = this.getTemplateAdjAcctLst(0, defaultAdjValue);
|
|
}
|
|
} else {
|
|
acctShape.x = (defaultWidth - acctShape.width) / 2;
|
|
if (this.isReversedPyramid()) {
|
|
acctShape.customAdj = this.getTemplateAdjAcctLst(0, defaultAdjValue);
|
|
} else {
|
|
acctShape.customAdj = this.getTemplateAdjAcctLst(defaultAdjValue, 0);
|
|
}
|
|
}
|
|
acctShape.y = mainShape.y + (defaultHeight - acctShape.height) / 2;
|
|
if (!this.isReversedPyramid()) {
|
|
acctShape.rot = Math.PI;
|
|
}
|
|
shapeContainer.push(acctShape);
|
|
|
|
const txNode = acctNode.contentNodes[0] && acctNode.contentNodes[0].getTextNode();
|
|
if (txNode) {
|
|
const textShape = txNode.getShape();
|
|
textShape.type = AscFormat.LayoutShapeType_shapeType_rect;
|
|
if (this.isAfterAcct()) {
|
|
textShape.x = mainShape.x + mainShape.width;
|
|
textShape.y = acctShape.y;
|
|
textShape.height = acctShape.height;
|
|
textShape.width = acctShape.width - (textShape.x - acctShape.x);
|
|
textShape.rot = acctShape.rot;
|
|
} else {
|
|
textShape.x = acctShape.x;
|
|
textShape.y = acctShape.y;
|
|
textShape.height = acctShape.height;
|
|
textShape.width = acctShape.width - acctHelper;
|
|
textShape.rot = acctShape.rot;
|
|
}
|
|
|
|
}
|
|
};
|
|
|
|
function CycleAlgorithm() {
|
|
PositionAlgorithm.call(this);
|
|
this.calcValues = {
|
|
radius: 0,
|
|
startAngle: 0,
|
|
stepAngle: 0,
|
|
mainElements: [],
|
|
centerNodeIndex: null,
|
|
isInit: false
|
|
};
|
|
}
|
|
AscFormat.InitClassWithoutType(CycleAlgorithm, PositionAlgorithm);
|
|
CycleAlgorithm.prototype.getChildAlgorithmAlignBounds = function (isCalculateCoefficients, skipRotate) {
|
|
const x = this.parentNode.getConstr(AscFormat.Constr_type_l, !isCalculateCoefficients);
|
|
const y = this.parentNode.getConstr(AscFormat.Constr_type_t, !isCalculateCoefficients);
|
|
const width = this.parentNode.getConstr(AscFormat.Constr_type_w, !isCalculateCoefficients);
|
|
const height = this.parentNode.getConstr(AscFormat.Constr_type_h, !isCalculateCoefficients);
|
|
return {
|
|
l: x,
|
|
t: y,
|
|
r: x + width,
|
|
b: y + height
|
|
};
|
|
};
|
|
CycleAlgorithm.prototype.getCenterNode = function () {
|
|
if (this.calcValues.centerNodeIndex !== null) {
|
|
return this.parentNode.childs[this.calcValues.centerNodeIndex];
|
|
}
|
|
};
|
|
CycleAlgorithm.prototype.getParentConnectionNode = function () {
|
|
return this.getCenterNode();
|
|
};
|
|
CycleAlgorithm.prototype.isClockwise = function () {
|
|
return this.calcValues.stepAngle > 0;
|
|
}
|
|
CycleAlgorithm.prototype.getShapeIndex = function (shape) {
|
|
return this.calcValues.mainElements.indexOf(shape);
|
|
};
|
|
CycleAlgorithm.prototype.getRadialConnectionInfo = function (node) {
|
|
const shape = node.getShape();
|
|
const shapeCenterPoint = new CCoordPoint(shape.x + shape.width / 2, shape.y + shape.height / 2);
|
|
let radius;
|
|
let angle;
|
|
let custVector;
|
|
if (shape.custCenterPoint) {
|
|
custVector = shape.custCenterPoint.getVector(shapeCenterPoint);
|
|
radius = custVector.getDistance();
|
|
angle = custVector.getAngle();
|
|
return {
|
|
point: shape.custCenterPoint,
|
|
radius: radius,
|
|
angle: angle,
|
|
isClockwise: this.isClockwise()
|
|
}
|
|
} else if (shape.radialVector) {
|
|
radius = shape.radialVector.getDistance();
|
|
angle = shape.radialVector.getAngle();
|
|
return {
|
|
point: new CCoordPoint(shapeCenterPoint.x - shape.radialVector.x, shapeCenterPoint.y - shape.radialVector.y),
|
|
radius: radius,
|
|
angle: angle,
|
|
isClockwise: this.isClockwise()
|
|
};
|
|
}
|
|
return null;
|
|
};
|
|
CycleAlgorithm.prototype.initParams = function (params) {
|
|
PositionAlgorithm.prototype.initParams.call(this, params);
|
|
if (this.params[AscFormat.Param_type_stAng] === undefined) {
|
|
this.params[AscFormat.Param_type_stAng] = 0;
|
|
}
|
|
if (this.params[AscFormat.Param_type_spanAng] === undefined) {
|
|
this.params[AscFormat.Param_type_spanAng] = 360;
|
|
}
|
|
if (this.params[AscFormat.Param_type_vertAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_vertAlign] = AscFormat.ParameterVal_verticalAlignment_mid;
|
|
}
|
|
if (this.params[AscFormat.Param_type_horzAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_horzAlign] = AscFormat.ParameterVal_horizontalAlignment_ctr;
|
|
}
|
|
|
|
if (this.params[AscFormat.Param_type_ctrShpMap] === undefined) {
|
|
this.params[AscFormat.Param_type_ctrShpMap] = AscFormat.ParameterVal_centerShapeMapping_none;
|
|
}
|
|
}
|
|
CycleAlgorithm.prototype.getCenterShapeRadius = function (centerBounds, anotherBounds, guideVector) {
|
|
if (!centerBounds || !anotherBounds) {
|
|
return 0;
|
|
}
|
|
const centerPoint = getShapePoint(centerBounds);
|
|
const anotherPoint = getShapePoint(anotherBounds);
|
|
const centerEdgePoint = getMinShapeEdgePoint(centerBounds, guideVector);
|
|
const anotherEdgePoint = getMinShapeEdgePoint(anotherBounds, new CVector(-guideVector.x, -guideVector.y));
|
|
if (centerEdgePoint && anotherEdgePoint) {
|
|
const centerDistance = centerPoint.getVector(centerEdgePoint).getDistance();
|
|
const anotherDistance = anotherPoint.getVector(anotherEdgePoint).getDistance();
|
|
const minPadding = this.parentNode.getConstr(AscFormat.Constr_type_sp);
|
|
return centerDistance + anotherDistance + minPadding;
|
|
}
|
|
return 0;
|
|
};
|
|
CycleAlgorithm.prototype.getStartCycleBounds = function () {
|
|
const centerNode = this.getCenterNode();
|
|
if (centerNode) {
|
|
const centerShape = centerNode.getShape(true);
|
|
const bounds = centerShape.getBounds(true);
|
|
const halfWidth = (bounds.r - bounds.l) / 2;
|
|
const halfHeight = (bounds.b - bounds.t) / 2;
|
|
return {
|
|
l: -halfWidth,
|
|
r: halfWidth,
|
|
t: -halfHeight,
|
|
b: halfHeight
|
|
};
|
|
}
|
|
return {l: 0, r: 0, t: 0, b: 0};
|
|
}
|
|
CycleAlgorithm.prototype.initCenterShapeMap = function () {
|
|
if (this.params[AscFormat.Param_type_ctrShpMap] === AscFormat.ParameterVal_centerShapeMapping_fNode) {
|
|
const childs = this.parentNode.childs;
|
|
for (let i = 0; i < childs.length; i += 1) {
|
|
const child = childs[i];
|
|
if (child.isContentNode()) {
|
|
this.calcValues.centerNodeIndex = i;
|
|
return i + 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
};
|
|
CycleAlgorithm.prototype.calculateStartValues = function () {
|
|
if (!this.calcValues.isInit) {
|
|
this.calcValues.isInit = true;
|
|
const spanAngle = this.params[AscFormat.Param_type_spanAng];
|
|
const startAngle = AscFormat.normalizeRotate(this.params[AscFormat.Param_type_stAng] * degToRad - Math.PI / 2);
|
|
|
|
const mainElements = this.calcValues.mainElements;
|
|
const childs = this.parentNode.childs;
|
|
let startIndex = this.initCenterShapeMap();
|
|
for (startIndex; startIndex < childs.length; startIndex += 1) {
|
|
const child = childs[startIndex];
|
|
if (child.isContentNode()) {
|
|
mainElements.push(child);
|
|
}
|
|
}
|
|
|
|
let stepAngle;
|
|
if (Math.abs(spanAngle) === 360) {
|
|
if (mainElements.length === 0) {
|
|
stepAngle = 0;
|
|
} else {
|
|
stepAngle = (spanAngle / mainElements.length) * degToRad;
|
|
}
|
|
|
|
} else {
|
|
if (mainElements.length === 0) {
|
|
stepAngle = 0;
|
|
} else {
|
|
stepAngle = (spanAngle / (mainElements.length - 1)) * degToRad;
|
|
}
|
|
}
|
|
this.calcValues.startAngle = startAngle;
|
|
this.calcValues.stepAngle = stepAngle;
|
|
}
|
|
};
|
|
CycleAlgorithm.prototype.getNormalizeSibSp = function () {
|
|
//todo think about how it is actually calculated
|
|
const stepAngle = this.calcValues.stepAngle;
|
|
const sibSp = this.parentNode.getConstr(AscFormat.Constr_type_sibSp);
|
|
if (this.isClockwise()) {
|
|
if (stepAngle > Math.PI / 2 && sibSp < 0) {
|
|
return 0;
|
|
}
|
|
} else {
|
|
if (stepAngle < -Math.PI / 2 && sibSp < 0) {
|
|
return 0;
|
|
}
|
|
}
|
|
return sibSp;
|
|
}
|
|
CycleAlgorithm.prototype.calcScaleCoefficients = function (smartartAlgorithm) {
|
|
const startAngle = this.calcValues.startAngle;
|
|
const stepAngle = this.calcValues.stepAngle;
|
|
const mainElements = this.calcValues.mainElements;
|
|
let previousAngle = startAngle;
|
|
let currentAngle = AscFormat.normalizeRotate(startAngle + stepAngle);
|
|
const divider = Math.sqrt(2 * (1 - Math.cos(Math.abs(stepAngle))));
|
|
const sibSp = this.getNormalizeSibSp();
|
|
|
|
const firstShape = mainElements[0] && mainElements[0].getShape(true)
|
|
const firstElementBounds = firstShape && firstShape.getBounds(true);
|
|
let maxRadius = 0;
|
|
const centerNode = this.getCenterNode();
|
|
let centerShapeBounds;
|
|
if (centerNode) {
|
|
const startGuideVector = CVector.getVectorByAngle(startAngle);
|
|
const centerShape = centerNode.getShape(true);
|
|
centerShapeBounds = centerShape.getBounds(true);
|
|
maxRadius = this.getCenterShapeRadius(centerShapeBounds, firstElementBounds, startGuideVector);
|
|
}
|
|
if (divider !== 0) {
|
|
let previousBounds = firstElementBounds;
|
|
for (let i = 1; i < mainElements.length + 1; i++) {
|
|
const curIndex = i === mainElements.length ? 0 : i;
|
|
const shape = mainElements[curIndex].getShape(true);
|
|
const currentBounds = shape.getBounds(true);
|
|
const centerGuideVector = CVector.getVectorByAngle(currentAngle);
|
|
const tempCenterRadius = this.getCenterShapeRadius(centerShapeBounds, currentBounds, centerGuideVector);
|
|
|
|
let tempSibRadius = 0;
|
|
|
|
const previousVector = CVector.getVectorByAngle(previousAngle);
|
|
const currentVector = CVector.getVectorByAngle(currentAngle);
|
|
const guideVector = currentVector.getDiffVector(previousVector);
|
|
const currentEdgePoint = getMinShapeEdgePoint(currentBounds, guideVector);
|
|
const previousEdgePoint = getMinShapeEdgePoint(previousBounds, new CVector(-guideVector.x, -guideVector.y));
|
|
if (currentEdgePoint && previousEdgePoint) {
|
|
const currentShapePoint = getShapePoint(currentBounds);
|
|
const previousShapePoint = getShapePoint(previousBounds);
|
|
const currentVector = currentShapePoint.getVector(currentEdgePoint);
|
|
const previousVector = previousShapePoint.getVector(previousEdgePoint);
|
|
const previousDistance = previousVector.getDistance();
|
|
const currentDistance = currentVector.getDistance();
|
|
|
|
tempSibRadius = (sibSp + previousDistance + currentDistance) / divider;
|
|
}
|
|
maxRadius = Math.max(maxRadius, tempSibRadius, tempCenterRadius);
|
|
previousAngle = currentAngle;
|
|
currentAngle = i === mainElements.length - 1 ? AscFormat.normalizeRotate(startAngle) : AscFormat.normalizeRotate(currentAngle + stepAngle);
|
|
previousBounds = currentBounds;
|
|
}
|
|
}
|
|
currentAngle = startAngle;
|
|
const cycleBounds = this.getStartCycleBounds();
|
|
const radiusBounds = {l: 0, r: 0, t: 0, b: 0};
|
|
for (let i = 0; i < mainElements.length; i++) {
|
|
const radiusVector = CVector.getVectorByAngle(currentAngle);
|
|
radiusVector.multiply(maxRadius);
|
|
const shape = mainElements[i].getShape(true);
|
|
const currentBounds = shape.getBounds(true);
|
|
const halfWidth = (currentBounds.r - currentBounds.l) / 2;
|
|
const halfHeight = (currentBounds.b - currentBounds.t) / 2;
|
|
const newL = radiusVector.x - halfWidth;
|
|
const newR = radiusVector.x + halfWidth;
|
|
const newT = radiusVector.y - halfHeight;
|
|
const newB = radiusVector.y + halfHeight;
|
|
|
|
if (newL < cycleBounds.l) {
|
|
cycleBounds.l = newL;
|
|
radiusBounds.l = radiusVector.x;
|
|
}
|
|
if (newT < cycleBounds.t) {
|
|
cycleBounds.t = newT;
|
|
radiusBounds.t = radiusVector.y;
|
|
}
|
|
if (newR > cycleBounds.r) {
|
|
cycleBounds.r = newR;
|
|
radiusBounds.r = radiusVector.x;
|
|
}
|
|
if (newB > cycleBounds.b) {
|
|
cycleBounds.b = newB;
|
|
radiusBounds.b = radiusVector.y;
|
|
}
|
|
|
|
currentAngle = AscFormat.normalizeRotate(currentAngle + stepAngle);
|
|
}
|
|
|
|
const parentWidth = this.getParentNodeWidth();
|
|
const parentHeight = this.getParentNodeHeight();
|
|
const cycleHeight = cycleBounds.b - cycleBounds.t;
|
|
const cycleWidth = cycleBounds.r - cycleBounds.l;
|
|
let coefficient = Math.min(1, parentWidth / cycleWidth, parentHeight / cycleHeight);
|
|
if (coefficient === 1 && smartartAlgorithm.factRuleState === factRuleState.enabled) {
|
|
smartartAlgorithm.setFactRuleState(factRuleState.disabled);
|
|
return;
|
|
}
|
|
let radiusCoefficient = coefficient;
|
|
const scaleFactor = this.getOffsetScaleFactor(radiusBounds, cycleBounds);
|
|
if (scaleFactor > 1) {
|
|
radiusCoefficient = Math.max(coefficient, scaleFactor);
|
|
}
|
|
const adaptRadius = maxRadius * radiusCoefficient;
|
|
this.calcValues.radius = maxRadius;
|
|
const constrRadius = this.getConstrRadius(true);
|
|
if (constrRadius !== undefined && adaptRadius > constrRadius) {
|
|
radiusCoefficient *= constrRadius / adaptRadius;
|
|
}
|
|
this.calcValues.radiusCoefficient = radiusCoefficient;
|
|
for (let i = 0; i < this.parentNode.childs.length; i += 1) {
|
|
const child = this.parentNode.childs[i];
|
|
child.setSizesScale(coefficient, coefficient);
|
|
}
|
|
};
|
|
CycleAlgorithm.prototype.getConstrRadius = function (isCalculateScaleCoefficients) {
|
|
const constrObject = this.parentNode.getConstraints(!isCalculateScaleCoefficients);
|
|
const diameter = constrObject[AscFormat.Constr_type_diam];
|
|
if (diameter !== undefined) {
|
|
return diameter / 2;
|
|
}
|
|
};
|
|
CycleAlgorithm.prototype.getOffsetScaleFactor = function (radiusBounds, cycleBounds) {
|
|
const parentNodeWidth = this.getParentNodeWidth();
|
|
const parentNodeHeight = this.getParentNodeHeight();
|
|
|
|
const radiusHeight = radiusBounds.b - radiusBounds.t;
|
|
const radiusWidth = radiusBounds.r - radiusBounds.l;
|
|
const parentWidth = parentNodeWidth - (radiusBounds.l - cycleBounds.l) - (cycleBounds.r - radiusBounds.r);
|
|
const parentHeight = parentNodeHeight - (radiusBounds.t - cycleBounds.t) - (cycleBounds.b - radiusBounds.b);
|
|
if (radiusHeight !== 0 && radiusWidth !== 0) {
|
|
return Math.max(1, Math.min(parentWidth / radiusWidth, parentHeight / radiusHeight));
|
|
} else if (radiusHeight === 0 && radiusWidth !== 0) {
|
|
return Math.max(1, parentWidth / radiusWidth);
|
|
} else if (radiusWidth === 0 && radiusHeight !== 0) {
|
|
return Math.max(1, parentHeight / radiusHeight);
|
|
}
|
|
return 1;
|
|
};
|
|
|
|
CycleAlgorithm.prototype.generateCurveShapeConnectors = function (smartartAlgorithm) {
|
|
for (let i = 0; i < this.parentNode.childs.length; i += 1) {
|
|
const child = this.parentNode.childs[i];
|
|
if (child.algorithm instanceof ConnectorAlgorithm && child.algorithm.isCurveShape()) {
|
|
child.algorithm.connectShapes(smartartAlgorithm);
|
|
}
|
|
}
|
|
};
|
|
CycleAlgorithm.prototype.resetConnectors = function () {
|
|
for (let i = 0; i < this.parentNode.childs.length; i += 1) {
|
|
const child = this.parentNode.childs[i];
|
|
if (child.algorithm instanceof ConnectorAlgorithm) {
|
|
child.algorithm.reset();
|
|
}
|
|
}
|
|
};
|
|
CycleAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm, isCalculateScaleCoefficients) {
|
|
this.calculateStartValues();
|
|
if (isCalculateScaleCoefficients) {
|
|
this.calcScaleCoefficients(smartartAlgorithm);
|
|
} else {
|
|
this._calculateShapePositions();
|
|
this.setConnections();
|
|
this.generateCurveShapeConnectors(smartartAlgorithm);
|
|
this.applyAlgorithmAligns(isCalculateScaleCoefficients);
|
|
this.resetConnectors();
|
|
this.applyPostAlgorithmSettings();
|
|
this.createShadowShape(isCalculateScaleCoefficients);
|
|
}
|
|
};
|
|
CycleAlgorithm.prototype.isAlongPath = function () {
|
|
return this.params[AscFormat.Param_type_rotPath] === AscFormat.ParameterVal_rotationPath_alongPath;
|
|
}
|
|
CycleAlgorithm.prototype.getAlongRot = function (currentAngle) {
|
|
if (this.isAlongPath()) {
|
|
return AscFormat.normalizeRotate(currentAngle + Math.PI / 2);
|
|
}
|
|
return 0;
|
|
};
|
|
CycleAlgorithm.prototype._calculateShapePositions = function () {
|
|
const childs = this.parentNode.childs;
|
|
const radius = this.calcValues.radius * this.calcValues.radiusCoefficient;
|
|
let currentAngle = this.calcValues.startAngle;
|
|
const stepAngle = this.calcValues.stepAngle;
|
|
const container = this.getShapeContainer();
|
|
let startIndex = 0;
|
|
let incAngleDivider = childs.length;
|
|
if (this.calcValues.centerNodeIndex !== null) {
|
|
incAngleDivider -= 1;
|
|
const centerNode = this.getCenterNode();
|
|
const shape = centerNode && centerNode.getShape(false);
|
|
if (shape) {
|
|
shape.moveTo(-(shape.x + shape.width / 2), -(shape.y + shape.height / 2));
|
|
container.push(shape);
|
|
}
|
|
startIndex = this.calcValues.centerNodeIndex + 1;
|
|
}
|
|
let incAngle = 0;
|
|
if (incAngleDivider > 0) {
|
|
incAngle = 2 * Math.PI / incAngleDivider;
|
|
}
|
|
|
|
for (let i = startIndex; i < childs.length; i++) {
|
|
const child = childs[i];
|
|
const shape = child.getShape(false);
|
|
if (child.isContentNode() && shape) {
|
|
const radiusGuideVector = CVector.getVectorByAngle(currentAngle);
|
|
radiusGuideVector.multiply(radius);
|
|
shape.setRadialInfo(radiusGuideVector, incAngle);
|
|
const bounds = shape.getBounds();
|
|
const width = bounds.r - bounds.l;
|
|
const height = bounds.b - bounds.t;
|
|
const offX = radiusGuideVector.x - (bounds.l + width / 2);
|
|
const offY = radiusGuideVector.y - (bounds.t + height / 2);
|
|
|
|
shape.rot = this.getAlongRot(currentAngle);
|
|
shape.moveTo(offX, offY);
|
|
currentAngle = currentAngle + stepAngle;
|
|
container.push(shape);
|
|
}
|
|
}
|
|
};
|
|
CycleAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createShadowShape(true, isCalculateScaleCoefficients);
|
|
};
|
|
CycleAlgorithm.prototype.getShapeContainer = function (isCalculateScaleCoefficient) {
|
|
if (isCalculateScaleCoefficient) {
|
|
if (this.coefficientShapeContainer === null) {
|
|
this.coefficientShapeContainer = new CycleContainer();
|
|
}
|
|
return this.coefficientShapeContainer;
|
|
}
|
|
if (this.shapeContainer === null) {
|
|
this.shapeContainer = new CycleContainer();
|
|
}
|
|
return this.shapeContainer;
|
|
};
|
|
|
|
function LinearAlgorithm() {
|
|
PositionAlgorithm.call(this);
|
|
}
|
|
AscFormat.InitClassWithoutType(LinearAlgorithm, PositionAlgorithm);
|
|
|
|
LinearAlgorithm.prototype.isRow = function () {
|
|
return this.params[AscFormat.Param_type_linDir] === AscFormat.ParameterVal_linearDirection_fromL ||
|
|
this.params[AscFormat.Param_type_linDir] === AscFormat.ParameterVal_linearDirection_fromR;
|
|
}
|
|
LinearAlgorithm.prototype.initParams = function (params) {
|
|
PositionAlgorithm.prototype.initParams.call(this, params);
|
|
if (this.params[AscFormat.Param_type_linDir] === undefined) {
|
|
this.params[AscFormat.Param_type_linDir] = AscFormat.ParameterVal_linearDirection_fromL;
|
|
}
|
|
|
|
if (this.params[AscFormat.Param_type_vertAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_vertAlign] = AscFormat.ParameterVal_verticalAlignment_mid;
|
|
}
|
|
if (this.params[AscFormat.Param_type_horzAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_horzAlign] = AscFormat.ParameterVal_horizontalAlignment_ctr;
|
|
}
|
|
|
|
if (this.isRow()) {
|
|
if (this.params[AscFormat.Param_type_nodeVertAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_nodeVertAlign] = AscFormat.ParameterVal_nodeVerticalAlignment_mid;
|
|
}
|
|
this.params[AscFormat.Param_type_nodeHorzAlign] = undefined;
|
|
} else {
|
|
if (this.params[AscFormat.Param_type_nodeHorzAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_nodeHorzAlign] = AscFormat.ParameterVal_nodeHorizontalAlignment_ctr;
|
|
}
|
|
this.params[AscFormat.Param_type_nodeVertAlign] = undefined;
|
|
}
|
|
}
|
|
LinearAlgorithm.prototype.applyLeftNodeAlign = function (isCalculateScaleCoefficients) {
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficients);
|
|
const bounds = shapeContainer.getBounds();
|
|
|
|
shapeContainer.forEachShape(function (shape) {
|
|
const shapeBounds = shape.getBounds();
|
|
shape.moveTo(bounds.l - shapeBounds.l, 0);
|
|
});
|
|
};
|
|
LinearAlgorithm.prototype.applyRightNodeAlign = function (isCalculateScaleCoefficients) {
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficients);
|
|
const bounds = shapeContainer.getBounds();
|
|
|
|
shapeContainer.forEachShape(function (shape) {
|
|
const shapeBounds = shape.getBounds();
|
|
shape.moveTo(bounds.r - shapeBounds.r, 0);
|
|
});
|
|
};
|
|
LinearAlgorithm.prototype.applyCenterNodeAlign = function (isCalculateScaleCoefficients) {
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficients);
|
|
const bounds = shapeContainer.getBounds();
|
|
const boundsCenter = bounds.l + (bounds.r - bounds.l) / 2;
|
|
shapeContainer.forEachShape(function (shape) {
|
|
const shapeBounds = shape.getBounds();
|
|
shape.moveTo(boundsCenter - (shapeBounds.l + (shapeBounds.r - shapeBounds.l) / 2), 0);
|
|
});
|
|
};
|
|
LinearAlgorithm.prototype.applyTopNodeAlign = function (isCalculateScaleCoefficients) {
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficients);
|
|
const bounds = shapeContainer.getBounds();
|
|
|
|
shapeContainer.forEachShape(function (shape) {
|
|
const shapeBounds = shape.getBounds();
|
|
shape.moveTo(0, bounds.t - shapeBounds.t);
|
|
});
|
|
};
|
|
LinearAlgorithm.prototype.applyBottomNodeAlign = function (isCalculateScaleCoefficients) {
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficients);
|
|
const bounds = shapeContainer.getBounds();
|
|
|
|
shapeContainer.forEachShape(function (shape) {
|
|
const shapeBounds = shape.getBounds();
|
|
shape.moveTo(0, bounds.b - shapeBounds.b);
|
|
});
|
|
};
|
|
LinearAlgorithm.prototype.applyMidNodeAlign = function (isCalculateScaleCoefficients) {
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficients);
|
|
const bounds = shapeContainer.getBounds();
|
|
const boundsCenter = bounds.t + (bounds.b - bounds.t) / 2;
|
|
shapeContainer.forEachShape(function (shape) {
|
|
const shapeBounds = shape.getBounds();
|
|
shape.moveTo(0, boundsCenter - (shapeBounds.t + (shapeBounds.b - shapeBounds.t) / 2));
|
|
});
|
|
};
|
|
LinearAlgorithm.prototype.applyNodeAligns = function (isCalculateScaleCoefficients) {
|
|
switch (this.params[AscFormat.Param_type_nodeHorzAlign]) {
|
|
case AscFormat.ParameterVal_nodeHorizontalAlignment_l:
|
|
this.applyLeftNodeAlign(isCalculateScaleCoefficients);
|
|
break;
|
|
case AscFormat.ParameterVal_nodeHorizontalAlignment_ctr:
|
|
this.applyCenterNodeAlign(isCalculateScaleCoefficients);
|
|
break;
|
|
case AscFormat.ParameterVal_nodeHorizontalAlignment_r:
|
|
this.applyRightNodeAlign(isCalculateScaleCoefficients);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch (this.params[AscFormat.Param_type_nodeVertAlign]) {
|
|
case AscFormat.ParameterVal_nodeVerticalAlignment_t:
|
|
this.applyTopNodeAlign(isCalculateScaleCoefficients);
|
|
break;
|
|
case AscFormat.ParameterVal_nodeVerticalAlignment_mid:
|
|
this.applyMidNodeAlign(isCalculateScaleCoefficients);
|
|
break;
|
|
case AscFormat.ParameterVal_nodeVerticalAlignment_b:
|
|
this.applyBottomNodeAlign(isCalculateScaleCoefficients);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
LinearAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createShadowShape(true, isCalculateScaleCoefficients);
|
|
};
|
|
LinearAlgorithm.prototype.isFromLeft = function () {
|
|
return this.params[AscFormat.Param_type_linDir] === AscFormat.ParameterVal_linearDirection_fromL;
|
|
};
|
|
LinearAlgorithm.prototype.isFromTop = function () {
|
|
return this.params[AscFormat.Param_type_linDir] === AscFormat.ParameterVal_linearDirection_fromT;
|
|
};
|
|
LinearAlgorithm.prototype._calculateShapePositions = function (isCalculateScaleCoefficients) {
|
|
switch (this.params[AscFormat.Param_type_linDir]) {
|
|
case AscFormat.ParameterVal_linearDirection_fromL:
|
|
case AscFormat.ParameterVal_linearDirection_fromR:
|
|
this.calculateRowShapePositions(isCalculateScaleCoefficients);
|
|
break;
|
|
case AscFormat.ParameterVal_linearDirection_fromT:
|
|
case AscFormat.ParameterVal_linearDirection_fromB:
|
|
this.calculateColumnShapePositions(isCalculateScaleCoefficients);
|
|
break;
|
|
}
|
|
};
|
|
LinearAlgorithm.prototype.isHaveChildLinear = function () {
|
|
for (let i = 0; i < this.parentNode.childs.length; i += 1) {
|
|
if (this.parentNode.childs[i].algorithm instanceof LinearAlgorithm) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
LinearAlgorithm.prototype.is2DFallback = function () {
|
|
return this.params[AscFormat.Param_type_fallback] === AscFormat.ParameterVal_fallbackDimension_2D || this.isHaveChildLinear();
|
|
}
|
|
LinearAlgorithm.prototype.setScaleCoefficient = function () {
|
|
if (!(!this.parentNode.parent || this.parentNode.parent.algorithm instanceof CompositeAlgorithm)) {
|
|
return;
|
|
}
|
|
|
|
const parentHeight = this.getParentNodeHeight(false);
|
|
const parentWidth = this.getParentNodeWidth(false);
|
|
if (!(parentHeight && parentWidth)) {
|
|
return;
|
|
}
|
|
const childs = this.parentNode.childs;
|
|
const length = this.isHideLastChild() ? childs.length - 1 : childs.length;
|
|
if (length > 0) {
|
|
const isRow = this.isRow();
|
|
const shapeContainer = this.getShapeContainer(true);
|
|
const bounds = shapeContainer.getBounds();
|
|
const width = bounds.r - bounds.l;
|
|
const height = bounds.b - bounds.t;
|
|
let widthCoefficient = Math.min(parentWidth / width, 1);
|
|
let heightCoefficient = Math.min(parentHeight / height, 1);
|
|
if (this.is2DFallback()) {
|
|
const commonCoefficient = Math.min(widthCoefficient, heightCoefficient);
|
|
widthCoefficient = commonCoefficient;
|
|
heightCoefficient = commonCoefficient;
|
|
} else if (isRow) {
|
|
//todo check the case when the height depends on the width
|
|
const cleanBounds = shapeContainer.getBounds(true, true);
|
|
const cleanHeightCoefficient = parentHeight / (cleanBounds.b - cleanBounds.t);
|
|
if (cleanHeightCoefficient >= 1 || fAlgDeltaEqual(cleanHeightCoefficient, 1)) {
|
|
heightCoefficient = 1;
|
|
}
|
|
} else {
|
|
const cleanBounds = shapeContainer.getBounds(true, true);
|
|
const cleanWidthCoefficient = parentWidth / (cleanBounds.r - cleanBounds.l);
|
|
if (cleanWidthCoefficient >= 1 || fAlgDeltaEqual(cleanWidthCoefficient, 1)) {
|
|
widthCoefficient = 1;
|
|
}
|
|
}
|
|
|
|
const heightSizeScale = isRow ? 1 : heightCoefficient;
|
|
const widthSizeScale = isRow ? widthCoefficient : 1;
|
|
const nodes = [this.parentNode];
|
|
while (nodes.length) {
|
|
const node = nodes.pop();
|
|
for (let i = 0; i < node.childs.length; i += 1) {
|
|
const childNode = node.childs[i];
|
|
|
|
childNode.setSizesScale(widthSizeScale, heightSizeScale);
|
|
const shapeType = childNode.layoutInfo.shape.type;
|
|
if (shapeType !== AscFormat.LayoutShapeType_outputShapeType_none &&
|
|
shapeType !== AscFormat.LayoutShapeType_outputShapeType_conn) {
|
|
if (isRow) {
|
|
if (childNode.getAspectRatio()) {
|
|
childNode.setParentScale(AscFormat.Constr_type_w, heightCoefficient);
|
|
childNode.setParentScale(AscFormat.Constr_type_h, heightCoefficient);
|
|
} else {
|
|
childNode.setParentScale(AscFormat.Constr_type_h, heightCoefficient);
|
|
}
|
|
} else {
|
|
if (childNode.getAspectRatio()) {
|
|
childNode.setParentScale(AscFormat.Constr_type_w, widthCoefficient);
|
|
childNode.setParentScale(AscFormat.Constr_type_h, widthCoefficient);
|
|
} else {
|
|
childNode.setParentScale(AscFormat.Constr_type_w, widthCoefficient);
|
|
}
|
|
}
|
|
}
|
|
nodes.push(childNode);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
LinearAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm, isCalculateScaleCoefficients) {
|
|
this._calculateShapePositions(isCalculateScaleCoefficients);
|
|
this.applyNodeAligns(isCalculateScaleCoefficients);
|
|
this.applyAlgorithmAligns(isCalculateScaleCoefficients);
|
|
if (isCalculateScaleCoefficients) {
|
|
this.setScaleCoefficient();
|
|
} else {
|
|
this.setConnections();
|
|
}
|
|
this.createShadowShape(isCalculateScaleCoefficients);
|
|
};
|
|
LinearAlgorithm.prototype.calculateRowShapePositions = function (isCalculateScaleCoefficients) {
|
|
const fromLeft = this.isFromLeft();
|
|
const childs = this.parentNode.childs;
|
|
const length = this.isHideLastChild() ? childs.length - 1 : childs.length;
|
|
let offX = 0;
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficients);
|
|
const row = new ShapeContainer();
|
|
shapeContainer.push(row);
|
|
for (let i = 0; i < length; i++) {
|
|
const node = childs[i];
|
|
const shape = node.getShape(isCalculateScaleCoefficients);
|
|
const bounds = shape.getBounds();
|
|
row.push(shape);
|
|
if (fromLeft) {
|
|
shape.moveTo(offX - bounds.l, 0);
|
|
offX += bounds.r - bounds.l;
|
|
} else {
|
|
shape.moveTo(offX - bounds.r, 0);
|
|
offX -= bounds.r - bounds.l;
|
|
}
|
|
}
|
|
};
|
|
|
|
LinearAlgorithm.prototype.calculateColumnShapePositions = function (isCalculateScaleCoefficients) {
|
|
const fromTop = this.isFromTop();
|
|
const childs = this.parentNode.childs;
|
|
const length = this.isHideLastChild() ? childs.length - 1 : childs.length;
|
|
if (length === 0) {
|
|
return;
|
|
}
|
|
const shapeContainer = this.getShapeContainer(isCalculateScaleCoefficients, true);
|
|
const row = new ShapeContainer();
|
|
shapeContainer.push(row);
|
|
let offY = 0;
|
|
for (let i = 0; i < length; i++) {
|
|
const node = childs[i];
|
|
const shape = node.getShape(isCalculateScaleCoefficients);
|
|
row.push(shape);
|
|
const bounds = shape.getBounds();
|
|
if (fromTop) {
|
|
shape.moveTo(0, offY - bounds.t);
|
|
offY += bounds.b - bounds.t;
|
|
} else {
|
|
shape.moveTo(0, offY - bounds.b);
|
|
offY -= bounds.b - bounds.t;
|
|
}
|
|
}
|
|
};
|
|
LinearAlgorithm.prototype.getShapeContainer = function (isCalculateScaleCoefficient, isColumn) {
|
|
if (isCalculateScaleCoefficient) {
|
|
if (this.coefficientShapeContainer === null) {
|
|
if (isColumn) {
|
|
this.coefficientShapeContainer = new ShapeColumns();
|
|
} else {
|
|
this.coefficientShapeContainer = new ShapeRows();
|
|
}
|
|
|
|
}
|
|
return this.coefficientShapeContainer;
|
|
}
|
|
if (this.shapeContainer === null) {
|
|
if (isColumn) {
|
|
this.shapeContainer = new ShapeColumns();
|
|
} else {
|
|
this.shapeContainer = new ShapeRows();
|
|
}
|
|
}
|
|
return this.shapeContainer;
|
|
};
|
|
|
|
function ConnectorAlgorithm() {
|
|
BaseAlgorithm.call(this);
|
|
this.startNode = null;
|
|
this.endNode = null;
|
|
this.connectionDistances = {
|
|
begin: null,
|
|
end: null
|
|
};
|
|
this.stemThick = 0.6;
|
|
this.diameterScale = 1;
|
|
this.parentAlgorithm = null;
|
|
this.calcValues = {
|
|
edgePoints: null,
|
|
radiusCenterPoint: null,
|
|
connectionPoints: null,
|
|
pointPositions: null
|
|
}
|
|
}
|
|
AscFormat.InitClassWithoutType(ConnectorAlgorithm, BaseAlgorithm);
|
|
ConnectorAlgorithm.prototype.reset = function () {
|
|
this.calcValues = {
|
|
edgePoints: null,
|
|
radiusCenterPoint: null,
|
|
connectionPoints: null,
|
|
pointPositions: null
|
|
}
|
|
const connectionDistanceResolver = this.parentAlgorithm.parentNode.connectionDistanceResolver;
|
|
if (connectionDistanceResolver) {
|
|
connectionDistanceResolver.connectionDistance = null;
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.isClockwise = function () {
|
|
if (this.constrClockwise !== null) {
|
|
return this.constrClockwise;
|
|
}
|
|
return this.parentAlgorithm.isClockwise();
|
|
};
|
|
ConnectorAlgorithm.prototype.initParams = function (params) {
|
|
BaseAlgorithm.prototype.initParams.call(this, params);
|
|
if (this.params[AscFormat.Param_type_dim] === undefined) {
|
|
this.params[AscFormat.Param_type_dim] = AscFormat.ParameterVal_connectorDimension_2D;
|
|
}
|
|
if (this.params[AscFormat.Param_type_begSty] === undefined) {
|
|
this.params[AscFormat.Param_type_begSty] = AscFormat.ParameterVal_arrowheadStyle_noArr;
|
|
}
|
|
if (this.params[AscFormat.Param_type_endSty] === undefined) {
|
|
this.params[AscFormat.Param_type_endSty] = AscFormat.ParameterVal_arrowheadStyle_arr;
|
|
}
|
|
if (this.params[AscFormat.Param_type_connRout] === undefined) {
|
|
this.params[AscFormat.Param_type_connRout] = AscFormat.ParameterVal_connectorRouting_stra;
|
|
}
|
|
if (this.params[AscFormat.Param_type_connRout] === AscFormat.ParameterVal_connectorRouting_bend) {
|
|
if (this.params[AscFormat.Param_type_bendPt] === undefined) {
|
|
this.params[AscFormat.Param_type_bendPt] = AscFormat.ParameterVal_bendPoint_end;
|
|
}
|
|
}
|
|
}
|
|
|
|
ConnectorAlgorithm.prototype.getConnectionDistCoefficient = function (isBegin) {
|
|
switch (this.params[AscFormat.Param_type_connRout]) {
|
|
case AscFormat.ParameterVal_connectorRouting_bend:
|
|
if (!this.connectionDistances.begin && !this.connectionDistances.end) {
|
|
return isBegin ? 0 : 1;
|
|
} else {
|
|
if (isBegin) {
|
|
return this.connectionDistances.begin || 0;
|
|
} else {
|
|
return this.connectionDistances.end || 1;
|
|
}
|
|
}
|
|
case AscFormat.ParameterVal_connectorRouting_stra:
|
|
if (!this.connectionDistances.begin && !this.connectionDistances.end) {
|
|
if (this.params[AscFormat.Param_type_dim] === AscFormat.ParameterVal_connectorDimension_2D) {
|
|
return isBegin ? 0.22 : 0.25;
|
|
}
|
|
return 0;
|
|
}
|
|
return isBegin ? this.connectionDistances.begin : this.connectionDistances.end;
|
|
default:
|
|
return isBegin ? this.connectionDistances.begin : this.connectionDistances.end;
|
|
}
|
|
}
|
|
ConnectorAlgorithm.prototype.getEdgePoints = function () {
|
|
if (!this.calcValues.edgePoints) {
|
|
this.calcValues.edgePoints = {
|
|
start: null,
|
|
end: null
|
|
};
|
|
this.calcValues.pointPositions = {
|
|
start: null,
|
|
end: null
|
|
};
|
|
|
|
let calcStartEdgePoint;
|
|
let calcEndEdgePoint;
|
|
const startEdgePoints = this.getAvailableEdgePoints(true);
|
|
const endEdgePoints = this.getAvailableEdgePoints();
|
|
let minDistance = null;
|
|
for (let i = 0; i < startEdgePoints.length; i += 1) {
|
|
const startEdgePoint = startEdgePoints[i].point;
|
|
for (let j = 0; j < endEdgePoints.length; j += 1) {
|
|
const endEdgePoint = endEdgePoints[j].point;
|
|
const distance = startEdgePoint.getVector(endEdgePoint).getDistance();
|
|
if (minDistance === null || minDistance > distance) {
|
|
minDistance = distance;
|
|
calcStartEdgePoint = startEdgePoints[i];
|
|
calcEndEdgePoint = endEdgePoints[j];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (calcStartEdgePoint && calcEndEdgePoint) {
|
|
this.calcValues.edgePoints.start = calcStartEdgePoint.point;
|
|
this.calcValues.pointPositions.start = calcStartEdgePoint.type;
|
|
this.calcValues.edgePoints.end = calcEndEdgePoint.point;
|
|
this.calcValues.pointPositions.end = calcEndEdgePoint.type;
|
|
}
|
|
if (this.isCurveConnection()) {
|
|
this.calcCurveEdgePoints(this.calcValues.edgePoints.start, this.calcValues.edgePoints.end);
|
|
}
|
|
}
|
|
if (this.calcValues.edgePoints.start && this.calcValues.edgePoints.end) {
|
|
return this.calcValues.edgePoints;
|
|
}
|
|
return null;
|
|
};
|
|
ConnectorAlgorithm.prototype.getBendConnectionPoints = function (startPoint, endPoint) {
|
|
const vector = startPoint.getVector(endPoint);
|
|
const startConnectionPoint = this.getBendConnectionPoint(startPoint, startPoint, vector, true);
|
|
const endConnectionPoint = this.getBendConnectionPoint(endPoint, startPoint, vector, false);
|
|
return {start: startConnectionPoint, end: endConnectionPoint};
|
|
};
|
|
|
|
ConnectorAlgorithm.prototype.getBendConnectionPoint = function (point, startPoint, vector, isStart) {
|
|
const position = this.getPointPosition(isStart);
|
|
const coefficient = this.getConnectionDistCoefficient(isStart);
|
|
switch (position) {
|
|
case AscFormat.ParameterVal_connectorPoint_bCtr:
|
|
case AscFormat.ParameterVal_connectorPoint_tCtr:
|
|
return new CCoordPoint(point.x, vector.y * coefficient + startPoint.y);
|
|
case AscFormat.ParameterVal_connectorPoint_midR:
|
|
case AscFormat.ParameterVal_connectorPoint_midL:
|
|
case AscFormat.ParameterVal_connectorPoint_tL:
|
|
case AscFormat.ParameterVal_connectorPoint_bR:
|
|
case AscFormat.ParameterVal_connectorPoint_tR:
|
|
case AscFormat.ParameterVal_connectorPoint_bL:
|
|
return new CCoordPoint(vector.x * coefficient + startPoint.x, point.y);
|
|
case AscFormat.ParameterVal_connectorPoint_radial:
|
|
case AscFormat.ParameterVal_connectorPoint_auto:
|
|
default:
|
|
return null;
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.getStraightConnectionPoints = function (startPoint, endPoint) {
|
|
const startCoefficient = this.getConnectionDistCoefficient(true);
|
|
const endCoefficient = 1 - this.getConnectionDistCoefficient(false);
|
|
const endConnectionPoint = new CCoordPoint((endPoint.x - startPoint.x) * endCoefficient + startPoint.x, (endPoint.y - startPoint.y) * endCoefficient + startPoint.y);
|
|
const startConnectionPoint = new CCoordPoint((endPoint.x - startPoint.x) * startCoefficient + startPoint.x, (endPoint.y - startPoint.y) * startCoefficient + startPoint.y);
|
|
|
|
return {start: startConnectionPoint, end: endConnectionPoint};
|
|
};
|
|
ConnectorAlgorithm.prototype.getCenterPoint = function () {
|
|
if (this.calcValues.radiusCenterPoint) {
|
|
return this.calcValues.radiusCenterPoint;
|
|
}
|
|
if (this.parentAlgorithm instanceof CycleAlgorithm) {
|
|
const startShape = this.getStartShape();
|
|
if (startShape.radialVector) {
|
|
const bounds = startShape.getBounds();
|
|
const centerShapePoint = getShapePoint(bounds);
|
|
return new CCoordPoint(centerShapePoint.x - startShape.radialVector.x, centerShapePoint.y - startShape.radialVector.y);
|
|
}
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.getCurveConnectionPoints = function (startPoint, endPoint) {
|
|
const result = {start: null, end: null};
|
|
const centerPoint = this.getCenterPoint();
|
|
if (centerPoint) {
|
|
const startCoefficient = this.getConnectionDistCoefficient(true);
|
|
const endCoefficient = this.getConnectionDistCoefficient(false);
|
|
|
|
const startVector = centerPoint.getVector(startPoint);
|
|
const radius = startVector.getDistance();
|
|
const endVector = centerPoint.getVector(endPoint);
|
|
const angle = startVector.getAngleBetween(endVector, !this.isClockwise());
|
|
const startAngle = startVector.getAngle();
|
|
const endAngle = endVector.getAngle();
|
|
|
|
let startConnectionVector;
|
|
let endConnectionVector;
|
|
if (this.isClockwise() === this.isLongCurve()) {
|
|
startConnectionVector = CVector.getVectorByAngle(startAngle - angle * startCoefficient);
|
|
endConnectionVector = CVector.getVectorByAngle(endAngle + angle * endCoefficient);
|
|
} else {
|
|
startConnectionVector = CVector.getVectorByAngle(startAngle + angle * startCoefficient);
|
|
endConnectionVector = CVector.getVectorByAngle(endAngle - angle * endCoefficient);
|
|
}
|
|
result.start = new CCoordPoint(centerPoint.x + startConnectionVector.x * radius, centerPoint.y + startConnectionVector.y * radius);
|
|
result.end = new CCoordPoint(centerPoint.x + endConnectionVector.x * radius, centerPoint.y + endConnectionVector.y * radius);
|
|
}
|
|
return result;
|
|
};
|
|
ConnectorAlgorithm.prototype.getConnectionPoints = function () {
|
|
if (!this.calcValues.connectionPoints) {
|
|
this.calcValues.connectionPoints = {
|
|
start: null,
|
|
end : null
|
|
};
|
|
const edgePoints = this.getEdgePoints();
|
|
if (edgePoints) {
|
|
const startPoint = edgePoints.start;
|
|
const endPoint = edgePoints.end;
|
|
let connectionPoints;
|
|
switch (this.params[AscFormat.Param_type_connRout]) {
|
|
case AscFormat.ParameterVal_connectorRouting_bend:
|
|
connectionPoints = this.getBendConnectionPoints(startPoint, endPoint);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorRouting_stra:
|
|
connectionPoints = this.getStraightConnectionPoints(startPoint, endPoint);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorRouting_curve:
|
|
case AscFormat.ParameterVal_connectorRouting_longCurve:
|
|
connectionPoints = this.getCurveConnectionPoints(startPoint, endPoint);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (connectionPoints) {
|
|
this.calcValues.connectionPoints.start = connectionPoints.start;
|
|
this.calcValues.connectionPoints.end = connectionPoints.end;
|
|
}
|
|
}
|
|
}
|
|
return this.calcValues.connectionPoints;
|
|
}
|
|
ConnectorAlgorithm.prototype.setParentAlgorithm = function (algorithm) {
|
|
this.parentAlgorithm = algorithm;
|
|
};
|
|
ConnectorAlgorithm.prototype.setConnectionDistance = function (value, isStart) {
|
|
if (isStart) {
|
|
this.connectionDistances.begin = value;
|
|
} else {
|
|
this.connectionDistances.end = value;
|
|
}
|
|
};
|
|
BaseAlgorithm.prototype.setStemThick = function (value) {
|
|
this.stemThick = value;
|
|
};
|
|
ConnectorAlgorithm.prototype.getPointPosition = function (isStart) {
|
|
if (!this.calcValues.pointPositions) {
|
|
this.getEdgePoints();
|
|
}
|
|
return isStart ? this.calcValues.pointPositions.start : this.calcValues.pointPositions.end;
|
|
};
|
|
ConnectorAlgorithm.prototype.getStartShape = function () {
|
|
return this.startNode.getShape(false);
|
|
};
|
|
ConnectorAlgorithm.prototype.getEndShape = function () {
|
|
return this.endNode.getShape(false);
|
|
};
|
|
ConnectorAlgorithm.prototype.isAutoCenterPoint = function (isStart, isFromLayout) {
|
|
const connCoefficient = this.getConnectionDistCoefficient(isStart);
|
|
return connCoefficient === 0 && this.params[AscFormat.Param_type_dim] === AscFormat.ParameterVal_connectorDimension_2D &&
|
|
isFromLayout;
|
|
};
|
|
ConnectorAlgorithm.prototype.getAutoEdgePoint = function (isStart, isFromLayout) {
|
|
const startShape = this.getStartShape();
|
|
const endShape = this.getEndShape();
|
|
const startBounds = startShape.getBounds();
|
|
const endBounds = endShape.getBounds();
|
|
if (this.isAutoCenterPoint(isStart, isFromLayout)) {
|
|
return isStart ? getShapePoint(startBounds) : getShapePoint(endBounds);
|
|
}
|
|
const startPoint = getShapePoint(startBounds);
|
|
const endPoint = getShapePoint(endBounds);
|
|
let guideVector;
|
|
if (isStart) {
|
|
guideVector = new CVector(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
|
|
} else {
|
|
guideVector = new CVector(startPoint.x - endPoint.x, startPoint.y - endPoint.y);
|
|
}
|
|
if (fAlgDeltaEqual(guideVector.getDistance(), 0)) {
|
|
return null;
|
|
}
|
|
const bounds = isStart ? startBounds : endBounds;
|
|
return getMinShapeEdgePoint(bounds, guideVector);
|
|
};
|
|
ConnectorAlgorithm.prototype.getEllipseRadialEdgePoint = function (radialInfo, bounds, isStart) {
|
|
const cycleAngle = radialInfo.angle;
|
|
const centerPoint = radialInfo.point;
|
|
const radius = radialInfo.radius;
|
|
const shapeRadius = (bounds.r - bounds.l) / 2;
|
|
const shapeAngle = Math.acos(1 - ((shapeRadius * shapeRadius) / (2 * radius * radius)));
|
|
let angle = cycleAngle;
|
|
if (radialInfo.isClockwise) {
|
|
if (isStart) {
|
|
angle += shapeAngle;
|
|
} else {
|
|
angle -= shapeAngle;
|
|
}
|
|
} else {
|
|
if (isStart) {
|
|
angle -= shapeAngle;
|
|
} else {
|
|
angle += shapeAngle;
|
|
}
|
|
}
|
|
|
|
|
|
return new CCoordPoint(Math.cos(angle) * radius + centerPoint.x, Math.sin(angle) * radius + centerPoint.y);
|
|
};
|
|
ConnectorAlgorithm.prototype.isPointOnInterval = function (point, startSegment, endSegment) {
|
|
if (startSegment.x === endSegment.x) {
|
|
return (point.y > startSegment.y) && (point.y < endSegment.y) && !(fIntervalDeltaEqual(point.y, startSegment.y) || fIntervalDeltaEqual(point.y, endSegment.y));
|
|
} else {
|
|
return (point.x > startSegment.x) && (point.x < endSegment.x) && !(fIntervalDeltaEqual(point.x, startSegment.x) || fIntervalDeltaEqual(point.x, endSegment.x));
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.isPointOnSegment = function (point, startSegment, endSegment) {
|
|
if (startSegment.x === endSegment.x) {
|
|
return (point.y > startSegment.y || fIntervalDeltaEqual(point.y, startSegment.y)) && (point.y < endSegment.y || fIntervalDeltaEqual(point.y, endSegment.y));
|
|
} else {
|
|
return (point.x > startSegment.x || fIntervalDeltaEqual(point.x, startSegment.x)) && (point.x < endSegment.x || fIntervalDeltaEqual(point.x, endSegment.x));
|
|
}
|
|
}
|
|
ConnectorAlgorithm.prototype.getCycleRadius = function () {
|
|
const radiusCoefficient = this.parentAlgorithm.calcValues.radiusCoefficient || 1;
|
|
if (this.parentAlgorithm instanceof CycleAlgorithm) {
|
|
const diamScale = Math.abs(this.diameterScale);
|
|
return this.parentAlgorithm.calcValues.radius * radiusCoefficient * diamScale;
|
|
}
|
|
const constrDiam = this.parentNode.getConstr(AscFormat.Constr_type_diam, true, true);
|
|
if (constrDiam !== undefined) {
|
|
return Math.abs(constrDiam) / 2;
|
|
}
|
|
|
|
};
|
|
|
|
ConnectorAlgorithm.prototype.calcCurveEdgePoints = function (startPoint, endPoint) {
|
|
if (!(startPoint && endPoint)) {
|
|
startPoint = this.getAutoEdgePoint(true);
|
|
endPoint = this.getAutoEdgePoint();
|
|
}
|
|
if (!(startPoint && endPoint)) {
|
|
const startShape = this.getStartShape();
|
|
const endShape = this.getEndShape();
|
|
const startBounds = startShape.getBounds();
|
|
const endBounds = endShape.getBounds();
|
|
startPoint = getShapePoint(startBounds);
|
|
endPoint = getShapePoint(endBounds);
|
|
}
|
|
if (startPoint && endPoint) {
|
|
this.calcValues.edgePoints.start = startPoint;
|
|
this.calcValues.edgePoints.end = endPoint;
|
|
|
|
const cycleRadius = this.getCycleRadius();
|
|
const isClockwise = this.isClockwise();
|
|
const lineVector = startPoint.getVector(endPoint);
|
|
const circlesIntersectionPoints = AscFormat.circlesIntersection(startPoint.x, startPoint.y, cycleRadius, endPoint.x, endPoint.y, cycleRadius);
|
|
if (circlesIntersectionPoints.length) {
|
|
const firstEllipsePoint = new CCoordPoint(circlesIntersectionPoints[0].x, circlesIntersectionPoints[0].y);
|
|
const secondEllipsePoint = new CCoordPoint(circlesIntersectionPoints[1].x, circlesIntersectionPoints[1].y);
|
|
let _isClockwisePoints = isClockwisePoints(firstEllipsePoint, startPoint, endPoint);
|
|
|
|
if (_isClockwisePoints) {
|
|
this.calcValues.radiusCenterPoint = isClockwise ? firstEllipsePoint : secondEllipsePoint;
|
|
} else {
|
|
this.calcValues.radiusCenterPoint = isClockwise ? secondEllipsePoint : firstEllipsePoint;
|
|
}
|
|
} else {
|
|
this.calcValues.radiusCenterPoint = new CCoordPoint(startPoint.x + lineVector.x / 2, startPoint.y + lineVector.y / 2);
|
|
}
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.getRectRadialEdgePoint = function (radialInfo, bounds, isStart) {
|
|
const centerPoint = radialInfo.point;
|
|
const radius = radialInfo.radius;
|
|
const isClockwise = radialInfo.isClockwise;
|
|
|
|
const ellipseBounds = {
|
|
l: centerPoint.x - radius,
|
|
r: centerPoint.x + radius,
|
|
t: centerPoint.y - radius,
|
|
b: centerPoint.y + radius
|
|
};
|
|
|
|
const linePoints = [
|
|
[new CCoordPoint(bounds.l, bounds.t), new CCoordPoint(bounds.r, bounds.t)],
|
|
[new CCoordPoint(bounds.l, bounds.t), new CCoordPoint(bounds.l, bounds.b)],
|
|
[new CCoordPoint(bounds.l, bounds.b), new CCoordPoint(bounds.r, bounds.b)],
|
|
[new CCoordPoint(bounds.r, bounds.t), new CCoordPoint(bounds.r, bounds.b)]
|
|
];
|
|
const rectCenterPoint = getShapePoint(bounds);
|
|
for (let i = 0; i < linePoints.length; i += 1) {
|
|
const coords = linePoints[i];
|
|
const paramLine = getParametricLinEquation(coords[0], new CVector(coords[1].x - coords[0].x, coords[1].y - coords[0].y));
|
|
const answer = resolveParameterLineAndShapeEquation(ellipseBounds, paramLine);
|
|
if (!answer.bError) {
|
|
let point;
|
|
const point1 = new CCoordPoint(paramLine.x + paramLine.ax * answer.x1, paramLine.y + paramLine.ay * answer.x1);
|
|
const point2 = new CCoordPoint(paramLine.x + paramLine.ax * answer.x2, paramLine.y + paramLine.ay * answer.x2);
|
|
|
|
if (this.isPointOnInterval(point1, coords[0], coords[1]) && this.isPointOnInterval(point2, coords[0], coords[1])) {
|
|
continue;
|
|
} else if (this.isPointOnSegment(point1, coords[0], coords[1])) {
|
|
point = point1;
|
|
} else if (this.isPointOnSegment(point2, coords[0], coords[1])) {
|
|
point = point2;
|
|
} else {
|
|
continue;
|
|
}
|
|
if (isStart && isClockwise || !isStart && !isClockwise) {
|
|
if (isClockwisePoints(centerPoint, rectCenterPoint, point)) {
|
|
return point;
|
|
}
|
|
} else {
|
|
if (isClockwisePoints(centerPoint, point, rectCenterPoint)) {
|
|
return point;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
ConnectorAlgorithm.prototype.getRadialEdgePoint = function (isStart) {
|
|
const shape = isStart ? this.getStartShape() : this.getEndShape();
|
|
const radialInfo = this.parentAlgorithm.getRadialConnectionInfo(shape.node);
|
|
if (!radialInfo || radialInfo.radius === 0) {
|
|
return null;
|
|
}
|
|
|
|
const bounds = shape.getBounds();
|
|
if (bounds.isEllipse) {
|
|
return this.getEllipseRadialEdgePoint(radialInfo, bounds, isStart);
|
|
}
|
|
return this.getRectRadialEdgePoint(radialInfo, bounds, isStart);
|
|
};
|
|
ConnectorAlgorithm.prototype.getAvailablePointPositions = function (isStart) {
|
|
const parameters = isStart ? this.params[AscFormat.Param_type_begPts] : this.params[AscFormat.Param_type_endPts];
|
|
return parameters || [AscFormat.ParameterVal_connectorPoint_auto];
|
|
|
|
}
|
|
ConnectorAlgorithm.prototype.isCurveConnection = function () {
|
|
return this.params[AscFormat.Param_type_connRout] === AscFormat.ParameterVal_connectorRouting_curve ||
|
|
this.params[AscFormat.Param_type_connRout] === AscFormat.ParameterVal_connectorRouting_longCurve;
|
|
};
|
|
ConnectorAlgorithm.prototype.isCurveShape = function () {
|
|
return this.params[AscFormat.Param_type_connRout] === AscFormat.ParameterVal_connectorRouting_curve &&
|
|
this.params[AscFormat.Param_type_dim] === AscFormat.ParameterVal_connectorDimension_2D;
|
|
};
|
|
ConnectorAlgorithm.prototype.getAvailableEdgePoints = function (isStart) {
|
|
const result = [];
|
|
const pointPositions = this.getAvailablePointPositions(isStart);
|
|
for (let i = 0; i < pointPositions.length; i += 1) {
|
|
const type = pointPositions[i];
|
|
let point;
|
|
switch (type) {
|
|
case AscFormat.ParameterVal_connectorPoint_radial:
|
|
point = this.getRadialEdgePoint(isStart);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_tL:
|
|
point = this.getTopLeftEdgePoint(isStart);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_tCtr:
|
|
point = this.getTopCenterEdgePoint(isStart);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_tR:
|
|
point = this.getTopRightEdgePoint(isStart);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_midR:
|
|
point = this.getMidRightEdgePoint(isStart);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_bR:
|
|
point = this.getBottomRightEdgePoint(isStart);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_bCtr:
|
|
point = this.getBottomCenterEdgePoint(isStart);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_bL:
|
|
point = this.getBottomLeftEdgePoint(isStart);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_midL:
|
|
point = this.getMidLeftEdgePoint(isStart);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_auto:
|
|
default:
|
|
point = this.getAutoEdgePoint(isStart, true);
|
|
break;
|
|
}
|
|
if (point) {
|
|
result.push({point: point, type: type});
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
ConnectorAlgorithm.prototype.getTopLeftEdgePoint = function (isStart) {
|
|
const shape = isStart ? this.getStartShape() : this.getEndShape();
|
|
const bounds = shape.getBounds();
|
|
return new CCoordPoint(bounds.l, bounds.t);
|
|
};
|
|
ConnectorAlgorithm.prototype.getTopCenterEdgePoint = function (isStart) {
|
|
const shape = isStart ? this.getStartShape() : this.getEndShape();
|
|
const bounds = shape.getBounds();
|
|
return new CCoordPoint(bounds.l + (bounds.r - bounds.l) / 2, bounds.t);
|
|
};
|
|
ConnectorAlgorithm.prototype.getTopRightEdgePoint = function (isStart) {
|
|
const shape = isStart ? this.getStartShape() : this.getEndShape();
|
|
const bounds = shape.getBounds();
|
|
return new CCoordPoint(bounds.r, bounds.t);
|
|
};
|
|
ConnectorAlgorithm.prototype.getMidRightEdgePoint = function (isStart) {
|
|
const shape = isStart ? this.getStartShape() : this.getEndShape();
|
|
const bounds = shape.getBounds();
|
|
return new CCoordPoint(bounds.r, bounds.t + (bounds.b - bounds.t) / 2);
|
|
};
|
|
ConnectorAlgorithm.prototype.getBottomRightEdgePoint = function (isStart) {
|
|
const shape = isStart ? this.getStartShape() : this.getEndShape();
|
|
const bounds = shape.getBounds();
|
|
return new CCoordPoint(bounds.r, bounds.b);
|
|
};
|
|
ConnectorAlgorithm.prototype.getBottomCenterEdgePoint = function (isStart) {
|
|
const shape = isStart ? this.getStartShape() : this.getEndShape();
|
|
const bounds = shape.getBounds();
|
|
return new CCoordPoint(bounds.l + (bounds.r - bounds.l) / 2, bounds.b);
|
|
};
|
|
ConnectorAlgorithm.prototype.getBottomLeftEdgePoint = function (isStart) {
|
|
const shape = isStart ? this.getStartShape() : this.getEndShape();
|
|
const bounds = shape.getBounds();
|
|
return new CCoordPoint(bounds.l, bounds.b);
|
|
};
|
|
ConnectorAlgorithm.prototype.getMidLeftEdgePoint = function (isStart) {
|
|
const shape = isStart ? this.getStartShape() : this.getEndShape();
|
|
const bounds = shape.getBounds();
|
|
return new CCoordPoint(bounds.l, bounds.t + (bounds.b - bounds.t) / 2);
|
|
};
|
|
|
|
ConnectorAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createShadowShape(false, isCalculateScaleCoefficients);
|
|
};
|
|
ConnectorAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm, isCalculateScaleCoefficients) {
|
|
this.createShadowShape(isCalculateScaleCoefficients);
|
|
if (!isCalculateScaleCoefficients) {
|
|
smartartAlgorithm.addConnectorAlgorithm(this);
|
|
}
|
|
}
|
|
|
|
ConnectorAlgorithm.prototype.setFirstConnectorNode = function (node) {
|
|
this.startNode = node;
|
|
};
|
|
ConnectorAlgorithm.prototype.setLastConnectorNode = function (node) {
|
|
this.endNode = node;
|
|
};
|
|
ConnectorAlgorithm.prototype.connectShapes = function (smartartAlgorithm) {
|
|
if (this.startNode && this.endNode) {
|
|
if (this.params[AscFormat.Param_type_dim] === AscFormat.ParameterVal_connectorDimension_2D) {
|
|
this.createShapeConnector(smartartAlgorithm);
|
|
} else if (this.params[AscFormat.Param_type_dim] === AscFormat.ParameterVal_connectorDimension_1D) {
|
|
this.createLineConnector();
|
|
}
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.getStraightAdjLst = function (shapeType) {
|
|
if (shapeType !== AscFormat.LayoutShapeType_shapeType_rect) {
|
|
const customAdjLst = new AscFormat.AdjLst();
|
|
const adj1 = new AscFormat.Adj();
|
|
const adj2 = new AscFormat.Adj();
|
|
adj1.setIdx(1);
|
|
adj2.setIdx(2);
|
|
adj1.setVal(this.stemThick);
|
|
adj2.setVal(0.5);
|
|
customAdjLst.addToLst(0, adj1);
|
|
customAdjLst.addToLst(0, adj2);
|
|
return customAdjLst;
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.isLongCurve = function () {
|
|
return this.params[AscFormat.Param_type_connRout] === AscFormat.ParameterVal_connectorRouting_longCurve;
|
|
}
|
|
ConnectorAlgorithm.prototype.getConnectorShapeType = function () {
|
|
const endStyle = this.params[AscFormat.Param_type_endSty];
|
|
const beginStyle = this.params[AscFormat.Param_type_begSty];
|
|
if (this.params[AscFormat.Param_type_connRout] === AscFormat.ParameterVal_connectorRouting_curve) {
|
|
if (endStyle === AscFormat.ParameterVal_arrowheadStyle_arr && beginStyle === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
return AscFormat.LayoutShapeType_shapeType_leftRightCircularArrow;
|
|
} else if (endStyle === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
if (this.isClockwise()) {
|
|
return AscFormat.LayoutShapeType_shapeType_circularArrow;
|
|
}
|
|
return AscFormat.LayoutShapeType_shapeType_leftCircularArrow;
|
|
} else if (beginStyle === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
if (this.isClockwise()) {
|
|
return AscFormat.LayoutShapeType_shapeType_leftCircularArrow;
|
|
}
|
|
return AscFormat.LayoutShapeType_shapeType_circularArrow;
|
|
}
|
|
return AscFormat.LayoutShapeType_shapeType_blockArc;
|
|
} else if (this.isLongCurve()) {
|
|
if (endStyle === AscFormat.ParameterVal_arrowheadStyle_arr && beginStyle === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
return AscFormat.LayoutShapeType_shapeType_leftRightCircularArrow;
|
|
} else if (endStyle === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
if (this.isClockwise()) {
|
|
return AscFormat.LayoutShapeType_shapeType_leftCircularArrow;
|
|
}
|
|
return AscFormat.LayoutShapeType_shapeType_circularArrow;
|
|
} else if (beginStyle === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
if (this.isClockwise()) {
|
|
return AscFormat.LayoutShapeType_shapeType_circularArrow;
|
|
}
|
|
return AscFormat.LayoutShapeType_shapeType_leftCircularArrow;
|
|
}
|
|
return AscFormat.LayoutShapeType_shapeType_blockArc;
|
|
} else {
|
|
if (endStyle === AscFormat.ParameterVal_arrowheadStyle_arr && beginStyle === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
return AscFormat.LayoutShapeType_shapeType_leftRightArrow;
|
|
} else if (endStyle === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
return AscFormat.LayoutShapeType_shapeType_rightArrow;
|
|
} else if (beginStyle === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
return AscFormat.LayoutShapeType_shapeType_leftArrow;
|
|
}
|
|
return AscFormat.LayoutShapeType_shapeType_rect;
|
|
}
|
|
}
|
|
ConnectorAlgorithm.prototype.getTemplateConnectorShape = function () {
|
|
const shape = this.parentNode.shape;
|
|
const connectorShape = new ShadowShape();
|
|
connectorShape.shape = shape.shape;
|
|
|
|
connectorShape.type = this.getConnectorShapeType();
|
|
connectorShape.cleanParams = {};
|
|
connectorShape.cleanParams.width = shape.cleanParams.width;
|
|
connectorShape.cleanParams.height = shape.cleanParams.height;
|
|
connectorShape.cleanParams.x = shape.cleanParams.x;
|
|
connectorShape.cleanParams.y = shape.cleanParams.y;
|
|
connectorShape.node = this.parentNode;
|
|
return connectorShape;
|
|
};
|
|
|
|
ConnectorAlgorithm.prototype.createBlockArcCurveShapeConnector = function (startAngle, endAngle, radius) {
|
|
const connectorShape = this.getTemplateConnectorShape();
|
|
const connectorHeight = this.parentNode.getConstr(AscFormat.Constr_type_h, true);
|
|
const stemThick = (connectorHeight / radius) / 3.4;
|
|
const customAdjLst = new AscFormat.AdjLst();
|
|
const adj1 = new AscFormat.Adj();
|
|
const adj2 = new AscFormat.Adj();
|
|
const adj3 = new AscFormat.Adj();
|
|
adj1.setIdx(1);
|
|
adj2.setIdx(2);
|
|
adj3.setIdx(3);
|
|
adj1.setVal(startAngle * radToDeg);
|
|
adj2.setVal(endAngle * radToDeg);
|
|
adj3.setVal(stemThick);
|
|
customAdjLst.addToLst(0, adj1);
|
|
customAdjLst.addToLst(0, adj2);
|
|
customAdjLst.addToLst(0, adj3);
|
|
connectorShape.customAdj = customAdjLst;
|
|
|
|
const centerPoint = this.getCenterPoint();
|
|
const absRadius = Math.abs(radius);
|
|
const diameterSide = absRadius * 2;
|
|
const truthSide = diameterSide / (1 - stemThick / 2);
|
|
const truthRadius = truthSide / 2;
|
|
connectorShape.width = truthSide;
|
|
connectorShape.height = truthSide;
|
|
connectorShape.x = centerPoint.x - truthRadius;
|
|
connectorShape.y = centerPoint.y - truthRadius;
|
|
const shape = this.parentNode.getShape();
|
|
shape.connectorShape = connectorShape;
|
|
};
|
|
ConnectorAlgorithm.prototype.createCircularArrowCurveShapeConnector = function (startAngle, endAngle, radius) {
|
|
const connectorShape = this.getTemplateConnectorShape();
|
|
const connectorHeight = this.parentNode.getConstr(AscFormat.Constr_type_h, true, true);
|
|
const constrArrowWidth = this.parentNode.getConstr(AscFormat.Constr_type_wArH, true, true);
|
|
const constrStemThick = this.parentNode.getConstr(AscFormat.Constr_type_stemThick, true, true);
|
|
const constrArrowHeight = this.parentNode.getConstr(AscFormat.Constr_type_hArH, true, true);
|
|
let adjArrowWidth;
|
|
let stemThick;
|
|
let adjArrowHeight;
|
|
let truthSide;
|
|
// todo: increase accuracy in Continuous Cycle
|
|
if (constrArrowWidth !== undefined && constrStemThick !== undefined && constrArrowHeight !== undefined) {
|
|
const diam = radius * 2;
|
|
const diamScale = Math.abs(this.diameterScale);
|
|
if (connectorHeight !== undefined) {
|
|
adjArrowWidth = constrArrowWidth / radius * 0.6195;
|
|
stemThick = adjArrowWidth / 1.16666;
|
|
adjArrowHeight = (constrArrowHeight / radius) * 28.65983;
|
|
truthSide = (diam / (1 - adjArrowWidth * 2)) * 0.98999;
|
|
} else {
|
|
adjArrowWidth = 1 / (diamScale) * 0.0598728;
|
|
stemThick = adjArrowWidth * 0.963;
|
|
adjArrowHeight = (1 / diamScale) * 5.731787;
|
|
truthSide = (diam / (1 - adjArrowWidth * 2)) * 0.9965;
|
|
}
|
|
} else if (connectorHeight !== undefined) {
|
|
const addValue = connectorHeight * 0.15;
|
|
truthSide = ((radius + addValue) * 2 + connectorHeight);
|
|
adjArrowWidth = 0.5 - ((radius - addValue / 3) / truthSide);
|
|
stemThick = adjArrowWidth * 0.85718;
|
|
adjArrowHeight = (connectorHeight / radius) * radToDeg / 2;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
|
|
const customAdjLst = new AscFormat.AdjLst();
|
|
const adj1 = new AscFormat.Adj();
|
|
const adj2 = new AscFormat.Adj();
|
|
const adj3 = new AscFormat.Adj();
|
|
const adj4 = new AscFormat.Adj();
|
|
const adj5 = new AscFormat.Adj();
|
|
adj1.setIdx(1);
|
|
adj2.setIdx(2);
|
|
adj3.setIdx(3);
|
|
adj4.setIdx(4);
|
|
adj5.setIdx(5);
|
|
adj1.setVal(stemThick);
|
|
adj2.setVal(adjArrowHeight);
|
|
if (this.getConnectorShapeType() === AscFormat.LayoutShapeType_shapeType_circularArrow) {
|
|
adj3.setVal(endAngle * radToDeg - adjArrowHeight);
|
|
adj4.setVal(startAngle * radToDeg);
|
|
} else {
|
|
adj3.setVal(startAngle * radToDeg + adjArrowHeight);
|
|
adj4.setVal(endAngle * radToDeg);
|
|
}
|
|
adj5.setVal(adjArrowWidth);
|
|
customAdjLst.addToLst(0, adj1);
|
|
customAdjLst.addToLst(0, adj2);
|
|
customAdjLst.addToLst(0, adj3);
|
|
customAdjLst.addToLst(0, adj4);
|
|
customAdjLst.addToLst(0, adj5);
|
|
connectorShape.customAdj = customAdjLst;
|
|
|
|
const centerPoint = this.getCenterPoint();
|
|
const truthRadius = truthSide / 2;
|
|
connectorShape.width = truthSide;
|
|
connectorShape.height = truthSide;
|
|
connectorShape.x = centerPoint.x - truthRadius;
|
|
connectorShape.y = centerPoint.y - truthRadius;
|
|
const shape = this.parentNode.getShape();
|
|
shape.connectorShape = connectorShape;
|
|
};
|
|
ConnectorAlgorithm.prototype.createCurveShapeConnector = function (smartartAlgorithm, startPoint, endPoint) {
|
|
const centerPoint = this.getCenterPoint();
|
|
const startVector = centerPoint.getVector(startPoint);
|
|
const endVector = centerPoint.getVector(endPoint);
|
|
let startAngle = startVector.getAngle();
|
|
let endAngle = endVector.getAngle();
|
|
const isClockwise = this.isClockwise();
|
|
if (fAlgDeltaEqual(startAngle, endAngle)) {
|
|
endAngle = startAngle + 0.000001;
|
|
} else if (isClockwise === this.isLongCurve()) {
|
|
const temp = startAngle;
|
|
startAngle = endAngle;
|
|
endAngle = temp;
|
|
}
|
|
const radius = startVector.getDistance();
|
|
switch (this.getConnectorShapeType()) {
|
|
case AscFormat.LayoutShapeType_shapeType_blockArc:
|
|
this.createBlockArcCurveShapeConnector(startAngle, endAngle, radius);
|
|
break;
|
|
case AscFormat.LayoutShapeType_shapeType_circularArrow:
|
|
case AscFormat.LayoutShapeType_shapeType_leftCircularArrow:
|
|
this.createCircularArrowCurveShapeConnector(startAngle, endAngle, radius);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
const shape = this.parentNode.getShape();
|
|
const connectorShape = shape.connectorShape;
|
|
if (connectorShape) {
|
|
const coefficient = connectorShape.width / shape.cleanParams.width;
|
|
const heightScale = this.parentNode.getHeightScale(true);
|
|
const widthScale = this.parentNode.getWidthScale(true);
|
|
const newWidth = connectorShape.width * widthScale;
|
|
const newHeight = connectorShape.height * heightScale;
|
|
connectorShape.x += (connectorShape.width - newWidth) / 2;
|
|
connectorShape.y += (connectorShape.height - newHeight) / 2;
|
|
connectorShape.width = newWidth;
|
|
connectorShape.height = newHeight;
|
|
this.applyPostAlgorithmSettingsForShape(smartartAlgorithm, connectorShape, coefficient);
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.createStraightShapeConnector = function (smartartAlgorithm, startPoint, endPoint) {
|
|
const cx = (startPoint.x + endPoint.x) / 2;
|
|
const cy = (startPoint.y + endPoint.y) / 2;
|
|
|
|
const arrowVector = new CVector(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
|
|
|
|
let width;
|
|
const connectionDistanceResolver = this.parentAlgorithm.parentNode.connectionDistanceResolver;
|
|
const minConnectionDistance = connectionDistanceResolver && connectionDistanceResolver.getConnectionDistance();
|
|
if (connectionDistanceResolver && minConnectionDistance !== -1) {
|
|
width = minConnectionDistance;
|
|
} else {
|
|
width = arrowVector.getDistance();
|
|
}
|
|
const constrObj = this.parentNode.getConstraints(true);
|
|
const height = constrObj[AscFormat.Constr_type_hArH] !== undefined ? constrObj[AscFormat.Constr_type_hArH] : this.parentNode.shape.height;
|
|
|
|
const x = cx - width / 2;
|
|
const y = cy - height / 2;
|
|
const shape = this.parentNode.getShape();
|
|
const connectorShape = this.getTemplateConnectorShape();
|
|
connectorShape.customAdj = this.getStraightAdjLst(connectorShape.type);
|
|
|
|
connectorShape.x = x;
|
|
connectorShape.y = y;
|
|
connectorShape.rot = arrowVector.getAngle();
|
|
shape.connectorShape = connectorShape;
|
|
|
|
const prSet = this.parentNode.getPrSet();
|
|
if (!prSet.getPresStyleLbl()) {
|
|
prSet.setPresStyleLbl("sibTrans2D1");
|
|
}
|
|
const coefficient = width / shape.cleanParams.width;
|
|
this.applyPostAlgorithmSettings(smartartAlgorithm, connectorShape, coefficient);
|
|
|
|
const heightScale = this.parentNode.getHeightScale(true);
|
|
const widthScale = this.parentNode.getWidthScale(true);
|
|
const scaleHeight = height * heightScale;
|
|
const scaleWidth = width * widthScale;
|
|
connectorShape.height = scaleHeight;
|
|
connectorShape.width = scaleWidth;
|
|
connectorShape.x += (width - scaleWidth) / 2;
|
|
connectorShape.y += (height - scaleHeight) / 2;
|
|
};
|
|
ConnectorAlgorithm.prototype.createShapeConnector = function (smartartAlgorithm) {
|
|
const connectionPoints = this.getConnectionPoints();
|
|
const startArrowPoint = connectionPoints.start;
|
|
const endArrowPoint = connectionPoints.end;
|
|
if (startArrowPoint && endArrowPoint) {
|
|
switch (this.params[AscFormat.Param_type_connRout]) {
|
|
case AscFormat.ParameterVal_connectorRouting_longCurve:
|
|
case AscFormat.ParameterVal_connectorRouting_curve:
|
|
this.createCurveShapeConnector(smartartAlgorithm, startArrowPoint, endArrowPoint);
|
|
break;
|
|
default:
|
|
this.createStraightShapeConnector(smartartAlgorithm, startArrowPoint, endArrowPoint);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
ConnectorAlgorithm.prototype.createLineConnector = function () {
|
|
const points = this.getConnectionPoints();
|
|
if (points.start && points.end) {
|
|
switch (this.params[AscFormat.Param_type_connRout]) {
|
|
case AscFormat.ParameterVal_connectorRouting_stra:
|
|
this.createStraightLineConnector(points.start, points.end);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorRouting_bend:
|
|
this.createBendLineConnector(points.start, points.end);
|
|
break;
|
|
case AscFormat.ParameterVal_connectorRouting_curve:
|
|
this.createCurveLineConnector(points.start, points.end);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.getStraightConnectionInfo = function (startPoint, endPoint) {
|
|
const cx = (startPoint.x + endPoint.x) / 2;
|
|
const cy = (startPoint.y + endPoint.y) / 2;
|
|
|
|
const arrowVector = new CVector(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
|
|
|
|
let width;
|
|
const connectionDistanceResolver = this.parentAlgorithm.parentNode.connectionDistanceResolver;
|
|
const minConnectionDistance = connectionDistanceResolver && connectionDistanceResolver.getConnectionDistance();
|
|
if (connectionDistanceResolver && minConnectionDistance !== -1) {
|
|
width = minConnectionDistance;
|
|
} else {
|
|
width = arrowVector.getDistance();
|
|
}
|
|
const shape = this.parentNode.shape;
|
|
const height = shape.height;
|
|
|
|
const x = cx - width / 2;
|
|
const y = cy - height / 2;
|
|
|
|
const coefficient = width / shape.cleanParams.width;
|
|
|
|
const heightScale = this.parentNode.getHeightScale(true);
|
|
const widthScale = this.parentNode.getWidthScale(true);
|
|
const scaleHeight = height * heightScale;
|
|
const scaleWidth = width * widthScale;
|
|
|
|
return {
|
|
x: x,
|
|
y: y,
|
|
width: scaleWidth,
|
|
height: scaleHeight,
|
|
offX: (width - scaleWidth) / 2,
|
|
offY: (height - scaleHeight) / 2,
|
|
rot: arrowVector.getAngle(),
|
|
coefficient: coefficient
|
|
}
|
|
}
|
|
ConnectorAlgorithm.prototype.isDoubleBendHorizontalConnector = function() {
|
|
const startPoint = this.getPointPosition(true);
|
|
const endPoint = this.getPointPosition();
|
|
return startPoint === AscFormat.ParameterVal_connectorPoint_midR && endPoint === AscFormat.ParameterVal_connectorPoint_midL ||
|
|
startPoint === AscFormat.ParameterVal_connectorPoint_midL && endPoint === AscFormat.ParameterVal_connectorPoint_midR;
|
|
};
|
|
ConnectorAlgorithm.prototype.isDoubleBendVerticalConnector = function() {
|
|
const startPoint = this.getPointPosition(true);
|
|
const endPoint = this.getPointPosition();
|
|
return startPoint === AscFormat.ParameterVal_connectorPoint_bCtr && endPoint === AscFormat.ParameterVal_connectorPoint_tCtr ||
|
|
startPoint === AscFormat.ParameterVal_connectorPoint_tCtr && endPoint === AscFormat.ParameterVal_connectorPoint_bCtr;
|
|
};
|
|
ConnectorAlgorithm.prototype.isWrongBendPoints = function (startPoint, endPoint) {
|
|
const endPointPosition = this.getPointPosition();
|
|
const startPointPosition = this.getPointPosition(true);
|
|
switch (endPointPosition) {
|
|
case AscFormat.ParameterVal_connectorPoint_tCtr:
|
|
if ((endPoint.y <= startPoint.y) ||
|
|
(startPointPosition === AscFormat.ParameterVal_connectorPoint_midR && endPoint.x <= startPoint.x) ||
|
|
(startPointPosition === AscFormat.ParameterVal_connectorPoint_midL && endPoint.x >= startPoint.x)) {
|
|
return true;
|
|
}
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_bCtr:
|
|
if ((endPoint.y >= startPoint.y) ||
|
|
(startPointPosition === AscFormat.ParameterVal_connectorPoint_midR && endPoint.x <= startPoint.x) ||
|
|
(startPointPosition === AscFormat.ParameterVal_connectorPoint_midL && endPoint.x >= startPoint.x)) {
|
|
return true;
|
|
}
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_midR:
|
|
case AscFormat.ParameterVal_connectorPoint_bR:
|
|
if ((endPoint.x >= startPoint.x) ||
|
|
((startPointPosition === AscFormat.ParameterVal_connectorPoint_bCtr ||
|
|
startPointPosition === AscFormat.ParameterVal_connectorPoint_tCtr) && endPoint.y <= startPoint.y)) {
|
|
return true;
|
|
}
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_midL:
|
|
case AscFormat.ParameterVal_connectorPoint_bL:
|
|
if ((endPoint.x <= startPoint.x) ||
|
|
((startPointPosition === AscFormat.ParameterVal_connectorPoint_bCtr ||
|
|
startPointPosition === AscFormat.ParameterVal_connectorPoint_tCtr) && endPoint.y <= startPoint.y)) {
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
return false;
|
|
};
|
|
ConnectorAlgorithm.prototype.getBendPoints = function (startPoint, endPoint) {
|
|
if (this.isWrongBendPoints(startPoint, endPoint)) {
|
|
return [];
|
|
}
|
|
const isReverse = this.params[AscFormat.Param_type_bendPt] === AscFormat.ParameterVal_bendPoint_end;
|
|
const edgePoints = this.getEdgePoints();
|
|
let startEdgePoint = edgePoints.start;
|
|
let endEdgePoint = edgePoints.end;
|
|
if (isReverse) {
|
|
const t = startPoint;
|
|
startPoint = endPoint;
|
|
endPoint = t;
|
|
startEdgePoint = edgePoints.end;
|
|
endEdgePoint = edgePoints.start;
|
|
}
|
|
let bendDist;
|
|
if (this.isDoubleBendHorizontalConnector()) {
|
|
bendDist = this.parentNode.adaptConstr[AscFormat.Constr_type_bendDist];
|
|
if (bendDist === undefined) {
|
|
bendDist = Math.abs(startEdgePoint.x - endEdgePoint.x) / 2;
|
|
}
|
|
} else if (this.isDoubleBendVerticalConnector()) {
|
|
bendDist = this.parentNode.adaptConstr[AscFormat.Constr_type_bendDist];
|
|
if (bendDist === undefined) {
|
|
bendDist = Math.abs(startEdgePoint.y - endEdgePoint.y) / 2;
|
|
}
|
|
}
|
|
const type = this.getPointPosition(!isReverse);
|
|
let bendPoints;
|
|
switch (type) {
|
|
case AscFormat.ParameterVal_connectorPoint_auto:
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_bCtr: {
|
|
if (bendDist === undefined) {
|
|
bendPoints = [new CCoordPoint(startPoint.x, endPoint.y)];
|
|
} else {
|
|
let y = Math.min(endPoint.y, startEdgePoint.y + bendDist);
|
|
bendPoints = [new CCoordPoint(startEdgePoint.x, y), new CCoordPoint(endEdgePoint.x, y)];
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.ParameterVal_connectorPoint_ctr:
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_bL:
|
|
case AscFormat.ParameterVal_connectorPoint_midL: {
|
|
if (bendDist === undefined) {
|
|
bendPoints = [new CCoordPoint(endPoint.x, startPoint.y)];
|
|
} else {
|
|
let x = Math.max(endPoint.x, startEdgePoint.x - bendDist);
|
|
bendPoints = [new CCoordPoint(x, startEdgePoint.y), new CCoordPoint(x, endEdgePoint.y)];
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.ParameterVal_connectorPoint_bR:
|
|
case AscFormat.ParameterVal_connectorPoint_midR: {
|
|
if (bendDist === undefined) {
|
|
bendPoints = [new CCoordPoint(endPoint.x, startPoint.y)];
|
|
} else {
|
|
let x = Math.min(endPoint.x, startEdgePoint.x + bendDist);
|
|
bendPoints = [new CCoordPoint(x, startEdgePoint.y), new CCoordPoint(x, endEdgePoint.y)];
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.ParameterVal_connectorPoint_radial:
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_tCtr: {
|
|
if (bendDist === undefined) {
|
|
bendPoints = [new CCoordPoint(startPoint.x, endPoint.y)];
|
|
} else {
|
|
let y = Math.max(endPoint.y, startEdgePoint.y - bendDist);
|
|
bendPoints = [new CCoordPoint(startEdgePoint.x, y), new CCoordPoint(endEdgePoint.x, y)];
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.ParameterVal_connectorPoint_tL:
|
|
break;
|
|
case AscFormat.ParameterVal_connectorPoint_tR:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (bendPoints) {
|
|
return isReverse ? bendPoints.reverse() : bendPoints;
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.getStartBendPoint = function (startPoint, endPoint) {
|
|
|
|
};
|
|
ConnectorAlgorithm.prototype.getEndBendPoint = function (startPoint, endPoint) {
|
|
|
|
};
|
|
ConnectorAlgorithm.prototype.getBendConnectionInfo = function (startPoint, endPoint) {
|
|
const x = endPoint.x < startPoint.x ? endPoint.x : startPoint.x;
|
|
const y = endPoint.y < startPoint.y ? endPoint.y : startPoint.y;
|
|
const width = Math.abs(endPoint.x - startPoint.x);
|
|
const height = Math.abs(endPoint.y - startPoint.y);
|
|
const bendPoints = this.getBendPoints(startPoint, endPoint);
|
|
return {
|
|
x: x,
|
|
y: y,
|
|
width: width,
|
|
height: height,
|
|
bendPoints: bendPoints
|
|
};
|
|
}
|
|
ConnectorAlgorithm.prototype.createBendLineConnector = function (startPoint, endPoint) {
|
|
const shape = this.parentNode.getShape(false);
|
|
shape.height = 0;
|
|
const info = this.getBendConnectionInfo(startPoint, endPoint);
|
|
const connectorShape = this.getTemplateConnectorLine();
|
|
|
|
connectorShape.x = info.x;
|
|
connectorShape.y = info.y;
|
|
connectorShape.width = info.width;
|
|
connectorShape.height = info.height;
|
|
|
|
shape.connectorShape = connectorShape;
|
|
|
|
const prSet = this.parentNode.getPrSet();
|
|
if (!prSet.getPresStyleLbl()) {
|
|
prSet.setPresStyleLbl("parChTrans1D2");
|
|
}
|
|
|
|
const bendPoints = info.bendPoints;
|
|
const localEndPoint = new CCoordPoint(endPoint.x - connectorShape.x, endPoint.y - connectorShape.y);
|
|
const localStartPoint = new CCoordPoint(startPoint.x - connectorShape.x, startPoint.y - connectorShape.y);
|
|
if (bendPoints) {
|
|
connectorShape.customGeom.push([0]);
|
|
connectorShape.customGeom.push([1, localStartPoint.x * 36000, localStartPoint.y * 36000]);
|
|
for (let i = 0; i < bendPoints.length; i++) {
|
|
const bendPoint = bendPoints[i];
|
|
const localBendPoint = new CCoordPoint(bendPoint.x - connectorShape.x, bendPoint.y - connectorShape.y);
|
|
connectorShape.customGeom.push([2, localBendPoint.x * 36000, localBendPoint.y * 36000]);
|
|
}
|
|
connectorShape.customGeom.push([2, localEndPoint.x * 36000, localEndPoint.y * 36000]);
|
|
|
|
} else {
|
|
connectorShape.customGeom.push([0]);
|
|
connectorShape.customGeom.push([1, localStartPoint.x * 36000, localStartPoint.y * 36000]);
|
|
connectorShape.customGeom.push([2, localEndPoint.x * 36000, localEndPoint.y * 36000]);
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.createCurveLineConnector = function (startPoint, endPoint) {
|
|
const centerPoint = this.calcValues.radiusCenterPoint;
|
|
if (centerPoint) {
|
|
const shape = this.parentNode.getShape();
|
|
const prSet = this.parentNode.getPrSet();
|
|
if (!prSet.getPresStyleLbl()) {
|
|
prSet.setPresStyleLbl("sibTrans1D1");
|
|
}
|
|
const startVector = centerPoint.getVector(startPoint);
|
|
const endVector = centerPoint.getVector(endPoint);
|
|
|
|
const radius = startVector.getDistance();
|
|
const side = radius * 2;
|
|
|
|
const isClockwise = this.isClockwise();
|
|
const swAngle = isClockwise ? startVector.getAngleBetween(endVector) : -startVector.getAngleBetween(endVector, true);
|
|
|
|
const connectorShape = this.getTemplateConnectorLine();
|
|
connectorShape.width = side;
|
|
connectorShape.height = side;
|
|
connectorShape.x = centerPoint.x - radius;
|
|
connectorShape.y = centerPoint.y - radius;
|
|
|
|
shape.connectorShape = connectorShape;
|
|
|
|
|
|
connectorShape.customGeom.push([0]);
|
|
connectorShape.customGeom.push([1, (startPoint.x - connectorShape.x) * 36000, (startPoint.y - connectorShape.y) * 36000]);
|
|
const startAngle = startVector.getAngle();
|
|
connectorShape.customGeom.push([3, radius * 36000, radius * 36000, startAngle * radToDeg * 60000, swAngle * radToDeg * 60000]);
|
|
}
|
|
};
|
|
ConnectorAlgorithm.prototype.createStraightLineConnector = function (startPoint, endPoint) {
|
|
const shape = this.parentNode.shape;
|
|
shape.height = 0;
|
|
const info = this.getStraightConnectionInfo(startPoint, endPoint);
|
|
const connectorShape = this.getTemplateConnectorLine();
|
|
|
|
connectorShape.x = info.x;
|
|
connectorShape.y = info.y;
|
|
connectorShape.rot = info.rot;
|
|
|
|
shape.connectorShape = connectorShape;
|
|
|
|
const prSet = this.parentNode.getPrSet();
|
|
if (!prSet.getPresStyleLbl()) {
|
|
prSet.setPresStyleLbl("parChTrans1D2");
|
|
}
|
|
|
|
connectorShape.height = info.height;
|
|
connectorShape.width = info.width;
|
|
connectorShape.x += info.offX;
|
|
connectorShape.y += info.offY;
|
|
|
|
connectorShape.customGeom.push([0]);
|
|
connectorShape.customGeom.push([1, 0, 0]);
|
|
connectorShape.customGeom.push([2, connectorShape.width * 36000, 0]);
|
|
connectorShape.customGeom.push([6]);
|
|
};
|
|
ConnectorAlgorithm.prototype.getTemplateConnectorLine = function () {
|
|
const shape = this.parentNode.shape;
|
|
const connectorShape = new ShadowShape();
|
|
connectorShape.shape = shape.shape;
|
|
|
|
connectorShape.type = AscFormat.LayoutShapeType_outputShapeType_conn;
|
|
connectorShape.cleanParams = {};
|
|
connectorShape.cleanParams.width = shape.cleanParams.width;
|
|
connectorShape.cleanParams.height = shape.cleanParams.height;
|
|
connectorShape.cleanParams.x = shape.cleanParams.x;
|
|
connectorShape.cleanParams.y = shape.cleanParams.y;
|
|
connectorShape.node = this.parentNode;
|
|
if (this.params[AscFormat.Param_type_endSty] === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
const endArrow = new AscFormat.EndArrow();
|
|
endArrow.type = AscFormat.LineEndType.Arrow;
|
|
connectorShape.tailLnArrow = endArrow;
|
|
}
|
|
if (this.params[AscFormat.Param_type_begSty] === AscFormat.ParameterVal_arrowheadStyle_arr) {
|
|
const endArrow = new AscFormat.EndArrow();
|
|
endArrow.type = AscFormat.LineEndType.Arrow;
|
|
connectorShape.headLnArrow = endArrow;
|
|
}
|
|
return connectorShape;
|
|
}
|
|
|
|
function SpaceAlgorithm() {
|
|
BaseAlgorithm.call(this);
|
|
}
|
|
AscFormat.InitClassWithoutType(SpaceAlgorithm, BaseAlgorithm);
|
|
|
|
SpaceAlgorithm.prototype.applyTextSettings = function (editorShape) {
|
|
const node = this.parentNode.node;
|
|
const textNodes = node.getTextNodes();
|
|
|
|
const textNode = textNodes.textNode;
|
|
if (textNode && textNodes.contentNode === this.parentNode) {
|
|
textNodes.textNode.algorithm.applyTextSettings(editorShape, this.parentNode.getShape());
|
|
}
|
|
};
|
|
SpaceAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm, isCalculateScaleCoefficients) {
|
|
this.createShadowShape(isCalculateScaleCoefficients);
|
|
if (!isCalculateScaleCoefficients) {
|
|
this.applyPostAlgorithmSettings(smartartAlgorithm);
|
|
}
|
|
}
|
|
SpaceAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createShadowShape(false, isCalculateScaleCoefficients);
|
|
};
|
|
function TextAlgorithm() {
|
|
BaseAlgorithm.call(this);
|
|
}
|
|
|
|
AscFormat.InitClassWithoutType(TextAlgorithm, BaseAlgorithm);
|
|
TextAlgorithm.prototype.initParams = function (params) {
|
|
BaseAlgorithm.prototype.initParams.call(this, params);
|
|
if (this.params[AscFormat.Param_type_parTxLTRAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_parTxLTRAlign] = AscFormat.ParameterVal_horizontalAlignment_ctr;
|
|
}
|
|
if (this.params[AscFormat.Param_type_parTxRTLAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_parTxRTLAlign] = AscFormat.ParameterVal_horizontalAlignment_ctr;
|
|
}
|
|
if (this.params[AscFormat.Param_type_shpTxLTRAlignCh] === undefined) {
|
|
this.params[AscFormat.Param_type_shpTxLTRAlignCh] = AscFormat.ParameterVal_horizontalAlignment_l;
|
|
}
|
|
if (this.params[AscFormat.Param_type_shpTxRTLAlignCh] === undefined) {
|
|
this.params[AscFormat.Param_type_shpTxRTLAlignCh] = AscFormat.ParameterVal_horizontalAlignment_r;
|
|
}
|
|
if (this.params[AscFormat.Param_type_txAnchorVert] === undefined) {
|
|
this.params[AscFormat.Param_type_txAnchorVert] = AscFormat.ParameterVal_textAnchorVertical_mid;
|
|
}
|
|
if (this.params[AscFormat.Param_type_txAnchorVertCh] === undefined) {
|
|
this.params[AscFormat.Param_type_txAnchorVertCh] = AscFormat.ParameterVal_textAnchorVertical_t;
|
|
}
|
|
if (this.params[AscFormat.Param_type_autoTxRot] === undefined) {
|
|
this.params[AscFormat.Param_type_autoTxRot] = AscFormat.ParameterVal_autoTextRotation_upr;
|
|
}
|
|
if (this.params[AscFormat.Param_type_stBulletLvl] === undefined) {
|
|
this.params[AscFormat.Param_type_stBulletLvl] = 2;
|
|
}
|
|
};
|
|
TextAlgorithm.prototype.applyContentFilling = function (editorShape) {
|
|
const shapeSmartArtInfo = editorShape.getSmartArtInfo();
|
|
const contentNodes = shapeSmartArtInfo.contentPoint;
|
|
if (!contentNodes.length) {
|
|
return;
|
|
}
|
|
|
|
|
|
const stBulletLvl = this.params[AscFormat.Param_type_stBulletLvl];
|
|
editorShape.createTextBody();
|
|
const shapeContent = editorShape.txBody.content;
|
|
|
|
const arrParagraphs = [];
|
|
let nBulletLevel = 0;
|
|
|
|
const startDepth = contentNodes[0].depth;
|
|
for (let i = 0; i < contentNodes.length; i += 1) {
|
|
const contentNode = contentNodes[i];
|
|
const mainPoint = contentNode.point;
|
|
const deltaDepth = contentNode.depth - startDepth;
|
|
if (contentNode.point) {
|
|
const dataContent = mainPoint.t && mainPoint.t.content;
|
|
if (dataContent) {
|
|
const firstParagraph = dataContent.Content[0];
|
|
if (firstParagraph) {
|
|
const copyParagraph = firstParagraph.Copy(shapeContent, shapeContent.DrawingDocument);
|
|
if (stBulletLvl === 1 || stBulletLvl === 2 && deltaDepth > 0) {
|
|
const oBullet = AscFormat.fGetPresentationBulletByNumInfo({Type: 0, SubType: 0});
|
|
oBullet.bulletTypeface.type = AscFormat.BULLET_TYPE_TYPEFACE_TX;
|
|
|
|
copyParagraph.Add_PresentationNumbering(oBullet);
|
|
copyParagraph.Set_PresentationLevel(nBulletLevel);
|
|
nBulletLevel = Math.min(nBulletLevel + 1, 8);
|
|
copyParagraph.Set_Ind({FirstLine: -7.9}, false);
|
|
}
|
|
copyParagraph.Set_Spacing({Line : 0.9, LineRule : Asc.linerule_Auto}, false);
|
|
arrParagraphs.push(copyParagraph);
|
|
for (let j = 1; j < dataContent.Content.length; j += 1) {
|
|
const paragraph = dataContent.Content[j];
|
|
const copyCurrentParagraph = paragraph.Copy();
|
|
if (copyParagraph.Pr.Ind) {
|
|
copyCurrentParagraph.Set_Ind({Left: copyParagraph.Pr.Ind.Left}, false);
|
|
|
|
}
|
|
if (copyParagraph.Pr.Spacing) {
|
|
copyCurrentParagraph.Set_Spacing(copyParagraph.Pr.Spacing, false);
|
|
}
|
|
arrParagraphs.push(copyCurrentParagraph);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (arrParagraphs.length) {
|
|
shapeContent.Internal_Content_RemoveAll();
|
|
for (let i = 0; i < arrParagraphs.length; i++) {
|
|
shapeContent.AddToContent(shapeContent.Content.length, arrParagraphs[i]);
|
|
}
|
|
}
|
|
};
|
|
TextAlgorithm.prototype.applyDataBodyPr = function (editorShape) {
|
|
const node = this.parentNode;
|
|
const contentNode = node.contentNodes[0];
|
|
const bodyPr = contentNode.point.t && contentNode.point.t.bodyPr;
|
|
if (bodyPr) {
|
|
const copyBodyPr = bodyPr.createDuplicate();
|
|
editorShape.txBody.setBodyPr(copyBodyPr);
|
|
}
|
|
};
|
|
TextAlgorithm.prototype.applyTextSettings = function (editorShape, contentShadowShape) {
|
|
if (!contentShadowShape && this.parentNode.isTxXfrm()) {
|
|
return;
|
|
}
|
|
const smartArtInfo = editorShape.getSmartArtInfo();
|
|
this.applyFontRelations(editorShape);
|
|
this.applyContentFilling(editorShape);
|
|
if (smartArtInfo.contentPoint.length) {
|
|
this.applyTxXfrmSettings(editorShape, contentShadowShape);
|
|
this.applyDataBodyPr(editorShape);
|
|
this.applyTextMargins(editorShape);
|
|
this.applyHorizontalAlignment(editorShape);
|
|
this.applyVerticalAlignment(editorShape);
|
|
if (!editorShape.isCanFitFontSize()) {
|
|
editorShape.applyCustTSettings();
|
|
}
|
|
}
|
|
};
|
|
TextAlgorithm.prototype.getTextRotate = function () {
|
|
const shadowShape = this.parentNode.getShape();
|
|
const shapeRotate = shadowShape.rot;
|
|
switch (this.params[AscFormat.Param_type_autoTxRot]) {
|
|
case AscFormat.ParameterVal_autoTextRotation_none:
|
|
return 0;
|
|
case AscFormat.ParameterVal_autoTextRotation_grav:
|
|
if ((shapeRotate > Math.PI / 2) && (shapeRotate < Math.PI * 3 / 2)) {
|
|
return Math.PI;
|
|
}
|
|
return 0;
|
|
case AscFormat.ParameterVal_autoTextRotation_upr:
|
|
default:
|
|
let rot = 0;
|
|
if (shapeRotate > Math.PI / 4) {
|
|
rot -= Math.PI / 2;
|
|
}
|
|
if (shapeRotate >= Math.PI * 3 / 4) {
|
|
rot -= Math.PI / 2;
|
|
}
|
|
if (shapeRotate > Math.PI * 5 / 4) {
|
|
rot -= Math.PI / 2;
|
|
}
|
|
if (shapeRotate >= Math.PI * 7 / 4) {
|
|
rot -= Math.PI / 2;
|
|
}
|
|
return AscFormat.normalizeRotate(rot);
|
|
}
|
|
};
|
|
TextAlgorithm.prototype.applyTxXfrmSettings = function (editorShape, contentShadowShape) {
|
|
const shadowShape = this.parentNode.getShape();
|
|
const txXfrm = new AscFormat.CXfrm();
|
|
const autoRot = this.getTextRotate();
|
|
let geometry = editorShape.spPr.geometry;
|
|
if (contentShadowShape) {
|
|
geometry = AscFormat.ExecuteNoHistory(function(){return AscFormat.CreateGeometry(shadowShape.getEditorShapeType());}, this, []);
|
|
shadowShape.applyAdjLst(geometry);
|
|
}
|
|
geometry.Recalculate(shadowShape.width, shadowShape.height);
|
|
const geometryRect = geometry.rect;
|
|
let extX;
|
|
let extY;
|
|
let offX;
|
|
let offY;
|
|
if (geometryRect) {
|
|
offX = geometryRect.l + shadowShape.x;
|
|
offY = geometryRect.t + shadowShape.y;
|
|
extX = geometryRect.r - geometryRect.l;
|
|
extY = geometryRect.b - geometryRect.t;
|
|
} else {
|
|
offX = shadowShape.x;
|
|
offY = shadowShape.y;
|
|
extX = shadowShape.width;
|
|
extY = shadowShape.height;
|
|
}
|
|
const shapeMatrix = shadowShape.getReverseMatrix();
|
|
const cx = shapeMatrix.TransformPointX(offX + extX / 2, offY + extY / 2);
|
|
const cy = shapeMatrix.TransformPointY(offX + extX / 2, offY + extY / 2);
|
|
offX = cx - extX / 2;
|
|
offY = cy - extY / 2;
|
|
|
|
const newSizes = AscFormat.fGetMaxInscribedRectangle(extX, extY, autoRot);
|
|
offX += (extX - newSizes.width) / 2;
|
|
offY += (extY - newSizes.height) / 2;
|
|
txXfrm.setOffX(offX);
|
|
txXfrm.setOffY(offY);
|
|
txXfrm.setExtX(newSizes.width);
|
|
txXfrm.setExtY(newSizes.height);
|
|
const contentShadowShapeRot = contentShadowShape ? (shadowShape.rot - contentShadowShape.rot) : 0;
|
|
txXfrm.setRot(AscFormat.normalizeRotate(autoRot + contentShadowShapeRot));
|
|
|
|
editorShape.setTxXfrm(txXfrm);
|
|
};
|
|
TextAlgorithm.prototype.initDefaultMarginScales = function () {
|
|
const node = this.parentNode;
|
|
|
|
if (node.textConstraints[AscFormat.Constr_type_bMarg] === undefined) {
|
|
const bMarg = node.getConstr(AscFormat.Constr_type_bMarg, true, true);
|
|
if (bMarg === undefined) {
|
|
node.textConstraints[AscFormat.Constr_type_bMarg] = 0.56;
|
|
}
|
|
}
|
|
if (node.textConstraints[AscFormat.Constr_type_tMarg] === undefined) {
|
|
const tMarg = node.getConstr(AscFormat.Constr_type_tMarg, true, true);
|
|
if (tMarg === undefined) {
|
|
node.textConstraints[AscFormat.Constr_type_tMarg] = 0.56;
|
|
}
|
|
}
|
|
|
|
if (node.textConstraints[AscFormat.Constr_type_rMarg] === undefined) {
|
|
const rMarg = node.getConstr(AscFormat.Constr_type_rMarg, true, true);
|
|
if (rMarg === undefined) {
|
|
node.textConstraints[AscFormat.Constr_type_rMarg] = 0.56;
|
|
}
|
|
}
|
|
|
|
if (node.textConstraints[AscFormat.Constr_type_lMarg] === undefined) {
|
|
const lMarg = node.getConstr(AscFormat.Constr_type_lMarg, true, true);
|
|
if (lMarg === undefined) {
|
|
node.textConstraints[AscFormat.Constr_type_lMarg] = 0.56;
|
|
}
|
|
}
|
|
};
|
|
TextAlgorithm.prototype.applyFontRelations = function (editorShape) {
|
|
const node = this.parentNode;
|
|
this.initDefaultMarginScales();
|
|
|
|
const shapeSmartArtInfo = editorShape.getSmartArtInfo();
|
|
shapeSmartArtInfo.textConstraintRelations = node.textConstraintRelations;
|
|
shapeSmartArtInfo.textConstraints = node.textConstraints;
|
|
shapeSmartArtInfo.params[AscFormat.Param_type_lnSpAfParP] = this.params[AscFormat.Param_type_lnSpAfParP];
|
|
shapeSmartArtInfo.params[AscFormat.Param_type_lnSpAfChP] = this.params[AscFormat.Param_type_lnSpAfChP];
|
|
};
|
|
TextAlgorithm.prototype.applyTextMargins = function (editorShape) {
|
|
const node = this.parentNode;
|
|
const paddings = {};
|
|
const isApplyInsets = node.contentNodes[0].point.isRecalculateInsets();
|
|
if (isApplyInsets.Bottom && node.textConstraints[AscFormat.Constr_type_bMarg] === undefined) {
|
|
paddings.Bottom = node.getConstr(AscFormat.Constr_type_bMarg, true) * g_dKoef_pt_to_mm;
|
|
}
|
|
|
|
if (isApplyInsets.Top && node.textConstraints[AscFormat.Constr_type_tMarg] === undefined) {
|
|
paddings.Top = node.getConstr(AscFormat.Constr_type_tMarg, true) * g_dKoef_pt_to_mm;
|
|
}
|
|
|
|
if (isApplyInsets.Right && node.textConstraints[AscFormat.Constr_type_rMarg] === undefined) {
|
|
paddings.Right = node.getConstr(AscFormat.Constr_type_rMarg, true) * g_dKoef_pt_to_mm;
|
|
}
|
|
|
|
if (isApplyInsets.Left && node.textConstraints[AscFormat.Constr_type_lMarg] === undefined) {
|
|
paddings.Left = node.getConstr(AscFormat.Constr_type_lMarg, true) * g_dKoef_pt_to_mm;
|
|
}
|
|
|
|
editorShape.setPaddings(paddings, {bNotCopyToPoints: true});
|
|
};
|
|
function isParentWithChildren(nodes) {
|
|
if (nodes.length) {
|
|
const startDepth = nodes[0].depth;
|
|
for (let i = 1; i < nodes.length; i += 1) {
|
|
if (nodes[i].depth - startDepth > 0) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
TextAlgorithm.prototype.applyVerticalAlignment = function (editorShape) {
|
|
const node = this.parentNode;
|
|
const bodyPr = editorShape.getBodyPr().createDuplicate();
|
|
const stBulletLvl = this.params[AscFormat.Param_type_stBulletLvl];
|
|
const firstNodeBodyPr = node.contentNodes[0].point.t.bodyPr;
|
|
if (firstNodeBodyPr && typeof firstNodeBodyPr.anchor === "number") {
|
|
bodyPr.setAnchor(firstNodeBodyPr.anchor);
|
|
} else if (isParentWithChildren(node.contentNodes) || stBulletLvl === 1) {
|
|
switch (this.params[AscFormat.Param_type_txAnchorVertCh]) {
|
|
case AscFormat.ParameterVal_textAnchorVertical_b:
|
|
bodyPr.setAnchor(AscFormat.VERTICAL_ANCHOR_TYPE_BOTTOM);
|
|
break;
|
|
case AscFormat.ParameterVal_textAnchorVertical_mid:
|
|
bodyPr.setAnchor(AscFormat.VERTICAL_ANCHOR_TYPE_CENTER);
|
|
break;
|
|
case AscFormat.ParameterVal_textAnchorVertical_t:
|
|
default:
|
|
bodyPr.setAnchor(AscFormat.VERTICAL_ANCHOR_TYPE_TOP);
|
|
break;
|
|
}
|
|
} else {
|
|
switch (this.params[AscFormat.Param_type_txAnchorVert]) {
|
|
case AscFormat.ParameterVal_textAnchorVertical_b:
|
|
bodyPr.setAnchor(AscFormat.VERTICAL_ANCHOR_TYPE_BOTTOM);
|
|
break;
|
|
case AscFormat.ParameterVal_textAnchorVertical_t:
|
|
bodyPr.setAnchor(AscFormat.VERTICAL_ANCHOR_TYPE_TOP);
|
|
break;
|
|
case AscFormat.ParameterVal_textAnchorVertical_mid:
|
|
default:
|
|
bodyPr.setAnchor(AscFormat.VERTICAL_ANCHOR_TYPE_CENTER);
|
|
break;
|
|
}
|
|
}
|
|
editorShape.txBody.setBodyPr(bodyPr);
|
|
};
|
|
TextAlgorithm.prototype.getTextAlignment = function (paramType) {
|
|
switch (this.params[paramType]) {
|
|
case AscFormat.ParameterVal_horizontalAlignment_l:
|
|
return AscCommon.align_Left;
|
|
case AscFormat.ParameterVal_horizontalAlignment_r:
|
|
return AscCommon.align_Right;
|
|
case AscFormat.ParameterVal_horizontalAlignment_ctr:
|
|
default:
|
|
return AscCommon.align_Center;
|
|
}
|
|
};
|
|
TextAlgorithm.prototype.applyHorizontalAlignment = function (editorShape) {
|
|
const drawingContent = editorShape.txBody.content;
|
|
const node = this.parentNode;
|
|
let paragraphLTRAlignment;
|
|
let paragraphRTLAlignment;
|
|
let isCtrHorzAlign;
|
|
const stBulletLvl = this.params[AscFormat.Param_type_stBulletLvl];
|
|
if (isParentWithChildren(node.contentNodes) || stBulletLvl === 1) {
|
|
paragraphLTRAlignment = this.getTextAlignment(AscFormat.Param_type_shpTxLTRAlignCh);
|
|
paragraphRTLAlignment = this.getTextAlignment(AscFormat.Param_type_shpTxRTLAlignCh);
|
|
isCtrHorzAlign = !!this.params[AscFormat.Param_type_txAnchorHorzCh];
|
|
} else {
|
|
paragraphLTRAlignment = this.getTextAlignment(AscFormat.Param_type_parTxLTRAlign);
|
|
paragraphRTLAlignment = this.getTextAlignment(AscFormat.Param_type_parTxRTLAlign);
|
|
isCtrHorzAlign = !!this.params[AscFormat.Param_type_txAnchorHorz];
|
|
}
|
|
let skipSettingAlignment = false;
|
|
for (let i = 0; i < drawingContent.Content.length; i++) {
|
|
const item = drawingContent.Content[i];
|
|
if (typeof item.Pr.Jc === "number") {
|
|
skipSettingAlignment = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!skipSettingAlignment) {
|
|
for (let i = 0; i < drawingContent.Content.length; i++) {
|
|
const item = drawingContent.Content[i];
|
|
item.SetApplyToAll(true);
|
|
if (item.isRtlDirection()) {
|
|
item.SetParagraphAlign(paragraphRTLAlignment);
|
|
} else {
|
|
item.SetParagraphAlign(paragraphLTRAlignment);
|
|
}
|
|
item.SetApplyToAll(false);
|
|
}
|
|
}
|
|
|
|
const bodyPr = editorShape.getBodyPr();
|
|
const firstNodeBodyPr = node.contentNodes[0].point.t.bodyPr;
|
|
if (firstNodeBodyPr && typeof firstNodeBodyPr.anchorCtr === "boolean") {
|
|
const copyBodyPr = bodyPr.createDuplicate();
|
|
bodyPr.anchorCtr = firstNodeBodyPr.anchorCtr;
|
|
editorShape.txBody.setBodyPr(copyBodyPr);
|
|
} else if (bodyPr.anchorCtr !== isCtrHorzAlign) {
|
|
const copyBodyPr = bodyPr.createDuplicate();
|
|
bodyPr.anchorCtr = isCtrHorzAlign;
|
|
editorShape.txBody.setBodyPr(copyBodyPr);
|
|
}
|
|
};
|
|
|
|
TextAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm, isCalculateScaleCoefficient) {
|
|
this.createShadowShape(isCalculateScaleCoefficient);
|
|
if (!isCalculateScaleCoefficient) {
|
|
this.applyPostAlgorithmSettings(smartartAlgorithm);
|
|
}
|
|
};
|
|
TextAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createShadowShape(false, isCalculateScaleCoefficients);
|
|
};
|
|
|
|
function CompositeAlgorithm() {
|
|
BaseAlgorithm.call(this);
|
|
}
|
|
AscFormat.InitClassWithoutType(CompositeAlgorithm, BaseAlgorithm);
|
|
CompositeAlgorithm.prototype.initParams = function (params) {
|
|
BaseAlgorithm.prototype.initParams.call(this, params);
|
|
if (this.params[AscFormat.Param_type_horzAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_horzAlign] = AscFormat.ParameterVal_horizontalAlignment_ctr;
|
|
}
|
|
if (this.params[AscFormat.Param_type_vertAlign] === undefined) {
|
|
this.params[AscFormat.Param_type_vertAlign] = AscFormat.ParameterVal_verticalAlignment_mid;
|
|
}
|
|
};
|
|
|
|
CompositeAlgorithm.prototype.createShadowShape = function (isCalculateScaleCoefficients) {
|
|
return this.parentNode.createShadowShape(true, isCalculateScaleCoefficients);
|
|
};
|
|
CompositeAlgorithm.prototype.calculateShapePositions = function (smartartAlgorithm, isCalculateCoefficients) {
|
|
this.applyAlgorithmAligns(isCalculateCoefficients);
|
|
if (!isCalculateCoefficients) {
|
|
this.setConnections();
|
|
}
|
|
this.createShadowShape(isCalculateCoefficients);
|
|
};
|
|
|
|
function PresNode(presPoint, contentNode) {
|
|
this.parent = null;
|
|
this.presPoint = presPoint || null;
|
|
this.childs = [];
|
|
this.algorithm = null;
|
|
this.node = contentNode;
|
|
this.contentNodes = [];
|
|
this.layoutInfo = {
|
|
constrLst: null,
|
|
ruleLst: null,
|
|
shape: null
|
|
};
|
|
|
|
this.shape = null;
|
|
this.moveWithNodes = [];
|
|
|
|
this.isHideLastTrans = true;
|
|
this.connectionDistanceResolver = null;
|
|
this.bounds = {
|
|
constraints: null
|
|
};
|
|
this.namedNodes = null;
|
|
this.moveWith = null;
|
|
this._isTxXfrm = null;
|
|
this.textConstraints = {};
|
|
this.textConstraintRelations = [];
|
|
|
|
this.cleanRules();
|
|
this.cleanConstraints();
|
|
this.cleanScales();
|
|
this.cleanPosition();
|
|
}
|
|
PresNode.prototype.cleanPosition = function () {
|
|
this.position = null;
|
|
};
|
|
PresNode.prototype.cleanScales = function () {
|
|
this.moveScaleCoefficients = {
|
|
width: 1,
|
|
height: 1
|
|
};
|
|
this.moveRot = 0;
|
|
this.parentScale = {};
|
|
};
|
|
PresNode.prototype.setSizesScale = function (widthCoefficient, heightCoefficient) {
|
|
const aspectRatio = this.getAspectRatio();
|
|
if (aspectRatio) {
|
|
const commonCoefficient = Math.min(widthCoefficient, heightCoefficient);
|
|
this.setWidthScale(commonCoefficient);
|
|
this.setHeightScale(commonCoefficient);
|
|
} else {
|
|
this.setWidthScale(widthCoefficient);
|
|
this.setHeightScale(heightCoefficient);
|
|
}
|
|
};
|
|
PresNode.prototype.initPresShape = function () {
|
|
if (!this.layoutInfo.shape) {
|
|
this.layoutInfo.shape = new AscFormat.SShape();
|
|
}
|
|
}
|
|
PresNode.prototype.getParentScale = function (type) {
|
|
return this.parentScale[type] === undefined ? 1 : this.parentScale[type];
|
|
}
|
|
PresNode.prototype.setParentScale = function (type, value) {
|
|
if (value < 1 && (this.parentScale[type] === undefined || this.parentScale[type] > value)) {
|
|
this.parentScale[type] = value;
|
|
}
|
|
}
|
|
PresNode.prototype.getDefaultConnectionNode = function() {
|
|
if (this.childs.length) {
|
|
return this.childs[0];
|
|
}
|
|
return this;
|
|
};
|
|
PresNode.prototype.getShape = function (isCalculateCoefficients) {
|
|
if (isCalculateCoefficients) {
|
|
if (!this.position) {
|
|
this.position = new Position(this);
|
|
}
|
|
return this.position;
|
|
}
|
|
if (!this.shape) {
|
|
this.shape = new ShadowShape(this);
|
|
}
|
|
return this.shape;
|
|
};
|
|
PresNode.prototype.getRelationConstr = function (type) {
|
|
return this.relations[type];
|
|
}
|
|
PresNode.prototype.setRelationConstr = function (refNode, constr) {
|
|
this.relations[constr.type] = {constr: constr, ref: refNode};
|
|
};
|
|
PresNode.prototype.setWidthScale = function (pr) {
|
|
const relation = this.getRelationConstr(AscFormat.Constr_type_w);
|
|
if (relation) {
|
|
const relationConstr = relation.constr;
|
|
const widthRef = relation.ref;
|
|
const summaryWidthScale = this.getSummaryWidthScale();
|
|
const newCoef = pr / summaryWidthScale;
|
|
if (widthRef.getPresName() === this.getPresName() &&
|
|
relationConstr.refType === AscFormat.Constr_type_h) {
|
|
this.setParentScale(AscFormat.Constr_type_h, newCoef);
|
|
} else {
|
|
this.setParentScale(AscFormat.Constr_type_w, newCoef);
|
|
}
|
|
}
|
|
}
|
|
PresNode.prototype.getSummaryScale = function (scaleType) {
|
|
let startCoefficient = 1;
|
|
const startRelation = this.getRelationConstr(scaleType);
|
|
if (!startRelation) {
|
|
return startCoefficient;
|
|
}
|
|
let refNode = startRelation.ref;
|
|
let relationConstr = startRelation.constr;
|
|
const mapRelations = {};
|
|
mapRelations[scaleType] = {};
|
|
if (refNode && refNode.getPresName() === this.getPresName() && relationConstr.type !== relationConstr.refType) {
|
|
mapRelations[scaleType][this.getPresName()] = true;
|
|
}
|
|
|
|
while (relationConstr && refNode) {
|
|
const refType = relationConstr.refType;
|
|
if (!mapRelations[refType]) {
|
|
mapRelations[refType] = {};
|
|
}
|
|
const refPresName = refNode.getPresName();
|
|
if (mapRelations[refType][refPresName]) {
|
|
break;
|
|
}
|
|
startCoefficient *= refNode.getParentScale(refType);
|
|
mapRelations[refType][refPresName] = true;
|
|
const refRelation = refNode.getRelationConstr(refType);
|
|
if (refRelation) {
|
|
relationConstr = refRelation.constr;
|
|
refNode = refRelation.ref;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
return startCoefficient;
|
|
}
|
|
|
|
PresNode.prototype.getSummaryHeightScale = function () {
|
|
return this.getSummaryScale(AscFormat.Constr_type_h);
|
|
};
|
|
|
|
PresNode.prototype.getSummaryWidthScale = function () {
|
|
return this.getSummaryScale(AscFormat.Constr_type_w);
|
|
};
|
|
PresNode.prototype.setHeightScale = function (pr) {
|
|
const relation = this.getRelationConstr(AscFormat.Constr_type_h);
|
|
if (relation) {
|
|
const relationConstr = relation.constr;
|
|
const heightRef = relation.ref;
|
|
const isSelfRelation = heightRef.getPresName() === this.getPresName();
|
|
const summaryHeight = this.getSummaryHeightScale();
|
|
const newCoef = pr / summaryHeight;
|
|
if (isSelfRelation &&
|
|
relationConstr.refType === AscFormat.Constr_type_w) {
|
|
this.setParentScale(AscFormat.Constr_type_w, newCoef);
|
|
} else {
|
|
this.setParentScale(AscFormat.Constr_type_h, newCoef);
|
|
}
|
|
}
|
|
}
|
|
PresNode.prototype.getNamedNode = function (name) {
|
|
if (name === undefined || name === this.getPresName()) {
|
|
return this;
|
|
}
|
|
if (this.namedNodes === null) {
|
|
this.namedNodes = {};
|
|
const childs = this.childs;
|
|
for (let i = 0; i < childs.length; i++) {
|
|
const child = childs[i];
|
|
this.namedNodes[child.getPresName()] = child;
|
|
}
|
|
}
|
|
return this.namedNodes[name];
|
|
};
|
|
PresNode.prototype.isRealShapeType = function () {
|
|
return !(this.algorithm instanceof ConnectorAlgorithm || (this.algorithm instanceof SpaceAlgorithm &&
|
|
(this.layoutInfo.shape.type === AscFormat.LayoutShapeType_outputShapeType_conn ||
|
|
this.layoutInfo.shape.type === AscFormat.LayoutShapeType_outputShapeType_none)));
|
|
}
|
|
PresNode.prototype.isSkipShape = function (isCalculateScaleCoefficient, isCycleAlgorithm) {
|
|
let shape = this.getShape(isCalculateScaleCoefficient);
|
|
if (shape.connectorShape) {
|
|
shape = shape.connectorShape;
|
|
}
|
|
return shape.width <= 0 && shape.height <= 0 ||
|
|
(this.algorithm instanceof ConnectorAlgorithm && !(isCycleAlgorithm && this.algorithm.isCurveShape())) ||
|
|
this.isTxXfrm() ||
|
|
!this.algorithm ||
|
|
(this.algorithm instanceof SpaceAlgorithm &&
|
|
!(this.parent && this.parent.algorithm instanceof CompositeAlgorithm) &&
|
|
(this.layoutInfo.shape.hideGeom || !this.isRealShapeType()));
|
|
};
|
|
PresNode.prototype.isSibNode = function () {
|
|
return this.node.isSibNode();
|
|
};
|
|
PresNode.prototype.isParNode = function () {
|
|
return this.node.isParNode();
|
|
};
|
|
PresNode.prototype.isContentNode = function () {
|
|
return this.node.isContentNode();
|
|
};
|
|
PresNode.prototype.getDescendantFilteredShapes = function () {
|
|
const nodes = [this];
|
|
const shapes = [];
|
|
while (nodes.length) {
|
|
const node = nodes.pop();
|
|
shapes.push(node.getShape());
|
|
|
|
for (let i = node.childs.length - 1; i >= 0; i -= 1) {
|
|
nodes.push(node.childs[i]);
|
|
}
|
|
}
|
|
return shapes.filter(function (shadowShape) {
|
|
if (shadowShape.height === 0 && shadowShape.width === 0 && shadowShape.node.algorithm instanceof TextAlgorithm) {
|
|
return false;
|
|
}
|
|
if (shadowShape.shape.hideGeom && shadowShape.shape.type === AscFormat.LayoutShapeType_shapeType_rect && shadowShape.node.algorithm instanceof TextAlgorithm && !shadowShape.node.isTxXfrm()) {
|
|
return true;
|
|
}
|
|
return !shadowShape.shape.hideGeom && !shadowShape.node.isTxXfrm() && shadowShape.shape.type !== AscFormat.LayoutShapeType_outputShapeType_none;
|
|
});
|
|
}
|
|
PresNode.prototype.getShadowShapesByZOrder = function () {
|
|
const shapes = this.getDescendantFilteredShapes();
|
|
const sortedShapes = shapes.slice();
|
|
let sortedIndex = 0;
|
|
for (let i = 0; i < shapes.length; i++) {
|
|
const shape = shapes[i];
|
|
const zOrderOff = shape.shape.zOrderOff;
|
|
if (zOrderOff === 0) {
|
|
continue;
|
|
}
|
|
while (sortedShapes[sortedIndex] !== shape) {
|
|
sortedIndex += 1;
|
|
}
|
|
const sortedShape = sortedShapes[sortedIndex];
|
|
sortedShapes.splice(sortedIndex, 1);
|
|
const insertIndex = Math.min(Math.max(0, sortedIndex + zOrderOff), sortedShapes.length);
|
|
sortedShapes.splice(insertIndex, 0, sortedShape);
|
|
}
|
|
|
|
return sortedShapes;
|
|
};
|
|
PresNode.prototype.getChildIndex = function (child) {
|
|
for (let i = 0; i < this.childs.length; i++) {
|
|
if (this.childs[i] === child) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
PresNode.prototype.getNeighbor = function () {
|
|
const parent = this.parent;
|
|
const index = parent.getChildIndex(this);
|
|
for (let i = index + 1; i < parent.childs.length; i += 1) {
|
|
const child = parent.childs[i];
|
|
const shape = child.shape;
|
|
if (child.isRealShapeType()) {
|
|
return child;
|
|
}
|
|
}
|
|
|
|
for (let i = index - 1; i >= 0; i -= 1) {
|
|
const child = parent.childs[i];
|
|
const shape = child.shape;
|
|
if (child.isRealShapeType()) {
|
|
return child;
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
PresNode.prototype.moveTo = function (deltaX, deltaY, isCalcScaleCoefficient, skipMoveWithNodes) {
|
|
deltaX = deltaX || 0;
|
|
deltaY = deltaY || 0;
|
|
this.forEachDesOrSelf(function (node) {
|
|
const shape = node.getShape(isCalcScaleCoefficient);
|
|
if (shape) {
|
|
shape.x += deltaX;
|
|
shape.y += deltaY;
|
|
}
|
|
});
|
|
if (!skipMoveWithNodes) {
|
|
for (let i = 0; i < this.moveWithNodes.length; i++) {
|
|
const moveNode = this.moveWithNodes[i];
|
|
const moveShape = moveNode.getShape(isCalcScaleCoefficient);
|
|
if (moveShape) {
|
|
moveShape.x += deltaX;
|
|
moveShape.y += deltaY;
|
|
}
|
|
}
|
|
const textNodes = this.contentNodes[0] && this.contentNodes[0].getTextNodes();
|
|
if (textNodes && textNodes.contentNode === this && textNodes.textNode) {
|
|
const moveShape = textNodes.textNode.getShape(isCalcScaleCoefficient);
|
|
if (moveShape) {
|
|
moveShape.x += deltaX;
|
|
moveShape.y += deltaY;
|
|
}
|
|
}
|
|
}
|
|
this.algorithm.moveToHierarchyOffsets(deltaX, deltaY);
|
|
};
|
|
|
|
PresNode.prototype.forEachChild = function (callback) {
|
|
for (let i = 0; i < this.childs.length; i += 1) {
|
|
callback(this.childs[i]);
|
|
}
|
|
};
|
|
|
|
PresNode.prototype.forEachDes = function (callback) {
|
|
const elements = [this];
|
|
while (elements.length) {
|
|
const element = elements.pop();
|
|
for (let i = 0; i < element.childs.length; i++) {
|
|
elements.push(element.childs[i]);
|
|
callback(element.childs[i]);
|
|
}
|
|
}
|
|
};
|
|
|
|
PresNode.prototype.forEachDesOrSelf = function (callback) {
|
|
callback(this);
|
|
this.forEachDes(callback);
|
|
};
|
|
PresNode.prototype.getAspectRatio = function () {
|
|
if (this.algorithm) {
|
|
return this.algorithm.getAspectRatio();
|
|
}
|
|
return 0;
|
|
}
|
|
PresNode.prototype.getPresStyleLbl = function () {
|
|
return this.presPoint.getPresStyleLbl();
|
|
}
|
|
PresNode.prototype.addMoveWithNode = function (node) {
|
|
this.moveWithNodes.push(node);
|
|
}
|
|
PresNode.prototype.checkMoveWith = function () {
|
|
for (let i = 0; i < this.childs.length; i += 1) {
|
|
const node = this.childs[i];
|
|
if (node.moveWith) {
|
|
const moveNode = this.getNamedNode(node.moveWith);
|
|
if (moveNode) {
|
|
moveNode.addMoveWithNode(node);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
PresNode.prototype.addChild = function (ch, pos) {
|
|
if (!AscFormat.isRealNumber(pos)) {
|
|
pos = this.childs.length;
|
|
}
|
|
this.childs.splice(pos, 0, ch);
|
|
ch.parent = this;
|
|
};
|
|
PresNode.prototype.removeChilds = function (pos, count) {
|
|
this.childs.splice(pos, count);
|
|
};
|
|
PresNode.prototype.getPresName = function () {
|
|
return this.presPoint.getPresName();
|
|
};
|
|
PresNode.prototype.getPrSet = function () {
|
|
return this.presPoint.getPrSet();
|
|
};
|
|
|
|
PresNode.prototype.setShape = function (shape) {
|
|
this.shape = shape;
|
|
};
|
|
|
|
PresNode.prototype.getNodesByAxis = function (nodes, constrType) {
|
|
switch (constrType) {
|
|
case AscFormat.Constr_for_self: {
|
|
nodes.push(this);
|
|
break;
|
|
}
|
|
case AscFormat.Constr_for_ch: {
|
|
for (let i = 0; i < this.childs.length; i++) {
|
|
nodes.push(this.childs[i]);
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_for_des: {
|
|
const elements = [this];
|
|
while (elements.length) {
|
|
const element = elements.pop();
|
|
for (let i = 0; i < element.childs.length; i++) {
|
|
const child = element.childs[i];
|
|
nodes.push(child);
|
|
elements.push(child);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
PresNode.prototype.setRules = function (smartartAlgorithm) {
|
|
const ruleLst = this.layoutInfo.ruleLst;
|
|
if (!ruleLst) {
|
|
return;
|
|
}
|
|
let cacheFor = {};
|
|
for (let i = 0; i < ruleLst.length; i++) {
|
|
const rule = ruleLst[i];
|
|
if (!cacheFor[rule.for]) {
|
|
cacheFor[rule.for] = [];
|
|
this.getNodesByAxis(cacheFor[rule.for], rule.for);
|
|
}
|
|
const nodes = cacheFor[rule.for];
|
|
for (let j = 0; j < nodes.length; j++) {
|
|
nodes[j].setRule(rule, smartartAlgorithm);
|
|
}
|
|
}
|
|
};
|
|
PresNode.prototype.getFactRule = function (constr) {
|
|
const ruleFactor = this.factRules[constr.type];
|
|
if (ruleFactor === undefined || ruleFactor > constr.fact) {
|
|
return constr.fact;
|
|
}
|
|
return ruleFactor;
|
|
};
|
|
PresNode.prototype.cleanRules = function () {
|
|
this.factRules = {};
|
|
this.valRules = {};
|
|
};
|
|
PresNode.prototype.cleanConstraints = function () {
|
|
this.relations = {};
|
|
this.equationRelations = {
|
|
adapt: {},
|
|
nonAdapt: {}
|
|
};
|
|
|
|
this.equationRelations.nonAdapt[AscFormat.Constr_op_equ] = {};
|
|
this.equationRelations.nonAdapt[AscFormat.Constr_op_gte] = {};
|
|
this.equationRelations.nonAdapt[AscFormat.Constr_op_lte] = {};
|
|
this.equationRelations.nonAdapt[AscFormat.Constr_op_none] = {};
|
|
this.equationRelations.adapt[AscFormat.Constr_op_equ] = {};
|
|
this.equationRelations.adapt[AscFormat.Constr_op_gte] = {};
|
|
this.equationRelations.adapt[AscFormat.Constr_op_lte] = {};
|
|
this.equationRelations.adapt[AscFormat.Constr_op_none] = {};
|
|
this.adaptConstr = {};
|
|
this.constr = {};
|
|
};
|
|
PresNode.prototype.setRule = function (rule, smartartAlgorithm) {
|
|
const node = this.getConstraintNode(rule.forName, rule.ptType);
|
|
if (node) {
|
|
if (AscFormat.isRealNumber(rule.fact)) {
|
|
if (rule.val !== rule.val) {
|
|
node.factRules[rule.type] = rule.fact;
|
|
smartartAlgorithm.setFactRuleState(factRuleState.enabled);
|
|
}
|
|
}
|
|
if (typeof rule.val === "number" && rule.val === rule.val) {
|
|
switch (rule.type) {
|
|
case AscFormat.Constr_type_diam: {
|
|
this.valRules[rule.type] = rule.val;
|
|
break;
|
|
}
|
|
case AscFormat.Constr_type_primFontSz:
|
|
case AscFormat.Constr_type_secFontSz: {
|
|
if (!this.textConstraints[rule.type]) {
|
|
this.textConstraints[rule.type] = new TextConstr();
|
|
}
|
|
const textConstr = this.textConstraints[rule.type];
|
|
if (!textConstr.rule || rule.val < textConstr.rule.val) {
|
|
textConstr.rule = rule;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
function TextConstr() {
|
|
this.op = {};
|
|
this.op[AscFormat.Constr_op_none] = [];
|
|
this.op[AscFormat.Constr_op_equ] = [];
|
|
this.op[AscFormat.Constr_op_gte] = [];
|
|
this.op[AscFormat.Constr_op_lte] = [];
|
|
this.rule = null;
|
|
}
|
|
TextConstr.prototype.getSecondaryFontSizeCoefficient = function () {
|
|
const info = this.op[AscFormat.Constr_op_none];
|
|
|
|
for (let i = 0; i < info.length; i += 1) {
|
|
const constr = info[i].constr;
|
|
if (constr.type === AscFormat.Constr_type_primFontSz && constr.refType === AscFormat.Constr_type_secFontSz) {
|
|
return 1 / constr.fact;
|
|
} else if (constr.refType === AscFormat.Constr_type_primFontSz && constr.type === AscFormat.Constr_type_secFontSz) {
|
|
return constr.fact;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
TextConstr.prototype.collectShapeSmartArtInfo = function (opType, array, mapShapes, collectRefNodes) {
|
|
const information = this.op[opType];
|
|
for (let i = 0; i < information.length; i++) {
|
|
const info = information[i];
|
|
const nodes = collectRefNodes ? info.refNodes : info.nodes;
|
|
for (let j = 0; j < nodes.length; j++) {
|
|
const node = nodes[j];
|
|
const editorShape = node.contentNodes[0] && node.contentNodes[0].getContentNode().getShape().editorShape;
|
|
if (editorShape && !mapShapes[editorShape.GetId()]) {
|
|
array.push(editorShape.getSmartArtInfo());
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
TextConstr.prototype.getMaxFontSizeFromInfo = function (opType, isUseChildrenCoefficient, isReturnFirstFindFontSize) {
|
|
const informations = this.op[opType];
|
|
let fontSize = 65;
|
|
//todo
|
|
for (let i = 0; i < informations.length; i += 1) {
|
|
const info = informations[i];
|
|
const constr = info.constr;
|
|
if (constr) {
|
|
if (constr.refType === AscFormat.Constr_type_none && constr.op !== AscFormat.Constr_op_equ) {
|
|
if (constr.val < fontSize) {
|
|
fontSize = constr.val;
|
|
}
|
|
if (isReturnFirstFindFontSize) {
|
|
break;
|
|
}
|
|
} else if (!(constr.for === constr.refFor && constr.forName === constr.refForName && constr.ptType === constr.refPtType)) {
|
|
const refNodes = info.refNodes;
|
|
for (let i = 0; i < refNodes.length; i += 1) {
|
|
const refNode = refNodes[i];
|
|
const editorShape = refNode.contentNodes[0] && refNode.contentNodes[0].getContentNode().getShape().editorShape;
|
|
if (editorShape) {
|
|
const shapeInfo = editorShape.getSmartArtInfo();
|
|
const shapeFontSize = shapeInfo.getRelFitFontSize(isUseChildrenCoefficient);
|
|
if (shapeFontSize !== null && shapeFontSize < fontSize) {
|
|
fontSize = shapeFontSize;
|
|
}
|
|
}
|
|
}
|
|
if (isReturnFirstFindFontSize) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return fontSize;
|
|
};
|
|
TextConstr.prototype.getMaxFontSize = function (isUseChildrenCoefficient) {
|
|
const noneFontSize = this.getMaxFontSizeFromInfo(AscFormat.Constr_op_none, isUseChildrenCoefficient, true);
|
|
const lteFontSize = this.getMaxFontSizeFromInfo(AscFormat.Constr_op_lte, isUseChildrenCoefficient);
|
|
return Math.min(noneFontSize, lteFontSize);
|
|
};
|
|
TextConstr.prototype.getMinFontSize = function () {
|
|
if (this.rule) {
|
|
return this.rule.val;
|
|
}
|
|
return 5;
|
|
};
|
|
function checkFontSizeConstraints(constr, refNodes, nodes) {
|
|
const truthRefNodes = [];
|
|
const truthNodes = [];
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
const node = nodes[i].getConstraintNode(constr.forName, constr.ptType);
|
|
if (node) {
|
|
truthNodes.push(node);
|
|
}
|
|
}
|
|
for (let i = 0; i < refNodes.length; i++) {
|
|
const node = refNodes[i].getConstraintNode(constr.refForName, constr.refPtType);
|
|
if (node) {
|
|
truthRefNodes.push(node);
|
|
}
|
|
}
|
|
for (let i = 0; i < truthNodes.length; i += 1) {
|
|
const node = truthNodes[i];
|
|
if (!node.textConstraints[constr.type]) {
|
|
node.textConstraints[constr.type] = new TextConstr();
|
|
}
|
|
const calcConstr = node.textConstraints[constr.type];
|
|
calcConstr.op[constr.op].push({constr: constr, refNodes: truthRefNodes, nodes: truthNodes});
|
|
}
|
|
if (constr.op === AscFormat.Constr_op_equ) {
|
|
for (let i = 0; i < truthRefNodes.length; i++) {
|
|
const node = truthRefNodes[i];
|
|
if (!node.textConstraints[constr.type]) {
|
|
node.textConstraints[constr.type] = new TextConstr();
|
|
}
|
|
const calcConstr = node.textConstraints[constr.type];
|
|
calcConstr.op[constr.op].push({constr: constr, refNodes: truthNodes, nodes: truthRefNodes});
|
|
}
|
|
}
|
|
if (constr.op === AscFormat.Constr_op_lte && !(constr.for === constr.refFor && constr.forName === constr.refForName && constr.ptType === constr.refPtType) && constr.refType !== AscFormat.Constr_type_none) {
|
|
for (let i = 0; i < truthRefNodes.length; i += 1) {
|
|
truthRefNodes[i].textConstraintRelations.push(truthNodes);
|
|
}
|
|
}
|
|
}
|
|
PresNode.prototype.setConstraints = function (isAdapt, smartartAlgorithm) {
|
|
const constrLst = this.layoutInfo.constrLst;
|
|
if (!constrLst) {
|
|
return;
|
|
}
|
|
const valueCache = {};
|
|
const cacheFor = {};
|
|
for (let i = 0; i < constrLst.length; i++) {
|
|
const constr = constrLst[i];
|
|
if (!cacheFor[constr.for]) {
|
|
cacheFor[constr.for] = [];
|
|
this.getNodesByAxis(cacheFor[constr.for], constr.for);
|
|
}
|
|
const nodes = cacheFor[constr.for];
|
|
|
|
if (!cacheFor[constr.refFor]) {
|
|
cacheFor[constr.refFor] = [];
|
|
this.getNodesByAxis(cacheFor[constr.refFor], constr.refFor);
|
|
}
|
|
const refNodes = cacheFor[constr.refFor];
|
|
|
|
for (let j = 0; j < refNodes.length; j++) {
|
|
const calcValue = refNodes[j].getCalcRefConstr(constr, isAdapt, valueCache);
|
|
if (AscFormat.isRealNumber(calcValue)) {
|
|
for (let k = 0; k < nodes.length; k++) {
|
|
nodes[k].setConstraintByNode(constr, refNodes[j], calcValue, isAdapt);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (isAdapt) {
|
|
switch (constr.type) {
|
|
case AscFormat.Constr_type_primFontSz:
|
|
case AscFormat.Constr_type_secFontSz:
|
|
checkFontSizeConstraints(constr, refNodes, nodes, smartartAlgorithm);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
PresNode.prototype.getPtType = function () {
|
|
const node = this.node;
|
|
return node.getPtType();
|
|
}
|
|
PresNode.prototype.checkPtType = function (elementType) {
|
|
const ptType = this.getPtType();
|
|
switch (elementType) {
|
|
case AscFormat.ElementType_value_all:
|
|
return this;
|
|
case AscFormat.ElementType_value_sibTrans:
|
|
if (ptType === AscFormat.Point_type_sibTrans) {
|
|
return this;
|
|
}
|
|
break;
|
|
case AscFormat.ElementType_value_parTrans:
|
|
if (ptType === AscFormat.Point_type_parTrans) {
|
|
return this;
|
|
}
|
|
break;
|
|
case AscFormat.ElementType_value_node:
|
|
if (ptType === AscFormat.Point_type_node || ptType === AscFormat.Point_type_asst) {
|
|
return this;
|
|
}
|
|
break;
|
|
case AscFormat.ElementType_value_asst:
|
|
if (ptType === AscFormat.Point_type_asst) {
|
|
return this;
|
|
}
|
|
break;
|
|
case AscFormat.ElementType_value_nonAsst:
|
|
if (ptType !== AscFormat.Point_type_asst) {
|
|
return this;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
PresNode.prototype.getConstraintNode = function (forName, ptType) {
|
|
let node = this;
|
|
if (forName) {
|
|
node = this.checkName(forName);
|
|
}
|
|
return node && node.checkPtType(ptType);
|
|
};
|
|
|
|
PresNode.prototype.getCalcRefConstr = function (constr, isAdapt, valueCache) {
|
|
if (!constr.refForName) {
|
|
if (!valueCache[constr.refFor]) {
|
|
valueCache[constr.refFor] = {};
|
|
}
|
|
if (!valueCache[constr.refFor][constr.refPtType]) {
|
|
valueCache[constr.refFor][constr.refPtType] = {};
|
|
}
|
|
const cacheValue = valueCache[constr.refFor][constr.refPtType][constr.refType];
|
|
if (AscFormat.isRealNumber(cacheValue)) {
|
|
return cacheValue;
|
|
}
|
|
}
|
|
|
|
const refNode = this.getConstraintNode(constr.refForName, constr.refPtType);
|
|
if (!refNode) {
|
|
return;
|
|
}
|
|
const calcValue = refNode.getRefConstr(constr, isAdapt);
|
|
if (constr.refType !== AscFormat.Constr_type_none && !constr.refForName && constr.refFor !== AscFormat.Constr_for_self) {
|
|
valueCache[constr.refFor][constr.refPtType][constr.refType] = calcValue;
|
|
}
|
|
return calcValue;
|
|
};
|
|
PresNode.prototype.setConstraintByNode = function (constr, refNode, calcValue, isAdapt) {
|
|
const constrNode = this.getConstraintNode(constr.forName, constr.ptType);
|
|
if (constrNode) {
|
|
constrNode.addEqualRelation(refNode, constr, isAdapt);
|
|
const isSettingConstraint = constrNode.setConstraint(constr, calcValue, isAdapt);
|
|
constrNode.setParamConstraint(constr, refNode);
|
|
if (isSettingConstraint) {
|
|
constrNode.applyEqualRelations(isAdapt);
|
|
setRelationConstraints(constrNode, refNode, constr);
|
|
}
|
|
}
|
|
};
|
|
|
|
function setRelationConstraints(constrNode, refNode, constr) {
|
|
switch (constr.type) {
|
|
case AscFormat.Constr_type_w:
|
|
case AscFormat.Constr_type_h:
|
|
constrNode.setRelationConstr(refNode, constr);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
PresNode.prototype.addEqualRelation = function (refNode, constr, isAdapt) {
|
|
const relations = isAdapt ? this.equationRelations.adapt : this.equationRelations.nonAdapt;
|
|
relations[constr.op][constr.type] = {constr: constr, ref: refNode};
|
|
};
|
|
PresNode.prototype.applyEqualRelations = function (isAdapt) {
|
|
const relations = isAdapt ? this.equationRelations.adapt : this.equationRelations.nonAdapt;
|
|
const equRelations = relations[AscFormat.Constr_op_equ];
|
|
for (let constrType in equRelations) {
|
|
const rel = equRelations[constrType];
|
|
const constr = rel.constr;
|
|
const refNode = rel.ref;
|
|
|
|
const refConstrObject = isAdapt ? refNode.adaptConstr : refNode.constr;
|
|
const curConstrObject = isAdapt ? this.adaptConstr : this.constr;
|
|
|
|
let factor = this.getFactRule(constr);
|
|
const refType = constr.refType === AscFormat.Constr_type_none && constr.refForName ? constr.type : constr.refType;
|
|
if (refConstrObject[refType]) {
|
|
if ( refNode === this && refConstrObject[refType] * factor !== curConstrObject[constr.type]) {
|
|
refConstrObject[refType] = curConstrObject[constr.type];
|
|
} else {
|
|
curConstrObject[constr.type] = refConstrObject[refType] * factor;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
PresNode.prototype.setParamConstraint = function (constr, refNode) {
|
|
switch (constr.type) {
|
|
case AscFormat.Constr_type_connDist: {
|
|
if (constr.for !== AscFormat.Constr_for_self) {
|
|
if (this.algorithm) {
|
|
if (!refNode.connectionDistanceResolver) {
|
|
refNode.connectionDistanceResolver = new CConnectionDistanceResolver();
|
|
}
|
|
refNode.connectionDistanceResolver.addConnection(this.algorithm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function isUserConstr(type) {
|
|
switch (type) {
|
|
case AscFormat.Constr_type_userA:
|
|
case AscFormat.Constr_type_userB:
|
|
case AscFormat.Constr_type_userC:
|
|
case AscFormat.Constr_type_userD:
|
|
case AscFormat.Constr_type_userE:
|
|
case AscFormat.Constr_type_userF:
|
|
case AscFormat.Constr_type_userG:
|
|
case AscFormat.Constr_type_userH:
|
|
case AscFormat.Constr_type_userI:
|
|
case AscFormat.Constr_type_userJ:
|
|
case AscFormat.Constr_type_userK:
|
|
case AscFormat.Constr_type_userL:
|
|
case AscFormat.Constr_type_userM:
|
|
case AscFormat.Constr_type_userN:
|
|
case AscFormat.Constr_type_userO:
|
|
case AscFormat.Constr_type_userP:
|
|
case AscFormat.Constr_type_userQ:
|
|
case AscFormat.Constr_type_userR:
|
|
case AscFormat.Constr_type_userS:
|
|
case AscFormat.Constr_type_userT:
|
|
case AscFormat.Constr_type_userU:
|
|
case AscFormat.Constr_type_userV:
|
|
case AscFormat.Constr_type_userW:
|
|
case AscFormat.Constr_type_userX:
|
|
case AscFormat.Constr_type_userY:
|
|
case AscFormat.Constr_type_userZ:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
PresNode.prototype.setConstraint = function (constr, value, isAdapt) {
|
|
if (!this.isCanAdapt(constr, isAdapt)) {
|
|
return false;
|
|
}
|
|
let factor = this.getFactRule(constr);
|
|
value *= factor;
|
|
const constrObject = this.getConstraints(isAdapt);
|
|
if (constrObject[constr.type] !== undefined && constr.refFor === AscFormat.Constr_for_self && constr.refType === AscFormat.Constr_type_none) {
|
|
return false;
|
|
}
|
|
|
|
switch (constr.op) {
|
|
case AscFormat.Constr_op_gte: {
|
|
const oldValue = constrObject[constr.type];
|
|
if (oldValue !== undefined && value < oldValue) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_op_lte: {
|
|
const oldValue = constrObject[constr.type];
|
|
if (oldValue !== undefined && value > oldValue) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
if (isAdapt) {
|
|
switch (constr.type) {
|
|
case AscFormat.Constr_type_w:
|
|
case AscFormat.Constr_type_h: {
|
|
const summaryScale = this.getSummaryScale(constr.type);
|
|
const parentScale = Math.min(this.getParentScale(constr.type) / summaryScale, 1);
|
|
value *= parentScale;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
switch (constr.type) {
|
|
case AscFormat.Constr_type_begPad:
|
|
case AscFormat.Constr_type_endPad: {
|
|
if (this.algorithm) {
|
|
const padFactor = constr.refType === AscFormat.Constr_type_none ? constr.val : constr.fact;
|
|
this.algorithm.setConnectionDistance(padFactor, constr.type === AscFormat.Constr_type_begPad);
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_type_stemThick: {
|
|
if (this.algorithm) {
|
|
this.algorithm.setStemThick(constr.fact);
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_type_diam:
|
|
if (this.algorithm) {
|
|
let val;
|
|
if (value === 0) {
|
|
val = constr.refType === AscFormat.Constr_type_none ? constr.val : constr.fact;
|
|
} else {
|
|
val = value;
|
|
}
|
|
this.algorithm.setConstrClockwise(val > 0);
|
|
this.algorithm.diameterScale = constr.fact;
|
|
break;
|
|
}
|
|
break;
|
|
case AscFormat.Constr_type_bMarg:
|
|
case AscFormat.Constr_type_tMarg:
|
|
case AscFormat.Constr_type_rMarg:
|
|
case AscFormat.Constr_type_lMarg:
|
|
if (this.textConstraints[constr.type] === undefined && constrObject[constr.type] === undefined) {
|
|
if (constr.refType === AscFormat.Constr_type_primFontSz || constr.refType === AscFormat.Constr_type_secFontSz) {
|
|
this.textConstraints[constr.type] = constr.fact;
|
|
} else if (AscFormat.isRealNumber(this.textConstraints[constr.refType])) {
|
|
this.textConstraints[constr.type] = this.textConstraints[constr.refType];
|
|
}
|
|
} else if (constr.refType === AscFormat.Constr_type_primFontSz || constr.refType === AscFormat.Constr_type_secFontSz) {
|
|
return;
|
|
}
|
|
break;
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
if (this.valRules[constr.type] !== Infinity) {
|
|
constrObject[constr.type] = value;
|
|
}
|
|
return true;
|
|
};
|
|
PresNode.prototype.getParentWidth = function (isAdapt) {
|
|
let node = this;
|
|
while (node.isContentNode() && node.parent) {
|
|
const parentConstrObject = isAdapt ? node.parent.adaptConstr : node.parent.constr;
|
|
let parentWidth = parentConstrObject[AscFormat.Constr_type_w];
|
|
let parentHeight = parentConstrObject[AscFormat.Constr_type_h];
|
|
const aspectRatio = node.parent.getAspectRatio();
|
|
if (aspectRatio) {
|
|
const aspectWidth = parentHeight * aspectRatio;
|
|
if (parentWidth > aspectWidth) {
|
|
parentWidth = aspectWidth;
|
|
}
|
|
}
|
|
if (parentWidth) {
|
|
return parentWidth;
|
|
}
|
|
node = node.parent;
|
|
}
|
|
};
|
|
PresNode.prototype.getParentHeight = function (isAdapt) {
|
|
let node = this;
|
|
while (node.isContentNode() && node.parent) {
|
|
const parentConstrObject = isAdapt ? node.parent.adaptConstr : node.parent.constr;
|
|
let parentWidth = parentConstrObject[AscFormat.Constr_type_w];
|
|
let parentHeight = parentConstrObject[AscFormat.Constr_type_h];
|
|
const aspectRatio = node.parent.getAspectRatio();
|
|
if (aspectRatio) {
|
|
const aspectWidth = parentHeight * aspectRatio;
|
|
if (parentWidth <= aspectWidth) {
|
|
parentHeight = parentWidth / aspectRatio;
|
|
}
|
|
}
|
|
if (parentHeight) {
|
|
return parentHeight;
|
|
}
|
|
node = node.parent;
|
|
}
|
|
};
|
|
PresNode.prototype.isCanAdapt = function (constr, isAdapt) {
|
|
if (isAdapt) {
|
|
switch (constr.type) {
|
|
case AscFormat.Constr_type_w:
|
|
case AscFormat.Constr_type_h: {
|
|
const relation = this.getRelationConstr(constr.type);
|
|
return !!(relation && constr === relation.constr);
|
|
}
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
PresNode.prototype.getRefConstr = function (constr, isAdapt) {
|
|
let aspectRatio;
|
|
if (!(constr.for === AscFormat.Constr_for_self && constr.refFor === AscFormat.Constr_for_self && !isUserConstr(constr.type))) {
|
|
aspectRatio = this.getAspectRatio();
|
|
}
|
|
const constrObject = isAdapt ? this.adaptConstr : this.constr;
|
|
let value;
|
|
if (isUserConstr(constr.type) && constr.refType === AscFormat.Constr_type_none && constrObject[constr.type] !== undefined && constr.refFor === AscFormat.Constr_for_self) {
|
|
value = constrObject[constr.type];
|
|
} else if (constr.refType === AscFormat.Constr_type_none) {
|
|
value = constr.val;
|
|
} else if (constrObject[constr.refType]) {
|
|
value = constrObject[constr.refType];
|
|
}
|
|
if (value !== undefined) {
|
|
if (aspectRatio) {
|
|
switch (constr.refType) {
|
|
case AscFormat.Constr_type_h:
|
|
const width = constrObject[AscFormat.Constr_type_w];
|
|
if (width !== undefined) {
|
|
const aspectWidth = width / aspectRatio;
|
|
if (aspectWidth < value) {
|
|
value = aspectWidth;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case AscFormat.Constr_type_w:
|
|
const height = constrObject[AscFormat.Constr_type_h];
|
|
if (height !== undefined) {
|
|
const aspectHeight = height * aspectRatio;
|
|
if (aspectHeight < value) {
|
|
value = aspectHeight;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
value = this.getConstr(constr.refType, isAdapt, true);
|
|
if (value === undefined) {
|
|
switch (constr.refType) {
|
|
case AscFormat.Constr_type_w: {
|
|
const parentWidth = this.getParentWidth(isAdapt);
|
|
constrObject[AscFormat.Constr_type_w] = parentWidth;
|
|
return parentWidth;
|
|
}
|
|
case AscFormat.Constr_type_h: {
|
|
const parentHeight = this.getParentHeight(isAdapt);
|
|
constrObject[AscFormat.Constr_type_h] = parentHeight;
|
|
return parentHeight;
|
|
}
|
|
default: {
|
|
value = constr.val;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return value;
|
|
};
|
|
|
|
PresNode.prototype.setAlgorithm = function (algorithm) {
|
|
this.algorithm = algorithm;
|
|
}
|
|
|
|
PresNode.prototype.getAlgorithm = function () {
|
|
return this.algorithm;
|
|
}
|
|
PresNode.prototype.getPositionConstrWithOffset = function (posConstrType, offsetConstrType, isAdapt) {
|
|
const constrObject = this.getConstraints(isAdapt);
|
|
const position = constrObject[posConstrType];
|
|
let result;
|
|
if (position !== undefined) {
|
|
result = position;
|
|
const offset = constrObject[offsetConstrType];
|
|
if (offset !== undefined) {
|
|
result += offset;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
PresNode.prototype.getConstrForCalculating = function (type, isAdapt) {
|
|
switch (type) {
|
|
case AscFormat.Constr_type_l:
|
|
return this.getPositionConstrWithOffset(type, AscFormat.Constr_type_lOff, isAdapt);
|
|
case AscFormat.Constr_type_r:
|
|
return this.getPositionConstrWithOffset(type, AscFormat.Constr_type_rOff, isAdapt);
|
|
case AscFormat.Constr_type_t:
|
|
return this.getPositionConstrWithOffset(type, AscFormat.Constr_type_tOff, isAdapt);
|
|
case AscFormat.Constr_type_b:
|
|
return this.getPositionConstrWithOffset(type, AscFormat.Constr_type_bOff, isAdapt);
|
|
case AscFormat.Constr_type_ctrX:
|
|
return this.getPositionConstrWithOffset(type, AscFormat.Constr_type_ctrXOff, isAdapt);
|
|
case AscFormat.Constr_type_ctrY:
|
|
return this.getPositionConstrWithOffset(type, AscFormat.Constr_type_ctrYOff, isAdapt);
|
|
case AscFormat.Constr_type_w:
|
|
return this.getPositionConstrWithOffset(type, AscFormat.Constr_type_wOff, isAdapt);
|
|
case AscFormat.Constr_type_h:
|
|
return this.getPositionConstrWithOffset(type, AscFormat.Constr_type_hOff, isAdapt);
|
|
default:
|
|
const constrObj = this.getConstraints(isAdapt);
|
|
return constrObj[type];
|
|
}
|
|
};
|
|
PresNode.prototype.getConstr = function (type, isAdapt, skipDefaultValue, depth) {
|
|
depth = depth || 0;
|
|
const constrObj = isAdapt ? this.adaptConstr : this.constr;
|
|
let result = this.getConstrForCalculating(type, isAdapt);
|
|
if (depth < 2) {
|
|
switch (type) {
|
|
case AscFormat.Constr_type_l: {
|
|
const width = this.getConstr(AscFormat.Constr_type_w, isAdapt, false, depth + 1);
|
|
const right = this.getConstrForCalculating(AscFormat.Constr_type_r, isAdapt);
|
|
const ctrX = this.getConstrForCalculating(AscFormat.Constr_type_ctrX, isAdapt);
|
|
if (ctrX !== undefined) {
|
|
result = ctrX - width / 2;
|
|
} else if (right !== undefined) {
|
|
result = right - width;
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_type_t: {
|
|
const height = this.getConstrForCalculating(AscFormat.Constr_type_h, isAdapt);
|
|
if (height !== undefined) {
|
|
const ctrY = this.getConstrForCalculating(AscFormat.Constr_type_ctrY, isAdapt);
|
|
const bottom = this.getConstrForCalculating(AscFormat.Constr_type_b, isAdapt);
|
|
if (ctrY !== undefined) {
|
|
result = ctrY - height / 2;
|
|
} else if (bottom !== undefined) {
|
|
result = bottom - height;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_type_w: {
|
|
const right = this.getConstrForCalculating(AscFormat.Constr_type_r, isAdapt);
|
|
const left = this.getConstrForCalculating(AscFormat.Constr_type_l, isAdapt);
|
|
if (right !== undefined && left !== undefined) {
|
|
result = right - left;
|
|
} else if (this.algorithm instanceof TextAlgorithm && result === undefined) {
|
|
const wOff = constrObj[AscFormat.Constr_type_wOff];
|
|
result = this.getParentWidth(isAdapt);
|
|
if (left !== undefined) {
|
|
result -= left;
|
|
} else if (wOff !== undefined) {
|
|
result += wOff;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_type_h: {
|
|
const bottom = this.getConstrForCalculating(AscFormat.Constr_type_b, isAdapt);
|
|
const top = this.getConstr(AscFormat.Constr_type_t, isAdapt, true, depth + 1);
|
|
if (bottom !== undefined && top !== undefined) {
|
|
result = bottom - top;
|
|
} else if (this.algorithm instanceof TextAlgorithm && result === undefined) {
|
|
const hOff = constrObj[AscFormat.Constr_type_hOff];
|
|
result = this.getParentHeight(isAdapt);
|
|
if (top !== undefined) {
|
|
result -= top;
|
|
} else if (hOff !== undefined) {
|
|
result += hOff;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_type_b: {
|
|
const height = this.getConstrForCalculating(AscFormat.Constr_type_h, isAdapt);
|
|
if (AscFormat.isRealNumber(height)) {
|
|
const top = this.getConstrForCalculating(AscFormat.Constr_type_t, isAdapt);
|
|
const ctrY = this.getConstrForCalculating(AscFormat.Constr_type_ctrY, isAdapt);
|
|
if (AscFormat.isRealNumber(top)) {
|
|
result = top + height;
|
|
} else if (AscFormat.isRealNumber(ctrY)) {
|
|
result = ctrY + height / 2;
|
|
} else {
|
|
result = height;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_type_r: {
|
|
const width = this.getConstr(AscFormat.Constr_type_w, isAdapt, true, depth + 1);
|
|
if (AscFormat.isRealNumber(width)) {
|
|
const left = this.getConstr(AscFormat.Constr_type_l, isAdapt, false, depth + 1);
|
|
result = left + width;
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_type_ctrY: {
|
|
const height = this.getConstr(AscFormat.Constr_type_h, isAdapt, true, depth + 1);
|
|
if (AscFormat.isRealNumber(height)) {
|
|
const top = this.getConstr(AscFormat.Constr_type_t, isAdapt, false, depth + 1);
|
|
result = top + height / 2;
|
|
}
|
|
break;
|
|
}
|
|
case AscFormat.Constr_type_ctrX: {
|
|
const width = this.getConstr(AscFormat.Constr_type_w, isAdapt, true, depth + 1);
|
|
if (AscFormat.isRealNumber(width)) {
|
|
const left = this.getConstr(AscFormat.Constr_type_l, isAdapt, false, depth + 1);
|
|
result = left + width / 2;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return skipDefaultValue ? result : (result || 0);
|
|
};
|
|
|
|
PresNode.prototype.checkName = function (name) {
|
|
if (this.getPresName() === name) {
|
|
return this;
|
|
}
|
|
}
|
|
|
|
PresNode.prototype.startAlgorithm = function (smartartAlgorithm, isCalculateScaleCoefficients) {
|
|
if (this.algorithm) {
|
|
this.algorithm.calculateShapePositions(smartartAlgorithm, isCalculateScaleCoefficients);
|
|
}
|
|
}
|
|
|
|
PresNode.prototype.calcScaleCoefficients = function (smartartAlgorithm) {
|
|
if (this.algorithm) {
|
|
this.algorithm.calcScaleCoefficients(smartartAlgorithm);
|
|
}
|
|
}
|
|
PresNode.prototype.setLayoutConstraints = function (lst) {
|
|
this.layoutInfo.constrLst = lst;
|
|
};
|
|
PresNode.prototype.setLayoutRules = function (lst) {
|
|
this.layoutInfo.ruleLst = lst;
|
|
};
|
|
PresNode.prototype.isTxXfrm = function () {
|
|
const contentNode = this.node;
|
|
const textNodes = contentNode.getTextNodes();
|
|
return !!(textNodes.textNode && textNodes.contentNode && textNodes.textNode === this);
|
|
};
|
|
|
|
PresNode.prototype.updateCompositeSizes = function (isCalculateCoefficients) {
|
|
const shape = this.getShape(isCalculateCoefficients);
|
|
if (!this.childs.length) {
|
|
shape.width = 0;
|
|
shape.height = 0;
|
|
return;
|
|
}
|
|
|
|
let shapeBounds;
|
|
let cleanShapeBounds;
|
|
for (let i = 0; i < this.childs.length; i += 1) {
|
|
const node = this.childs[i];
|
|
const childShape = node.getShape(isCalculateCoefficients);
|
|
// todo: check this
|
|
if (childShape.width <= 0 && childShape.height <= 0 || (node.algorithm instanceof ConnectorAlgorithm) || ((node.algorithm instanceof TextAlgorithm) && !node.isRealShapeType()) || node.isTxXfrm()) {
|
|
continue;
|
|
}
|
|
if (shapeBounds) {
|
|
checkBounds(shapeBounds, childShape.getBounds());
|
|
checkBounds(cleanShapeBounds, childShape.getBounds(true));
|
|
} else {
|
|
shapeBounds = childShape.getBounds();
|
|
cleanShapeBounds = childShape.getBounds(true);
|
|
}
|
|
}
|
|
if (!shapeBounds) {
|
|
shape.width = 0;
|
|
shape.height = 0;
|
|
return;
|
|
}
|
|
|
|
|
|
shape.x = shapeBounds.l;
|
|
shape.y = shapeBounds.t;
|
|
shape.cleanParams.x = cleanShapeBounds.l;
|
|
shape.cleanParams.y = cleanShapeBounds.t;
|
|
|
|
|
|
shape.width = shapeBounds.r - shapeBounds.l;
|
|
shape.height = shapeBounds.b - shapeBounds.t;
|
|
|
|
shape.cleanParams.width = cleanShapeBounds.r - cleanShapeBounds.l;
|
|
shape.cleanParams.height = cleanShapeBounds.b - cleanShapeBounds.t;
|
|
return shapeBounds;
|
|
};
|
|
|
|
PresNode.prototype.createShadowShape = function (isComposite, isCalculateCoefficients) {
|
|
|
|
const shape = this.getShape(isCalculateCoefficients);
|
|
shape.initFromShape(this.layoutInfo.shape);
|
|
this.createShadowShapeFromConstraints(this.layoutInfo.shape, isCalculateCoefficients);
|
|
if (isComposite) {
|
|
this.forEachChild(function (node) {
|
|
node.moveTo(shape.x, shape.y, isCalculateCoefficients, true);
|
|
});
|
|
this.algorithm.setConstraintSizes(shape);
|
|
return this.updateCompositeSizes(isCalculateCoefficients);
|
|
}
|
|
};
|
|
PresNode.prototype.createHierarchyRootShadowShape = function (isCalculateCoefficients) {
|
|
const algorithm = this.algorithm;
|
|
if (algorithm) {
|
|
const root = algorithm.getRoot();
|
|
const shape = this.getShape(isCalculateCoefficients);
|
|
shape.initFromShape(this.layoutInfo.shape);
|
|
// root.algorithm.getBounds();
|
|
const rootShape = root.getShape(isCalculateCoefficients);
|
|
shape.x = rootShape.x;
|
|
shape.y = rootShape.y;
|
|
shape.width = rootShape.width;
|
|
shape.height = rootShape.height;
|
|
shape.rot = rootShape.rot;
|
|
shape.cleanParams = Object.assign({}, rootShape.cleanParams);
|
|
}
|
|
};
|
|
PresNode.prototype.createHierarchyChildShadowShape = function (isCalculateCoefficients) {
|
|
const shape = this.getShape(isCalculateCoefficients);
|
|
shape.initFromShape(this.layoutInfo.shape);
|
|
const childs = this.algorithm.getMainChilds();
|
|
if (!childs.length) {
|
|
return;
|
|
}
|
|
let bounds = childs[0].algorithm.getBounds(isCalculateCoefficients);
|
|
for (let i = 1; i < childs.length; i += 1) {
|
|
const child = childs[i];
|
|
const algorithm = child.algorithm;
|
|
bounds = algorithm.getBounds(isCalculateCoefficients, bounds);
|
|
}
|
|
if (bounds) {
|
|
shape.x = bounds.l;
|
|
shape.y = bounds.t;
|
|
shape.width = bounds.r - bounds.l;
|
|
shape.height = bounds.b - bounds.t;
|
|
}
|
|
};
|
|
PresNode.prototype.getConstraints = function (isAdapt) {
|
|
return isAdapt ? this.adaptConstr : this.constr;
|
|
};
|
|
PresNode.prototype.setMoveRot = function (rot) {
|
|
this.moveRot = rot;
|
|
}
|
|
PresNode.prototype.createShadowShapeFromConstraints = function (layoutShape, isCalculateCoefficients) {
|
|
const isChildInSpaceAlgorithm = this.parent && this.parent.algorithm instanceof SpaceAlgorithm;
|
|
const constrNode = isChildInSpaceAlgorithm ? this.parent : this;
|
|
|
|
const shape = this.getShape(isCalculateCoefficients);
|
|
shape.rot = AscFormat.normalizeRotate(degToRad * layoutShape.rot);
|
|
|
|
const widthCoef = this.getWidthScale();
|
|
const heightCoef = this.getHeightScale();
|
|
let x = constrNode.getConstr(AscFormat.Constr_type_l, !isCalculateCoefficients);
|
|
let y = constrNode.getConstr(AscFormat.Constr_type_t, !isCalculateCoefficients);
|
|
let width = constrNode.getConstr(AscFormat.Constr_type_w, !isCalculateCoefficients, !isChildInSpaceAlgorithm);
|
|
let height = constrNode.getConstr(AscFormat.Constr_type_h, !isCalculateCoefficients, !isChildInSpaceAlgorithm);
|
|
if (width === undefined && height === undefined) {
|
|
const isSpaceAlgorithm = this.algorithm instanceof SpaceAlgorithm;
|
|
width = isSpaceAlgorithm ? (constrNode.getParentWidth(!isCalculateCoefficients) || 0) : 0;
|
|
height = isSpaceAlgorithm ? (constrNode.getParentHeight(!isCalculateCoefficients) || 0): 0;
|
|
} else {
|
|
width = width || 0;
|
|
height = height || 0;
|
|
}
|
|
const newSizes = AscFormat.fGetMaxInscribedRectangle(width, height, shape.rot);
|
|
const newScaledSizes = AscFormat.fGetMaxInscribedRectangle(width * widthCoef, height * heightCoef, shape.rot);
|
|
x += (width - newSizes.width) / 2;
|
|
y += (height - newSizes.height) / 2;
|
|
width = newSizes.width;
|
|
height = newSizes.height;
|
|
const scaleWidth = newScaledSizes.width;
|
|
const scaleHeight = newScaledSizes.height;
|
|
shape.x = x;
|
|
shape.y = y;
|
|
|
|
|
|
shape.width = scaleWidth;
|
|
shape.height = scaleHeight;
|
|
const offX = (width - shape.width) / 2;
|
|
const offY = (height - shape.height) / 2;
|
|
shape.x += offX;
|
|
shape.y += offY;
|
|
|
|
let moveRot = 0;
|
|
const prSet = this.getPrSet();
|
|
|
|
if (prSet && prSet.custAng) {
|
|
moveRot = prSet.custAng;
|
|
}
|
|
for (let i = 0; i < this.moveWithNodes.length; i += 1) {
|
|
const moveNode = this.moveWithNodes[i];
|
|
if (moveNode.isInitShape(isCalculateCoefficients)) {
|
|
const moveShape = moveNode.getShape(isCalculateCoefficients);
|
|
const scaleMoveWidth = moveShape.width * widthCoef;
|
|
const scaleMoveHeight = moveShape.height * heightCoef;
|
|
const moveOffX = (shape.x + (moveShape.x - x) * widthCoef) - moveShape.x;
|
|
const moveOffY = (moveShape.height - scaleMoveHeight) / 2;
|
|
moveShape.width = scaleMoveWidth;
|
|
moveShape.height = scaleMoveHeight;
|
|
moveNode.moveTo(moveOffX, moveOffY, isCalculateCoefficients);
|
|
|
|
|
|
} else {
|
|
moveNode.setMoveScaleCoefficients(widthCoef, heightCoef);
|
|
}
|
|
moveNode.setMoveRot(moveRot);
|
|
}
|
|
const textNodes = this.contentNodes[0] && this.contentNodes[0].getTextNodes();
|
|
if (textNodes && textNodes.contentNode === this && textNodes.textNode) {
|
|
if (textNodes.textNode.isInitShape(isCalculateCoefficients)) {
|
|
const moveShape = textNodes.textNode.getShape(isCalculateCoefficients);
|
|
const scaleMoveWidth = moveShape.width * widthCoef;
|
|
const scaleMoveHeight = moveShape.height * heightCoef;
|
|
const moveOffX = shape.x + shape.width / 2 + (moveShape.x + moveShape.width / 2 - (x + width / 2)) * widthCoef - (moveShape.x + scaleMoveWidth / 2);
|
|
const moveOffY = shape.y + shape.height / 2 + (moveShape.y + moveShape.height / 2 - (y + height / 2)) * heightCoef - (moveShape.y + scaleMoveHeight / 2);
|
|
moveShape.width = scaleMoveWidth;
|
|
moveShape.height = scaleMoveHeight;
|
|
textNodes.textNode.moveTo(moveOffX, moveOffY, isCalculateCoefficients);
|
|
}
|
|
}
|
|
|
|
shape.cleanParams = {
|
|
width: width,
|
|
height: height,
|
|
x: x,
|
|
y: y
|
|
};
|
|
};
|
|
PresNode.prototype.isInitShape = function (isCalculateScaleCoefficient) {
|
|
return !!(isCalculateScaleCoefficient ? this.position : this.shape);
|
|
};
|
|
PresNode.prototype.setMoveScaleCoefficients = function (widthCoefficient, heightCoefficient) {
|
|
this.moveScaleCoefficients.width = widthCoefficient;
|
|
this.moveScaleCoefficients.height = heightCoefficient;
|
|
};
|
|
PresNode.prototype.getChildConstraintBounds = function (isCalculateCoefficients) {
|
|
if (this.bounds.constraints === null) {
|
|
const constrBounds = {
|
|
l: 0,
|
|
r: 0,
|
|
t: 0,
|
|
b: 0
|
|
};
|
|
this.bounds.constraints = constrBounds;
|
|
if (this.childs.length) {
|
|
const firstNodeConstraints = this.childs[0].algorithm && this.childs[0].algorithm.constraintSizes;
|
|
if (firstNodeConstraints) {
|
|
constrBounds.b = firstNodeConstraints.y + firstNodeConstraints.height;
|
|
constrBounds.t = firstNodeConstraints.y;
|
|
constrBounds.l = firstNodeConstraints.x;
|
|
constrBounds.r = firstNodeConstraints.x + firstNodeConstraints.width;
|
|
} else {
|
|
const shape = this.childs[0].getShape(isCalculateCoefficients);
|
|
constrBounds.b = shape.y + shape.height;
|
|
constrBounds.t = shape.y;
|
|
constrBounds.l = shape.x;
|
|
constrBounds.r = shape.x + shape.width;
|
|
}
|
|
for (let i = 1; i < this.childs.length; i++) {
|
|
this.childs[i].checkConstraintBounds(constrBounds, isCalculateCoefficients);
|
|
}
|
|
}
|
|
}
|
|
return this.bounds.constraints;
|
|
};
|
|
PresNode.prototype.checkConstraintBounds = function (bounds, isCalculateScaleCoefficient) {
|
|
if (!this.isContentNode()) {
|
|
return;
|
|
}
|
|
const constraintSizes = this.algorithm && this.algorithm.constraintSizes;
|
|
if (constraintSizes) {
|
|
if (constraintSizes.x < bounds.l) {
|
|
bounds.l = constraintSizes.x;
|
|
}
|
|
if (constraintSizes.y < bounds.t) {
|
|
bounds.t = constraintSizes.y;
|
|
}
|
|
const right = constraintSizes.x + constraintSizes.width;
|
|
if (right > bounds.r) {
|
|
bounds.r = right;
|
|
}
|
|
const bottom = constraintSizes.y + constraintSizes.height;
|
|
if (bottom > bounds.b) {
|
|
bounds.b = bottom;
|
|
}
|
|
} else {
|
|
const shape = this.getShape(isCalculateScaleCoefficient);
|
|
if (shape.x < bounds.l) {
|
|
bounds.l = shape.x;
|
|
}
|
|
if (shape.y < bounds.t) {
|
|
bounds.t = shape.y;
|
|
}
|
|
const right = shape.x + shape.width;
|
|
if (right > bounds.r) {
|
|
bounds.r = right;
|
|
}
|
|
const bottom = shape.y + shape.height;
|
|
if (bottom > bounds.b) {
|
|
bounds.b = bottom;
|
|
}
|
|
}
|
|
};
|
|
|
|
PresNode.prototype.getHeightScale = function (force) {
|
|
if (!force && !this.isRealShapeType()) {
|
|
return this.moveScaleCoefficients.height;
|
|
}
|
|
const prSet = this.getPrSet();
|
|
if (prSet) {
|
|
return (prSet.custScaleY || 1) * this.moveScaleCoefficients.height;
|
|
}
|
|
return this.moveScaleCoefficients.height;
|
|
}
|
|
|
|
PresNode.prototype.getWidthScale = function (force) {
|
|
if (!force && !this.isRealShapeType()) {
|
|
return this.moveScaleCoefficients.width;
|
|
}
|
|
const prSet = this.getPrSet();
|
|
if (prSet) {
|
|
return (prSet.custScaleX || 1) * this.moveScaleCoefficients.width;
|
|
}
|
|
return this.moveScaleCoefficients.width;
|
|
}
|
|
|
|
PresNode.prototype.initRootConstraints = function (smartArt, smartartAlgorithm) {
|
|
const sizes = smartArt.getSizes();
|
|
this.constr[AscFormat.Constr_type_w] = sizes.width;
|
|
this.constr[AscFormat.Constr_type_h] = sizes.height;
|
|
this.adaptConstr[AscFormat.Constr_type_w] = sizes.width;
|
|
this.adaptConstr[AscFormat.Constr_type_h] = sizes.height;
|
|
};
|
|
PresNode.prototype.getModelId = function () {
|
|
return this.presPoint.getModelId();
|
|
};
|
|
|
|
function CConnectionDistanceResolver() {
|
|
this.connectionAlgorithms = [];
|
|
this.connectionDistance = null;
|
|
}
|
|
|
|
CConnectionDistanceResolver.prototype.calcChildConnectionDistance = function () {
|
|
this.connectionDistance = -1;
|
|
const firstAlg = this.connectionAlgorithms[0];
|
|
if (firstAlg) {
|
|
const points = firstAlg.getConnectionPoints();
|
|
if (points.end && points.start) {
|
|
const v = new CVector(points.end.x - points.start.x, points.end.y - points.start.y);
|
|
this.connectionDistance = v.getDistance();
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
for (let i = 1; i < this.connectionAlgorithms.length; i++) {
|
|
const alg = this.connectionAlgorithms[i];
|
|
const points = alg.getConnectionPoints();
|
|
if (points.end && points.start) {
|
|
const v = new CVector(points.end.x - points.start.x, points.end.y - points.start.y);
|
|
const distance = v.getDistance();
|
|
if (distance < this.connectionDistance) {
|
|
this.connectionDistance = distance;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
CConnectionDistanceResolver.prototype.getConnectionDistance = function () {
|
|
if (this.connectionDistance === null) {
|
|
this.calcChildConnectionDistance();
|
|
}
|
|
return this.connectionDistance;
|
|
};
|
|
CConnectionDistanceResolver.prototype.addConnection = function (algorithm) {
|
|
this.connectionAlgorithms.push(algorithm);
|
|
}
|
|
|
|
function getShapePoint(bounds) {
|
|
return new CCoordPoint(bounds.l + (bounds.r - bounds.l) / 2, bounds.t + (bounds.b - bounds.t) / 2);
|
|
}
|
|
function getMinShapeEdgePoint(bounds, guideVector) {
|
|
if (bounds.isEllipse) {
|
|
return getMinCircleEdgePoint(bounds, guideVector);
|
|
} else {
|
|
return getMinRectEdgePoint(bounds, guideVector);
|
|
}
|
|
}
|
|
function resolveParameterLineAndShapeEquation(ellipseBounds, paramLine) {
|
|
const width = ellipseBounds.r - ellipseBounds.l;
|
|
const height = ellipseBounds.b - ellipseBounds.t;
|
|
const cw = width / 2;
|
|
const ch = height / 2;
|
|
const cx = cw + ellipseBounds.l;
|
|
const cy = ch + ellipseBounds.t;
|
|
|
|
const px = paramLine.ax;
|
|
const py = paramLine.ay;
|
|
const x1 = paramLine.x;
|
|
const y1 = paramLine.y;
|
|
const ch2 = ch * ch;
|
|
const cw2 = cw * cw;
|
|
const a = ch2 * px * px + cw2 * py * py;
|
|
const b = 2 * ch2 * px * (x1 - cx) + 2 * cw2 * py * (y1 - cy);
|
|
const c = ch2 * (cy * cy - 2 * cy * y1 + y1 * y1) + cw2 * (cx * cx - 2 * cx * x1 + x1 * x1) - cw2 * ch2;
|
|
return AscFormat.fSolveQuadraticEquation(a, b, c);
|
|
}
|
|
|
|
function getMinCircleEdgePoint(bounds, guideVector) {
|
|
const shapePoint = getShapePoint(bounds);
|
|
const line = getParametricLinEquation(shapePoint, guideVector);
|
|
const answer = resolveParameterLineAndShapeEquation(bounds, line);
|
|
if (answer.bError) {
|
|
return null;
|
|
}
|
|
const angle = guideVector.getAngle();
|
|
|
|
const xt1 = line.x + line.ax * answer.x1;
|
|
const yt1 = line.y + line.ay * answer.x1;
|
|
|
|
let edgeAngle = new CVector(xt1 - shapePoint.x, yt1 - shapePoint.y).getAngle();
|
|
if (AscFormat.fApproxEqual(edgeAngle, angle, algDelta)) {
|
|
return new CCoordPoint(xt1, yt1);
|
|
}
|
|
|
|
const xt2 = line.x + line.ax * answer.x2;
|
|
const yt2 = line.y + line.ay * answer.x2;
|
|
|
|
edgeAngle = new CVector(xt2 - shapePoint.x, yt2 - shapePoint.y).getAngle();
|
|
if (AscFormat.fApproxEqual(edgeAngle, angle, algDelta)) {
|
|
return new CCoordPoint(xt2, yt2);
|
|
}
|
|
}
|
|
|
|
function getMinRectEdgePoint(bounds, guideVector) {
|
|
const shapePoint = getShapePoint(bounds);
|
|
const centerAngle = guideVector.getAngle();
|
|
let checkEdges = [
|
|
[new CCoordPoint(bounds.l, bounds.t), new CCoordPoint(bounds.r, bounds.t)],
|
|
[new CCoordPoint(bounds.r, bounds.t), new CCoordPoint(bounds.r, bounds.b)],
|
|
[new CCoordPoint(bounds.l, bounds.t), new CCoordPoint(bounds.l, bounds.b)],
|
|
[new CCoordPoint(bounds.l, bounds.b), new CCoordPoint(bounds.r, bounds.b)]
|
|
];
|
|
for (let i = 0; i < checkEdges.length; i += 1) {
|
|
const edge = checkEdges[i];
|
|
const point = getRectEdgePoint(shapePoint, guideVector, edge[0], edge[1]);
|
|
if (point) {
|
|
const edgeGuideVector = new CVector(point.x - shapePoint.x, point.y - shapePoint.y);
|
|
const edgeAngle = edgeGuideVector.getAngle();
|
|
if (AscFormat.fApproxEqual(edgeAngle, centerAngle, algDelta)) {
|
|
return point;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function getParametricLinEquation(startPoint, guideVector) {
|
|
const len = guideVector.getDistance();
|
|
return {
|
|
x: startPoint.x,
|
|
ax: guideVector.x / len,
|
|
y: startPoint.y,
|
|
ay: guideVector.y / len
|
|
};
|
|
}
|
|
function getRectEdgePoint(linePoint, guideVector, rectEdgePoint1, rectEdgePoint2) {
|
|
const line1 = getParametricLinEquation(linePoint, guideVector);
|
|
const line2 = getParametricLinEquation(rectEdgePoint1, new CVector(rectEdgePoint2.x - rectEdgePoint1.x, rectEdgePoint2.y - rectEdgePoint1.y));
|
|
return getIntersectionLines(line1, line2, rectEdgePoint1, rectEdgePoint2);
|
|
}
|
|
function getIntersectionLines(line1, line2, rectEdgePoint1, rectEdgePoint2) {
|
|
const divider = line1.ay * line2.ax - line1.ax * line2.ay;
|
|
if (divider === 0) {
|
|
return null;
|
|
}
|
|
const parameter = (line1.ax * (line2.y - line1.y) - line1.ay * (line2.x - line1.x)) / divider;
|
|
const x = line2.x + line2.ax * parameter;
|
|
const y = line2.y + line2.ay * parameter;
|
|
if (((x > rectEdgePoint1.x && x < rectEdgePoint2.x) || AscFormat.fApproxEqual(x, rectEdgePoint2.x, algDelta) || AscFormat.fApproxEqual(x, rectEdgePoint1.x, algDelta))
|
|
&& ((y > rectEdgePoint1.y && y < rectEdgePoint2.y) || AscFormat.fApproxEqual(y, rectEdgePoint2.y, algDelta) || AscFormat.fApproxEqual(y, rectEdgePoint1.y, algDelta))) {
|
|
return new CCoordPoint(x, y);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// document.body.addEventListener('keydown', function (e) {
|
|
// if (e.ctrlKey && e.altKey && e.keyCode === 82) {
|
|
// const oSM = editor.getGraphicController().selectedObjects[0];
|
|
// const smartArtAlgorithm = new SmartArtAlgorithm(oSM);
|
|
// smartArtAlgorithm.startFromBegin();
|
|
// const drawing = oSM.spTree[0];
|
|
// const shapeLength = drawing.spTree.length;
|
|
// for (let i = 0; i < shapeLength; i++) {
|
|
// drawing.removeFromSpTreeByPos(0);
|
|
// }
|
|
// const shapes = smartArtAlgorithm.getShapes();
|
|
//
|
|
// for (let i = shapes.length - 1; i >= 0; i -= 1) {
|
|
// drawing.addToSpTree(0, shapes[i]);
|
|
// }
|
|
//
|
|
// oSM.recalculate();
|
|
//
|
|
// editor.getLogicDocument().Recalculate();
|
|
// oSM.fitFontSize();
|
|
// editor.getLogicDocument().Recalculate();
|
|
// }
|
|
// });
|
|
|
|
AscFormat.SmartArtAlgorithm = SmartArtAlgorithm;
|
|
AscFormat.TextAlgorithm = TextAlgorithm;
|
|
})(window);
|
|
|