kekule
Version:
Open source JavaScript toolkit for chemoinformatics
739 lines (691 loc) • 24.2 kB
JavaScript
/**
* @fileoverview
* Implementation of line based glyphs defined by a series of nodes and paths.
* @author Partridge Jiang
*/
/*
* requires /lan/classes.js
* requires /core/kekule.common.js
* requires /core/kekule.structures.js
* requires /chemdoc/kekule.glyph.base.js
* requires /chemdoc/kekule.glyph.pathGlyphs.js
* requires /chemdoc/kekule.glyph.utils.js
*/
(function(){
"use strict";
var OU = Kekule.ObjUtils;
var NT = Kekule.Glyph.NodeType;
var PT = Kekule.Glyph.PathType;
var CU = Kekule.CoordUtils;
var CM = Kekule.CoordMode;
/**
* A glyph of straight line.
* @class
* @augments Kekule.Glyph.PathGlyph
*/
Kekule.Glyph.StraightLine = Class.create(Kekule.Glyph.PathGlyph,
/** @lends Kekule.Glyph.StraightLine# */
{
/** @private */
CLASS_NAME: 'Kekule.Glyph.StraightLine',
/** @constructs */
initialize: function(/*$super, */id, refLength, initialParams, coord2D, coord3D)
{
this.tryApplySuper('initialize', [id, refLength, initialParams, coord2D, coord3D]) /* $super(id, refLength, initialParams, coord2D, coord3D) */;
},
/** @private */
doCreateDefaultStructure: function(refLength, initialParams)
{
// initialParams can include additional field: lineLength
var C = Kekule.CoordUtils;
var coord2D = {'x': 0, 'y': 0};
var coord3D = {'x': 0, 'y': 0, 'z': 0};
var delta = {'x': refLength * (initialParams.lineLength || 1)};
var node1 = new Kekule.Glyph.PathGlyphNode(null, null, coord2D, coord3D);
var node2 = new Kekule.Glyph.PathGlyphNode(null, null, C.add(coord2D, delta), C.add(coord3D, delta));
var connector = new Kekule.Glyph.PathGlyphConnector(null, PT.LINE, [node1, node2]);
this._applyParamsToConnector(connector, initialParams);
this.appendNode(node1);
this.appendNode(node2);
this.appendConnector(connector);
},
/** @private */
_applyParamsToConnector: function(connector, initialParams)
{
//connector.setPathParams(initialParams);
var p = Object.create(initialParams);
if (Kekule.ObjUtils.isUnset(initialParams.autoOffset))
p.autoOffset = false;
connector.setPathParams(p);
},
/** @ignore */
getDirectManipulationTarget: function()
{
return this.getNodeAt(this.getNodeCount() - 1);
}
/* @ignore */
/*
getAllowChildCoordStickTo: function(child, dest)
{
return true;
},
*/
/* @ignore */
/*
getChildAcceptCoordStickFrom: function(child, fromObj)
{
return true;
}
*/
});
/**
* A glyph of polygon formed by straight lines.
* @class
* @augments Kekule.Glyph.PathGlyph
*/
Kekule.Glyph.Polygon = Class.create(Kekule.Glyph.PathGlyph,
/** @lends Kekule.Glyph.Polygon# */
{
/** @private */
CLASS_NAME: 'Kekule.Glyph.Polygon',
/** @constructs */
initialize: function(/*$super, */id, refLength, initialParams, coord2D, coord3D)
{
this.tryApplySuper('initialize', [id, refLength, initialParams, coord2D, coord3D]) /* $super(id, refLength, initialParams, coord2D, coord3D) */;
},
/** @private */
getRefLengthRatio: function()
{
return 1;
},
/** @private */
doCreateDefaultStructure: function(refLength, initialParams)
{
// initialParams can include additional field: lineLength, edgeCount
// node props, connector props
var C = Kekule.CoordUtils;
var coord2D = {'x': 0, 'y': 0};
var coord3D = {'x': 0, 'y': 0, 'z': 0};
var nodeProps = initialParams.nodeProps;
var connectorProps = initialParams.connectorProps;
var r = refLength * (initialParams.lineLength || 1) * this.getRefLengthRatio();
var edgeCount = initialParams.edgeCount || 3;
var angleDelta = Math.PI * 2 / edgeCount;
var startingAngle = (edgeCount % 2)?0: -angleDelta / 2;
var currAngle = startingAngle;
var firstNode, lastNode;
for (var i = 0; i < edgeCount; ++i)
{
var c = {'x': r * Math.sin(currAngle), 'y': r * Math.cos(currAngle)};
var node = new Kekule.Glyph.PathGlyphNode(null, null, C.add(coord2D, c), C.add(coord3D, c));
if (nodeProps)
node.setPropValues(nodeProps);
this.appendNode(node);
if (i === 0)
firstNode = node;
if (lastNode)
{
var connector = new Kekule.Glyph.PathGlyphConnector(null, PT.LINE, [lastNode, node]);
if (connectorProps)
connector.setPropValues(connectorProps);
this._applyParamsToConnector(connector, initialParams);
this.appendConnector(connector);
}
lastNode = node;
currAngle += angleDelta;
}
var connector = new Kekule.Glyph.PathGlyphConnector(null, PT.LINE, [node, firstNode]);
if (connectorProps)
connector.setPropValues(connectorProps);
this._applyParamsToConnector(connector, initialParams);
this.appendConnector(connector);
},
/** @private */
_applyParamsToConnector: function(connector, initialParams)
{
connector.setPathParams(initialParams);
}
});
/**
* A base glyph of arc segment.
* @class
* @augments Kekule.Glyph.PathGlyph
*/
Kekule.Glyph.BaseArc = Class.create(Kekule.Glyph.PathGlyph,
/** @lends Kekule.Glyph.BaseArc# */
{
/** @private */
CLASS_NAME: 'Kekule.Glyph.BaseArc',
/** @constructs */
initialize: function(/*$super, */id, refLength, initialParams, coord2D, coord3D)
{
this.tryApplySuper('initialize', [id, refLength, initialParams, coord2D, coord3D]) /* $super(id, refLength, initialParams, coord2D, coord3D) */;
},
/** @ignore */
doCreateDefaultStructure: function(refLength, initialParams)
{
// initialParams can include additional field: lineLength
var C = Kekule.CoordUtils;
var coord2D = {'x': 0, 'y': 0};
var coord3D = {'x': 0, 'y': 0, 'z': 0};
var delta = {'x': refLength * (initialParams.lineLength || 1)};
//var controllerDelta = {'x': 0, 'y': delta.x / 2};
var node1 = new Kekule.Glyph.PathGlyphNode(null, null, coord2D, coord3D); // starting node
var node2 = new Kekule.Glyph.PathGlyphNode(null, null, C.add(coord2D, delta), C.add(coord3D, delta)); // ending node
this.appendNode(node1);
this.appendNode(node2);
//var node3 = new Kekule.Glyph.PathGlyphNode(null, Kekule.Glyph.NodeType.CONTROLLER, C.add(coord2D, controllerDelta), C.add(coord3D, controllerDelta)); // control node
var connector = new Kekule.Glyph.PathGlyphArcConnector(null, [node1, node2]);
this._applyParamsToConnector(connector, initialParams);
/*
var controlPoint = connector.getControlPoint();
//controlPoint.setDistanceToChord(delta.x)
controlPoint.setCoord2D(controllerDelta)
.setCoord3D(controllerDelta);
*/
this.appendConnector(connector);
connector.setInteractMode(Kekule.ChemObjInteractMode.HIDDEN);
//node1.setInteractMode(Kekule.ChemObjInteractMode.HIDDEN);
//node2.setInteractMode(Kekule.ChemObjInteractMode.HIDDEN);
},
/** @ignore */
getDirectManipulationTarget: function()
{
return this.getNodeAt(this.getNodeCount() - 1);
},
/** @private */
_isValidChemNodeOrConnectorStickTarget: function(targetObj)
{
/*
var result = (targetObj instanceof Kekule.ChemStructureNode) || (targetObj instanceof Kekule.ChemStructureConnector);
if (!result && (targetObj instanceof Kekule.ChemMarker.BaseMarker))
{
var parent = targetObj.getParent && targetObj.getParent();
if (parent) // the marker of node/connector (e.g., electron pair) can also be a valid target
result = (parent instanceof Kekule.ChemStructureNode) || (parent instanceof Kekule.ChemStructureConnector);
}
return result;
*/
return Kekule.Glyph.ElectronArrowGlyphUtils.isValidChemNodeOrConnectorStickTarget(targetObj);
},
/** @private */
_applyParamsToConnector: function(connector, initialParams)
{
connector.setPathParams(initialParams);
},
/** @ignore */
getAllowChildCoordStickTo: function(child, dest)
{
var result = !dest // dest not set, a general test, just returns true
|| (this._isValidChemNodeOrConnectorStickTarget(dest, child) && !this._isChildrenStickingTo(dest, [child]));
/*
|| ((dest instanceof Kekule.ChemStructureNode) || (dest instanceof Kekule.ChemStructureConnector)) && (!this._isChildrenStickingTo(dest, [child]))
|| (dest instanceof Kekule.ChemMarker.BaseMarker);
*/
//console.log('allow stick to', dest && dest.getClassName(), result);
return result;
},
/** @ignore */
getChildUseCoordStickOffset: function(/*$super, */child, stickDest)
{
if (stickDest instanceof Kekule.ChemStructureNode || stickDest instanceof Kekule.ChemStructureConnector)
{
return true;
}
else
{
return false;
//return $super(child, stickDest);
}
},
/** @private */
_isChildrenStickingTo: function(dest, excludeChildren)
{
var nodes = this.getNodes();
nodes = Kekule.ArrayUtils.exclude(nodes, excludeChildren || []);
for (var i = 0, l = nodes.length; i < l; ++i)
{
var n = nodes[i];
if (n.getCoordStickTarget() === dest)
return true;
}
return false;
}
});
/**
* A base glyph of double arc glyph (for bond forming electron pushing arrow).
* @class
* @augments Kekule.Glyph.PathGlyph
*/
Kekule.Glyph.BaseTwinArc = Class.create(Kekule.Glyph.PathGlyph,
/** @lends Kekule.Glyph.BaseTwinArc# */
{
/** @private */
CLASS_NAME: 'Kekule.Glyph.BaseTwinArc',
/** @private */
DEF_MIN_PATH_END_DISTANCE_RATIO: 0.05,
/** @private */
DEF_INIT_PATH_END_GAP_RATIO: 0.2,
/** @private */
FIELD_ARC_END_NODE_FLAG: '__$arcEndNode$__',
/**
* @constructs
*/
initialize: function(/*$super, */id, refLength, initialParams, coord2D, coord3D)
{
/*
this._insideNodeGetIndirectCoordRefLengthsBind = this._insideNodeGetIndirectCoordRefLengths.bind(this);
this._insideNodeGetIndirectCoordRefCoordsBind = this._insideNodeGetIndirectCoordRefCoords.bind(this);
this._insideNodeCalcIndirectCoordStorageBind = this._insideNodeCalcIndirectCoordStorage.bind(this);
this._insideNodeCalcIndirectCoordValueBind = this._insideNodeCalcIndirectCoordValue.bind(this);
*/
this.setPropStoreFieldValue('minPathEndDistanceRatio', this.DEF_MIN_PATH_END_DISTANCE_RATIO);
this.tryApplySuper('initialize', [id, refLength, initialParams, coord2D, coord3D]) /* $super(id, refLength, initialParams, coord2D, coord3D) */;
},
/** @private */
initProperties: function()
{
this.defineProp('minPathEndDistanceRatio', {'dataType': DataType.FLOAT});
this.defineProp('oppositePathEndArrowSides', {
'dataType': DataType.BOOL, 'serializable': false,
'getter': function()
{
return this._isPathArrowSideOpposite('end');
},
'setter': function(value)
{
this._setPathArrowSideOpposite('end', !!value);
}
});
this.defineProp('oppositePathStartArrowSides', {
'dataType': DataType.BOOL, 'serializable': false,
'getter': function()
{
return this._isPathArrowSideOpposite('start');
},
'setter': function(value)
{
this._setPathArrowSideOpposite('start', !!value);
}
});
},
/** @ignore */
loaded: function(rootObj)
{
var result = this.tryApplySuper('loaded', [rootObj]);
// when add new child object, and the two arcs are ready, handle the arc end nodes
if (this._isTwinArcSetup())
{
this._setupArcEndNode(this.getNodeAt(1));
this._setupArcEndNode(this.getNodeAt(2));
}
return result;
},
/** @private */
_isPathArrowSideOpposite: function(arrowPos)
{
// arrowPos is a string, either of 'start' or 'end'
var connCount = this.getConnectorCount();
if (connCount < 2)
return null; // undeterminated
else
{
var lastSide;
var result = null;
for (var i = 0; i < connCount; ++i)
{
var conn = this.getConnectorAt(i);
var pathParam = conn.getPathParams();
var arrowType = pathParam[arrowPos + 'ArrowType'];
if (arrowType === Kekule.Glyph.ArrowType.NONE) // no side
return null;
var arrowSide = pathParam[arrowPos + 'ArrowSide'];
if (arrowSide === Kekule.Glyph.ArrowSide.BOTH)
return null;
if (i === 0)
lastSide = arrowSide;
else
{
var currResult = (lastSide === arrowSide)? false: true;
if (OU.isUnset(result))
result = currResult;
else if (result !== currResult)
return null;
lastSide = arrowSide;
}
}
return result;
}
},
/** @private */
_setPathArrowSideOpposite: function(arrowPos, reversed)
{
// arrowPos is a string, either of 'start' or 'end'
var connCount = this.getConnectorCount();
if (connCount < 2)
return null; // undeterminated
else
{
var ASide = Kekule.Glyph.ArrowSide;
var lastSide;
var applicable = true;
for (var i = 0; i < connCount; ++i)
{
var conn = this.getConnectorAt(i);
var pathParam = conn.getPathParams();
var arrowType = pathParam[arrowPos + 'ArrowType'];
if (arrowType === Kekule.Glyph.ArrowType.NONE) // no side
applicable = false;
var arrowSide = pathParam[arrowPos + 'ArrowSide'];
if (arrowSide === Kekule.Glyph.ArrowSide.BOTH)
applicable = false;
if (!applicable)
{
lastSide = null;
}
else
{
if (OU.isUnset(lastSide))
lastSide = arrowSide;
else
{
var currSide;
if (reversed)
currSide = (lastSide === ASide.SINGLE)? ASide.REVERSED: ASide.SINGLE;
else
currSide = lastSide;
pathParam[arrowPos + 'ArrowSide'] = currSide;
lastSide = currSide;
}
}
}
return null;
}
},
/** @private */
_isTwinArcSetup: function()
{
return (this.getConnectorCount() === 2) && (this.getNodeCount() === 4);
},
/** @ignore */
getDirectManipulationTarget: function()
{
return this.getNodeAt(this.getNodeCount() - 1);
},
/** @ignore */
doCreateDefaultStructure: function(refLength, initialParams)
{
// initialParams can include additional field: lineLength
var C = Kekule.CoordUtils;
var coord2D = {'x': 0, 'y': 0};
var coord3D = {'x': 0, 'y': 0, 'z': 0};
var lineLength = initialParams.lineLength || 1;
var minPathEndDistanceRatio = (initialParams.minPathEndDistanceRatio || this.getMinPathEndDistanceRatio() || this.DEF_MIN_PATH_END_DISTANCE_RATIO); // min distance bewteen arc ends
var minPathEndDistance = lineLength * minPathEndDistanceRatio;
this.setMinPathEndDistanceRatio(minPathEndDistanceRatio);
var pathEndGap = (initialParams.pathEndGap || lineLength * this.DEF_INIT_PATH_END_GAP_RATIO);
pathEndGap = Math.max(pathEndGap, minPathEndDistance);
var deltaLine = {'x': refLength * ((lineLength - pathEndGap) / 2)};
var deltaGap = {'x': refLength * pathEndGap};
var deltaTotal = {'x': refLength * lineLength};
var node1 = new Kekule.Glyph.PathGlyphNode(null, null, coord2D, coord3D); // starting node of first arc
var node2 = new Kekule.Glyph.PathGlyphNode(null, null); // ending node of first arc
this._setupArcEndNode(node2);
var node3 = new Kekule.Glyph.PathGlyphNode(null, null); // ending node of second arc
var node4 = new Kekule.Glyph.PathGlyphNode(null, null, C.add(coord2D, deltaTotal), C.add(coord3D, deltaTotal)); // starting node of second arc
this._setupArcEndNode(node3);
this.appendNode(node1);
this.appendNode(node2);
this.appendNode(node3);
this.appendNode(node4);
node2.setCoord2D(C.add(coord2D, deltaLine)).setCoord3D(C.add(coord3D, deltaLine));
node3.setCoord2D(C.add(coord2D, CU.add(deltaLine, deltaGap))).setCoord3D(C.add(coord3D, CU.add(deltaLine, deltaGap)));
var connector1 = new Kekule.Glyph.PathGlyphArcConnector(null, [node1, node2]);
var connector2 = new Kekule.Glyph.PathGlyphArcConnector(null, [node4, node3]);
this._applyParamsToConnector(connector1, initialParams);
this._applyParamsToConnector(connector2, initialParams);
connector2.getControlPointAt(0).setDistanceToChord(-connector2.getControlPointAt(0).getDistanceToChord()); // ensure the two arc arrow at same side
this.appendConnector(connector1);
this.appendConnector(connector2);
connector1.setInteractMode(Kekule.ChemObjInteractMode.HIDDEN);
connector2.setInteractMode(Kekule.ChemObjInteractMode.HIDDEN);
},
/** @private */
_applyParamsToConnector: function(connector, initialParams)
{
connector.setPathParams(initialParams);
},
/** @private */
_setupArcEndNode: function(node)
{
if (!node[this.FIELD_ARC_END_NODE_FLAG])
{
this._overwriteChildPathNodeMethods(node);
node.setEnableIndirectCoord(true);
node[this.FIELD_ARC_END_NODE_FLAG] = true;
}
},
/** @private */
_overwriteChildPathNodeMethods: function(node)
{
node.overwriteMethod('getIndirectCoordRefLengths', this._insideNodeGetIndirectCoordRefLengths)
.overwriteMethod('getIndirectCoordRefCoords', this._insideNodeGetIndirectCoordRefCoords)
.overwriteMethod('calcIndirectCoordStorage', this._insideNodeCalcIndirectCoordStorage)
.overwriteMethod('calcIndirectCoordValue', this._insideNodeCalcIndirectCoordValue)
.overwriteMethod('_childPathNodeGetParentGlyph', this._childPathNodeGetParentGlyph)
.overwriteMethod('_childPathNodeGetGlyphMinPathEndDistanceRatio', this._childPathNodeGetGlyphMinPathEndDistanceRatio);
},
/** @private */
_getArrowStartingNodes: function()
{
var result = [];
if (this._isTwinArcSetup())
{
for (var i = 0, l = this.getConnectorCount(); i < l; ++i)
{
var connector = this.getConnectorAt(i);
var node = connector.getConnectedObjAt(0);
if (node)
result.push(node);
}
}
return result;
},
// overwrite methods of two inside nodes of arcs, so this these methods, this var refers to the node but not the glyph
/** @private */
_childPathNodeGetParentGlyph: function($old) // return this parent glyph of path node
{
var p = this.getParent();
if (p instanceof Kekule.Glyph.BaseTwinArc)
return p;
else
return null;
},
/** @private */
_childPathNodeGetGlyphMinPathEndDistanceRatio: function($old)
{
var p = this._childPathNodeGetParentGlyph();
return p && p.getMinPathEndDistanceRatio();
},
/** @private */
_insideNodeGetIndirectCoordRefLengths: function($old, coordMode, allowCoordBorrow)
{
var glyph = this.getParent();
if (glyph && coordMode === Kekule.CoordMode.COORD2D)
{
var nodeStart = glyph.getNodeAt(0);
var nodeEnd = glyph.getNodeAt(glyph.getNodeCount() - 1);
if (nodeStart && nodeEnd)
{
var coord1 = nodeStart.getAbsCoordOfMode(coordMode);
var coord2 = nodeEnd.getAbsCoordOfMode(coordMode);
var d = Kekule.CoordUtils.getDistance(coord2, coord1);
var result = {'x': d, 'y': d, 'length': d};
//console.log('_insideNodeGetIndirectCoordRefLengths', result);
return result;
}
}
else
return $old(coordMode, allowCoordBorrow);
},
/** @private */
_insideNodeGetIndirectCoordRefCoords: function($old, coordMode, allowCoordBorrow)
{
var glyph = this.getParent();
if (glyph && coordMode === CM.COORD2D)
{
var nodeStart = glyph.getNodeAt(0);
var nodeEnd = glyph.getNodeAt(glyph.getNodeCount() - 1);
if (nodeStart && nodeEnd)
{
/*
var coord1 = nodeStart.getAbsCoordOfMode(coordMode);
var coord2 = nodeEnd.getAbsCoordOfMode(coordMode);
*/
var coord1 = nodeStart.getCoordOfMode(coordMode);
var coord2 = nodeEnd.getCoordOfMode(coordMode);
//console.log('_insideNodeGetIndirectCoordRefCoords', coord);
return [coord1, coord2];
}
}
else
return $old(coordMode, allowCoordBorrow);
},
/** @private */
_insideNodeCalcIndirectCoordStorage: function($old, coordMode, coordValue, oldCoordValue, allowCoordBorrow)
{
var glyph = this.getParent();
if (glyph && coordMode === CM.COORD2D)
{
//var refLength = this._insideNodeGetIndirectCoordRefLengths(null, coordMode, allowCoordBorrow).length;
var refCoords = this.getIndirectCoordRefCoords(coordMode, allowCoordBorrow);
//var refLength = CU.getDistance(refCoords[1], refCoords[0]);
if (refCoords)
{
var nodeStart = glyph.getNodeAt(0);
var baseCoord = nodeStart.getCoordOfMode(coordMode);
var crossPoint = Kekule.GeometryUtils.getPerpendicularCrossPointFromCoordToLine(coordValue, refCoords[0], refCoords[1], false);
if (!crossPoint) // outside ref line
{
var d0 =CU.getDistance(coordValue, refCoords[0]);
var d1 =CU.getDistance(coordValue, refCoords[1]);
if (d0 < d1)
crossPoint = refCoords[0];
else
crossPoint = refCoords[1];
}
var crossPointDistance = CU.getDistance(baseCoord, crossPoint);
var refDistance = CU.getDistance(refCoords[1], refCoords[0]);
var ratio = refDistance? crossPointDistance / refDistance: 0;
var minDistanceRatio = this._childPathNodeGetGlyphMinPathEndDistanceRatio() || 0;
if (ratio < minDistanceRatio)
{
ratio = minDistanceRatio;
}
else if (ratio > 1 - minDistanceRatio)
{
ratio = 1 - minDistanceRatio;
}
return {'x': ratio, 'y': ratio, 'ratio': ratio};
}
}
return $old(coordMode, coordValue, oldCoordValue, allowCoordBorrow);
},
/** @private */
_insideNodeCalcIndirectCoordValue: function($old, coordMode, allowCoordBorrow)
{
var glyph = this.getParent();
if (glyph && coordMode === CM.COORD2D)
{
var refCoords = this.getIndirectCoordRefCoords(coordMode, allowCoordBorrow);
if (refCoords)
{
var refDelta = CU.substract(refCoords[1], refCoords[0]);
var nodeStart = glyph.getNodeAt(0);
var baseCoord = nodeStart.getCoordOfMode(coordMode);
var ratio = this.getIndirectCoordStorageOfMode(coordMode)['ratio'];
if (Kekule.ObjUtils.notUnset(ratio))
{
var delta = CU.multiply(refDelta, ratio);
var result = CU.add(baseCoord, delta);
//console.log('calc', this.getIndirectCoordStorageOfMode(coordMode), ratio, delta, result);
return result;
}
}
}
return $old(coordMode, allowCoordBorrow);
},
/** @private */
_isValidChemNodeOrConnectorStickTarget: function(targetObj)
{
var result = (targetObj instanceof Kekule.ChemStructureNode) || (targetObj instanceof Kekule.ChemStructureConnector);
if (!result && (targetObj instanceof Kekule.ChemMarker.BaseMarker))
{
var parent = targetObj.getParent && targetObj.getParent();
if (parent) // the marker of node/connector (e.g., electron pair) can also be a valid target
result = (parent instanceof Kekule.ChemStructureNode) || (parent instanceof Kekule.ChemStructureConnector);
}
return result;
},
/** @ignore */
getAllowChildCoordStickTo: function(child, dest)
{
var index = this.indexOfNode(child);
if (index === 0 || index === this.getNodeCount() - 1) // only the leading and tailing node can be sticked
{
var result = !dest // dest not set, a general test, just returns true
|| (this._isValidChemNodeOrConnectorStickTarget(dest, child) && !this._isChildrenStickingTo(dest, [child]));
return result;
}
else
return false;
},
/** @ignore */
getChildUseCoordStickOffset: function(/*$super, */child, stickDest)
{
if (stickDest instanceof Kekule.ChemStructureNode || stickDest instanceof Kekule.ChemStructureConnector)
{
return true;
}
else
{
return false;
}
},
/** @private */
_isChildrenStickingTo: function(dest, excludeChildren)
{
var nodes = this._getArrowStartingNodes();
nodes = Kekule.ArrayUtils.exclude(nodes, excludeChildren || []);
for (var i = 0, l = nodes.length; i < l; ++i)
{
var n = nodes[i];
if (n.getCoordStickTarget() === dest)
return true;
}
return false;
}
});
/**
* A general arc glyph.
* @class
* @augments Kekule.Glyph.BaseArc
*/
Kekule.Glyph.Arc = Class.create(Kekule.Glyph.BaseArc,
/** @lends Kekule.Glyph.Arc# */
{
/** @private */
CLASS_NAME: 'Kekule.Glyph.Arc'
});
/**
* A general twin arc glyph.
* @class
* @augments Kekule.Glyph.BaseTwinArc
*/
Kekule.Glyph.TwinArc = Class.create(Kekule.Glyph.BaseTwinArc,
/** @lends Kekule.Glyph.TwinArc# */
{
/** @private */
CLASS_NAME: 'Kekule.Glyph.TwinArc'
});
})();