1/** js sequence diagrams 2 * https://bramp.github.io/js-sequence-diagrams/ 3 * (c) 2012-2017 Andrew Brampton (bramp.net) 4 * Simplified BSD license. 5 */ 6/*global Diagram, Raphael, _ */ 7 8if (typeof Raphael != 'undefined') { 9 10 var LINE = { 11 'stroke': '#000000', 12 'stroke-width': 2, 13 'fill': 'none' 14 }; 15 16 var RECT = { 17 'stroke': '#000000', 18 'stroke-width': 2, 19 'fill': '#fff' 20 }; 21 22 /****************** 23 * Raphaƫl extras 24 ******************/ 25 Raphael.fn.line = function(x1, y1, x2, y2) { 26 assert(_.all([x1,x2,y1,y2], _.isFinite), 'x1,x2,y1,y2 must be numeric'); 27 return this.path('M{0},{1} L{2},{3}', x1, y1, x2, y2); 28 }; 29 30 /****************** 31 * RaphaelTheme 32 ******************/ 33 34 var RaphaelTheme = function(diagram, options, resume) { 35 this.init(diagram, _.defaults(options, { 36 'font-size': 16, 37 'font-family': 'Andale Mono, monospace' 38 }), resume); 39 }; 40 41 _.extend(RaphaelTheme.prototype, BaseTheme.prototype, { 42 43 init: function(diagram, options, resume) { 44 BaseTheme.prototype.init.call(this, diagram); 45 46 this.paper_ = undefined; 47 this.font_ = { 48 'font-size': options['font-size'], 49 'font-family': options['font-family'] 50 }; 51 52 var a = this.arrowTypes_ = {}; 53 a[ARROWTYPE.FILLED] = 'block'; 54 a[ARROWTYPE.OPEN] = 'open'; 55 56 var l = this.lineTypes_ = {}; 57 l[LINETYPE.SOLID] = ''; 58 l[LINETYPE.DOTTED] = '-'; 59 60 resume(this); 61 }, 62 63 setupPaper: function(container) { 64 this.paper_ = new Raphael(container, 320, 200); 65 this.paper_.setStart(); 66 }, 67 68 draw: function(container) { 69 BaseTheme.prototype.draw.call(this, container); 70 this.paper_.setFinish(); 71 }, 72 73 layout: function() { 74 BaseTheme.prototype.layout.call(this); 75 this.paper_.setSize( 76 this.diagram.width, 77 this.diagram.height 78 ); 79 }, 80 81 /** 82 * Strip whitespace from each newline 83 */ 84 cleanText: function(text) { 85 text = _.invoke(text.split('\n'), 'trim'); 86 return text.join('\n'); 87 }, 88 89 /** 90 * Returns the text's bounding box 91 */ 92 textBBox: function(text, font) { 93 text = this.cleanText(text); 94 font = font || {}; 95 var p; 96 if (font.obj_) { 97 p = this.paper_.print(0, 0, text, font.obj_, font['font-size']); 98 } else { 99 p = this.paper_.text(0, 0, text); 100 p.attr(font); 101 } 102 103 var bb = p.getBBox(); 104 p.remove(); 105 106 return bb; 107 }, 108 109 drawLine: function(x1, y1, x2, y2, linetype, arrowhead) { 110 var line = this.paper_.line(x1, y1, x2, y2).attr(LINE); 111 if (arrowhead !== undefined) { 112 line.attr('arrow-end', this.arrowTypes_[arrowhead] + '-wide-long'); 113 } 114 if (arrowhead !== undefined) { 115 line.attr('stroke-dasharray', this.lineTypes_[linetype]); 116 } 117 return line; 118 }, 119 120 drawRect: function(x, y, w, h) { 121 return this.paper_.rect(x, y, w, h).attr(RECT); 122 }, 123 124 /** 125 * Draws text with a optional white background 126 * x,y (int) x,y top left point of the text, or the center of the text (depending on align param) 127 * text (string) text to print 128 * font (Object) 129 * align (string) ALIGN_LEFT or ALIGN_CENTER 130 */ 131 drawText: function(x, y, text, font, align) { 132 text = this.cleanText(text); 133 font = font || {}; 134 align = align || ALIGN_LEFT; 135 136 var paper = this.paper_; 137 var bb = this.textBBox(text, font); 138 139 if (align == ALIGN_CENTER) { 140 x = x - bb.width / 2; 141 y = y - bb.height / 2; 142 } 143 144 var t; 145 if (font.obj_) { 146 // When using a font, we have to use .print(..) 147 t = paper.print(x - bb.x, y - bb.y, text, font.obj_, font['font-size']); 148 } else { 149 t = paper.text(x - bb.x - bb.width / 2, y - bb.y, text); 150 t.attr(font); 151 t.attr({'text-anchor': 'start'}); 152 } 153 154 return t; 155 } 156 }); 157 158 /****************** 159 * RaphaelHandTheme 160 ******************/ 161 162 var RaphaelHandTheme = function(diagram, options, resume) { 163 this.init(diagram, _.defaults(options, { 164 'font-size': 16, 165 'font-family': 'daniel' 166 }), resume); 167 }; 168 169 // Take the standard RaphaelTheme and make all the lines wobbly 170 _.extend(RaphaelHandTheme.prototype, RaphaelTheme.prototype, { 171 setupPaper: function(container) { 172 RaphaelTheme.prototype.setupPaper.call(this, container); 173 this.font_.obj_ = this.paper_.getFont('daniel'); 174 }, 175 176 drawLine: function(x1, y1, x2, y2, linetype, arrowhead) { 177 var line = this.paper_.path(handLine(x1, y1, x2, y2)).attr(LINE); 178 if (arrowhead !== undefined) { 179 line.attr('arrow-end', this.arrowTypes_[arrowhead] + '-wide-long'); 180 } 181 if (arrowhead !== undefined) { 182 line.attr('stroke-dasharray', this.lineTypes_[linetype]); 183 } 184 return line; 185 }, 186 187 drawRect: function(x, y, w, h) { 188 return this.paper_.path(handRect(x, y, w, h)).attr(RECT); 189 } 190 }); 191 192 registerTheme('raphaelSimple', RaphaelTheme); 193 registerTheme('raphaelHand', RaphaelHandTheme); 194} 195