Clear the canvas before each Draw()
[rgbconverter.git] / RGB Converter.wdgt / Widget.js
1 /*=====================================================================*\
2 || ###################################################################
3 || # RGB Converter
4 || # Copyright (c)2002-2010 Blue Static
5 || #
6 || # This program 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; version 2 of the License.
9 || #
10 || # This program is distributed in the hope that it will be useful, but
11 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 || # more details.
14 || #
15 || # You should have received a copy of the GNU General Public License along
16 || # with this program; if not, write to the Free Software Foundation, Inc.,
17 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 || ###################################################################
19 \*=====================================================================*/
20
21 var colors_ = {
22 red : 60,
23 green : 60,
24 blue : 60,
25 hex : '3C3C3C'
26 };
27
28 var backShowing_ = false;
29
30 // ###################################################################
31 // widget init
32 function setup()
33 {
34 Draw();
35 createGenericButton(document.getElementById("backbutton"), "Done", hide_back, 0);
36 document.getElementById("revision").innerHTML = "(r" + document.getElementById("revision").innerHTML.replace(/[^0-9]/g, "") + ")";
37 }
38
39 // ###################################################################
40 // watches the three RGB fields to make sure they don't go over the limites
41 function rgbwatcher(color)
42 {
43 field = document.getElementById(color + "input");
44
45 // handle RGB triads
46 if (triad = field.value.match(/(rgb)?\(?([0-9]{1,3}),\s?([0-9]{1,3}),\s?([0-9]{1,3})\)?/))
47 {
48 document.getElementById("redinput").value = triad[2];
49 document.getElementById("greeninput").value = triad[3];
50 document.getElementById("blueinput").value = triad[4];
51
52 rgbwatcher("red");
53 rgbwatcher("green");
54 rgbwatcher("blue");
55 return;
56 }
57
58 // sanitize the number
59 var newval = field.value.replace(/[^0-9\-\.]*/g, "");
60 newval = Math.floor(newval);
61
62 // make sure we don't go over 255
63 if (newval > 255)
64 {
65 newval = 255;
66 }
67 else if (newval < 0)
68 {
69 newval = 0;
70 }
71
72 // update the text field
73 field.value = newval;
74
75 // set fields[]
76 colors_[color] = newval;
77
78 // set hex
79 update_hex();
80
81 // redraw the swatch
82 Draw();
83 }
84
85 // ###################################################################
86 function Draw()
87 {
88 var canvas = document.getElementById('wheel');
89 var context = canvas.getContext('2d');
90 var radius = canvas.width / 2 - 3;
91 var center = [canvas.width / 2, canvas.height / 2];
92 context.strokeStyle = 'black';
93
94 context.clearRect(0, 0, canvas.width, canvas.height);
95
96 if (backShowing_) {
97 // Draw the sheen gradient.
98 context.beginPath();
99 context.arc(center[0], center[1], radius, 0, Math.PI * 2, true);
100 var gradient = context.createLinearGradient(0, 0, 0, canvas.height);
101 gradient.addColorStop(0, 'rgb(200, 200, 200)');
102 gradient.addColorStop(1, 'rgb(0, 0, 0)');
103 context.fillStyle = gradient;
104 context.fill();
105 context.closePath();
106 return;
107 }
108
109 // Draw the individual components. Start with red.
110 context.beginPath();
111 context.moveTo(center[0], center[1]);
112 context.arc(canvas.width / 2,
113 canvas.height / 2,
114 radius,
115 Math.PI * 4/3,
116 Math.PI * 6/3,
117 false);
118 context.lineTo(center[0], center[1]);
119 context.fillStyle = _GetComponentColorString('red');
120 context.fill();
121 context.stroke();
122
123 // Green component.
124 context.beginPath();
125 context.moveTo(center[0], center[1]);
126 context.arc(canvas.width / 2,
127 canvas.height / 2,
128 radius,
129 Math.PI * 0,
130 Math.PI * 2/3,
131 false);
132 context.lineTo(center[0], center[1]);
133 context.fillStyle = _GetComponentColorString('green');
134 context.fill();
135 context.stroke();
136
137 // Blue component.
138 context.beginPath();
139 context.moveTo(center[0], center[1]);
140 context.arc(canvas.width / 2,
141 canvas.height / 2,
142 radius,
143 Math.PI * 2/3,
144 Math.PI * 4/3,
145 false);
146 context.lineTo(center[0], center[1]);
147 context.fillStyle = _GetComponentColorString('blue');
148 context.fill();
149 context.stroke();
150
151 // Draw the sheen gradient.
152 context.beginPath();
153 context.arc(center[0], center[1], radius, 0, Math.PI * 2, true);
154 var gradient = context.createLinearGradient(0, 0, 0, canvas.height);
155 gradient.addColorStop(0, 'rgba(255,255,255,.5)');
156 gradient.addColorStop(1, 'rgba(0,0,0,0)');
157 context.fillStyle = gradient;
158 context.fill();
159 context.closePath();
160
161 // Draw the inner wheel.
162 context.beginPath();
163 context.arc(center[0], center[1], canvas.width / 4.75, 0, Math.PI * 2, true);
164 context.fillStyle = _GetRGBColorString();
165 context.fill();
166 context.strokeStyle = 'black';
167 context.stroke();
168 context.closePath();
169 }
170
171 // ###################################################################
172 // Returns the rgb(,,,) color string.
173
174 function _GetRGBColorString()
175 {
176 return 'rgb(' + colors_.red + ',' + colors_.green + ',' + colors_.blue + ')';
177 }
178
179 // ###################################################################
180 // Returns an individual color component's color string.
181
182 function _GetComponentColorString(color)
183 {
184 if (color == 'red') {
185 return 'rgb(' + colors_.red + ',0,0)';
186 } else if (color == 'green') {
187 return 'rgb(0,' + colors_.green + ',0)';
188 } else if (color == 'blue') {
189 return 'rgb(0,0,' + colors_.blue + ')';
190 }
191 alert('Invalid color ' + color);
192 }
193
194 // ###################################################################
195 // watches the hex field for updates
196 function hexwatcher()
197 {
198 field = document.getElementById("hexinput");
199
200 // sanitize the hex
201 var newval = field.value.replace(/[^0-9a-f]*/gi, "");
202
203 // get the length
204 var length = newval.length;
205
206 // make sure we're always 6
207 if (length > 6)
208 {
209 newval = newval.substr(0, 6);
210 }
211 else if (length == 3)
212 {
213 newval = newval.substr(0, 1) + newval.substr(0, 1) + newval.substr(1, 1) + newval.substr(1, 1) + newval.substr(2, 1) + newval.substr(2, 1);
214 }
215 else if (length < 6)
216 {
217 for (var i = length; i <= 6; i++)
218 {
219 newval = "" + newval + "0";
220 }
221 }
222
223 // update the field
224 field.value = newval;
225
226 // update fields[]
227 colors_.hex = newval;
228
229 // set RGB
230 update_rgb();
231
232 // redraw the swatch
233 Draw();
234 }
235
236 // ###################################################################
237 // update the hex value
238 function update_hex()
239 {
240 var hexstr = dec2hex(colors_.red) + dec2hex(colors_.green) + dec2hex(colors_.blue);
241 colors_.hex = hexstr;
242 document.getElementById("hexinput").value = hexstr;
243 }
244
245 // ###################################################################
246 // update the RGB values
247 function update_rgb()
248 {
249 // regex match the bits
250 var bits = colors_.hex.match(/(..)(..)(..)/);
251
252 colors_.red = hex2dec(bits[1]);
253 colors_.green = hex2dec(bits[2]);
254 colors_.blue = hex2dec(bits[3]);
255
256 // construct the hex values
257 document.getElementById("redinput").value = colors_.red;
258 document.getElementById("greeninput").value = colors_.green;
259 document.getElementById("blueinput").value = colors_.blue;
260 }
261
262 // ###################################################################
263 // convert a decimal to a hexidecimal
264 function dec2hex(dec)
265 {
266 var hexstr = "0123456789ABCDEF";
267 var low = dec % 16;
268 var high = (dec - low) / 16;
269 hex = "" + hexstr.charAt(high) + hexstr.charAt(low);
270
271 return hex.toString();
272 }
273
274 // ###################################################################
275 // converts a hexidecimal to a decimal
276 function hex2dec(hex)
277 {
278 return parseInt(hex, 16);
279 }
280
281 // ###################################################################
282 // ###################################################################
283 // ###################################################################
284
285 // flip data
286
287 function show_back()
288 {
289 backShowing_ = true;
290
291 var front = document.getElementById("front");
292 var back = document.getElementById("back");
293
294 if (window.widget)
295 {
296 widget.prepareForTransition("ToBack");
297 }
298
299 front.style.display = "none";
300 back.style.display = "block";
301
302 if (window.widget)
303 {
304 setTimeout("widget.performTransition();", 0);
305 }
306
307 document.getElementById("fliprollie").style.display = "none";
308
309 Draw();
310 }
311
312 function hide_back()
313 {
314 backShowing_ = false;
315
316 var front = document.getElementById("front");
317 var back = document.getElementById("back");
318
319 if (window.widget)
320 {
321 widget.prepareForTransition("ToFront");
322 }
323
324 back.style.display = "none";
325 front.style.display = "block";
326
327 if (window.widget)
328 {
329 setTimeout("widget.performTransition();", 0);
330 }
331
332 Draw();
333 }
334
335 var flipShown = false;
336
337 var animation = {
338 duration : 0,
339 starttime : 0,
340 to : 1.0,
341 now : 0.0,
342 from : 0.0,
343 firstElement : null,
344 timer : null
345 };
346
347 function mousemove(event)
348 {
349 if (backShowing_)
350 return;
351
352 if (!flipShown)
353 {
354 if (animation.timer != null)
355 {
356 clearInterval(animation.timer);
357 animation.timer = null;
358 }
359
360 var starttime = (new Date).getTime() - 13;
361
362 animation.duration = 500;
363 animation.starttime = starttime;
364 animation.firstElement = document.getElementById("flip");
365 animation.timer = setInterval("animate();", 13);
366 animation.from = animation.now;
367 animation.to = 1.0;
368 animate();
369 flipShown = true;
370 }
371 }
372
373 function mouseexit(event)
374 {
375 if (backShowing_)
376 return;
377
378 if (flipShown)
379 {
380 // fade in the flip widget
381 if (animation.timer != null)
382 {
383 clearInterval (animation.timer);
384 animation.timer = null;
385 }
386
387 var starttime = (new Date).getTime() - 13;
388
389 animation.duration = 500;
390 animation.starttime = starttime;
391 animation.firstElement = document.getElementById("flip");
392 animation.timer = setInterval("animate();", 13);
393 animation.from = animation.now;
394 animation.to = 0.0;
395 animate();
396 flipShown = false;
397 }
398 }
399
400
401 function animate()
402 {
403 var T;
404 var ease;
405 var time = (new Date).getTime();
406
407 T = limit_3(time - animation.starttime, 0, animation.duration);
408
409 if (T >= animation.duration)
410 {
411 clearInterval(animation.timer);
412 animation.timer = null;
413 animation.now = animation.to;
414 }
415 else
416 {
417 ease = 0.5 - (0.5 * Math.cos(Math.PI * T / animation.duration));
418 animation.now = compute_next_float(animation.from, animation.to, ease);
419 }
420
421 animation.firstElement.style.opacity = animation.now;
422 }
423
424 function limit_3 (a, b, c)
425 {
426 return a < b ? b : (a > c ? c : a);
427 }
428
429 function compute_next_float(from, to, ease)
430 {
431 return from + (to - from) * ease;
432 }
433
434 function enterflip(event)
435 {
436 document.getElementById("fliprollie").style.display = "block";
437 }
438
439 function exitflip(event)
440 {
441 document.getElementById("fliprollie").style.display = "none";
442 }
443
444 /*=====================================================================*\
445 || ###################################################################
446 || # $HeadURL$
447 || # $Id$
448 || ###################################################################
449 \*=====================================================================*/