1 (function(global){ // BEGIN CLOSURE 2 3 var Joint = global.Joint, 4 Element = Joint.dia.Element; 5 6 /** 7 * @name Joint.dia.devs 8 * @namespace Holds functionality related to Discrete EVent System (DEVS) diagrams. 9 */ 10 var devs = Joint.dia.devs = {}; 11 12 /** 13 * Predefined arrow. 14 * @name Joint.dia.devs.arrow 15 * @memberOf Joint.dia.devs 16 * @example a1.port("o", "out1").joint(c1.port("i", "in"), Joint.dia.devs.arrow); 17 */ 18 devs.arrow = { 19 endArrow: { type: "none" }, 20 startArrow: {type: "none"}, 21 attrs: { "stroke-dasharray": "none" } 22 }; 23 24 /** 25 * DEVS atomic/coupled model. 26 * @name Model.create 27 * @methodOf Joint.dia.devs 28 * @param {Object} properties 29 * @param {Object} properties.rect Bounding box of the model (e.g. {x: 50, y: 100, width: 150, height: 100}). 30 * @param {String} [properties.label] The name of the model. 31 * @param {Number} [properties.labelOffsetX] Offset in x-axis of the label from the model rectangle origin. 32 * @param {Number} [properties.labelOffsetY] Offset in y-axis of the label from the model rectangle origin. 33 * @param {Number} [properties.portsOffsetX] Offset in x-axis of the ports from the model rectangle origin. 34 * @param {Number} [properties.portsOffsetY] Offset in y-axis of the ports from the model rectangle origin. 35 * @param {Number} [properties.iPortRadius] Radius of the input ports circle. 36 * @param {Number} [properties.oPortRadius] Radius of the output ports circle. 37 * @param {Object} [properties.iPortAttrs] SVG attributes of the appearance of the input ports. 38 * @param {Object} [properties.oPortAttrs] SVG attributes of the appearance of the output ports. 39 * @param {Number} [properties.iPortLabelOffsetX] Offset in x-axis of the input ports label. 40 * @param {Number} [properties.oPortLabelOffsetX] Offset in x-axis of the output ports label. 41 * @param {array} [properties.iPorts] The input port names. 42 * @param {array} [properties.oPorts] The output port names. 43 * @param {Object} [properties.attrs] SVG attributes of the appearance of the model. 44 * @example 45 var a1 = Joint.dia.devs.Model.create({ 46 rect: {x: 30, y: 90, width: 100, height: 60}, 47 label: "Atomic 1", 48 attrs: { 49 fill: "90-#000-#f00:1-#fff" 50 }, 51 iPorts: ["in1"], 52 oPorts: ["out1", "out2"] 53 }); 54 */ 55 devs.Model = Element.extend({ 56 object: "Model", 57 module: "devs", 58 init: function(properties){ 59 // options 60 var p = Joint.DeepSupplement(this.properties, properties, { 61 labelOffsetX: 20, 62 labelOffsetY: 5, 63 portsOffsetX: 5, 64 portsOffsetY: 20, 65 iPortRadius: 5, 66 oPortRadius: 5, 67 iPortAttrs: { fill: 'green', stroke: 'black' }, 68 oPortAttrs: { fill: 'red', stroke: 'black' }, 69 iPortLabelOffsetX: -10, 70 iPortLabelOffsetY: -10, 71 oPortLabelOffsetX: 10, 72 oPortLabelOffsetY: -10, 73 iPorts: [], 74 oPorts: [] 75 }); 76 // wrapper 77 var paper = this.paper, i; 78 this.setWrapper(paper.rect(p.rect.x, p.rect.y, p.rect.width, p.rect.height).attr(p.attrs)); 79 // inner 80 this.addInner(this.getLabelElement()); // label 81 // draw ports 82 for (i = 0, l = p.iPorts.length; i < l; i++){ 83 this.addInner(this.getPortElement("i", i + 1, p.iPorts[i])); 84 } 85 for (i = 0, l = p.oPorts.length; i < l; i++){ 86 this.addInner(this.getPortElement("o", i + 1, p.oPorts[i])); 87 } 88 // delete all ports related properties, they are saved in port objects 89 p.iPorts = p.oPorts = p.portsOffsetX = p.portsOffsetY = p.iPortRadius = p.oPortRadius = p.iPortAttrs = p.oPortAttrs = p.iPortLabelOffsetX = p.iPortLabelOffsetY = p.oPortLabelOffsetX = p.oPortLabelOffsetY = undefined; 90 }, 91 getLabelElement: function(){ 92 var p = this.properties, 93 bb = this.wrapper.getBBox(), 94 t = this.paper.text(bb.x, bb.y, p.label).attr(p.labelAttrs || {}), 95 tbb = t.getBBox(); 96 t.translate(bb.x - tbb.x + p.labelOffsetX, bb.y - tbb.y + p.labelOffsetY); 97 return t; 98 }, 99 getPortElement: function(type, index, label){ 100 var bb = this.wrapper.getBBox(), p = this.properties, 101 port = devs.Port.create({ 102 label: label, 103 type: type, 104 position: {x: bb.x + ((type === "o") ? bb.width : 0), y: bb.y + p.portsOffsetY * index}, 105 radius: p[type + "PortRadius"], 106 attrs: p[type + "PortAttrs"], 107 offsetX: p[type + "PortLabelOffsetX"], 108 offsetY: p[type + "PortLabelOffsetY"] 109 }); 110 return port; 111 }, 112 /** 113 * Get a port object. It can be used further for connecting other port objects. 114 * @param {String} type "i"|"o" 115 * @param {String} label Name of the port. 116 * @return {Port} 117 */ 118 port: function(type, label){ 119 var el; 120 for (var i = 0, l = this.inner.length; i < l; i++){ 121 el = this.inner[i]; 122 if (el.properties && label == el.properties.label && type == el.properties.type){ 123 return el; 124 } 125 } 126 return undefined; 127 }, 128 joint: function(oPort, to, iPort, opt){ 129 // shorthand 130 if (!to.port) return undefined; // non-DEVS object 131 return this.port("o", oPort).joint(to.port("i", iPort), opt); 132 }, 133 zoom: function(){ 134 // @todo 135 } 136 }); 137 138 devs.Port = Element.extend({ 139 object: "Port", 140 module: "devs", 141 // doesn't have object and module properties => it's invisible for serializer 142 init: function(properties){ 143 var p = Joint.DeepSupplement(this.properties, properties, { 144 label: '', 145 offsetX: 0, 146 offsetY: 0, 147 type: 'i' 148 }); 149 this.setWrapper(this.paper.circle(p.position.x, p.position.y, p.radius).attr(p.attrs)); 150 this.addInner(this.getLabelElement()); 151 }, 152 getLabelElement: function(){ 153 var bb = this.wrapper.getBBox(), p = this.properties, 154 t = this.paper.text(bb.x, bb.y, p.label), 155 tbb = t.getBBox(); 156 t.translate(bb.x - tbb.x + p.offsetX, bb.y - tbb.y + p.offsetY); 157 return t; 158 }, 159 zoom: function(){ 160 // @todo 161 } 162 }); 163 164 })(this); // END CLOSURE 165