1 // This file contains some FOX functions redefinitions (FOX hacks for the Clearlooks controls)
2 // The Clearlooks controls try to mimic the GTK Clearlooks theme
3 // They are optional and can be set within the Preferences dialog
4 // The hack is done mainly by redefining the onPaint() functions of the various widgets
5 
6 
7 // Integer scaling factor for check and radio boxes
8 extern FXint scaleint;
9 
10 
11 //
12 // Some useful functions and macros
13 //
14 
15 
16 // Draw rectangle with gradient effect
17 // Default is vertical gradient
drawGradientRectangle(FXDC & dc,FXColor upper,FXColor lower,int x,int y,int w,int h,FXbool vert=true)18 static void drawGradientRectangle(FXDC& dc, FXColor upper, FXColor lower, int x, int y, int w, int h, FXbool vert = true)
19 {
20     register int rr, gg, bb, dr, dg, db, r1, g1, b1, r2, g2, b2, yl, yh, yy, dy, n, t, ww;
21     const int    MAXSTEPS = 128;
22 
23     if ((0 < w) && (0 < h))
24     {
25         // Horizontal gradient : exchange w and h
26         if (!vert)
27         {
28             ww = w;
29             w = h;
30             h = ww;
31         }
32 
33         dc.setStipple(STIPPLE_NONE);
34         dc.setFillStyle(FILL_SOLID);
35 
36         r1 = FXREDVAL(upper);
37         r2 = FXREDVAL(lower);
38         dr = r2-r1;
39         g1 = FXGREENVAL(upper);
40         g2 = FXGREENVAL(lower);
41         dg = g2-g1;
42         b1 = FXBLUEVAL(upper);
43         b2 = FXBLUEVAL(lower);
44         db = b2-b1;
45 
46         n = FXABS(dr);
47         if ((t = FXABS(dg)) > n)
48         {
49             n = t;
50         }
51         if ((t = FXABS(db)) > n)
52         {
53             n = t;
54         }
55         n++;
56         if (n > h)
57         {
58             n = h;
59         }
60         if (n > MAXSTEPS)
61         {
62             n = MAXSTEPS;
63         }
64         rr = (r1<<16)+32767;
65         gg = (g1<<16)+32767;
66         bb = (b1<<16)+32767;
67         yy = 32767;
68 
69         dr = (dr<<16)/n;
70         dg = (dg<<16)/n;
71         db = (db<<16)/n;
72         dy = (h<<16)/n;
73 
74         do
75         {
76             yl = yy>>16;
77             yy += dy;
78             yh = yy>>16;
79             dc.setForeground(FXRGB(rr>>16, gg>>16, bb>>16));
80 
81             // Vertical gradient
82             if (vert)
83             {
84                 dc.fillRectangle(x, y+yl, w, yh-yl);
85             }
86 
87             // Horizontal gradient
88             else
89             {
90                 dc.fillRectangle(x+yl, y, yh-yl, w);
91             }
92 
93             rr += dr;
94             gg += dg;
95             bb += db;
96         } while (yh < h);
97     }
98 }
99 
100 
101 // These macros are used to simplify the code
102 // They draw a button in Standard or Clearlooks mode, in up or down state
103 
104 #define DRAW_CLEARLOOKS_BUTTON_UP                                              \
105     dc.setForeground(backColor);                                               \
106     dc.drawPoints(basebackground, 4);                                          \
107                                                                                \
108     dc.setForeground(bordercolor);                                             \
109     dc.drawRectangle(2, 0, width-5, 0);                                        \
110     dc.drawRectangle(2, height-1, width-5, height-1);                          \
111     dc.drawRectangle(0, 2, 0, height-5);                                       \
112     dc.drawRectangle(width-1, 2, 0, height-5);                                 \
113     dc.drawPoints(bordercorners, 4);                                           \
114     dc.setForeground(shadecolor);                                              \
115     dc.drawPoints(bordershade, 16);                                            \
116                                                                                \
117     drawGradientRectangle(dc, topcolor, bottomcolor, 2, 1, width-4, height-2); \
118     dc.setForeground(topcolor);                                                \
119     dc.drawRectangle(1, 3, 0, height-7);                                       \
120     dc.setForeground(bottomcolor);                                             \
121     dc.drawRectangle(width-2, 3, 0, height-7);
122 
123 
124 #define DRAW_CLEARLOOKS_BUTTON_DOWN                   \
125     dc.setForeground(shadecolor);                     \
126     dc.fillRectangle(0, 0, width, height);            \
127                                                       \
128     dc.setForeground(backColor);                      \
129     dc.drawPoints(basebackground, 4);                 \
130                                                       \
131     dc.setForeground(bordercolor);                    \
132     dc.drawRectangle(2, 0, width-5, 0);               \
133     dc.drawRectangle(2, height-1, width-5, height-1); \
134     dc.drawRectangle(0, 2, 0, height-5);              \
135     dc.drawRectangle(width-1, 2, 0, height-5);        \
136     dc.drawPoints(bordercorners, 4);                  \
137     dc.setForeground(shadecolor);                     \
138     dc.drawPoints(bordershade, 16);
139 
140 
141 #define DRAW_STANDARD_BUTTON_UP                                        \
142     dc.setForeground(backColor);                                       \
143     dc.fillRectangle(border, border, width-border*2, height-border*2); \
144     if (options&FRAME_THICK) {                                         \
145         drawDoubleRaisedRectangle(dc, 0, 0, width, height); }          \
146     else{                                                              \
147         drawRaisedRectangle(dc, 0, 0, width, height); }
148 
149 
150 #define DRAW_STANDARD_BUTTON_DOWN                                      \
151     dc.setForeground(hiliteColor);                                     \
152     dc.fillRectangle(border, border, width-border*2, height-border*2); \
153     if (options&FRAME_THICK) {                                         \
154         drawDoubleSunkenRectangle(dc, 0, 0, width, height); }          \
155     else{                                                              \
156         drawSunkenRectangle(dc, 0, 0, width, height); }
157 
158 
159 #define INIT_CLEARLOOKS                                                                          \
160     static FXbool init = true;                                                                   \
161     static FXbool  use_clearlooks = true;                                                        \
162     static FXColor topcolor, bottomcolor, shadecolor, bordercolor;                               \
163                                                                                                  \
164     FXPoint basebackground[4] = { FXPoint(0, 0), FXPoint(width-1, 0), FXPoint(0, height-1),      \
165                                   FXPoint(width-1, height-1) };                                  \
166     FXPoint bordershade[16] = { FXPoint(0, 1), FXPoint(1, 0), FXPoint(1, 2), FXPoint(2, 1),      \
167                                 FXPoint(width-2, 0), FXPoint(width-1, 1), FXPoint(width-3, 1),   \
168                                 FXPoint(width-2, 2), FXPoint(0, height-2), FXPoint(1, height-1), \
169                                 FXPoint(1, height-3), FXPoint(2, height-2),                      \
170                                 FXPoint(width-1, height-2), FXPoint(width-2, height-1),          \
171                                 FXPoint(width-2, height-3), FXPoint(width-3, height-2)           \
172     };                                                                                           \
173     FXPoint bordercorners[4] = { FXPoint(1, 1), FXPoint(1, height-2), FXPoint(width-2, 1),       \
174                                  FXPoint(width-2, height-2) };                                   \
175                                                                                                  \
176     if (init)                                                                                    \
177     {                                                                                            \
178         use_clearlooks = getApp()->reg().readUnsignedEntry("SETTINGS", "use_clearlooks", true);  \
179                                                                                                  \
180         if (use_clearlooks)                                                                      \
181         {                                                                                        \
182             FXuint r = FXREDVAL(baseColor);                                                      \
183             FXuint g = FXGREENVAL(baseColor);                                                    \
184             FXuint b = FXBLUEVAL(baseColor);                                                     \
185                                                                                                  \
186             topcolor = FXRGB(FXMIN(1.1*r, 255), FXMIN(1.1*g, 255), FXMIN(1.1*b, 255));           \
187             (void)topcolor;      /* Hack to avoid unused variable compiler warning */            \
188             bottomcolor = FXRGB(0.9*r, 0.9*g, 0.9*b);                                            \
189             (void)bottomcolor;   /* Hack to avoid unused variable compiler warning */            \
190             shadecolor = FXRGB(0.9*r, 0.9*g, 0.9*b);                                             \
191             bordercolor = FXRGB(0.5*r, 0.5*g, 0.5*b);                                            \
192         }                                                                                        \
193         init = false;                                                                            \
194     }
195 
196 
197 
198 //
199 // Hack of FXButton (button with gradient effect and rounded corners)
200 // Original author : Sander Jansen <sander@knology.net>
201 //
202 
203 
204 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)205 long FXButton::onPaint(FXObject*, FXSelector, void* ptr)
206 {
207     // Initialize Clearlooks
208     INIT_CLEARLOOKS
209 
210     FXEvent*   ev = (FXEvent*)ptr;
211     FXDCWindow dc(this, ev);
212     int        tw = 0, th = 0, iw = 0, ih = 0, tx, ty, ix, iy;
213 
214     // Button with nice gradient effect and rounded corners (Clearlooks)
215     if (use_clearlooks)
216     {
217         // Toolbar style
218         if (options&BUTTON_TOOLBAR)
219         {
220             // Enabled and cursor inside, and up
221             if (isEnabled() && underCursor() && (state == STATE_UP))
222             {
223                 DRAW_CLEARLOOKS_BUTTON_UP
224             }
225 
226             // Enabled and cursor inside and down
227             else if (isEnabled() && underCursor() && (state == STATE_DOWN))
228             {
229                 DRAW_CLEARLOOKS_BUTTON_DOWN
230             }
231 
232             // Enabled and checked
233             else if (isEnabled() && (state == STATE_ENGAGED))
234             {
235                 DRAW_CLEARLOOKS_BUTTON_UP
236             }
237 
238             // Disabled or unchecked or not under cursor
239             else
240             {
241                 dc.setForeground(backColor);
242                 dc.fillRectangle(0, 0, width, height);
243             }
244         }
245 
246         // Normal style
247         else
248         {
249             // Draw in up state if disabled or up
250             if (!isEnabled() || (state == STATE_UP))
251             {
252                 DRAW_CLEARLOOKS_BUTTON_UP
253             }
254 
255             // Draw in down state if enabled and either checked or pressed
256             else
257             {
258                 DRAW_CLEARLOOKS_BUTTON_DOWN
259             }
260         }
261     }   // End of gradient painting
262 
263     // Normal flat rectangular button
264     else
265     {
266         // Got a border at all?
267         if (options&(FRAME_RAISED|FRAME_SUNKEN))
268         {
269             // Toolbar style
270             if (options&BUTTON_TOOLBAR)
271             {
272                 // Enabled and cursor inside, and up
273                 if (isEnabled() && underCursor() && (state == STATE_UP))
274                 {
275                     DRAW_STANDARD_BUTTON_UP
276                 }
277 
278                 // Enabled and cursor inside and down
279                 else if (isEnabled() && underCursor() && (state == STATE_DOWN))
280                 {
281                     DRAW_STANDARD_BUTTON_DOWN
282                 }
283 
284                 // Enabled and checked
285                 else if (isEnabled() && (state == STATE_ENGAGED))
286                 {
287                     DRAW_STANDARD_BUTTON_DOWN
288                 }
289 
290                 // Disabled or unchecked or not under cursor
291                 else
292                 {
293                     dc.setForeground(backColor);
294                     dc.fillRectangle(0, 0, width, height);
295                 }
296             }
297 
298             // Normal style
299             else
300             {
301                 // Draw in up state if disabled or up
302                 if (!isEnabled() || (state == STATE_UP))
303                 {
304                     DRAW_STANDARD_BUTTON_UP
305                 }
306 
307                 // Draw sunken if enabled and either checked or pressed
308                 // Caution! This one is different!
309                 else
310                 {
311                     if (state == STATE_ENGAGED)
312                     {
313                         dc.setForeground(hiliteColor);
314                     }
315                     else
316                     {
317                         dc.setForeground(backColor);
318                     }
319                     dc.fillRectangle(border, border, width-border*2, height-border*2);
320                     if (options&FRAME_THICK)
321                     {
322                         drawDoubleSunkenRectangle(dc, 0, 0, width, height);
323                     }
324                     else
325                     {
326                         drawSunkenRectangle(dc, 0, 0, width, height);
327                     }
328                 }
329             }
330         }
331 
332         // No borders
333         else
334         {
335             if (isEnabled() && (state == STATE_ENGAGED))
336             {
337                 dc.setForeground(hiliteColor);
338                 dc.fillRectangle(0, 0, width, height);
339             }
340             else
341             {
342                 dc.setForeground(backColor);
343                 dc.fillRectangle(0, 0, width, height);
344             }
345         }
346     }   // End of normal painting
347 
348     // Place text & icon
349     if (!label.empty())
350     {
351         tw = labelWidth(label);
352         th = labelHeight(label);
353     }
354     if (icon)
355     {
356         iw = icon->getWidth();
357         ih = icon->getHeight();
358     }
359 
360     just_x(tx, ix, tw, iw);
361     just_y(ty, iy, th, ih);
362 
363     // Shift a bit when pressed
364     if (state && (options&(FRAME_RAISED|FRAME_SUNKEN)))
365     {
366         ++tx;
367         ++ty;
368         ++ix;
369         ++iy;
370     }
371 
372     // Draw enabled state
373     if (isEnabled())
374     {
375         if (icon)
376         {
377             dc.drawIcon(icon, ix, iy);
378         }
379         if (!label.empty())
380         {
381             dc.setFont(font);
382             dc.setForeground(textColor);
383             drawLabel(dc, label, hotoff, tx, ty, tw, th);
384         }
385         if (hasFocus())
386         {
387             dc.drawFocusRectangle(border+1, border+1, width-2*border-2, height-2*border-2);
388         }
389     }
390 
391     // Draw grayed-out state
392     else
393     {
394         if (icon)
395         {
396             dc.drawIconSunken(icon, ix, iy);
397         }
398         if (!label.empty())
399         {
400             dc.setFont(font);
401             dc.setForeground(hiliteColor);
402             drawLabel(dc, label, hotoff, tx+1, ty+1, tw, th);
403             dc.setForeground(shadowColor);
404             drawLabel(dc, label, hotoff, tx, ty, tw, th);
405         }
406     }
407 
408     return(1);
409 }
410 
411 
412 //
413 // Hack of FXCheckButton
414 //
415 
416 // Includes HiDPI scaling
417 
418 
419 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)420 long FXCheckButton::onPaint(FXObject*, FXSelector, void* ptr)
421 {
422     // Initialize Clearlooks (don't use the macro because here it's different)
423     static FXbool  init = true;
424     static FXbool  use_clearlooks = true;
425     static FXColor shadecolor, bordercolor;
426 
427     if (init)
428     {
429         use_clearlooks = getApp()->reg().readUnsignedEntry("SETTINGS", "use_clearlooks", true);
430 
431         if (use_clearlooks)
432         {
433             FXuint r = FXREDVAL(baseColor);
434             FXuint g = FXGREENVAL(baseColor);
435             FXuint b = FXBLUEVAL(baseColor);
436 
437             shadecolor = FXRGB(0.9*r, 0.9*g, 0.9*b);
438             bordercolor = FXRGB(0.5*r, 0.5*g, 0.5*b);
439         }
440         init = false;
441     }
442 
443     FXEvent* ev = (FXEvent*)ptr;
444     FXint    tw = 0, th = 0, tx, ty, ix, iy;
445 
446     FXDCWindow dc(this, ev);
447 
448     // Figure text size
449     if (!label.empty())
450     {
451         tw = labelWidth(label);
452         th = labelHeight(label);
453     }
454 
455     // Placement
456     just_x(tx, ix, tw, scaleint * 13);
457     just_y(ty, iy, th, scaleint * 13);
458 	ix = FXMAX(ix, 0);
459 	iy = FXMAX(iy, 0);
460 
461     // Button with nice gradient effect and rounded corners (Clearlooks)
462     if (use_clearlooks)
463     {
464         // Widget background
465         dc.setForeground(backColor);
466         dc.fillRectangle(ev->rect.x, ev->rect.y, scaleint * ev->rect.w, scaleint * ev->rect.h);
467 
468 		FXRectangle recs[4];
469 
470 		// Check background
471 		recs[0].x = ix+2*scaleint;
472 		recs[0].y = iy+2*scaleint;
473 		recs[0].w = 9*scaleint;
474 		recs[0].h = 9*scaleint;
475 		if ((check == MAYBE) || !isEnabled())
476 		{
477 			dc.setForeground(baseColor);
478 		}
479 		else
480 		{
481 			dc.setForeground(boxColor);
482 		}
483 		dc.fillRectangles(recs, 1);
484 
485 		// Check border
486 		recs[0].x = ix+2*scaleint;
487 		recs[0].y = iy+1*scaleint;
488 		recs[0].w = 9*scaleint;
489 		recs[0].h = 1*scaleint;
490 		recs[1].x = ix+2*scaleint;
491 		recs[1].y = iy+11*scaleint;
492 		recs[1].w = 9*scaleint;
493 		recs[1].h = 1*scaleint;
494 		recs[2].x = ix+1*scaleint;
495 		recs[2].y = iy+2*scaleint;
496 		recs[2].w = 1*scaleint;
497 		recs[2].h = 9*scaleint;
498 		recs[3].x = ix+11*scaleint;
499 		recs[3].y = iy+2*scaleint;
500 		recs[3].w = 1*scaleint;
501 		recs[3].h = 9*scaleint;
502         dc.setForeground(bordercolor);
503 		dc.fillRectangles(recs, 4);
504 
505 		// Check border corners
506 		recs[0].x = ix+1*scaleint;
507 		recs[0].y = iy+1*scaleint;
508 		recs[0].w = 1*scaleint;
509 		recs[0].h = 1*scaleint;
510 		recs[1].x = ix+11*scaleint;
511 		recs[1].y = iy+1*scaleint;
512 		recs[1].w = 1*scaleint;
513 		recs[1].h = 1*scaleint;
514 		recs[2].x = ix+1*scaleint;
515 		recs[2].y = iy+11*scaleint;
516 		recs[2].w = 1*scaleint;
517 		recs[2].h = 1*scaleint;
518 		recs[3].x = ix+11*scaleint;
519 		recs[3].y = iy+11*scaleint;
520 		recs[3].w = 1*scaleint;
521 		recs[3].h = 1*scaleint;
522         dc.setForeground(shadecolor);
523 		dc.fillRectangles(recs, 4);
524 
525         // Check color
526         if ((check == MAYBE) || !isEnabled())
527         {
528             dc.setForeground(shadowColor);
529         }
530         else
531         {
532             dc.setForeground(checkColor);
533         }
534     }
535 
536     // Normal flat rectangular button
537     else
538     {
539         // Widget background
540         dc.setForeground(backColor);
541         dc.fillRectangle(ev->rect.x, ev->rect.y, scaleint * ev->rect.w, scaleint * ev->rect.h);
542 
543 		FXRectangle recs[2];
544 
545 		// Check background
546 		recs[0].x = ix+2*scaleint;
547 		recs[0].y = iy+2*scaleint;
548 		recs[0].w = 9*scaleint;
549 		recs[0].h = 9*scaleint;
550 		if ((check == MAYBE) || !isEnabled())
551 		{
552 			dc.setForeground(baseColor);
553 		}
554 		else
555 		{
556 			dc.setForeground(boxColor);
557 		}
558 		dc.fillRectangles(recs, 1);
559 
560         // Check border for +
561         if (options&CHECKBUTTON_PLUS)
562         {
563             dc.setForeground(textColor);
564             dc.drawRectangle(ix+scaleint*2, iy+scaleint*2, 8*scaleint, 8*scaleint);
565         }
566 
567         // Check border for v
568         else
569         {
570 			// Check border
571 			recs[0].x = ix;
572 			recs[0].y = iy;
573 			recs[0].w = 12*scaleint;
574 			recs[0].h = 1*scaleint;
575 			recs[1].x = ix;
576 			recs[1].y = iy+1*scaleint;
577 			recs[1].w = 1*scaleint;
578 			recs[1].h = 11*scaleint;
579 			dc.setForeground(shadowColor);
580 			dc.fillRectangles(recs, 2);
581 
582 			recs[0].x = ix+1*scaleint;
583 			recs[0].y = iy+1*scaleint;
584 			recs[0].w = 10*scaleint;
585 			recs[0].h = 1*scaleint;
586 			recs[1].x = ix+1*scaleint;
587 			recs[1].y = iy+2*scaleint;
588 			recs[1].w = 1*scaleint;
589 			recs[1].h = 9*scaleint;
590 			dc.setForeground(borderColor);
591 			dc.fillRectangles(recs, 2);
592 
593 			recs[0].x = ix;
594 			recs[0].y = iy+12*scaleint;
595 			recs[0].w = 13*scaleint;
596 			recs[0].h = 1*scaleint;
597 			recs[1].x = ix+12*scaleint;
598 			recs[1].y = iy;
599 			recs[1].w = 1*scaleint;
600 			recs[1].h = 13*scaleint;
601 			dc.setForeground(hiliteColor);
602 			dc.fillRectangles(recs, 2);
603         }
604 
605         // Check color
606         if ((check == MAYBE) || !isEnabled())
607         {
608             dc.setForeground(shadowColor);
609         }
610         else
611         {
612             dc.setForeground(checkColor);
613         }
614     }
615 
616     // Show as +
617     if (options&CHECKBUTTON_PLUS)
618     {
619         if (check != true)
620         {
621             dc.fillRectangle(ix+scaleint*6, iy+scaleint*4, 1*scaleint, 5*scaleint);
622         }
623         dc.fillRectangle(ix+scaleint*4, iy+scaleint*6, 5*scaleint, 1*scaleint);
624     }
625 
626     // Show as v
627     else
628     {
629         if (check != false)
630         {
631             FXRectangle recs[7];
632             recs[0].x = ix+3*scaleint;
633             recs[0].y = iy+5*scaleint;
634             recs[0].w = 1*scaleint;
635             recs[0].h = 3*scaleint;
636             recs[1].x = ix+4*scaleint;
637             recs[1].y = iy+6*scaleint;
638             recs[1].w = 1*scaleint;
639             recs[1].h = 3*scaleint;
640             recs[2].x = ix+5*scaleint;
641             recs[2].y = iy+7*scaleint;
642             recs[2].w = 1*scaleint;
643             recs[2].h = 3*scaleint;
644             recs[3].x = ix+6*scaleint;
645             recs[3].y = iy+6*scaleint;
646             recs[3].w = 1*scaleint;
647             recs[3].h = 3*scaleint;
648             recs[4].x = ix+7*scaleint;
649             recs[4].y = iy+5*scaleint;
650             recs[4].w = 1*scaleint;
651             recs[4].h = 3*scaleint;
652             recs[5].x = ix+8*scaleint;
653             recs[5].y = iy+4*scaleint;
654             recs[5].w = 1*scaleint;
655             recs[5].h = 3*scaleint;
656             recs[6].x = ix+9*scaleint;
657             recs[6].y = iy+3*scaleint;
658             recs[6].w = 1*scaleint;
659             recs[6].h = 3*scaleint;
660 			dc.fillRectangles(recs, 7);
661         }
662     }
663 
664     // Text
665     if (!label.empty() && (label != " ") )
666     {
667         dc.setFont(font);
668         if (isEnabled())
669         {
670             dc.setForeground(textColor);
671             drawLabel(dc, label, hotoff, tx, ty, tw, th);
672             if (hasFocus())
673             {
674                 dc.drawFocusRectangle(tx-1, ty-1, tw+2, th+2);
675             }
676         }
677         else
678         {
679             dc.setForeground(hiliteColor);
680             drawLabel(dc, label, hotoff, tx+1, ty+1, tw, th);
681             dc.setForeground(shadowColor);
682             drawLabel(dc, label, hotoff, tx, ty, tw, th);
683         }
684     }
685 
686     // Frame
687     drawFrame(dc, 0, 0, width, height);
688 
689     return(1);
690 }
691 
692 
693 //
694 // Hack of FXTextField
695 //
696 
697 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)698 long FXTextField::onPaint(FXObject*, FXSelector, void* ptr)
699 {
700     // Initialize Clearlooks
701     INIT_CLEARLOOKS
702 
703     FXEvent*   ev = (FXEvent*)ptr;
704     FXDCWindow dc(this, ev);
705 
706     // Draw frame
707     drawFrame(dc, 0, 0, width, height);
708 
709     // Draw background
710     dc.setForeground(backColor);
711     dc.fillRectangle(border, border, width-(border<<1), height-(border<<1));
712 
713     // !!! Hack to get an optional rounded rectangle shape
714     // only if _TEXTFIELD_NOFRAME is not specified !!!
715     if ( (!(options&_TEXTFIELD_NOFRAME))  & use_clearlooks )
716     {
717         // Outside Background
718         dc.setForeground(baseColor);
719         dc.fillRectangle(0, 0, width, height);
720         dc.drawPoints(basebackground, 4);
721 
722         // Border
723         dc.setForeground(bordercolor);
724         dc.drawRectangle(2, 0, width-5, 0);
725         dc.drawRectangle(2, height-1, width-5, height-1);
726         dc.drawRectangle(0, 2, 0, height-5);
727         dc.drawRectangle(width-1, 2, 0, height-5);
728         dc.drawPoints(bordercorners, 4);
729         dc.setForeground(shadecolor);
730         dc.drawPoints(bordershade, 16);
731         dc.setForeground(backColor);
732         dc.fillRectangle(2, 1, width-4, height-2);
733     }
734     // !!! End of hack
735 
736     // Draw text, clipped against frame interior
737     dc.setClipRectangle(border, border, width-(border<<1), height-(border<<1));
738     drawTextRange(dc, 0, contents.length());
739 
740     // Draw caret
741     if (flags&FLAG_CARET)
742     {
743         int xx = coord(cursor)-1;
744         dc.setForeground(cursorColor);
745         dc.fillRectangle(xx, padtop+border, 1, height-padbottom-padtop-(border<<1));
746         dc.fillRectangle(xx-2, padtop+border, 5, 1);
747         dc.fillRectangle(xx-2, height-border-padbottom-1, 5, 1);
748     }
749 
750     return(1);
751 }
752 
753 
754 //
755 // Hack of FXToggleButton
756 //
757 
758 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)759 long FXToggleButton::onPaint(FXObject*, FXSelector, void* ptr)
760 {
761     // Initialize Clearlooks
762     INIT_CLEARLOOKS
763 
764     int        tw = 0, th = 0, iw = 0, ih = 0, tx, ty, ix, iy;
765     FXEvent*   ev = (FXEvent*)ptr;
766     FXDCWindow dc(this, ev);
767 
768     // Button with nice gradient effect and rounded corners (Clearlooks)
769     if (use_clearlooks)
770     {
771         // Button style is toolbar
772         if (options&TOGGLEBUTTON_TOOLBAR)
773         {
774             // Enabled and cursor inside and button down
775             if (down || ((options&TOGGLEBUTTON_KEEPSTATE) && state))
776             {
777                 DRAW_CLEARLOOKS_BUTTON_DOWN
778             }
779             // Enabled and cursor inside but button not down
780             else if (isEnabled() && underCursor())
781             {
782                 DRAW_CLEARLOOKS_BUTTON_UP
783             }
784 
785             // Disabled or unchecked or not under cursor
786             else
787             {
788                 dc.setForeground(backColor);
789                 dc.fillRectangle(0, 0, width, height);
790             }
791         }
792 
793         // Button style is normal
794         else
795         {
796             // Button down
797             if (down || ((options&TOGGLEBUTTON_KEEPSTATE) && state))
798             {
799                 DRAW_CLEARLOOKS_BUTTON_DOWN
800             }
801 
802             // Button up
803             else
804             {
805                 DRAW_CLEARLOOKS_BUTTON_UP
806             }
807         }
808     }   // End of gradient painting
809 
810     // Normal flat rectangular button
811     else
812     {
813         // Got a border at all?
814         if (options&(FRAME_RAISED|FRAME_SUNKEN))
815         {
816             // Button style is normal
817             if (options&TOGGLEBUTTON_TOOLBAR)
818             {
819                 // Enabled and cursor inside and down
820                 if (down || ((options&TOGGLEBUTTON_KEEPSTATE) && state))
821                 {
822                     DRAW_STANDARD_BUTTON_DOWN
823                 }
824 
825                 // Enabled and cursor inside, and up
826                 else if (isEnabled() && underCursor())
827                 {
828                     DRAW_STANDARD_BUTTON_UP
829                 }
830 
831                 // Disabled or unchecked or not under cursor
832                 else
833                 {
834                     dc.setForeground(backColor);
835                     dc.fillRectangle(0, 0, width, height);
836                 }
837             }
838 
839             // Button style is normal
840             else
841             {
842                 // Draw sunken if pressed
843                 if (down || ((options&TOGGLEBUTTON_KEEPSTATE) && state))
844                 {
845                     DRAW_STANDARD_BUTTON_DOWN
846                 }
847 
848                 // Draw raised if not currently pressed down
849                 else
850                 {
851                     DRAW_STANDARD_BUTTON_UP
852                 }
853             }
854         }
855 
856         // No borders
857         else
858         {
859             dc.setForeground(backColor);
860             dc.fillRectangle(0, 0, width, height);
861         }
862     }   // End of normal painting
863 
864     // Place text & icon
865     if (state && !altlabel.empty())
866     {
867         tw = labelWidth(altlabel);
868         th = labelHeight(altlabel);
869     }
870     else if (!label.empty())
871     {
872         tw = labelWidth(label);
873         th = labelHeight(label);
874     }
875     if (state && alticon)
876     {
877         iw = alticon->getWidth();
878         ih = alticon->getHeight();
879     }
880     else if (icon)
881     {
882         iw = icon->getWidth();
883         ih = icon->getHeight();
884     }
885 
886     just_x(tx, ix, tw, iw);
887     just_y(ty, iy, th, ih);
888 
889     // Shift a bit when pressed
890     if ((down || ((options&TOGGLEBUTTON_KEEPSTATE) && state)) && (options&(FRAME_RAISED|FRAME_SUNKEN)))
891     {
892         ++tx;
893         ++ty;
894         ++ix;
895         ++iy;
896     }
897 
898     // Draw enabled state
899     if (isEnabled())
900     {
901         if (state && alticon)
902         {
903             dc.drawIcon(alticon, ix, iy);
904         }
905         else if (icon)
906         {
907             dc.drawIcon(icon, ix, iy);
908         }
909         if (state && !altlabel.empty())
910         {
911             dc.setFont(font);
912             dc.setForeground(textColor);
913             drawLabel(dc, altlabel, althotoff, tx, ty, tw, th);
914         }
915         else if (!label.empty())
916         {
917             dc.setFont(font);
918             dc.setForeground(textColor);
919             drawLabel(dc, label, hotoff, tx, ty, tw, th);
920         }
921         if (hasFocus())
922         {
923             dc.drawFocusRectangle(border+1, border+1, width-2*border-2, height-2*border-2);
924         }
925     }
926 
927     // Draw grayed-out state
928     else
929     {
930         if (state && alticon)
931         {
932             dc.drawIconSunken(alticon, ix, iy);
933         }
934         else if (icon)
935         {
936             dc.drawIconSunken(icon, ix, iy);
937         }
938         if (state && !altlabel.empty())
939         {
940             dc.setFont(font);
941             dc.setForeground(hiliteColor);
942             drawLabel(dc, altlabel, althotoff, tx+1, ty+1, tw, th);
943             dc.setForeground(shadowColor);
944             drawLabel(dc, altlabel, althotoff, tx, ty, tw, th);
945         }
946         else if (!label.empty())
947         {
948             dc.setFont(font);
949             dc.setForeground(hiliteColor);
950             drawLabel(dc, label, hotoff, tx+1, ty+1, tw, th);
951             dc.setForeground(shadowColor);
952             drawLabel(dc, label, hotoff, tx, ty, tw, th);
953         }
954     }
955 
956     return(1);
957 }
958 
959 
960 //
961 // Hack of FXScrollBar
962 //
963 
964 
965 // Draw scrollbar button with gradient effect and nice grip
drawGradientScrollButton(FXDCWindow & dc,FXColor topcolor,FXColor bottomcolor,FXColor shadecolor,FXColor lightcolor,FXuint options,int x,int y,int w,int h)966 static void drawGradientScrollButton(FXDCWindow& dc, FXColor topcolor, FXColor bottomcolor, FXColor shadecolor, FXColor lightcolor,
967                                      FXuint options, int x, int y, int w, int h)
968 {
969     // Fill rectangle with gradient in the right direction (vertical or horizontal)
970     FXbool vertical = ((options&SCROLLBAR_HORIZONTAL) ? true : false);
971 
972     drawGradientRectangle(dc, topcolor, bottomcolor, x, y, w, h, vertical);
973 
974     // Draw button borders
975     dc.setForeground(lightcolor);
976     dc.fillRectangle(x+1, y+1, w-1, 1);
977     dc.fillRectangle(x+1, y+1, 1, h-2);
978     dc.setForeground(shadecolor);
979     dc.fillRectangle(x, y, w, 1);
980     dc.fillRectangle(x, y, 1, h-1);
981     dc.fillRectangle(x, y+h-1, w, 1);
982     dc.fillRectangle(x+w-1, y, 1, h);
983 
984     // Draw grip lines for horizontal scrollbar
985     if ((options&SCROLLBAR_HORIZONTAL))
986     {
987         dc.setForeground(shadecolor);
988         dc.fillRectangle(x+w/2-3, y+4, 1, h-7);
989         dc.fillRectangle(x+w/2, y+4, 1, h-7);
990         dc.fillRectangle(x+w/2+3, y+4, 1, h-7);
991         dc.setForeground(lightcolor);
992         dc.fillRectangle(x+w/2-2, y+4, 1, h-7);
993         dc.fillRectangle(x+w/2+1, y+4, 1, h-7);
994         dc.fillRectangle(x+w/2+4, y+4, 1, h-7);
995     }
996 
997     // Draw grip lines for vertical scrollbar
998     else
999     {
1000         dc.setForeground(shadecolor);
1001         dc.fillRectangle(x+4, y+h/2-3, w-7, 1);
1002         dc.fillRectangle(x+4, y+h/2, w-7, 1);
1003         dc.fillRectangle(x+4, y+h/2+3, w-7, 1);
1004         dc.setForeground(lightcolor);
1005         dc.fillRectangle(x+4, y+h/2-2, w-7, 1);
1006         dc.fillRectangle(x+4, y+h/2+1, w-7, 1);
1007         dc.fillRectangle(x+4, y+h/2+4, w-7, 1);
1008     }
1009 }
1010 
1011 
1012 // Small hack to set the minimum length of the scrollbar button to barsize*2 instead of barsize/2
setPosition(int p)1013 void FXScrollBar::setPosition(int p)
1014 {
1015     int total, travel, lo, hi, l, h;
1016 
1017     pos = p;
1018     if (pos < 0)
1019     {
1020         pos = 0;
1021     }
1022     if (pos > (range-page))
1023     {
1024         pos = range-page;
1025     }
1026     lo = thumbpos;
1027     hi = thumbpos+thumbsize;
1028     if (options&SCROLLBAR_HORIZONTAL)
1029     {
1030         total = width-height-height;
1031         thumbsize = (total*page)/range;
1032         // !!! Hack to change the minimum button size !!!
1033         if (thumbsize < (barsize<<1))
1034         {
1035             thumbsize = (barsize<<1);
1036         }
1037         // !!! End of hack !!!
1038         travel = total-thumbsize;
1039         if (range > page)
1040         {
1041             thumbpos = height+(int)((((double)pos)*travel)/(range-page));
1042         }
1043         else
1044         {
1045             thumbpos = height;
1046         }
1047         l = thumbpos;
1048         h = thumbpos+thumbsize;
1049         if ((l != lo) || (h != hi))
1050         {
1051             update(FXMIN(l, lo), 0, FXMAX(h, hi)-FXMIN(l, lo), height);
1052         }
1053     }
1054     else
1055     {
1056         total = height-width-width;
1057         thumbsize = (total*page)/range;
1058         // !!! Hack to change the minimum button size !!!
1059         if (thumbsize < (barsize<<1))
1060         {
1061             thumbsize = (barsize<<1);
1062         }
1063         // !!! End of hack !!!
1064         travel = total-thumbsize;
1065         if (range > page)
1066         {
1067             thumbpos = width+(int)((((double)pos)*travel)/(range-page));
1068         }
1069         else
1070         {
1071             thumbpos = width;
1072         }
1073         l = thumbpos;
1074         h = thumbpos+thumbsize;
1075         if ((l != lo) || (h != hi))
1076         {
1077             update(0, FXMIN(l, lo), width, FXMAX(h, hi)-FXMIN(l, lo));
1078         }
1079     }
1080 }
1081 
1082 
1083 // Arrow directions
1084 enum
1085 {
1086     _ARROW_LEFT,
1087     _ARROW_RIGHT,
1088     _ARROW_UP,
1089     _ARROW_DOWN
1090 };
1091 
1092 
1093 // Draw arrow button in scrollbar with gradient effect and rounded corners (Clearlooks)
drawGradientArrowButton(FXDCWindow & dc,FXColor backcolor,FXColor topcolor,FXColor bottomcolor,FXColor shadecolor,FXColor lightcolor,FXColor bordercolor,FXColor arrowcolor,FXuint options,int x,int y,int w,int h,FXbool down,FXuint direction)1094 static void drawGradientArrowButton(FXDCWindow& dc, FXColor backcolor, FXColor topcolor, FXColor bottomcolor, FXColor shadecolor,
1095                                     FXColor lightcolor, FXColor bordercolor, FXColor arrowcolor,
1096                                     FXuint options, int x, int y, int w, int h, FXbool down, FXuint direction)
1097 {
1098     FXPoint arrowpoints[3];
1099     int     xx, yy, ah, ab;
1100 
1101     FXPoint basebackground[2];
1102     FXPoint bordershade[8];
1103     FXPoint bordercorners[2];
1104 
1105     // Rounded corner and arrow point coordinates depend on the button direction
1106     if (direction == _ARROW_UP)
1107     {
1108         // Rounded corners
1109         basebackground[0] = FXPoint(0, 0);
1110         basebackground[1] = FXPoint(w-1, 0);
1111         bordercorners[0] = FXPoint(1, 1);
1112         bordercorners[1] = FXPoint(w-2, 1);
1113         bordershade[0] = FXPoint(0, 1);
1114         bordershade[1] = FXPoint(1, 0);
1115         bordershade[2] = FXPoint(1, 2);
1116         bordershade[3] = FXPoint(2, 1);
1117         bordershade[4] = FXPoint(w-2, 0);
1118         bordershade[5] = FXPoint(w-1, 1);
1119         bordershade[6] = FXPoint(w-3, 1);
1120         bordershade[7] = FXPoint(w-2, 2);
1121 
1122         // Arrow points
1123         ab = (w-7)|1;
1124         ah = ab>>1;
1125         xx = x+((w-ab)>>1);
1126         yy = y+((h-ah)>>1);
1127         if (down)
1128         {
1129             ++xx;
1130             ++yy;
1131         }
1132         arrowpoints[0] = FXPoint(xx+(ab>>1), yy-1);
1133         arrowpoints[1] = FXPoint(xx, yy+ah);
1134         arrowpoints[2] = FXPoint(xx+ab, yy+ah);
1135     }
1136     else if (direction == _ARROW_DOWN)
1137     {
1138         // Rounded corners
1139         basebackground[0] = FXPoint(x, y+h-1);
1140         basebackground[1] = FXPoint(x+w-1, y+h-1);
1141         bordercorners[0] = FXPoint(x+1, y+h-2);
1142         bordercorners[1] = FXPoint(x+w-2, y+h-2);
1143         bordershade[0] = FXPoint(x, y+h-2);
1144         bordershade[1] = FXPoint(x+1, y+h-1);
1145         bordershade[2] = FXPoint(x+1, y+h-3);
1146         bordershade[3] = FXPoint(x+2, y+h-2);
1147         bordershade[4] = FXPoint(x+w-1, y+h-2);
1148         bordershade[5] = FXPoint(x+w-2, y+h-1);
1149         bordershade[6] = FXPoint(x+w-2, y+h-3);
1150         bordershade[7] = FXPoint(x+w-3, y+h-2);
1151 
1152         // Arrow points
1153         ab = (w-7)|1;
1154         ah = ab>>1;
1155         xx = x+((w-ab)>>1);
1156         yy = y+((h-ah)>>1);
1157         if (down)
1158         {
1159             ++xx;
1160             ++yy;
1161         }
1162         arrowpoints[0] = FXPoint(xx+1, yy);
1163         arrowpoints[1] = FXPoint(xx+ab-1, yy);
1164         arrowpoints[2] = FXPoint(xx+(ab>>1), yy+ah);
1165     }
1166     else if (direction == _ARROW_LEFT)
1167     {
1168         // Rounded corners
1169         basebackground[0] = FXPoint(0, 0);
1170         basebackground[1] = FXPoint(0, h-1);
1171         bordercorners[0] = FXPoint(1, 1);
1172         bordercorners[1] = FXPoint(1, h-2);
1173         bordershade[0] = FXPoint(0, 1);
1174         bordershade[1] = FXPoint(1, 0);
1175         bordershade[2] = FXPoint(1, 2);
1176         bordershade[3] = FXPoint(2, 1);
1177         bordershade[4] = FXPoint(0, h-2);
1178         bordershade[5] = FXPoint(1, h-1);
1179         bordershade[6] = FXPoint(1, h-3);
1180         bordershade[7] = FXPoint(2, h-2);
1181 
1182         // Arrow points
1183         ab = (h-7)|1;
1184         ah = ab>>1;
1185         xx = x+((w-ah)>>1);
1186         yy = y+((h-ab)>>1);
1187         if (down)
1188         {
1189             ++xx;
1190             ++yy;
1191         }
1192         arrowpoints[0] = FXPoint(xx+ah, yy);
1193         arrowpoints[1] = FXPoint(xx+ah, yy+ab-1);
1194         arrowpoints[2] = FXPoint(xx, yy+(ab>>1));
1195     }
1196     else // _ARROW_RIGHT
1197     {
1198         // Rounded corners
1199         basebackground[0] = FXPoint(x+w-1, y);
1200         basebackground[1] = FXPoint(x+w-1, y+h-1);
1201         bordercorners[0] = FXPoint(x+w-2, y+1);
1202         bordercorners[1] = FXPoint(x+w-2, y+h-2);
1203         bordershade[0] = FXPoint(x+w-2, y);
1204         bordershade[1] = FXPoint(x+w-1, y+1);
1205         bordershade[2] = FXPoint(x+w-3, y+1);
1206         bordershade[3] = FXPoint(x+w-2, y+2);
1207         bordershade[4] = FXPoint(x+w-1, y+h-2);
1208         bordershade[5] = FXPoint(x+w-2, y+h-1);
1209         bordershade[6] = FXPoint(x+w-2, y+h-3);
1210         bordershade[7] = FXPoint(x+w-3, y+h-2);
1211 
1212         // Arrow points
1213         ab = (h-7)|1;
1214         ah = ab>>1;
1215         xx = x+((w-ah)>>1);
1216         yy = y+((h-ab)>>1);
1217         if (down)
1218         {
1219             ++xx;
1220             ++yy;
1221         }
1222         arrowpoints[0] = FXPoint(xx, yy);
1223         arrowpoints[1] = FXPoint(xx, yy+ab-1);
1224         arrowpoints[2] = FXPoint(xx+ah, yy+(ab>>1));
1225     }
1226 
1227     // Draw button when up
1228     if (!down)
1229     {
1230         // Fill rectangle with gradient in the right direction (vertical or horizontal)
1231         FXbool vertical = ((options&SCROLLBAR_HORIZONTAL) ? true : false);
1232         drawGradientRectangle(dc, topcolor, bottomcolor, x, y, w, h, vertical);
1233 
1234         // Button borders
1235         dc.setForeground(lightcolor);
1236         dc.fillRectangle(x+1, y+1, w-1, 1);
1237         dc.fillRectangle(x+1, y+1, 1, h-2);
1238         dc.setForeground(shadecolor);
1239         dc.fillRectangle(x, y, w, 1);
1240         dc.fillRectangle(x, y, 1, h-1);
1241         dc.fillRectangle(x, y+h-1, w, 1);
1242         dc.fillRectangle(x+w-1, y, 1, h);
1243 
1244         // Rounded corners
1245         dc.setForeground(backcolor);
1246         dc.drawPoints(basebackground, 2);
1247         dc.setForeground(shadecolor);
1248         dc.drawPoints(bordercorners, 2);
1249         dc.setForeground(bordercolor);
1250         dc.drawPoints(bordershade, 8);
1251 
1252         // Arrow
1253         dc.setForeground(arrowcolor);
1254         dc.fillPolygon(arrowpoints, 3);
1255     }
1256 
1257     // Draw button when down (pressed)
1258     else
1259     {
1260         // Dark background
1261         dc.setForeground(bordercolor);
1262         dc.fillRectangle(x, y, w, h);
1263 
1264         // Button borders
1265         dc.setForeground(lightcolor);
1266         dc.fillRectangle(x+1, y+1, w-1, 1);
1267         dc.fillRectangle(x+1, y+1, 1, h-2);
1268         dc.setForeground(shadecolor);
1269         dc.fillRectangle(x, y, w, 1);
1270         dc.fillRectangle(x, y, 1, h-1);
1271         dc.fillRectangle(x, y+h-1, w, 1);
1272         dc.fillRectangle(x+w-1, y, 1, h);
1273 
1274         // Rounded corners
1275         dc.setForeground(backcolor);
1276         dc.drawPoints(basebackground, 2);
1277         dc.setForeground(shadecolor);
1278         dc.drawPoints(bordercorners, 2);
1279         dc.setForeground(bordercolor);
1280         dc.drawPoints(bordershade, 8);
1281 
1282         // Arrow
1283         dc.setForeground(arrowcolor);
1284         dc.fillPolygon(arrowpoints, 3);
1285     }
1286 }
1287 
1288 
1289 // Draw flat scrollbar button with selected colors
drawFlatScrollButton(FXDCWindow & dc,FXint x,FXint y,FXint w,FXint h,FXbool down,FXColor hilitecolor,FXColor shadowcolor,FXColor bordercolor,FXColor scrollbarcolor)1290 static void drawFlatScrollButton(FXDCWindow& dc, FXint x, FXint y, FXint w, FXint h, FXbool down, FXColor hilitecolor, FXColor shadowcolor, FXColor bordercolor, FXColor scrollbarcolor)
1291 {
1292     dc.setForeground(scrollbarcolor);
1293     dc.fillRectangle(x+2, y+2, w-4, h-4);
1294     if (!down)
1295     {
1296         dc.setForeground(scrollbarcolor);
1297         dc.fillRectangle(x, y, w-1, 1);
1298         dc.fillRectangle(x, y, 1, h-1);
1299         dc.setForeground(hilitecolor);
1300         dc.fillRectangle(x+1, y+1, w-2, 1);
1301         dc.fillRectangle(x+1, y+1, 1, h-2);
1302         dc.setForeground(shadowcolor);
1303         dc.fillRectangle(x+1, y+h-2, w-2, 1);
1304         dc.fillRectangle(x+w-2, y+1, 1, h-2);
1305         dc.setForeground(bordercolor);
1306         dc.fillRectangle(x, y+h-1, w, 1);
1307         dc.fillRectangle(x+w-1, y, 1, h);
1308     }
1309     else
1310     {
1311         dc.setForeground(bordercolor);
1312         dc.fillRectangle(x, y, w-2, 1);
1313         dc.fillRectangle(x, y, 1, h-2);
1314         dc.setForeground(shadowcolor);
1315         dc.fillRectangle(x+1, y+1, w-3, 1);
1316         dc.fillRectangle(x+1, y+1, 1, h-3);
1317         dc.setForeground(hilitecolor);
1318         dc.fillRectangle(x, y+h-1, w-1, 1);
1319         dc.fillRectangle(x+w-1, y+1, 1, h-1);
1320         dc.setForeground(scrollbarcolor);
1321         dc.fillRectangle(x+1, y+h-2, w-1, 1);
1322         dc.fillRectangle(x+w-2, y+2, 1, h-2);
1323     }
1324 }
1325 
1326 
1327 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)1328 long FXScrollBar::onPaint(FXObject*, FXSelector, void* ptr)
1329 {
1330     // Caution! Don't use the macro here because it's slightly different
1331 
1332     static FXbool  init = true;
1333     static FXbool  use_clearlooks = true;
1334     static FXColor bg_topcolor, bg_bottomcolor, bg_shadecolor, bg_bordercolor, bg_lightcolor;
1335     static FXColor sb_topcolor, sb_bottomcolor, sb_shadecolor, sb_bordercolor, sb_lightcolor, scrollbarcolor;
1336 
1337     register FXEvent* ev = (FXEvent*)ptr;
1338     register int      total;
1339     FXDCWindow        dc(this, ev);
1340 
1341     // At first run, select the scrollbar style and color
1342     if (init)
1343     {
1344         use_clearlooks = getApp()->reg().readUnsignedEntry("SETTINGS", "use_clearlooks", true);
1345         scrollbarcolor = getApp()->reg().readColorEntry("SETTINGS", "scrollbarcolor", FXRGB(237, 233, 227));
1346 
1347         // Compute gradient colors from the base color
1348         if (use_clearlooks)
1349         {
1350             // Decompose the base color
1351             FXuint r = FXREDVAL(backColor);
1352             FXuint g = FXGREENVAL(backColor);
1353             FXuint b = FXBLUEVAL(backColor);
1354 
1355             // Compute the gradient colors from the base color (background)
1356             bg_topcolor = FXRGB(FXMIN(1.1*r, 255), FXMIN(1.1*g, 255), FXMIN(1.1*b, 255));
1357             bg_bottomcolor = FXRGB(0.9*r, 0.9*g, 0.9*b);
1358             bg_shadecolor = FXRGB(0.8*r, 0.8*g, 0.8*b);
1359             bg_bordercolor = FXRGB(0.9*r, 0.9*g, 0.9*b);
1360             bg_lightcolor = FXRGB(FXMIN(1.3*r, 255), FXMIN(1.3*g, 255), FXMIN(1.3*b, 255));
1361 
1362             // Compute the gradient colors from the base color (scrollbar)
1363             r = FXREDVAL(scrollbarcolor);
1364             g = FXGREENVAL(scrollbarcolor);
1365             b = FXBLUEVAL(scrollbarcolor);
1366             sb_topcolor = FXRGB(FXMIN(1.1*r, 255), FXMIN(1.1*g, 255), FXMIN(1.1*b, 255));
1367             sb_bottomcolor = FXRGB(0.9*r, 0.9*g, 0.9*b);
1368             sb_shadecolor = FXRGB(0.8*r, 0.8*g, 0.8*b);
1369             sb_bordercolor = FXRGB(0.9*r, 0.9*g, 0.9*b);
1370             (void)sb_bordercolor; // Hack to avoid unused variable compiler warning
1371             sb_lightcolor = FXRGB(FXMIN(1.3*r, 255), FXMIN(1.3*g, 255), FXMIN(1.3*b, 255));
1372         }
1373         init = false;
1374     }
1375 
1376     // Nice scrollbar with gradient and rounded corners
1377     if (use_clearlooks)
1378     {
1379         if (options&SCROLLBAR_HORIZONTAL)
1380         {
1381             total = width-height-height;
1382             if (thumbsize < total)                                    // Scrollable
1383             {
1384                 drawGradientScrollButton(dc, sb_topcolor, sb_bottomcolor, sb_shadecolor, sb_lightcolor, options, thumbpos, 0, thumbsize, height);
1385                 dc.setForeground(bg_bordercolor);
1386                 dc.setBackground(backColor);
1387                 dc.fillRectangle(height, 0, thumbpos-height, height);
1388                 dc.fillRectangle(thumbpos+thumbsize, 0, width-height-thumbpos-thumbsize, height);
1389             }
1390             else                                                    // Non-scrollable
1391             {
1392                 dc.setForeground(bg_bordercolor);
1393                 dc.setBackground(backColor);
1394                 dc.fillRectangle(height, 0, total, height);
1395             }
1396             drawGradientArrowButton(dc, backColor, bg_topcolor, bg_bottomcolor, bg_shadecolor, bg_lightcolor, bg_bordercolor, arrowColor, options, width-height, 0, height, height, (mode == MODE_INC), _ARROW_RIGHT);
1397             drawGradientArrowButton(dc, backColor, bg_topcolor, bg_bottomcolor, bg_shadecolor, bg_lightcolor, bg_bordercolor, arrowColor, options, 0, 0, height, height, (mode == MODE_DEC), _ARROW_LEFT);
1398         }
1399 
1400         // Vertical
1401         else
1402         {
1403             total = height-width-width;
1404             if (thumbsize < total)                                    // Scrollable
1405             {
1406                 drawGradientScrollButton(dc, sb_topcolor, sb_bottomcolor, sb_shadecolor, sb_lightcolor, options, 0, thumbpos, width, thumbsize);
1407                 dc.setForeground(bg_bordercolor);
1408                 dc.setBackground(backColor);
1409                 dc.fillRectangle(0, width, width, thumbpos-width);
1410                 dc.fillRectangle(0, thumbpos+thumbsize, width, height-width-thumbpos-thumbsize);
1411             }
1412             else                                                    // Non-scrollable
1413             {
1414                 dc.setForeground(bg_bordercolor);
1415                 dc.setBackground(backColor);
1416                 dc.fillRectangle(0, width, width, total);
1417             }
1418             drawGradientArrowButton(dc, backColor, bg_topcolor, bg_bottomcolor, bg_shadecolor, bg_lightcolor, bg_bordercolor, arrowColor, options, 0, height-width, width, width, (mode == MODE_INC), _ARROW_DOWN);
1419             drawGradientArrowButton(dc, backColor, bg_topcolor, bg_bottomcolor, bg_shadecolor, bg_lightcolor, bg_bordercolor, arrowColor, options, 0, 0, width, width, (mode == MODE_DEC), _ARROW_UP);
1420         }
1421     }
1422 
1423     // Standard (flat) scrollbar with selected color
1424     else
1425     {
1426         if (options&SCROLLBAR_HORIZONTAL)
1427         {
1428             total = width-height-height;
1429             if (thumbsize < total)                                    // Scrollable
1430             {
1431                 drawFlatScrollButton(dc, thumbpos, 0, thumbsize, height, 0, hiliteColor, shadowColor, borderColor, scrollbarcolor);
1432                 dc.setStipple(STIPPLE_GRAY);
1433                 dc.setFillStyle(FILL_OPAQUESTIPPLED);
1434                 if (mode == MODE_PAGE_DEC)
1435                 {
1436                     dc.setForeground(backColor);
1437                     dc.setBackground(shadowColor);
1438                 }
1439                 else
1440                 {
1441                     dc.setForeground(hiliteColor);
1442                     dc.setBackground(backColor);
1443                 }
1444                 dc.fillRectangle(height, 0, thumbpos-height, height);
1445                 if (mode == MODE_PAGE_INC)
1446                 {
1447                     dc.setForeground(backColor);
1448                     dc.setBackground(shadowColor);
1449                 }
1450                 else
1451                 {
1452                     dc.setForeground(hiliteColor);
1453                     dc.setBackground(backColor);
1454                 }
1455                 dc.fillRectangle(thumbpos+thumbsize, 0, width-height-thumbpos-thumbsize, height);
1456             }
1457             else                                                    // Non-scrollable
1458             {
1459                 dc.setStipple(STIPPLE_GRAY);
1460                 dc.setFillStyle(FILL_OPAQUESTIPPLED);
1461                 dc.setForeground(hiliteColor);
1462                 dc.setBackground(backColor);
1463                 dc.fillRectangle(height, 0, total, height);
1464             }
1465             dc.setFillStyle(FILL_SOLID);
1466             drawButton(dc, width-height, 0, height, height, (mode == MODE_INC));
1467             drawRightArrow(dc, width-height, 0, height, height, (mode == MODE_INC));
1468             drawButton(dc, 0, 0, height, height, (mode == MODE_DEC));
1469             drawLeftArrow(dc, 0, 0, height, height, (mode == MODE_DEC));
1470         }
1471         else
1472         {
1473             total = height-width-width;
1474             if (thumbsize < total)                                    // Scrollable
1475             {
1476                 drawFlatScrollButton(dc, 0, thumbpos, width, thumbsize, 0, hiliteColor, shadowColor, borderColor, scrollbarcolor);
1477                 dc.setStipple(STIPPLE_GRAY);
1478                 dc.setFillStyle(FILL_OPAQUESTIPPLED);
1479                 if (mode == MODE_PAGE_DEC)
1480                 {
1481                     dc.setForeground(backColor);
1482                     dc.setBackground(shadowColor);
1483                 }
1484                 else
1485                 {
1486                     dc.setForeground(hiliteColor);
1487                     dc.setBackground(backColor);
1488                 }
1489                 dc.fillRectangle(0, width, width, thumbpos-width);
1490                 if (mode == MODE_PAGE_INC)
1491                 {
1492                     dc.setForeground(backColor);
1493                     dc.setBackground(shadowColor);
1494                 }
1495                 else
1496                 {
1497                     dc.setForeground(hiliteColor);
1498                     dc.setBackground(backColor);
1499                 }
1500                 dc.fillRectangle(0, thumbpos+thumbsize, width, height-width-thumbpos-thumbsize);
1501             }
1502             else                                                    // Non-scrollable
1503             {
1504                 dc.setStipple(STIPPLE_GRAY);
1505                 dc.setFillStyle(FILL_OPAQUESTIPPLED);
1506                 dc.setForeground(hiliteColor);
1507                 dc.setBackground(backColor);
1508                 dc.fillRectangle(0, width, width, total);
1509             }
1510             dc.setFillStyle(FILL_SOLID);
1511             drawButton(dc, 0, height-width, width, width, (mode == MODE_INC));
1512             drawDownArrow(dc, 0, height-width, width, width, (mode == MODE_INC));
1513             drawButton(dc, 0, 0, width, width, (mode == MODE_DEC));
1514             drawUpArrow(dc, 0, 0, width, width, (mode == MODE_DEC));
1515         }
1516     }
1517     return(1);
1518 }
1519 
1520 
1521 //
1522 // Hack of FXComboBox
1523 //
1524 
1525 
1526 #define MENUBUTTONARROW_WIDTH     11
1527 #define MENUBUTTONARROW_HEIGHT    5
1528 
1529 
1530 // Small hack related to the Clearlooks theme
FXComboBox(FXComposite * p,int cols,FXObject * tgt,FXSelector sel,FXuint opts,int x,int y,int w,int h,int pl,int pr,int pt,int pb)1531 FXComboBox::FXComboBox(FXComposite* p, int cols, FXObject* tgt, FXSelector sel, FXuint opts, int x, int y, int w, int h, int pl, int pr, int pt, int pb) :
1532     FXPacker(p, opts, x, y, w, h, 0, 0, 0, 0, 0, 0)
1533 {
1534     flags |= FLAG_ENABLED;
1535     target = tgt;
1536     message = sel;
1537 
1538     // !!! Hack to set options to TEXTFIELD_NORMAL instead of 0 (used by the Clearlooks theme)
1539     field = new FXTextField(this, cols, this, FXComboBox::ID_TEXT, TEXTFIELD_NORMAL, 0, 0, 0, 0, pl, pr, pt, pb);
1540     // !!! End of hack
1541 
1542     if (options&COMBOBOX_STATIC)
1543     {
1544         field->setEditable(false);
1545     }
1546     pane = new FXPopup(this, FRAME_LINE);
1547     list = new FXList(pane, this, FXComboBox::ID_LIST, LIST_BROWSESELECT|LIST_AUTOSELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y|SCROLLERS_TRACK|HSCROLLER_NEVER);
1548     if (options&COMBOBOX_STATIC)
1549     {
1550         list->setScrollStyle(SCROLLERS_TRACK|HSCROLLING_OFF);
1551     }
1552     button = new FXMenuButton(this, FXString::null, NULL, pane, FRAME_RAISED|FRAME_THICK|MENUBUTTON_DOWN|MENUBUTTON_ATTACH_RIGHT, 0, 0, 0, 0, 0, 0, 0, 0);
1553     button->setXOffset(border);
1554     button->setYOffset(border);
1555 
1556     flags &= ~FLAG_UPDATE;  // Never GUI update
1557 }
1558 
1559 
1560 //
1561 // Hack of FXMenuTitle
1562 //
1563 
1564 // This hack adds an optional gradient with rounded corner theme to the menu title (Clearlooks)
1565 
1566 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)1567 long FXMenuTitle::onPaint(FXObject*, FXSelector, void* ptr)
1568 {
1569     // Initialize Clearlooks
1570     FXColor baseColor = backColor;
1571     INIT_CLEARLOOKS
1572 
1573     FXEvent*   ev = (FXEvent*)ptr;
1574     FXDCWindow dc(this, ev);
1575     FXint      xx, yy;
1576 
1577     dc.setFont(font);
1578     xx = 6;
1579     yy = 0;
1580 
1581     if (isEnabled())
1582     {
1583         if (isActive())
1584         {
1585             // Button with nice gradient effect and rounded corners (Clearlooks)
1586             if (use_clearlooks)
1587             {
1588                 dc.setForeground(selbackColor);
1589                 dc.fillRectangle(0, 0, width, height);
1590                 dc.setForeground(backColor);
1591                 dc.drawPoints(basebackground, 4);
1592                 dc.setForeground(bordercolor);
1593                 dc.drawRectangle(2, 0, width-5, 0);
1594                 dc.drawRectangle(2, height-1, width-5, height-1);
1595                 dc.drawRectangle(0, 2, 0, height-5);
1596                 dc.drawRectangle(width-1, 2, 0, height-5);
1597                 dc.drawPoints(bordercorners, 4);
1598                 dc.setForeground(selbackColor);
1599                 dc.drawPoints(bordershade, 16);
1600             }
1601 
1602             // Normal flat rectangular button
1603             else
1604             {
1605                 dc.setForeground(selbackColor);
1606                 dc.fillRectangle(1, 1, width-2, height-2);
1607                 dc.setForeground(shadowColor);
1608                 dc.fillRectangle(0, 0, width, 1);
1609                 dc.fillRectangle(0, 0, 1, height);
1610                 dc.setForeground(hiliteColor);
1611                 dc.fillRectangle(0, height-1, width, 1);
1612                 dc.fillRectangle(width-1, 0, 1, height);
1613             }
1614             xx++;
1615             yy++;
1616         }
1617         else if (underCursor())
1618         {
1619             // Button with nice gradient effect and rounded corners (Clearlooks)
1620             if (use_clearlooks)
1621             {
1622                 DRAW_CLEARLOOKS_BUTTON_UP
1623             }
1624 
1625             // Normal flat rectangular button
1626             else
1627             {
1628                 dc.setForeground(backColor);
1629                 dc.fillRectangle(1, 1, width-2, height-2);
1630                 dc.setForeground(shadowColor);
1631                 dc.fillRectangle(0, height-1, width, 1);
1632                 dc.fillRectangle(width-1, 0, 1, height);
1633                 dc.setForeground(hiliteColor);
1634                 dc.fillRectangle(0, 0, width, 1);
1635                 dc.fillRectangle(0, 0, 1, height);
1636             }
1637         }
1638 
1639         else
1640         {
1641             dc.setForeground(backColor);
1642             dc.fillRectangle(0, 0, width, height);
1643         }
1644 
1645         if (icon)
1646         {
1647             dc.drawIcon(icon, xx, yy+(height-icon->getHeight())/2);
1648             xx += 5+icon->getWidth();
1649         }
1650 
1651         if (!label.empty())
1652         {
1653             yy += font->getFontAscent()+(height-font->getFontHeight())/2;
1654             dc.setForeground(isActive() ? seltextColor : textColor);
1655             dc.drawText(xx, yy, label);
1656             if (0 <= hotoff)
1657             {
1658                 dc.fillRectangle(xx+font->getTextWidth(&label[0], hotoff), yy+1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
1659             }
1660         }
1661     }
1662 
1663     else
1664     {
1665         dc.setForeground(backColor);
1666         dc.fillRectangle(0, 0, width, height);
1667         if (icon)
1668         {
1669             dc.drawIconSunken(icon, xx, yy+(height-icon->getHeight())/2);
1670             xx += 5+icon->getWidth();
1671         }
1672         if (!label.empty())
1673         {
1674             yy += font->getFontAscent()+(height-font->getFontHeight())/2;
1675             dc.setForeground(hiliteColor);
1676             dc.drawText(xx+1, yy+1, label);
1677             if (0 <= hotoff)
1678             {
1679                 dc.fillRectangle(xx+font->getTextWidth(&label[0], hotoff), yy+1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
1680             }
1681             dc.setForeground(shadowColor);
1682             dc.drawText(xx, yy, label);
1683             if (0 <= hotoff)
1684             {
1685                 dc.fillRectangle(xx+font->getTextWidth(&label[0], hotoff), yy+1, font->getTextWidth(&label[hotoff], wclen(&label[hotoff])), 1);
1686             }
1687         }
1688     }
1689 
1690     return(1);
1691 }
1692 
1693 
1694 //
1695 // Hack of FXRadioButton
1696 //
1697 
1698 // Includes HiDPI scaling
1699 
1700 
1701 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)1702 long FXRadioButton::onPaint(FXObject*, FXSelector, void* ptr)
1703 {
1704     // Initialize Clearlooks (don't use the macro because here it's different)
1705     static FXbool  init = true;
1706     static FXbool  use_clearlooks = true;
1707     static FXColor bordercolor;
1708 
1709     if (init)
1710     {
1711         use_clearlooks = getApp()->reg().readUnsignedEntry("SETTINGS", "use_clearlooks", true);
1712 
1713         if (use_clearlooks)
1714         {
1715             FXuint r = FXREDVAL(baseColor);
1716             FXuint g = FXGREENVAL(baseColor);
1717             FXuint b = FXBLUEVAL(baseColor);
1718 
1719             bordercolor = FXRGB(0.5*r, 0.5*g, 0.5*b);
1720         }
1721         init = false;
1722     }
1723 
1724     FXEvent*    ev = (FXEvent*)ptr;
1725     FXint       tw = 0, th = 0, tx, ty, ix, iy;
1726     FXRectangle recs[6];
1727     FXDCWindow  dc(this, ev);
1728 
1729     dc.setForeground(backColor);
1730     dc.fillRectangle(ev->rect.x, ev->rect.y, ev->rect.w, ev->rect.h);
1731 
1732     if (!label.empty())
1733     {
1734         tw = labelWidth(label);
1735         th = labelHeight(label);
1736     }
1737 
1738     // Placement
1739     just_x(tx, ix, tw, scaleint * 13);
1740     just_y(ty, iy, th, scaleint * 13);
1741 	ix = FXMAX(ix, 0);
1742 	iy = FXMAX(iy, 0);
1743 
1744     // Inside
1745     recs[0].x = ix+4*scaleint;
1746     recs[0].y = iy+2*scaleint;
1747     recs[0].w = 4*scaleint;
1748     recs[0].h = 1*scaleint;
1749     recs[1].x = ix+3*scaleint;
1750     recs[1].y = iy+3*scaleint;
1751     recs[1].w = 6*scaleint;
1752     recs[1].h = 1*scaleint;
1753     recs[2].x = ix+2*scaleint;
1754     recs[2].y = iy+4*scaleint;
1755     recs[2].w = 8*scaleint;
1756     recs[2].h = 4*scaleint;
1757     recs[3].x = ix+3*scaleint;
1758     recs[3].y = iy+8*scaleint;
1759     recs[3].w = 6*scaleint;
1760     recs[3].h = 1*scaleint;
1761     recs[4].x = ix+4*scaleint;
1762     recs[4].y = iy+9*scaleint;
1763     recs[4].w = 4*scaleint;
1764     recs[4].h = 1*scaleint;
1765 
1766     if (!isEnabled())  // fix by Daniel Gehriger (gehriger@linkcad.com)
1767     {
1768         dc.setForeground(baseColor);
1769     }
1770     else
1771     {
1772         dc.setForeground(diskColor);
1773     }
1774     dc.fillRectangles(recs, 5);
1775 
1776     // Radio button with Clearlooks appearance
1777     if (use_clearlooks)
1778     {
1779         // Top left inside
1780         recs[0].x = ix+4*scaleint;
1781         recs[0].y = iy+1*scaleint;
1782         recs[0].w = 4*scaleint;
1783         recs[0].h = 1*scaleint;
1784         recs[1].x = ix+2*scaleint;
1785         recs[1].y = iy+2*scaleint;
1786         recs[1].w = 2*scaleint;
1787         recs[1].h = 1*scaleint;
1788         recs[2].x = ix+8*scaleint;
1789         recs[2].y = iy+2*scaleint;
1790         recs[2].w = 2*scaleint;
1791         recs[2].h = 1*scaleint;
1792         recs[3].x = ix+2*scaleint;
1793         recs[3].y = iy+3*scaleint;
1794         recs[3].w = 1*scaleint;
1795         recs[3].h = 1*scaleint;
1796         recs[4].x = ix+1*scaleint;
1797         recs[4].y = iy+4*scaleint;
1798         recs[4].w = 1*scaleint;
1799         recs[4].h = 4*scaleint;
1800         recs[5].x = ix+2*scaleint;
1801         recs[5].y = iy+8*scaleint;
1802         recs[5].w = 1*scaleint;
1803         recs[5].h = 2*scaleint;
1804         dc.setForeground(bordercolor);
1805         dc.fillRectangles(recs, 6);
1806 
1807         // Bottom right inside
1808         recs[0].x = ix+9*scaleint;
1809         recs[0].y = iy+3*scaleint;
1810         recs[0].w = 1*scaleint;
1811         recs[0].h = 1*scaleint;
1812         recs[1].x = ix+10*scaleint;
1813         recs[1].y = iy+4*scaleint;
1814         recs[1].w = 1*scaleint;
1815         recs[1].h = 4*scaleint;
1816         recs[2].x = ix+9*scaleint;
1817         recs[2].y = iy+8*scaleint;
1818         recs[2].w = 1*scaleint;
1819         recs[2].h = 1*scaleint;
1820         recs[3].x = ix+8*scaleint;
1821         recs[3].y = iy+9*scaleint;
1822         recs[3].w = 2*scaleint;
1823         recs[3].h = 1*scaleint;
1824         recs[4].x = ix+3*scaleint;
1825         recs[4].y = iy+9*scaleint;
1826         recs[4].w = 1*scaleint;
1827         recs[4].h = 1*scaleint;
1828         recs[5].x = ix+4*scaleint;
1829         recs[5].y = iy+10*scaleint;
1830         recs[5].w = 4*scaleint;
1831         recs[5].h = 1*scaleint;
1832         dc.setForeground(bordercolor);
1833         dc.fillRectangles(recs, 6);
1834     }
1835 
1836     // Standard radio button
1837     else
1838     {
1839         // Top left outside
1840         recs[0].x = ix+4*scaleint;
1841         recs[0].y = iy+0*scaleint;
1842         recs[0].w = 4*scaleint;
1843         recs[0].h = 1*scaleint;
1844         recs[1].x = ix+2*scaleint;
1845         recs[1].y = iy+1*scaleint;
1846         recs[1].w = 2*scaleint;
1847         recs[1].h = 1*scaleint;
1848         recs[2].x = ix+8*scaleint;
1849         recs[2].y = iy+1*scaleint;
1850         recs[2].w = 2*scaleint;
1851         recs[2].h = 1*scaleint;
1852         recs[3].x = ix+1*scaleint;
1853         recs[3].y = iy+2*scaleint;
1854         recs[3].w = 1*scaleint;
1855         recs[3].h = 2*scaleint;
1856         recs[4].x = ix+0*scaleint;
1857         recs[4].y = iy+4*scaleint;
1858         recs[4].w = 1*scaleint;
1859         recs[4].h = 4*scaleint;
1860         recs[5].x = ix+1*scaleint;
1861         recs[5].y = iy+8*scaleint;
1862         recs[5].w = 1*scaleint;
1863         recs[5].h = 2*scaleint;
1864         dc.setForeground(shadowColor);
1865         dc.fillRectangles(recs, 6);
1866 
1867         // Top left inside
1868         recs[0].x = ix+4*scaleint;
1869         recs[0].y = iy+1*scaleint;
1870         recs[0].w = 4*scaleint;
1871         recs[0].h = 1*scaleint;
1872         recs[1].x = ix+2*scaleint;
1873         recs[1].y = iy+2*scaleint;
1874         recs[1].w = 2*scaleint;
1875         recs[1].h = 1*scaleint;
1876         recs[2].x = ix+8*scaleint;
1877         recs[2].y = iy+2*scaleint;
1878         recs[2].w = 2*scaleint;
1879         recs[2].h = 1*scaleint;
1880         recs[3].x = ix+2*scaleint;
1881         recs[3].y = iy+3*scaleint;
1882         recs[3].w = 1*scaleint;
1883         recs[3].h = 1*scaleint;
1884         recs[4].x = ix+1*scaleint;
1885         recs[4].y = iy+4*scaleint;
1886         recs[4].w = 1*scaleint;
1887         recs[4].h = 4*scaleint;
1888         recs[5].x = ix+2*scaleint;
1889         recs[5].y = iy+8*scaleint;
1890         recs[5].w = 1*scaleint;
1891         recs[5].h = 2*scaleint;
1892         dc.setForeground(borderColor);
1893         dc.fillRectangles(recs, 6);
1894 
1895         // Bottom right outside
1896         recs[0].x = ix+10*scaleint;
1897         recs[0].y = iy+2*scaleint;
1898         recs[0].w = 1*scaleint;
1899         recs[0].h = 2*scaleint;
1900         recs[1].x = ix+11*scaleint;
1901         recs[1].y = iy+4*scaleint;
1902         recs[1].w = 1*scaleint;
1903         recs[1].h = 4*scaleint;
1904         recs[2].x = ix+10*scaleint;
1905         recs[2].y = iy+8*scaleint;
1906         recs[2].w = 1*scaleint;
1907         recs[2].h = 2*scaleint;
1908         recs[3].x = ix+8*scaleint;
1909         recs[3].y = iy+10*scaleint;
1910         recs[3].w = 2*scaleint;
1911         recs[3].h = 1*scaleint;
1912         recs[4].x = ix+2*scaleint;
1913         recs[4].y = iy+10*scaleint;
1914         recs[4].w = 2*scaleint;
1915         recs[4].h = 1*scaleint;
1916         recs[5].x = ix+4*scaleint;
1917         recs[5].y = iy+11*scaleint;
1918         recs[5].w = 4*scaleint;
1919         recs[5].h = 1*scaleint;
1920         dc.setForeground(hiliteColor);
1921         dc.fillRectangles(recs, 6);
1922 
1923         // Bottom right inside
1924         recs[0].x = ix+9*scaleint;
1925         recs[0].y = iy+3*scaleint;
1926         recs[0].w = 1*scaleint;
1927         recs[0].h = 1*scaleint;
1928         recs[1].x = ix+10*scaleint;
1929         recs[1].y = iy+4*scaleint;
1930         recs[1].w = 1*scaleint;
1931         recs[1].h = 4*scaleint;
1932         recs[2].x = ix+9*scaleint;
1933         recs[2].y = iy+8*scaleint;
1934         recs[2].w = 1*scaleint;
1935         recs[2].h = 1*scaleint;
1936         recs[3].x = ix+8*scaleint;
1937         recs[3].y = iy+9*scaleint;
1938         recs[3].w = 2*scaleint;
1939         recs[3].h = 1*scaleint;
1940         recs[4].x = ix+3*scaleint;
1941         recs[4].y = iy+9*scaleint;
1942         recs[4].w = 1*scaleint;
1943         recs[4].h = 1*scaleint;
1944         recs[5].x = ix+4*scaleint;
1945         recs[5].y = iy+10*scaleint;
1946         recs[5].w = 4*scaleint;
1947         recs[5].h = 1*scaleint;
1948         dc.setForeground(baseColor);
1949         dc.fillRectangles(recs, 6);
1950     }
1951 
1952     // Ball inside
1953     if (check != false)
1954     {
1955         recs[0].x = ix+5*scaleint;
1956         recs[0].y = iy+4*scaleint;
1957         recs[0].w = 2*scaleint;
1958         recs[0].h = 1*scaleint;
1959         recs[1].x = ix+4*scaleint;
1960         recs[1].y = iy+5*scaleint;
1961         recs[1].w = 4*scaleint;
1962         recs[1].h = 2*scaleint;
1963         recs[2].x = ix+5*scaleint;
1964         recs[2].y = iy+7*scaleint;
1965         recs[2].w = 2*scaleint;
1966         recs[2].h = 1*scaleint;
1967         if (isEnabled())
1968         {
1969             dc.setForeground(radioColor);
1970         }
1971         else
1972         {
1973             dc.setForeground(shadowColor);
1974         }
1975         dc.fillRectangles(recs, 3);
1976     }
1977 
1978     // Label
1979     if (!label.empty())
1980     {
1981         dc.setFont(font);
1982         if (isEnabled())
1983         {
1984             dc.setForeground(textColor);
1985             drawLabel(dc, label, hotoff, tx, ty, tw, th);
1986             if (hasFocus())
1987             {
1988                 dc.drawFocusRectangle(tx-1, ty-1, tw+2*scaleint, th+2);
1989             }
1990         }
1991         else
1992         {
1993             dc.setForeground(hiliteColor);
1994             drawLabel(dc, label, hotoff, tx+1, ty+1, tw, th);
1995             dc.setForeground(shadowColor);
1996             drawLabel(dc, label, hotoff, tx, ty, tw, th);
1997         }
1998     }
1999     drawFrame(dc, 0, 0, width, height);
2000     return(1);
2001 }
2002 
2003 
2004 //
2005 // Hack of FXMenuButton
2006 //
2007 
2008 
2009 
2010 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)2011 long FXMenuButton::onPaint(FXObject*, FXSelector, void* ptr)
2012 {
2013     // Initialize Clearlooks
2014     INIT_CLEARLOOKS
2015 
2016     int        tw = 0, th = 0, iw = 0, ih = 0, tx, ty, ix, iy;
2017     FXEvent*   ev = (FXEvent*)ptr;
2018     FXPoint    points[3];
2019     FXDCWindow dc(this, ev);
2020 
2021     // Button with nice gradient effect and rounded corners (Clearlooks)
2022     if (use_clearlooks)
2023     {
2024         // Toolbar style
2025         if (options&MENUBUTTON_TOOLBAR)
2026         {
2027             // Enabled and cursor inside, and not popped up
2028             if (isEnabled() && underCursor() && !state)
2029             {
2030                 DRAW_CLEARLOOKS_BUTTON_DOWN
2031             }
2032 
2033             // Enabled and popped up
2034             else if (isEnabled() && state)
2035             {
2036                 DRAW_CLEARLOOKS_BUTTON_UP
2037             }
2038 
2039             // Disabled or unchecked or not under cursor
2040             else
2041             {
2042                 dc.setForeground(backColor);
2043                 dc.fillRectangle(0, 0, width, height);
2044             }
2045         }
2046 
2047         // Normal style
2048         else
2049         {
2050             // Draw in up state if disabled or up
2051             if (!isEnabled() || !state)
2052             {
2053                 DRAW_CLEARLOOKS_BUTTON_UP
2054             }
2055 
2056             // If enabled and either checked or pressed
2057             else
2058             {
2059                 DRAW_CLEARLOOKS_BUTTON_DOWN
2060             }
2061         }
2062     }   // End of gradient painting
2063 
2064 
2065     // Normal flat rectangular button
2066     else
2067     {
2068         // Got a border at all?
2069         if (options&(FRAME_RAISED|FRAME_SUNKEN))
2070         {
2071             // Toolbar style
2072             if (options&MENUBUTTON_TOOLBAR)
2073             {
2074                 // Enabled and cursor inside, and not popped up
2075                 if (isEnabled() && underCursor() && !state)
2076                 {
2077                     DRAW_STANDARD_BUTTON_DOWN
2078                 }
2079 
2080                 // Enabled and popped up
2081                 else if (isEnabled() && state)
2082                 {
2083                     DRAW_STANDARD_BUTTON_UP
2084                 }
2085 
2086                 // Disabled or unchecked or not under cursor
2087                 else
2088                 {
2089                     dc.setForeground(backColor);
2090                     dc.fillRectangle(0, 0, width, height);
2091                 }
2092             }
2093 
2094             // Normal style
2095             else
2096             {
2097                 // Draw in up state if disabled or up
2098                 if (!isEnabled() || !state)
2099                 {
2100                     DRAW_STANDARD_BUTTON_UP
2101                 }
2102 
2103                 // Draw sunken if enabled and either checked or pressed
2104                 else
2105                 {
2106                     DRAW_STANDARD_BUTTON_DOWN
2107                 }
2108             }
2109         }
2110 
2111         // No borders
2112         else
2113         {
2114             if (isEnabled() && state)
2115             {
2116                 dc.setForeground(hiliteColor);
2117                 dc.fillRectangle(0, 0, width, height);
2118             }
2119             else
2120             {
2121                 dc.setForeground(backColor);
2122                 dc.fillRectangle(0, 0, width, height);
2123             }
2124         }
2125     }   // End of normal painting
2126 
2127     // Position text & icon
2128     if (!label.empty())
2129     {
2130         tw = labelWidth(label);
2131         th = labelHeight(label);
2132     }
2133 
2134     // Icon?
2135     if (icon)
2136     {
2137         iw = icon->getWidth();
2138         ih = icon->getHeight();
2139     }
2140 
2141     // Arrows?
2142     else if (!(options&MENUBUTTON_NOARROWS))
2143     {
2144         if (options&MENUBUTTON_LEFT)
2145         {
2146             ih = MENUBUTTONARROW_WIDTH;
2147             iw = MENUBUTTONARROW_HEIGHT;
2148         }
2149         else
2150         {
2151             iw = MENUBUTTONARROW_WIDTH;
2152             ih = MENUBUTTONARROW_HEIGHT;
2153         }
2154     }
2155 
2156     // Keep some room for the arrow!
2157     just_x(tx, ix, tw, iw);
2158     just_y(ty, iy, th, ih);
2159 
2160     // Move a bit when pressed
2161     if (state)
2162     {
2163         ++tx;
2164         ++ty;
2165         ++ix;
2166         ++iy;
2167     }
2168 
2169     // Draw icon
2170     if (icon)
2171     {
2172         if (isEnabled())
2173         {
2174             dc.drawIcon(icon, ix, iy);
2175         }
2176         else
2177         {
2178             dc.drawIconSunken(icon, ix, iy);
2179         }
2180     }
2181 
2182     // Draw arrows
2183     else if (!(options&MENUBUTTON_NOARROWS))
2184     {
2185         // Right arrow
2186         if ((options&MENUBUTTON_RIGHT) == MENUBUTTON_RIGHT)
2187         {
2188             if (isEnabled())
2189             {
2190                 dc.setForeground(textColor);
2191             }
2192             else
2193             {
2194                 dc.setForeground(shadowColor);
2195             }
2196             points[0].x = ix;
2197             points[0].y = iy;
2198             points[1].x = ix;
2199             points[1].y = iy+MENUBUTTONARROW_WIDTH-1;
2200             points[2].x = ix+MENUBUTTONARROW_HEIGHT;
2201             points[2].y = (short)(iy+(MENUBUTTONARROW_WIDTH>>1));
2202             dc.fillPolygon(points, 3);
2203         }
2204 
2205         // Left arrow
2206         else if (options&MENUBUTTON_LEFT)
2207         {
2208             if (isEnabled())
2209             {
2210                 dc.setForeground(textColor);
2211             }
2212             else
2213             {
2214                 dc.setForeground(shadowColor);
2215             }
2216             points[0].x = ix+MENUBUTTONARROW_HEIGHT;
2217             points[0].y = iy;
2218             points[1].x = ix+MENUBUTTONARROW_HEIGHT;
2219             points[1].y = iy+MENUBUTTONARROW_WIDTH-1;
2220             points[2].x = ix;
2221             points[2].y = (short)(iy+(MENUBUTTONARROW_WIDTH>>1));
2222             dc.fillPolygon(points, 3);
2223         }
2224 
2225         // Up arrow
2226         else if (options&MENUBUTTON_UP)
2227         {
2228             if (isEnabled())
2229             {
2230                 dc.setForeground(textColor);
2231             }
2232             else
2233             {
2234                 dc.setForeground(shadowColor);
2235             }
2236             points[0].x = (short)(ix+(MENUBUTTONARROW_WIDTH>>1));
2237             points[0].y = iy-1;
2238             points[1].x = ix;
2239             points[1].y = iy+MENUBUTTONARROW_HEIGHT;
2240             points[2].x = ix+MENUBUTTONARROW_WIDTH;
2241             points[2].y = iy+MENUBUTTONARROW_HEIGHT;
2242             dc.fillPolygon(points, 3);
2243         }
2244 
2245         // Down arrow
2246         else
2247         {
2248             if (isEnabled())
2249             {
2250                 dc.setForeground(textColor);
2251             }
2252             else
2253             {
2254                 dc.setForeground(shadowColor);
2255             }
2256             points[0].x = ix+1;
2257             points[0].y = iy;
2258             points[2].x = ix+MENUBUTTONARROW_WIDTH-1;
2259             points[2].y = iy;
2260             points[1].x = (short)(ix+(MENUBUTTONARROW_WIDTH>>1));
2261             points[1].y = iy+MENUBUTTONARROW_HEIGHT;
2262             dc.fillPolygon(points, 3);
2263         }
2264     }
2265 
2266     // Draw text
2267     if (!label.empty())
2268     {
2269         dc.setFont(font);
2270         if (isEnabled())
2271         {
2272             dc.setForeground(textColor);
2273             drawLabel(dc, label, hotoff, tx, ty, tw, th);
2274         }
2275         else
2276         {
2277             dc.setForeground(hiliteColor);
2278             drawLabel(dc, label, hotoff, tx+1, ty+1, tw, th);
2279             dc.setForeground(shadowColor);
2280             drawLabel(dc, label, hotoff, tx, ty, tw, th);
2281         }
2282     }
2283 
2284     // Draw focus
2285     if (hasFocus())
2286     {
2287         if (isEnabled())
2288         {
2289             dc.drawFocusRectangle(border+1, border+1, width-2*border-2, height-2*border-2);
2290         }
2291     }
2292     return(1);
2293 }
2294 
2295 
2296 //
2297 // Hack of FXArrowButton
2298 //
2299 
2300 
2301 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)2302 long FXArrowButton::onPaint(FXObject*, FXSelector, void* ptr)
2303 {
2304     // Initialize Clearlooks
2305     INIT_CLEARLOOKS
2306 
2307     FXEvent*   ev = (FXEvent*)ptr;
2308     FXDCWindow dc(this, ev);
2309     FXPoint    points[3];
2310     int        xx, yy, ww, hh, q;
2311 
2312     // Button with nice gradient effect and rounded corners (Clearlooks)
2313     if (use_clearlooks)
2314     {
2315         // Toolbar style
2316         if (options&ARROW_TOOLBAR)
2317         {
2318             // Enabled and cursor inside, and up
2319             if (isEnabled() && underCursor() && !state)
2320             {
2321                 DRAW_CLEARLOOKS_BUTTON_UP
2322             }
2323 
2324             // Enabled and cursor inside and down
2325             else if (isEnabled() && state)
2326             {
2327                 DRAW_CLEARLOOKS_BUTTON_DOWN
2328             }
2329 
2330             // Disabled or unchecked or not under cursor
2331             else
2332             {
2333                 dc.setForeground(backColor);
2334                 dc.fillRectangle(0, 0, width, height);
2335             }
2336         }
2337 
2338         // Normal style
2339         else
2340         {
2341             // Draw sunken if enabled and pressed
2342             if (isEnabled() && state)
2343             {
2344                 DRAW_CLEARLOOKS_BUTTON_DOWN
2345             }
2346 
2347             // Draw in up state if disabled or up
2348             else
2349             {
2350                 DRAW_CLEARLOOKS_BUTTON_UP
2351             }
2352         }
2353     }   // End of gradient painting
2354 
2355     // Normal flat rectangular button
2356     else
2357     {
2358         // With borders
2359         if (options&(FRAME_RAISED|FRAME_SUNKEN))
2360         {
2361             // Toolbar style
2362             if (options&ARROW_TOOLBAR)
2363             {
2364                 // Enabled and cursor inside, and up
2365                 if (isEnabled() && underCursor() && !state)
2366                 {
2367                     DRAW_STANDARD_BUTTON_UP
2368                 }
2369 
2370                 // Enabled and cursor inside and down
2371                 else if (isEnabled() && state)
2372                 {
2373                     DRAW_STANDARD_BUTTON_DOWN
2374                 }
2375 
2376                 // Disabled or unchecked or not under cursor
2377                 else
2378                 {
2379                     dc.setForeground(backColor);
2380                     dc.fillRectangle(0, 0, width, height);
2381                 }
2382             }
2383 
2384             // Normal style
2385             else
2386             {
2387                 // Draw sunken if enabled and pressed
2388                 if (isEnabled() && state)
2389                 {
2390                     DRAW_STANDARD_BUTTON_DOWN
2391                 }
2392 
2393                 // Draw in up state if disabled or up
2394                 else
2395                 {
2396                     DRAW_STANDARD_BUTTON_UP
2397                 }
2398             }
2399         }
2400 
2401         // No borders
2402         else
2403         {
2404             if (isEnabled() && state)
2405             {
2406                 dc.setForeground(hiliteColor);
2407                 dc.fillRectangle(0, 0, width, height);
2408             }
2409             else
2410             {
2411                 dc.setForeground(backColor);
2412                 dc.fillRectangle(0, 0, width, height);
2413             }
2414         }
2415     }   // End of normal painting
2416 
2417     // Compute size of the arrows....
2418     ww = width-padleft-padright-(border<<1);
2419     hh = height-padtop-padbottom-(border<<1);
2420     if (options&(ARROW_UP|ARROW_DOWN))
2421     {
2422         q = ww|1;
2423         if (q > (hh<<1))
2424         {
2425             q = (hh<<1)-1;
2426         }
2427         ww = q;
2428         hh = q>>1;
2429     }
2430     else
2431     {
2432         q = hh|1;
2433         if (q > (ww<<1))
2434         {
2435             q = (ww<<1)-1;
2436         }
2437         ww = q>>1;
2438         hh = q;
2439     }
2440 
2441     if (options&JUSTIFY_LEFT)
2442     {
2443         xx = padleft+border;
2444     }
2445     else if (options&JUSTIFY_RIGHT)
2446     {
2447         xx = width-ww-padright-border;
2448     }
2449     else
2450     {
2451         xx = (width-ww)/2;
2452     }
2453 
2454     if (options&JUSTIFY_TOP)
2455     {
2456         yy = padtop+border;
2457     }
2458     else if (options&JUSTIFY_BOTTOM)
2459     {
2460         yy = height-hh-padbottom-border;
2461     }
2462     else
2463     {
2464         yy = (height-hh)/2;
2465     }
2466 
2467     if (state)
2468     {
2469         ++xx;
2470         ++yy;
2471     }
2472 
2473     if (isEnabled())
2474     {
2475         dc.setForeground(arrowColor);
2476     }
2477     else
2478     {
2479         dc.setForeground(shadowColor);
2480     }
2481 
2482     // NB Size of arrow should stretch
2483     if (options&ARROW_UP)
2484     {
2485         points[0].x = xx+(ww>>1);
2486         points[0].y = yy-1;
2487         points[1].x = xx;
2488         points[1].y = yy+hh;
2489         points[2].x = xx+ww;
2490         points[2].y = yy+hh;
2491         dc.fillPolygon(points, 3);
2492     }
2493     else if (options&ARROW_DOWN)
2494     {
2495         points[0].x = xx+1;
2496         points[0].y = yy;
2497         points[1].x = xx+ww-1;
2498         points[1].y = yy;
2499         points[2].x = xx+(ww>>1);
2500         points[2].y = yy+hh;
2501         dc.fillPolygon(points, 3);
2502     }
2503     else if (options&ARROW_LEFT)
2504     {
2505         points[0].x = xx+ww;
2506         points[0].y = yy;
2507         points[1].x = xx+ww;
2508         points[1].y = yy+hh-1;
2509         points[2].x = xx;
2510         points[2].y = yy+(hh>>1);
2511         dc.fillPolygon(points, 3);
2512     }
2513     else if (options&ARROW_RIGHT)
2514     {
2515         points[0].x = xx;
2516         points[0].y = yy;
2517         points[1].x = xx;
2518         points[1].y = yy+hh-1;
2519         points[2].x = xx+ww;
2520         points[2].y = yy+(hh>>1);
2521         dc.fillPolygon(points, 3);
2522     }
2523     return(1);
2524 }
2525 
2526 
2527 //
2528 // Hack of FXProgressBar
2529 //
2530 
2531 // Note : Not implemented for the dial and vertical progress bar!
2532 //        This hacks assumes that border = 2
2533 
2534 
2535 // Draw only the interior, i.e. the part that changes
drawInterior(FXDCWindow & dc)2536 void FXProgressBar::drawInterior(FXDCWindow& dc)
2537 {
2538     static FXbool  init = true;
2539     static FXbool  use_clearlooks = true;
2540     static FXColor topcolor, bottomcolor, bordercolor;
2541 
2542     FXPoint bordercorners[4] = { FXPoint(1, 1), FXPoint(1, height-2), FXPoint(width-2, 1),
2543                                  FXPoint(width-2, height-2) };
2544 
2545     // Init Clearlooks (don't use the macro because here it's different)
2546     if (init)
2547     {
2548         use_clearlooks = getApp()->reg().readUnsignedEntry("SETTINGS", "use_clearlooks", true);
2549 
2550         if (use_clearlooks)
2551         {
2552             FXuint r = FXREDVAL(barColor);
2553             FXuint g = FXGREENVAL(barColor);
2554             FXuint b = FXBLUEVAL(barColor);
2555 
2556             topcolor = FXRGB(FXMIN(1.2*r, 255), FXMIN(1.2*g, 255), FXMIN(1.2*b, 255));
2557             bottomcolor = FXRGB(0.9*r, 0.9*g, 0.9*b);
2558 
2559             r = FXREDVAL(baseColor);
2560             g = FXGREENVAL(baseColor);
2561             b = FXBLUEVAL(baseColor);
2562 
2563             bordercolor = FXRGB(0.5*r, 0.5*g, 0.5*b);
2564         }
2565         init = false;
2566     }
2567 
2568     int  percent, barlength, barfilled, tx, ty, tw, th, n, d;
2569     char numtext[6];
2570 
2571     if (options&PROGRESSBAR_DIAL)
2572     {
2573         // If total is 0, it's 100%
2574         barfilled = 23040;
2575         percent = 100;
2576         if (total != 0)
2577         {
2578             barfilled = (FXuint)(((double)progress * (double)23040) / (double)total);
2579             percent = (FXuint)(((double)progress * 100.0) / (double)total);
2580         }
2581 
2582         tw = width-(border<<1)-padleft-padright;
2583         th = height-(border<<1)-padtop-padbottom;
2584         d = FXMIN(tw, th)-1;
2585 
2586         tx = border+padleft+((tw-d)/2);
2587         ty = border+padtop+((th-d)/2);
2588 
2589         if (barfilled != 23040)
2590         {
2591             dc.setForeground(barBGColor);
2592             dc.fillArc(tx, ty, d, d, 5760, 23040-barfilled);
2593         }
2594         if (barfilled != 0)
2595         {
2596             dc.setForeground(barColor);
2597             dc.fillArc(tx, ty, d, d, 5760, -barfilled);
2598         }
2599 
2600         // Draw outside circle
2601         dc.setForeground(borderColor);
2602         dc.drawArc(tx+1, ty, d, d, 90*64, 45*64);
2603         dc.drawArc(tx, ty+1, d, d, 135*64, 45*64);
2604         dc.setForeground(baseColor);
2605         dc.drawArc(tx-1, ty, d, d, 270*64, 45*64);
2606         dc.drawArc(tx, ty-1, d, d, 315*64, 45*64);
2607 
2608         dc.setForeground(shadowColor);
2609         dc.drawArc(tx, ty, d, d, 45*64, 180*64);
2610         dc.setForeground(hiliteColor);
2611         dc.drawArc(tx, ty, d, d, 225*64, 180*64);
2612 
2613         // Draw text
2614         if (options&PROGRESSBAR_PERCENTAGE)
2615         {
2616             dc.setFont(font);
2617             tw = font->getTextWidth("100%", 4);
2618             if (tw > (10*d)/16)
2619             {
2620                 return;
2621             }
2622             th = font->getFontHeight();
2623             if (th > d/2)
2624             {
2625                 return;
2626             }
2627             snprintf(numtext, sizeof(numtext)-1, "%d%%", percent);
2628             n = strlen(numtext);
2629             tw = font->getTextWidth(numtext, n);
2630             th = font->getFontHeight();
2631             tx = tx+d/2-tw/2;
2632             ty = ty+d/2+font->getFontAscent()+5;
2633             //dc.setForeground(textNumColor);
2634 #ifdef HAVE_XFT_H
2635             dc.setForeground(barBGColor);             // Code for XFT until XFT can use BLT_SRC_XOR_DST
2636             dc.drawText(tx-1, ty, numtext, n);
2637             dc.drawText(tx+1, ty, numtext, n);
2638             dc.drawText(tx, ty-1, numtext, n);
2639             dc.drawText(tx, ty+1, numtext, n);
2640             dc.setForeground(textNumColor);
2641             dc.drawText(tx, ty, numtext, n);
2642 #else
2643             dc.setForeground(FXRGB(255, 255, 255));     // Original code
2644             dc.setFunction(BLT_SRC_XOR_DST);
2645             dc.drawText(tx, ty, numtext, n);
2646 #endif
2647         }
2648     }
2649 
2650     // Vertical bar
2651     else if (options&PROGRESSBAR_VERTICAL)
2652     {
2653         // If total is 0, it's 100%
2654         barlength = height-border-border;
2655         barfilled = barlength;
2656         percent = 100;
2657 
2658         if (total != 0)
2659         {
2660             barfilled = (FXuint)(((double)progress * (double)barlength) / (double)total);
2661             percent = (FXuint)(((double)progress * 100.0) / (double)total);
2662         }
2663 
2664         // Draw completed bar
2665         if (0 < barfilled)
2666         {
2667 			dc.setForeground(barColor);
2668 			dc.fillRectangle(border, height-border-barfilled, width-(border<<1), barfilled);
2669         }
2670 
2671         // Draw uncompleted bar
2672         if (barfilled < barlength)
2673         {
2674 			dc.setForeground(barBGColor);
2675 			dc.fillRectangle(border, border, width-(border<<1), barlength-barfilled);
2676         }
2677 
2678         // Draw text
2679         if (options&PROGRESSBAR_PERCENTAGE)
2680         {
2681             dc.setFont(font);
2682             snprintf(numtext, sizeof(numtext)-1, "%d%%", percent);
2683             n = strlen(numtext);
2684             tw = font->getTextWidth(numtext, n);
2685             th = font->getFontHeight();
2686             ty = (height-th)/2+font->getFontAscent();
2687             tx = (width-tw)/2;
2688             if (height-border-barfilled > ty)           // In upper side
2689             {
2690                 dc.setForeground(textNumColor);
2691                 dc.setClipRectangle(border, border, width-(border<<1), height-(border<<1));
2692                 dc.drawText(tx, ty, numtext, n);
2693             }
2694             else if (ty-th > height-border-barfilled)   // In lower side
2695             {
2696                 dc.setForeground(textAltColor);
2697                 dc.setClipRectangle(border, border, width-(border<<1), height-(border<<1));
2698                 dc.drawText(tx, ty, numtext, n);
2699             }
2700             else                                      // In between!
2701             {
2702                 dc.setForeground(textAltColor);
2703                 dc.setClipRectangle(border, height-border-barfilled, width-(border<<1), barfilled);
2704                 dc.drawText(tx, ty, numtext, n);
2705                 dc.setForeground(textNumColor);
2706                 dc.setClipRectangle(border, border, width-(border<<1), barlength-barfilled);
2707                 dc.drawText(tx, ty, numtext, n);
2708                 dc.clearClipRectangle();
2709             }
2710         }
2711     }
2712 
2713     // Horizontal bar
2714     else
2715     {
2716         // If total is 0, it's 100%
2717         barlength = width-border-border;
2718         barfilled = barlength;
2719         percent = 100;
2720         if (total != 0)
2721         {
2722             barfilled = (FXuint)(((double)progress * (double)barlength) / (double)total);
2723             percent = (FXuint)(((double)progress * 100.0) / (double)total);
2724         }
2725 
2726         // Draw uncompleted bar
2727         if (barfilled < barlength)
2728         {
2729             // Clearlooks (gradient with rounded corners)
2730             if (use_clearlooks)
2731             {
2732 	            dc.setForeground(barBGColor);
2733 	            dc.fillRectangle(border+barfilled+(border>>1), border>>1, barlength-barfilled, height-border);
2734             }
2735             // Standard (flat)
2736             else
2737             {
2738 	            dc.setForeground(barBGColor);
2739 	            dc.fillRectangle(border+barfilled, border, barlength-barfilled, height-(border<<1));
2740             }
2741         }
2742 
2743         // Draw completed bar
2744         if (0 < barfilled)
2745         {
2746             // Clearlooks (gradient with rounded corners)
2747             if (use_clearlooks)
2748             {
2749                 drawGradientRectangle(dc, topcolor, bottomcolor, border-1, border-1, barfilled+2, height-border, true);
2750 
2751 				dc.setForeground(bordercolor);
2752 				dc.fillRectangle(barfilled+3, 2, 1, height-(border<<1));
2753 				dc.drawPoints(bordercorners, 4);
2754 
2755     			FXPoint barcorners[2] = { FXPoint(barfilled+2, 1), FXPoint(barfilled+2, height-border) };
2756 				dc.drawPoints(barcorners, 2);
2757 			}
2758             // Standard (flat)
2759             else
2760             {
2761                 dc.setForeground(barColor);
2762                 dc.fillRectangle(border, border, barfilled, height-(border<<1));
2763             }
2764         }
2765         // Draw text
2766         if (options&PROGRESSBAR_PERCENTAGE)
2767         {
2768             dc.setFont(font);
2769             snprintf(numtext, sizeof(numtext)-1, "%d%%", percent);
2770             n = strlen(numtext);
2771             tw = font->getTextWidth(numtext, n);
2772             th = font->getFontHeight();
2773             ty = (height-th)/2+font->getFontAscent();
2774             tx = (width-tw)/2;
2775             if (border+barfilled <= tx)           // In right side
2776             {
2777                 dc.setForeground(textNumColor);
2778                 dc.setClipRectangle(border, border, width-(border<<1), height-(border<<1));
2779                 dc.drawText(tx, ty, numtext, n);
2780             }
2781             else if (tx+tw <= border+barfilled)   // In left side
2782             {
2783                 dc.setForeground(textAltColor);
2784                 dc.setClipRectangle(border, border, width-(border<<1), height-(border<<1));
2785                 dc.drawText(tx, ty, numtext, n);
2786             }
2787             else                                // In between!
2788             {
2789                 dc.setForeground(textAltColor);
2790                 dc.setClipRectangle(border, border, barfilled, height);
2791                 dc.drawText(tx, ty, numtext, n);
2792                 dc.setForeground(textNumColor);
2793                 dc.setClipRectangle(border+barfilled, border, barlength-barfilled, height);
2794                 dc.drawText(tx, ty, numtext, n);
2795                 dc.clearClipRectangle();
2796             }
2797         }
2798     }
2799 }
2800 
2801 
2802 // Draw the progress bar
onPaint(FXObject *,FXSelector,void * ptr)2803 long FXProgressBar::onPaint(FXObject*,FXSelector,void *ptr)
2804 {
2805     // Initialize Clearlooks
2806     INIT_CLEARLOOKS
2807 
2808 	FXEvent *event=(FXEvent*)ptr;
2809 	FXDCWindow dc(this,event);
2810 
2811 	// Draw borders if any
2812 	drawFrame(dc,0,0,width,height);
2813 
2814 	// Background
2815 	dc.setForeground(getBaseColor());
2816 	dc.fillRectangle(border,border,width-(border<<1),height-(border<<1));
2817 
2818     // !!! Hack to get an optional rounded rectangle shape
2819     // only if _TEXTFIELD_NOFRAME is not specified !!!
2820     if ( (!(options&_TEXTFIELD_NOFRAME))  & use_clearlooks )
2821     {
2822         // Outside Background
2823         dc.setForeground(baseColor);
2824         dc.fillRectangle(0, 0, width, height);
2825         dc.drawPoints(basebackground, 4);
2826 
2827         // Border
2828         dc.setForeground(bordercolor);
2829         dc.drawRectangle(2, 0, width-5, 0);
2830         dc.drawRectangle(2, height-1, width-5, height-1);
2831         dc.drawRectangle(0, 2, 0, height-5);
2832         dc.drawRectangle(width-1, 2, 0, height-5);
2833         dc.drawPoints(bordercorners, 4);
2834         dc.setForeground(shadecolor);
2835         dc.drawPoints(bordershade, 16);
2836         dc.setForeground(backColor);
2837         dc.fillRectangle(2, 1, width-4, height-2);
2838     }
2839     // !!! End of hack
2840 
2841 	// Interior
2842 	drawInterior(dc);
2843 	return 1;
2844 }
2845 
2846 
2847 //
2848 // Hack of FXPacker
2849 //
2850 
2851 // This hack optionally draws a rectangle with rounded corners (Clearlooks)
drawGrooveRectangle(FXDCWindow & dc,FXint x,FXint y,FXint w,FXint h)2852 void FXPacker::drawGrooveRectangle(FXDCWindow& dc, FXint x, FXint y, FXint w, FXint h)
2853 {
2854     static FXbool  init = true;
2855     static FXbool  use_clearlooks = true;
2856     static FXColor shadecolor, bordercolor;
2857 
2858     FXPoint bordershade[16] =
2859     {
2860         FXPoint(x, y+1), FXPoint(x+1, y), FXPoint(x+1, y+2), FXPoint(x+2, y+1),
2861         FXPoint(x+w-2, y), FXPoint(x+w-1, y+1), FXPoint(x+w-3, y+1),
2862         FXPoint(x+w-2, y+2), FXPoint(x, y+h-2), FXPoint(x+1, y+h-1),
2863         FXPoint(x+1, y+h-3), FXPoint(x+2, y+h-2),
2864         FXPoint(x+w-1, y+h-2), FXPoint(x+w-2, y+h-1),
2865         FXPoint(x+w-2, y+h-3), FXPoint(x+w-3, y+h-2)
2866     };
2867     FXPoint bordercorners[4] =
2868     {
2869         FXPoint(x+1, y+1), FXPoint(x+1, y+h-2), FXPoint(x+w-2, y+1),
2870         FXPoint(x+w-2, y+h-2)
2871     };
2872 
2873     if (init)
2874     {
2875         use_clearlooks = getApp()->reg().readUnsignedEntry("SETTINGS", "use_clearlooks", true);
2876 
2877         if (use_clearlooks)
2878         {
2879             FXuint r = FXREDVAL(backColor);
2880             FXuint g = FXGREENVAL(backColor);
2881             FXuint b = FXBLUEVAL(backColor);
2882 
2883             shadecolor = FXRGB(0.9*r, 0.9*g, 0.9*b);
2884             bordercolor = FXRGB(0.5*r, 0.5*g, 0.5*b);
2885             (void)bordercolor; // Hack to avoid unused variable compiler warning
2886         }
2887         init = false;
2888     }
2889 
2890     if ((0 < w) && (0 < h))
2891     {
2892         // Rectangle with rounded corners (Clearlooks)
2893         if (use_clearlooks)
2894         {
2895             // Draw the 4 edges
2896             dc.setForeground(shadowColor);
2897             dc.drawRectangle(x+w-1, y+2, 0, h-5); // right
2898             dc.drawRectangle(x, y+2, 0, h-5);     // left
2899             dc.drawRectangle(x+2, y, w-5, 0);     // up
2900             dc.drawRectangle(x+2, y+h-1, w-5, 0); // down
2901 
2902             // Draw the 4 rounded corners (with shade)
2903             dc.setForeground(shadowColor);
2904             dc.drawPoints(bordercorners, 4);
2905             dc.setForeground(shadecolor);
2906             dc.drawPoints(bordershade, 16);
2907         }
2908 
2909         // Standard rectangle
2910         else
2911         {
2912             dc.setForeground(shadowColor);
2913             dc.fillRectangle(x, y, w, 1);
2914             dc.fillRectangle(x, y, 1, h);
2915             dc.setForeground(hiliteColor);
2916             dc.fillRectangle(x, y+h-1, w, 1);
2917             dc.fillRectangle(x+w-1, y, 1, h);
2918             if ((1 < w) && (1 < h))
2919             {
2920                 dc.setForeground(shadowColor);
2921                 dc.fillRectangle(x+1, y+h-2, w-2, 1);
2922                 dc.fillRectangle(x+w-2, y+1, 1, h-2);
2923                 dc.setForeground(hiliteColor);
2924                 dc.fillRectangle(x+1, y+1, w-3, 1);
2925                 dc.fillRectangle(x+1, y+1, 1, h-3);
2926             }
2927         }
2928     }
2929 }
2930 
2931 
2932 //
2933 // Hack of FXMenuRadio
2934 //
2935 
2936 // For HiDPI scaling
2937 
2938 #define LEADSPACE   22
2939 #define TRAILSPACE  16
2940 
2941 
2942 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)2943 long FXMenuRadio::onPaint(FXObject*,FXSelector,void* ptr)
2944 {
2945     FXEvent *ev=(FXEvent*)ptr;
2946     FXDCWindow dc(this,ev);
2947     FXint xx,yy;
2948 
2949     xx=LEADSPACE;
2950 
2951     // Grayed out
2952     if(!isEnabled())
2953     {
2954         dc.setForeground(backColor);
2955         dc.fillRectangle(0,0,width,height);
2956         if(!label.empty())
2957         {
2958             yy=font->getFontAscent()+(height-font->getFontHeight())/2;
2959             dc.setFont(font);
2960             dc.setForeground(hiliteColor);
2961             dc.drawText(xx+1,yy+1,label);
2962             if(!accel.empty()) dc.drawText(width-TRAILSPACE-font->getTextWidth(accel)+1,yy+1,accel);
2963             if(0<=hotoff) dc.fillRectangle(xx+font->getTextWidth(&label[0],hotoff)+1,yy+2,font->getTextWidth(&label[hotoff],wclen(&label[hotoff])),1);
2964             dc.setForeground(shadowColor);
2965             dc.drawText(xx,yy,label);
2966             if(!accel.empty()) dc.drawText(width-TRAILSPACE-font->getTextWidth(accel),yy,accel);
2967             if(0<=hotoff) dc.fillRectangle(xx+font->getTextWidth(&label[0],hotoff),yy+1,font->getTextWidth(&label[hotoff],wclen(&label[hotoff])),1);
2968         }
2969     }
2970 
2971     // Active
2972     else if(isActive())
2973     {
2974         dc.setForeground(selbackColor);
2975         dc.fillRectangle(0,0,width,height);
2976         if(!label.empty())
2977         {
2978             yy=font->getFontAscent()+(height-font->getFontHeight())/2;
2979             dc.setFont(font);
2980             dc.setForeground(isEnabled() ? seltextColor : shadowColor);
2981             dc.drawText(xx,yy,label);
2982             if(!accel.empty()) dc.drawText(width-TRAILSPACE-font->getTextWidth(accel),yy,accel);
2983             if(0<=hotoff) dc.fillRectangle(xx+font->getTextWidth(&label[0],hotoff),yy+1,font->getTextWidth(&label[hotoff],wclen(&label[hotoff])),1);
2984         }
2985     }
2986 
2987     // Normal
2988     else
2989     {
2990         dc.setForeground(backColor);
2991         dc.fillRectangle(0,0,width,height);
2992         if(!label.empty())
2993         {
2994             yy=font->getFontAscent()+(height-font->getFontHeight())/2;
2995             dc.setFont(font);
2996             dc.setForeground(textColor);
2997             dc.drawText(xx,yy,label);
2998             if(!accel.empty()) dc.drawText(width-TRAILSPACE-font->getTextWidth(accel),yy,accel);
2999             if(0<=hotoff) dc.fillRectangle(xx+font->getTextWidth(&label[0],hotoff),yy+1,font->getTextWidth(&label[hotoff],wclen(&label[hotoff])),1);
3000         }
3001     }
3002 
3003     // Draw the radio
3004     xx=5/scaleint;
3005     yy=(height-9*scaleint)/2;
3006 
3007     if(!isEnabled())
3008         dc.setForeground(backColor);
3009     else
3010         dc.setForeground(radioColor);
3011     dc.fillArc(xx,yy,9*scaleint,9*scaleint,0,360*64);
3012     dc.setForeground(shadowColor);
3013     dc.drawArc(xx,yy,9*scaleint,9*scaleint,0,360*64);
3014 
3015     // Draw the bullit
3016     if(check!=FALSE)
3017     {
3018         FXRectangle recs[3];
3019         recs[0].x=xx+4*scaleint;
3020         recs[0].y=yy+3*scaleint;
3021         recs[0].w=2*scaleint;
3022         recs[0].h=1*scaleint;
3023         recs[1].x=xx+3*scaleint;
3024         recs[1].y=yy+4*scaleint;
3025         recs[1].w=4*scaleint;
3026         recs[1].h=2*scaleint;
3027         recs[2].x=xx+4*scaleint;
3028         recs[2].y=yy+6*scaleint;
3029         recs[2].w=2*scaleint;
3030         recs[2].h=1*scaleint;
3031         if(isEnabled())
3032         {
3033             if(check==MAYBE)
3034                 dc.setForeground(shadowColor);
3035             else
3036                 dc.setForeground(textColor);
3037         }
3038         else
3039         {
3040             dc.setForeground(shadowColor);
3041         }
3042         dc.fillRectangles(recs,3);
3043     }
3044 
3045     return 1;
3046 }
3047 
3048 
3049 //
3050 // Hack of FXMenuCheck
3051 //
3052 
3053 // For HiDPI scaling
3054 
3055 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)3056 long FXMenuCheck::onPaint(FXObject*,FXSelector,void* ptr)
3057 {
3058     FXEvent *ev=(FXEvent*)ptr;
3059     FXDCWindow dc(this,ev);
3060     FXint xx,yy;
3061 
3062     xx=LEADSPACE;
3063 
3064     // Grayed out
3065     if(!isEnabled())
3066     {
3067         dc.setForeground(backColor);
3068         dc.fillRectangle(0,0,width,height);
3069         if(!label.empty())
3070         {
3071             yy=font->getFontAscent()+(height-font->getFontHeight())/2;
3072             dc.setFont(font);
3073             dc.setForeground(hiliteColor);
3074             dc.drawText(xx+1,yy+1,label);
3075             if(!accel.empty()) dc.drawText(width-TRAILSPACE-font->getTextWidth(accel)+1,yy+1,accel);
3076             if(0<=hotoff) dc.fillRectangle(xx+font->getTextWidth(&label[0],hotoff)+1,yy+2,font->getTextWidth(&label[hotoff],wclen(&label[hotoff])),1);
3077             dc.setForeground(shadowColor);
3078             dc.drawText(xx,yy,label);
3079             if(!accel.empty()) dc.drawText(width-TRAILSPACE-font->getTextWidth(accel),yy,accel);
3080             if(0<=hotoff) dc.fillRectangle(xx+font->getTextWidth(&label[0],hotoff),yy+1,font->getTextWidth(&label[hotoff],wclen(&label[hotoff])),1);
3081         }
3082     }
3083 
3084     // Active
3085     else if(isActive())
3086     {
3087         dc.setForeground(selbackColor);
3088         dc.fillRectangle(0,0,width,height);
3089         if(!label.empty())
3090         {
3091             yy=font->getFontAscent()+(height-font->getFontHeight())/2;
3092             dc.setFont(font);
3093             dc.setForeground(isEnabled() ? seltextColor : shadowColor);
3094             dc.drawText(xx,yy,label);
3095             if(!accel.empty()) dc.drawText(width-TRAILSPACE-font->getTextWidth(accel),yy,accel);
3096             if(0<=hotoff) dc.fillRectangle(xx+font->getTextWidth(&label[0],hotoff),yy+1,font->getTextWidth(&label[hotoff],wclen(&label[hotoff])),1);
3097         }
3098     }
3099 
3100     // Normal
3101     else
3102     {
3103         dc.setForeground(backColor);
3104         dc.fillRectangle(0,0,width,height);
3105         if(!label.empty())
3106         {
3107             yy=font->getFontAscent()+(height-font->getFontHeight())/2;
3108             dc.setFont(font);
3109             dc.setForeground(textColor);
3110             dc.drawText(xx,yy,label);
3111             if(!accel.empty()) dc.drawText(width-TRAILSPACE-font->getTextWidth(accel),yy,accel);
3112             if(0<=hotoff) dc.fillRectangle(xx+font->getTextWidth(&label[0],hotoff),yy+1,font->getTextWidth(&label[hotoff],wclen(&label[hotoff])),1);
3113         }
3114     }
3115 
3116     // Draw the box
3117     xx=5/scaleint;
3118     yy=(height-9*scaleint)/2;
3119     if(!isEnabled())
3120         dc.setForeground(backColor);
3121     else
3122         dc.setForeground(boxColor);
3123     dc.fillRectangle(xx+1,yy+1,8*scaleint,8*scaleint);
3124     dc.setForeground(shadowColor);
3125     dc.drawRectangle(xx,yy,9*scaleint,9*scaleint);
3126 
3127     // Draw the check
3128     if(check!=FALSE)
3129     {
3130 		FXRectangle recs[7];
3131 		recs[0].x = xx+2*scaleint;
3132 		recs[0].y = yy+4*scaleint;
3133 		recs[0].w = 1*scaleint;
3134 		recs[0].h = 3*scaleint;
3135 		recs[1].x = xx+3*scaleint;
3136 		recs[1].y = yy+5*scaleint;
3137 		recs[1].w = 1*scaleint;
3138 		recs[1].h = 3*scaleint;
3139 		recs[2].x = xx+4*scaleint;
3140 		recs[2].y = yy+6*scaleint;
3141 		recs[2].w = 1*scaleint;
3142 		recs[2].h = 3*scaleint;
3143 		recs[3].x = xx+5*scaleint;
3144 		recs[3].y = yy+5*scaleint;
3145 		recs[3].w = 1*scaleint;
3146 		recs[3].h = 3*scaleint;
3147 		recs[4].x = xx+6*scaleint;
3148 		recs[4].y = yy+4*scaleint;
3149 		recs[4].w = 1*scaleint;
3150 		recs[4].h = 3*scaleint;
3151 		recs[5].x = xx+7*scaleint;
3152 		recs[5].y = yy+3*scaleint;
3153 		recs[5].w = 1*scaleint;
3154 		recs[5].h = 3*scaleint;
3155 		recs[6].x = xx+8*scaleint;
3156 		recs[6].y = yy+2*scaleint;
3157 		recs[6].w = 1*scaleint;
3158 		recs[6].h = 3*scaleint;
3159 
3160         if(isEnabled())
3161         {
3162             if(check==MAYBE)
3163                 dc.setForeground(shadowColor);
3164             else
3165                 dc.setForeground(textColor);
3166         }
3167         else
3168         {
3169             dc.setForeground(shadowColor);
3170         }
3171         dc.fillRectangles(recs, 7);
3172     }
3173 
3174     return 1;
3175 }
3176 
3177 
3178 //
3179 // Hack of FXTreeList
3180 //
3181 
3182 // For HiDPI scaling
3183 
3184 
3185 #define SIDE_SPACING        4   // Spacing between side and item
3186 #define HALFBOX_SIZE        4   // Half box size
3187 
3188 // Draw item list
onPaint(FXObject *,FXSelector,void * ptr)3189 long FXTreeList::onPaint(FXObject*,FXSelector,void* ptr)
3190 {
3191     FXEvent* event=(FXEvent*)ptr;
3192     FXTreeItem* item=firstitem;
3193     FXTreeItem* p;
3194     FXint yh,xh,x,y,w,h,xp,hh;
3195     FXDCWindow dc(this,event);
3196     dc.setFont(font);
3197     x=pos_x;
3198     y=pos_y;
3199     if(options&TREELIST_ROOT_BOXES) x+=(4+indent);
3200     while(item && y<event->rect.y+event->rect.h)
3201     {
3202         w=item->getWidth(this);
3203         h=item->getHeight(this);
3204         if(event->rect.y<=y+h)
3205         {
3206             // Draw item
3207             dc.setForeground(backColor);
3208             dc.fillRectangle(0,y,width,h);
3209             item->draw(this,dc,x,y,w,h);
3210 
3211             // Show other paraphernalia such as dotted lines and expand-boxes
3212             if((options&(TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES)) && (item->parent || (options&TREELIST_ROOT_BOXES)))
3213             {
3214                 hh=h/2;
3215                 yh=y+hh;
3216                 xh=x-indent+(SIDE_SPACING/2) - (scaleint - 1) * SIDE_SPACING;
3217                 dc.setForeground(lineColor);
3218                 dc.setBackground(backColor);
3219                 dc.setStipple(STIPPLE_GRAY,pos_x&1,pos_y&1);
3220                 if(options&TREELIST_SHOWS_LINES)                    // Connect items with lines
3221                 {
3222                     p=item->parent;
3223                     xp=xh;
3224                     dc.setFillStyle(FILL_OPAQUESTIPPLED);
3225                     while(p)
3226                     {
3227                         xp-=(indent+p->getHeight(this)/2);
3228                         if(p->next) dc.fillRectangle(xp,y,1,h);
3229                         p=p->parent;
3230                     }
3231                     if((options&TREELIST_SHOWS_BOXES) && (item->hasItems() || item->getFirst()))
3232                     {
3233                         if(item->prev || item->parent) dc.fillRectangle(xh,y,1,yh-y-scaleint*HALFBOX_SIZE);
3234                         if(item->next) dc.fillRectangle(xh,yh+scaleint*HALFBOX_SIZE,1,(y+h-yh-scaleint*HALFBOX_SIZE));
3235                     }
3236                     else
3237                     {
3238                         if(item->prev || item->parent) dc.fillRectangle(xh,y,1,hh);
3239                         if(item->next) dc.fillRectangle(xh,yh,1,h);
3240                         dc.fillRectangle(xh,yh,x+(SIDE_SPACING/2)-scaleint*2-xh,1);
3241                     }
3242                     dc.setFillStyle(FILL_SOLID);
3243                 }
3244 
3245                 // Boxes before items for expand/collapse of item
3246                 if((options&TREELIST_SHOWS_BOXES) && (item->hasItems() || item->getFirst()))
3247                 {
3248                     dc.setFillStyle(FILL_OPAQUESTIPPLED);
3249                     dc.fillRectangle((xh+scaleint*4),yh,scaleint*( (SIDE_SPACING/2)-2 ),scaleint*1);
3250                     dc.setFillStyle(FILL_SOLID);
3251                     dc.drawRectangle(xh-scaleint*HALFBOX_SIZE,yh-scaleint*HALFBOX_SIZE, scaleint*(HALFBOX_SIZE+HALFBOX_SIZE),scaleint*(HALFBOX_SIZE+HALFBOX_SIZE));
3252                     dc.setForeground(textColor);
3253                     dc.fillRectangle(xh-scaleint*(HALFBOX_SIZE-2),yh,scaleint*(HALFBOX_SIZE+HALFBOX_SIZE-3),scaleint*1);
3254                     if(!(options&TREELIST_AUTOSELECT) && !item->isExpanded())
3255                     {
3256                         dc.fillRectangle(xh,yh-scaleint*(HALFBOX_SIZE-2),scaleint*1,scaleint*(HALFBOX_SIZE+HALFBOX_SIZE-3));
3257                     }
3258                 }
3259             }
3260         }
3261 
3262         y+=h;
3263 
3264         // Move on to the next item
3265         if(item->first && ((options&TREELIST_AUTOSELECT) || item->isExpanded()))
3266         {
3267             x+=(indent+h/2);
3268             item=item->first;
3269             continue;
3270         }
3271         while(!item->next && item->parent)
3272         {
3273             item=item->parent;
3274             x-=(indent+item->getHeight(this)/2);
3275         }
3276         item=item->next;
3277     }
3278     if(y<event->rect.y+event->rect.h)
3279     {
3280         dc.setForeground(backColor);
3281         dc.fillRectangle(event->rect.x,y,event->rect.w,event->rect.y+event->rect.h-y);
3282     }
3283     return 1;
3284 }
3285 
3286