OSDN Git Service

import source-tree based svn r84.
[bluegriffon/BlueGriffon.git] / base / content / bluegriffon / js / colourPicker.js
1 var gColorObj = {};
2 var gWindowTitle = "";
3 var gShowTransparency = false;
4
5 var colours;
6 var satSlider = new objColour();
7 var hexChars = "0123456789ABCDEF";
8 var selectedColour = 0;
9 var mouseDown = false;
10 var eventInitiator = null;
11 var mouseX, mouseY, offsetLeft, offsetTop;
12
13 var gColor = "";
14 var LastPickedColor = "";
15 var ColorType = "Text";
16 var TextType = false;
17 var HighlightType = false;
18 var TableOrCell = false;
19 var LastPickedIsDefault = false;
20 var NoDefault = false;
21
22 var namedColorsArray = [
23   { name:"aqua",     value:"#00ffff" },
24   { name:"black",    value:"#000000" },
25   { name:"blue",     value:"#0000ff" },
26   { name:"fuchsia",  value:"#ff00ff" },
27   { name:"gray",     value:"#808080" },
28   { name:"green",    value:"#008000" },
29   { name:"lime",     value:"#00ff00" },
30   { name:"maroon",   value:"#800000" },
31   { name:"navy",     value:"#000080" },
32   { name:"olive",    value:"#808000" },
33   { name:"orange",   value:"#FFA500" },    
34   { name:"purple",   value:"#800080" },
35   { name:"red",      value:"#ff0000" },
36   { name:"silver",   value:"#c0c0c0" },
37   { name:"teal",     value:"#008080" },
38   { name:"white",    value:"#ffffff" },
39   { name:"yellow",   value:"#ffff00" }
40   ];
41
42
43 function StartUp()
44 {
45   GetUIElements();
46
47
48   if (!window.arguments[0])
49   {
50     dump("colourPicker: Missing color object param\n");
51     return;
52   }
53
54   // window.arguments[0] is object to get initial values and return color data
55   gColorObj = window.arguments[0];
56   gWindowTitle  = window.arguments[1];
57   gShowTransparency = window.arguments[2];
58
59   gColorObj.cancelled = false;
60
61   colours = new objColour();
62
63   makeDraggable(gDialog.hueAndSaturationImg);
64   makeDraggable(gDialog.hueAndSaturationCrosshair);
65   makeDraggable(gDialog.brightnessImg);
66
67   gDialog.hexColour.value = "";
68   var tmpColor;
69   var haveTableRadio = false;
70   var showTransparencyCheckbox = false;
71
72   if (!gShowTransparency)
73     gDialog.transparencyCheckbox.setAttribute("hidden", true);
74
75   gColorObj.currentColor = ConvertRGBColorIntoHEXColor(gColorObj.currentColor);
76   gColorObj.lastPickedColor = ConvertRGBColorIntoHEXColor(gColorObj.lastPickedColor);
77
78   gDialog.LastPickedColor.setAttribute("style", "background-color: " +
79                                        gColorObj.lastPickedColor);
80
81   // Set initial color in input field and in the colorpicker
82   SetCurrentColor(gColorObj.currentColor);
83   if (!showTransparencyCheckbox)
84     gDialog.colorpicker.initColor(gColorObj.currentColor);
85
86   // Caller can prevent user from submitting an empty, i.e., default color
87   NoDefault = gColorObj.NoDefault;
88   if (NoDefault)
89   {
90     // Hide the "Default button -- user must pick a color
91     var defaultColorButton = document.getElementById("DefaultColorButton");
92     if (defaultColorButton)
93       defaultColorButton.collapsed = true;
94   }
95
96   // Set focus to colorpicker if not set to table radio buttons above
97   if (!haveTableRadio)
98     gDialog.colorpicker.focus();
99
100   // SetWindowLocation();
101 }
102
103 // * utility function to convert predefined HTML4 color names
104 //   into their #rrggbb equivalent and back
105 function getHexColorFromColorName(color)
106 {
107   color = color.toLowerCase();
108   for (var i=0; i< namedColorsArray.length; i++) {
109     if (color == namedColorsArray[i].name) {
110       return namedColorsArray[i].value;
111     }
112   }
113   return null;
114 }
115
116 function getColorNameFromHexColor(color)
117 {
118   color = color.toLowerCase();
119   for (var i=0; i< namedColorsArray.length; i++) {
120     if (color == namedColorsArray[i].value) {
121       return namedColorsArray[i].name;
122     }
123   }
124   return null;
125 }
126
127 function makeDraggable(obj)
128 {
129    obj.onmousedown = startDrag;
130    obj.onmousemove = moveDrag;
131    obj.onmouseup = endDrag;
132 }
133
134 function computeOffsets(t)
135 {
136   offsetLeft = 0;
137   offsetTop = 0;
138   while (t && !(t instanceof XULElement))
139   {
140     offsetLeft += t.offsetLeft;
141     offsetTop  += t.offsetTop;
142     t = t.parentNode;
143   }
144 }
145
146 function startDrag(e)
147 {
148    mouseDown = true;
149
150    var target = e.target;
151    if (target.id == "hueAndSaturationCrosshair")
152      target = target.parentNode;
153
154    eventInitiator = target;
155    computeOffsets(target);
156    mouseX = e.clientX - offsetLeft + 1;
157    mouseY = e.clientY - offsetTop + 1;
158
159    handleValueChange(target);
160    e.preventDefault();
161
162 }
163
164 function moveDrag(e)
165 {
166    var target = e.target;
167    if (target.id == "hueAndSaturationCrosshair")
168      target = target.parentNode;
169
170    if (mouseDown && target == eventInitiator)
171    {
172       computeOffsets(target);
173       mouseX = e.clientX - offsetLeft  + 1;
174       mouseY = e.clientY - offsetTop  + 1;
175
176       mouseX = Math.max(0, Math.min(mouseX, 199));
177       mouseY = Math.max(0, Math.min(mouseY, 199));
178
179       handleValueChange(target);
180    }
181 }
182
183 function endDrag(e)
184 {
185
186    mouseDown = false;
187    eventInitiator = null;
188    handleValueChange(e.target);
189    e.preventDefault();
190 }
191
192 function handleValueChange(obj)
193 {
194    var sWidth = 200;
195
196    if (obj.id == "brightnessImg")
197    { 
198          var bVal = mouseX * 255 / sWidth;
199          var h = colours.getHue();
200          var s = colours.getSaturation();
201          colours.setHSB(h, s, bVal);
202          redrawEverything();
203    }
204    else if (obj.id == "hueAndSaturationImg")
205    {
206          var hVal = mouseX * 360 / sWidth;
207          var sVal = (200 - mouseY) * 100 / sWidth;
208          var b = colours.getBrightness();
209          if (!b)
210            b = 1;
211          colours.setHSB(hVal, sVal/100, b);
212          redrawEverything();
213    }
214 }
215
216 function checkRange(value, min, max)
217 {
218   return Math.max(min, Math.min(value, max));
219 }
220
221 // the user has changed the RGB textboxes
222 function changeRGB()
223 {
224
225    var red   = gDialog.red;
226    var green = gDialog.green;
227    var blue  = gDialog.blue;
228
229    // XXX Check for numbers
230    red.value   = checkRange(red.value, 0, 255);
231    green.value = checkRange(green.value, 0, 255);
232    blue.value  = checkRange(blue.value, 0, 255);
233
234    colours.setRGB(red.value, green.value, blue.value);
235    redrawEverything();
236 }
237
238 function changeHSB()
239 {
240    var hue        = gDialog.hue;
241    var saturation = gDialog.saturation;
242    var brightness = gDialog.brightness;
243
244    // XXX Check for letters
245    brightness.value = checkRange(brightness.value, 0, 255);
246    saturation.value = checkRange(saturation.value, 0, 100);
247
248    var sat = saturation.value / 100;
249
250    // Hue is a degree from 0-360
251    // XXX Maybe rotate it back until it's 0-360
252    hue.value = checkRange(hue.value, 0, 359);
253
254    colours.setHSB(hue.value, sat, brightness.value);
255    redrawEverything();
256 }
257
258 function SetCurrentColor(color)
259 {
260   if (!color)
261     color = "transparent";
262
263   if (color == "transparent")
264     gDialog.transparencyCheckbox.checked = true;
265   else
266   {
267     var hexCol = getHexColorFromColorName(color);
268     if (hexCol)
269       color = hexCol;
270     gDialog.hexColour.value = color;
271     changeHex();
272   }
273   ToggleTransparency(gDialog.transparencyCheckbox);
274 }
275
276 function changeHex()
277 {
278    var hex = gDialog.hexColour.value;
279
280    // XXX Check to see if they are hex digits
281    if (hex.length < 6)
282    {
283      alert("Color is not made of a hash ('#') followed by six hex digits");
284      return;
285    }
286
287    colours.setHex(hex.toUpperCase().substr(1, hex.length-1));
288    redrawEverything();
289 }
290
291
292 function redrawEverything()
293 {
294    gDialog.transparencyCheckbox.checked = false;
295    ToggleTransparency(gDialog.transparencyCheckbox);
296
297    LastPickedIsDefault = false;  
298
299    redisplaySwatches();
300    redisplayHexValue();
301    redisplayRGBValues();
302    redisplayHSBValues();
303
304    redisplayColorName();
305    redisplayBrightness();
306 }
307
308 function redisplayBrightness()
309 {
310    var sat = gDialog.brightnessImg;
311    var h = colours.getHue();
312    var s = colours.getSaturation();
313    satSlider.setHSB(h, s, 255);
314    sat.setAttribute("style",
315      sat.getAttribute("style") + ";background-color: #" + satSlider.getHex());
316 }
317
318 function redisplaySaturation()
319 {
320    var sat = gDialog.saturationImg;
321    var h = colours.getHue();
322    var b = colours.getBrightness();
323    satSlider.setHSB(h, 1, b);
324    sat.setAttribute("style",
325      sat.getAttribute("style") + ";background-color: #" + satSlider.getHex());
326 }
327
328 function redisplaySwatches()
329 {
330   gDialog.swatch.style.backgroundColor = "#" + colours.getHex();
331 }
332
333 function redisplayHexValue()
334 {
335    gDialog.hexColour.value = "#" + colours.getHex();
336 }
337
338 function redisplayColorName()
339 {
340    var color = getColorNameFromHexColor("#" + colours.getHex());
341    if (color)
342      gDialog.nameColour.value = color;
343    else
344      gDialog.nameColour.value = "";
345 }
346
347 function redisplayRGBValues()
348 {
349    gDialog.red.value   = Math.round(colours.getRed());
350    gDialog.green.value = Math.round(colours.getGreen());
351    gDialog.blue.value  = Math.round(colours.getBlue());
352 }
353
354 function redisplayHSBValues()
355 {
356   var h = Math.round(colours.getHue());
357   var s = Math.round(colours.getSaturation() * 100);
358   var b = Math.round(colours.getBrightness());
359
360   gDialog.hue.value        = h;
361   gDialog.saturation.value = s;
362   gDialog.brightness.value = b;
363
364   computeOffsets(gDialog.hueAndSaturationCrosshair.parentNode);
365
366   var arrow = gDialog.brightnessArrow;
367   arrow.setAttribute("style",
368     arrow.getAttribute("style") + ";left: " + (b/255*200 + 2) + "px");
369
370   var crosshair = gDialog.hueAndSaturationCrosshair;
371   crosshair.setAttribute("style",
372     crosshair.getAttribute("style") + ";left: " + (h/360*200 + 4) + "px"
373                                     + ";top:  " + ((100-s)/100*200 +4) + "px");
374
375 }
376
377
378 // The object that stores the colours in ram
379 function objColour()
380 {
381
382  this.r = 128;
383  this.g = (128 + (Math.random() * 100));
384  this.b = 128;
385
386  // Returns the hex value
387  this.getHex = function()
388  {
389    var v = Math.floor(this.r) * 256 * 256 +
390            Math.floor(this.g) *256 +
391            Math.floor(this.b);
392    var c = Number(v).toString(16);
393    while (c.length < 6)
394      c = "0" + c;
395    return c;
396  }
397  this.getRed = function()
398  {
399    return this.r;
400  }
401  this.getGreen = function()
402  {
403    return this.g;
404  }
405  this.getBlue = function()
406  {
407    return this.b;
408  }
409  this.getBrightness = function()
410  {
411    // find the min and max rgb values
412    var max1 = Math.max(this.r, this.g);
413    var max2 = Math.max(max1, this.b);
414    return max2;
415  }
416  this.getSaturation = function()
417  {
418    // find the min and max rgb values
419    var min1 = Math.min(this.r, this.g);
420    var min2 = Math.min(min1, this.b);
421    var max1 = Math.max(this.r, this.g);
422    var max2 = Math.max(max1, this.b); // v
423
424    var delta = max2 - min2;
425    var sat = 0;
426    if (max2 != 0)
427    {
428       sat = delta / max2;
429    }
430    return sat;
431  }
432
433  this.getHue = function()
434  {
435    var hue = 0;
436    // If all the values are the same, there is no hue, just brightness
437    if (this.r == this.g && this.g == this.b)
438    {
439       hue = 0;
440       return hue;
441    }
442
443    // find the min and max rgb values
444    var min1 = Math.min(this.r, this.g);
445    var min2 = Math.min(min1, this.b);
446    var max1 = Math.max(this.r, this.g);
447    var max2 = Math.max(max1, this.b); // v
448
449    var delta = max2 - min2;
450
451    if (max2 == 0)
452    {
453       hue = 0;
454       return hue; // Saturation is undefined, so there is no hue
455    }
456
457    if (this.r == max2)
458    {
459       hue = (this.g - this.b) / delta; // It's between yellow and magenta
460    }
461    else if (this.g == max2)
462    {
463       hue = 2 + (this.b - this.r) / delta; // It's between cyan and yellow
464    }
465    else
466    {
467       hue = 4 + (this.r - this.g) / delta; // It's between magenta and cyan
468    }
469
470    hue *= 60; // Get it in degrees
471    if (hue < 0)
472    {
473       hue += 360;
474    }
475    if (!hue)
476    {
477       hue = 0;
478    }
479    return hue;
480  }
481
482  this.setRGB = function(r, g, b)
483  {
484     this.r = r;
485     this.g = g;
486     this.b = b;
487  }
488
489  this.setHSB = function(h, s, b)
490  {
491
492     if (s == 0)
493     {
494        // Set it to a grey based on the brightness
495        this.r = b;
496        this.g = b;
497        this.b = b;
498        return;
499     }
500
501     h /= 60; // Get it out of degrees
502
503     var i = Math.floor(h);
504     var f = h - i; // Grab the decimal part
505     var p = b * (1 - s);
506     var q = b * (1 - s * f);
507     var t = b * (1 - s * (1 - f));
508
509     switch (i)
510     {
511        case 0:
512           this.r = b;
513           this.g = t;
514           this.b = p;
515           break;
516        case 1:
517           this.r = q;
518           this.g = b;
519           this.b = p;
520           break;
521        case 2:
522           this.r = p;
523           this.g = b;
524           this.b = t;
525           break;
526        case 3:
527           this.r = p;
528           this.g = q;
529           this.b = b;
530           break;
531        case 4:
532           this.r = t;
533           this.g = p;
534           this.b = b;
535           break;
536        default:
537           this.r = b;
538           this.g = p;
539           this.b = q;
540           break;
541     }
542  }
543
544  this.setHex = function(hex)
545  {
546     var c = hex.split("");
547     var red = hex2dec(c[0]) * 16 + hex2dec(c[1]);
548     var green = hex2dec(c[2]) * 16 + hex2dec(c[3]);
549     var blue = hex2dec(c[4]) * 16 + hex2dec(c[5]);
550     this.r = red;
551     this.g = green;
552     this.b = blue;
553  }
554 }
555
556
557 // Returns the decimal value of a hex character
558 function hex2dec(hex)
559 {
560    return hexChars.indexOf(hex);
561 }
562
563 // return the hexidecimal value of a decimal digit from 1-16
564 function dec2hex(dec)
565 {
566    return hexChars.charAt(dec);
567 }
568
569 function SelectColor()
570 {
571   var color = gDialog.colorpicker.color;
572   if (color)
573   {
574     colours.setHex(color.toUpperCase().substr(1, color.length-1));
575     redrawEverything();
576   }
577 }
578
579 function onAccept()
580 {
581   if (gDialog.transparencyCheckbox.checked)
582     gColorObj.currentColor = "transparent";
583   else
584     gColorObj.currentColor = gDialog.hexColour.value;
585   gColorObj.lastPickedColor = gColorObj.currentColor;
586   return true;
587 }
588
589 function ValidateData()
590 {
591 }
592
593 function onCancelColor()
594 {
595   // Tells caller that user canceled
596   gColorObj.cancelled = true;
597   //SaveWindowLocation();
598   return true;
599 }
600
601 function IncreaseTextboxValue(id, maxValue)
602 {
603   var e = document.getElementById(id);
604   if (e)
605   {
606     var v = e.value;
607     var newValue = Math.min(maxValue, Number(v) + 1);
608     e.value = newValue;
609     if (newValue != v)
610       redrawEverythingAfterTexboxValueChanged(id);
611   }
612 }
613
614 function DecreaseTextboxValue(id, minValue)
615 {
616   var e = document.getElementById(id);
617   if (e)
618   {
619     var v = e.value;
620     var newValue = Math.max(minValue, Number(v) - 1);
621     e.value = newValue;
622     if (newValue != v)
623       redrawEverythingAfterTexboxValueChanged(id);
624   }
625 }
626
627 function redrawEverythingAfterTexboxValueChanged(id)
628 {
629   if (id == "hue" ||
630       id == "saturation" ||
631       id == "brightness")
632   {
633     var h = gDialog.hue.value;
634     var s = gDialog.saturation.value;
635     var b = gDialog.brightness.value;
636     colours.setHSB(h, s/100, b);
637   }
638   else
639   {
640     var r = gDialog.red.value;
641     var g = gDialog.green.value;
642     var b = gDialog.blue.value;
643     colours.setRGB(r, g, b);
644   }
645   redrawEverything();
646 }
647
648 function onTextboxValueChanged(e, id)
649 {
650   forceInteger(id);
651   var v = e.value;
652   switch (id)
653   {
654     case "hue":
655       v = checkRange(v, 0, 359);
656       break;
657     case "brightness":
658     case "red":
659     case "green":
660     case "blue":
661       v = checkRange(v, 0, 255);
662       break;
663     case "saturation":
664       v = checkRange(v, 0, 100);
665       break;
666   }
667   e.value = v;
668   redrawEverythingAfterTexboxValueChanged(id);
669 }
670
671 function ToggleTransparency(elt)
672 {
673   if (elt.checked)
674   {
675     gDialog.red.setAttribute("disabled", true);
676     gDialog.blue.setAttribute("disabled", true);
677     gDialog.green.setAttribute("disabled", true);
678     gDialog.hue.setAttribute("disabled", true);
679     gDialog.saturation.setAttribute("disabled", true);
680     gDialog.brightness.setAttribute("disabled", true);
681     gDialog.hexColour.setAttribute("disabled", true);
682     gDialog.nameColour.setAttribute("disabled", true);
683     gDialog.redLabel.setAttribute("disabled", true);
684     gDialog.blueLabel.setAttribute("disabled", true);
685     gDialog.greenLabel.setAttribute("disabled", true);
686     gDialog.hueLabel.setAttribute("disabled", true);
687     gDialog.saturationLabel.setAttribute("disabled", true);
688     gDialog.brightnessLabel.setAttribute("disabled", true);
689     gDialog.hexColourLabel.setAttribute("disabled", true);
690     gDialog.nameColourLabel.setAttribute("disabled", true);
691
692     gDialog.swatch.style.backgroundColor = "#ffffff";
693   }
694   else
695   {
696     gDialog.red.removeAttribute("disabled");
697     gDialog.blue.removeAttribute("disabled");
698     gDialog.green.removeAttribute("disabled");
699     gDialog.hue.removeAttribute("disabled");
700     gDialog.saturation.removeAttribute("disabled");
701     gDialog.brightness.removeAttribute("disabled");
702     gDialog.hexColour.removeAttribute("disabled");
703     gDialog.nameColour.removeAttribute("disabled");
704     gDialog.redLabel.removeAttribute("disabled");
705     gDialog.blueLabel.removeAttribute("disabled");
706     gDialog.greenLabel.removeAttribute("disabled");
707     gDialog.hueLabel.removeAttribute("disabled");
708     gDialog.saturationLabel.removeAttribute("disabled");
709     gDialog.brightnessLabel.removeAttribute("disabled");
710     gDialog.hexColourLabel.removeAttribute("disabled");
711     gDialog.nameColourLabel.removeAttribute("disabled");
712
713     gDialog.swatch.style.backgroundColor = "#" + colours.getHex();
714   }
715 }
716
717 function onNamedColourChanged(elt)
718 {
719   var namedColour = elt.value;
720   var i, l = namedColorsArray.length;
721   for (i=0; i<l; i++)
722   {
723     if (namedColorsArray[i].name == namedColour)
724     {
725       gDialog.hexColour.value = namedColorsArray[i].value;
726       changeHex();
727       return;
728     }
729   }
730 }
731
732 function SelectLastPickedColor()
733 {
734   SetCurrentColor(gColorObj.lastPickedColor);
735   LastPickedIsDefault = true;  
736   if ( onAccept() )
737   {
738     window.close();
739     return true;
740   }
741   return false;
742 }
743
744 function forceInteger(elementID)
745 {
746   var editField = document.getElementById( elementID );
747   if ( !editField )
748     return;
749
750   var stringIn = editField.value;
751   if (stringIn && stringIn.length > 0)
752   {
753     // Strip out all nonnumeric characters
754     stringIn = stringIn.replace(/\D+/g,"");
755     if (!stringIn) stringIn = "";
756
757     // Write back only if changed
758     if (stringIn != editField.value)
759       editField.value = stringIn;
760   }
761 }
762
763
764 function ConvertRGBColorIntoHEXColor(color)
765 {
766   if ( /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/.test(color) ) {
767     var r = Number(RegExp.$1).toString(16);
768     if (r.length == 1) r = "0"+r;
769     var g = Number(RegExp.$2).toString(16);
770     if (g.length == 1) g = "0"+g;
771     var b = Number(RegExp.$3).toString(16);
772     if (b.length == 1) b = "0"+b;
773     return "#"+r+g+b;
774   }
775   else
776   {
777     return color;
778   }
779 }