home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
wxos2240.zip
/
wxWindows-2.4.0
/
contrib
/
src
/
fl
/
rowlayoutpl.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2002-04-04
|
31KB
|
1,217 lines
/////////////////////////////////////////////////////////////////////////////
// Name: rowlayoutpl.cpp
// Purpose: cbRowLayoutPlugin implementation.
// Author: Aleksandras Gluchovas
// Modified by:
// Created: 09/09/98
// RCS-ID: $Id: rowlayoutpl.cpp,v 1.4 2002/04/04 21:05:14 JS Exp $
// Copyright: (c) Aleksandras Gluchovas
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation "rowlayoutpl.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/fl/rowlayoutpl.h"
// exerimental "features" are still buggy
#undef __EXPERIMENTAL
/***** Implementation for class cbRowLayoutPlugin *****/
IMPLEMENT_DYNAMIC_CLASS( cbRowLayoutPlugin, cbPluginBase )
BEGIN_EVENT_TABLE( cbRowLayoutPlugin, cbPluginBase )
EVT_PL_LAYOUT_ROW ( cbRowLayoutPlugin::OnLayoutRow )
EVT_PL_LAYOUT_ROWS( cbRowLayoutPlugin::OnLayoutRows )
EVT_PL_RESIZE_ROW ( cbRowLayoutPlugin::OnResizeRow )
EVT_PL_INSERT_BAR ( cbRowLayoutPlugin::OnInsertBar )
EVT_PL_REMOVE_BAR ( cbRowLayoutPlugin::OnRemoveBar )
END_EVENT_TABLE()
cbRowLayoutPlugin::cbRowLayoutPlugin(void)
: mpPane( 0 )
{}
cbRowLayoutPlugin::cbRowLayoutPlugin( wxFrameLayout* pPanel, int paneMask )
: cbPluginBase( pPanel, paneMask ),
mpPane( 0 )
{}
void cbRowLayoutPlugin::CheckIfAtTheBoundary( cbBarInfo* pTheBar, cbRowInfo& rowInfo )
{
// this method handles situation, when fixed bar is inserted
// into the row, where among fixed bars not-fixed ones are present.
// In this case we need to check if the pBarNode appears to be inserted
// chain of fixed-bars on the very right or left side of the row,
// then all the white-space, such chain should be eliminated,
// and the resulting chain justified to the right or the left
// side of the row
if ( !pTheBar->IsFixed() || rowInfo.mHasOnlyFixedBars )
return;
cbBarInfo* pBar = rowInfo.mBars[ rowInfo.mBars.Count() - 1 ];
// slide fixed bars to the right on the right side relative to the pBarNode
int prevX = mpPane->mPaneWidth;
do
{
if ( !pBar->IsFixed() )
break;
wxRect& bounds = pBar->mBounds;
bounds.x = prevX - bounds.width;
prevX = bounds.x;
if ( pBar == pTheBar ) break;
pBar = pBar->mpPrev;
}
while( 1 );
// slide fixed bars to the left on the left side relative to the pBarNode
pBar = rowInfo.mBars[0];
prevX = 0;
do
{
if ( pBar->IsFixed() )
break;
wxRect& bounds = pBar->mBounds;
bounds.x = prevX;
prevX = bounds.x + bounds.width;
if ( pBar == pTheBar ) break;
pBar = pBar->mpNext;
}
while( 1 );
}
void cbRowLayoutPlugin::ExpandNotFixedBars( cbRowInfo* pRow )
{
ApplyLengthRatios( pRow );
// FIXME:: something's wrong?
return;
double freeSpc = (double)GetRowFreeSpace( pRow );
// calculate sum of precents
double pcntSum = 0.0;
size_t i;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
if ( !pRow->mBars[i]->IsFixed() )
pcntSum += pRow->mBars[i]->mLenRatio;
}
// setup bar lengths
int curX = 0;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
cbBarInfo& bar = *pRow->mBars[i];
if ( !bar.IsFixed() )
{
bar.mLenRatio = bar.mLenRatio/(pcntSum);
bar.mBounds.width =
wxMax( mpPane->mProps.mMinCBarDim.x, int( freeSpc*bar.mLenRatio ) );
}
bar.mBounds.x = curX;
curX = bar.mBounds.x + bar.mBounds.width;
}
}
void cbRowLayoutPlugin::AdjustLengthOfInserted( cbRowInfo* pRow, cbBarInfo* pTheBar )
{
return; // TBD: Makes following code unreachable
// pTheBar is not-fixed
// FIXME:: what is this for??
#if 1
int totalLen = 0;
size_t i;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
if ( !pRow->mBars[i]->IsFixed() )
totalLen += pRow->mBars[i]->mBounds.width;
}
double curWidth = pTheBar->mBounds.width;
if ( pRow->mBars.Count() )
pTheBar->mBounds.width = int( mpPane->mPaneWidth * (curWidth / double(totalLen)) );
#else
double freeSpc = (double)GetRowFreeSpace( pRow );
double pcntSum = 0.0;
size_t i;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
if ( !pRow->mBars[i]->IsFixed() )
pcntSum += pRow->mBars[i]->mLenRatio;
}
// if no longer "balanced", assume that `pTheBar' was previously
// removed from this row (kind of AI...)
if ( pcntSum < 0.98 )
pTheBar->mBounds.width = freeSpc * (1.0 - pcntSum);
#endif
}
void cbRowLayoutPlugin::FitBarsToRange( int from, int till,
cbBarInfo* pTheBar, cbRowInfo* pRow )
{
cbBarInfo* pFromBar = NULL;
cbBarInfo* pTillBar = NULL;
if ( pTheBar->mBounds.x > from )
{
// it's range from the left
pFromBar = pRow->mBars[0];
pTillBar = pTheBar;
}
else
{
pFromBar = pTheBar->mpNext;
pTillBar = NULL;
}
// calc free space in the range
cbBarInfo* pBar = pFromBar;
int freeSpc = till-from;
double pcntSum = 0;
while( pBar != pTillBar )
{
if ( pBar->IsFixed() )
freeSpc -= pBar->mBounds.width;
else
pcntSum += pBar->mLenRatio;
pBar = pBar->mpNext;
}
// adjust not-fixed bar sizes in the range
pBar = pFromBar;
while ( pBar != pTillBar )
{
if ( !pBar->IsFixed() )
{
pBar->mBounds.width =
wxMax( mpPane->mProps.mMinCBarDim.x,
int( double(freeSpc) * (pBar->mLenRatio/pcntSum) )
);
}
pBar = pBar->mpNext;
}
// layout range, starting from the left-most bar
pBar = pFromBar;
int prevX = from;
bool hasNotFixedBars = FALSE;
while ( pBar != pTillBar )
{
wxRect& bounds = pBar->mBounds;
if ( !pBar->IsFixed() )
{
hasNotFixedBars = TRUE;
freeSpc -= bounds.width;
}
bounds.x = prevX;
prevX = bounds.x + bounds.width;
pBar = pBar->mpNext;
}
// make width adjustment for the right-most bar in the range, due to
// lost precision when seting widths using f.p. length-ratios
if ( hasNotFixedBars )
{
if ( pTheBar->mBounds.x > from )
{
if ( pTillBar->mpPrev )
{
wxRect& tillBar = pTillBar->mpPrev->mBounds;
//tillBar.width = bar.mBounds.x - tillBar.x;
tillBar.width += freeSpc;
}
}
else
{
cbBarInfo* pLast = pRow->mBars[ pRow->mBars.Count() - 1 ];
if ( pLast != pTheBar )
{
pTheBar->mBounds.width += freeSpc;
SlideRightSideBars( pTheBar );
}
}
}
}
void cbRowLayoutPlugin::MinimzeNotFixedBars( cbRowInfo* pRow, cbBarInfo* pBarToPreserve )
{
size_t i;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
if ( !pRow->mBars[i]->IsFixed() && pRow->mBars[i] != pBarToPreserve )
pRow->mBars[i]->mBounds.width = mpPane->mProps.mMinCBarDim.x;
}
}
int cbRowLayoutPlugin::GetRowFreeSpace( cbRowInfo* pRow )
{
int freeSpc = mpPane->mPaneWidth;
size_t i;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
// not-fixed bars variable length, thus their
// dimensions are ignored
if ( pRow->mBars[i]->IsFixed() )
freeSpc -= pRow->mBars[i]->mBounds.width;
}
return freeSpc;
}
void cbRowLayoutPlugin::RecalcLengthRatios( cbRowInfo* pRow )
{
double freeSpc = double( GetRowFreeSpace( pRow ) );
cbBarInfo* pBar = pRow->mBars[0];
cbBarInfo* pLastNotFixed = NULL;
double pcntLeft = 1.0; // (100%)
#ifdef __EXPERIMENTAL
int totalLen = 0;
size_t i;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
if ( !pRow->mBars[i]->IsFixed() )
totalLen += pRow->mBars[i]->mBounds.width;
}
#endif
size_t i;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
cbBarInfo& bar = *pRow->mBars[i];
if ( !bar.IsFixed() )
{
#ifdef __EXPERIMENTAL
bar.mLenRatio = double(bar.mBounds.width)/double(totalLen);
#else
bar.mLenRatio = double(bar.mBounds.width)/freeSpc;
#endif
pcntLeft -= bar.mLenRatio;
pLastNotFixed = pBar;
}
}
// attach remainder (the result of lost precision) to the
// last not-fixed bar
#if !defined(__EXPERIMENTAL)
if ( pLastNotFixed )
pLastNotFixed->mLenRatio += pcntLeft;
#endif
}
void cbRowLayoutPlugin::ApplyLengthRatios( cbRowInfo* pRow )
{
double pcntSum = 0;
// FOR NOW:: all-in-one
size_t i = 0;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
if ( !pRow->mBars[i]->IsFixed() )
pcntSum += pRow->mBars[i]->mLenRatio;
}
/*
pBar = node_to_first_bar_node( pRow );
while( pBar )
{
cbBarInfo& bar = node_to_bar( pBar );
if ( !bar.IsFixed() )
bar.mLenRatio = pcntSum / bar.mLenRatio;
pBar = pBar->Next();
}
*/
int prevX = 0;
double freeSpc = GetRowFreeSpace( pRow );
// tricky stuff (improtant!):
// when not-fixed bar is removed from the row and there are
// still some other not-fixed ones left in that row, then
// the sum of mLenRatio's is no longer 1.0 - this is left
// intintionally to handle the case when the removed bar
// is returned right back to the row - so that it would retain
// it's original dimensions in this row (this is kind of AI...)
//
// The problem is - when it's remvoed, the sum of
// mLenRatio's is not in "balance", i.e. is < 1.0,
// it's possible to restore balance, but instead of that
// we artifically ajdust freeSpc value in a way that it would
// look like total of mLetRatio's is 1.0, thus original
// len. ratios are _preserved_:
double unit = freeSpc / pcntSum;
bool haveSquished = FALSE;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
if ( !pRow->mBars[i]->IsFixed() )
{
cbBarInfo& bar = *pRow->mBars[i];
if ( int( unit * bar.mLenRatio ) < mpPane->mProps.mMinCBarDim.x )
{
haveSquished = TRUE;
bar.mBounds.width = -1; // mark as "squished"
pcntSum -= bar.mLenRatio;
freeSpc -= mpPane->mProps.mMinCBarDim.x;
}
}
} // for
if ( haveSquished )
unit = freeSpc / pcntSum;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
cbBarInfo& bar = *pRow->mBars[i];
bar.mBounds.x = prevX;
if ( !bar.IsFixed() )
{
if ( bar.mBounds.width == -1 )
bar.mBounds.width = mpPane->mProps.mMinCBarDim.x;
else
bar.mBounds.width = int( unit * bar.mLenRatio );
// a little bit of AI:
// memorize bar's height and width, when docked in
// the current orientation - by making the current
// dimensions to be "preffered" ones for this docking state
if ( !bar.IsFixed() )
{
bar.mDimInfo.mSizes[ bar.mState ].x = bar.mBounds.width;
bar.mDimInfo.mSizes[ bar.mState ].y = bar.mBounds.height;
}
}
prevX = bar.mBounds.x + bar.mBounds.width;
}
}
void cbRowLayoutPlugin::DetectBarHandles( cbRowInfo* pRow )
{
// first pass from left to right (detect left-side handles)
bool foundNotFixed = FALSE;
size_t i;
for ( i = 0; i != pRow->mBars.Count(); ++i )
{
cbBarInfo& bar = *pRow->mBars[i];
bar.mHasLeftHandle = FALSE;
if ( !bar.IsFixed() )
{
if ( foundNotFixed )
if ( bar.mpPrev &&
bar.mpPrev->IsFixed() )
bar.mHasLeftHandle = TRUE;
foundNotFixed = TRUE;
}
}
// pass from right to left (detect right-side handles)
foundNotFixed = FALSE;
cbBarInfo* pBar = pRow->mBars[ pRow->mBars.Count() - 1 ];
while( pBar )
{
pBar->mHasRightHandle = FALSE;
if ( !pBar->IsFixed() )
{
if ( foundNotFixed )
if ( pBar->mpNext )
pBar->mHasRightHandle = TRUE;
foundNotFixed = TRUE;
}
pBar = pBar->mpPrev;
}
}
void cbRowLayoutPlugin::RelayoutNotFixedBarsAround( cbBarInfo* pTheBar, cbRowInfo* pRow )
{
if ( !pTheBar->mpPrev )
{
if ( !pTheBar->IsFixed() )
{
// this bar the first in the row, move it's
// left edge to the very left
pTheBar->mBounds.width += pTheBar->mBounds.x;
pTheBar->mBounds.x = 0;
}
}
else
FitBarsToRange( 0, pTheBar->mBounds.x, pTheBar, pRow );
if ( !pTheBar->mpNext )
{
if ( !pTheBar->IsFixed() )
{
// this bar is the last one, move it's
// right edge to the very right
pTheBar->mBounds.width = mpPane->mPaneWidth - pTheBar->mBounds.x;
}
}
else
FitBarsToRange( pTheBar->mBounds.x + pTheBar->mBounds.width, mpPane->mPaneWidth,
pTheBar, pRow
);
}
void cbRowLayoutPlugin::LayoutItemsVertically( cbRowInfo& row )
{
size_t i;
for ( i = 0; i != row.mBars.Count(); ++i )
{
cbBarInfo& bar = *row.mBars[i];
bar.mBounds.y = row.mRowY;
if ( !bar.IsFixed() )
// make all not-fixed bars of equal height
bar.mBounds.height = row.mRowHeight;
if ( row.mHasUpperHandle )
bar.mBounds.y += mpPane->mProps.mResizeHandleSize;
}
}
int cbRowLayoutPlugin::CalcRowHeight( cbRowInfo& row )
{
int maxHeight = 0;
size_t i;
for ( i = 0; i != row.mBars.Count(); ++i )
maxHeight = wxMax( maxHeight, row.mBars[i]->mBounds.height );
return maxHeight;
}
void cbRowLayoutPlugin::StickRightSideBars( cbBarInfo* pToBar )
{
cbBarInfo* pBar = pToBar->mpNext;
cbBarInfo* pPrev = pToBar;
while( pBar )
{
wxRect& cur = pBar->mBounds;
wxRect& prev = pPrev->mBounds;
cur.x = prev.x + prev.width;
pPrev = pBar;
pBar = pBar->mpNext;
}
}
void cbRowLayoutPlugin::SlideLeftSideBars( cbBarInfo* pTheBar )
{
// shift left-side-bars to the left (with respect to "theBar"),
// so that they would not obscured by each other
cbBarInfo* pBar = pTheBar->mpPrev;
cbBarInfo* pPrev = pTheBar;
while( pBar )
{
wxRect& cur = pBar->mBounds;
wxRect& prev = pPrev->mBounds;
if ( cur.x + cur.width > prev.x )
cur.x = prev.x - cur.width;
pPrev = pBar;
pBar = pBar->mpPrev;
}
}
void cbRowLayoutPlugin::SlideRightSideBars( cbBarInfo* pTheBar )
{
// shift right-side-bars to the right (with respect to "theBar"),
// so that they would not be obscured by each other
cbBarInfo* pBar = pTheBar->mpNext;
cbBarInfo* pPrev = pTheBar;
while( pBar )
{
wxRect& cur = pBar->mBounds;
wxRect& prev = pPrev->mBounds;
if ( cur.x < prev.x + prev.width )
cur.x = prev.x + prev.width;
pPrev = pBar;
pBar = pBar->mpNext;
}
}
void cbRowLayoutPlugin::ShiftLeftTrashold( cbBarInfo* pTheBar, cbRowInfo& row )
{
wxRect& first = row.mBars[0]->mBounds;
if ( first.x < 0 )
{
row.mBars[0]->mBounds.x = 0;
SlideRightSideBars( row.mBars[0] );
}
}
void cbRowLayoutPlugin::ShiftRightTrashold( cbBarInfo* pTheBar, cbRowInfo& row )
{
wxRect& theBar = pTheBar->mBounds;
do
{
cbBarInfo* pBar = pTheBar;
// calculate free spece on the left side
int leftFreeSpc = 0;
while( pBar )
{
wxRect& cur = pBar->mBounds;
if ( pBar->mpPrev )
{
wxRect& prev = pBar->mpPrev->mBounds;
leftFreeSpc += cur.x - prev.x - prev.width;
}
else
leftFreeSpc += cur.x;
if ( cur.x < 0 )
{
leftFreeSpc = 0;
break;
}
pBar = pBar->mpPrev;
}
pBar = pTheBar;
int rightOverflow = 0;
if ( pTheBar->IsFixed() )
while( pBar )
{
if ( !pBar->mpNext )
{
wxRect& cur = pBar->mBounds;
if ( cur.x + cur.width > mpPane->mPaneWidth )
rightOverflow = cur.x + cur.width - mpPane->mPaneWidth;
}
pBar = pBar->mpNext;
}
if ( rightOverflow > 0 )
{
if ( leftFreeSpc <= 0 ) return;
if ( pTheBar->mpNext )
{
wxRect& next = pTheBar->mpNext->mBounds;
// if there's enough space on the left, move over one half-obscured
// bar from the right to the left side with respect to "theBar"
if ( next.width < leftFreeSpc )
{
cbBarInfo* pNext = pTheBar->mpNext;
row.mBars.Remove( pNext );
row.mBars.Insert( pNext, row.mBars.Index( pTheBar ) );
next.x = theBar.x - next.width;
// re-setup mpPrev/mpNext references after insertion
mpPane->InitLinksForRow( &row );
// tighten things
StickRightSideBars( pTheBar );
SlideLeftSideBars ( pTheBar );
continue;
}
}
int leftShift = ( rightOverflow > leftFreeSpc )
? leftFreeSpc
: rightOverflow;
theBar.x -= leftShift;
StickRightSideBars( pTheBar );
SlideLeftSideBars ( pTheBar );
break;
} // end of if ( rightOverflow )
else
break;
} while(1);
}
void cbRowLayoutPlugin::InsertBefore( cbBarInfo* pBeforeBar,
cbBarInfo* pTheBar,
cbRowInfo& row )
{
if ( pBeforeBar )
row.mBars.Insert( pTheBar, row.mBars.Index( pBeforeBar ) );
else
row.mBars.Add( pTheBar );
pTheBar->mpRow = &row;
}
void cbRowLayoutPlugin::DoInsertBar( cbBarInfo* pTheBar, cbRowInfo& row )
{
wxRect& theBar = pTheBar->mBounds;
/* OLD STUFF::
if ( theBar.x < 0 && !node_to_bar( pTheBar ).IsFixed() )
{
// AI::
theBar.width += theBar.x;
theBar.x = 0;
} */
size_t i;
for ( i = 0; i != row.mBars.Count(); ++i )
{
cbBarInfo& bar = *row.mBars[i];
wxRect& cur = bar.mBounds;
// if bar hits the left edge
if ( theBar.x <= cur.x )
{
InsertBefore( &bar, pTheBar, row );
return;
}
else
// if bar hits the right edge
if ( theBar.x <= cur.x + cur.width )
{
if ( theBar.x + theBar.width > cur.x + cur.width )
{
InsertBefore( bar.mpNext, pTheBar, row );
return;
}
// otherwise the bar lies within the bounds of current bar
int leftDist = theBar.x - cur.x;
int rightDist = cur.x + cur.width - (theBar.x + theBar.width);
if ( leftDist < rightDist )
InsertBefore( &bar, pTheBar, row );
else
InsertBefore( bar.mpNext, pTheBar, row );
return;
}
}
InsertBefore( NULL, pTheBar, row ); // insert at the end
}
// evnet handlers
void cbRowLayoutPlugin::OnInsertBar( cbInsertBarEvent& event )
{
cbBarInfo* pBarToInsert = event.mpBar;
cbRowInfo* pIntoRow = event.mpRow;
mpPane = event.mpPane;
if ( !pBarToInsert->IsFixed() )
AdjustLengthOfInserted( pIntoRow, pBarToInsert );
DoInsertBar( pBarToInsert, *pIntoRow );
mpPane->InitLinksForRow( pIntoRow ); // relink "mpNext/mpPrev"s
// perform relayouting of the bars after insertion
// init bar location info
pBarToInsert->mAlignment = event.mpPane->mAlignment;
pBarToInsert->mRowNo = event.mpPane->GetRowIndex( pIntoRow );
#ifdef __EXPERIMENTAL
if ( !pIntoRow->mHasOnlyFixedBars || !pBarToInsert->IsFixed() )
RecalcLengthRatios( pIntoRow );
#endif
MinimzeNotFixedBars( pIntoRow, pBarToInsert );
SlideLeftSideBars ( pBarToInsert );
SlideRightSideBars( pBarToInsert );
ShiftLeftTrashold ( pBarToInsert, *pIntoRow );
ShiftRightTrashold( pBarToInsert, *pIntoRow );
mpPane->SyncRowFlags( pIntoRow );
CheckIfAtTheBoundary( pBarToInsert, *pIntoRow );
if ( event.mpPane->IsHorizontal() )
pBarToInsert->mState = wxCBAR_DOCKED_HORIZONTALLY;
else
pBarToInsert->mState = wxCBAR_DOCKED_VERTICALLY;
if ( !pIntoRow->mHasOnlyFixedBars )
{
#ifdef __EXPERIMENTAL
ExpandNotFixedBars( pIntoRow );
#else
RelayoutNotFixedBarsAround( pBarToInsert, pIntoRow );
RecalcLengthRatios( pIntoRow );
#endif
DetectBarHandles( pIntoRow );
// do proportional resizing of not-fixed bars
ApplyLengthRatios( pIntoRow );
}
// adjust the bar's docking state
// a little bit of AI:
// memorize bar's height and width, when docked in
// the current orientation - by making the current
// dimensions to be "preferred" ones for this docking state
if ( !pBarToInsert->IsFixed() )
{
cbBarInfo& bar = *pBarToInsert;
bar.mDimInfo.mSizes[ bar.mState ].x = bar.mBounds.width;
bar.mDimInfo.mSizes[ bar.mState ].y = bar.mBounds.height;
}
}
void cbRowLayoutPlugin::OnRemoveBar ( cbRemoveBarEvent& event )
{
cbBarInfo* pBar = event.mpBar;
mpPane = event.mpPane;
cbRowInfo* pRow = pBar->mpRow;
mpLayout->GetUpdatesManager().OnBarWillChange( pBar, pRow, event.mpPane );
// invalidate the whole row
//pFirst->mpRowInfo->mMgrData.mPrevBounds.x = -1;
pRow->mBars.Remove( pBar );
// rest bar information after removing it from the row
pBar->mpRow = NULL;
pBar->mHasLeftHandle = FALSE;
pBar->mHasRightHandle = FALSE;
mpPane->InitLinksForRow( pRow ); // relink "mpNext/mpPrev"s
if ( pRow->mBars.Count() == 0 )
{
// empty rows should not exist
event.mpPane->GetRowList().Remove( pRow );
delete pRow;
mpPane->InitLinksForRows();
}
else
{
// force repainting of bars, in the row, from which the bar was removed
// FIXME:: really needed?
pRow->mBars[0]->mUMgrData.SetDirty(TRUE);
// re-setup mHasOnlyFixedBars flag for the row information
event.mpPane->SyncRowFlags( pRow );
DetectBarHandles( pRow );
if ( !pRow->mHasOnlyFixedBars )
ExpandNotFixedBars( pRow );
}
}
void cbRowLayoutPlugin::OnLayoutRow( cbLayoutRowEvent& event )
{
cbRowInfo* pRow = event.mpRow;
mpPane = event.mpPane;
MinimzeNotFixedBars( pRow, NULL );
if ( !pRow->mHasOnlyFixedBars )
{
// do proportional resizing of not-fixed bars
ApplyLengthRatios( pRow );
}
cbBarInfo& lastBar = *pRow->mBars[ pRow->mBars.Count() - 1 ];
cbBarInfo& firstBar = *pRow->mBars[ 0 ];
// FIXME:: Next line not used
// wxRect& bounds = lastBar.mBounds;
if ( lastBar.mBounds.x + lastBar.mBounds.width > mpPane->mPaneWidth )
{
lastBar.mBounds.x = mpPane->mPaneWidth - lastBar.mBounds.width;
// first simulate left-row-edge friction
SlideLeftSideBars( &lastBar );
if ( firstBar.mBounds.x < 0 )
firstBar.mBounds.x = 0;
// then left-row-edge function, though this
// may cause some of the right-side bars going
// out of row bounds, but left-side always
// has the highest "priority"
SlideRightSideBars( &firstBar );
}
event.Skip(); // pass event to the next handler
}
void cbRowLayoutPlugin::OnLayoutRows( cbLayoutRowsEvent& event )
{
mpPane = event.mpPane;
int curY = 0;
// FIXME:: Next line not used.
// RowArrayT& arr = mpPane->GetRowList();
size_t i;
for ( i = 0; i != mpPane->GetRowList().Count(); ++i )
{
cbRowInfo& row = *mpPane->GetRowList()[ i ];
//mpPane->CalcLengthRatios(& row);
// setup "has-handle" flags for rows, which depend on the existance
// of not-fixed bars in the row
if ( !row.mHasOnlyFixedBars )
{
if ( mpPane->mAlignment == FL_ALIGN_TOP ||
mpPane->mAlignment == FL_ALIGN_LEFT )
{
row.mHasLowerHandle = TRUE;
row.mHasUpperHandle = FALSE;
}
else
{
row.mHasUpperHandle = TRUE;
row.mHasLowerHandle = FALSE;
}
}
else
{
// otherwise, rows with fixed-bars only, have no height-resizing handles
row.mHasUpperHandle = FALSE;
row.mHasLowerHandle = FALSE;
}
// setup vertical positions for items in the row
row.mRowY = curY;
row.mRowWidth = mpPane->mPaneWidth;
row.mRowHeight = CalcRowHeight( row );
LayoutItemsVertically( row );
if ( row.mHasUpperHandle )
row.mRowHeight += mpPane->mProps.mResizeHandleSize;
if ( row.mHasLowerHandle )
row.mRowHeight += mpPane->mProps.mResizeHandleSize;
curY += row.mRowHeight;
}
event.Skip(); // pass event to the next handler - other hookeds plugin
// may also add some "refinements" to the layout now
}
void cbRowLayoutPlugin::OnResizeRow( cbResizeRowEvent& event )
{
// extract resize-event info
int ofs = event.mHandleOfs;
bool forUpperHandle = event.mForUpperHandle;
cbRowInfo* pTheRow = event.mpRow;
mpPane = event.mpPane;
// FIXME:: Next line not used.
//int newHeight = pTheRow->mRowHeight;
int freeSpc = 0;
if ( forUpperHandle )
{
// calculate available free space from above,
// which can be obtained by squeezing not-fixed height rows
cbRowInfo* pRow = pTheRow->mpPrev;
while( pRow )
{
freeSpc += pRow->mRowHeight - event.mpPane->GetMinimalRowHeight( pRow );
pRow = pRow->mpPrev;
}
}
else
{
// calculate available free space from below,
// which can be obtained by squeezing not-fixed height rows
cbRowInfo* pRow = pTheRow->mpNext;
while( pRow )
{
freeSpc += pRow->mRowHeight - mpPane->GetMinimalRowHeight( pRow );
pRow = pRow->mpNext;
}
}
mpLayout->GetUpdatesManager().OnStartChanges();
int clientSize;
// allow user adjusting pane vs. client-area space, for upper-handle
if ( mpPane->IsHorizontal() )
clientSize = mpLayout->GetClientHeight();
else
clientSize = mpLayout->GetClientWidth();
if ( forUpperHandle && ofs < -clientSize )
{
int needed = -(ofs + clientSize);
cbRowInfo* pRow = mpPane->GetRowList()[ 0 ];
// start squeezing rows from the top row towards bottom
while( pRow != pTheRow && needed )
{
// only not-fixed rows can be squeezed
if ( !pRow->mHasOnlyFixedBars )
{
int prevHeight = pRow->mRowHeight;
int newHeight = wxMax( event.mpPane->GetMinimalRowHeight( pRow ),
prevHeight - needed );
if ( newHeight != prevHeight )
{
event.mpPane->SetRowHeight( pRow, newHeight );
needed -= prevHeight - pRow->mRowHeight;
}
}
pRow = pRow->mpNext;
}
}
// allow user adjusting pane vs. client-area space, for lower-handle
if ( !forUpperHandle && ofs > clientSize )
{
int needed = ofs - clientSize;
cbRowInfo* pRow = mpPane->GetRowList()[ mpPane->GetRowList().Count() - 1 ];
// start squeezing rows from the bottom towards the top row
while( pRow && needed )
{
// only not-fixed rows can be squeezed
if ( !pRow->mHasOnlyFixedBars )
{
int prevHeight = pRow->mRowHeight;
int newHeight = wxMax( event.mpPane->GetMinimalRowHeight( pRow ),
prevHeight - needed );
if ( newHeight != prevHeight )
{
event.mpPane->SetRowHeight( pRow, newHeight );
needed -= prevHeight - pRow->mRowHeight;
}
}
pRow = pRow->mpPrev;
}
}
if ( forUpperHandle )
event.mpPane->SetRowHeight( pTheRow, pTheRow->mRowHeight + (-ofs) );
else
event.mpPane->SetRowHeight( pTheRow, pTheRow->mRowHeight + ofs );
mpLayout->RecalcLayout(FALSE);
mpLayout->GetUpdatesManager().OnFinishChanges();
mpLayout->GetUpdatesManager().UpdateNow();
}