cleaned all trailing white space from source files.
[sdk] / ecere / src / gui / skins / AquaSkin.ec
1 #ifndef NOBLENDING
2 import "Window"
3
4 #define BORDER       5 //4
5 #define TOP          3
6 #define BOTTOM       (4 + 2)
7 #define CORNER       (BORDER * 2 + 6)
8 #define CAPTION      22 // 20
9 #define DEAD_BORDER  0 //3
10 #define MIN_WIDTH    68
11 #define MIN_HEIGHT   8
12 #define BUTTON_OFFSET   4
13 #define NAME_OFFSET   2
14 #define NAME_OFFSETX  10
15
16 #define SB_WIDTH  16
17 #define SB_HEIGHT 16
18
19 #define MENU_HEIGHT     25
20 #define STATUS_HEIGHT   18
21
22 /*
23 #define TEXT_COLOR   black
24
25 #define GRADIENT_DIRECTION horizontal
26
27 static ColorKey gradient[] =
28 {
29    { Color { 128, 128, 255}, 0.00f },
30    { Color { 254, 254, 254}, 0.60f },
31    { Color {   0,   0, 255}, 1.00f }
32 };
33 */
34 /*
35 #define GRADIENT_DIRECTION Vertical
36 static ColorKey gradient[] =
37 {
38    { Color {   0,   0, 255}, 0.00f },
39    { Color { 254, 254, 254}, 0.60f },
40    { Color { 128, 128, 255}, 1.00f }
41 };
42
43 static ColorKey gradientInactive[] =
44 {
45    { Color {   0,   0,  0},  0.00f },
46    { Color { 254, 254, 254}, 0.60f },
47    { Color { 128, 128, 128}, 1.00f }
48 };
49 */
50
51 #define GRADIENT_SMOOTHNESS 1.0f
52 #define GRADIENT_DIRECTION horizontal
53 #define TEXT_COLOR         white
54 #define TEXT_INACTIVE      darkGray // Color { 212,208,200 }
55
56 static ColorKey gradient[] =
57 {
58    { ColorAlpha { 255, Color {  10,   36, 106 } }, 0.00f },
59    { ColorAlpha { 255, Color { 166,  202, 240 } }, 1.00f }
60 };
61 static ColorKey gradientInactive[] =
62 {
63    { ColorAlpha { 255, Color { 128, 128, 128 } }, 0.00f },
64    { ColorAlpha { 255, Color { 192, 192, 192 } }, 1.00f }
65 };
66
67
68
69 BitmapResource bmpUpMiddle { "<:ecere>aqua/upMiddle.png", alphaBlend = true };
70 BitmapResource bmpUpLeft { "<:ecere>aqua/upLeft.png", alphaBlend = true };
71 BitmapResource bmpUpRight { "<:ecere>aqua/upRight.png", alphaBlend = true };
72
73 BitmapResource bmpDownMiddle { "<:ecere>aqua/downMiddle.png", alphaBlend = true };
74 BitmapResource bmpDownLeft { "<:ecere>aqua/downLeft.png", alphaBlend = true };
75 BitmapResource bmpDownRight { "<:ecere>aqua/downRight.png", alphaBlend = true };
76
77 BitmapResource bmpScrollUp { "<:ecere>aqua/scrollUp.png", alphaBlend = true };
78 BitmapResource bmpScrollDown { "<:ecere>aqua/scrollDown.png", alphaBlend = true };
79 BitmapResource bmpScrollVert { "<:ecere>aqua/scrollVert.png", alphaBlend = true };
80
81 BitmapResource bmpThumbUp { "<:ecere>aqua/thumbUp.png", alphaBlend = true };
82 BitmapResource bmpThumbDown { "<:ecere>aqua/thumbDown.png", alphaBlend = true };
83 BitmapResource bmpThumbVert { "<:ecere>aqua/thumbVert.png", alphaBlend = true };
84
85 BitmapResource bmpLeftBorder { "<:ecere>aqua/leftBorder.png", alphaBlend = true };
86 BitmapResource bmpRightBorder { "<:ecere>aqua/rightBorder.png", alphaBlend = true };
87 BitmapResource bmpTopBorder { "<:ecere>aqua/topBorder.png", alphaBlend = true };
88 BitmapResource bmpBottomBorder { "<:ecere>aqua/bottomBorder.png", alphaBlend = true };
89
90 BitmapResource bmpTopLeftBorder { "<:ecere>aqua/topLeftBorder.png", alphaBlend = true };
91 BitmapResource bmpTopRightBorder { "<:ecere>aqua/topRightBorder.png", alphaBlend = true };
92 BitmapResource bmpBottomLeftBorder { "<:ecere>aqua/bottomLeftBorder.png", alphaBlend = true };
93 BitmapResource bmpBottomRightBorder { "<:ecere>aqua/bottomRightBorder.png", alphaBlend = true };
94
95 #define PUREVTBL(c)     ((int (**)())*(void **)((byte *)class(c).data + 4))
96
97 default:
98 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw;
99 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnResizing;
100 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnPostCreate;
101 private:
102 /*
103 static void Dummy()
104 {
105    Window w;
106    w.OnRedraw(null);
107    w.OnResizing(null, null);
108 }
109 */
110
111 static void Button::ThumbOnRedraw(Surface surface)
112 {
113    int offset = (buttonState == down) ? this.offset : 0;
114    BitmapResource left = bmpThumbUp;
115    BitmapResource right = bmpThumbDown;
116    BitmapResource middle = bmpThumbVert;
117    int sizeW = size.w;
118    int x = 1; //-40 * sizeH / 96;
119    int y = -6; //-7 * sizeH / 96;
120    int w = 14;// * sizeW / 14;
121    int sideH = 10; // * sizeW / 14;
122    int middleH = size.h - 2 * (sideH + y);
123
124    surface.Stretch(left.bitmap, x, y, 0,0, w, sideH, left.bitmap.width, left.bitmap.height);
125    surface.HTile(middle.bitmap, x, y + sideH, w, middleH);
126    surface.Stretch(right.bitmap, x, y + sideH + middleH, 0,0, w, sideH, right.bitmap.width, right.bitmap.height);
127
128    /*
129    surface.Filter(left.bitmap, x, y, 0,0, w, sideH, left.bitmap.width, left.bitmap.height);
130    surface.FilterVTile(middle.bitmap, x, y + sideH, w, middleH);
131    surface.Filter(right.bitmap, x, y + sideH + middleH, 0,0, w, sideH, right.bitmap.width, right.bitmap.height);
132    */
133 }
134
135 static bool Button::ThumbIsInside(int x, int y)
136 {
137    return (x >= 0 && y >= 0 && x < size.w && y < size.h);
138 }
139
140 static void Button::ThumbSetBox(Box box)
141 {
142    box.top -= 6;
143    box.left += 1;
144    box.right -= 1;
145    box.bottom += 6;
146 }
147
148 public class AquaSkin_ScrollBar : ScrollBar
149 {
150    void OnApplyGraphics()
151    {
152       if(sbStyle.vertical)
153       {
154          downBtn.size.h = 24;
155          downBtn.offset = false;
156          downBtn.anchor = Anchor { left = 0, bottom = 0, right = 0 };
157
158          upBtn.size.h = 24;
159          upBtn.offset = false;
160          upBtn.anchor = Anchor { left = 0, right = 0, top = 0 };
161
162          thumb.Move(0,0, Max(clientSize.w, 16), thumbSize);
163       }
164       else
165       {
166       }
167    }
168
169    bool OnPostCreate()
170    {
171       bool result = PUREVTBL(ScrollBar)[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnPostCreate](this);
172
173       AddResource(bmpScrollUp);
174       AddResource(bmpScrollDown);
175       AddResource(bmpScrollVert);
176       AddResource(bmpThumbUp);
177       AddResource(bmpThumbDown);
178       AddResource(bmpThumbVert);
179
180       if(sbStyle.vertical)
181       {
182          downBtn.bevel = false;
183          downBtn.size.h = 18;
184          downBtn.anchor = Anchor { left = 0, right = 0, bottom = 0 };
185          downBtn.bitmap = { fileName = "<:ecere>aqua/scrollDown.png", alphaBlend = true };
186
187          upBtn.bevel = false;
188          upBtn.size.h = 18;
189          upBtn.anchor = Anchor { left = 0, right = 0, bottom = 0 };
190          upBtn.bitmap = { fileName = "<:ecere>aqua/scrollUp.png", alphaBlend = true };
191
192          thumb.OnRedraw = ThumbOnRedraw;
193          thumb.IsInside = ThumbIsInside;
194          thumb.SetBox = ThumbSetBox;
195       }
196       else
197       {
198
199       }
200       return true;
201    }
202
203    void OnRedraw(Surface surface)
204    {
205       surface.VTile(bmpScrollVert.bitmap, 0, 0, clientSize.w, clientSize.h);
206
207    }
208 }
209
210 public class AquaSkin_Button : Button
211 {
212    bool OnResizing(int *width, int *height)
213    {
214       bool result = PUREVTBL(Button)[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnResizing](this, width, height);
215       if(!bitmap)
216       {
217          int w;
218          display.FontExtent(fontObject, " ", 1, &w, null);
219          *width += 2*w;
220       }
221       return result;
222    }
223
224    void SetBox(Box box)
225    {
226       if(!bitmap)
227       {
228          int sizeH = size.h;
229          box.top -= 7 * sizeH / 96;
230          box.left -= 40 * sizeH / 96;
231          box.right += 40 * sizeH / 96;
232          box.bottom += 75 * sizeH / 96;
233       }
234    }
235
236    bool IsInside(int x, int y)
237    {
238       if(!bitmap)
239       {
240          int sizeW = size.w;
241          int sizeH = size.h;
242          if(x >= 0 && y >= 0 && x < sizeW && y < sizeH)
243          {
244             ColorAlpha * picture;
245             int sideW = (107 - 40) * sizeH / 96;
246             y = y * 96 / sizeH + 7;
247             if(x < sideW)
248             {
249                x = 40 + x * 96 / sizeH;
250                picture = ((ColorAlpha *)bmpUpLeft.bitmap.picture) + y * bmpUpLeft.bitmap.stride + x;
251                return picture->a > 75;
252             }
253             else if(x > sizeW - sideW)
254             {
255                x = (x - (sizeW - sideW)) * 96 / sizeH;
256                picture = ((ColorAlpha *)bmpUpRight.bitmap.picture) + y * bmpUpRight.bitmap.stride + x;
257                return picture->a > 75;
258             }
259             else
260                return true;
261          }
262       }
263       else
264          return (x >= 0 && y >= 0 && x < size.w && y < size.h);
265
266       return false;
267    }
268
269    void OnApplyGraphics()
270    {
271       if(!bitmap)
272       {
273          // font = { "Arial", size = 9, bold = true };
274          opacity = 0;
275          drawBehind = true;
276          AddResource(bmpUpLeft);
277          AddResource(bmpUpMiddle);
278          AddResource(bmpUpRight);
279          AddResource(bmpDownLeft);
280          AddResource(bmpDownMiddle);
281          AddResource(bmpDownRight);
282       }
283    }
284
285    void OnRedraw(Surface surface)
286    {
287       if(bitmap)
288       {
289          return PUREVTBL(Button)[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw](this, surface);
290       }
291       else
292       {
293          int offset = (buttonState == down) ? this.offset : 0;
294          BitmapResource left = (buttonState == down) ? bmpDownLeft : bmpUpLeft;
295          BitmapResource right = (buttonState == down) ? bmpDownRight : bmpUpRight;
296          BitmapResource middle = (buttonState == down) ? bmpDownMiddle : bmpUpMiddle;
297          int sizeH = size.h;
298          int x = -40 * sizeH / 96;
299          int y = -7 * sizeH / 96;
300          int textH;
301          int h = 178 * sizeH / 96;
302          int sideW = 107 * sizeH / 96;
303          int middleW = size.w - 2 * (sideW + x);
304          surface.TextExtent(" ", 1, null, &textH);
305          /*
306          surface.Stretch(left.bitmap, x, y, 0,0, sideW, h, left.bitmap.width, left.bitmap.height);
307          surface.HTile(middle.bitmap, x + sideW, y, middleW, h);
308          surface.Stretch(right.bitmap, x + sideW + middleW, y, 0,0, sideW, h, left.bitmap.width, left.bitmap.height);
309          */
310          surface.Filter(left.bitmap, x, y, 0,0, sideW, h, left.bitmap.width, left.bitmap.height);
311          surface.FilterHTile(middle.bitmap, x + sideW, y, middleW, h);
312          surface.Filter(right.bitmap, x + sideW + middleW, y, 0,0, sideW, h, left.bitmap.width, left.bitmap.height);
313
314
315          surface.CenterTextf(clientSize.w/2 + offset, (clientSize.h - textH * 1.1) / 2 + offset, text);
316       }
317    }
318 }
319
320
321 char * cursorsBitmaps[] =
322 {
323    "<:ecere>cursors/arrow.png",
324    "<:ecere>cursors/iBeam.png",
325    "<:ecere>cursors/cross.png",
326    "<:ecere>cursors/move.png",
327    "<:ecere>cursors/sizeNorthEastSouthWest.png",
328    "<:ecere>cursors/sizeNorthSouth.png",
329    "<:ecere>cursors/sizeNorthWestSouthEast.png",
330    "<:ecere>cursors/sizeWestEast.png",
331    "<:ecere>cursors/move.png"
332 };
333
334 static Point cursorsHotSpots[] =
335 {
336    { 0, 0 },
337    { 0, 0 },
338    { 8, 8 },
339    { 10, 10 },
340    { 8, 8 },
341    { 4, 10 },
342    { 7, 7 },
343    { 5, 0 }
344 };
345
346 static char * skinBitmaps[SkinBitmap] =
347 {
348    "<:ecere>elements/areaMinimize.png",
349    "<:ecere>elements/areaMaximize.png",
350    "<:ecere>elements/areaRestore.png",
351    "<:ecere>elements/areaClose.png"
352 };
353
354 class AquaSkin : Skin
355 {
356    class_property(name) = "Aqua";
357    class_property(selectionColor) = Color { 10, 36, 106 };
358
359    FontResource ::SystemFont()
360    {
361       return FontResource { faceName = "Tahoma", size = 8.25f };
362    }
363
364    FontResource ::CaptionFont()
365    {
366       return FontResource { faceName = "Tahoma", size = 10.0f, bold = true };
367    }
368
369    char * ::CursorsBitmaps(uint id, int * hotSpotX, int *hotSpotY, byte ** paletteShades)
370    {
371       *hotSpotX = cursorsHotSpots[id].x;
372       *hotSpotY = cursorsHotSpots[id].y;
373       *paletteShades = null;
374       return cursorsBitmaps[id];
375    }
376
377    BitmapResource ::GetBitmap(SkinBitmap id)
378    {
379       return BitmapResource { fileName = skinBitmaps[id] };
380    }
381
382    int ::VerticalSBW() { return SB_WIDTH; }
383    int ::HorizontalSBH() { return SB_HEIGHT; }
384 };
385
386
387 public class AquaSkin_Window : Window
388 {
389    bool OnPostCreate()
390    {
391       AddResource(bmpLeftBorder);
392       AddResource(bmpRightBorder);
393       AddResource(bmpTopBorder);
394       AddResource(bmpBottomBorder);
395
396       AddResource(bmpTopLeftBorder);
397       AddResource(bmpTopRightBorder);
398       AddResource(bmpBottomLeftBorder);
399       AddResource(bmpBottomRightBorder);
400       return true;
401    }
402
403    void GetDecorationsSize(MinMaxValue * w, MinMaxValue * h)
404    {
405       *w = *h = 0;
406       if((((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel) && state != minimized)
407       {
408          *w += 4;
409          *h += 4;
410       }
411       if(((BorderBits)borderStyle).fixed /*sizable*/ && (state == normal))
412       {
413          *w += 2 * BORDER + 2;
414          *h += TOP + BOTTOM;
415       }
416       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
417       {
418          *h += CAPTION;
419          if(!((BorderBits)borderStyle).sizable || state == minimized)
420          {
421             *h += 2*DEAD_BORDER;
422             *w += 2*DEAD_BORDER;
423          }
424       }
425       if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
426       {
427          *w += 2;
428          *h += 2;
429       }
430       if(hasMenuBar && state != minimized)
431       {
432          *h += MENU_HEIGHT;
433       }
434       if(statusBar && state != minimized)
435       {
436          *h += STATUS_HEIGHT;
437       }
438    }
439
440    void SetWindowMinimum(MinMaxValue * mw, MinMaxValue * mh)
441    {
442       bool isNormal = (state == normal);
443       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
444       {
445          *mw = MIN_WIDTH;
446          *mh = MIN_HEIGHT;
447       }
448       else
449          *mw = *mh = 0;
450
451       if(((BorderBits)borderStyle).fixed /*sizable*/ && isNormal)
452          *mw += 2*CORNER;
453
454       // GetDecorationsSize(window, mw, mh);
455
456       if(hasVertScroll)
457          *mw += SB_WIDTH;
458       if(hasHorzScroll)
459          *mh += SB_HEIGHT;
460       if(hasVertScroll && hasHorzScroll)
461       {
462          *mw += 2 * SB_WIDTH + SB_WIDTH;
463          *mh += 2 * SB_HEIGHT + SB_HEIGHT;
464          if(((BorderBits)borderStyle).fixed /*sizable*/ && isNormal)
465             *mw -= 2*CORNER;
466       }
467    }
468
469    void SetWindowArea(int * x, int * y, MinMaxValue * w, MinMaxValue * h, MinMaxValue * cw, MinMaxValue * ch)
470    {
471       bool isNormal = (state == normal);
472       MinMaxValue aw = 0, ah = 0;
473
474       *x = *y = 0;
475
476       GetDecorationsSize(&aw, &ah);
477
478       // Compute client area start
479       if(((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel)
480       {
481          *x += 2;
482          *y += 2;
483       }
484
485       if(((BorderBits)borderStyle).fixed /*sizable*/ && isNormal)
486       {
487          *x += BORDER;
488          *y += TOP;
489       }
490
491       if(hasMenuBar)
492       {
493          *y += MENU_HEIGHT;
494       }
495
496       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
497       {
498          *y += CAPTION;
499          if(!((BorderBits)borderStyle).sizable || state == minimized)
500          {
501             *y += DEAD_BORDER;
502             *x += DEAD_BORDER;
503          }
504       }
505
506       if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
507       {
508          *x += 1;
509          *y += 1;
510       }
511
512       // Reduce client area
513       *cw = *w - aw;
514       *ch = *h - ah;
515
516       *cw = Max(*cw, 0);
517       *ch = Max(*ch, 0);
518    }
519
520    void PreShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving)
521    {
522       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
523       {
524          if(rootWindow == this)
525          {
526             surface.SetBackground({ 0 });
527
528             // Top
529             surface.Area(0,0,size.w, bmpTopBorder.bitmap.height);
530             // Left
531             surface.Area(0,0,8, size.h);
532             // Right
533             surface.Area(size.w-9, bmpTopBorder.bitmap.height, size.w-1, size.h);
534             // Bottom
535             surface.Area(0,size.h-9,size.w-1, size.h);
536          }
537       }
538    }
539
540    void ShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving)
541    {
542       bool isNormal = (state == normal);
543       int top = 0, border = 0, bottom = 0;
544       if(state == minimized)
545          top = border = bottom = DEAD_BORDER;
546       else if(((BorderBits)borderStyle).fixed /*sizable*/)
547       {
548          top = isNormal ? TOP : 0;
549          border = isNormal ? BORDER : 0;
550          bottom = BOTTOM;
551       }
552       else if(((BorderBits)borderStyle).fixed)
553       {
554          top = DEAD_BORDER;
555          border = DEAD_BORDER;
556          bottom = DEAD_BORDER;
557       }
558       else if(((BorderBits)borderStyle).contour)
559       {
560          top = 1;
561          border = 1;
562          bottom = 1;
563       }
564
565       if(((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel)
566       {
567          int deepTop = 0, deepBottom = 0, deepBorder = 0;
568          if(((BorderBits)borderStyle).contour)
569          {
570             deepBorder = border;
571             deepTop = (((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar)) ? (top + CAPTION) : top;
572             deepBottom = (((BorderBits)borderStyle).fixed /*sizable*/ && isNormal) ? bottom : border;
573          }
574
575          surface.Bevel(((BorderBits)borderStyle).bevel ? false : true, deepBorder, deepTop,
576             size.w - deepBorder - deepBorder, size.h - deepBottom - deepTop);
577       }
578
579       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
580       {
581          /*
582          // Frame for ES_CAPTION windows
583          surface.Bevel(false, 0, 0, size.w, size.h);
584          surface.SetForeground(activeBorder);
585          surface.Rectangle(2, 2, size.w-3, size.h-3);
586
587          // Resizeable frame is 1 pixel thicker
588          if(((BorderBits)borderStyle).sizable && isNormal)
589             surface.Rectangle(3, 3, size.w - 4, size.h - 4);
590
591          // Caption
592
593          if(active)
594             surface.Gradient(gradient, sizeof(gradient) / sizeof(ColorKey), GRADIENT_SMOOTHNESS, GRADIENT_DIRECTION,
595                border, top, size.w - border - 1, top + CAPTION - 2);
596          else
597             surface.Gradient(gradientInactive, sizeof(gradientInactive) / sizeof(ColorKey),
598             GRADIENT_SMOOTHNESS, GRADIENT_DIRECTION,
599                border, top, size.w - border - 1, top + CAPTION - 2);
600          */
601          /*
602          surface.Blit(bmpTopBorder.bitmap, 0, 0, 0, 0, bmpTopBorder.bitmap.width, bmpTopBorder.bitmap.height);
603          surface.Blit(bmpLeftBorder.bitmap, 0, 27, 0, 0, bmpLeftBorder.bitmap.width, bmpLeftBorder.bitmap.height);
604          surface.Blit(bmpRightBorder.bitmap, 646-9, 27, 0, 0, bmpRightBorder.bitmap.width, bmpRightBorder.bitmap.height);
605          surface.Blit(bmpBottomBorder.bitmap, 0, 27 + 448, 0, 0, bmpBottomBorder.bitmap.width, bmpBottomBorder.bitmap.height);
606          */
607          surface.alphaWrite = blend;
608          // surface.blend = rootWindow != this;
609
610          surface.Blit(bmpTopLeftBorder.bitmap, 0, 0, 0, 0, bmpTopLeftBorder.bitmap.width, bmpTopLeftBorder.bitmap.height);
611          surface.Stretch(bmpTopBorder.bitmap, bmpTopLeftBorder.bitmap.width, 0, 0, 0, size.w - 2 * bmpTopLeftBorder.bitmap.width, bmpTopBorder.bitmap.height,
612             bmpTopBorder.bitmap.width, bmpTopBorder.bitmap.height);
613          surface.Blit(bmpTopRightBorder.bitmap, size.w - bmpTopRightBorder.bitmap.width, 0, 0, 0, bmpTopRightBorder.bitmap.width, bmpTopRightBorder.bitmap.height);
614
615          surface.Stretch(bmpLeftBorder.bitmap, 0, 27, 0, 0, bmpLeftBorder.bitmap.width, size.h - 27 - 9, bmpLeftBorder.bitmap.width, bmpLeftBorder.bitmap.height);
616          surface.Stretch(bmpRightBorder.bitmap, size.w-9, 27, 0, 0, bmpRightBorder.bitmap.width, size.h - 27 - 9, bmpLeftBorder.bitmap.width, bmpLeftBorder.bitmap.height);
617
618          surface.Blit(bmpBottomLeftBorder.bitmap, 0, size.h - 9, 0, 0, bmpBottomLeftBorder.bitmap.width, bmpBottomLeftBorder.bitmap.height);
619          surface.Stretch(bmpBottomBorder.bitmap, bmpBottomLeftBorder.bitmap.width, size.h - 9, 0, 0, size.w - 2 * bmpBottomLeftBorder.bitmap.width, bmpBottomBorder.bitmap.height,
620             bmpBottomBorder.bitmap.width, bmpBottomBorder.bitmap.height);
621          surface.Blit(bmpBottomRightBorder.bitmap, size.w - bmpBottomRightBorder.bitmap.width, size.h - 9, 0, 0, bmpBottomRightBorder.bitmap.width, bmpBottomRightBorder.bitmap.height);
622          //surface.alphaWrite = DontWrite;
623          surface.blend = true;
624
625          surface.SetForeground(activeBorder);
626          /*
627          if(state != minimized)
628             surface.HLine(border, size.w-border-1, top + CAPTION-1);
629          */
630
631          surface.SetForeground((active ? TEXT_COLOR : TEXT_INACTIVE));
632          surface.TextOpacity(false);
633          surface.TextFont(captionFont);
634          if(name)
635          {
636             int buttonsSize = border +
637                ((hasMaximize || hasMinimize) ? 60 : 26);
638             surface.WriteTextDots(left, border + NAME_OFFSETX, top + NAME_OFFSET,
639                size.w - (buttonsSize + border + NAME_OFFSETX /*4*/), name, strlen(name));
640          }
641       }
642       if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
643       {
644          surface.SetForeground(black);
645          surface.Rectangle(0, 0, size.w - 1, size.h - 1);
646       }
647
648       if(state != minimized && hasHorzScroll && hasVertScroll)
649       {
650          if(sbh && sbh.visible && sbv && sbv.visible)
651          {
652             surface.SetBackground(activeBorder);
653             surface.Area(
654                clientStart.x + clientSize.w,
655                clientStart.y + clientSize.h,
656                clientStart.x + clientSize.w + SB_WIDTH - 1,
657                clientStart.y + clientSize.h + SB_HEIGHT - 1);
658          }
659       }
660    }
661
662    bool IsMouseMoving(int x, int y, int w, int h)
663    {
664       bool isNormal = (state == normal);
665       bool result = false;
666
667       if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
668       {
669          int corner = 0, border = 0, top = 0;
670          if(((BorderBits)borderStyle).fixed /*sizable*/ && isNormal)
671          {
672             corner = CORNER;
673             border = BORDER;
674             top    = TOP;
675          }
676          // Special case for having caption on resize bar
677          if(!CAPTION)
678             result = Box { corner, 0, w-corner-1, TOP-1 }.IsPointInside({x,y});
679          else
680             result = Box { border, top, w-border-1, top+CAPTION-1 }.IsPointInside({x, y});
681       }
682       return result;
683    }
684
685    bool IsMouseResizing(int x, int y, int w, int h, bool *resizeX, bool *resizeY, bool *resizeEndX, bool *resizeEndY)
686    {
687       bool result = false;
688
689       *resizeX = *resizeY = *resizeEndX = *resizeEndY = false;
690
691       if(((BorderBits)borderStyle).sizable && (state == normal))
692       {
693          // TopLeft Corner
694          if(Box { 0, 0,CORNER-1, TOP-1 }.IsPointInside({x, y}))
695             result = *resizeX = *resizeY = true;
696          // TopRight Corner
697          if(Box { w-CORNER-1, 0, w-1, TOP-1 }.IsPointInside({x, y}))
698             result = *resizeEndX = *resizeY = true;
699          // BottomLeft Corner
700          if(Box { 0, h-BOTTOM-1, CORNER-1, h-1 }.IsPointInside({x, y}))
701             result = *resizeX = *resizeEndY = true;
702          // BottomRight Corner
703          if(Box { w-CORNER-1, h-BOTTOM-1, w-1, h-1 }.IsPointInside({x, y}))
704             result = *resizeEndX = *resizeEndY = true;
705          // Left Border
706          if(Box { 0,TOP, BORDER, h-BOTTOM-1 }.IsPointInside({x, y}))
707             result = *resizeX = true;
708          // Right Border
709          if(Box { w-BORDER-1, TOP, w-1, h-BOTTOM-1 }.IsPointInside({x, y}))
710             result = *resizeEndX = true;
711          // Top Border
712          if(Box { CORNER, 0, w-CORNER-1, TOP-1 }.IsPointInside({x, y}))
713             result = *resizeY = true;
714          // Bottom Border
715          if(Box { CORNER, h-BOTTOM-1, w-CORNER-1, h-1 }.IsPointInside({x, y}))
716             result = *resizeEndY = true;
717       }
718       return result;
719    }
720
721    void UpdateNonClient()
722    {
723       bool isNormal = (state == normal);
724       int top = 0, border = 0;
725       int insideBorder;
726       if(state == minimized)
727          top = border = DEAD_BORDER;
728       else if(((BorderBits)borderStyle).fixed /*sizable*/)
729       {
730          if(state == maximized && parent.menuBar)
731          {
732             top = 2;
733             border = 2;
734          }
735          else
736          {
737             top = isNormal ? TOP : 0;
738             border = isNormal ? BORDER : 0;
739          }
740       }
741       else if(((BorderBits)borderStyle).fixed)
742       {
743          top = DEAD_BORDER;
744          border = DEAD_BORDER;
745       }
746       else if(((BorderBits)borderStyle).contour)
747       {
748          top = 1;
749          border = 1;
750       }
751       insideBorder = border;
752       if(((BorderBits)borderStyle).deep)
753          insideBorder += 2;
754
755       if(menuBar)
756       {
757          if(state == minimized)
758             menuBar.visible = false;
759          else
760             menuBar.visible = true;
761          menuBar.Move(clientStart.x, clientStart.y - MENU_HEIGHT, size.w - insideBorder * 2, MENU_HEIGHT);
762       }
763       if(statusBar)
764       {
765          if(state == minimized)
766             statusBar.visible = false;
767          else
768          {
769             statusBar.visible = true;
770             statusBar.anchor = { left = clientStart.x, bottom = border };
771             statusBar.size.w = size.w - insideBorder * 2;
772          }
773       }
774       if(sysButtons[0])
775       {
776          sysButtons[0].anchor = { right = 43 + border, top = top + BUTTON_OFFSET };
777          sysButtons[0].size = { 15, 15 };
778          sysButtons[0].bevel = true;
779          sysButtons[0].bitmap = { skinBitmaps[(state == minimized) ? restore : minimize] };
780          sysButtons[0].visible = true;
781       }
782       if(sysButtons[1])
783       {
784          sysButtons[1].anchor = { right = 28 + border, top = top + BUTTON_OFFSET };
785          sysButtons[1].size = { 15, 15 };
786          sysButtons[1].bevel = true;
787          sysButtons[1].bitmap = { skinBitmaps[(state == maximized) ? restore : maximize] };
788          sysButtons[1].visible = true;
789       }
790       if(sysButtons[2])
791       {
792          sysButtons[2].anchor = { right = 10 + border, top = top + BUTTON_OFFSET };
793          sysButtons[2].size = { 15, 15 };
794          sysButtons[2].bevel = true;
795          sysButtons[2].bitmap = { skinBitmaps[close] };
796          sysButtons[2].visible = true;
797       }
798    }
799
800    bool IsOpaque()
801    {
802       return (!style.drawBehind && opacity == 1.0) && !((BorderBits)borderStyle).fixed;
803    }
804 }
805 #else
806 import "instance"
807 #endif