1 /* These widgets have initially been created by Martin Oberzalek who gave them into
2  * the public domain via an email to the mailing list foxgui-users on 17th of June, 2010
3  * ("here the source. Free to use for alll.").
4  * I (Martin Preuss) adapted them to be usable with FOX 1.6 and also added some widgets of
5  * my own (for now: ThemeHeaderItem).
6  */
7 
8 #ifdef HAVE_CONFIG_H
9 # include <config.h>
10 #endif
11 
12 
13 #include "theme.h"
14 
15 #define ICON_SPACING  4
16 
17 
18 // Draw rectangle
drawRectangle(FXDC & dc,FXColor lower,FXColor upper,FXint x,FXint y,FXint w,FXint h)19 static void drawRectangle(FXDC& dc,FXColor lower,FXColor upper,FXint x,FXint y,FXint w,FXint h) {
20   register FXint rr,gg,bb,dr,dg,db,r1,g1,b1,r2,g2,b2,yl,yh,yy,dy,n,t;
21   const FXint MAXSTEPS=128;
22 
23   if(0<w && 0<h) {
24     dc.setStipple(STIPPLE_NONE);
25     dc.setFillStyle(FILL_SOLID);
26 
27     r1=FXREDVAL(lower);
28     r2=FXREDVAL(upper);
29     dr=r2-r1;
30     g1=FXGREENVAL(lower);
31     g2=FXGREENVAL(upper);
32     dg=g2-g1;
33     b1=FXBLUEVAL(lower);
34     b2=FXBLUEVAL(upper);
35     db=b2-b1;
36 
37     n=FXABS(dr);
38     if((t=FXABS(dg))>n) n=t;
39     if((t=FXABS(db))>n) n=t;
40     n++;
41     if(n>h) n=h;
42     if(n>MAXSTEPS) n=MAXSTEPS;
43     rr=(r1<<16)+32767;
44     gg=(g1<<16)+32767;
45     bb=(b1<<16)+32767;
46     yy=32767;
47 
48     dr=(dr<<16)/n;
49     dg=(dg<<16)/n;
50     db=(db<<16)/n;
51     dy=(h<<16)/n;
52 
53     do {
54       yl=yy>>16;
55       yy+=dy;
56       yh=yy>>16;
57       dc.setForeground(FXRGB(rr>>16,gg>>16,bb>>16));
58       dc.fillRectangle(x,y+yl,w,yh-yl);
59       rr+=dr;
60       gg+=dg;
61       bb+=db;
62     }
63     while(yh<h);
64   }
65 }
66 
67 
68 
69 
70 FXDEFMAP(ThemeButton) ThemeButtonMap[]= {
71   FXMAPFUNC( SEL_PAINT, 0, ThemeButton::onPaint)
72 };
73 
74 FXIMPLEMENT( ThemeButton, FXButton, ThemeButtonMap, ARRAYNUMBER(ThemeButtonMap) );
75 
76 
ThemeButton(FXComposite * p,const FXString & text,FXIcon * ic,FXObject * tgt,FXSelector sel,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb)77 ThemeButton::ThemeButton(FXComposite* p, const FXString& text, FXIcon* ic,
78                          FXObject* tgt, FXSelector sel, FXuint opts,
79                          FXint x, FXint y, FXint w, FXint h,
80                          FXint pl, FXint pr, FXint pt, FXint pb)
81   : FXButton( p, text, ic, tgt, sel, opts, x, y, w, h, pl, pr, pt, pb )
82 {}
83 
84 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)85 long ThemeButton::onPaint(FXObject*,FXSelector,void* ptr) {
86   FXint tw=0,th=0,iw=0,ih=0,tx,ty,ix,iy;
87   FXEvent*ev=(FXEvent*)ptr;
88   FXDCWindow dc(this,ev);
89 
90 
91   FXColor top         = FXRGB(0xfe,0xfd,0xfd);
92   FXColor bottom      = FXRGB(0xdd,0xd7,0xce);
93   FXColor shade       = FXRGB(0xdc,0xd9,0xd4);
94 
95 // 	FXColor bordercolor = FXRGB(0x78,0x70,0x63);
96 
97   FXColor bordercolor = FXRGB(123,158,189);
98 
99   /*
100     FXPoint borderbackground[12]={FXPoint(0,0),FXPoint(0,1),FXPoint(1,0),
101     FXPoint(width-1,0),FXPoint(width-2,0),FXPoint(width-1,1),
102     FXPoint(0,height-1),FXPoint(0,height-2),FXPoint(1,height-1),
103     FXPoint(width-1,height-1),FXPoint(width-1,height-2),FXPoint(width-2,height-1)};
104   */
105   FXPoint basebackground[4]= {FXPoint(0,0),FXPoint(width-1,0),FXPoint(0,height-1),FXPoint(width-1,height-1)};
106 
107   FXPoint bordershade[16]= {
108     FXPoint(0,1),FXPoint(1,0),FXPoint(1,2),FXPoint(2,1),
109     FXPoint(width-2,0),FXPoint(width-1,1),FXPoint(width-3,1),FXPoint(width-2,2),
110     FXPoint(0,height-2),FXPoint(1,height-1),FXPoint(1,height-3),FXPoint(2,height-2),
111     FXPoint(width-1,height-2),FXPoint(width-2,height-1),FXPoint(width-2,height-3),FXPoint(width-3,height-2)
112   };
113   FXPoint bordercorners[4]= {
114     FXPoint(1,1),FXPoint(1,height-2),FXPoint(width-2,1),FXPoint(width-2,height-2)
115   };
116 
117 
118   if (options&BUTTON_TOOLBAR && !underCursor()) {
119     dc.setForeground(baseColor);
120     dc.fillRectangle(0,0,width,height);
121   }
122   else if (state==STATE_UP && ((options&BUTTON_TOOLBAR)==0 || (options&BUTTON_TOOLBAR && underCursor()))) {
123     /// Outside Background
124     dc.setForeground(baseColor);
125     dc.drawPoints(basebackground,4);
126     /// Border
127     dc.setForeground(bordercolor);
128     dc.drawRectangle(2,0,width-5,0);
129     dc.drawRectangle(2,height-1,width-5,height-1);
130     dc.drawRectangle(0,2,0,height-5);
131     dc.drawRectangle(width-1,2,width-1,height-5);
132     dc.drawPoints(bordercorners,4);
133     dc.setForeground(shade);
134     dc.drawPoints(bordershade,16);
135     /// Gradient
136     drawRectangle(dc,top,bottom,2,1,width-4,height-2);
137     dc.setForeground(top);
138     dc.drawRectangle(1,3,0,height-7);
139     dc.setForeground(bottom);
140     dc.drawRectangle(width-2,3,0,height-7);
141   }
142   else {
143     /// Outside Background
144     dc.setForeground(baseColor);
145     dc.drawPoints(basebackground,4);
146     /// Border
147     dc.setForeground(bordercolor);
148     dc.drawRectangle(2,0,width-5,0);
149     dc.drawRectangle(2,height-1,width-5,height-1);
150     dc.drawRectangle(0,2,0,height-5);
151     dc.drawRectangle(width-1,2,width-1,height-5);
152     dc.drawPoints(bordercorners,4);
153     dc.setForeground(shade);
154     dc.drawPoints(bordershade,16);
155 
156     dc.setForeground(FXRGB(0xdc,0xd4,0xc9));
157     dc.fillRectangle(2,1,width-4,height-2);
158   }
159 
160   // Place text & icon
161   if(!label.empty()) {
162     tw=labelWidth(label);
163     th=labelHeight(label);
164   }
165   if(icon) {
166     iw=icon->getWidth();
167     ih=icon->getHeight();
168   }
169 
170   just_x(tx,ix,tw,iw);
171   just_y(ty,iy,th,ih);
172 
173   // Shift a bit when pressed
174   if (state && (options&(FRAME_RAISED|FRAME_SUNKEN))) {
175     ++tx;
176     ++ty;
177     ++ix;
178     ++iy;
179   }
180 
181   // Draw enabled state
182   if(isEnabled()) {
183     if(icon) {
184       dc.drawIcon(icon,ix,iy);
185     }
186     if(!label.empty()) {
187       dc.setFont(font);
188       dc.setForeground(textColor);
189       drawLabel(dc,label,hotoff,tx,ty,tw,th);
190     }
191     if(hasFocus()) {
192       dc.drawFocusRectangle(border+1,border+1,width-2*border-2,height-2*border-2);
193     }
194   }
195 
196   // Draw grayed-out state
197   else {
198     if (icon) {
199       dc.drawIconSunken(icon,ix,iy);
200     }
201     if(!label.empty()) {
202       dc.setFont(font);
203       dc.setForeground(hiliteColor);
204       drawLabel(dc,label,hotoff,tx+1,ty+1,tw,th);
205       dc.setForeground(shadowColor);
206       drawLabel(dc,label,hotoff,tx,ty,tw,th);
207     }
208   }
209   return 1;
210 }
211 
212 
213 
214 
215 FXDEFMAP(ThemeTextField) ThemeTextFieldMap[]= {
216   FXMAPFUNC( SEL_PAINT, 0, ThemeTextField::onPaint)
217 };
218 
219 FXIMPLEMENT( ThemeTextField, FXTextField, ThemeTextFieldMap, ARRAYNUMBER(ThemeTextFieldMap) );
220 
ThemeTextField(FXComposite * p,FXint ncols,FXObject * tgt,FXSelector sel,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb)221 ThemeTextField::ThemeTextField(FXComposite* p,FXint ncols,FXObject* tgt,FXSelector sel,
222                                FXuint opts,FXint x,FXint y,FXint w,FXint h,
223                                FXint pl,FXint pr,FXint pt,FXint pb)
224   : FXTextField( p, ncols, tgt, sel, opts, x, y, w, h, pl, pr, pt, pb ) {
225 
226 }
227 
drawFrame(FXDCWindow & dc,FXint x,FXint y,FXint w,FXint h)228 static void drawFrame(FXDCWindow& dc,FXint x,FXint y,FXint w,FXint h) {
229   if(0<w && 0<h) {
230     dc.setForeground(FXRGB(123,158,189));
231     dc.fillRectangle(x,y,w,1);
232     dc.fillRectangle(x,y,1,h);
233     // dc.setForeground(hiliteColor);
234     dc.fillRectangle(x,y+h-1,w,1);
235     dc.fillRectangle(x+w-1,y,1,h);
236   }
237 }
238 
239 
240 
241 
drawSunkenFrame(FXDCWindow & dc,FXint x,FXint y,FXint w,FXint h)242 static void drawSunkenFrame(FXDCWindow& dc,FXint x,FXint y,FXint w,FXint h) {
243   if(0<w && 0<h) {
244     dc.setForeground(FXRGB(255,158,100));
245     dc.fillRectangle(x,y,w,1);
246     dc.fillRectangle(x,y,1,h);
247     // dc.setForeground(hiliteColor);
248     dc.fillRectangle(x,y+h-1,w,1);
249     dc.fillRectangle(x+w-1,y,1,h);
250 
251     if(1<w && 1<h) {
252       dc.fillRectangle(x+1,y+1,w-3,1);
253       dc.fillRectangle(x+1,y+1,1,h-3);
254       dc.fillRectangle(x+1,y+h-2,w-2,1);
255       dc.fillRectangle(x+w-2,y+1,1,h-2);
256     }
257   }
258 }
259 
260 
261 
drawHighlightFrame(FXDCWindow & dc,FXint x,FXint y,FXint w,FXint h)262 static void drawHighlightFrame(FXDCWindow& dc,FXint x,FXint y,FXint w,FXint h) {
263   if (0<w && 0<h) {
264     dc.setForeground(FXRGB(123,158,255));
265     dc.fillRectangle(x,y,w,1);
266     dc.fillRectangle(x,y,1,h);
267     // dc.setForeground(hiliteColor);
268     dc.fillRectangle(x,y+h-1,w,1);
269     dc.fillRectangle(x+w-1,y,1,h);
270 
271     if (1<w && 1<h) {
272       dc.fillRectangle(x+1,y+1,w-3,1);
273       dc.fillRectangle(x+1,y+1,1,h-3);
274       dc.fillRectangle(x+1,y+h-2,w-2,1);
275       dc.fillRectangle(x+w-2,y+1,1,h-2);
276     }
277   }
278 }
279 
280 
281 
onPaint(FXObject *,FXSelector,void * ptr)282 long ThemeTextField::onPaint(FXObject*,FXSelector,void* ptr) {
283   FXEvent *ev=(FXEvent*)ptr;
284   FXDCWindow dc(this,ev);
285 
286   // Set font
287   dc.setFont(font);
288 
289   // Draw frame
290   ::drawFrame(dc,0,0,width,height);
291 
292   // Gray background if disabled
293   dc.setForeground(isEnabled() ? backColor : baseColor);
294 
295   // Draw background
296   dc.fillRectangle(border,border,width-(border<<1),height-(border<<1));
297 
298   // Draw text, clipped against frame interior
299   dc.setClipRectangle(border,border,width-(border<<1),height-(border<<1));
300   drawTextRange(dc,0,contents.length());
301 
302   // Draw caret
303   if (flags&FLAG_CARET) {
304     int xx=coord(cursor)-1;
305     dc.setForeground(cursorColor);
306     dc.fillRectangle(xx,padtop+border,1,height-padbottom-padtop-(border<<1));
307     dc.fillRectangle(xx-2,padtop+border,5,1);
308     dc.fillRectangle(xx-2,height-border-padbottom-1,5,1);
309   }
310   return 1;
311 }
312 
313 
314 
315 struct ColorTheme {
316   const FXchar* name;
317   FXColor base;
318   FXColor border;
319   FXColor back;
320   FXColor fore;
321   FXColor selback;
322   FXColor selfore;
323   FXColor tipback;
324   FXColor tipfore;
325   FXColor menuback;
326   FXColor menufore;
327 };
328 
329 
330 const ColorTheme ColorThemes[]= {
331   {"Redmond XP",FXRGB(238,238,230),FXRGB(  0,  0,  0),FXRGB(255,255,255),FXRGB(  0,  0,  0),FXRGB( 74,121,205),FXRGB(255,255,255),FXRGB(255,255,225),FXRGB(  0,  0,  0),FXRGB( 74,121,205),FXRGB(255,255,255)}
332 };
333 
334 
335 
init_theme(FXApp * app)336 void init_theme(FXApp *app) {
337   app->setBaseColor( ColorThemes[0].base );
338   app->setBorderColor( ColorThemes[0].border );
339   app->setBackColor( ColorThemes[0].back );
340   app->setForeColor( ColorThemes[0].fore );
341   app->setSelforeColor( ColorThemes[0].selfore );
342   app->setSelbackColor( ColorThemes[0].selback );
343   app->setTipforeColor( ColorThemes[0].tipfore );
344   app->setTipbackColor( ColorThemes[0].tipback );
345   app->setSelMenuTextColor( ColorThemes[0].menufore );
346   app->setSelMenuBackColor( ColorThemes[0].menuback );
347   // app->setHiliteColor(FXRGB(123,158,189));
348 }
349 
350 
351 
352 
353 FXDEFMAP(ThemeComboBox) ThemeComboBoxMap[]= {
354   FXMAPFUNC( SEL_PAINT, 0, ThemeComboBox::onPaint)
355 };
356 
357 FXIMPLEMENT( ThemeComboBox, FXComboBox, ThemeComboBoxMap, ARRAYNUMBER(ThemeComboBoxMap) );
358 
ThemeComboBox(FXComposite * p,FXint cols,FXObject * tgt,FXSelector sel,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb)359 ThemeComboBox::ThemeComboBox(FXComposite *p,FXint cols,FXObject* tgt,FXSelector sel,FXuint opts,
360                              FXint x,FXint y,FXint w,FXint h,
361                              FXint pl,FXint pr,FXint pt,FXint pb)
362   : FXComboBox(p,cols, tgt, sel, opts,x,y,w,h, pl,pr,pt,pb) {
363   delete button;
364 
365   button=new ThemeMenuButton(this,FXString::null, NULL, pane,
366                              FRAME_RAISED|MENUBUTTON_DOWN|MENUBUTTON_ATTACH_RIGHT,
367                              0,0,0,0, 0,0,0,0);
368   button->setXOffset(border);
369   button->setYOffset(border);
370 }
371 
372 
373 
onPaint(FXObject *,FXSelector,void * ptr)374 long ThemeComboBox::onPaint(FXObject*,FXSelector,void* ptr) {
375   FXEvent *ev=(FXEvent*)ptr;
376   FXDCWindow dc(this,ev);
377 
378   dc.setForeground(backColor);
379   dc.fillRectangle(ev->rect.x,ev->rect.y,ev->rect.w,ev->rect.h);
380   drawFrame(dc,0,0,width,height);
381   return 1;
382 }
383 
384 
385 
386 
387 
388 FXDEFMAP(ThemeLabel) ThemeLabelMap[]= {
389   FXMAPFUNC( SEL_PAINT, 0, ThemeLabel::onPaint )
390 };
391 
392 FXIMPLEMENT( ThemeLabel, FXLabel, ThemeLabelMap, ARRAYNUMBER( ThemeLabelMap ));
393 
ThemeLabel(FXComposite * p,const FXString & text,FXIcon * ic,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb)394 ThemeLabel::ThemeLabel(FXComposite* p,const FXString& text,FXIcon* ic,FXuint opts,
395                        FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb)
396   : FXLabel( p, text, ic, opts, x, y, w, h, pl, pr, pt, pb ) {
397 
398 }
399 
400 
401 
402 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)403 long ThemeLabel::onPaint(FXObject*,FXSelector,void* ptr) {
404   FXEvent   *ev=(FXEvent*)ptr;
405   FXDCWindow dc(this,ev);
406   FXint      tw=0,th=0,iw=0,ih=0,tx,ty,ix,iy;
407   dc.setForeground(backColor);
408   dc.fillRectangle(0,0,width,height);
409   if (!label.empty()) {
410     tw=labelWidth(label);
411     th=labelHeight(label);
412   }
413   if (icon) {
414     iw=icon->getWidth();
415     ih=icon->getHeight();
416   }
417   just_x(tx,ix,tw,iw);
418   just_y(ty,iy,th,ih);
419   if(icon) {
420     if(isEnabled())
421       dc.drawIcon(icon,ix,iy);
422     else
423       dc.drawIconSunken(icon,ix,iy);
424   }
425   if (!label.empty()) {
426     dc.setFont(font);
427     if(isEnabled()) {
428       dc.setForeground(textColor);
429       drawLabel(dc,label,hotoff,tx,ty,tw,th);
430     }
431     else {
432       dc.setForeground(hiliteColor);
433       drawLabel(dc,label,hotoff,tx+1,ty+1,tw,th);
434       dc.setForeground(shadowColor);
435       drawLabel(dc,label,hotoff,tx,ty,tw,th);
436     }
437   }
438   if (options & (FRAME_THICK|FRAME_RAISED|FRAME_SUNKEN)) {
439     if( options & (FRAME_SUNKEN) )
440       drawSunkenFrame(dc,0,0,width,height);
441     else if( options & (FRAME_RAISED) )
442       drawHighlightFrame(dc,0,0,width,height);
443     else
444       drawFrame(dc,0,0,width,height);
445   }
446 
447   return 1;
448 }
449 
450 
451 
452 
453 FXDEFMAP(ThemeTabItem) ThemeTabItemMap[]= {
454 //	FXMAPFUNC( SEL_PAINT, 0, ThemeTabItem::onPaint )
455 };
456 
457 FXIMPLEMENT( ThemeTabItem, FXTabItem, ThemeTabItemMap, ARRAYNUMBER( ThemeTabItemMap ));
458 
ThemeTabItem(FXTabBar * p,const FXString & text,FXIcon * ic,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb)459 ThemeTabItem::ThemeTabItem(FXTabBar* p,const FXString& text,FXIcon* ic,FXuint opts,
460                            FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb)
461   : FXTabItem(p,text,ic,opts,x,y,w,h,pl,pr,pt,pb) {
462   shadowColor = FXRGB(123,158,189);
463   borderColor = FXRGB(123,158,189);
464   hiliteColor = FXRGB(123,158,189);
465 }
466 
467 
468 
469 
ThemeVerticalFrame(FXComposite * p,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb,FXint hs,FXint vs)470 ThemeVerticalFrame::ThemeVerticalFrame(FXComposite* p,FXuint opts,FXint x,FXint y,FXint w,FXint h,
471                                        FXint pl,FXint pr,FXint pt,FXint pb,FXint hs,FXint vs)
472   : FXVerticalFrame( p, opts, x, y, w, h, pl, pr, pt, pb, hs, vs ) {
473   setHiliteColor( FXRGB(123,158,189) );
474 }
475 
476 
ThemeHorizontalFrame(FXComposite * p,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb,FXint hs,FXint vs)477 ThemeHorizontalFrame::ThemeHorizontalFrame(FXComposite* p,FXuint opts,FXint x,FXint y,FXint w,FXint h,
478     FXint pl,FXint pr,FXint pt,FXint pb,FXint hs,FXint vs)
479   : FXHorizontalFrame( p, opts, x, y, w, h, pl, pr, pt, pb, hs, vs ) {
480   setHiliteColor( FXRGB(123,158,189) );
481 }
482 
483 
484 
485 
486 #define MENUBUTTONARROW_WIDTH  13
487 #define MENUBUTTONARROW_HEIGHT  5
488 
489 FXDEFMAP(ThemeMenuButton) ThemeMenuButtonMap[]= {
490   FXMAPFUNC( SEL_PAINT, 0, ThemeMenuButton::onPaint)
491 };
492 
493 FXIMPLEMENT( ThemeMenuButton, FXMenuButton, ThemeMenuButtonMap, ARRAYNUMBER(ThemeMenuButtonMap) );
494 
495 
ThemeMenuButton(FXComposite * p,const FXString & text,FXIcon * ic,FXPopup * pup,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb)496 ThemeMenuButton::ThemeMenuButton(FXComposite* p,const FXString& text,
497                                  FXIcon* ic,FXPopup* pup,FXuint opts,
498                                  FXint x,FXint y,FXint w,FXint h,
499                                  FXint pl,FXint pr,FXint pt,FXint pb )
500   : FXMenuButton( p, text, ic, pup, opts, x, y, w, h,
501                   pl, pr, pt, pb) {
502 }
503 
504 
505 
506 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)507 long ThemeMenuButton::onPaint(FXObject*,FXSelector,void* ptr) {
508   FXint tw=0,th=0,iw=0,ih=0,tx,ty,ix,iy;
509   FXEvent *ev=(FXEvent*)ptr;
510   FXPoint points[6];
511   FXDCWindow dc(this,ev);
512   /*
513   FXColor top         = FXRGB(0xfe,0xfd,0xfd);
514   FXColor bottom      = FXRGB(0xdd,0xd7,0xce);
515   FXColor shade       = FXRGB(0xdc,0xd9,0xd4);
516   */
517   FXColor top         = FXRGB(0xde,0xe7,0xff);
518   FXColor bottom      = FXRGB(0xbd,0xcf,0xff);
519   FXColor shade       = FXRGB(0xbd,0xcb,0xf7);
520 
521   FXColor buttoncolor = FXRGB(0x4a,0x61,0x84);
522 
523   // FXColor bordercolor = FXRGB(123,158,189);
524   FXColor bordercolor = shade;
525 
526   FXPoint basebackground[4]= {
527     FXPoint(0,0),FXPoint(width-1,0),FXPoint(0,height-1),FXPoint(width-1,height-1)
528   };
529   FXPoint bordershade[16]= {
530     FXPoint(0,1),FXPoint(1,0),FXPoint(1,2),FXPoint(2,1),
531     FXPoint(width-2,0),FXPoint(width-1,1),FXPoint(width-3,1),FXPoint(width-2,2),
532     FXPoint(0,height-2),FXPoint(1,height-1),FXPoint(1,height-3),FXPoint(2,height-2),
533     FXPoint(width-1,height-2),FXPoint(width-2,height-1),FXPoint(width-2,height-3),FXPoint(width-3,height-2)
534   };
535   FXPoint bordercorners[4]= {
536     FXPoint(1,1),FXPoint(1,height-2),FXPoint(width-2,1),FXPoint(width-2,height-2)
537   };
538 
539 
540   // Got a border at all?
541   if (options&(FRAME_RAISED|FRAME_SUNKEN)) {
542 
543     // Toolbar style
544     if (options&MENUBUTTON_TOOLBAR) {
545 
546       // Enabled and cursor inside, and not popped up
547       if (isEnabled() && underCursor() && !state) {
548         dc.setForeground(backColor);
549         dc.fillRectangle(border,border,width-border*2,height-border*2);
550         if(options&FRAME_THICK) drawDoubleRaisedRectangle(dc,0,0,width,height);
551         else drawRaisedRectangle(dc,0,0,width,height);
552       }
553 
554       // Enabled and popped up
555       else if (isEnabled() && state) {
556         dc.setForeground(hiliteColor);
557         dc.fillRectangle(border,border,width-border*2,height-border*2);
558         if(options&FRAME_THICK) drawDoubleSunkenRectangle(dc,0,0,width,height);
559         else drawSunkenRectangle(dc,0,0,width,height);
560       }
561 
562       // Disabled or unchecked or not under cursor
563       else {
564         dc.setForeground(backColor);
565         dc.fillRectangle(0,0,width,height);
566       }
567     }
568 
569     // Normal style
570     else {
571       // Draw in up state if disabled or up
572       if (!isEnabled() || !state) {
573         /*
574                * dc.setForeground(backColor);
575          dc.fillRectangle(border,border,width-border*2,height-border*2);
576          if(options&FRAME_THICK) drawDoubleRaisedRectangle(dc,0,0,width,height);
577          else drawRaisedRectangle(dc,0,0,width,height);
578          */
579         /// Outside Background
580         dc.setForeground(baseColor);
581         dc.drawPoints(basebackground,4);
582         /// Border
583         dc.setForeground(bordercolor);
584         dc.drawRectangle(2,0,width-5,0);
585         dc.drawRectangle(2,height-1,width-5,height-1);
586         dc.drawRectangle(0,2,0,height-5);
587         dc.drawRectangle(width-1,2,0,height-5);
588         dc.drawPoints(bordercorners,4);
589         dc.setForeground(shade);
590         dc.drawPoints(bordershade,16);
591         /// Gradient
592         drawRectangle(dc,top,bottom,2,1,width-4,height-2);
593         dc.setForeground(top);
594         dc.drawRectangle(1,3,0,height-7);
595         dc.setForeground(bottom);
596         dc.drawRectangle(width-2,3,0,height-7);
597       }
598 
599       // Draw sunken if enabled and either checked or pressed
600       else {
601         dc.setForeground(baseColor);
602         dc.drawPoints(basebackground,4);
603         /// Border
604         dc.setForeground(bordercolor);
605         dc.drawRectangle(2,0,width-5,0);
606         dc.drawRectangle(2,height-1,width-5,height-1);
607         dc.drawRectangle(0,2,0,height-5);
608         dc.drawRectangle(width-1,2,0,height-5);
609         dc.drawPoints(bordercorners,4);
610         dc.setForeground(shade);
611         dc.drawPoints(bordershade,16);
612 
613         dc.setForeground(FXRGB(0xdc,0xd4,0xc9));
614         dc.fillRectangle(2,1,width-4,height-2);
615       }
616     }
617   }
618 
619   // No borders
620   else {
621     if(isEnabled() && state) {
622       dc.setForeground(hiliteColor);
623       dc.fillRectangle(0,0,width,height);
624     }
625     else {
626       dc.setForeground(backColor);
627       dc.fillRectangle(0,0,width,height);
628     }
629   }
630 
631   // Position text & icon
632   if (!label.empty()) {
633     tw=labelWidth(label);
634     th=labelHeight(label);
635   }
636 
637   // Icon?
638   if (icon) {
639     iw=icon->getWidth();
640     ih=icon->getHeight();
641   }
642 
643   // Arrows?
644   else if(!(options&MENUBUTTON_NOARROWS)) {
645     if(options&MENUBUTTON_LEFT) {
646       ih=MENUBUTTONARROW_WIDTH;
647       iw=MENUBUTTONARROW_HEIGHT;
648     }
649     else {
650       iw=MENUBUTTONARROW_WIDTH;
651       ih=MENUBUTTONARROW_HEIGHT;
652     }
653   }
654 
655   // Keep some room for the arrow!
656   just_x(tx,ix,tw,iw);
657   just_y(ty,iy,th,ih);
658 
659   // Move a bit when pressed
660   if (state) {
661     ++tx;
662     ++ty;
663     ++ix;
664     ++iy;
665   }
666 
667   // Draw icon
668   if (icon) {
669     if (isEnabled())
670       dc.drawIcon(icon,ix,iy);
671     else
672       dc.drawIconSunken(icon,ix,iy);
673   }
674 
675   // Draw arrows
676   else if (!(options&MENUBUTTON_NOARROWS)) {
677 
678     // Right arrow
679     if ((options&MENUBUTTON_RIGHT)==MENUBUTTON_RIGHT) {
680       if (isEnabled())
681         dc.setForeground(buttoncolor);
682       else
683         dc.setForeground(shadowColor);
684       points[0].x=ix;
685       points[0].y=iy;
686       points[1].x=ix;
687       points[1].y=iy+MENUBUTTONARROW_WIDTH-1;
688       points[2].x=ix+MENUBUTTONARROW_HEIGHT;
689       points[2].y=(FXshort)(iy+(MENUBUTTONARROW_WIDTH>>1));
690       dc.fillPolygon(points,3);
691     }
692 
693     // Left arrow
694     else if (options&MENUBUTTON_LEFT) {
695       if (isEnabled())
696         dc.setForeground(buttoncolor);
697       else
698         dc.setForeground(shadowColor);
699       points[0].x=ix+MENUBUTTONARROW_HEIGHT;
700       points[0].y=iy;
701       points[1].x=ix+MENUBUTTONARROW_HEIGHT;
702       points[1].y=iy+MENUBUTTONARROW_WIDTH-1;
703       points[2].x=ix;
704       points[2].y=(FXshort)(iy+(MENUBUTTONARROW_WIDTH>>1));
705       dc.fillPolygon(points,3);
706     }
707 
708     // Up arrow
709     else if (options&MENUBUTTON_UP) {
710       if(isEnabled())
711         dc.setForeground(buttoncolor);
712       else
713         dc.setForeground(shadowColor);
714       points[0].x=(FXshort)(ix+(MENUBUTTONARROW_WIDTH>>1));
715       points[0].y=iy-1;
716       points[1].x=ix;
717       points[1].y=iy+MENUBUTTONARROW_HEIGHT;
718       points[2].x=ix+MENUBUTTONARROW_WIDTH;
719       points[2].y=iy+MENUBUTTONARROW_HEIGHT;
720       dc.fillPolygon(points,3);
721     }
722 
723     // Down arrow
724     else {
725       if(isEnabled())
726         dc.setForeground(buttoncolor);
727       else
728         dc.setForeground(shadowColor);
729       points[0].x=ix+1;
730       points[0].y=iy;
731       points[2].x=ix+MENUBUTTONARROW_WIDTH-1;
732       points[2].y=iy;
733       points[1].x=(FXshort)(ix+(MENUBUTTONARROW_WIDTH>>1));
734       points[1].y=iy+MENUBUTTONARROW_HEIGHT;
735       points[3].x=ix+MENUBUTTONARROW_WIDTH-3;
736       points[3].y=iy;
737       points[4].x=(FXshort)(ix+(MENUBUTTONARROW_WIDTH>>1));
738       points[4].y=iy+MENUBUTTONARROW_HEIGHT-3;
739       points[5].x=ix+3;
740       points[5].y=iy;
741       dc.fillConcavePolygon(points,6);
742     }
743   }
744 
745   // Draw text
746   if (!label.empty()) {
747     dc.setFont(font);
748     if(isEnabled()) {
749       dc.setForeground(textColor);
750       drawLabel(dc,label,hotoff,tx,ty,tw,th);
751     }
752     else {
753       dc.setForeground(hiliteColor);
754       drawLabel(dc,label,hotoff,tx+1,ty+1,tw,th);
755       dc.setForeground(shadowColor);
756       drawLabel(dc,label,hotoff,tx,ty,tw,th);
757     }
758   }
759 
760   // Draw focus
761   if (hasFocus()) {
762     if (isEnabled()) {
763       dc.drawFocusRectangle(border+1,border+1,width-2*border-2,height-2*border-2);
764     }
765   }
766   return 1;
767 }
768 
769 
770 
771 // Get default width
getDefaultWidth()772 FXint ThemeMenuButton::getDefaultWidth() {
773   FXint tw=0,iw=0,s=0,w,pw;
774 
775   if (!label.empty()) {
776     tw=labelWidth(label);
777     s=4;
778   }
779   if (!(options&MENUBUTTON_NOARROWS)) {
780     if (options&MENUBUTTON_LEFT)
781       iw=MENUBUTTONARROW_HEIGHT;
782     else
783       iw=MENUBUTTONARROW_WIDTH;
784   }
785   if(icon)
786     iw=icon->getWidth();
787   if (!(options&(ICON_AFTER_TEXT|ICON_BEFORE_TEXT)))
788     w=FXMAX(tw,iw);
789   else
790     w=tw+iw+s;
791   w=padleft+padright+(border<<1)+w;
792   if (!(options&MENUBUTTON_LEFT) &&
793       (options&MENUBUTTON_ATTACH_RIGHT) &&
794       (options&MENUBUTTON_ATTACH_CENTER)) {
795     if (pane) {
796       pw=pane->getDefaultWidth();
797       if(pw>w)
798         w=pw;
799     }
800   }
801   return w;
802 }
803 
804 
805 
806 
807 #if 0
808 FXDEFMAP(ThemeHeaderItem) ThemeHeaderItemMap[]= {
809   FXMAPFUNC(SEL_PAINT, 0, ThemeHeaderItem::onPaint)
810 };
811 
812 FXIMPLEMENT(ThemeHeaderItem, FXHeaderItem, ThemeHeaderItemMap, ARRAYNUMBER(ThemeHeaderItemMap));
813 #endif
814 
815 
ThemeHeaderItem(const FXString & text,FXIcon * ic,FXint s,void * ptr)816 ThemeHeaderItem::ThemeHeaderItem(const FXString& text, FXIcon* ic, FXint s, void* ptr)
817   :FXHeaderItem(text, ic, s, ptr) {
818 }
819 
820 
821 
draw(const FXHeader * header,FXDC & dc,FXint x,FXint y,FXint w,FXint h)822 void ThemeHeaderItem::draw(const FXHeader* header,FXDC& dc,FXint x,FXint y,FXint w,FXint h) {
823   register FXint tx,ty,tw,th,ix,iy,iw,ih,s,ml,mr,mt,mb,beg,end,t,xx,yy,bb,aa,ax,ay;
824   register FXFont *font=header->getFont();
825   FXColor top         = FXRGB(0xfe,0xfd,0xfd);
826   FXColor bottom      = FXRGB(0xdd,0xd7,0xce);
827   FXColor shade       = FXRGB(0xdc,0xd9,0xd4);
828 
829   // Get border width and padding
830   bb=header->getBorderWidth();
831   ml=header->getPadLeft()+bb;
832   mr=header->getPadRight()+bb;
833   mt=header->getPadTop()+bb;
834   mb=header->getPadBottom()+bb;
835 
836   dc.setForeground(shade);
837   /// Gradient
838   drawRectangle(dc,top, bottom, x+2, y+1, w-4, h-2);
839 
840   // Shrink by margins
841   x+=ml;
842   w-=ml+mr;
843   y+=mt;
844   h-=mt+mb;
845 
846   // Initial clip rectangle
847   dc.setClipRectangle(x,y,w,h);
848 
849   dc.setForeground(header->getTextColor());
850   // Text width and height
851   tw=th=iw=ih=beg=s=0;
852   do {
853     end=beg;
854     while(end<label.length() && label[end]!='\n') end++;
855     if((t=font->getTextWidth(&label[beg],end-beg))>tw) tw=t;
856     th+=font->getFontHeight();
857     beg=end+1;
858   }
859   while(end<label.length());
860 
861   // Icon size
862   if(icon) {
863     iw=icon->getWidth();
864     ih=icon->getHeight();
865   }
866 
867   // Icon-text spacing
868   if(iw && tw)
869     s=ICON_SPACING;
870 
871   // Draw arrows
872   if (state&(ARROW_UP|ARROW_DOWN)) {
873     aa=(font->getFontHeight()-5)|1;
874     ay=y+(h-aa)/2;
875     ax=x+w-aa-2;
876     if(state&ARROW_UP) {
877       dc.setForeground(header->getHiliteColor());
878       dc.drawLine(ax+aa/2,ay,ax+aa-1,ay+aa);
879       dc.drawLine(ax,ay+aa,ax+aa,ay+aa);
880       dc.setForeground(header->getShadowColor());
881       dc.drawLine(ax+aa/2,ay,ax,ay+aa);
882     }
883     else {
884       dc.setForeground(header->getHiliteColor());
885       dc.drawLine(ax+aa/2,ay+aa,ax+aa-1,ay);
886       dc.setForeground(header->getShadowColor());
887       dc.drawLine(ax+aa/2,ay+aa,ax,ay);
888       dc.drawLine(ax,ay,ax+aa,ay);
889     }
890     w-=aa+4;
891     dc.setClipRectangle(x,y,w,h);
892   }
893 
894   // Fix x coordinate
895   if (state&LEFT) {
896     if(state&BEFORE) {
897       ix=x;
898       tx=ix+iw+s;
899     }
900     else if (state&AFTER) {
901       tx=x;
902       ix=tx+tw+s;
903     }
904     else {
905       ix=x;
906       tx=x;
907     }
908   }
909   else if(state&RIGHT) {
910     if(state&BEFORE) {
911       tx=x+w-tw;
912       ix=tx-iw-s;
913     }
914     else if (state&AFTER) {
915       ix=x+w-iw;
916       tx=ix-tw-s;
917     }
918     else {
919       ix=x+w-iw;
920       tx=x+w-tw;
921     }
922   }
923   else {
924     if (state&BEFORE) {
925       ix=x+(w-tw-iw-s)/2;
926       tx=ix+iw+s;
927     }
928     else if (state&AFTER) {
929       tx=x+(w-tw-iw-s)/2;
930       ix=tx+tw+s;
931     }
932     else {
933       ix=x+(w-iw)/2;
934       tx=x+(w-tw)/2;
935     }
936   }
937 
938   // Fix y coordinate
939   if(state&TOP) {
940     if (state&ABOVE) {
941       iy=y;
942       ty=iy+ih;
943     }
944     else if (state&BELOW) {
945       ty=y;
946       iy=ty+th;
947     }
948     else {
949       iy=y;
950       ty=y;
951     }
952   }
953   else if(state&BOTTOM) {
954     if (state&ABOVE) {
955       ty=y+h-th;
956       iy=ty-ih;
957     }
958     else if (state&BELOW) {
959       iy=y+h-ih;
960       ty=iy-th;
961     }
962     else {
963       iy=y+h-ih;
964       ty=y+h-th;
965     }
966   }
967   else {
968     if (state&ABOVE) {
969       iy=y+(h-th-ih)/2;
970       ty=iy+ih;
971     }
972     else if (state&BELOW) {
973       ty=y+(h-th-ih)/2;
974       iy=ty+th;
975     }
976     else {
977       iy=y+(h-ih)/2;
978       ty=y+(h-th)/2;
979     }
980   }
981 
982   // Offset a bit when pressed
983   if (state&PRESSED) {
984     tx++;
985     ty++;
986     ix++;
987     iy++;
988   }
989 
990   // Paint icon
991   if (icon) {
992     dc.drawIcon(icon,ix,iy);
993   }
994 
995   // Text color
996   dc.setForeground(header->getTextColor());
997 
998   // Draw text
999   yy=ty+font->getFontAscent();
1000   beg=0;
1001   do {
1002     end=beg;
1003     while(end<label.length() && label[end]!='\n')
1004       end++;
1005     if (state&LEFT)
1006       xx=tx;
1007     else if(state&RIGHT)
1008       xx=tx+tw-font->getTextWidth(&label[beg],end-beg);
1009     else
1010       xx=tx+(tw-font->getTextWidth(&label[beg],end-beg))/2;
1011     dc.drawText(xx,yy,&label[beg],end-beg);
1012     yy+=font->getFontHeight();
1013     beg=end+1;
1014   }
1015   while(end<label.length());
1016 
1017   // Restore original clip path
1018   dc.clearClipRectangle();
1019 }
1020 
1021 
1022 
1023 
1024 
1025 
1026