1 /////////////////////////////////////////////////////////////////////////////
2 // Name: rowlayoutpl.cpp
3 // Purpose: cbRowLayoutPlugin implementation.
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
23 #include "wx/fl/rowlayoutpl.h"
25 // exerimental "features" are still buggy
28 /***** Implementation for class cbRowLayoutPlugin *****/
30 IMPLEMENT_DYNAMIC_CLASS( cbRowLayoutPlugin
, cbPluginBase
)
32 BEGIN_EVENT_TABLE( cbRowLayoutPlugin
, cbPluginBase
)
34 EVT_PL_LAYOUT_ROW ( cbRowLayoutPlugin::OnLayoutRow
)
35 EVT_PL_LAYOUT_ROWS( cbRowLayoutPlugin::OnLayoutRows
)
36 EVT_PL_RESIZE_ROW ( cbRowLayoutPlugin::OnResizeRow
)
38 EVT_PL_INSERT_BAR ( cbRowLayoutPlugin::OnInsertBar
)
39 EVT_PL_REMOVE_BAR ( cbRowLayoutPlugin::OnRemoveBar
)
43 cbRowLayoutPlugin::cbRowLayoutPlugin(void)
47 cbRowLayoutPlugin::cbRowLayoutPlugin( wxFrameLayout
* pPanel
, int paneMask
)
49 : cbPluginBase( pPanel
, paneMask
),
53 void cbRowLayoutPlugin::CheckIfAtTheBoundary( cbBarInfo
* pTheBar
, cbRowInfo
& rowInfo
)
55 // this method handles situation, when fixed bar is inserted
56 // into the row, where among fixed bars not-fixed ones are present.
57 // In this case we need to check if the pBarNode appears to be inserted
58 // chain of fixed-bars on the very right or left side of the row,
59 // then all the white-space, such chain should be eliminated,
60 // and the resulting chain justified to the right or the left
63 if ( !pTheBar
->IsFixed() || rowInfo
.mHasOnlyFixedBars
)
67 cbBarInfo
* pBar
= rowInfo
.mBars
[ rowInfo
.mBars
.Count() - 1 ];
69 // slide fixed bars to the right on the right side relative to the pBarNode
71 int prevX
= mpPane
->mPaneWidth
;
75 if ( !pBar
->IsFixed() )
78 wxRect
& bounds
= pBar
->mBounds
;
80 bounds
.x
= prevX
- bounds
.width
;
84 if ( pBar
== pTheBar
) break;
90 // slide fixed bars to the left on the left side relative to the pBarNode
92 pBar
= rowInfo
.mBars
[0];
98 if ( pBar
->IsFixed() )
102 wxRect
& bounds
= pBar
->mBounds
;
106 prevX
= bounds
.x
+ bounds
.width
;
108 if ( pBar
== pTheBar
) break;
115 void cbRowLayoutPlugin::ExpandNotFixedBars( cbRowInfo
* pRow
)
117 ApplyLengthRatios( pRow
);
121 // FIXME:: something's wrong?
126 double freeSpc
= (double)GetRowFreeSpace( pRow
);
128 // calculate sum of precents
130 double pcntSum
= 0.0;
133 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
135 if ( !pRow
->mBars
[i
]->IsFixed() )
136 pcntSum
+= pRow
->mBars
[i
]->mLenRatio
;
143 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
145 cbBarInfo
& bar
= *pRow
->mBars
[i
];
147 if ( !bar
.IsFixed() )
149 bar
.mLenRatio
= bar
.mLenRatio
/(pcntSum
);
153 wxMax( mpPane
->mProps
.mMinCBarDim
.x
, int( freeSpc
*bar
.mLenRatio
) );
156 bar
.mBounds
.x
= curX
;
157 curX
= bar
.mBounds
.x
+ bar
.mBounds
.width
;
162 void cbRowLayoutPlugin::AdjustLengthOfInserted( cbRowInfo
* WXUNUSED(pRow
), cbBarInfo
* WXUNUSED(pTheBar
) )
168 // TBD: Makes following code unreachable
170 // pTheBar is not-fixed
172 // FIXME:: what is this for??
179 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
181 if ( !pRow
->mBars
[i
]->IsFixed() )
182 totalLen
+= pRow
->mBars
[i
]->mBounds
.width
;
185 double curWidth
= pTheBar
->mBounds
.width
;
187 if ( pRow
->mBars
.Count() )
189 pTheBar
->mBounds
.width
= int( mpPane
->mPaneWidth
* (curWidth
/ double(totalLen
)) );
192 double freeSpc
= (double)GetRowFreeSpace( pRow
);
194 double pcntSum
= 0.0;
197 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
199 if ( !pRow
->mBars
[i
]->IsFixed() )
200 pcntSum
+= pRow
->mBars
[i
]->mLenRatio
;
203 // if no longer "balanced", assume that `pTheBar' was previously
204 // removed from this row (kind of AI...)
206 if ( pcntSum
< 0.98 )
208 pTheBar
->mBounds
.width
= freeSpc
* (1.0 - pcntSum
);
215 void cbRowLayoutPlugin::FitBarsToRange( int from
, int till
,
216 cbBarInfo
* pTheBar
, cbRowInfo
* pRow
)
221 if ( pTheBar
->mBounds
.x
> from
)
223 // it's range from the left
224 pFromBar
= pRow
->mBars
[0];
229 pFromBar
= pTheBar
->mpNext
;
233 // calc free space in the range
235 cbBarInfo
* pBar
= pFromBar
;
236 int freeSpc
= till
-from
;
239 while( pBar
!= pTillBar
)
241 if ( pBar
->IsFixed() )
242 freeSpc
-= pBar
->mBounds
.width
;
244 pcntSum
+= pBar
->mLenRatio
;
249 // adjust not-fixed bar sizes in the range
253 while ( pBar
!= pTillBar
)
255 if ( !pBar
->IsFixed() )
257 pBar
->mBounds
.width
=
258 wxMax( mpPane
->mProps
.mMinCBarDim
.x
,
259 (int)( ((double)freeSpc
) * (pBar
->mLenRatio
/pcntSum
) )
265 // layout range, starting from the left-most bar
269 bool hasNotFixedBars
= false;
271 while ( pBar
!= pTillBar
)
273 wxRect
& bounds
= pBar
->mBounds
;
275 if ( !pBar
->IsFixed() )
277 hasNotFixedBars
= true;
279 freeSpc
-= bounds
.width
;
284 prevX
= bounds
.x
+ bounds
.width
;
289 // make width adjustment for the right-most bar in the range, due to
290 // lost precision when seting widths using f.p. length-ratios
292 if ( hasNotFixedBars
)
294 if ( pTheBar
->mBounds
.x
> from
)
296 if ( pTillBar
->mpPrev
)
298 wxRect
& tillBar
= pTillBar
->mpPrev
->mBounds
;
300 //tillBar.width = bar.mBounds.x - tillBar.x;
301 tillBar
.width
+= freeSpc
;
306 cbBarInfo
* pLast
= pRow
->mBars
[ pRow
->mBars
.Count() - 1 ];
308 if ( pLast
!= pTheBar
)
310 pTheBar
->mBounds
.width
+= freeSpc
;
312 SlideRightSideBars( pTheBar
);
318 void cbRowLayoutPlugin::MinimzeNotFixedBars( cbRowInfo
* pRow
, cbBarInfo
* pBarToPreserve
)
321 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
323 if ( !pRow
->mBars
[i
]->IsFixed() && pRow
->mBars
[i
] != pBarToPreserve
)
324 pRow
->mBars
[i
]->mBounds
.width
= mpPane
->mProps
.mMinCBarDim
.x
;
328 int cbRowLayoutPlugin::GetRowFreeSpace( cbRowInfo
* pRow
)
330 int freeSpc
= mpPane
->mPaneWidth
;
333 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
335 // not-fixed bars variable length, thus their
336 // dimensions are ignored
337 if ( pRow
->mBars
[i
]->IsFixed() )
338 freeSpc
-= pRow
->mBars
[i
]->mBounds
.width
;
344 void cbRowLayoutPlugin::RecalcLengthRatios( cbRowInfo
* pRow
)
346 double freeSpc
= double( GetRowFreeSpace( pRow
) );
348 cbBarInfo
* pBar
= pRow
->mBars
[0];
349 cbBarInfo
* pLastNotFixed
= NULL
;
351 double pcntLeft
= 1.0; // (100%)
353 #ifdef __EXPERIMENTAL
358 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
360 if ( !pRow
->mBars
[i
]->IsFixed() )
361 totalLen
+= pRow
->mBars
[i
]->mBounds
.width
;
366 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
368 cbBarInfo
& bar
= *pRow
->mBars
[i
];
370 if ( !bar
.IsFixed() )
373 #ifdef __EXPERIMENTAL
375 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalLen
);
377 bar
.mLenRatio
= double(bar
.mBounds
.width
)/freeSpc
;
380 pcntLeft
-= bar
.mLenRatio
;
381 pLastNotFixed
= pBar
;
385 // attach remainder (the result of lost precision) to the
386 // last not-fixed bar
388 #if !defined(__EXPERIMENTAL)
392 pLastNotFixed
->mLenRatio
+= pcntLeft
;
397 void cbRowLayoutPlugin::ApplyLengthRatios( cbRowInfo
* pRow
)
402 // FOR NOW:: all-in-one
404 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
406 if ( !pRow
->mBars
[i
]->IsFixed() )
407 pcntSum
+= pRow
->mBars
[i
]->mLenRatio
;
411 pBar = node_to_first_bar_node( pRow );
415 cbBarInfo& bar = node_to_bar( pBar );
417 if ( !bar.IsFixed() )
419 bar.mLenRatio = pcntSum / bar.mLenRatio;
426 double freeSpc
= GetRowFreeSpace( pRow
);
428 // tricky stuff (improtant!):
429 // when not-fixed bar is removed from the row and there are
430 // still some other not-fixed ones left in that row, then
431 // the sum of mLenRatio's is no longer 1.0 - this is left
432 // intintionally to handle the case when the removed bar
433 // is returned right back to the row - so that it would retain
434 // it's original dimensions in this row (this is kind of AI...)
436 // The problem is - when it's remvoed, the sum of
437 // mLenRatio's is not in "balance", i.e. is < 1.0,
438 // it's possible to restore balance, but instead of that
439 // we artifically ajdust freeSpc value in a way that it would
440 // look like total of mLetRatio's is 1.0, thus original
441 // len. ratios are _preserved_:
446 double unit
= freeSpc
/ pcntSum
;
448 bool haveSquished
= false;
450 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
452 if ( !pRow
->mBars
[i
]->IsFixed() )
454 cbBarInfo
& bar
= *pRow
->mBars
[i
];
456 if ( int( unit
* bar
.mLenRatio
) < mpPane
->mProps
.mMinCBarDim
.x
)
460 bar
.mBounds
.width
= -1; // mark as "squished"
462 pcntSum
-= bar
.mLenRatio
;
464 freeSpc
-= mpPane
->mProps
.mMinCBarDim
.x
;
470 unit
= freeSpc
/ pcntSum
;
472 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
474 cbBarInfo
& bar
= *pRow
->mBars
[i
];
476 bar
.mBounds
.x
= prevX
;
478 if ( !bar
.IsFixed() )
480 if ( bar
.mBounds
.width
== -1 )
482 bar
.mBounds
.width
= mpPane
->mProps
.mMinCBarDim
.x
;
484 bar
.mBounds
.width
= int( unit
* bar
.mLenRatio
);
486 // a little bit of AI:
487 // memorize bar's height and width, when docked in
488 // the current orientation - by making the current
489 // dimensions to be "preffered" ones for this docking state
491 if ( !bar
.IsFixed() )
493 bar
.mDimInfo
.mSizes
[ bar
.mState
].x
= bar
.mBounds
.width
;
494 bar
.mDimInfo
.mSizes
[ bar
.mState
].y
= bar
.mBounds
.height
;
498 prevX
= bar
.mBounds
.x
+ bar
.mBounds
.width
;
502 void cbRowLayoutPlugin::DetectBarHandles( cbRowInfo
* pRow
)
504 // first pass from left to right (detect left-side handles)
506 bool foundNotFixed
= false;
509 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
511 cbBarInfo
& bar
= *pRow
->mBars
[i
];
513 bar
.mHasLeftHandle
= false;
515 if ( !bar
.IsFixed() )
520 bar
.mpPrev
->IsFixed() )
522 bar
.mHasLeftHandle
= true;
524 foundNotFixed
= true;
528 // pass from right to left (detect right-side handles)
530 foundNotFixed
= false;
532 cbBarInfo
* pBar
= pRow
->mBars
[ pRow
->mBars
.Count() - 1 ];
536 pBar
->mHasRightHandle
= false;
538 if ( !pBar
->IsFixed() )
544 pBar
->mHasRightHandle
= true;
546 foundNotFixed
= true;
553 void cbRowLayoutPlugin::RelayoutNotFixedBarsAround( cbBarInfo
* pTheBar
, cbRowInfo
* pRow
)
555 if ( !pTheBar
->mpPrev
)
557 if ( !pTheBar
->IsFixed() )
559 // this bar the first in the row, move it's
560 // left edge to the very left
561 pTheBar
->mBounds
.width
+= pTheBar
->mBounds
.x
;
562 pTheBar
->mBounds
.x
= 0;
566 FitBarsToRange( 0, pTheBar
->mBounds
.x
, pTheBar
, pRow
);
568 if ( !pTheBar
->mpNext
)
570 if ( !pTheBar
->IsFixed() )
572 // this bar is the last one, move it's
573 // right edge to the very right
575 pTheBar
->mBounds
.width
= mpPane
->mPaneWidth
- pTheBar
->mBounds
.x
;
579 FitBarsToRange( pTheBar
->mBounds
.x
+ pTheBar
->mBounds
.width
, mpPane
->mPaneWidth
,
584 void cbRowLayoutPlugin::LayoutItemsVertically( cbRowInfo
& row
)
587 for ( i
= 0; i
!= row
.mBars
.Count(); ++i
)
589 cbBarInfo
& bar
= *row
.mBars
[i
];
591 bar
.mBounds
.y
= row
.mRowY
;
593 if ( !bar
.IsFixed() )
595 // make all not-fixed bars of equal height
596 bar
.mBounds
.height
= row
.mRowHeight
;
598 if ( row
.mHasUpperHandle
)
600 bar
.mBounds
.y
+= mpPane
->mProps
.mResizeHandleSize
;
604 int cbRowLayoutPlugin::CalcRowHeight( cbRowInfo
& row
)
609 for ( i
= 0; i
!= row
.mBars
.Count(); ++i
)
611 maxHeight
= wxMax( maxHeight
, row
.mBars
[i
]->mBounds
.height
);
616 void cbRowLayoutPlugin::StickRightSideBars( cbBarInfo
* pToBar
)
618 cbBarInfo
* pBar
= pToBar
->mpNext
;
619 cbBarInfo
* pPrev
= pToBar
;
623 wxRect
& cur
= pBar
->mBounds
;
624 wxRect
& prev
= pPrev
->mBounds
;
626 cur
.x
= prev
.x
+ prev
.width
;
633 void cbRowLayoutPlugin::SlideLeftSideBars( cbBarInfo
* pTheBar
)
635 // shift left-side-bars to the left (with respect to "theBar"),
636 // so that they would not obscured by each other
638 cbBarInfo
* pBar
= pTheBar
->mpPrev
;
639 cbBarInfo
* pPrev
= pTheBar
;
643 wxRect
& cur
= pBar
->mBounds
;
644 wxRect
& prev
= pPrev
->mBounds
;
646 if ( cur
.x
+ cur
.width
> prev
.x
)
648 cur
.x
= prev
.x
- cur
.width
;
655 void cbRowLayoutPlugin::SlideRightSideBars( cbBarInfo
* pTheBar
)
657 // shift right-side-bars to the right (with respect to "theBar"),
658 // so that they would not be obscured by each other
660 cbBarInfo
* pBar
= pTheBar
->mpNext
;
661 cbBarInfo
* pPrev
= pTheBar
;
665 wxRect
& cur
= pBar
->mBounds
;
666 wxRect
& prev
= pPrev
->mBounds
;
668 if ( cur
.x
< prev
.x
+ prev
.width
)
670 cur
.x
= prev
.x
+ prev
.width
;
677 void cbRowLayoutPlugin::ShiftLeftTrashold( cbBarInfo
* WXUNUSED(pTheBar
), cbRowInfo
& row
)
679 wxRect
& first
= row
.mBars
[0]->mBounds
;
683 row
.mBars
[0]->mBounds
.x
= 0;
685 SlideRightSideBars( row
.mBars
[0] );
689 void cbRowLayoutPlugin::ShiftRightTrashold( cbBarInfo
* pTheBar
, cbRowInfo
& row
)
691 wxRect
& theBar
= pTheBar
->mBounds
;
695 cbBarInfo
* pBar
= pTheBar
;
697 // calculate free spece on the left side
703 wxRect
& cur
= pBar
->mBounds
;
707 wxRect
& prev
= pBar
->mpPrev
->mBounds
;
709 leftFreeSpc
+= cur
.x
- prev
.x
- prev
.width
;
712 leftFreeSpc
+= cur
.x
;
725 int rightOverflow
= 0;
727 if ( pTheBar
->IsFixed() )
733 wxRect
& cur
= pBar
->mBounds
;
735 if ( cur
.x
+ cur
.width
> mpPane
->mPaneWidth
)
737 rightOverflow
= cur
.x
+ cur
.width
- mpPane
->mPaneWidth
;
743 if ( rightOverflow
> 0 )
745 if ( leftFreeSpc
<= 0 ) return;
747 if ( pTheBar
->mpNext
)
749 wxRect
& next
= pTheBar
->mpNext
->mBounds
;
751 // if there's enough space on the left, move over one half-obscured
752 // bar from the right to the left side with respect to "theBar"
754 if ( next
.width
< leftFreeSpc
)
756 cbBarInfo
* pNext
= pTheBar
->mpNext
;
758 row
.mBars
.Remove( pNext
);
760 row
.mBars
.Insert( pNext
, row
.mBars
.Index( pTheBar
) );
762 next
.x
= theBar
.x
- next
.width
;
764 // re-setup mpPrev/mpNext references after insertion
766 mpPane
->InitLinksForRow( &row
);
770 StickRightSideBars( pTheBar
);
771 SlideLeftSideBars ( pTheBar
);
777 int leftShift
= ( rightOverflow
> leftFreeSpc
)
781 theBar
.x
-= leftShift
;
783 StickRightSideBars( pTheBar
);
784 SlideLeftSideBars ( pTheBar
);
788 } // end of if ( rightOverflow )
795 void cbRowLayoutPlugin::InsertBefore( cbBarInfo
* pBeforeBar
,
801 row
.mBars
.Insert( pTheBar
, row
.mBars
.Index( pBeforeBar
) );
803 row
.mBars
.Add( pTheBar
);
805 pTheBar
->mpRow
= &row
;
808 void cbRowLayoutPlugin::DoInsertBar( cbBarInfo
* pTheBar
, cbRowInfo
& row
)
810 wxRect
& theBar
= pTheBar
->mBounds
;
813 if ( theBar.x < 0 && !node_to_bar( pTheBar ).IsFixed() )
816 theBar.width += theBar.x;
821 for ( i
= 0; i
!= row
.mBars
.Count(); ++i
)
823 cbBarInfo
& bar
= *row
.mBars
[i
];
825 wxRect
& cur
= bar
.mBounds
;
827 // if bar hits the left edge
828 if ( theBar
.x
<= cur
.x
)
830 InsertBefore( &bar
, pTheBar
, row
);
835 // if bar hits the right edge
836 if ( theBar
.x
<= cur
.x
+ cur
.width
)
838 if ( theBar
.x
+ theBar
.width
> cur
.x
+ cur
.width
)
840 InsertBefore( bar
.mpNext
, pTheBar
, row
);
844 // otherwise the bar lies within the bounds of current bar
846 int leftDist
= theBar
.x
- cur
.x
;
847 int rightDist
= cur
.x
+ cur
.width
- (theBar
.x
+ theBar
.width
);
849 if ( leftDist
< rightDist
)
851 InsertBefore( &bar
, pTheBar
, row
);
853 InsertBefore( bar
.mpNext
, pTheBar
, row
);
859 InsertBefore( NULL
, pTheBar
, row
); // insert at the end
864 void cbRowLayoutPlugin::OnInsertBar( cbInsertBarEvent
& event
)
866 cbBarInfo
* pBarToInsert
= event
.mpBar
;
867 cbRowInfo
* pIntoRow
= event
.mpRow
;
868 mpPane
= event
.mpPane
;
870 if ( !pBarToInsert
->IsFixed() )
872 AdjustLengthOfInserted( pIntoRow
, pBarToInsert
);
874 DoInsertBar( pBarToInsert
, *pIntoRow
);
876 mpPane
->InitLinksForRow( pIntoRow
); // relink "mpNext/mpPrev"s
878 // perform relayouting of the bars after insertion
880 // init bar location info
881 pBarToInsert
->mAlignment
= event
.mpPane
->mAlignment
;
882 pBarToInsert
->mRowNo
= event
.mpPane
->GetRowIndex( pIntoRow
);
884 #ifdef __EXPERIMENTAL
886 if ( !pIntoRow
->mHasOnlyFixedBars
|| !pBarToInsert
->IsFixed() )
888 RecalcLengthRatios( pIntoRow
);
892 MinimzeNotFixedBars( pIntoRow
, pBarToInsert
);
894 SlideLeftSideBars ( pBarToInsert
);
895 SlideRightSideBars( pBarToInsert
);
897 ShiftLeftTrashold ( pBarToInsert
, *pIntoRow
);
898 ShiftRightTrashold( pBarToInsert
, *pIntoRow
);
900 mpPane
->SyncRowFlags( pIntoRow
);
902 CheckIfAtTheBoundary( pBarToInsert
, *pIntoRow
);
904 if ( event
.mpPane
->IsHorizontal() )
906 pBarToInsert
->mState
= wxCBAR_DOCKED_HORIZONTALLY
;
908 pBarToInsert
->mState
= wxCBAR_DOCKED_VERTICALLY
;
910 if ( !pIntoRow
->mHasOnlyFixedBars
)
913 #ifdef __EXPERIMENTAL
915 ExpandNotFixedBars( pIntoRow
);
918 RelayoutNotFixedBarsAround( pBarToInsert
, pIntoRow
);
919 RecalcLengthRatios( pIntoRow
);
923 DetectBarHandles( pIntoRow
);
925 // do proportional resizing of not-fixed bars
926 ApplyLengthRatios( pIntoRow
);
929 // adjust the bar's docking state
931 // a little bit of AI:
932 // memorize bar's height and width, when docked in
933 // the current orientation - by making the current
934 // dimensions to be "preferred" ones for this docking state
936 if ( !pBarToInsert
->IsFixed() )
938 cbBarInfo
& bar
= *pBarToInsert
;
940 bar
.mDimInfo
.mSizes
[ bar
.mState
].x
= bar
.mBounds
.width
;
941 bar
.mDimInfo
.mSizes
[ bar
.mState
].y
= bar
.mBounds
.height
;
945 void cbRowLayoutPlugin::OnRemoveBar ( cbRemoveBarEvent
& event
)
947 cbBarInfo
* pBar
= event
.mpBar
;
948 mpPane
= event
.mpPane
;
950 cbRowInfo
* pRow
= pBar
->mpRow
;
952 mpLayout
->GetUpdatesManager().OnBarWillChange( pBar
, pRow
, event
.mpPane
);
954 // invalidate the whole row
955 //pFirst->mpRowInfo->mMgrData.mPrevBounds.x = -1;
957 pRow
->mBars
.Remove( pBar
);
959 // rest bar information after removing it from the row
961 pBar
->mHasLeftHandle
= false;
962 pBar
->mHasRightHandle
= false;
964 mpPane
->InitLinksForRow( pRow
); // relink "mpNext/mpPrev"s
966 if ( pRow
->mBars
.Count() == 0 )
968 // empty rows should not exist
970 event
.mpPane
->GetRowList().Remove( pRow
);
974 mpPane
->InitLinksForRows();
978 // force repainting of bars, in the row, from which the bar was removed
980 // FIXME:: really needed?
981 pRow
->mBars
[0]->mUMgrData
.SetDirty(true);
983 // re-setup mHasOnlyFixedBars flag for the row information
984 event
.mpPane
->SyncRowFlags( pRow
);
986 DetectBarHandles( pRow
);
988 if ( !pRow
->mHasOnlyFixedBars
)
990 ExpandNotFixedBars( pRow
);
994 void cbRowLayoutPlugin::OnLayoutRow( cbLayoutRowEvent
& event
)
996 cbRowInfo
* pRow
= event
.mpRow
;
997 mpPane
= event
.mpPane
;
999 MinimzeNotFixedBars( pRow
, NULL
);
1001 if ( !pRow
->mHasOnlyFixedBars
)
1003 // do proportional resizing of not-fixed bars
1004 ApplyLengthRatios( pRow
);
1007 cbBarInfo
& lastBar
= *pRow
->mBars
[ pRow
->mBars
.Count() - 1 ];
1008 cbBarInfo
& firstBar
= *pRow
->mBars
[ 0 ];
1010 // FIXME:: Next line not used
1011 // wxRect& bounds = lastBar.mBounds;
1013 if ( lastBar
.mBounds
.x
+ lastBar
.mBounds
.width
> mpPane
->mPaneWidth
)
1015 lastBar
.mBounds
.x
= mpPane
->mPaneWidth
- lastBar
.mBounds
.width
;
1017 // first simulate left-row-edge friction
1019 SlideLeftSideBars( &lastBar
);
1021 if ( firstBar
.mBounds
.x
< 0 )
1022 firstBar
.mBounds
.x
= 0;
1024 // then left-row-edge function, though this
1025 // may cause some of the right-side bars going
1026 // out of row bounds, but left-side always
1027 // has the highest "priority"
1029 SlideRightSideBars( &firstBar
);
1032 event
.Skip(); // pass event to the next handler
1035 void cbRowLayoutPlugin::OnLayoutRows( cbLayoutRowsEvent
& event
)
1037 mpPane
= event
.mpPane
;
1041 // FIXME:: Next line not used.
1042 // RowArrayT& arr = mpPane->GetRowList();
1045 for ( i
= 0; i
!= mpPane
->GetRowList().Count(); ++i
)
1047 cbRowInfo
& row
= *mpPane
->GetRowList()[ i
];
1048 //mpPane->CalcLengthRatios(& row);
1050 // setup "has-handle" flags for rows, which depend on the existence
1051 // of not-fixed bars in the row
1053 if ( !row
.mHasOnlyFixedBars
)
1055 if ( mpPane
->mAlignment
== FL_ALIGN_TOP
||
1056 mpPane
->mAlignment
== FL_ALIGN_LEFT
)
1058 row
.mHasLowerHandle
= true;
1060 row
.mHasUpperHandle
= false;
1064 row
.mHasUpperHandle
= true;
1066 row
.mHasLowerHandle
= false;
1071 // otherwise, rows with fixed-bars only, have no height-resizing handles
1072 row
.mHasUpperHandle
= false;
1073 row
.mHasLowerHandle
= false;
1076 // setup vertical positions for items in the row
1080 row
.mRowWidth
= mpPane
->mPaneWidth
;
1081 row
.mRowHeight
= CalcRowHeight( row
);
1083 LayoutItemsVertically( row
);
1085 if ( row
.mHasUpperHandle
)
1086 row
.mRowHeight
+= mpPane
->mProps
.mResizeHandleSize
;
1087 if ( row
.mHasLowerHandle
)
1088 row
.mRowHeight
+= mpPane
->mProps
.mResizeHandleSize
;
1090 curY
+= row
.mRowHeight
;
1093 event
.Skip(); // pass event to the next handler - other hookeds plugin
1094 // may also add some "refinements" to the layout now
1097 void cbRowLayoutPlugin::OnResizeRow( cbResizeRowEvent
& event
)
1099 // extract resize-event info
1100 int ofs
= event
.mHandleOfs
;
1101 bool forUpperHandle
= event
.mForUpperHandle
;
1102 cbRowInfo
* pTheRow
= event
.mpRow
;
1103 mpPane
= event
.mpPane
;
1105 // FIXME:: Next line not used.
1106 //int newHeight = pTheRow->mRowHeight;
1108 if ( forUpperHandle
)
1110 // calculate available free space from above,
1111 // which can be obtained by squeezing not-fixed height rows
1113 cbRowInfo
* pRow
= pTheRow
->mpPrev
;
1117 pRow
= pRow
->mpPrev
;
1122 // calculate available free space from below,
1123 // which can be obtained by squeezing not-fixed height rows
1125 cbRowInfo
* pRow
= pTheRow
->mpNext
;
1129 pRow
= pRow
->mpNext
;
1133 mpLayout
->GetUpdatesManager().OnStartChanges();
1137 // allow user adjusting pane vs. client-area space, for upper-handle
1139 if ( mpPane
->IsHorizontal() )
1141 clientSize
= mpLayout
->GetClientHeight();
1143 clientSize
= mpLayout
->GetClientWidth();
1145 if ( forUpperHandle
&& ofs
< -clientSize
)
1147 int needed
= -(ofs
+ clientSize
);
1149 cbRowInfo
* pRow
= mpPane
->GetRowList()[ 0 ];
1151 // start squeezing rows from the top row towards bottom
1153 while( pRow
!= pTheRow
&& needed
)
1155 // only not-fixed rows can be squeezed
1157 if ( !pRow
->mHasOnlyFixedBars
)
1159 int prevHeight
= pRow
->mRowHeight
;
1161 int newHeight
= wxMax( event
.mpPane
->GetMinimalRowHeight( pRow
),
1162 prevHeight
- needed
);
1164 if ( newHeight
!= prevHeight
)
1166 event
.mpPane
->SetRowHeight( pRow
, newHeight
);
1168 needed
-= prevHeight
- pRow
->mRowHeight
;
1172 pRow
= pRow
->mpNext
;
1176 // allow user adjusting pane vs. client-area space, for lower-handle
1178 if ( !forUpperHandle
&& ofs
> clientSize
)
1180 int needed
= ofs
- clientSize
;
1182 cbRowInfo
* pRow
= mpPane
->GetRowList()[ mpPane
->GetRowList().Count() - 1 ];
1184 // start squeezing rows from the bottom towards the top row
1186 while( pRow
&& needed
)
1188 // only not-fixed rows can be squeezed
1190 if ( !pRow
->mHasOnlyFixedBars
)
1192 int prevHeight
= pRow
->mRowHeight
;
1194 int newHeight
= wxMax( event
.mpPane
->GetMinimalRowHeight( pRow
),
1195 prevHeight
- needed
);
1197 if ( newHeight
!= prevHeight
)
1199 event
.mpPane
->SetRowHeight( pRow
, newHeight
);
1201 needed
-= prevHeight
- pRow
->mRowHeight
;
1205 pRow
= pRow
->mpPrev
;
1209 if ( forUpperHandle
)
1211 event
.mpPane
->SetRowHeight( pTheRow
, pTheRow
->mRowHeight
+ (-ofs
) );
1213 event
.mpPane
->SetRowHeight( pTheRow
, pTheRow
->mRowHeight
+ ofs
);
1215 mpLayout
->RecalcLayout(false);
1217 mpLayout
->GetUpdatesManager().OnFinishChanges();
1218 mpLayout
->GetUpdatesManager().UpdateNow();