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:21:13 +0300 $ 21 */ 22 23 /** 24 * @author <a lang="ro" href="http://www.robodesign.ro/mihai">Mihai Şucan</a> 25 * @fileOverview Holds the rectangle tool implementation. 26 */ 27 28 /** 29 * @class The rectangle tool. 30 * 31 * @param {PaintWeb} app Reference to the main paint application object. 32 */ 33 pwlib.tools.rectangle = 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 MathAbs = Math.abs, 41 MathMin = Math.min, 42 mouse = app.mouse, 43 setInterval = app.win.setInterval; 44 45 /** 46 * The interval ID used for invoking the drawing operation every few 47 * milliseconds. 48 * 49 * @private 50 * @see PaintWeb.config.toolDrawDelay 51 */ 52 var timer = null; 53 54 /** 55 * Tells if the <kbd>Shift</kbd> key is down or not. This is used by the 56 * drawing function. 57 * 58 * @private 59 * @type Boolean 60 * @default false 61 */ 62 var shiftKey = false; 63 64 /** 65 * Tells if the drawing canvas needs to be updated or not. 66 * 67 * @private 68 * @type Boolean 69 * @default false 70 */ 71 var needsRedraw = false; 72 73 /** 74 * Holds the starting point on the <var>x</var> axis of the image, for the 75 * current drawing operation. 76 * 77 * @private 78 * @type Number 79 */ 80 var x0 = 0; 81 82 /** 83 * Holds the starting point on the <var>y</var> axis of the image, for the 84 * current drawing operation. 85 * 86 * @private 87 * @type Number 88 */ 89 var y0 = 0; 90 91 /** 92 * Tool deactivation event handler. 93 */ 94 this.deactivate = function () { 95 if (timer) { 96 clearInterval(timer); 97 timer = null; 98 } 99 100 if (mouse.buttonDown) { 101 context.clearRect(0, 0, image.width, image.height); 102 } 103 104 needsRedraw = false; 105 }; 106 107 /** 108 * Initialize the drawing operation. 109 * 110 * @param {Event} ev The DOM Event object. 111 */ 112 this.mousedown = function (ev) { 113 x0 = mouse.x; 114 y0 = mouse.y; 115 116 if (!timer) { 117 timer = setInterval(_self.draw, config.toolDrawDelay); 118 } 119 shiftKey = ev.shiftKey; 120 needsRedraw = false; 121 122 gui.statusShow('rectangleMousedown'); 123 124 return true; 125 }; 126 127 /** 128 * Store the <kbd>Shift</kbd> key state which is used by the drawing function. 129 * 130 * @param {Event} ev The DOM Event object. 131 */ 132 this.mousemove = function (ev) { 133 shiftKey = ev.shiftKey; 134 needsRedraw = true; 135 }; 136 137 /** 138 * Perform the drawing operation. This function is called every few 139 * milliseconds. 140 * 141 * <p>Hold down the <kbd>Shift</kbd> key to draw a square. 142 * <p>Press <kbd>Escape</kbd> to cancel the drawing operation. 143 * 144 * @see PaintWeb.config.toolDrawDelay 145 */ 146 this.draw = function () { 147 if (!needsRedraw) { 148 return; 149 } 150 151 context.clearRect(0, 0, image.width, image.height); 152 153 var x = MathMin(mouse.x, x0), 154 y = MathMin(mouse.y, y0), 155 w = MathAbs(mouse.x - x0), 156 h = MathAbs(mouse.y - y0); 157 158 if (!w || !h) { 159 needsRedraw = false; 160 return; 161 } 162 163 // Constrain the shape to a square 164 if (shiftKey) { 165 if (w > h) { 166 if (y == mouse.y) { 167 y -= w-h; 168 } 169 h = w; 170 } else { 171 if (x == mouse.x) { 172 x -= h-w; 173 } 174 w = h; 175 } 176 } 177 178 if (config.shapeType != 'stroke') { 179 context.fillRect(x, y, w, h); 180 } 181 182 if (config.shapeType != 'fill') { 183 context.strokeRect(x, y, w, h); 184 } 185 186 needsRedraw = false; 187 }; 188 189 /** 190 * End the drawing operation, once the user releases the mouse button. 191 * 192 * @param {Event} ev The DOM Event object. 193 */ 194 this.mouseup = function (ev) { 195 // Allow click+mousemove, not only mousedown+move+up 196 if (mouse.x == x0 && mouse.y == y0) { 197 mouse.buttonDown = true; 198 return true; 199 } 200 201 if (timer) { 202 clearInterval(timer); 203 timer = null; 204 } 205 206 shiftKey = ev.shiftKey; 207 _self.draw(); 208 app.layerUpdate(); 209 gui.statusShow('rectangleActive'); 210 211 return true; 212 }; 213 214 /** 215 * Allows the user to press <kbd>Escape</kbd> to cancel the drawing operation. 216 * 217 * @param {Event} ev The DOM Event object. 218 * 219 * @returns {Boolean} True if the drawing operation was cancelled, or false if 220 * not. 221 */ 222 this.keydown = function (ev) { 223 if (!mouse.buttonDown || ev.kid_ != 'Escape') { 224 return false; 225 } 226 227 if (timer) { 228 clearInterval(timer); 229 timer = null; 230 } 231 232 context.clearRect(0, 0, image.width, image.height); 233 mouse.buttonDown = false; 234 needsRedraw = false; 235 236 gui.statusShow('rectangleActive'); 237 238 return true; 239 }; 240 }; 241 242 // vim:set spell spl=en fo=wan1croqlt tw=80 ts=2 sw=2 sts=2 sta et ai cin fenc=utf-8 ff=unix: 243 244 245