1 /** 2 This View is used by Greenhouse when application is in design mode 3 This is a Drawing View: 4 If you want to draw a new shape you can pass in the information: 5 For a Line: 6 7 { 8 +shape: SC.LINE, 9 +start: {x: 0, y: 0}, 10 +end: {x: 100, y: 100}, 11 ?style: { 12 ?width: 5, 13 ?color: 'orange' | '#FFA500' | 'rgb(255,165,0)' | 'rgba(255,165,0,1)' 14 ?transparency: 0.2 15 } 16 } 17 18 For a Rectangle: 19 20 { 21 +shape: SC.RECT, 22 +start: {x: 0, y: 0}, 23 +size: {width: 100, height: 100}, 24 ?type: SC.FILL | SC.STROKE 25 ?style: { 26 ?width: 5, 27 ?color: 'orange' | '#FFA500' | 'rgb(255,165,0)' | 'rgba(255,165,0,1)' 28 ?transparency: 0.2 29 } 30 } 31 32 For a Circle: 33 34 { 35 +shape: SC.CIRCLE, 36 +center: {x: 0, y: 0}, 37 +radius: 20, 38 ?type: SC.FILL | SC.STROKE 39 ?style: { 40 ?width: 5, 41 ?color: 'orange' | '#FFA500' | 'rgb(255,165,0)' | 'rgba(255,165,0,1)' 42 ?transparency: 0.2 43 } 44 } 45 46 For a Polygon: 47 48 { 49 +shape: SC.POLY 50 +path: [ 51 +{x: 0, y: 0}, 52 +{x: 10, y: 10}, 53 ?{x: 0, y: 50} 54 ], 55 ?type: SC.FILL | SC.STROKE 56 ?style: { 57 ?width: 5, 58 ?color: 'orange' | '#FFA500' | 'rgb(255,165,0)' | 'rgba(255,165,0,1)' 59 ?transparency: 0.2 60 } 61 } 62 63 @author Evin Grano 64 @extends SC.View 65 @since SproutCore 1.0 66 */ 67 SC.LINE = 'line'; 68 SC.RECT = 'rect'; 69 SC.CIRCLE = 'circle'; 70 SC.POLY = 'poly'; 71 72 SC.FILL = 'fill'; 73 SC.STROKE = 'stroke'; 74 75 76 SC.DrawingView = SC.View.extend({ 77 78 classNames: 'scui-drawing-view', 79 80 shapes: [], 81 82 _drawingManager: {}, 83 84 shapesDidChange: function(){ 85 this.set('layerNeedsUpdate', YES); 86 this.updateLayerIfNeeded(); 87 }.observes('*shapes.[]'), 88 89 init: function(){ 90 sc_super(); 91 92 // Register Basic Shapes 93 94 // Drawing a Line 95 this.registerShapeDrawing( SC.LINE, function(ctx, params){ 96 if (params.style){ 97 if (params.style.width) ctx.lineWidth = params.style.width; 98 if (params.style.color) ctx.strokeStyle = params.style.color; 99 if (params.style.transparency) ctx.globalAlpha = params.style.transparency; 100 } 101 ctx.beginPath(); 102 ctx.moveTo(params.start.x, params.start.y); 103 ctx.lineTo(params.end.x, params.end.y); 104 ctx.stroke(); 105 }); 106 107 // Drawing a Rectangle 108 this.registerShapeDrawing( SC.RECT, function(ctx, params){ 109 if (params.style){ 110 if (params.style.width) ctx.lineWidth = params.style.width; 111 if (params.style.color) ctx.fillStyle = ctx.strokeStyle = params.style.color; 112 if (params.style.transparency) ctx.globalAlpha = params.style.transparency; 113 } 114 switch(params.type){ 115 case SC.FILL: 116 ctx.fillRect(params.start.x, params.start.y, params.size.width, params.size.height); 117 break; 118 case SC.STROKE: 119 ctx.strokeRect(params.start.x, params.start.y, params.size.width, params.size.height); 120 break; 121 default: 122 ctx.clearRect(params.start.x, params.start.y, params.size.width, params.size.height); 123 break; 124 } 125 }); 126 127 // Drawing a Circle 128 this.registerShapeDrawing( SC.CIRCLE, function(ctx, params){ 129 if (params.style){ 130 if (params.style.width) ctx.lineWidth = params.style.width; 131 if (params.style.color) ctx.fillStyle = ctx.strokeStyle = params.style.color; 132 if (params.style.transparency) ctx.globalAlpha = params.style.transparency; 133 } 134 ctx.beginPath(); 135 ctx.arc(params.center.x,params.center.y,params.radius,0,Math.PI*2,true); 136 if (params.type === SC.FILL) ctx.fill(); 137 else ctx.stroke(); 138 }); 139 140 // Drawing a Polygon 141 this.registerShapeDrawing( SC.POLY, function(ctx, params){ 142 if (params.style){ 143 if (params.style.width) ctx.lineWidth = params.style.width; 144 if (params.style.color) ctx.fillStyle = ctx.strokeStyle = params.style.color; 145 if (params.style.transparency) ctx.globalAlpha = params.style.transparency; 146 } 147 ctx.beginPath(); 148 var len = params.path ? params.path.length : 0; 149 if (len < 2) return; 150 151 var path = params.path, curr; 152 ctx.moveTo(path[0].x, path[0].y); 153 for(var i = 1; i < len; i++){ 154 curr = path[i]; 155 ctx.lineTo(curr.x, curr.y); 156 } 157 ctx.lineTo(path[0].x, path[0].y); 158 if (params.type === SC.FILL) ctx.fill(); 159 else ctx.stroke(); 160 }); 161 }, 162 163 render: function(context, firstTime) { 164 //console.log('%@.render()'.fmt(this)); 165 var frame = this.get('frame'); 166 if (firstTime) { 167 if (!SC.browser.isIE) { 168 context.push('<canvas class="base-layer" width="%@" height="%@">You can\'t use canvas tags</canvas>'.fmt(frame.width, frame.height)); 169 } 170 } 171 else { 172 var canvasElem = this.$('canvas.base-layer'); 173 if (canvasElem) { 174 canvasElem.attr('width', frame.width); 175 canvasElem.attr('height', frame.height); 176 if (canvasElem.length > 0) { 177 var cntx = canvasElem[0].getContext('2d'); // Get the actual canvas object context 178 if (cntx) { 179 cntx.clearRect(0, 0, frame.width, frame.height); 180 this._drawShapes(cntx); 181 } 182 else { 183 SC.Logger.error("SC.DrawingView.render(): Canvas object context is not accessible."); 184 } 185 } 186 else { 187 SC.Logger.error("SC.DrawingView.render(): Canvas element array length is zero."); 188 } 189 } 190 else { 191 SC.Logger.error("SC.DrawingView.render(): Canvas element is not accessible."); 192 } 193 } 194 195 return sc_super(); 196 }, 197 198 registerShapeDrawing: function(name, drawingFunction){ 199 if (!name) { 200 SC.Logger.error('Can\'t register this drawing paradigm because name is null'); 201 return NO; 202 } 203 204 // OK, create the drawing paradigm 205 this._drawingManager[name] = drawingFunction; 206 this.set('layerNeedsUpdate', YES); 207 this.updateLayerIfNeeded(); 208 return YES; 209 }, 210 211 /** 212 @private 213 214 Function for actually drawing the shapes that we have listed 215 */ 216 _drawShapes: function(cntx){ 217 var curr; 218 var shapes = this.get('shapes'); 219 var drawingFunc; 220 for (var i=0,len=shapes.length;i<len;i++){ 221 curr = shapes[i]; 222 drawingFunc = this._drawingManager[curr.shape]; 223 if (drawingFunc) drawingFunc(cntx, curr); 224 } 225 } 226 }); 227