1 /********************************************************************************
2 *                                                                               *
3 *                     T o o l   B a r   T a b   O b j e c t                     *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 1999,2006 by Jeroen van der Zijp.   All Rights Reserved.        *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or                 *
9 * modify it under the terms of the GNU Lesser General Public                    *
10 * License as published by the Free Software Foundation; either                  *
11 * version 2.1 of the License, or (at your option) any later version.            *
12 *                                                                               *
13 * This library is distributed in the hope that it will be useful,               *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU             *
16 * Lesser General Public License for more details.                               *
17 *                                                                               *
18 * You should have received a copy of the GNU Lesser General Public              *
19 * License along with this library; if not, write to the Free Software           *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.    *
21 *********************************************************************************
22 * $Id: FXToolBarTab.cpp 4937 2019-03-10 19:59:30Z arthurcnorman $                    *
23 ********************************************************************************/
24 #include "xincs.h"
25 #include "fxver.h"
26 #include "fxdefs.h"
27 #include "fxkeys.h"
28 #include "FXHash.h"
29 #include "FXThread.h"
30 #include "FXStream.h"
31 #include "FXString.h"
32 #include "FXSize.h"
33 #include "FXPoint.h"
34 #include "FXRectangle.h"
35 #include "FXRegistry.h"
36 #include "FXApp.h"
37 #include "FXDCWindow.h"
38 #include "FXFont.h"
39 #include "FXToolBarTab.h"
40 
41 
42 /*
43   To do:
44 */
45 
46 
47 // Size
48 #define TOOLBARTAB_WIDTH    9       // Width for horizontal toolbar tab
49 #define TOOLBARTAB_HEIGHT   24      // Height for horizontal toolbar tab
50 
51 // Tool Bar Tab styles
52 #define TOOLBARTAB_MASK        TOOLBARTAB_VERTICAL
53 
54 using namespace FX;
55 
56 /*******************************************************************************/
57 
58 namespace FX {
59 
60 // Map
61 FXDEFMAP(FXToolBarTab) FXToolBarTabMap[]={
62   FXMAPFUNC(SEL_PAINT,0,FXToolBarTab::onPaint),
63   FXMAPFUNC(SEL_UPDATE,0,FXToolBarTab::onUpdate),
64   FXMAPFUNC(SEL_ENTER,0,FXToolBarTab::onEnter),
65   FXMAPFUNC(SEL_LEAVE,0,FXToolBarTab::onLeave),
66   FXMAPFUNC(SEL_UNGRABBED,0,FXToolBarTab::onUngrabbed),
67   FXMAPFUNC(SEL_LEFTBUTTONPRESS,0,FXToolBarTab::onLeftBtnPress),
68   FXMAPFUNC(SEL_LEFTBUTTONRELEASE,0,FXToolBarTab::onLeftBtnRelease),
69   FXMAPFUNC(SEL_KEYPRESS,0,FXToolBarTab::onKeyPress),
70   FXMAPFUNC(SEL_KEYRELEASE,0,FXToolBarTab::onKeyRelease),
71   FXMAPFUNC(SEL_QUERY_TIP,0,FXToolBarTab::onQueryTip),
72   FXMAPFUNC(SEL_UPDATE,FXToolBarTab::ID_COLLAPSE,FXToolBarTab::onUpdCollapse),
73   FXMAPFUNC(SEL_UPDATE,FXToolBarTab::ID_UNCOLLAPSE,FXToolBarTab::onUpdUncollapse),
74   FXMAPFUNC(SEL_COMMAND,FXToolBarTab::ID_COLLAPSE,FXToolBarTab::onCmdCollapse),
75   FXMAPFUNC(SEL_COMMAND,FXToolBarTab::ID_UNCOLLAPSE,FXToolBarTab::onCmdUncollapse),
76   FXMAPFUNC(SEL_COMMAND,FXToolBarTab::ID_SETTIPSTRING,FXToolBarTab::onCmdSetTip),
77   FXMAPFUNC(SEL_COMMAND,FXToolBarTab::ID_GETTIPSTRING,FXToolBarTab::onCmdGetTip),
78   };
79 
80 
81 // Object implementation
FXIMPLEMENT(FXToolBarTab,FXFrame,FXToolBarTabMap,ARRAYNUMBER (FXToolBarTabMap))82 FXIMPLEMENT(FXToolBarTab,FXFrame,FXToolBarTabMap,ARRAYNUMBER(FXToolBarTabMap))
83 
84 
85 // Deserialization
86 FXToolBarTab::FXToolBarTab(){
87   flags|=FLAG_ENABLED;
88   activeColor=FXRGB(150,156,224);
89   collapsed=FALSE;
90   down=FALSE;
91   }
92 
93 
94 // Construct and init
FXToolBarTab(FXComposite * p,FXObject * tgt,FXSelector sel,FXuint opts,FXint x,FXint y,FXint w,FXint h)95 FXToolBarTab::FXToolBarTab(FXComposite* p,FXObject* tgt,FXSelector sel,FXuint opts,FXint x,FXint y,FXint w,FXint h):
96   FXFrame(p,opts,x,y,w,h){
97   flags|=FLAG_ENABLED;
98   activeColor=FXRGB(150,156,224);
99   target=tgt;
100   message=sel;
101   collapsed=FALSE;
102   down=FALSE;
103   }
104 
105 
106 // If window can have focus
canFocus() const107 bool FXToolBarTab::canFocus() const { return true; }
108 
109 
110 // Enable the window
enable()111 void FXToolBarTab::enable(){
112   if(!(flags&FLAG_ENABLED)){
113     FXFrame::enable();
114     update();
115     }
116   }
117 
118 
119 // Disable the window
disable()120 void FXToolBarTab::disable(){
121   if(flags&FLAG_ENABLED){
122     FXFrame::disable();
123     update();
124     }
125   }
126 
127 
128 // Get default width
getDefaultWidth()129 FXint FXToolBarTab::getDefaultWidth(){
130   FXWindow *sibling=getNext() ? getNext() : getPrev();
131   FXint w;
132   if(options&TOOLBARTAB_VERTICAL){          // Vertical
133     if(collapsed){
134       w=TOOLBARTAB_WIDTH;
135       }
136     else{
137       w=TOOLBARTAB_HEIGHT;
138       if(sibling) w=sibling->getDefaultWidth();
139       }
140     }
141   else{                                     // Horizontal
142     if(collapsed){
143       w=TOOLBARTAB_HEIGHT;
144       if(sibling) w=sibling->getDefaultHeight();
145       }
146     else{
147       w=TOOLBARTAB_WIDTH;
148       }
149     }
150   return w;
151   }
152 
153 
154 // Get default height
getDefaultHeight()155 FXint FXToolBarTab::getDefaultHeight(){
156   FXWindow *sibling=getNext() ? getNext() : getPrev();
157   FXint h;
158   if(options&TOOLBARTAB_VERTICAL){          // Vertical
159     if(collapsed){
160       h=TOOLBARTAB_HEIGHT;
161       if(sibling) h=sibling->getDefaultWidth();
162       }
163     else{
164       h=TOOLBARTAB_WIDTH;
165       }
166     }
167   else{                                     // Horizontal
168     if(collapsed){
169       h=TOOLBARTAB_WIDTH;
170       }
171     else{
172       h=TOOLBARTAB_HEIGHT;
173       if(sibling) h=sibling->getDefaultHeight();
174       }
175     }
176   return h;
177   }
178 
179 
180 // Collapse or uncollapse
collapse(FXbool fold,FXbool notify)181 void FXToolBarTab::collapse(FXbool fold,FXbool notify){
182   FXWindow *sibling;
183   if(fold!=collapsed){
184     sibling=getNext() ? getNext() : getPrev();
185     if(sibling){
186       if(fold){
187         sibling->hide();
188         }
189       else{
190         sibling->show();
191         }
192       }
193     collapsed=fold;
194     recalc();
195     update();
196     if(notify && target) target->tryHandle(this,FXSEL(SEL_COMMAND,message),(void*)(FXuval)fold);
197     }
198   }
199 
200 
201 // Update
onUpdate(FXObject * sender,FXSelector sel,void * ptr)202 long FXToolBarTab::onUpdate(FXObject* sender,FXSelector sel,void* ptr){
203   FXWindow *sibling=getNext() ? getNext() : getPrev();
204   FXFrame::onUpdate(sender,sel,ptr);
205   if(sibling){
206     if(sibling->shown() && collapsed){
207       collapsed=FALSE;
208       update();
209       recalc();
210       }
211     else if(!sibling->shown() && !collapsed){
212       collapsed=TRUE;
213       update();
214       recalc();
215       }
216     }
217   return 1;
218   }
219 
220 
221 // Entered button
onEnter(FXObject * sender,FXSelector sel,void * ptr)222 long FXToolBarTab::onEnter(FXObject* sender,FXSelector sel,void* ptr){
223   FXFrame::onEnter(sender,sel,ptr);
224   if(isEnabled()){
225     if(flags&FLAG_PRESSED) down=TRUE;
226     update();
227     }
228   return 1;
229   }
230 
231 
232 // Leave button
onLeave(FXObject * sender,FXSelector sel,void * ptr)233 long FXToolBarTab::onLeave(FXObject* sender,FXSelector sel,void* ptr){
234   FXFrame::onLeave(sender,sel,ptr);
235   if(isEnabled()){
236     if(flags&FLAG_PRESSED) down=FALSE;
237     update();
238     }
239   return 1;
240   }
241 
242 
243 // Pressed mouse button
onLeftBtnPress(FXObject * sender,FXSelector sel,void * ptr)244 long FXToolBarTab::onLeftBtnPress(FXObject* sender,FXSelector sel,void* ptr){
245   if(!FXFrame::onLeftBtnPress(sender,sel,ptr)){
246     if(isEnabled() && !(flags&FLAG_PRESSED)){
247       flags|=FLAG_PRESSED;
248       flags&=~FLAG_UPDATE;
249       down=TRUE;
250       update();
251       return 1;
252       }
253     }
254   return 0;
255   }
256 
257 
258 // Released mouse button
onLeftBtnRelease(FXObject * sender,FXSelector sel,void * ptr)259 long FXToolBarTab::onLeftBtnRelease(FXObject* sender,FXSelector sel,void* ptr){
260   FXbool click=down;
261   if(!FXFrame::onLeftBtnRelease(sender,sel,ptr)){
262     if(isEnabled() && (flags&FLAG_PRESSED)){
263       flags|=FLAG_UPDATE;
264       flags&=~FLAG_PRESSED;
265       down=FALSE;
266       update();
267       if(click) collapse(!collapsed,TRUE);
268       return 1;
269       }
270     }
271   return 0;
272   }
273 
274 
275 // The widget lost the grab for some reason
onUngrabbed(FXObject * sender,FXSelector sel,void * ptr)276 long FXToolBarTab::onUngrabbed(FXObject* sender,FXSelector sel,void* ptr){
277   FXFrame::onUngrabbed(sender,sel,ptr);
278   flags&=~FLAG_PRESSED;
279   flags|=FLAG_UPDATE;
280   down=FALSE;
281   update();
282   return 1;
283   }
284 
285 
286 // Key Press
onKeyPress(FXObject *,FXSelector,void * ptr)287 long FXToolBarTab::onKeyPress(FXObject*,FXSelector,void* ptr){
288   FXEvent* event=(FXEvent*)ptr;
289   flags&=~FLAG_TIP;
290   if(isEnabled() && !(flags&FLAG_PRESSED)){
291     if(target && target->tryHandle(this,FXSEL(SEL_KEYPRESS,message),ptr)) return 1;
292     if(event->code==KEY_space || event->code==KEY_KP_Space){
293       down=TRUE;
294       update();
295       flags|=FLAG_PRESSED;
296       flags&=~FLAG_UPDATE;
297       return 1;
298       }
299     }
300   return 0;
301   }
302 
303 
304 // Key Release
onKeyRelease(FXObject *,FXSelector,void * ptr)305 long FXToolBarTab::onKeyRelease(FXObject*,FXSelector,void* ptr){
306   FXEvent* event=(FXEvent*)ptr;
307   if(isEnabled() && (flags&FLAG_PRESSED)){
308     if(target && target->tryHandle(this,FXSEL(SEL_KEYRELEASE,message),ptr)) return 1;
309     if(event->code==KEY_space || event->code==KEY_KP_Space){
310       down=FALSE;
311       update();
312       flags|=FLAG_UPDATE;
313       flags&=~FLAG_PRESSED;
314       collapse(!collapsed,TRUE);
315       return 1;
316       }
317     }
318   return 0;
319   }
320 
321 
322 // Collapse
onCmdCollapse(FXObject *,FXSelector,void *)323 long FXToolBarTab::onCmdCollapse(FXObject*,FXSelector,void*){
324   collapse(TRUE,TRUE);
325   return 1;
326   }
327 
328 
329 // Update collapse
onUpdCollapse(FXObject * sender,FXSelector,void *)330 long FXToolBarTab::onUpdCollapse(FXObject* sender,FXSelector,void*){
331   if(collapsed)
332     sender->handle(this,FXSEL(SEL_COMMAND,ID_CHECK),NULL);
333   else
334     sender->handle(this,FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
335   return 1;
336   }
337 
338 
339 // Uncollapse
onCmdUncollapse(FXObject *,FXSelector,void *)340 long FXToolBarTab::onCmdUncollapse(FXObject*,FXSelector,void*){
341   collapse(FALSE,TRUE);
342   return 1;
343   }
344 
345 
346 // Update uncollapse
onUpdUncollapse(FXObject * sender,FXSelector,void *)347 long FXToolBarTab::onUpdUncollapse(FXObject* sender,FXSelector,void*){
348   if(!collapsed)
349     sender->handle(this,FXSEL(SEL_COMMAND,ID_CHECK),NULL);
350   else
351     sender->handle(this,FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
352   return 1;
353   }
354 
355 
356 // We were asked about tip text
onQueryTip(FXObject * sender,FXSelector sel,void * ptr)357 long FXToolBarTab::onQueryTip(FXObject* sender,FXSelector sel,void* ptr){
358   if(FXWindow::onQueryTip(sender,sel,ptr)) return 1;
359   if((flags&FLAG_TIP) && !tip.empty()){
360     sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&tip);
361     return 1;
362     }
363   return 0;
364   }
365 
366 
367 // Set tip using a message
onCmdSetTip(FXObject *,FXSelector,void * ptr)368 long FXToolBarTab::onCmdSetTip(FXObject*,FXSelector,void* ptr){
369   setTipText(*((FXString*)ptr));
370   return 1;
371   }
372 
373 
374 // Get tip using a message
onCmdGetTip(FXObject *,FXSelector,void * ptr)375 long FXToolBarTab::onCmdGetTip(FXObject*,FXSelector,void* ptr){
376   *((FXString*)ptr)=getTipText();
377   return 1;
378   }
379 
380 
381 // Draw horizontal speckles
drawHSpeckles(FXDCWindow & dc,FXint x,FXint w)382 void FXToolBarTab::drawHSpeckles(FXDCWindow& dc,FXint x,FXint w){
383   FXint i;
384   dc.setForeground(hiliteColor);
385   for(i=0; i<w-5; i+=4){dc.drawPoint(x+i,2);dc.drawPoint(x+i+1,5);}
386   dc.setForeground(shadowColor);
387   for(i=0; i<w-5; i+=4){dc.drawPoint(x+i+1,3);dc.drawPoint(x+i+2,6);}
388   }
389 
390 
391 // Draw vertical speckles
drawVSpeckles(FXDCWindow & dc,FXint y,FXint h)392 void FXToolBarTab::drawVSpeckles(FXDCWindow& dc,FXint y,FXint h){
393   FXint i;
394   dc.setForeground(hiliteColor);
395   for(i=0; i<h-5; i+=3){dc.drawPoint(2,y+i+1);dc.drawPoint(5,y+i);}
396   dc.setForeground(shadowColor);
397   for(i=0; i<h-5; i+=3){dc.drawPoint(6,y+i+1);dc.drawPoint(3,y+i+2);}
398   }
399 
400 
401 // Draw up arrow
drawUpArrow(FXDCWindow & dc)402 void FXToolBarTab::drawUpArrow(FXDCWindow& dc){
403   dc.setForeground(borderColor);
404   dc.drawLine(2,height-5,6,height-5);
405   dc.drawPoint(3,height-6);
406   dc.drawPoint(4,height-7);
407   dc.drawPoint(5,height-6);
408   dc.drawPoint(4,height-6);
409   }
410 
411 
412 // Draw down arrow
drawDownArrow(FXDCWindow & dc)413 void FXToolBarTab::drawDownArrow(FXDCWindow& dc){
414   dc.setForeground(borderColor);
415   dc.drawLine(2,4,6,4);
416   dc.drawPoint(3,5);
417   dc.drawPoint(4,6);
418   dc.drawPoint(5,5);
419   dc.drawPoint(4,5);
420   }
421 
422 
423 // Draw left arrow
drawLeftArrow(FXDCWindow & dc)424 void FXToolBarTab::drawLeftArrow(FXDCWindow& dc){
425   dc.setForeground(borderColor);
426   dc.drawLine(width-5,2,width-5,6);
427   dc.drawPoint(width-6,3);
428   dc.drawPoint(width-7,4);
429   dc.drawPoint(width-6,5);
430   dc.drawPoint(width-6,4);
431   }
432 
433 
434 // Draw right arrow
drawRightArrow(FXDCWindow & dc)435 void FXToolBarTab::drawRightArrow(FXDCWindow& dc){
436   dc.setForeground(borderColor);
437   dc.drawLine(4,2,4,6);
438   dc.drawPoint(5,3);
439   dc.drawPoint(6,4);
440   dc.drawPoint(5,5);
441   dc.drawPoint(5,4);
442   }
443 
444 
445 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)446 long FXToolBarTab::onPaint(FXObject*,FXSelector,void* ptr){
447   FXEvent *ev=(FXEvent*)ptr;
448   FXDCWindow dc(this,ev);
449 
450   // Got a border at all?
451   if(options&(FRAME_RAISED|FRAME_SUNKEN)){
452 
453     // Draw sunken if enabled and either checked or pressed
454     if(isEnabled() && down){
455       if(down) dc.setForeground(hiliteColor); else dc.setForeground(backColor);
456       dc.fillRectangle(border,border,width-border*2,height-border*2);
457       if(options&FRAME_THICK) drawDoubleSunkenRectangle(dc,0,0,width,height);
458       else drawSunkenRectangle(dc,0,0,width,height);
459       }
460 
461     // Draw in up state if disabled or up
462     else{
463       if(underCursor())
464         dc.setForeground(activeColor);
465       else
466         dc.setForeground(backColor);
467       dc.fillRectangle(border,border,width-border*2,height-border*2);
468       if(options&FRAME_THICK) drawDoubleRaisedRectangle(dc,0,0,width,height);
469       else drawRaisedRectangle(dc,0,0,width,height);
470       }
471     }
472 
473   // No borders
474   else{
475     if(isEnabled() && down){
476       dc.setForeground(hiliteColor);
477       dc.fillRectangle(0,0,width,height);
478       }
479     else{
480       if(underCursor())
481         dc.setForeground(activeColor);
482       else
483         dc.setForeground(backColor);
484       dc.fillRectangle(0,0,width,height);
485       }
486     }
487 
488   // Draw spickles
489   if(options&TOOLBARTAB_VERTICAL){          // Vertical
490     if(collapsed){
491       if(options&LAYOUT_BOTTOM){
492         drawVSpeckles(dc,3,height-10);
493         drawUpArrow(dc);
494         }
495       else{
496         drawVSpeckles(dc,10,height-10);
497         drawDownArrow(dc);
498         }
499       }
500     else{
501       if(options&LAYOUT_RIGHT){
502         drawHSpeckles(dc,3,width-10);
503         drawLeftArrow(dc);
504         }
505       else{
506         drawHSpeckles(dc,10,width-10);
507         drawRightArrow(dc);
508         }
509       }
510     }
511   else{                                     // Horizontal
512     if(collapsed){
513       if(options&LAYOUT_RIGHT){
514         drawHSpeckles(dc,3,width-10);
515         drawLeftArrow(dc);
516         }
517       else{
518         drawHSpeckles(dc,10,width-10);
519         drawRightArrow(dc);
520         }
521       }
522     else{
523       if(options&LAYOUT_BOTTOM){
524         drawVSpeckles(dc,3,height-10);
525         drawUpArrow(dc);
526         }
527       else{
528         drawVSpeckles(dc,10,height-10);
529         drawDownArrow(dc);
530         }
531       }
532     }
533   return 1;
534   }
535 
536 
537 // Change tab style
setTabStyle(FXuint style)538 void FXToolBarTab::setTabStyle(FXuint style){
539   FXuint opts=(options&~TOOLBARTAB_MASK) | (style&TOOLBARTAB_MASK);
540   if(options!=opts){
541     options=opts;
542     update();
543     }
544   }
545 
546 
547 // Get tab style
getTabStyle() const548 FXuint FXToolBarTab::getTabStyle() const {
549   return (options&TOOLBARTAB_MASK);
550   }
551 
552 
553 // Set text color
setActiveColor(FXColor clr)554 void FXToolBarTab::setActiveColor(FXColor clr){
555   if(clr!=activeColor){
556     activeColor=clr;
557     update();
558     }
559   }
560 
561 
562 // Save object to stream
save(FXStream & store) const563 void FXToolBarTab::save(FXStream& store) const {
564   FXFrame::save(store);
565   store << activeColor;
566   store << tip;
567   store << collapsed;
568   }
569 
570 
571 
572 // Load object from stream
load(FXStream & store)573 void FXToolBarTab::load(FXStream& store){
574   FXFrame::load(store);
575   store >> activeColor;
576   store >> tip;
577   store >> collapsed;
578   }
579 
580 }
581