]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/hintanimpl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: hintanimpl.cpp
3 // Purpose: cbHintAnimationPlugin implementation.
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "hintanimpl.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #include "wx/fl/hintanimpl.h"
29 #define POS_UNDEFINED -32768
31 /***** Implementation for class cbHintAnimationPlugin *****/
33 // FIXME:: some of the below code should be eliminated by
34 // reusing parts of cbBarDragPlugin's implementation
36 IMPLEMENT_DYNAMIC_CLASS( cbHintAnimationPlugin
, cbPluginBase
)
38 BEGIN_EVENT_TABLE( cbHintAnimationPlugin
, cbPluginBase
)
40 EVT_PL_DRAW_HINT_RECT( cbHintAnimationPlugin::OnDrawHintRect
)
44 cbHintAnimationPlugin::cbHintAnimationPlugin(void)
48 mAnimStarted( FALSE
),
52 mInClientHintBorder( 4 ),
53 mAccelerationOn( TRUE
)
56 cbHintAnimationPlugin::cbHintAnimationPlugin( wxFrameLayout
* pPanel
, int paneMask
)
58 : cbPluginBase( pPanel
, paneMask
),
61 mAnimStarted( FALSE
),
65 mInClientHintBorder( 4 ),
66 mAccelerationOn( TRUE
)
69 cbHintAnimationPlugin::~cbHintAnimationPlugin()
71 if ( mpScrDc
) delete mpScrDc
;
74 /*** rect-tracking related methods ***/
76 void cbHintAnimationPlugin::OnDrawHintRect( cbDrawHintRectEvent
& event
)
78 if ( !mAnimStarted
&& !mpScrDc
)
82 mPrevInClient
= event
.mIsInClient
;
84 mPrevRect
= event
.mRect
;
89 if ( !event
.mEraseRect
)
91 // pass on current hint-rect info to the animation "thread", in
92 // order to make adjustments to the morph-target on-the-fly
94 mCurRect
.x
= event
.mRect
.x
;
95 mCurRect
.y
= event
.mRect
.y
;
96 mCurRect
.width
= event
.mRect
.width
;
97 mCurRect
.height
= event
.mRect
.height
;
100 // check the amount of change in the shape of hint,
101 // and start morph-effect if change is "sufficient"
103 int change
= abs( mCurRect
.width
- mPrevRect
.width
) +
104 abs( mCurRect
.height
- mPrevRect
.height
);
106 if ( change
> 10 && !event
.mLastTime
&& !event
.mEraseRect
)
110 mpAnimTimer
= new cbHintAnimTimer();
112 // init the animation "thread", or reinit if already started
114 mpAnimTimer
->Init( this, mAnimStarted
);
121 DoDrawHintRect( event
.mRect
, event
.mIsInClient
);
123 if ( event
.mLastTime
)
127 mPrevInClient
= event
.mIsInClient
;
131 mCurInClient
= event
.mIsInClient
;
133 if ( event
.mLastTime
&& mpAnimTimer
)
137 if ( mpAnimTimer
->mPrevMorphed
.x
!= POS_UNDEFINED
)
139 // erase previous rect
140 DoDrawHintRect( mpAnimTimer
->mPrevMorphed
, mPrevInClient
);
144 mPrevRect
= event
.mRect
;
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.
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
158 void cbHintAnimationPlugin::StartTracking()
160 mpScrDc
= new wxScreenDC
;
162 wxScreenDC::StartDrawingOnTop(&mpLayout
->GetParentFrame());
165 void cbHintAnimationPlugin::DoDrawHintRect( wxRect
& rect
, bool isInClientRect
)
169 RectToScr( rect
, scrRect
);
171 int prevLF
= mpScrDc
->GetLogicalFunction();
173 mpScrDc
->SetLogicalFunction( wxXOR
);
175 if ( isInClientRect
)
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
181 wxBitmap
checker( (const char*)_gCheckerImg
, 8,8 );
183 wxBrush
checkerBrush( checker
);
185 mpScrDc
->SetPen( mpLayout
->mNullPen
);
186 mpScrDc
->SetBrush( checkerBrush
);
188 int half
= mInClientHintBorder
/ 2;
190 mpScrDc
->DrawRectangle( scrRect
.x
- half
, scrRect
.y
- half
,
191 scrRect
.width
+ 2*half
, mInClientHintBorder
);
193 mpScrDc
->DrawRectangle( scrRect
.x
- half
, scrRect
.y
+ scrRect
.height
- half
,
194 scrRect
.width
+ 2*half
, mInClientHintBorder
);
196 mpScrDc
->DrawRectangle( scrRect
.x
- half
, scrRect
.y
+ half
- 1,
197 mInClientHintBorder
, scrRect
.height
- 2*half
+ 2);
199 mpScrDc
->DrawRectangle( scrRect
.x
+ scrRect
.width
- half
,
200 scrRect
.y
+ half
- 1,
201 mInClientHintBorder
, scrRect
.height
- 2*half
+ 2);
203 mpScrDc
->SetBrush( wxNullBrush
);
207 // otherwise draw 1-pixel thin borders
209 mpScrDc
->SetPen( mpLayout
->mBlackPen
);
211 mpScrDc
->DrawLine( scrRect
.x
, scrRect
.y
,
212 scrRect
.x
+ scrRect
.width
, scrRect
.y
);
214 mpScrDc
->DrawLine( scrRect
.x
, scrRect
.y
+ 1,
215 scrRect
.x
, scrRect
.y
+ scrRect
.height
);
217 mpScrDc
->DrawLine( scrRect
.x
+1, scrRect
.y
+ scrRect
.height
,
218 scrRect
.x
+ scrRect
.width
, scrRect
.y
+ scrRect
.height
);
220 mpScrDc
->DrawLine( scrRect
.x
+ scrRect
.width
, scrRect
.y
,
221 scrRect
.x
+ scrRect
.width
, scrRect
.y
+ scrRect
.height
+ 1);
224 mpScrDc
->SetLogicalFunction( prevLF
);
227 void cbHintAnimationPlugin::DrawHintRect ( wxRect
& rect
, bool isInClientRect
)
229 DoDrawHintRect( rect
, isInClientRect
);
232 void cbHintAnimationPlugin::EraseHintRect( wxRect
& rect
, bool isInClientRect
)
234 DoDrawHintRect( rect
, isInClientRect
);
237 void cbHintAnimationPlugin::FinishTracking()
239 wxScreenDC::EndDrawingOnTop();
246 void cbHintAnimationPlugin::RectToScr( wxRect
& frameRect
, wxRect
& scrRect
)
250 int x
= frameRect
.x
, y
= frameRect
.y
;
252 mpLayout
->GetParentFrame().ClientToScreen( &x
, &y
);
258 /***** Implementation for class cbHintAnimTimer *****/
260 cbHintAnimTimer::cbHintAnimTimer(void)
266 mPrevMorphed
.x
= POS_UNDEFINED
;
269 void cbHintAnimTimer::MorphPoint( wxPoint
& origin
, MorphInfoT
& info
, wxPoint
& point
)
271 // simulate lienar movement (FOR NOW:: without acceleration)
275 if ( mpPl
->mAccelerationOn
)
277 k
= double( mCurIter
*mCurIter
) /
278 double( (mpPl
->mMaxFrames
- 1)*(mpPl
->mMaxFrames
- 1) );
280 k
= double( mCurIter
) / double( mpPl
->mMaxFrames
- 1 );
282 point
.x
= int ( double ( info
.mFrom
.x
+ double (info
.mTill
.x
- info
.mFrom
.x
) * k
) );
284 point
.y
= int ( double ( info
.mFrom
.y
+ double (info
.mTill
.y
- info
.mFrom
.y
) * k
) );
290 void cbHintAnimTimer::Notify(void)
292 // FIXME:: "clean" implementation should use mutex to sync
293 // between GUI and animation threads
295 if ( mpPl
->mStopPending
)
299 mpPl
->FinishTracking();
301 mpPl
->mStopPending
= FALSE
;
302 mpPl
->mpAnimTimer
= NULL
;
303 mpPl
->mAnimStarted
= FALSE
;
305 mPrevMorphed
.x
= POS_UNDEFINED
;
312 wxPoint
origin( mpPl
->mCurRect
.x
, mpPl
->mCurRect
.y
);
314 wxPoint curUpper
, curLower
;
316 MorphPoint( origin
, mUpperLeft
, curUpper
);
317 MorphPoint( origin
, mLowerRight
, curLower
);
319 if ( mPrevMorphed
.x
!= POS_UNDEFINED
)
321 // erase previous rect
322 mpPl
->DoDrawHintRect( mPrevMorphed
, mpPl
->mPrevInClient
);
324 wxRect
morphed( curUpper
.x
, curUpper
.y
,
325 curLower
.x
- curUpper
.x
,
326 curLower
.y
- curUpper
.y
);
328 // draw rect of current iteration
329 mpPl
->DoDrawHintRect( morphed
,
330 ( mCurIter
!= mpPl
->mMaxFrames
- 1 )
331 ? mpPl
->mPrevInClient
: mpPl
->mCurInClient
);
333 mPrevMorphed
= morphed
;
335 if ( mCurIter
== mpPl
->mMaxFrames
- 1 )
339 mpPl
->FinishTracking();
340 mpPl
->mpAnimTimer
= NULL
;
341 mpPl
->mAnimStarted
= FALSE
;
343 mPrevMorphed
.x
= POS_UNDEFINED
;
351 bool cbHintAnimTimer::Init( cbHintAnimationPlugin
* pAnimPl
, bool reinit
)
356 // morph-points are set up relatively to the upper-left corner
357 // of the current hint-rectangle
361 mUpperLeft
.mFrom
.x
= mpPl
->mPrevRect
.x
- mpPl
->mCurRect
.x
;
362 mUpperLeft
.mFrom
.y
= mpPl
->mPrevRect
.y
- mpPl
->mCurRect
.y
;
364 mLowerRight
.mFrom
.x
= ( mUpperLeft
.mFrom
.x
+ mpPl
->mPrevRect
.width
);
365 mLowerRight
.mFrom
.y
= ( mUpperLeft
.mFrom
.y
+ mpPl
->mPrevRect
.height
);
369 wxPoint
origin( mpPl
->mPrevRect
.x
, mpPl
->mPrevRect
.y
);
371 wxPoint curUpper
, curLower
;
373 MorphPoint( origin
, mUpperLeft
, curUpper
);
374 MorphPoint( origin
, mLowerRight
, curLower
);
376 mUpperLeft
.mFrom
.x
= curUpper
.x
- mpPl
->mCurRect
.x
;
377 mUpperLeft
.mFrom
.y
= curUpper
.y
- mpPl
->mCurRect
.y
;
379 mLowerRight
.mFrom
.x
= ( mUpperLeft
.mFrom
.x
+ curLower
.x
- curUpper
.x
);
380 mLowerRight
.mFrom
.y
= ( mUpperLeft
.mFrom
.y
+ curLower
.y
- curUpper
.y
);
383 mUpperLeft
.mTill
.x
= 0;
384 mUpperLeft
.mTill
.y
= 0;
386 mLowerRight
.mTill
.x
= mpPl
->mCurRect
.width
;
387 mLowerRight
.mTill
.y
= mpPl
->mCurRect
.height
;
393 Start( mpPl
->mMorphDelay
);