git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11170 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1221 lines
25 KiB
C++
1221 lines
25 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: No names yet.
|
|
// Purpose: Contrib. demo
|
|
// Author: Aleksandras Gluchovas
|
|
// Modified by:
|
|
// Created: 09/09/98
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) Aleksandras Gluchovas
|
|
// Licence: wxWindows license
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#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 = 0;
|
|
|
|
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;
|
|
|
|
// 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 ];
|
|
|
|
// 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();
|
|
}
|
|
|