1 (function(global){	// BEGIN CLOSURE
  2 
  3 var Joint = global.Joint,
  4      Element = Joint.dia.Element;
  5 
  6 /**
  7  * @name Joint.dia.pn
  8  * @namespace Holds functionality related to Petri net diagrams.
  9  */
 10 var pn = Joint.dia.pn = {};
 11 
 12 /**
 13  * Predefined arrow.
 14  * @name Joint.dia.pn.arrow
 15  * @memberOf Joint.dia.pn
 16  * @example p1.joint(e2, Joint.dia.pn.arrow);
 17  */
 18 pn.arrow = {
 19     startArrow: {type: "none"},
 20     endArrow: {type: "basic", size: 5}, 
 21     attrs: {"stroke-dasharray": "none"}
 22 };
 23 
 24 /**
 25  * Petri net place.
 26  * @name Place.create
 27  * @methodOf Joint.dia.pn
 28  * @param {Object} properties
 29  * @param {Object} properties.position Position of the place (e.g. {x: 50, y: 100}).
 30  * @param {Number} [properties.radius] Radius of the circle of the place.
 31  * @param {Number} [properties.tokenRadius] Radius of the tokens of the place.
 32  * @param {Number} [properties.tokens] Number of tokens.
 33  * @param {String} [properties.label] The name of the place.
 34  * @param {Object} [properties.attrs] SVG attributes of the appearance of the place.
 35  * @param {Object} [properties.tokenAttrs] SVG attributes of the appearance of the token circles.
 36  * @example
 37 var p1 = Joint.dia.pn.Place.create({
 38   position: {x: 120, y: 70},
 39   radius: 25,
 40   tokenRadius: 4,
 41   tokens: 3,
 42   label: "p1",
 43   attrs: {
 44     stroke: "blue"
 45   },
 46   tokenAttrs: {
 47     fill: "red"
 48   }
 49 });
 50  */
 51 pn.Place = Element.extend({
 52      object: "Place",
 53      module: "pn",
 54      init: function(properties){
 55 	 // options
 56 	 var p = Joint.DeepSupplement(this.properties, properties, {
 57              radius: 20,
 58              tokenRadius: 3,
 59              tokens: 0,
 60              attrs: { fill: 'white' },
 61              tokenAttrs: { fill: 'black' }
 62          });
 63 	 // wrapper
 64 	 var paper = this.paper;
 65 	 this.setWrapper(paper.circle(p.position.x, p.position.y, p.radius).attr(p.attrs));
 66 	 // inner
 67 	 var strut = 2; // px
 68 	 switch (p.tokens){
 69 	 case 0:
 70 	     break;
 71 	 case 1:
 72 	     this.addInner(paper.circle(p.position.x, p.position.y, p.tokenRadius).attr(p.tokenAttrs));
 73 	     break;
 74 	 case 2:
 75 	     this.addInner(paper.circle(p.position.x - (p.tokenRadius * 2), p.position.y, p.tokenRadius).attr(p.tokenAttrs));
 76 	     this.addInner(paper.circle(p.position.x + (p.tokenRadius * 2), p.position.y, p.tokenRadius).attr(p.tokenAttrs));
 77 	     break;
 78 	 case 3:
 79 	     this.addInner(paper.circle(p.position.x - (p.tokenRadius * 2) - strut, p.position.y, p.tokenRadius).attr(p.tokenAttrs));
 80 	     this.addInner(paper.circle(p.position.x + (p.tokenRadius * 2) + strut, p.position.y, p.tokenRadius).attr(p.tokenAttrs));
 81 	     this.addInner(paper.circle(p.position.x, p.position.y, p.tokenRadius).attr(p.tokenAttrs));
 82 	     break;
 83 	 default:
 84 	     this.addInner(paper.text(p.position.x, p.position.y, p.tokens.toString()));
 85 	     break;
 86 	 }
 87 	 // label
 88 	 if (p.label){
 89 	     this.addInner(paper.text(p.position.x, p.position.y - p.radius, p.label));
 90 	     this.inner[this.inner.length - 1].translate(0, -this.inner[this.inner.length - 1].getBBox().height);
 91 	 }
 92      },
 93      zoom: function(){
 94 	 // @todo tokens must move accordingly
 95 	 for (var i = 0, len = this.inner.length; i < len; i++){
 96 	     this.inner[i].scale.apply(this.inner[i], arguments);
 97 	 }
 98 	 if (this.label){
 99 	     this.inner[this.inner.length - 1].remove();
100 	     var bb = this.wrapper.getBBox();
101 	     this.inner[this.inner.length - 1] = this.paper.text(bb.x, bb.y, this.properties.label);
102 	     this.inner[this.inner.length - 1].translate(0, -this.inner[this.inner.length - 1].getBBox().height);
103 	 }
104      }
105 });
106 
107 /**
108  * Petri net event.
109  * @name Event.create
110  * @methodOf Joint.dia.pn
111  * @param {Object} properties
112  * @param {Object} properties.rect Bounding box of the event (e.g. {x: 50, y: 100, width: 30, height: 100}).
113  * @param {String} [properties.label] The name of the event.
114  * @param {Object} [properties.attrs] SVG attributes of the appearance of the event.
115  * @example
116 var p1 = Joint.dia.pn.Event.create({
117   rect: {x: 120, y: 70, width: 50, height: 7},
118   label: "e1",
119   attrs: {
120     stroke: "blue",
121     fill: "yellow"
122   }
123 });
124  */
125 pn.Event = Element.extend({
126      object: "Event",
127      module: "pn",
128      init: function(properties){
129 	 // options
130 	 var p = Joint.DeepSupplement(this.properties, properties, {
131              attrs: { fill: 'black', stroke: 'black' }
132          });
133 	 // wrapper
134 	 var paper = this.paper;
135 	 this.setWrapper(paper.rect(p.rect.x, p.rect.y, p.rect.width, p.rect.height).attr(p.attrs));
136 	 if (p.label){
137 	     this.addInner(paper.text(p.rect.x, p.rect.y, p.label));
138 	     this.inner[0].translate(0, -this.inner[0].getBBox().height);
139 	 }
140      },
141      zoom: function(){
142 	 if (this.properties.label){
143 	     this.inner[0].remove();
144 	     var bb = this.wrapper.getBBox();
145 	     this.inner[0] = this.paper.text(bb.x, bb.y, this.properties.label);
146 	     this.inner[0].translate(0, -this.inner[0].getBBox().height);
147 	 }
148      }
149 });
150 
151 })(this);	// END CLOSURE
152