1/**
2 * $Id: mxIOS7Ui.js,v 1.6 2013/12/04 16:48:54 mate Exp $
3 * Copyright (c) 2006-2013, JGraph Ltd
4 */
5
6var mxIOS7C =
7{
8		MAIN_TEXT : 'mainText',
9		SUB_TEXT : 'subText',
10		TEXT_COLOR : 'textColor',
11		TEXT_SIZE : 'textSize',
12		BAR_POS : 'barPos',
13		BUTTON_TEXT : 'buttonText',
14		BUTTON_STATE : 'buttonState',
15		SELECTED : '+', 		//has to be one character long
16		STATE_ON : 'on',
17		STATE_OFF : 'off',
18		GRID_SIZE : 'gridSize',
19
20		SHAPE_IOS7_APP_BAR : 'mxgraph.ios7ui.appBar',
21		SHAPE_IOS7_ON_OFF_BUTTON : 'mxgraph.ios7ui.onOffButton',
22		SHAPE_IOS7_SLIDER : 'mxgraph.ios7ui.slider',
23		SHAPE_IOS7_DOWNLOAD_BAR : 'mxgraph.ios7ui.downloadBar',
24		SHAPE_IOS7_ICON : 'mxgraph.ios7ui.icon',
25		SHAPE_IOS7_HOR_BUTTON_BAR : 'mxgraph.ios7ui.horButtonBar',
26		SHAPE_IOS7_PAGE_CONTROL : 'mxgraph.ios7ui.pageControl',
27		SHAPE_IOS7_EXPAND :  'mxgraph.ios7ui.expand',
28		SHAPE_IOS7_ICON_GRID : 'mxgraph.ios7ui.iconGrid',
29		SHAPE_IOS7_PHONE : 'mxgraph.ios7ui.phone',
30		SHAPE_IOS7_SEARCH_BOX : 'mxgraph.ios7ui.searchBox',
31		SHAPE_IOS7_URL : 'mxgraph.ios7ui.url',
32		SHAPE_IOS7_ACTION_DIALOG : 'mxgraph.ios7ui.actionDialog',
33
34		STYLE_FILLCOLOR2 : 'fillColor2',
35		STYLE_FILLCOLOR3 : 'fillColor3',
36		STYLE_TEXTCOLOR : 'textColor',
37		STYLE_TEXTCOLOR2 : 'textColor2',
38		STYLE_STROKECOLOR2 : 'strokeColor2',
39		STYLE_STROKECOLOR3 : 'strokeColor3',
40		STYLE_TEXTSIZE : 'textSize'
41};
42
43//**********************************************************************************************************************************************************
44//iOS7 Application Bar
45//**********************************************************************************************************************************************************
46/**
47 * Extends mxShape.
48 */
49function mxShapeIOS7AppBar(bounds, fill, stroke, strokewidth)
50{
51	mxShape.call(this);
52	this.bounds = bounds;
53	this.fill = fill;
54	this.stroke = stroke;
55	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
56};
57
58/**
59 * Extends mxShape.
60 */
61mxUtils.extend(mxShapeIOS7AppBar, mxShape);
62
63mxShapeIOS7AppBar.prototype.customProperties = [
64	{name: 'fillColor2', dispName: 'Fill Color 2', type: 'color'}
65];
66
67/**
68 * Function: paintVertexShape
69 *
70 * Paints the vertex shape.
71 */
72mxShapeIOS7AppBar.prototype.paintVertexShape = function(c, x, y, w, h)
73{
74	c.translate(x, y);
75	this.background(c, x, y, w, h);
76	c.setShadow(false);
77	this.foreground(c, x, y, w, h);
78};
79
80mxShapeIOS7AppBar.prototype.background = function(c, x, y, w, h)
81{
82	c.rect(0, 0, w, h);
83	c.fill();
84};
85
86mxShapeIOS7AppBar.prototype.foreground = function(c, x, y, w, h)
87{
88	c.setFillColor(mxUtils.getValue(this.style, mxIOS7C.STYLE_FILLCOLOR2, '#222222'));
89
90	c.ellipse(5, h * 0.5 - 1.5, 3, 3);
91	c.fill();
92	c.ellipse(9, h * 0.5 - 1.5, 3, 3);
93	c.fill();
94	c.ellipse(13, h * 0.5 - 1.5, 3, 3);
95	c.fill();
96	c.ellipse(17, h * 0.5 - 1.5, 3, 3);
97	c.fill();
98	c.ellipse(21, h * 0.5 - 1.5, 3, 3);
99	c.fill();
100
101	c.ellipse(54, h * 0.5 + 2, 2, 2);
102	c.fillAndStroke();
103
104	c.setStrokeWidth(2);
105	c.begin();
106	c.moveTo(52, h * 0.5 + 1);
107	c.arcTo(3.5, 3.5, 0, 0, 1, 58, h * 0.5 + 1);
108	c.stroke();
109
110	c.begin();
111	c.moveTo(50, h * 0.5 - 1);
112	c.arcTo(6, 6, 0, 0, 1, 60, h * 0.5 - 1);
113	c.stroke();
114
115	c.begin();
116	c.moveTo(w - 19, h * 0.5 - 2);
117	c.lineTo(w - 6, h * 0.5 - 2);
118	c.lineTo(w - 6, h * 0.5 + 2);
119	c.lineTo(w - 19, h * 0.5 + 2);
120	c.close();
121	c.fill();
122
123	c.setStrokeWidth(1);
124	c.begin();
125	c.moveTo(w - 44, h * 0.5  - 2.5);
126	c.lineTo(w - 36, h * 0.5  + 2.5);
127	c.lineTo(w - 40, h * 0.5 + 5);
128	c.lineTo(w - 40, h * 0.5 - 5);
129	c.lineTo(w - 36, h * 0.5 - 2.5);
130	c.lineTo(w - 44, h * 0.5 + 2.5);
131	c.stroke();
132
133	c.begin();
134	c.moveTo(w - 20, h * 0.5 - 3);
135	c.lineTo(w - 5, h * 0.5 - 3);
136	c.lineTo(w - 5, h * 0.5 - 1);
137	c.lineTo(w - 3.5, h * 0.5 - 1);
138	c.lineTo(w - 3.5, h * 0.5 + 1);
139	c.lineTo(w - 5, h * 0.5 + 1);
140	c.lineTo(w - 5, h * 0.5 + 3);
141	c.lineTo(w - 20, h * 0.5 + 3);
142	c.close();
143	c.stroke();
144};
145
146mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_APP_BAR, mxShapeIOS7AppBar);
147
148//**********************************************************************************************************************************************************
149//On-Off Button
150//**********************************************************************************************************************************************************
151/**
152* Extends mxShape.
153*/
154function mxShapeIOS7OnOffButton(bounds, fill, stroke, strokewidth)
155{
156	mxShape.call(this);
157	this.bounds = bounds;
158	this.fill = fill;
159	this.stroke = stroke;
160	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
161};
162
163/**
164* Extends mxShape.
165*/
166mxUtils.extend(mxShapeIOS7OnOffButton, mxShape);
167
168mxShapeIOS7OnOffButton.prototype.customProperties = [
169	{name: 'buttonState', dispName: 'Button State', type: 'enum',
170		enumList: [{val: 'on', dispName: 'On'},
171				   {val: 'off', dispName: 'Off'}]
172	},
173	{name: 'strokeColor2', dispName: 'Stroke Color 2', type: 'color'},
174	{name: 'fillColor2', dispName: 'Fill Color 2', type: 'color'},
175];
176
177/**
178* Function: paintVertexShape
179*
180* Paints the vertex shape.
181*/
182mxShapeIOS7OnOffButton.prototype.paintVertexShape = function(c, x, y, w, h)
183{
184	c.translate(x, y);
185	w = Math.max(w, 2 * h);
186	var state = mxUtils.getValue(this.style, mxIOS7C.BUTTON_STATE, mxIOS7C.STATE_ON);
187	this.background(c, x, y, w, h, state);
188	c.setShadow(false);
189	this.foreground(c, x, y, w, h, state);
190};
191
192mxShapeIOS7OnOffButton.prototype.background = function(c, x, y, w, h, state)
193{
194	if (state === mxIOS7C.STATE_ON)
195	{
196		c.roundrect(0, 0, w, h, h * 0.5, h * 0.5);
197		c.fillAndStroke();
198	}
199	else if (state === mxIOS7C.STATE_OFF)
200	{
201		c.setStrokeColor(mxUtils.getValue(this.style, mxIOS7C.STYLE_STROKECOLOR2, '#aaaaaa'));
202		c.setFillColor(mxUtils.getValue(this.style, mxIOS7C.STYLE_FILLCOLOR2, '#ffffff'));
203		c.roundrect(0, 0, w, h, h * 0.5, h * 0.5);
204		c.fillAndStroke();
205	}
206
207};
208
209mxShapeIOS7OnOffButton.prototype.foreground = function(c, x, y, w, h, state)
210{
211	c.setFillColor('#ffffff');
212
213	if (state === mxIOS7C.STATE_ON)
214	{
215		c.ellipse(w - h + 1, 1, h - 2, h - 2);
216		c.fill();
217	}
218	else
219	{
220		c.ellipse(0, 0, h, h);
221		c.stroke();
222	}
223};
224
225mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_ON_OFF_BUTTON, mxShapeIOS7OnOffButton);
226
227//**********************************************************************************************************************************************************
228//Slider
229//**********************************************************************************************************************************************************
230/**
231* Extends mxShape.
232*/
233function mxShapeIOS7Slider(bounds, fill, stroke, strokewidth)
234{
235	mxShape.call(this);
236	this.bounds = bounds;
237	this.fill = fill;
238	this.stroke = stroke;
239	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
240	this.barPos = 80;
241};
242
243/**
244* Extends mxShape.
245*/
246mxUtils.extend(mxShapeIOS7Slider, mxShape);
247
248
249
250/**
251* Function: paintVertexShape
252*
253* Paints the vertex shape.
254*/
255mxShapeIOS7Slider.prototype.paintVertexShape = function(c, x, y, w, h)
256{
257	c.translate(x, y);
258	c.setShadow(false);
259
260	this.foreground(c, w, h);
261};
262
263mxShapeIOS7Slider.prototype.foreground = function(c, w, h)
264{
265	c.setStrokeWidth(2);
266
267	c.begin();
268	c.moveTo(0, h * 0.5);
269	c.lineTo(w, h * 0.5);
270	c.stroke();
271
272	var barPos = mxUtils.getValue(this.style, mxIOS7C.BAR_POS, '80');
273	barPos = Math.min(barPos, 100);
274	barPos = Math.max(barPos, 0);
275	var deadzone = 0;
276	var virRange = w - 2 * deadzone;
277	var truePos = deadzone + virRange * barPos / 100;
278
279	c.setStrokeColor(mxUtils.getValue(this.style, mxIOS7C.STYLE_STROKECOLOR2, '#a0a0a0'));
280	c.ellipse(truePos - 5, h * 0.5 - 5, 10, 10);
281	c.fillAndStroke();
282};
283
284mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_SLIDER, mxShapeIOS7Slider);
285
286Graph.handleFactory[mxIOS7C.SHAPE_IOS7_SLIDER] = function(state)
287{
288	var handles = [Graph.createHandle(state, ['barPos'], function(bounds)
289			{
290				var barPos = Math.max(0, Math.min(100, parseFloat(mxUtils.getValue(this.state.style, 'barPos', this.barPos))));
291
292				return new mxPoint(bounds.x + barPos / 100 * bounds.width, bounds.y + bounds.height / 2);
293			}, function(bounds, pt)
294			{
295				this.state.style['barPos'] = Math.round(1000 * Math.max(0, Math.min(100, (pt.x - bounds.x) * 100 / bounds.width))) / 1000;
296			})];
297
298	return handles;
299}
300
301//**********************************************************************************************************************************************************
302//Download Bar
303//**********************************************************************************************************************************************************
304/**
305* Extends mxShape.
306*/
307function mxShapeIOS7DownloadBar(bounds, fill, stroke, strokewidth)
308{
309	mxShape.call(this);
310	this.bounds = bounds;
311	this.fill = fill;
312	this.stroke = stroke;
313	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
314	this.barPos = 80;
315};
316
317/**
318* Extends mxShape.
319*/
320mxUtils.extend(mxShapeIOS7DownloadBar, mxShape);
321
322mxShapeIOS7DownloadBar.prototype.customProperties = [
323	{name: 'barPos', dispName: 'Handle Position', type: 'float', min:0, max:1, defVal:30},
324	{name: 'strokeColor2', dispName: 'Stroke Color 2', type: 'color'}
325];
326
327/**
328* Function: paintVertexShape
329*
330* Paints the vertex shape.
331*/
332mxShapeIOS7DownloadBar.prototype.paintVertexShape = function(c, x, y, w, h)
333{
334	c.translate(x, y);
335
336	this.foreground(c, w, h);
337};
338
339mxShapeIOS7DownloadBar.prototype.foreground = function(c, w, h)
340{
341	var fieldText = mxUtils.getValue(this.style, mxIOS7C.BUTTON_TEXT, '');
342	c.setFontStyle(mxConstants.FONT_BOLD);
343	c.text(w * 0.5, h * 0.2, 0, 0, fieldText, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
344
345	var barPos = mxUtils.getValue(this.style, mxIOS7C.BAR_POS, '80');
346	barPos = Math.min(barPos, 100);
347	barPos = Math.max(barPos, 0);
348	var truePos = w * barPos / 100;
349
350	c.setStrokeWidth(2);
351	c.setStrokeColor(mxUtils.getValue(this.style, mxConstants.STYLE_FILLCOLOR, ''));
352	c.begin();
353	c.moveTo(0, h * 0.5);
354	c.lineTo(w, h * 0.5);
355	c.stroke();
356
357	c.setStrokeColor(mxUtils.getValue(this.style, mxConstants.STYLE_STROKECOLOR, ''));
358	c.begin();
359	c.moveTo(0, h * 0.5);
360	c.lineTo(truePos, h * 0.5);
361	c.stroke();
362};
363
364mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_DOWNLOAD_BAR, mxShapeIOS7DownloadBar);
365
366Graph.handleFactory[mxIOS7C.SHAPE_IOS7_DOWNLOAD_BAR] = function(state)
367{
368	var handles = [Graph.createHandle(state, ['barPos'], function(bounds)
369			{
370				var barPos = Math.max(0, Math.min(100, parseFloat(mxUtils.getValue(this.state.style, 'barPos', this.barPos))));
371
372				return new mxPoint(bounds.x + barPos / 100 * bounds.width, bounds.y + bounds.height / 2);
373			}, function(bounds, pt)
374			{
375				this.state.style['barPos'] = Math.round(1000 * Math.max(0, Math.min(100, (pt.x - bounds.x) * 100 / bounds.width))) / 1000;
376			})];
377
378	return handles;
379}
380
381//**********************************************************************************************************************************************************
382//Icon
383//**********************************************************************************************************************************************************
384/**
385* Extends mxShape.
386*/
387function mxShapeIOS7Icon(bounds, fill, stroke, strokewidth)
388{
389	mxShape.call(this);
390	this.bounds = bounds;
391	this.fill = fill;
392	this.stroke = stroke;
393	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
394};
395
396/**
397* Extends mxShape.
398*/
399mxUtils.extend(mxShapeIOS7Icon, mxShape);
400
401/**
402* Function: paintVertexShape
403*
404* Paints the vertex shape.
405*/
406mxShapeIOS7Icon.prototype.paintVertexShape = function(c, x, y, w, h)
407{
408	c.translate(x, y);
409
410	this.foreground(c, w, h);
411};
412
413mxShapeIOS7Icon.prototype.foreground = function(c, w, h)
414{
415	c.setGradient('#00D0F0', '#0080F0', w * 0.325, 0, w * 0.675, h * 0.5, mxConstants.DIRECTION_SOUTH, 1, 1);
416	c.roundrect(0, 0, w, h, w * 0.1, h * 0.1);
417	c.fill();
418
419	var fieldText = mxUtils.getValue(this.style, mxIOS7C.BUTTON_TEXT, '');
420	c.setFontColor('#ffffff');
421	c.setFontStyle(mxConstants.FONT_BOLD);
422	c.setFontSize(8);
423	c.text(w * 0.5, h * 0.5, 0, 0, fieldText, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
424};
425
426mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_ICON, mxShapeIOS7Icon);
427
428//**********************************************************************************************************************************************************
429//Horizontal Button Bar
430//**********************************************************************************************************************************************************
431/**
432* Extends mxShape.
433*/
434function mxShapeIOS7horButtonBar(bounds, fill, stroke, strokewidth)
435{
436	mxShape.call(this);
437	this.bounds = bounds;
438	this.fill = fill;
439	this.stroke = stroke;
440	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
441};
442
443/**
444* Extends mxShape.
445*/
446mxUtils.extend(mxShapeIOS7horButtonBar, mxShape);
447
448/**
449* Function: paintVertexShape
450*
451* Paints the vertex shape.
452*/
453mxShapeIOS7horButtonBar.prototype.paintVertexShape = function(c, x, y, w, h)
454{
455	var textStrings = mxUtils.getValue(this.style, mxIOS7C.BUTTON_TEXT, '+Button 1, Button 2, Button 3').toString().split(',');
456	var fontColor = mxUtils.getValue(this.style, mxIOS7C.STYLE_TEXTCOLOR, '#666666');
457	var selectedFontColor = mxUtils.getValue(this.style, mxIOS7C.STYLE_TEXTCOLOR2, '#ffffff');
458	var fontSize = mxUtils.getValue(this.style, mxConstants.STYLE_FONTSIZE, '8.5').toString();
459	var frameColor = mxUtils.getValue(this.style, mxConstants.STYLE_STROKECOLOR, '#666666');
460	var bgColor = mxUtils.getValue(this.style, mxConstants.STYLE_FILLCOLOR, '#ffffff');
461	var selectedFillColor = mxUtils.getValue(this.style, mxIOS7C.STYLE_FILLCOLOR2, '#008cff');
462	var buttonNum = textStrings.length;
463	var buttonWidths = new Array(buttonNum);
464	var buttonTotalWidth = 0;
465	var selectedButton = -1;
466	var rSize = 2.5; //rounding size
467	var labelOffset = 2.5;
468
469	for (var i = 0; i < buttonNum; i++)
470	{
471		var buttonText = textStrings[i];
472
473		if(buttonText.charAt(0) === mxIOS7C.SELECTED)
474		{
475			buttonText = textStrings[i].substring(1);
476			selectedButton = i;
477		}
478
479		buttonWidths[i] = mxUtils.getSizeForString(buttonText, fontSize, mxConstants.DEFAULT_FONTFAMILY).width;
480		buttonTotalWidth += buttonWidths[i];
481	}
482
483	var trueH = Math.max(h, fontSize * 1.5, 10);
484	var minW = 2 * labelOffset * buttonNum + buttonTotalWidth;
485	var trueW = Math.max(w, minW);
486
487	c.translate(x, y);
488	this.background(c, trueW, trueH, rSize, buttonNum, buttonWidths, labelOffset, minW, frameColor, bgColor, selectedFillColor, selectedButton);
489	c.setShadow(false);
490
491	var currWidth = 0;
492
493	for (var i = 0; i < buttonNum; i++)
494	{
495		if (i === selectedButton)
496		{
497			c.setFontColor(selectedFontColor);
498		}
499		else
500		{
501			c.setFontColor(fontColor);
502		}
503
504		currWidth = currWidth + labelOffset;
505		this.buttonText(c, currWidth, trueH, textStrings[i], buttonWidths[i], fontSize, minW, trueW);
506		currWidth = currWidth + buttonWidths[i] + labelOffset;
507	}
508};
509
510mxShapeIOS7horButtonBar.prototype.background = function(c, w, h, rSize, buttonNum, buttonWidths, labelOffset, minW, frameColor, bgColor, selectedFillColor, selectedButton)
511{
512	c.begin();
513
514	//draw the frame
515	c.setStrokeColor(frameColor);
516	c.setFillColor(bgColor);
517	c.moveTo(0, rSize);
518	c.arcTo(rSize, rSize, 0, 0, 1, rSize, 0);
519	c.lineTo(w - rSize, 0);
520	c.arcTo(rSize, rSize, 0, 0, 1, w, rSize);
521	c.lineTo(w, h - rSize);
522	c.arcTo(rSize, rSize, 0, 0, 1, w - rSize, h);
523	c.lineTo(rSize, h);
524	c.arcTo(rSize, rSize, 0, 0, 1, 0, h - rSize);
525	c.close();
526	c.fillAndStroke();
527
528	//draw the button separators
529	c.setStrokeColor(frameColor);
530	c.begin();
531	for (var i = 1; i < buttonNum; i++)
532	{
533		if (i !== selectedButton && i !== (selectedButton + 1))
534		{
535			var currWidth = 0;
536
537			for (var j = 0; j < i; j++)
538			{
539				currWidth += buttonWidths[j] + 2 * labelOffset;
540			}
541
542			currWidth = currWidth * w / minW;
543			c.moveTo(currWidth, 0);
544			c.lineTo(currWidth, h);
545		}
546	}
547
548	c.stroke();
549
550	//draw the selected button
551	var buttonLeft = 0;
552	c.setStrokeColor(mxConstants.NONE);
553
554	for (var i = 0; i < selectedButton; i++)
555	{
556		buttonLeft += buttonWidths[i] + 2 * labelOffset;
557	}
558
559	buttonLeft = buttonLeft * w / minW;
560	var buttonRight = (buttonWidths[selectedButton] + 2 * labelOffset) * w / minW;
561	buttonRight += buttonLeft;
562	c.setFillColor('#0080F0');
563
564	if (selectedButton === 0)
565	{
566		c.begin();
567		// we draw a path for the first button
568		c.moveTo(0, rSize);
569		c.arcTo(rSize, rSize, 0, 0, 1, rSize, 0);
570		c.lineTo(buttonRight, 0);
571		c.lineTo(buttonRight, h);
572		c.lineTo(rSize, h);
573		c.arcTo(rSize, rSize, 0, 0, 1, 0, h - rSize);
574		c.close();
575		c.fill();
576	}
577	else if (selectedButton === buttonNum - 1)
578	{
579		c.begin();
580		// we draw a path for the last button
581		c.moveTo(buttonLeft, 0);
582		c.lineTo(buttonRight - rSize, 0);
583		c.arcTo(rSize, rSize, 0, 0, 1, buttonRight, rSize);
584		c.lineTo(buttonRight, h - rSize);
585		c.arcTo(rSize, rSize, 0, 0, 1, buttonRight - rSize, h);
586		c.lineTo(buttonLeft, h);
587		c.close();
588		c.fill();
589	}
590	else if (selectedButton !== -1)
591	{
592		c.begin();
593		// we draw a path rectangle for one of the buttons in the middle
594		c.moveTo(buttonLeft, 0);
595		c.lineTo(buttonRight, 0);
596		c.lineTo(buttonRight, h);
597		c.lineTo(buttonLeft, h);
598		c.close();
599		c.fill();
600	}
601
602	//draw the frame again, to achieve a nicer effect
603	c.setStrokeColor(frameColor);
604	c.setFillColor(bgColor);
605	c.begin();
606	c.moveTo(0, rSize);
607	c.arcTo(rSize, rSize, 0, 0, 1, rSize, 0);
608	c.lineTo(w - rSize, 0);
609	c.arcTo(rSize, rSize, 0, 0, 1, w, rSize);
610	c.lineTo(w, h - rSize);
611	c.arcTo(rSize, rSize, 0, 0, 1, w - rSize, h);
612	c.lineTo(rSize, h);
613	c.arcTo(rSize, rSize, 0, 0, 1, 0, h - rSize);
614	c.close();
615	c.stroke();
616};
617
618mxShapeIOS7horButtonBar.prototype.buttonText = function(c, w, h, textString, buttonWidth, fontSize, minW, trueW)
619{
620	if(textString.charAt(0) === mxIOS7C.SELECTED)
621	{
622		textString = textString.substring(1);
623	}
624
625	c.begin();
626	c.setFontSize(fontSize);
627	c.text((w + buttonWidth * 0.5) * trueW / minW, h * 0.5, 0, 0, textString, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
628};
629
630mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_HOR_BUTTON_BAR, mxShapeIOS7horButtonBar);
631
632//**********************************************************************************************************************************************************
633//Page Control
634//**********************************************************************************************************************************************************
635/**
636* Extends mxShape.
637*/
638function mxShapeIOS7pageControl(bounds, fill, stroke, strokewidth)
639{
640	mxShape.call(this);
641	this.bounds = bounds;
642	this.fill = fill;
643	this.stroke = stroke;
644	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
645};
646
647/**
648* Extends mxShape.
649*/
650mxUtils.extend(mxShapeIOS7pageControl, mxShape);
651
652/**
653* Function: paintVertexShape
654*
655* Paints the vertex shape.
656*/
657mxShapeIOS7pageControl.prototype.paintVertexShape = function(c, x, y, w, h)
658{
659	c.translate(x, y);
660
661	var fillColor = mxUtils.getValue(this.style, mxConstants.STYLE_FILLCOLOR, '#000000');
662	var strokeColor = mxUtils.getValue(this.style, mxConstants.STYLE_STROKECOLOR, '#000000');
663
664	var rSize = Math.min(h * 0.5, w * 0.05);
665	c.setFillColor(strokeColor);
666	c.ellipse(0, h * 0.5 - rSize, 2 * rSize, 2 * rSize);
667	c.fill();
668	c.ellipse(w * 0.25 - rSize * 0.5, h * 0.5 - rSize, 2 * rSize, 2 * rSize);
669	c.fill();
670	c.ellipse(w * 0.5 - rSize, h * 0.5 - rSize, 2 * rSize, 2 * rSize);
671	c.fill();
672	c.ellipse(w * 0.75 - rSize * 1.5, h * 0.5 - rSize, 2 * rSize, 2 * rSize);
673	c.fill();
674	c.setFillColor(fillColor);
675	c.ellipse(w - 2 * rSize, h * 0.5 - rSize, 2 * rSize, 2 * rSize);
676	c.fill();
677};
678
679mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_PAGE_CONTROL, mxShapeIOS7pageControl);
680
681//**********************************************************************************************************************************************************
682//Icon Grid
683//**********************************************************************************************************************************************************
684/**
685* Extends mxShape.
686*/
687function mxShapeIOS7iconGrid(bounds, fill, stroke, strokewidth)
688{
689	mxShape.call(this);
690	this.bounds = bounds;
691	this.fill = fill;
692	this.stroke = stroke;
693	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
694};
695
696/**
697* Extends mxShape.
698*/
699mxUtils.extend(mxShapeIOS7iconGrid, mxShape);
700
701mxShapeIOS7iconGrid.prototype.customProperties = [
702	{name: 'gridSize', dispName: 'Grid Size', type: 'String'},
703];
704
705/**
706* Function: paintVertexShape
707*
708* Paints the vertex shape.
709*/
710mxShapeIOS7iconGrid.prototype.paintVertexShape = function(c, x, y, w, h)
711{
712	c.translate(x, y);
713	var gridSize = mxUtils.getValue(this.style, mxIOS7C.GRID_SIZE, '4,7').toString().split(',');
714
715	var boxSizeX = w / (parseInt(gridSize[0],10) + (gridSize[0]-1) * 0.1);
716	var boxSizeY = h / (parseInt(gridSize[1],10) + (gridSize[1]-1) * 0.1);
717
718	for (var i = 0; i < gridSize[0]; i++)
719	{
720		for (var j = 0; j < gridSize[1]; j++)
721		{
722			c.rect(boxSizeX * 1.1 * i, boxSizeY * 1.1 * j, boxSizeX, boxSizeY);
723			c.fill();
724		}
725	}
726};
727
728mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_ICON_GRID, mxShapeIOS7iconGrid);
729
730//**********************************************************************************************************************************************************
731//iPhone Vertical
732//**********************************************************************************************************************************************************
733/**
734* Extends mxShape.
735*/
736function mxShapeIOS7phone(bounds, fill, stroke, strokewidth)
737{
738	mxShape.call(this);
739	this.bounds = bounds;
740	this.fill = fill;
741	this.stroke = stroke;
742	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
743};
744
745/**
746* Extends mxShape.
747*/
748mxUtils.extend(mxShapeIOS7phone, mxShape);
749
750/**
751* Function: paintVertexShape
752*
753* Paints the vertex shape.
754*/
755mxShapeIOS7phone.prototype.paintVertexShape = function(c, x, y, w, h)
756{
757	c.translate(x, y);
758	var rSize = 25;
759
760	c.roundrect(0, 0, w, h, rSize, rSize);
761	c.fillAndStroke();
762
763	c.setShadow(false);
764
765	this.foreground(c, x, y, w, h, rSize);
766};
767
768mxShapeIOS7phone.prototype.foreground = function(c, x, y, w, h, rSize)
769{
770	c.rect(w * 0.0625, h * 0.15, w * 0.875, h * 0.7);
771	c.stroke();
772
773	c.ellipse(w * 0.4875, h * 0.04125, w * 0.025, h * 0.0125);
774	c.stroke();
775
776	c.roundrect(w * 0.375, h * 0.075, w * 0.25, h * 0.01875, w * 0.02, h * 0.01);
777	c.stroke();
778	c.ellipse(w * 0.4, h * 0.875, w * 0.2, h * 0.1);
779	c.stroke();
780	c.roundrect(w * 0.4575, h * 0.905, w * 0.085, h * 0.04375, h * 0.00625, h * 0.00625);
781	c.stroke();
782};
783
784mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_PHONE, mxShapeIOS7phone);
785
786//**********************************************************************************************************************************************************
787//Search Box
788//**********************************************************************************************************************************************************
789/**
790* Extends mxShape.
791*/
792function mxShapeIOS7searchBox(bounds, fill, stroke, strokewidth)
793{
794	mxShape.call(this);
795	this.bounds = bounds;
796	this.fill = fill;
797	this.stroke = stroke;
798	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
799};
800
801/**
802* Extends mxShape.
803*/
804mxUtils.extend(mxShapeIOS7searchBox, mxShape);
805
806/**
807* Function: paintVertexShape
808*
809* Paints the vertex shape.
810*/
811mxShapeIOS7searchBox.prototype.paintVertexShape = function(c, x, y, w, h)
812{
813	c.translate(x, y);
814	this.background(c, w, h);
815	c.setShadow(false);
816	this.foreground(c, w, h);
817};
818
819mxShapeIOS7searchBox.prototype.background = function(c, w, h)
820{
821	c.rect(0, 0, w, h);
822	c.fill();
823};
824
825mxShapeIOS7searchBox.prototype.foreground = function(c, w, h)
826{
827	var mainText = mxUtils.getValue(this.style, mxIOS7C.BUTTON_TEXT, 'Search');
828	var fontColor = mxUtils.getValue(this.style, mxIOS7C.STYLE_TEXTCOLOR, '#666666');
829	var strokeColor2 = mxUtils.getValue(this.style, mxIOS7C.STYLE_STROKECOLOR2, '#008cff');
830	var fontSize = mxUtils.getValue(this.style, mxIOS7C.STYLE_TEXTSIZE, '17');
831	var rSize = Math.min(w, h) * 0.1;
832
833	c.setFillColor('#ffffff');
834	c.roundrect(w * 0.05, h * 0.15, w * 0.5, h * 0.7, rSize, rSize);
835	c.fillAndStroke();
836
837	c.setFontColor(fontColor);
838	c.setFontSize(Math.min(h * 0.7, w * 0.1));
839
840	c.text(5, h * 0.5, 0, 0, mainText, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
841
842	c.setStrokeColor(strokeColor2);
843	c.ellipse(w * 0.05 + 3, h * 0.5 - 3, 4, 4);
844	c.stroke();
845	c.begin();
846	c.moveTo(w * 0.05 + 8, h * 0.5 + 3.5);
847	c.lineTo(w * 0.05 + 6, h * 0.5 + 0.5);
848	c.stroke();
849};
850
851mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_SEARCH_BOX, mxShapeIOS7searchBox);
852
853//**********************************************************************************************************************************************************
854//URL
855//**********************************************************************************************************************************************************
856/**
857* Extends mxShape.
858*/
859function mxShapeIOS7URL(bounds, fill, stroke, strokewidth)
860{
861	mxShape.call(this);
862	this.bounds = bounds;
863	this.fill = fill;
864	this.stroke = stroke;
865	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
866};
867
868/**
869* Extends mxShape.
870*/
871mxUtils.extend(mxShapeIOS7URL, mxShape);
872
873/**
874* Function: paintVertexShape
875*
876* Paints the vertex shape.
877*/
878mxShapeIOS7URL.prototype.paintVertexShape = function(c, x, y, w, h)
879{
880	c.translate(x, y);
881	this.background(c, w, h);
882	c.setShadow(false);
883	this.foreground(c, w, h);
884};
885
886mxShapeIOS7URL.prototype.background = function(c, w, h)
887{
888	c.rect(0, 0, w, h);
889	c.fill();
890};
891
892mxShapeIOS7URL.prototype.foreground = function(c, w, h)
893{
894	var mainText = mxUtils.getValue(this.style, mxIOS7C.BUTTON_TEXT, 'draw.io');
895	var fontColor = mxUtils.getValue(this.style, mxIOS7C.STYLE_TEXTCOLOR, '#666666');
896	var strokeColor2 = mxUtils.getValue(this.style, mxIOS7C.STYLE_STROKECOLOR2, '#008cff');
897	var fontSize = mxUtils.getValue(this.style, mxIOS7C.STYLE_TEXTSIZE, '17');
898	var rSize = Math.min(w, h) * 0.1;
899
900	c.setFillColor('#d8d8d8');
901	c.roundrect(w * 0.05, h * 0.15, w * 0.9, h * 0.7, rSize, rSize);
902	c.fill();
903
904	c.setFontColor(fontColor);
905	c.setFontSize(Math.min(h * 0.7, w * 0.1));
906
907	c.text(w * 0.5, h * 0.5, 0, 0, mainText, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
908
909	c.setStrokeColor(strokeColor2);
910	c.begin();
911	c.moveTo(w * 0.95 - 5, h * 0.5);
912	c.arcTo(3, 3, 0, 1, 1, w * 0.95 - 8, h * 0.5 - 3);
913	c.stroke();
914
915	c.setFillColor(strokeColor2);
916	c.begin();
917	c.moveTo(w * 0.95 - 8, h * 0.5 - 4);
918	c.lineTo(w * 0.95 - 6, h * 0.5 - 3);
919	c.lineTo(w * 0.95 - 8, h * 0.5 - 2);
920	c.close();
921	c.fillAndStroke();
922};
923
924mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_URL, mxShapeIOS7URL);
925
926//**********************************************************************************************************************************************************
927//Action Dialog
928//**********************************************************************************************************************************************************
929/**
930* Extends mxShape.
931*/
932function mxShapeIOS7Actiondialog(bounds, fill, stroke, strokewidth)
933{
934	mxShape.call(this);
935	this.bounds = bounds;
936	this.fill = fill;
937	this.stroke = stroke;
938	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
939};
940
941/**
942* Extends mxShape.
943*/
944mxUtils.extend(mxShapeIOS7Actiondialog, mxShape);
945
946/**
947* Function: paintVertexShape
948*
949* Paints the vertex shape.
950*/
951mxShapeIOS7Actiondialog.prototype.paintVertexShape = function(c, x, y, w, h)
952{
953	var mainText = mxUtils.getValue(this.style, mxIOS7C.MAIN_TEXT, 'Main Text');
954	var subText = mxUtils.getValue(this.style, mxIOS7C.SUB_TEXT, 'Sub Text');
955	var fontColor = mxUtils.getValue(this.style, mxIOS7C.STYLE_TEXTCOLOR, '#666666');
956	var fontSize = mxUtils.getValue(this.style, mxIOS7C.STYLE_TEXTSIZE, '17');
957	c.translate(x, y);
958	this.background(c, x, y, w, h);
959
960	c.setShadow(false);
961
962	c.setFillColor('#e0e0e0');
963	c.roundrect(w * 0.05, h * 0.1, w * 0.9, h * 0.35, w * 0.025, h * 0.05);
964	c.fill();
965	c.roundrect(w * 0.05, h * 0.55, w * 0.9, h * 0.35, w * 0.025, h * 0.05);
966	c.fill();
967
968	c.setFontStyle(mxConstants.FONT_BOLD);
969	this.mainText(c, x, y, w, h, mainText, fontSize, fontColor);
970	this.subText(c, x, y, w, h, subText, fontSize / 1.4, fontColor);
971};
972
973mxShapeIOS7Actiondialog.prototype.background = function(c, x, y, w, h)
974{
975	c.rect(0, 0, w, h);
976	c.fill();
977};
978
979mxShapeIOS7Actiondialog.prototype.mainText = function(c, x, y, w, h, text, fontSize, fontColor)
980{
981	c.begin();
982	c.setFontSize(fontSize);
983	c.setFontColor(fontColor);
984	c.text(w * 0.5, h * 0.4, 0, 0, text, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
985};
986
987mxShapeIOS7Actiondialog.prototype.subText = function(c, x, y, w, h, text, fontSize, fontColor)
988{
989	c.begin();
990	c.setFontSize(fontSize);
991	c.text(w * 0.5, h * 0.7, 0, 0, text, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
992};
993
994mxCellRenderer.registerShape(mxIOS7C.SHAPE_IOS7_ACTION_DIALOG, mxShapeIOS7Actiondialog);
995
996//**********************************************************************************************************************************************************
997//Anchor (a dummy shape without visuals used for anchoring)
998//**********************************************************************************************************************************************************
999/**
1000* Extends mxShape.
1001*/
1002function mxShapeIOS7Anchor(bounds, fill, stroke, strokewidth)
1003{
1004	mxShape.call(this);
1005	this.bounds = bounds;
1006};
1007
1008/**
1009* Extends mxShape.
1010*/
1011mxUtils.extend(mxShapeIOS7Anchor, mxShape);
1012
1013mxShapeIOS7Anchor.prototype.cst = {
1014		ANCHOR : 'mxgraph.ios7ui.anchor'
1015};
1016
1017/**
1018* Function: paintVertexShape
1019*
1020* Paints the vertex shape.
1021*/
1022mxShapeIOS7Anchor.prototype.paintVertexShape = function(c, x, y, w, h)
1023{
1024};
1025
1026mxCellRenderer.registerShape(mxShapeIOS7Anchor.prototype.cst.ANCHOR, mxShapeIOS7Anchor);
1027
1028//**********************************************************************************************************************************************************
1029//Rounded rectangle (adjustable rounding)
1030//**********************************************************************************************************************************************************
1031/**
1032* Extends mxShape.
1033*/
1034function mxShapeIOS7RRect(bounds, fill, stroke, strokewidth)
1035{
1036	mxShape.call(this);
1037	this.bounds = bounds;
1038	this.fill = fill;
1039	this.stroke = stroke;
1040	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1041};
1042
1043/**
1044* Extends mxShape.
1045*/
1046mxUtils.extend(mxShapeIOS7RRect, mxShape);
1047
1048mxShapeIOS7RRect.prototype.cst = {
1049		RRECT : 'mxgraph.ios7ui.rrect',
1050		R_SIZE : 'rSize'
1051};
1052
1053mxShapeIOS7RRect.prototype.customProperties = [
1054	{name: 'rSize', dispName: 'Arc Size', type: 'float', min:0, defVal:3}
1055];
1056
1057/**
1058* Function: paintVertexShape
1059*
1060* Paints the vertex shape.
1061*/
1062mxShapeIOS7RRect.prototype.paintVertexShape = function(c, x, y, w, h)
1063{
1064	c.translate(x, y);
1065
1066	var rSize = parseInt(mxUtils.getValue(this.style, mxShapeIOS7RRect.prototype.cst.R_SIZE, '10'));
1067	c.roundrect(0, 0, w, h, rSize);
1068	c.fillAndStroke();
1069};
1070
1071mxCellRenderer.registerShape(mxShapeIOS7RRect.prototype.cst.RRECT, mxShapeIOS7RRect);
1072
1073//**********************************************************************************************************************************************************
1074//Left Button
1075//**********************************************************************************************************************************************************
1076/**
1077* Extends mxShape.
1078*/
1079function mxShapeIOS7LeftButton(bounds, fill, stroke, strokewidth)
1080{
1081	mxShape.call(this);
1082	this.bounds = bounds;
1083	this.fill = fill;
1084	this.stroke = stroke;
1085	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1086};
1087
1088/**
1089* Extends mxShape.
1090*/
1091mxUtils.extend(mxShapeIOS7LeftButton, mxShape);
1092
1093mxShapeIOS7LeftButton.prototype.cst = {
1094		LEFT_BUTTON : 'mxgraph.ios7ui.leftButton',
1095		R_SIZE : 'rSize'
1096};
1097
1098mxShapeIOS7LeftButton.prototype.customProperties = [
1099	{name: 'rSize', dispName: 'Arc Size', type: 'float', min:0, defVal:3}
1100];
1101
1102/**
1103* Function: paintVertexShape
1104*
1105* Paints the vertex shape.
1106*/
1107mxShapeIOS7LeftButton.prototype.paintVertexShape = function(c, x, y, w, h)
1108{
1109	c.translate(x, y);
1110
1111	var rSize = parseInt(mxUtils.getValue(this.style, mxShapeIOS7LeftButton.prototype.cst.R_SIZE, '10'));
1112
1113	c.begin();
1114	c.moveTo(w, 0);
1115	c.lineTo(w, h);
1116	c.lineTo(rSize, h);
1117	c.arcTo(rSize, rSize, 0, 0, 1, 0, h - rSize);
1118	c.lineTo(0, rSize);
1119	c.arcTo(rSize, rSize, 0, 0, 1, rSize, 0);
1120	c.close();
1121	c.fillAndStroke();
1122};
1123
1124mxCellRenderer.registerShape(mxShapeIOS7LeftButton.prototype.cst.LEFT_BUTTON, mxShapeIOS7LeftButton);
1125
1126//**********************************************************************************************************************************************************
1127//Right Button
1128//**********************************************************************************************************************************************************
1129/**
1130* Extends mxShape.
1131*/
1132function mxShapeIOS7RightButton(bounds, fill, stroke, strokewidth)
1133{
1134	mxShape.call(this);
1135	this.bounds = bounds;
1136	this.fill = fill;
1137	this.stroke = stroke;
1138	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1139};
1140
1141/**
1142* Extends mxShape.
1143*/
1144mxUtils.extend(mxShapeIOS7RightButton, mxShape);
1145
1146mxShapeIOS7RightButton.prototype.cst = {
1147		RIGHT_BUTTON : 'mxgraph.ios7ui.rightButton',
1148		R_SIZE : 'rSize'
1149};
1150
1151mxShapeIOS7RightButton.prototype.customProperties = [
1152	{name: 'rSize', dispName: 'Arc Size', type: 'float', min:0, defVal:3}
1153];
1154
1155/**
1156* Function: paintVertexShape
1157*
1158* Paints the vertex shape.
1159*/
1160mxShapeIOS7RightButton.prototype.paintVertexShape = function(c, x, y, w, h)
1161{
1162	c.translate(x, y);
1163
1164	var rSize = parseInt(mxUtils.getValue(this.style, mxShapeIOS7RightButton.prototype.cst.R_SIZE, '10'));
1165
1166	c.begin();
1167	c.moveTo(0, 0);
1168	c.lineTo(w - rSize, 0);
1169	c.arcTo(rSize, rSize, 0, 0, 1, w, rSize);
1170	c.lineTo(w, h - rSize);
1171	c.arcTo(rSize, rSize, 0, 0, 1, w - rSize, h);
1172	c.lineTo(0, h);
1173	c.close();
1174	c.fillAndStroke();
1175};
1176
1177mxCellRenderer.registerShape(mxShapeIOS7RightButton.prototype.cst.RIGHT_BUTTON, mxShapeIOS7RightButton);
1178
1179//**********************************************************************************************************************************************************
1180//Top Button
1181//**********************************************************************************************************************************************************
1182/**
1183* Extends mxShape.
1184*/
1185function mxShapeIOS7TopButton(bounds, fill, stroke, strokewidth)
1186{
1187	mxShape.call(this);
1188	this.bounds = bounds;
1189	this.fill = fill;
1190	this.stroke = stroke;
1191	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1192};
1193
1194/**
1195* Extends mxShape.
1196*/
1197mxUtils.extend(mxShapeIOS7TopButton, mxShape);
1198
1199mxShapeIOS7TopButton.prototype.cst = {
1200		TOP_BUTTON : 'mxgraph.ios7ui.topButton',
1201		R_SIZE : 'rSize'
1202};
1203
1204mxShapeIOS7TopButton.prototype.customProperties = [
1205	{name: 'rSize', dispName: 'Arc Size', type: 'float', min:0, defVal:3}
1206];
1207
1208/**
1209* Function: paintVertexShape
1210*
1211* Paints the vertex shape.
1212*/
1213mxShapeIOS7TopButton.prototype.paintVertexShape = function(c, x, y, w, h)
1214{
1215	c.translate(x, y);
1216
1217	var rSize = parseInt(mxUtils.getValue(this.style, mxShapeIOS7TopButton.prototype.cst.R_SIZE, '10'));
1218
1219	c.begin();
1220	c.moveTo(w, h);
1221	c.lineTo(0, h);
1222	c.lineTo(0, rSize);
1223	c.arcTo(rSize, rSize, 0, 0, 1, rSize, 0);
1224	c.lineTo(w - rSize, 0);
1225	c.arcTo(rSize, rSize, 0, 0, 1, w, rSize);
1226	c.close();
1227	c.fillAndStroke();
1228};
1229
1230mxCellRenderer.registerShape(mxShapeIOS7TopButton.prototype.cst.TOP_BUTTON, mxShapeIOS7TopButton);
1231
1232//**********************************************************************************************************************************************************
1233//Bottom Button
1234//**********************************************************************************************************************************************************
1235/**
1236* Extends mxShape.
1237*/
1238function mxShapeIOS7BottomButton(bounds, fill, stroke, strokewidth)
1239{
1240	mxShape.call(this);
1241	this.bounds = bounds;
1242	this.fill = fill;
1243	this.stroke = stroke;
1244	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1245};
1246
1247/**
1248* Extends mxShape.
1249*/
1250mxUtils.extend(mxShapeIOS7BottomButton, mxShape);
1251
1252mxShapeIOS7BottomButton.prototype.cst = {
1253		BOTTOM_BUTTON : 'mxgraph.ios7ui.bottomButton',
1254		R_SIZE : 'rSize'
1255};
1256
1257mxShapeIOS7BottomButton.prototype.customProperties = [
1258	{name: 'rSize', dispName: 'Arc Size', type: 'float', min:0, defVal:3},
1259];
1260
1261/**
1262* Function: paintVertexShape
1263*
1264* Paints the vertex shape.
1265*/
1266mxShapeIOS7BottomButton.prototype.paintVertexShape = function(c, x, y, w, h)
1267{
1268	c.translate(x, y);
1269
1270	var rSize = parseInt(mxUtils.getValue(this.style, mxShapeIOS7BottomButton.prototype.cst.R_SIZE, '10'));
1271
1272	c.begin();
1273	c.moveTo(w, 0);
1274	c.lineTo(0, 0);
1275	c.lineTo(0, h - rSize);
1276	c.arcTo(rSize, rSize, 0, 0, 0, rSize, h);
1277	c.lineTo(w - rSize, h);
1278	c.arcTo(rSize, rSize, 0, 0, 0, w, h - rSize);
1279	c.close();
1280	c.fillAndStroke();
1281};
1282
1283mxCellRenderer.registerShape(mxShapeIOS7BottomButton.prototype.cst.BOTTOM_BUTTON, mxShapeIOS7BottomButton);
1284
1285//**********************************************************************************************************************************************************
1286//Horizontal Lines
1287//**********************************************************************************************************************************************************
1288/**
1289* Extends mxShape.
1290*/
1291function mxShapeIOS7HorLines(bounds, fill, stroke, strokewidth)
1292{
1293	mxShape.call(this);
1294	this.bounds = bounds;
1295	this.fill = fill;
1296	this.stroke = stroke;
1297	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1298};
1299
1300/**
1301* Extends mxShape.
1302*/
1303mxUtils.extend(mxShapeIOS7HorLines, mxShape);
1304
1305mxShapeIOS7HorLines.prototype.cst = {
1306		HOR_LINES : 'mxgraph.ios7ui.horLines'
1307};
1308
1309/**
1310* Function: paintVertexShape
1311*
1312* Paints the vertex shape.
1313*/
1314mxShapeIOS7HorLines.prototype.paintVertexShape = function(c, x, y, w, h)
1315{
1316	c.translate(x, y);
1317
1318	c.rect(0, 0, w, h);
1319	c.fill();
1320
1321	c.begin();
1322	c.moveTo(0, 0);
1323	c.lineTo(w, 0);
1324	c.moveTo(0, h);
1325	c.lineTo(w, h);
1326	c.stroke();
1327};
1328
1329mxCellRenderer.registerShape(mxShapeIOS7HorLines.prototype.cst.HOR_LINES, mxShapeIOS7HorLines);
1330
1331//**********************************************************************************************************************************************************
1332//rect with margins
1333//**********************************************************************************************************************************************************
1334/**
1335* Extends mxShape.
1336*/
1337function mxShapeIOS7MarginRect(bounds, fill, stroke, strokewidth)
1338{
1339	mxShape.call(this);
1340	this.bounds = bounds;
1341	this.fill = fill;
1342	this.stroke = stroke;
1343	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1344};
1345
1346/**
1347* Extends mxShape.
1348*/
1349mxUtils.extend(mxShapeIOS7MarginRect, mxShape);
1350
1351mxShapeIOS7MarginRect.prototype.customProperties = [
1352	{name: 'rx', dispName: 'Hor. Rounding Size', type: 'float', min:0, defVal:3},
1353	{name: 'ry', dispName: 'Ver. Rounding Size', type: 'float', min:0, defVal:3},
1354	{name: 'rectMargin', dispName: 'Global Margin', type: 'float', min:0, defVal:5},
1355	{name: 'rectMarginTop', dispName: 'Top Margin', type: 'float', min:0, defVal:0},
1356	{name: 'rectMarginLeft', dispName: 'Left Margin', type: 'float', min:0, defVal:0},
1357	{name: 'rectMarginBottom', dispName: 'Bottom Margin', type: 'float', min:0, defVal:0},
1358	{name: 'rectMarginRight', dispName: 'Right Margin', type: 'float', min:0, defVal:0}
1359];
1360
1361mxShapeIOS7MarginRect.prototype.cst = {
1362		SHAPE_MARGIN_RECT : 'mxgraph.ios7ui.marginRect',
1363		MARGIN : 'rectMargin',
1364		RX : 'rx',
1365		RY : 'ry',
1366		MARGIN_TOP : 'rectMarginTop',
1367		MARGIN_LEFT : 'rectMarginLeft',
1368		MARGIN_BOTTOM : 'rectMarginBottom',
1369		MARGIN_RIGHT : 'rectMarginRight'
1370};
1371/**
1372* Function: paintVertexShape
1373*
1374* Paints the vertex shape.
1375*/
1376mxShapeIOS7MarginRect.prototype.paintVertexShape = function(c, x, y, w, h)
1377{
1378
1379	c.translate(x, y);
1380	this.background(c, x, y, w, h);
1381};
1382
1383mxShapeIOS7MarginRect.prototype.background = function(c, x, y, w, h, state)
1384{
1385	var margin = parseFloat(mxUtils.getValue(this.style, mxShapeIOS7MarginRect.prototype.cst.MARGIN, '0'));
1386	var marginTop = parseFloat(mxUtils.getValue(this.style, mxShapeIOS7MarginRect.prototype.cst.MARGIN_TOP, '0'));
1387	var marginLeft = parseFloat(mxUtils.getValue(this.style, mxShapeIOS7MarginRect.prototype.cst.MARGIN_LEFT, '0'));
1388	var marginBottom = parseFloat(mxUtils.getValue(this.style, mxShapeIOS7MarginRect.prototype.cst.MARGIN_BOTTOM, '0'));
1389	var marginRight = parseFloat(mxUtils.getValue(this.style, mxShapeIOS7MarginRect.prototype.cst.MARGIN_RIGHT, '0'));
1390	var rx = parseFloat(mxUtils.getValue(this.style, mxShapeIOS7MarginRect.prototype.cst.RX, '0'));
1391	var ry = parseFloat(mxUtils.getValue(this.style, mxShapeIOS7MarginRect.prototype.cst.RY, '0'));
1392
1393	var x1 = margin + marginLeft;
1394	var y1 = margin + marginTop;
1395	var w1 = w - marginRight - x1 - margin;
1396	var h1 = h - marginBottom - y1 - margin;
1397
1398	if (w1 >0 && h1 > 0)
1399	{
1400		c.begin();
1401		c.roundrect(x1, y1, w1, h1, rx, ry);
1402		c.fillAndStroke();
1403	}
1404};
1405
1406mxCellRenderer.registerShape(mxShapeIOS7MarginRect.prototype.cst.SHAPE_MARGIN_RECT, mxShapeIOS7MarginRect);
1407
1408//**********************************************************************************************************************************************************
1409//Callout
1410//**********************************************************************************************************************************************************
1411/**
1412* Extends mxShape.
1413*/
1414function mxShapeIOS7Callout(bounds, fill, stroke, strokewidth)
1415{
1416	mxShape.call(this);
1417	this.bounds = bounds;
1418	this.fill = fill;
1419	this.stroke = stroke;
1420	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1421};
1422
1423/**
1424* Extends mxShape.
1425*/
1426mxUtils.extend(mxShapeIOS7Callout, mxShape);
1427
1428mxShapeIOS7Callout.prototype.cst = {
1429		SHAPE_CALLOUT : 'mxgraph.ios7ui.callout'
1430};
1431
1432/**
1433* Function: paintVertexShape
1434*
1435* Paints the vertex shape.
1436*/
1437mxShapeIOS7Callout.prototype.paintVertexShape = function(c, x, y, w, h)
1438{
1439
1440	c.translate(x, y);
1441	this.background(c, x, y, w, h);
1442};
1443
1444mxShapeIOS7Callout.prototype.background = function(c, x, y, w, h, state)
1445{
1446	var r = 10;
1447
1448	if (w >= 30 && h >= 20)
1449	{
1450		c.begin();
1451		c.moveTo(15, h - r * 0.3);
1452		c.arcTo(r * 2, r, 0, 0, 1, 0, h);
1453		c.arcTo(r * 1.5, r * 1.5, 0, 0, 0, 10, h - r * 1);
1454		c.lineTo(r, r);
1455		c.arcTo(r, r, 0, 0, 1, r * 2, 0);
1456		c.lineTo(w - r, 0);
1457		c.arcTo(r, r, 0, 0, 1, w, r);
1458		c.lineTo(w, h - r);
1459		c.arcTo(r, r, 0, 0, 1, w - r, h);
1460		c.lineTo(r * 2, h);
1461		c.arcTo(r, r, 0, 0, 1, r * 1.5, h - r * 0.3);
1462		c.close();
1463		c.fillAndStroke();
1464	}
1465};
1466
1467mxCellRenderer.registerShape(mxShapeIOS7Callout.prototype.cst.SHAPE_CALLOUT, mxShapeIOS7Callout);
1468
1469//**********************************************************************************************************************************************************
1470//Select Bar
1471//**********************************************************************************************************************************************************
1472/**
1473* Extends mxShape.
1474*/
1475function mxShapeIOS7SelectBar(bounds, fill, stroke, strokewidth)
1476{
1477	mxShape.call(this);
1478	this.bounds = bounds;
1479	this.fill = fill;
1480	this.stroke = stroke;
1481	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1482	this.dy = 0.5;
1483	this.dx = 0.5;
1484	this.dx2 = 70;
1485	this.size = 10;
1486};
1487
1488/**
1489* Extends mxShape.
1490*/
1491mxUtils.extend(mxShapeIOS7SelectBar, mxActor);
1492
1493mxShapeIOS7SelectBar.prototype.cst = {
1494		SELECT_BAR : 'mxgraph.ios7ui.selectBar'
1495};
1496
1497mxShapeIOS7SelectBar.prototype.customProperties = [
1498	{name: 'dx', dispName: 'Callout Position', type: 'float', min:0, defVal:120},
1499	{name: 'dx2', dispName: 'Field Size', type: 'float', min:0, defVal: 75},
1500	{name: 'size', dispName: 'Rounding size', type: 'float', min:0, defVal:5},
1501	{name: 'dy', dispName: 'Callout Size', type: 'float', min:0, defVal:5}
1502];
1503
1504/**
1505* Function: paintVertexShape
1506*
1507* Paints the vertex shape.
1508*/
1509mxShapeIOS7SelectBar.prototype.paintVertexShape = function(c, x, y, w, h)
1510{
1511	c.translate(x, y);
1512
1513	var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
1514	var dx2 = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
1515	var r = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
1516	var dy = Math.max(0, Math.min(h, (w - Math.max(20, r) - r) / 2, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
1517
1518	r = Math.min(h / 2, w / 2, r);
1519	dx = Math.max(r + dy, dx);
1520	dx = Math.min(w - r - dy, w - 20 - dy, dx);
1521
1522	c.begin();
1523	c.moveTo(dx - dy, h);
1524	c.lineTo(r, h);
1525	c.arcTo(r, r, 0, 0, 1, 0, h - r);
1526	c.lineTo(0, r);
1527	c.arcTo(r, r, 0, 0, 1, r, 0);
1528	c.lineTo(w - r, 0);
1529	c.arcTo(r, r, 0, 0, 1, w, r);
1530	c.lineTo(w, h - r);
1531	c.arcTo(r, r, 0, 0, 1, w - r, h);
1532	c.lineTo(dx + dy, h);
1533	c.lineTo(dx, h + dy);
1534	c.close();
1535	c.fillAndStroke();
1536
1537	c.setShadow(false);
1538
1539	c.begin();
1540	c.moveTo(w - Math.max(20, r), 0);
1541	c.lineTo(w - Math.max(20, r), h);
1542	c.stroke();
1543
1544	var currDx = dx2;
1545
1546	c.begin();
1547
1548	while (currDx < (w - Math.max(20, r)))
1549	{
1550		c.moveTo(currDx, 0);
1551		c.lineTo(currDx, h);
1552
1553		currDx = currDx + dx2;
1554	}
1555
1556	c.stroke();
1557
1558	var w1 = Math.min(Math.max(20, r), h);
1559	var x1 = w - w1 * 0.5;
1560	var y1 = h * 0.5;
1561
1562	c.setFillColor(mxUtils.getValue(this.style, mxConstants.STYLE_STROKECOLOR, ''));
1563	c.begin();
1564	c.moveTo(x1 - w1 * 0.15, y1 - w1 * 0.225);
1565	c.lineTo(x1 + w1 * 0.25, y1);
1566	c.lineTo(x1 - w1 * 0.15, y1 + w1 * 0.225);
1567	c.close();
1568	c.fill();
1569};
1570
1571mxCellRenderer.registerShape(mxShapeIOS7SelectBar.prototype.cst.SELECT_BAR, mxShapeIOS7SelectBar);
1572
1573mxShapeIOS7SelectBar.prototype.constraints = null;
1574
1575Graph.handleFactory[mxShapeIOS7SelectBar.prototype.cst.SELECT_BAR] = function(state)
1576{
1577	var handles = [Graph.createHandle(state, ['dx'], function(bounds)
1578			{
1579				var dx = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
1580
1581				return new mxPoint(bounds.x + dx, bounds.y + bounds.height);
1582			}, function(bounds, pt)
1583			{
1584				var y = parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy)) * 0.6;
1585				this.state.style['dx'] = Math.round(100 * Math.max(y, Math.min(bounds.width - y, pt.x - bounds.x))) / 100;
1586			})];
1587
1588	var handle2 = Graph.createHandle(state, ['dy'], function(bounds)
1589			{
1590				var dy = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
1591
1592				return new mxPoint(bounds.x + parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx)), bounds.y + bounds.height + dy);
1593			}, function(bounds, pt)
1594			{
1595				this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(bounds.height, pt.y - bounds.y - bounds.height))) / 100;
1596			});
1597
1598	handles.push(handle2);
1599
1600	var handle3 = Graph.createHandle(state, ['size'], function(bounds)
1601			{
1602				var size = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'size', this.size))));
1603
1604				return new mxPoint(bounds.x + bounds.width - size, bounds.y + 10);
1605			}, function(bounds, pt)
1606			{
1607				this.state.style['size'] = Math.round(100 * Math.max(0, Math.min(bounds.width / 2, bounds.height / 2, bounds.x + bounds.width - pt.x))) / 100;
1608			});
1609
1610	handles.push(handle3);
1611
1612	var handle4 = Graph.createHandle(state, ['dx2'], function(bounds)
1613			{
1614				var dx2 = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2))));
1615
1616				return new mxPoint(bounds.x + dx2, bounds.y + bounds.height / 2);
1617			}, function(bounds, pt)
1618			{
1619				this.state.style['dx2'] = Math.round(100 * Math.max(0, Math.min(bounds.width, pt.x - bounds.x))) / 100;
1620			});
1621
1622	handles.push(handle4);
1623
1624	return handles;
1625
1626}
1627
1628//**********************************************************************************************************************************************************
1629//slider
1630//**********************************************************************************************************************************************************
1631/**
1632* Extends mxShape.
1633*/
1634//mxShapeIOS7SelectBar
1635function mxShapeIOS7Slider2(bounds, fill, stroke, strokewidth)
1636{
1637	mxShape.call(this);
1638	this.bounds = bounds;
1639	this.fill = fill;
1640	this.stroke = stroke;
1641	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1642};
1643
1644/**
1645* Extends mxShape.
1646*/
1647mxUtils.extend(mxShapeIOS7Slider2, mxShape);
1648
1649mxShapeIOS7Slider2.prototype.cst = {
1650		SHAPE_SLIDER : 'mxgraph.ios7ui.slider',
1651		BAR_POS : 'barPos',
1652		HANDLE_SIZE : 'handleSize'
1653};
1654
1655mxShapeIOS7Slider2.prototype.customProperties = [
1656	{name: 'barPos', dispName: 'Handle Position', type: 'float', min:0, max:1, defVal:20},
1657	{name: 'handleSize', dispName: 'Handle Size', type: 'float', min:0, defVal:10}
1658];
1659
1660/**
1661* Function: paintVertexShape
1662*
1663* Paints the vertex shape.
1664*/
1665mxShapeIOS7Slider2.prototype.paintVertexShape = function(c, x, y, w, h)
1666{
1667
1668	c.translate(x, y);
1669	this.background(c, x, y, w, h);
1670	c.setShadow(true);
1671};
1672
1673mxShapeIOS7Slider2.prototype.background = function(c, x, y, w, h)
1674{
1675	var hSize = parseFloat(mxUtils.getValue(this.style, mxShapeIOS7Slider2.prototype.cst.HANDLE_SIZE, '10'));
1676	var barPos = parseFloat(mxUtils.getValue(this.style, mxShapeIOS7Slider2.prototype.cst.BAR_POS, '40')) / 100;
1677
1678	barPos = Math.max(0, Math.min(1, barPos));
1679
1680	c.save();
1681	c.setStrokeColor('#bbbbbb');
1682	c.begin();
1683	c.moveTo(0, h * 0.5);
1684	c.lineTo(w, h * 0.5);
1685	c.fillAndStroke();
1686
1687
1688	c.restore();
1689	c.begin();
1690	c.moveTo(0, h * 0.5);
1691	c.lineTo(barPos * w, h * 0.5);
1692	c.fillAndStroke();
1693
1694	c.setStrokeColor('#bbbbbb');
1695	c.begin();
1696	c.ellipse(barPos * w - hSize * 0.5, h * 0.5 - hSize * 0.5, hSize, hSize);
1697	c.fillAndStroke();
1698
1699};
1700
1701mxCellRenderer.registerShape(mxShapeIOS7Slider2.prototype.cst.SHAPE_SLIDER, mxShapeIOS7Slider2);
1702
1703mxShapeIOS7Slider2.prototype.constraints = null;
1704
1705Graph.handleFactory[mxShapeIOS7Slider2.prototype.cst.SHAPE_SLIDER] = function(state)
1706{
1707	var handles = [Graph.createHandle(state, ['barPos'], function(bounds)
1708			{
1709				var barPos = Math.max(0, Math.min(bounds.width, parseFloat(mxUtils.getValue(this.state.style, 'barPos', 0.4))));
1710
1711				return new mxPoint(bounds.x + barPos * bounds.width / 100, bounds.y + bounds.height / 2);
1712			}, function(bounds, pt)
1713			{
1714				this.state.style['barPos'] = Math.round(100 * Math.max(0, Math.min(100, (pt.x - bounds.x) * 100 / bounds.width))) / 100;
1715			})];
1716
1717	return handles;
1718};
1719
1720