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