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