1 /////////////////////////////////////////////////////////////////////////////
2 // Name: rowlayoutpl.cpp
3 // Purpose: cbRowLayoutPlugin implementation.
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "rowlayoutpl.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #include "wx/fl/rowlayoutpl.h"
29 // exerimental "features" are still buggy
32 /***** Implementation for class cbRowLayoutPlugin *****/
34 IMPLEMENT_DYNAMIC_CLASS( cbRowLayoutPlugin
, cbPluginBase
)
36 BEGIN_EVENT_TABLE( cbRowLayoutPlugin
, cbPluginBase
)
38 EVT_PL_LAYOUT_ROW ( cbRowLayoutPlugin::OnLayoutRow
)
39 EVT_PL_LAYOUT_ROWS( cbRowLayoutPlugin::OnLayoutRows
)
40 EVT_PL_RESIZE_ROW ( cbRowLayoutPlugin::OnResizeRow
)
42 EVT_PL_INSERT_BAR ( cbRowLayoutPlugin::OnInsertBar
)
43 EVT_PL_REMOVE_BAR ( cbRowLayoutPlugin::OnRemoveBar
)
47 cbRowLayoutPlugin::cbRowLayoutPlugin(void)
51 cbRowLayoutPlugin::cbRowLayoutPlugin( wxFrameLayout
* pPanel
, int paneMask
)
53 : cbPluginBase( pPanel
, paneMask
),
57 void cbRowLayoutPlugin::CheckIfAtTheBoundary( cbBarInfo
* pTheBar
, cbRowInfo
& rowInfo
)
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
67 if ( !pTheBar
->IsFixed() || rowInfo
.mHasOnlyFixedBars
)
71 cbBarInfo
* pBar
= rowInfo
.mBars
[ rowInfo
.mBars
.Count() - 1 ];
73 // slide fixed bars to the right on the right side relative to the pBarNode
75 int prevX
= mpPane
->mPaneWidth
;
79 if ( !pBar
->IsFixed() )
82 wxRect
& bounds
= pBar
->mBounds
;
84 bounds
.x
= prevX
- bounds
.width
;
88 if ( pBar
== pTheBar
) break;
94 // slide fixed bars to the left on the left side relative to the pBarNode
96 pBar
= rowInfo
.mBars
[0];
102 if ( pBar
->IsFixed() )
106 wxRect
& bounds
= pBar
->mBounds
;
110 prevX
= bounds
.x
+ bounds
.width
;
112 if ( pBar
== pTheBar
) break;
119 void cbRowLayoutPlugin::ExpandNotFixedBars( cbRowInfo
* pRow
)
121 ApplyLengthRatios( pRow
);
123 // 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
;
161 void cbRowLayoutPlugin::AdjustLengthOfInserted( cbRowInfo
* pRow
, cbBarInfo
* pTheBar
)
163 return; // TBD: Makes following code unreachable
165 // pTheBar is not-fixed
168 // FIXME:: what is this for??
175 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
177 if ( !pRow
->mBars
[i
]->IsFixed() )
178 totalLen
+= pRow
->mBars
[i
]->mBounds
.width
;
181 double curWidth
= pTheBar
->mBounds
.width
;
183 if ( pRow
->mBars
.Count() )
185 pTheBar
->mBounds
.width
= int( mpPane
->mPaneWidth
* (curWidth
/ double(totalLen
)) );
188 double freeSpc
= (double)GetRowFreeSpace( pRow
);
190 double pcntSum
= 0.0;
193 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
195 if ( !pRow
->mBars
[i
]->IsFixed() )
196 pcntSum
+= pRow
->mBars
[i
]->mLenRatio
;
199 // if no longer "balanced", assume that `pTheBar' was previously
200 // removed from this row (kind of AI...)
202 if ( pcntSum
< 0.98 )
204 pTheBar
->mBounds
.width
= freeSpc
* (1.0 - pcntSum
);
208 void cbRowLayoutPlugin::FitBarsToRange( int from
, int till
,
209 cbBarInfo
* pTheBar
, cbRowInfo
* pRow
)
211 cbBarInfo
* pFromBar
= NULL
;
212 cbBarInfo
* pTillBar
= NULL
;
214 if ( pTheBar
->mBounds
.x
> from
)
216 // it's range from the left
217 pFromBar
= pRow
->mBars
[0];
222 pFromBar
= pTheBar
->mpNext
;
226 // calc free space in the range
228 cbBarInfo
* pBar
= pFromBar
;
229 int freeSpc
= till
-from
;
232 while( pBar
!= pTillBar
)
234 if ( pBar
->IsFixed() )
235 freeSpc
-= pBar
->mBounds
.width
;
237 pcntSum
+= pBar
->mLenRatio
;
242 // adjust not-fixed bar sizes in the range
246 while ( pBar
!= pTillBar
)
248 if ( !pBar
->IsFixed() )
250 pBar
->mBounds
.width
=
251 wxMax( mpPane
->mProps
.mMinCBarDim
.x
,
252 int( double(freeSpc
) * (pBar
->mLenRatio
/pcntSum
) )
258 // layout range, starting from the left-most bar
262 bool hasNotFixedBars
= FALSE
;
264 while ( pBar
!= pTillBar
)
266 wxRect
& bounds
= pBar
->mBounds
;
268 if ( !pBar
->IsFixed() )
270 hasNotFixedBars
= TRUE
;
272 freeSpc
-= bounds
.width
;
277 prevX
= bounds
.x
+ bounds
.width
;
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
285 if ( hasNotFixedBars
)
287 if ( pTheBar
->mBounds
.x
> from
)
289 if ( pTillBar
->mpPrev
)
291 wxRect
& tillBar
= pTillBar
->mpPrev
->mBounds
;
293 //tillBar.width = bar.mBounds.x - tillBar.x;
294 tillBar
.width
+= freeSpc
;
299 cbBarInfo
* pLast
= pRow
->mBars
[ pRow
->mBars
.Count() - 1 ];
301 if ( pLast
!= pTheBar
)
303 pTheBar
->mBounds
.width
+= freeSpc
;
305 SlideRightSideBars( pTheBar
);
311 void cbRowLayoutPlugin::MinimzeNotFixedBars( cbRowInfo
* pRow
, cbBarInfo
* pBarToPreserve
)
314 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
316 if ( !pRow
->mBars
[i
]->IsFixed() && pRow
->mBars
[i
] != pBarToPreserve
)
317 pRow
->mBars
[i
]->mBounds
.width
= mpPane
->mProps
.mMinCBarDim
.x
;
321 int cbRowLayoutPlugin::GetRowFreeSpace( cbRowInfo
* pRow
)
323 int freeSpc
= mpPane
->mPaneWidth
;
326 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
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
;
337 void cbRowLayoutPlugin::RecalcLengthRatios( cbRowInfo
* pRow
)
339 double freeSpc
= double( GetRowFreeSpace( pRow
) );
341 cbBarInfo
* pBar
= pRow
->mBars
[0];
342 cbBarInfo
* pLastNotFixed
= NULL
;
344 double pcntLeft
= 1.0; // (100%)
346 #ifdef __EXPERIMENTAL
351 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
353 if ( !pRow
->mBars
[i
]->IsFixed() )
354 totalLen
+= pRow
->mBars
[i
]->mBounds
.width
;
359 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
361 cbBarInfo
& bar
= *pRow
->mBars
[i
];
363 if ( !bar
.IsFixed() )
366 #ifdef __EXPERIMENTAL
368 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalLen
);
370 bar
.mLenRatio
= double(bar
.mBounds
.width
)/freeSpc
;
373 pcntLeft
-= bar
.mLenRatio
;
374 pLastNotFixed
= pBar
;
378 // attach remainder (the result of lost precision) to the
379 // last not-fixed bar
381 #if !defined(__EXPERIMENTAL)
385 pLastNotFixed
->mLenRatio
+= pcntLeft
;
390 void cbRowLayoutPlugin::ApplyLengthRatios( cbRowInfo
* pRow
)
394 // FOR NOW:: all-in-one
397 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
399 if ( !pRow
->mBars
[i
]->IsFixed() )
400 pcntSum
+= pRow
->mBars
[i
]->mLenRatio
;
404 pBar = node_to_first_bar_node( pRow );
408 cbBarInfo& bar = node_to_bar( pBar );
410 if ( !bar.IsFixed() )
412 bar.mLenRatio = pcntSum / bar.mLenRatio;
419 double freeSpc
= GetRowFreeSpace( pRow
);
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...)
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_:
439 double unit
= freeSpc
/ pcntSum
;
441 bool haveSquished
= FALSE
;
443 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
445 if ( !pRow
->mBars
[i
]->IsFixed() )
447 cbBarInfo
& bar
= *pRow
->mBars
[i
];
449 if ( int( unit
* bar
.mLenRatio
) < mpPane
->mProps
.mMinCBarDim
.x
)
453 bar
.mBounds
.width
= -1; // mark as "squished"
455 pcntSum
-= bar
.mLenRatio
;
457 freeSpc
-= mpPane
->mProps
.mMinCBarDim
.x
;
463 unit
= freeSpc
/ pcntSum
;
465 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
467 cbBarInfo
& bar
= *pRow
->mBars
[i
];
469 bar
.mBounds
.x
= prevX
;
471 if ( !bar
.IsFixed() )
473 if ( bar
.mBounds
.width
== -1 )
475 bar
.mBounds
.width
= mpPane
->mProps
.mMinCBarDim
.x
;
477 bar
.mBounds
.width
= int( unit
* bar
.mLenRatio
);
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
484 if ( !bar
.IsFixed() )
486 bar
.mDimInfo
.mSizes
[ bar
.mState
].x
= bar
.mBounds
.width
;
487 bar
.mDimInfo
.mSizes
[ bar
.mState
].y
= bar
.mBounds
.height
;
491 prevX
= bar
.mBounds
.x
+ bar
.mBounds
.width
;
495 void cbRowLayoutPlugin::DetectBarHandles( cbRowInfo
* pRow
)
497 // first pass from left to right (detect left-side handles)
499 bool foundNotFixed
= FALSE
;
502 for ( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
504 cbBarInfo
& bar
= *pRow
->mBars
[i
];
506 bar
.mHasLeftHandle
= FALSE
;
508 if ( !bar
.IsFixed() )
513 bar
.mpPrev
->IsFixed() )
515 bar
.mHasLeftHandle
= TRUE
;
517 foundNotFixed
= TRUE
;
521 // pass from right to left (detect right-side handles)
523 foundNotFixed
= FALSE
;
525 cbBarInfo
* pBar
= pRow
->mBars
[ pRow
->mBars
.Count() - 1 ];
529 pBar
->mHasRightHandle
= FALSE
;
531 if ( !pBar
->IsFixed() )
537 pBar
->mHasRightHandle
= TRUE
;
539 foundNotFixed
= TRUE
;
546 void cbRowLayoutPlugin::RelayoutNotFixedBarsAround( cbBarInfo
* pTheBar
, cbRowInfo
* pRow
)
548 if ( !pTheBar
->mpPrev
)
550 if ( !pTheBar
->IsFixed() )
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;
559 FitBarsToRange( 0, pTheBar
->mBounds
.x
, pTheBar
, pRow
);
561 if ( !pTheBar
->mpNext
)
563 if ( !pTheBar
->IsFixed() )
565 // this bar is the last one, move it's
566 // right edge to the very right
568 pTheBar
->mBounds
.width
= mpPane
->mPaneWidth
- pTheBar
->mBounds
.x
;
572 FitBarsToRange( pTheBar
->mBounds
.x
+ pTheBar
->mBounds
.width
, mpPane
->mPaneWidth
,
577 void cbRowLayoutPlugin::LayoutItemsVertically( cbRowInfo
& row
)
580 for ( i
= 0; i
!= row
.mBars
.Count(); ++i
)
582 cbBarInfo
& bar
= *row
.mBars
[i
];
584 bar
.mBounds
.y
= row
.mRowY
;
586 if ( !bar
.IsFixed() )
588 // make all not-fixed bars of equal height
589 bar
.mBounds
.height
= row
.mRowHeight
;
591 if ( row
.mHasUpperHandle
)
593 bar
.mBounds
.y
+= mpPane
->mProps
.mResizeHandleSize
;
597 int cbRowLayoutPlugin::CalcRowHeight( cbRowInfo
& row
)
602 for ( i
= 0; i
!= row
.mBars
.Count(); ++i
)
604 maxHeight
= wxMax( maxHeight
, row
.mBars
[i
]->mBounds
.height
);
609 void cbRowLayoutPlugin::StickRightSideBars( cbBarInfo
* pToBar
)
611 cbBarInfo
* pBar
= pToBar
->mpNext
;
612 cbBarInfo
* pPrev
= pToBar
;
616 wxRect
& cur
= pBar
->mBounds
;
617 wxRect
& prev
= pPrev
->mBounds
;
619 cur
.x
= prev
.x
+ prev
.width
;
626 void cbRowLayoutPlugin::SlideLeftSideBars( cbBarInfo
* pTheBar
)
628 // shift left-side-bars to the left (with respect to "theBar"),
629 // so that they would not obscured by each other
631 cbBarInfo
* pBar
= pTheBar
->mpPrev
;
632 cbBarInfo
* pPrev
= pTheBar
;
636 wxRect
& cur
= pBar
->mBounds
;
637 wxRect
& prev
= pPrev
->mBounds
;
639 if ( cur
.x
+ cur
.width
> prev
.x
)
641 cur
.x
= prev
.x
- cur
.width
;
648 void cbRowLayoutPlugin::SlideRightSideBars( cbBarInfo
* pTheBar
)
650 // shift right-side-bars to the right (with respect to "theBar"),
651 // so that they would not be obscured by each other
653 cbBarInfo
* pBar
= pTheBar
->mpNext
;
654 cbBarInfo
* pPrev
= pTheBar
;
658 wxRect
& cur
= pBar
->mBounds
;
659 wxRect
& prev
= pPrev
->mBounds
;
661 if ( cur
.x
< prev
.x
+ prev
.width
)
663 cur
.x
= prev
.x
+ prev
.width
;
670 void cbRowLayoutPlugin::ShiftLeftTrashold( cbBarInfo
* pTheBar
, cbRowInfo
& row
)
672 wxRect
& first
= row
.mBars
[0]->mBounds
;
676 row
.mBars
[0]->mBounds
.x
= 0;
678 SlideRightSideBars( row
.mBars
[0] );
682 void cbRowLayoutPlugin::ShiftRightTrashold( cbBarInfo
* pTheBar
, cbRowInfo
& row
)
684 wxRect
& theBar
= pTheBar
->mBounds
;
688 cbBarInfo
* pBar
= pTheBar
;
690 // calculate free spece on the left side
696 wxRect
& cur
= pBar
->mBounds
;
700 wxRect
& prev
= pBar
->mpPrev
->mBounds
;
702 leftFreeSpc
+= cur
.x
- prev
.x
- prev
.width
;
705 leftFreeSpc
+= cur
.x
;
718 int rightOverflow
= 0;
720 if ( pTheBar
->IsFixed() )
726 wxRect
& cur
= pBar
->mBounds
;
728 if ( cur
.x
+ cur
.width
> mpPane
->mPaneWidth
)
730 rightOverflow
= cur
.x
+ cur
.width
- mpPane
->mPaneWidth
;
736 if ( rightOverflow
> 0 )
738 if ( leftFreeSpc
<= 0 ) return;
740 if ( pTheBar
->mpNext
)
742 wxRect
& next
= pTheBar
->mpNext
->mBounds
;
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"
747 if ( next
.width
< leftFreeSpc
)
749 cbBarInfo
* pNext
= pTheBar
->mpNext
;
751 row
.mBars
.Remove( pNext
);
753 row
.mBars
.Insert( pNext
, row
.mBars
.Index( pTheBar
) );
755 next
.x
= theBar
.x
- next
.width
;
757 // re-setup mpPrev/mpNext references after insertion
759 mpPane
->InitLinksForRow( &row
);
763 StickRightSideBars( pTheBar
);
764 SlideLeftSideBars ( pTheBar
);
770 int leftShift
= ( rightOverflow
> leftFreeSpc
)
774 theBar
.x
-= leftShift
;
776 StickRightSideBars( pTheBar
);
777 SlideLeftSideBars ( pTheBar
);
781 } // end of if ( rightOverflow )
788 void cbRowLayoutPlugin::InsertBefore( cbBarInfo
* pBeforeBar
,
794 row
.mBars
.Insert( pTheBar
, row
.mBars
.Index( pBeforeBar
) );
796 row
.mBars
.Add( pTheBar
);
798 pTheBar
->mpRow
= &row
;
801 void cbRowLayoutPlugin::DoInsertBar( cbBarInfo
* pTheBar
, cbRowInfo
& row
)
803 wxRect
& theBar
= pTheBar
->mBounds
;
806 if ( theBar.x < 0 && !node_to_bar( pTheBar ).IsFixed() )
809 theBar.width += theBar.x;
814 for ( i
= 0; i
!= row
.mBars
.Count(); ++i
)
816 cbBarInfo
& bar
= *row
.mBars
[i
];
818 wxRect
& cur
= bar
.mBounds
;
820 // if bar hits the left edge
821 if ( theBar
.x
<= cur
.x
)
823 InsertBefore( &bar
, pTheBar
, row
);
828 // if bar hits the right edge
829 if ( theBar
.x
<= cur
.x
+ cur
.width
)
831 if ( theBar
.x
+ theBar
.width
> cur
.x
+ cur
.width
)
833 InsertBefore( bar
.mpNext
, pTheBar
, row
);
837 // otherwise the bar lies within the bounds of current bar
839 int leftDist
= theBar
.x
- cur
.x
;
840 int rightDist
= cur
.x
+ cur
.width
- (theBar
.x
+ theBar
.width
);
842 if ( leftDist
< rightDist
)
844 InsertBefore( &bar
, pTheBar
, row
);
846 InsertBefore( bar
.mpNext
, pTheBar
, row
);
852 InsertBefore( NULL
, pTheBar
, row
); // insert at the end
857 void cbRowLayoutPlugin::OnInsertBar( cbInsertBarEvent
& event
)
859 cbBarInfo
* pBarToInsert
= event
.mpBar
;
860 cbRowInfo
* pIntoRow
= event
.mpRow
;
861 mpPane
= event
.mpPane
;
863 if ( !pBarToInsert
->IsFixed() )
865 AdjustLengthOfInserted( pIntoRow
, pBarToInsert
);
867 DoInsertBar( pBarToInsert
, *pIntoRow
);
869 mpPane
->InitLinksForRow( pIntoRow
); // relink "mpNext/mpPrev"s
871 // perform relayouting of the bars after insertion
873 // init bar location info
874 pBarToInsert
->mAlignment
= event
.mpPane
->mAlignment
;
875 pBarToInsert
->mRowNo
= event
.mpPane
->GetRowIndex( pIntoRow
);
877 #ifdef __EXPERIMENTAL
879 if ( !pIntoRow
->mHasOnlyFixedBars
|| !pBarToInsert
->IsFixed() )
881 RecalcLengthRatios( pIntoRow
);
885 MinimzeNotFixedBars( pIntoRow
, pBarToInsert
);
887 SlideLeftSideBars ( pBarToInsert
);
888 SlideRightSideBars( pBarToInsert
);
890 ShiftLeftTrashold ( pBarToInsert
, *pIntoRow
);
891 ShiftRightTrashold( pBarToInsert
, *pIntoRow
);
893 mpPane
->SyncRowFlags( pIntoRow
);
895 CheckIfAtTheBoundary( pBarToInsert
, *pIntoRow
);
897 if ( event
.mpPane
->IsHorizontal() )
899 pBarToInsert
->mState
= wxCBAR_DOCKED_HORIZONTALLY
;
901 pBarToInsert
->mState
= wxCBAR_DOCKED_VERTICALLY
;
903 if ( !pIntoRow
->mHasOnlyFixedBars
)
906 #ifdef __EXPERIMENTAL
908 ExpandNotFixedBars( pIntoRow
);
911 RelayoutNotFixedBarsAround( pBarToInsert
, pIntoRow
);
912 RecalcLengthRatios( pIntoRow
);
916 DetectBarHandles( pIntoRow
);
918 // do proportional resizing of not-fixed bars
919 ApplyLengthRatios( pIntoRow
);
922 // adjust the bar's docking state
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
929 if ( !pBarToInsert
->IsFixed() )
931 cbBarInfo
& bar
= *pBarToInsert
;
933 bar
.mDimInfo
.mSizes
[ bar
.mState
].x
= bar
.mBounds
.width
;
934 bar
.mDimInfo
.mSizes
[ bar
.mState
].y
= bar
.mBounds
.height
;
938 void cbRowLayoutPlugin::OnRemoveBar ( cbRemoveBarEvent
& event
)
940 cbBarInfo
* pBar
= event
.mpBar
;
941 mpPane
= event
.mpPane
;
943 cbRowInfo
* pRow
= pBar
->mpRow
;
945 mpLayout
->GetUpdatesManager().OnBarWillChange( pBar
, pRow
, event
.mpPane
);
947 // invalidate the whole row
948 //pFirst->mpRowInfo->mMgrData.mPrevBounds.x = -1;
950 pRow
->mBars
.Remove( pBar
);
952 // rest bar information after removing it from the row
954 pBar
->mHasLeftHandle
= FALSE
;
955 pBar
->mHasRightHandle
= FALSE
;
957 mpPane
->InitLinksForRow( pRow
); // relink "mpNext/mpPrev"s
959 if ( pRow
->mBars
.Count() == 0 )
961 // empty rows should not exist
963 event
.mpPane
->GetRowList().Remove( pRow
);
967 mpPane
->InitLinksForRows();
971 // force repainting of bars, in the row, from which the bar was removed
973 // FIXME:: really needed?
974 pRow
->mBars
[0]->mUMgrData
.SetDirty(TRUE
);
976 // re-setup mHasOnlyFixedBars flag for the row information
977 event
.mpPane
->SyncRowFlags( pRow
);
979 DetectBarHandles( pRow
);
981 if ( !pRow
->mHasOnlyFixedBars
)
983 ExpandNotFixedBars( pRow
);
987 void cbRowLayoutPlugin::OnLayoutRow( cbLayoutRowEvent
& event
)
989 cbRowInfo
* pRow
= event
.mpRow
;
990 mpPane
= event
.mpPane
;
992 MinimzeNotFixedBars( pRow
, NULL
);
994 if ( !pRow
->mHasOnlyFixedBars
)
996 // do proportional resizing of not-fixed bars
997 ApplyLengthRatios( pRow
);
1000 cbBarInfo
& lastBar
= *pRow
->mBars
[ pRow
->mBars
.Count() - 1 ];
1001 cbBarInfo
& firstBar
= *pRow
->mBars
[ 0 ];
1003 // FIXME:: Next line not used
1004 // wxRect& bounds = lastBar.mBounds;
1006 if ( lastBar
.mBounds
.x
+ lastBar
.mBounds
.width
> mpPane
->mPaneWidth
)
1008 lastBar
.mBounds
.x
= mpPane
->mPaneWidth
- lastBar
.mBounds
.width
;
1010 // first simulate left-row-edge friction
1012 SlideLeftSideBars( &lastBar
);
1014 if ( firstBar
.mBounds
.x
< 0 )
1015 firstBar
.mBounds
.x
= 0;
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"
1022 SlideRightSideBars( &firstBar
);
1025 event
.Skip(); // pass event to the next handler
1028 void cbRowLayoutPlugin::OnLayoutRows( cbLayoutRowsEvent
& event
)
1030 mpPane
= event
.mpPane
;
1034 // FIXME:: Next line not used.
1035 // RowArrayT& arr = mpPane->GetRowList();
1038 for ( i
= 0; i
!= mpPane
->GetRowList().Count(); ++i
)
1040 cbRowInfo
& row
= *mpPane
->GetRowList()[ i
];
1041 //mpPane->CalcLengthRatios(& row);
1043 // setup "has-handle" flags for rows, which depend on the existance
1044 // of not-fixed bars in the row
1046 if ( !row
.mHasOnlyFixedBars
)
1048 if ( mpPane
->mAlignment
== FL_ALIGN_TOP
||
1049 mpPane
->mAlignment
== FL_ALIGN_LEFT
)
1051 row
.mHasLowerHandle
= TRUE
;
1053 row
.mHasUpperHandle
= FALSE
;
1057 row
.mHasUpperHandle
= TRUE
;
1059 row
.mHasLowerHandle
= FALSE
;
1064 // otherwise, rows with fixed-bars only, have no height-resizing handles
1065 row
.mHasUpperHandle
= FALSE
;
1066 row
.mHasLowerHandle
= FALSE
;
1069 // setup vertical positions for items in the row
1073 row
.mRowWidth
= mpPane
->mPaneWidth
;
1074 row
.mRowHeight
= CalcRowHeight( row
);
1076 LayoutItemsVertically( row
);
1078 if ( row
.mHasUpperHandle
)
1079 row
.mRowHeight
+= mpPane
->mProps
.mResizeHandleSize
;
1080 if ( row
.mHasLowerHandle
)
1081 row
.mRowHeight
+= mpPane
->mProps
.mResizeHandleSize
;
1083 curY
+= row
.mRowHeight
;
1086 event
.Skip(); // pass event to the next handler - other hookeds plugin
1087 // may also add some "refinements" to the layout now
1090 void cbRowLayoutPlugin::OnResizeRow( cbResizeRowEvent
& event
)
1092 // extract resize-event info
1093 int ofs
= event
.mHandleOfs
;
1094 bool forUpperHandle
= event
.mForUpperHandle
;
1095 cbRowInfo
* pTheRow
= event
.mpRow
;
1096 mpPane
= event
.mpPane
;
1098 // FIXME:: Next line not used.
1099 //int newHeight = pTheRow->mRowHeight;
1103 if ( forUpperHandle
)
1105 // calculate available free space from above,
1106 // which can be obtained by squeezing not-fixed height rows
1108 cbRowInfo
* pRow
= pTheRow
->mpPrev
;
1112 freeSpc
+= pRow
->mRowHeight
- event
.mpPane
->GetMinimalRowHeight( pRow
);
1114 pRow
= pRow
->mpPrev
;
1119 // calculate available free space from below,
1120 // which can be obtained by squeezing not-fixed height rows
1122 cbRowInfo
* pRow
= pTheRow
->mpNext
;
1126 freeSpc
+= pRow
->mRowHeight
- mpPane
->GetMinimalRowHeight( pRow
);
1128 pRow
= pRow
->mpNext
;
1132 mpLayout
->GetUpdatesManager().OnStartChanges();
1136 // allow user adjusting pane vs. client-area space, for upper-handle
1138 if ( mpPane
->IsHorizontal() )
1140 clientSize
= mpLayout
->GetClientHeight();
1142 clientSize
= mpLayout
->GetClientWidth();
1144 if ( forUpperHandle
&& ofs
< -clientSize
)
1146 int needed
= -(ofs
+ clientSize
);
1148 cbRowInfo
* pRow
= mpPane
->GetRowList()[ 0 ];
1150 // start squeezing rows from the top row towards bottom
1152 while( pRow
!= pTheRow
&& needed
)
1154 // only not-fixed rows can be squeezed
1156 if ( !pRow
->mHasOnlyFixedBars
)
1158 int prevHeight
= pRow
->mRowHeight
;
1160 int newHeight
= wxMax( event
.mpPane
->GetMinimalRowHeight( pRow
),
1161 prevHeight
- needed
);
1163 if ( newHeight
!= prevHeight
)
1165 event
.mpPane
->SetRowHeight( pRow
, newHeight
);
1167 needed
-= prevHeight
- pRow
->mRowHeight
;
1171 pRow
= pRow
->mpNext
;
1175 // allow user adjusting pane vs. client-area space, for lower-handle
1177 if ( !forUpperHandle
&& ofs
> clientSize
)
1179 int needed
= ofs
- clientSize
;
1181 cbRowInfo
* pRow
= mpPane
->GetRowList()[ mpPane
->GetRowList().Count() - 1 ];
1183 // start squeezing rows from the bottom towards the top row
1185 while( pRow
&& needed
)
1187 // only not-fixed rows can be squeezed
1189 if ( !pRow
->mHasOnlyFixedBars
)
1191 int prevHeight
= pRow
->mRowHeight
;
1193 int newHeight
= wxMax( event
.mpPane
->GetMinimalRowHeight( pRow
),
1194 prevHeight
- needed
);
1196 if ( newHeight
!= prevHeight
)
1198 event
.mpPane
->SetRowHeight( pRow
, newHeight
);
1200 needed
-= prevHeight
- pRow
->mRowHeight
;
1204 pRow
= pRow
->mpPrev
;
1208 if ( forUpperHandle
)
1210 event
.mpPane
->SetRowHeight( pTheRow
, pTheRow
->mRowHeight
+ (-ofs
) );
1212 event
.mpPane
->SetRowHeight( pTheRow
, pTheRow
->mRowHeight
+ ofs
);
1214 mpLayout
->RecalcLayout(FALSE
);
1216 mpLayout
->GetUpdatesManager().OnFinishChanges();
1217 mpLayout
->GetUpdatesManager().UpdateNow();