drawio-offline
Version:
diagrams.net desktop
1,916 lines (1,624 loc) • 229 kB
JavaScript
/**
* Copyright (c) 2006-2015, JGraph Ltd
*/
/**
* Registers shapes.
*/
(function()
{
// LATER: Use this to implement striping
function paintTableBackground(state, c, x, y, w, h, r)
{
if (state != null)
{
var graph = state.view.graph;
var start = graph.getActualStartSize(state.cell);
var rows = graph.model.getChildCells(state.cell, true);
if (rows.length > 0)
{
var events = false;
if (this.style != null)
{
events = mxUtils.getValue(this.style, mxConstants.STYLE_POINTER_EVENTS, '1') == '1';
}
if (!events)
{
c.pointerEvents = false;
}
var evenRowColor = mxUtils.getValue(state.style,
'evenRowColor', mxConstants.NONE);
var oddRowColor = mxUtils.getValue(state.style,
'oddRowColor', mxConstants.NONE);
var evenColColor = mxUtils.getValue(state.style,
'evenColumnColor', mxConstants.NONE);
var oddColColor = mxUtils.getValue(state.style,
'oddColumnColor', mxConstants.NONE);
var cols = graph.model.getChildCells(rows[0], true);
// Paints column backgrounds
for (var i = 0; i < cols.length; i++)
{
var clr = (mxUtils.mod(i, 2) == 1) ? evenColColor : oddColColor;
var geo = graph.getCellGeometry(cols[i]);
if (geo != null && clr != mxConstants.NONE)
{
c.setFillColor(clr);
c.begin();
c.moveTo(x + geo.x, y + start.y);
if (r > 0 && i == cols.length - 1)
{
c.lineTo(x + geo.x + geo.width - r, y);
c.quadTo(x + geo.x + geo.width, y, x + geo.x + geo.width, y + r);
c.lineTo(x + geo.x + geo.width, y + h - r);
c.quadTo(x + geo.x + geo.width, y + h, x + geo.x + geo.width - r, y + h);
}
else
{
c.lineTo(x + geo.x + geo.width, y + start.y);
c.lineTo(x + geo.x + geo.width, y + h - start.height);
}
c.lineTo(x + geo.x, y + h);
c.close();
c.fill();
}
}
// Paints row backgrounds
for (var i = 0; i < rows.length; i++)
{
var clr = (mxUtils.mod(i, 2) == 1) ? evenRowColor : oddRowColor;
var geo = graph.getCellGeometry(rows[i]);
if (geo != null && clr != mxConstants.NONE)
{
var b = (i == rows.length - 1) ? y + h : y + geo.y + geo.height;
c.setFillColor(clr);
c.begin();
c.moveTo(x + start.x, y + geo.y);
c.lineTo(x + w - start.width, y + geo.y);
if (r > 0 && i == rows.length - 1)
{
c.lineTo(x + w, b - r);
c.quadTo(x + w, b, x + w - r, b);
c.lineTo(x + r, b);
c.quadTo(x, b, x, b - r);
}
else
{
c.lineTo(x + w - start.width, b);
c.lineTo(x + start.x, b);
}
c.close();
c.fill();
}
}
}
}
};
// Table Shape
function TableShape()
{
mxSwimlane.call(this);
};
mxUtils.extend(TableShape, mxSwimlane);
TableShape.prototype.getLabelBounds = function(rect)
{
var start = this.getTitleSize();
if (start == 0)
{
return mxShape.prototype.getLabelBounds.apply(this, arguments);
}
else
{
return mxSwimlane.prototype.getLabelBounds.apply(this, arguments);
}
};
TableShape.prototype.paintVertexShape = function(c, x, y, w, h)
{
// LATER: Split background to add striping
//paintTableBackground(this.state, c, x, y, w, h);
var start = this.getTitleSize();
if (start == 0)
{
mxRectangleShape.prototype.paintBackground.apply(this, arguments);
}
else
{
mxSwimlane.prototype.paintVertexShape.apply(this, arguments);
c.translate(-x, -y);
}
this.paintForeground(c, x, y, w, h);
};
TableShape.prototype.paintForeground = function(c, x, y, w, h)
{
if (this.state != null)
{
var flipH = this.flipH;
var flipV = this.flipV;
if (this.direction == mxConstants.DIRECTION_NORTH || this.direction == mxConstants.DIRECTION_SOUTH)
{
var tmp = flipH;
flipH = flipV;
flipV = tmp;
}
// Negative transform to avoid save/restore
c.rotate(-this.getShapeRotation(), flipH, flipV, x + w / 2, y + h / 2);
s = this.scale;
x = this.bounds.x / s;
y = this.bounds.y / s;
w = this.bounds.width / s;
h = this.bounds.height / s;
this.paintTableForeground(c, x, y, w, h);
}
};
TableShape.prototype.paintTableForeground = function(c, x, y, w, h)
{
var graph = this.state.view.graph;
var start = graph.getActualStartSize(this.state.cell);
var rows = graph.model.getChildCells(this.state.cell, true);
if (rows.length > 0)
{
var rowLines = mxUtils.getValue(this.state.style,
'rowLines', '1') != '0';
var columnLines = mxUtils.getValue(this.state.style,
'columnLines', '1') != '0';
// Paints row lines
if (rowLines)
{
for (var i = 1; i < rows.length; i++)
{
var geo = graph.getCellGeometry(rows[i]);
if (geo != null)
{
c.begin();
c.moveTo(x + start.x, y + geo.y);
c.lineTo(x + w - start.width, y + geo.y);
c.end();
c.stroke();
}
}
}
if (columnLines)
{
var cols = graph.model.getChildCells(rows[0], true);
// Paints column lines
for (var i = 1; i < cols.length; i++)
{
var geo = graph.getCellGeometry(cols[i]);
if (geo != null)
{
c.begin();
c.moveTo(x + geo.x + start.x, y + start.y);
c.lineTo(x + geo.x + start.x, y + h - start.height);
c.end();
c.stroke();
}
}
}
}
};
mxCellRenderer.registerShape('table', TableShape);
// Cube Shape, supports size style
function CubeShape()
{
mxCylinder.call(this);
};
mxUtils.extend(CubeShape, mxCylinder);
CubeShape.prototype.size = 20;
CubeShape.prototype.darkOpacity = 0;
CubeShape.prototype.darkOpacity2 = 0;
CubeShape.prototype.paintVertexShape = 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 op = Math.max(-1, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'darkOpacity', this.darkOpacity))));
var op2 = Math.max(-1, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'darkOpacity2', this.darkOpacity2))));
c.translate(x, y);
c.begin();
c.moveTo(0, 0);
c.lineTo(w - s, 0);
c.lineTo(w, s);
c.lineTo(w, h);
c.lineTo(s, h);
c.lineTo(0, h - s);
c.lineTo(0, 0);
c.close();
c.end();
c.fillAndStroke();
if (!this.outline)
{
c.setShadow(false);
if (op != 0)
{
c.setFillAlpha(Math.abs(op));
c.setFillColor((op < 0) ? '#FFFFFF' : '#000000');
c.begin();
c.moveTo(0, 0);
c.lineTo(w - s, 0);
c.lineTo(w, s);
c.lineTo(s, s);
c.close();
c.fill();
}
if (op2 != 0)
{
c.setFillAlpha(Math.abs(op2));
c.setFillColor((op2 < 0) ? '#FFFFFF' : '#000000');
c.begin();
c.moveTo(0, 0);
c.lineTo(s, s);
c.lineTo(s, h);
c.lineTo(0, h - s);
c.close();
c.fill();
}
c.begin();
c.moveTo(s, h);
c.lineTo(s, s);
c.lineTo(0, 0);
c.moveTo(s, s);
c.lineTo(w, s);
c.end();
c.stroke();
}
};
CubeShape.prototype.getLabelMargins = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
var s = parseFloat(mxUtils.getValue(this.style, 'size', this.size)) * this.scale;
return new mxRectangle(s, s, 0, 0);
}
return null;
};
mxCellRenderer.registerShape('cube', CubeShape);
var tan30 = Math.tan(mxUtils.toRadians(30));
var tan30Dx = (0.5 - tan30) / 2;
mxCellRenderer.registerShape('isoRectangle', IsoRectangleShape);
// Cube Shape, supports size style
function WaypointShape()
{
mxCylinder.call(this);
};
mxUtils.extend(WaypointShape, mxCylinder);
WaypointShape.prototype.size = 6;
WaypointShape.prototype.paintVertexShape = function(c, x, y, w, h)
{
c.setFillColor(this.stroke);
var s = Math.max(0, parseFloat(mxUtils.getValue(this.style, 'size', this.size)) - 2) + 2 * this.strokewidth;
c.ellipse(x + (w - s) * 0.5, y + (h - s) * 0.5, s, s);
c.fill();
c.setFillColor(mxConstants.NONE);
c.rect(x, y, w, h);
c.fill();
};
mxCellRenderer.registerShape('waypoint', WaypointShape);
// Cube Shape, supports size style
function IsoRectangleShape()
{
mxActor.call(this);
};
mxUtils.extend(IsoRectangleShape, mxActor);
IsoRectangleShape.prototype.size = 20;
IsoRectangleShape.prototype.redrawPath = function(path, x, y, w, h)
{
var m = Math.min(w, h / tan30);
path.translate((w - m) / 2, (h - m) / 2 + m / 4);
path.moveTo(0, 0.25 * m);
path.lineTo(0.5 * m, m * tan30Dx);
path.lineTo(m, 0.25 * m);
path.lineTo(0.5 * m, (0.5 - tan30Dx) * m);
path.lineTo(0, 0.25 * m);
path.close();
path.end();
};
mxCellRenderer.registerShape('isoRectangle', IsoRectangleShape);
// Cube Shape, supports size style
function IsoCubeShape()
{
mxCylinder.call(this);
};
mxUtils.extend(IsoCubeShape, mxCylinder);
IsoCubeShape.prototype.size = 20;
IsoCubeShape.prototype.redrawPath = function(path, x, y, w, h, isForeground)
{
var m = Math.min(w, h / (0.5 + tan30));
if (isForeground)
{
path.moveTo(0, 0.25 * m);
path.lineTo(0.5 * m, (0.5 - tan30Dx) * m);
path.lineTo(m, 0.25 * m);
path.moveTo(0.5 * m, (0.5 - tan30Dx) * m);
path.lineTo(0.5 * m, (1 - tan30Dx) * m);
path.end();
}
else
{
path.translate((w - m) / 2, (h - m) / 2);
path.moveTo(0, 0.25 * m);
path.lineTo(0.5 * m, m * tan30Dx);
path.lineTo(m, 0.25 * m);
path.lineTo(m, 0.75 * m);
path.lineTo(0.5 * m, (1 - tan30Dx) * m);
path.lineTo(0, 0.75 * m);
path.close();
path.end();
}
};
mxCellRenderer.registerShape('isoCube', IsoCubeShape);
// 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.getLabelMargins = function(rect)
{
return new mxRectangle(0, 2.5 * Math.min(rect.height / 2,
Math.round(rect.height / 8) + this.strokewidth - 1), 0, 0);
}
mxCellRenderer.registerShape('datastore', DataStoreShape);
// Note Shape, supports size style
function NoteShape()
{
mxCylinder.call(this);
};
mxUtils.extend(NoteShape, mxCylinder);
NoteShape.prototype.size = 30;
NoteShape.prototype.darkOpacity = 0;
NoteShape.prototype.paintVertexShape = 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 op = Math.max(-1, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'darkOpacity', this.darkOpacity))));
c.translate(x, y);
c.begin();
c.moveTo(0, 0);
c.lineTo(w - s, 0);
c.lineTo(w, s);
c.lineTo(w, h);
c.lineTo(0, h);
c.lineTo(0, 0);
c.close();
c.end();
c.fillAndStroke();
if (!this.outline)
{
c.setShadow(false);
if (op != 0)
{
c.setFillAlpha(Math.abs(op));
c.setFillColor((op < 0) ? '#FFFFFF' : '#000000');
c.begin();
c.moveTo(w - s, 0);
c.lineTo(w - s, s);
c.lineTo(w, s);
c.close();
c.fill();
}
c.begin();
c.moveTo(w - s, 0);
c.lineTo(w - s, s);
c.lineTo(w, s);
c.end();
c.stroke();
}
};
mxCellRenderer.registerShape('note', NoteShape);
// Note Shape, supports size style
function NoteShape2()
{
NoteShape.call(this);
};
mxUtils.extend(NoteShape2, NoteShape);
mxCellRenderer.registerShape('note2', NoteShape2);
NoteShape2.prototype.getLabelMargins = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
var size = mxUtils.getValue(this.style, 'size', 15);
return new mxRectangle(0, Math.min(rect.height * this.scale, size * this.scale), 0, 0);
}
return null;
};
// Flexible cube Shape
function IsoCubeShape2()
{
mxShape.call(this);
};
mxUtils.extend(IsoCubeShape2, mxShape);
IsoCubeShape2.prototype.isoAngle = 15;
IsoCubeShape2.prototype.paintVertexShape = function(c, x, y, w, h)
{
var isoAngle = Math.max(0.01, Math.min(94, parseFloat(mxUtils.getValue(this.style, 'isoAngle', this.isoAngle)))) * Math.PI / 200 ;
var isoH = Math.min(w * Math.tan(isoAngle), h * 0.5);
c.translate(x,y);
c.begin();
c.moveTo(w * 0.5, 0);
c.lineTo(w, isoH);
c.lineTo(w, h - isoH);
c.lineTo(w * 0.5, h);
c.lineTo(0, h - isoH);
c.lineTo(0, isoH);
c.close();
c.fillAndStroke();
c.setShadow(false);
c.begin();
c.moveTo(0, isoH);
c.lineTo(w * 0.5, 2 * isoH);
c.lineTo(w, isoH);
c.moveTo(w * 0.5, 2 * isoH);
c.lineTo(w * 0.5, h);
c.stroke();
};
mxCellRenderer.registerShape('isoCube2', IsoCubeShape2);
// (LEGACY) Flexible cylinder Shape
function CylinderShape()
{
mxShape.call(this);
};
mxUtils.extend(CylinderShape, mxShape);
CylinderShape.prototype.size = 15;
CylinderShape.prototype.paintVertexShape = function(c, x, y, w, h)
{
var size = Math.max(0, Math.min(h * 0.5, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
c.translate(x,y);
if (size == 0)
{
c.rect(0, 0, w, h);
c.fillAndStroke();
}
else
{
c.begin();
c.moveTo(0, size);
c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, 0);
c.arcTo(w * 0.5, size, 0, 0, 1, w, size);
c.lineTo(w, h - size);
c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, h);
c.arcTo(w * 0.5, size, 0, 0, 1, 0, h - size);
c.close();
c.fillAndStroke();
c.setShadow(false);
c.begin();
c.moveTo(w, size);
c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, 2 * size);
c.arcTo(w * 0.5, size, 0, 0, 1, 0, size);
c.stroke();
}
};
mxCellRenderer.registerShape('cylinder2', CylinderShape);
// Flexible cylinder3 Shape with offset label
function CylinderShape3(bounds, fill, stroke, strokewidth)
{
mxShape.call(this);
this.bounds = bounds;
this.fill = fill;
this.stroke = stroke;
this.strokewidth = (strokewidth != null) ? strokewidth : 1;
};
mxUtils.extend(CylinderShape3, mxCylinder);
CylinderShape3.prototype.size = 15;
CylinderShape3.prototype.paintVertexShape = function(c, x, y, w, h)
{
var size = Math.max(0, Math.min(h * 0.5, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
var lid = mxUtils.getValue(this.style, 'lid', true);
c.translate(x,y);
if (size == 0)
{
c.rect(0, 0, w, h);
c.fillAndStroke();
}
else
{
c.begin();
if (lid)
{
c.moveTo(0, size);
c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, 0);
c.arcTo(w * 0.5, size, 0, 0, 1, w, size);
}
else
{
c.moveTo(0, 0);
c.arcTo(w * 0.5, size, 0, 0, 0, w * 0.5, size);
c.arcTo(w * 0.5, size, 0, 0, 0, w, 0);
}
c.lineTo(w, h - size);
c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, h);
c.arcTo(w * 0.5, size, 0, 0, 1, 0, h - size);
c.close();
c.fillAndStroke();
c.setShadow(false);
if (lid)
{
c.begin();
c.moveTo(w, size);
c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, 2 * size);
c.arcTo(w * 0.5, size, 0, 0, 1, 0, size);
c.stroke();
}
}
};
mxCellRenderer.registerShape('cylinder3', CylinderShape3);
// Switch 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.registerShape('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.arcSize = 0.1;
FolderShape.prototype.paintVertexShape = function(c, x, y, w, h)
{
c.translate(x, y);
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);
var rounded = mxUtils.getValue(this.style, 'rounded', false);
var absArcSize = mxUtils.getValue(this.style, 'absoluteArcSize', false);
var arcSize = parseFloat(mxUtils.getValue(this.style, 'arcSize', this.arcSize));
if (!absArcSize)
{
arcSize = Math.min(w, h) * arcSize;
}
arcSize = Math.min(arcSize, w * 0.5, (h - dy) * 0.5);
dx = Math.max(dx, arcSize);
dx = Math.min(w - arcSize, dx);
if (!rounded)
{
arcSize = 0;
}
c.begin();
if (tp == 'left')
{
c.moveTo(Math.max(arcSize, 0), dy);
c.lineTo(Math.max(arcSize, 0), 0);
c.lineTo(dx, 0);
c.lineTo(dx, dy);
}
// Right is default
else
{
c.moveTo(w - dx, dy);
c.lineTo(w - dx, 0);
c.lineTo(w - Math.max(arcSize, 0), 0);
c.lineTo(w - Math.max(arcSize, 0), dy);
}
if (rounded)
{
c.moveTo(0, arcSize + dy);
c.arcTo(arcSize, arcSize, 0, 0, 1, arcSize, dy);
c.lineTo(w - arcSize, dy);
c.arcTo(arcSize, arcSize, 0, 0, 1, w, arcSize + dy);
c.lineTo(w, h - arcSize);
c.arcTo(arcSize, arcSize, 0, 0, 1, w - arcSize, h);
c.lineTo(arcSize, h);
c.arcTo(arcSize, arcSize, 0, 0, 1, 0, h - arcSize);
}
else
{
c.moveTo(0, dy);
c.lineTo(w, dy);
c.lineTo(w, h);
c.lineTo(0, h);
}
c.close();
c.fillAndStroke();
c.setShadow(false);
var sym = mxUtils.getValue(this.style, 'folderSymbol', null);
if (sym == 'triangle')
{
c.begin();
c.moveTo(w - 30, dy + 20);
c.lineTo(w - 20, dy + 10);
c.lineTo(w - 10, dy + 20);
c.close();
c.stroke();
}
};
mxCellRenderer.registerShape('folder', FolderShape);
FolderShape.prototype.getLabelMargins = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
var sizeY = mxUtils.getValue(this.style, 'tabHeight', 15) * this.scale;
if (mxUtils.getValue(this.style, 'labelInHeader', false))
{
var sizeX = mxUtils.getValue(this.style, 'tabWidth', 15) * this.scale;
var sizeY = mxUtils.getValue(this.style, 'tabHeight', 15) * this.scale;
var rounded = mxUtils.getValue(this.style, 'rounded', false);
var absArcSize = mxUtils.getValue(this.style, 'absoluteArcSize', false);
var arcSize = parseFloat(mxUtils.getValue(this.style, 'arcSize', this.arcSize));
if (!absArcSize)
{
arcSize = Math.min(rect.width, rect.height) * arcSize;
}
arcSize = Math.min(arcSize, rect.width * 0.5, (rect.height - sizeY) * 0.5);
if (!rounded)
{
arcSize = 0;
}
if (mxUtils.getValue(this.style, 'tabPosition', this.tabPosition) == 'left')
{
return new mxRectangle(arcSize, 0, Math.min(rect.width, rect.width - sizeX), Math.min(rect.height, rect.height - sizeY));
}
else
{
return new mxRectangle(Math.min(rect.width, rect.width - sizeX), 0, arcSize, Math.min(rect.height, rect.height - sizeY));
}
}
else
{
return new mxRectangle(0, Math.min(rect.height, sizeY), 0, 0);
}
}
return null;
};
//**********************************************************************************************************************************************************
//UML State shape
//**********************************************************************************************************************************************************
function UMLStateShape()
{
mxCylinder.call(this);
};
mxUtils.extend(UMLStateShape, mxCylinder);
UMLStateShape.prototype.arcSize = 0.1;
UMLStateShape.prototype.paintVertexShape = function(c, x, y, w, h)
{
c.translate(x, y);
var rounded = mxUtils.getValue(this.style, 'rounded', false);
var absArcSize = mxUtils.getValue(this.style, 'absoluteArcSize', false);
var arcSize = parseFloat(mxUtils.getValue(this.style, 'arcSize', this.arcSize));
var connPoint = mxUtils.getValue(this.style, 'umlStateConnection', null);
if (!absArcSize)
{
arcSize = Math.min(w, h) * arcSize;
}
arcSize = Math.min(arcSize, w * 0.5, h * 0.5);
if (!rounded)
{
arcSize = 0;
}
var dx = 0;
if (connPoint != null)
{
dx = 10;
}
c.begin();
c.moveTo(dx, arcSize);
c.arcTo(arcSize, arcSize, 0, 0, 1, dx + arcSize, 0);
c.lineTo(w - arcSize, 0);
c.arcTo(arcSize, arcSize, 0, 0, 1, w, arcSize);
c.lineTo(w, h - arcSize);
c.arcTo(arcSize, arcSize, 0, 0, 1, w - arcSize, h);
c.lineTo(dx + arcSize, h);
c.arcTo(arcSize, arcSize, 0, 0, 1, dx, h - arcSize);
c.close();
c.fillAndStroke();
c.setShadow(false);
var sym = mxUtils.getValue(this.style, 'umlStateSymbol', null);
if (sym == 'collapseState')
{
c.roundrect(w - 40, h - 20, 10, 10, 3, 3);
c.stroke();
c.roundrect(w - 20, h - 20, 10, 10, 3, 3);
c.stroke();
c.begin();
c.moveTo(w - 30, h - 15);
c.lineTo(w - 20, h - 15);
c.stroke();
}
if (connPoint == 'connPointRefEntry')
{
c.ellipse(0, h * 0.5 - 10, 20, 20);
c.fillAndStroke();
}
else if (connPoint == 'connPointRefExit')
{
c.ellipse(0, h * 0.5 - 10, 20, 20);
c.fillAndStroke();
c.begin();
c.moveTo(5, h * 0.5 - 5);
c.lineTo(15, h * 0.5 + 5);
c.moveTo(15, h * 0.5 - 5);
c.lineTo(5, h * 0.5 + 5);
c.stroke();
}
};
UMLStateShape.prototype.getLabelMargins = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
var connPoint = mxUtils.getValue(this.style, 'umlStateConnection', null);
if (connPoint != null)
{
return new mxRectangle(10 * this.scale, 0, 0, 0);
}
}
return null;
};
mxCellRenderer.registerShape('umlState', UMLStateShape);
// Card shape
function CardShape()
{
mxActor.call(this);
};
mxUtils.extend(CardShape, mxActor);
CardShape.prototype.size = 30;
CardShape.prototype.isRoundable = function()
{
return true;
};
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.registerShape('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();
};
TapeShape.prototype.getLabelBounds = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
var size = mxUtils.getValue(this.style, 'size', this.size);
var w = rect.width;
var h = rect.height;
if (this.direction == null ||
this.direction == mxConstants.DIRECTION_EAST ||
this.direction == mxConstants.DIRECTION_WEST)
{
var dy = h * size;
return new mxRectangle(rect.x, rect.y + dy, w, h - 2 * dy);
}
else
{
var dx = w * size;
return new mxRectangle(rect.x + dx, rect.y, w - 2 * dx, h);
}
}
return rect;
};
mxCellRenderer.registerShape('tape', TapeShape);
// Document shape
function DocumentShape()
{
mxActor.call(this);
};
mxUtils.extend(DocumentShape, mxActor);
DocumentShape.prototype.size = 0.3;
DocumentShape.prototype.getLabelMargins = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
return new mxRectangle(0, 0, 0, parseFloat(mxUtils.getValue(
this.style, 'size', this.size)) * rect.height);
}
return null;
};
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.registerShape('document', DocumentShape);
var cylinderGetCylinderSize = mxCylinder.prototype.getCylinderSize;
mxCylinder.prototype.getCylinderSize = function(x, y, w, h)
{
var size = mxUtils.getValue(this.style, 'size');
if (size != null)
{
return h * Math.max(0, Math.min(1, size));
}
else
{
return cylinderGetCylinderSize.apply(this, arguments);
}
};
mxCylinder.prototype.getLabelMargins = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
var size = mxUtils.getValue(this.style, 'size', 0.15) * 2;
return new mxRectangle(0, Math.min(this.maxHeight * this.scale, rect.height * size), 0, 0);
}
return null;
};
CylinderShape3.prototype.getLabelMargins = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
var size = mxUtils.getValue(this.style, 'size', 15);
if (!mxUtils.getValue(this.style, 'lid', true))
{
size /= 2;
}
return new mxRectangle(0, Math.min(rect.height * this.scale, size * 2 * this.scale), 0, Math.max(0, size * 0.3 * this.scale));
}
return null;
};
FolderShape.prototype.getLabelMargins = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
var sizeY = mxUtils.getValue(this.style, 'tabHeight', 15) * this.scale;
if (mxUtils.getValue(this.style, 'labelInHeader', false))
{
var sizeX = mxUtils.getValue(this.style, 'tabWidth', 15) * this.scale;
var sizeY = mxUtils.getValue(this.style, 'tabHeight', 15) * this.scale;
var rounded = mxUtils.getValue(this.style, 'rounded', false);
var absArcSize = mxUtils.getValue(this.style, 'absoluteArcSize', false);
var arcSize = parseFloat(mxUtils.getValue(this.style, 'arcSize', this.arcSize));
if (!absArcSize)
{
arcSize = Math.min(rect.width, rect.height) * arcSize;
}
arcSize = Math.min(arcSize, rect.width * 0.5, (rect.height - sizeY) * 0.5);
if (!rounded)
{
arcSize = 0;
}
if (mxUtils.getValue(this.style, 'tabPosition', this.tabPosition) == 'left')
{
return new mxRectangle(arcSize, 0, Math.min(rect.width, rect.width - sizeX), Math.min(rect.height, rect.height - sizeY));
}
else
{
return new mxRectangle(Math.min(rect.width, rect.width - sizeX), 0, arcSize, Math.min(rect.height, rect.height - sizeY));
}
}
else
{
return new mxRectangle(0, Math.min(rect.height, sizeY), 0, 0);
}
}
return null;
};
UMLStateShape.prototype.getLabelMargins = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
var connPoint = mxUtils.getValue(this.style, 'umlStateConnection', null);
if (connPoint != null)
{
return new mxRectangle(10 * this.scale, 0, 0, 0);
}
}
return null;
};
NoteShape2.prototype.getLabelMargins = function(rect)
{
if (mxUtils.getValue(this.style, 'boundedLbl', false))
{
var size = mxUtils.getValue(this.style, 'size', 15);
return new mxRectangle(0, Math.min(rect.height * this.scale, size * this.scale), 0, Math.max(0, size * this.scale));
}
return null;
};
// Parallelogram shape
function ParallelogramShape()
{
mxActor.call(this);
};
mxUtils.extend(ParallelogramShape, mxActor);
ParallelogramShape.prototype.size = 0.2;
ParallelogramShape.prototype.fixedSize = 20;
ParallelogramShape.prototype.isRoundable = function()
{
return true;
};
ParallelogramShape.prototype.redrawPath = function(c, x, y, w, h)
{
var fixed = mxUtils.getValue(this.style, 'fixedSize', '0') != '0';
var dx = (fixed) ? Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'size', this.fixedSize)))) : 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.registerShape('parallelogram', ParallelogramShape);
// Trapezoid shape
function TrapezoidShape()
{
mxActor.call(this);
};
mxUtils.extend(TrapezoidShape, mxActor);
TrapezoidShape.prototype.size = 0.2;
TrapezoidShape.prototype.fixedSize = 20;
TrapezoidShape.prototype.isRoundable = function()
{
return true;
};
TrapezoidShape.prototype.redrawPath = function(c, x, y, w, h)
{
var fixed = mxUtils.getValue(this.style, 'fixedSize', '0') != '0';
var dx = (fixed) ? Math.max(0, Math.min(w * 0.5, parseFloat(mxUtils.getValue(this.style, 'size', this.fixedSize)))) : 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.registerShape('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.registerShape('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.registerShape('parallelMarker', ParallelMarkerShape);
/**
* Adds handJiggle style (jiggle=n sets jiggle)
*/
function HandJiggle(canvas, defaultVariation)
{
this.canvas = canvas;
// Avoids "spikes" in the output
this.canvas.setLineJoin('round');
this.canvas.setLineCap('round');
this.defaultVariation = defaultVariation;
this.originalLineTo = this.canvas.lineTo;
this.canvas.lineTo = mxUtils.bind(this, HandJiggle.prototype.lineTo);
this.originalMoveTo = this.canvas.moveTo;
this.canvas.moveTo = mxUtils.bind(this, HandJiggle.prototype.moveTo);
this.originalClose = this.canvas.close;
this.canvas.close = mxUtils.bind(this, HandJiggle.prototype.close);
this.originalQuadTo = this.canvas.quadTo;
this.canvas.quadTo = mxUtils.bind(this, HandJiggle.prototype.quadTo);
this.originalCurveTo = this.canvas.curveTo;
this.canvas.curveTo = mxUtils.bind(this, HandJiggle.prototype.curveTo);
this.originalArcTo = this.canvas.arcTo;
this.canvas.arcTo = mxUtils.bind(this, HandJiggle.prototype.arcTo);
};
HandJiggle.prototype.moveTo = function(endX, endY)
{
this.originalMoveTo.apply(this.canvas, arguments);
this.lastX = endX;
this.lastY = endY;
this.firstX = endX;
this.firstY = endY;
};
HandJiggle.prototype.close = function()
{
if (this.firstX != null && this.firstY != null)
{
this.lineTo(this.firstX, this.firstY);
this.originalClose.apply(this.canvas, arguments);
}
this.originalClose.apply(this.canvas, arguments);
};
HandJiggle.prototype.quadTo = function(x1, y1, x2, y2)
{
this.originalQuadTo.apply(this.canvas, arguments);
this.lastX = x2;
this.lastY = y2;
};
HandJiggle.prototype.curveTo = function(x1, y1, x2, y2, x3, y3)
{
this.originalCurveTo.apply(this.canvas, arguments);
this.lastX = x3;
this.lastY = y3;
};
HandJiggle.prototype.arcTo = function(rx, ry, angle, largeArcFlag, sweepFlag, x, y)
{
this.originalArcTo.apply(this.canvas, arguments);
this.lastX = x;
this.lastY = y;
};
HandJiggle.prototype.lineTo = function(endX, endY)
{
// LATER: Check why this.canvas.lastX cannot be used
if (this.lastX != null && this.lastY != null)
{
var dx = Math.abs(endX - this.lastX);
var dy = Math.abs(endY - this.lastY);
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 2)
{
this.originalLineTo.apply(this.canvas, arguments);
this.lastX = endX;
this.lastY = endY;
return;
}
var segs = Math.round(dist / 10);
var variation = this.defaultVariation;
if (segs < 5)
{
segs = 5;
variation /= 3;
}
function sign(x)
{
return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN;
}
var stepX = sign(endX - this.lastX) * dx / segs;
var stepY = sign(endY - this.lastY) * dy / segs;
var fx = dx / dist;
var fy = dy / dist;
for (var s = 0; s < segs; s++)
{
var x = stepX * s + this.lastX;
var y = stepY * s + this.lastY;
var offset = (Math.random() - 0.5) * variation;
this.originalLineTo.call(this.canvas, x - offset * fy, y - offset * fx);
}
this.originalLineTo.call(this.canvas, endX, endY);
this.lastX = endX;
this.lastY = endY;
}
else
{
this.originalLineTo.apply(this.canvas, arguments);
this.lastX = endX;
this.lastY = endY;
}
};
HandJiggle.prototype.destroy = function()
{
this.canvas.lineTo = this.originalLineTo;
this.canvas.moveTo = this.originalMoveTo;
this.canvas.close = this.originalClose;
this.canvas.quadTo = this.originalQuadTo;
this.canvas.curveTo = this.originalCurveTo;
this.canvas.arcTo = this.originalArcTo;
};
// Installs hand jiggle for comic and sketch style
mxShape.prototype.defaultJiggle = 1.5;
var shapeBeforePaint = mxShape.prototype.beforePaint;
mxShape.prototype.beforePaint = function(c)
{
shapeBeforePaint.apply(this, arguments);
if (c.handJiggle == null)
{
c.handJiggle = this.createHandJiggle(c);
}
};
var shapeAfterPaint = mxShape.prototype.afterPaint;
mxShape.prototype.afterPaint = function(c)
{
shapeAfterPaint.apply(this, arguments);
if (c.handJiggle != null)
{
c.handJiggle.destroy();
delete c.handJiggle;
}
};
// Returns a new HandJiggle canvas
mxShape.prototype.createComicCanvas = function(c)
{
return new HandJiggle(c, mxUtils.getValue(this.style, 'jiggle', this.defaultJiggle));
};
// Overrides to avoid call to rect
mxShape.prototype.createHandJiggle = function(c)
{
if (!this.outline && this.style != null && mxUtils.getValue(this.style, 'comic', '0') != '0')
{
return this.createComicCanvas(c);
}
return null;
};
// Sets default jiggle for diamond
mxRhombus.prototype.defaultJiggle = 2;
// Overrides to avoid call to rect
var mxRectangleShapeIsHtmlAllowed0 = mxRectangleShape.prototype.isHtmlAllowed;
mxRectangleShape.prototype.isHtmlAllowed = function()
{
return !this.outline && (this.style == null || (mxUtils.getValue(this.style, 'comic', '0') == '0' &&
mxUtils.getValue(this.style, 'sketch', (urlParams['rough'] == '1') ? '1' : '0') == '0')) &&
mxRectangleShapeIsHtmlAllowed0.apply(this, arguments);
};
var mxRectangleShapePaintBackground0 = mxRectangleShape.prototype.paintBackground;
mxRectangleShape.prototype.paintBackground = function(c, x, y, w, h)
{
if (c.handJiggle == null || c.handJiggle.constructor != HandJiggle)
{
mxRectangleShapePaintBackground0.apply(this, arguments);
}
else
{
var events = true;
if (this.style != null)
{
events = mxUtils.getValue(this.style, mxConstants.STYLE_POINTER_EVENTS, '1') == '1';
}
if (events || (this.fill != null && this.fill != mxConstants.NONE) ||
(this.stroke != null && this.stroke != mxConstants.NONE))
{
if (!events && (this.fill == null || this.fill == mxConstants.NONE))
{
c.pointerEvents = false;
}
c.begin();
if (this.isRounded)
{
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);
}
c.moveTo(x + r, y);
c.lineTo(x + w - r, y);
c.quadTo(x + w, y, x + w, y + r);
c.lineTo(x + w, y + h - r);
c.quadTo(x + w, y + h, x + w - r, y + h);
c.lineTo(x + r, y + h);
c.quadTo(x, y + h, x, y + h - r);
c.lineTo(x, y + r);
c.quadTo(x, y, x + r, y);
}
else
{
c.moveTo(x, y);
c.lineTo(x + w, y);
c.lineTo(x + w, y + h);
c.lineTo(x, y + h);
c.lineTo(x, y);
}
// LATER: Check if close is needed here
c.close();
c.end();
c.fillAndStroke();
}
}
};
// End of hand jiggle integration
// Process Shape
function ProcessShape()
{
mxRectangleShape.call(this);
};
mxUtils.extend(ProcessShape, mxRectangleShape);
ProcessShape.prototype.size = 0.1;
ProcessShape.prototype.fixedSize = false;
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 += Math.round(inset);
r.width -= Math.round(2 * inset);
return r;
}
return rect;
};
ProcessShape.prototype.paintForeground = function(c, x, y, w, h)
{
var isFixedSize = mxUtils.getValue(this.style, 'fixedSize', this.fixedSize);
var inset = parseFloat(mxUtils.getValue(this.style, 'size', this.size));
if (isFixedSize)
{
inset = Math.max(0, Math.min(w, inset));
}
else
{
inset = w * Math.max(0, Math.min(1, inset));
}
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));
}
// Crisp rendering of inner lines
inset = Math.round(inset);
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.registerShape('process', ProcessShape);
//Register the same shape with another name for backwards compatibility
mxCellRenderer.registerShape('process2', ProcessShape);
// Transparent Shape
function TransparentShape()
{
mxRectangleShape.call(this);
};
mxUtils.extend(TransparentShape, mxRectangleShape);
TransparentShape.prototype.paintBackground = function(c, x, y, w, h)
{
c.setFillColor(mxConstants.NONE);
c.rect(x, y, w, h);
c.fill();
};
TransparentShape.prototype.paintForeground = function(c, x, y, w, h) { };
mxCellRenderer.registerShape('transparent', TransparentShape);
// Callout shape
function CalloutShape()
{
mxActor.call(this);
};
mxUtils.extend(CalloutShape, mxHexagon);
CalloutShape.prototype.size = 30;
CalloutShape.prototype.position = 0.5;
CalloutShape.prototype.position2 = 0.5;
CalloutShape.prototype.base = 20;
CalloutShape.prototype.getLabelMargins = function()
{
return new mxRectangle(0, 0, 0, parseFloat(mxUtils.getValue(
this.style, 'size', this.size)) * this.scale);
};
CalloutShape.prototype.isRoundable = function()
{
return true;
};
CalloutShape.prototype.redrawPath = function(c, x, y, w, h)
{
var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
var s = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
var dx = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'position', this.position))));
var dx2 = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'position2', this.position2))));
var base = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'base', this.base))));
this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w, 0), new mxPoint(w, h - s),
new mxPoint(Math.min(w, dx + base), h - s), new mxPoint(dx2, h),
new mxPoint(Math.max(0, dx), h - s), new mxPoint(0, h - s)],
this.isRounded, arcSize, true, [4]);
};
mxCellRenderer.registerShape('callout', CalloutShape);
// Step shape
function StepShape()
{
mxActor.call(this);
};
mxUtils.extend(StepShape, mxActor);
StepShape.prototype.size = 0.2;
StepShape.prototype.fixedSize = 20;
StepShape.prototype.isRoundable = function()
{
return true;
};
StepShape.prototype.redrawPath = function(c, x, y, w, h)
{
var fixed = mxUtils.getValue(this.style, 'fixedSize', '0') != '0';
var s = (fixed) ? Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'size', this.fixedSize)))) :
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.registerShape('step', StepShape);
// Hexagon shape
function HexagonShape()
{
mxActor.call(this);
};
mxUtils.extend(HexagonShape, mxHexagon);
HexagonShape.prototype.size = 0.25;
HexagonShape.prototype.fixedSize = 20;
HexagonShape.prototype.isRoundable = function()
{
return true;
};
HexagonShape.prototype.redrawPath = function(c, x, y, w, h)
{
var fixed = mxUtils.getValue(this.style, 'fixedSize', '0') != '0';
var s = (fixed) ? Math.max(0, Math.min(w * 0.5, parseFloat(mxUtils.getValue(this.style, 'size', this.fixedSize)))) :
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.registerShape('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.registerShape('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.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 vspacing = this.style['symbol' + counter + 'VSpacing'] || spacing;
var arcspacing = this.style['symbol' + counter + 'ArcSpacing'];
if (arcspacing != null)
{
var arcSize = this.getArcSize(w + this.strokewidth, h + this.strokewidth) * arcspacing;
spacing += arcSize;
vspacing += arcSize;
}
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 - vspacing;
}
else
{
y2 += vspacing;
}
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.registerShape('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.line