]>
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 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
23 #include "wx/fl/hintanimpl.h"
25 #define POS_UNDEFINED -32768
27 /***** Implementation for class cbHintAnimationPlugin *****/
29 // FIXME:: some of the below code should be eliminated by
30 // reusing parts of cbBarDragPlugin's implementation
32 IMPLEMENT_DYNAMIC_CLASS( cbHintAnimationPlugin
, cbPluginBase
)
34 BEGIN_EVENT_TABLE( cbHintAnimationPlugin
, cbPluginBase
)
36 EVT_PL_DRAW_HINT_RECT( cbHintAnimationPlugin::OnDrawHintRect
)
40 cbHintAnimationPlugin::cbHintAnimationPlugin(void)
44 mAnimStarted( false ),
48 mInClientHintBorder( 4 ),
49 mAccelerationOn( true )
52 cbHintAnimationPlugin::cbHintAnimationPlugin( wxFrameLayout
* pPanel
, int paneMask
)
54 : cbPluginBase( pPanel
, paneMask
),
57 mAnimStarted( false ),
61 mInClientHintBorder( 4 ),
62 mAccelerationOn( true )
65 cbHintAnimationPlugin::~cbHintAnimationPlugin()
67 if ( mpScrDc
) delete mpScrDc
;
70 /*** rect-tracking related methods ***/
72 void cbHintAnimationPlugin::OnDrawHintRect( cbDrawHintRectEvent
& event
)
74 if ( !mAnimStarted
&& !mpScrDc
)
78 mPrevInClient
= event
.mIsInClient
;
80 mPrevRect
= event
.mRect
;
85 if ( !event
.mEraseRect
)
87 // pass on current hint-rect info to the animation "thread", in
88 // order to make adjustments to the morph-target on-the-fly
90 mCurRect
.x
= event
.mRect
.x
;
91 mCurRect
.y
= event
.mRect
.y
;
92 mCurRect
.width
= event
.mRect
.width
;
93 mCurRect
.height
= event
.mRect
.height
;
96 // check the amount of change in the shape of hint,
97 // and start morph-effect if change is "sufficient"
99 int change
= abs( mCurRect
.width
- mPrevRect
.width
) +
100 abs( mCurRect
.height
- mPrevRect
.height
);
102 if ( change
> 10 && !event
.mLastTime
&& !event
.mEraseRect
)
106 mpAnimTimer
= new cbHintAnimTimer();
108 // init the animation "thread", or reinit if already started
110 mpAnimTimer
->Init( this, mAnimStarted
);
117 DoDrawHintRect( event
.mRect
, event
.mIsInClient
);
119 if ( event
.mLastTime
)
123 mPrevInClient
= event
.mIsInClient
;
127 mCurInClient
= event
.mIsInClient
;
129 if ( event
.mLastTime
&& mpAnimTimer
)
133 if ( mpAnimTimer
->mPrevMorphed
.x
!= POS_UNDEFINED
)
135 // erase previous rect
136 DoDrawHintRect( mpAnimTimer
->mPrevMorphed
, mPrevInClient
);
140 mPrevRect
= event
.mRect
;
143 #define _IMG_A 0xAA // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
144 #define _IMG_B 0x00 // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
145 #define _IMG_C 0x55 // Note: modified from _C to _IMG_C, for consistency reasons.
146 #define _IMG_D 0x00 // Note: modified from _D to _IMG_D, for consistency reasons.
148 static const unsigned char _gCheckerImg
[16] = { _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
,
149 _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
,
150 _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
,
151 _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
154 void cbHintAnimationPlugin::StartTracking()
156 mpScrDc
= new wxScreenDC
;
158 wxScreenDC::StartDrawingOnTop(&mpLayout
->GetParentFrame());
161 void cbHintAnimationPlugin::DoDrawHintRect( wxRect
& rect
, bool isInClientRect
)
165 RectToScr( rect
, scrRect
);
167 int prevLF
= mpScrDc
->GetLogicalFunction();
169 mpScrDc
->SetLogicalFunction( wxXOR
);
171 if ( isInClientRect
)
173 // BUG BUG BUG (wx):: somehow stippled brush works only
174 // when the bitmap created on stack, not
175 // as a member of the class
177 wxBitmap
checker( (const char*)_gCheckerImg
, 8,8 );
179 wxBrush
checkerBrush( checker
);
181 mpScrDc
->SetPen( mpLayout
->mNullPen
);
182 mpScrDc
->SetBrush( checkerBrush
);
184 int half
= mInClientHintBorder
/ 2;
186 mpScrDc
->DrawRectangle( scrRect
.x
- half
, scrRect
.y
- half
,
187 scrRect
.width
+ 2*half
, mInClientHintBorder
);
189 mpScrDc
->DrawRectangle( scrRect
.x
- half
, scrRect
.y
+ scrRect
.height
- half
,
190 scrRect
.width
+ 2*half
, mInClientHintBorder
);
192 mpScrDc
->DrawRectangle( scrRect
.x
- half
, scrRect
.y
+ half
- 1,
193 mInClientHintBorder
, scrRect
.height
- 2*half
+ 2);
195 mpScrDc
->DrawRectangle( scrRect
.x
+ scrRect
.width
- half
,
196 scrRect
.y
+ half
- 1,
197 mInClientHintBorder
, scrRect
.height
- 2*half
+ 2);
199 mpScrDc
->SetBrush( wxNullBrush
);
203 // otherwise draw 1-pixel thin borders
205 mpScrDc
->SetPen( mpLayout
->mBlackPen
);
207 mpScrDc
->DrawLine( scrRect
.x
, scrRect
.y
,
208 scrRect
.x
+ scrRect
.width
, scrRect
.y
);
210 mpScrDc
->DrawLine( scrRect
.x
, scrRect
.y
+ 1,
211 scrRect
.x
, scrRect
.y
+ scrRect
.height
);
213 mpScrDc
->DrawLine( scrRect
.x
+1, scrRect
.y
+ scrRect
.height
,
214 scrRect
.x
+ scrRect
.width
, scrRect
.y
+ scrRect
.height
);
216 mpScrDc
->DrawLine( scrRect
.x
+ scrRect
.width
, scrRect
.y
,
217 scrRect
.x
+ scrRect
.width
, scrRect
.y
+ scrRect
.height
+ 1);
220 mpScrDc
->SetLogicalFunction( prevLF
);
223 void cbHintAnimationPlugin::DrawHintRect ( wxRect
& rect
, bool isInClientRect
)
225 DoDrawHintRect( rect
, isInClientRect
);
228 void cbHintAnimationPlugin::EraseHintRect( wxRect
& rect
, bool isInClientRect
)
230 DoDrawHintRect( rect
, isInClientRect
);
233 void cbHintAnimationPlugin::FinishTracking()
235 wxScreenDC::EndDrawingOnTop();
242 void cbHintAnimationPlugin::RectToScr( wxRect
& frameRect
, wxRect
& scrRect
)
246 int x
= frameRect
.x
, y
= frameRect
.y
;
248 mpLayout
->GetParentFrame().ClientToScreen( &x
, &y
);
254 /***** Implementation for class cbHintAnimTimer *****/
256 cbHintAnimTimer::cbHintAnimTimer(void)
262 mPrevMorphed
.x
= POS_UNDEFINED
;
265 void cbHintAnimTimer::MorphPoint( wxPoint
& origin
, MorphInfoT
& info
, wxPoint
& point
)
267 // simulate lienar movement (FOR NOW:: without acceleration)
271 if ( mpPl
->mAccelerationOn
)
273 k
= double( mCurIter
*mCurIter
) /
274 double( (mpPl
->mMaxFrames
- 1)*(mpPl
->mMaxFrames
- 1) );
276 k
= double( mCurIter
) / double( mpPl
->mMaxFrames
- 1 );
278 point
.x
= int ( double ( info
.mFrom
.x
+ double (info
.mTill
.x
- info
.mFrom
.x
) * k
) );
280 point
.y
= int ( double ( info
.mFrom
.y
+ double (info
.mTill
.y
- info
.mFrom
.y
) * k
) );
286 void cbHintAnimTimer::Notify(void)
288 // FIXME:: "clean" implementation should use mutex to sync
289 // between GUI and animation threads
291 if ( mpPl
->mStopPending
)
295 mpPl
->FinishTracking();
297 mpPl
->mStopPending
= false;
298 mpPl
->mpAnimTimer
= NULL
;
299 mpPl
->mAnimStarted
= false;
301 mPrevMorphed
.x
= POS_UNDEFINED
;
308 wxPoint
origin( mpPl
->mCurRect
.x
, mpPl
->mCurRect
.y
);
310 wxPoint curUpper
, curLower
;
312 MorphPoint( origin
, mUpperLeft
, curUpper
);
313 MorphPoint( origin
, mLowerRight
, curLower
);
315 if ( mPrevMorphed
.x
!= POS_UNDEFINED
)
317 // erase previous rect
318 mpPl
->DoDrawHintRect( mPrevMorphed
, mpPl
->mPrevInClient
);
320 wxRect
morphed( curUpper
.x
, curUpper
.y
,
321 curLower
.x
- curUpper
.x
,
322 curLower
.y
- curUpper
.y
);
324 // draw rect of current iteration
325 mpPl
->DoDrawHintRect( morphed
,
326 ( mCurIter
!= mpPl
->mMaxFrames
- 1 )
327 ? mpPl
->mPrevInClient
: mpPl
->mCurInClient
);
329 mPrevMorphed
= morphed
;
331 if ( mCurIter
== mpPl
->mMaxFrames
- 1 )
335 mpPl
->FinishTracking();
336 mpPl
->mpAnimTimer
= NULL
;
337 mpPl
->mAnimStarted
= false;
339 mPrevMorphed
.x
= POS_UNDEFINED
;
347 bool cbHintAnimTimer::Init( cbHintAnimationPlugin
* pAnimPl
, bool reinit
)
352 // morph-points are set up relatively to the upper-left corner
353 // of the current hint-rectangle
357 mUpperLeft
.mFrom
.x
= mpPl
->mPrevRect
.x
- mpPl
->mCurRect
.x
;
358 mUpperLeft
.mFrom
.y
= mpPl
->mPrevRect
.y
- mpPl
->mCurRect
.y
;
360 mLowerRight
.mFrom
.x
= ( mUpperLeft
.mFrom
.x
+ mpPl
->mPrevRect
.width
);
361 mLowerRight
.mFrom
.y
= ( mUpperLeft
.mFrom
.y
+ mpPl
->mPrevRect
.height
);
365 wxPoint
origin( mpPl
->mPrevRect
.x
, mpPl
->mPrevRect
.y
);
367 wxPoint curUpper
, curLower
;
369 MorphPoint( origin
, mUpperLeft
, curUpper
);
370 MorphPoint( origin
, mLowerRight
, curLower
);
372 mUpperLeft
.mFrom
.x
= curUpper
.x
- mpPl
->mCurRect
.x
;
373 mUpperLeft
.mFrom
.y
= curUpper
.y
- mpPl
->mCurRect
.y
;
375 mLowerRight
.mFrom
.x
= ( mUpperLeft
.mFrom
.x
+ curLower
.x
- curUpper
.x
);
376 mLowerRight
.mFrom
.y
= ( mUpperLeft
.mFrom
.y
+ curLower
.y
- curUpper
.y
);
379 mUpperLeft
.mTill
.x
= 0;
380 mUpperLeft
.mTill
.y
= 0;
382 mLowerRight
.mTill
.x
= mpPl
->mCurRect
.width
;
383 mLowerRight
.mTill
.y
= mpPl
->mCurRect
.height
;
389 Start( mpPl
->mMorphDelay
);