1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "rowlayoutpl.h"
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
28 #include "rowlayoutpl.h"
30 // exerimental "features" are still buggy
33 /***** Implementaiton for class cbRowLayoutPlugin *****/
35 IMPLEMENT_DYNAMIC_CLASS( cbRowLayoutPlugin
, cbPluginBase
)
37 BEGIN_EVENT_TABLE( cbRowLayoutPlugin
, cbPluginBase
)
39 EVT_PL_LAYOUT_ROW ( cbRowLayoutPlugin::OnLayoutRow
)
40 EVT_PL_LAYOUT_ROWS( cbRowLayoutPlugin::OnLayoutRows
)
41 EVT_PL_RESIZE_ROW ( cbRowLayoutPlugin::OnResizeRow
)
43 EVT_PL_INSERT_BAR ( cbRowLayoutPlugin::OnInsertBar
)
44 EVT_PL_REMOVE_BAR ( cbRowLayoutPlugin::OnRemoveBar
)
48 cbRowLayoutPlugin::cbRowLayoutPlugin(void)
52 cbRowLayoutPlugin::cbRowLayoutPlugin( wxFrameLayout
* pPanel
, int paneMask
)
54 : cbPluginBase( pPanel
, paneMask
),
58 void cbRowLayoutPlugin::CheckIfAtTheBoundary( cbBarInfo
* pTheBar
, cbRowInfo
& rowInfo
)
60 // this method handles situation, when fixed bar is inserted
61 // into the row, where among fixed bars not-fixed ones are present.
62 // In this case we need to check if the pBarNode appears to be inserted
63 // chain of fixed-bars on the very right or left side of the row,
64 // then all the white-space, such chain should be eliminated,
65 // and the resulting chain justified to the right or the left
68 if ( !pTheBar
->IsFixed() || rowInfo
.mHasOnlyFixedBars
)
72 cbBarInfo
* pBar
= rowInfo
.mBars
[ rowInfo
.mBars
.Count() - 1 ];
74 // slide fixed bars to the right on the right side relative to the pBarNode
76 int prevX
= mpPane
->mPaneWidth
;
80 if ( !pBar
->IsFixed() )
83 wxRect
& bounds
= pBar
->mBounds
;
85 bounds
.x
= prevX
- bounds
.width
;
89 if ( pBar
== pTheBar
) break;
95 // slide fixed bars to the left on the left side relative to the pBarNode
97 pBar
= rowInfo
.mBars
[0];
103 if ( pBar
->IsFixed() )
107 wxRect
& bounds
= pBar
->mBounds
;
111 prevX
= bounds
.x
+ bounds
.width
;
113 if ( pBar
== pTheBar
) break;
120 void cbRowLayoutPlugin::ExpandNotFixedBars( cbRowInfo
* pRow
)
122 ApplyLenghtRatios( pRow
);
124 // FIXME:: something's wrong?
127 double freeSpc
= (double)GetRowFreeSpace( pRow
);
129 // calculate sum of precents
131 double pcntSum
= 0.0;
135 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
137 if ( !pRow
->mBars
[i
]->IsFixed() )
139 pcntSum
+= pRow
->mBars
[i
]->mLenRatio
;
145 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
147 cbBarInfo
& bar
= *pRow
->mBars
[i
];
149 if ( !bar
.IsFixed() )
151 bar
.mLenRatio
= bar
.mLenRatio
/(pcntSum
);
155 wxMax( mpPane
->mProps
.mMinCBarDim
.x
, int( freeSpc
*bar
.mLenRatio
) );
158 bar
.mBounds
.x
= curX
;
159 curX
= bar
.mBounds
.x
+ bar
.mBounds
.width
;
163 void cbRowLayoutPlugin::AdjustLenghtOfInserted( cbRowInfo
* pRow
, cbBarInfo
* pTheBar
)
167 // pTheBar is not-fixed
170 // FIXME:: what is this for??
176 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
178 if( !pRow
->mBars
[i
]->IsFixed() )
180 totalLen
+= pRow
->mBars
[i
]->mBounds
.width
;
182 double curWidth
= pTheBar
->mBounds
.width
;
184 if ( pRow
->mBars
.Count() )
186 pTheBar
->mBounds
.width
= int( mpPane
->mPaneWidth
* (curWidth
/ double(totalLen
)) );
190 double freeSpc
= (double)GetRowFreeSpace( pRow
);
192 double pcntSum
= 0.0;
194 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
196 if( !pRow
->mBars
[i
]->IsFixed() )
198 pcntSum
+= pRow
->mBars
[i
]->mLenRatio
;
200 // if no longer "balanced", assume that `pTheBar' was previousely
201 // removed from this row (kind of AI...)
203 if ( pcntSum
< 0.98 )
205 pTheBar
->mBounds
.width
= freeSpc
* (1.0 - pcntSum
);
209 void cbRowLayoutPlugin::FitBarsToRange( int from
, int till
,
210 cbBarInfo
* pTheBar
, cbRowInfo
* pRow
)
212 cbBarInfo
* pFromBar
= NULL
;
213 cbBarInfo
* pTillBar
= NULL
;
215 if ( pTheBar
->mBounds
.x
> from
)
217 // it's range from the left
218 pFromBar
= pRow
->mBars
[0];
223 pFromBar
= pTheBar
->mpNext
;
227 // calc free space in the range
229 cbBarInfo
* pBar
= pFromBar
;
230 int freeSpc
= till
-from
;
233 while( pBar
!= pTillBar
)
235 if ( pBar
->IsFixed() )
237 freeSpc
-= pBar
->mBounds
.width
;
239 pcntSum
+= pBar
->mLenRatio
;
244 // adjust not-fixed bar sizes in the range
248 while( pBar
!= pTillBar
)
250 if ( !pBar
->IsFixed() )
252 pBar
->mBounds
.width
=
254 wxMax( mpPane
->mProps
.mMinCBarDim
.x
,
255 int( double(freeSpc
) * (pBar
->mLenRatio
/pcntSum
) )
261 // layout range, starting from the left-most bar
265 bool hasNotFixedBars
= FALSE
;
267 while ( pBar
!= pTillBar
)
269 wxRect
& bounds
= pBar
->mBounds
;
271 if ( !pBar
->IsFixed() )
273 hasNotFixedBars
= TRUE
;
275 freeSpc
-= bounds
.width
;
280 prevX
= bounds
.x
+ bounds
.width
;
285 // make width adjustment for the right-most bar in the range, due to
286 // lost precision when seting widths using f.p. length-ratios
288 if ( hasNotFixedBars
)
290 if ( pTheBar
->mBounds
.x
> from
)
292 if ( pTillBar
->mpPrev
)
294 wxRect
& tillBar
= pTillBar
->mpPrev
->mBounds
;
296 //tillBar.width = bar.mBounds.x - tillBar.x;
297 tillBar
.width
+= freeSpc
;
302 cbBarInfo
* pLast
= pRow
->mBars
[ pRow
->mBars
.Count() - 1 ];
304 if ( pLast
!= pTheBar
)
306 pTheBar
->mBounds
.width
+= freeSpc
;
308 SlideRightSideBars( pTheBar
);
314 void cbRowLayoutPlugin::MinimzeNotFixedBars( cbRowInfo
* pRow
, cbBarInfo
* pBarToPreserve
)
316 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
318 if ( !pRow
->mBars
[i
]->IsFixed() && pRow
->mBars
[i
] != pBarToPreserve
)
320 pRow
->mBars
[i
]->mBounds
.width
= mpPane
->mProps
.mMinCBarDim
.x
;
323 int cbRowLayoutPlugin::GetRowFreeSpace( cbRowInfo
* pRow
)
326 int freeSpc
= mpPane
->mPaneWidth
;
328 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
330 // not-fixed bars variable length, thus their
331 // dimensions are ignored
333 if ( pRow
->mBars
[i
]->IsFixed() )
335 freeSpc
-= pRow
->mBars
[i
]->mBounds
.width
;
340 void cbRowLayoutPlugin::RecalcLenghtRatios( cbRowInfo
* pRow
)
342 double freeSpc
= double( GetRowFreeSpace( pRow
) );
344 cbBarInfo
* pBar
= pRow
->mBars
[0];
345 cbBarInfo
* pLastNotFixed
= NULL
;
347 double pcntLeft
= 1.0; // (100%)
349 #ifdef __EXPERIMENTAL
353 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
355 if ( !pRow
->mBars
[i
]->IsFixed() )
357 totalLen
+= pRow
->mBars
[i
]->mBounds
.width
;
360 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
362 cbBarInfo
& bar
= *pRow
->mBars
[i
];
364 if ( !bar
.IsFixed() )
367 #ifdef __EXPERIMENTAL
369 bar
.mLenRatio
= double(bar
.mBounds
.width
)/double(totalLen
);
371 bar
.mLenRatio
= double(bar
.mBounds
.width
)/freeSpc
;
374 pcntLeft
-= bar
.mLenRatio
;
375 pLastNotFixed
= pBar
;
379 // attach remainder (the result of lost precision) to the
380 // last not-fixed bar
382 #if !defined(__EXPERIMENTAL)
386 pLastNotFixed
->mLenRatio
+= pcntLeft
;
391 void cbRowLayoutPlugin::ApplyLenghtRatios( cbRowInfo
* pRow
)
395 // FOR NOW:: all-in-one
399 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
401 if ( !pRow
->mBars
[i
]->IsFixed() )
403 pcntSum
+= pRow
->mBars
[i
]->mLenRatio
;
406 pBar = node_to_first_bar_node( pRow );
410 cbBarInfo& bar = node_to_bar( pBar );
412 if ( !bar.IsFixed() )
414 bar.mLenRatio = pcntSum / bar.mLenRatio;
421 double freeSpc
= GetRowFreeSpace( pRow
);
423 // tricky stuff (improtant!):
424 // when not-fixed bar is removed from the row and there are
425 // still some other not-fixed ones left in that row, then
426 // the sum of mLenRatio's is no longer 1.0 - this is left
427 // intintionally to handle the case when the removed bar
428 // is returned right back to the row - so that it would retain
429 // it's original dimensions in this row (this is kind of AI...)
431 // The problem is - when it's remvoed, the sum of
432 // mLenRatio's is not in "balance", i.e. is < 1.0,
433 // it's possible to restore balance, but instead of that
434 // we artifically ajdust freeSpc value in a way that it would
435 // look like total of mLetRatio's is 1.0, thus original
436 // len. ratios are _preserved_:
438 double unit
= freeSpc
/ pcntSum
;
440 bool haveSquished
= FALSE
;
442 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
444 if ( !pRow
->mBars
[i
]->IsFixed() )
446 cbBarInfo
& bar
= *pRow
->mBars
[i
];
448 if ( int( unit
* bar
.mLenRatio
) < mpPane
->mProps
.mMinCBarDim
.x
)
452 bar
.mBounds
.width
= -1; // mark as "squished"
454 pcntSum
-= bar
.mLenRatio
;
456 freeSpc
-= mpPane
->mProps
.mMinCBarDim
.x
;
462 unit
= freeSpc
/ pcntSum
;
464 for( i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
466 cbBarInfo
& bar
= *pRow
->mBars
[i
];
468 bar
.mBounds
.x
= prevX
;
470 if ( !bar
.IsFixed() )
472 if ( bar
.mBounds
.width
== -1 )
474 bar
.mBounds
.width
= mpPane
->mProps
.mMinCBarDim
.x
;
476 bar
.mBounds
.width
= int( unit
* bar
.mLenRatio
);
478 // a little bit of AI:
479 // memorize bar's height and width, when docked in
480 // the current orientation - by making the current
481 // dimensions to be "preffered" ones for this docking state
483 if ( !bar
.IsFixed() )
485 bar
.mDimInfo
.mSizes
[ bar
.mState
].x
= bar
.mBounds
.width
;
486 bar
.mDimInfo
.mSizes
[ bar
.mState
].y
= bar
.mBounds
.height
;
490 prevX
= bar
.mBounds
.x
+ bar
.mBounds
.width
;
494 void cbRowLayoutPlugin::DetectBarHandles( cbRowInfo
* pRow
)
496 // first pass from left to right (detect left-side handles)
498 bool foundNotFixed
= FALSE
;
500 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
502 cbBarInfo
& bar
= *pRow
->mBars
[i
];
504 bar
.mHasLeftHandle
= FALSE
;
506 if ( !bar
.IsFixed() )
511 bar
.mpPrev
->IsFixed() )
513 bar
.mHasLeftHandle
= TRUE
;
515 foundNotFixed
= TRUE
;
519 // pass from right to left (detect right-side handles)
521 foundNotFixed
= FALSE
;
523 cbBarInfo
* pBar
= pRow
->mBars
[ pRow
->mBars
.Count() - 1 ];
527 pBar
->mHasRightHandle
= FALSE
;
529 if ( !pBar
->IsFixed() )
535 pBar
->mHasRightHandle
= TRUE
;
537 foundNotFixed
= TRUE
;
544 void cbRowLayoutPlugin::RelayoutNotFixedBarsAround( cbBarInfo
* pTheBar
, cbRowInfo
* pRow
)
546 if ( !pTheBar
->mpPrev
)
548 if ( !pTheBar
->IsFixed() )
550 // this bar the first in the row, move it's
551 // left edge to the very left
552 pTheBar
->mBounds
.width
+= pTheBar
->mBounds
.x
;
553 pTheBar
->mBounds
.x
= 0;
557 FitBarsToRange( 0, pTheBar
->mBounds
.x
, pTheBar
, pRow
);
559 if ( !pTheBar
->mpNext
)
561 if ( !pTheBar
->IsFixed() )
563 // this bar is the last one, move it's
564 // right edge to the very right
566 pTheBar
->mBounds
.width
= mpPane
->mPaneWidth
- pTheBar
->mBounds
.x
;
570 FitBarsToRange( pTheBar
->mBounds
.x
+ pTheBar
->mBounds
.width
, mpPane
->mPaneWidth
,
575 void cbRowLayoutPlugin::LayoutItemsVertically( cbRowInfo
& row
)
577 for( size_t i
= 0; i
!= row
.mBars
.Count(); ++i
)
579 cbBarInfo
& bar
= *row
.mBars
[i
];
581 bar
.mBounds
.y
= row
.mRowY
;
583 if ( !bar
.IsFixed() )
585 // make all not-fixed bars of equal height
586 bar
.mBounds
.height
= row
.mRowHeight
;
588 if ( row
.mHasUpperHandle
)
590 bar
.mBounds
.y
+= mpPane
->mProps
.mResizeHandleSize
;
594 int cbRowLayoutPlugin::CalcRowHeight( cbRowInfo
& row
)
598 for( size_t i
= 0; i
!= row
.mBars
.Count(); ++i
)
600 maxHeight
= wxMax( maxHeight
, row
.mBars
[i
]->mBounds
.height
);
605 void cbRowLayoutPlugin::StickRightSideBars( cbBarInfo
* pToBar
)
607 cbBarInfo
* pBar
= pToBar
->mpNext
;
608 cbBarInfo
* pPrev
= pToBar
;
612 wxRect
& cur
= pBar
->mBounds
;
613 wxRect
& prev
= pPrev
->mBounds
;
615 cur
.x
= prev
.x
+ prev
.width
;
622 void cbRowLayoutPlugin::SlideLeftSideBars( cbBarInfo
* pTheBar
)
624 // shift left-side-bars to the left (with respect to "theBar"),
625 // so that they would not obscured by each other
627 cbBarInfo
* pBar
= pTheBar
->mpPrev
;
628 cbBarInfo
* pPrev
= pTheBar
;
632 wxRect
& cur
= pBar
->mBounds
;
633 wxRect
& prev
= pPrev
->mBounds
;
635 if ( cur
.x
+ cur
.width
> prev
.x
)
637 cur
.x
= prev
.x
- cur
.width
;
644 void cbRowLayoutPlugin::SlideRightSideBars( cbBarInfo
* pTheBar
)
646 // shift right-side-bars to the right (with respect to "theBar"),
647 // so that they would not be obscured by each other
649 cbBarInfo
* pBar
= pTheBar
->mpNext
;
650 cbBarInfo
* pPrev
= pTheBar
;
654 wxRect
& cur
= pBar
->mBounds
;
655 wxRect
& prev
= pPrev
->mBounds
;
657 if ( cur
.x
< prev
.x
+ prev
.width
)
659 cur
.x
= prev
.x
+ prev
.width
;
666 void cbRowLayoutPlugin::ShiftLeftTrashold( cbBarInfo
* pTheBar
, cbRowInfo
& row
)
668 wxRect
& first
= row
.mBars
[0]->mBounds
;
672 row
.mBars
[0]->mBounds
.x
= 0;
674 SlideRightSideBars( row
.mBars
[0] );
678 void cbRowLayoutPlugin::ShiftRightTrashold( cbBarInfo
* pTheBar
, cbRowInfo
& row
)
680 wxRect
& theBar
= pTheBar
->mBounds
;
684 cbBarInfo
* pBar
= pTheBar
;
686 // calculate free spece on the left side
692 wxRect
& cur
= pBar
->mBounds
;
696 wxRect
& prev
= pBar
->mpPrev
->mBounds
;
698 leftFreeSpc
+= cur
.x
- prev
.x
- prev
.width
;
701 leftFreeSpc
+= cur
.x
;
714 int rightOverflow
= 0;
716 if ( pTheBar
->IsFixed() )
722 wxRect
& cur
= pBar
->mBounds
;
724 if ( cur
.x
+ cur
.width
> mpPane
->mPaneWidth
)
726 rightOverflow
= cur
.x
+ cur
.width
- mpPane
->mPaneWidth
;
732 if ( rightOverflow
> 0 )
734 if ( leftFreeSpc
<= 0 ) return;
736 if ( pTheBar
->mpNext
)
738 wxRect
& next
= pTheBar
->mpNext
->mBounds
;
740 // if there's enough space on the left, move over one half-obscured
741 // bar from the right to the left side with respect to "theBar"
743 if ( next
.width
< leftFreeSpc
)
745 cbBarInfo
* pNext
= pTheBar
->mpNext
;
747 row
.mBars
.Remove( pNext
);
749 row
.mBars
.Insert( pNext
, row
.mBars
.Index( pTheBar
) );
751 next
.x
= theBar
.x
- next
.width
;
753 // re-setup mpPrev/mpNext references after insertion
755 mpPane
->InitLinksForRow( &row
);
759 StickRightSideBars( pTheBar
);
760 SlideLeftSideBars ( pTheBar
);
766 int leftShift
= ( rightOverflow
> leftFreeSpc
)
770 theBar
.x
-= leftShift
;
772 StickRightSideBars( pTheBar
);
773 SlideLeftSideBars ( pTheBar
);
777 } // end of if ( rightOverflow )
784 void cbRowLayoutPlugin::InsertBefore( cbBarInfo
* pBeforeBar
,
790 row
.mBars
.Insert( pTheBar
, row
.mBars
.Index( pBeforeBar
) );
792 row
.mBars
.Add( pTheBar
);
794 pTheBar
->mpRow
= &row
;
797 void cbRowLayoutPlugin::DoInsertBar( cbBarInfo
* pTheBar
, cbRowInfo
& row
)
799 wxRect
& theBar
= pTheBar
->mBounds
;
802 if ( theBar.x < 0 && !node_to_bar( pTheBar ).IsFixed() )
805 theBar.width += theBar.x;
809 for( size_t i
= 0; i
!= row
.mBars
.Count(); ++i
)
811 cbBarInfo
& bar
= *row
.mBars
[i
];
813 wxRect
& cur
= bar
.mBounds
;
815 // if bar hits the left edge
816 if ( theBar
.x
<= cur
.x
)
818 InsertBefore( &bar
, pTheBar
, row
);
823 // if bar hits the right edge
824 if ( theBar
.x
<= cur
.x
+ cur
.width
)
826 if ( theBar
.x
+ theBar
.width
> cur
.x
+ cur
.width
)
828 InsertBefore( bar
.mpNext
, pTheBar
, row
);
832 // otherwise the bar lies within the bounds of current bar
834 int leftDist
= theBar
.x
- cur
.x
;
835 int rightDist
= cur
.x
+ cur
.width
- (theBar
.x
+ theBar
.width
);
837 if ( leftDist
< rightDist
)
839 InsertBefore( &bar
, pTheBar
, row
);
841 InsertBefore( bar
.mpNext
, pTheBar
, row
);
847 InsertBefore( NULL
, pTheBar
, row
); // insert at the end
852 void cbRowLayoutPlugin::OnInsertBar( cbInsertBarEvent
& event
)
854 cbBarInfo
* pBarToInsert
= event
.mpBar
;
855 cbRowInfo
* pIntoRow
= event
.mpRow
;
856 mpPane
= event
.mpPane
;
858 if ( !pBarToInsert
->IsFixed() )
860 AdjustLenghtOfInserted( pIntoRow
, pBarToInsert
);
862 DoInsertBar( pBarToInsert
, *pIntoRow
);
864 mpPane
->InitLinksForRow( pIntoRow
); // relink "mpNext/mpPrev"s
866 // perform relayouting of the bars after insertion
868 // init bar location info
869 pBarToInsert
->mAlignment
= event
.mpPane
->mAlignment
;
870 pBarToInsert
->mRowNo
= event
.mpPane
->GetRowIndex( pIntoRow
);
872 #ifdef __EXPERIMENTAL
874 if ( !pIntoRow
->mHasOnlyFixedBars
|| !pBarToInsert
->IsFixed() )
876 RecalcLenghtRatios( pIntoRow
);
880 MinimzeNotFixedBars( pIntoRow
, pBarToInsert
);
882 SlideLeftSideBars ( pBarToInsert
);
883 SlideRightSideBars( pBarToInsert
);
885 ShiftLeftTrashold ( pBarToInsert
, *pIntoRow
);
886 ShiftRightTrashold( pBarToInsert
, *pIntoRow
);
888 mpPane
->SyncRowFlags( pIntoRow
);
890 CheckIfAtTheBoundary( pBarToInsert
, *pIntoRow
);
892 if ( event
.mpPane
->IsHorizontal() )
894 pBarToInsert
->mState
= wxCBAR_DOCKED_HORIZONTALLY
;
896 pBarToInsert
->mState
= wxCBAR_DOCKED_VERTICALLY
;
898 if ( !pIntoRow
->mHasOnlyFixedBars
)
901 #ifdef __EXPERIMENTAL
903 ExpandNotFixedBars( pIntoRow
);
906 RelayoutNotFixedBarsAround( pBarToInsert
, pIntoRow
);
907 RecalcLenghtRatios( pIntoRow
);
911 DetectBarHandles( pIntoRow
);
913 // do proportional resizing of not-fixed bars
914 ApplyLenghtRatios( pIntoRow
);
917 // adjust the bar's docking state
919 // a little bit of AI:
920 // memorize bar's height and width, when docked in
921 // the current orientation - by making the current
922 // dimensions to be "preferred" ones for this docking state
924 if ( !pBarToInsert
->IsFixed() )
926 cbBarInfo
& bar
= *pBarToInsert
;
928 bar
.mDimInfo
.mSizes
[ bar
.mState
].x
= bar
.mBounds
.width
;
929 bar
.mDimInfo
.mSizes
[ bar
.mState
].y
= bar
.mBounds
.height
;
933 void cbRowLayoutPlugin::OnRemoveBar ( cbRemoveBarEvent
& event
)
935 cbBarInfo
* pBar
= event
.mpBar
;
936 mpPane
= event
.mpPane
;
938 cbRowInfo
* pRow
= pBar
->mpRow
;
940 mpLayout
->GetUpdatesManager().OnBarWillChange( pBar
, pRow
, event
.mpPane
);
942 // invalidate the whole row
943 //pFirst->mpRowInfo->mMgrData.mPrevBounds.x = -1;
945 pRow
->mBars
.Remove( pBar
);
947 // rest bar information after removing it from the row
949 pBar
->mHasLeftHandle
= FALSE
;
950 pBar
->mHasRightHandle
= FALSE
;
952 mpPane
->InitLinksForRow( pRow
); // relink "mpNext/mpPrev"s
954 if ( pRow
->mBars
.Count() == 0 )
956 // empty rows should not exist
958 event
.mpPane
->GetRowList().Remove( pRow
);
962 mpPane
->InitLinksForRows();
966 // force repainting of bars, in the row, from which the bar was removed
968 // FIXME:: really needed?
969 pRow
->mBars
[0]->mUMgrData
.SetDirty(TRUE
);
971 // re-setup mHasOnlyFixedBars flag for the row information
972 event
.mpPane
->SyncRowFlags( pRow
);
974 DetectBarHandles( pRow
);
976 if ( !pRow
->mHasOnlyFixedBars
)
978 ExpandNotFixedBars( pRow
);
982 void cbRowLayoutPlugin::OnLayoutRow( cbLayoutRowEvent
& event
)
984 cbRowInfo
* pRow
= event
.mpRow
;
985 mpPane
= event
.mpPane
;
987 MinimzeNotFixedBars( pRow
, NULL
);
989 if ( !pRow
->mHasOnlyFixedBars
)
991 // do proportional resizing of not-fixed bars
993 ApplyLenghtRatios( pRow
);
995 cbBarInfo
& lastBar
= *pRow
->mBars
[ pRow
->mBars
.Count() - 1 ];
996 cbBarInfo
& firstBar
= *pRow
->mBars
[ 0 ];
998 wxRect
& bounds
= lastBar
.mBounds
;
1000 if ( lastBar
.mBounds
.x
+ lastBar
.mBounds
.width
> mpPane
->mPaneWidth
)
1002 lastBar
.mBounds
.x
= mpPane
->mPaneWidth
- lastBar
.mBounds
.width
;
1004 // first simulate left-row-edge friction
1006 SlideLeftSideBars( &lastBar
);
1008 if ( firstBar
.mBounds
.x
< 0 ) firstBar
.mBounds
.x
= 0;
1010 // then left-row-edge firciton,though this
1011 // may cause some of the right-side bars going
1012 // out of row bounds, but-left side always
1013 // has the highest "priority"
1015 SlideRightSideBars( &firstBar
);
1018 event
.Skip(); // pass event to the next handler
1021 void cbRowLayoutPlugin::OnLayoutRows( cbLayoutRowsEvent
& event
)
1023 mpPane
= event
.mpPane
;
1027 RowArrayT
& arr
= mpPane
->GetRowList();
1029 for( size_t i
= 0; i
!= mpPane
->GetRowList().Count(); ++i
)
1031 cbRowInfo
& row
= *mpPane
->GetRowList()[ i
];
1033 // setup "has-handle" flags for rows, which depend on the existance
1034 // of not-fixed bars in the row
1036 if ( !row
.mHasOnlyFixedBars
)
1038 if ( mpPane
->mAlignment
== wxTOP
||
1039 mpPane
->mAlignment
== wxLEFT
)
1041 row
.mHasLowerHandle
= TRUE
;
1043 row
.mHasUpperHandle
= FALSE
;
1047 row
.mHasUpperHandle
= TRUE
;
1049 row
.mHasLowerHandle
= FALSE
;
1054 // otherwise, rows with fixed-bars only, have no height-resizing handles
1055 row
.mHasUpperHandle
= FALSE
;
1056 row
.mHasLowerHandle
= FALSE
;
1059 // setup vertical positions for items in the row
1063 row
.mRowWidth
= mpPane
->mPaneWidth
;
1064 row
.mRowHeight
= CalcRowHeight( row
);
1066 LayoutItemsVertically( row
);
1068 if ( row
.mHasUpperHandle
) row
.mRowHeight
+= mpPane
->mProps
.mResizeHandleSize
;
1069 if ( row
.mHasLowerHandle
) row
.mRowHeight
+= mpPane
->mProps
.mResizeHandleSize
;
1071 curY
+= row
.mRowHeight
;
1074 event
.Skip(); // pass event to the next handler - other hookeds plugin
1075 // may also add some "refinements" to the layout now
1078 void cbRowLayoutPlugin::OnResizeRow( cbResizeRowEvent
& event
)
1080 // extract resize-event info
1081 int ofs
= event
.mHandleOfs
;
1082 bool forUpperHandle
= event
.mForUpperHandle
;
1083 cbRowInfo
* pTheRow
= event
.mpRow
;
1084 mpPane
= event
.mpPane
;
1086 int newHeight
= pTheRow
->mRowHeight
;
1090 if ( forUpperHandle
)
1092 // calculate available free space from above,
1093 // which can be obtained by squeezing not-fixed height rows
1095 cbRowInfo
* pRow
= pTheRow
->mpPrev
;
1099 freeSpc
+= pRow
->mRowHeight
- event
.mpPane
->GetMinimalRowHeight( pRow
);
1101 pRow
= pRow
->mpPrev
;
1106 // calculate available free space from below,
1107 // which can be obtained by squeezing not-fixed height rows
1109 cbRowInfo
* pRow
= pTheRow
->mpNext
;
1113 freeSpc
+= pRow
->mRowHeight
- mpPane
->GetMinimalRowHeight( pRow
);
1115 pRow
= pRow
->mpNext
;
1119 mpLayout
->GetUpdatesManager().OnStartChanges();
1123 // allow user adjusting pane vs. client-area space, for upper-handle
1125 if ( mpPane
->IsHorizontal() )
1127 clientSize
= mpLayout
->GetClientHeight();
1129 clientSize
= mpLayout
->GetClientWidth();
1131 if ( forUpperHandle
&& ofs
< -clientSize
)
1133 int needed
= -(ofs
+ clientSize
);
1135 cbRowInfo
* pRow
= mpPane
->GetRowList()[ 0 ];
1137 // start squeezing rows from the top row towards bottom
1139 while( pRow
!= pTheRow
&& needed
)
1141 // only not-fixed rows can be squeezed
1143 if ( !pRow
->mHasOnlyFixedBars
)
1145 int prevHeight
= pRow
->mRowHeight
;
1147 int newHeight
= wxMax( event
.mpPane
->GetMinimalRowHeight( pRow
),
1148 prevHeight
- needed
);
1150 if ( newHeight
!= prevHeight
)
1152 event
.mpPane
->SetRowHeight( pRow
, newHeight
);
1154 needed
-= prevHeight
- pRow
->mRowHeight
;
1158 pRow
= pRow
->mpNext
;
1162 // allow user adjusting pane vs. client-area space, for lower-handle
1164 if ( !forUpperHandle
&& ofs
> clientSize
)
1166 int needed
= ofs
- clientSize
;
1168 cbRowInfo
* pRow
= mpPane
->GetRowList()[ mpPane
->GetRowList().Count() - 1 ];
1170 // start squeezing rows from the bottom towards the top row
1172 while( pRow
&& needed
)
1174 // only not-fixed rows can be squeezed
1176 if ( !pRow
->mHasOnlyFixedBars
)
1178 int prevHeight
= pRow
->mRowHeight
;
1180 int newHeight
= wxMax( event
.mpPane
->GetMinimalRowHeight( pRow
),
1181 prevHeight
- needed
);
1183 if ( newHeight
!= prevHeight
)
1185 event
.mpPane
->SetRowHeight( pRow
, newHeight
);
1187 needed
-= prevHeight
- pRow
->mRowHeight
;
1191 pRow
= pRow
->mpPrev
;
1195 if ( forUpperHandle
)
1197 event
.mpPane
->SetRowHeight( pTheRow
, pTheRow
->mRowHeight
+ (-ofs
) );
1199 event
.mpPane
->SetRowHeight( pTheRow
, pTheRow
->mRowHeight
+ ofs
);
1201 mpLayout
->RecalcLayout(FALSE
);
1203 mpLayout
->GetUpdatesManager().OnFinishChanges();
1204 mpLayout
->GetUpdatesManager().UpdateNow();