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 / hintanimpl.cpp < prev    next >
C/C++ Source or Header  |  2002-01-21  |  11KB  |  398 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        hintanimpl.cpp
  3. // Purpose:     cbHintAnimationPlugin implementation.
  4. // Author:      Aleksandras Gluchovas
  5. // Modified by:
  6. // Created:     9/11/98
  7. // RCS-ID:      $Id: hintanimpl.cpp,v 1.2 2002/01/21 22:34:42 JS Exp $
  8. // Copyright:   (c) Aleksandras Gluchovas
  9. // Licence:       wxWindows license
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13.     #pragma implementation "hintanimpl.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/hintanimpl.h"
  28.  
  29. #define POS_UNDEFINED -32768
  30.  
  31. /***** Implementation for class cbHintAnimationPlugin *****/
  32.  
  33. // FIXME:: some of the below code should be eliminated by 
  34. //         reusing parts of cbBarDragPlugin's implementation
  35.  
  36. IMPLEMENT_DYNAMIC_CLASS( cbHintAnimationPlugin, cbPluginBase )
  37.  
  38. BEGIN_EVENT_TABLE( cbHintAnimationPlugin, cbPluginBase )
  39.  
  40.     EVT_PL_DRAW_HINT_RECT( cbHintAnimationPlugin::OnDrawHintRect )
  41.  
  42. END_EVENT_TABLE()
  43.  
  44. cbHintAnimationPlugin::cbHintAnimationPlugin(void)
  45.  
  46.     : mpScrDc( NULL ),
  47.       mpAnimTimer( 0 ),
  48.       mAnimStarted( FALSE ),
  49.       
  50.       mMorphDelay    ( 5   ),
  51.       mMaxFrames     ( 20   ),
  52.       mInClientHintBorder( 4 ),
  53.       mAccelerationOn( TRUE )
  54. {}
  55.  
  56. cbHintAnimationPlugin::cbHintAnimationPlugin( wxFrameLayout* pPanel, int paneMask )
  57.  
  58.     : cbPluginBase( pPanel, paneMask ),
  59.       mpScrDc( NULL ),
  60.       mpAnimTimer( 0 ),
  61.       mAnimStarted( FALSE ),
  62.  
  63.       mMorphDelay    ( 5   ),
  64.       mMaxFrames     ( 20   ),
  65.       mInClientHintBorder( 4 ),
  66.       mAccelerationOn( TRUE )
  67. {}
  68.  
  69. cbHintAnimationPlugin::~cbHintAnimationPlugin()
  70. {
  71.     if ( mpScrDc ) delete mpScrDc;
  72. }
  73.  
  74. /*** rect-tracking related methods ***/
  75.  
  76. void cbHintAnimationPlugin::OnDrawHintRect( cbDrawHintRectEvent& event )
  77. {
  78.     if ( !mAnimStarted && !mpScrDc ) 
  79.     {
  80.         StartTracking();
  81.  
  82.         mPrevInClient = event.mIsInClient;
  83.  
  84.         mPrevRect = event.mRect;
  85.  
  86.         mStopPending = FALSE;
  87.     }
  88.  
  89.     if ( !event.mEraseRect )
  90.     {
  91.         // pass on current hint-rect info to the animation "thread", in 
  92.         // order to make adjustments to the morph-target on-the-fly
  93.  
  94.         mCurRect.x = event.mRect.x;
  95.         mCurRect.y = event.mRect.y;
  96.         mCurRect.width  = event.mRect.width;
  97.         mCurRect.height = event.mRect.height;
  98.     }
  99.  
  100.     // check the amount of change in the shape of hint,
  101.     // and start morph-effect if change is "sufficient"
  102.  
  103.     int change = abs( mCurRect.width  - mPrevRect.width  ) +
  104.                  abs( mCurRect.height - mPrevRect.height );
  105.  
  106.     if ( change > 10 && !event.mLastTime && !event.mEraseRect )
  107.     {
  108.         if ( !mpAnimTimer )
  109.  
  110.             mpAnimTimer  = new cbHintAnimTimer();
  111.  
  112.         // init the animation "thread", or reinit if already started
  113.  
  114.         mpAnimTimer->Init( this, mAnimStarted );
  115.  
  116.         mAnimStarted = TRUE;
  117.     }
  118.     else
  119.     if ( !mAnimStarted )
  120.     {
  121.         DoDrawHintRect( event.mRect, event.mIsInClient );
  122.  
  123.         if ( event.mLastTime )
  124.  
  125.             FinishTracking();
  126.  
  127.         mPrevInClient = event.mIsInClient;
  128.     }
  129.     else
  130.     {
  131.         mCurInClient = event.mIsInClient;
  132.  
  133.         if ( event.mLastTime && mpAnimTimer ) 
  134.         {
  135.             mStopPending = TRUE;
  136.  
  137.             if ( mpAnimTimer->mPrevMorphed.x != POS_UNDEFINED )
  138.  
  139.                 // erase previous rect
  140.                 DoDrawHintRect( mpAnimTimer->mPrevMorphed, mPrevInClient );
  141.         }
  142.     }
  143.  
  144.     mPrevRect = event.mRect;
  145. }
  146.  
  147. #define _IMG_A  0xAA    // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
  148. #define _IMG_B  0x00    // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
  149. #define _IMG_C  0x55    // Note: modified from _C to _IMG_C, for consistency reasons.
  150. #define _IMG_D  0x00    // Note: modified from _D to _IMG_D, for consistency reasons.
  151.  
  152. static const unsigned char _gCheckerImg[16] = { _IMG_A,_IMG_B,_IMG_C,_IMG_D,
  153.                                                 _IMG_A,_IMG_B,_IMG_C,_IMG_D,
  154.                                                 _IMG_A,_IMG_B,_IMG_C,_IMG_D,
  155.                                                 _IMG_A,_IMG_B,_IMG_C,_IMG_D
  156.                                               };
  157.  
  158. void cbHintAnimationPlugin::StartTracking()
  159. {
  160.     mpScrDc = new wxScreenDC;
  161.  
  162.     wxScreenDC::StartDrawingOnTop(&mpLayout->GetParentFrame());
  163. }
  164.  
  165. void cbHintAnimationPlugin::DoDrawHintRect( wxRect& rect, bool isInClientRect)
  166. {
  167.     wxRect scrRect;
  168.  
  169.     RectToScr( rect, scrRect );
  170.  
  171.     int prevLF = mpScrDc->GetLogicalFunction();
  172.  
  173.     mpScrDc->SetLogicalFunction( wxXOR );
  174.  
  175.     if ( isInClientRect )
  176.     {
  177.         // BUG BUG BUG (wx):: somehow stippled brush works only  
  178.         //                      when the bitmap created on stack, not
  179.         //                      as a member of the class
  180.  
  181.         wxBitmap checker( (const char*)_gCheckerImg, 8,8 );
  182.  
  183.         wxBrush checkerBrush( checker );
  184.  
  185.         mpScrDc->SetPen( mpLayout->mNullPen );
  186.         mpScrDc->SetBrush( checkerBrush );
  187.  
  188.         int half = mInClientHintBorder / 2;
  189.  
  190.         mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y - half,
  191.                                 scrRect.width + 2*half, mInClientHintBorder );
  192.  
  193.         mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y + scrRect.height - half,
  194.                                 scrRect.width + 2*half, mInClientHintBorder );
  195.  
  196.         mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y + half - 1,
  197.                                 mInClientHintBorder, scrRect.height - 2*half + 2);
  198.  
  199.         mpScrDc->DrawRectangle( scrRect.x + scrRect.width - half,
  200.                                 scrRect.y + half - 1,
  201.                                 mInClientHintBorder, scrRect.height - 2*half + 2);
  202.  
  203.         mpScrDc->SetBrush( wxNullBrush );
  204.     }
  205.     else
  206.     {
  207.         // otherwise draw 1-pixel thin borders
  208.  
  209.         mpScrDc->SetPen( mpLayout->mBlackPen );
  210.  
  211.         mpScrDc->DrawLine( scrRect.x, scrRect.y, 
  212.                            scrRect.x + scrRect.width, scrRect.y );
  213.  
  214.         mpScrDc->DrawLine( scrRect.x, scrRect.y + 1, 
  215.                            scrRect.x, scrRect.y + scrRect.height );
  216.  
  217.         mpScrDc->DrawLine( scrRect.x+1, scrRect.y + scrRect.height, 
  218.                            scrRect.x + scrRect.width, scrRect.y + scrRect.height );
  219.  
  220.         mpScrDc->DrawLine( scrRect.x + scrRect.width , scrRect.y, 
  221.                            scrRect.x + scrRect.width, scrRect.y + scrRect.height + 1);
  222.     }
  223.  
  224.     mpScrDc->SetLogicalFunction( prevLF );
  225. }
  226.  
  227. void cbHintAnimationPlugin::DrawHintRect ( wxRect& rect, bool isInClientRect)
  228. {
  229.     DoDrawHintRect( rect, isInClientRect );    
  230. }
  231.  
  232. void cbHintAnimationPlugin::EraseHintRect( wxRect& rect, bool isInClientRect)
  233. {
  234.     DoDrawHintRect( rect, isInClientRect );    
  235. }
  236.  
  237. void cbHintAnimationPlugin::FinishTracking()
  238. {
  239.     wxScreenDC::EndDrawingOnTop();
  240.  
  241.     delete mpScrDc;
  242.  
  243.     mpScrDc = NULL;
  244. }
  245.  
  246. void cbHintAnimationPlugin::RectToScr( wxRect& frameRect, wxRect& scrRect )
  247. {
  248.     scrRect = frameRect;
  249.  
  250.     int x = frameRect.x, y = frameRect.y;
  251.  
  252.     mpLayout->GetParentFrame().ClientToScreen( &x, &y );
  253.  
  254.     scrRect.x = x;
  255.     scrRect.y = y;
  256. }
  257.  
  258. /***** Implementation for class cbHintAnimTimer *****/
  259.  
  260. cbHintAnimTimer::cbHintAnimTimer(void)
  261. {
  262. #ifdef __WINDOWS__
  263.     mLock = 0L;
  264. #endif
  265.  
  266.     mPrevMorphed.x = POS_UNDEFINED;
  267. }
  268.  
  269. void cbHintAnimTimer::MorphPoint( wxPoint& origin, MorphInfoT& info, wxPoint& point )
  270. {
  271.     // simulate lienar movement (FOR NOW:: without acceleration)
  272.  
  273.     double k;
  274.     
  275.     if ( mpPl->mAccelerationOn )
  276.         
  277.         k = double( mCurIter*mCurIter ) / 
  278.             double( (mpPl->mMaxFrames - 1)*(mpPl->mMaxFrames - 1) );
  279.     else
  280.         k = double( mCurIter ) / double( mpPl->mMaxFrames - 1 );
  281.  
  282.     point.x = int ( double ( info.mFrom.x + double (info.mTill.x - info.mFrom.x) * k ) );
  283.  
  284.     point.y = int ( double ( info.mFrom.y + double (info.mTill.y - info.mFrom.y) * k ) );
  285.  
  286.     point.x += origin.x;
  287.     point.y += origin.y;
  288. }
  289.  
  290. void cbHintAnimTimer::Notify(void)
  291. {
  292.     // FIXME:: "clean" implementation should use mutex to sync
  293.     //         between GUI and animation threads
  294.  
  295.     if ( mpPl->mStopPending )
  296.     {
  297.         Stop(); // top timer
  298.  
  299.         mpPl->FinishTracking();
  300.  
  301.         mpPl->mStopPending = FALSE;
  302.         mpPl->mpAnimTimer  = NULL;
  303.         mpPl->mAnimStarted = FALSE;
  304.  
  305.         mPrevMorphed.x = POS_UNDEFINED;
  306.  
  307.         delete this;
  308.  
  309.         return;
  310.     }
  311.  
  312.     wxPoint origin( mpPl->mCurRect.x, mpPl->mCurRect.y );
  313.  
  314.     wxPoint curUpper, curLower;
  315.  
  316.     MorphPoint( origin, mUpperLeft,  curUpper  );
  317.     MorphPoint( origin, mLowerRight, curLower );
  318.  
  319.     if ( mPrevMorphed.x != POS_UNDEFINED )
  320.  
  321.         // erase previous rect
  322.         mpPl->DoDrawHintRect( mPrevMorphed, mpPl->mPrevInClient );
  323.  
  324.     wxRect morphed( curUpper.x,  curUpper.y,
  325.                     curLower.x - curUpper.x,
  326.                     curLower.y - curUpper.y );
  327.  
  328.     // draw rect of current iteration
  329.     mpPl->DoDrawHintRect( morphed, 
  330.                           ( mCurIter != mpPl->mMaxFrames - 1 ) 
  331.                           ? mpPl->mPrevInClient : mpPl->mCurInClient );
  332.  
  333.     mPrevMorphed = morphed;
  334.  
  335.     if ( mCurIter == mpPl->mMaxFrames - 1 ) 
  336.     {
  337.         Stop(); // top timer
  338.         
  339.         mpPl->FinishTracking();
  340.         mpPl->mpAnimTimer  = NULL;
  341.         mpPl->mAnimStarted = FALSE;
  342.  
  343.         mPrevMorphed.x = POS_UNDEFINED;
  344.  
  345.         delete this;
  346.     }
  347.     else
  348.         ++mCurIter;
  349. }
  350.  
  351. bool cbHintAnimTimer::Init( cbHintAnimationPlugin* pAnimPl, bool reinit )
  352. {
  353.  
  354.     mpPl = pAnimPl;
  355.  
  356.     // morph-points are set up relatively to the upper-left corner
  357.     // of the current hint-rectangle
  358.  
  359.     if ( !reinit )
  360.     {
  361.         mUpperLeft.mFrom.x = mpPl->mPrevRect.x - mpPl->mCurRect.x;
  362.         mUpperLeft.mFrom.y = mpPl->mPrevRect.y - mpPl->mCurRect.y;
  363.  
  364.         mLowerRight.mFrom.x = ( mUpperLeft.mFrom.x + mpPl->mPrevRect.width  );
  365.         mLowerRight.mFrom.y = ( mUpperLeft.mFrom.y + mpPl->mPrevRect.height );
  366.     }
  367.     else
  368.     {
  369.         wxPoint origin( mpPl->mPrevRect.x, mpPl->mPrevRect.y );
  370.  
  371.         wxPoint curUpper, curLower;
  372.  
  373.         MorphPoint( origin, mUpperLeft,  curUpper  );
  374.         MorphPoint( origin, mLowerRight, curLower );
  375.  
  376.         mUpperLeft.mFrom.x = curUpper.x - mpPl->mCurRect.x;
  377.         mUpperLeft.mFrom.y = curUpper.y - mpPl->mCurRect.y;
  378.  
  379.         mLowerRight.mFrom.x = ( mUpperLeft.mFrom.x + curLower.x - curUpper.x );
  380.         mLowerRight.mFrom.y = ( mUpperLeft.mFrom.y + curLower.y - curUpper.y );
  381.     }
  382.  
  383.     mUpperLeft.mTill.x = 0;
  384.     mUpperLeft.mTill.y = 0;
  385.  
  386.     mLowerRight.mTill.x = mpPl->mCurRect.width;
  387.     mLowerRight.mTill.y = mpPl->mCurRect.height;
  388.  
  389.     mCurIter = 1;
  390.     
  391.     if ( !reinit )
  392.  
  393.         Start( mpPl->mMorphDelay );
  394.  
  395.     return TRUE;
  396. }
  397.  
  398.