/** * Copyright (c) 2006-2015, JGraph Ltd */ /** * Registers shapes. */ (function() { // Cube Shape, supports size style function CubeShape() { mxCylinder.call(this); }; mxUtils.extend(CubeShape, mxCylinder); CubeShape.prototype.size = 20; CubeShape.prototype.redrawPath = function(path, x, y, w, h, isForeground) { var s = Math.max(0, Math.min(w, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))))); if (isForeground) { path.moveTo(s, h); path.lineTo(s, s); path.lineTo(0, 0); path.moveTo(s, s); path.lineTo(w, s); path.end(); } else { path.moveTo(0, 0); path.lineTo(w - s, 0); path.lineTo(w, s); path.lineTo(w, h); path.lineTo(s, h); path.lineTo(0, h - s); path.lineTo(0, 0); path.close(); path.end(); } }; mxCellRenderer.prototype.defaultShapes['cube'] = CubeShape; // DataStore Shape, supports size style function DataStoreShape() { mxCylinder.call(this); }; mxUtils.extend(DataStoreShape, mxCylinder); DataStoreShape.prototype.redrawPath = function(c, x, y, w, h, isForeground) { var dy = Math.min(h / 2, Math.round(h / 8) + this.strokewidth - 1); if ((isForeground && this.fill != null) || (!isForeground && this.fill == null)) { c.moveTo(0, dy); c.curveTo(0, 2 * dy, w, 2 * dy, w, dy); // Needs separate shapes for correct hit-detection if (!isForeground) { c.stroke(); c.begin(); } c.translate(0, dy / 2); c.moveTo(0, dy); c.curveTo(0, 2 * dy, w, 2 * dy, w, dy); // Needs separate shapes for correct hit-detection if (!isForeground) { c.stroke(); c.begin(); } c.translate(0, dy / 2); c.moveTo(0, dy); c.curveTo(0, 2 * dy, w, 2 * dy, w, dy); // Needs separate shapes for correct hit-detection if (!isForeground) { c.stroke(); c.begin(); } c.translate(0, -dy); } if (!isForeground) { c.moveTo(0, dy); c.curveTo(0, -dy / 3, w, -dy / 3, w, dy); c.lineTo(w, h - dy); c.curveTo(w, h + dy / 3, 0, h + dy / 3, 0, h - dy); c.close(); } }; DataStoreShape.prototype.getLabelBounds = function(rect) { var dy = 2.5 * Math.min(rect.height / 2, Math.round(rect.height / 8) + this.strokewidth - 1); if ((!this.flipV && (this.direction == null || this.direction == mxConstants.DIRECTION_EAST) || (this.flipV && this.direction == mxConstants.DIRECTION_WEST))) { rect.y += dy; rect.height -= dy; } else if ((!this.flipV && this.direction == mxConstants.DIRECTION_SOUTH) || ((this.flipV && this.direction == mxConstants.DIRECTION_NORTH))) { rect.width -= dy; } else if ((!this.flipV && this.direction == mxConstants.DIRECTION_WEST) || (this.flipV && (this.direction == null || this.direction == mxConstants.DIRECTION_EAST))) { rect.height -= dy; } else if ((!this.flipV && this.direction == mxConstants.DIRECTION_NORTH) || (this.flipV && this.direction == mxConstants.DIRECTION_SOUTH)) { rect.x += dy; rect.width -= dy; } return rect; }; mxCellRenderer.prototype.defaultShapes['datastore'] = DataStoreShape; // Note Shape, supports size style function NoteShape() { mxCylinder.call(this); }; mxUtils.extend(NoteShape, mxCylinder); NoteShape.prototype.size = 30; NoteShape.prototype.redrawPath = function(path, x, y, w, h, isForeground) { var s = Math.max(0, Math.min(w, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))))); if (isForeground) { path.moveTo(w - s, 0); path.lineTo(w - s, s); path.lineTo(w, s); path.end(); } else { path.moveTo(0, 0); path.lineTo(w - s, 0); path.lineTo(w, s); path.lineTo(w, h); path.lineTo(0, h); path.lineTo(0, 0); path.close(); path.end(); } }; mxCellRenderer.prototype.defaultShapes['note'] = NoteShape; // Note Shape, supports size style function SwitchShape() { mxActor.call(this); }; mxUtils.extend(SwitchShape, mxActor); SwitchShape.prototype.redrawPath = function(c, x, y, w, h) { var curve = 0.5; c.moveTo(0, 0); c.quadTo(w / 2, h * curve, w, 0); c.quadTo(w * (1 - curve), h / 2, w, h); c.quadTo(w / 2, h * (1 - curve), 0, h); c.quadTo(w * curve, h / 2, 0, 0); c.end(); }; mxCellRenderer.prototype.defaultShapes['switch'] = SwitchShape; // Folder Shape, supports tabWidth, tabHeight styles function FolderShape() { mxCylinder.call(this); }; mxUtils.extend(FolderShape, mxCylinder); FolderShape.prototype.tabWidth = 60; FolderShape.prototype.tabHeight = 20; FolderShape.prototype.tabPosition = 'right'; FolderShape.prototype.redrawPath = function(path, x, y, w, h, isForeground) { var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'tabWidth', this.tabWidth)))); var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'tabHeight', this.tabHeight)))); var tp = mxUtils.getValue(this.style, 'tabPosition', this.tabPosition); if (isForeground) { if (tp == 'left') { path.moveTo(0, dy); path.lineTo(dx, dy); } // Right is default else { path.moveTo(w - dx, dy); path.lineTo(w, dy); } path.end(); } else { if (tp == 'left') { path.moveTo(0, 0); path.lineTo(dx, 0); path.lineTo(dx, dy); path.lineTo(w, dy); } // Right is default else { path.moveTo(0, dy); path.lineTo(w - dx, dy); path.lineTo(w - dx, 0); path.lineTo(w, 0); } path.lineTo(w, h); path.lineTo(0, h); path.lineTo(0, dy); path.close(); path.end(); } }; mxCellRenderer.prototype.defaultShapes['folder'] = FolderShape; // Card shape function CardShape() { mxActor.call(this); }; mxUtils.extend(CardShape, mxActor); CardShape.prototype.size = 30; CardShape.prototype.redrawPath = function(c, x, y, w, h) { var s = Math.max(0, Math.min(w, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(s, 0), new mxPoint(w, 0), new mxPoint(w, h), new mxPoint(0, h), new mxPoint(0, s)], this.isRounded, arcSize, true); c.end(); }; mxCellRenderer.prototype.defaultShapes['card'] = CardShape; // Tape shape function TapeShape() { mxActor.call(this); }; mxUtils.extend(TapeShape, mxActor); TapeShape.prototype.size = 0.4; TapeShape.prototype.redrawPath = function(c, x, y, w, h) { var dy = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var fy = 1.4; c.moveTo(0, dy / 2); c.quadTo(w / 4, dy * fy, w / 2, dy / 2); c.quadTo(w * 3 / 4, dy * (1 - fy), w, dy / 2); c.lineTo(w, h - dy / 2); c.quadTo(w * 3 / 4, h - dy * fy, w / 2, h - dy / 2); c.quadTo(w / 4, h - dy * (1 - fy), 0, h - dy / 2); c.lineTo(0, dy / 2); c.close(); c.end(); }; mxCellRenderer.prototype.defaultShapes['tape'] = TapeShape; // Document shape function DocumentShape() { mxActor.call(this); }; mxUtils.extend(DocumentShape, mxActor); DocumentShape.prototype.size = 0.3; DocumentShape.prototype.redrawPath = function(c, x, y, w, h) { var dy = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var fy = 1.4; c.moveTo(0, 0); c.lineTo(w, 0); c.lineTo(w, h - dy / 2); c.quadTo(w * 3 / 4, h - dy * fy, w / 2, h - dy / 2); c.quadTo(w / 4, h - dy * (1 - fy), 0, h - dy / 2); c.lineTo(0, dy / 2); c.close(); c.end(); }; mxCellRenderer.prototype.defaultShapes['document'] = DocumentShape; // Parallelogram shape function ParallelogramShape() { mxActor.call(this); }; mxUtils.extend(ParallelogramShape, mxActor); ParallelogramShape.prototype.size = 0.2; ParallelogramShape.prototype.redrawPath = function(c, x, y, w, h) { var dx = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(0, h), new mxPoint(dx, 0), new mxPoint(w, 0), new mxPoint(w - dx, h)], this.isRounded, arcSize, true); c.end(); }; mxCellRenderer.prototype.defaultShapes['parallelogram'] = ParallelogramShape; // Trapezoid shape function TrapezoidShape() { mxActor.call(this); }; mxUtils.extend(TrapezoidShape, mxActor); TrapezoidShape.prototype.size = 0.2; TrapezoidShape.prototype.redrawPath = function(c, x, y, w, h) { var dx = w * Math.max(0, Math.min(0.5, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(0, h), new mxPoint(dx, 0), new mxPoint(w - dx, 0), new mxPoint(w, h)], this.isRounded, arcSize, true); }; mxCellRenderer.prototype.defaultShapes['trapezoid'] = TrapezoidShape; // Curly Bracket shape function CurlyBracketShape() { mxActor.call(this); }; mxUtils.extend(CurlyBracketShape, mxActor); CurlyBracketShape.prototype.size = 0.5; CurlyBracketShape.prototype.redrawPath = function(c, x, y, w, h) { c.setFillColor(null); var s = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(w, 0), new mxPoint(s, 0), new mxPoint(s, h / 2), new mxPoint(0, h / 2), new mxPoint(s, h / 2), new mxPoint(s, h), new mxPoint(w, h)], this.isRounded, arcSize, false); c.end(); }; mxCellRenderer.prototype.defaultShapes['curlyBracket'] = CurlyBracketShape; // Parallel marker shape function ParallelMarkerShape() { mxActor.call(this); }; mxUtils.extend(ParallelMarkerShape, mxActor); ParallelMarkerShape.prototype.redrawPath = function(c, x, y, w, h) { c.setStrokeWidth(1); c.setFillColor(this.stroke); var w2 = w / 5; c.rect(0, 0, w2, h); c.fillAndStroke(); c.rect(2 * w2, 0, w2, h); c.fillAndStroke(); c.rect(4 * w2, 0, w2, h); c.fillAndStroke(); }; mxCellRenderer.prototype.defaultShapes['parallelMarker'] = ParallelMarkerShape; // Process Shape function ProcessShape() { mxRectangleShape.call(this); }; mxUtils.extend(ProcessShape, mxRectangleShape); ProcessShape.prototype.size = 0.1; ProcessShape.prototype.isHtmlAllowed = function() { return false; }; ProcessShape.prototype.getLabelBounds = function(rect) { if (mxUtils.getValue(this.state.style, mxConstants.STYLE_HORIZONTAL, true) == (this.direction == null || this.direction == mxConstants.DIRECTION_EAST || this.direction == mxConstants.DIRECTION_WEST)) { var w = rect.width; var h = rect.height; var r = new mxRectangle(rect.x, rect.y, w, h); var inset = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); if (this.isRounded) { var f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100; inset = Math.max(inset, Math.min(w * f, h * f)); } r.x += inset; r.width -= 2 * inset; return r; } return rect; }; ProcessShape.prototype.paintForeground = function(c, x, y, w, h) { var inset = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); if (this.isRounded) { var f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100; inset = Math.max(inset, Math.min(w * f, h * f)); } c.begin(); c.moveTo(x + inset, y); c.lineTo(x + inset, y + h); c.moveTo(x + w - inset, y); c.lineTo(x + w - inset, y + h); c.end(); c.stroke(); mxRectangleShape.prototype.paintForeground.apply(this, arguments); }; mxCellRenderer.prototype.defaultShapes['process'] = ProcessShape; // Step shape function StepShape() { mxActor.call(this); }; mxUtils.extend(StepShape, mxActor); StepShape.prototype.size = 0.2; StepShape.prototype.redrawPath = function(c, x, y, w, h) { var s = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w - s, 0), new mxPoint(w, h / 2), new mxPoint(w - s, h), new mxPoint(0, h), new mxPoint(s, h / 2)], this.isRounded, arcSize, true); c.end(); }; mxCellRenderer.prototype.defaultShapes['step'] = StepShape; // Hexagon shape function HexagonShape() { mxActor.call(this); }; mxUtils.extend(HexagonShape, mxHexagon); HexagonShape.prototype.size = 0.25; HexagonShape.prototype.redrawPath = function(c, x, y, w, h) { var s = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(s, 0), new mxPoint(w - s, 0), new mxPoint(w, 0.5 * h), new mxPoint(w - s, h), new mxPoint(s, h), new mxPoint(0, 0.5 * h)], this.isRounded, arcSize, true); }; mxCellRenderer.prototype.defaultShapes['hexagon'] = HexagonShape; // Plus Shape function PlusShape() { mxRectangleShape.call(this); }; mxUtils.extend(PlusShape, mxRectangleShape); PlusShape.prototype.isHtmlAllowed = function() { return false; }; PlusShape.prototype.paintForeground = function(c, x, y, w, h) { var border = Math.min(w / 5, h / 5) + 1; c.begin(); c.moveTo(x + w / 2, y + border); c.lineTo(x + w / 2, y + h - border); c.moveTo(x + border, y + h / 2); c.lineTo(x + w - border, y + h / 2); c.end(); c.stroke(); mxRectangleShape.prototype.paintForeground.apply(this, arguments); }; mxCellRenderer.prototype.defaultShapes['plus'] = PlusShape; // Overrides painting of rhombus shape to allow for double style var mxRhombusPaintVertexShape = mxRhombus.prototype.paintVertexShape; mxRhombus.prototype.getLabelBounds = function(rect) { if (this.style['double'] == 1) { var margin = (Math.max(2, this.strokewidth + 1) * 2 + parseFloat(this.style[mxConstants.STYLE_MARGIN] || 0)) * this.scale; return new mxRectangle(rect.x + margin, rect.y + margin, rect.width - 2 * margin, rect.height - 2 * margin); } return rect; }; mxRhombus.prototype.paintVertexShape = function(c, x, y, w, h) { mxRhombusPaintVertexShape.apply(this, arguments); if (!this.outline && this.style['double'] == 1) { var margin = Math.max(2, this.strokewidth + 1) * 2 + parseFloat(this.style[mxConstants.STYLE_MARGIN] || 0); x += margin; y += margin; w -= 2 * margin; h -= 2 * margin; if (w > 0 && h > 0) { c.setShadow(false); // Workaround for closure compiler bug where the lines with x and y above // are removed if arguments is used as second argument in call below. mxRhombusPaintVertexShape.apply(this, [c, x, y, w, h]); } } }; // CompositeShape function ExtendedShape() { mxRectangleShape.call(this); }; mxUtils.extend(ExtendedShape, mxRectangleShape); ExtendedShape.prototype.isHtmlAllowed = function() { return false; }; ExtendedShape.prototype.getLabelBounds = function(rect) { if (this.style['double'] == 1) { var margin = (Math.max(2, this.strokewidth + 1) + parseFloat(this.style[mxConstants.STYLE_MARGIN] || 0)) * this.scale; return new mxRectangle(rect.x + margin, rect.y + margin, rect.width - 2 * margin, rect.height - 2 * margin); } return rect; }; ExtendedShape.prototype.paintForeground = function(c, x, y, w, h) { if (this.style != null) { if (!this.outline && this.style['double'] == 1) { var margin = Math.max(2, this.strokewidth + 1) + parseFloat(this.style[mxConstants.STYLE_MARGIN] || 0); x += margin; y += margin; w -= 2 * margin; h -= 2 * margin; if (w > 0 && h > 0) { mxRectangleShape.prototype.paintBackground.apply(this, arguments); } } c.setDashed(false); // Draws the symbols defined in the style. The symbols are // numbered from 1...n. Possible postfixes are align, // verticalAlign, spacing, arcSpacing, width, height var counter = 0; var shape = null; do { shape = mxCellRenderer.prototype.defaultShapes[this.style['symbol' + counter]]; if (shape != null) { var align = this.style['symbol' + counter + 'Align']; var valign = this.style['symbol' + counter + 'VerticalAlign']; var width = this.style['symbol' + counter + 'Width']; var height = this.style['symbol' + counter + 'Height']; var spacing = this.style['symbol' + counter + 'Spacing'] || 0; var arcspacing = this.style['symbol' + counter + 'ArcSpacing']; if (arcspacing != null) { spacing += this.getArcSize(w + this.strokewidth, h + this.strokewidth) * arcspacing; } var x2 = x; var y2 = y; if (align == mxConstants.ALIGN_CENTER) { x2 += (w - width) / 2; } else if (align == mxConstants.ALIGN_RIGHT) { x2 += w - width - spacing; } else { x2 += spacing; } if (valign == mxConstants.ALIGN_MIDDLE) { y2 += (h - height) / 2; } else if (valign == mxConstants.ALIGN_BOTTOM) { y2 += h - height - spacing; } else { y2 += spacing; } c.save(); // Small hack to pass style along into subshape var tmp = new shape(); // TODO: Clone style and override settings (eg. strokewidth) tmp.style = this.style; shape.prototype.paintVertexShape.call(tmp, c, x2, y2, width, height); c.restore(); } counter++; } while (shape != null); } // Paints glass effect mxRectangleShape.prototype.paintForeground.apply(this, arguments); }; mxCellRenderer.prototype.defaultShapes['ext'] = ExtendedShape; // Tape Shape, supports size style function MessageShape() { mxCylinder.call(this); }; mxUtils.extend(MessageShape, mxCylinder); MessageShape.prototype.redrawPath = function(path, x, y, w, h, isForeground) { if (isForeground) { path.moveTo(0, 0); path.lineTo(w / 2, h / 2); path.lineTo(w, 0); path.end(); } else { path.moveTo(0, 0); path.lineTo(w, 0); path.lineTo(w, h); path.lineTo(0, h); path.close(); } }; mxCellRenderer.prototype.defaultShapes['message'] = MessageShape; // UML Actor Shape function UmlActorShape() { mxShape.call(this); }; mxUtils.extend(UmlActorShape, mxShape); UmlActorShape.prototype.paintBackground = function(c, x, y, w, h) { c.translate(x, y); // Head c.ellipse(w / 4, 0, w / 2, h / 4); c.fillAndStroke(); c.begin(); c.moveTo(w / 2, h / 4); c.lineTo(w / 2, 2 * h / 3); // Arms c.moveTo(w / 2, h / 3); c.lineTo(0, h / 3); c.moveTo(w / 2, h / 3); c.lineTo(w, h / 3); // Legs c.moveTo(w / 2, 2 * h / 3); c.lineTo(0, h); c.moveTo(w / 2, 2 * h / 3); c.lineTo(w, h); c.end(); c.stroke(); }; // Replaces existing actor shape mxCellRenderer.prototype.defaultShapes['umlActor'] = UmlActorShape; // UML Boundary Shape function UmlBoundaryShape() { mxShape.call(this); }; mxUtils.extend(UmlBoundaryShape, mxShape); UmlBoundaryShape.prototype.getLabelBounds = function(rect) { return new mxRectangle(rect.x + rect.width / 6, rect.y, rect.width * 5 / 6, rect.height); }; UmlBoundaryShape.prototype.paintBackground = function(c, x, y, w, h) { c.translate(x, y); // Base line c.begin(); c.moveTo(0, h / 4); c.lineTo(0, h * 3 / 4); c.end(); c.stroke(); // Horizontal line c.begin(); c.moveTo(0, h / 2); c.lineTo(w / 6, h / 2); c.end(); c.stroke(); // Circle c.ellipse(w / 6, 0, w * 5 / 6, h); c.fillAndStroke(); }; // Replaces existing actor shape mxCellRenderer.prototype.defaultShapes['umlBoundary'] = UmlBoundaryShape; // UML Entity Shape function UmlEntityShape() { mxEllipse.call(this); }; mxUtils.extend(UmlEntityShape, mxEllipse); UmlEntityShape.prototype.paintVertexShape = function(c, x, y, w, h) { mxEllipse.prototype.paintVertexShape.apply(this, arguments); c.begin(); c.moveTo(x + w / 8, y + h); c.lineTo(x + w * 7 / 8, y + h); c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['umlEntity'] = UmlEntityShape; // UML Destroy Shape function UmlDestroyShape() { mxShape.call(this); }; mxUtils.extend(UmlDestroyShape, mxShape); UmlDestroyShape.prototype.paintVertexShape = function(c, x, y, w, h) { c.translate(x, y); c.begin(); c.moveTo(w, 0); c.lineTo(0, h); c.moveTo(0, 0); c.lineTo(w, h); c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['umlDestroy'] = UmlDestroyShape; // UML Control Shape function UmlControlShape() { mxShape.call(this); }; mxUtils.extend(UmlControlShape, mxShape); UmlControlShape.prototype.getLabelBounds = function(rect) { return new mxRectangle(rect.x, rect.y + rect.height / 8, rect.width, rect.height * 7 / 8); }; UmlControlShape.prototype.paintBackground = function(c, x, y, w, h) { c.translate(x, y); // Upper line c.begin(); c.moveTo(w * 3 / 8, h / 8 * 1.1); c.lineTo(w * 5 / 8, 0); c.end(); c.stroke(); // Circle c.ellipse(0, h / 8, w, h * 7 / 8); c.fillAndStroke(); }; UmlControlShape.prototype.paintForeground = function(c, x, y, w, h) { // Lower line c.begin(); c.moveTo(w * 3 / 8, h / 8 * 1.1); c.lineTo(w * 5 / 8, h / 4); c.end(); c.stroke(); }; // Replaces existing actor shape mxCellRenderer.prototype.defaultShapes['umlControl'] = UmlControlShape; // UML Lifeline Shape function UmlLifeline() { mxRectangleShape.call(this); }; mxUtils.extend(UmlLifeline, mxRectangleShape); UmlLifeline.prototype.size = 40; UmlLifeline.prototype.isHtmlAllowed = function() { return false; }; UmlLifeline.prototype.getLabelBounds = function(rect) { var size = Math.max(0, Math.min(rect.height, parseFloat(mxUtils.getValue(this.style, 'size', this.size)) * this.scale)); return new mxRectangle(rect.x, rect.y, rect.width, size); }; UmlLifeline.prototype.paintBackground = function(c, x, y, w, h) { var size = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var participant = mxUtils.getValue(this.style, 'participant'); if (participant == null || this.state == null) { mxRectangleShape.prototype.paintBackground.call(this, c, x, y, w, size); } else { var ctor = this.state.view.graph.cellRenderer.getShape(participant); if (ctor != null && ctor != UmlLifeline) { var shape = new ctor(); shape.apply(this.state); c.save(); shape.paintVertexShape(c, x, y, w, size); c.restore(); } } if (size < h) { c.setDashed(true); c.begin(); c.moveTo(x + w / 2, y + size); c.lineTo(x + w / 2, y + h); c.end(); c.stroke(); } }; UmlLifeline.prototype.paintForeground = function(c, x, y, w, h) { var size = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); mxRectangleShape.prototype.paintForeground.call(this, c, x, y, w, Math.min(h, size)); }; mxCellRenderer.prototype.defaultShapes['umlLifeline'] = UmlLifeline; // UML Frame Shape function UmlFrame() { mxShape.call(this); }; mxUtils.extend(UmlFrame, mxShape); UmlFrame.prototype.width = 60; UmlFrame.prototype.height = 30; UmlFrame.prototype.corner = 10; UmlFrame.prototype.getLabelBounds = function(rect) { var w = Math.max(0, Math.min(rect.width, parseFloat(mxUtils.getValue(this.style, 'width', this.width)) * this.scale)); var h = Math.max(0, Math.min(rect.height, parseFloat(mxUtils.getValue(this.style, 'height', this.height)) * this.scale)); return new mxRectangle(rect.x, rect.y, w, h); }; UmlFrame.prototype.paintBackground = function(c, x, y, w, h) { var co = this.corner; var w0 = Math.min(w, Math.max(co, parseFloat(mxUtils.getValue(this.style, 'width', this.width)))); var h0 = Math.min(h, Math.max(co * 1.5, parseFloat(mxUtils.getValue(this.style, 'height', this.height)))); c.begin(); c.moveTo(x, y); c.lineTo(x + w0, y); c.lineTo(x + w0, y + Math.max(0, h0 - co * 1.5)); c.lineTo(x + Math.max(0, w0 - co), y + h0); c.lineTo(x, y + h0); c.close(); c.fillAndStroke(); c.begin(); c.moveTo(x + w0, y); c.lineTo(x + w, y); c.lineTo(x + w, y + h); c.lineTo(x, y + h); c.lineTo(x, y + h0); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['umlFrame'] = UmlFrame; mxPerimeter.LifelinePerimeter = function (bounds, vertex, next, orthogonal) { var size = UmlLifeline.prototype.size; if (vertex != null) { size = mxUtils.getValue(vertex.style, 'size', size) * vertex.view.scale; } return new mxPoint(bounds.getCenterX(), Math.min(bounds.y + bounds.height, Math.max(bounds.y + size, next.y))); }; mxStyleRegistry.putValue('lifelinePerimeter', mxPerimeter.LifelinePerimeter); mxPerimeter.OrthogonalPerimeter = function (bounds, vertex, next, orthogonal) { orthogonal = true; return mxPerimeter.RectanglePerimeter.apply(this, arguments); }; mxStyleRegistry.putValue('orthogonalPerimeter', mxPerimeter.OrthogonalPerimeter); // Lollipop Shape function LollipopShape() { mxShape.call(this); }; mxUtils.extend(LollipopShape, mxShape); LollipopShape.prototype.size = 10; LollipopShape.prototype.paintBackground = function(c, x, y, w, h) { var sz = parseFloat(mxUtils.getValue(this.style, 'size', this.size)); c.translate(x, y); c.ellipse((w - sz) / 2, 0, sz, sz); c.fillAndStroke(); c.begin(); c.moveTo(w / 2, sz); c.lineTo(w / 2, h); c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['lollipop'] = LollipopShape; // Lollipop Shape function RequiresShape() { mxShape.call(this); }; mxUtils.extend(RequiresShape, mxShape); RequiresShape.prototype.size = 10; RequiresShape.prototype.inset = 2; RequiresShape.prototype.paintBackground = function(c, x, y, w, h) { var sz = parseFloat(mxUtils.getValue(this.style, 'size', this.size)); var inset = parseFloat(mxUtils.getValue(this.style, 'inset', this.inset)) + this.strokewidth; c.translate(x, y); c.begin(); c.moveTo(w / 2, sz + inset); c.lineTo(w / 2, h); c.end(); c.stroke(); c.begin(); c.moveTo((w - sz) / 2 - inset, sz / 2); c.quadTo((w - sz) / 2 - inset, sz + inset, w / 2, sz + inset); c.quadTo((w + sz) / 2 + inset, sz + inset, (w + sz) / 2 + inset, sz / 2); c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['requires'] = RequiresShape; // Component shape function ComponentShape() { mxCylinder.call(this); }; mxUtils.extend(ComponentShape, mxCylinder); ComponentShape.prototype.jettyWidth = 32; ComponentShape.prototype.jettyHeight = 12; ComponentShape.prototype.redrawPath = function(path, x, y, w, h, isForeground) { var dx = parseFloat(mxUtils.getValue(this.style, 'jettyWidth', this.jettyWidth)); var dy = parseFloat(mxUtils.getValue(this.style, 'jettyHeight', this.jettyHeight)); var x0 = dx / 2; var x1 = x0 + dx / 2; var y0 = 0.3 * h - dy / 2; var y1 = 0.7 * h - dy / 2; if (isForeground) { path.moveTo(x0, y0); path.lineTo(x1, y0); path.lineTo(x1, y0 + dy); path.lineTo(x0, y0 + dy); path.moveTo(x0, y1); path.lineTo(x1, y1); path.lineTo(x1, y1 + dy); path.lineTo(x0, y1 + dy); path.end(); } else { path.moveTo(x0, 0); path.lineTo(w, 0); path.lineTo(w, h); path.lineTo(x0, h); path.lineTo(x0, y1 + dy); path.lineTo(0, y1 + dy); path.lineTo(0, y1); path.lineTo(x0, y1); path.lineTo(x0, y0 + dy); path.lineTo(0, y0 + dy); path.lineTo(0, y0); path.lineTo(x0, y0); path.close(); path.end(); } }; mxCellRenderer.prototype.defaultShapes['component'] = ComponentShape; // State Shapes derives from double ellipse function StateShape() { mxDoubleEllipse.call(this); }; mxUtils.extend(StateShape, mxDoubleEllipse); StateShape.prototype.outerStroke = true; StateShape.prototype.paintVertexShape = function(c, x, y, w, h) { var inset = Math.min(4, Math.min(w / 5, h / 5)); if (w > 0 && h > 0) { c.ellipse(x + inset, y + inset, w - 2 * inset, h - 2 * inset); c.fillAndStroke(); } c.setShadow(false); if (this.outerStroke) { c.ellipse(x, y, w, h); c.stroke(); } }; mxCellRenderer.prototype.defaultShapes['endState'] = StateShape; function StartStateShape() { StateShape.call(this); }; mxUtils.extend(StartStateShape, StateShape); StartStateShape.prototype.outerStroke = false; mxCellRenderer.prototype.defaultShapes['startState'] = StartStateShape; // Link shape function LinkShape() { mxArrowConnector.call(this); this.spacing = 0; }; mxUtils.extend(LinkShape, mxArrowConnector); LinkShape.prototype.defaultWidth = 4; LinkShape.prototype.isOpenEnded = function() { return true; }; LinkShape.prototype.getEdgeWidth = function() { return mxUtils.getNumber(this.style, 'width', this.defaultWidth) + Math.max(0, this.strokewidth - 1); }; LinkShape.prototype.isArrowRounded = function() { return this.isRounded; }; // Registers the link shape mxCellRenderer.prototype.defaultShapes['link'] = LinkShape; // Generic arrow function FlexArrowShape() { mxArrowConnector.call(this); this.spacing = 0; }; mxUtils.extend(FlexArrowShape, mxArrowConnector); FlexArrowShape.prototype.defaultWidth = 10; FlexArrowShape.prototype.defaultArrowWidth = 20; FlexArrowShape.prototype.getStartArrowWidth = function() { return this.getEdgeWidth() + mxUtils.getNumber(this.style, 'startWidth', this.defaultArrowWidth); }; FlexArrowShape.prototype.getEndArrowWidth = function() { return this.getEdgeWidth() + mxUtils.getNumber(this.style, 'endWidth', this.defaultArrowWidth);; }; FlexArrowShape.prototype.getEdgeWidth = function() { return mxUtils.getNumber(this.style, 'width', this.defaultWidth) + Math.max(0, this.strokewidth - 1); }; // Registers the link shape mxCellRenderer.prototype.defaultShapes['flexArrow'] = FlexArrowShape; // Manual Input shape function ManualInputShape() { mxActor.call(this); }; mxUtils.extend(ManualInputShape, mxActor); ManualInputShape.prototype.size = 30; ManualInputShape.prototype.redrawPath = function(c, x, y, w, h) { var s = Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(0, h), new mxPoint(0, s), new mxPoint(w, 0), new mxPoint(w, h)], this.isRounded, arcSize, true); c.end(); }; mxCellRenderer.prototype.defaultShapes['manualInput'] = ManualInputShape; // Internal storage function InternalStorageShape() { mxRectangleShape.call(this); }; mxUtils.extend(InternalStorageShape, mxRectangleShape); InternalStorageShape.prototype.dx = 20; InternalStorageShape.prototype.dy = 20; InternalStorageShape.prototype.isHtmlAllowed = function() { return false; }; InternalStorageShape.prototype.paintForeground = function(c, x, y, w, h) { mxRectangleShape.prototype.paintForeground.apply(this, arguments); var inset = 0; if (this.isRounded) { var f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100; inset = Math.max(inset, Math.min(w * f, h * f)); } var dx = Math.max(inset, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx)))); var dy = Math.max(inset, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy)))); c.begin(); c.moveTo(x, y + dy); c.lineTo(x + w, y + dy); c.end(); c.stroke(); c.begin(); c.moveTo(x + dx, y); c.lineTo(x + dx, y + h); c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['internalStorage'] = InternalStorageShape; // Internal storage function CornerShape() { mxActor.call(this); }; mxUtils.extend(CornerShape, mxActor); CornerShape.prototype.dx = 20; CornerShape.prototype.dy = 20; // Corner CornerShape.prototype.redrawPath = function(c, x, y, w, h) { var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx)))); var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy)))); var s = Math.min(w / 2, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w, 0), new mxPoint(w, dy), new mxPoint(dx, dy), new mxPoint(dx, h), new mxPoint(0, h)], this.isRounded, arcSize, true); c.end(); }; mxCellRenderer.prototype.defaultShapes['corner'] = CornerShape; // Internal storage function TeeShape() { mxActor.call(this); }; mxUtils.extend(TeeShape, mxActor); TeeShape.prototype.dx = 20; TeeShape.prototype.dy = 20; // Corner TeeShape.prototype.redrawPath = function(c, x, y, w, h) { var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx)))); var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy)))); var w2 = Math.abs(w - dx) / 2; var s = Math.min(w / 2, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w, 0), new mxPoint(w, dy), new mxPoint((w + dx) / 2, dy), new mxPoint((w + dx) / 2, h), new mxPoint((w - dx) / 2, h), new mxPoint((w - dx) / 2, dy), new mxPoint(0, dy)], this.isRounded, arcSize, true); c.end(); }; mxCellRenderer.prototype.defaultShapes['tee'] = TeeShape; // Arrow function SingleArrowShape() { mxActor.call(this); }; mxUtils.extend(SingleArrowShape, mxActor); SingleArrowShape.prototype.arrowWidth = 0.3; SingleArrowShape.prototype.arrowSize = 0.2; SingleArrowShape.prototype.redrawPath = function(c, x, y, w, h) { var aw = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowWidth', this.arrowWidth)))); var as = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowSize', this.arrowSize)))); var at = (h - aw) / 2; var ab = at + aw; var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(0, at), new mxPoint(w - as, at), new mxPoint(w - as, 0), new mxPoint(w, h / 2), new mxPoint(w - as, h), new mxPoint(w - as, ab), new mxPoint(0, ab)], this.isRounded, arcSize, true); c.end(); }; mxCellRenderer.prototype.defaultShapes['singleArrow'] = SingleArrowShape; // Arrow function DoubleArrowShape() { mxActor.call(this); }; mxUtils.extend(DoubleArrowShape, mxActor); DoubleArrowShape.prototype.redrawPath = function(c, x, y, w, h) { var aw = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowWidth', SingleArrowShape.prototype.arrowWidth)))); var as = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowSize', SingleArrowShape.prototype.arrowSize)))); var at = (h - aw) / 2; var ab = at + aw; var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(0, h / 2), new mxPoint(as, 0), new mxPoint(as, at), new mxPoint(w - as, at), new mxPoint(w - as, 0), new mxPoint(w, h / 2), new mxPoint(w - as, h), new mxPoint(w - as, ab), new mxPoint(as, ab), new mxPoint(as, h)], this.isRounded, arcSize, true); c.end(); }; mxCellRenderer.prototype.defaultShapes['doubleArrow'] = DoubleArrowShape; // Data storage function DataStorageShape() { mxActor.call(this); }; mxUtils.extend(DataStorageShape, mxActor); DataStorageShape.prototype.size = 0.1; DataStorageShape.prototype.redrawPath = function(c, x, y, w, h) { var s = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); c.moveTo(s, 0); c.lineTo(w, 0); c.quadTo(w - s * 2, h / 2, w, h); c.lineTo(s, h); c.quadTo(s - s * 2, h / 2, s, 0); c.close(); c.end(); }; mxCellRenderer.prototype.defaultShapes['dataStorage'] = DataStorageShape; // Or function OrShape() { mxActor.call(this); }; mxUtils.extend(OrShape, mxActor); OrShape.prototype.redrawPath = function(c, x, y, w, h) { c.moveTo(0, 0); c.quadTo(w, 0, w, h / 2); c.quadTo(w, h, 0, h); c.close(); c.end(); }; mxCellRenderer.prototype.defaultShapes['or'] = OrShape; // Xor function XorShape() { mxActor.call(this); }; mxUtils.extend(XorShape, mxActor); XorShape.prototype.redrawPath = function(c, x, y, w, h) { c.moveTo(0, 0); c.quadTo(w, 0, w, h / 2); c.quadTo(w, h, 0, h); c.quadTo(w / 2, h / 2, 0, 0); c.close(); c.end(); }; mxCellRenderer.prototype.defaultShapes['xor'] = XorShape; // Loop limit function LoopLimitShape() { mxActor.call(this); }; mxUtils.extend(LoopLimitShape, mxActor); LoopLimitShape.prototype.size = 20; LoopLimitShape.prototype.redrawPath = function(c, x, y, w, h) { var s = Math.min(w / 2, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(s, 0), new mxPoint(w - s, 0), new mxPoint(w, s * 0.8), new mxPoint(w, h), new mxPoint(0, h), new mxPoint(0, s * 0.8)], this.isRounded, arcSize, true); c.end(); }; mxCellRenderer.prototype.defaultShapes['loopLimit'] = LoopLimitShape; // Off page connector function OffPageConnectorShape() { mxActor.call(this); }; mxUtils.extend(OffPageConnectorShape, mxActor); OffPageConnectorShape.prototype.size = 3 / 8; OffPageConnectorShape.prototype.redrawPath = function(c, x, y, w, h) { var s = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2; this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w, 0), new mxPoint(w, h - s), new mxPoint(w / 2, h), new mxPoint(0, h - s)], this.isRounded, arcSize, true); c.end(); }; mxCellRenderer.prototype.defaultShapes['offPageConnector'] = OffPageConnectorShape; // Internal storage function TapeDataShape() { mxEllipse.call(this); }; mxUtils.extend(TapeDataShape, mxEllipse); TapeDataShape.prototype.paintVertexShape = function(c, x, y, w, h) { mxEllipse.prototype.paintVertexShape.apply(this, arguments); c.begin(); c.moveTo(x + w / 2, y + h); c.lineTo(x + w, y + h); c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['tapeData'] = TapeDataShape; // OrEllipseShape function OrEllipseShape() { mxEllipse.call(this); }; mxUtils.extend(OrEllipseShape, mxEllipse); OrEllipseShape.prototype.paintVertexShape = function(c, x, y, w, h) { mxEllipse.prototype.paintVertexShape.apply(this, arguments); c.setShadow(false); c.begin(); c.moveTo(x, y + h / 2); c.lineTo(x + w, y + h / 2); c.end(); c.stroke(); c.begin(); c.moveTo(x + w / 2, y); c.lineTo(x + w / 2, y + h); c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['orEllipse'] = OrEllipseShape; // SumEllipseShape function SumEllipseShape() { mxEllipse.call(this); }; mxUtils.extend(SumEllipseShape, mxEllipse); SumEllipseShape.prototype.paintVertexShape = function(c, x, y, w, h) { mxEllipse.prototype.paintVertexShape.apply(this, arguments); var s2 = 0.145; c.setShadow(false); c.begin(); c.moveTo(x + w * s2, y + h * s2); c.lineTo(x + w * (1 - s2), y + h * (1 - s2)); c.end(); c.stroke(); c.begin(); c.moveTo(x + w * (1 - s2), y + h * s2); c.lineTo(x + w * s2, y + h * (1 - s2)); c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['sumEllipse'] = SumEllipseShape; // SortShape function SortShape() { mxRhombus.call(this); }; mxUtils.extend(SortShape, mxRhombus); SortShape.prototype.paintVertexShape = function(c, x, y, w, h) { mxRhombus.prototype.paintVertexShape.apply(this, arguments); c.setShadow(false); c.begin(); c.moveTo(x, y + h / 2); c.lineTo(x + w, y + h / 2); c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['sortShape'] = SortShape; // CollateShape function CollateShape() { mxEllipse.call(this); }; mxUtils.extend(CollateShape, mxEllipse); CollateShape.prototype.paintVertexShape = function(c, x, y, w, h) { c.begin(); c.moveTo(x, y); c.lineTo(x + w, y); c.lineTo(x + w / 2, y + h / 2); c.close(); c.fillAndStroke(); c.begin(); c.moveTo(x, y + h); c.lineTo(x + w, y + h); c.lineTo(x + w / 2, y + h / 2); c.close(); c.fillAndStroke(); }; mxCellRenderer.prototype.defaultShapes['collate'] = CollateShape; // DimensionShape function DimensionShape() { mxEllipse.call(this); }; mxUtils.extend(DimensionShape, mxEllipse); DimensionShape.prototype.paintVertexShape = function(c, x, y, w, h) { // Arrow size var al = 10; var cy = y + h - al / 2; c.begin(); c.moveTo(x, y); c.lineTo(x, y + h); c.moveTo(x, cy); c.lineTo(x + al, cy - al / 2); c.moveTo(x, cy); c.lineTo(x + al, cy + al / 2); c.moveTo(x, cy); c.lineTo(x + w, cy); // Opposite side c.moveTo(x + w, y); c.lineTo(x + w, y + h); c.moveTo(x + w, cy); c.lineTo(x + w - al, cy - al / 2); c.moveTo(x + w, cy); c.lineTo(x + w - al, cy + al / 2); c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['dimension'] = DimensionShape; // PartialRectangleShape function PartialRectangleShape() { mxEllipse.call(this); }; mxUtils.extend(PartialRectangleShape, mxEllipse); PartialRectangleShape.prototype.paintVertexShape = function(c, x, y, w, h) { if (!this.outline) { c.setStrokeColor(null); } mxRectangleShape.prototype.paintBackground.apply(this, arguments); if (this.style != null) { c.setStrokeColor(this.stroke); c.rect(x, y, w, h); c.fill(); c.begin(); c.moveTo(x, y); if (mxUtils.getValue(this.style, 'top', '1') == '1') { c.lineTo(x + w, y); } else { c.moveTo(x + w, y); } if (mxUtils.getValue(this.style, 'right', '1') == '1') { c.lineTo(x + w, y + h); } else { c.moveTo(x + w, y + h); } if (mxUtils.getValue(this.style, 'bottom', '1') == '1') { c.lineTo(x, y + h); } else { c.moveTo(x, y + h); } if (mxUtils.getValue(this.style, 'left', '1') == '1') { c.lineTo(x, y); } else { c.moveTo(x, y); } c.end(); c.stroke(); } }; mxCellRenderer.prototype.defaultShapes['partialRectangle'] = PartialRectangleShape; // LineEllipseShape function LineEllipseShape() { mxEllipse.call(this); }; mxUtils.extend(LineEllipseShape, mxEllipse); LineEllipseShape.prototype.paintVertexShape = function(c, x, y, w, h) { mxEllipse.prototype.paintVertexShape.apply(this, arguments); c.setShadow(false); c.begin(); if (mxUtils.getValue(this.style, 'line') == 'vertical') { c.moveTo(x + w / 2, y); c.lineTo(x + w / 2, y + h); } else { c.moveTo(x, y + h / 2); c.lineTo(x + w, y + h / 2); } c.end(); c.stroke(); }; mxCellRenderer.prototype.defaultShapes['lineEllipse'] = LineEllipseShape; // Delay function DelayShape() { mxActor.call(this); }; mxUtils.extend(DelayShape, mxActor); DelayShape.prototype.redrawPath = function(c, x, y, w, h) { var dx = Math.min(w, h / 2); c.moveTo(0, 0); c.lineTo(w - dx, 0); c.quadTo(w, 0, w, h / 2); c.quadTo(w, h, w - dx, h); c.lineTo(0, h); c.close(); c.end(); }; mxCellRenderer.prototype.defaultShapes['delay'] = DelayShape; // Cross Shape function CrossShape() { mxActor.call(this); }; mxUtils.extend(CrossShape, mxActor); CrossShape.prototype.size = 0.2; CrossShape.prototype.redrawPath = function(c, x, y, w, h) { var m = Math.min(h, w); var size = Math.max(0, Math.min(m, m * parseFloat(mxUtils.getValue(this.style, 'size', this.size)))); var t = (h - size) / 2; var b = t + size; var l = (w - size) / 2; var r = l + size; c.moveTo(0, t); c.lineTo(l, t); c.lineTo(l, 0); c.lineTo(r, 0); c.lineTo(r, t); c.lineTo(w, t); c.lineTo(w, b); c.lineTo(r, b); c.lineTo(r, h); c.lineTo(l, h); c.lineTo(l, b); c.lineTo(0, b); c.close(); c.end(); }; mxCellRenderer.prototype.defaultShapes['cross'] = CrossShape; // Display function DisplayShape() { mxActor.call(this); }; mxUtils.extend(DisplayShape, mxActor); DisplayShape.prototype.size = 0.25; DisplayShape.prototype.redrawPath = function(c, x, y, w, h) { var dx = Math.min(w, h / 2); var s = Math.min(w - dx, Math.max(0, parseFloat(mxUtils.getValue(this.style, 'size', this.size))) * w); c.moveTo(0, h / 2); c.lineTo(s, 0); c.lineTo(w - dx, 0); c.quadTo(w, 0, w, h / 2); c.quadTo(w, h, w - dx, h); c.lineTo(s, h); c.close(); c.end(); }; mxCellRenderer.prototype.defaultShapes['display'] = DisplayShape; // Registers and defines the custom marker mxMarker.addMarker('dash', function(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) { var nx = unitX * (size + sw + 1); var ny = unitY * (size + sw + 1); return function() { canvas.begin(); canvas.moveTo(pe.x - nx / 2 - ny / 2, pe.y - ny / 2 + nx / 2); canvas.lineTo(pe.x + ny / 2 - 3 * nx / 2, pe.y - 3 * ny / 2 - nx / 2); canvas.stroke(); }; }); // Handlers are only added if mxVertexHandler is defined (ie. not in embedded graph) if (typeof mxVertexHandler !== 'undefined') { function createHandle(state, keys, getPositionFn, setPositionFn, ignoreGrid) { var handle = new mxHandle(state, null, mxVertexHandler.prototype.secondaryHandleImage); handle.execute = function() { for (var i = 0; i < keys.length; i++) { this.copyStyle(keys[i]); } }; handle.getPosition = getPositionFn; handle.setPosition = setPositionFn; handle.ignoreGrid = (ignoreGrid != null) ? ignoreGrid : true; return handle; }; function createArcHandle(state, yOffset) { return createHandle(state, [mxConstants.STYLE_ARCSIZE], function(bounds) { var arcSize = Math.max(0, parseFloat(mxUtils.getValue(state.style, mxConstants.STYLE_ARCSIZE, mxConstants.RECTANGLE_ROUNDING_FACTOR * 100))) / 100; var tmp = (yOffset != null) ? yOffset : bounds.height / 8; return new mxPoint(bounds.x + bounds.width - Math.min(Math.max(bounds.width / 2, bounds.height / 2), Math.min(bounds.width, bounds.height) * arcSize), bounds.y + tmp); }, function(bounds, pt, me) { var f = Math.min(50, Math.max(0, (bounds.width - pt.x + bounds.x) * 100 / Math.min(bounds.width, bounds.height))); this.state.style[mxConstants.STYLE_ARCSIZE] = Math.round(f); }); } function createArcHandleFunction() { return function(state) { var handles = []; if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) { handles.push(createArcHandle(state)); } return handles; }; }; function createTrapezoidHandleFunction(max) { return function(state) { var handles = [createHandle(state, ['size'], function(bounds) { var size = Math.max(0, Math.min(max, parseFloat(mxUtils.getValue(this.state.style, 'size', TrapezoidShape.prototype.size)))); return new mxPoint(bounds.x + size * bounds.width * 0.75, bounds.y + bounds.height / 4); }, function(bounds, pt) { this.state.style['size'] = Math.max(0, Math.min(max, (pt.x - bounds.x) / (bounds.width * 0.75))); })]; if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) { handles.push(createArcHandle(state)); } return handles; }; }; function createDisplayHandleFunction(defaultValue, allowArcHandle, max) { max = (max != null) ? max : 1; return function(state) { var handles = [createHandle(state, ['size'], function(bounds) { var size = parseFloat(mxUtils.getValue(this.state.style, 'size', defaultValue)); return new mxPoint(bounds.x + size * bounds.width, bounds.getCenterY()); }, function(bounds, pt) { this.state.style['size'] = Math.max(0, Math.min(max, (pt.x - bounds.x) / bounds.width)); })]; if (allowArcHandle && mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) { handles.push(createArcHandle(state)); } return handles; }; }; function createCubeHandleFunction(factor, defaultValue, allowArcHandle) { return function(state) { var handles = [createHandle(state, ['size'], function(bounds) { var size = Math.max(0, Math.min(bounds.width, Math.min(bounds.height, parseFloat( mxUtils.getValue(this.state.style, 'size', defaultValue))))) * factor; return new mxPoint(bounds.x + size, bounds.y + size); }, function(bounds, pt) { this.state.style['size'] = Math.round(Math.max(0, Math.min(Math.min(bounds.width, pt.x - bounds.x), Math.min(bounds.height, pt.y - bounds.y))) / factor); })]; if (allowArcHandle && mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) { handles.push(createArcHandle(state)); } return handles; }; }; function createArrowHandleFunction(maxSize) { return function(state) { return [createHandle(state, ['arrowWidth', 'arrowSize'], function(bounds) { var aw = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'arrowWidth', SingleArrowShape.prototype.arrowWidth))); var as = Math.max(0, Math.min(maxSize, mxUtils.getValue(this.state.style, 'arrowSize', SingleArrowShape.prototype.arrowSize))); return new mxPoint(bounds.x + (1 - as) * bounds.width, bounds.y + (1 - aw) * bounds.height / 2); }, function(bounds, pt) { this.state.style['arrowWidth'] = Math.max(0, Math.min(1, Math.abs(bounds.y + bounds.height / 2 - pt.y) / bounds.height * 2)); this.state.style['arrowSize'] = Math.max(0, Math.min(maxSize, (bounds.x + bounds.width - pt.x) / (bounds.width))); })]; }; }; function createEdgeHandle(state, keys, start, getPosition, setPosition) { var pts = state.absolutePoints; var n = pts.length - 1; var tr = state.view.translate; var s = state.view.scale; var p0 = (start) ? pts[0] : pts[n]; var p1 = (start) ? pts[1] : pts[n - 1]; var dx = (start) ? p1.x - p0.x : p1.x - p0.x; var dy = (start) ? p1.y - p0.y : p1.y - p0.y; var dist = Math.sqrt(dx * dx + dy * dy); return createHandle(state, keys, function(bounds) { var pt = getPosition.call(this, dist, dx / dist, dy / dist, p0, p1); return new mxPoint(pt.x / s - tr.x, pt.y / s - tr.y); }, function(bounds, pt, me) { var dist = Math.sqrt(dx * dx + dy * dy); pt.x = (pt.x + tr.x) * s; pt.y = (pt.y + tr.y) * s; setPosition.call(this, dist, dx / dist, dy / dist, p0, p1, pt, me); }); }; function createEdgeWidthHandle(state, start, spacing) { return createEdgeHandle(state, ['width'], start, function(dist, nx, ny, p0, p1) { var w = state.shape.getEdgeWidth() * state.view.scale + spacing; return new mxPoint(p0.x + nx * dist / 4 + ny * w / 2, p0.y + ny * dist / 4 - nx * w / 2); }, function(dist, nx, ny, p0, p1, pt) { var w = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, p1.x, p1.y, pt.x, pt.y)); state.style['width'] = Math.round(w * 2) / state.view.scale - spacing; }); }; function ptLineDistance(x1, y1, x2, y2, x0, y0) { return Math.abs((y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1) / Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1)); } var handleFactory = { 'link': function(state) { var spacing = 10; return [createEdgeWidthHandle(state, true, spacing), createEdgeWidthHandle(state, false, spacing)]; }, 'flexArrow': function(state) { // Do not use state.shape.startSize/endSize since it is cached var tol = state.view.graph.gridSize / state.view.scale; var handles = []; if (mxUtils.getValue(state.style, mxConstants.STYLE_STARTARROW, mxConstants.NONE) != mxConstants.NONE) { handles.push(createEdgeHandle(state, ['width', mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE], true, function(dist, nx, ny, p0, p1) { var w = (state.shape.getEdgeWidth() - state.shape.strokewidth) * state.view.scale; var l = mxUtils.getNumber(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.ARROW_SIZE / 5) * 3 * state.view.scale; return new mxPoint(p0.x + nx * (l + state.shape.strokewidth * state.view.scale) + ny * w / 2, p0.y + ny * (l + state.shape.strokewidth * state.view.scale) - nx * w / 2); }, function(dist, nx, ny, p0, p1, pt, me) { var w = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, p1.x, p1.y, pt.x, pt.y)); var l = mxUtils.ptLineDist(p0.x, p0.y, p0.x + ny, p0.y - nx, pt.x, pt.y); state.style[mxConstants.STYLE_STARTSIZE] = Math.round((l - state.shape.strokewidth) * 100 / 3) / 100 / state.view.scale; state.style['width'] = Math.round(w * 2) / state.view.scale; // Applies to opposite side if (mxEvent.isControlDown(me.getEvent())) { state.style[mxConstants.STYLE_ENDSIZE] = state.style[mxConstants.STYLE_STARTSIZE]; } // Snaps to end geometry if (!mxEvent.isAltDown(me.getEvent())) { if (Math.abs(parseFloat(state.style[mxConstants.STYLE_STARTSIZE]) - parseFloat(state.style[mxConstants.STYLE_ENDSIZE])) < tol / 6) { state.style[mxConstants.STYLE_STARTSIZE] = state.style[mxConstants.STYLE_ENDSIZE]; } } })); handles.push(createEdgeHandle(state, ['startWidth', 'endWidth', mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE], true, function(dist, nx, ny, p0, p1) { var w = (state.shape.getStartArrowWidth() - state.shape.strokewidth) * state.view.scale; var l = mxUtils.getNumber(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.ARROW_SIZE / 5) * 3 * state.view.scale; return new mxPoint(p0.x + nx * (l + state.shape.strokewidth * state.view.scale) + ny * w / 2, p0.y + ny * (l + state.shape.strokewidth * state.view.scale) - nx * w / 2); }, function(dist, nx, ny, p0, p1, pt, me) { var w = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, p1.x, p1.y, pt.x, pt.y)); var l = mxUtils.ptLineDist(p0.x, p0.y, p0.x + ny, p0.y - nx, pt.x, pt.y); state.style[mxConstants.STYLE_STARTSIZE] = Math.round((l - state.shape.strokewidth) * 100 / 3) / 100 / state.view.scale; state.style['startWidth'] = Math.max(0, Math.round(w * 2) - state.shape.getEdgeWidth()) / state.view.scale; // Applies to opposite side if (mxEvent.isControlDown(me.getEvent())) { state.style[mxConstants.STYLE_ENDSIZE] = state.style[mxConstants.STYLE_STARTSIZE]; state.style['endWidth'] = state.style['startWidth']; } // Snaps to endWidth if (!mxEvent.isAltDown(me.getEvent())) { if (Math.abs(parseFloat(state.style[mxConstants.STYLE_STARTSIZE]) - parseFloat(state.style[mxConstants.STYLE_ENDSIZE])) < tol / 6) { state.style[mxConstants.STYLE_STARTSIZE] = state.style[mxConstants.STYLE_ENDSIZE]; } if (Math.abs(parseFloat(state.style['startWidth']) - parseFloat(state.style['endWidth'])) < tol) { state.style['startWidth'] = state.style['endWidth']; } } })); } if (mxUtils.getValue(state.style, mxConstants.STYLE_ENDARROW, mxConstants.NONE) != mxConstants.NONE) { handles.push(createEdgeHandle(state, ['width', mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE], false, function(dist, nx, ny, p0, p1) { var w = (state.shape.getEdgeWidth() - state.shape.strokewidth) * state.view.scale; var l = mxUtils.getNumber(state.style, mxConstants.STYLE_ENDSIZE, mxConstants.ARROW_SIZE / 5) * 3 * state.view.scale; return new mxPoint(p0.x + nx * (l + state.shape.strokewidth * state.view.scale) - ny * w / 2, p0.y + ny * (l + state.shape.strokewidth * state.view.scale) + nx * w / 2); }, function(dist, nx, ny, p0, p1, pt, me) { var w = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, p1.x, p1.y, pt.x, pt.y)); var l = mxUtils.ptLineDist(p0.x, p0.y, p0.x + ny, p0.y - nx, pt.x, pt.y); state.style[mxConstants.STYLE_ENDSIZE] = Math.round((l - state.shape.strokewidth) * 100 / 3) / 100 / state.view.scale; state.style['width'] = Math.round(w * 2) / state.view.scale; // Applies to opposite side if (mxEvent.isControlDown(me.getEvent())) { state.style[mxConstants.STYLE_STARTSIZE] = state.style[mxConstants.STYLE_ENDSIZE]; } // Snaps to start geometry if (!mxEvent.isAltDown(me.getEvent())) { if (Math.abs(parseFloat(state.style[mxConstants.STYLE_ENDSIZE]) - parseFloat(state.style[mxConstants.STYLE_STARTSIZE])) < tol / 6) { state.style[mxConstants.STYLE_ENDSIZE] = state.style[mxConstants.STYLE_STARTSIZE]; } } })); handles.push(createEdgeHandle(state, ['startWidth', 'endWidth', mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE], false, function(dist, nx, ny, p0, p1) { var w = (state.shape.getEndArrowWidth() - state.shape.strokewidth) * state.view.scale; var l = mxUtils.getNumber(state.style, mxConstants.STYLE_ENDSIZE, mxConstants.ARROW_SIZE / 5) * 3 * state.view.scale; return new mxPoint(p0.x + nx * (l + state.shape.strokewidth * state.view.scale) - ny * w / 2, p0.y + ny * (l + state.shape.strokewidth * state.view.scale) + nx * w / 2); }, function(dist, nx, ny, p0, p1, pt, me) { var w = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, p1.x, p1.y, pt.x, pt.y)); var l = mxUtils.ptLineDist(p0.x, p0.y, p0.x + ny, p0.y - nx, pt.x, pt.y); state.style[mxConstants.STYLE_ENDSIZE] = Math.round((l - state.shape.strokewidth) * 100 / 3) / 100 / state.view.scale; state.style['endWidth'] = Math.max(0, Math.round(w * 2) - state.shape.getEdgeWidth()) / state.view.scale; // Applies to opposite side if (mxEvent.isControlDown(me.getEvent())) { state.style[mxConstants.STYLE_STARTSIZE] = state.style[mxConstants.STYLE_ENDSIZE]; state.style['startWidth'] = state.style['endWidth']; } // Snaps to start geometry if (!mxEvent.isAltDown(me.getEvent())) { if (Math.abs(parseFloat(state.style[mxConstants.STYLE_ENDSIZE]) - parseFloat(state.style[mxConstants.STYLE_STARTSIZE])) < tol / 6) { state.style[mxConstants.STYLE_ENDSIZE] = state.style[mxConstants.STYLE_STARTSIZE]; } if (Math.abs(parseFloat(state.style['endWidth']) - parseFloat(state.style['startWidth'])) < tol) { state.style['endWidth'] = state.style['startWidth']; } } })); } return handles; }, 'swimlane': function(state) { var handles = [createHandle(state, [mxConstants.STYLE_STARTSIZE], function(bounds) { var size = parseFloat(mxUtils.getValue(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE)); if (mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, 1) == 1) { return new mxPoint(bounds.getCenterX(), bounds.y + Math.max(0, Math.min(bounds.height, size))); } else { return new mxPoint(bounds.x + Math.max(0, Math.min(bounds.width, size)), bounds.getCenterY()); } }, function(bounds, pt) { state.style[mxConstants.STYLE_STARTSIZE] = (mxUtils.getValue(this.state.style, mxConstants.STYLE_HORIZONTAL, 1) == 1) ? Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y))) : Math.round(Math.max(0, Math.min(bounds.width, pt.x - bounds.x))); })]; if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED)) { var size = parseFloat(mxUtils.getValue(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE)); handles.push(createArcHandle(state, size / 2)); } return handles; }, 'label': createArcHandleFunction(), 'ext': createArcHandleFunction(), 'rectangle': createArcHandleFunction(), 'triangle': createArcHandleFunction(), 'rhombus': createArcHandleFunction(), 'hexagon': createArcHandleFunction(), 'umlLifeline': function(state) { return [createHandle(state, ['size'], function(bounds) { var size = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'size', UmlLifeline.prototype.size)))); return new mxPoint(bounds.getCenterX(), bounds.y + size); }, function(bounds, pt) { this.state.style['size'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y))); }, false)]; }, 'umlFrame': function(state) { var handles = [createHandle(state, ['width', 'height'], function(bounds) { var w0 = Math.max(UmlFrame.prototype.corner, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'width', UmlFrame.prototype.width))); var h0 = Math.max(UmlFrame.prototype.corner * 1.5, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'height', UmlFrame.prototype.height))); return new mxPoint(bounds.x + w0, bounds.y + h0); }, function(bounds, pt) { this.state.style['width'] = Math.round(Math.max(UmlFrame.prototype.corner, Math.min(bounds.width, pt.x - bounds.x))); this.state.style['height'] = Math.round(Math.max(UmlFrame.prototype.corner * 1.5, Math.min(bounds.height, pt.y - bounds.y))); }, false)]; if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) { handles.push(createArcHandle(state)); } return handles; }, 'process': function(state) { var handles = [createHandle(state, ['size'], function(bounds) { var size = Math.max(0, Math.min(0.5, parseFloat(mxUtils.getValue(this.state.style, 'size', ProcessShape.prototype.size)))); return new mxPoint(bounds.x + bounds.width * size, bounds.y + bounds.height / 4); }, function(bounds, pt) { this.state.style['size'] = Math.max(0, Math.min(0.5, (pt.x - bounds.x) / bounds.width)); })]; if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) { handles.push(createArcHandle(state)); } return handles; }, 'cross': function(state) { return [createHandle(state, ['size'], function(bounds) { var m = Math.min(bounds.width, bounds.height); var size = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'size', CrossShape.prototype.size))) * m / 2; return new mxPoint(bounds.getCenterX() - size, bounds.getCenterY() - size); }, function(bounds, pt) { var m = Math.min(bounds.width, bounds.height); this.state.style['size'] = Math.max(0, Math.min(1, Math.min((Math.max(0, bounds.getCenterY() - pt.y) / m) * 2, (Math.max(0, bounds.getCenterX() - pt.x) / m) * 2))); })]; }, 'note': function(state) { return [createHandle(state, ['size'], function(bounds) { var size = Math.max(0, Math.min(bounds.width, Math.min(bounds.height, parseFloat( mxUtils.getValue(this.state.style, 'size', NoteShape.prototype.size))))); return new mxPoint(bounds.x + bounds.width - size, bounds.y + size); }, function(bounds, pt) { this.state.style['size'] = Math.round(Math.max(0, Math.min(Math.min(bounds.width, bounds.x + bounds.width - pt.x), Math.min(bounds.height, pt.y - bounds.y)))); })]; }, 'manualInput': function(state) { var handles = [createHandle(state, ['size'], function(bounds) { var size = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'size', ManualInputShape.prototype.size))); return new mxPoint(bounds.x + bounds.width / 4, bounds.y + size * 3 / 4); }, function(bounds, pt) { this.state.style['size'] = Math.round(Math.max(0, Math.min(bounds.height, (pt.y - bounds.y) * 4 / 3))); })]; if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) { handles.push(createArcHandle(state)); } return handles; }, 'dataStorage': function(state) { return [createHandle(state, ['size'], function(bounds) { var size = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'size', DataStorageShape.prototype.size)))); return new mxPoint(bounds.x + (1 - size) * bounds.width, bounds.getCenterY()); }, function(bounds, pt) { this.state.style['size'] = Math.max(0, Math.min(1, (bounds.x + bounds.width - pt.x) / bounds.width)); })]; }, 'internalStorage': function(state) { var handles = [createHandle(state, ['dx', 'dy'], function(bounds) { var dx = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'dx', InternalStorageShape.prototype.dx))); var dy = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'dy', InternalStorageShape.prototype.dy))); return new mxPoint(bounds.x + dx, bounds.y + dy); }, function(bounds, pt) { this.state.style['dx'] = Math.round(Math.max(0, Math.min(bounds.width, pt.x - bounds.x))); this.state.style['dy'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y))); })]; if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) { handles.push(createArcHandle(state)); } return handles; }, 'corner': function(state) { return [createHandle(state, ['dx', 'dy'], function(bounds) { var dx = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'dx', CornerShape.prototype.dx))); var dy = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'dy', CornerShape.prototype.dy))); return new mxPoint(bounds.x + dx, bounds.y + dy); }, function(bounds, pt) { this.state.style['dx'] = Math.round(Math.max(0, Math.min(bounds.width, pt.x - bounds.x))); this.state.style['dy'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y))); })]; }, 'tee': function(state) { return [createHandle(state, ['dx', 'dy'], function(bounds) { var dx = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'dx', TeeShape.prototype.dx))); var dy = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'dy', TeeShape.prototype.dy))); return new mxPoint(bounds.x + (bounds.width + dx) / 2, bounds.y + dy); }, function(bounds, pt) { this.state.style['dx'] = Math.round(Math.max(0, Math.min(bounds.width / 2, (pt.x - bounds.x - bounds.width / 2)) * 2)); this.state.style['dy'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y))); })]; }, 'singleArrow': createArrowHandleFunction(1), 'doubleArrow': createArrowHandleFunction(0.5), 'folder': function(state) { return [createHandle(state, ['tabWidth', 'tabHeight'], function(bounds) { var tw = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'tabWidth', FolderShape.prototype.tabWidth))); var th = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'tabHeight', FolderShape.prototype.tabHeight))); if (mxUtils.getValue(this.state.style, 'tabPosition', FolderShape.prototype.tabPosition) == mxConstants.ALIGN_RIGHT) { tw = bounds.width - tw; } return new mxPoint(bounds.x + tw, bounds.y + th); }, function(bounds, pt) { var tw = Math.max(0, Math.min(bounds.width, pt.x - bounds.x)); if (mxUtils.getValue(this.state.style, 'tabPosition', FolderShape.prototype.tabPosition) == mxConstants.ALIGN_RIGHT) { tw = bounds.width - tw; } this.state.style['tabWidth'] = Math.round(tw); this.state.style['tabHeight'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y))); })]; }, 'document': function(state) { return [createHandle(state, ['size'], function(bounds) { var size = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'size', DocumentShape.prototype.size)))); return new mxPoint(bounds.x + 3 * bounds.width / 4, bounds.y + (1 - size) * bounds.height); }, function(bounds, pt) { this.state.style['size'] = Math.max(0, Math.min(1, (bounds.y + bounds.height - pt.y) / bounds.height)); })]; }, 'tape': function(state) { return [createHandle(state, ['size'], function(bounds) { var size = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'size', TapeShape.prototype.size)))); return new mxPoint(bounds.getCenterX(), bounds.y + size * bounds.height / 2); }, function(bounds, pt) { this.state.style['size'] = Math.max(0, Math.min(1, ((pt.y - bounds.y) / bounds.height) * 2)); })]; }, 'offPageConnector': function(state) { return [createHandle(state, ['size'], function(bounds) { var size = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'size', OffPageConnectorShape.prototype.size)))); return new mxPoint(bounds.getCenterX(), bounds.y + (1 - size) * bounds.height); }, function(bounds, pt) { this.state.style['size'] = Math.max(0, Math.min(1, (bounds.y + bounds.height - pt.y) / bounds.height)); })]; }, 'step': createDisplayHandleFunction(StepShape.prototype.size, true), 'hexagon': createDisplayHandleFunction(HexagonShape.prototype.size, true, 0.5), 'curlyBracket': createDisplayHandleFunction(CurlyBracketShape.prototype.size, false), 'display': createDisplayHandleFunction(DisplayShape.prototype.size, false), 'cube': createCubeHandleFunction(1, CubeShape.prototype.size, false), 'card': createCubeHandleFunction(0.5, CardShape.prototype.size, true), 'loopLimit': createCubeHandleFunction(0.5, LoopLimitShape.prototype.size, true), 'trapezoid': createTrapezoidHandleFunction(0.5), 'parallelogram': createTrapezoidHandleFunction(1) }; mxVertexHandler.prototype.createCustomHandles = function() { // Not rotatable means locked if (this.graph.isCellRotatable(this.state.cell)) // LATER: Make locked state independent of rotatable flag, fix toggle if default is false //if (this.graph.isCellResizable(this.state.cell) || this.graph.isCellMovable(this.state.cell)) { var fn = handleFactory[this.state.style['shape']]; if (fn != null) { return fn(this.state); } } return null; }; mxEdgeHandler.prototype.createCustomHandles = function() { var fn = handleFactory[this.state.style['shape']]; if (fn != null) { return fn(this.state); } } } mxRectangleShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0), true), new mxConnectionConstraint(new mxPoint(0.5, 0), true), new mxConnectionConstraint(new mxPoint(0.75, 0), true), new mxConnectionConstraint(new mxPoint(0, 0.25), true), new mxConnectionConstraint(new mxPoint(0, 0.5), true), new mxConnectionConstraint(new mxPoint(0, 0.75), true), new mxConnectionConstraint(new mxPoint(1, 0.25), true), new mxConnectionConstraint(new mxPoint(1, 0.5), true), new mxConnectionConstraint(new mxPoint(1, 0.75), true), new mxConnectionConstraint(new mxPoint(0.25, 1), true), new mxConnectionConstraint(new mxPoint(0.5, 1), true), new mxConnectionConstraint(new mxPoint(0.75, 1), true)]; mxEllipse.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0), true), new mxConnectionConstraint(new mxPoint(1, 0), true), new mxConnectionConstraint(new mxPoint(0, 1), true), new mxConnectionConstraint(new mxPoint(1, 1), true), new mxConnectionConstraint(new mxPoint(0.5, 0), true), new mxConnectionConstraint(new mxPoint(0.5, 1), true), new mxConnectionConstraint(new mxPoint(0, 0.5), true), new mxConnectionConstraint(new mxPoint(1, 0.5))]; mxLabel.prototype.constraints = mxRectangleShape.prototype.constraints; mxImageShape.prototype.constraints = mxRectangleShape.prototype.constraints; mxSwimlane.prototype.constraints = mxRectangleShape.prototype.constraints; PlusShape.prototype.constraints = mxRectangleShape.prototype.constraints; NoteShape.prototype.constraints = mxRectangleShape.prototype.constraints; CardShape.prototype.constraints = mxRectangleShape.prototype.constraints; CubeShape.prototype.constraints = mxRectangleShape.prototype.constraints; FolderShape.prototype.constraints = mxRectangleShape.prototype.constraints; InternalStorageShape.prototype.constraints = mxRectangleShape.prototype.constraints; DataStorageShape.prototype.constraints = mxRectangleShape.prototype.constraints; TapeDataShape.prototype.constraints = mxEllipse.prototype.constraints; OrEllipseShape.prototype.constraints = mxEllipse.prototype.constraints; SumEllipseShape.prototype.constraints = mxEllipse.prototype.constraints; LineEllipseShape.prototype.constraints = mxEllipse.prototype.constraints; ManualInputShape.prototype.constraints = mxRectangleShape.prototype.constraints; DelayShape.prototype.constraints = mxRectangleShape.prototype.constraints; DisplayShape.prototype.constraints = mxRectangleShape.prototype.constraints; LoopLimitShape.prototype.constraints = mxRectangleShape.prototype.constraints; OffPageConnectorShape.prototype.constraints = mxRectangleShape.prototype.constraints; mxCylinder.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.15, 0.05), false), new mxConnectionConstraint(new mxPoint(0.5, 0), true), new mxConnectionConstraint(new mxPoint(0.85, 0.05), false), new mxConnectionConstraint(new mxPoint(0, 0.3), true), new mxConnectionConstraint(new mxPoint(0, 0.5), true), new mxConnectionConstraint(new mxPoint(0, 0.7), true), new mxConnectionConstraint(new mxPoint(1, 0.3), true), new mxConnectionConstraint(new mxPoint(1, 0.5), true), new mxConnectionConstraint(new mxPoint(1, 0.7), true), new mxConnectionConstraint(new mxPoint(0.15, 0.95), false), new mxConnectionConstraint(new mxPoint(0.5, 1), true), new mxConnectionConstraint(new mxPoint(0.85, 0.95), false)]; UmlActorShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0.1), false), new mxConnectionConstraint(new mxPoint(0.5, 0), false), new mxConnectionConstraint(new mxPoint(0.75, 0.1), false), new mxConnectionConstraint(new mxPoint(0, 1/3), false), new mxConnectionConstraint(new mxPoint(0, 1), false), new mxConnectionConstraint(new mxPoint(1, 1/3), false), new mxConnectionConstraint(new mxPoint(1, 1), false), new mxConnectionConstraint(new mxPoint(0.5, 0.5), false)]; ComponentShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0), true), new mxConnectionConstraint(new mxPoint(0.5, 0), true), new mxConnectionConstraint(new mxPoint(0.75, 0), true), new mxConnectionConstraint(new mxPoint(0, 0.3), true), new mxConnectionConstraint(new mxPoint(0, 0.7), true), new mxConnectionConstraint(new mxPoint(1, 0.25), true), new mxConnectionConstraint(new mxPoint(1, 0.5), true), new mxConnectionConstraint(new mxPoint(1, 0.75), true), new mxConnectionConstraint(new mxPoint(0.25, 1), true), new mxConnectionConstraint(new mxPoint(0.5, 1), true), new mxConnectionConstraint(new mxPoint(0.75, 1), true)]; mxActor.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.5, 0), true), new mxConnectionConstraint(new mxPoint(0.25, 0.2), false), new mxConnectionConstraint(new mxPoint(0.1, 0.5), false), new mxConnectionConstraint(new mxPoint(0, 0.75), true), new mxConnectionConstraint(new mxPoint(0.75, 0.25), false), new mxConnectionConstraint(new mxPoint(0.9, 0.5), false), new mxConnectionConstraint(new mxPoint(1, 0.75), true), new mxConnectionConstraint(new mxPoint(0.25, 1), true), new mxConnectionConstraint(new mxPoint(0.5, 1), true), new mxConnectionConstraint(new mxPoint(0.75, 1), true)]; SwitchShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0), false), new mxConnectionConstraint(new mxPoint(0.5, 0.25), false), new mxConnectionConstraint(new mxPoint(1, 0), false), new mxConnectionConstraint(new mxPoint(0.25, 0.5), false), new mxConnectionConstraint(new mxPoint(0.75, 0.5), false), new mxConnectionConstraint(new mxPoint(0, 1), false), new mxConnectionConstraint(new mxPoint(0.5, 0.75), false), new mxConnectionConstraint(new mxPoint(1, 1), false)]; TapeShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.35), false), new mxConnectionConstraint(new mxPoint(0, 0.5), false), new mxConnectionConstraint(new mxPoint(0, 0.65), false), new mxConnectionConstraint(new mxPoint(1, 0.35), false), new mxConnectionConstraint(new mxPoint(1, 0.5), false), new mxConnectionConstraint(new mxPoint(1, 0.65), false), new mxConnectionConstraint(new mxPoint(0.25, 1), false), new mxConnectionConstraint(new mxPoint(0.75, 0), false)]; // TODO: Relative ports StepShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0), true), new mxConnectionConstraint(new mxPoint(0.5, 0), true), new mxConnectionConstraint(new mxPoint(0.75, 0), true), new mxConnectionConstraint(new mxPoint(0.25, 1), true), new mxConnectionConstraint(new mxPoint(0.5, 1), true), new mxConnectionConstraint(new mxPoint(0.75, 1), true), new mxConnectionConstraint(new mxPoint(0.1, 0.25), false), new mxConnectionConstraint(new mxPoint(0.2, 0.5), false), new mxConnectionConstraint(new mxPoint(0.1, 0.75), false), new mxConnectionConstraint(new mxPoint(0.9, 0.25), false), new mxConnectionConstraint(new mxPoint(1, 0.5), false), new mxConnectionConstraint(new mxPoint(0.9, 0.75), false)]; mxLine.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.5), false), new mxConnectionConstraint(new mxPoint(0.25, 0.5), false), new mxConnectionConstraint(new mxPoint(0.75, 0.5), false), new mxConnectionConstraint(new mxPoint(1, 0.5), false)]; LollipopShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.5, 0), false), new mxConnectionConstraint(new mxPoint(0.5, 1), false)]; mxDoubleEllipse.prototype.constraints = mxEllipse.prototype.constraints; mxRhombus.prototype.constraints = mxEllipse.prototype.constraints; mxTriangle.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.25), true), new mxConnectionConstraint(new mxPoint(0, 0.5), true), new mxConnectionConstraint(new mxPoint(0, 0.75), true), new mxConnectionConstraint(new mxPoint(0.5, 0), true), new mxConnectionConstraint(new mxPoint(0.5, 1), true), new mxConnectionConstraint(new mxPoint(1, 0.5), true)]; mxHexagon.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.375, 0), true), new mxConnectionConstraint(new mxPoint(0.5, 0), true), new mxConnectionConstraint(new mxPoint(0.625, 0), true), new mxConnectionConstraint(new mxPoint(0.125, 0.25), false), new mxConnectionConstraint(new mxPoint(0, 0.5), true), new mxConnectionConstraint(new mxPoint(0.125, 0.75), false), new mxConnectionConstraint(new mxPoint(0.875, 0.25), false), new mxConnectionConstraint(new mxPoint(0, 0.5), true), new mxConnectionConstraint(new mxPoint(1, 0.5), true), new mxConnectionConstraint(new mxPoint(0.875, 0.75), false), new mxConnectionConstraint(new mxPoint(0.375, 1), true), new mxConnectionConstraint(new mxPoint(0.5, 1), true), new mxConnectionConstraint(new mxPoint(0.625, 1), true)]; mxCloud.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0.25), false), new mxConnectionConstraint(new mxPoint(0.4, 0.1), false), new mxConnectionConstraint(new mxPoint(0.16, 0.55), false), new mxConnectionConstraint(new mxPoint(0.07, 0.4), false), new mxConnectionConstraint(new mxPoint(0.31, 0.8), false), new mxConnectionConstraint(new mxPoint(0.13, 0.77), false), new mxConnectionConstraint(new mxPoint(0.8, 0.8), false), new mxConnectionConstraint(new mxPoint(0.55, 0.95), false), new mxConnectionConstraint(new mxPoint(0.875, 0.5), false), new mxConnectionConstraint(new mxPoint(0.96, 0.7), false), new mxConnectionConstraint(new mxPoint(0.625, 0.2), false), new mxConnectionConstraint(new mxPoint(0.88, 0.25), false)]; ParallelogramShape.prototype.constraints = mxRectangleShape.prototype.constraints; TrapezoidShape.prototype.constraints = mxRectangleShape.prototype.constraints; DocumentShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0), true), new mxConnectionConstraint(new mxPoint(0.5, 0), true), new mxConnectionConstraint(new mxPoint(0.75, 0), true), new mxConnectionConstraint(new mxPoint(0, 0.25), true), new mxConnectionConstraint(new mxPoint(0, 0.5), true), new mxConnectionConstraint(new mxPoint(0, 0.75), true), new mxConnectionConstraint(new mxPoint(1, 0.25), true), new mxConnectionConstraint(new mxPoint(1, 0.5), true), new mxConnectionConstraint(new mxPoint(1, 0.75), true)]; mxArrow.prototype.constraints = null; TeeShape.prototype.constraints = null; CornerShape.prototype.constraints = null; SingleArrowShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.5), false), new mxConnectionConstraint(new mxPoint(1, 0.5), false)]; DoubleArrowShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.5), false), new mxConnectionConstraint(new mxPoint(1, 0.5), false)]; CrossShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.5), false), new mxConnectionConstraint(new mxPoint(1, 0.5), false), new mxConnectionConstraint(new mxPoint(0.5, 0), false), new mxConnectionConstraint(new mxPoint(0.5, 1), false)]; UmlLifeline.prototype.constraints = null; OrShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.25), false), new mxConnectionConstraint(new mxPoint(0, 0.5), false), new mxConnectionConstraint(new mxPoint(0, 0.75), false), new mxConnectionConstraint(new mxPoint(1, 0.5), false), new mxConnectionConstraint(new mxPoint(0.7, 0.1), false), new mxConnectionConstraint(new mxPoint(0.7, 0.9), false)]; XorShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.175, 0.25), false), new mxConnectionConstraint(new mxPoint(0.25, 0.5), false), new mxConnectionConstraint(new mxPoint(0.175, 0.75), false), new mxConnectionConstraint(new mxPoint(1, 0.5), false), new mxConnectionConstraint(new mxPoint(0.7, 0.1), false), new mxConnectionConstraint(new mxPoint(0.7, 0.9), false)]; })();