Draw a black gradient when the back side is showing.
[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 if (backShowing_) {
95 // Draw the sheen gradient.
96 context.beginPath();
97 context.arc(center[0], center[1], radius, 0, Math.PI * 2, true);
98 var gradient = context.createLinearGradient(0, 0, 0, canvas.height);
99 gradient.addColorStop(0, 'rgb(200, 200, 200)');
100 gradient.addColorStop(1, 'rgb(0, 0, 0)');
101 context.fillStyle = gradient;
102 context.fill();
103 context.closePath();
104 return;
105 }
106
107 // Draw the individual components. Start with red.
108 context.beginPath();
109 context.moveTo(center[0], center[1]);
110 context.arc(canvas.width / 2,
111 canvas.height / 2,
112 radius,
113 Math.PI * 4/3,
114 Math.PI * 6/3,
115 false);
116 context.lineTo(center[0], center[1]);
117 context.fillStyle = _GetComponentColorString('red');
118 context.fill();
119 context.stroke();
120
121 // Green component.
122 context.beginPath();
123 context.moveTo(center[0], center[1]);
124 context.arc(canvas.width / 2,
125 canvas.height / 2,
126 radius,
127 Math.PI * 0,
128 Math.PI * 2/3,
129 false);
130 context.lineTo(center[0], center[1]);
131 context.fillStyle = _GetComponentColorString('green');
132 context.fill();
133 context.stroke();
134
135 // Blue component.
136 context.beginPath();
137 context.moveTo(center[0], center[1]);
138 context.arc(canvas.width / 2,
139 canvas.height / 2,
140 radius,
141 Math.PI * 2/3,
142 Math.PI * 4/3,
143 false);
144 context.lineTo(center[0], center[1]);
145 context.fillStyle = _GetComponentColorString('blue');
146 context.fill();
147 context.stroke();
148
149 // Draw the sheen gradient.
150 context.beginPath();
151 context.arc(center[0], center[1], radius, 0, Math.PI * 2, true);
152 var gradient = context.createLinearGradient(0, 0, 0, canvas.height);
153 gradient.addColorStop(0, 'rgba(255,255,255,.5)');
154 gradient.addColorStop(1, 'rgba(0,0,0,0)');
155 context.fillStyle = gradient;
156 context.fill();
157 context.closePath();
158
159 // Draw the inner wheel.
160 context.beginPath();
161 context.arc(center[0], center[1], canvas.width / 4.75, 0, Math.PI * 2, true);
162 context.fillStyle = _GetRGBColorString();
163 context.fill();
164 context.strokeStyle = 'black';
165 context.stroke();
166 context.closePath();
167 }
168
169 // ###################################################################
170 // Returns the rgb(,,,) color string.
171
172 function _GetRGBColorString()
173 {
174 return 'rgb(' + colors_.red + ',' + colors_.green + ',' + colors_.blue + ')';
175 }
176
177 // ###################################################################
178 // Returns an individual color component's color string.
179
180 function _GetComponentColorString(color)
181 {
182 if (color == 'red') {
183 return 'rgb(' + colors_.red + ',0,0)';
184 } else if (color == 'green') {
185 return 'rgb(0,' + colors_.green + ',0)';
186 } else if (color == 'blue') {
187 return 'rgb(0,0,' + colors_.blue + ')';
188 }
189 alert('Invalid color ' + color);
190 }
191
192 // ###################################################################
193 // watches the hex field for updates
194 function hexwatcher()
195 {
196 field = document.getElementById("hexinput");
197
198 // sanitize the hex
199 var newval = field.value.replace(/[^0-9a-f]*/gi, "");
200
201 // get the length
202 var length = newval.length;
203
204 // make sure we're always 6
205 if (length > 6)
206 {
207 newval = newval.substr(0, 6);
208 }
209 else if (length == 3)
210 {
211 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);
212 }
213 else if (length < 6)
214 {
215 for (var i = length; i <= 6; i++)
216 {
217 newval = "" + newval + "0";
218 }
219 }
220
221 // update the field
222 field.value = newval;
223
224 // update fields[]
225 colors_.hex = newval;
226
227 // set RGB
228 update_rgb();
229
230 // redraw the swatch
231 Draw();
232 }
233
234 // ###################################################################
235 // update the hex value
236 function update_hex()
237 {
238 var hexstr = dec2hex(colors_.red) + dec2hex(colors_.green) + dec2hex(colors_.blue);
239 colors_.hex = hexstr;
240 document.getElementById("hexinput").value = hexstr;
241 }
242
243 // ###################################################################
244 // update the RGB values
245 function update_rgb()
246 {
247 // regex match the bits
248 var bits = colors_.hex.match(/(..)(..)(..)/);
249
250 colors_.red = hex2dec(bits[1]);
251 colors_.green = hex2dec(bits[2]);
252 colors_.blue = hex2dec(bits[3]);
253
254 // construct the hex values
255 document.getElementById("redinput").value = colors_.red;
256 document.getElementById("greeninput").value = colors_.green;
257 document.getElementById("blueinput").value = colors_.blue;
258 }
259
260 // ###################################################################
261 // convert a decimal to a hexidecimal
262 function dec2hex(dec)
263 {
264 var hexstr = "0123456789ABCDEF";
265 var low = dec % 16;
266 var high = (dec - low) / 16;
267 hex = "" + hexstr.charAt(high) + hexstr.charAt(low);
268
269 return hex.toString();
270 }
271
272 // ###################################################################
273 // converts a hexidecimal to a decimal
274 function hex2dec(hex)
275 {
276 return parseInt(hex, 16);
277 }
278
279 // ###################################################################
280 // ###################################################################
281 // ###################################################################
282
283 // flip data
284
285 function show_back()
286 {
287 backShowing_ = true;
288
289 var front = document.getElementById("front");
290 var back = document.getElementById("back");
291
292 if (window.widget)
293 {
294 widget.prepareForTransition("ToBack");
295 }
296
297 front.style.display = "none";
298 back.style.display = "block";
299
300 if (window.widget)
301 {
302 setTimeout("widget.performTransition();", 0);
303 }
304
305 document.getElementById("fliprollie").style.display = "none";
306
307 Draw();
308 }
309
310 function hide_back()
311 {
312 backShowing_ = false;
313
314 var front = document.getElementById("front");
315 var back = document.getElementById("back");
316
317 if (window.widget)
318 {
319 widget.prepareForTransition("ToFront");
320 }
321
322 back.style.display = "none";
323 front.style.display = "block";
324
325 if (window.widget)
326 {
327 setTimeout("widget.performTransition();", 0);
328 }
329
330 Draw();
331 }
332
333 var flipShown = false;
334
335 var animation = {
336 duration : 0,
337 starttime : 0,
338 to : 1.0,
339 now : 0.0,
340 from : 0.0,
341 firstElement : null,
342 timer : null
343 };
344
345 function mousemove(event)
346 {
347 if (!flipShown)
348 {
349 if (animation.timer != null)
350 {
351 clearInterval(animation.timer);
352 animation.timer = null;
353 }
354
355 var starttime = (new Date).getTime() - 13;
356
357 animation.duration = 500;
358 animation.starttime = starttime;
359 animation.firstElement = document.getElementById("flip");
360 animation.timer = setInterval("animate();", 13);
361 animation.from = animation.now;
362 animation.to = 1.0;
363 animate();
364 flipShown = true;
365 }
366 }
367
368 function mouseexit(event)
369 {
370 if (flipShown)
371 {
372 // fade in the flip widget
373 if (animation.timer != null)
374 {
375 clearInterval (animation.timer);
376 animation.timer = null;
377 }
378
379 var starttime = (new Date).getTime() - 13;
380
381 animation.duration = 500;
382 animation.starttime = starttime;
383 animation.firstElement = document.getElementById("flip");
384 animation.timer = setInterval("animate();", 13);
385 animation.from = animation.now;
386 animation.to = 0.0;
387 animate();
388 flipShown = false;
389 }
390 }
391
392
393 function animate()
394 {
395 var T;
396 var ease;
397 var time = (new Date).getTime();
398
399 T = limit_3(time - animation.starttime, 0, animation.duration);
400
401 if (T >= animation.duration)
402 {
403 clearInterval(animation.timer);
404 animation.timer = null;
405 animation.now = animation.to;
406 }
407 else
408 {
409 ease = 0.5 - (0.5 * Math.cos(Math.PI * T / animation.duration));
410 animation.now = compute_next_float(animation.from, animation.to, ease);
411 }
412
413 animation.firstElement.style.opacity = animation.now;
414 }
415
416 function limit_3 (a, b, c)
417 {
418 return a < b ? b : (a > c ? c : a);
419 }
420
421 function compute_next_float(from, to, ease)
422 {
423 return from + (to - from) * ease;
424 }
425
426 function enterflip(event)
427 {
428 document.getElementById("fliprollie").style.display = "block";
429 }
430
431 function exitflip(event)
432 {
433 document.getElementById("fliprollie").style.display = "none";
434 }
435
436 /*=====================================================================*\
437 || ###################################################################
438 || # $HeadURL$
439 || # $Id$
440 || ###################################################################
441 \*=====================================================================*/