sdk: const correctness
[sdk] / ecere / src / gfx / Color.ec
1 namespace gfx;
2
3 import "ListBox"
4 import "DropBox"
5 import "ColorPicker"
6
7 public struct ColorRGB { float r, g, b; };
8 public struct ColorRGBAf
9 {
10    float r, g, b, a;
11
12    property ColorAlpha
13    {
14       set { this = ColorRGBAf { value.color.r/255.0f, value.color.g/255.0f, value.color.b/255.0f, value.a/255.0f }; }
15       get { return ColorAlpha { (byte)(a * 255), Color { (byte)(r * 255), (byte)(g * 255), (byte)(b * 255) } }; }
16    }
17    property Color
18    {
19       set { this = ColorRGBAf { value.r/255.0f, value.g/255.0f, value.b/255.0f, 1.0f }; }
20       get { return Color { (byte)(r * 255), (byte)(g * 255), (byte)(b * 255) }; }
21    }
22 };
23
24 public class Color : uint
25 {
26 public:
27    byte r:8:16, g:8:8, b:8:0;
28    property ColorRGB
29    {
30       get { value = ColorRGB { r/255.0f, g/255.0f, b/255.0f }; }
31       set { return Color { (byte)(value.r*255), (byte)(value.g*255), (byte)(value.b*255) }; }
32    }
33
34    bool OnSaveEdit(DropBox dropBox, void * object)
35    {
36       return dropBox.Save();
37    }
38
39    Window OnEdit(Window dataBox, Window master, int x, int y, int w, int h, Window control)
40    {
41       const char * string = "";
42       ColorDropBox colorDropBox
43       {
44          dataBox, master = master, editText = true, //position = Point { x + 24, y }, /*clientSize.h = */size.h = h, size.w = w - 24,
45          anchor = { left = 24, top = 0, right = 0, bottom = 0 },
46          color = this, control = control
47       };
48       colorDropBox.Create();
49
50       //if(this)
51       {
52          char tempString[MAX_F_STRING];
53          const char * result;
54          bool needClass = false;
55          tempString[0] = 0;
56          result = OnGetString(tempString, null, &needClass);
57          if(result) string = result;
58       }
59       colorDropBox.contents = string;
60       // This is to highlight text on DataBox::Refresh
61       colorDropBox.editBox.SelectAll();
62       return colorDropBox;
63    }
64
65    const char * OnGetString(char * stringOutput, void * fieldData, bool * needClass)
66    {
67       const char * string;
68       if((string = ((DefinedColor)this).class::OnGetString(stringOutput, null, needClass)) ||
69          (string = ((SystemColor)this).class::OnGetString(stringOutput, null, needClass)))
70       {
71          if(needClass) *needClass = false;
72          return string;
73       }
74       else
75       {
76          char tempString[256];
77          const char * colorValue;
78          bool subNeedClass;
79          int value;
80
81          tempString[0] = '\0';
82          value = r;
83          colorValue = value.OnGetString(tempString, null, &subNeedClass);
84          strcpy(stringOutput, "r = "); strcat(stringOutput, colorValue);
85
86          // Weird bug in VS
87          memset(tempString, 0, 256);
88          tempString[0] = '\0';
89
90          value = g;
91          colorValue = value.OnGetString(tempString, null, &subNeedClass);
92          strcat(stringOutput, ", g = "); strcat(stringOutput, colorValue);
93
94          // Weird bug in VS
95          memset(tempString, 0, 256);
96          tempString[0] = '\0';
97
98          value = b;
99          colorValue = value.OnGetString(tempString, null, &subNeedClass);
100          strcat(stringOutput, ", b = "); strcat(stringOutput, colorValue);
101          return stringOutput;
102       }
103    }
104
105    bool OnGetDataFromString(const char * string)
106    {
107       if(!atoi(string) && (((DefinedColor)this).class::OnGetDataFromString(string) ||
108          ((SystemColor)this).class::OnGetDataFromString(string)))
109          return true;
110       else
111          return class::OnGetDataFromString(string);
112    }
113
114    void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
115    {
116       char tempString[1024] = "";
117       bool needClass = false;
118       // TODO: This isn't an ideal way of obtaining the clipped height, will fail on hidden areas
119       // This doesn't seem to help anymore?
120       // - Makes SavingDataBox draw at 2 different spots depending if active or not.
121       // - Color property in IDE is fine as well
122       // - How is it on Linux?
123       int yOffset = 0;//(1+surface.box.bottom - surface.box.top - 17)/2;
124       const char * string = OnGetString(tempString, null, &needClass);
125       surface.WriteTextDots(alignment, x + 24, y + 1, width - 24, string, strlen(string));
126
127       // Erase background?
128       y += yOffset-1;
129       surface.SetBackground(white);
130       surface.Area(x - 4, y, x + 20, y + 15);
131
132       surface.SetBackground(this);
133       surface.Area(x, y + 2, x+17, y+13);
134       surface.SetForeground(black);
135       surface.Rectangle(x-1, y + 1, x + 18, y + 14);
136    }
137 }
138
139 public struct ColorHSV
140 {
141    Degrees h;
142    float s,v;
143
144    property ColorRGB
145    {
146       set
147       {
148          float r = value.r, g = value.g, b = value.b;
149          float minV, maxV, diff,dr,dg,db;
150
151          float h, s, v;
152
153          minV = Min(r, g);
154          minV = Min(minV, b);
155
156          maxV = Max(r, g);
157          maxV = Max(maxV, b);
158
159          diff = maxV - minV;
160          v = maxV;
161          if(diff)
162          {
163             s = diff/maxV;
164             dr = (maxV - r)/diff;
165             dg = (maxV - g)/diff;
166             db = (maxV - b)/diff;
167
168             /*
169                 if R=V then -- between yellow and magenta [degrees]
170                   H=60.0*(G-B)/Delta
171                 else if G=V then -- between cyan and yellow
172                     H=120.0+60.0*(B-R)/Delta
173                 else -- between magenta and cyan
174                     H=240.0+60.0*(R-G)/Delta
175             */
176             if(r == maxV)
177                h = db - dg;
178             else if(g == maxV)
179                h = 2 + dr - db;
180             else if(b == maxV)
181                h = 4 + dg - dr;
182             if(h < 0)
183                h += 6;
184          }
185          else
186          {
187             h = 0;
188             s = 0;
189          }
190          this.h = h * Degrees { 60 };
191          this.s = s * 100;
192          this.v = v * 100;
193       }
194
195       get
196       {
197          float deg = (float)(this.h / 60);
198          float h = (deg == 6) ? 0 : deg, s = this.s / 100, v = this.v / 100;
199          int i = (int) h;
200          float f = h - i;
201          float p = v*(1-s);
202          float q = v*(1-(s*f));
203          float t = v*(1-s*(1-f));
204          float r,g,b;
205          switch(i)
206          {
207             case 0: r = v; g = t; b = p; break;
208             case 1: r = q; g = v; b = p; break;
209             case 2: r = p; g = v; b = t; break;
210             case 3: r = p; g = q; b = v; break;
211             case 4: r = t; g = p; b = v; break;
212             case 5: r = v; g = p; b = q; break;
213          }
214          // TODO: Figure out where this is needed
215          r = Max(Min(r, 1),0);
216          g = Max(Min(g, 1),0);
217          b = Max(Min(b, 1),0);
218
219          value.r = r;
220          value.g = g;
221          value.b = b;
222       }
223    }
224 };
225
226 public struct ColorLab
227 {
228    float l,a,b;
229
230    property ColorRGB
231    {
232       set
233       {
234          float r = value.r, g = value.g, b = value.b;
235          float y2;
236
237          r = (float)pow((r + 0.055)/1.055, 2.4);
238          g = (float)pow((g + 0.055)/1.055, 2.4);
239          b = (float)pow((b + 0.055)/1.055, 2.4);
240
241          {
242             float x = r * 0.412453f + g * 0.357580f + b * 0.180423f;
243             float y = r * 0.212671f + g * 0.715160f + b * 0.072169f;
244             float z = r * 0.019334f + g * 0.119193f + b * 0.950227f;
245
246             x /= 0.950456f;
247             y /= 1;
248             z /= 1.088754f;
249
250             x  = (x > 0.008856f) ? (float)pow(x, 1.0f/3) : (7.787f * x + 16/116.0f);
251             y2 = (y > 0.008856f) ? (float)pow(y, 1.0f/3) : (7.787f * y + 16/116.0f);
252             z  = (z > 0.008856f) ? (float)pow(z, 1.0f/3) : (7.787f * z + 16/116.0f);
253
254             if(y > 0.008856)
255                l = 116 * y2 - 16;
256             else
257                l = 903.3f * y;
258             this.a = 500 * (x - y2);
259             this.b = 200 * (y2 - z);
260          }
261       }
262
263       get
264       {
265          float x,y,z,r,g,b, P;
266
267          P = (l + 16)/116;
268
269          if(l > 903.3f * 0.008856f)
270          {
271             y = (l + 16) / 116;
272             y = y*y*y;
273          }
274          else
275             y = l / 903.3f;
276
277          if(y > 0.008856f)
278             P = (l + 16) / 116;
279          else
280             P = (903.3f * y + 16) / 116;
281
282
283          x = a / 500 + P;
284          if(x > 0.206893f)
285             x = x*x*x;
286          else
287             x = (116 * x - 16) / 903.3f;
288
289          z = P - this.b / 200;
290          if(z > 0.206893f)
291             z = z*z*z;
292          else
293             z = (116 * z - 16) / 903.3f;
294
295
296          x *= 0.950456f;
297          y *= 1;
298          z *= 1.088754f;
299
300          r = x * 3.240479f + y * -1.537150f + z *-0.498535f;
301          g = x *-0.969256f + y *  1.875992f + z * 0.041556f;
302          b = x * 0.055648f + y * -0.204043f + z * 1.057311f;
303
304          r = (r > 0.00304f) ? (1.055f * (float)pow(r, 1/2.4) - 0.055f) : (12.92f * r);
305          g = (g > 0.00304f) ? (1.055f * (float)pow(g, 1/2.4) - 0.055f) : (12.92f * g);
306          b = (b > 0.00304f) ? (1.055f * (float)pow(b, 1/2.4) - 0.055f) : (12.92f * b);
307
308          // TODO: Figure out where this is needed
309          r = Max(Min(r, 1),0);
310          g = Max(Min(g, 1),0);
311          b = Max(Min(b, 1),0);
312
313          value.r = r;
314          value.g = g;
315          value.b = b;
316       }
317    }
318 };
319
320 public struct ColorCMYK
321 {
322    float c,m,y,k;
323    property ColorRGB
324    {
325       set
326       {
327          float c = 1 - value.r;
328          float m = 1 - value.g;
329          float y = 1 - value.b;
330          float k = Min(Min(c,m), y);
331          if(k == 1)
332             this.c = this.m = this.y = 0;
333          else
334          {
335             this.c = (c-k)/(1-k) * 100;
336             this.m = (m-k)/(1-k) * 100;
337             this.y = (y-k)/(1-k) * 100;
338          }
339          this.k = k * 100;
340       }
341
342       get
343       {
344          float k = this.k/100;
345          value.r = 1 - ((c / 100) * (1-k) + k);
346          value.g = 1 - ((m / 100) * (1-k) + k);
347          value.b = 1 - ((y / 100) * (1-k) + k);
348
349          // TODO: Figure out where this is needed
350          value.r = Max(Min(value.r, 1),0);
351          value.g = Max(Min(value.g, 1),0);
352          value.b = Max(Min(value.b, 1),0);
353       }
354    }
355 };
356
357 public class Color565 : uint16
358 {
359 public:
360    byte r:5:11;
361    byte g:6:5;
362    byte b:5:0;
363    property Color
364    {
365       set { return Color565 { value.r >> 3, value.g >> 2, value.b >> 3 }; }
366       get { return Color    { r << 3, g << 2, b << 3 }; }
367    }
368 }
369
370 public class Color555 : uint16
371 {
372 public:
373    byte r:5:10;
374    byte g:5:5;
375    byte b:5:0;
376    property Color
377    {
378       set { return Color555 { value.r >> 3, value.g >> 3, value.b >> 3 }; }
379       get { return Color    { r << 3, g << 3, b << 3 }; }
380    }
381 }
382
383 public class Color444 : uint16
384 {
385 public:
386    byte r:4:8;
387    byte g:4:4;
388    byte b:4:0;
389    property Color
390    {
391       set { return Color444 { value.r >> 4, value.g >> 4, value.b >> 4 }; }
392       get { return Color    { r << 4, g << 4, b << 4 }; }
393    }
394 }
395
396 public class ColorAlpha
397 {
398 public:
399    byte a:8:24;
400    Color color:24:0;
401
402    property Color
403    {
404       set { return ColorAlpha { 255, value }; }
405       get { return color; }
406    }
407    /*property ColorRGBA
408    {
409       set { return ColorAlpha { value.a, Color { value.r, value.g, value.b } }; }
410       get { return ColorRGBA { color.r, color.g, color.b, a }; }
411    }*/
412 }
413
414 public class ColorRGBA
415 {
416 public:
417    byte r:8;
418    byte g:8;
419    byte b:8;
420    byte a:8;
421    property ColorAlpha
422    {
423       set { return ColorRGBA { value.color.r, value.color.g, value.color.b, value.a }; }
424       get { return ColorAlpha { a, Color { r, g, b } }; }
425    }
426    property Color
427    {
428       set { return ColorRGBA { value.r, value.g, value.b, 255 }; }
429       get { return Color { r, g, b }; }
430    }
431 }
432
433 public enum DefinedColor : Color
434 {
435    black               = Color {   0,   0,   0 },
436    dimGray             = Color { 105, 105, 105 },
437    gray                = Color { 128, 128, 128 },
438    darkGray            = Color { 169, 169, 165 },
439    silver              = Color { 192, 192, 192 },
440    lightGray           = Color { 211, 211, 211 },
441    gainsboro           = Color { 220, 220, 220 },
442    whiteSmoke          = Color { 245, 245, 245 },
443    white               = Color { 255, 255, 255 },
444    rosyBrown           = Color { 188, 143, 143 },
445    indianRed           = Color { 205,  92,  92 },
446    brown               = Color { 165,  42,  42 },
447    fireBrick           = Color { 178,  34,  34 },
448    lightCoral          = Color { 240, 128, 128 },
449    maroon              = Color { 128,   0,   0 },
450    darkRed             = Color { 139,   0,   0 },
451    red                 = Color { 255,   0,   0 },
452    snow                = Color { 255, 250, 250 },
453    mistyRose           = Color { 255, 228, 225 },
454    salmon              = Color { 250, 128, 114 },
455    tomato              = Color { 255,  99,  71 },
456    darkSalmon          = Color { 233, 150, 122 },
457    coral               = Color { 255, 127,  80 },
458    orangeRed           = Color { 255,  69,   0 },
459    lightSalmon         = Color { 255, 160, 122 },
460    sienna              = Color { 160,  82,  45 },
461    seaShell            = Color { 255, 245, 238 },
462    chocolate           = Color { 210, 105,  30 },
463    saddleBrown         = Color { 139,  69,  19 },
464    sandyBrown          = Color { 244, 164,  96 },
465    peachPuff           = Color { 255, 218, 185 },
466    peru                = Color { 205, 133,  63 },
467    linen               = Color { 250, 240, 230 },
468    bisque              = Color { 255, 228, 196 },
469    darkOrange          = Color { 255, 140,   0 },
470    burlyWood           = Color { 222, 184, 135 },
471    tan                 = Color { 210, 180, 140 },
472    antiqueWhite        = Color { 250, 235, 215 },
473    navajoWhite         = Color { 255, 222, 173 },
474    blanchedAlmond      = Color { 255, 235, 205 },
475    papayaWhip          = Color { 255, 239, 213 },
476    mocassin            = Color { 255, 228, 181 },
477    orange              = Color { 255, 165,   0 },
478    wheat               = Color { 245, 222, 179 },
479    oldLace             = Color { 253, 245, 230 },
480    floralWhite         = Color { 255, 250, 240 },
481    darkGoldenrod       = Color { 184, 134,  11 },
482    goldenrod           = Color { 218, 165,  32 },
483    cornsilk            = Color { 255, 248, 220 },
484    gold                = Color { 255, 215,   0 },
485    khaki               = Color { 240, 230, 140 },
486    lemonChiffon        = Color { 255, 250, 205 },
487    paleGoldenrod       = Color { 238, 232, 170 },
488    darkKhaki           = Color { 189, 183, 107 },
489    beige               = Color { 245, 245, 220 },
490    lightGoldenRodYellow= Color { 250, 250, 210 },
491    olive               = Color { 128, 128,   0 },
492    yellow              = Color { 255, 255,   0 },
493    lightYellow         = Color { 255, 255, 224 },
494    ivory               = Color { 255, 255, 240 },
495    oliveDrab           = Color { 107, 142,  35 },
496    yellowGreen         = Color { 154, 205,  50 },
497    darkOliveGreen      = Color {  85, 107,  47 },
498    greenYellow         = Color { 173, 255,  47 },
499    chartreuse          = Color { 127, 255,   0 },
500    lawnGreen           = Color { 124, 252,   0 },
501    darkSeaGreen        = Color { 143, 188, 139 },
502    forestGreen         = Color {  34, 139,  34 },
503    limeGreen           = Color {  50, 205,  50 },
504    lightGreen          = Color { 144, 238, 144 },
505    paleGreen           = Color { 152, 251, 152 },
506    darkGreen           = Color {   0, 100,   0 },
507    green               = Color {   0, 128,   0 },
508    lime                = Color {   0, 255,   0 },
509    honeyDew            = Color { 240, 255, 240 },
510    seaGreen            = Color {  46, 139,  87 },
511    mediumSeaGreen      = Color {  60, 179, 113 },
512    springGreen         = Color {   0, 255, 127 },
513    mintCream           = Color { 245, 255, 250 },
514    mediumSpringGreen   = Color {   0, 250, 154 },
515    mediumAquaMarine    = Color { 102, 205, 170 },
516    aquamarine          = Color { 127, 255, 212 },
517    turquoise           = Color {  64, 224, 208 },
518    lightSeaGreen       = Color {  32, 178, 170 },
519    mediumTurquoise     = Color {  72, 209, 204 },
520    darkSlateGray       = Color {  47,  79,  79 },
521    paleTurquoise       = Color { 175, 238, 238 },
522    teal                = Color {   0, 128, 128 },
523    darkCyan            = Color {   0, 139, 139 },
524    aqua                = Color {   0, 255, 255 },
525    cyan                = Color {   0, 255, 255 },
526    lightCyan           = Color { 224, 255, 255 },
527    azure               = Color { 240, 255, 255 },
528    darkTurquoise       = Color {   0, 206, 209 },
529    cadetBlue           = Color {  95, 158, 160 },
530    powderBlue          = Color { 176, 224, 230 },
531    lightBlue           = Color { 173, 216, 230 },
532    deepSkyBlue         = Color {   0, 191, 255 },
533    skyBlue             = Color { 135, 206, 235 },
534    lightSkyBlue        = Color { 135, 206, 250 },
535    steelBlue           = Color {  70, 130, 180 },
536    aliceBlue           = Color { 240, 248, 255 },
537    dodgerBlue          = Color {  30, 144, 255 },
538    slateGray           = Color { 112, 128, 144 },
539    lightSlateGray      = Color { 119, 136, 153 },
540    lightSteelBlue      = Color { 176, 196, 222 },
541    cornflowerBlue      = Color { 100, 149, 237 },
542    royalBlue           = Color {  65, 105, 225 },
543    midnightBlue        = Color {  25,  25, 112 },
544    lavender            = Color { 230, 230, 250 },
545    navy                = Color {   0,   0, 128 },
546    darkBlue            = Color {   0,   0, 139 },
547    mediumBlue          = Color {   0,   0, 205 },
548    blue                = Color {   0,   0, 255 },
549    ghostWhite          = Color { 248, 248, 255 },
550    slateBlue           = Color { 106,  90, 205 },
551    darkSlateBlue       = Color {  72,  61, 139 },
552    mediumSlateBlue     = Color { 123, 104, 238 },
553    mediumPurple        = Color { 147, 112, 219 },
554    blueViolet          = Color { 138,  43, 226 },
555    indigo              = Color {  75,   0, 130 },
556    darkOrchid          = Color { 153,  50, 204 },
557    darkViolet          = Color { 148,   0, 211 },
558    mediumOrchid        = Color { 186,  85, 211 },
559    thistle             = Color { 216, 191, 216 },
560    plum                = Color { 221, 160, 221 },
561    violet              = Color { 238, 130, 238 },
562    purple              = Color { 128,   0, 128 },
563    darkMagenta         = Color { 139,   0, 139 },
564    magenta             = Color { 255,   0, 255 },
565    fuschia             = Color { 255,   0, 255 },
566    orchid              = Color { 218, 112, 214 },
567    mediumVioletRed     = Color { 199,  21, 133 },
568    deepPink            = Color { 255,  20, 147 },
569    hotPink             = Color { 255, 155, 180 },
570    lavenderBlush       = Color { 255, 240, 245 },
571    paleVioletRed       = Color { 219, 112, 147 },
572    crimson             = Color { 220,  20,  60 },
573    pink                = Color { 255, 192, 203 },
574    lightPink           = Color { 255, 182, 193 }
575 };
576
577 // TODO: We really should improve on this, only formColor has been used so far
578 public enum SystemColor : Color
579 {
580    // activeBorder         = Color { 212, 208, 200 },
581    formColor            = Color { 229, 234, 245 },
582    activeBorder         = Color { 229, 234, 245 },
583    control              = Color { 212, 208, 200 },
584    controlLight         = Color { 212, 208, 200 },
585    inactiveBorder       = Color { 212, 208, 200 },
586    inactiveCaptionText  = Color { 212, 208, 200 },
587    menu                 = Color { 212, 208, 200 },
588    scrollBar            = Color { 212, 208, 200 }
589 };
590
591 private class ColorValue : Color
592 {
593    void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
594    {
595       // surface.WriteTextDots(alignment, x + 24, y + 1, width - 24, string, strlen(string));
596       surface.SetBackground(this);
597       surface.Area(x, y + 4, x+19, y+11);
598
599       surface.SetForeground(black);
600       surface.Rectangle(x-1, y + 3, x + 20, y + 12);
601    }
602 }
603
604 // TODO: ColorSelected was declared as non static
605 /*static */class ColorDropBox : DropBox
606 {
607    ListBox listBox;
608    Color color;
609    Window control;
610    borderStyle = 0;
611
612    DataField sysColorField { dataType = "ColorValue", width = 20 };
613    DataField sysColorName { };
614    DataField definedColorField { dataType = "ColorValue", width = 20 };
615    DataField definedColorName { };
616
617    ColorDropBox()
618    {
619       system.AddField(sysColorField);
620       system.AddField(sysColorName);
621       defined.AddField(definedColorField);
622       defined.AddField(definedColorName);
623    }
624
625    Window pullDown
626    {
627       master = this, interim = true, autoCreate = false, minSize = { 204, 222 },
628       background = formColor, borderStyle = contour|bevel;
629
630       bool OnKeyDown(Key key, unichar ch)
631       {
632          ColorDropBox colorDropBox = (ColorDropBox)master;
633          if((SmartKey)key == enter)
634          {
635             if(!colorDropBox.ColorSelected(colorDropBox.listBox, colorDropBox.listBox.currentRow, 0))
636                return false;
637          }
638          if(key == escape)
639          {
640             return colorDropBox.OnKeyDown(key, ch);
641          }
642          return true;
643       }
644    };
645
646    bool ColorSelected(ListBox listBox, DataRow row, Modifiers mods)
647    {
648       Color color = row ? row.GetData(null) : black;
649
650       incref this;
651       ((DataBox)parent).SetData(&color, false);
652
653       this.color = color;
654
655       {
656          char tempString[1024] = "";
657          bool needClass = false;
658          const char * string = color.OnGetString(tempString, null, &needClass);
659          contents = string;
660       }
661       OnKeyDown(escape, 0);
662       Deactivate();
663       delete this;
664
665       //OnKeyDown(escape, 0);
666       //master.OnKeyDown(escape, 0);
667
668       return true;
669    }
670
671    ListBox defined
672    {
673       master = this, parent = pullDown,
674       freeSelect = true,
675       hasVertScroll = true,
676       anchor = Anchor { left = 0, top = 16, right = 0, bottom = 0 },
677       NotifySelect = ColorSelected
678    };
679    ListBox system
680    {
681       master = this, parent = pullDown,
682       freeSelect = true,
683       hasVertScroll = true,
684       anchor = Anchor { left = 0, top = 16, right = 0, bottom = 0 },
685       NotifySelect = ColorSelected
686    };
687
688    ColorPicker dialog
689    {
690       text = $"Select Color",
691       master = this,
692       autoCreate = false
693    };
694
695    Button button
696    {
697       master = this, parent = pullDown,
698       text = $"Custom",
699       size.w = 68,
700       position = Point { 0, 0 },
701       bevelOver = true,
702       inactive = true,
703       hotKey = altC;
704       // isRadio = true, bitmap = null;
705
706       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
707       {
708          dialog.color = color;
709
710          OnKeyDown(escape, 0);
711          Deactivate();
712
713          //OnKeyDown(Escape, 0);
714          //master.OnKeyDown(Escape, 0);
715
716          incref this;
717          if(dialog.Modal() == ok)
718          {
719             color = dialog.color;
720             ((DataBox)master).SetData(&color, false);
721             {
722                char tempString[1024] = "";
723                bool needClass = false;
724                const char * string = color.OnGetString(tempString, null, &needClass);
725                contents = string;
726             }
727          }
728          delete this;
729          return true;
730       }
731    };
732    Button definedButton
733    {
734       master = this, parent = pullDown,
735       text = $"Defined",
736       hotKey = altD,
737       size.w = 68,
738       position = Point { 68, 0 },
739       isRadio = true,
740       bevelOver = true,
741       inactive = true,
742       bitmap = null;
743
744       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
745       {
746          system.visible = false;
747          defined.visible = true;
748          listBox = defined;
749          return true;
750       }
751    };
752    Button systemButton
753    {
754       master = this, parent = pullDown,
755       text = $"System",
756       hotKey = altS,
757       size.w = 68,
758       position = Point { 136, 0 },
759       isRadio = true,
760       bevelOver = true,
761       inactive = true,
762       bitmap = null;
763
764       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
765       {
766          defined.visible = false;
767          system.visible = true;
768          listBox = system;
769          return true;
770       }
771    };
772
773    Window OnDropDown()
774    {
775       char tempString[256];
776       pullDown.size.w = size.w + 24;
777
778       pullDown.Create();
779
780       {
781          NamedLink item;
782          bool found = false;
783          DataRow currentRow = null;
784
785          defined.Clear();
786          for(item = ((EnumClassData)class(DefinedColor).data).values.first; item; item = item.next)
787          {
788             DataRow row = defined.AddRow();
789             row.SetData(definedColorField, (Color)(uint)item.data);
790             strcpy(tempString, item.name);
791             tempString[0] = (char)toupper(tempString[0]);
792             row.SetData(definedColorName, tempString);
793             // TOCHECK: A uint cast is necessary here, the void * was causing ColorRGB conversion to be called
794             if(!found && (Color)(uint)item.data == color)
795             {
796                currentRow = row;
797                found = true;
798             }
799          }
800          if(currentRow)
801             defined.currentRow = currentRow;
802       }
803       {
804          bool found = false;
805          NamedLink item;
806          DataRow currentRow = null;
807
808          system.Clear();
809          for(item = ((EnumClassData)class(SystemColor).data).values.first; item; item = item.next)
810          {
811             DataRow row = system.AddRow();
812             row.SetData(sysColorField, (Color)(uint)item.data);
813             strcpy(tempString, item.name);
814             tempString[0] = (char)toupper(tempString[0]);
815             row.SetData(sysColorName, tempString);
816
817             // TOCHECK: A uint cast is necessary here, the void * was causing ColorRGB conversion to be called
818             if(!found && (Color)(uint)item.data == color)
819             {
820                currentRow = row;
821                found = true;
822             }
823          }
824          if(currentRow)
825             system.currentRow = currentRow;
826
827          if(found)
828          {
829             defined.visible = false;
830             system.visible = true;
831             systemButton.checked = true;
832             listBox = system;
833          }
834          else
835          {
836             system.visible = false;
837             defined.visible = true;
838             definedButton.checked = true;
839             listBox = defined;
840          }
841       }
842       return pullDown;
843    }
844
845    void OnCloseDropDown(Window pullDown)
846    {
847       // TOFIX: Patch for update bug
848       master.Update(null);
849       pullDown.Destroy(0);
850    }
851
852    bool DataBox::NotifyTextEntry(ColorDropBox colorDropBox, const char * string, bool save)
853    {
854       if(save)
855       {
856          Color color = 0;
857          if(color.OnGetDataFromString(string))
858             SetData(&color, false);
859       }
860       else
861       {
862          char tempString[1024] = "";
863          bool needClass = false;
864          const char * string = colorDropBox.color.OnGetString(tempString, null, &needClass);
865          colorDropBox.contents = string;
866       }
867       return true;
868    }
869 }