1 /*
  2  * © 2009 ROBO Design
  3  * http://www.robodesign.ro
  4  *
  5  * $Date: 2009-04-21 14:43:04 +0300 $
  6  */
  7 
  8 /**
  9  * @author <a lang="ro" href="http://www.robodesign.ro/mihai">Mihai Şucan</a>
 10  * @fileOverview The drawing tools for the paint application.
 11  */
 12 
 13 /**
 14  * Holds the implementation of each drawing tool.
 15  */
 16 var PaintTools = {};
 17 
 18 /**
 19  * @class The drawing pencil.
 20  *
 21  * @param {Painter} app Reference to the main paint application object.
 22  */
 23 PaintTools.pencil = function (app) {
 24   var _self   = this,
 25       context = app.buffer.context,
 26       update  = app.layerUpdate,
 27       mouse   = app.mouse;
 28 
 29   /**
 30    * Initialize the drawing operation.
 31    *
 32    * @param {Event} ev The DOM Event object.
 33    */
 34   this.mousedown = function (ev) {
 35     context.beginPath();
 36     context.moveTo(ev.x_, ev.y_);
 37   };
 38 
 39   /**
 40    * Perform the drawing operation, while the user moves the mouse.
 41    *
 42    * @param {Event} ev The DOM Event object.
 43    */
 44   this.mousemove = function (ev) {
 45     if (mouse.buttonDown) {
 46       context.lineTo(ev.x_, ev.y_);
 47       context.stroke();
 48     }
 49   };
 50 
 51   /**
 52    * End the drawing operation, once the user releases the mouse button.
 53    *
 54    * @param {Event} ev The DOM Event object.
 55    */
 56   this.mouseup = function (ev) {
 57     if (mouse.buttonDown) {
 58       _self.mousemove(ev);
 59       context.closePath();
 60       update();
 61     }
 62   };
 63 };
 64 
 65 /**
 66  * @class The rectangle tool.
 67  *
 68  * @param {Painter} app Reference to the main paint application object.
 69  */
 70 PaintTools.rect = function (app) {
 71   var _self   = this,
 72       context = app.buffer.context,
 73       canvas  = app.buffer.canvas,
 74       update  = app.layerUpdate,
 75       mouse   = app.mouse;
 76 
 77   /**
 78    * Holds the starting point on the <var>x</var> axis of the image, for the 
 79    * current drawing operation.
 80    *
 81    * @private
 82    * @type Number
 83    */
 84   var x0 = 0;
 85 
 86   /**
 87    * Holds the starting point on the <var>y</var> axis of the image, for the 
 88    * current drawing operation.
 89    *
 90    * @private
 91    * @type Number
 92    */
 93   var y0 = 0;
 94 
 95   /**
 96    * Initialize the drawing operation, by storing the location of the pointer, 
 97    * the start position.
 98    *
 99    * @param {Event} ev The DOM Event object.
100    */
101   this.mousedown = function (ev) {
102     x0 = ev.x_;
103     y0 = ev.y_;
104   };
105 
106   /**
107    * Perform the drawing operation, while the user moves the mouse.
108    *
109    * <p>Hold down the <kbd>Shift</kbd> key to draw a square.
110    * <p>Press <kbd>Escape</kbd> to cancel the drawing operation.
111    *
112    * @param {Event} ev The DOM Event object.
113    */
114   this.mousemove = function (ev) {
115     if (!mouse.buttonDown) {
116       return;
117     }
118 
119     var x = Math.min(ev.x_,  x0),
120         y = Math.min(ev.y_,  y0),
121         w = Math.abs(ev.x_ - x0),
122         h = Math.abs(ev.y_ - y0);
123 
124     context.clearRect(0, 0, canvas.width, canvas.height);
125 
126     if (!w || !h) {
127       return;
128     }
129 
130     // Constrain the shape to a square when the user holds down the Shift key.
131     if (ev.shiftKey) {
132       if (w > h) {
133         if (y == ev.y_) {
134           y -= w-h;
135         }
136         h = w;
137       } else {
138         if (x == ev.x_) {
139           x -= h-w;
140         }
141         w = h;
142       }
143     }
144 
145     context.strokeRect(x, y, w, h);
146   };
147 
148   /**
149    * End the drawing operation, once the user releases the mouse button.
150    *
151    * @param {Event} ev The DOM Event object.
152    */
153   this.mouseup = function (ev) {
154     if (mouse.buttonDown) {
155       _self.mousemove(ev);
156       update();
157     }
158   };
159 
160   /**
161    * Allows the user to press <kbd>Escape</kbd> to cancel the drawing operation.
162    *
163    * @param {Event} ev The DOM Event object.
164    *
165    * @returns {Boolean} True if the drawing operation was cancelled, or false if 
166    * not.
167    */
168   this.keydown = function (ev) {
169     if (!mouse.buttonDown || ev.kid_ != 'Escape') {
170       return false;
171     }
172 
173     context.clearRect(0, 0, canvas.width, canvas.height);
174     mouse.buttonDown = false;
175   };
176 };
177 
178 /**
179  * @class The line tool.
180  *
181  * @param {Painter} app Reference to the main paint application object.
182  */
183 PaintTools.line = function (app) {
184   var _self   = this,
185       context = app.buffer.context,
186       canvas  = app.buffer.canvas,
187       update  = app.layerUpdate,
188       mouse   = app.mouse;
189 
190   /**
191    * Holds the starting point on the <var>x</var> axis of the image, for the 
192    * current drawing operation.
193    *
194    * @private
195    * @type Number
196    */
197   var x0 = 0;
198 
199   /**
200    * Holds the starting point on the <var>y</var> axis of the image, for the 
201    * current drawing operation.
202    *
203    * @private
204    * @type Number
205    */
206   var y0 = 0;
207 
208   /**
209    * Initialize the drawing operation, by storing the location of the pointer, 
210    * the start position.
211    *
212    * @param {Event} ev The DOM Event object.
213    */
214   this.mousedown = function (ev) {
215     x0 = ev.x_;
216     y0 = ev.y_;
217   };
218 
219   /**
220    * Perform the drawing operation, while the user moves the mouse.
221    *
222    * <p>Hold down the <kbd>Shift</kbd> key to draw a straight 
223    * horizontal/vertical line.
224    * <p>Press <kbd>Escape</kbd> to cancel the drawing operation.
225    *
226    * @param {Event} ev The DOM Event object.
227    */
228   this.mousemove = function (ev) {
229     if (!mouse.buttonDown) {
230       return;
231     }
232 
233     context.clearRect(0, 0, canvas.width, canvas.height);
234 
235     context.beginPath();
236     context.moveTo(x0, y0);
237 
238     // Snap the line to be horizontal or vertical, when the Shift key is down.
239     if (ev.shiftKey) {
240       var diffx = Math.abs(ev.x_ - x0),
241           diffy = Math.abs(ev.y_ - y0);
242 
243       if (diffx > diffy) {
244         ev.y_ = y0;
245       } else {
246         ev.x_ = x0;
247       }
248     }
249 
250     context.lineTo(ev.x_, ev.y_);
251     context.stroke();
252     context.closePath();
253   };
254 
255   /**
256    * End the drawing operation, once the user releases the mouse button.
257    *
258    * @param {Event} ev The DOM Event object.
259    */
260   this.mouseup = function (ev) {
261     if (mouse.buttonDown) {
262       _self.mousemove(ev);
263       update();
264     }
265   };
266 
267   /**
268    * Allows the user to press <kbd>Escape</kbd> to cancel the drawing operation.
269    *
270    * @param {Event} ev The DOM Event object.
271    *
272    * @returns {Boolean} True if the drawing operation was cancelled, or false if 
273    * not.
274    */
275   this.keydown = function (ev) {
276     if (!mouse.buttonDown || ev.kid_ != 'Escape') {
277       return false;
278     }
279 
280     context.clearRect(0, 0, canvas.width, canvas.height);
281     mouse.buttonDown = false;
282   };
283 };
284 
285 // vim:set spell spl=en fo=wan1croql tw=80 ts=2 sw=2 sts=2 sta et ai cin fenc=utf-8 ff=unix:
286