1 /********************************************************************************
2 *                                                                               *
3 *                         D o c k   S i t e   W i d g e t                       *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 2004,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 "FXApp.h"
39 #include "FXPacker.h"
40 #include "FXDockBar.h"
41 #include "FXDockSite.h"
42 
43 
44 /*
45   Notes:
46   - Use "Box-Car" algorithm when sliding horizontally (vertically).
47   - Vertical arrangement is very tricky; we don't insert in between
48     galleys when dragging since its not so easy to use; but this remains
49     a possibility for future expansion.
50   - We can STILL do wrapping of individual toolbars inside the toolbar dock;
51     normally we compute the width the standard way, but if this does not
52     fit the available space and its the first widget on the galley, we
53     can call getHeightForWidth() and thereby wrap the item in on the
54     galley.  Thus we have both wrapping of the toobars as well as
55     wrapping inside the toolbar.
56   - FIXME we should look at LAYOUT_DOCK_NEXT before shown() because
57     if you hide a bar, we want to keep stuff in the same place.
58   - Another nice addition would be to constrain docking from adding
59     extra galleys, except when unavoidable.
60 */
61 
62 #define FUDGE 20        // Amount to move down/up before jumping into next galley
63 
64 using namespace FX;
65 
66 /*******************************************************************************/
67 
68 namespace FX {
69 
70 // Map
71 FXDEFMAP(FXDockSite) FXDockSiteMap[]={
72 //  FXMAPFUNC(SEL_MOTION,0,FXDockSite::onMotion),
73 //  FXMAPFUNC(SEL_ENTER,0,FXDockSite::onEnter),
74 //  FXMAPFUNC(SEL_LEAVE,0,FXDockSite::onLeave),
75 //  FXMAPFUNC(SEL_LEFTBUTTONPRESS,0,FXDockSite::onLeftBtnPress),
76 //  FXMAPFUNC(SEL_LEFTBUTTONRELEASE,0,FXDockSite::onLeftBtnRelease),
77   FXMAPFUNC(SEL_FOCUS_PREV,0,FXDockSite::onFocusLeft),
78   FXMAPFUNC(SEL_FOCUS_NEXT,0,FXDockSite::onFocusRight),
79   };
80 
81 
82 // Object implementation
FXIMPLEMENT(FXDockSite,FXPacker,FXDockSiteMap,ARRAYNUMBER (FXDockSiteMap))83 FXIMPLEMENT(FXDockSite,FXPacker,FXDockSiteMap,ARRAYNUMBER(FXDockSiteMap))
84 
85 
86 /*
87 // Cursor shape based on mode
88 const FXDefaultCursor FXDockSite::cursorType[16]={
89   DEF_ARROW_CURSOR,
90   DEF_DRAGH_CURSOR,     // DRAG_TOP
91   DEF_DRAGH_CURSOR,     // DRAG_BOTTOM
92   DEF_ARROW_CURSOR,
93 
94   DEF_DRAGV_CURSOR,     // DRAG_LEFT
95   DEF_DRAGTL_CURSOR,    // DRAG_LEFT DRAG_TOP
96   DEF_DRAGTR_CURSOR,    // DRAG_LEFT DRAG_BOTTOM
97   DEF_ARROW_CURSOR,
98 
99   DEF_DRAGV_CURSOR,     // DRAG_RIGHT
100   DEF_DRAGTR_CURSOR,    // DRAG_RIGHT DRAG_TOP
101   DEF_DRAGTL_CURSOR,    // DRAG_RIGHT DRAG_BOTTOM
102   DEF_ARROW_CURSOR,
103 
104   DEF_ARROW_CURSOR,
105   DEF_ARROW_CURSOR,
106   DEF_ARROW_CURSOR,
107   DEF_ARROW_CURSOR,
108   };
109 */
110 
111 // Make a dock site
112 FXDockSite::FXDockSite(FXComposite* p,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb,FXint hs,FXint vs):FXPacker(p,opts,x,y,w,h,pl,pr,pt,pb,hs,vs){
113 //  mode=DRAG_NONE;
114   }
115 
116 
117 // Change wrap option
wrapGalleys(FXbool wrap)118 void FXDockSite::wrapGalleys(FXbool wrap){
119   if(wrap && wrapGalleys()){
120     options&=~DOCKSITE_NO_WRAP;
121     recalc();
122     }
123   else if(!wrap && !wrapGalleys()){
124     options|=DOCKSITE_NO_WRAP;
125     recalc();
126     }
127   }
128 
129 
130 // Get wrap option
wrapGalleys() const131 FXbool FXDockSite::wrapGalleys() const {
132   return (options&DOCKSITE_NO_WRAP)==0;
133   }
134 
135 
136 // Compute minimum width based on child layout hints
getDefaultWidth()137 FXint FXDockSite::getDefaultWidth(){
138   FXint total=0,galw=0,w;
139   FXWindow *child;
140   FXuint hints;
141 
142   // Vertically oriented
143   if(options&LAYOUT_SIDE_LEFT){
144     for(child=getFirst(); child; child=child->getNext()){
145       if(child->shown()){
146         hints=child->getLayoutHints();
147         w=(hints&LAYOUT_FIX_WIDTH)?child->getWidth():child->getDefaultWidth();
148         if(hints&LAYOUT_DOCK_NEXT){
149           if(total) total+=hspacing;
150           total+=galw;
151           galw=w;
152           }
153         else{
154           if(w>galw) galw=w;
155           }
156         }
157       }
158     total+=galw;
159     }
160 
161   // Horizontally oriented
162   else{
163     for(child=getFirst(); child; child=child->getNext()){
164       if(child->shown()){
165         hints=child->getLayoutHints();
166         w=(hints&LAYOUT_FIX_WIDTH)?child->getWidth():child->getDefaultWidth();
167         if(hints&LAYOUT_DOCK_NEXT){
168           if(galw>total) total=galw;
169           galw=w;
170           }
171         else{
172           if(galw) galw+=hspacing;
173           galw+=w;
174           }
175         }
176       }
177     if(galw>total) total=galw;
178     }
179   return padleft+padright+total+(border<<1);
180   }
181 
182 
183 // Compute minimum height based on child layout hints
getDefaultHeight()184 FXint FXDockSite::getDefaultHeight(){
185   FXint total=0,galh=0,h;
186   FXWindow *child;
187   FXuint hints;
188 
189   // Vertically oriented
190   if(options&LAYOUT_SIDE_LEFT){
191     for(child=getFirst(); child; child=child->getNext()){
192       if(child->shown()){
193         hints=child->getLayoutHints();
194         h=(hints&LAYOUT_FIX_HEIGHT)?child->getHeight():child->getDefaultHeight();
195         if(hints&LAYOUT_DOCK_NEXT){
196           if(galh>total) total=galh;
197           galh=h;
198           }
199         else{
200           if(galh) galh+=vspacing;
201           galh+=h;
202           }
203         }
204       }
205     if(galh>total) total=galh;
206     }
207 
208   // Horizontally oriented
209   else{
210     for(child=getFirst(); child; child=child->getNext()){
211       if(child->shown()){
212         hints=child->getLayoutHints();
213         h=(hints&LAYOUT_FIX_HEIGHT)?child->getHeight():child->getDefaultHeight();
214         if(hints&LAYOUT_DOCK_NEXT){
215           if(total) total+=vspacing;
216           total+=galh;
217           galh=h;
218           }
219         else{
220           if(h>galh) galh=h;
221           }
222         }
223       }
224     total+=galh;
225     }
226   return padtop+padbottom+total+(border<<1);
227   }
228 
229 
230 // Return width for given height (vertical orientation)
getWidthForHeight(FXint givenheight)231 FXint FXDockSite::getWidthForHeight(FXint givenheight){
232   FXint total=0,galh=0,galw=0,w,h;
233   FXWindow *child;
234   FXuint hints;
235   givenheight-=padtop+padbottom+border+border;
236   for(child=getFirst(); child; child=child->getNext()){
237     if(child->shown()){
238       hints=child->getLayoutHints();
239       w=(hints&LAYOUT_FIX_WIDTH)?child->getWidth():child->getDefaultWidth();
240       h=(hints&LAYOUT_FIX_HEIGHT)?child->getHeight():child->getDefaultHeight();
241       if((hints&LAYOUT_DOCK_NEXT) || (!(options&DOCKSITE_NO_WRAP) && galh+h>givenheight)){
242         if(total) total+=hspacing;
243         total+=galw;
244         galw=w;
245         galh=h+vspacing;
246         }
247       else{
248         galh+=h+vspacing;
249         if(w>galw) galw=w;
250         }
251       }
252     }
253   total+=galw;
254   return padleft+padright+total+(border<<1);
255   }
256 
257 
258 // Return height for given width (horizontal orientation)
getHeightForWidth(FXint givenwidth)259 FXint FXDockSite::getHeightForWidth(FXint givenwidth){
260   FXint total=0,galh=0,galw=0,w,h;
261   FXWindow *child;
262   FXuint hints;
263   givenwidth-=padleft+padright+border+border;
264   for(child=getFirst(); child; child=child->getNext()){
265     if(child->shown()){
266       hints=child->getLayoutHints();
267       w=(hints&LAYOUT_FIX_WIDTH)?child->getWidth():child->getDefaultWidth();
268       h=(hints&LAYOUT_FIX_HEIGHT)?child->getHeight():child->getDefaultHeight();
269       if((hints&LAYOUT_DOCK_NEXT) || (!(options&DOCKSITE_NO_WRAP) && galw+w>givenwidth)){
270         if(total) total+=vspacing;
271         total+=galh;
272         galw=w+hspacing;
273         galh=h;
274         }
275       else{
276         galw+=w+hspacing;
277         if(h>galh) galh=h;
278         }
279       }
280     }
281   total+=galh;
282   return padtop+padbottom+total+(border<<1);
283   }
284 
285 
286 // Find begin and end of galley containing bar on horizontal dock site
galleyOfHorzBar(FXWindow * bar,FXWindow * & begin,FXWindow * & end) const287 void FXDockSite::galleyOfHorzBar(FXWindow *bar,FXWindow*& begin,FXWindow*& end) const {
288   FXint space=width-padleft-padright-border-border,ss=0,w;
289   FXWindow *child;
290   for(child=bar; child->getPrev(); child=child->getPrev()){
291     if(child->shown() && (child->getLayoutHints()&LAYOUT_DOCK_NEXT)) break;
292     }
293   for(begin=child; child!=bar; child=child->getNext()){
294     if(!child->shown()) continue;
295     w=(child->getLayoutHints()&LAYOUT_FIX_WIDTH) ? child->getWidth() : child->getDefaultWidth();
296     if(!(options&DOCKSITE_NO_WRAP) && ss+w>space){
297       begin=child;
298       ss=w+hspacing;
299       }
300     else{
301       ss+=w+hspacing;
302       }
303     }
304   for(end=child; child; end=child,child=child->getNext()){
305     if(!child->shown()) continue;
306     w=(child->getLayoutHints()&LAYOUT_FIX_WIDTH) ? child->getWidth() : child->getDefaultWidth();
307     if(ss && ((child->getLayoutHints()&LAYOUT_DOCK_NEXT) || (!(options&DOCKSITE_NO_WRAP) && ss+w>space))) break;
308     ss+=w+hspacing;
309     }
310   }
311 
312 
313 // Find begin and end of galley containing bar on vertical dock site
galleyOfVertBar(FXWindow * bar,FXWindow * & begin,FXWindow * & end) const314 void FXDockSite::galleyOfVertBar(FXWindow *bar,FXWindow*& begin,FXWindow*& end) const {
315   FXint space=height-padtop-padbottom-border-border,ss=0,h;
316   FXWindow *child;
317   for(child=bar; child->getPrev(); child=child->getPrev()){
318     if(child->shown() && (child->getLayoutHints()&LAYOUT_DOCK_NEXT)) break;
319     }
320   for(begin=child; child!=bar; child=child->getNext()){
321     if(child->shown()){
322       h=(child->getLayoutHints()&LAYOUT_FIX_HEIGHT) ? child->getHeight() : child->getDefaultHeight();
323       if(!(options&DOCKSITE_NO_WRAP) && ss+h>space){
324         begin=child;
325         ss=h+vspacing;
326         }
327       else{
328         ss+=h+vspacing;
329         }
330       }
331     }
332   for(end=child; child; end=child,child=child->getNext()){
333     if(child->shown()){
334       h=(child->getLayoutHints()&LAYOUT_FIX_HEIGHT) ? child->getHeight() : child->getDefaultHeight();
335       if(ss && ((child->getLayoutHints()&LAYOUT_DOCK_NEXT) || (!(options&DOCKSITE_NO_WRAP) && ss+h>space))) break;
336       ss+=h+vspacing;
337       }
338     }
339   }
340 
341 
342 
343 // Determine vertical galley size
galleyWidth(FXWindow * begin,FXWindow * & end,FXint space,FXint & require,FXint & expand) const344 FXint FXDockSite::galleyWidth(FXWindow *begin,FXWindow*& end,FXint space,FXint& require,FXint& expand) const {
345   FXint galley,any,w,h;
346   FXWindow *child;
347   FXuint hints;
348   require=expand=galley=any=0;
349   for(child=end=begin; child; end=child,child=child->getNext()){
350     if(child->shown()){
351 
352       // Get size
353       hints=child->getLayoutHints();
354       w=(hints&LAYOUT_FIX_WIDTH)?child->getWidth():child->getDefaultWidth();
355       h=(hints&LAYOUT_FIX_HEIGHT)?child->getHeight():child->getDefaultHeight();
356 
357       // Break for new galley?
358       if(any && ((hints&LAYOUT_DOCK_NEXT) || ((require+h>space) && wrapGalleys()))) break;
359 
360       // Expanding widgets
361       if(hints&LAYOUT_FILL_Y) expand+=h;
362 
363       // Figure galley size
364       require+=h+vspacing;
365       if(w>galley) galley=w;
366       any=1;
367       }
368     }
369   require-=vspacing;
370   return galley;
371   }
372 
373 
374 // Determine horizontal galley size
galleyHeight(FXWindow * begin,FXWindow * & end,FXint space,FXint & require,FXint & expand) const375 FXint FXDockSite::galleyHeight(FXWindow *begin,FXWindow*& end,FXint space,FXint& require,FXint& expand) const {
376   FXint galley,any,w,h;
377   FXWindow *child;
378   FXuint hints;
379   require=expand=galley=any=0;
380   for(child=end=begin; child; end=child,child=child->getNext()){
381     if(child->shown()){
382 
383       // Get size
384       hints=child->getLayoutHints();
385       w=(hints&LAYOUT_FIX_WIDTH)?child->getWidth():child->getDefaultWidth();
386       h=(hints&LAYOUT_FIX_HEIGHT)?child->getHeight():child->getDefaultHeight();
387 
388       // Break for new galley?
389       if(any && ((hints&LAYOUT_DOCK_NEXT) || ((require+w>space) && wrapGalleys()))) break;
390 
391       // Expanding widgets
392       if(hints&LAYOUT_FILL_X) expand+=w;
393 
394       // Figure galley size
395       require+=w+hspacing;
396       if(h>galley) galley=h;
397       any=1;
398       }
399     }
400   require-=hspacing;
401   return galley;
402   }
403 
404 
405 // Recalculate layout
layout()406 void FXDockSite::layout(){
407   FXint expand,remain,require,left,right,top,bottom,galx,galy,galw,galh,e,t,x,y,w,h;
408   FXWindow *begin,*end,*child;
409   FXuint hints;
410 
411   // Vertically oriented
412   if(options&LAYOUT_SIDE_LEFT){
413 
414     // Galley height
415     left=border+padleft;
416     right=width-padright-border;
417 
418     // Loop over galleys
419     for(begin=getFirst(); begin; begin=end->getNext()){
420 
421       // Space available
422       top=border+padtop;
423       bottom=height-padbottom-border;
424 
425       // Galley width
426       galw=galleyWidth(begin,end,bottom-top,require,expand);
427 
428       // Remaining space
429       remain=bottom-top-require;
430       if(expand) require=bottom-top;
431 
432       // Start next galley
433       galx=left;
434       left=left+galw+hspacing;
435 
436       // Placement of widgets on galley
437       for(child=begin,e=0; child; child=child->getNext()){
438         if(child->shown()){
439 
440           // Get size
441           hints=child->getLayoutHints();
442           w=(hints&LAYOUT_FIX_WIDTH)?child->getWidth():child->getDefaultWidth();
443           h=(hints&LAYOUT_FIX_HEIGHT)?child->getHeight():child->getDefaultHeight();
444 
445           // X-filled
446           if(hints&LAYOUT_FILL_X) w=galw;
447 
448           // Y-filled
449           if(hints&LAYOUT_FILL_Y){
450             t=h*remain;
451             e+=t%expand;
452             h+=t/expand+e/expand;
453             e%=expand;
454             }
455 
456           require-=h;
457 
458           // Determine child x-position
459           x=child->getX();
460           if(x<galx) x=galx;
461           if(x+w>galx+galw) x=galx+galw-w;
462 
463           // Determine child y-position
464           y=child->getY();
465           if(y+h>bottom-require) y=bottom-require-h;
466           if(y<top) y=top;
467           top=y+h+vspacing;
468 
469           require-=vspacing;
470 
471           // Placement on this galley
472           child->position(x,y,w,h);
473           }
474         if(child==end) break;
475         }
476       }
477     }
478 
479   // Horizontally oriented
480   else{
481 
482     // Galley height
483     top=border+padtop;
484     bottom=height-padbottom-border;
485 
486     // Loop over galleys
487     for(begin=getFirst(); begin; begin=end->getNext()){
488 
489       // Space available
490       left=border+padleft;
491       right=width-padright-border;
492 
493       // Galley height
494       galh=galleyHeight(begin,end,right-left,require,expand);
495 
496       // Remaining space
497       remain=right-left-require;
498       if(expand) require=right-left;
499 
500       // Start next galley
501       galy=top;
502       top=top+galh+vspacing;
503 
504       // Placement of widgets on galley
505       for(child=begin,e=0; child; child=child->getNext()){
506         if(child->shown()){
507 
508           // Get size
509           hints=child->getLayoutHints();
510           w=(hints&LAYOUT_FIX_WIDTH)?child->getWidth():child->getDefaultWidth();
511           h=(hints&LAYOUT_FIX_HEIGHT)?child->getHeight():child->getDefaultHeight();
512 
513           // Y-filled
514           if(hints&LAYOUT_FILL_Y) h=galh;
515 
516           // X-filled
517           if(hints&LAYOUT_FILL_X){
518             t=w*remain;
519             e+=t%expand;
520             w+=t/expand+e/expand;
521             e%=expand;
522             }
523 
524           require-=w;
525 
526           // Determine child y-position
527           y=child->getY();
528           if(y<galy) y=galy;
529           if(y+h>galy+galh) y=galy+galh-h;
530 
531           // Determine child x-position
532           x=child->getX();
533           if(x+w>right-require) x=right-require-w;
534           if(x<left) x=left;
535           left=x+w+hspacing;
536 
537           require-=hspacing;
538 
539           // Placement on this galley
540           child->position(x,y,w,h);
541           }
542         if(child==end) break;
543         }
544       }
545     }
546   flags&=~FLAG_DIRTY;
547   }
548 
549 
550 /*******************************************************************************/
551 
552 
553 // Move bar vertically in galley [begin..end]
moveVerBar(FXWindow * & begin,FXWindow * & end,FXWindow * bar,FXint barx,FXint bary,FXint barw,FXint barh,FXbool hop)554 void FXDockSite::moveVerBar(FXWindow*& begin,FXWindow*& end,FXWindow* bar,FXint barx,FXint bary,FXint barw,FXint barh,FXbool hop){
555   FXWindow *child; FXint pos,by;
556 
557   by=bary;
558 
559   // Pushing up
560   if(bary<bar->getY()){
561 
562     // Figure minimum position
563     for(child=begin,pos=border+padtop; child && child!=bar; child=child->getNext()){
564       if(child->shown()){ pos+=child->getHeight()+vspacing; }
565       }
566 
567     // Can't move higher
568     if(bary<pos){
569       if(barh==bar->getHeight()){bary=pos;}else{barh=bary+barh-pos;bary=pos;}
570       }
571 
572     // Bars in front of this one?
573     if(bar!=begin){
574       child=bar;
575       pos=bary;
576 
577       // Move bars in box-car fashion
578       do{
579         child=child->getPrev();
580         if(!child->shown()) continue;
581         pos=pos-vspacing-child->getHeight();
582         if(child->getY()<=pos) break;
583         child->move(child->getX(),pos);
584         }
585       while(child!=begin);
586 
587       // Hop bar over
588       child=bar->getPrev();
589       if(hop && by<child->getY()){
590 
591         // Hopping over first on galley:- transfer flag over to new first
592         if((child==begin) && (child->getLayoutHints()&LAYOUT_DOCK_NEXT)){
593           child->setLayoutHints(child->getLayoutHints()&~LAYOUT_DOCK_NEXT);
594           bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
595           }
596 
597         // And rearrange order of children
598         bary=child->getY();
599         child->move(child->getY(),bary+barh+vspacing);
600         bar->reparent(this,child);
601 
602         // Update galley
603         if(child==begin) begin=bar;
604         if(bar==end) end=child;
605         }
606       }
607     }
608 
609   // Pushing down
610   if(bary+barh>bar->getY()+bar->getHeight()){
611 
612     // Figure maximum position
613     for(child=end,pos=height-padbottom-border; child && child!=bar; child=child->getPrev()){
614       if(child->shown()){ pos-=child->getHeight()+vspacing; }
615       }
616 
617     // Can't move lower
618     if(bary+barh>pos){
619       if(barh==bar->getHeight()){bary=pos-barh;}else{barh=pos-bary;}
620       }
621 
622     // Bars after this one?
623     if(bar!=end){
624       child=bar;
625       pos=bary+barh+vspacing;
626 
627       // Move bars in box-car fashion
628       do{
629         child=child->getNext();
630         if(!child->shown()) continue;
631         if(child->getY()>=pos) break;
632         child->move(child->getX(),pos);
633         pos=pos+vspacing+child->getHeight();
634         }
635       while(child!=end);
636 
637       // Hop bar over
638       child=bar->getNext();
639       if(hop && by+barh>child->getY()+child->getHeight()){
640 
641         // First on galley hopped over to the right:- transfer flag to new first
642         if((bar==begin) && (bar->getLayoutHints()&LAYOUT_DOCK_NEXT)){
643           bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
644           child->setLayoutHints(child->getLayoutHints()|LAYOUT_DOCK_NEXT);
645           }
646 
647         // And rearrange order of children
648         bary=child->getY()+child->getHeight()-barh;
649         child->move(child->getX(),bary-child->getHeight()-vspacing);
650         bar->reparent(this,child->getNext());
651 
652         // Update galley
653         if(child==end) end=bar;
654         if(bar==begin) begin=child;
655         }
656       }
657     }
658 
659   // Move it
660   bar->position(barx,bary,barw,barh);
661   }
662 
663 
664 // Move bar horizontally in galley [begin..end]
moveHorBar(FXWindow * & begin,FXWindow * & end,FXWindow * bar,FXint barx,FXint bary,FXint barw,FXint barh,FXbool hop)665 void FXDockSite::moveHorBar(FXWindow*& begin,FXWindow*& end,FXWindow* bar,FXint barx,FXint bary,FXint barw,FXint barh,FXbool hop){
666   FXWindow *child; FXint pos,bx;
667 
668   bx=barx;
669 
670   // Pushing left
671   if(barx<bar->getX()){
672 
673     // Figure minimum position
674     for(child=begin,pos=border+padleft; child && child!=bar; child=child->getNext()){
675       if(child->shown()){ pos+=child->getWidth()+hspacing; }
676       }
677 
678     // Can't move leftward
679     if(barx<pos){
680       if(barw==bar->getWidth()){barx=pos;}else{barw=barx+barw-pos;barx=pos;}
681       }
682 
683     // Bars in front of this one?
684     if(bar!=begin){
685       child=bar;
686       pos=barx;
687 
688       // Move bars in box-car fashion
689       do{
690         child=child->getPrev();
691         if(!child->shown()) continue;
692         pos=pos-hspacing-child->getWidth();
693         if(child->getX()<=pos) break;
694         child->move(pos,child->getY());
695         }
696       while(child!=begin);
697 
698       // Hop bar over
699       child=bar->getPrev();
700       if(hop && bx<child->getX()){
701 
702         // Hopping over first on galley:- transfer flag over to new first
703         if((child==begin) && (child->getLayoutHints()&LAYOUT_DOCK_NEXT)){
704           child->setLayoutHints(child->getLayoutHints()&~LAYOUT_DOCK_NEXT);
705           bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
706           }
707 
708         // And rearrange order of children
709         barx=child->getX();
710         child->move(barx+barw+hspacing,child->getY());
711         bar->reparent(this,child);
712 
713         // Update galley
714         if(child==begin) begin=bar;
715         if(bar==end) end=child;
716         }
717       }
718     }
719 
720   // Pushing right
721   if(barx+barw>bar->getX()+bar->getWidth()){
722 
723     // Figure maximum position
724     for(child=end,pos=width-padright-border; child && child!=bar; child=child->getPrev()){
725       if(child->shown()){ pos-=child->getWidth()+hspacing; }
726       }
727 
728     // Can't move rightward
729     if(barx+barw>pos){
730       if(barw==bar->getWidth()){barx=pos-barw;}else{barw=pos-barx;}
731       }
732 
733     // Bars after this one?
734     if(bar!=end){
735       child=bar;
736       pos=barx+barw+hspacing;
737 
738       // Move bars in box-car fashion
739       do{
740         child=child->getNext();
741         if(!child->shown()) continue;
742         if(child->getX()>=pos) break;
743         child->move(pos,child->getY());
744         pos=pos+hspacing+child->getWidth();
745         }
746       while(child!=end);
747 
748       // Hop bar over
749       child=bar->getNext();
750       if(hop && bx+barw>child->getX()+child->getWidth()){
751 
752         // First on galley hopped over to the right:- transfer flag to new first
753         if((bar==begin) && (bar->getLayoutHints()&LAYOUT_DOCK_NEXT)){
754           bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
755           child->setLayoutHints(child->getLayoutHints()|LAYOUT_DOCK_NEXT);
756           }
757 
758         // And rearrange order of children
759         barx=child->getX()+child->getWidth()-barw;
760         child->move(barx-child->getWidth()-hspacing,child->getY());
761         bar->reparent(this,child->getNext());
762 
763         // Update galley
764         if(child==end) end=bar;
765         if(bar==begin) begin=child;
766         }
767       }
768     }
769 
770   // Move it
771   bar->position(barx,bary,barw,barh);
772   }
773 
774 
775 /*******************************************************************************/
776 
777 
778 // FIXME can not move left edge if docked on right and widget NOT galley-wide yet
779 // Position toolbar
resizeToolBar(FXDockBar * bar,FXint barx,FXint bary,FXint barw,FXint barh)780 void FXDockSite::resizeToolBar(FXDockBar* bar,FXint barx,FXint bary,FXint barw,FXint barh){
781   if(bar && bar->getParent()==this){
782     FXint top,bottom,left,right,expand,require,w,h,mbw,mbh,t;
783     FXWindow *begin,*end,*c;
784 
785     //FXTRACE((100,"barx=%d bary=%d barw=%d barh=%d\n",barx,bary,barw,barh));
786 
787     // Interior
788     top=border+padtop;
789     bottom=height-padbottom-border;
790     left=border+padleft;
791     right=width-padright-border;
792 
793     // Vertically oriented
794     if(options&LAYOUT_SIDE_LEFT){
795 
796       // Minimum bar width
797       mbw=bar->getPadLeft()+bar->getPadRight()+bar->getBorderWidth()+bar->getBorderWidth();
798 
799       // Determine galley sizes
800       for(begin=end=getFirst(); begin; begin=end->getNext()){
801         w=galleyWidth(begin,end,bottom-top,require,expand);
802 
803         // Found galley of the bar
804         if(before(begin,bar) && before(bar,end)){
805 
806           // Dragging the right
807           if(barx+barw!=bar->getX()+bar->getWidth()){
808             if(barw<mbw){ barw=mbw; }
809             if(options&LAYOUT_SIDE_BOTTOM){     // Docked on right
810               if(barx+barw>=left+w){                    // Can not drag rightward
811                 barw=left+w-barx;
812                 }
813               else{                                     // Only drag leftward if another widget holds the galley up
814                 for(c=begin,t=-1; c; c=c->getNext()){
815                   if(c!=bar && c->shown() && (t=(c->getLayoutHints()&LAYOUT_FIX_WIDTH) ? c->getWidth() : c->getDefaultWidth())==w) break;
816                   if(c==end) break;
817                   }
818                 if(t<w){
819                   barw=left+w-barx;
820                   }
821                 }
822               }
823             }
824 
825           // Dragging the left
826           if(barx!=bar->getX()){
827             if(barw<mbw){ barx=barx+barw-mbw; barw=mbw; }
828             if(!(options&LAYOUT_SIDE_BOTTOM)){  // Docked on left
829               if(barx<=left){                           // Can not drag leftward
830                 barw=barx+barw-left; barx=left;
831                 }
832               else{                                     // Only drag rightward if another widget holds galley up
833                 for(c=begin,t=-1; c; c=c->getNext()){
834                   if(c!=bar && c->shown() && (t=(c->getLayoutHints()&LAYOUT_FIX_WIDTH) ? c->getWidth() : c->getDefaultWidth())==w) break;
835                   if(c==end) break;
836                   }
837                 if(t<w){
838                   barw=barx+barw-left; barx=left;
839                   }
840                 }
841               }
842             }
843 
844           // Move bar vertically; this may change the galley start and end!
845           moveVerBar(begin,end,bar,barx,bary,barw,barh,false);
846           break;
847           }
848         left+=w+hspacing;
849         }
850       }
851 
852     // Horizontally oriented
853     else{
854 
855       // Minimum bar height
856       mbh=bar->getPadTop()+bar->getPadBottom()+bar->getBorderWidth()+bar->getBorderWidth();
857 
858       // Determine galley sizes
859       for(begin=end=getFirst(); begin; begin=end->getNext()){
860         h=galleyHeight(begin,end,right-left,require,expand);
861 
862         // Found galley of the bar
863         if(before(begin,bar) && before(bar,end)){
864 
865           // Same bar, move horizontally
866           if(bary<top) bary=top;
867           if(bary+barh>top+h) bary=top+h-barh;
868 
869           // Move bar horizontally; this may change the galley start and end!
870           moveHorBar(begin,end,bar,barx,bary,barw,barh,false);
871           break;
872           }
873         top+=h+vspacing;
874         }
875       }
876     }
877   }
878 
879 
880 /*******************************************************************************/
881 
882 
883 // Move dock bar, changing its options to suit position
moveToolBar(FXDockBar * bar,FXint barx,FXint bary)884 void FXDockSite::moveToolBar(FXDockBar* bar,FXint barx,FXint bary){
885   FXint left,right,top,bottom,galx,galy,galw,galh,dockx,docky,barw,barh,expand,require,w,h;
886   FXWindow *begin,*end,*cur,*curend,*nxt,*nxtend,*prv,*prvend;
887 
888   // We insist this bar hangs under this dock site
889   if(bar && bar->getParent()==this){
890 
891     // Proposed location
892     dockx=barx;
893     docky=bary;
894 
895     // Bar size
896     barw=bar->getWidth();
897     barh=bar->getHeight();
898 
899     // Interior
900     top=border+padtop;
901     bottom=height-padbottom-border;
902     left=border+padleft;
903     right=width-padright-border;
904 
905     // Vertically oriented
906     if(options&LAYOUT_SIDE_LEFT){
907 
908       // Determine galley sizes
909       galx=left;
910       galw=0;
911       for(begin=getFirst(),cur=prv=nxt=curend=prvend=nxtend=NULL; begin; begin=end->getNext()){
912         w=galleyWidth(begin,end,bottom-top,require,expand);
913         if(!after(end,bar)){ if(left<=barx && barx<left+w){ prv=begin; prvend=end; } }
914         else if(!after(bar,begin)){ if(left<=barx+barw && barx+barw<left+w){ nxt=begin; nxtend=end; } }
915         else{ cur=begin; curend=end; galx=left; galw=w; }
916         left+=w+hspacing;
917         }
918 
919       // Same bar, move vertically
920       if(dockx<galx) dockx=galx;
921       if(dockx+barw>galx+galw) dockx=galx+galw-barw;
922 
923       // Move bar vertically; this may change the galley start and end!
924       moveVerBar(cur,curend,bar,dockx,docky,barw,barh,true);
925 
926       // Moving bar right, unless we're about to pull it out of the dock
927       if(barx+barw>=galx+galw+FUDGE && (!bar->getWetDock() || barx+barw<width-padright-border)){
928         if(nxt){                                  // Hang at end of next galley
929           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
930           nxt->setLayoutHints(nxt->getLayoutHints()|LAYOUT_DOCK_NEXT);
931           bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
932           bar->reparent(this,nxtend->getNext());
933           }
934         else{                                     // Hang below last
935           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
936           else cur->setLayoutHints(cur->getLayoutHints()|LAYOUT_DOCK_NEXT);
937           bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
938           bar->reparent(this,NULL);
939           }
940         }
941 
942       // Moving bar left, unless we're about to pull it out of the dock
943       else if(barx<galx-FUDGE && (!bar->getWetDock() || barx>padleft+border)){
944         if(prv){                                  // Hang at end of previous galley
945           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
946           prv->setLayoutHints(prv->getLayoutHints()|LAYOUT_DOCK_NEXT);
947           bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
948           bar->reparent(this,prvend->getNext());
949           }
950         else{                                     // Hand above first
951           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
952           else cur->setLayoutHints(cur->getLayoutHints()|LAYOUT_DOCK_NEXT);
953           bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
954           bar->reparent(this,getFirst());
955           }
956         }
957 #if 0
958       // Determine galley sizes
959       galx=left;
960       galw=0;
961       for(begin=getFirst(),cur=prv=nxt=curend=prvend=nxtend=NULL; begin; begin=end->getNext()){
962         w=galleyWidth(begin,end,bottom-top,require,expand);
963         if(!after(end,bar)){ if(left<=barx && barx<left+w){ prv=begin; prvend=end; } }
964         else if(!after(bar,begin)){ if(left<=barx+barw && barx+barw<left+w){ nxt=begin; nxtend=end; }  }
965         else{ cur=begin; curend=end; galx=left; galw=w; }
966         left+=w+hspacing;
967         }
968 
969       // Same bar, move vertically
970       if(dockx<galx) dockx=galx;
971       if(dockx+barw>galx+galw) dockx=galx+galw-barw;
972 
973       // Move bar vertically; this may change the galley start and end!
974       moveVerBar(cur,curend,bar,dockx,docky,barw,barh,true);
975 
976       // Moving bar right, unless we're about to pull it out of the dock
977       if(barx+barw>=galx+galw+FUDGE && (!bar->getWetDock() || barx+barw<width-padright-border)){
978         if(nxt){                                  // Hang at end of next galley
979           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
980           nxt->setLayoutHints(nxt->getLayoutHints()|LAYOUT_DOCK_NEXT);
981           bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
982           bar->reparent(this,nxtend->getNext());
983           }
984         else{                                     // Hang below last
985           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
986           else cur->setLayoutHints(cur->getLayoutHints()|LAYOUT_DOCK_NEXT);
987           bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
988           bar->reparent(this,NULL);
989           }
990         }
991 
992       // Moving bar left, unless we're about to pull it out of the dock
993       else if(barx<galx-FUDGE && (!bar->getWetDock() || barx>padleft+border)){
994         if(prv){                                  // Hang at end of previous galley
995           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
996           prv->setLayoutHints(prv->getLayoutHints()|LAYOUT_DOCK_NEXT);
997           bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
998           bar->reparent(this,prvend->getNext());
999           }
1000         else{                                     // Hand above first
1001           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
1002           else cur->setLayoutHints(cur->getLayoutHints()|LAYOUT_DOCK_NEXT);
1003           bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
1004           bar->reparent(this,getFirst());
1005           }
1006         }
1007 #endif
1008       }
1009 
1010     // Horizontally oriented
1011     else{
1012 
1013       // Determine galley sizes
1014       galy=top;
1015       galh=0;
1016       for(begin=getFirst(),cur=prv=nxt=curend=prvend=nxtend=NULL; begin; begin=end->getNext()){
1017         h=galleyHeight(begin,end,right-left,require,expand);
1018         if(!after(end,bar)){ if(top<=bary && bary<top+h){ prv=begin; prvend=end; } }
1019         else if(!after(bar,begin)){ if(top<=bary+barh && bary+barh<top+h){ nxt=begin; nxtend=end; }  }
1020         else{ cur=begin; curend=end; galy=top; galh=h; }
1021         top+=h+vspacing;
1022         }
1023 
1024       // Same bar, move horizontally
1025       if(docky<galy) docky=galy;
1026       if(docky+barh>galy+galh) docky=galy+galh-barh;
1027 
1028       // Move bar horizontally; this may change the galley start and end!
1029       moveHorBar(cur,curend,bar,dockx,docky,barw,barh,true);
1030 
1031       // Moving bar down, unless we're about to pull it out of the dock
1032       if(bary+barh>=galy+galh+FUDGE && (!bar->getWetDock() || bary+barh<height-padbottom-border)){
1033         if(nxt){                                  // Hang at end of next galley
1034           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
1035           nxt->setLayoutHints(nxt->getLayoutHints()|LAYOUT_DOCK_NEXT);
1036           bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
1037           bar->reparent(this,nxtend->getNext());
1038           }
1039         else{                                     // Hang below last
1040           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
1041           else cur->setLayoutHints(cur->getLayoutHints()|LAYOUT_DOCK_NEXT);
1042           bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
1043           bar->reparent(this,NULL);
1044           }
1045         }
1046 
1047       // Moving bar up, unless we're about to pull it out of the dock
1048       else if(bary<galy-FUDGE && (!bar->getWetDock() || bary>border+padtop)){
1049         if(prv){                                  // Hang at end of previous galley
1050           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
1051           prv->setLayoutHints(prv->getLayoutHints()|LAYOUT_DOCK_NEXT);
1052           bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
1053           bar->reparent(this,prvend->getNext());
1054           }
1055         else{                                     // Hand above first
1056           if(cur==bar && bar!=curend) cur->getNext()->setLayoutHints(cur->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
1057           else cur->setLayoutHints(cur->getLayoutHints()|LAYOUT_DOCK_NEXT);
1058           bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
1059           bar->reparent(this,getFirst());
1060           }
1061         }
1062       }
1063     }
1064   }
1065 
1066 
1067 // Fix layouts for undocking given bar
undockToolBar(FXDockBar * bar)1068 void FXDockSite::undockToolBar(FXDockBar* bar){
1069   FXWindow *begin,*end;
1070 
1071   // We insist this bar hangs under this dock site
1072   if(bar && bar->getParent()==this){
1073 
1074     // Vertically oriented
1075     if(options&LAYOUT_SIDE_LEFT){
1076 
1077       // Get galley of bar
1078       galleyOfVertBar(bar,begin,end);
1079 
1080       // Adjust layout options
1081       if(begin==bar && bar!=end)
1082         begin->getNext()->setLayoutHints(begin->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
1083       else
1084         begin->setLayoutHints(begin->getLayoutHints()|LAYOUT_DOCK_NEXT);
1085       }
1086 
1087     // Horizontally oriented
1088     else{
1089 
1090       // Get galley of bar
1091       galleyOfHorzBar(bar,begin,end);
1092 
1093       // Adjust layout options
1094       if(begin==bar && bar!=end)
1095         begin->getNext()->setLayoutHints(begin->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
1096       else
1097         begin->setLayoutHints(begin->getLayoutHints()|LAYOUT_DOCK_NEXT);
1098       }
1099 
1100     // Fix bar's layout hints too
1101     bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
1102     }
1103   }
1104 
1105 
1106 // Fix layouts for docking given bar at given position
dockToolBar(FXDockBar * bar,FXWindow * other)1107 void FXDockSite::dockToolBar(FXDockBar* bar,FXWindow* other){
1108 
1109   // We insist this bar hangs under this dock site
1110   if(bar && bar->getParent()==this){
1111 
1112     // New galley for bar
1113     bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
1114     if(other) other->setLayoutHints(bar->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
1115     }
1116   }
1117 
1118 
1119 // Fix layouts for docking given bar at given position
dockToolBar(FXDockBar * bar,FXint barx,FXint bary)1120 void FXDockSite::dockToolBar(FXDockBar* bar,FXint barx,FXint bary){
1121   FXint left,right,top,bottom,barw,barh,expand,require,cx,cy,w,h;
1122   FXWindow *begin,*end,*child;
1123 
1124   // We insist this bar hangs under this dock site
1125   if(bar && bar->getParent()==this){
1126 
1127     // Interior
1128     top=border+padtop;
1129     left=border+padleft;
1130     bottom=height-padbottom-border;
1131     right=width-padright-border;
1132 
1133     // Bar size
1134     barw=bar->getWidth();
1135     barh=bar->getHeight();
1136 
1137     // Vertically oriented
1138     if(options&LAYOUT_SIDE_LEFT){
1139 
1140       cx=barx+barw/2;
1141 
1142       // Tentatively
1143       bar->reparent(this,getFirst());
1144       bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
1145       if(bar->getNext()){
1146 
1147         // Start galley on next
1148         bar->getNext()->setLayoutHints(bar->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
1149 
1150         // Right of the left edge
1151         if(left<=cx){
1152 
1153           // Determine galley
1154           for(begin=bar->getNext(); begin; begin=end->getNext()){
1155             w=galleyWidth(begin,end,bottom-top,require,expand);
1156             if(left<=cx && cx<left+w){
1157 
1158               // Find spot on galley
1159               for(child=begin; child!=end->getNext() && (!child->shown() || bary>=child->getY()); child=child->getNext()){}
1160 
1161               // At the front
1162               if((child==begin) && (child->getLayoutHints()&LAYOUT_DOCK_NEXT)){
1163                 child->setLayoutHints(child->getLayoutHints()&~LAYOUT_DOCK_NEXT);
1164                 }
1165               else{
1166                 bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
1167                 }
1168 
1169               // hang in front
1170               bar->reparent(this,child);
1171               goto ver;
1172               }
1173             left+=w+hspacing;
1174             }
1175 
1176           // Link at the bottom
1177           bar->reparent(this,NULL);
1178           }
1179         }
1180 
1181       // Move horizontally
1182 ver:  bar->move(FXCLAMP(left,barx,right),bary);
1183       }
1184 
1185     // Horizontally oriented
1186     else{
1187 
1188       cy=bary+barh/2;
1189 
1190       // Tentatively
1191       bar->reparent(this,getFirst());
1192       bar->setLayoutHints(bar->getLayoutHints()|LAYOUT_DOCK_NEXT);
1193       if(bar->getNext()){
1194 
1195         // Start galley on next
1196         bar->getNext()->setLayoutHints(bar->getNext()->getLayoutHints()|LAYOUT_DOCK_NEXT);
1197 
1198         // Below top edge
1199         if(top<=cy){
1200 
1201           // Determine galley
1202           for(begin=bar->getNext(); begin; begin=end->getNext()){
1203             h=galleyHeight(begin,end,right-left,require,expand);
1204             if(top<=cy && cy<top+h){
1205 
1206               // Find spot on galley
1207               for(child=begin; child!=end->getNext() && (!child->shown() || barx>=child->getX()); child=child->getNext()){}
1208 
1209               // At the front
1210               if((child==begin) && (child->getLayoutHints()&LAYOUT_DOCK_NEXT)){
1211                 child->setLayoutHints(child->getLayoutHints()&~LAYOUT_DOCK_NEXT);
1212                 }
1213               else{
1214                 bar->setLayoutHints(bar->getLayoutHints()&~LAYOUT_DOCK_NEXT);
1215                 }
1216 
1217               // hang in front
1218               bar->reparent(this,child);
1219               goto hor;
1220               }
1221             top+=h+vspacing;
1222             }
1223 
1224           // Link at the bottom
1225           bar->reparent(this,NULL);
1226           }
1227         }
1228 
1229       // Move horizontally
1230 hor:  bar->move(barx,FXCLAMP(top,bary,bottom));
1231       }
1232     }
1233   }
1234 
1235 /*
1236 // Find out where window was grabbed
1237 FXuchar FXDockSite::where(FXint x,FXint y) const {
1238   FXuchar code=DRAG_NONE;
1239   if((0<=x && x<border+padleft) || (0<=y && y<border+padtop) || (width-padright-border<=x && x<width) || (height-padbottom-border<=y && y<height)){
1240     if(x<HANDLESIZE) code|=DRAG_LEFT;
1241     if(width-HANDLESIZE<=x) code|=DRAG_RIGHT;
1242     if(y<HANDLESIZE) code|=DRAG_TOP;
1243     if(height-HANDLESIZE<=y) code|=DRAG_BOTTOM;
1244     }
1245   return code;
1246   }
1247 
1248 
1249 // Change cursor if we entered the window normally
1250 long FXDockSite::onEnter(FXObject* sender,FXSelector sel,void* ptr){
1251   FXPacker::onEnter(sender,sel,ptr);
1252   if(((FXEvent*)ptr)->code!=CROSSINGGRAB){
1253     setDefaultCursor(getApp()->getDefaultCursor(cursorType[where(((FXEvent*)ptr)->win_x,((FXEvent*)ptr)->win_y)]));
1254     }
1255   return 1;
1256   }
1257 
1258 
1259 // Restore cursor if we left the window normally
1260 long FXDockSite::onLeave(FXObject* sender,FXSelector sel,void* ptr){
1261   FXPacker::onLeave(sender,sel,ptr);
1262   if(((FXEvent*)ptr)->code!=CROSSINGUNGRAB){
1263     setDefaultCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
1264     }
1265   return 1;
1266   }
1267 
1268 
1269 // Pressed LEFT button
1270 long FXDockSite::onLeftBtnPress(FXObject*,FXSelector,void* ptr){
1271   FXEvent *event=(FXEvent*)ptr;
1272   flags&=~FLAG_TIP;
1273   handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr);
1274   if(isEnabled()){
1275     grab();
1276     if(target && target->tryHandle(this,FXSEL(SEL_LEFTBUTTONPRESS,message),ptr)) return 1;
1277     mode=where(event->win_x,event->win_y);
1278     if(mode!=DRAG_NONE){
1279       if(mode&DRAG_TOP) gripy=event->win_y;
1280       else if(mode&DRAG_BOTTOM) gripy=event->win_y-height;
1281       if(mode&DRAG_LEFT) gripx=event->win_x;
1282       else if(mode&DRAG_RIGHT) gripx=event->win_x-width;
1283       setDragCursor(getApp()->getDefaultCursor(cursorType[mode]));
1284       }
1285     return 1;
1286     }
1287   return 0;
1288   }
1289 
1290 
1291 // Released LEFT button
1292 long FXDockSite::onLeftBtnRelease(FXObject*,FXSelector,void* ptr){
1293   if(isEnabled()){
1294     ungrab();
1295     setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
1296     if(target && target->tryHandle(this,FXSEL(SEL_LEFTBUTTONRELEASE,message),ptr)) return 1;
1297     if(mode!=DRAG_NONE){
1298       mode=DRAG_NONE;
1299       recalc();
1300       }
1301     return 1;
1302     }
1303   return 0;
1304   }
1305 
1306 
1307 // Moved the mouse
1308 long FXDockSite::onMotion(FXObject*,FXSelector,void* ptr){
1309   FXEvent *event=(FXEvent*)ptr;
1310   if(mode!=DRAG_NONE){
1311     FXDockSite *toolbardock=dynamic_cast<FXDockSite*>(getParent());
1312     FXint mousex,mousey;
1313     FXint x,y,w,h;
1314 
1315     // Translate to dock site's frame
1316     toolbardock->translateCoordinatesFrom(mousex,mousey,getRoot(),event->root_x-gripx,event->root_y-gripy);
1317 
1318     x=xpos;
1319     y=ypos;
1320     w=width;
1321     h=height;
1322 
1323     // Vertical
1324     if(mode&DRAG_TOP){
1325       y=mousey;
1326       h=ypos+height-mousey;
1327       }
1328     else if(mode&DRAG_BOTTOM){
1329       h=mousey-ypos;
1330       }
1331 
1332     // Horizontal
1333     if(mode&DRAG_LEFT){
1334       x=mousex;
1335       w=xpos+width-mousex;
1336       }
1337     else if(mode&DRAG_RIGHT){
1338       w=mousex-xpos;
1339       }
1340 
1341     // Resize and move
1342     toolbardock->resizeToolBar(this,x,y,w,h);
1343     recalc();
1344     return 1;
1345     }
1346 
1347   // Change cursor based on location
1348   setDefaultCursor(getApp()->getDefaultCursor(cursorType[where(event->win_x,event->win_y)]));
1349   return 0;
1350   }
1351 */
1352 
1353 }
1354 
1355