7 public struct ColorRGB { float r, g, b; };
8 public struct ColorRGBAf
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) } }; }
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) }; }
24 public class Color : uint
27 byte r:8:16, g:8:8, b:8:0;
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) }; }
34 bool OnSaveEdit(DropBox dropBox, void * object)
36 return dropBox.Save();
39 Window OnEdit(Window dataBox, Window master, int x, int y, int w, int h, Window control)
41 const char * string = "";
42 ColorDropBox colorDropBox
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
48 colorDropBox.Create();
52 char tempString[MAX_F_STRING];
54 bool needClass = false;
56 result = OnGetString(tempString, null, &needClass);
57 if(result) string = result;
59 colorDropBox.contents = string;
60 // This is to highlight text on DataBox::Refresh
61 colorDropBox.editBox.SelectAll();
65 const char * OnGetString(char * stringOutput, void * fieldData, bool * needClass)
68 if((string = ((DefinedColor)this).class::OnGetString(stringOutput, null, needClass)) ||
69 (string = ((SystemColor)this).class::OnGetString(stringOutput, null, needClass)))
71 if(needClass) *needClass = false;
77 const char * colorValue;
83 colorValue = value.OnGetString(tempString, null, &subNeedClass);
84 strcpy(stringOutput, "r = "); strcat(stringOutput, colorValue);
87 memset(tempString, 0, 256);
91 colorValue = value.OnGetString(tempString, null, &subNeedClass);
92 strcat(stringOutput, ", g = "); strcat(stringOutput, colorValue);
95 memset(tempString, 0, 256);
99 colorValue = value.OnGetString(tempString, null, &subNeedClass);
100 strcat(stringOutput, ", b = "); strcat(stringOutput, colorValue);
105 bool OnGetDataFromString(const char * string)
107 if(!atoi(string) && (((DefinedColor)this).class::OnGetDataFromString(string) ||
108 ((SystemColor)this).class::OnGetDataFromString(string)))
111 return class::OnGetDataFromString(string);
114 void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
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));
129 surface.SetBackground(white);
130 surface.Area(x - 4, y, x + 20, y + 15);
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);
139 public struct ColorHSV
148 float r = value.r, g = value.g, b = value.b;
149 float minV, maxV, diff,dr,dg,db;
164 dr = (maxV - r)/diff;
165 dg = (maxV - g)/diff;
166 db = (maxV - b)/diff;
169 if R=V then -- between yellow and magenta [degrees]
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
190 this.h = h * Degrees { 60 };
197 float deg = (float)(this.h / 60);
198 float h = (deg == 6) ? 0 : deg, s = this.s / 100, v = this.v / 100;
202 float q = v*(1-(s*f));
203 float t = v*(1-s*(1-f));
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;
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);
226 public struct ColorLab
234 float r = value.r, g = value.g, b = value.b;
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);
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;
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);
258 this.a = 500 * (x - y2);
259 this.b = 200 * (y2 - z);
265 float x,y,z,r,g,b, P;
269 if(l > 903.3f * 0.008856f)
280 P = (903.3f * y + 16) / 116;
287 x = (116 * x - 16) / 903.3f;
289 z = P - this.b / 200;
293 z = (116 * z - 16) / 903.3f;
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;
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);
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);
320 public struct ColorCMYK
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);
332 this.c = this.m = this.y = 0;
335 this.c = (c-k)/(1-k) * 100;
336 this.m = (m-k)/(1-k) * 100;
337 this.y = (y-k)/(1-k) * 100;
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);
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);
357 public class Color565 : uint16
365 set { return Color565 { value.r >> 3, value.g >> 2, value.b >> 3 }; }
366 get { return Color { r << 3, g << 2, b << 3 }; }
370 public class Color555 : uint16
378 set { return Color555 { value.r >> 3, value.g >> 3, value.b >> 3 }; }
379 get { return Color { r << 3, g << 3, b << 3 }; }
383 public class Color444 : uint16
391 set { return Color444 { value.r >> 4, value.g >> 4, value.b >> 4 }; }
392 get { return Color { r << 4, g << 4, b << 4 }; }
396 public class ColorAlpha
404 set { return ColorAlpha { 255, value }; }
405 get { return color; }
409 set { return ColorAlpha { value.a, Color { value.r, value.g, value.b } }; }
410 get { return ColorRGBA { color.r, color.g, color.b, a }; }
414 public class ColorRGBA
423 set { return ColorRGBA { value.color.r, value.color.g, value.color.b, value.a }; }
424 get { return ColorAlpha { a, Color { r, g, b } }; }
428 set { return ColorRGBA { value.r, value.g, value.b, 255 }; }
429 get { return Color { r, g, b }; }
433 public enum DefinedColor : Color
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 }
577 // TODO: We really should improve on this, only formColor has been used so far
578 public enum SystemColor : Color
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 }
591 private class ColorValue : Color
593 void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
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);
599 surface.SetForeground(black);
600 surface.Rectangle(x-1, y + 3, x + 20, y + 12);
604 // TODO: ColorSelected was declared as non static
605 /*static */class ColorDropBox : DropBox
612 DataField sysColorField { dataType = "ColorValue", width = 20 };
613 DataField sysColorName { };
614 DataField definedColorField { dataType = "ColorValue", width = 20 };
615 DataField definedColorName { };
619 system.AddField(sysColorField);
620 system.AddField(sysColorName);
621 defined.AddField(definedColorField);
622 defined.AddField(definedColorName);
627 master = this, interim = true, autoCreate = false, minSize = { 204, 222 },
628 background = formColor, borderStyle = contour|bevel;
630 bool OnKeyDown(Key key, unichar ch)
632 ColorDropBox colorDropBox = (ColorDropBox)master;
633 if((SmartKey)key == enter)
635 if(!colorDropBox.ColorSelected(colorDropBox.listBox, colorDropBox.listBox.currentRow, 0))
640 return colorDropBox.OnKeyDown(key, ch);
646 bool ColorSelected(ListBox listBox, DataRow row, Modifiers mods)
648 Color color = row ? row.GetData(null) : black;
651 ((DataBox)parent).SetData(&color, false);
656 char tempString[1024] = "";
657 bool needClass = false;
658 const char * string = color.OnGetString(tempString, null, &needClass);
661 OnKeyDown(escape, 0);
665 //OnKeyDown(escape, 0);
666 //master.OnKeyDown(escape, 0);
673 master = this, parent = pullDown,
675 hasVertScroll = true,
676 anchor = Anchor { left = 0, top = 16, right = 0, bottom = 0 },
677 NotifySelect = ColorSelected
681 master = this, parent = pullDown,
683 hasVertScroll = true,
684 anchor = Anchor { left = 0, top = 16, right = 0, bottom = 0 },
685 NotifySelect = ColorSelected
690 text = $"Select Color",
697 master = this, parent = pullDown,
700 position = Point { 0, 0 },
704 // isRadio = true, bitmap = null;
706 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
708 dialog.color = color;
710 OnKeyDown(escape, 0);
713 //OnKeyDown(Escape, 0);
714 //master.OnKeyDown(Escape, 0);
717 if(dialog.Modal() == ok)
719 color = dialog.color;
720 ((DataBox)master).SetData(&color, false);
722 char tempString[1024] = "";
723 bool needClass = false;
724 const char * string = color.OnGetString(tempString, null, &needClass);
734 master = this, parent = pullDown,
738 position = Point { 68, 0 },
744 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
746 system.visible = false;
747 defined.visible = true;
754 master = this, parent = pullDown,
758 position = Point { 136, 0 },
764 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
766 defined.visible = false;
767 system.visible = true;
775 char tempString[256];
776 pullDown.size.w = size.w + 24;
783 DataRow currentRow = null;
786 for(item = ((EnumClassData)class(DefinedColor).data).values.first; item; item = item.next)
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)
801 defined.currentRow = currentRow;
806 DataRow currentRow = null;
809 for(item = ((EnumClassData)class(SystemColor).data).values.first; item; item = item.next)
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);
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)
825 system.currentRow = currentRow;
829 defined.visible = false;
830 system.visible = true;
831 systemButton.checked = true;
836 system.visible = false;
837 defined.visible = true;
838 definedButton.checked = true;
845 void OnCloseDropDown(Window pullDown)
847 // TOFIX: Patch for update bug
852 bool DataBox::NotifyTextEntry(ColorDropBox colorDropBox, const char * string, bool save)
857 if(color.OnGetDataFromString(string))
858 SetData(&color, false);
862 char tempString[1024] = "";
863 bool needClass = false;
864 const char * string = colorDropBox.color.OnGetString(tempString, null, &needClass);
865 colorDropBox.contents = string;