123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674 |
- /**
- * Copyright (c) 2006-2015, JGraph Ltd
- * Copyright (c) 2006-2015, Gaudenz Alder
- */
- /**
- * Class: mxShape
- *
- * Base class for all shapes. A shape in mxGraph is a
- * separate implementation for SVG, VML and HTML. Which
- * implementation to use is controlled by the <dialect>
- * property which is assigned from within the <mxCellRenderer>
- * when the shape is created. The dialect must be assigned
- * for a shape, and it does normally depend on the browser and
- * the confiuration of the graph (see <mxGraph> rendering hint).
- *
- * For each supported shape in SVG and VML, a corresponding
- * shape exists in mxGraph, namely for text, image, rectangle,
- * rhombus, ellipse and polyline. The other shapes are a
- * combination of these shapes (eg. label and swimlane)
- * or they consist of one or more (filled) path objects
- * (eg. actor and cylinder). The HTML implementation is
- * optional but may be required for a HTML-only view of
- * the graph.
- *
- * Custom Shapes:
- *
- * To extend from this class, the basic code looks as follows.
- * In the special case where the custom shape consists only of
- * one filled region or one filled region and an additional stroke
- * the <mxActor> and <mxCylinder> should be subclassed,
- * respectively.
- *
- * (code)
- * function CustomShape() { }
- *
- * CustomShape.prototype = new mxShape();
- * CustomShape.prototype.constructor = CustomShape;
- * (end)
- *
- * To register a custom shape in an existing graph instance,
- * one must register the shape under a new name in the graph's
- * cell renderer as follows:
- *
- * (code)
- * mxCellRenderer.registerShape('customShape', CustomShape);
- * (end)
- *
- * The second argument is the name of the constructor.
- *
- * In order to use the shape you can refer to the given name above
- * in a stylesheet. For example, to change the shape for the default
- * vertex style, the following code is used:
- *
- * (code)
- * var style = graph.getStylesheet().getDefaultVertexStyle();
- * style[mxConstants.STYLE_SHAPE] = 'customShape';
- * (end)
- *
- * Constructor: mxShape
- *
- * Constructs a new shape.
- */
- function mxShape(stencil)
- {
- this.stencil = stencil;
- this.initStyles();
- };
- /**
- * Variable: dialect
- *
- * Holds the dialect in which the shape is to be painted.
- * This can be one of the DIALECT constants in <mxConstants>.
- */
- mxShape.prototype.dialect = null;
- /**
- * Variable: scale
- *
- * Holds the scale in which the shape is being painted.
- */
- mxShape.prototype.scale = 1;
- /**
- * Variable: antiAlias
- *
- * Rendering hint for configuring the canvas.
- */
- mxShape.prototype.antiAlias = true;
- /**
- * Variable: minSvgStrokeWidth
- *
- * Minimum stroke width for SVG output.
- */
- mxShape.prototype.minSvgStrokeWidth = 1;
- /**
- * Variable: bounds
- *
- * Holds the <mxRectangle> that specifies the bounds of this shape.
- */
- mxShape.prototype.bounds = null;
- /**
- * Variable: points
- *
- * Holds the array of <mxPoints> that specify the points of this shape.
- */
- mxShape.prototype.points = null;
- /**
- * Variable: node
- *
- * Holds the outermost DOM node that represents this shape.
- */
- mxShape.prototype.node = null;
-
- /**
- * Variable: state
- *
- * Optional reference to the corresponding <mxCellState>.
- */
- mxShape.prototype.state = null;
- /**
- * Variable: style
- *
- * Optional reference to the style of the corresponding <mxCellState>.
- */
- mxShape.prototype.style = null;
- /**
- * Variable: boundingBox
- *
- * Contains the bounding box of the shape, that is, the smallest rectangle
- * that includes all pixels of the shape.
- */
- mxShape.prototype.boundingBox = null;
- /**
- * Variable: stencil
- *
- * Holds the <mxStencil> that defines the shape.
- */
- mxShape.prototype.stencil = null;
- /**
- * Variable: svgStrokeTolerance
- *
- * Event-tolerance for SVG strokes (in px). Default is 8. This is only passed
- * to the canvas in <createSvgCanvas> if <pointerEvents> is true.
- */
- mxShape.prototype.svgStrokeTolerance = 8;
- /**
- * Variable: pointerEvents
- *
- * Specifies if pointer events should be handled. Default is true.
- */
- mxShape.prototype.pointerEvents = true;
- /**
- * Variable: svgPointerEvents
- *
- * Specifies if pointer events should be handled. Default is true.
- */
- mxShape.prototype.svgPointerEvents = 'all';
- /**
- * Variable: shapePointerEvents
- *
- * Specifies if pointer events outside of shape should be handled. Default
- * is false.
- */
- mxShape.prototype.shapePointerEvents = false;
- /**
- * Variable: stencilPointerEvents
- *
- * Specifies if pointer events outside of stencils should be handled. Default
- * is false. Set this to true for backwards compatibility with the 1.x branch.
- */
- mxShape.prototype.stencilPointerEvents = false;
- /**
- * Variable: vmlScale
- *
- * Scale for improving the precision of VML rendering. Default is 1.
- */
- mxShape.prototype.vmlScale = 1;
- /**
- * Variable: outline
- *
- * Specifies if the shape should be drawn as an outline. This disables all
- * fill colors and can be used to disable other drawing states that should
- * not be painted for outlines. Default is false. This should be set before
- * calling <apply>.
- */
- mxShape.prototype.outline = false;
- /**
- * Variable: visible
- *
- * Specifies if the shape is visible. Default is true.
- */
- mxShape.prototype.visible = true;
- /**
- * Variable: useSvgBoundingBox
- *
- * Allows to use the SVG bounding box in SVG. Default is false for performance
- * reasons.
- */
- mxShape.prototype.useSvgBoundingBox = false;
- /**
- * Function: init
- *
- * Initializes the shape by creaing the DOM node using <create>
- * and adding it into the given container.
- *
- * Parameters:
- *
- * container - DOM node that will contain the shape.
- */
- mxShape.prototype.init = function(container)
- {
- if (this.node == null)
- {
- this.node = this.create(container);
-
- if (container != null)
- {
- container.appendChild(this.node);
- }
- }
- };
- /**
- * Function: initStyles
- *
- * Sets the styles to their default values.
- */
- mxShape.prototype.initStyles = function(container)
- {
- this.strokewidth = 1;
- this.rotation = 0;
- this.opacity = 100;
- this.fillOpacity = 100;
- this.strokeOpacity = 100;
- this.flipH = false;
- this.flipV = false;
- };
- /**
- * Function: isParseVml
- *
- * Specifies if any VML should be added via insertAdjacentHtml to the DOM. This
- * is only needed in IE8 and only if the shape contains VML markup. This method
- * returns true.
- */
- mxShape.prototype.isParseVml = function()
- {
- return true;
- };
- /**
- * Function: isHtmlAllowed
- *
- * Returns true if HTML is allowed for this shape. This implementation always
- * returns false.
- */
- mxShape.prototype.isHtmlAllowed = function()
- {
- return false;
- };
- /**
- * Function: getSvgScreenOffset
- *
- * Returns 0, or 0.5 if <strokewidth> % 2 == 1.
- */
- mxShape.prototype.getSvgScreenOffset = function()
- {
- var sw = this.stencil && this.stencil.strokewidth != 'inherit' ? Number(this.stencil.strokewidth) : this.strokewidth;
-
- return (mxUtils.mod(Math.max(1, Math.round(sw * this.scale)), 2) == 1) ? 0.5 : 0;
- };
- /**
- * Function: create
- *
- * Creates and returns the DOM node(s) for the shape in
- * the given container. This implementation invokes
- * <createSvg>, <createHtml> or <createVml> depending
- * on the <dialect> and style settings.
- *
- * Parameters:
- *
- * container - DOM node that will contain the shape.
- */
- mxShape.prototype.create = function(container)
- {
- var node = null;
-
- if (container != null && container.ownerSVGElement != null)
- {
- node = this.createSvg(container);
- }
- else if (document.documentMode == 8 || !mxClient.IS_VML ||
- (this.dialect != mxConstants.DIALECT_VML && this.isHtmlAllowed()))
- {
- node = this.createHtml(container);
- }
- else
- {
- node = this.createVml(container);
- }
-
- return node;
- };
- /**
- * Function: createSvg
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
- mxShape.prototype.createSvg = function()
- {
- return document.createElementNS(mxConstants.NS_SVG, 'g');
- };
- /**
- * Function: createVml
- *
- * Creates and returns the VML node to represent this shape.
- */
- mxShape.prototype.createVml = function()
- {
- var node = document.createElement(mxClient.VML_PREFIX + ':group');
- node.style.position = 'absolute';
-
- return node;
- };
- /**
- * Function: createHtml
- *
- * Creates and returns the HTML DOM node(s) to represent
- * this shape. This implementation falls back to <createVml>
- * so that the HTML creation is optional.
- */
- mxShape.prototype.createHtml = function()
- {
- var node = document.createElement('div');
- node.style.position = 'absolute';
-
- return node;
- };
- /**
- * Function: reconfigure
- *
- * Reconfigures this shape. This will update the colors etc in
- * addition to the bounds or points.
- */
- mxShape.prototype.reconfigure = function()
- {
- this.redraw();
- };
- /**
- * Function: redraw
- *
- * Creates and returns the SVG node(s) to represent this shape.
- */
- mxShape.prototype.redraw = function()
- {
- this.updateBoundsFromPoints();
-
- if (this.visible && this.checkBounds())
- {
- this.node.style.visibility = 'visible';
- this.clear();
-
- if (this.node.nodeName == 'DIV' && (this.isHtmlAllowed() || !mxClient.IS_VML))
- {
- this.redrawHtmlShape();
- }
- else
- {
- this.redrawShape();
- }
- this.updateBoundingBox();
- }
- else
- {
- this.node.style.visibility = 'hidden';
- this.boundingBox = null;
- }
- };
- /**
- * Function: clear
- *
- * Removes all child nodes and resets all CSS.
- */
- mxShape.prototype.clear = function()
- {
- if (this.node.ownerSVGElement != null)
- {
- while (this.node.lastChild != null)
- {
- this.node.removeChild(this.node.lastChild);
- }
- }
- else
- {
- this.node.style.cssText = 'position:absolute;' + ((this.cursor != null) ?
- ('cursor:' + this.cursor + ';') : '');
- this.node.innerHTML = '';
- }
- };
- /**
- * Function: updateBoundsFromPoints
- *
- * Updates the bounds based on the points.
- */
- mxShape.prototype.updateBoundsFromPoints = function()
- {
- var pts = this.points;
-
- if (pts != null && pts.length > 0 && pts[0] != null)
- {
- this.bounds = new mxRectangle(Number(pts[0].x), Number(pts[0].y), 1, 1);
-
- for (var i = 1; i < this.points.length; i++)
- {
- if (pts[i] != null)
- {
- this.bounds.add(new mxRectangle(Number(pts[i].x), Number(pts[i].y), 1, 1));
- }
- }
- }
- };
- /**
- * Function: getLabelBounds
- *
- * Returns the <mxRectangle> for the label bounds of this shape, based on the
- * given scaled and translated bounds of the shape. This method should not
- * change the rectangle in-place. This implementation returns the given rect.
- */
- mxShape.prototype.getLabelBounds = function(rect)
- {
- var d = mxUtils.getValue(this.style, mxConstants.STYLE_DIRECTION, mxConstants.DIRECTION_EAST);
- var bounds = rect;
-
- // Normalizes argument for getLabelMargins hook
- if (d != mxConstants.DIRECTION_SOUTH && d != mxConstants.DIRECTION_NORTH &&
- this.state != null && this.state.text != null &&
- this.state.text.isPaintBoundsInverted())
- {
- bounds = bounds.clone();
- var tmp = bounds.width;
- bounds.width = bounds.height;
- bounds.height = tmp;
- }
-
- var m = this.getLabelMargins(bounds);
-
- if (m != null)
- {
- var flipH = mxUtils.getValue(this.style, mxConstants.STYLE_FLIPH, false) == '1';
- var flipV = mxUtils.getValue(this.style, mxConstants.STYLE_FLIPV, false) == '1';
-
- // Handles special case for vertical labels
- if (this.state != null && this.state.text != null &&
- this.state.text.isPaintBoundsInverted())
- {
- var tmp = m.x;
- m.x = m.height;
- m.height = m.width;
- m.width = m.y;
- m.y = tmp;
- tmp = flipH;
- flipH = flipV;
- flipV = tmp;
- }
-
- return mxUtils.getDirectedBounds(rect, m, this.style, flipH, flipV);
- }
-
- return rect;
- };
- /**
- * Function: getLabelMargins
- *
- * Returns the scaled top, left, bottom and right margin to be used for
- * computing the label bounds as an <mxRectangle>, where the bottom and right
- * margin are defined in the width and height of the rectangle, respectively.
- */
- mxShape.prototype.getLabelMargins= function(rect)
- {
- return null;
- };
- /**
- * Function: checkBounds
- *
- * Returns true if the bounds are not null and all of its variables are numeric.
- */
- mxShape.prototype.checkBounds = function()
- {
- return (!isNaN(this.scale) && isFinite(this.scale) && this.scale > 0 &&
- this.bounds != null && !isNaN(this.bounds.x) && !isNaN(this.bounds.y) &&
- !isNaN(this.bounds.width) && !isNaN(this.bounds.height) &&
- this.bounds.width > 0 && this.bounds.height > 0);
- };
- /**
- * Function: createVmlGroup
- *
- * Returns the temporary element used for rendering in IE8 standards mode.
- */
- mxShape.prototype.createVmlGroup = function()
- {
- var node = document.createElement(mxClient.VML_PREFIX + ':group');
- node.style.position = 'absolute';
- node.style.width = this.node.style.width;
- node.style.height = this.node.style.height;
-
- return node;
- };
- /**
- * Function: redrawShape
- *
- * Updates the SVG or VML shape.
- */
- mxShape.prototype.redrawShape = function()
- {
- var canvas = this.createCanvas();
-
- if (canvas != null)
- {
- // Specifies if events should be handled
- canvas.pointerEvents = this.pointerEvents;
-
- this.beforePaint(canvas);
- this.paint(canvas);
- this.afterPaint(canvas);
-
- if (this.node != canvas.root)
- {
- // Forces parsing in IE8 standards mode - slow! avoid
- this.node.insertAdjacentHTML('beforeend', canvas.root.outerHTML);
- }
-
- if (this.node.nodeName == 'DIV' && document.documentMode == 8)
- {
- // Makes DIV transparent to events for IE8 in IE8 standards
- // mode (Note: Does not work for IE9 in IE8 standards mode
- // and not for IE11 in enterprise mode)
- this.node.style.filter = '';
-
- // Adds event transparency in IE8 standards
- mxUtils.addTransparentBackgroundFilter(this.node);
- }
-
- this.destroyCanvas(canvas);
- }
- };
- /**
- * Function: createCanvas
- *
- * Creates a new canvas for drawing this shape. May return null.
- */
- mxShape.prototype.createCanvas = function()
- {
- var canvas = null;
-
- // LATER: Check if reusing existing DOM nodes improves performance
- if (this.node.ownerSVGElement != null)
- {
- canvas = this.createSvgCanvas();
- }
- else if (mxClient.IS_VML)
- {
- this.updateVmlContainer();
- canvas = this.createVmlCanvas();
- }
-
- if (canvas != null && this.outline)
- {
- canvas.setStrokeWidth(this.strokewidth);
- canvas.setStrokeColor(this.stroke);
-
- if (this.isDashed != null)
- {
- canvas.setDashed(this.isDashed);
- }
-
- canvas.setStrokeWidth = function() {};
- canvas.setStrokeColor = function() {};
- canvas.setFillColor = function() {};
- canvas.setGradient = function() {};
- canvas.setDashed = function() {};
- canvas.text = function() {};
- }
- return canvas;
- };
- /**
- * Function: createSvgCanvas
- *
- * Creates and returns an <mxSvgCanvas2D> for rendering this shape.
- */
- mxShape.prototype.createSvgCanvas = function()
- {
- var canvas = new mxSvgCanvas2D(this.node, false);
- canvas.strokeTolerance = (this.pointerEvents) ? this.svgStrokeTolerance : 0;
- canvas.pointerEventsValue = this.svgPointerEvents;
- var off = this.getSvgScreenOffset();
- if (off != 0)
- {
- this.node.setAttribute('transform', 'translate(' + off + ',' + off + ')');
- }
- else
- {
- this.node.removeAttribute('transform');
- }
- canvas.minStrokeWidth = this.minSvgStrokeWidth;
-
- if (!this.antiAlias)
- {
- // Rounds all numbers in the SVG output to integers
- canvas.format = function(value)
- {
- return Math.round(parseFloat(value));
- };
- }
-
- return canvas;
- };
- /**
- * Function: createVmlCanvas
- *
- * Creates and returns an <mxVmlCanvas2D> for rendering this shape.
- */
- mxShape.prototype.createVmlCanvas = function()
- {
- // Workaround for VML rendering bug in IE8 standards mode
- var node = (document.documentMode == 8 && this.isParseVml()) ? this.createVmlGroup() : this.node;
- var canvas = new mxVmlCanvas2D(node, false);
-
- if (node.tagUrn != '')
- {
- var w = Math.max(1, Math.round(this.bounds.width));
- var h = Math.max(1, Math.round(this.bounds.height));
- node.coordsize = (w * this.vmlScale) + ',' + (h * this.vmlScale);
- canvas.scale(this.vmlScale);
- canvas.vmlScale = this.vmlScale;
- }
- // Painting relative to top, left shape corner
- var s = this.scale;
- canvas.translate(-Math.round(this.bounds.x / s), -Math.round(this.bounds.y / s));
-
- return canvas;
- };
- /**
- * Function: updateVmlContainer
- *
- * Updates the bounds of the VML container.
- */
- mxShape.prototype.updateVmlContainer = function()
- {
- this.node.style.left = Math.round(this.bounds.x) + 'px';
- this.node.style.top = Math.round(this.bounds.y) + 'px';
- var w = Math.max(1, Math.round(this.bounds.width));
- var h = Math.max(1, Math.round(this.bounds.height));
- this.node.style.width = w + 'px';
- this.node.style.height = h + 'px';
- this.node.style.overflow = 'visible';
- };
- /**
- * Function: redrawHtml
- *
- * Allow optimization by replacing VML with HTML.
- */
- mxShape.prototype.redrawHtmlShape = function()
- {
- // LATER: Refactor methods
- this.updateHtmlBounds(this.node);
- this.updateHtmlFilters(this.node);
- this.updateHtmlColors(this.node);
- };
- /**
- * Function: updateHtmlFilters
- *
- * Allow optimization by replacing VML with HTML.
- */
- mxShape.prototype.updateHtmlFilters = function(node)
- {
- var f = '';
-
- if (this.opacity < 100)
- {
- f += 'alpha(opacity=' + (this.opacity) + ')';
- }
-
- if (this.isShadow)
- {
- // FIXME: Cannot implement shadow transparency with filter
- f += 'progid:DXImageTransform.Microsoft.dropShadow (' +
- 'OffX=\'' + Math.round(mxConstants.SHADOW_OFFSET_X * this.scale) + '\', ' +
- 'OffY=\'' + Math.round(mxConstants.SHADOW_OFFSET_Y * this.scale) + '\', ' +
- 'Color=\'' + mxConstants.VML_SHADOWCOLOR + '\')';
- }
-
- if (this.fill != null && this.fill != mxConstants.NONE && this.gradient && this.gradient != mxConstants.NONE)
- {
- var start = this.fill;
- var end = this.gradient;
- var type = '0';
-
- var lookup = {east:0,south:1,west:2,north:3};
- var dir = (this.direction != null) ? lookup[this.direction] : 0;
-
- if (this.gradientDirection != null)
- {
- dir = mxUtils.mod(dir + lookup[this.gradientDirection] - 1, 4);
- }
- if (dir == 1)
- {
- type = '1';
- var tmp = start;
- start = end;
- end = tmp;
- }
- else if (dir == 2)
- {
- var tmp = start;
- start = end;
- end = tmp;
- }
- else if (dir == 3)
- {
- type = '1';
- }
-
- f += 'progid:DXImageTransform.Microsoft.gradient(' +
- 'startColorStr=\'' + start + '\', endColorStr=\'' + end +
- '\', gradientType=\'' + type + '\')';
- }
- node.style.filter = f;
- };
- /**
- * Function: updateHtmlColors
- *
- * Allow optimization by replacing VML with HTML.
- */
- mxShape.prototype.updateHtmlColors = function(node)
- {
- var color = this.stroke;
-
- if (color != null && color != mxConstants.NONE)
- {
- node.style.borderColor = color;
- if (this.isDashed)
- {
- node.style.borderStyle = 'dashed';
- }
- else if (this.strokewidth > 0)
- {
- node.style.borderStyle = 'solid';
- }
- node.style.borderWidth = Math.max(1, Math.ceil(this.strokewidth * this.scale)) + 'px';
- }
- else
- {
- node.style.borderWidth = '0px';
- }
- color = (this.outline) ? null : this.fill;
-
- if (color != null && color != mxConstants.NONE)
- {
- node.style.backgroundColor = color;
- node.style.backgroundImage = 'none';
- }
- else if (this.pointerEvents)
- {
- node.style.backgroundColor = 'transparent';
- }
- else if (document.documentMode == 8)
- {
- mxUtils.addTransparentBackgroundFilter(node);
- }
- else
- {
- this.setTransparentBackgroundImage(node);
- }
- };
- /**
- * Function: updateHtmlBounds
- *
- * Allow optimization by replacing VML with HTML.
- */
- mxShape.prototype.updateHtmlBounds = function(node)
- {
- var sw = (document.documentMode >= 9) ? 0 : Math.ceil(this.strokewidth * this.scale);
- node.style.borderWidth = Math.max(1, sw) + 'px';
- node.style.overflow = 'hidden';
-
- node.style.left = Math.round(this.bounds.x - sw / 2) + 'px';
- node.style.top = Math.round(this.bounds.y - sw / 2) + 'px';
- if (document.compatMode == 'CSS1Compat')
- {
- sw = -sw;
- }
-
- node.style.width = Math.round(Math.max(0, this.bounds.width + sw)) + 'px';
- node.style.height = Math.round(Math.max(0, this.bounds.height + sw)) + 'px';
- };
- /**
- * Function: destroyCanvas
- *
- * Destroys the given canvas which was used for drawing. This implementation
- * increments the reference counts on all shared gradients used in the canvas.
- */
- mxShape.prototype.destroyCanvas = function(canvas)
- {
- // Manages reference counts
- if (canvas instanceof mxSvgCanvas2D)
- {
- // Increments ref counts
- for (var key in canvas.gradients)
- {
- var gradient = canvas.gradients[key];
-
- if (gradient != null)
- {
- gradient.mxRefCount = (gradient.mxRefCount || 0) + 1;
- }
- }
-
- this.releaseSvgGradients(this.oldGradients);
- this.oldGradients = canvas.gradients;
- }
- };
- /**
- * Function: beforePaint
- *
- * Invoked before paint is called.
- */
- mxShape.prototype.beforePaint = function(c) { }
- /**
- * Function: afterPaint
- *
- * Invokes after paint was called.
- */
- mxShape.prototype.afterPaint = function(c) { }
- /**
- * Function: paint
- *
- * Generic rendering code.
- */
- mxShape.prototype.paint = function(c)
- {
- var strokeDrawn = false;
-
- if (c != null && this.outline)
- {
- var stroke = c.stroke;
-
- c.stroke = function()
- {
- strokeDrawn = true;
- stroke.apply(this, arguments);
- };
- var fillAndStroke = c.fillAndStroke;
-
- c.fillAndStroke = function()
- {
- strokeDrawn = true;
- fillAndStroke.apply(this, arguments);
- };
- }
- // Scale is passed-through to canvas
- var s = this.scale;
- var x = this.bounds.x / s;
- var y = this.bounds.y / s;
- var w = this.bounds.width / s;
- var h = this.bounds.height / s;
- if (this.isPaintBoundsInverted())
- {
- var t = (w - h) / 2;
- x += t;
- y -= t;
- var tmp = w;
- w = h;
- h = tmp;
- }
-
- this.updateTransform(c, x, y, w, h);
- this.configureCanvas(c, x, y, w, h);
- // Adds background rectangle to capture events
- var bg = null;
-
- if ((this.stencil == null && this.points == null && this.shapePointerEvents) ||
- (this.stencil != null && this.stencilPointerEvents))
- {
- var bb = this.createBoundingBox();
-
- if (this.dialect == mxConstants.DIALECT_SVG)
- {
- bg = this.createTransparentSvgRectangle(bb.x, bb.y, bb.width, bb.height);
- this.node.appendChild(bg);
- }
- else
- {
- var rect = c.createRect('rect', bb.x / s, bb.y / s, bb.width / s, bb.height / s);
- rect.appendChild(c.createTransparentFill());
- rect.stroked = 'false';
- c.root.appendChild(rect);
- }
- }
- if (this.stencil != null)
- {
- this.stencil.drawShape(c, this, x, y, w, h);
- }
- else
- {
- // Stencils have separate strokewidth
- c.setStrokeWidth(this.strokewidth);
-
- if (this.points != null)
- {
- // Paints edge shape
- var pts = [];
-
- for (var i = 0; i < this.points.length; i++)
- {
- if (this.points[i] != null)
- {
- pts.push(new mxPoint(this.points[i].x / s, this.points[i].y / s));
- }
- }
- this.paintEdgeShape(c, pts);
- }
- else
- {
- // Paints vertex shape
- this.paintVertexShape(c, x, y, w, h);
- }
- }
-
- if (bg != null && c.state != null && c.state.transform != null)
- {
- bg.setAttribute('transform', c.state.transform);
- }
-
- // Draws highlight rectangle if no stroke was used
- if (c != null && this.outline && !strokeDrawn)
- {
- c.rect(x, y, w, h);
- c.stroke();
- }
- };
- /**
- * Function: configureCanvas
- *
- * Sets the state of the canvas for drawing the shape.
- */
- mxShape.prototype.configureCanvas = function(c, x, y, w, h)
- {
- var dash = null;
-
- if (this.style != null)
- {
- dash = this.style['dashPattern'];
- }
- c.setAlpha(this.opacity / 100);
- c.setFillAlpha(this.fillOpacity / 100);
- c.setStrokeAlpha(this.strokeOpacity / 100);
- // Sets alpha, colors and gradients
- if (this.isShadow != null)
- {
- c.setShadow(this.isShadow);
- }
-
- // Dash pattern
- if (this.isDashed != null)
- {
- c.setDashed(this.isDashed, (this.style != null) ?
- mxUtils.getValue(this.style, mxConstants.STYLE_FIX_DASH, false) == 1 : false);
- }
- if (dash != null)
- {
- c.setDashPattern(dash);
- }
- if (this.fill != null && this.fill != mxConstants.NONE && this.gradient && this.gradient != mxConstants.NONE)
- {
- var b = this.getGradientBounds(c, x, y, w, h);
- c.setGradient(this.fill, this.gradient, b.x, b.y, b.width, b.height, this.gradientDirection);
- }
- else
- {
- c.setFillColor(this.fill);
- }
- c.setStrokeColor(this.stroke);
- };
- /**
- * Function: getGradientBounds
- *
- * Returns the bounding box for the gradient box for this shape.
- */
- mxShape.prototype.getGradientBounds = function(c, x, y, w, h)
- {
- return new mxRectangle(x, y, w, h);
- };
- /**
- * Function: updateTransform
- *
- * Sets the scale and rotation on the given canvas.
- */
- mxShape.prototype.updateTransform = function(c, x, y, w, h)
- {
- // NOTE: Currently, scale is implemented in state and canvas. This will
- // move to canvas in a later version, so that the states are unscaled
- // and untranslated and do not need an update after zooming or panning.
- c.scale(this.scale);
- c.rotate(this.getShapeRotation(), this.flipH, this.flipV, x + w / 2, y + h / 2);
- };
- /**
- * Function: paintVertexShape
- *
- * Paints the vertex shape.
- */
- mxShape.prototype.paintVertexShape = function(c, x, y, w, h)
- {
- this.paintBackground(c, x, y, w, h);
-
- if (!this.outline || this.style == null || mxUtils.getValue(
- this.style, mxConstants.STYLE_BACKGROUND_OUTLINE, 0) == 0)
- {
- c.setShadow(false);
- this.paintForeground(c, x, y, w, h);
- }
- };
- /**
- * Function: paintBackground
- *
- * Hook for subclassers. This implementation is empty.
- */
- mxShape.prototype.paintBackground = function(c, x, y, w, h) { };
- /**
- * Function: paintForeground
- *
- * Hook for subclassers. This implementation is empty.
- */
- mxShape.prototype.paintForeground = function(c, x, y, w, h) { };
- /**
- * Function: paintEdgeShape
- *
- * Hook for subclassers. This implementation is empty.
- */
- mxShape.prototype.paintEdgeShape = function(c, pts) { };
- /**
- * Function: getArcSize
- *
- * Returns the arc size for the given dimension.
- */
- mxShape.prototype.getArcSize = function(w, h)
- {
- var r = 0;
-
- if (mxUtils.getValue(this.style, mxConstants.STYLE_ABSOLUTE_ARCSIZE, 0) == '1')
- {
- r = Math.min(w / 2, Math.min(h / 2, mxUtils.getValue(this.style,
- mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2));
- }
- else
- {
- var f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE,
- mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100;
- r = Math.min(w * f, h * f);
- }
-
- return r;
- };
- /**
- * Function: paintGlassEffect
- *
- * Paints the glass gradient effect.
- */
- mxShape.prototype.paintGlassEffect = function(c, x, y, w, h, arc)
- {
- var sw = Math.ceil(this.strokewidth / 2);
- var size = 0.4;
-
- c.setGradient('#ffffff', '#ffffff', x, y, w, h * 0.6, 'south', 0.9, 0.1);
- c.begin();
- arc += 2 * sw;
-
- if (this.isRounded)
- {
- c.moveTo(x - sw + arc, y - sw);
- c.quadTo(x - sw, y - sw, x - sw, y - sw + arc);
- c.lineTo(x - sw, y + h * size);
- c.quadTo(x + w * 0.5, y + h * 0.7, x + w + sw, y + h * size);
- c.lineTo(x + w + sw, y - sw + arc);
- c.quadTo(x + w + sw, y - sw, x + w + sw - arc, y - sw);
- }
- else
- {
- c.moveTo(x - sw, y - sw);
- c.lineTo(x - sw, y + h * size);
- c.quadTo(x + w * 0.5, y + h * 0.7, x + w + sw, y + h * size);
- c.lineTo(x + w + sw, y - sw);
- }
-
- c.close();
- c.fill();
- };
- /**
- * Function: addPoints
- *
- * Paints the given points with rounded corners.
- */
- mxShape.prototype.addPoints = function(c, pts, rounded, arcSize, close, exclude, initialMove)
- {
- if (pts != null && pts.length > 0)
- {
- initialMove = (initialMove != null) ? initialMove : true;
- var pe = pts[pts.length - 1];
-
- // Adds virtual waypoint in the center between start and end point
- if (close && rounded)
- {
- pts = pts.slice();
- var p0 = pts[0];
- var wp = new mxPoint(pe.x + (p0.x - pe.x) / 2, pe.y + (p0.y - pe.y) / 2);
- pts.splice(0, 0, wp);
- }
-
- var pt = pts[0];
- var i = 1;
-
- // Draws the line segments
- if (initialMove)
- {
- c.moveTo(pt.x, pt.y);
- }
- else
- {
- c.lineTo(pt.x, pt.y);
- }
-
- while (i < ((close) ? pts.length : pts.length - 1))
- {
- var tmp = pts[mxUtils.mod(i, pts.length)];
- var dx = pt.x - tmp.x;
- var dy = pt.y - tmp.y;
-
- if (rounded && (dx != 0 || dy != 0) && (exclude == null || mxUtils.indexOf(exclude, i - 1) < 0))
- {
- // Draws a line from the last point to the current
- // point with a spacing of size off the current point
- // into direction of the last point
- var dist = Math.sqrt(dx * dx + dy * dy);
- var nx1 = dx * Math.min(arcSize, dist / 2) / dist;
- var ny1 = dy * Math.min(arcSize, dist / 2) / dist;
-
- var x1 = tmp.x + nx1;
- var y1 = tmp.y + ny1;
- c.lineTo(x1, y1);
-
- // Draws a curve from the last point to the current
- // point with a spacing of size off the current point
- // into direction of the next point
- var next = pts[mxUtils.mod(i + 1, pts.length)];
-
- // Uses next non-overlapping point
- while (i < pts.length - 2 && Math.round(next.x - tmp.x) == 0 && Math.round(next.y - tmp.y) == 0)
- {
- next = pts[mxUtils.mod(i + 2, pts.length)];
- i++;
- }
-
- dx = next.x - tmp.x;
- dy = next.y - tmp.y;
-
- dist = Math.max(1, Math.sqrt(dx * dx + dy * dy));
- var nx2 = dx * Math.min(arcSize, dist / 2) / dist;
- var ny2 = dy * Math.min(arcSize, dist / 2) / dist;
-
- var x2 = tmp.x + nx2;
- var y2 = tmp.y + ny2;
-
- c.quadTo(tmp.x, tmp.y, x2, y2);
- tmp = new mxPoint(x2, y2);
- }
- else
- {
- c.lineTo(tmp.x, tmp.y);
- }
-
- pt = tmp;
- i++;
- }
-
- if (close)
- {
- c.close();
- }
- else
- {
- c.lineTo(pe.x, pe.y);
- }
- }
- };
- /**
- * Function: resetStyles
- *
- * Resets all styles.
- */
- mxShape.prototype.resetStyles = function()
- {
- this.initStyles();
- this.spacing = 0;
-
- delete this.fill;
- delete this.gradient;
- delete this.gradientDirection;
- delete this.stroke;
- delete this.startSize;
- delete this.endSize;
- delete this.startArrow;
- delete this.endArrow;
- delete this.direction;
- delete this.isShadow;
- delete this.isDashed;
- delete this.isRounded;
- delete this.glass;
- };
- /**
- * Function: apply
- *
- * Applies the style of the given <mxCellState> to the shape. This
- * implementation assigns the following styles to local fields:
- *
- * - <mxConstants.STYLE_FILLCOLOR> => fill
- * - <mxConstants.STYLE_GRADIENTCOLOR> => gradient
- * - <mxConstants.STYLE_GRADIENT_DIRECTION> => gradientDirection
- * - <mxConstants.STYLE_OPACITY> => opacity
- * - <mxConstants.STYLE_FILL_OPACITY> => fillOpacity
- * - <mxConstants.STYLE_STROKE_OPACITY> => strokeOpacity
- * - <mxConstants.STYLE_STROKECOLOR> => stroke
- * - <mxConstants.STYLE_STROKEWIDTH> => strokewidth
- * - <mxConstants.STYLE_SHADOW> => isShadow
- * - <mxConstants.STYLE_DASHED> => isDashed
- * - <mxConstants.STYLE_SPACING> => spacing
- * - <mxConstants.STYLE_STARTSIZE> => startSize
- * - <mxConstants.STYLE_ENDSIZE> => endSize
- * - <mxConstants.STYLE_ROUNDED> => isRounded
- * - <mxConstants.STYLE_STARTARROW> => startArrow
- * - <mxConstants.STYLE_ENDARROW> => endArrow
- * - <mxConstants.STYLE_ROTATION> => rotation
- * - <mxConstants.STYLE_DIRECTION> => direction
- * - <mxConstants.STYLE_GLASS> => glass
- *
- * This keeps a reference to the <style>. If you need to keep a reference to
- * the cell, you can override this method and store a local reference to
- * state.cell or the <mxCellState> itself. If <outline> should be true, make
- * sure to set it before calling this method.
- *
- * Parameters:
- *
- * state - <mxCellState> of the corresponding cell.
- */
- mxShape.prototype.apply = function(state)
- {
- this.state = state;
- this.style = state.style;
- if (this.style != null)
- {
- this.fill = mxUtils.getValue(this.style, mxConstants.STYLE_FILLCOLOR, this.fill);
- this.gradient = mxUtils.getValue(this.style, mxConstants.STYLE_GRADIENTCOLOR, this.gradient);
- this.gradientDirection = mxUtils.getValue(this.style, mxConstants.STYLE_GRADIENT_DIRECTION, this.gradientDirection);
- this.opacity = mxUtils.getValue(this.style, mxConstants.STYLE_OPACITY, this.opacity);
- this.fillOpacity = mxUtils.getValue(this.style, mxConstants.STYLE_FILL_OPACITY, this.fillOpacity);
- this.strokeOpacity = mxUtils.getValue(this.style, mxConstants.STYLE_STROKE_OPACITY, this.strokeOpacity);
- this.stroke = mxUtils.getValue(this.style, mxConstants.STYLE_STROKECOLOR, this.stroke);
- this.strokewidth = mxUtils.getNumber(this.style, mxConstants.STYLE_STROKEWIDTH, this.strokewidth);
- this.spacing = mxUtils.getValue(this.style, mxConstants.STYLE_SPACING, this.spacing);
- this.startSize = mxUtils.getNumber(this.style, mxConstants.STYLE_STARTSIZE, this.startSize);
- this.endSize = mxUtils.getNumber(this.style, mxConstants.STYLE_ENDSIZE, this.endSize);
- this.startArrow = mxUtils.getValue(this.style, mxConstants.STYLE_STARTARROW, this.startArrow);
- this.endArrow = mxUtils.getValue(this.style, mxConstants.STYLE_ENDARROW, this.endArrow);
- this.rotation = mxUtils.getValue(this.style, mxConstants.STYLE_ROTATION, this.rotation);
- this.direction = mxUtils.getValue(this.style, mxConstants.STYLE_DIRECTION, this.direction);
- this.flipH = mxUtils.getValue(this.style, mxConstants.STYLE_FLIPH, 0) == 1;
- this.flipV = mxUtils.getValue(this.style, mxConstants.STYLE_FLIPV, 0) == 1;
-
- // Legacy support for stencilFlipH/V
- if (this.stencil != null)
- {
- this.flipH = mxUtils.getValue(this.style, 'stencilFlipH', 0) == 1 || this.flipH;
- this.flipV = mxUtils.getValue(this.style, 'stencilFlipV', 0) == 1 || this.flipV;
- }
-
- if (this.direction == mxConstants.DIRECTION_NORTH || this.direction == mxConstants.DIRECTION_SOUTH)
- {
- var tmp = this.flipH;
- this.flipH = this.flipV;
- this.flipV = tmp;
- }
- this.isShadow = mxUtils.getValue(this.style, mxConstants.STYLE_SHADOW, this.isShadow) == 1;
- this.isDashed = mxUtils.getValue(this.style, mxConstants.STYLE_DASHED, this.isDashed) == 1;
- this.isRounded = mxUtils.getValue(this.style, mxConstants.STYLE_ROUNDED, this.isRounded) == 1;
- this.glass = mxUtils.getValue(this.style, mxConstants.STYLE_GLASS, this.glass) == 1;
-
- if (this.fill == mxConstants.NONE)
- {
- this.fill = null;
- }
- if (this.gradient == mxConstants.NONE)
- {
- this.gradient = null;
- }
- if (this.stroke == mxConstants.NONE)
- {
- this.stroke = null;
- }
- }
- };
- /**
- * Function: setCursor
- *
- * Sets the cursor on the given shape.
- *
- * Parameters:
- *
- * cursor - The cursor to be used.
- */
- mxShape.prototype.setCursor = function(cursor)
- {
- if (cursor == null)
- {
- cursor = '';
- }
-
- this.cursor = cursor;
- if (this.node != null)
- {
- this.node.style.cursor = cursor;
- }
- };
- /**
- * Function: getCursor
- *
- * Returns the current cursor.
- */
- mxShape.prototype.getCursor = function()
- {
- return this.cursor;
- };
- /**
- * Function: isRoundable
- *
- * Hook for subclassers.
- */
- mxShape.prototype.isRoundable = function()
- {
- return false;
- };
- /**
- * Function: updateBoundingBox
- *
- * Updates the <boundingBox> for this shape using <createBoundingBox> and
- * <augmentBoundingBox> and stores the result in <boundingBox>.
- */
- mxShape.prototype.updateBoundingBox = function()
- {
- // Tries to get bounding box from SVG subsystem
- // LATER: Use getBoundingClientRect for fallback in VML
- if (this.useSvgBoundingBox && this.node != null && this.node.ownerSVGElement != null)
- {
- try
- {
- var b = this.node.getBBox();
-
- if (b.width > 0 && b.height > 0)
- {
- this.boundingBox = new mxRectangle(b.x, b.y, b.width, b.height);
-
- // Adds strokeWidth
- this.boundingBox.grow(this.strokewidth * this.scale / 2);
-
- return;
- }
- }
- catch(e)
- {
- // fallback to code below
- }
- }
- if (this.bounds != null)
- {
- var bbox = this.createBoundingBox();
-
- if (bbox != null)
- {
- this.augmentBoundingBox(bbox);
- var rot = this.getShapeRotation();
-
- if (rot != 0)
- {
- bbox = mxUtils.getBoundingBox(bbox, rot);
- }
- }
- this.boundingBox = bbox;
- }
- };
- /**
- * Function: createBoundingBox
- *
- * Returns a new rectangle that represents the bounding box of the bare shape
- * with no shadows or strokewidths.
- */
- mxShape.prototype.createBoundingBox = function()
- {
- var bb = this.bounds.clone();
- if ((this.stencil != null && (this.direction == mxConstants.DIRECTION_NORTH ||
- this.direction == mxConstants.DIRECTION_SOUTH)) || this.isPaintBoundsInverted())
- {
- bb.rotate90();
- }
-
- return bb;
- };
- /**
- * Function: augmentBoundingBox
- *
- * Augments the bounding box with the strokewidth and shadow offsets.
- */
- mxShape.prototype.augmentBoundingBox = function(bbox)
- {
- if (this.isShadow)
- {
- bbox.width += Math.ceil(mxConstants.SHADOW_OFFSET_X * this.scale);
- bbox.height += Math.ceil(mxConstants.SHADOW_OFFSET_Y * this.scale);
- }
-
- // Adds strokeWidth
- bbox.grow(this.strokewidth * this.scale / 2);
- };
- /**
- * Function: isPaintBoundsInverted
- *
- * Returns true if the bounds should be inverted.
- */
- mxShape.prototype.isPaintBoundsInverted = function()
- {
- // Stencil implements inversion via aspect
- return this.stencil == null && (this.direction == mxConstants.DIRECTION_NORTH ||
- this.direction == mxConstants.DIRECTION_SOUTH);
- };
- /**
- * Function: getRotation
- *
- * Returns the rotation from the style.
- */
- mxShape.prototype.getRotation = function()
- {
- return (this.rotation != null) ? this.rotation : 0;
- };
- /**
- * Function: getTextRotation
- *
- * Returns the rotation for the text label.
- */
- mxShape.prototype.getTextRotation = function()
- {
- var rot = this.getRotation();
-
- if (mxUtils.getValue(this.style, mxConstants.STYLE_HORIZONTAL, 1) != 1)
- {
- rot += mxText.prototype.verticalTextRotation;
- }
-
- return rot;
- };
- /**
- * Function: getShapeRotation
- *
- * Returns the actual rotation of the shape.
- */
- mxShape.prototype.getShapeRotation = function()
- {
- var rot = this.getRotation();
-
- if (this.direction != null)
- {
- if (this.direction == mxConstants.DIRECTION_NORTH)
- {
- rot += 270;
- }
- else if (this.direction == mxConstants.DIRECTION_WEST)
- {
- rot += 180;
- }
- else if (this.direction == mxConstants.DIRECTION_SOUTH)
- {
- rot += 90;
- }
- }
-
- return rot;
- };
- /**
- * Function: createTransparentSvgRectangle
- *
- * Adds a transparent rectangle that catches all events.
- */
- mxShape.prototype.createTransparentSvgRectangle = function(x, y, w, h)
- {
- var rect = document.createElementNS(mxConstants.NS_SVG, 'rect');
- rect.setAttribute('x', x);
- rect.setAttribute('y', y);
- rect.setAttribute('width', w);
- rect.setAttribute('height', h);
- rect.setAttribute('fill', 'none');
- rect.setAttribute('stroke', 'none');
- rect.setAttribute('pointer-events', 'all');
-
- return rect;
- };
- /**
- * Function: setTransparentBackgroundImage
- *
- * Sets a transparent background CSS style to catch all events.
- *
- * Paints the line shape.
- */
- mxShape.prototype.setTransparentBackgroundImage = function(node)
- {
- node.style.backgroundImage = 'url(\'' + mxClient.imageBasePath + '/transparent.gif\')';
- };
- /**
- * Function: releaseSvgGradients
- *
- * Paints the line shape.
- */
- mxShape.prototype.releaseSvgGradients = function(grads)
- {
- if (grads != null)
- {
- for (var key in grads)
- {
- var gradient = grads[key];
-
- if (gradient != null)
- {
- gradient.mxRefCount = (gradient.mxRefCount || 0) - 1;
-
- if (gradient.mxRefCount == 0 && gradient.parentNode != null)
- {
- gradient.parentNode.removeChild(gradient);
- }
- }
- }
- }
- };
- /**
- * Function: destroy
- *
- * Destroys the shape by removing it from the DOM and releasing the DOM
- * node associated with the shape using <mxEvent.release>.
- */
- mxShape.prototype.destroy = function()
- {
- if (this.node != null)
- {
- mxEvent.release(this.node);
-
- if (this.node.parentNode != null)
- {
- this.node.parentNode.removeChild(this.node);
- }
-
- this.node = null;
- }
-
- // Decrements refCount and removes unused
- this.releaseSvgGradients(this.oldGradients);
- this.oldGradients = null;
- };
- __mxOutput.mxShape = typeof mxShape !== 'undefined' ? mxShape : undefined;
|