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 >
C/C++ Source or Header  |  2002-04-04  |  31KB  |  1,217 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        rowlayoutpl.cpp
  3. // Purpose:     cbRowLayoutPlugin implementation.
  4. // Author:      Aleksandras Gluchovas
  5. // Modified by:
  6. // Created:     09/09/98
  7. // RCS-ID:      $Id: rowlayoutpl.cpp,v 1.4 2002/04/04 21:05:14 JS Exp $
  8. // Copyright:   (c) Aleksandras Gluchovas
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13.     #pragma implementation "rowlayoutpl.h"
  14. #endif
  15.  
  16. // For compilers that support precompilation, includes "wx.h".
  17. #include "wx/wxprec.h"
  18.  
  19. #ifdef __BORLANDC__
  20. #pragma hdrstop
  21. #endif
  22.  
  23. #ifndef WX_PRECOMP
  24. #include "wx/wx.h"
  25. #endif
  26.  
  27. #include "wx/fl/rowlayoutpl.h"
  28.  
  29. // exerimental "features" are still buggy
  30. #undef __EXPERIMENTAL
  31.  
  32. /***** Implementation for class cbRowLayoutPlugin *****/
  33.  
  34. IMPLEMENT_DYNAMIC_CLASS( cbRowLayoutPlugin, cbPluginBase )
  35.  
  36. BEGIN_EVENT_TABLE( cbRowLayoutPlugin, cbPluginBase )
  37.  
  38.     EVT_PL_LAYOUT_ROW ( cbRowLayoutPlugin::OnLayoutRow  )
  39.     EVT_PL_LAYOUT_ROWS( cbRowLayoutPlugin::OnLayoutRows )
  40.     EVT_PL_RESIZE_ROW ( cbRowLayoutPlugin::OnResizeRow  )
  41.  
  42.     EVT_PL_INSERT_BAR ( cbRowLayoutPlugin::OnInsertBar  )
  43.     EVT_PL_REMOVE_BAR ( cbRowLayoutPlugin::OnRemoveBar  )
  44.  
  45. END_EVENT_TABLE()
  46.  
  47. cbRowLayoutPlugin::cbRowLayoutPlugin(void)
  48.     : mpPane( 0 )
  49. {}
  50.  
  51. cbRowLayoutPlugin::cbRowLayoutPlugin( wxFrameLayout* pPanel, int paneMask )
  52.  
  53.     : cbPluginBase( pPanel, paneMask ),
  54.       mpPane( 0 )
  55. {}
  56.  
  57. void cbRowLayoutPlugin::CheckIfAtTheBoundary( cbBarInfo* pTheBar, cbRowInfo& rowInfo )
  58. {
  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 
  65.     // side of the row
  66.  
  67.     if ( !pTheBar->IsFixed() || rowInfo.mHasOnlyFixedBars ) 
  68.  
  69.         return;
  70.  
  71.     cbBarInfo* pBar = rowInfo.mBars[ rowInfo.mBars.Count() - 1 ];
  72.  
  73.     // slide fixed bars to the right on the right side relative to the pBarNode
  74.  
  75.     int prevX = mpPane->mPaneWidth;
  76.  
  77.     do
  78.     {
  79.         if ( !pBar->IsFixed() ) 
  80.             break;
  81.  
  82.         wxRect& bounds = pBar->mBounds;
  83.  
  84.         bounds.x = prevX - bounds.width;
  85.  
  86.         prevX = bounds.x;
  87.  
  88.         if ( pBar == pTheBar ) break;
  89.  
  90.         pBar = pBar->mpPrev;
  91.     }
  92.     while( 1 );
  93.  
  94.     // slide fixed bars to the left on the left side relative to the pBarNode   
  95.  
  96.     pBar = rowInfo.mBars[0];
  97.  
  98.     prevX = 0;
  99.     
  100.     do
  101.     {
  102.         if ( pBar->IsFixed() ) 
  103.  
  104.             break;
  105.  
  106.         wxRect& bounds = pBar->mBounds;
  107.  
  108.         bounds.x = prevX;
  109.  
  110.         prevX = bounds.x + bounds.width;
  111.  
  112.         if ( pBar == pTheBar ) break;
  113.  
  114.         pBar = pBar->mpNext;
  115.     }
  116.     while( 1 );
  117. }
  118.  
  119. void cbRowLayoutPlugin::ExpandNotFixedBars( cbRowInfo* pRow )
  120. {
  121.     ApplyLengthRatios( pRow );
  122.  
  123.    // FIXME:: something's wrong?
  124.    return;
  125.  
  126.     double freeSpc = (double)GetRowFreeSpace( pRow );
  127.  
  128.     // calculate sum of precents
  129.  
  130.     double pcntSum = 0.0;
  131.  
  132.     size_t i;
  133.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  134.     {
  135.         if ( !pRow->mBars[i]->IsFixed() )
  136.             pcntSum += pRow->mBars[i]->mLenRatio;
  137.     }
  138.  
  139.     // setup bar lengths
  140.  
  141.     int curX = 0;
  142.  
  143.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  144.     {
  145.         cbBarInfo& bar = *pRow->mBars[i];
  146.  
  147.         if ( !bar.IsFixed() )
  148.         {
  149.             bar.mLenRatio = bar.mLenRatio/(pcntSum);
  150.  
  151.             bar.mBounds.width = 
  152.                 
  153.                 wxMax( mpPane->mProps.mMinCBarDim.x, int( freeSpc*bar.mLenRatio ) );
  154.         }
  155.         
  156.         bar.mBounds.x = curX;
  157.         curX = bar.mBounds.x + bar.mBounds.width;
  158.     }
  159. }
  160.  
  161. void cbRowLayoutPlugin::AdjustLengthOfInserted( cbRowInfo* pRow, cbBarInfo* pTheBar )
  162. {
  163.     return;  // TBD: Makes following code unreachable
  164.  
  165.     // pTheBar is not-fixed
  166.  
  167.  
  168.     // FIXME:: what is this for??
  169.  
  170. #if 1
  171.  
  172.     int totalLen = 0;
  173.  
  174.     size_t i;
  175.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  176.     {
  177.         if ( !pRow->mBars[i]->IsFixed() )
  178.             totalLen += pRow->mBars[i]->mBounds.width;
  179.     }
  180.  
  181.     double curWidth = pTheBar->mBounds.width;
  182.  
  183.     if ( pRow->mBars.Count() )
  184.  
  185.         pTheBar->mBounds.width = int( mpPane->mPaneWidth * (curWidth / double(totalLen)) );
  186. #else
  187.  
  188.     double freeSpc = (double)GetRowFreeSpace( pRow );
  189.  
  190.     double pcntSum = 0.0;
  191.  
  192.    size_t i;
  193.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  194.    {
  195.         if ( !pRow->mBars[i]->IsFixed() )
  196.             pcntSum += pRow->mBars[i]->mLenRatio;
  197.    }
  198.  
  199.     // if no longer "balanced", assume that `pTheBar' was previously
  200.     // removed from this row (kind of AI...)
  201.  
  202.     if ( pcntSum < 0.98 )
  203.  
  204.         pTheBar->mBounds.width = freeSpc * (1.0 - pcntSum);
  205. #endif
  206. }
  207.  
  208. void cbRowLayoutPlugin::FitBarsToRange( int from, int till,
  209.                                         cbBarInfo* pTheBar, cbRowInfo* pRow )
  210. {
  211.     cbBarInfo* pFromBar = NULL;
  212.     cbBarInfo* pTillBar = NULL;
  213.  
  214.     if ( pTheBar->mBounds.x > from )
  215.     {
  216.         // it's range from the left
  217.         pFromBar = pRow->mBars[0];
  218.         pTillBar = pTheBar;
  219.     }
  220.     else
  221.     {
  222.         pFromBar = pTheBar->mpNext;
  223.         pTillBar = NULL;
  224.     }
  225.  
  226.     // calc free space in the range
  227.  
  228.     cbBarInfo* pBar = pFromBar;
  229.     int     freeSpc = till-from;
  230.     double  pcntSum = 0;
  231.  
  232.     while( pBar != pTillBar )
  233.     {
  234.         if ( pBar->IsFixed() )
  235.             freeSpc -= pBar->mBounds.width;
  236.         else
  237.             pcntSum += pBar->mLenRatio;
  238.  
  239.         pBar = pBar->mpNext;
  240.     }
  241.  
  242.     // adjust not-fixed bar sizes in the range
  243.  
  244.     pBar = pFromBar;
  245.  
  246.     while ( pBar != pTillBar )
  247.     {
  248.         if ( !pBar->IsFixed() )
  249.       {
  250.             pBar->mBounds.width =
  251.                 wxMax( mpPane->mProps.mMinCBarDim.x,
  252.                        int( double(freeSpc) * (pBar->mLenRatio/pcntSum) )
  253.                      );
  254.       }
  255.         pBar = pBar->mpNext;
  256.     }
  257.  
  258.     // layout range, starting from the left-most bar
  259.  
  260.     pBar      = pFromBar;
  261.     int prevX = from;
  262.     bool hasNotFixedBars = FALSE;
  263.  
  264.     while ( pBar != pTillBar )
  265.     {
  266.         wxRect& bounds = pBar->mBounds;
  267.  
  268.         if ( !pBar->IsFixed() )
  269.         {
  270.             hasNotFixedBars = TRUE;
  271.  
  272.             freeSpc -= bounds.width;
  273.         }
  274.  
  275.         bounds.x = prevX;
  276.  
  277.         prevX = bounds.x + bounds.width;
  278.         
  279.         pBar = pBar->mpNext;
  280.     }
  281.  
  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
  284.  
  285.     if ( hasNotFixedBars )
  286.     {
  287.         if ( pTheBar->mBounds.x > from )
  288.         {
  289.             if ( pTillBar->mpPrev )
  290.             {
  291.                 wxRect& tillBar = pTillBar->mpPrev->mBounds;
  292.  
  293.                 //tillBar.width = bar.mBounds.x - tillBar.x;
  294.                 tillBar.width += freeSpc;
  295.             }
  296.         }
  297.         else
  298.         {
  299.             cbBarInfo* pLast = pRow->mBars[ pRow->mBars.Count() - 1 ];
  300.  
  301.             if ( pLast != pTheBar )
  302.             {
  303.                 pTheBar->mBounds.width += freeSpc;
  304.  
  305.                 SlideRightSideBars( pTheBar );
  306.             }
  307.         }
  308.     }
  309. }
  310.  
  311. void cbRowLayoutPlugin::MinimzeNotFixedBars( cbRowInfo* pRow, cbBarInfo* pBarToPreserve )
  312. {
  313.     size_t i;
  314.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  315.     {
  316.         if ( !pRow->mBars[i]->IsFixed() && pRow->mBars[i] != pBarToPreserve )
  317.             pRow->mBars[i]->mBounds.width = mpPane->mProps.mMinCBarDim.x;
  318.     }
  319. }
  320.  
  321. int cbRowLayoutPlugin::GetRowFreeSpace( cbRowInfo* pRow )
  322. {
  323.     int freeSpc = mpPane->mPaneWidth;
  324.  
  325.     size_t i;
  326.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  327.     {
  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;
  332.     }
  333.  
  334.     return freeSpc;
  335. }
  336.  
  337. void cbRowLayoutPlugin::RecalcLengthRatios( cbRowInfo* pRow )
  338. {
  339.     double freeSpc = double( GetRowFreeSpace( pRow ) );
  340.  
  341.     cbBarInfo* pBar          = pRow->mBars[0];
  342.     cbBarInfo* pLastNotFixed = NULL;
  343.  
  344.     double pcntLeft = 1.0; // (100%)
  345.  
  346. #ifdef __EXPERIMENTAL
  347.  
  348.     int totalLen = 0;
  349.  
  350.     size_t i;
  351.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  352.     {
  353.         if ( !pRow->mBars[i]->IsFixed() )
  354.             totalLen += pRow->mBars[i]->mBounds.width;
  355.     }
  356. #endif
  357.  
  358.     size_t i;
  359.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  360.     {
  361.         cbBarInfo& bar = *pRow->mBars[i];
  362.  
  363.         if ( !bar.IsFixed() )
  364.         {
  365.  
  366. #ifdef __EXPERIMENTAL
  367.  
  368.             bar.mLenRatio = double(bar.mBounds.width)/double(totalLen);
  369. #else
  370.             bar.mLenRatio = double(bar.mBounds.width)/freeSpc;
  371. #endif
  372.  
  373.             pcntLeft      -= bar.mLenRatio;
  374.             pLastNotFixed  = pBar;
  375.         }
  376.     }
  377.  
  378.     // attach remainder (the result of lost precision) to the
  379.     // last not-fixed bar
  380.  
  381. #if !defined(__EXPERIMENTAL)    
  382.  
  383.     if ( pLastNotFixed )
  384.         
  385.         pLastNotFixed->mLenRatio += pcntLeft;
  386. #endif
  387.  
  388. }
  389.  
  390. void cbRowLayoutPlugin::ApplyLengthRatios( cbRowInfo* pRow )
  391. {
  392.     double pcntSum = 0;
  393.  
  394.     // FOR NOW:: all-in-one
  395.  
  396.     size_t i = 0;
  397.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  398.     {
  399.         if ( !pRow->mBars[i]->IsFixed() )
  400.             pcntSum += pRow->mBars[i]->mLenRatio;
  401.     }
  402.  
  403.     /*
  404.     pBar = node_to_first_bar_node( pRow );
  405.     
  406.     while( pBar )
  407.     {
  408.         cbBarInfo& bar = node_to_bar( pBar );
  409.  
  410.         if ( !bar.IsFixed() )
  411.         
  412.             bar.mLenRatio = pcntSum / bar.mLenRatio;
  413.  
  414.         pBar = pBar->Next();
  415.     }
  416.     */
  417.  
  418.     int    prevX   = 0;
  419.     double freeSpc = GetRowFreeSpace( pRow );
  420.  
  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...)
  428.     //
  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_:
  435.  
  436.     double unit = freeSpc / pcntSum;
  437.  
  438.     bool haveSquished = FALSE;
  439.  
  440.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  441.     {
  442.         if ( !pRow->mBars[i]->IsFixed() )
  443.         {
  444.             cbBarInfo& bar = *pRow->mBars[i];   
  445.             
  446.             if ( int( unit * bar.mLenRatio ) < mpPane->mProps.mMinCBarDim.x )
  447.             {
  448.                 haveSquished = TRUE;
  449.  
  450.                 bar.mBounds.width = -1; // mark as "squished"
  451.  
  452.                 pcntSum -= bar.mLenRatio;
  453.  
  454.                 freeSpc -= mpPane->mProps.mMinCBarDim.x;
  455.             }
  456.         }
  457.     }  // for
  458.  
  459.     if ( haveSquished )
  460.         unit = freeSpc / pcntSum;
  461.  
  462.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  463.     {
  464.         cbBarInfo& bar = *pRow->mBars[i];
  465.  
  466.         bar.mBounds.x = prevX;
  467.  
  468.         if ( !bar.IsFixed() )
  469.         {
  470.             if ( bar.mBounds.width == -1 )
  471.  
  472.                 bar.mBounds.width = mpPane->mProps.mMinCBarDim.x;
  473.             else
  474.                 bar.mBounds.width = int( unit * bar.mLenRatio );
  475.  
  476.             // a little bit of AI: 
  477.             // memorize bar's height and width, when docked in 
  478.             // the current orientation - by making the current
  479.             // dimensions to be "preffered" ones for this docking state
  480.  
  481.             if ( !bar.IsFixed() )
  482.             {
  483.                 bar.mDimInfo.mSizes[ bar.mState ].x = bar.mBounds.width;
  484.                 bar.mDimInfo.mSizes[ bar.mState ].y = bar.mBounds.height;
  485.             }
  486.         }
  487.  
  488.         prevX = bar.mBounds.x + bar.mBounds.width;
  489.     }
  490. }
  491.  
  492. void cbRowLayoutPlugin::DetectBarHandles( cbRowInfo* pRow )
  493. {
  494.     // first pass from left to right (detect left-side handles)
  495.  
  496.     bool foundNotFixed = FALSE;
  497.  
  498.     size_t i;
  499.     for ( i = 0; i != pRow->mBars.Count(); ++i )
  500.     {
  501.         cbBarInfo& bar = *pRow->mBars[i];
  502.         
  503.         bar.mHasLeftHandle = FALSE;
  504.  
  505.         if ( !bar.IsFixed() )
  506.         {
  507.             if ( foundNotFixed )
  508.         
  509.                 if ( bar.mpPrev &&
  510.                      bar.mpPrev->IsFixed() )
  511.                 
  512.                     bar.mHasLeftHandle = TRUE;
  513.  
  514.             foundNotFixed = TRUE;
  515.         }
  516.     }
  517.  
  518.     // pass from right to left (detect right-side handles)
  519.  
  520.     foundNotFixed = FALSE;
  521.  
  522.     cbBarInfo* pBar = pRow->mBars[ pRow->mBars.Count() - 1 ];
  523.  
  524.     while( pBar )
  525.     {
  526.         pBar->mHasRightHandle = FALSE;
  527.  
  528.         if ( !pBar->IsFixed() )
  529.         {
  530.             if ( foundNotFixed )
  531.  
  532.                 if ( pBar->mpNext )
  533.  
  534.                      pBar->mHasRightHandle = TRUE;
  535.  
  536.             foundNotFixed = TRUE;
  537.         }
  538.  
  539.         pBar = pBar->mpPrev;
  540.     }
  541. }
  542.  
  543. void cbRowLayoutPlugin::RelayoutNotFixedBarsAround( cbBarInfo* pTheBar, cbRowInfo* pRow )
  544. {
  545.     if ( !pTheBar->mpPrev )
  546.     {
  547.         if (  !pTheBar->IsFixed() )
  548.         {
  549.             // this bar the first in the row, move it's 
  550.             // left edge to the very left
  551.             pTheBar->mBounds.width += pTheBar->mBounds.x;
  552.             pTheBar->mBounds.x      = 0;
  553.         }
  554.     }
  555.     else
  556.         FitBarsToRange( 0, pTheBar->mBounds.x, pTheBar, pRow );
  557.  
  558.     if ( !pTheBar->mpNext )
  559.     {
  560.         if ( !pTheBar->IsFixed() )
  561.         {
  562.             // this bar is the last one, move it's 
  563.             // right edge to the very right
  564.  
  565.             pTheBar->mBounds.width = mpPane->mPaneWidth - pTheBar->mBounds.x;
  566.         }
  567.     }
  568.     else
  569.         FitBarsToRange( pTheBar->mBounds.x + pTheBar->mBounds.width, mpPane->mPaneWidth,
  570.                         pTheBar, pRow
  571.                       );
  572. }
  573.  
  574. void cbRowLayoutPlugin::LayoutItemsVertically( cbRowInfo& row )
  575. {
  576.     size_t i;
  577.     for ( i = 0; i != row.mBars.Count(); ++i )
  578.     {
  579.         cbBarInfo& bar = *row.mBars[i];
  580.  
  581.         bar.mBounds.y = row.mRowY;
  582.  
  583.         if ( !bar.IsFixed() )
  584.  
  585.             // make all not-fixed bars of equal height
  586.             bar.mBounds.height = row.mRowHeight;
  587.  
  588.         if ( row.mHasUpperHandle )
  589.  
  590.             bar.mBounds.y += mpPane->mProps.mResizeHandleSize;
  591.     }
  592. }
  593.  
  594. int cbRowLayoutPlugin::CalcRowHeight( cbRowInfo& row )
  595. {
  596.     int maxHeight = 0;
  597.  
  598.     size_t i;
  599.     for ( i = 0; i != row.mBars.Count(); ++i )
  600.     
  601.         maxHeight = wxMax( maxHeight, row.mBars[i]->mBounds.height );
  602.  
  603.     return maxHeight;
  604. }
  605.  
  606. void cbRowLayoutPlugin::StickRightSideBars( cbBarInfo* pToBar )
  607. {
  608.     cbBarInfo* pBar  = pToBar->mpNext;
  609.     cbBarInfo* pPrev = pToBar;
  610.  
  611.     while( pBar )
  612.     {
  613.         wxRect& cur  = pBar->mBounds;
  614.         wxRect& prev = pPrev->mBounds;
  615.  
  616.         cur.x = prev.x + prev.width;
  617.  
  618.         pPrev = pBar;
  619.         pBar  = pBar->mpNext;
  620.     }
  621. }
  622.  
  623. void cbRowLayoutPlugin::SlideLeftSideBars( cbBarInfo* pTheBar )
  624. {
  625.     // shift left-side-bars to the left (with respect to "theBar"),
  626.     // so that they would not obscured by each other
  627.  
  628.     cbBarInfo* pBar  = pTheBar->mpPrev;
  629.     cbBarInfo* pPrev = pTheBar;
  630.  
  631.     while( pBar )
  632.     {
  633.         wxRect& cur  = pBar->mBounds;
  634.         wxRect& prev = pPrev->mBounds;
  635.  
  636.         if ( cur.x + cur.width > prev.x )
  637.  
  638.             cur.x = prev.x - cur.width;
  639.  
  640.         pPrev = pBar;
  641.         pBar  = pBar->mpPrev;
  642.     }
  643. }
  644.  
  645. void cbRowLayoutPlugin::SlideRightSideBars( cbBarInfo* pTheBar )
  646. {
  647.     // shift right-side-bars to the right (with respect to "theBar"),
  648.     // so that they would not be obscured by each other
  649.  
  650.     cbBarInfo* pBar  = pTheBar->mpNext;
  651.     cbBarInfo* pPrev = pTheBar;
  652.  
  653.     while( pBar )
  654.     {
  655.         wxRect& cur  = pBar->mBounds;
  656.         wxRect& prev = pPrev->mBounds;
  657.  
  658.         if ( cur.x < prev.x + prev.width )
  659.  
  660.             cur.x = prev.x + prev.width;
  661.  
  662.         pPrev = pBar;
  663.         pBar  = pBar->mpNext;
  664.     }
  665. }
  666.  
  667. void cbRowLayoutPlugin::ShiftLeftTrashold( cbBarInfo* pTheBar, cbRowInfo& row )
  668. {
  669.     wxRect& first = row.mBars[0]->mBounds;
  670.  
  671.     if ( first.x < 0 )
  672.     {
  673.         row.mBars[0]->mBounds.x = 0;
  674.  
  675.         SlideRightSideBars( row.mBars[0] );
  676.     }
  677. }
  678.  
  679. void cbRowLayoutPlugin::ShiftRightTrashold( cbBarInfo* pTheBar, cbRowInfo& row )
  680. {
  681.     wxRect& theBar = pTheBar->mBounds;
  682.  
  683.     do
  684.     {
  685.         cbBarInfo* pBar = pTheBar;
  686.  
  687.         // calculate free spece on the left side
  688.  
  689.         int leftFreeSpc = 0;
  690.  
  691.         while( pBar )
  692.         {
  693.             wxRect& cur = pBar->mBounds;
  694.  
  695.             if ( pBar->mpPrev )
  696.             {
  697.                 wxRect& prev = pBar->mpPrev->mBounds;
  698.  
  699.                 leftFreeSpc += cur.x - prev.x - prev.width;
  700.             }
  701.             else
  702.                 leftFreeSpc += cur.x;
  703.  
  704.             if ( cur.x < 0 )
  705.             {
  706.                 leftFreeSpc = 0;
  707.                 break;
  708.             }
  709.  
  710.             pBar = pBar->mpPrev;
  711.         }
  712.  
  713.         pBar = pTheBar;
  714.  
  715.         int rightOverflow = 0;
  716.  
  717.         if ( pTheBar->IsFixed() )
  718.  
  719.             while( pBar )
  720.             {
  721.                 if ( !pBar->mpNext )
  722.                 {
  723.                     wxRect& cur = pBar->mBounds;
  724.  
  725.                     if ( cur.x + cur.width > mpPane->mPaneWidth )
  726.  
  727.                         rightOverflow = cur.x + cur.width - mpPane->mPaneWidth;
  728.                 }
  729.  
  730.                 pBar = pBar->mpNext;
  731.             }
  732.  
  733.         if ( rightOverflow > 0 )
  734.         {
  735.             if ( leftFreeSpc <= 0 ) return;
  736.  
  737.             if ( pTheBar->mpNext )
  738.             {
  739.                 wxRect& next = pTheBar->mpNext->mBounds;
  740.  
  741.                 // if there's enough space on the left, move over one half-obscured
  742.                 // bar from the right to the left side with respect to "theBar"
  743.  
  744.                 if ( next.width < leftFreeSpc )
  745.                 {
  746.                     cbBarInfo* pNext = pTheBar->mpNext;
  747.  
  748.                     row.mBars.Remove( pNext );
  749.  
  750.                     row.mBars.Insert( pNext, row.mBars.Index( pTheBar ) );
  751.  
  752.                     next.x = theBar.x - next.width;
  753.  
  754.                     // re-setup mpPrev/mpNext references after insertion
  755.  
  756.                     mpPane->InitLinksForRow( &row );
  757.  
  758.                     // tighten things
  759.  
  760.                     StickRightSideBars( pTheBar );
  761.                     SlideLeftSideBars ( pTheBar );
  762.  
  763.                     continue;
  764.                 }
  765.             }
  766.  
  767.             int leftShift = ( rightOverflow > leftFreeSpc ) 
  768.                             ? leftFreeSpc 
  769.                             : rightOverflow;
  770.  
  771.             theBar.x -= leftShift;
  772.  
  773.             StickRightSideBars( pTheBar );
  774.             SlideLeftSideBars ( pTheBar );
  775.  
  776.             break;
  777.  
  778.         } // end of if ( rightOverflow )
  779.         else
  780.             break;
  781.  
  782.     } while(1);
  783. }
  784.  
  785. void cbRowLayoutPlugin::InsertBefore( cbBarInfo* pBeforeBar, 
  786.                                       cbBarInfo* pTheBar,
  787.                                       cbRowInfo& row        )
  788. {
  789.     if ( pBeforeBar )
  790.  
  791.         row.mBars.Insert( pTheBar, row.mBars.Index( pBeforeBar ) );
  792.     else
  793.         row.mBars.Add( pTheBar );
  794.  
  795.     pTheBar->mpRow = &row;
  796. }
  797.  
  798. void cbRowLayoutPlugin::DoInsertBar( cbBarInfo* pTheBar, cbRowInfo& row )
  799. {
  800.     wxRect& theBar = pTheBar->mBounds;
  801.  
  802.     /* OLD STUFF::
  803.     if ( theBar.x < 0 && !node_to_bar( pTheBar ).IsFixed() )
  804.     {
  805.         // AI::
  806.         theBar.width += theBar.x;
  807.         theBar.x = 0;
  808.     } */
  809.  
  810.     size_t i;
  811.     for ( i = 0; i != row.mBars.Count(); ++i )
  812.     {
  813.         cbBarInfo& bar = *row.mBars[i];
  814.  
  815.         wxRect& cur = bar.mBounds;
  816.  
  817.         // if bar hits the left edge
  818.         if ( theBar.x <= cur.x )
  819.         {
  820.             InsertBefore( &bar, pTheBar, row );
  821.             return;
  822.         }
  823.         
  824.         else
  825.         // if bar hits the right edge
  826.         if ( theBar.x <= cur.x + cur.width )
  827.         {
  828.             if ( theBar.x + theBar.width > cur.x + cur.width )
  829.             {
  830.                 InsertBefore( bar.mpNext, pTheBar, row );
  831.                 return;
  832.             }
  833.  
  834.             // otherwise the bar lies within the bounds of current bar
  835.  
  836.             int leftDist  = theBar.x - cur.x;
  837.             int rightDist = cur.x + cur.width - (theBar.x + theBar.width);
  838.  
  839.             if ( leftDist < rightDist )
  840.  
  841.                 InsertBefore( &bar, pTheBar, row );
  842.             else
  843.                 InsertBefore( bar.mpNext, pTheBar, row );
  844.  
  845.             return;
  846.         }
  847.     }
  848.  
  849.     InsertBefore( NULL, pTheBar, row ); // insert at the end
  850. }
  851.  
  852. // evnet handlers
  853.  
  854. void cbRowLayoutPlugin::OnInsertBar( cbInsertBarEvent& event )
  855. {
  856.     cbBarInfo* pBarToInsert = event.mpBar;
  857.     cbRowInfo* pIntoRow     = event.mpRow;
  858.     mpPane                  = event.mpPane;
  859.  
  860.     if ( !pBarToInsert->IsFixed() )
  861.  
  862.         AdjustLengthOfInserted( pIntoRow, pBarToInsert );
  863.  
  864.     DoInsertBar( pBarToInsert, *pIntoRow );
  865.  
  866.     mpPane->InitLinksForRow( pIntoRow ); // relink "mpNext/mpPrev"s
  867.  
  868.     // perform relayouting of the bars after insertion
  869.  
  870.     // init bar location info
  871.     pBarToInsert->mAlignment = event.mpPane->mAlignment;
  872.     pBarToInsert->mRowNo     = event.mpPane->GetRowIndex( pIntoRow );
  873.  
  874. #ifdef __EXPERIMENTAL
  875.  
  876.     if ( !pIntoRow->mHasOnlyFixedBars || !pBarToInsert->IsFixed() )
  877.  
  878.         RecalcLengthRatios( pIntoRow );
  879.  
  880. #endif
  881.  
  882.     MinimzeNotFixedBars( pIntoRow, pBarToInsert );
  883.  
  884.     SlideLeftSideBars ( pBarToInsert );
  885.     SlideRightSideBars( pBarToInsert );
  886.  
  887.     ShiftLeftTrashold ( pBarToInsert, *pIntoRow );
  888.     ShiftRightTrashold( pBarToInsert, *pIntoRow );
  889.  
  890.     mpPane->SyncRowFlags( pIntoRow );
  891.  
  892.     CheckIfAtTheBoundary( pBarToInsert, *pIntoRow );
  893.  
  894.     if ( event.mpPane->IsHorizontal() )
  895.  
  896.         pBarToInsert->mState = wxCBAR_DOCKED_HORIZONTALLY;
  897.     else
  898.         pBarToInsert->mState = wxCBAR_DOCKED_VERTICALLY;
  899.  
  900.     if ( !pIntoRow->mHasOnlyFixedBars )
  901.     {
  902.  
  903. #ifdef __EXPERIMENTAL
  904.  
  905.         ExpandNotFixedBars( pIntoRow );
  906. #else
  907.  
  908.         RelayoutNotFixedBarsAround( pBarToInsert, pIntoRow );
  909.         RecalcLengthRatios( pIntoRow );
  910.  
  911. #endif
  912.  
  913.         DetectBarHandles( pIntoRow );
  914.  
  915.         // do proportional resizing of not-fixed bars 
  916.         ApplyLengthRatios( pIntoRow );
  917.     }
  918.  
  919.     // adjust the bar's docking state
  920.  
  921.     // a little bit of AI: 
  922.     // memorize bar's height and width, when docked in 
  923.     // the current orientation - by making the current
  924.     // dimensions to be "preferred" ones for this docking state
  925.  
  926.     if ( !pBarToInsert->IsFixed() )
  927.     {
  928.         cbBarInfo& bar = *pBarToInsert;
  929.  
  930.         bar.mDimInfo.mSizes[ bar.mState ].x = bar.mBounds.width;
  931.         bar.mDimInfo.mSizes[ bar.mState ].y = bar.mBounds.height;
  932.     }
  933. }
  934.  
  935. void cbRowLayoutPlugin::OnRemoveBar ( cbRemoveBarEvent& event )
  936. {
  937.     cbBarInfo* pBar = event.mpBar;
  938.     mpPane          = event.mpPane;
  939.  
  940.     cbRowInfo* pRow = pBar->mpRow;
  941.  
  942.     mpLayout->GetUpdatesManager().OnBarWillChange( pBar, pRow, event.mpPane );
  943.  
  944.     // invalidate the whole row
  945.     //pFirst->mpRowInfo->mMgrData.mPrevBounds.x = -1;
  946.  
  947.     pRow->mBars.Remove( pBar );
  948.  
  949.     // rest bar information after removing it from the row
  950.     pBar->mpRow           = NULL;
  951.     pBar->mHasLeftHandle  = FALSE;
  952.     pBar->mHasRightHandle = FALSE;
  953.  
  954.     mpPane->InitLinksForRow( pRow ); // relink "mpNext/mpPrev"s
  955.  
  956.     if ( pRow->mBars.Count() == 0 )
  957.     {
  958.         // empty rows should not exist
  959.  
  960.         event.mpPane->GetRowList().Remove( pRow );
  961.  
  962.         delete pRow;
  963.  
  964.         mpPane->InitLinksForRows();
  965.     }
  966.     else
  967.     {
  968.         // force repainting of bars, in the row, from which the bar was removed
  969.  
  970.         // FIXME:: really needed?
  971.         pRow->mBars[0]->mUMgrData.SetDirty(TRUE);
  972.  
  973.         // re-setup mHasOnlyFixedBars flag for the row information
  974.         event.mpPane->SyncRowFlags( pRow );
  975.  
  976.         DetectBarHandles( pRow );
  977.  
  978.         if ( !pRow->mHasOnlyFixedBars )
  979.  
  980.             ExpandNotFixedBars( pRow );
  981.     }
  982. }
  983.  
  984. void cbRowLayoutPlugin::OnLayoutRow( cbLayoutRowEvent& event )
  985. {
  986.     cbRowInfo* pRow = event.mpRow;
  987.     mpPane          = event.mpPane;
  988.  
  989.     MinimzeNotFixedBars( pRow, NULL );
  990.  
  991.     if ( !pRow->mHasOnlyFixedBars )
  992.     {
  993.         // do proportional resizing of not-fixed bars 
  994.         ApplyLengthRatios( pRow );
  995.     }
  996.  
  997.     cbBarInfo& lastBar  = *pRow->mBars[ pRow->mBars.Count() - 1 ];
  998.     cbBarInfo& firstBar = *pRow->mBars[ 0 ];
  999.  
  1000.     // FIXME:: Next line not used
  1001.     // wxRect& bounds = lastBar.mBounds;
  1002.  
  1003.     if ( lastBar.mBounds.x + lastBar.mBounds.width > mpPane->mPaneWidth )
  1004.     {
  1005.         lastBar.mBounds.x = mpPane->mPaneWidth - lastBar.mBounds.width;
  1006.  
  1007.         // first simulate left-row-edge friction
  1008.  
  1009.         SlideLeftSideBars( &lastBar );
  1010.  
  1011.         if ( firstBar.mBounds.x < 0 )
  1012.             firstBar.mBounds.x = 0;
  1013.  
  1014.         // then left-row-edge function, though this
  1015.         // may cause some of the right-side bars going
  1016.         // out of row bounds, but left-side always
  1017.         // has the highest "priority"
  1018.  
  1019.         SlideRightSideBars( &firstBar );
  1020.     }
  1021.  
  1022.     event.Skip(); // pass event to the next handler
  1023. }
  1024.  
  1025. void cbRowLayoutPlugin::OnLayoutRows( cbLayoutRowsEvent& event )
  1026. {
  1027.     mpPane       = event.mpPane;
  1028.  
  1029.     int curY = 0;
  1030.  
  1031.     // FIXME:: Next line not used.
  1032.     // RowArrayT& arr = mpPane->GetRowList();
  1033.  
  1034.     size_t i;
  1035.     for ( i = 0; i != mpPane->GetRowList().Count(); ++i )
  1036.     {
  1037.         cbRowInfo& row = *mpPane->GetRowList()[ i ];
  1038.         //mpPane->CalcLengthRatios(& row);
  1039.  
  1040.         // setup "has-handle" flags for rows, which depend on the existance 
  1041.         // of not-fixed bars in the row
  1042.  
  1043.         if ( !row.mHasOnlyFixedBars )
  1044.         {
  1045.             if ( mpPane->mAlignment == FL_ALIGN_TOP ||
  1046.                  mpPane->mAlignment == FL_ALIGN_LEFT   )
  1047.             {
  1048.                 row.mHasLowerHandle = TRUE;
  1049.  
  1050.                 row.mHasUpperHandle = FALSE; 
  1051.             }
  1052.             else
  1053.             {
  1054.                 row.mHasUpperHandle = TRUE;
  1055.  
  1056.                 row.mHasLowerHandle = FALSE; 
  1057.             }
  1058.         }
  1059.         else
  1060.         {
  1061.             // otherwise, rows with fixed-bars only, have no height-resizing handles
  1062.             row.mHasUpperHandle = FALSE; 
  1063.             row.mHasLowerHandle = FALSE; 
  1064.         }
  1065.  
  1066.         // setup vertical positions for items in the row
  1067.  
  1068.         row.mRowY = curY;
  1069.  
  1070.         row.mRowWidth  = mpPane->mPaneWidth;
  1071.         row.mRowHeight = CalcRowHeight( row );
  1072.  
  1073.         LayoutItemsVertically( row );
  1074.  
  1075.         if ( row.mHasUpperHandle )
  1076.             row.mRowHeight += mpPane->mProps.mResizeHandleSize;
  1077.         if ( row.mHasLowerHandle )
  1078.             row.mRowHeight += mpPane->mProps.mResizeHandleSize;
  1079.  
  1080.         curY += row.mRowHeight;
  1081.     }
  1082.  
  1083.     event.Skip(); // pass event to the next handler - other hookeds plugin
  1084.                   // may also add some "refinements" to the layout now
  1085. }
  1086.  
  1087. void cbRowLayoutPlugin::OnResizeRow( cbResizeRowEvent& event )
  1088. {
  1089.     // extract resize-event info
  1090.     int     ofs            = event.mHandleOfs;
  1091.     bool    forUpperHandle = event.mForUpperHandle;
  1092.     cbRowInfo* pTheRow     = event.mpRow;
  1093.             mpPane         = event.mpPane;
  1094.  
  1095.     // FIXME:: Next line not used.
  1096.     //int     newHeight      = pTheRow->mRowHeight;
  1097.  
  1098.     int     freeSpc        = 0;
  1099.  
  1100.     if ( forUpperHandle )
  1101.     {
  1102.         // calculate available free space from above,
  1103.         // which can be obtained by squeezing not-fixed height rows
  1104.  
  1105.         cbRowInfo* pRow = pTheRow->mpPrev;
  1106.  
  1107.         while( pRow ) 
  1108.         {
  1109.             freeSpc += pRow->mRowHeight - event.mpPane->GetMinimalRowHeight( pRow );
  1110.  
  1111.             pRow = pRow->mpPrev;
  1112.         }
  1113.     }
  1114.     else
  1115.     {
  1116.         // calculate available free space from below,
  1117.         // which can be obtained by squeezing not-fixed height rows
  1118.  
  1119.         cbRowInfo* pRow = pTheRow->mpNext;
  1120.  
  1121.         while( pRow ) 
  1122.         {
  1123.             freeSpc += pRow->mRowHeight - mpPane->GetMinimalRowHeight( pRow );
  1124.  
  1125.             pRow = pRow->mpNext;
  1126.         }
  1127.     }
  1128.  
  1129.     mpLayout->GetUpdatesManager().OnStartChanges();
  1130.  
  1131.     int clientSize;
  1132.  
  1133.     // allow user adjusting pane vs. client-area space, for upper-handle
  1134.  
  1135.     if ( mpPane->IsHorizontal() )
  1136.  
  1137.         clientSize = mpLayout->GetClientHeight();
  1138.     else
  1139.         clientSize = mpLayout->GetClientWidth();
  1140.  
  1141.     if ( forUpperHandle && ofs < -clientSize )
  1142.     {
  1143.         int needed = -(ofs + clientSize);
  1144.  
  1145.         cbRowInfo* pRow = mpPane->GetRowList()[ 0 ];
  1146.  
  1147.         // start squeezing rows from the top row towards bottom
  1148.  
  1149.         while( pRow != pTheRow && needed )
  1150.         {
  1151.             // only not-fixed rows can be squeezed
  1152.  
  1153.             if ( !pRow->mHasOnlyFixedBars )
  1154.             {
  1155.                 int prevHeight = pRow->mRowHeight;
  1156.  
  1157.                 int newHeight  = wxMax( event.mpPane->GetMinimalRowHeight( pRow ), 
  1158.                                         prevHeight - needed );
  1159.  
  1160.                 if ( newHeight != prevHeight )
  1161.                 {
  1162.                     event.mpPane->SetRowHeight( pRow, newHeight );
  1163.  
  1164.                     needed -= prevHeight - pRow->mRowHeight;
  1165.                 }
  1166.             }
  1167.  
  1168.             pRow = pRow->mpNext;
  1169.         }
  1170.     }
  1171.  
  1172.     // allow user adjusting pane vs. client-area space, for lower-handle
  1173.  
  1174.     if ( !forUpperHandle && ofs > clientSize )
  1175.     {
  1176.         int needed = ofs - clientSize;
  1177.  
  1178.         cbRowInfo* pRow = mpPane->GetRowList()[ mpPane->GetRowList().Count() - 1 ];
  1179.  
  1180.         // start squeezing rows from the bottom towards the top row
  1181.  
  1182.         while( pRow && needed )
  1183.         {
  1184.             // only not-fixed rows can be squeezed
  1185.  
  1186.             if ( !pRow->mHasOnlyFixedBars )
  1187.             {
  1188.                 int prevHeight = pRow->mRowHeight;
  1189.  
  1190.                 int newHeight  = wxMax( event.mpPane->GetMinimalRowHeight( pRow ), 
  1191.                                         prevHeight - needed );
  1192.  
  1193.                 if ( newHeight != prevHeight )
  1194.                 {
  1195.                     event.mpPane->SetRowHeight( pRow, newHeight );
  1196.  
  1197.                     needed -= prevHeight - pRow->mRowHeight;
  1198.                 }
  1199.             }
  1200.  
  1201.             pRow = pRow->mpPrev;
  1202.         }
  1203.     }
  1204.  
  1205.     if ( forUpperHandle )
  1206.     
  1207.         event.mpPane->SetRowHeight( pTheRow, pTheRow->mRowHeight + (-ofs) );
  1208.     else
  1209.         event.mpPane->SetRowHeight( pTheRow, pTheRow->mRowHeight +   ofs  );
  1210.  
  1211.     mpLayout->RecalcLayout(FALSE);
  1212.  
  1213.     mpLayout->GetUpdatesManager().OnFinishChanges();
  1214.     mpLayout->GetUpdatesManager().UpdateNow();
  1215. }
  1216.  
  1217.