1/**
2 * $Id: mxArrows.js,v 1.5 2016/03/23 12:32:06 mate Exp $
3 * Copyright (c) 2006-2016, JGraph Ltd
4 */
5
6//**********************************************************************************************************************************************************
7//Arrow
8//**********************************************************************************************************************************************************
9/**
10* Extends mxShape.
11*/
12function mxShapeArrows2Arrow(bounds, fill, stroke, strokewidth)
13{
14	mxShape.call(this);
15	this.bounds = bounds;
16	this.fill = fill;
17	this.stroke = stroke;
18	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
19	this.dy = 0.5;
20	this.dx = 0.5;
21	this.notch = 0;
22};
23
24/**
25* Extends mxShape.
26*/
27mxUtils.extend(mxShapeArrows2Arrow, mxActor);
28
29mxShapeArrows2Arrow.prototype.customProperties = [
30	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min: 0, defVal: 40},
31	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, max:1, defVal: 0.6},
32	{name: 'notch', dispName: 'Notch', type: 'float', min:0, defVal: 0},
33	{name: 'headCrossline', dispName: 'Head Crossline', type: 'bool', defVal: false},
34	{name: 'tailCrossline', dispName: 'Tail Crossline', type: 'bool', defVal: false}
35];
36
37mxShapeArrows2Arrow.prototype.cst = {
38		ARROW : 'mxgraph.arrows2.arrow'
39};
40
41/**
42* Function: paintVertexShape
43*
44* Paints the vertex shape.
45*/
46mxShapeArrows2Arrow.prototype.paintVertexShape = function(c, x, y, w, h)
47{
48	c.translate(x, y);
49
50	var dy = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
51	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
52	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
53	var headCrossline = mxUtils.getValue(this.style, 'headCrossline', false);
54	var tailCrossline = mxUtils.getValue(this.style, 'tailCrossline', false);
55
56	c.begin();
57	c.moveTo(0, dy);
58	c.lineTo(w - dx, dy);
59	c.lineTo(w - dx, 0);
60	c.lineTo(w, h * 0.5);
61	c.lineTo(w - dx, h);
62	c.lineTo(w - dx, h - dy);
63	c.lineTo(0, h - dy);
64	c.lineTo(notch, h * 0.5);
65	c.close();
66	c.fillAndStroke();
67
68	c.setShadow(false);
69
70	if (headCrossline)
71	{
72		c.begin();
73		c.moveTo(w - dx, dy);
74		c.lineTo(w - dx, h - dy);
75		c.stroke();
76	}
77
78	if (tailCrossline)
79	{
80		c.begin();
81		c.moveTo(notch, dy);
82		c.lineTo(notch, h - dy);
83		c.stroke();
84	}
85};
86
87mxShapeArrows2Arrow.prototype.getLabelBounds = function(rect)
88{
89	if (mxUtils.getValue(this.style, 'boundedLbl', false))
90	{
91		var w = rect.width;
92		var h = rect.height;
93
94		var dy, dx;
95		var direction = this.direction || mxConstants.DIRECTION_EAST;
96
97		if (mxUtils.getValue(this.style, 'flipH', false))
98		{
99			if (direction == mxConstants.DIRECTION_WEST)
100				direction = mxConstants.DIRECTION_EAST;
101			else if (direction == mxConstants.DIRECTION_EAST)
102				direction = mxConstants.DIRECTION_WEST;
103		}
104
105		if (mxUtils.getValue(this.style, 'flipV', false))
106		{
107			if (direction == mxConstants.DIRECTION_NORTH)
108				direction = mxConstants.DIRECTION_SOUTH;
109			else if (direction == mxConstants.DIRECTION_SOUTH)
110				direction = mxConstants.DIRECTION_NORTH;
111		}
112
113		if (direction == mxConstants.DIRECTION_NORTH
114				|| direction == mxConstants.DIRECTION_SOUTH)
115		{
116			dy = w * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
117			dx = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
118		}
119		else
120		{
121			dy = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
122			dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
123		}
124
125		if (direction == mxConstants.DIRECTION_EAST)
126		{
127			return new mxRectangle(rect.x, rect.y + dy, w - dx, h - 2 * dy);
128		}
129		else if (direction == mxConstants.DIRECTION_WEST)
130		{
131			return new mxRectangle(rect.x + dx, rect.y + dy, w - dx, h - 2 * dy);
132		}
133		else if (direction == mxConstants.DIRECTION_NORTH)
134		{
135			return new mxRectangle(rect.x + dy, rect.y + dx, w - 2 * dy, h - dx);
136		}
137		else
138		{
139			return new mxRectangle(rect.x + dy, rect.y, w - 2 * dy, h - dx);
140		}
141	}
142
143	return rect;
144};
145
146mxCellRenderer.registerShape(mxShapeArrows2Arrow.prototype.cst.ARROW, mxShapeArrows2Arrow);
147
148Graph.handleFactory[mxShapeArrows2Arrow.prototype.cst.ARROW] = function(state)
149{
150	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
151			{
152				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
153				var dy = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
154
155				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + dy * bounds.height / 2);
156			}, function(bounds, pt)
157			{
158				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.x + bounds.width - pt.x))) / 100;
159				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(1, (((pt.y - bounds.y) / bounds.height) * 2)))) / 100;
160			})];
161
162	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
163			{
164				var notch = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
165
166				return new mxPoint(bounds.x + notch, bounds.y + bounds.height / 2);
167			}, function(bounds, pt)
168			{
169				this.state.style['notch'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), pt.x - bounds.x))) / 100;
170			});
171
172	handles.push(handle2);
173
174	return handles;
175
176}
177
178mxShapeArrows2Arrow.prototype.getConstraints = function(style, w, h)
179{
180	var constr = [];
181	var dy = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
182	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
183	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
184
185	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
186	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null, notch, 0));
187	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, dy));
188	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - dy));
189	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, dy));
190	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, 0));
191	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h - dy));
192	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h));
193	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx) * 0.5, dy));
194	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx) * 0.5, h - dy));
195
196	return (constr);
197};
198
199//**********************************************************************************************************************************************************
200//Two Way Arrow
201//**********************************************************************************************************************************************************
202/**
203* Extends mxShape.
204*/
205function mxShapeArrows2TwoWayArrow(bounds, fill, stroke, strokewidth)
206{
207	mxShape.call(this);
208	this.bounds = bounds;
209	this.fill = fill;
210	this.stroke = stroke;
211	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
212	this.dy = 0.5;
213	this.dx = 0.5;
214};
215
216/**
217* Extends mxShape.
218*/
219mxUtils.extend(mxShapeArrows2TwoWayArrow, mxActor);
220
221mxShapeArrows2TwoWayArrow.prototype.cst = {
222		TWO_WAY_ARROW : 'mxgraph.arrows2.twoWayArrow'
223};
224
225mxShapeArrows2TwoWayArrow.prototype.customProperties = [
226	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal: 35},
227	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, max:1, defVal: 0.6}
228];
229
230/**
231* Function: paintVertexShape
232*
233* Paints the vertex shape.
234*/
235mxShapeArrows2TwoWayArrow.prototype.paintVertexShape = function(c, x, y, w, h)
236{
237	c.translate(x, y);
238
239	var dy = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
240	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
241
242	c.begin();
243	c.moveTo(dx, dy);
244	c.lineTo(w - dx, dy);
245	c.lineTo(w - dx, 0);
246	c.lineTo(w, h * 0.5);
247	c.lineTo(w - dx, h);
248	c.lineTo(w - dx, h - dy);
249	c.lineTo(dx, h - dy);
250	c.lineTo(dx, h);
251	c.lineTo(0, h * 0.5);
252	c.lineTo(dx, 0);
253	c.close();
254	c.fillAndStroke();
255};
256
257mxShapeArrows2TwoWayArrow.prototype.getLabelBounds = function(rect)
258{
259	if (mxUtils.getValue(this.style, 'boundedLbl', false))
260	{
261		var w = rect.width;
262		var h = rect.height;
263		var vertical = this.direction == mxConstants.DIRECTION_NORTH
264						|| this.direction == mxConstants.DIRECTION_SOUTH;
265
266		var dy, dx;
267
268		if (vertical)
269		{
270			dy = w * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
271			dx = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
272		}
273		else
274		{
275			dy = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
276			dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
277		}
278
279		if (vertical)
280		{
281			return new mxRectangle(rect.x + dy, rect.y + dx, w - 2 * dy, h - 2 * dx);
282		}
283		else
284		{
285			return new mxRectangle(rect.x + dx, rect.y + dy, w - 2 * dx, h - 2 * dy);
286		}
287	}
288
289	return rect;
290};
291
292mxCellRenderer.registerShape(mxShapeArrows2TwoWayArrow.prototype.cst.TWO_WAY_ARROW, mxShapeArrows2TwoWayArrow);
293
294mxShapeArrows2TwoWayArrow.prototype.constraints = null;
295
296Graph.handleFactory[mxShapeArrows2TwoWayArrow.prototype.cst.TWO_WAY_ARROW] = function(state)
297{
298	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
299			{
300				var dx = Math.max(0, Math.min(bounds.width / 2, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
301				var dy = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
302
303				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + dy * bounds.height / 2);
304			}, function(bounds, pt)
305			{
306				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(bounds.width / 2, bounds.x + bounds.width - pt.x))) / 100;
307				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(1, (((pt.y - bounds.y) / bounds.height) * 2)))) / 100;
308			})];
309
310	return handles;
311
312}
313
314mxShapeArrows2TwoWayArrow.prototype.getConstraints = function(style, w, h)
315{
316	var constr = [];
317	var dy = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
318	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
319
320	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
321	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, 0));
322	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, dy));
323	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h));
324	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h - dy));
325	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
326	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, 0));
327	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, dy));
328	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h));
329	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h - dy));
330	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false, null, 0, dy));
331	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false, null, 0, h - dy));
332
333	return (constr);
334};
335
336//**********************************************************************************************************************************************************
337//Stylised Arrow
338//**********************************************************************************************************************************************************
339/**
340* Extends mxShape.
341*/
342function mxShapeArrows2StylisedArrow(bounds, fill, stroke, strokewidth)
343{
344	mxShape.call(this);
345	this.bounds = bounds;
346	this.fill = fill;
347	this.stroke = stroke;
348	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
349	this.dy = 0.5;
350	this.dx = 0.5;
351	this.notch = 0;
352	this.feather = 0.5;
353};
354
355/**
356* Extends mxShape.
357*/
358mxUtils.extend(mxShapeArrows2StylisedArrow, mxActor);
359
360mxShapeArrows2StylisedArrow.prototype.customProperties = [
361	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:40},
362	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, max:1, defVal:0.6},
363	{name: 'notch', dispName: 'Notch', type: 'float', min:0, defVal:0},
364	{name: 'feather', dispName: 'Feather', type: 'float', min:0, max:1, defVal:0.4},
365];
366
367mxShapeArrows2StylisedArrow.prototype.cst = {
368		STYLISED_ARROW : 'mxgraph.arrows2.stylisedArrow'
369};
370
371/**
372* Function: paintVertexShape
373*
374* Paints the vertex shape.
375*/
376mxShapeArrows2StylisedArrow.prototype.paintVertexShape = function(c, x, y, w, h)
377{
378	c.translate(x, y);
379
380	var dy = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
381	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
382	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
383	var feather = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'feather', this.feather))));
384
385	c.begin();
386	c.moveTo(0, feather);
387	c.lineTo(w - dx, dy);
388	c.lineTo(w - dx - 10, 0);
389	c.lineTo(w, h * 0.5);
390	c.lineTo(w - dx - 10, h);
391	c.lineTo(w - dx, h - dy);
392	c.lineTo(0, h - feather);
393	c.lineTo(notch, h * 0.5);
394	c.close();
395	c.fillAndStroke();
396};
397
398mxCellRenderer.registerShape(mxShapeArrows2StylisedArrow.prototype.cst.STYLISED_ARROW, mxShapeArrows2StylisedArrow);
399
400mxShapeArrows2StylisedArrow.prototype.constraints = null;
401
402Graph.handleFactory[mxShapeArrows2StylisedArrow.prototype.cst.STYLISED_ARROW] = function(state)
403{
404	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
405			{
406				var dx = Math.max(0, Math.min(bounds.width - 10, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
407				var dy = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
408
409				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + dy * bounds.height / 2);
410			}, function(bounds, pt)
411			{
412				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(bounds.width - 10, bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.x + bounds.width - pt.x))) / 100;
413				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(1, (((pt.y - bounds.y) / bounds.height) * 2)))) / 100;
414			})];
415
416	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
417			{
418				var notch = Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
419
420				return new mxPoint(bounds.x + notch, bounds.y + bounds.height / 2);
421			}, function(bounds, pt)
422			{
423				this.state.style['notch'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), pt.x - bounds.x))) / 100;
424			});
425
426	handles.push(handle2);
427
428	var handle3 = Graph.createHandle(state, ['feather'], function(bounds)
429			{
430				var feather = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'feather', this.dy))));
431
432				return new mxPoint(bounds.x, bounds.y + feather * bounds.height / 2);
433			}, function(bounds, pt)
434			{
435				this.state.style['feather'] = Math.round(100 * Math.max(0, Math.min(1, (((pt.y - bounds.y) / bounds.height) * 2)))) / 100;
436			});
437
438	handles.push(handle3);
439
440	return handles;
441
442}
443
444mxShapeArrows2StylisedArrow.prototype.getConstraints = function(style, w, h)
445{
446	var constr = [];
447	var dy = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
448	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
449	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
450	var feather = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'feather', this.feather))));
451
452	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
453	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null, notch, 0));
454	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, feather));
455	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - feather));
456	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, dy));
457	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx - 10, 0));
458	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h - dy));
459	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx - 10, h));
460	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx) * 0.5, (dy + feather) * 0.5));
461	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx) * 0.5, h - (dy + feather) * 0.5));
462
463	return (constr);
464};
465
466//**********************************************************************************************************************************************************
467//Sharp Arrow
468//**********************************************************************************************************************************************************
469/**
470* Extends mxShape.
471*/
472function mxShapeArrows2SharpArrow(bounds, fill, stroke, strokewidth)
473{
474	mxShape.call(this);
475	this.bounds = bounds;
476	this.fill = fill;
477	this.stroke = stroke;
478	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
479	this.dy1 = 0.5;
480	this.dx1 = 0.5;
481	this.dx2 = 0.5;
482	this.notch = 0;
483};
484
485/**
486* Extends mxShape.
487*/
488mxUtils.extend(mxShapeArrows2SharpArrow, mxActor);
489
490mxShapeArrows2SharpArrow.prototype.cst = {
491		SHARP_ARROW : 'mxgraph.arrows2.sharpArrow'
492};
493
494mxShapeArrows2SharpArrow.prototype.customProperties = [
495	{name: 'dx1', dispName: 'Arrowhead Arrow Width', type: 'float', min:0, defVal:18},
496	{name: 'dy1', dispName: 'Arrow Arrow Width', type: 'float', min:0, max:1, defVal:0.67},
497	{name: 'dx2', dispName: 'Arrowhead Angle', type: 'float', min:0, defVal:18},
498	{name: 'notch', dispName: 'Notch', type: 'float', min:0, defVal:0}
499];
500
501/**
502* Function: paintVertexShape
503*
504* Paints the vertex shape.
505*/
506mxShapeArrows2SharpArrow.prototype.paintVertexShape = function(c, x, y, w, h)
507{
508	c.translate(x, y);
509
510	var dy1 = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
511	var dx1 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
512	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
513	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
514	var dx1a = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
515	var dy1a = h * 0.5 * Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
516	var x2 = 0;
517
518	if (h != 0)
519	{
520		x2 = dx1a + dx2 * dy1a * 2 / h;
521	}
522
523	c.begin();
524	c.moveTo(0, dy1);
525	c.lineTo(w - dx1, dy1);
526	c.lineTo(w - x2, 0);
527	c.lineTo(w - dx2, 0);
528	c.lineTo(w, h * 0.5);
529	c.lineTo(w - dx2, h);
530	c.lineTo(w - x2, h);
531	c.lineTo(w - dx1, h - dy1);
532	c.lineTo(0, h - dy1);
533	c.lineTo(notch, h * 0.5);
534	c.close();
535	c.fillAndStroke();
536};
537
538mxCellRenderer.registerShape(mxShapeArrows2SharpArrow.prototype.cst.SHARP_ARROW, mxShapeArrows2SharpArrow);
539
540mxShapeArrows2SharpArrow.prototype.constraints = null;
541
542Graph.handleFactory[mxShapeArrows2SharpArrow.prototype.cst.SHARP_ARROW] = function(state)
543{
544	var handles = [Graph.createHandle(state, ['dx1', 'dy1'], function(bounds)
545			{
546				var dx1 = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1))));
547				var dy1 = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1))));
548
549				return new mxPoint(bounds.x + bounds.width - dx1, bounds.y + dy1 * bounds.height / 2);
550			}, function(bounds, pt)
551			{
552				this.state.style['dx1'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.x + bounds.width - pt.x))) / 100;
553				this.state.style['dy1'] = Math.round(100 * Math.max(0, Math.min(1, (((pt.y - bounds.y) / bounds.height) * 2)))) / 100;
554			})];
555
556	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
557			{
558				var notch = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
559
560				return new mxPoint(bounds.x + notch, bounds.y + bounds.height / 2);
561			}, function(bounds, pt)
562			{
563				this.state.style['notch'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1)), pt.x - bounds.x))) / 100;
564			});
565
566	handles.push(handle2);
567
568	var handle3 = Graph.createHandle(state, ['dx2'], function(bounds)
569			{
570				var dx2 = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2))));
571
572				return new mxPoint(bounds.x + bounds.width - dx2, bounds.y);
573			}, function(bounds, pt)
574			{
575				this.state.style['dx2'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.x + bounds.width - pt.x))) / 100;
576			});
577
578	handles.push(handle3);
579
580	return handles;
581};
582
583mxShapeArrows2SharpArrow.prototype.getConstraints = function(style, w, h)
584{
585	var constr = [];
586	var dy1 = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
587	var dx1 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
588	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
589	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
590	var dx1a = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
591	var dy1a = h * 0.5 * Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
592	var x2 = 0;
593
594	if (h != 0)
595	{
596		x2 = dx1a + dx2 * dy1a * 2 / h;
597	}
598
599	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
600	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null, notch, 0));
601	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, dy1));
602	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx1, dy1));
603	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - x2, 0));
604	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx2, 0));
605	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - dy1));
606	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx1, h - dy1));
607	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - x2, h));
608	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx2, h));
609	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx1) * 0.5, dy1));
610	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx1) * 0.5, h - dy1));
611
612	return (constr);
613};
614
615//**********************************************************************************************************************************************************
616//Sharp Arrow2
617//**********************************************************************************************************************************************************
618/**
619* Extends mxShape.
620*/
621function mxShapeArrows2SharpArrow2(bounds, fill, stroke, strokewidth)
622{
623	mxShape.call(this);
624	this.bounds = bounds;
625	this.fill = fill;
626	this.stroke = stroke;
627	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
628	this.dy1 = 0.5;
629	this.dx1 = 0.5;
630	this.dx2 = 0.5;
631	this.dy3 = 0.5;
632	this.dx3 = 0.5;
633
634	this.notch = 0;
635};
636
637/**
638* Extends mxShape.
639*/
640mxUtils.extend(mxShapeArrows2SharpArrow2, mxActor);
641
642mxShapeArrows2SharpArrow2.prototype.customProperties = [
643	{name: 'dx1', dispName: 'Arrowhead Arrow Width', type: 'float', min:0, defVal:18},
644	{name: 'dy1', dispName: 'Arrow Width', type: 'float', min:0, max:1, defVal:0.67},
645	{name: 'dx2', dispName: 'Arrowhead Angle', type: 'float', min:0, defVal:18},
646	{name: 'dx3', dispName: 'Arrowhead Edge X', type: 'float', min:0, defVal:27},
647	{name: 'dy3', dispName: 'Arrowhead Edge Y', type: 'float', min:0, max:1, defVal:0.15},
648	{name: 'notch', dispName: 'Notch', type: 'float', min:0, defVal:0}
649];
650
651mxShapeArrows2SharpArrow2.prototype.cst = {
652		SHARP_ARROW2 : 'mxgraph.arrows2.sharpArrow2'
653};
654
655/**
656* Function: paintVertexShape
657*
658* Paints the vertex shape.
659*/
660mxShapeArrows2SharpArrow2.prototype.paintVertexShape = function(c, x, y, w, h)
661{
662	c.translate(x, y);
663
664	var dy1 = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
665	var dx1 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
666	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
667	var dy3 = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy3', this.dy3))));
668	var dx3 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx3', this.dx3))));
669	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
670	var dx1a = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
671	var dy1a = h * 0.5 * Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
672
673	c.begin();
674	c.moveTo(0, dy1);
675	c.lineTo(w - dx1, dy1);
676	c.lineTo(w - dx3, dy3);
677	c.lineTo(w - dx2, 0);
678	c.lineTo(w, h * 0.5);
679	c.lineTo(w - dx2, h);
680	c.lineTo(w - dx3, h - dy3);
681	c.lineTo(w - dx1, h - dy1);
682	c.lineTo(0, h - dy1);
683	c.lineTo(notch, h * 0.5);
684	c.close();
685	c.fillAndStroke();
686};
687
688mxCellRenderer.registerShape(mxShapeArrows2SharpArrow2.prototype.cst.SHARP_ARROW2, mxShapeArrows2SharpArrow2);
689
690mxShapeArrows2SharpArrow2.prototype.constraints = null;
691
692Graph.handleFactory[mxShapeArrows2SharpArrow2.prototype.cst.SHARP_ARROW2] = function(state)
693{
694	var handles = [Graph.createHandle(state, ['dx1', 'dy1'], function(bounds)
695			{
696				var dx1 = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1))));
697				var dy1 = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1))));
698
699				return new mxPoint(bounds.x + bounds.width - dx1, bounds.y + dy1 * bounds.height / 2);
700			}, function(bounds, pt)
701			{
702				this.state.style['dx1'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.x + bounds.width - pt.x))) / 100;
703				this.state.style['dy1'] = Math.round(100 * Math.max(0, Math.min(1, (((pt.y - bounds.y) / bounds.height) * 2)))) / 100;
704			})];
705
706	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
707			{
708				var notch = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
709
710				return new mxPoint(bounds.x + notch, bounds.y + bounds.height / 2);
711			}, function(bounds, pt)
712			{
713				this.state.style['notch'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1)), pt.x - bounds.x))) / 100;
714			});
715
716	handles.push(handle2);
717
718	var handle3 = Graph.createHandle(state, ['dx2'], function(bounds)
719			{
720				var dx2 = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2))));
721
722				return new mxPoint(bounds.x + bounds.width - dx2, bounds.y);
723			}, function(bounds, pt)
724			{
725				this.state.style['dx2'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.x + bounds.width - pt.x))) / 100;
726			});
727
728	handles.push(handle3);
729
730	var handle4 = Graph.createHandle(state, ['dx3', 'dy3'], function(bounds)
731			{
732				var dx3 = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx3', this.dx3))));
733				var dy3 = Math.max(0, Math.min(1 - parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)) / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy3', this.dy3))));
734
735				return new mxPoint(bounds.x + bounds.width - dx3, bounds.y + dy3 * bounds.height / 2);
736			}, function(bounds, pt)
737			{
738				this.state.style['dx3'] = Math.round(100 * Math.max(parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2)), Math.min(bounds.width, bounds.x + bounds.width - pt.x))) / 100;
739				this.state.style['dy3'] = Math.round(100 * Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)), (((pt.y - bounds.y) / bounds.height) * 2)))) / 100;
740			});
741
742	handles.push(handle4);
743
744	return handles;
745};
746
747mxShapeArrows2SharpArrow2.prototype.getConstraints = function(style, w, h)
748{
749	var constr = [];
750	var dy1 = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
751	var dx1 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
752	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
753	var dy3 = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy3', this.dy3))));
754	var dx3 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx3', this.dx3))));
755	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
756	var dx1a = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
757	var dy1a = h * 0.5 * Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
758
759	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
760	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null, notch, 0));
761	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, dy1));
762	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx1, dy1));
763	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx3, dy3));
764	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx2, 0));
765	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - dy1));
766	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx1, h - dy1));
767	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx3, h - dy3));
768	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx2, h));
769	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx1) * 0.5, dy1));
770	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx1) * 0.5, h - dy1));
771
772	return (constr);
773};
774
775//**********************************************************************************************************************************************************
776//Callout Arrow
777//**********************************************************************************************************************************************************
778/**
779* Extends mxShape.
780*/
781function mxShapeArrows2CalloutArrow(bounds, fill, stroke, strokewidth)
782{
783	mxShape.call(this);
784	this.bounds = bounds;
785	this.fill = fill;
786	this.stroke = stroke;
787	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
788	this.dy = 0.5;
789	this.dx = 0.5;
790	this.notch = 0;
791	this.arrowHead = 0;
792};
793
794/**
795* Extends mxShape.
796*/
797mxUtils.extend(mxShapeArrows2CalloutArrow, mxActor);
798
799mxShapeArrows2CalloutArrow.prototype.customProperties = [
800	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:20},
801	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:10},
802	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, defVal:10},
803	{name: 'notch', dispName: 'Rectangle Width', type: 'float', min:0, defVal:60}
804];
805
806mxShapeArrows2CalloutArrow.prototype.cst = {
807		CALLOUT_ARROW : 'mxgraph.arrows2.calloutArrow'
808};
809
810/**
811* Function: paintVertexShape
812*
813* Paints the vertex shape.
814*/
815mxShapeArrows2CalloutArrow.prototype.paintVertexShape = function(c, x, y, w, h)
816{
817	c.translate(x, y);
818
819	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
820	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
821	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
822	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
823
824	c.begin();
825	c.moveTo(0, 0);
826	c.lineTo(notch, 0);
827	c.lineTo(notch, h * 0.5 - dy);
828	c.lineTo(w - dx, h * 0.5 - dy);
829	c.lineTo(w - dx, h * 0.5 - dy - arrowHead);
830	c.lineTo(w, h * 0.5);
831	c.lineTo(w - dx, h * 0.5 + dy + arrowHead);
832	c.lineTo(w - dx, h * 0.5 + dy);
833	c.lineTo(notch, h * 0.5 + dy);
834	c.lineTo(notch, h);
835	c.lineTo(0, h);
836	c.close();
837	c.fillAndStroke();
838};
839
840mxCellRenderer.registerShape(mxShapeArrows2CalloutArrow.prototype.cst.CALLOUT_ARROW, mxShapeArrows2CalloutArrow);
841
842mxShapeArrows2CalloutArrow.prototype.constraints = null;
843
844Graph.handleFactory[mxShapeArrows2CalloutArrow.prototype.cst.CALLOUT_ARROW] = function(state)
845{
846	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
847			{
848				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
849				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
850				var dy = Math.max(0, Math.min(bounds.height / 2 - arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
851
852				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + bounds.height / 2 - dy);
853			}, function(bounds, pt)
854			{
855				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.x + bounds.width - pt.x))) / 100;
856				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), bounds.y + bounds.height / 2 - pt.y))) / 100;
857
858			})];
859
860	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
861			{
862				var notch = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
863
864				return new mxPoint(bounds.x + notch, bounds.y + bounds.height / 2);
865			}, function(bounds, pt)
866			{
867				this.state.style['notch'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), pt.x - bounds.x))) / 100;
868			});
869
870	handles.push(handle2);
871
872	var handle3 = Graph.createHandle(state, ['arrowHead'], function(bounds)
873			{
874				var dx = 		Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
875				var dy =        Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
876				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
877
878				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + bounds.height / 2 - dy - arrowHead);
879			}, function(bounds, pt)
880			{
881			this.state.style['arrowHead'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), bounds.y + bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)) - pt.y))) / 100;
882			});
883
884	handles.push(handle3);
885
886	return handles;
887};
888
889mxShapeArrows2CalloutArrow.prototype.getConstraints = function(style, w, h)
890{
891	var constr = [];
892	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
893	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
894	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
895	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
896
897	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false));
898	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, notch, 0));
899	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null,notch, h * 0.5 - dy));
900	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h * 0.5 - dy));
901	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h * 0.5 - dy - arrowHead));
902	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, h * 0.5));
903	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h * 0.5 + dy + arrowHead));
904	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h * 0.5 + dy));
905	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, notch, h * 0.5 + dy));
906	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, notch, h));
907	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h));
908	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, notch * 0.5 , 0));
909	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, notch * 0.5 , h));
910	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null, (notch + w - dx) * 0.5, -dy));
911	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null, (notch + w - dx) * 0.5, dy));
912
913	return (constr);
914};
915
916//**********************************************************************************************************************************************************
917//Bend Arrow
918//**********************************************************************************************************************************************************
919/**
920* Extends mxShape.
921*/
922function mxShapeArrows2BendArrow(bounds, fill, stroke, strokewidth)
923{
924	mxShape.call(this);
925	this.bounds = bounds;
926	this.fill = fill;
927	this.stroke = stroke;
928	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
929	this.dy = 0.5;
930	this.dx = 0.5;
931	this.notch = 0;
932	this.arrowHead = 40;
933};
934
935/**
936* Extends mxShape.
937*/
938mxUtils.extend(mxShapeArrows2BendArrow, mxActor);
939
940mxShapeArrows2BendArrow.prototype.customProperties = [
941	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal: 38},
942	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, defVal: 15},
943	{name: 'notch', dispName: 'Notch', type: 'float', min:0, defVal: 0},
944	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:55},
945	{name: 'rounded', dispName: 'Rounded', type: 'boolean', defVal: false}
946];
947
948mxShapeArrows2BendArrow.prototype.cst = {
949		BEND_ARROW : 'mxgraph.arrows2.bendArrow'
950};
951
952/**
953* Function: paintVertexShape
954*
955* Paints the vertex shape.
956*/
957mxShapeArrows2BendArrow.prototype.paintVertexShape = function(c, x, y, w, h)
958{
959	c.translate(x, y);
960
961	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
962	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
963	var notch = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
964	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
965	var rounded = mxUtils.getValue(this.style, 'rounded', '0');
966
967	c.begin();
968	c.moveTo(w - dx, 0);
969	c.lineTo(w, arrowHead * 0.5);
970	c.lineTo(w - dx, arrowHead);
971	c.lineTo(w - dx, arrowHead / 2 + dy);
972
973	if (rounded == '1')
974	{
975		c.lineTo(dy * 2.2, arrowHead / 2 + dy);
976		c.arcTo(dy * 0.2, dy * 0.2, 0, 0, 0, dy * 2, arrowHead / 2 + dy * 1.2);
977	}
978	else
979	{
980		c.lineTo(dy * 2, arrowHead / 2 + dy);
981	}
982
983	c.lineTo(dy * 2, h);
984	c.lineTo(dy, h - notch);
985	c.lineTo(0, h);
986
987	if (rounded == '1')
988	{
989		c.lineTo(0, arrowHead / 2 + dy);
990		c.arcTo(dy * 2, dy * 2, 0, 0, 1, dy * 2, arrowHead / 2 - dy);
991	}
992	else
993	{
994		c.lineTo(0, arrowHead / 2 - dy);
995	}
996
997	c.lineTo(w - dx, arrowHead / 2 - dy);
998	c.close();
999	c.fillAndStroke();
1000};
1001
1002mxCellRenderer.registerShape(mxShapeArrows2BendArrow.prototype.cst.BEND_ARROW, mxShapeArrows2BendArrow);
1003
1004mxShapeArrows2BendArrow.prototype.constraints = null;
1005
1006Graph.handleFactory[mxShapeArrows2BendArrow.prototype.cst.BEND_ARROW] = function(state)
1007{
1008	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
1009			{
1010				var arrowHead = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1011				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1012				var dy = Math.max(0, Math.min(arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1013
1014				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + arrowHead / 2 - dy);
1015			}, function(bounds, pt)
1016			{
1017				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)) * 2.2, bounds.x + bounds.width - pt.x))) / 100;
1018				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2, bounds.y + parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2 - pt.y))) / 100;
1019
1020			})];
1021
1022	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
1023			{
1024				var arrowHead = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1025				var dy = Math.max(0, Math.min(arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1026
1027				var notch = Math.max(0, Math.min(bounds.height - arrowHead / 2 - dy, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
1028
1029				return new mxPoint(bounds.x + dy, bounds.y + bounds.height - notch);
1030			}, function(bounds, pt)
1031			{
1032				this.state.style['notch'] = Math.round(100 * Math.max(0, Math.min(bounds.height - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), bounds.y + bounds.height - pt.y))) / 100;
1033			});
1034
1035	handles.push(handle2);
1036
1037	var handle3 = Graph.createHandle(state, ['arrowHead'], function(bounds)
1038			{
1039				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1040				var arrowHead = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1041
1042				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + arrowHead);
1043			}, function(bounds, pt)
1044			{
1045				this.state.style['arrowHead'] = Math.round(100 * Math.max(2 * parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), Math.min(bounds.height, pt.y - bounds.y))) / 100;
1046			});
1047
1048	handles.push(handle3);
1049
1050	return handles;
1051};
1052
1053mxShapeArrows2BendArrow.prototype.getConstraints = function(style, w, h)
1054{
1055	var constr = [];
1056	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1057	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1058	var notch = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
1059	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1060	var rounded = mxUtils.getValue(this.style, 'rounded', '0');
1061
1062	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx + dy * 2) * 0.5, arrowHead / 2 - dy));
1063	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, arrowHead / 2 - dy));
1064	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, 0));
1065	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, arrowHead * 0.5));
1066	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, arrowHead));
1067	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, arrowHead / 2 + dy));
1068	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx + dy * 2) * 0.5, arrowHead / 2 + dy));
1069	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dy * 2, (h - arrowHead / 2 - dy) * 0.5 + arrowHead / 2 + dy));
1070	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dy * 2, h));
1071	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dy, h - notch));
1072	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h));
1073	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, (h - arrowHead / 2 - dy) * 0.5 + arrowHead / 2 + dy));
1074
1075	if (rounded == '1')
1076	{
1077		constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dy * 0.586, arrowHead / 2 - dy * 0.414));
1078		constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 2 * dy  + dy * 0.0586, arrowHead / 2 + dy + dy * 0.0586));
1079	}
1080	else
1081	{
1082		constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, arrowHead / 2 - dy));
1083		constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dy * 2, arrowHead / 2 + dy));
1084	}
1085
1086	return (constr);
1087};
1088
1089//**********************************************************************************************************************************************************
1090//Bend Double Arrow
1091//**********************************************************************************************************************************************************
1092/**
1093* Extends mxShape.
1094*/
1095function mxShapeArrows2BendDoubleArrow(bounds, fill, stroke, strokewidth)
1096{
1097	mxShape.call(this);
1098	this.bounds = bounds;
1099	this.fill = fill;
1100	this.stroke = stroke;
1101	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1102	this.dy = 0.5;
1103	this.dx = 0.5;
1104	this.notch = 0;
1105	this.arrowHead = 40;
1106};
1107
1108/**
1109* Extends mxShape.
1110*/
1111mxUtils.extend(mxShapeArrows2BendDoubleArrow, mxActor);
1112
1113mxShapeArrows2BendDoubleArrow.prototype.customProperties = [
1114	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:38},
1115	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, defVal:15},
1116	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:55},
1117	{name: 'rounded', dispName: 'Rounded', type: 'boolean', defVal:false}
1118];
1119
1120mxShapeArrows2BendDoubleArrow.prototype.cst = {
1121		BEND_DOUBLE_ARROW : 'mxgraph.arrows2.bendDoubleArrow'
1122};
1123
1124/**
1125* Function: paintVertexShape
1126*
1127* Paints the vertex shape.
1128*/
1129mxShapeArrows2BendDoubleArrow.prototype.paintVertexShape = function(c, x, y, w, h)
1130{
1131	c.translate(x, y);
1132
1133	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1134	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1135	var arrowHead = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1136	var rounded = mxUtils.getValue(this.style, 'rounded', '0');
1137
1138	c.begin();
1139	c.moveTo(w - dx, 0);
1140	c.lineTo(w, arrowHead * 0.5);
1141	c.lineTo(w - dx, arrowHead);
1142	c.lineTo(w - dx, arrowHead / 2 + dy);
1143
1144	if (rounded == '1')
1145	{
1146		c.lineTo(arrowHead / 2 + dy * 1.2, arrowHead / 2 + dy);
1147		c.arcTo(dy * 0.2, dy * 0.2, 0, 0, 0, arrowHead /2 + dy, arrowHead / 2 + dy * 1.2);
1148	}
1149	else
1150	{
1151		c.lineTo(arrowHead / 2 + dy, arrowHead / 2 + dy);
1152	}
1153
1154	c.lineTo(arrowHead / 2 + dy, h - dx);
1155	c.lineTo(arrowHead, h - dx);
1156	c.lineTo(arrowHead / 2, h);
1157	c.lineTo(0, h - dx);
1158	c.lineTo(arrowHead / 2 - dy, h - dx);
1159
1160	if (rounded == '1')
1161	{
1162		c.lineTo(arrowHead / 2 - dy, arrowHead / 2 + dy);
1163		c.arcTo(dy * 2, dy * 2, 0, 0, 1, arrowHead / 2 + dy, arrowHead / 2 - dy);
1164	}
1165	else
1166	{
1167		c.lineTo(arrowHead / 2 - dy, arrowHead / 2 - dy);
1168	}
1169
1170	c.lineTo(w - dx, arrowHead / 2 - dy);
1171	c.close();
1172	c.fillAndStroke();
1173};
1174
1175mxCellRenderer.registerShape(mxShapeArrows2BendDoubleArrow.prototype.cst.BEND_DOUBLE_ARROW, mxShapeArrows2BendDoubleArrow);
1176
1177mxShapeArrows2BendDoubleArrow.prototype.constraints = null;
1178
1179Graph.handleFactory[mxShapeArrows2BendDoubleArrow.prototype.cst.BEND_DOUBLE_ARROW] = function(state)
1180{
1181	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
1182			{
1183				var arrowHead = Math.max(0, Math.min(Math.min(bounds.height, bounds.width) - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1184				var dx = Math.max(0, Math.min(Math.min(bounds.width, bounds.height) - arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1185				var dy = Math.max(0, Math.min(arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1186
1187				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + arrowHead / 2 - dy);
1188			}, function(bounds, pt)
1189			{
1190				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(Math.min(bounds.width, bounds.height) - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), bounds.x + bounds.width - pt.x))) / 100;
1191				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2, bounds.y + parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2 - pt.y))) / 100;
1192
1193			})];
1194
1195	var handle2 = Graph.createHandle(state, ['arrowHead'], function(bounds)
1196			{
1197				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1198				var arrowHead = Math.max(0, Math.min(Math.min(bounds.height, bounds.width) - dx, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1199
1200				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + arrowHead);
1201			}, function(bounds, pt)
1202			{
1203				this.state.style['arrowHead'] = Math.round(100 * Math.max(2 * parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), Math.min(Math.min(bounds.height, bounds.width) - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), pt.y - bounds.y))) / 100;
1204			});
1205
1206	handles.push(handle2);
1207
1208	return handles;
1209};
1210
1211mxShapeArrows2BendDoubleArrow.prototype.getConstraints = function(style, w, h)
1212{
1213	var constr = [];
1214	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1215	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1216	var arrowHead = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1217	var rounded = mxUtils.getValue(this.style, 'rounded', '0');
1218
1219	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx , 0));
1220	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, arrowHead * 0.5));
1221	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, arrowHead));
1222	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, arrowHead / 2 + dy));
1223	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (arrowHead / 2 + dy + w - dx) * 0.5, arrowHead / 2 + dy));
1224	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (arrowHead / 2 + dy + w - dx) * 0.5, arrowHead / 2 - dy));
1225	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead / 2 + dy, (arrowHead / 2 + dy + h - dx) * 0.5));
1226	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead / 2 - dy, (arrowHead / 2 + dy + h - dx) * 0.5));
1227	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead / 2 + dy, h - dx));
1228	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead, h - dx));
1229	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead / 2, h));
1230	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - dx));
1231	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead / 2 - dy, h - dx));
1232
1233	if (rounded == '1')
1234	{
1235		constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead / 2 - dy * 0.414, arrowHead / 2 - dy * 0.414));
1236		constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead / 2 + dy + dy * 0.0586, arrowHead / 2 + dy + dy * 0.0586));
1237	}
1238	else
1239	{
1240		constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead / 2 - dy, arrowHead / 2 - dy));
1241		constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead / 2 + dy, arrowHead / 2 + dy));
1242	}
1243
1244	return (constr);
1245};
1246
1247//**********************************************************************************************************************************************************
1248//Callout Double Arrow
1249//**********************************************************************************************************************************************************
1250/**
1251* Extends mxShape.
1252*/
1253function mxShapeArrows2CalloutDoubleArrow(bounds, fill, stroke, strokewidth)
1254{
1255	mxShape.call(this);
1256	this.bounds = bounds;
1257	this.fill = fill;
1258	this.stroke = stroke;
1259	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1260	this.dy = 0.5;
1261	this.dx = 0.5;
1262	this.notch = 0;
1263	this.arrowHead = 0;
1264};
1265
1266/**
1267* Extends mxShape.
1268*/
1269mxUtils.extend(mxShapeArrows2CalloutDoubleArrow, mxActor);
1270
1271mxShapeArrows2CalloutDoubleArrow.prototype.customProperties = [
1272	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:20},
1273	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, defVal:10},
1274	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:10},
1275	{name: 'notch', dispName: 'Rect Size', type: 'float', min:0, defVal:24}
1276];
1277
1278mxShapeArrows2CalloutDoubleArrow.prototype.cst = {
1279		CALLOUT_DOUBLE_ARROW : 'mxgraph.arrows2.calloutDoubleArrow'
1280};
1281
1282/**
1283* Function: paintVertexShape
1284*
1285* Paints the vertex shape.
1286*/
1287mxShapeArrows2CalloutDoubleArrow.prototype.paintVertexShape = function(c, x, y, w, h)
1288{
1289	c.translate(x, y);
1290
1291	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1292	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1293	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
1294	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1295
1296	c.begin();
1297	c.moveTo(w / 2 - notch, 0);
1298	c.lineTo(w / 2 + notch, 0);
1299	c.lineTo(w / 2 + notch, h * 0.5 - dy);
1300	c.lineTo(w - dx, h * 0.5 - dy);
1301	c.lineTo(w - dx, h * 0.5 - dy - arrowHead);
1302	c.lineTo(w, h * 0.5);
1303	c.lineTo(w - dx, h * 0.5 + dy + arrowHead);
1304	c.lineTo(w - dx, h * 0.5 + dy);
1305	c.lineTo(w / 2 + notch, h * 0.5 + dy);
1306	c.lineTo(w / 2 + notch, h);
1307	c.lineTo(w / 2 - notch, h);
1308	c.lineTo(w / 2 - notch, h * 0.5 + dy);
1309	c.lineTo(dx, h * 0.5 + dy);
1310	c.lineTo(dx, h * 0.5 + dy + arrowHead);
1311	c.lineTo(0, h * 0.5);
1312	c.lineTo(dx, h * 0.5 - dy - arrowHead);
1313	c.lineTo(dx, h * 0.5 - dy);
1314	c.lineTo(w / 2 - notch, h * 0.5 - dy);
1315	c.close();
1316	c.fillAndStroke();
1317};
1318
1319mxCellRenderer.registerShape(mxShapeArrows2CalloutDoubleArrow.prototype.cst.CALLOUT_DOUBLE_ARROW, mxShapeArrows2CalloutDoubleArrow);
1320
1321mxShapeArrows2CalloutDoubleArrow.prototype.constraints = null;
1322
1323Graph.handleFactory[mxShapeArrows2CalloutDoubleArrow.prototype.cst.CALLOUT_DOUBLE_ARROW] = function(state)
1324{
1325	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
1326			{
1327				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1328				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1329				var dy = Math.max(0, Math.min(bounds.height / 2 - arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1330
1331				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + bounds.height / 2 - dy);
1332			}, function(bounds, pt)
1333			{
1334				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(bounds.width / 2 - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.x + bounds.width - pt.x))) / 100;
1335				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), bounds.y + bounds.height / 2 - pt.y))) / 100;
1336
1337			})];
1338
1339	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
1340			{
1341				var notch = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
1342
1343				return new mxPoint(bounds.x + bounds.width / 2 + notch, bounds.y + bounds.height / 2);
1344			}, function(bounds, pt)
1345			{
1346				this.state.style['notch'] = Math.round(100 * Math.max(0, Math.min(bounds.width / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), pt.x - bounds.x - bounds.width / 2))) / 100;
1347			});
1348
1349	handles.push(handle2);
1350
1351	var handle3 = Graph.createHandle(state, ['arrowHead'], function(bounds)
1352			{
1353				var dx = 		Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1354				var dy =        Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1355				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1356
1357				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + bounds.height / 2 - dy - arrowHead);
1358			}, function(bounds, pt)
1359			{
1360				this.state.style['arrowHead'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), bounds.y + bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)) - pt.y))) / 100;
1361			});
1362
1363	handles.push(handle3);
1364
1365	return handles;
1366};
1367
1368mxShapeArrows2CalloutDoubleArrow.prototype.getConstraints = function(style, w, h)
1369{
1370	var constr = [];
1371	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1372	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1373	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
1374	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1375
1376	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
1377	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
1378	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
1379	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
1380	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w / 2 - notch, 0));
1381	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w / 2 + notch, 0));
1382	constr.push(new mxConnectionConstraint(new mxPoint(0, 1), false, null, w / 2 - notch, 0));
1383	constr.push(new mxConnectionConstraint(new mxPoint(0, 1), false, null, w / 2 + notch, 0));
1384	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h * 0.5 - dy - arrowHead));
1385	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h * 0.5 + dy + arrowHead));
1386	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h * 0.5 - dy - arrowHead));
1387	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h * 0.5 + dy + arrowHead));
1388	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w * 1.5 - dx + notch) * 0.5, h * 0.5 - dy));
1389	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w * 1.5 - dx + notch) * 0.5, h * 0.5 + dy));
1390	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w * 0.5 + dx - notch) * 0.5, h * 0.5 - dy));
1391	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w * 0.5 + dx - notch) * 0.5, h * 0.5 + dy));
1392
1393	return (constr);
1394};
1395
1396//**********************************************************************************************************************************************************
1397//Callout Quad Arrow
1398//**********************************************************************************************************************************************************
1399/**
1400* Extends mxShape.
1401*/
1402function mxShapeArrows2CalloutQuadArrow(bounds, fill, stroke, strokewidth)
1403{
1404	mxShape.call(this);
1405	this.bounds = bounds;
1406	this.fill = fill;
1407	this.stroke = stroke;
1408	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1409	this.dy = 0.5;
1410	this.dx = 0.5;
1411	this.notch = 0;
1412	this.arrowHead = 0;
1413};
1414
1415/**
1416* Extends mxShape.
1417*/
1418mxUtils.extend(mxShapeArrows2CalloutQuadArrow, mxActor);
1419
1420mxShapeArrows2CalloutQuadArrow.prototype.customProperties = [
1421	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:20},
1422	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, defVal: 10},
1423	{name: 'notch', dispName: 'Rect Size', type: 'float', min:0, defVal:24},
1424	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:10}
1425];
1426
1427mxShapeArrows2CalloutQuadArrow.prototype.cst = {
1428		CALLOUT_QUAD_ARROW : 'mxgraph.arrows2.calloutQuadArrow'
1429};
1430
1431/**
1432* Function: paintVertexShape
1433*
1434* Paints the vertex shape.
1435*/
1436mxShapeArrows2CalloutQuadArrow.prototype.paintVertexShape = function(c, x, y, w, h)
1437{
1438	c.translate(x, y);
1439
1440	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1441	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1442	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
1443	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1444
1445	c.begin();
1446	c.moveTo(w * 0.5 + dy, h * 0.5 - notch);
1447	c.lineTo(w * 0.5 + notch, h * 0.5 - notch);
1448	c.lineTo(w * 0.5 + notch, h * 0.5 - dy);
1449	c.lineTo(w - dx, h * 0.5 - dy);
1450	c.lineTo(w - dx, h * 0.5 - dy - arrowHead);
1451	c.lineTo(w, h * 0.5);
1452	c.lineTo(w - dx, h * 0.5 + dy + arrowHead);
1453	c.lineTo(w - dx, h * 0.5 + dy);
1454	c.lineTo(w * 0.5 + notch, h * 0.5 + dy);
1455	c.lineTo(w * 0.5 + notch, h * 0.5 + notch);
1456	c.lineTo(w * 0.5 + dy, h * 0.5 + notch);
1457	c.lineTo(w * 0.5 + dy, h - dx);
1458	c.lineTo(w * 0.5 + dy + arrowHead, h - dx);
1459	c.lineTo(w * 0.5, h);
1460	c.lineTo(w * 0.5 - dy - arrowHead, h - dx);
1461	c.lineTo(w * 0.5 - dy, h - dx);
1462	c.lineTo(w * 0.5 - dy, h * 0.5 + notch);
1463	c.lineTo(w * 0.5 - notch, h * 0.5 + notch);
1464	c.lineTo(w * 0.5 - notch, h * 0.5 + dy);
1465	c.lineTo(dx, h * 0.5 + dy);
1466	c.lineTo(dx, h * 0.5 + dy + arrowHead);
1467	c.lineTo(0, h * 0.5);
1468	c.lineTo(dx, h * 0.5 - dy - arrowHead);
1469	c.lineTo(dx, h * 0.5 - dy);
1470	c.lineTo(w * 0.5 - notch, h * 0.5 - dy);
1471	c.lineTo(w * 0.5 - notch, h * 0.5 - notch);
1472	c.lineTo(w * 0.5 - dy, h * 0.5 - notch);
1473	c.lineTo(w * 0.5 - dy, dx);
1474	c.lineTo(w * 0.5 - dy - arrowHead, dx);
1475	c.lineTo(w * 0.5, 0);
1476	c.lineTo(w * 0.5 + dy + arrowHead, dx);
1477	c.lineTo(w * 0.5 + dy, dx);
1478	c.close();
1479	c.fillAndStroke();
1480};
1481
1482mxCellRenderer.registerShape(mxShapeArrows2CalloutQuadArrow.prototype.cst.CALLOUT_QUAD_ARROW, mxShapeArrows2CalloutQuadArrow);
1483
1484mxShapeArrows2CalloutQuadArrow.prototype.constraints = null;
1485
1486Graph.handleFactory[mxShapeArrows2CalloutQuadArrow.prototype.cst.CALLOUT_QUAD_ARROW] = function(state)
1487{
1488	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
1489			{
1490				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1491				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1492				var dy = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1493
1494				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + bounds.height / 2 - dy);
1495			}, function(bounds, pt)
1496			{
1497				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(Math.min(bounds.width, bounds.height) / 2 - Math.max(parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))), bounds.x + bounds.width - pt.x))) / 100;
1498				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.y + bounds.height / 2 - pt.y))) / 100;
1499
1500			})];
1501
1502	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
1503			{
1504				var notch = Math.max(parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), Math.min(Math.min(bounds.width, bounds.height), parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
1505
1506				return new mxPoint(bounds.x + bounds.width / 2 + notch, bounds.y + bounds.height / 2);
1507			}, function(bounds, pt)
1508			{
1509				this.state.style['notch'] = Math.round(100 * Math.max(parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), Math.min(Math.min(bounds.width, bounds.height) / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), pt.x - bounds.x - bounds.width / 2))) / 100;
1510			});
1511
1512	handles.push(handle2);
1513
1514	var handle3 = Graph.createHandle(state, ['arrowHead'], function(bounds)
1515			{
1516				var dx = 		Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1517				var dy =        Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1518				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1519
1520				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + bounds.height / 2 - dy - arrowHead);
1521			}, function(bounds, pt)
1522			{
1523				this.state.style['arrowHead'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), bounds.y + bounds.height / 2 - pt.y))) / 100;
1524			});
1525
1526	handles.push(handle3);
1527
1528	return handles;
1529};
1530
1531mxShapeArrows2CalloutQuadArrow.prototype.getConstraints = function(style, w, h)
1532{
1533	var constr = [];
1534	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1535	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1536	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
1537	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1538
1539	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
1540	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
1541	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
1542	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
1543	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + dy, h * 0.5 - notch));
1544	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + notch, h * 0.5 - notch));
1545	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + notch, h * 0.5 - dy));
1546	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + dy, h * 0.5 + notch));
1547	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + notch, h * 0.5 + notch));
1548	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + notch, h * 0.5 + dy));
1549	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - dy, h * 0.5 + notch));
1550	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - notch, h * 0.5 + notch));
1551	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - notch, h * 0.5 + dy));
1552	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - dy, h * 0.5 - notch));
1553	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - notch, h * 0.5 - notch));
1554	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - notch, h * 0.5 - dy));
1555	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h * 0.5 - dy - arrowHead));
1556	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h * 0.5 + dy + arrowHead));
1557	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - dy - arrowHead, h - dx));
1558	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + dy + arrowHead, h - dx));
1559	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h * 0.5 - dy - arrowHead));
1560	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h * 0.5 + dy + arrowHead));
1561	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - dy - arrowHead, dx));
1562	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + dy + arrowHead, dx));
1563	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.75 + (notch - dx) * 0.5, h * 0.5 - dy));
1564	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.75 + (notch - dx) * 0.5, h * 0.5 + dy));
1565	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - dy, h * 0.75 + (notch - dx) * 0.5));
1566	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + dy, h * 0.75 + (notch - dx) * 0.5));
1567	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.25 - (notch - dx) * 0.5, h * 0.5 - dy));
1568	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.25 - (notch - dx) * 0.5, h * 0.5 + dy));
1569	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - dy, h * 0.25 - (notch - dx) * 0.5));
1570	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + dy, h * 0.25 - (notch - dx) * 0.5));
1571
1572	return (constr);
1573};
1574
1575//**********************************************************************************************************************************************************
1576//Callout Double 90 Arrow
1577//**********************************************************************************************************************************************************
1578/**
1579* Extends mxShape.
1580*/
1581function mxShapeArrows2CalloutDouble90Arrow(bounds, fill, stroke, strokewidth)
1582{
1583	mxShape.call(this);
1584	this.bounds = bounds;
1585	this.fill = fill;
1586	this.stroke = stroke;
1587	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1588	this.dy1 = 0.5;
1589	this.dx1 = 0.5;
1590	this.dx2 = 0;
1591	this.dy2 = 0;
1592	this.arrowHead = 0;
1593};
1594
1595/**
1596* Extends mxShape.
1597*/
1598mxUtils.extend(mxShapeArrows2CalloutDouble90Arrow, mxActor);
1599
1600mxShapeArrows2CalloutDouble90Arrow.prototype.customProperties = [
1601	{name: 'dx1', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:20},
1602	{name: 'dy1', dispName: 'Arrow Width', type: 'float', min:0, defVal: 10},
1603	{name: 'dx2', dispName: 'Callout Width', type: 'float', min:0, defVal:70},
1604	{name: 'dy2', dispName: 'Callout Height', type: 'float', min:0, defVal:70},
1605	{name: 'arrowHead', dispName: 'ArrowHead Width', type: 'float', min:0, defVal:10}
1606];
1607
1608mxShapeArrows2CalloutDouble90Arrow.prototype.cst = {
1609		CALLOUT_DOUBLE_90_ARROW : 'mxgraph.arrows2.calloutDouble90Arrow'
1610};
1611
1612/**
1613* Function: paintVertexShape
1614*
1615* Paints the vertex shape.
1616*/
1617mxShapeArrows2CalloutDouble90Arrow.prototype.paintVertexShape = function(c, x, y, w, h)
1618{
1619	c.translate(x, y);
1620
1621	var dy1 = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
1622	var dx1 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
1623	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
1624	var dy2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dy2', this.dy2))));
1625	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1626
1627	c.begin();
1628	c.moveTo(0, 0);
1629	c.lineTo(dx2, 0);
1630	c.lineTo(dx2, dy2 * 0.5 - dy1);
1631	c.lineTo(w - dx1, dy2 * 0.5 - dy1);
1632	c.lineTo(w - dx1, dy2 * 0.5 - dy1 - arrowHead);
1633	c.lineTo(w, dy2 * 0.5);
1634	c.lineTo(w - dx1, dy2 * 0.5 + dy1 + arrowHead);
1635	c.lineTo(w - dx1, dy2 * 0.5 + dy1);
1636	c.lineTo(dx2, dy2 * 0.5 + dy1);
1637	c.lineTo(dx2, dy2);
1638	c.lineTo(dx2 / 2 + dy1, dy2);
1639	c.lineTo(dx2 / 2 + dy1, h - dx1);
1640	c.lineTo(dx2 / 2 + dy1 + arrowHead, h - dx1);
1641	c.lineTo(dx2 / 2, h);
1642	c.lineTo(dx2 / 2 - dy1 - arrowHead, h - dx1);
1643	c.lineTo(dx2 / 2 - dy1, h - dx1);
1644	c.lineTo(dx2 / 2 - dy1, dy2);
1645	c.lineTo(0, dy2);
1646	c.close();
1647	c.fillAndStroke();
1648};
1649
1650mxCellRenderer.registerShape(mxShapeArrows2CalloutDouble90Arrow.prototype.cst.CALLOUT_DOUBLE_90_ARROW, mxShapeArrows2CalloutDouble90Arrow);
1651
1652mxShapeArrows2CalloutDouble90Arrow.prototype.constraints = null;
1653
1654Graph.handleFactory[mxShapeArrows2CalloutDouble90Arrow.prototype.cst.CALLOUT_DOUBLE_90_ARROW] = function(state)
1655{
1656	var handles = [Graph.createHandle(state, ['dx1', 'dy1'], function(bounds)
1657			{
1658				var arrowHead = Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1659				var dx1 = Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2)), parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1))));
1660				var dy1 = Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) / 2 - arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1))));
1661
1662				return new mxPoint(bounds.x + bounds.width - dx1, bounds.y + parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) / 2 - dy1);
1663			}, function(bounds, pt)
1664			{
1665				this.state.style['dx1'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2)), bounds.height - parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)), bounds.x + bounds.width - pt.x))) / 100;
1666				this.state.style['dy1'] = Math.round(100 * Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) / 2 - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), bounds.y + parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) / 2 - pt.y))) / 100;
1667
1668			})];
1669
1670	var handle2 = Graph.createHandle(state, ['dx2', 'dy2'], function(bounds)
1671			{
1672				var dx2 = Math.max(parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)) + parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1)), parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2))));
1673				var dy2 = Math.max(parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)) + parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), Math.min(bounds.height - parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)), parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2))));
1674
1675				return new mxPoint(bounds.x + dx2, bounds.y + dy2);
1676			}, function(bounds, pt)
1677			{
1678				this.state.style['dx2'] = Math.round(100 * Math.max(parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)) + parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1)), pt.x - bounds.x))) / 100;
1679				this.state.style['dy2'] = Math.round(100 * Math.max(parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)) + parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), Math.min(bounds.height - parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1)), pt.y - bounds.y))) / 100;
1680			});
1681
1682	handles.push(handle2);
1683
1684	var handle3 = Graph.createHandle(state, ['arrowHead'], function(bounds)
1685			{
1686				var dx1 = 		Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1))));
1687				var dy1 =        Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1))));
1688				var arrowHead = Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1689
1690				return new mxPoint(bounds.x + bounds.width - dx1, bounds.y + parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) / 2 - dy1 - arrowHead);
1691			}, function(bounds, pt)
1692			{
1693				this.state.style['arrowHead'] = Math.round(100 * Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)), bounds.y + parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)) - pt.y))) / 100;
1694			});
1695
1696	handles.push(handle3);
1697
1698	return handles;
1699};
1700
1701mxShapeArrows2CalloutDouble90Arrow.prototype.getConstraints = function(style, w, h)
1702{
1703	var constr = [];
1704	var dy1 = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
1705	var dx1 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
1706	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
1707	var dy2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dy2', this.dy2))));
1708	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1709
1710	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false));
1711	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2 * 0.5, 0));
1712	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2, 0));
1713	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx1 + dx2) * 0.5, dy2 * 0.5 - dy1));
1714	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx1, dy2 * 0.5 - dy1 - arrowHead));
1715	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, dy2 * 0.5));
1716	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx1, dy2 * 0.5 + dy1 + arrowHead));
1717	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx1 + dx2) * 0.5, dy2 * 0.5 + dy1));
1718	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2, dy2));
1719	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2 * 0.5 + dy1, (h - dx1 + dy2) * 0.5));
1720	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2 * 0.5 - dy1, (h - dx1 + dy2) * 0.5));
1721	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2 / 2 + dy1 + arrowHead, h - dx1));
1722	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2 / 2, h));
1723	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2 / 2 - dy1 - arrowHead, h - dx1));
1724	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, dy2));
1725
1726	return (constr);
1727};
1728
1729//**********************************************************************************************************************************************************
1730//Quad Arrow
1731//**********************************************************************************************************************************************************
1732/**
1733* Extends mxShape.
1734*/
1735function mxShapeArrows2QuadArrow(bounds, fill, stroke, strokewidth)
1736{
1737	mxShape.call(this);
1738	this.bounds = bounds;
1739	this.fill = fill;
1740	this.stroke = stroke;
1741	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1742	this.dy = 0.5;
1743	this.dx = 0.5;
1744	this.notch = 0;
1745	this.arrowHead = 0;
1746};
1747
1748/**
1749* Extends mxShape.
1750*/
1751mxUtils.extend(mxShapeArrows2QuadArrow, mxActor);
1752
1753mxShapeArrows2QuadArrow.prototype.customProperties = [
1754	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:20},
1755	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, defVal:10},
1756	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:10}
1757];
1758
1759mxShapeArrows2QuadArrow.prototype.cst = {
1760		QUAD_ARROW : 'mxgraph.arrows2.quadArrow'
1761};
1762
1763/**
1764* Function: paintVertexShape
1765*
1766* Paints the vertex shape.
1767*/
1768mxShapeArrows2QuadArrow.prototype.paintVertexShape = function(c, x, y, w, h)
1769{
1770	c.translate(x, y);
1771
1772	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1773	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1774	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1775
1776	c.begin();
1777	c.moveTo(w * 0.5 + dy, h * 0.5 - dy);
1778	c.lineTo(w - dx, h * 0.5 - dy);
1779	c.lineTo(w - dx, h * 0.5 - dy - arrowHead);
1780	c.lineTo(w, h * 0.5);
1781	c.lineTo(w - dx, h * 0.5 + dy + arrowHead);
1782	c.lineTo(w - dx, h * 0.5 + dy);
1783	c.lineTo(w * 0.5 + dy, h * 0.5 + dy);
1784	c.lineTo(w * 0.5 + dy, h - dx);
1785	c.lineTo(w * 0.5 + dy + arrowHead, h - dx);
1786	c.lineTo(w * 0.5, h);
1787	c.lineTo(w * 0.5 - dy - arrowHead, h - dx);
1788	c.lineTo(w * 0.5 - dy, h - dx);
1789	c.lineTo(w * 0.5 - dy, h * 0.5 + dy);
1790	c.lineTo(dx, h * 0.5 + dy);
1791	c.lineTo(dx, h * 0.5 + dy + arrowHead);
1792	c.lineTo(0, h * 0.5);
1793	c.lineTo(dx, h * 0.5 - dy - arrowHead);
1794	c.lineTo(dx, h * 0.5 - dy);
1795	c.lineTo(w * 0.5 - dy, h * 0.5 - dy);
1796	c.lineTo(w * 0.5 - dy, dx);
1797	c.lineTo(w * 0.5 - dy - arrowHead, dx);
1798	c.lineTo(w * 0.5, 0);
1799	c.lineTo(w * 0.5 + dy + arrowHead, dx);
1800	c.lineTo(w * 0.5 + dy, dx);
1801	c.close();
1802	c.fillAndStroke();
1803};
1804
1805mxCellRenderer.registerShape(mxShapeArrows2QuadArrow.prototype.cst.QUAD_ARROW, mxShapeArrows2QuadArrow);
1806
1807mxShapeArrows2QuadArrow.prototype.constraints = null;
1808
1809Graph.handleFactory[mxShapeArrows2QuadArrow.prototype.cst.QUAD_ARROW] = function(state)
1810{
1811	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
1812			{
1813				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1814				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1815				var dy = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1816
1817				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + bounds.height / 2 - dy);
1818			}, function(bounds, pt)
1819			{
1820				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(Math.min(bounds.width, bounds.height) / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)) - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), bounds.x + bounds.width - pt.x))) / 100;
1821				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), bounds.y + bounds.height / 2 - pt.y))) / 100;
1822
1823			})];
1824
1825	var handle2 = Graph.createHandle(state, ['arrowHead'], function(bounds)
1826			{
1827				var dx = 		Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1828				var dy =        Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1829				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1830
1831				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + bounds.height / 2 - dy - arrowHead);
1832			}, function(bounds, pt)
1833			{
1834				this.state.style['arrowHead'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), bounds.y + bounds.height / 2 - pt.y))) / 100;
1835			});
1836
1837	handles.push(handle2);
1838
1839	return handles;
1840};
1841
1842mxShapeArrows2QuadArrow.prototype.getConstraints = function(style, w, h)
1843{
1844	var constr = [];
1845	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1846	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1847	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1848
1849	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
1850	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
1851	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
1852	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
1853	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h * 0.5 - dy - arrowHead));
1854	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h * 0.5 + dy + arrowHead));
1855	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h * 0.5 - dy - arrowHead));
1856	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h * 0.5 + dy + arrowHead));
1857	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - dy - arrowHead, dx));
1858	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + dy + arrowHead, dx));
1859	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - dy - arrowHead, h - dx));
1860	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + dy + arrowHead, h - dx));
1861	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - dy, (dx - dy) * 0.5 + h * 0.25));
1862	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + dy, (dx - dy) * 0.5 + h * 0.25));
1863	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - dy, (dy - dx) * 0.5 + h * 0.75));
1864	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + dy, (dy - dx) * 0.5 + h * 0.75));
1865	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (dx - dy) * 0.5 + w * 0.25, h * 0.5 - dy));
1866	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (dx - dy) * 0.5 + w * 0.25, h * 0.5 + dy));
1867	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (dy - dx) * 0.5 + w * 0.75, h * 0.5 - dy));
1868	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (dy - dx) * 0.5 + w * 0.75, h * 0.5 + dy));
1869
1870	return (constr);
1871};
1872
1873//**********************************************************************************************************************************************************
1874//Triad Arrow
1875//**********************************************************************************************************************************************************
1876/**
1877* Extends mxShape.
1878*/
1879function mxShapeArrows2TriadArrow(bounds, fill, stroke, strokewidth)
1880{
1881	mxShape.call(this);
1882	this.bounds = bounds;
1883	this.fill = fill;
1884	this.stroke = stroke;
1885	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1886	this.dy = 0.5;
1887	this.dx = 0.5;
1888	this.arrowHead = 0;
1889};
1890
1891/**
1892* Extends mxShape.
1893*/
1894mxUtils.extend(mxShapeArrows2TriadArrow, mxActor);
1895
1896mxShapeArrows2TriadArrow.prototype.customProperties = [
1897	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:20},
1898	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, defVal:10},
1899	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:40}
1900];
1901
1902mxShapeArrows2TriadArrow.prototype.cst = {
1903		TRIAD_ARROW : 'mxgraph.arrows2.triadArrow'
1904};
1905
1906/**
1907* Function: paintVertexShape
1908*
1909* Paints the vertex shape.
1910*/
1911mxShapeArrows2TriadArrow.prototype.paintVertexShape = function(c, x, y, w, h)
1912{
1913	c.translate(x, y);
1914
1915	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1916	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1917	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1918
1919	c.begin();
1920	c.moveTo(w * 0.5 + arrowHead * 0.5 - dy, h - arrowHead + dy);
1921	c.lineTo(w - dx, h - arrowHead + dy);
1922	c.lineTo(w - dx, h - arrowHead);
1923	c.lineTo(w, h - arrowHead * 0.5);
1924	c.lineTo(w - dx, h);
1925	c.lineTo(w - dx, h - dy);
1926	c.lineTo(dx, h - dy);
1927	c.lineTo(dx, h);
1928	c.lineTo(0, h - arrowHead * 0.5);
1929	c.lineTo(dx, h - arrowHead);
1930	c.lineTo(dx, h - arrowHead + dy);
1931	c.lineTo(w * 0.5 - arrowHead * 0.5 + dy, h - arrowHead + dy);
1932	c.lineTo(w * 0.5 - arrowHead * 0.5 + dy, dx);
1933	c.lineTo(w * 0.5 - arrowHead * 0.5, dx);
1934	c.lineTo(w * 0.5, 0);
1935	c.lineTo(w * 0.5 + arrowHead * 0.5, dx);
1936	c.lineTo(w * 0.5 + arrowHead * 0.5 - dy, dx);
1937	c.close();
1938	c.fillAndStroke();
1939};
1940
1941mxCellRenderer.registerShape(mxShapeArrows2TriadArrow.prototype.cst.TRIAD_ARROW, mxShapeArrows2TriadArrow);
1942
1943mxShapeArrows2TriadArrow.prototype.constraints = null;
1944
1945Graph.handleFactory[mxShapeArrows2TriadArrow.prototype.cst.TRIAD_ARROW] = function(state)
1946{
1947	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
1948			{
1949				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1950				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1951				var dy = Math.max(0, Math.min(arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1952
1953				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + bounds.height - dy);
1954			}, function(bounds, pt)
1955			{
1956				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(Math.min(bounds.height - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), bounds.width / 2 - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2), bounds.x + bounds.width - pt.x))) / 100;
1957				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2, bounds.y + bounds.height - pt.y))) / 100;
1958
1959			})];
1960
1961	var handle2 = Graph.createHandle(state, ['arrowHead'], function(bounds)
1962			{
1963				var dx = 		Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1964				var dy =        Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1965				var arrowHead = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
1966
1967				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + bounds.height - arrowHead);
1968			}, function(bounds, pt)
1969			{
1970				this.state.style['arrowHead'] = Math.round(100 * Math.max(2 * parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), Math.min(bounds.height - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)) * 2, bounds.y + bounds.height - pt.y))) / 100;
1971			});
1972
1973	handles.push(handle2);
1974
1975	return handles;
1976};
1977
1978mxShapeArrows2TriadArrow.prototype.getConstraints = function(style, w, h)
1979{
1980	var constr = [];
1981	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1982	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1983	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
1984
1985	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false, null, - arrowHead * 0.5, dx));
1986	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
1987	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5, h - dy));
1988	constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false, null, arrowHead * 0.5, dx));
1989	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h - arrowHead));
1990	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, h - arrowHead * 0.5));
1991	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h));
1992	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h - arrowHead));
1993	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - arrowHead * 0.5));
1994	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h));
1995	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w * 1.5 - dx + arrowHead * 0.5 - dy) * 0.5, h - arrowHead + dy));
1996	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w * 1.5 - dx + arrowHead * 0.5 - dy) * 0.5, h - dy));
1997	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w * 0.5 + dx - arrowHead * 0.5 + dy) * 0.5, h - arrowHead + dy));
1998	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w * 0.5 + dx - arrowHead * 0.5 + dy) * 0.5, h - dy));
1999	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 - arrowHead * 0.5 + dy, (dx + h - arrowHead + dy) * 0.5));
2000	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5 + arrowHead * 0.5 - dy, (dx + h - arrowHead + dy) * 0.5));
2001
2002	return (constr);
2003};
2004
2005//**********************************************************************************************************************************************************
2006//Tailed Arrow
2007//**********************************************************************************************************************************************************
2008/**
2009* Extends mxShape.
2010*/
2011function mxShapeArrows2TailedArrow(bounds, fill, stroke, strokewidth)
2012{
2013	mxShape.call(this);
2014	this.bounds = bounds;
2015	this.fill = fill;
2016	this.stroke = stroke;
2017	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
2018	this.dy = 0.5;
2019	this.dx = 0.5;
2020	this.notch = 0;
2021	this.arrowHead = 0;
2022};
2023
2024/**
2025* Extends mxShape.
2026*/
2027mxUtils.extend(mxShapeArrows2TailedArrow, mxActor);
2028
2029mxShapeArrows2TailedArrow.prototype.customProperties = [
2030	{name: 'dx1', dispName: 'Arrowhead Length', type: 'float', min:0, defVal: 20},
2031	{name: 'dy1', dispName: 'Arrow Width', type: 'float', min:0, defVal: 10},
2032	{name: 'dx2', dispName: 'Tail Length', type: 'float', min:0, defVal: 25},
2033	{name: 'dy2', dispName: 'Tail Width', type: 'float', min:0, defVal:30},
2034	{name: 'notch', dispName: 'Notch', type: 'float', min:0, defVal: 0},
2035	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:20}
2036];
2037
2038mxShapeArrows2TailedArrow.prototype.cst = {
2039		TAILED_ARROW : 'mxgraph.arrows2.tailedArrow'
2040};
2041
2042/**
2043* Function: paintVertexShape
2044*
2045* Paints the vertex shape.
2046*/
2047mxShapeArrows2TailedArrow.prototype.paintVertexShape = function(c, x, y, w, h)
2048{
2049	c.translate(x, y);
2050
2051	var dy1 = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
2052	var dx1 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
2053	var dy2 = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy2', this.dy2))));
2054	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
2055	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
2056	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
2057	var x2 = 0;
2058
2059	if (dy2 != 0)
2060	{
2061		x2 = dx2 + dy2 * (dy2 - dy1) / dy2;
2062	}
2063
2064	c.begin();
2065	c.moveTo(0, h * 0.5 - dy2);
2066	c.lineTo(dx2, h * 0.5 - dy2);
2067	c.lineTo(x2, h * 0.5 - dy1);
2068	c.lineTo(w - dx1, h * 0.5 - dy1);
2069	c.lineTo(w - dx1, h * 0.5 - dy1 - arrowHead);
2070	c.lineTo(w, h * 0.5);
2071	c.lineTo(w - dx1, h * 0.5 + dy1 + arrowHead);
2072	c.lineTo(w - dx1, h * 0.5 + dy1);
2073	c.lineTo(x2, h * 0.5 + dy1);
2074	c.lineTo(dx2, h * 0.5 + dy2);
2075	c.lineTo(0, h * 0.5 + dy2);
2076	c.lineTo(notch, h * 0.5);
2077	c.close();
2078	c.fillAndStroke();
2079};
2080
2081mxCellRenderer.registerShape(mxShapeArrows2TailedArrow.prototype.cst.TAILED_ARROW, mxShapeArrows2TailedArrow);
2082
2083mxShapeArrows2TailedArrow.prototype.constraints = null;
2084
2085Graph.handleFactory[mxShapeArrows2TailedArrow.prototype.cst.TAILED_ARROW] = function(state)
2086{
2087	var handles = [Graph.createHandle(state, ['dx1', 'dy1'], function(bounds)
2088			{
2089				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
2090				var dx1 = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1))));
2091				var dy1 = Math.max(0, Math.min(bounds.height / 2 - arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1))));
2092
2093				return new mxPoint(bounds.x + bounds.width - dx1, bounds.y + bounds.height / 2 - dy1);
2094			}, function(bounds, pt)
2095			{
2096				this.state.style['dx1'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2)), bounds.x + bounds.width - pt.x))) / 100;
2097				this.state.style['dy1'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)), bounds.y + bounds.height / 2 - pt.y))) / 100;
2098
2099			})];
2100
2101	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
2102			{
2103				var notch = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
2104
2105				return new mxPoint(bounds.x + notch, bounds.y + bounds.height / 2);
2106			}, function(bounds, pt)
2107			{
2108				this.state.style['notch'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1)), parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2)), pt.x - bounds.x))) / 100;
2109			});
2110
2111	handles.push(handle2);
2112
2113	var handle3 = Graph.createHandle(state, ['arrowHead'], function(bounds)
2114			{
2115				var dx1 = 		Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1))));
2116				var dy1 =        Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1))));
2117				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
2118
2119				return new mxPoint(bounds.x + bounds.width - dx1, bounds.y + bounds.height / 2 - dy1 - arrowHead);
2120			}, function(bounds, pt)
2121			{
2122				this.state.style['arrowHead'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)), bounds.y + bounds.height / 2 - pt.y))) / 100;
2123			});
2124
2125	handles.push(handle3);
2126
2127	var handle4 = Graph.createHandle(state, ['dx2', 'dy2'], function(bounds)
2128			{
2129				var dx2 = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2))));
2130				var dy2 = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2))));
2131
2132				return new mxPoint(bounds.x + dx2, bounds.y + bounds.height / 2 - dy2);
2133			}, function(bounds, pt)
2134			{
2135				this.state.style['dx2'] = Math.round(100 * Math.max(parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1)) - parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)) + parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)) - 1, pt.x - bounds.x))) / 100;
2136				this.state.style['dy2'] = Math.round(100 * Math.max(parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)), Math.min(bounds.height / 2, bounds.y + bounds.height / 2 - pt.y))) / 100;
2137
2138			});
2139
2140	handles.push(handle4);
2141
2142	return handles;
2143};
2144
2145mxShapeArrows2TailedArrow.prototype.getConstraints = function(style, w, h)
2146{
2147	var constr = [];
2148	var dy1 = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
2149	var dx1 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
2150	var dy2 = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy2', this.dy2))));
2151	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
2152	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
2153	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
2154	var x2 = 0;
2155
2156	if (dy2 != 0)
2157	{
2158		x2 = dx2 + dy2 * (dy2 - dy1) / dy2;
2159	}
2160
2161	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null, notch, 0));
2162	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h * 0.5 - dy2));
2163	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2, h * 0.5 - dy2));
2164	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx1 + x2) * 0.5, h * 0.5 - dy1));
2165	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx1, h * 0.5 - dy1 - arrowHead));
2166	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h * 0.5 + dy2));
2167	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2, h * 0.5 + dy2));
2168	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx1 + x2) * 0.5, h * 0.5 + dy1));
2169	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx1, h * 0.5 + dy1 + arrowHead));
2170	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
2171
2172	return (constr);
2173};
2174
2175//**********************************************************************************************************************************************************
2176//Tailed Arrow with Notch
2177//**********************************************************************************************************************************************************
2178/**
2179* Extends mxShape.
2180*/
2181function mxShapeArrows2TailedNotchedArrow(bounds, fill, stroke, strokewidth)
2182{
2183	mxShape.call(this);
2184	this.bounds = bounds;
2185	this.fill = fill;
2186	this.stroke = stroke;
2187	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
2188	this.dy = 0.5;
2189	this.dx = 0.5;
2190	this.notch = 0;
2191	this.arrowHead = 0;
2192};
2193
2194/**
2195* Extends mxShape.
2196*/
2197mxUtils.extend(mxShapeArrows2TailedNotchedArrow, mxActor);
2198
2199mxShapeArrows2TailedNotchedArrow.prototype.customProperties = [
2200	{name: 'dx1', dispName: 'Arrowhead Length', type: 'float', mix:0, defVal:20},
2201	{name: 'dy1', dispName: 'Arrow Width', type: 'float', min:0, defVal:10},
2202	{name: 'dx2', dispName: 'Tail Length', type: 'float', min:0, defVal:25},
2203	{name: 'dy2', dispName: 'Tail Width', type: 'float', min:0, defVal:30},
2204	{name: 'notch', dispName: 'Notch', type: 'float', min:0, defVal:20},
2205	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:20}
2206];
2207
2208mxShapeArrows2TailedNotchedArrow.prototype.cst = {
2209		TAILED_NOTCHED_ARROW : 'mxgraph.arrows2.tailedNotchedArrow'
2210};
2211
2212/**
2213* Function: paintVertexShape
2214*
2215* Paints the vertex shape.
2216*/
2217mxShapeArrows2TailedNotchedArrow.prototype.paintVertexShape = function(c, x, y, w, h)
2218{
2219	c.translate(x, y);
2220
2221	var dy1 = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
2222	var dx1 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
2223	var dy2 = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy2', this.dy2))));
2224	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
2225	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
2226	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
2227	var x2 = 0;
2228
2229	if (dy2 != 0)
2230	{
2231		x2 = dx2 + notch * (dy2 - dy1) / dy2;
2232	}
2233
2234	c.begin();
2235	c.moveTo(0, h * 0.5 - dy2);
2236	c.lineTo(dx2, h * 0.5 - dy2);
2237	c.lineTo(x2, h * 0.5 - dy1);
2238	c.lineTo(w - dx1, h * 0.5 - dy1);
2239	c.lineTo(w - dx1, h * 0.5 - dy1 - arrowHead);
2240	c.lineTo(w, h * 0.5);
2241	c.lineTo(w - dx1, h * 0.5 + dy1 + arrowHead);
2242	c.lineTo(w - dx1, h * 0.5 + dy1);
2243	c.lineTo(x2, h * 0.5 + dy1);
2244	c.lineTo(dx2, h * 0.5 + dy2);
2245	c.lineTo(0, h * 0.5 + dy2);
2246	c.lineTo(notch, h * 0.5);
2247	c.close();
2248	c.fillAndStroke();
2249};
2250
2251mxCellRenderer.registerShape(mxShapeArrows2TailedNotchedArrow.prototype.cst.TAILED_NOTCHED_ARROW, mxShapeArrows2TailedNotchedArrow);
2252
2253mxShapeArrows2TailedNotchedArrow.prototype.constraints = null;
2254
2255Graph.handleFactory[mxShapeArrows2TailedNotchedArrow.prototype.cst.TAILED_NOTCHED_ARROW] = function(state)
2256{
2257	var handles = [Graph.createHandle(state, ['dx1', 'dy1'], function(bounds)
2258			{
2259				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
2260				var dx1 = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1))));
2261				var dy1 = Math.max(0, Math.min(bounds.height / 2 - arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1))));
2262
2263				return new mxPoint(bounds.x + bounds.width - dx1, bounds.y + bounds.height / 2 - dy1);
2264			}, function(bounds, pt)
2265			{
2266				this.state.style['dx1'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))- parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2)), bounds.x + bounds.width - pt.x))) / 100;
2267				this.state.style['dy1'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)), parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2)), bounds.y + bounds.height / 2 - pt.y))) / 100;
2268
2269			})];
2270
2271	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
2272			{
2273				var notch = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
2274
2275				return new mxPoint(bounds.x + notch, bounds.y + bounds.height / 2);
2276			}, function(bounds, pt)
2277			{
2278				this.state.style['notch'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1)), pt.x - bounds.x))) / 100;
2279			});
2280
2281	handles.push(handle2);
2282
2283	var handle3 = Graph.createHandle(state, ['arrowHead'], function(bounds)
2284			{
2285				var dx1 = 		Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1))));
2286				var dy1 =        Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1))));
2287				var arrowHead = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
2288
2289				return new mxPoint(bounds.x + bounds.width - dx1, bounds.y + bounds.height / 2 - dy1 - arrowHead);
2290			}, function(bounds, pt)
2291			{
2292				this.state.style['arrowHead'] = Math.round(100 * Math.max(0, Math.min(bounds.height / 2 - parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)), bounds.y + bounds.height / 2 - pt.y))) / 100;
2293			});
2294
2295	handles.push(handle3);
2296
2297	var handle4 = Graph.createHandle(state, ['dx2', 'dy2'], function(bounds)
2298			{
2299				var dx2 = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2))));
2300				var dy2 = Math.max(0, Math.min(bounds.height / 2, parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2))));
2301
2302				return new mxPoint(bounds.x + dx2, bounds.y + bounds.height / 2 - dy2);
2303			}, function(bounds, pt)
2304			{
2305				this.state.style['dx2'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)) - parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1)), pt.x - bounds.x))) / 100;
2306				this.state.style['dy2'] = Math.round(100 * Math.max(parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1)), Math.min(bounds.height / 2, bounds.y + bounds.height / 2 - pt.y))) / 100;
2307
2308			});
2309
2310	handles.push(handle4);
2311
2312	return handles;
2313};
2314
2315mxShapeArrows2TailedNotchedArrow.prototype.getConstraints = function(style, w, h)
2316{
2317	var constr = [];
2318	var dy1 = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
2319	var dx1 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
2320	var dy2 = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy2', this.dy2))));
2321	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
2322	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
2323	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
2324	var x2 = 0;
2325
2326	if (dy2 != 0)
2327	{
2328		x2 = dx2 + notch * (dy2 - dy1) / dy2;
2329	}
2330
2331	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null, notch, 0));
2332	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h * 0.5 - dy2));
2333	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2, h * 0.5 - dy2));
2334	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx1 + x2) * 0.5, h * 0.5 - dy1));
2335	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx1, h * 0.5 - dy1 - arrowHead));
2336	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h * 0.5 + dy2));
2337	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2, h * 0.5 + dy2));
2338	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx1 + x2) * 0.5, h * 0.5 + dy1));
2339	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx1, h * 0.5 + dy1 + arrowHead));
2340	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
2341
2342	return (constr);
2343};
2344
2345//**********************************************************************************************************************************************************
2346//Striped Arrow
2347//**********************************************************************************************************************************************************
2348/**
2349* Extends mxShape.
2350*/
2351function mxShapeArrows2StripedArrow(bounds, fill, stroke, strokewidth)
2352{
2353	mxShape.call(this);
2354	this.bounds = bounds;
2355	this.fill = fill;
2356	this.stroke = stroke;
2357	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
2358	this.dy = 0.5;
2359	this.dx = 0.5;
2360	this.notch = 0;
2361};
2362
2363/**
2364* Extends mxShape.
2365*/
2366mxUtils.extend(mxShapeArrows2StripedArrow, mxActor);
2367
2368mxShapeArrows2StripedArrow.prototype.customProperties = [
2369	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:40},
2370	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, max:1, defVal:0.6},
2371	{name: 'notch', dispName: 'Stripes Length', type: 'float', min:0, defVal:25}
2372];
2373
2374mxShapeArrows2StripedArrow.prototype.cst = {
2375		STRIPED_ARROW : 'mxgraph.arrows2.stripedArrow'
2376};
2377
2378/**
2379* Function: paintVertexShape
2380*
2381* Paints the vertex shape.
2382*/
2383mxShapeArrows2StripedArrow.prototype.paintVertexShape = function(c, x, y, w, h)
2384{
2385	c.translate(x, y);
2386
2387	var dy = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
2388	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
2389	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
2390
2391	c.begin();
2392	c.moveTo(notch, dy);
2393	c.lineTo(w - dx, dy);
2394	c.lineTo(w - dx, 0);
2395	c.lineTo(w, h * 0.5);
2396	c.lineTo(w - dx, h);
2397	c.lineTo(w - dx, h - dy);
2398	c.lineTo(notch, h - dy);
2399	c.close();
2400	c.moveTo(0, h - dy);
2401	c.lineTo(notch * 0.16, h - dy);
2402	c.lineTo(notch * 0.16, dy);
2403	c.lineTo(0, dy);
2404	c.close();
2405	c.moveTo(notch * 0.32, h - dy);
2406	c.lineTo(notch * 0.8, h - dy);
2407	c.lineTo(notch * 0.8, dy);
2408	c.lineTo(notch * 0.32, dy);
2409	c.close();
2410	c.fillAndStroke();
2411};
2412
2413mxCellRenderer.registerShape(mxShapeArrows2StripedArrow.prototype.cst.STRIPED_ARROW, mxShapeArrows2StripedArrow);
2414
2415mxShapeArrows2StripedArrow.prototype.constraints = null;
2416
2417Graph.handleFactory[mxShapeArrows2StripedArrow.prototype.cst.STRIPED_ARROW] = function(state)
2418{
2419	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
2420			{
2421				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
2422				var dy = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
2423
2424				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + dy * bounds.height / 2);
2425			}, function(bounds, pt)
2426			{
2427				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch)), bounds.x + bounds.width - pt.x))) / 100;
2428				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(1, (((pt.y - bounds.y) / bounds.height) * 2)))) / 100;
2429			})];
2430
2431	var handle2 = Graph.createHandle(state, ['notch'], function(bounds)
2432			{
2433				var notch = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))));
2434
2435				return new mxPoint(bounds.x + notch, bounds.y + bounds.height / 2);
2436			}, function(bounds, pt)
2437			{
2438				this.state.style['notch'] = Math.round(100 * Math.max(0, Math.min(bounds.width - parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), pt.x - bounds.x))) / 100;
2439			});
2440
2441	handles.push(handle2);
2442
2443	return handles;
2444};
2445
2446mxShapeArrows2StripedArrow.prototype.getConstraints = function(style, w, h)
2447{
2448	var constr = [];
2449	var dy = h * 0.5 * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
2450	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
2451	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
2452
2453	constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
2454	constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null, 0, 0));
2455	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, dy));
2456	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - dy));
2457	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, dy));
2458	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, 0));
2459	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h - dy));
2460	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h));
2461	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx) * 0.5, dy));
2462	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx) * 0.5, h - dy));
2463
2464	return (constr);
2465};
2466
2467//**********************************************************************************************************************************************************
2468//Jump-In Arrow
2469//**********************************************************************************************************************************************************
2470/**
2471* Extends mxShape.
2472*/
2473function mxShapeArrows2JumpInArrow(bounds, fill, stroke, strokewidth)
2474{
2475	mxShape.call(this);
2476	this.bounds = bounds;
2477	this.fill = fill;
2478	this.stroke = stroke;
2479	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
2480	this.dy = 0.5;
2481	this.dx = 0.5;
2482	this.arrowHead = 40;
2483};
2484
2485/**
2486* Extends mxShape.
2487*/
2488mxUtils.extend(mxShapeArrows2JumpInArrow, mxActor);
2489
2490mxShapeArrows2JumpInArrow.prototype.customProperties = [
2491	{name: 'dx', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:38},
2492	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, defVal:15},
2493	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:55}
2494];
2495
2496mxShapeArrows2JumpInArrow.prototype.cst = {
2497		JUMP_IN_ARROW : 'mxgraph.arrows2.jumpInArrow'
2498};
2499
2500/**
2501* Function: paintVertexShape
2502*
2503* Paints the vertex shape.
2504*/
2505mxShapeArrows2JumpInArrow.prototype.paintVertexShape = function(c, x, y, w, h)
2506{
2507	c.translate(x, y);
2508
2509	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
2510	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
2511	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
2512
2513	c.begin();
2514	c.moveTo(w - dx, 0);
2515	c.lineTo(w, arrowHead * 0.5);
2516	c.lineTo(w - dx, arrowHead);
2517	c.lineTo(w - dx, arrowHead / 2 + dy);
2518	c.arcTo(w - dx, h - arrowHead / 2 - dy, 0, 0, 0, 0, h);
2519	c.arcTo(w - dx, h - arrowHead / 2 + dy, 0, 0, 1, w - dx, arrowHead / 2 - dy);
2520	c.close();
2521	c.fillAndStroke();
2522};
2523
2524mxCellRenderer.registerShape(mxShapeArrows2JumpInArrow.prototype.cst.JUMP_IN_ARROW, mxShapeArrows2JumpInArrow);
2525
2526mxShapeArrows2JumpInArrow.prototype.constraints = null;
2527
2528Graph.handleFactory[mxShapeArrows2JumpInArrow.prototype.cst.JUMP_IN_ARROW] = function(state)
2529{
2530	var handles = [Graph.createHandle(state, ['dx', 'dy'], function(bounds)
2531			{
2532				var arrowHead = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
2533				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
2534				var dy = Math.max(0, Math.min(arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
2535
2536				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + arrowHead / 2 - dy);
2537			}, function(bounds, pt)
2538			{
2539				this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(bounds.width, bounds.x + bounds.width - pt.x))) / 100;
2540				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2, bounds.y + parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2 - pt.y))) / 100;
2541
2542			})];
2543
2544	var handle2 = Graph.createHandle(state, ['arrowHead'], function(bounds)
2545			{
2546				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
2547				var arrowHead = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
2548
2549				return new mxPoint(bounds.x + bounds.width - dx, bounds.y + arrowHead);
2550			}, function(bounds, pt)
2551			{
2552				this.state.style['arrowHead'] = Math.round(100 * Math.max(2 * parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), Math.min(bounds.height, pt.y - bounds.y))) / 100;
2553			});
2554
2555	handles.push(handle2);
2556
2557	return handles;
2558};
2559
2560mxShapeArrows2JumpInArrow.prototype.getConstraints = function(style, w, h)
2561{
2562	var constr = [];
2563	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
2564	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
2565	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
2566
2567	constr.push(new mxConnectionConstraint(new mxPoint(0, 1), false));
2568	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, 0));
2569	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, arrowHead * 0.5));
2570	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, arrowHead));
2571
2572	return (constr);
2573};
2574
2575//**********************************************************************************************************************************************************
2576//U Turn Arrow
2577//**********************************************************************************************************************************************************
2578/**
2579* Extends mxShape.
2580*/
2581function mxShapeArrows2UTurnArrow(bounds, fill, stroke, strokewidth)
2582{
2583	mxShape.call(this);
2584	this.bounds = bounds;
2585	this.fill = fill;
2586	this.stroke = stroke;
2587	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
2588	this.dy = 0.5;
2589	this.dx = 0.5;
2590	this.arrowHead = 40;
2591};
2592
2593/**
2594* Extends mxShape.
2595*/
2596mxUtils.extend(mxShapeArrows2UTurnArrow, mxActor);
2597
2598mxShapeArrows2UTurnArrow.prototype.customProperties = [
2599	{name: 'dx2', dispName: 'Arrowhead Length', type: 'float', min:0, defVal:25},
2600	{name: 'dy', dispName: 'Arrow Width', type: 'float', min:0, defVal:11},
2601	{name: 'arrowHead', dispName: 'Arrowhead Width', type: 'float', min:0, defVal:43}
2602];
2603
2604mxShapeArrows2UTurnArrow.prototype.cst = {
2605		U_TURN_ARROW : 'mxgraph.arrows2.uTurnArrow'
2606};
2607
2608/**
2609* Function: paintVertexShape
2610*
2611* Paints the vertex shape.
2612*/
2613mxShapeArrows2UTurnArrow.prototype.paintVertexShape = function(c, x, y, w, h)
2614{
2615	c.translate(x, y);
2616
2617	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
2618	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
2619	var dx = (h - arrowHead / 2 + dy) / 2;
2620	var dx2 = Math.max(0, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2)));
2621
2622	c.begin();
2623	c.moveTo(dx, 0);
2624	c.lineTo(dx + dx2, arrowHead * 0.5);
2625	c.lineTo(dx, arrowHead);
2626	c.lineTo(dx, arrowHead / 2 + dy);
2627	c.arcTo(dx - 2 * dy, dx - 2 * dy, 0, 0, 0, dx, h - 2 * dy);
2628	c.lineTo(Math.max(w, dx), h - 2 * dy);
2629	c.lineTo(Math.max(w, dx), h);
2630	c.lineTo(dx, h);
2631	c.arcTo(dx, dx, 0, 0, 1, dx, arrowHead / 2 - dy);
2632	c.close();
2633	c.fillAndStroke();
2634};
2635
2636mxCellRenderer.registerShape(mxShapeArrows2UTurnArrow.prototype.cst.U_TURN_ARROW, mxShapeArrows2UTurnArrow);
2637
2638mxShapeArrows2UTurnArrow.prototype.constraints = null;
2639
2640Graph.handleFactory[mxShapeArrows2UTurnArrow.prototype.cst.U_TURN_ARROW] = function(state)
2641{
2642	var handles = [Graph.createHandle(state, ['dy'], function(bounds)
2643			{
2644				var arrowHead = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
2645				var dy = Math.max(0, Math.min(arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
2646				var dx = (bounds.height - arrowHead / 2 + dy) / 2;
2647
2648				return new mxPoint(bounds.x + dx, bounds.y + arrowHead / 2 - dy);
2649			}, function(bounds, pt)
2650			{
2651				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2, bounds.y + parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead)) / 2 - pt.y))) / 100;
2652
2653			})];
2654
2655	var handle2 = Graph.createHandle(state, ['dx2'], function(bounds)
2656			{
2657				var arrowHead = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
2658				var dy = Math.max(0, Math.min(arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
2659				var dx = (bounds.height - arrowHead / 2 + dy) / 2;
2660
2661				var dx2 = Math.max(0, Math.min(bounds.width - dx, parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2))));
2662
2663				return new mxPoint(bounds.x + dx + dx2, bounds.y + arrowHead / 2);
2664			}, function(bounds, pt)
2665			{
2666				var arrowHead = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
2667				var dy = Math.max(0, Math.min(arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
2668				var dx = (bounds.height - arrowHead / 2 + dy) / 2;
2669				this.state.style['dx2'] = Math.round(100 * Math.max(0, Math.min(Math.max(bounds.width, dx), pt.x - bounds.x - dx))) / 100;
2670			});
2671
2672	handles.push(handle2);
2673
2674	var handle3 = Graph.createHandle(state, ['arrowHead'], function(bounds)
2675			{
2676				var arrowHead = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'arrowHead', this.arrowHead))));
2677				var dy = Math.max(0, Math.min(arrowHead, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
2678				var dx = (bounds.height - arrowHead / 2 + dy) / 2;
2679
2680				return new mxPoint(bounds.x + dx, bounds.y + arrowHead);
2681			}, function(bounds, pt)
2682			{
2683				this.state.style['arrowHead'] = Math.round(100 * Math.max(2 * parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)), Math.min(bounds.height / 2, pt.y - bounds.y))) / 100;
2684			});
2685
2686	handles.push(handle3);
2687
2688	return handles;
2689};
2690
2691mxShapeArrows2UTurnArrow.prototype.getConstraints = function(style, w, h)
2692{
2693	var constr = [];
2694	var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
2695	var arrowHead = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'arrowHead', this.arrowHead))));
2696	var dx = (h - arrowHead / 2 + dy) / 2;
2697	var dx2 = Math.max(0, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2)));
2698
2699	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, 0));
2700	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx + dx2, arrowHead * 0.5));
2701	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, arrowHead));
2702	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (dx + w) * 0.5, h - 2 * dy));
2703	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, Math.max(w, dx), h - 2 * dy));
2704	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, Math.max(w, dx), h - dy));
2705	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, Math.max(w, dx), h));
2706	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (dx + w) * 0.5, h));
2707	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h));
2708	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, (h + arrowHead * 0.5 - dy) * 0.5));
2709	constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, arrowHead - 2 * dy, (h + arrowHead * 0.5 - dy) * 0.5));
2710
2711	return (constr);
2712};
2713