1 /*
  2  * Copyright (C) 2008, 2009 Mihai Şucan
  3  *
  4  * This file is part of PaintWeb.
  5  *
  6  * PaintWeb is free software: you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License as published by
  8  * the Free Software Foundation, either version 3 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * PaintWeb is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  * GNU General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU General Public License
 17  * along with PaintWeb.  If not, see <http://www.gnu.org/licenses/>.
 18  *
 19  * $URL: http://code.google.com/p/paintweb $
 20  * $Date: 2009-06-11 20:23:04 +0300 $
 21  */
 22 
 23 /**
 24  * @author <a lang="ro" href="http://www.robodesign.ro/mihai">Mihai Şucan</a>
 25  * @fileOverview Holds the line tool implementation.
 26  */
 27 
 28 /**
 29  * @class The line tool.
 30  *
 31  * @param {PaintWeb} app Reference to the main paint application object.
 32  */
 33 pwlib.tools.line = function (app) {
 34   var _self         = this,
 35       clearInterval = app.win.clearInterval,
 36       config        = app.config,
 37       context       = app.buffer.context,
 38       gui           = app.gui,
 39       image         = app.image,
 40       mouse         = app.mouse,
 41       setInterval   = app.win.setInterval,
 42       snapXY        = app.toolSnapXY;
 43 
 44   /**
 45    * The interval ID used for invoking the drawing operation every few 
 46    * milliseconds.
 47    *
 48    * @private
 49    * @see PaintWeb.config.toolDrawDelay
 50    */
 51   var timer = null;
 52 
 53   /**
 54    * Tells if the <kbd>Shift</kbd> key is down or not. This is used by the 
 55    * drawing function.
 56    *
 57    * @private
 58    * @type Boolean
 59    * @default false
 60    */
 61   var shiftKey = false;
 62 
 63   /**
 64    * Tells if the drawing canvas needs to be updated or not.
 65    *
 66    * @private
 67    * @type Boolean
 68    * @default false
 69    */
 70   var needsRedraw = false;
 71 
 72   /**
 73    * Holds the starting point on the <var>x</var> axis of the image, for the 
 74    * current drawing operation.
 75    *
 76    * @private
 77    * @type Number
 78    */
 79   var x0 = 0;
 80 
 81   /**
 82    * Holds the starting point on the <var>y</var> axis of the image, for the 
 83    * current drawing operation.
 84    *
 85    * @private
 86    * @type Number
 87    */
 88   var y0 = 0;
 89 
 90   /**
 91    * Tool deactivation event handler.
 92    */
 93   this.deactivate = function () {
 94     if (timer) {
 95       clearInterval(timer);
 96       timer = null;
 97     }
 98 
 99     if (mouse.buttonDown) {
100       context.clearRect(0, 0, image.width, image.height);
101     }
102 
103     needsRedraw = false;
104 
105     return true;
106   };
107 
108   /**
109    * Initialize the drawing operation, by storing the location of the pointer, 
110    * the start position.
111    *
112    * @param {Event} ev The DOM Event object.
113    */
114   this.mousedown = function (ev) {
115     x0 = mouse.x;
116     y0 = mouse.y;
117 
118     if (!timer) {
119       timer = setInterval(_self.draw, config.toolDrawDelay);
120     }
121     shiftKey = ev.shiftKey;
122     needsRedraw = false;
123 
124     gui.statusShow('lineMousedown');
125 
126     return true;
127   };
128 
129   /**
130    * Store the <kbd>Shift</kbd> key state which is used by the drawing function.
131    *
132    * @param {Event} ev The DOM Event object.
133    */
134   this.mousemove = function (ev) {
135     shiftKey = ev.shiftKey;
136     needsRedraw = true;
137   };
138 
139   /**
140    * Perform the drawing operation. This function is called every few 
141    * milliseconds.
142    *
143    * <p>Hold down the <kbd>Shift</kbd> key to draw a straight 
144    * horizontal/vertical line.
145    * <p>Press <kbd>Escape</kbd> to cancel the drawing operation.
146    *
147    * @see PaintWeb.config.toolDrawDelay
148    */
149   this.draw = function () {
150     if (!needsRedraw) {
151       return;
152     }
153 
154     context.clearRect(0, 0, image.width, image.height);
155 
156     // Snapping on the X/Y axis.
157     if (shiftKey) {
158       snapXY(x0, y0);
159     }
160 
161     context.beginPath();
162     context.moveTo(x0, y0);
163     context.lineTo(mouse.x, mouse.y);
164     context.stroke();
165     context.closePath();
166 
167     needsRedraw = false;
168   };
169 
170   /**
171    * End the drawing operation, once the user releases the mouse button.
172    *
173    * @param {Event} ev The DOM Event object.
174    */
175   this.mouseup = function (ev) {
176     // Allow users to click then drag, not only mousedown+drag+mouseup.
177     if (mouse.x == x0 && mouse.y == y0) {
178       mouse.buttonDown = true;
179       return true;
180     }
181 
182     if (timer) {
183       clearInterval(timer);
184       timer = null;
185     }
186 
187     shiftKey = ev.shiftKey;
188     _self.draw();
189     gui.statusShow('lineActive');
190     app.layerUpdate();
191 
192     return true;
193   };
194 
195   /**
196    * Allows the user to press <kbd>Escape</kbd> to cancel the drawing operation.
197    *
198    * @param {Event} ev The DOM Event object.
199    *
200    * @returns {Boolean} True if the drawing operation was cancelled, or false if 
201    * not.
202    */
203   this.keydown = function (ev) {
204     if (!mouse.buttonDown || ev.kid_ != 'Escape') {
205       return false;
206     }
207 
208     if (timer) {
209       clearInterval(timer);
210       timer = null;
211     }
212 
213     context.clearRect(0, 0, image.width, image.height);
214     mouse.buttonDown = false;
215     needsRedraw = false;
216 
217     gui.statusShow('lineActive');
218 
219     return true;
220   };
221 };
222 
223 // vim:set spell spl=en fo=wan1croqlt tw=80 ts=2 sw=2 sts=2 sta et ai cin fenc=utf-8 ff=unix:
224 
225