1/**
2 * $Id: mxElectrical.js,v 1.0 2016/10/25 17:05:39 mate Exp $
3 * Copyright (c) 2006-2016, JGraph Ltd
4 */
5
6//**********************************************************************************************************************************************************
7//Test Point
8//**********************************************************************************************************************************************************
9/**
10* Extends mxShape.
11*/
12function mxShapeElectricalTestPoint(bounds, fill, stroke, strokewidth)
13{
14	mxShape.call(this);
15	this.bounds = bounds;
16	this.fill = fill;
17	this.stroke = stroke;
18	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
19};
20
21/**
22* Extends mxShape.
23*/
24mxUtils.extend(mxShapeElectricalTestPoint, mxShape);
25
26mxShapeElectricalTestPoint.prototype.cst = {
27		SHAPE_TEST_POINT : 'mxgraph.electrical.transmission.testPoint'
28};
29
30/**
31* Function: paintVertexShape
32*
33* Paints the vertex shape.
34*/
35mxShapeElectricalTestPoint.prototype.paintVertexShape = function(c, x, y, w, h)
36{
37	c.translate(x, y);
38	var strokeColor = mxUtils.getValue(this.style, mxConstants.STYLE_STROKECOLOR, '#000000');
39
40	var size = Math.min(w, h);
41
42	c.setFillColor(strokeColor);
43	c.begin();
44	c.ellipse(w * 0.5 - size / 2, 0, size, size);
45	c.fillAndStroke();
46
47	if (h > w)
48	{
49		c.begin();
50		c.moveTo(w * 0.5, size);
51		c.lineTo(w * 0.5, h);
52		c.stroke();
53	}
54};
55
56mxCellRenderer.registerShape(mxShapeElectricalTestPoint.prototype.cst.SHAPE_TEST_POINT, mxShapeElectricalTestPoint);
57
58mxShapeElectricalTestPoint.prototype.constraints = [
59                                                  new mxConnectionConstraint(new mxPoint(0.5, 0), true),
60                                                  new mxConnectionConstraint(new mxPoint(0.5, 1), true)
61                                                  ];
62
63//**********************************************************************************************************************************************************
64//Straight Bus
65//**********************************************************************************************************************************************************
66/**
67* Extends mxShape.
68*/
69function mxShapeElectricalStraightBus(bounds, fill, stroke, strokewidth)
70{
71	mxShape.call(this);
72	this.bounds = bounds;
73	this.fill = fill;
74	this.stroke = stroke;
75	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
76};
77
78/**
79* Extends mxShape.
80*/
81mxUtils.extend(mxShapeElectricalStraightBus, mxShape);
82
83mxShapeElectricalStraightBus.prototype.cst = {
84		SHAPE_STRAIGHT_BUS : 'mxgraph.electrical.transmission.straightBus'
85};
86
87
88
89/**
90* Function: paintVertexShape
91*
92* Paints the vertex shape.
93*/
94mxShapeElectricalStraightBus.prototype.paintVertexShape = function(c, x, y, w, h)
95{
96	c.translate(x, y);
97
98	var x1 = w * 0.2;
99	var y1 = 0;
100
101	if (w > h)
102	{
103		y1 = h * 0.5;
104	}
105	else
106	{
107		y1 = w / 2;
108	}
109
110	c.begin();
111	c.moveTo(w - x1, 0);
112	c.lineTo(w - x1, h - y1);
113	c.lineTo(w, h - y1);
114	c.lineTo(w * 0.5, h);
115	c.lineTo(0, h - y1);
116	c.lineTo(x1, h - y1);
117	c.lineTo(x1, 0);
118	c.fillAndStroke();
119};
120
121mxCellRenderer.registerShape(mxShapeElectricalStraightBus.prototype.cst.SHAPE_STRAIGHT_BUS, mxShapeElectricalStraightBus);
122
123mxShapeElectricalStraightBus.prototype.constraints = [
124                                                    new mxConnectionConstraint(new mxPoint(0.5, 0), true),
125                                                    new mxConnectionConstraint(new mxPoint(0.5, 1), true)
126                                                    ];
127
128//**********************************************************************************************************************************************************
129//Two-Line Bus Elbow
130//**********************************************************************************************************************************************************
131/**
132* Extends mxShape.
133*/
134function mxShapeElectricalTwoLineBusElbow(bounds, fill, stroke, strokewidth)
135{
136	mxShape.call(this);
137	this.bounds = bounds;
138	this.fill = fill;
139	this.stroke = stroke;
140	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
141	this.notch = 0;
142};
143
144/**
145* Extends mxShape.
146*/
147mxUtils.extend(mxShapeElectricalTwoLineBusElbow, mxShape);
148
149mxShapeElectricalTwoLineBusElbow.prototype.cst = {
150		SHAPE_TWO_LINE_BUS_ELBOW : 'mxgraph.electrical.transmission.twoLineBusElbow'
151};
152
153mxShapeElectricalTwoLineBusElbow.prototype.customProperties = [
154	{name:'notch', dispName:'Spacing', type:'float', min:0, defVal:25}
155];
156
157/**
158* Function: paintVertexShape
159*
160* Paints the vertex shape.
161*/
162mxShapeElectricalTwoLineBusElbow.prototype.paintVertexShape = function(c, x, y, w, h)
163{
164	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
165
166	c.translate(x, y);
167
168	c.begin();
169	c.moveTo(0, h);
170	c.lineTo(w, h);
171	c.lineTo(w, 0);
172	c.stroke();
173
174	var wn = Math.min(w, notch);
175	var hn = Math.min(h, notch);
176
177	c.begin();
178	c.moveTo(0, h - hn);
179	c.lineTo(w - wn, h - hn);
180	c.lineTo(w - wn, 0);
181	c.stroke();
182};
183
184mxCellRenderer.registerShape(mxShapeElectricalTwoLineBusElbow.prototype.cst.SHAPE_TWO_LINE_BUS_ELBOW, mxShapeElectricalTwoLineBusElbow);
185
186mxShapeElectricalTwoLineBusElbow.prototype.constraints = null;
187
188Graph.handleFactory[mxShapeElectricalTwoLineBusElbow.prototype.cst.SHAPE_TWO_LINE_BUS_ELBOW] = function(state)
189{
190	var handles = [Graph.createHandle(state, ['notch'], function(bounds)
191	{
192		var notch = Math.max(Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))), 0);
193
194		return new mxPoint(bounds.x + bounds.width / 4, bounds.y + bounds.height - notch);
195	}, function(bounds, pt)
196	{
197		this.state.style['notch'] = Math.round(0.2 * Math.max(0, bounds.width - pt.y + bounds.y)) / 0.2;
198	})];
199
200	return handles;
201
202}
203
204//**********************************************************************************************************************************************************
205//Three-Line Bus Elbow
206//**********************************************************************************************************************************************************
207/**
208* Extends mxShape.
209*/
210function mxShapeElectricalThreeLineBusElbow(bounds, fill, stroke, strokewidth)
211{
212	mxShape.call(this);
213	this.bounds = bounds;
214	this.fill = fill;
215	this.stroke = stroke;
216	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
217	this.notch = 0;
218};
219
220/**
221* Extends mxShape.
222*/
223mxUtils.extend(mxShapeElectricalThreeLineBusElbow, mxShape);
224
225mxShapeElectricalThreeLineBusElbow.prototype.cst = {
226		SHAPE_THREE_LINE_BUS_ELBOW : 'mxgraph.electrical.transmission.threeLineBusElbow'
227};
228
229mxShapeElectricalThreeLineBusElbow.prototype.customProperties = [
230	{name:'notch', dispName:'Spacing', type:'float', min:0, defVal:30}
231];
232
233/**
234* Function: paintVertexShape
235*
236* Paints the vertex shape.
237*/
238mxShapeElectricalThreeLineBusElbow.prototype.paintVertexShape = function(c, x, y, w, h)
239{
240	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
241
242	c.translate(x, y);
243
244	c.begin();
245	c.moveTo(0, h);
246	c.lineTo(w, h);
247	c.lineTo(w, 0);
248	c.stroke();
249
250	var wn = Math.min(w, notch);
251	var hn = Math.min(h, notch);
252
253	c.begin();
254	c.moveTo(0, h - hn);
255	c.lineTo(w - wn, h - hn);
256	c.lineTo(w - wn, 0);
257	c.stroke();
258
259	c.begin();
260	c.moveTo(0, h - hn / 2);
261	c.lineTo(w - wn / 2, h - hn / 2);
262	c.lineTo(w - wn / 2, 0);
263	c.stroke();
264};
265
266mxCellRenderer.registerShape(mxShapeElectricalThreeLineBusElbow.prototype.cst.SHAPE_THREE_LINE_BUS_ELBOW, mxShapeElectricalThreeLineBusElbow);
267
268mxShapeElectricalThreeLineBusElbow.prototype.constraints = null;
269
270Graph.handleFactory[mxShapeElectricalThreeLineBusElbow.prototype.cst.SHAPE_THREE_LINE_BUS_ELBOW] = function(state)
271{
272	var handles = [Graph.createHandle(state, ['notch'], function(bounds)
273	{
274		var notch = Math.max(Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))), 0);
275
276		return new mxPoint(bounds.x + bounds.width / 4, bounds.y + bounds.height - notch);
277	}, function(bounds, pt)
278	{
279		this.state.style['notch'] = Math.round(0.2 * Math.max(0, bounds.width - pt.y + bounds.y)) / 0.2;
280	})];
281
282	return handles;
283
284}
285
286//**********************************************************************************************************************************************************
287//Four-Line Bus Elbow
288//**********************************************************************************************************************************************************
289/**
290* Extends mxShape.
291*/
292function mxShapeElectricalFourLineBusElbow(bounds, fill, stroke, strokewidth)
293{
294	mxShape.call(this);
295	this.bounds = bounds;
296	this.fill = fill;
297	this.stroke = stroke;
298	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
299	this.notch = 0;
300};
301
302/**
303* Extends mxShape.
304*/
305mxUtils.extend(mxShapeElectricalFourLineBusElbow, mxShape);
306
307mxShapeElectricalFourLineBusElbow.prototype.cst = {
308		SHAPE_FOUR_LINE_BUS_ELBOW : 'mxgraph.electrical.transmission.fourLineBusElbow'
309};
310
311mxShapeElectricalFourLineBusElbow.prototype.customProperties = [
312	{name:'notch', dispName:'Spacing', type:'float', min:0, defVal:75}
313];
314
315/**
316* Function: paintVertexShape
317*
318* Paints the vertex shape.
319*/
320mxShapeElectricalFourLineBusElbow.prototype.paintVertexShape = function(c, x, y, w, h)
321{
322	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
323
324	c.translate(x, y);
325
326	c.begin();
327	c.moveTo(0, h);
328	c.lineTo(w, h);
329	c.lineTo(w, 0);
330	c.stroke();
331
332	var wn = Math.min(w, notch);
333	var hn = Math.min(h, notch);
334
335	c.begin();
336	c.moveTo(0, h - hn);
337	c.lineTo(w - wn, h - hn);
338	c.lineTo(w - wn, 0);
339	c.stroke();
340
341	c.begin();
342	c.moveTo(0, h - hn / 3);
343	c.lineTo(w - wn / 3, h - hn / 3);
344	c.lineTo(w - wn / 3, 0);
345	c.stroke();
346
347	c.begin();
348	c.moveTo(0, h - hn * 2 / 3);
349	c.lineTo(w - wn * 2 / 3, h - hn * 2 / 3);
350	c.lineTo(w - wn * 2 / 3, 0);
351	c.stroke();
352};
353
354mxCellRenderer.registerShape(mxShapeElectricalFourLineBusElbow.prototype.cst.SHAPE_FOUR_LINE_BUS_ELBOW, mxShapeElectricalFourLineBusElbow);
355
356mxShapeElectricalFourLineBusElbow.prototype.constraints = null;
357
358Graph.handleFactory[mxShapeElectricalFourLineBusElbow.prototype.cst.SHAPE_FOUR_LINE_BUS_ELBOW] = function(state)
359{
360	var handles = [Graph.createHandle(state, ['notch'], function(bounds)
361	{
362		var notch = Math.max(Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))), 0);
363
364		return new mxPoint(bounds.x + bounds.width / 4, bounds.y + bounds.height - notch);
365	}, function(bounds, pt)
366	{
367		this.state.style['notch'] = Math.round(0.2 * Math.max(0, bounds.width - pt.y + bounds.y)) / 0.2;
368	})];
369
370	return handles;
371}
372
373//**********************************************************************************************************************************************************
374//Four-Line Bus Elbow
375//**********************************************************************************************************************************************************
376/**
377* Extends mxShape.
378*/
379function mxShapeElectricalEightLineBusElbow(bounds, fill, stroke, strokewidth)
380{
381	mxShape.call(this);
382	this.bounds = bounds;
383	this.fill = fill;
384	this.stroke = stroke;
385	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
386	this.notch = 0;
387};
388
389/**
390* Extends mxShape.
391*/
392mxUtils.extend(mxShapeElectricalEightLineBusElbow, mxShape);
393
394mxShapeElectricalEightLineBusElbow.prototype.cst = {
395		SHAPE_EIGHT_LINE_BUS_ELBOW : 'mxgraph.electrical.transmission.eightLineBusElbow'
396};
397
398mxShapeElectricalEightLineBusElbow.prototype.customProperties = [
399	{name:'notch', dispName:'Spacing', type:'float', min:0, defVal:180}
400];
401
402/**
403* Function: paintVertexShape
404*
405* Paints the vertex shape.
406*/
407mxShapeElectricalEightLineBusElbow.prototype.paintVertexShape = function(c, x, y, w, h)
408{
409	var notch = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'notch', this.notch))));
410
411	c.translate(x, y);
412
413	c.begin();
414	c.moveTo(0, h);
415	c.lineTo(w, h);
416	c.lineTo(w, 0);
417	c.stroke();
418
419	var wn = Math.min(w, notch);
420	var hn = Math.min(h, notch);
421
422	c.begin();
423	c.moveTo(0, h - hn);
424	c.lineTo(w - wn, h - hn);
425	c.lineTo(w - wn, 0);
426	c.stroke();
427
428	c.begin();
429	c.moveTo(0, h - hn / 7);
430	c.lineTo(w - wn / 7, h - hn / 7);
431	c.lineTo(w - wn / 7, 0);
432	c.stroke();
433
434	c.begin();
435	c.moveTo(0, h - hn * 2 / 7);
436	c.lineTo(w - wn * 2 / 7, h - hn * 2 / 7);
437	c.lineTo(w - wn * 2 / 7, 0);
438	c.stroke();
439
440	c.begin();
441	c.moveTo(0, h - hn * 3 / 7);
442	c.lineTo(w - wn * 3 / 7, h - hn * 3 / 7);
443	c.lineTo(w - wn * 3 / 7, 0);
444	c.stroke();
445
446	c.begin();
447	c.moveTo(0, h - hn * 4 / 7);
448	c.lineTo(w - wn * 4 / 7, h - hn * 4 / 7);
449	c.lineTo(w - wn * 4 / 7, 0);
450	c.stroke();
451
452	c.begin();
453	c.moveTo(0, h - hn * 5 / 7);
454	c.lineTo(w - wn * 5 / 7, h - hn * 5 / 7);
455	c.lineTo(w - wn * 5 / 7, 0);
456	c.stroke();
457
458	c.begin();
459	c.moveTo(0, h - hn * 6 / 7);
460	c.lineTo(w - wn * 6 / 7, h - hn * 6 / 7);
461	c.lineTo(w - wn * 6 / 7, 0);
462	c.stroke();
463
464};
465
466mxCellRenderer.registerShape(mxShapeElectricalEightLineBusElbow.prototype.cst.SHAPE_EIGHT_LINE_BUS_ELBOW, mxShapeElectricalEightLineBusElbow);
467
468mxShapeElectricalEightLineBusElbow.prototype.constraints = null;
469
470Graph.handleFactory[mxShapeElectricalEightLineBusElbow.prototype.cst.SHAPE_EIGHT_LINE_BUS_ELBOW] = function(state)
471{
472	var handles = [Graph.createHandle(state, ['notch'], function(bounds)
473	{
474		var notch = Math.max(Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'notch', this.notch))), 0);
475
476		return new mxPoint(bounds.x + bounds.width / 4, bounds.y + bounds.height - notch);
477	}, function(bounds, pt)
478	{
479		this.state.style['notch'] = Math.round(0.2 * Math.max(0, bounds.width - pt.y + bounds.y)) / 0.2;
480	})];
481
482	return handles;
483}
484
485//**********************************************************************************************************************************************************
486//Logic Gate
487//**********************************************************************************************************************************************************
488/**
489* Extends mxShape.
490*/
491function mxShapeElectricalLogicGate(bounds, fill, stroke, strokewidth)
492{
493	mxShape.call(this);
494	this.bounds = bounds;
495	this.fill = fill;
496	this.stroke = stroke;
497	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
498};
499
500/**
501* Extends mxShape.
502*/
503mxUtils.extend(mxShapeElectricalLogicGate, mxShape);
504
505mxShapeElectricalLogicGate.prototype.cst = {
506		SHAPE_LOGIC_GATE : 'mxgraph.electrical.logic_gates.logic_gate'
507};
508
509mxShapeElectricalLogicGate.prototype.customProperties = [
510	{name: 'operation', dispName: 'Operation', type: 'enum', defVal:'and',
511		enumList:[
512			{val:'and', dispName:'And'},
513			{val:'or', dispName:'Or'},
514			{val:'xor', dispName:'Xor'}
515		]},
516	{name: 'numInputs', dispName: 'Inputs', type: 'int', min:2, defVal:2},
517	{name: 'negating', dispName: 'Negating', type: 'bool', defVal:0}
518];
519
520/**
521* Function: paintVertexShape
522*
523* Paints the vertex shape.
524*/
525mxShapeElectricalLogicGate.prototype.paintVertexShape = function(c, x, y, w, h)
526{
527	c.translate(x, y);
528	var numInputs = parseInt(mxUtils.getValue(this.style, 'numInputs', '2'));
529	var spacing = h / numInputs;
530	var currH = spacing * 0.5;
531
532	c.begin();
533	c.moveTo(w * 0.8, h * 0.5);
534	c.lineTo(w, h * 0.5);
535
536	var operation = mxUtils.getValue(this.style, 'operation', 'and');
537
538	for (var i = 0; i < numInputs; i++)
539	{
540		c.moveTo(0, currH);
541
542		if (operation == 'and')
543		{
544			c.lineTo(w * 0.2, currH);
545		}
546		else
547		{
548			c.lineTo(w * 0.23, currH);
549		}
550
551		currH = currH + spacing;
552	}
553
554	c.stroke();
555
556
557	switch(operation) {
558	  case 'xor':
559			c.begin();
560			c.moveTo(w * 0.1, 0);
561			c.arcTo(w * 0.6, h, 0, 0, 1, w * 0.1, h);
562			c.stroke();
563			//no break operation needed, XOR needs to draw an OR shape too
564	  case 'or':
565			c.begin();
566			c.moveTo(w * 0.4, 0);
567			c.arcTo(w * 0.45, h * 0.83, 0, 0, 1, w * 0.8, h * 0.5);
568			c.arcTo(w * 0.45, h * 0.83, 0, 0, 1, w * 0.4, h);
569			c.lineTo(w * 0.15, h);
570			c.arcTo(w * 0.6, h, 0, 0, 0, w * 0.15, 0);
571			c.close();
572			c.fillAndStroke();
573	    break;
574	  default:
575			c.begin();
576			c.moveTo(w * 0.2, 0);
577			c.lineTo(w * 0.5, 0);
578			c.arcTo(w * 0.3, h * 0.5, 0, 0, 1, w * 0.5, h);
579			c.lineTo(w * 0.2, h);
580			c.close();
581			c.fillAndStroke();
582	};
583
584
585	var negating = mxUtils.getValue(this.style, 'negating', '0');
586
587	if (negating == '1')
588	{
589		var negSize;
590
591		if(this.style.negSize)
592		{
593			var tmpSize = parseFloat(mxUtils.getValue(this.style, 'negSize', '0.13'));
594			negSize = Math.min(w * tmpSize * 0.5, h * tmpSize);
595		}
596		else
597		{
598			negSize = Math.min(w * 0.04, h * 0.07);
599		}
600
601		c.begin();
602		c.ellipse(w * 0.8, h * 0.5 - negSize * 0.5, negSize, negSize);
603		c.fillAndStroke();
604	}
605};
606
607mxCellRenderer.registerShape(mxShapeElectricalLogicGate.prototype.cst.SHAPE_LOGIC_GATE, mxShapeElectricalLogicGate);
608
609mxShapeElectricalLogicGate.prototype.getConstraints = function(style)
610{
611	var constr = [new mxConnectionConstraint(new mxPoint(1, 0.5), false)];
612
613	var numInputs = parseInt(mxUtils.getValue(style, 'numInputs', '2'));
614	var spacing = 1 / numInputs;
615	var currH = spacing * 0.5;
616
617	for (var i = 0; i < numInputs; i++)
618	{
619		constr.push(new mxConnectionConstraint(new mxPoint(0, currH), false));
620		currH = currH + spacing;
621	}
622
623	return (constr);
624}
625
626//**********************************************************************************************************************************************************
627//Buffer
628//**********************************************************************************************************************************************************
629/**
630* Extends mxShape.
631*/
632function mxShapeElectricalBuffer(bounds, fill, stroke, strokewidth)
633{
634	mxShape.call(this);
635	this.bounds = bounds;
636	this.fill = fill;
637	this.stroke = stroke;
638	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
639};
640
641/**
642* Extends mxShape.
643*/
644mxUtils.extend(mxShapeElectricalBuffer, mxShape);
645
646mxShapeElectricalBuffer.prototype.cst = {
647		SHAPE_BUFFER2 : 'mxgraph.electrical.logic_gates.buffer2'
648};
649
650mxShapeElectricalBuffer.prototype.customProperties = [
651	{name: 'negating', dispName: 'Negating', type: 'bool', defVal:0}
652];
653
654/**
655* Function: paintVertexShape
656*
657* Paints the vertex shape.
658*/
659mxShapeElectricalBuffer.prototype.paintVertexShape = function(c, x, y, w, h)
660{
661	c.translate(x, y);
662
663	c.begin();
664	c.moveTo(0, h * 0.5);
665	c.lineTo(w * 0.2, h * 0.5);
666	c.moveTo(w * 0.8, h * 0.5);
667	c.lineTo(w, h * 0.5);
668	c.stroke();
669
670	c.begin();
671	c.moveTo(w * 0.2, 0);
672	c.lineTo(w * 0.8, h * 0.5);
673	c.lineTo(w * 0.2, h);
674	c.close();
675	c.fillAndStroke();
676
677	var negating = mxUtils.getValue(this.style, 'negating', '0');
678
679	if (negating == '1')
680	{
681		var negSize = Math.min(w * 0.04, h * 0.07);
682		c.begin();
683		c.ellipse(w * 0.8, h * 0.5 - negSize * 0.5, negSize, negSize);
684		c.fillAndStroke();
685	}
686};
687
688mxCellRenderer.registerShape(mxShapeElectricalBuffer.prototype.cst.SHAPE_BUFFER2, mxShapeElectricalBuffer);
689
690mxShapeElectricalBuffer.prototype.constraints = [
691    new mxConnectionConstraint(new mxPoint(0, 0.5), true),
692    new mxConnectionConstraint(new mxPoint(1, 0.5), true)
693    ];
694
695//**********************************************************************************************************************************************************
696//Dual In-Line IC
697//**********************************************************************************************************************************************************
698/**
699* Extends mxShape.
700*/
701function mxShapeElectricalDualInLineIC(bounds, fill, stroke, strokewidth)
702{
703	mxShape.call(this);
704	this.bounds = bounds;
705	this.fill = fill;
706	this.stroke = stroke;
707	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
708};
709
710/**
711* Extends mxShape.
712*/
713mxUtils.extend(mxShapeElectricalDualInLineIC, mxShape);
714
715mxShapeElectricalDualInLineIC.prototype.cst = {
716		SHAPE_DUAL_INLINE_IC : 'mxgraph.electrical.logic_gates.dual_inline_ic'
717};
718
719mxShapeElectricalDualInLineIC.prototype.customProperties = [
720	{name: 'pinStyle', dispName: 'Pin Style', type: 'enum', defVal:'line',
721		enumList:[
722			{val:'line', dispName:'Line'},
723			{val:'square', dispName:'Square'}
724		]},
725	{name: 'startPin', dispName: 'Starting Pin', type: 'enum', defVal:'n',
726		enumList:[
727			{val:'n', dispName:'N'},
728			{val:'e', dispName:'E'},
729			{val:'s', dispName:'S'},
730			{val:'w', dispName:'W'}
731		]},
732	{name: 'pinSpacing', dispName: 'Pin Spacing', type: 'float', min:1, defVal:20},
733	{name: 'pinLabelType', dispName: 'Pin Label Type', type: 'enum', defVal:'gen',
734		enumList:[
735			{val:'gen', dispName:'Generated'},
736			{val:'cust', dispName:'Custom'}
737		]},
738	{name: 'labelCount', dispName: 'Number of Labels', type: 'int', defVal: 20, dependentProps: ['labelNames']},
739	{name: 'labelNames', dispName: 'Label Names', type: 'staticArr', subType: 'string', sizeProperty: 'labelCount', subDefVal: 'a'}
740];
741
742/**
743* Function: paintVertexShape
744*
745* Paints the vertex shape.
746*/
747mxShapeElectricalDualInLineIC.prototype.paintVertexShape = function(c, x, y, w, h)
748{
749	c.translate(x, y);
750	var fontColor = mxUtils.getValue(this.style, 'fontColor', '#000000');
751	c.setFontColor(fontColor);
752	var startPin = mxUtils.getValue(this.style, 'startPin', 'n');
753	var pinLabelType = mxUtils.getValue(this.style, 'pinLabelType', 'gen');
754	var labelNames = mxUtils.getValue(this.style, 'labelNames', '').toString().split(',');
755
756	c.begin();
757
758	if (startPin == 'n' || startPin == 's')
759	{
760		c.rect(10, 0, w - 20, h);
761	}
762	else
763	{
764		c.rect(0, 10, w, h - 20);
765	}
766
767	c.fillAndStroke();
768
769	var pinSpacing = parseFloat(mxUtils.getValue(this.style, 'pinSpacing', '20'));
770	var pinStyle = mxUtils.getValue(this.style, 'pinStyle', 'line');
771	var fontSize = parseFloat(mxUtils.getValue(this.style, 'fontSize', '12'));
772
773	if (startPin == 'n' || startPin == 's')
774	{
775		var pinsOne = parseInt(h / pinSpacing);
776	}
777	else
778	{
779		var pinsOne = parseInt(w / pinSpacing);
780	}
781
782	if (pinStyle == 'line')
783	{
784		c.setFontSize(fontSize * 0.8);
785		var pinCount = 1;
786		var currH = pinSpacing * 0.5;
787
788		c.begin();
789
790		if (startPin == 'n' || startPin == 's')
791		{
792			while (pinCount * pinSpacing <= h)
793			{
794				c.moveTo(0, currH);
795				c.lineTo(10, currH);
796				c.moveTo(w - 10, currH);
797				c.lineTo(w, currH);
798
799				if (startPin == 'n')
800				{
801					var currPinNum = pinCount;
802				}
803				else
804				{
805					var currPinNum = pinsOne + pinCount;
806				}
807
808				if (pinLabelType == 'gen')
809				{
810					c.text(20, currH, 0, 0, currPinNum.toString(), mxConstants.ALIGN_LEFT, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
811				}
812				else if (currPinNum - 1 < labelNames.length)
813				{
814					c.text(20, currH, 0, 0, labelNames[currPinNum - 1].toString(), mxConstants.ALIGN_LEFT, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
815				}
816
817				if (startPin == 'n')
818				{
819					var pc2 = 2 * pinsOne - pinCount + 1;
820				}
821				else
822				{
823					var pc2 = pinsOne - pinCount + 1;
824				}
825
826				if (pinLabelType == 'gen')
827				{
828					c.text(w - 20, currH, 0, 0, pc2.toString(), mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
829				}
830				else if (pc2 - 1 < labelNames.length)
831				{
832					c.text(w - 20, currH, 0, 0, labelNames[pc2 - 1].toString(), mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
833				}
834
835				currH = currH + pinSpacing;
836				pinCount++;
837			}
838		}
839		else
840		{
841			while (pinCount * pinSpacing <= w)
842			{
843				c.moveTo(currH, 0);
844				c.lineTo(currH, 10);
845				c.moveTo(currH, h - 10);
846				c.lineTo(currH, h);
847
848				if (startPin == 'e')
849				{
850					var currPinNum = pinsOne - pinCount + 1;
851				}
852				else
853				{
854					var currPinNum = 2 * pinsOne - pinCount + 1;
855				}
856
857				if (pinLabelType == 'gen')
858				{
859					c.text(currH, 20, 0, 0, currPinNum.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
860				}
861				else if (currPinNum - 1 < labelNames.length)
862				{
863					c.text(currH, 20, 0, 0, labelNames[currPinNum - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
864				}
865
866				if (startPin == 'e')
867				{
868					var pc2 = pinsOne + pinCount;
869				}
870				else
871				{
872					var pc2 = pinCount;
873				}
874
875				if (pinLabelType == 'gen')
876				{
877					c.text(currH, h - 20, 0, 0, pc2.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
878				}
879				else if (pc2 - 1 < labelNames.length)
880				{
881					c.text(currH, h - 20, 0, 0, labelNames[pc2 - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
882				}
883
884				currH = currH + pinSpacing;
885				pinCount++;
886			}
887		}
888
889		c.stroke();
890	}
891	else
892	{
893		c.setFontSize(fontSize * 0.5);
894		var pinCount = 1;
895		var currH = pinSpacing * 0.5;
896
897		if (startPin == 'n' || startPin == 's')
898		{
899			while (pinCount * pinSpacing <= h)
900			{
901				c.begin();
902				c.rect(0, currH - pinSpacing * 0.25, 10, pinSpacing * 0.5);
903				c.fillAndStroke();
904
905				c.begin();
906				c.rect(w - 10, currH - pinSpacing * 0.25, 10, pinSpacing * 0.5);
907				c.fillAndStroke();
908
909				if (startPin == 'n')
910				{
911					var currPinNum = pinCount;
912				}
913				else
914				{
915					var currPinNum = pinsOne + pinCount;
916				}
917
918				if (pinLabelType == 'gen')
919				{
920					c.text(5, currH + 1, 0, 0, currPinNum.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
921				}
922				else if (currPinNum - 1 < labelNames.length)
923				{
924					c.text(5, currH + 1, 0, 0, labelNames[currPinNum - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
925				}
926
927				if (startPin == 'n')
928				{
929					var pc2 = 2 * pinsOne - pinCount + 1;
930				}
931				else
932				{
933					var pc2 = pinsOne - pinCount + 1;
934				}
935
936				if (pinLabelType == 'gen')
937				{
938					c.text(w - 5, currH + 1, 0, 0, pc2.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
939				}
940				else if (pc2 - 1 < labelNames.length)
941				{
942					c.text(w - 5, currH + 1, 0, 0, labelNames[pc2 - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
943				}
944
945				currH = currH + pinSpacing;
946				pinCount++;
947			}
948		}
949		else
950		{
951			while (pinCount * pinSpacing <= w)
952			{
953				c.begin();
954				c.rect(currH - pinSpacing * 0.25, 0, pinSpacing * 0.5, 10);
955				c.fillAndStroke();
956
957				c.begin();
958				c.rect(currH - pinSpacing * 0.25, h - 10, pinSpacing * 0.5, 10);
959				c.fillAndStroke();
960
961				if (startPin == 'e')
962				{
963					var currPinNum = pinsOne - pinCount + 1;
964				}
965				else
966				{
967					var currPinNum = 2 * pinsOne - pinCount + 1;
968				}
969
970				if (pinLabelType == 'gen')
971				{
972					c.text(currH, 5, 0, 0, currPinNum.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
973				}
974				else if (currPinNum - 1 < labelNames.length)
975				{
976					c.text(currH, 5, 0, 0, labelNames[currPinNum - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
977				}
978
979				if (startPin == 'e')
980				{
981					var pc2 = pinsOne + pinCount;
982				}
983				else
984				{
985					var pc2 = pinCount;
986				}
987
988				if (pinLabelType == 'gen')
989				{
990					c.text(currH, h - 5, 0, 0, pc2.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
991				}
992				else if (pc2 - 1 < labelNames.length)
993				{
994					c.text(currH, h - 5, 0, 0, labelNames[pc2 - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
995				}
996
997				currH = currH + pinSpacing;
998				pinCount++;
999			}
1000		}
1001
1002	}
1003
1004	c.setShadow(false);
1005
1006	c.begin();
1007
1008	switch(startPin) {
1009	  case 'e':
1010			if (h > 40)
1011			{
1012				c.moveTo(w, h * 0.5 - 10);
1013				c.arcTo(12, 12, 0, 0, 0, w, h * 0.5 + 10);
1014			}
1015	    break;
1016	  case 's':
1017			if (w > 40)
1018			{
1019				c.moveTo(w * 0.5 - 10, h);
1020				c.arcTo(12, 12, 0, 0, 1, w * 0.5 + 10, h);
1021			}
1022	    break;
1023	  case 'w':
1024			if (h > 40)
1025			{
1026				c.moveTo(0, h * 0.5 - 10);
1027				c.arcTo(12, 12, 0, 0, 1, 0, h * 0.5 + 10);
1028			}
1029	    break;
1030	  default:
1031			if (w > 40)
1032			{
1033				c.moveTo(w * 0.5 - 10, 0);
1034				c.arcTo(12, 12, 0, 0, 0, w * 0.5 + 10, 0);
1035			}
1036	}
1037
1038	c.stroke();
1039};
1040
1041mxCellRenderer.registerShape(mxShapeElectricalDualInLineIC.prototype.cst.SHAPE_DUAL_INLINE_IC, mxShapeElectricalDualInLineIC);
1042
1043mxShapeElectricalDualInLineIC.prototype.getConstraints = function(style, w, h)
1044{
1045	var constr = [];
1046
1047	var pinSpacing = parseFloat(mxUtils.getValue(this.style, 'pinSpacing', '20'));
1048	var startPin = mxUtils.getValue(this.style, 'startPin', 'n');
1049	var pinCount = 1;
1050	var currH = pinSpacing * 0.5;
1051	var pinsOne = parseInt(h / pinSpacing);
1052
1053	if (startPin == 'n' || startPin == 's')
1054	{
1055		while (pinCount * pinSpacing <= h)
1056		{
1057			constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, currH));
1058			constr.push(new mxConnectionConstraint(new mxPoint(1, 0), false, null, 0, currH));
1059			currH = currH + pinSpacing;
1060			pinCount++;
1061		}
1062	}
1063	else
1064	{
1065		while (pinCount * pinSpacing <= w)
1066		{
1067			constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, currH, 0));
1068			constr.push(new mxConnectionConstraint(new mxPoint(0, 1), false, null, currH, 0));
1069			currH = currH + pinSpacing;
1070			pinCount++;
1071		}
1072	}
1073
1074	return (constr);
1075}
1076
1077//**********************************************************************************************************************************************************
1078//Quad Flat Package IC
1079//**********************************************************************************************************************************************************
1080/**
1081* Extends mxShape.
1082*/
1083function mxShapeElectricalQFPIC(bounds, fill, stroke, strokewidth)
1084{
1085	mxShape.call(this);
1086	this.bounds = bounds;
1087	this.fill = fill;
1088	this.stroke = stroke;
1089	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1090};
1091
1092/**
1093* Extends mxShape.
1094*/
1095mxUtils.extend(mxShapeElectricalQFPIC, mxShape);
1096
1097mxShapeElectricalQFPIC.prototype.cst = {
1098		SHAPE_QFP_IC : 'mxgraph.electrical.logic_gates.qfp_ic'
1099};
1100
1101mxShapeElectricalQFPIC.prototype.customProperties = [
1102	{name: 'pinStyle', dispName: 'Pin Style', type: 'enum', defVal:'line',
1103		enumList:[
1104			{val:'line', dispName:'Line'},
1105			{val:'square', dispName:'Square'}
1106		]},
1107	{name: 'startPin', dispName: 'Starting Pin', type: 'enum', defVal:'sw',
1108		enumList:[
1109			{val:'sw', dispName:'SW'},
1110			{val:'nw', dispName:'NW'},
1111			{val:'ne', dispName:'NE'},
1112			{val:'se', dispName:'SE'}
1113		]},
1114	{name: 'pinSpacing', dispName: 'Pin Spacing', type: 'float', min:1, defVal:20},
1115	{name: 'pinLabelType', dispName: 'Pin Label Type', type: 'enum', defVal:'gen',
1116		enumList:[
1117			{val:'gen', dispName:'Generated'},
1118			{val:'cust', dispName:'Custom'}
1119		]},
1120	{name: 'labelCount', dispName: 'Number of Labels', type: 'int', defVal: 40, dependentProps: ['labelNames']},
1121	{name: 'labelNames', dispName: 'Label Names', type: 'staticArr', subType: 'string', sizeProperty: 'labelCount', subDefVal: 'a'}
1122];
1123
1124/**
1125* Function: paintVertexShape
1126*
1127* Paints the vertex shape.
1128*/
1129mxShapeElectricalQFPIC.prototype.paintVertexShape = function(c, x, y, w, h)
1130{
1131	c.translate(x, y);
1132
1133	c.begin();
1134	c.moveTo(15, 10);
1135	c.lineTo(w - 15, 10);
1136	c.lineTo(w - 10, 15);
1137	c.lineTo(w - 10, h - 15);
1138	c.lineTo(w - 15, h - 10);
1139	c.lineTo(15, h - 10);
1140	c.lineTo(10, h - 15);
1141	c.lineTo(10, 15);
1142	c.close();
1143	c.fillAndStroke();
1144
1145	var pinSpacing = parseFloat(mxUtils.getValue(this.style, 'pinSpacing', '20'));
1146	var pinStyle = mxUtils.getValue(this.style, 'pinStyle', 'line');
1147	var pinLabelType = mxUtils.getValue(this.style, 'pinLabelType', 'gen');
1148	var labelNames = mxUtils.getValue(this.style, 'labelNames', '').toString().split(',');
1149	var fontSize = parseFloat(mxUtils.getValue(this.style, 'fontSize', '12'));
1150	var fontColor = mxUtils.getValue(this.style, 'fontColor', '#000000');
1151	c.setFontColor(fontColor);
1152	var startPin = mxUtils.getValue(this.style, 'startPin', 'sw');
1153
1154	if (pinStyle == 'line')
1155	{
1156		c.setFontSize(fontSize * 0.8);
1157		var pinCount = 1;
1158		var currH = pinSpacing * 0.5 + 20;
1159
1160		c.begin();
1161
1162		var pinsVOne = parseInt((h - pinSpacing - 40) / pinSpacing) + 1;
1163		var pinsHOne = parseInt((w - pinSpacing - 40) / pinSpacing) + 1;
1164
1165		while (currH <= h - pinSpacing * 0.5 - 20)
1166		{
1167			c.moveTo(0, currH);
1168			c.lineTo(10, currH);
1169			c.moveTo(w - 10, currH);
1170			c.lineTo(w, currH);
1171
1172			//west pins
1173			switch(startPin) {
1174			  case 'nw':
1175					var currPinNum = pinCount;
1176			    break;
1177			  case 'ne':
1178					var currPinNum = pinsHOne + pinCount;
1179			    break;
1180			  case 'se':
1181					var currPinNum = pinsVOne + pinsHOne + pinCount;
1182			    break;
1183			  default:
1184					var currPinNum = pinsVOne + 2 * pinsHOne + pinCount;
1185			}
1186
1187			if (pinLabelType == 'gen')
1188			{
1189				c.text(20, currH, 0, 0, currPinNum.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1190			}
1191			else if (currPinNum - 1 < labelNames.length)
1192			{
1193				c.text(20, currH, 0, 0, labelNames[currPinNum - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1194			}
1195
1196			//east pins
1197			switch(startPin) {
1198			  case 'nw':
1199					var pc2 = pinsHOne + 2 * pinsVOne - pinCount + 1;
1200			    break;
1201			  case 'ne':
1202					var pc2 = 2 * pinsHOne + 2 * pinsVOne - pinCount + 1;
1203			    break;
1204			  case 'se':
1205					var pc2 = pinsVOne - pinCount + 1;
1206			    break;
1207			  default:
1208					var pc2 = pinsHOne + pinsVOne - pinCount + 1;
1209			}
1210
1211			if (pinLabelType == 'gen')
1212			{
1213				c.text(w - 20, currH, 0, 0, pc2.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1214			}
1215			else if (pc2 - 1 < labelNames.length)
1216			{
1217				c.text(w - 20, currH, 0, 0, labelNames[pc2 - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1218			}
1219
1220			currH = currH + pinSpacing;
1221			pinCount++;
1222		}
1223
1224		var pinCount = 1;
1225		var currH = pinSpacing * 0.5 + 20;
1226
1227		while (currH <= w - pinSpacing * 0.5 - 20)
1228		{
1229			c.moveTo(currH, 0);
1230			c.lineTo(currH, 10);
1231			c.moveTo(currH, h - 10);
1232			c.lineTo(currH, h);
1233
1234			//south pins
1235			switch(startPin) {
1236			  case 'nw':
1237					var currPinNum = pinsVOne + pinCount;
1238			    break;
1239			  case 'ne':
1240					var currPinNum = pinsVOne + pinsHOne + pinCount;
1241			    break;
1242			  case 'se':
1243					var currPinNum = 2 * pinsVOne + pinsHOne + pinCount;
1244			    break;
1245			  default:
1246					var currPinNum = pinCount;
1247			}
1248
1249			if (pinLabelType == 'gen')
1250			{
1251				c.text(currH, h - 20, 0, 0, currPinNum.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1252			}
1253			else if (currPinNum - 1 < labelNames.length)
1254			{
1255				c.text(currH, h - 20, 0, 0, labelNames[currPinNum - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1256			}
1257
1258			//north pins
1259			switch(startPin) {
1260			  case 'nw':
1261					var pc2 = 2 * pinsHOne + 2 * pinsVOne - pinCount + 1;
1262			    break;
1263			  case 'ne':
1264					var pc2 = pinsHOne - pinCount + 1;
1265			    break;
1266			  case 'se':
1267					var pc2 = pinsHOne + pinsVOne - pinCount + 1;
1268			    break;
1269			  default:
1270					var pc2 = 2 * pinsHOne + pinsVOne - pinCount + 1;
1271			}
1272
1273			if (pinLabelType == 'gen')
1274			{
1275				c.text(currH, 20, 0, 0, pc2.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1276			}
1277			else if (pc2 - 1 < labelNames.length)
1278			{
1279				c.text(currH, 20, 0, 0, labelNames[pc2 - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1280			}
1281
1282			currH = currH + pinSpacing;
1283			pinCount++;
1284		}
1285
1286		c.stroke();
1287	}
1288	else
1289	{
1290		c.setFontSize(fontSize * 0.5);
1291		var pinCount = 1;
1292		var currH = pinSpacing * 0.5 + 20;
1293		var pinsVOne = parseInt((h - pinSpacing - 40) / pinSpacing) + 1;
1294		var pinsHOne = parseInt((w - pinSpacing - 40) / pinSpacing) + 1;
1295
1296		while (currH <= h - pinSpacing * 0.5 - 20)
1297		{
1298			c.begin();
1299			c.rect(0, currH - pinSpacing * 0.25, 10, pinSpacing * 0.5);
1300			c.fillAndStroke();
1301
1302			c.begin();
1303			c.rect(w - 10, currH - pinSpacing * 0.25, 10, pinSpacing * 0.5);
1304			c.fillAndStroke();
1305
1306			//west pins
1307			switch(startPin) {
1308			  case 'nw':
1309					var currPinNum = pinCount;
1310			    break;
1311			  case 'ne':
1312					var currPinNum = pinsHOne + pinCount;
1313			    break;
1314			  case 'se':
1315					var currPinNum = pinsVOne + pinsHOne + pinCount;
1316			    break;
1317			  default:
1318					var currPinNum = pinsVOne + 2 * pinsHOne + pinCount;
1319			}
1320
1321			if (pinLabelType == 'gen')
1322			{
1323				c.text(5, currH + 1, 0, 0, currPinNum.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1324			}
1325			else if (currPinNum - 1 < labelNames.length)
1326			{
1327				c.text(5, currH + 1, 0, 0, labelNames[currPinNum - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1328			}
1329
1330			//east pins
1331			switch(startPin) {
1332			  case 'nw':
1333					var pc2 = pinsHOne + 2 * pinsVOne - pinCount + 1;
1334			    break;
1335			  case 'ne':
1336					var pc2 = 2 * pinsHOne + 2 * pinsVOne - pinCount + 1;
1337			    break;
1338			  case 'se':
1339					var pc2 = pinsVOne - pinCount + 1;
1340			    break;
1341			  default:
1342					var pc2 = pinsHOne + pinsVOne - pinCount + 1;
1343			}
1344
1345			if (pinLabelType == 'gen')
1346			{
1347				c.text(w - 5, currH + 1, 0, 0, pc2.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1348			}
1349			else if (pc2 - 1 < labelNames.length)
1350			{
1351				c.text(w - 5, currH + 1, 0, 0, labelNames[pc2 - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1352			}
1353
1354			currH = currH + pinSpacing;
1355			pinCount++;
1356		}
1357
1358		var pinCount = 1;
1359		var currH = pinSpacing * 0.5 + 20;
1360
1361		while (currH <= w - pinSpacing * 0.5 - 20)
1362		{
1363			c.begin();
1364			c.rect(currH - pinSpacing * 0.25, 0, pinSpacing * 0.5, 10);
1365			c.fillAndStroke();
1366
1367			c.begin();
1368			c.rect(currH - pinSpacing * 0.25, h - 10, pinSpacing * 0.5, 10);
1369			c.fillAndStroke();
1370
1371			//south pins
1372			switch(startPin) {
1373			  case 'nw':
1374					var currPinNum = pinsVOne + pinCount;
1375			    break;
1376			  case 'ne':
1377					var currPinNum = pinsVOne + pinsHOne + pinCount;
1378			    break;
1379			  case 'se':
1380					var currPinNum = 2 * pinsVOne + pinsHOne + pinCount;
1381			    break;
1382			  default:
1383					var currPinNum = pinCount;
1384			}
1385
1386			if (pinLabelType == 'gen')
1387			{
1388				c.text(currH, h - 4, 0, 0, currPinNum.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1389			}
1390			else if (currPinNum - 1 < labelNames.length)
1391			{
1392				c.text(currH, h - 4, 0, 0, labelNames[currPinNum - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1393			}
1394
1395			//north pins
1396			switch(startPin) {
1397			  case 'nw':
1398					var pc2 = 2 * pinsHOne + 2 * pinsVOne - pinCount + 1;
1399			    break;
1400			  case 'ne':
1401					var pc2 = pinsHOne - pinCount + 1;
1402			    break;
1403			  case 'se':
1404					var pc2 = pinsHOne + pinsVOne - pinCount + 1;
1405			    break;
1406			  default:
1407					var pc2 = 2 * pinsHOne + pinsVOne - pinCount + 1;
1408			}
1409
1410			if (pinLabelType == 'gen')
1411			{
1412				c.text(currH, 6, 0, 0, pc2.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1413			}
1414			else if (pc2 - 1 < labelNames.length)
1415			{
1416				c.text(currH, 6, 0, 0, labelNames[pc2 - 1].toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
1417			}
1418
1419			currH = currH + pinSpacing;
1420			pinCount++;
1421		}
1422	}
1423
1424	c.setShadow(false);
1425
1426	if (w > 40)
1427	{
1428		c.setFillColor(mxUtils.getValue(this.style, 'strokeColor', '#000000'));
1429
1430		c.begin();
1431
1432		switch(startPin) {
1433		  case 'nw':
1434				c.ellipse(15, 15, 10, 10);
1435		    break;
1436		  case 'ne':
1437				c.ellipse(w - 25, 15, 10, 10);
1438		    break;
1439		  case 'se':
1440				c.ellipse(w - 25, h - 25, 10, 10);
1441		    break;
1442		  default:
1443				c.ellipse(15, h - 25, 10, 10);
1444		}
1445
1446		c.fillAndStroke();
1447	}
1448};
1449
1450mxCellRenderer.registerShape(mxShapeElectricalQFPIC.prototype.cst.SHAPE_QFP_IC, mxShapeElectricalQFPIC);
1451
1452mxShapeElectricalQFPIC.prototype.getConstraints = function(style, w, h)
1453{
1454	var constr = [];
1455
1456	var pinSpacing = parseFloat(mxUtils.getValue(this.style, 'pinSpacing', '20'));
1457	var pinCount = 1;
1458	var currH = pinSpacing * 0.5 + 20;
1459
1460	var pinsOne = parseInt(h / pinSpacing);
1461
1462	while (currH <= h - pinSpacing * 0.5 - 20)
1463	{
1464		constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, currH));
1465		constr.push(new mxConnectionConstraint(new mxPoint(1, 0), false, null, 0, currH));
1466		currH = currH + pinSpacing;
1467	}
1468
1469	var pinCount = 1;
1470	var currH = pinSpacing * 0.5 + 20;
1471
1472	while (currH <= w - pinSpacing * 0.5 - 20)
1473	{
1474		constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, currH, 0));
1475		constr.push(new mxConnectionConstraint(new mxPoint(0, 1), false, null, currH, 0));
1476		currH = currH + pinSpacing;
1477	}
1478
1479
1480	return (constr);
1481}
1482
1483//**********************************************************************************************************************************************************
1484//Mux
1485//**********************************************************************************************************************************************************
1486/**
1487* Extends mxShape.
1488*/
1489function mxShapeElectricalMux(bounds, fill, stroke, strokewidth)
1490{
1491	mxShape.call(this);
1492	this.bounds = bounds;
1493	this.fill = fill;
1494	this.stroke = stroke;
1495	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1496};
1497
1498/**
1499* Extends mxShape.
1500*/
1501mxUtils.extend(mxShapeElectricalMux, mxShape);
1502
1503mxShapeElectricalMux.prototype.cst = {
1504		SHAPE_MUX : 'mxgraph.electrical.abstract.mux2'
1505};
1506
1507mxShapeElectricalMux.prototype.customProperties = [
1508	{name: 'operation', dispName: 'Operation', type: 'enum', defVal:'mux',
1509		enumList:[
1510			{val:'mux', dispName:'Mux'},
1511			{val:'demux', dispName:'Demux'}
1512		]},
1513	{name: 'selectorPins', dispName: 'Selector Pins', type: 'int', min:1, max:8, defVal:1},
1514];
1515
1516/**
1517* Function: paintVertexShape
1518*
1519* Paints the vertex shape.
1520*/
1521mxShapeElectricalMux.prototype.paintVertexShape = function(c, x, y, w, h)
1522{
1523	c.translate(x, y);
1524	var selectorPins = parseInt(mxUtils.getValue(this.style, 'selectorPins', '1'));
1525	var operation = mxUtils.getValue(this.style, 'operation', 'mux');
1526	var fontSize = parseFloat(mxUtils.getValue(this.style, 'fontSize', '12'));
1527	c.setFontSize(fontSize * 0.5);
1528	var fontColor = mxUtils.getValue(this.style, 'fontColor', '#000000');
1529	c.setFontColor(fontColor);
1530	var dir = mxUtils.getValue(this.style, 'direction', 'east');
1531	var txtRot = 0;
1532
1533	switch(dir)
1534	{
1535		case 'south' :
1536			txtRot = 270;
1537			break;
1538		case 'west' :
1539			txtRot = 180;
1540			break;
1541		case 'north' :
1542			txtRot = 90;
1543			break;
1544	}
1545
1546	switch(operation)
1547	{
1548	  case 'demux':
1549			c.begin();
1550			c.moveTo(w - 10, 0);
1551			c.lineTo(10, h * 0.1);
1552			c.lineTo(10, h * 0.9 - 10);
1553			c.lineTo(w - 10, h - 10);
1554			c.close();
1555			c.fillAndStroke();
1556	    break;
1557	  default:
1558			c.begin();
1559			c.moveTo(10, 0);
1560			c.lineTo(w - 10, h * 0.1);
1561			c.lineTo(w - 10, h * 0.9 - 10);
1562			c.lineTo(10, h - 10);
1563			c.close();
1564			c.fillAndStroke();
1565	};
1566
1567	var numInputs = 1;
1568	var numOutputs = 1;
1569
1570	if (operation == 'mux')
1571	{
1572		numInputs = Math.pow(2, selectorPins);
1573		var spacing = (h - 16) / numInputs;
1574	}
1575	else
1576	{
1577		numOutputs = Math.pow(2, selectorPins);
1578		var spacing = (h - 16) / numOutputs;
1579	}
1580
1581	var currH = 3 + spacing * 0.5;
1582
1583	c.begin();
1584
1585	if (numInputs == 1)
1586	{
1587		c.moveTo(0, (h - 10) * 0.5);
1588		c.lineTo(10, (h - 10) * 0.5);
1589	}
1590	else
1591	{
1592		for (var i = 0; i < numInputs; i++)
1593		{
1594			c.moveTo(0, currH);
1595			c.lineTo(10, currH);
1596			c.text(14, currH + 1, 0, 0, '' + i.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, txtRot);
1597			currH = currH + spacing;
1598		}
1599	}
1600
1601	if (numOutputs == 1)
1602	{
1603		c.moveTo(w - 10, (h - 10) * 0.5);
1604		c.lineTo(w, (h - 10) * 0.5);
1605	}
1606	else
1607	{
1608		for (var i = 0; i < numOutputs; i++)
1609		{
1610			c.moveTo(w - 10, currH);
1611			c.lineTo(w, currH);
1612			c.text(w - 14, currH + 1, 0, 0, '' + i.toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, txtRot);
1613			currH = currH + spacing;
1614		}
1615	}
1616
1617	var spacing = (w - 20) / selectorPins;
1618	var currW = 10 + spacing * 0.5;
1619
1620	for (var i = 0; i < selectorPins; i++)
1621	{
1622		if (operation == 'mux')
1623		{
1624			c.moveTo(currW, h - 10 - (currW - 10) / (w - 20) * h * 0.1);
1625		}
1626		else
1627		{
1628			c.moveTo(currW, h - 10 - (w - currW - 10) / (w - 20) * h * 0.1);
1629		}
1630
1631		c.lineTo(currW, h);
1632
1633		c.text(currW + 5, h -4, 0, 0, 'S' + (selectorPins - i - 1).toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, txtRot);
1634		currW = currW + spacing;
1635	}
1636
1637	c.stroke();
1638};
1639
1640mxCellRenderer.registerShape(mxShapeElectricalMux.prototype.cst.SHAPE_MUX, mxShapeElectricalMux);
1641
1642mxShapeElectricalMux.prototype.getConstraints = function(style, w, h)
1643{
1644	var constr = [];
1645	var pinRange = (h - 16) / h;
1646	var selectorPins = parseInt(mxUtils.getValue(this.style, 'selectorPins', '1'));
1647	var operation = mxUtils.getValue(this.style, 'operation', 'mux');
1648
1649	var numInputs = 1;
1650	var numOutputs = 1;
1651
1652	if (operation == 'mux')
1653	{
1654		numInputs = Math.pow(2, selectorPins);
1655		var spacing = pinRange / numInputs;
1656	}
1657	else
1658	{
1659		numOutputs = Math.pow(2, selectorPins);
1660		var spacing = pinRange / numOutputs;
1661	}
1662
1663	var currH = spacing * 0.5;
1664
1665	if (numInputs == 1)
1666	{
1667		constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5 * (h - 10) / h), false, 0, 0));
1668	}
1669	else
1670	{
1671		for (var i = 0; i < numInputs; i++)
1672		{
1673			constr.push(new mxConnectionConstraint(new mxPoint(0, currH), false, null, 0, 3));
1674			currH = currH + spacing;
1675		}
1676	}
1677
1678	if (numOutputs == 1)
1679	{
1680		constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false, null, 0, -5));
1681	}
1682	else
1683	{
1684		for (var i = 0; i < numOutputs; i++)
1685		{
1686			constr.push(new mxConnectionConstraint(new mxPoint(1, currH), false, null, 0, 3));
1687			currH = currH + spacing;
1688		}
1689	}
1690
1691	var spacing = (w - 20) / (w * selectorPins);
1692	var currW = spacing * 0.5;
1693
1694	for (var i = 0; i < selectorPins; i++)
1695	{
1696		constr.push(new mxConnectionConstraint(new mxPoint(currW, 1), false, null, 10, 0));
1697		currW = currW + spacing;
1698	}
1699
1700	return (constr);
1701}
1702
1703//**********************************************************************************************************************************************************
1704//Battery stack
1705//**********************************************************************************************************************************************************
1706/**
1707* Extends mxShape.
1708*/
1709function mxShapeElectricalBatteryStack(bounds, fill, stroke, strokewidth)
1710{
1711	mxShape.call(this);
1712	this.bounds = bounds;
1713	this.fill = fill;
1714	this.stroke = stroke;
1715	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1716};
1717
1718/**
1719* Extends mxShape.
1720*/
1721mxUtils.extend(mxShapeElectricalBatteryStack, mxShape);
1722
1723mxShapeElectricalBatteryStack.prototype.cst = {
1724		SHAPE_BATTERY_STACK : 'mxgraph.electrical.miscellaneous.batteryStack'
1725};
1726
1727/**
1728* Function: paintVertexShape
1729*
1730* Paints the vertex shape.
1731*/
1732mxShapeElectricalBatteryStack.prototype.paintVertexShape = function(c, x, y, w, h)
1733{
1734	c.translate(x, y);
1735
1736	var bw = h * 0.3;
1737	var strokeColor = mxUtils.getValue(this.style, mxConstants.STYLE_STROKECOLOR, '#000000');
1738	var dashed = mxUtils.getValue(this.style, mxConstants.STYLE_DASHED, '0');
1739
1740	var bNum = Math.floor((w - 20) / bw);
1741	var startX = (w - bNum * bw) * 0.5;
1742
1743	if (bNum > 0)
1744	{
1745		c.begin();
1746		c.moveTo(0, h * 0.5);
1747		c.lineTo(startX + bw * 0.2, h * 0.5);
1748		c.moveTo(w - startX - bw * 0.2, h * 0.5);
1749		c.lineTo(w, h * 0.5);
1750		c.stroke();
1751
1752		var currX = startX;
1753		c.setFillColor(strokeColor);
1754
1755		for (var i = 0; i < bNum; i++)
1756		{
1757
1758			c.rect(currX + bw * 0.2, h * 0.25, bw * 0.2, h * 0.5);
1759			c.fillAndStroke();
1760
1761			c.begin();
1762			c.moveTo(currX + bw * 0.8, 0);
1763			c.lineTo(currX + bw * 0.8, h);
1764			c.stroke();
1765
1766			if (i > 0)
1767			{
1768				c.setDashed('1');
1769				c.begin();
1770				c.moveTo(currX - bw * 0.2, h * 0.5);
1771				c.lineTo(currX + bw * 0.2, h * 0.5);
1772				c.stroke();
1773				c.setDashed(dashed);
1774			}
1775
1776			currX = currX + bw;
1777		}
1778	}
1779};
1780
1781mxCellRenderer.registerShape(mxShapeElectricalBatteryStack.prototype.cst.SHAPE_BATTERY_STACK, mxShapeElectricalBatteryStack);
1782
1783mxShapeElectricalBatteryStack.prototype.constraints = [
1784    new mxConnectionConstraint(new mxPoint(0, 0.5), true),
1785    new mxConnectionConstraint(new mxPoint(1, 0.5), true)
1786    ];
1787
1788//**********************************************************************************************************************************************************
1789//DC Source 3 v2
1790//**********************************************************************************************************************************************************
1791/**
1792* Extends mxShape.
1793*/
1794function mxShapeElectricalDCSource3_v2(bounds, fill, stroke, strokewidth)
1795{
1796	mxShape.call(this);
1797	this.bounds = bounds;
1798	this.fill = fill;
1799	this.stroke = stroke;
1800	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1801};
1802
1803/**
1804* Extends mxShape.
1805*/
1806mxUtils.extend(mxShapeElectricalDCSource3_v2, mxShape);
1807
1808mxShapeElectricalDCSource3_v2.prototype.cst = {
1809		SHAPE_DC_SOURCE_3_V2 : 'mxgraph.electrical.signal_sources.dc_source_3_v2'
1810};
1811
1812/**
1813* Function: paintVertexShape
1814*
1815* Paints the vertex shape.
1816*/
1817mxShapeElectricalDCSource3_v2.prototype.paintVertexShape = function(c, x, y, w, h)
1818{
1819	c.translate(x, y);
1820
1821	var ss = Math.max(3, Math.min(h, w) * 0.05); // half of symbol size
1822	var i = 3; //indent
1823	c.ellipse(0, 0, w, h);
1824	c.fillAndStroke();
1825
1826	c.begin();
1827	c.moveTo(w * 0.5 - ss, h * 0.05 + i);
1828	c.lineTo(w * 0.5 + ss, h * 0.05 + i);
1829	c.moveTo(w * 0.5, h * 0.05 - ss + i);
1830	c.lineTo(w * 0.5, h * 0.05 + ss + i);
1831	c.moveTo(w * 0.5 - ss, h * 0.95 - i);
1832	c.lineTo(w * 0.5 + ss, h * 0.95 - i);
1833	c.stroke();
1834};
1835
1836mxCellRenderer.registerShape(mxShapeElectricalDCSource3_v2.prototype.cst.SHAPE_DC_SOURCE_3_V2, mxShapeElectricalDCSource3_v2);
1837
1838mxShapeElectricalDCSource3_v2.prototype.constraints = [
1839  new mxConnectionConstraint(new mxPoint(0.5, 0), true),
1840  new mxConnectionConstraint(new mxPoint(0.5, 1), true)
1841  ];
1842
1843//**********************************************************************************************************************************************************
1844//Source
1845//**********************************************************************************************************************************************************
1846/**
1847* Extends mxShape.
1848*/
1849function mxShapeElectricalSource(bounds, fill, stroke, strokewidth)
1850{
1851	mxShape.call(this);
1852	this.bounds = bounds;
1853	this.fill = fill;
1854	this.stroke = stroke;
1855	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
1856};
1857
1858/**
1859* Extends mxShape.
1860*/
1861mxUtils.extend(mxShapeElectricalSource, mxShape);
1862
1863mxShapeElectricalSource.prototype.cst = {
1864		SHAPE_SOURCE : 'mxgraph.electrical.signal_sources.source'
1865};
1866
1867mxShapeElectricalSource.prototype.customProperties = [
1868	{name: 'elSourceType', dispName: 'Source Type', type: 'enum', defVal: 'independent',
1869		enumList: [{val: 'independent', dispName: 'Independent'},
1870			       {val: 'dependent', dispName: 'Dependent'}]
1871	},
1872	{name: 'elSignalType', dispName: 'Signal Type', type: 'enum', defVal: 'ac',
1873		enumList: [{val: 'ac', dispName: 'AC'},
1874	       	   {val: 'none', dispName: 'None'},
1875	       	   {val: 'square', dispName: 'Square'},
1876	       	   {val: 'triangular', dispName: 'Triangular'},
1877	       	   {val: 'sawtooth', dispName: 'Sawtooth'},
1878	       	   {val: 'noise', dispName: 'Noise'},
1879	       	   {val: 'ideal', dispName: 'Ideal'},
1880	       	   {val: 'expSquib', dispName: 'Explosive Squib'},
1881	       	   {val: 'pulse', dispName: 'Pulse'},
1882	       	   {val: 'invPulse', dispName: 'Inverse Pulse'},
1883	       	   {val: 'chopSquare', dispName: 'Chopped Square'},
1884	       	   {val: 'stepOn', dispName: 'Step On'},
1885	       	   {val: 'stepOff', dispName: 'Step Off'},
1886	       	   {val: 'dc1', dispName: 'DC Horizontal'},
1887		       {val: 'dc2', dispName: 'DC Vertical'},
1888		       {val: 'dc3', dispName: 'DC Plus minus'}]
1889	}
1890];
1891
1892/**
1893* Function: paintVertexShape
1894*
1895* Paints the vertex shape.
1896*/
1897mxShapeElectricalSource.prototype.paintVertexShape = function(c, x, y, w, h)
1898{
1899	c.translate(x, y);
1900
1901	var sourceType = mxUtils.getValue(this.style, 'elSourceType', 'independent');
1902	var signalType = mxUtils.getValue(this.style, 'elSignalType', 'none');
1903
1904	switch (sourceType)
1905	{
1906		case "independent" :
1907				c.ellipse(0, 0, w, h);
1908				c.fillAndStroke();
1909			break;
1910		case "dependent" :
1911				c.begin();
1912				c.moveTo(0, h * 0.5);
1913				c.lineTo(w * 0.5, 0);
1914				c.lineTo(w, h * 0.5);
1915				c.lineTo(w * 0.5, h);
1916				c.lineTo(0, h * 0.5);
1917				c.close();
1918				c.fillAndStroke();
1919			break;
1920	}
1921
1922	switch (signalType)
1923	{
1924		case "ac" :
1925				c.begin();
1926				c.moveTo(w * 0.3, h * 0.5);
1927				c.quadTo(w * 0.34, h * 0.35, w * 0.4, h * 0.35);
1928				c.quadTo(w * 0.46, h * 0.35, w * 0.5, h * 0.5);
1929				c.quadTo(w * 0.53, h * 0.65, w * 0.6, h * 0.65);
1930				c.quadTo(w * 0.66, h * 0.65, w * 0.7, h * 0.5);
1931				c.stroke();
1932			break;
1933		case "square" :
1934				c.begin();
1935				c.moveTo(w * 0.3, h * 0.5);
1936				c.lineTo(w * 0.3, h * 0.35);
1937				c.lineTo(w * 0.5, h * 0.35);
1938				c.lineTo(w * 0.5, h * 0.65);
1939				c.lineTo(w * 0.7, h * 0.65);
1940				c.lineTo(w * 0.7, h * 0.5);
1941				c.stroke();
1942			break;
1943		case "triangular" :
1944				c.begin();
1945				c.moveTo(w * 0.3, h * 0.65);
1946				c.lineTo(w * 0.4, h * 0.35);
1947				c.lineTo(w * 0.5, h * 0.65);
1948				c.lineTo(w * 0.6, h * 0.35);
1949				c.lineTo(w * 0.7, h * 0.65);
1950				c.stroke();
1951			break;
1952		case "sawtooth" :
1953				c.begin();
1954				c.moveTo(w * 0.24, h * 0.65);
1955				c.lineTo(w * 0.42, h * 0.35);
1956				c.lineTo(w * 0.42, h * 0.65);
1957				c.lineTo(w * 0.58, h * 0.35);
1958				c.lineTo(w * 0.58, h * 0.65);
1959				c.lineTo(w * 0.76, h * 0.35);
1960				c.lineTo(w * 0.76, h * 0.65);
1961				c.stroke();
1962			break;
1963		case "noise" :
1964				c.begin();
1965				c.moveTo(w * 0.5, h * 0.17);
1966				c.lineTo(w * 0.5, h * 0.5);
1967				c.moveTo(w * 0.18, h * 0.42);
1968				c.lineTo(w * 0.5, h * 0.5);
1969				c.moveTo(w * 0.32, h * 0.78);
1970				c.lineTo(w * 0.5, h * 0.5);
1971				c.moveTo(w * 0.82, h * 0.42);
1972				c.lineTo(w * 0.5, h * 0.5);
1973				c.moveTo(w * 0.68, h * 0.78);
1974				c.lineTo(w * 0.5, h * 0.5);
1975				c.stroke();
1976			break;
1977		case "ideal" :
1978				c.begin();
1979				c.moveTo(0, h * 0.5);
1980				c.lineTo(w, h * 0.5);
1981				c.stroke();
1982			break;
1983		case "expSquib" :
1984				c.ellipse(0, h * 0.43, w * 0.14, h * 0.14);
1985				c.stroke();
1986				c.ellipse(w * 0.86, h * 0.43, w * 0.14, h * 0.14);
1987				c.stroke();
1988				c.begin();
1989				c.moveTo(w * 0.83, h * 0.63);
1990				c.lineTo(w * 0.73, h * 0.73);
1991				c.lineTo(w * 0.27, h * 0.27);
1992				c.lineTo(w * 0.17, h * 0.37);
1993				c.stroke();
1994				c.begin();
1995
1996				var strokeColor = mxUtils.getValue(this.style, mxConstants.STYLE_STROKECOLOR, '#000000');
1997				c.setFillColor(strokeColor);
1998
1999				c.moveTo(w * 0.2, h * 0.25);
2000				c.lineTo(w * 0.13, h * 0.4);
2001				c.lineTo(w * 0.28, h * 0.33);
2002				c.close();
2003				c.fillAndStroke();
2004			break;
2005		case "pulse" :
2006				c.begin();
2007				c.moveTo(w * 0.3, h * 0.65);
2008				c.lineTo(w * 0.4, h * 0.65);
2009				c.lineTo(w * 0.4, h * 0.35);
2010				c.lineTo(w * 0.6, h * 0.35);
2011				c.lineTo(w * 0.6, h * 0.65);
2012				c.lineTo(w * 0.7, h * 0.65);
2013				c.stroke();
2014			break;
2015		case "invPulse" :
2016				c.begin();
2017				c.moveTo(w * 0.3, h * 0.35);
2018				c.lineTo(w * 0.4, h * 0.35);
2019				c.lineTo(w * 0.4, h * 0.65);
2020				c.lineTo(w * 0.6, h * 0.65);
2021				c.lineTo(w * 0.6, h * 0.35);
2022				c.lineTo(w * 0.7, h * 0.35);
2023				c.stroke();
2024			break;
2025		case "chopSquare" :
2026				c.begin();
2027				c.moveTo(w * 0.3, h * 0.5);
2028				c.lineTo(w * 0.33, h * 0.35);
2029				c.lineTo(w * 0.47, h * 0.35);
2030				c.lineTo(w * 0.53, h * 0.65);
2031				c.lineTo(w * 0.67, h * 0.65);
2032				c.lineTo(w * 0.7, h * 0.5);
2033				c.stroke();
2034			break;
2035		case "stepOn" :
2036				c.begin();
2037				c.moveTo(w * 0.3, h * 0.65);
2038				c.lineTo(w * 0.5, h * 0.65);
2039				c.lineTo(w * 0.5, h * 0.35);
2040				c.lineTo(w * 0.7, h * 0.35);
2041				c.stroke();
2042			break;
2043		case "stepOff" :
2044				c.begin();
2045				c.moveTo(w * 0.3, h * 0.35);
2046				c.lineTo(w * 0.5, h * 0.35);
2047				c.lineTo(w * 0.5, h * 0.65);
2048				c.lineTo(w * 0.7, h * 0.65);
2049				c.stroke();
2050			break;
2051		case "dc1" :
2052				c.begin();
2053				c.moveTo(w * 0.17, h * 0.5);
2054				c.lineTo(w * 0.83, h * 0.5);
2055				c.moveTo(w * 0.67, h * 0.42);
2056				c.lineTo(w * 0.83, h * 0.5);
2057				c.lineTo(w * 0.67, h * 0.58);
2058				c.stroke();
2059			break;
2060		case "dc2" :
2061				c.begin();
2062				c.moveTo(w * 0.5, h * 0.17);
2063				c.lineTo(w * 0.5, h * 0.83);
2064				c.moveTo(w * 0.42, h * 0.67);
2065				c.lineTo(w * 0.5, h * 0.83);
2066				c.lineTo(w * 0.58, h * 0.67);
2067				c.stroke();
2068			break;
2069		case "dc3" :
2070				var ss = Math.max(3, Math.min(h, w) * 0.05); // half of symbol size
2071				var i = 3; //indent
2072
2073				if (sourceType == 'dependent')
2074				{
2075					i += 3;
2076				}
2077
2078				c.begin();
2079				c.moveTo(w * 0.5 - ss, h * 0.05 + i);
2080				c.lineTo(w * 0.5 + ss, h * 0.05 + i);
2081				c.moveTo(w * 0.5, h * 0.05 - ss + i);
2082				c.lineTo(w * 0.5, h * 0.05 + ss + i);
2083				c.moveTo(w * 0.5 - ss, h * 0.95 - i);
2084				c.lineTo(w * 0.5 + ss, h * 0.95 - i);
2085				c.stroke();
2086			break;
2087	}
2088};
2089
2090mxCellRenderer.registerShape(mxShapeElectricalSource.prototype.cst.SHAPE_SOURCE, mxShapeElectricalSource);
2091