3fb2421cf7fada1e4ce9c72c92a0f837fe1c446d
[sdk] / extras / gui / skins / SimSkin.ec
1 #if defined(WIN32)
2 #define WIN32_LEAN_AND_MEAN
3 #define Method _Method
4 #include <windows.h>
5 #undef Method
6 #endif
7
8 public import "ecere"
9
10 //define test = Color { 5, 4, 2 };
11 define skinMainColor = Color { 0, 71, 128 };
12 define skinOppositeColor = blue; //Color { 252, 114, 22 };
13 //define skinBackground = Color { 40, 40, 40 };
14 //define skinBackground = Color { 185, 201, 215 };
15 //define skinBackground = Color { 229, 236, 241 };
16 define skinBackground = Color { 255, 255, 255 };
17
18 #define BORDER       2
19 #define TOP          2
20 #define BOTTOM       2
21 #define CORNER       (BORDER * 2)
22 #define CAPTION      14
23 #define DEAD_BORDER  2
24 #define MIN_WIDTH    60
25 #define MIN_HEIGHT   3
26 #define BUTTON_OFFSET   0
27 #define NAME_OFFSET   2
28 #define NAME_OFFSETX  4
29
30 #define SB_WIDTH  16
31 #define SB_HEIGHT 16
32
33 #define MENU_HEIGHT     25
34 #define STATUS_HEIGHT   18
35
36 define skinForeground = skinMainColor;
37 define skinTextForeground = black;
38 define evenRowBackground = red; //Color { 80, 70, 60 };
39
40 define skinTextColor = skinMainColor;
41 define skinInactiveTextColor = Color { skinMainColor.r - 20, skinMainColor.g - 20, skinMainColor.b - 20 };
42
43 ColorKey skinGradient[3] =
44 {
45    { Color { 40,40,40 }, 0.0f },
46    { darkGray, 0.5f },
47    { Color { 40,40,40 }, 1.0f },
48 };
49
50 class SimSkin_Window : Window
51 {
52    void ShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving)
53    {
54       bool isNormal = (state == normal || state == maximized);
55       int top = 0, border = 0, bottom = 0;
56
57       if(nativeDecorations && rootWindow == this) return;
58
59       if(state == minimized)
60          top = border = bottom = DEAD_BORDER;
61       else if(((BorderBits)borderStyle).sizable)
62       {
63          top = isNormal ? TOP : 0;
64          border = isNormal ? BORDER : 0;
65          bottom = BOTTOM;
66       }
67       else if(((BorderBits)borderStyle).fixed)
68       {
69          top = 2; //DEAD_BORDER;
70          border = DEAD_BORDER;
71          bottom = DEAD_BORDER;
72       }
73       else if(((BorderBits)borderStyle).contour)
74       {
75          top = 1;
76          border = 1;
77          bottom = 1;
78       }
79
80       if(((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel)
81       {
82          int deepTop = 0, deepBottom = 0, deepBorder = 0;
83          if(((BorderBits)borderStyle).contour)
84          {
85             deepBorder = border;
86             deepTop = (((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar)) ? (top + CAPTION) : top;
87             deepBottom = (((BorderBits)borderStyle).sizable && isNormal) ? bottom : border;
88          }
89
90          surface.Bevel(((BorderBits)borderStyle).bevel ? false : true, deepBorder, deepTop, 
91             size.w - deepBorder - deepBorder, size.h - deepBottom - deepTop);
92       }
93
94       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
95       {
96          /*
97          if(state != maximized || !((BorderBits)borderStyle).sizable)
98          {
99             // Frame for ES_CAPTION windows
100             surface.Bevel(false, 0, 0, size.w, size.h);
101             surface.SetForeground(activeBorder);
102             surface.Rectangle(2, 2, size.w-3, size.h-3);
103
104             // Resizeable frame is 1 pixel thicker 
105             if(((BorderBits)borderStyle).sizable && isNormal)
106                surface.Rectangle(3, 3, size.w - 4, size.h - 4);
107          }
108
109          // Caption
110          if(active)
111             surface.Gradient(gradient, sizeof(gradient) / sizeof(ColorKey), GRADIENT_SMOOTHNESS, GRADIENT_DIRECTION,
112                border, top, size.w - border - 1, top + CAPTION - 2);
113          else
114             surface.Gradient(gradientInactive, sizeof(gradientInactive) / sizeof(ColorKey), 
115             GRADIENT_SMOOTHNESS, GRADIENT_DIRECTION,
116                border, top, size.w - border - 1, top + CAPTION - 2);
117
118          surface.SetForeground(activeBorder);
119          if(state != minimized)
120             surface.HLine(border, size.w-border-1, top + CAPTION-1);
121          */
122
123          surface.SetForeground(skinBackground);
124          surface.Rectangle(0,0, size.w-1, size.h-1);
125          surface.SetForeground(active ? skinTextColor : skinInactiveTextColor);
126          surface.Rectangle(1,1, size.w-2, size.h-2);
127          surface.SetBackground(skinBackground);
128          surface.Area(2, 2, size.w-3, CAPTION + 1);
129
130          // surface.TextFont(captionFont);
131          // surface.WriteText(4,2, name, strlen(name));
132
133          surface.SetForeground((active ? skinTextColor : skinInactiveTextColor));
134          surface.TextOpacity(false);
135          surface.TextFont(captionFont);
136          if(name)
137          {
138             int buttonsSize = border +
139                ((hasMaximize || hasMinimize) ? 52 : 18);
140             surface.WriteTextDots(left, border + NAME_OFFSETX, top + NAME_OFFSET, 
141                size.w - (buttonsSize + border + 4), name, (int)strlen(name));
142          }
143       }
144       if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
145       {
146          surface.SetForeground(skinForeground /*black*/);
147          surface.Rectangle(0, 0, size.w - 1, size.h - 1);
148       }
149
150       if(state != minimized && hasHorzScroll && hasVertScroll)
151       {
152          if(sbh && sbh.visible && sbv && sbv.visible)
153          {
154             surface.SetBackground(activeBorder);
155             surface.Area(
156                clientStart.x + clientSize.w,
157                clientStart.y + clientSize.h,
158                clientStart.x + clientSize.w + SB_WIDTH - 1,
159                clientStart.y + clientSize.h + SB_HEIGHT - 1);
160          }
161       }
162    }
163
164    void GetDecorationsSize(MinMaxValue * w, MinMaxValue * h)
165    {
166       *w = *h = 0;
167
168       if(hasMenuBar && state != minimized)
169       {
170          *h += MENU_HEIGHT;
171       }
172       if(statusBar && state != minimized)
173       {
174          *h += STATUS_HEIGHT;
175       }
176
177       if(nativeDecorations && rootWindow == this)
178       {
179 #if defined(WIN32)
180          RECT rcClient, rcWindow;
181          GetClientRect(systemHandle, &rcClient);
182          GetWindowRect(systemHandle, &rcWindow);
183          *w += (rcWindow.right - rcWindow.left) - rcClient.right;
184          *h += (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
185
186          // PrintLn(_class.name, " is at l = ", rcWindow.left, ", r = ", rcWindow.right);
187 #endif
188          return;
189       }
190       if((((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel) && state != minimized)
191       {
192          *w += 4;
193          *h += 4;
194       }
195       if(((BorderBits)borderStyle).sizable && (state == normal || state == maximized))
196       {
197          *w += 2 * BORDER;
198          *h += TOP + BOTTOM;
199       }
200       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
201       {
202          *h += CAPTION;
203          if(!((BorderBits)borderStyle).sizable || state == minimized)
204          {
205             *h += 2*DEAD_BORDER;
206             *w += 2*DEAD_BORDER;
207          }
208       }
209       if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
210       {
211          *w += 2;
212          *h += 2;
213       }
214    }
215
216    bool IsMouseMoving(int x, int y, int w, int h)
217    {
218       BorderBits style = (BorderBits)borderStyle; // TOFIX: borderStyle.fixed doesn't work
219       if(nativeDecorations && rootWindow == this) return false;
220       if(style.fixed)
221       {
222          bool resizeX, resizeY, resizeEndX, resizeEndY;
223          if(!IsMouseResizing(x, y, w, h, &resizeX, &resizeY, &resizeEndX, &resizeEndY))
224             return true;
225       }
226       return false;
227    }
228
229    bool IsMouseResizing(int x, int y, int w, int h, bool *resizeX, bool *resizeY, bool *resizeEndX, bool *resizeEndY)
230    {
231       bool result = false;
232
233       *resizeX = *resizeY = *resizeEndX = *resizeEndY = false;
234       if(nativeDecorations && rootWindow == this) return false;
235
236       if(((BorderBits)borderStyle).sizable && (state == normal))
237       {
238          // TopLeft Corner
239          if(Box { 0, 0,CORNER-1, TOP-1 }.IsPointInside({x, y}))
240             result = *resizeX = *resizeY = true;
241          // TopRight Corner
242          if(Box { w-CORNER-1, 0, w-1, TOP-1 }.IsPointInside({x, y}))
243             result = *resizeEndX = *resizeY = true;
244          // BottomLeft Corner
245          if(Box { 0, h-BOTTOM-1, CORNER-1, h-1 }.IsPointInside({x, y}))
246             result = *resizeX = *resizeEndY = true;
247          // BottomRight Corner
248          if(Box { w-CORNER-1, h-BOTTOM-1, w-1, h-1 }.IsPointInside({x, y}))
249             result = *resizeEndX = *resizeEndY = true;
250          // Left Border
251          if(Box { 0,TOP, BORDER, h-BOTTOM-1 }.IsPointInside({x, y}))
252             result = *resizeX = true;
253          // Right Border
254          if(Box { w-BORDER-1, TOP, w-1, h-BOTTOM-1 }.IsPointInside({x, y}))
255             result = *resizeEndX = true;
256          // Top Border
257          if(Box { CORNER, 0, w-CORNER-1, TOP-1 }.IsPointInside({x, y}))
258             result = *resizeY = true;
259          // Bottom Border
260          if(Box { CORNER, h-BOTTOM-1, w-CORNER-1, h-1 }.IsPointInside({x, y}))
261             result = *resizeEndY = true;
262       }
263       return result;
264    }
265
266    void SetWindowMinimum(MinMaxValue * mw, MinMaxValue * mh)
267    {
268       bool isNormal = (state == normal || state == maximized);
269       if(nativeDecorations && rootWindow == this) return;
270       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
271       {
272          *mw = MIN_WIDTH;
273          *mh = MIN_HEIGHT;
274       }
275       else
276          *mw = *mh = 0;
277       /*
278       if(((BorderBits)borderStyle).sizable && isNormal)
279          *mw += 2*CORNER;
280       // GetDecorationsSize(window, mw, mh);
281       */
282
283       if(hasVertScroll)
284          *mw += SB_WIDTH;
285       if(hasHorzScroll)
286          *mh += SB_HEIGHT;
287       if(hasVertScroll && hasHorzScroll)
288       {
289          *mw += 2 * SB_WIDTH + SB_WIDTH;
290          *mh += 2 * SB_HEIGHT + SB_HEIGHT;
291          /*
292          if(((BorderBits)borderStyle).sizable && isNormal)
293             *mw -= 2*CORNER;
294          */
295       }
296    }
297
298    void SetWindowArea(int * x, int * y, MinMaxValue * w, MinMaxValue * h, MinMaxValue * cw, MinMaxValue * ch)
299    {
300       bool isNormal = (state == normal || state == maximized);
301       MinMaxValue aw = 0, ah = 0;
302
303       *x = *y = 0;
304
305       if(hasMenuBar)
306       {
307          *y += MENU_HEIGHT;
308       }
309
310       GetDecorationsSize(&aw, &ah);
311
312       if(nativeDecorations && rootWindow == this)
313       {
314 #if defined(WIN32)
315          RECT rcWindow;
316          POINT client00 = { 0, 0 };
317          ClientToScreen(systemHandle, &client00);
318          GetWindowRect(systemHandle, &rcWindow);
319          *x += client00.x - rcWindow.left;
320          *y += client00.y - rcWindow.top;
321 #endif
322       }
323       else
324       {
325          // Compute client area start
326          if(((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel)
327          {
328             *x += 2;
329             *y += 2;
330          }
331
332          if(((BorderBits)borderStyle).sizable && isNormal)
333          {
334             *x += BORDER;
335             *y += TOP;
336          }
337
338          if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
339          {
340             *y += CAPTION;
341             if(!((BorderBits)borderStyle).sizable || state == minimized)
342             {
343                *y += DEAD_BORDER;
344                *x += DEAD_BORDER;
345             }
346          }
347
348          if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
349          {
350             *x += 1;
351             *y += 1;
352          }
353       }
354
355       // Reduce client area
356       *cw = *w - aw;
357       *ch = *h - ah;
358
359       *cw = Max(*cw, 0);
360       *ch = Max(*ch, 0);
361    }
362
363    void UpdateNonClient()
364    {
365       bool isNormal = (state == normal || state == maximized);
366       int top = 0, border = 0;
367       int insideBorder;
368
369       if(!nativeDecorations || rootWindow != this)
370       {
371          if(state == minimized)
372             top = border = DEAD_BORDER;
373          else if(((BorderBits)borderStyle).sizable)
374          {
375             if(state == maximized && parent.menuBar)
376             {
377                top = 2;
378                border = 2;
379             }
380             else
381             {
382                top = isNormal ? TOP : 0;
383                border = isNormal ? BORDER : 0;
384             }
385          }
386          else if(((BorderBits)borderStyle).fixed)
387          {
388             top = 2;
389             border = 2;
390          }
391          else if(((BorderBits)borderStyle).contour)
392          {
393             top = 1;
394             border = 1;
395          }
396          insideBorder = border;
397          if(((BorderBits)borderStyle).deep)
398             insideBorder += 2;
399
400          if(menuBar)
401          {
402             if(state == minimized)
403                menuBar.visible = false;
404             else
405                menuBar.visible = true;
406             menuBar.Move(clientStart.x, clientStart.y - MENU_HEIGHT, size.w - insideBorder * 2, MENU_HEIGHT);
407          }
408          if(statusBar)
409          {
410             if(state == minimized)
411                statusBar.visible = false;
412             else
413             {
414                statusBar.visible = true;
415                statusBar.anchor = { left = clientStart.x, bottom = border };
416                statusBar.size.w = size.w - insideBorder * 2;
417             }
418          }
419       }
420       if(!nativeDecorations || rootWindow != this)
421       {
422          if(minimizeButton)
423          {
424             minimizeButton.anchor = { right = ((maximizeButton && !maximizeButton.disabled) ? 25 + 34 + 4 : 34 + 4) + border, top = top + BUTTON_OFFSET };
425             minimizeButton.size = { 20, 10 };
426             minimizeButton.foreground = skinForeground;
427             minimizeButton.background = skinBackground;
428             minimizeButton.bevel = false;
429             minimizeButton.OnRedraw = Minimize_OnRedraw;
430             minimizeButton.visible = true;
431          }
432          if(maximizeButton && !maximizeButton.disabled)
433          {
434             maximizeButton.anchor = { right = 34 + 4 + border, top = top + BUTTON_OFFSET };
435             maximizeButton.size = { 20, 10 };
436             maximizeButton.bevel = false;
437             maximizeButton.foreground = skinForeground;
438             maximizeButton.background = skinBackground;
439             maximizeButton.OnRedraw = Maximize_OnRedraw;
440             maximizeButton.visible = true;
441          }
442          if(closeButton)
443          {
444             closeButton.anchor = { right = -1 + border, top = top + BUTTON_OFFSET };
445             closeButton.size = { 34, 10 };
446             closeButton.bevel = false;
447             closeButton.foreground = skinForeground;
448             closeButton.background = skinBackground;
449             closeButton.OnRedraw = Close_OnRedraw;
450             closeButton.visible = true;
451          }
452       }
453    }
454
455    void OnApplyGraphics()
456    {
457       /*if(background)
458          background = skinBackground;
459       foreground = skinForeground;*/
460       // Find something better?
461    }
462 }
463
464 static void Button::SmallButton_OnRedraw(Surface surface)
465 {
466    surface.SetBackground(parent.active ? background : skinBackground);
467    surface.Area(0, 0, clientSize.w - 2, clientSize.w - 1);
468    surface.SetForeground(parent.active ? skinTextColor : skinInactiveTextColor);
469    surface.VLine(0, clientSize.h - 2, 0);
470    surface.VLine(0, clientSize.h - 2, clientSize.w - 1);
471    surface.HLine(1, clientSize.w - 2, clientSize.h - 1);
472 }
473
474 static void Button::Minimize_OnRedraw(Surface surface)
475 {
476    SmallButton_OnRedraw(this, surface);
477    surface.DrawLine( 5, 3, 14, 3);
478    surface.DrawLine( 5, 4, 14, 4);
479 }
480
481 static void Button::Maximize_OnRedraw(Surface surface)
482 {
483    SmallButton_OnRedraw(this, surface);
484    surface.Rectangle( 5, 2, 14, 7);
485    surface.DrawLine( 5, 3, 14, 3);
486 }
487
488 static void Button::Close_OnRedraw(Surface surface)
489 {
490    SmallButton_OnRedraw(this, surface);
491    //surface.SetForeground(black);
492    surface.DrawLine( 7+7, 2, 12+7, 7);
493    surface.DrawLine( 8+7, 2, 13+7, 7);
494    surface.DrawLine( 12+7, 2, 7+7, 7);
495    surface.DrawLine( 13+7, 2, 8+7, 7);
496 }
497
498 /*class SimSkin_StatusBar : StatusBar
499 {
500    void OnApplyGraphics()
501    {
502       background = skinBackground;
503       foreground = skinForeground;
504    }
505 }*/
506
507 /*class SimSkin_FileDialog : FileDialog
508 {
509    void OnApplyGraphics()
510    {
511       Window child;
512       background = skinBackground;
513       foreground = skinForeground;
514       for(child = firstChild; child; child = child.next)
515       {
516          if(!child.opacity)
517             child.foreground = skinForeground;
518       }
519    }
520 }*/
521
522 #define PUREVTBL(c)     ((int (**)())*(void **)((byte *)class(c).data + sizeof(void *)))
523
524 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnApplyGraphics;
525 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw;
526
527 static void Dummy()
528 {
529    Window a;
530    a.OnApplyGraphics();
531    a.OnRedraw(null);
532 }
533
534 class SimSkin_Button : Button
535 {/*
536    void OnApplyGraphics()
537    {
538       //background = skinBackground;
539       background = Color { (int)70 * 6/10, (int)130* 6/10, (int)180* 6/10 };
540       foreground = skinForeground;
541    }
542
543    void OnRedraw(Surface surface)
544    {
545       int isDefault = (int)this.isDefault;
546       ((void (*)(Window, Surface))(void *)PUREVTBL(Button)[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw])(this, surface);
547       if(bevel || (bevelOver && (buttonState == down || buttonState == over || checked)))
548       {
549          Color c = steelBlue;
550          if(buttonState == down || checked)
551          {
552             surface.SetForeground(skinMainColor);
553             surface.HLine(isDefault + 0, clientSize.w-2-isDefault, 0);
554             surface.VLine(isDefault + 1, clientSize.h-2-isDefault, 0);
555             surface.SetForeground(Color { Min((int)c.r * 16/10, 255), Min((int)c.g * 16/10, 255), Min((int)c.b * 16/10,255) });
556             surface.HLine(isDefault + 0, clientSize.w-1-isDefault, clientSize.h-1-isDefault);
557             surface.VLine(isDefault + 0, clientSize.h-2-isDefault, clientSize.w-1-isDefault);
558          }
559          else
560          {
561             surface.SetForeground(Color { Min((int)c.r * 16/10, 255), Min((int)c.g * 16/10, 255), Min((int)c.b * 16/10,255) });
562             surface.HLine(0 + isDefault, clientSize.w-2 - isDefault,  isDefault);
563             surface.VLine(1 + isDefault, clientSize.h-2 - isDefault,  isDefault);
564             
565             
566             surface.SetForeground(skinMainColor);
567             surface.HLine(1 + isDefault, clientSize.w-2 - isDefault, clientSize.h-2 - isDefault);
568             surface.VLine(1 + isDefault, clientSize.h-3 - isDefault, clientSize.w-2 - isDefault);
569             
570             if(bevel)
571             {
572                //surface.SetForeground(skinForeground);
573                surface.SetForeground(Color { c.r * 4/10, c.g * 4/10, c.b * 4/10 });
574                surface.HLine( isDefault, clientSize.w-1 - isDefault, clientSize.h-1 - isDefault);
575                surface.VLine( isDefault, clientSize.h-2 - isDefault, clientSize.w-1 - isDefault);
576             }
577          }
578       }
579       if(isDefault)
580       {
581          surface.SetForeground(skinForeground);
582          surface.Rectangle(0,0,clientSize.w-1,clientSize.h-1);
583       }
584       if(!(bevelOver) && !isRemote)
585       {
586          if(active)
587          {
588             int x1,y1,x2,y2;
589             int offset = (buttonState == down && this.offset) ? 1 : 0;
590             surface.SetForeground(skinForeground);
591             surface.LineStipple(0x5555);
592
593             #define CAPTION_DISTANCE   18
594             if((isRadio || isCheckbox) && text)
595             {
596                //x1 = clientSize.h + CAPTION_DISTANCE;
597                x1 = CAPTION_DISTANCE;
598                y1 = 0;
599                x2 = clientSize.w-4;
600                y2 = clientSize.h-4;
601             }
602             else
603             {
604                x1 = 3+offset;
605                y1 = 3+offset;
606                x2 = clientSize.w - 5+offset;
607                y2 = clientSize.h - 5+offset;
608
609                if(isRadio || isCheckbox)
610                {
611                   x1-=3;
612                   y1-=3;
613                   x2+=1;
614                   y2+=1;
615                }
616             }
617             if((x2 - x1) & 1) x2++;
618             if((y2 - y1) & 1) y2++;
619
620             surface.Rectangle(x1, y1, x2, y2);
621             surface.LineStipple(0);
622          }
623       }
624    }
625    */
626    #define CAPTION_DISTANCE   18
627
628    void OnRedraw(Surface surface)
629    {
630       if(isRadio)
631       {
632          ((void (*)(Window, Surface))(void *)PUREVTBL(Button)[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw])(this, surface);
633          return;
634       }
635       // if(bevel)
636       {
637          ButtonState state = this.buttonState;
638          Bitmap buttonBitmap = bitmap ? bitmap.bitmap : null;
639          char * text = this.text;
640          int offset = (state == down && this.offset) ? 1 : 0;
641          Color backColor = background;
642          int isDefault = this.isDefault;
643          Font font;
644
645          font = fontObject;
646
647          if(bevelOver && checked)
648             offset = 1;
649
650          if(!isEnabled)
651             state = disabled;
652
653          // Background
654          if((bevel || bevelOver) /* && opacity && backColor*/)
655          {
656             if(!scaleBitmap || !buttonBitmap)
657             {
658                /*
659                surface.SetBackground({(byte)(opacity * 255), backColor});
660                //surface.Area(1, 1,clientSize.w-3+offset,clientSize.h-3+offset);
661                surface.Area(0, 0,clientSize.w-1,clientSize.h-1);
662                */
663                ColorKey keys[2] = { { silver, 0.0f }, { white, 1.0f } };
664                surface.Gradient(keys, sizeof(keys) / sizeof(ColorKey), 1, vertical, 0, 0, clientSize.w-1, clientSize.h-1);
665             }
666          }
667
668          // Checkbox
669          if(isCheckbox && !buttonBitmap)
670          {
671             int height = 16;
672             int start = (clientSize.h - height) / 2;
673
674             if(!isEnabled)
675                // surface.SetBackground(activeBorder);
676                surface.SetBackground(gainsboro);
677             else if(active && !text)
678                surface.SetBackground((offset ? activeBorder : Color { 0,0,170 }));
679             else
680                surface.SetBackground((offset ? activeBorder : white));
681             surface.Area(2, start+2,height-3,start+height-3);
682
683             surface.SetForeground(Color { 85, 85, 85 });
684             surface.HLine(0, height - 2, start + 0);
685             surface.VLine(start+1, start+height - 2, 0);
686
687             surface.SetForeground(Color { 64,64,64 });
688             surface.HLine(1, height - 3, start + 1);
689             surface.VLine(start+2, start+height - 3, 1);
690
691             surface.SetForeground(Color { 212,208,200 });
692             surface.HLine(1, height - 2, start + height-2);
693             surface.VLine(start+1, start+height - 3, height-2);
694
695             surface.SetForeground(white);
696             surface.HLine(0, height - 1, start + height-1);
697             surface.VLine(start+0, start+height - 2, height-1);
698
699             if(checked)
700             {
701                if(active && !text)
702                   surface.SetForeground(white);
703                else if(!isEnabled)
704                   surface.SetForeground(Color { 85, 85, 85 });
705                else
706                   surface.SetForeground(black);
707                surface.DrawLine(4, start+8, 7,start+11);
708                surface.DrawLine(4, start+9, 7,start+12);
709                surface.DrawLine(7, start+11, 11,start+3);
710                surface.DrawLine(7, start+12, 11,start+4);
711             }
712          }
713
714          // Bitmaps
715          if(buttonBitmap)
716          {
717             surface.SetForeground(white);
718             if(isRadio || isCheckbox)
719             {
720                int x = 0, y = (clientSize.h-buttonBitmap.height)/2;
721                if(bevelOver && text)
722                {
723                   x = (CAPTION_DISTANCE-buttonBitmap.width)/2 + offset;
724                   y = (clientSize.h-buttonBitmap.height)/2 + offset;
725
726
727                }
728
729                // Radio Buttons and Checkboxes
730                surface.Blit(buttonBitmap,
731                   x, y,
732                   0,0,buttonBitmap.width,buttonBitmap.height);
733             }
734             else 
735             {
736                // Push Buttons
737                if(scaleBitmap)
738                {
739                   if(bevel || offset)
740                      surface.Stretch(buttonBitmap, 
741                         1 + offset, 1 + offset,0,0,
742                         clientSize.w-3,clientSize.h-3,buttonBitmap.width,buttonBitmap.height);
743                   else
744                      surface.Stretch(buttonBitmap, 0,0, 0,0,
745                         clientSize.w,clientSize.h,buttonBitmap.width,buttonBitmap.height);
746                }
747                else
748                {
749                   if(bevel || offset)
750                      surface.Blit(buttonBitmap,
751                         (clientSize.w-buttonBitmap.width) /2 + offset,
752                         (clientSize.h-buttonBitmap.height)/2 + offset,
753                         0,0,buttonBitmap.width,buttonBitmap.height);
754                   else
755                      surface.Blit(buttonBitmap,
756                         (clientSize.w-buttonBitmap.width)/2,
757                         (clientSize.h-buttonBitmap.height)/2,
758                         0,0,buttonBitmap.width,buttonBitmap.height);
759                }
760             }
761          }
762
763          // Shadows
764          if(bevel || (bevelOver && (state == down || state == over || checked)))
765          {
766             if(state == down || checked)
767             {
768                surface.SetForeground(Color { 85, 85, 85 });
769                surface.HLine(isDefault + 0, clientSize.w-2-isDefault, 0);
770                surface.VLine(isDefault + 1, clientSize.h-2-isDefault, 0);
771                surface.SetForeground(white);
772                surface.HLine(isDefault + 0, clientSize.w-1-isDefault, clientSize.h-1-isDefault);
773                surface.VLine(isDefault + 0, clientSize.h-2-isDefault, clientSize.w-1-isDefault);
774             }
775             else
776             {
777                surface.SetForeground(white);
778                surface.HLine(0 + isDefault, clientSize.w-2 - isDefault,  isDefault);
779                surface.VLine(1 + isDefault, clientSize.h-2 - isDefault,  isDefault);
780                surface.SetForeground(Color { 85, 85, 85 });
781                surface.HLine(1 + isDefault, clientSize.w-2 - isDefault, clientSize.h-2 - isDefault);
782                surface.VLine(1 + isDefault, clientSize.h-3 - isDefault, clientSize.w-2 - isDefault);
783
784                if(bevel)
785                {
786                   surface.SetForeground(black);
787                   surface.HLine( isDefault, clientSize.w-1 - isDefault, clientSize.h-1 - isDefault);
788                   surface.VLine( isDefault, clientSize.h-2 - isDefault, clientSize.w-1 - isDefault);
789                }
790             }
791          }
792
793          // Text
794          surface.TextOpacity(false);
795          surface.TextFont(font);
796          surface.SetForeground(foreground);
797          if(text)
798          {
799             int tw, th;
800             surface.TextExtent(text, (int)strlen(text),&tw, &th);
801
802             if((isRadio || isCheckbox) && !bevelOver)
803                WriteCaption(surface, /*clientSize.h +*/ CAPTION_DISTANCE + 3, 
804                   (clientSize.h - th - 4)/2);
805             else 
806             {
807                int x, y = (clientSize.h - th - 1)/2 + offset;
808                
809                if(ellipsis)
810                {
811                   int width = clientSize.w - 2*6;
812                   int x = 6 + offset;
813
814                   surface.WriteTextDots(alignment, x, y, width, text, (int)strlen(text));
815                }
816                else
817                {
818                   int width = clientSize.w - 2 * 6;
819                   x = 6 + offset;
820                   if(isCheckbox || ((isRadio || bevelOver) && buttonBitmap))
821                   {
822                      x += CAPTION_DISTANCE + 3;
823                   }
824
825                   if(tw < width)
826                   {
827                      if(alignment == right)
828                         x += width - tw - 1;
829                      else if(alignment == center)
830                         x += (width - tw) / 2;
831                   }
832                   WriteCaption(surface, x, y);
833                }
834             }
835          }
836
837          // Activation Highlight
838          if(isDefault)
839          {
840             surface.SetForeground(black);
841             surface.Rectangle(0,0,clientSize.w-1,clientSize.h-1);
842          }
843          if(!bevelOver && !isRemote)
844          {
845             if(active/* && (text || !(buttonStyle.radio || buttonStyle.checkBox))*/)
846             {
847                int x1,y1,x2,y2;
848                surface.SetForeground(black);
849                surface.LineStipple(0x5555);
850
851                if((isRadio || isCheckbox) && text)
852                {
853                   x1 = /*clientSize.h + */CAPTION_DISTANCE;
854                   y1 = 0;
855                   x2 = clientSize.w-4;
856                   y2 = clientSize.h-4;
857                }
858                else
859                {
860                   x1 = 3+offset;
861                   y1 = 3+offset;
862                   x2 = clientSize.w - 5+offset;
863                   y2 = clientSize.h - 5+offset;
864
865                   if(isRadio || isCheckbox)
866                   {
867                      x1-=3;
868                      y1-=3;
869                      x2+=1;
870                      y2+=1;
871                   }
872                }
873                if((x2 - x1) & 1) x2++;
874                if((y2 - y1) & 1) y2++;
875
876                surface.Rectangle(x1, y1, x2, y2);
877                surface.LineStipple(0);
878             }
879          }
880       }
881       /*else
882       {
883          Button::OnRedraw(surface);
884       }*/
885    }
886 }
887
888 class SimSkin_ScrollBar : ScrollBar
889 {
890    void OnApplyGraphics()
891    {
892       ((void (*)(Window))(void *)PUREVTBL(ScrollBar)[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnApplyGraphics])(this);
893
894       //background = { skinBackground.r * 9 / 6, skinBackground.g * 9 / 6, skinBackground.b * 9 / 6 };
895 /*
896       upBtn.background = Color {  70 * 6/10, 130* 6/10, 180* 6/10 }; //skinBackground;
897       upBtn.bitmap = { (direction == vertical) ? "<:ecere>elements/arrowUp.png" : "<:ecere>elements/arrowLeft.png", monochrome = true };
898       downBtn.background = Color {  70 * 6/10, 130* 6/10, 180* 6/10 }; //skinBackground;
899       downBtn.bitmap = { (direction == vertical) ? "<:ecere>elements/arrowDown.png" : "<:ecere>elements/arrowRight.png", monochrome = true };
900       thumb.background = Color {  70 * 6/10, 130* 6/10, 180* 6/10 }; //skinBackground;*/
901    }   
902 }
903
904 /*class SimSkin_DropBox : DropBox
905 {
906    void OnApplyGraphics()
907    {
908       ((void (*)(Window))(void *)PUREVTBL(DropBox)[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnApplyGraphics])(this);
909       button.bitmap = { "<:ecere>elements/arrowDown.png", monochrome = true };
910       background = skinBackground;
911       foreground = skinForeground;
912       selectionColor = skinMainColor;
913    }   
914 }*/
915
916 /*class SimSkin_ListBox : ListBox
917 {
918    void OnApplyGraphics()
919    {
920       ((void (*)(Window))(void *)PUREVTBL(ListBox)[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnApplyGraphics])(this);
921       background = skinBackground;
922       foreground = skinForeground;
923       selectionColor = skinMainColor;
924    }   
925 }*/
926
927 public class SimSkin : Skin
928 {
929    class_property(name) = "Sim";
930    class_property(selectionColor) = (Color)skinMainColor;
931    class_property(disabledBackColor) = (Color)Color{ 128,128,128 };
932    class_property(disabledFrontColor) = (Color)Color{ 255,255,255 };
933    class_property(selectionText)  = (Color)white;
934
935    FontResource ::SystemFont()
936    {
937       return { faceName = "Tahoma", size = 8.25f };
938    }
939
940    FontResource ::CaptionFont()
941    {
942       return { faceName = "Verdana", size = 6.5f };
943    }
944
945    char * ::CursorsBitmaps(uint id, int *hotSpotX, int *hotSpotY, byte ** paletteShades)
946    {
947       return null;
948    }
949
950    BitmapResource ::GetBitmap(int id)
951    {
952       return null;
953    }
954
955    int ::VerticalSBW()
956    {
957       return 16;
958    }
959
960    int ::HorizontalSBH()
961    {
962       return 16;
963    }
964 }