📄 rowlayoutpl.cpp
字号:
/////////////////////////////////////////////////////////////////////////////// Name: rowlayoutpl.cpp// Purpose: cbRowLayoutPlugin implementation.// Author: Aleksandras Gluchovas// Modified by:// Created: 09/09/98// RCS-ID: $Id: rowlayoutpl.cpp,v 1.11 2005/09/23 12:47:44 MR Exp $// Copyright: (c) Aleksandras Gluchovas// Licence: wxWindows licence/////////////////////////////////////////////////////////////////////////////// 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 ); #if 1 // FIXME:: something's wrong? return; #else 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; } #endif}void cbRowLayoutPlugin::AdjustLengthOfInserted( cbRowInfo* WXUNUSED(pRow), cbBarInfo* WXUNUSED(pTheBar) ){ return;#if 0 // 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#endif}void cbRowLayoutPlugin::FitBarsToRange( int from, int till, cbBarInfo* pTheBar, cbRowInfo* pRow ){ cbBarInfo* pFromBar; cbBarInfo* pTillBar; 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 ){ size_t i; double pcntSum = 0; // FOR NOW:: all-in-one 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_: if (pcntSum == 0.0) pcntSum = 1.0; 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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -