1 /********************************************************************************
2 * *
3 * S h u t t e r C o n t a i n e r W i d g e t *
4 * *
5 *********************************************************************************
6 * Copyright (C) 1998,2005 by Charles W. Warren. 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: FXShutter.cpp,v 1.40 2005/01/16 16:06:07 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 "FXAccelTable.h"
36 #include "FXApp.h"
37 #include "FXIcon.h"
38 #include "FXFrame.h"
39 #include "FXPacker.h"
40 #include "FXVerticalFrame.h"
41 #include "FXLabel.h"
42 #include "FXButton.h"
43 #include "FXScrollBar.h"
44 #include "FXScrollWindow.h"
45 #include "FXShutter.h"
46
47 /*
48 Notes:
49 - Works now by means of integers, i.e. setCurrent(0) instead of having
50 to hang on to pointers to specific shutter items.
51 Advantage: You can make it connect to other widgets.
52 */
53
54 using namespace FX;
55
56 /*******************************************************************************/
57
58 namespace FX {
59
60 // Map
61 FXDEFMAP(FXShutterItem) FXShutterItemMap[]={
62 FXMAPFUNC(SEL_FOCUS_UP,0,FXShutterItem::onFocusUp),
63 FXMAPFUNC(SEL_FOCUS_DOWN,0,FXShutterItem::onFocusDown),
64 FXMAPFUNC(SEL_COMMAND,FXShutterItem::ID_SHUTTERITEM_BUTTON,FXShutterItem::onCmdButton),
65 };
66
67
68 // Object implementation
FXIMPLEMENT(FXShutterItem,FXVerticalFrame,FXShutterItemMap,ARRAYNUMBER (FXShutterItemMap))69 FXIMPLEMENT(FXShutterItem,FXVerticalFrame,FXShutterItemMap,ARRAYNUMBER(FXShutterItemMap))
70
71
72 FXShutterItem::FXShutterItem(FXShutter* p,const FXString& text,FXIcon* icon,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb,FXint hs,FXint vs):
73 FXVerticalFrame(p,(opts&~(PACK_UNIFORM_HEIGHT|PACK_UNIFORM_WIDTH)),x,y,w,h,0,0,0,0,0,0){
74 button=new FXButton(this,text,icon,this,FXShutterItem::ID_SHUTTERITEM_BUTTON,FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT,0,0,0,0,0,0,0,0);
75 scrollWindow=new FXScrollWindow(this,VSCROLLER_NEVER|HSCROLLER_NEVER|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_LEFT|LAYOUT_TOP,0,0,0,0);
76 content=new FXVerticalFrame(scrollWindow,LAYOUT_FILL_X|LAYOUT_FILL_Y|(opts&(PACK_UNIFORM_HEIGHT|PACK_UNIFORM_WIDTH)),0,0,0,0,pl,pr,pt,pb,hs,vs);
77 content->setBackColor(getApp()->getShadowColor());
78 }
79
80
81 // Button Pressed
onCmdButton(FXObject *,FXSelector,void * ptr)82 long FXShutterItem::onCmdButton(FXObject*,FXSelector,void* ptr){
83 getParent()->handle(this,FXSEL(SEL_COMMAND,FXShutter::ID_OPEN_SHUTTERITEM),ptr);
84 return 1;
85 }
86
87
88 // Focus moved up
onFocusUp(FXObject * sender,FXSelector sel,void * ptr)89 long FXShutterItem::onFocusUp(FXObject* sender,FXSelector sel,void* ptr){
90 return FXVerticalFrame::onFocusPrev(sender,sel,ptr);
91 }
92
93
94 // Focus moved down
onFocusDown(FXObject * sender,FXSelector sel,void * ptr)95 long FXShutterItem::onFocusDown(FXObject* sender,FXSelector sel,void* ptr){
96 return FXVerticalFrame::onFocusNext(sender,sel,ptr);
97 }
98
99
100 // Change help text
setHelpText(const FXString & text)101 void FXShutterItem::setHelpText(const FXString& text){
102 button->setHelpText(text);
103 }
104
105
106 // Get help text
getHelpText() const107 FXString FXShutterItem::getHelpText() const {
108 return button->getHelpText();
109 }
110
111
112 // Change tip text
setTipText(const FXString & text)113 void FXShutterItem::setTipText(const FXString& text){
114 button->setTipText(text);
115 }
116
117
118 // Get tip text
getTipText() const119 FXString FXShutterItem::getTipText() const {
120 return button->getTipText();
121 }
122
123
124
125 // Thrash it
~FXShutterItem()126 FXShutterItem::~FXShutterItem(){
127 button=(FXButton*)-1L;
128 scrollWindow=(FXScrollWindow*)-1L;
129 content=(FXVerticalFrame*)-1L;
130 }
131
132
133 /*******************************************************************************/
134
135 // Map
136 FXDEFMAP(FXShutter) FXShutterMap[]={
137 FXMAPFUNC(SEL_FOCUS_UP,0,FXShutter::onFocusUp),
138 FXMAPFUNC(SEL_FOCUS_DOWN,0,FXShutter::onFocusDown),
139 FXMAPFUNCS(SEL_UPDATE,FXShutter::ID_OPEN_FIRST,FXShutter::ID_OPEN_LAST,FXShutter::onUpdOpen),
140 FXMAPFUNC(SEL_TIMEOUT,FXShutter::ID_SHUTTER_TIMEOUT,FXShutter::onTimeout),
141 FXMAPFUNC(SEL_COMMAND,FXShutter::ID_OPEN_SHUTTERITEM,FXShutter::onOpenItem),
142 FXMAPFUNC(SEL_COMMAND,FXShutter::ID_SETVALUE,FXShutter::onCmdSetValue),
143 FXMAPFUNC(SEL_COMMAND,FXShutter::ID_SETINTVALUE,FXShutter::onCmdSetIntValue),
144 FXMAPFUNC(SEL_COMMAND,FXShutter::ID_GETINTVALUE,FXShutter::onCmdGetIntValue),
145 FXMAPFUNCS(SEL_COMMAND,FXShutter::ID_OPEN_FIRST,FXShutter::ID_OPEN_LAST,FXShutter::onCmdOpen),
146 };
147
148
149 // Object implementation
FXIMPLEMENT(FXShutter,FXVerticalFrame,FXShutterMap,ARRAYNUMBER (FXShutterMap))150 FXIMPLEMENT(FXShutter,FXVerticalFrame,FXShutterMap,ARRAYNUMBER(FXShutterMap))
151
152
153 // Make shutter
154 FXShutter::FXShutter(FXComposite* p,FXObject* tgt,FXSelector sel,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb,FXint hs,FXint vs):
155 FXVerticalFrame(p,opts,x,y,w,h,pl,pr,pt,pb,hs,vs){
156 target=tgt;
157 message=sel;
158 heightIncrement=1;
159 closingHeight=0;
160 closingHadScrollbar=FALSE;
161 current=0;
162 closing=-1;
163 }
164
165
166 // Focus moved up
onFocusUp(FXObject * sender,FXSelector sel,void * ptr)167 long FXShutter::onFocusUp(FXObject* sender,FXSelector sel,void* ptr){
168 return FXVerticalFrame::onFocusPrev(sender,sel,ptr);
169 }
170
171
172 // Focus moved down
onFocusDown(FXObject * sender,FXSelector sel,void * ptr)173 long FXShutter::onFocusDown(FXObject* sender,FXSelector sel,void* ptr){
174 return FXVerticalFrame::onFocusNext(sender,sel,ptr);
175 }
176
177 // Update value from a message
onCmdSetValue(FXObject *,FXSelector,void * ptr)178 long FXShutter::onCmdSetValue(FXObject*,FXSelector,void* ptr){
179 setCurrent((FXint)(FXival)ptr);
180 return 1;
181 }
182
183
184 // Update value from a message
onCmdSetIntValue(FXObject *,FXSelector,void * ptr)185 long FXShutter::onCmdSetIntValue(FXObject*,FXSelector,void* ptr){
186 setCurrent(*((FXint*)ptr));
187 return 1;
188 }
189
190
191 // Obtain value from text field
onCmdGetIntValue(FXObject *,FXSelector,void * ptr)192 long FXShutter::onCmdGetIntValue(FXObject*,FXSelector,void* ptr){
193 *((FXint*)ptr)=current;
194 return 1;
195 }
196
197
198 // Open item
onCmdOpen(FXObject *,FXSelector sel,void *)199 long FXShutter::onCmdOpen(FXObject*,FXSelector sel,void*){
200 setCurrent(FXSELID(sel)-ID_OPEN_FIRST);
201 return 1;
202 }
203
204
205 // Update the nth button
onUpdOpen(FXObject * sender,FXSelector sel,void * ptr)206 long FXShutter::onUpdOpen(FXObject* sender,FXSelector sel,void* ptr){
207 sender->handle(this,((FXSELID(sel)-ID_OPEN_FIRST)==current) ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK),ptr);
208 return 1;
209 }
210
211
212 // The sender of the message is the item to open up
onOpenItem(FXObject * sender,FXSelector,void *)213 long FXShutter::onOpenItem(FXObject* sender,FXSelector,void*){
214 FXint which=indexOfChild((FXWindow*)sender);
215 FXuint speed=getApp()->getAnimSpeed();
216 FXShutterItem *closingItem;
217 if(current==which) which--; // Clicking on title button of currently active item should close it; "Markus Fleck" <fleck@gnu.org>
218 if(0<=which){
219 if(speed){
220 closing=current;
221 heightIncrement=1;
222 closingItem=(FXShutterItem*)childAtIndex(closing);
223 closingHeight=closingItem->getHeight();
224 closingHadScrollbar=closingItem->scrollWindow->verticalScrollBar()->shown();
225 getApp()->addTimeout(this,ID_SHUTTER_TIMEOUT,speed);
226 }
227 current=which;
228 recalc();
229 if(target) target->tryHandle(this,FXSEL(SEL_COMMAND,message),(void*)(FXival)current);
230 }
231 return 1;
232 }
233
234
235 // Shutter Item Animation
onTimeout(FXObject *,FXSelector,void *)236 long FXShutter::onTimeout(FXObject*,FXSelector,void*){
237
238 // Closing item got deleted
239 if(closing<0) return 0;
240
241 // Shrink closing item a bit more
242 closingHeight-=heightIncrement;
243 heightIncrement+=5;
244
245 // Force layout again
246 recalc();
247
248 // Still not fully closed?
249 if(closingHeight>0){
250 getApp()->addTimeout(this,ID_SHUTTER_TIMEOUT,getApp()->getAnimSpeed());
251 return 1;
252 }
253
254 // Now fully closed
255 closing=-1;
256
257 return 1;
258 }
259
260
261 // Layout
layout()262 void FXShutter::layout(){
263 register FXShutterItem* child;
264 register FXint index,numchildren;
265
266 numchildren=numChildren();
267
268 // One of the children may have disappeared
269 if(current>=numchildren) current=numchildren-1;
270 if(current==-1 && numchildren>0) current=0; // Fix by "Martin Welch" <mwelch@totalise.co.uk>
271 if(closing>=numchildren) closing=-1;
272
273 // Force only one of the children to be open
274 for(child=(FXShutterItem*)getFirst(),index=0; child; child=(FXShutterItem*)child->getNext(),index++){
275 if(child->shown()){
276 if(index==current){
277 child->setLayoutHints(LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_LEFT|LAYOUT_TOP);
278 child->scrollWindow->setScrollStyle((closing>=0) ? (VSCROLLER_NEVER|HSCROLLER_NEVER) : HSCROLLER_NEVER);
279 child->scrollWindow->show();
280 }
281 else if(index==closing){
282 child->setLayoutHints(LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT|LAYOUT_LEFT|LAYOUT_TOP);
283 child->scrollWindow->setScrollStyle(closingHadScrollbar ? (VSCROLLER_ALWAYS|HSCROLLER_NEVER) : (VSCROLLER_NEVER|HSCROLLER_NEVER));
284 child->setHeight(closingHeight);
285 }
286 else{
287 child->setLayoutHints(LAYOUT_FILL_X|LAYOUT_LEFT|LAYOUT_TOP);
288 child->scrollWindow->hide();
289 }
290 }
291 }
292
293 // Then layout normally
294 FXVerticalFrame::layout();
295 flags&=~FLAG_DIRTY;
296 }
297
298
299 // Set current subwindow
setCurrent(FXint panel)300 void FXShutter::setCurrent(FXint panel){
301 if(0<=panel && current!=panel){
302 current=panel;
303 recalc();
304 }
305 }
306
307
308 // Clean up
~FXShutter()309 FXShutter::~FXShutter() {
310 getApp()->removeTimeout(this,ID_SHUTTER_TIMEOUT);
311 }
312
313 }
314
315