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 / antiflickpl.cpp next >
C/C++ Source or Header  |  2002-01-21  |  6KB  |  237 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        antiflickpl.cpp
  3. // Purpose:     Double-buffering plugin class for reducing flickering.
  4. // Author:      Aleksandras Gluchovas (@Lithuania)
  5. // Modified by:
  6. // Created:     23/10/98
  7. // RCS-ID:      $Id: antiflickpl.cpp,v 1.2 2002/01/21 22:34:41 JS Exp $
  8. // Copyright:   (c) Aleksandras Gluchovas
  9. // Licence:       wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13.     #pragma implementation "antiflickpl.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/antiflickpl.h"
  28.  
  29. /***** Implementation for class cbAntiflickerPlugin *****/
  30.  
  31. IMPLEMENT_DYNAMIC_CLASS( cbAntiflickerPlugin, cbPluginBase )
  32.  
  33. BEGIN_EVENT_TABLE( cbAntiflickerPlugin, cbPluginBase )
  34.  
  35.     EVT_PL_START_DRAW_IN_AREA  ( cbAntiflickerPlugin::OnStartDrawInArea  )
  36.     EVT_PL_FINISH_DRAW_IN_AREA ( cbAntiflickerPlugin::OnFinishDrawInArea )
  37.  
  38. END_EVENT_TABLE()
  39.  
  40. // initialization of static members
  41.  
  42. int cbAntiflickerPlugin::mRefCount    = 0;
  43.  
  44. wxBitmap*   cbAntiflickerPlugin::mpVertBuf    = 0;
  45. wxBitmap*   cbAntiflickerPlugin::mpHorizBuf   = 0;
  46. wxMemoryDC* cbAntiflickerPlugin::mpVertBufDc  = 0;
  47. wxMemoryDC* cbAntiflickerPlugin::mpHorizBufDc = 0;
  48.  
  49. // constructors
  50.  
  51. cbAntiflickerPlugin::cbAntiflickerPlugin(void)
  52.     : mpLRUBufDc  ( NULL ),
  53.       mLRUArea    ( -1,-1, -1,-1 )
  54. {
  55.     ++mRefCount;
  56. }
  57.  
  58. cbAntiflickerPlugin::cbAntiflickerPlugin( wxFrameLayout* pPanel, int paneMask )
  59.  
  60.     : cbPluginBase( pPanel, paneMask ),
  61.       mpLRUBufDc  ( NULL ),
  62.       mLRUArea    ( -1,-1, -1,-1 )
  63. {
  64.     ++mRefCount;
  65. }
  66.  
  67. cbAntiflickerPlugin::~cbAntiflickerPlugin()
  68. {
  69.     if ( --mRefCount == 0 )
  70.     {
  71.         if ( mpHorizBuf )
  72.         {
  73.             mpHorizBufDc->SelectObject( wxNullBitmap );
  74.             delete mpHorizBuf;
  75.             delete mpHorizBufDc;
  76.             mpHorizBuf   = 0;
  77.             mpHorizBufDc = 0;
  78.         }
  79.  
  80.         if ( mpVertBuf ) 
  81.         {
  82.             mpVertBufDc->SelectObject( wxNullBitmap );
  83.             delete mpVertBuf; 
  84.             delete mpVertBufDc;
  85.             mpVertBuf   = 0;
  86.             mpVertBufDc = 0;
  87.         }
  88.     }
  89. }
  90.  
  91. wxDC* cbAntiflickerPlugin::FindSuitableBuffer( const wxRect& forArea )
  92. {
  93.     if ( mpVertBuf )
  94.     {
  95.         if ( mpVertBuf->GetHeight() >= forArea.height &&
  96.              mpVertBuf->GetWidth()  >= forArea.width )
  97.  
  98.              return mpVertBufDc;
  99.     }
  100.     else
  101.     if ( mpHorizBuf )
  102.     {
  103.         if ( mpHorizBuf->GetHeight() >= forArea.height &&
  104.              mpHorizBuf->GetWidth()  >= forArea.width )
  105.  
  106.              return mpHorizBufDc;
  107.     }
  108.  
  109.     return 0;
  110. }
  111.  
  112. wxDC* cbAntiflickerPlugin::AllocNewBuffer( const wxRect& forArea )
  113. {
  114.     // TBD:: preallocate bit larger bitmap at once, to avoid
  115.     //       excessive realocations later
  116.  
  117.     // check whether the given area is oriented horizontally
  118.     // or vertically and choose corresponding bitmap to create or
  119.     // recreate
  120.  
  121.     if ( forArea.height > forArea.width )
  122.     {
  123.         wxSize prevDim( 0,0 );
  124.  
  125.         if ( mpVertBuf ) 
  126.         {
  127.             prevDim.x = mpVertBuf->GetWidth();
  128.             prevDim.y = mpVertBuf->GetHeight();
  129.  
  130.             mpVertBufDc->SelectObject( wxNullBitmap );
  131.             delete mpVertBuf;
  132.         }
  133.         else
  134.             mpVertBufDc = new wxMemoryDC();
  135.         
  136.         mpVertBuf = new wxBitmap( int( wxMax(forArea.width,  prevDim.x ) ), 
  137.                                   int( wxMax(forArea.height, prevDim.y ) )
  138.                                 );
  139.  
  140.         mpVertBufDc->SelectObject( *mpVertBuf );
  141.  
  142.         return mpVertBufDc;
  143.     }
  144.     else
  145.     {
  146.         wxSize prevDim( 0,0 );
  147.  
  148.         if ( mpHorizBuf ) 
  149.         {
  150.             prevDim.x = mpHorizBuf->GetWidth();
  151.             prevDim.y = mpHorizBuf->GetHeight();
  152.  
  153.             mpHorizBufDc->SelectObject( wxNullBitmap );
  154.             delete mpHorizBuf;
  155.         }
  156.         else
  157.             mpHorizBufDc = new wxMemoryDC();
  158.         
  159.         mpHorizBuf = new wxBitmap( int( wxMax(forArea.width,  prevDim.x ) ), 
  160.                                    int( wxMax(forArea.height, prevDim.y ) )
  161.                                  );
  162.  
  163.         mpHorizBufDc->SelectObject( *mpHorizBuf );
  164.  
  165.         return mpHorizBufDc;
  166.     }
  167. }
  168.  
  169. void cbAntiflickerPlugin::OnStartDrawInArea( cbStartDrawInAreaEvent& event )
  170. {
  171.     wxASSERT( mpLRUBufDc == NULL ); // DBG:: see comments in OnFinishDrawInArea(..) method
  172.  
  173.     // short-cut
  174.     wxRect& area = event.mArea;
  175.  
  176.     if ( event.mArea.width  < 0 || 
  177.          event.mArea.height < 0 ) return;
  178.  
  179.     // memorize given area
  180.     mLRUArea.x      = area.x;
  181.     mLRUArea.y      = area.y;
  182.     mLRUArea.width  = area.width;
  183.     mLRUArea.height = area.height;
  184.  
  185.     wxDC* pBufDc = FindSuitableBuffer( area );
  186.  
  187.     if ( !pBufDc )
  188.     
  189.         pBufDc = AllocNewBuffer( area );
  190.  
  191.     pBufDc->SetDeviceOrigin( -area.x, -area.y );
  192.  
  193.     pBufDc->SetClippingRegion( area.x,     area.y,
  194.                                area.width, area.height );
  195.  
  196.     wxClientDC clntDc( &mpLayout->GetParentFrame() );
  197.  
  198.     (*event.mppDc) = pBufDc;
  199.  
  200.     mpLRUBufDc = pBufDc; // memorize buffer, which will be flushed to screen
  201.                          // upon "commiting" the drawing
  202.  
  203.     /*
  204.     // OLD STUFF::
  205.     mpLRUBufDc->Blit( pos.x, pos.y, size.x, size.y,
  206.                       &clntDc, pos.x, pos.y, wxCOPY );
  207.                     */
  208. }
  209.  
  210. void cbAntiflickerPlugin::OnFinishDrawInArea( cbFinishDrawInAreaEvent& event )
  211. {
  212.     wxRect& area = event.mArea;
  213.  
  214.     if ( event.mArea.width  < 0 || 
  215.          event.mArea.height < 0 ) return;
  216.  
  217.     wxASSERT( mpLRUBufDc ); // DBG:: OnStartDrawInArea should be called first
  218.  
  219.     // FOR NOW:: OnStartDrawInArea(..) should be immediately followed
  220.     //           by OnFinishDrawInArea(..) for the same area
  221.  
  222.     wxASSERT( mLRUArea.x      == area.x      );
  223.     wxASSERT( mLRUArea.y      == area.y      );
  224.     wxASSERT( mLRUArea.width  == area.width  );
  225.     wxASSERT( mLRUArea.height == area.height );
  226.  
  227.     wxClientDC clntDc( &mpLayout->GetParentFrame() );
  228.  
  229.     // "commit" drawings in one-shot
  230.     clntDc.Blit( area.x, area.y, area.width, area.height,
  231.                  mpLRUBufDc, area.x, area.y, wxCOPY );
  232.  
  233.     mpLRUBufDc->DestroyClippingRegion();
  234.     mpLRUBufDc = 0;
  235. }
  236.  
  237.