1 /********************************************************************************
2 *                                                                               *
3 *                      S w i t c h   P a n e l   C l a s s                      *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 1997,2020 by Jeroen van der Zijp.   All Rights Reserved.        *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify          *
9 * it under the terms of the GNU Lesser General Public License as published by   *
10 * the Free Software Foundation; either version 3 of the License, or             *
11 * (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                 *
16 * GNU Lesser General Public License for more details.                           *
17 *                                                                               *
18 * You should have received a copy of the GNU Lesser General Public License      *
19 * along with this program.  If not, see <http://www.gnu.org/licenses/>          *
20 ********************************************************************************/
21 #include "xincs.h"
22 #include "fxver.h"
23 #include "fxdefs.h"
24 #include "fxmath.h"
25 #include "FXArray.h"
26 #include "FXHash.h"
27 #include "FXMutex.h"
28 #include "FXStream.h"
29 #include "FXString.h"
30 #include "FXSize.h"
31 #include "FXPoint.h"
32 #include "FXRectangle.h"
33 #include "FXStringDictionary.h"
34 #include "FXSettings.h"
35 #include "FXRegistry.h"
36 #include "FXEvent.h"
37 #include "FXWindow.h"
38 #include "FXDCWindow.h"
39 #include "FXApp.h"
40 #include "FXSwitcher.h"
41 
42 
43 /*
44   Notes:
45   - We do not look at LAYOUT_FIX_WIDTH and LAYOUT_FIX_HEIGHT because
46     FXSwitcher resizes its children anyway and doing this would cause
47     the size to grow instead of shrinkwrap to the biggest child.
48   - Thanks to Charles Warren for the suggestion for the collapse
49     modes.
50   - The current panel number is adjusted if the number of panels changes.
51 */
52 
53 
54 // Switcher styles
55 #define SWITCHER_MASK (SWITCHER_HCOLLAPSE|SWITCHER_VCOLLAPSE)
56 
57 using namespace FX;
58 
59 /*******************************************************************************/
60 
61 namespace FX {
62 
63 // Map
64 FXDEFMAP(FXSwitcher) FXSwitcherMap[]={
65   FXMAPFUNC(SEL_PAINT,0,FXSwitcher::onPaint),
66   FXMAPFUNCS(SEL_UPDATE,FXSwitcher::ID_OPEN_FIRST,FXSwitcher::ID_OPEN_LAST,FXSwitcher::onUpdOpen),
67   FXMAPFUNC(SEL_COMMAND,FXSwitcher::ID_SETVALUE,FXSwitcher::onCmdSetValue),
68   FXMAPFUNC(SEL_COMMAND,FXSwitcher::ID_SETINTVALUE,FXSwitcher::onCmdSetIntValue),
69   FXMAPFUNC(SEL_COMMAND,FXSwitcher::ID_GETINTVALUE,FXSwitcher::onCmdGetIntValue),
70   FXMAPFUNCS(SEL_COMMAND,FXSwitcher::ID_OPEN_FIRST,FXSwitcher::ID_OPEN_LAST,FXSwitcher::onCmdOpen),
71   };
72 
73 
74 // Object implementation
FXIMPLEMENT(FXSwitcher,FXPacker,FXSwitcherMap,ARRAYNUMBER (FXSwitcherMap))75 FXIMPLEMENT(FXSwitcher,FXPacker,FXSwitcherMap,ARRAYNUMBER(FXSwitcherMap))
76 
77 
78 // Serialization
79 FXSwitcher::FXSwitcher():current(-1){
80   }
81 
82 
83 // Make a switcher window
FXSwitcher(FXComposite * p,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb)84 FXSwitcher::FXSwitcher(FXComposite *p,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb):FXPacker(p,opts,x,y,w,h,pl,pr,pt,pb,0,0),current(-1){
85   }
86 
87 
88 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)89 long FXSwitcher::onPaint(FXObject*,FXSelector,void* ptr){
90   FXEvent *ev=(FXEvent*)ptr;
91   FXDCWindow dc(this,ev);
92   dc.setForeground(backColor);
93   dc.fillRectangle(ev->rect.x,ev->rect.y,ev->rect.w,ev->rect.h);
94   drawFrame(dc,0,0,width,height);
95   return 1;
96   }
97 
98 
99 // Update value from a message
onCmdSetValue(FXObject *,FXSelector,void * ptr)100 long FXSwitcher::onCmdSetValue(FXObject*,FXSelector,void* ptr){
101   setCurrent((FXint)(FXuval)ptr);
102   return 1;
103   }
104 
105 
106 // Update value from a message
onCmdSetIntValue(FXObject *,FXSelector,void * ptr)107 long FXSwitcher::onCmdSetIntValue(FXObject*,FXSelector,void* ptr){
108   setCurrent(*((FXint*)ptr));
109   return 1;
110   }
111 
112 
113 // Obtain value from text field
onCmdGetIntValue(FXObject *,FXSelector,void * ptr)114 long FXSwitcher::onCmdGetIntValue(FXObject*,FXSelector,void* ptr){
115   *((FXint*)ptr)=getCurrent();
116   return 1;
117   }
118 
119 
120 // Bring nth to the top
onCmdOpen(FXObject *,FXSelector sel,void *)121 long FXSwitcher::onCmdOpen(FXObject*,FXSelector sel,void*){
122   setCurrent(FXSELID(sel)-ID_OPEN_FIRST,true);
123   return 1;
124   }
125 
126 
127 // Update the nth button
onUpdOpen(FXObject * sender,FXSelector sel,void * ptr)128 long FXSwitcher::onUpdOpen(FXObject* sender,FXSelector sel,void* ptr){
129   sender->handle(this,((FXSELID(sel)-ID_OPEN_FIRST)==current) ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),ptr);
130   return 1;
131   }
132 
133 
134 // Get maximum child width
getDefaultWidth()135 FXint FXSwitcher::getDefaultWidth(){
136   FXWindow* child;
137   FXint i,w,wmax=0,wcur=0;
138   for(i=0,child=getFirst(); child; child=child->getNext(),i++){
139     if(i==current) wcur=child->getDefaultWidth();
140     if(wmax<(w=child->getDefaultWidth())) wmax=w;
141     }
142   if(options&SWITCHER_HCOLLAPSE) wmax=wcur;
143   return padleft+padright+(border<<1)+wmax;
144   }
145 
146 
147 // Get maximum child height
getDefaultHeight()148 FXint FXSwitcher::getDefaultHeight(){
149   FXWindow* child;
150   FXint i,h,hmax=0,hcur=0;
151   for(i=0,child=getFirst(); child; child=child->getNext(),i++){
152     if(i==current) hcur=child->getDefaultHeight();
153     if(hmax<(h=child->getDefaultHeight())) hmax=h;
154     }
155   if(options&SWITCHER_VCOLLAPSE) hmax=hcur;
156   return padtop+padbottom+(border<<1)+hmax;
157   }
158 
159 
160 // Recalculate layout
layout()161 void FXSwitcher::layout(){
162   FXWindow *child;
163   FXint i,x,y,w,h;
164   x=border+padleft;
165   y=border+padtop;
166   w=width-padright-padleft-(border<<1);
167   h=height-padtop-padbottom-(border<<1);
168   if(current<0) current=0;
169   if(current>=numChildren()) current=numChildren()-1;
170   for(child=getFirst(),i=0; child; child=child->getNext(),i++){
171     child->position(x,y,w,h);
172     if(i==current){
173       child->show();
174       }
175     else{
176       child->hide();
177       }
178     }
179   flags&=~FLAG_DIRTY;
180   }
181 
182 
183 // Set current subwindow
setCurrent(FXint panel,FXbool notify)184 void FXSwitcher::setCurrent(FXint panel,FXbool notify){
185   if(current!=panel && 0<=panel && panel<numChildren()){
186     current=panel;
187     recalc();
188     if(notify && target){ target->tryHandle(this,FXSEL(SEL_COMMAND,message),(void*)(FXival)current); }
189     }
190   }
191 
192 
193 // Set switcher style
setSwitcherStyle(FXuint style)194 void FXSwitcher::setSwitcherStyle(FXuint style){
195   FXuint opts=(options&~SWITCHER_MASK) | (style&SWITCHER_MASK);
196   if(options!=opts){
197     options=opts;
198     recalc();
199     }
200   }
201 
202 
203 // Get switcher style
getSwitcherStyle() const204 FXuint FXSwitcher::getSwitcherStyle() const {
205   return (options&SWITCHER_MASK);
206   }
207 
208 
209 // Save object to stream
save(FXStream & store) const210 void FXSwitcher::save(FXStream& store) const {
211   FXPacker::save(store);
212   store << current;
213   }
214 
215 
216 // Load object from stream
load(FXStream & store)217 void FXSwitcher::load(FXStream& store){
218   FXPacker::load(store);
219   store >> current;
220   }
221 
222 }
223