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