1 /********************************************************************************
2 *                                                                               *
3 *                    T o o l   B a r   G r i p   W i d g e t                    *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 2000,2021 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 "fxkeys.h"
25 #include "fxmath.h"
26 #include "FXArray.h"
27 #include "FXHash.h"
28 #include "FXMutex.h"
29 #include "FXStream.h"
30 #include "FXString.h"
31 #include "FXSize.h"
32 #include "FXPoint.h"
33 #include "FXRectangle.h"
34 #include "FXStringDictionary.h"
35 #include "FXSettings.h"
36 #include "FXRegistry.h"
37 #include "FXEvent.h"
38 #include "FXWindow.h"
39 #include "FXDCWindow.h"
40 #include "FXApp.h"
41 #include "FXToolBar.h"
42 #include "FXToolBarGrip.h"
43 
44 
45 /*
46   Notes:
47   - Tool bar grip is a small grabber contained in the toolbar which lets
48     a user move the toolbar around, dock and undock it, and so on.
49   - The convention is to let single-rebar tool bar grips rearrange the
50     bars in a dock site, and double-rebar grips dock and undock.
51     This convention is recommended but not enforced.
52 */
53 
54 
55 // Size
56 #define GRIP_SINGLE  3          // Single grip for arrangable toolbars
57 #define GRIP_DOUBLE  7          // Double grip for dockable toolbars
58 
59 #define JUSTIFY_MASK (JUSTIFY_HZ_APART|JUSTIFY_VT_APART)
60 
61 
62 using namespace FX;
63 
64 /*******************************************************************************/
65 
66 namespace FX {
67 
68 // Map
69 FXDEFMAP(FXToolBarGrip) FXToolBarGripMap[]={
70   FXMAPFUNC(SEL_PAINT,0,FXToolBarGrip::onPaint),
71   FXMAPFUNC(SEL_ENTER,0,FXToolBarGrip::onEnter),
72   FXMAPFUNC(SEL_LEAVE,0,FXToolBarGrip::onLeave),
73   FXMAPFUNC(SEL_MOTION,0,FXToolBarGrip::onMotion),
74   FXMAPFUNC(SEL_LEFTBUTTONPRESS,0,FXToolBarGrip::onLeftBtnPress),
75   FXMAPFUNC(SEL_LEFTBUTTONRELEASE,0,FXToolBarGrip::onLeftBtnRelease),
76   FXMAPFUNC(SEL_KEYPRESS,0,FXToolBarGrip::onKeyPress),
77   FXMAPFUNC(SEL_KEYRELEASE,0,FXToolBarGrip::onKeyRelease),
78   FXMAPFUNC(SEL_COMMAND,FXToolBarGrip::ID_SETHELPSTRING,FXToolBarGrip::onCmdSetHelp),
79   FXMAPFUNC(SEL_COMMAND,FXToolBarGrip::ID_GETHELPSTRING,FXToolBarGrip::onCmdGetHelp),
80   FXMAPFUNC(SEL_COMMAND,FXToolBarGrip::ID_SETTIPSTRING,FXToolBarGrip::onCmdSetTip),
81   FXMAPFUNC(SEL_COMMAND,FXToolBarGrip::ID_GETTIPSTRING,FXToolBarGrip::onCmdGetTip),
82   };
83 
84 
85 // Object implementation
FXIMPLEMENT(FXToolBarGrip,FXDockHandler,FXToolBarGripMap,ARRAYNUMBER (FXToolBarGripMap))86 FXIMPLEMENT(FXToolBarGrip,FXDockHandler,FXToolBarGripMap,ARRAYNUMBER(FXToolBarGripMap))
87 
88 
89 // Deserialization
90 FXToolBarGrip::FXToolBarGrip(){
91   activeColor=0;
92   }
93 
94 
95 // Construct and init
FXToolBarGrip(FXComposite * p,FXObject * tgt,FXSelector sel,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb)96 FXToolBarGrip::FXToolBarGrip(FXComposite* p,FXObject* tgt,FXSelector sel,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb):FXDockHandler(p,tgt,sel,opts,x,y,w,h,pl,pr,pt,pb){
97   activeColor=FXRGB(0,0,255);
98   }
99 
100 
101 
102 // Get default width
getDefaultWidth()103 FXint FXToolBarGrip::getDefaultWidth(){
104   return padleft+padright+(border<<1)+((options&TOOLBARGRIP_DOUBLE)?GRIP_DOUBLE:GRIP_SINGLE);
105   }
106 
107 
108 // Get default height
getDefaultHeight()109 FXint FXToolBarGrip::getDefaultHeight(){
110   return padtop+padbottom+(border<<1)+((options&TOOLBARGRIP_DOUBLE)?GRIP_DOUBLE:GRIP_SINGLE);
111   }
112 
113 
114 // Can have focus
canFocus() const115 FXbool FXToolBarGrip::canFocus() const { return false; }
116 
117 
118 // Change toolbar orientation
setDoubleBar(FXbool dbl)119 void FXToolBarGrip::setDoubleBar(FXbool dbl){
120   FXuint opts=dbl?(options|TOOLBARGRIP_DOUBLE):(options&~TOOLBARGRIP_DOUBLE);
121   if(opts!=options){
122     options=opts;
123     recalc();
124     }
125   }
126 
127 
128 // Return true if toolbar grip is displayed as a double bar
isDoubleBar() const129 FXbool FXToolBarGrip::isDoubleBar() const {
130   return (options&TOOLBARGRIP_DOUBLE)!=0;
131   }
132 
133 
134 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)135 long FXToolBarGrip::onPaint(FXObject*,FXSelector,void* ptr){
136   FXEvent* event=static_cast<FXEvent*>(ptr);
137   FXDCWindow dc(this,event);
138   FXint xx,yy,ww,hh;
139   dc.setForeground(backColor);
140   dc.fillRectangle(border,border,width-(border<<1),height-(border<<1));
141   ww=width-padleft-padright-(border<<1);
142   hh=height-padtop-padbottom-(border<<1);
143   if(width>height){
144     xx=border+padleft;
145     if(options&TOOLBARGRIP_DOUBLE){     // =
146       yy=border+padtop+(hh-GRIP_DOUBLE)/2;
147       dc.setForeground(hiliteColor);
148       dc.fillRectangle(xx,yy,1,2);
149       dc.fillRectangle(xx,yy+4,1,2);
150       dc.fillRectangle(xx,yy,ww-1,1);
151       dc.fillRectangle(xx,yy+4,ww-1,1);
152       dc.setForeground(shadowColor);
153       dc.fillRectangle(xx+ww-1,yy,1,3);
154       dc.fillRectangle(xx+ww-1,yy+4,1,3);
155       dc.fillRectangle(xx,yy+2,ww-1,1);
156       dc.fillRectangle(xx,yy+6,ww-1,1);
157       if(flags&(FLAG_ACTIVE|FLAG_TRYDRAG|FLAG_DODRAG)){
158         dc.setForeground(activeColor);
159         dc.fillRectangle(xx+1,yy+1,ww-2,1);
160         dc.fillRectangle(xx+1,yy+5,ww-2,1);
161         }
162       }
163     else{                               // -
164       yy=border+padtop+(hh-GRIP_SINGLE)/2;
165       dc.setForeground(hiliteColor);
166       dc.fillRectangle(xx,yy,1,2);
167       dc.fillRectangle(xx,yy,ww-1,1);
168       dc.setForeground(shadowColor);
169       dc.fillRectangle(xx+ww-1,yy,1,3);
170       dc.fillRectangle(xx,yy+2,ww-1,1);
171       if(flags&(FLAG_ACTIVE|FLAG_TRYDRAG|FLAG_DODRAG)){
172         dc.setForeground(activeColor);
173         dc.fillRectangle(xx+1,yy+1,ww-2,1);
174         }
175       }
176     }
177   else{
178     yy=border+padtop;
179     if(options&TOOLBARGRIP_DOUBLE){     // ||
180       xx=border+padleft+(ww-GRIP_DOUBLE)/2;
181       dc.setForeground(hiliteColor);
182       dc.fillRectangle(xx,yy,2,1);
183       dc.fillRectangle(xx+4,yy,2,1);
184       dc.fillRectangle(xx,yy,1,hh-1);
185       dc.fillRectangle(xx+4,yy,1,hh-1);
186       dc.setForeground(shadowColor);
187       dc.fillRectangle(xx,yy+hh-1,3,1);
188       dc.fillRectangle(xx+4,yy+hh-1,3,1);
189       dc.fillRectangle(xx+2,yy,1,hh-1);
190       dc.fillRectangle(xx+6,yy,1,hh-1);
191       if(flags&(FLAG_ACTIVE|FLAG_TRYDRAG|FLAG_DODRAG)){
192         dc.setForeground(activeColor);
193         dc.fillRectangle(xx+1,yy+1,1,hh-2);
194         dc.fillRectangle(xx+5,yy+1,1,hh-2);
195         }
196       }
197     else{                               // |
198       xx=border+padleft+(ww-GRIP_SINGLE)/2;
199       dc.setForeground(hiliteColor);
200       dc.fillRectangle(xx,yy,2,1);
201       dc.fillRectangle(xx,yy,1,hh-1);
202       dc.setForeground(shadowColor);
203       dc.fillRectangle(xx,yy+hh-1,3,1);
204       dc.fillRectangle(xx+2,yy,1,hh-1);
205       if(flags&(FLAG_ACTIVE|FLAG_TRYDRAG|FLAG_DODRAG)){
206         dc.setForeground(activeColor);
207         dc.fillRectangle(xx+1,yy+1,1,hh-2);
208         }
209       }
210     }
211   drawFrame(dc,0,0,width,height);
212   return 1;
213   }
214 
215 
216 // Entered button
onEnter(FXObject * sender,FXSelector sel,void * ptr)217 long FXToolBarGrip::onEnter(FXObject* sender,FXSelector sel,void* ptr){
218   FXDockHandler::onEnter(sender,sel,ptr);
219   if(isEnabled()){ flags|=FLAG_ACTIVE; update(); }
220   return 1;
221   }
222 
223 
224 // Leave button
onLeave(FXObject * sender,FXSelector sel,void * ptr)225 long FXToolBarGrip::onLeave(FXObject* sender,FXSelector sel,void* ptr){
226   FXDockHandler::onLeave(sender,sel,ptr);
227   if(isEnabled()){ flags&=~FLAG_ACTIVE; update(); }
228   return 1;
229   }
230 
231 
232 
233 // Set active color
setActiveColor(FXColor clr)234 void FXToolBarGrip::setActiveColor(FXColor clr){
235   if(clr!=activeColor){
236     activeColor=clr;
237     update();
238     }
239   }
240 
241 
242 // Save data
save(FXStream & store) const243 void FXToolBarGrip::save(FXStream& store) const {
244   FXDockHandler::save(store);
245   store << activeColor;
246   }
247 
248 
249 // Load data
load(FXStream & store)250 void FXToolBarGrip::load(FXStream& store){
251   FXDockHandler::load(store);
252   store >> activeColor;
253   }
254 
255 
256 }
257