]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/rowlayoutpl.cpp
minor corrections for compilation with gcc 3.3 (use cast of address instead
[wxWidgets.git] / contrib / src / fl / rowlayoutpl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: rowlayoutpl.cpp
3 // Purpose: cbRowLayoutPlugin implementation.
4 // Author: Aleksandras Gluchovas
5 // Modified by:
6 // Created: 09/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "rowlayoutpl.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 #include "wx/fl/rowlayoutpl.h"
28
29 // exerimental "features" are still buggy
30 #undef __EXPERIMENTAL
31
32 /***** Implementation for class cbRowLayoutPlugin *****/
33
34 IMPLEMENT_DYNAMIC_CLASS( cbRowLayoutPlugin, cbPluginBase )
35
36 BEGIN_EVENT_TABLE( cbRowLayoutPlugin, cbPluginBase )
37
38 EVT_PL_LAYOUT_ROW ( cbRowLayoutPlugin::OnLayoutRow )
39 EVT_PL_LAYOUT_ROWS( cbRowLayoutPlugin::OnLayoutRows )
40 EVT_PL_RESIZE_ROW ( cbRowLayoutPlugin::OnResizeRow )
41
42 EVT_PL_INSERT_BAR ( cbRowLayoutPlugin::OnInsertBar )
43 EVT_PL_REMOVE_BAR ( cbRowLayoutPlugin::OnRemoveBar )
44
45 END_EVENT_TABLE()
46
47 cbRowLayoutPlugin::cbRowLayoutPlugin(void)
48 : mpPane( 0 )
49 {}
50
51 cbRowLayoutPlugin::cbRowLayoutPlugin( wxFrameLayout* pPanel, int paneMask )
52
53 : cbPluginBase( pPanel, paneMask ),
54 mpPane( 0 )
55 {}
56
57 void cbRowLayoutPlugin::CheckIfAtTheBoundary( cbBarInfo* pTheBar, cbRowInfo& rowInfo )
58 {
59 // this method handles situation, when fixed bar is inserted
60 // into the row, where among fixed bars not-fixed ones are present.
61 // In this case we need to check if the pBarNode appears to be inserted
62 // chain of fixed-bars on the very right or left side of the row,
63 // then all the white-space, such chain should be eliminated,
64 // and the resulting chain justified to the right or the left
65 // side of the row
66
67 if ( !pTheBar->IsFixed() || rowInfo.mHasOnlyFixedBars )
68
69 return;
70
71 cbBarInfo* pBar = rowInfo.mBars[ rowInfo.mBars.Count() - 1 ];
72
73 // slide fixed bars to the right on the right side relative to the pBarNode
74
75 int prevX = mpPane->mPaneWidth;
76
77 do
78 {
79 if ( !pBar->IsFixed() )
80 break;
81
82 wxRect& bounds = pBar->mBounds;
83
84 bounds.x = prevX - bounds.width;
85
86 prevX = bounds.x;
87
88 if ( pBar == pTheBar ) break;
89
90 pBar = pBar->mpPrev;
91 }
92 while( 1 );
93
94 // slide fixed bars to the left on the left side relative to the pBarNode
95
96 pBar = rowInfo.mBars[0];
97
98 prevX = 0;
99
100 do
101 {
102 if ( pBar->IsFixed() )
103
104 break;
105
106 wxRect& bounds = pBar->mBounds;
107
108 bounds.x = prevX;
109
110 prevX = bounds.x + bounds.width;
111
112 if ( pBar == pTheBar ) break;
113
114 pBar = pBar->mpNext;
115 }
116 while( 1 );
117 }
118
119 void cbRowLayoutPlugin::ExpandNotFixedBars( cbRowInfo* pRow )
120 {
121 ApplyLengthRatios( pRow );
122
123 // FIXME:: something's wrong?
124 return;
125
126 double freeSpc = (double)GetRowFreeSpace( pRow );
127
128 // calculate sum of precents
129
130 double pcntSum = 0.0;
131
132 size_t i;
133 for ( i = 0; i != pRow->mBars.Count(); ++i )
134 {
135 if ( !pRow->mBars[i]->IsFixed() )
136 pcntSum += pRow->mBars[i]->mLenRatio;
137 }
138
139 // setup bar lengths
140
141 int curX = 0;
142
143 for ( i = 0; i != pRow->mBars.Count(); ++i )
144 {
145 cbBarInfo& bar = *pRow->mBars[i];
146
147 if ( !bar.IsFixed() )
148 {
149 bar.mLenRatio = bar.mLenRatio/(pcntSum);
150
151 bar.mBounds.width =
152
153 wxMax( mpPane->mProps.mMinCBarDim.x, int( freeSpc*bar.mLenRatio ) );
154 }
155
156 bar.mBounds.x = curX;
157 curX = bar.mBounds.x + bar.mBounds.width;
158 }
159 }
160
161 void cbRowLayoutPlugin::AdjustLengthOfInserted( cbRowInfo* pRow, cbBarInfo* pTheBar )
162 {
163 return; // TBD: Makes following code unreachable
164
165 // pTheBar is not-fixed
166
167
168 // FIXME:: what is this for??
169
170 #if 1
171
172 int totalLen = 0;
173
174 size_t i;
175 for ( i = 0; i != pRow->mBars.Count(); ++i )
176 {
177 if ( !pRow->mBars[i]->IsFixed() )
178 totalLen += pRow->mBars[i]->mBounds.width;
179 }
180
181 double curWidth = pTheBar->mBounds.width;
182
183 if ( pRow->mBars.Count() )
184
185 pTheBar->mBounds.width = int( mpPane->mPaneWidth * (curWidth / double(totalLen)) );
186 #else
187
188 double freeSpc = (double)GetRowFreeSpace( pRow );
189
190 double pcntSum = 0.0;
191
192 size_t i;
193 for ( i = 0; i != pRow->mBars.Count(); ++i )
194 {
195 if ( !pRow->mBars[i]->IsFixed() )
196 pcntSum += pRow->mBars[i]->mLenRatio;
197 }
198
199 // if no longer "balanced", assume that `pTheBar' was previously
200 // removed from this row (kind of AI...)
201
202 if ( pcntSum < 0.98 )
203
204 pTheBar->mBounds.width = freeSpc * (1.0 - pcntSum);
205 #endif
206 }
207
208 void cbRowLayoutPlugin::FitBarsToRange( int from, int till,
209 cbBarInfo* pTheBar, cbRowInfo* pRow )
210 {
211 cbBarInfo* pFromBar = NULL;
212 cbBarInfo* pTillBar = NULL;
213
214 if ( pTheBar->mBounds.x > from )
215 {
216 // it's range from the left
217 pFromBar = pRow->mBars[0];
218 pTillBar = pTheBar;
219 }
220 else
221 {
222 pFromBar = pTheBar->mpNext;
223 pTillBar = NULL;
224 }
225
226 // calc free space in the range
227
228 cbBarInfo* pBar = pFromBar;
229 int freeSpc = till-from;
230 double pcntSum = 0;
231
232 while( pBar != pTillBar )
233 {
234 if ( pBar->IsFixed() )
235 freeSpc -= pBar->mBounds.width;
236 else
237 pcntSum += pBar->mLenRatio;
238
239 pBar = pBar->mpNext;
240 }
241
242 // adjust not-fixed bar sizes in the range
243
244 pBar = pFromBar;
245
246 while ( pBar != pTillBar )
247 {
248 if ( !pBar->IsFixed() )
249 {
250 pBar->mBounds.width =
251 wxMax( mpPane->mProps.mMinCBarDim.x,
252 int( double(freeSpc) * (pBar->mLenRatio/pcntSum) )
253 );
254 }
255 pBar = pBar->mpNext;
256 }
257
258 // layout range, starting from the left-most bar
259
260 pBar = pFromBar;
261 int prevX = from;
262 bool hasNotFixedBars = FALSE;
263
264 while ( pBar != pTillBar )
265 {
266 wxRect& bounds = pBar->mBounds;
267
268 if ( !pBar->IsFixed() )
269 {
270 hasNotFixedBars = TRUE;
271
272 freeSpc -= bounds.width;
273 }
274
275 bounds.x = prevX;
276
277 prevX = bounds.x + bounds.width;
278
279 pBar = pBar->mpNext;
280 }
281
282 // make width adjustment for the right-most bar in the range, due to
283 // lost precision when seting widths using f.p. length-ratios
284
285 if ( hasNotFixedBars )
286 {
287 if ( pTheBar->mBounds.x > from )
288 {
289 if ( pTillBar->mpPrev )
290 {
291 wxRect& tillBar = pTillBar->mpPrev->mBounds;
292
293 //tillBar.width = bar.mBounds.x - tillBar.x;
294 tillBar.width += freeSpc;
295 }
296 }
297 else
298 {
299 cbBarInfo* pLast = pRow->mBars[ pRow->mBars.Count() - 1 ];
300
301 if ( pLast != pTheBar )
302 {
303 pTheBar->mBounds.width += freeSpc;
304
305 SlideRightSideBars( pTheBar );
306 }
307 }
308 }
309 }
310
311 void cbRowLayoutPlugin::MinimzeNotFixedBars( cbRowInfo* pRow, cbBarInfo* pBarToPreserve )
312 {
313 size_t i;
314 for ( i = 0; i != pRow->mBars.Count(); ++i )
315 {
316 if ( !pRow->mBars[i]->IsFixed() && pRow->mBars[i] != pBarToPreserve )
317 pRow->mBars[i]->mBounds.width = mpPane->mProps.mMinCBarDim.x;
318 }
319 }
320
321 int cbRowLayoutPlugin::GetRowFreeSpace( cbRowInfo* pRow )
322 {
323 int freeSpc = mpPane->mPaneWidth;
324
325 size_t i;
326 for ( i = 0; i != pRow->mBars.Count(); ++i )
327 {
328 // not-fixed bars variable length, thus their
329 // dimensions are ignored
330 if ( pRow->mBars[i]->IsFixed() )
331 freeSpc -= pRow->mBars[i]->mBounds.width;
332 }
333
334 return freeSpc;
335 }
336
337 void cbRowLayoutPlugin::RecalcLengthRatios( cbRowInfo* pRow )
338 {
339 double freeSpc = double( GetRowFreeSpace( pRow ) );
340
341 cbBarInfo* pBar = pRow->mBars[0];
342 cbBarInfo* pLastNotFixed = NULL;
343
344 double pcntLeft = 1.0; // (100%)
345
346 #ifdef __EXPERIMENTAL
347
348 int totalLen = 0;
349
350 size_t i;
351 for ( i = 0; i != pRow->mBars.Count(); ++i )
352 {
353 if ( !pRow->mBars[i]->IsFixed() )
354 totalLen += pRow->mBars[i]->mBounds.width;
355 }
356 #endif
357
358 size_t i;
359 for ( i = 0; i != pRow->mBars.Count(); ++i )
360 {
361 cbBarInfo& bar = *pRow->mBars[i];
362
363 if ( !bar.IsFixed() )
364 {
365
366 #ifdef __EXPERIMENTAL
367
368 bar.mLenRatio = double(bar.mBounds.width)/double(totalLen);
369 #else
370 bar.mLenRatio = double(bar.mBounds.width)/freeSpc;
371 #endif
372
373 pcntLeft -= bar.mLenRatio;
374 pLastNotFixed = pBar;
375 }
376 }
377
378 // attach remainder (the result of lost precision) to the
379 // last not-fixed bar
380
381 #if !defined(__EXPERIMENTAL)
382
383 if ( pLastNotFixed )
384
385 pLastNotFixed->mLenRatio += pcntLeft;
386 #endif
387
388 }
389
390 void cbRowLayoutPlugin::ApplyLengthRatios( cbRowInfo* pRow )
391 {
392 double pcntSum = 0;
393
394 // FOR NOW:: all-in-one
395
396 size_t i = 0;
397 for ( i = 0; i != pRow->mBars.Count(); ++i )
398 {
399 if ( !pRow->mBars[i]->IsFixed() )
400 pcntSum += pRow->mBars[i]->mLenRatio;
401 }
402
403 /*
404 pBar = node_to_first_bar_node( pRow );
405
406 while( pBar )
407 {
408 cbBarInfo& bar = node_to_bar( pBar );
409
410 if ( !bar.IsFixed() )
411
412 bar.mLenRatio = pcntSum / bar.mLenRatio;
413
414 pBar = pBar->Next();
415 }
416 */
417
418 int prevX = 0;
419 double freeSpc = GetRowFreeSpace( pRow );
420
421 // tricky stuff (improtant!):
422 // when not-fixed bar is removed from the row and there are
423 // still some other not-fixed ones left in that row, then
424 // the sum of mLenRatio's is no longer 1.0 - this is left
425 // intintionally to handle the case when the removed bar
426 // is returned right back to the row - so that it would retain
427 // it's original dimensions in this row (this is kind of AI...)
428 //
429 // The problem is - when it's remvoed, the sum of
430 // mLenRatio's is not in "balance", i.e. is < 1.0,
431 // it's possible to restore balance, but instead of that
432 // we artifically ajdust freeSpc value in a way that it would
433 // look like total of mLetRatio's is 1.0, thus original
434 // len. ratios are _preserved_:
435
436 if (pcntSum == 0.0)
437 pcntSum = 1.0;
438
439 double unit = freeSpc / pcntSum;
440
441 bool haveSquished = FALSE;
442
443 for ( i = 0; i != pRow->mBars.Count(); ++i )
444 {
445 if ( !pRow->mBars[i]->IsFixed() )
446 {
447 cbBarInfo& bar = *pRow->mBars[i];
448
449 if ( int( unit * bar.mLenRatio ) < mpPane->mProps.mMinCBarDim.x )
450 {
451 haveSquished = TRUE;
452
453 bar.mBounds.width = -1; // mark as "squished"
454
455 pcntSum -= bar.mLenRatio;
456
457 freeSpc -= mpPane->mProps.mMinCBarDim.x;
458 }
459 }
460 } // for
461
462 if ( haveSquished )
463 unit = freeSpc / pcntSum;
464
465 for ( i = 0; i != pRow->mBars.Count(); ++i )
466 {
467 cbBarInfo& bar = *pRow->mBars[i];
468
469 bar.mBounds.x = prevX;
470
471 if ( !bar.IsFixed() )
472 {
473 if ( bar.mBounds.width == -1 )
474
475 bar.mBounds.width = mpPane->mProps.mMinCBarDim.x;
476 else
477 bar.mBounds.width = int( unit * bar.mLenRatio );
478
479 // a little bit of AI:
480 // memorize bar's height and width, when docked in
481 // the current orientation - by making the current
482 // dimensions to be "preffered" ones for this docking state
483
484 if ( !bar.IsFixed() )
485 {
486 bar.mDimInfo.mSizes[ bar.mState ].x = bar.mBounds.width;
487 bar.mDimInfo.mSizes[ bar.mState ].y = bar.mBounds.height;
488 }
489 }
490
491 prevX = bar.mBounds.x + bar.mBounds.width;
492 }
493 }
494
495 void cbRowLayoutPlugin::DetectBarHandles( cbRowInfo* pRow )
496 {
497 // first pass from left to right (detect left-side handles)
498
499 bool foundNotFixed = FALSE;
500
501 size_t i;
502 for ( i = 0; i != pRow->mBars.Count(); ++i )
503 {
504 cbBarInfo& bar = *pRow->mBars[i];
505
506 bar.mHasLeftHandle = FALSE;
507
508 if ( !bar.IsFixed() )
509 {
510 if ( foundNotFixed )
511
512 if ( bar.mpPrev &&
513 bar.mpPrev->IsFixed() )
514
515 bar.mHasLeftHandle = TRUE;
516
517 foundNotFixed = TRUE;
518 }
519 }
520
521 // pass from right to left (detect right-side handles)
522
523 foundNotFixed = FALSE;
524
525 cbBarInfo* pBar = pRow->mBars[ pRow->mBars.Count() - 1 ];
526
527 while( pBar )
528 {
529 pBar->mHasRightHandle = FALSE;
530
531 if ( !pBar->IsFixed() )
532 {
533 if ( foundNotFixed )
534
535 if ( pBar->mpNext )
536
537 pBar->mHasRightHandle = TRUE;
538
539 foundNotFixed = TRUE;
540 }
541
542 pBar = pBar->mpPrev;
543 }
544 }
545
546 void cbRowLayoutPlugin::RelayoutNotFixedBarsAround( cbBarInfo* pTheBar, cbRowInfo* pRow )
547 {
548 if ( !pTheBar->mpPrev )
549 {
550 if ( !pTheBar->IsFixed() )
551 {
552 // this bar the first in the row, move it's
553 // left edge to the very left
554 pTheBar->mBounds.width += pTheBar->mBounds.x;
555 pTheBar->mBounds.x = 0;
556 }
557 }
558 else
559 FitBarsToRange( 0, pTheBar->mBounds.x, pTheBar, pRow );
560
561 if ( !pTheBar->mpNext )
562 {
563 if ( !pTheBar->IsFixed() )
564 {
565 // this bar is the last one, move it's
566 // right edge to the very right
567
568 pTheBar->mBounds.width = mpPane->mPaneWidth - pTheBar->mBounds.x;
569 }
570 }
571 else
572 FitBarsToRange( pTheBar->mBounds.x + pTheBar->mBounds.width, mpPane->mPaneWidth,
573 pTheBar, pRow
574 );
575 }
576
577 void cbRowLayoutPlugin::LayoutItemsVertically( cbRowInfo& row )
578 {
579 size_t i;
580 for ( i = 0; i != row.mBars.Count(); ++i )
581 {
582 cbBarInfo& bar = *row.mBars[i];
583
584 bar.mBounds.y = row.mRowY;
585
586 if ( !bar.IsFixed() )
587
588 // make all not-fixed bars of equal height
589 bar.mBounds.height = row.mRowHeight;
590
591 if ( row.mHasUpperHandle )
592
593 bar.mBounds.y += mpPane->mProps.mResizeHandleSize;
594 }
595 }
596
597 int cbRowLayoutPlugin::CalcRowHeight( cbRowInfo& row )
598 {
599 int maxHeight = 0;
600
601 size_t i;
602 for ( i = 0; i != row.mBars.Count(); ++i )
603
604 maxHeight = wxMax( maxHeight, row.mBars[i]->mBounds.height );
605
606 return maxHeight;
607 }
608
609 void cbRowLayoutPlugin::StickRightSideBars( cbBarInfo* pToBar )
610 {
611 cbBarInfo* pBar = pToBar->mpNext;
612 cbBarInfo* pPrev = pToBar;
613
614 while( pBar )
615 {
616 wxRect& cur = pBar->mBounds;
617 wxRect& prev = pPrev->mBounds;
618
619 cur.x = prev.x + prev.width;
620
621 pPrev = pBar;
622 pBar = pBar->mpNext;
623 }
624 }
625
626 void cbRowLayoutPlugin::SlideLeftSideBars( cbBarInfo* pTheBar )
627 {
628 // shift left-side-bars to the left (with respect to "theBar"),
629 // so that they would not obscured by each other
630
631 cbBarInfo* pBar = pTheBar->mpPrev;
632 cbBarInfo* pPrev = pTheBar;
633
634 while( pBar )
635 {
636 wxRect& cur = pBar->mBounds;
637 wxRect& prev = pPrev->mBounds;
638
639 if ( cur.x + cur.width > prev.x )
640
641 cur.x = prev.x - cur.width;
642
643 pPrev = pBar;
644 pBar = pBar->mpPrev;
645 }
646 }
647
648 void cbRowLayoutPlugin::SlideRightSideBars( cbBarInfo* pTheBar )
649 {
650 // shift right-side-bars to the right (with respect to "theBar"),
651 // so that they would not be obscured by each other
652
653 cbBarInfo* pBar = pTheBar->mpNext;
654 cbBarInfo* pPrev = pTheBar;
655
656 while( pBar )
657 {
658 wxRect& cur = pBar->mBounds;
659 wxRect& prev = pPrev->mBounds;
660
661 if ( cur.x < prev.x + prev.width )
662
663 cur.x = prev.x + prev.width;
664
665 pPrev = pBar;
666 pBar = pBar->mpNext;
667 }
668 }
669
670 void cbRowLayoutPlugin::ShiftLeftTrashold( cbBarInfo* pTheBar, cbRowInfo& row )
671 {
672 wxRect& first = row.mBars[0]->mBounds;
673
674 if ( first.x < 0 )
675 {
676 row.mBars[0]->mBounds.x = 0;
677
678 SlideRightSideBars( row.mBars[0] );
679 }
680 }
681
682 void cbRowLayoutPlugin::ShiftRightTrashold( cbBarInfo* pTheBar, cbRowInfo& row )
683 {
684 wxRect& theBar = pTheBar->mBounds;
685
686 do
687 {
688 cbBarInfo* pBar = pTheBar;
689
690 // calculate free spece on the left side
691
692 int leftFreeSpc = 0;
693
694 while( pBar )
695 {
696 wxRect& cur = pBar->mBounds;
697
698 if ( pBar->mpPrev )
699 {
700 wxRect& prev = pBar->mpPrev->mBounds;
701
702 leftFreeSpc += cur.x - prev.x - prev.width;
703 }
704 else
705 leftFreeSpc += cur.x;
706
707 if ( cur.x < 0 )
708 {
709 leftFreeSpc = 0;
710 break;
711 }
712
713 pBar = pBar->mpPrev;
714 }
715
716 pBar = pTheBar;
717
718 int rightOverflow = 0;
719
720 if ( pTheBar->IsFixed() )
721
722 while( pBar )
723 {
724 if ( !pBar->mpNext )
725 {
726 wxRect& cur = pBar->mBounds;
727
728 if ( cur.x + cur.width > mpPane->mPaneWidth )
729
730 rightOverflow = cur.x + cur.width - mpPane->mPaneWidth;
731 }
732
733 pBar = pBar->mpNext;
734 }
735
736 if ( rightOverflow > 0 )
737 {
738 if ( leftFreeSpc <= 0 ) return;
739
740 if ( pTheBar->mpNext )
741 {
742 wxRect& next = pTheBar->mpNext->mBounds;
743
744 // if there's enough space on the left, move over one half-obscured
745 // bar from the right to the left side with respect to "theBar"
746
747 if ( next.width < leftFreeSpc )
748 {
749 cbBarInfo* pNext = pTheBar->mpNext;
750
751 row.mBars.Remove( pNext );
752
753 row.mBars.Insert( pNext, row.mBars.Index( pTheBar ) );
754
755 next.x = theBar.x - next.width;
756
757 // re-setup mpPrev/mpNext references after insertion
758
759 mpPane->InitLinksForRow( &row );
760
761 // tighten things
762
763 StickRightSideBars( pTheBar );
764 SlideLeftSideBars ( pTheBar );
765
766 continue;
767 }
768 }
769
770 int leftShift = ( rightOverflow > leftFreeSpc )
771 ? leftFreeSpc
772 : rightOverflow;
773
774 theBar.x -= leftShift;
775
776 StickRightSideBars( pTheBar );
777 SlideLeftSideBars ( pTheBar );
778
779 break;
780
781 } // end of if ( rightOverflow )
782 else
783 break;
784
785 } while(1);
786 }
787
788 void cbRowLayoutPlugin::InsertBefore( cbBarInfo* pBeforeBar,
789 cbBarInfo* pTheBar,
790 cbRowInfo& row )
791 {
792 if ( pBeforeBar )
793
794 row.mBars.Insert( pTheBar, row.mBars.Index( pBeforeBar ) );
795 else
796 row.mBars.Add( pTheBar );
797
798 pTheBar->mpRow = &row;
799 }
800
801 void cbRowLayoutPlugin::DoInsertBar( cbBarInfo* pTheBar, cbRowInfo& row )
802 {
803 wxRect& theBar = pTheBar->mBounds;
804
805 /* OLD STUFF::
806 if ( theBar.x < 0 && !node_to_bar( pTheBar ).IsFixed() )
807 {
808 // AI::
809 theBar.width += theBar.x;
810 theBar.x = 0;
811 } */
812
813 size_t i;
814 for ( i = 0; i != row.mBars.Count(); ++i )
815 {
816 cbBarInfo& bar = *row.mBars[i];
817
818 wxRect& cur = bar.mBounds;
819
820 // if bar hits the left edge
821 if ( theBar.x <= cur.x )
822 {
823 InsertBefore( &bar, pTheBar, row );
824 return;
825 }
826
827 else
828 // if bar hits the right edge
829 if ( theBar.x <= cur.x + cur.width )
830 {
831 if ( theBar.x + theBar.width > cur.x + cur.width )
832 {
833 InsertBefore( bar.mpNext, pTheBar, row );
834 return;
835 }
836
837 // otherwise the bar lies within the bounds of current bar
838
839 int leftDist = theBar.x - cur.x;
840 int rightDist = cur.x + cur.width - (theBar.x + theBar.width);
841
842 if ( leftDist < rightDist )
843
844 InsertBefore( &bar, pTheBar, row );
845 else
846 InsertBefore( bar.mpNext, pTheBar, row );
847
848 return;
849 }
850 }
851
852 InsertBefore( NULL, pTheBar, row ); // insert at the end
853 }
854
855 // evnet handlers
856
857 void cbRowLayoutPlugin::OnInsertBar( cbInsertBarEvent& event )
858 {
859 cbBarInfo* pBarToInsert = event.mpBar;
860 cbRowInfo* pIntoRow = event.mpRow;
861 mpPane = event.mpPane;
862
863 if ( !pBarToInsert->IsFixed() )
864
865 AdjustLengthOfInserted( pIntoRow, pBarToInsert );
866
867 DoInsertBar( pBarToInsert, *pIntoRow );
868
869 mpPane->InitLinksForRow( pIntoRow ); // relink "mpNext/mpPrev"s
870
871 // perform relayouting of the bars after insertion
872
873 // init bar location info
874 pBarToInsert->mAlignment = event.mpPane->mAlignment;
875 pBarToInsert->mRowNo = event.mpPane->GetRowIndex( pIntoRow );
876
877 #ifdef __EXPERIMENTAL
878
879 if ( !pIntoRow->mHasOnlyFixedBars || !pBarToInsert->IsFixed() )
880
881 RecalcLengthRatios( pIntoRow );
882
883 #endif
884
885 MinimzeNotFixedBars( pIntoRow, pBarToInsert );
886
887 SlideLeftSideBars ( pBarToInsert );
888 SlideRightSideBars( pBarToInsert );
889
890 ShiftLeftTrashold ( pBarToInsert, *pIntoRow );
891 ShiftRightTrashold( pBarToInsert, *pIntoRow );
892
893 mpPane->SyncRowFlags( pIntoRow );
894
895 CheckIfAtTheBoundary( pBarToInsert, *pIntoRow );
896
897 if ( event.mpPane->IsHorizontal() )
898
899 pBarToInsert->mState = wxCBAR_DOCKED_HORIZONTALLY;
900 else
901 pBarToInsert->mState = wxCBAR_DOCKED_VERTICALLY;
902
903 if ( !pIntoRow->mHasOnlyFixedBars )
904 {
905
906 #ifdef __EXPERIMENTAL
907
908 ExpandNotFixedBars( pIntoRow );
909 #else
910
911 RelayoutNotFixedBarsAround( pBarToInsert, pIntoRow );
912 RecalcLengthRatios( pIntoRow );
913
914 #endif
915
916 DetectBarHandles( pIntoRow );
917
918 // do proportional resizing of not-fixed bars
919 ApplyLengthRatios( pIntoRow );
920 }
921
922 // adjust the bar's docking state
923
924 // a little bit of AI:
925 // memorize bar's height and width, when docked in
926 // the current orientation - by making the current
927 // dimensions to be "preferred" ones for this docking state
928
929 if ( !pBarToInsert->IsFixed() )
930 {
931 cbBarInfo& bar = *pBarToInsert;
932
933 bar.mDimInfo.mSizes[ bar.mState ].x = bar.mBounds.width;
934 bar.mDimInfo.mSizes[ bar.mState ].y = bar.mBounds.height;
935 }
936 }
937
938 void cbRowLayoutPlugin::OnRemoveBar ( cbRemoveBarEvent& event )
939 {
940 cbBarInfo* pBar = event.mpBar;
941 mpPane = event.mpPane;
942
943 cbRowInfo* pRow = pBar->mpRow;
944
945 mpLayout->GetUpdatesManager().OnBarWillChange( pBar, pRow, event.mpPane );
946
947 // invalidate the whole row
948 //pFirst->mpRowInfo->mMgrData.mPrevBounds.x = -1;
949
950 pRow->mBars.Remove( pBar );
951
952 // rest bar information after removing it from the row
953 pBar->mpRow = NULL;
954 pBar->mHasLeftHandle = FALSE;
955 pBar->mHasRightHandle = FALSE;
956
957 mpPane->InitLinksForRow( pRow ); // relink "mpNext/mpPrev"s
958
959 if ( pRow->mBars.Count() == 0 )
960 {
961 // empty rows should not exist
962
963 event.mpPane->GetRowList().Remove( pRow );
964
965 delete pRow;
966
967 mpPane->InitLinksForRows();
968 }
969 else
970 {
971 // force repainting of bars, in the row, from which the bar was removed
972
973 // FIXME:: really needed?
974 pRow->mBars[0]->mUMgrData.SetDirty(TRUE);
975
976 // re-setup mHasOnlyFixedBars flag for the row information
977 event.mpPane->SyncRowFlags( pRow );
978
979 DetectBarHandles( pRow );
980
981 if ( !pRow->mHasOnlyFixedBars )
982
983 ExpandNotFixedBars( pRow );
984 }
985 }
986
987 void cbRowLayoutPlugin::OnLayoutRow( cbLayoutRowEvent& event )
988 {
989 cbRowInfo* pRow = event.mpRow;
990 mpPane = event.mpPane;
991
992 MinimzeNotFixedBars( pRow, NULL );
993
994 if ( !pRow->mHasOnlyFixedBars )
995 {
996 // do proportional resizing of not-fixed bars
997 ApplyLengthRatios( pRow );
998 }
999
1000 cbBarInfo& lastBar = *pRow->mBars[ pRow->mBars.Count() - 1 ];
1001 cbBarInfo& firstBar = *pRow->mBars[ 0 ];
1002
1003 // FIXME:: Next line not used
1004 // wxRect& bounds = lastBar.mBounds;
1005
1006 if ( lastBar.mBounds.x + lastBar.mBounds.width > mpPane->mPaneWidth )
1007 {
1008 lastBar.mBounds.x = mpPane->mPaneWidth - lastBar.mBounds.width;
1009
1010 // first simulate left-row-edge friction
1011
1012 SlideLeftSideBars( &lastBar );
1013
1014 if ( firstBar.mBounds.x < 0 )
1015 firstBar.mBounds.x = 0;
1016
1017 // then left-row-edge function, though this
1018 // may cause some of the right-side bars going
1019 // out of row bounds, but left-side always
1020 // has the highest "priority"
1021
1022 SlideRightSideBars( &firstBar );
1023 }
1024
1025 event.Skip(); // pass event to the next handler
1026 }
1027
1028 void cbRowLayoutPlugin::OnLayoutRows( cbLayoutRowsEvent& event )
1029 {
1030 mpPane = event.mpPane;
1031
1032 int curY = 0;
1033
1034 // FIXME:: Next line not used.
1035 // RowArrayT& arr = mpPane->GetRowList();
1036
1037 size_t i;
1038 for ( i = 0; i != mpPane->GetRowList().Count(); ++i )
1039 {
1040 cbRowInfo& row = *mpPane->GetRowList()[ i ];
1041 //mpPane->CalcLengthRatios(& row);
1042
1043 // setup "has-handle" flags for rows, which depend on the existance
1044 // of not-fixed bars in the row
1045
1046 if ( !row.mHasOnlyFixedBars )
1047 {
1048 if ( mpPane->mAlignment == FL_ALIGN_TOP ||
1049 mpPane->mAlignment == FL_ALIGN_LEFT )
1050 {
1051 row.mHasLowerHandle = TRUE;
1052
1053 row.mHasUpperHandle = FALSE;
1054 }
1055 else
1056 {
1057 row.mHasUpperHandle = TRUE;
1058
1059 row.mHasLowerHandle = FALSE;
1060 }
1061 }
1062 else
1063 {
1064 // otherwise, rows with fixed-bars only, have no height-resizing handles
1065 row.mHasUpperHandle = FALSE;
1066 row.mHasLowerHandle = FALSE;
1067 }
1068
1069 // setup vertical positions for items in the row
1070
1071 row.mRowY = curY;
1072
1073 row.mRowWidth = mpPane->mPaneWidth;
1074 row.mRowHeight = CalcRowHeight( row );
1075
1076 LayoutItemsVertically( row );
1077
1078 if ( row.mHasUpperHandle )
1079 row.mRowHeight += mpPane->mProps.mResizeHandleSize;
1080 if ( row.mHasLowerHandle )
1081 row.mRowHeight += mpPane->mProps.mResizeHandleSize;
1082
1083 curY += row.mRowHeight;
1084 }
1085
1086 event.Skip(); // pass event to the next handler - other hookeds plugin
1087 // may also add some "refinements" to the layout now
1088 }
1089
1090 void cbRowLayoutPlugin::OnResizeRow( cbResizeRowEvent& event )
1091 {
1092 // extract resize-event info
1093 int ofs = event.mHandleOfs;
1094 bool forUpperHandle = event.mForUpperHandle;
1095 cbRowInfo* pTheRow = event.mpRow;
1096 mpPane = event.mpPane;
1097
1098 // FIXME:: Next line not used.
1099 //int newHeight = pTheRow->mRowHeight;
1100
1101 int freeSpc = 0;
1102
1103 if ( forUpperHandle )
1104 {
1105 // calculate available free space from above,
1106 // which can be obtained by squeezing not-fixed height rows
1107
1108 cbRowInfo* pRow = pTheRow->mpPrev;
1109
1110 while( pRow )
1111 {
1112 freeSpc += pRow->mRowHeight - event.mpPane->GetMinimalRowHeight( pRow );
1113
1114 pRow = pRow->mpPrev;
1115 }
1116 }
1117 else
1118 {
1119 // calculate available free space from below,
1120 // which can be obtained by squeezing not-fixed height rows
1121
1122 cbRowInfo* pRow = pTheRow->mpNext;
1123
1124 while( pRow )
1125 {
1126 freeSpc += pRow->mRowHeight - mpPane->GetMinimalRowHeight( pRow );
1127
1128 pRow = pRow->mpNext;
1129 }
1130 }
1131
1132 mpLayout->GetUpdatesManager().OnStartChanges();
1133
1134 int clientSize;
1135
1136 // allow user adjusting pane vs. client-area space, for upper-handle
1137
1138 if ( mpPane->IsHorizontal() )
1139
1140 clientSize = mpLayout->GetClientHeight();
1141 else
1142 clientSize = mpLayout->GetClientWidth();
1143
1144 if ( forUpperHandle && ofs < -clientSize )
1145 {
1146 int needed = -(ofs + clientSize);
1147
1148 cbRowInfo* pRow = mpPane->GetRowList()[ 0 ];
1149
1150 // start squeezing rows from the top row towards bottom
1151
1152 while( pRow != pTheRow && needed )
1153 {
1154 // only not-fixed rows can be squeezed
1155
1156 if ( !pRow->mHasOnlyFixedBars )
1157 {
1158 int prevHeight = pRow->mRowHeight;
1159
1160 int newHeight = wxMax( event.mpPane->GetMinimalRowHeight( pRow ),
1161 prevHeight - needed );
1162
1163 if ( newHeight != prevHeight )
1164 {
1165 event.mpPane->SetRowHeight( pRow, newHeight );
1166
1167 needed -= prevHeight - pRow->mRowHeight;
1168 }
1169 }
1170
1171 pRow = pRow->mpNext;
1172 }
1173 }
1174
1175 // allow user adjusting pane vs. client-area space, for lower-handle
1176
1177 if ( !forUpperHandle && ofs > clientSize )
1178 {
1179 int needed = ofs - clientSize;
1180
1181 cbRowInfo* pRow = mpPane->GetRowList()[ mpPane->GetRowList().Count() - 1 ];
1182
1183 // start squeezing rows from the bottom towards the top row
1184
1185 while( pRow && needed )
1186 {
1187 // only not-fixed rows can be squeezed
1188
1189 if ( !pRow->mHasOnlyFixedBars )
1190 {
1191 int prevHeight = pRow->mRowHeight;
1192
1193 int newHeight = wxMax( event.mpPane->GetMinimalRowHeight( pRow ),
1194 prevHeight - needed );
1195
1196 if ( newHeight != prevHeight )
1197 {
1198 event.mpPane->SetRowHeight( pRow, newHeight );
1199
1200 needed -= prevHeight - pRow->mRowHeight;
1201 }
1202 }
1203
1204 pRow = pRow->mpPrev;
1205 }
1206 }
1207
1208 if ( forUpperHandle )
1209
1210 event.mpPane->SetRowHeight( pTheRow, pTheRow->mRowHeight + (-ofs) );
1211 else
1212 event.mpPane->SetRowHeight( pTheRow, pTheRow->mRowHeight + ofs );
1213
1214 mpLayout->RecalcLayout(FALSE);
1215
1216 mpLayout->GetUpdatesManager().OnFinishChanges();
1217 mpLayout->GetUpdatesManager().UpdateNow();
1218 }
1219