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,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: FXSwitcher.cpp,v 1.35 2006/01/22 17:58:43 fox Exp $ *
23 ********************************************************************************/
24 #include "xincs.h"
25 #include "fxver.h"
26 #include "fxdefs.h"
27 #include "FXHash.h"
28 #include "FXThread.h"
29 #include "FXStream.h"
30 #include "FXString.h"
31 #include "FXSize.h"
32 #include "FXPoint.h"
33 #include "FXRectangle.h"
34 #include "FXRegistry.h"
35 #include "FXApp.h"
36 #include "FXDCWindow.h"
37 #include "FXSwitcher.h"
38
39
40 /*
41 Notes:
42 - We do not look at LAYOUT_FIX_WIDTH and LAYOUT_FIX_HEIGHT because
43 FXSwitcher resizes its children anyway and doing this would cause
44 the size to grow instead of shrinkwrap to the biggest child.
45 - Thanks to Charles Warren for the suggestion for the collapse
46 modes.
47 */
48
49
50 // Switcher styles
51 #define SWITCHER_MASK (SWITCHER_HCOLLAPSE|SWITCHER_VCOLLAPSE)
52
53 using namespace FX;
54
55 /*******************************************************************************/
56
57 namespace FX {
58
59 // Map
60 FXDEFMAP(FXSwitcher) FXSwitcherMap[]={
61 FXMAPFUNC(SEL_PAINT,0,FXSwitcher::onPaint),
62 FXMAPFUNCS(SEL_UPDATE,FXSwitcher::ID_OPEN_FIRST,FXSwitcher::ID_OPEN_LAST,FXSwitcher::onUpdOpen),
63 FXMAPFUNC(SEL_COMMAND,FXSwitcher::ID_SETVALUE,FXSwitcher::onCmdSetValue),
64 FXMAPFUNC(SEL_COMMAND,FXSwitcher::ID_SETINTVALUE,FXSwitcher::onCmdSetIntValue),
65 FXMAPFUNC(SEL_COMMAND,FXSwitcher::ID_GETINTVALUE,FXSwitcher::onCmdGetIntValue),
66 FXMAPFUNCS(SEL_COMMAND,FXSwitcher::ID_OPEN_FIRST,FXSwitcher::ID_OPEN_LAST,FXSwitcher::onCmdOpen),
67 };
68
69
70 // Object implementation
FXIMPLEMENT(FXSwitcher,FXPacker,FXSwitcherMap,ARRAYNUMBER (FXSwitcherMap))71 FXIMPLEMENT(FXSwitcher,FXPacker,FXSwitcherMap,ARRAYNUMBER(FXSwitcherMap))
72
73
74
75 // Make a switcher window
76 FXSwitcher::FXSwitcher(FXComposite *p,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb):
77 FXPacker(p,opts,x,y,w,h,pl,pr,pt,pb,0,0){
78 current=0;
79 }
80
81
82 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)83 long FXSwitcher::onPaint(FXObject*,FXSelector,void* ptr){
84 FXEvent *ev=(FXEvent*)ptr;
85 FXDCWindow dc(this,ev);
86 dc.setForeground(backColor);
87 dc.fillRectangle(ev->rect.x,ev->rect.y,ev->rect.w,ev->rect.h);
88 drawFrame(dc,0,0,width,height);
89 return 1;
90 }
91
92
93 // Update value from a message
onCmdSetValue(FXObject *,FXSelector,void * ptr)94 long FXSwitcher::onCmdSetValue(FXObject*,FXSelector,void* ptr){
95 setCurrent((FXint)(FXuval)ptr);
96 return 1;
97 }
98
99
100 // Update value from a message
onCmdSetIntValue(FXObject *,FXSelector,void * ptr)101 long FXSwitcher::onCmdSetIntValue(FXObject*,FXSelector,void* ptr){
102 setCurrent(*((FXint*)ptr));
103 return 1;
104 }
105
106
107 // Obtain value from text field
onCmdGetIntValue(FXObject *,FXSelector,void * ptr)108 long FXSwitcher::onCmdGetIntValue(FXObject*,FXSelector,void* ptr){
109 *((FXint*)ptr)=getCurrent();
110 return 1;
111 }
112
113
114 // Bring nth to the top
onCmdOpen(FXObject *,FXSelector sel,void *)115 long FXSwitcher::onCmdOpen(FXObject*,FXSelector sel,void*){
116 setCurrent(FXSELID(sel)-ID_OPEN_FIRST,TRUE);
117 return 1;
118 }
119
120
121 // Update the nth button
onUpdOpen(FXObject * sender,FXSelector sel,void * ptr)122 long FXSwitcher::onUpdOpen(FXObject* sender,FXSelector sel,void* ptr){
123 sender->handle(this,((FXSELID(sel)-ID_OPEN_FIRST)==current) ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),ptr);
124 return 1;
125 }
126
127
128 // Get maximum child width
getDefaultWidth()129 FXint FXSwitcher::getDefaultWidth(){
130 register FXWindow* child;
131 register FXint i,w,wmax=0,wcur=0;
132 for(i=0,child=getFirst(); child; child=child->getNext(),i++){
133 if(i==current) wcur=child->getDefaultWidth();
134 if(wmax<(w=child->getDefaultWidth())) wmax=w;
135 }
136 if(options&SWITCHER_HCOLLAPSE) wmax=wcur;
137 return padleft+padright+(border<<1)+wmax;
138 }
139
140
141 // Get maximum child height
getDefaultHeight()142 FXint FXSwitcher::getDefaultHeight(){
143 register FXWindow* child;
144 register FXint i,h,hmax=0,hcur=0;
145 for(i=0,child=getFirst(); child; child=child->getNext(),i++){
146 if(i==current) hcur=child->getDefaultHeight();
147 if(hmax<(h=child->getDefaultHeight())) hmax=h;
148 }
149 if(options&SWITCHER_VCOLLAPSE) hmax=hcur;
150 return padtop+padbottom+(border<<1)+hmax;
151 }
152
153
154 // Recalculate layout
layout()155 void FXSwitcher::layout(){
156 register FXWindow *child;
157 register FXint i,x,y,w,h;
158 x=border+padleft;
159 y=border+padtop;
160 w=width-padright-padleft-(border<<1);
161 h=height-padtop-padbottom-(border<<1);
162 for(i=0,child=getFirst(); child; child=child->getNext(),i++){
163 child->position(x,y,w,h);
164 if(i==current){
165 child->show();
166 }
167 else{
168 child->hide();
169 }
170 }
171 flags&=~FLAG_DIRTY;
172 }
173
174
175 // Set current subwindow
setCurrent(FXint panel,FXbool notify)176 void FXSwitcher::setCurrent(FXint panel,FXbool notify){
177 if(0<=panel && panel<numChildren() && current!=panel){
178 current=panel;
179 recalc();
180 if(notify && target){ target->tryHandle(this,FXSEL(SEL_COMMAND,message),(void*)(FXival)current); }
181 }
182 }
183
184
185 // Set switcher style
setSwitcherStyle(FXuint style)186 void FXSwitcher::setSwitcherStyle(FXuint style){
187 FXuint opts=(options&~SWITCHER_MASK) | (style&SWITCHER_MASK);
188 if(options!=opts){
189 options=opts;
190 recalc();
191 }
192 }
193
194
195 // Get switcher style
getSwitcherStyle() const196 FXuint FXSwitcher::getSwitcherStyle() const {
197 return (options&SWITCHER_MASK);
198 }
199
200
201 // Save object to stream
save(FXStream & store) const202 void FXSwitcher::save(FXStream& store) const {
203 FXPacker::save(store);
204 store << current;
205 }
206
207
208 // Load object from stream
load(FXStream & store)209 void FXSwitcher::load(FXStream& store){
210 FXPacker::load(store);
211 store >> current;
212 }
213
214 }
215