Files
DocumentServer-v-9.2.0/sdkjs/common/SmartArts/SmartArtTree.js
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

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);