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