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