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 / gcupdatesmgr.cpp < prev    next >
C/C++ Source or Header  |  2002-01-21  |  12KB  |  411 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        gcupdatesmgr.cpp
  3. // Purpose:     cbGCUpdatesMgr class, optimizing refresh using GarbageCollector
  4. // Author:      Aleksandras Gluchovas
  5. // Modified by:
  6. // Created:     19/10/98
  7. // RCS-ID:      $Id: gcupdatesmgr.cpp,v 1.3 2002/01/21 22:34:42 JS Exp $
  8. // Copyright:   (c) Aleksandras Gluchovas 
  9. // Licence:       wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13.     #pragma implementation "gcupdatesmgr.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/gcupdatesmgr.h"
  28.  
  29. // helper function
  30.  
  31. static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
  32. {
  33.     if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
  34.          ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
  35.  
  36.         if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
  37.              ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
  38.              
  39.             return 1;
  40.  
  41.     return 0;
  42. }
  43.  
  44. // helper structure
  45.  
  46. struct cbRectInfo
  47. {
  48.     cbBarInfo*  mpBar;
  49.     cbDockPane* mpPane;
  50.     wxRect*     mpCurBounds;
  51.     wxRect*     mpPrevBounds;
  52. };
  53.  
  54. static inline cbRectInfo& node_to_rect_info( wxNode* pNode )
  55. {
  56.     return *( (cbRectInfo*) (pNode->Data()) );
  57. }
  58.  
  59. /***** Implementation for class cbSimpleUpdatesMgr *****/
  60.  
  61. IMPLEMENT_DYNAMIC_CLASS( cbGCUpdatesMgr, cbSimpleUpdatesMgr )
  62.  
  63. cbGCUpdatesMgr::cbGCUpdatesMgr( wxFrameLayout* pPanel )
  64.     : cbSimpleUpdatesMgr( pPanel )
  65. {}
  66.  
  67. void cbGCUpdatesMgr::AddItem( wxList&     itemList,
  68.                               cbBarInfo*  pBar, 
  69.                               cbDockPane* pPane,
  70.                               wxRect&     curBounds,
  71.                               wxRect&     prevBounds )
  72. {
  73.     cbRectInfo* pInfo = new cbRectInfo();
  74.  
  75.     pInfo->mpBar     = pBar;
  76.     pInfo->mpPane       = pPane;
  77.     pInfo->mpCurBounds  = &curBounds;
  78.     pInfo->mpPrevBounds = &prevBounds;
  79.  
  80.     itemList.Append( (wxObject*) pInfo );
  81. }
  82.  
  83. void cbGCUpdatesMgr::OnStartChanges()
  84. {
  85.     // memorize states of ALL items in the layout -
  86.     // this is quite excessive, but OK for the decent 
  87.     // implementation of updates manager
  88.  
  89.     mpLayout->GetPrevClientRect() = mpLayout->GetClientRect();
  90.  
  91.     cbDockPane** panes = mpLayout->GetPanesArray();
  92.  
  93.     for( int n = 0; n != MAX_PANES; ++n )
  94.     {
  95.         cbDockPane& pane = *(panes[n]);
  96.  
  97.         // store pane state
  98.         pane.mUMgrData.StoreItemState( pane.mBoundsInParent );
  99.         pane.mUMgrData.SetDirty( FALSE );
  100.  
  101.         cbRowInfo* pRow = pane.GetFirstRow();
  102.  
  103.         while ( pRow )
  104.         {
  105.             cbBarInfo* pBar = pRow->GetFirstBar();
  106.  
  107.             // store row state
  108.             pRow->mUMgrData.StoreItemState( pRow->mBoundsInParent );
  109.             pRow->mUMgrData.SetDirty( FALSE );
  110.  
  111.             while( pBar )
  112.             {
  113.                 // store bar state
  114.                 pBar->mUMgrData.StoreItemState( pBar->mBoundsInParent );
  115.                 pBar->mUMgrData.SetDirty( FALSE );
  116.  
  117.                 pBar = pBar->mpNext;
  118.             }
  119.  
  120.             pRow = pRow->mpNext;
  121.         }
  122.     }
  123. }
  124.  
  125. void cbGCUpdatesMgr::UpdateNow()
  126. {
  127.     cbDockPane** panes = mpLayout->GetPanesArray();
  128.  
  129.     wxRect& r1 = mpLayout->GetClientRect();
  130.     wxRect& r2 = mpLayout->GetPrevClientRect();
  131.  
  132.     // detect changes in client window's area
  133.  
  134.     bool clientWindowChanged = ( r1.x      != r2.x     ||
  135.                                  r1.y      != r2.y     ||
  136.                                  r1.width  != r2.width ||
  137.                                  r1.height != r2.height );
  138.  
  139.     // step #1 - detect changes in each row of each pane,
  140.     //           and repaint decorations around changed windows
  141.  
  142.     wxList mBarsToResize;
  143.  
  144.     int n;
  145.     for ( n = 0; n != MAX_PANES; ++n )
  146.     {
  147.         cbDockPane& pane = *(panes[n]);
  148.  
  149.         bool paneChanged = WasChanged( pane.mUMgrData, pane.mBoundsInParent );
  150.  
  151.         if ( paneChanged )
  152.         {
  153.             wxClientDC dc( &mpLayout->GetParentFrame() );
  154.             pane.PaintPaneBackground( dc );
  155.         }
  156.  
  157.         wxRect realBounds;
  158.  
  159.         cbRowInfo* pRow = pane.GetFirstRow();
  160.  
  161.         while ( pRow )
  162.         {
  163.             wxDC* pDc = 0;
  164.  
  165.             cbBarInfo* pBar = pRow->GetFirstBar();
  166.  
  167.             bool rowChanged = FALSE;
  168. //            bool rowBkPainted  = FALSE;
  169.  
  170.             // FIXME:: the below should not be fixed
  171.             cbBarInfo* barsToRepaint[128];
  172.             // number of bars, that were changed in the current row
  173.             int nBars = 0; 
  174.  
  175.             wxRect r1 = pRow->mUMgrData.mPrevBounds;
  176.             wxRect r2 = pRow->mBoundsInParent;
  177.  
  178.             if ( WasChanged( pRow->mUMgrData, pRow->mBoundsInParent ) )
  179.             
  180.                 rowChanged = TRUE;
  181.             else
  182.                 while( pBar )
  183.                 {
  184.                     if ( WasChanged( pBar->mUMgrData, pBar->mBoundsInParent ) )
  185.                     
  186.                         barsToRepaint[nBars++] = pBar;
  187.  
  188.                     pBar = pBar->mpNext;
  189.                 }
  190.  
  191.             if ( nBars || rowChanged )
  192.             {
  193.                 realBounds = pRow->mBoundsInParent;
  194.  
  195.                 // include 1-pixel thick shades around the row
  196.                 realBounds.x -= 1;
  197.                 realBounds.y -= 1;
  198.                 realBounds.width  += 2;
  199.                 realBounds.height += 2;
  200.  
  201.                 pDc = pane.StartDrawInArea( realBounds );
  202.             }
  203.  
  204.             if ( rowChanged )
  205.             {
  206.                 // postphone the resizement and refreshing the changed
  207.                 // bar windows
  208.  
  209.                 cbBarInfo* pCurBar = pRow->GetFirstBar();
  210.  
  211.                 while ( pCurBar )
  212.                 {
  213.                     if ( WasChanged( pCurBar->mUMgrData, 
  214.                                      pCurBar->mBoundsInParent ) )
  215.  
  216.                         AddItem( mBarsToResize, pCurBar, &pane, 
  217.                                  pCurBar->mBoundsInParent,
  218.                                  pCurBar->mUMgrData.mPrevBounds );
  219.  
  220.                     pCurBar = pCurBar->mpNext;
  221.                 }
  222.  
  223.                 // draw only their decorations now
  224.  
  225.                 pane.PaintRow( pRow, *pDc );
  226.             }
  227.             else
  228.             if ( nBars != 0 )
  229.             {
  230.                 for ( int i = 0; i != nBars; ++i )
  231.  
  232.                     // postphone the resizement and refreshing the changed
  233.                     // bar windows
  234.  
  235.                     AddItem( mBarsToResize, 
  236.                              barsToRepaint[i], 
  237.                              &pane, 
  238.                              barsToRepaint[i]->mBoundsInParent,
  239.                              barsToRepaint[i]->mUMgrData.mPrevBounds );
  240.  
  241.                 // redraw decorations of entire row, regardless of how much
  242.                 // of the bars were changed
  243.  
  244.                 pane.PaintRow( pRow, *pDc );
  245.             }
  246.  
  247.             if ( pDc )
  248.         
  249.                 pane.FinishDrawInArea( realBounds );
  250.  
  251.             pRow = pRow->mpNext;
  252.  
  253.         } // end of while
  254.  
  255.         if ( paneChanged )
  256.         {
  257.             wxClientDC dc( &mpLayout->GetParentFrame() );
  258.             pane.PaintPaneDecorations( dc );
  259.         }
  260.  
  261.     } // end of for
  262.  
  263.     if ( clientWindowChanged && !mpLayout->mClientWndRefreshPending )
  264.     {
  265.         // ptr to client-window object is "marked" as NULL
  266.  
  267.         AddItem( mBarsToResize, NULL, NULL, 
  268.                  mpLayout->GetClientRect(),
  269.                  mpLayout->GetPrevClientRect() );
  270.     }
  271.  
  272.     // step #2 - do ordered refreshing and resizing of bar window objects now
  273.  
  274.     DoRepositionItems( mBarsToResize );
  275. }
  276.  
  277. void cbGCUpdatesMgr::DoRepositionItems( wxList& items )
  278. {
  279.     wxNode* pNode1 = items.First();
  280.  
  281.     while( pNode1 )
  282.     {
  283.         cbRectInfo& info = node_to_rect_info( pNode1 );
  284.  
  285.         wxNode* pNode2 = items.First();
  286.  
  287.         // and node itself
  288.  
  289.         mGC.AddObject( &info );
  290.  
  291.         while( pNode2 )
  292.         {
  293.             if ( pNode2 != pNode1 ) // node should not depend on itself
  294.             {
  295.                 // Add references to objects on which this object
  296.                 // depends. Dependency here indicates intersection of current
  297.                 // bounds of this object with the initial bounds of the
  298.                 // other object.
  299.  
  300.                 cbRectInfo& otherInfo = node_to_rect_info( pNode2 );
  301.  
  302.                 if ( rect_hits_rect( *info.mpCurBounds, *otherInfo.mpPrevBounds ) )
  303.                 
  304.                                     // the node    depends on node
  305.                     mGC.AddDependency( &info,      &otherInfo      );
  306.             }
  307.  
  308.             pNode2 = pNode2->Next();
  309.         }
  310.  
  311.         pNode1 = pNode1->Next();
  312.     }
  313.  
  314.     mGC.ArrangeCollection(); // order nodes according "least-dependency" rule,
  315.                              // and find out cycled chains
  316.  
  317.     // Regular item nodes need to be resized, but not repainted (since
  318.     // they stand in linear (not cyclic) dependency with other
  319.     // regular nodes).
  320.  
  321.     wxNode* pNode = mGC.GetRegularObjects().First();
  322.  
  323.     while ( pNode )
  324.     {
  325.         cbRectInfo& info = *((cbRectInfo*)gc_node_to_obj(pNode));
  326.  
  327.         if ( info.mpBar == NULL ) 
  328.             
  329.             mpLayout->PositionClientWindow();
  330.         else
  331.             info.mpPane->SizeBar( info.mpBar );
  332.  
  333.         pNode = pNode->Next();
  334.     }
  335.  
  336.     // cycled item nodes, need to be both resized and repainted
  337.  
  338.     pNode = mGC.GetCycledObjects().First();
  339.  
  340.     while ( pNode )
  341.     {
  342.         cbRectInfo& info = *((cbRectInfo*)gc_node_to_obj(pNode));
  343.  
  344.         if ( info.mpBar == NULL ) 
  345.         {
  346.             wxWindow* pClntWnd = mpLayout->GetFrameClient();
  347.  
  348.             mpLayout->PositionClientWindow();
  349.  
  350.             // FIXME FIXME:: excessive!
  351.  
  352.             pClntWnd->Show( FALSE );
  353.             pClntWnd->Show( TRUE  );
  354.  
  355.             // OLD STUFF:: mpLayout->PositionClientWindow();
  356.         }
  357.         else
  358.         if ( info.mpBar->mpBarWnd )
  359.         {
  360.             wxWindow* pWnd = info.mpBar->mpBarWnd;
  361.  
  362.             // resize
  363.             info.mpPane->SizeBar( info.mpBar );
  364.  
  365.             // repaint
  366.  
  367.             /* OLD STUFF:: bool isChoice = info.mpBar->IsKindOf( CLASSINFO( wxChoice ) );
  368.  
  369.             //#ifdef __WINDOWS__
  370.             //int result = ::SendMessage( (HWND)pWnd->m_hWnd, WM_NCPAINT, 0, 0 );
  371.             //#endif
  372.             */
  373.  
  374.             // FIXME FIXME:: there's no other way to repaint non-client area of the wxWindow!!
  375.             //                 so we do *excessive* "hide 'n show"
  376.  
  377.             pWnd->Show(FALSE);
  378.             pWnd->Show(TRUE);
  379.                 
  380.             pWnd->Refresh();
  381.         }
  382.  
  383.         pNode = pNode->Next();
  384.     }
  385.  
  386.     // release data prepared for GC alg.
  387.  
  388.     pNode = items.First();
  389.  
  390.     while( pNode )
  391.     {
  392.         cbRectInfo* pInfo = (cbRectInfo*)(pNode->Data());
  393.  
  394.         delete pInfo;
  395.  
  396.         pNode = pNode->Next();
  397.     }
  398.  
  399.     mGC.Reset(); // reinit GC
  400.  
  401.     // FIXME:: this is a dirty-workaround for messy client-area,
  402.     //         as a result of docking bar out of floated-container window
  403.  
  404.     if ( mpLayout->mClientWndRefreshPending )
  405.     {
  406.         mpLayout->PositionClientWindow();
  407.         mpLayout->GetFrameClient()->Refresh();
  408.     }
  409. }
  410.  
  411.