|
1 /* |
|
2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: ?Description |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <AknsDrawUtils.h> |
|
20 |
|
21 #include "EIKFANIM.H" |
|
22 |
|
23 /** |
|
24 * High priority is well argumented because running the active object will |
|
25 * result in animation deletion -> resources released. |
|
26 */ |
|
27 CEikFormAnim::CEikFormAnim(): CActive( EPriorityHigh ) |
|
28 { |
|
29 // Derived from CActive (derives from CBase) -> members zeroed |
|
30 } |
|
31 |
|
32 void CEikFormAnim::ConstructL() |
|
33 { |
|
34 iAnimFlags.Set( EFlagUseAnimation ); // Animations are created by default |
|
35 CActiveScheduler::Add( this ); |
|
36 } |
|
37 |
|
38 CEikFormAnim* CEikFormAnim::NewL() |
|
39 { |
|
40 CEikFormAnim* self = new(ELeave) CEikFormAnim(); |
|
41 CleanupStack::PushL( self ); |
|
42 self->ConstructL(); |
|
43 CleanupStack::Pop( self ); |
|
44 return self; |
|
45 } |
|
46 |
|
47 CEikFormAnim::~CEikFormAnim() |
|
48 { |
|
49 Cancel(); |
|
50 |
|
51 // Stop receiving foreground events |
|
52 CCoeEnv* env = CCoeEnv::Static(); |
|
53 env->RemoveForegroundObserver( *this ); |
|
54 |
|
55 delete iAnimation; |
|
56 } |
|
57 |
|
58 void CEikFormAnim::SetObserver( MEikFormAnimObserver* aObserver ) |
|
59 { |
|
60 iObserver = aObserver; |
|
61 } |
|
62 |
|
63 MEikFormAnimObserver* CEikFormAnim::Observer() |
|
64 { |
|
65 return iObserver; |
|
66 } |
|
67 |
|
68 void CEikFormAnim::NoAnimIfError( TInt aError ) |
|
69 { |
|
70 if( KErrNone != aError ) |
|
71 UseNoAnimation(); |
|
72 } |
|
73 |
|
74 /** |
|
75 * Reconfigures the animation size. Animation construction is attempted when |
|
76 * this method is called for the first time. |
|
77 * |
|
78 * @param aItemCellSize The size of the list cell highlight |
|
79 */ |
|
80 void CEikFormAnim::SetHighlightSize( const TSize& aItemCellSize ) |
|
81 { |
|
82 if( iAnimation ) // Animation exists -> try to resize |
|
83 { |
|
84 if( iAnimation->Size() == aItemCellSize ) |
|
85 { |
|
86 return; |
|
87 } |
|
88 |
|
89 // Resize animation |
|
90 TBool aboutToStart = ETrue; |
|
91 if( iAnimation->State() == EAknsAnimStateStopped ) |
|
92 aboutToStart = EFalse; |
|
93 |
|
94 TRAPD( err, DoResizeL( aItemCellSize, aboutToStart ) ); |
|
95 if( KErrNone != err ) |
|
96 { |
|
97 // Repaint is not allowed inside resize |
|
98 UseNoAnimation(); |
|
99 } |
|
100 } |
|
101 else if( iAnimFlags.IsSet( EFlagUseAnimation ) ) |
|
102 { |
|
103 // This must be the first call because animation does not exist. |
|
104 TRAPD( err, CreateAnimationL( aItemCellSize ) ); |
|
105 if( KErrNone != err ) |
|
106 { |
|
107 // Repaint is not allowed inside resize |
|
108 UseNoAnimation(); |
|
109 } |
|
110 } |
|
111 } |
|
112 |
|
113 CAknsEffectAnim* CEikFormAnim::Animation() const |
|
114 { |
|
115 return iAnimation; |
|
116 } |
|
117 |
|
118 /** |
|
119 * Falls back to normal rendering. |
|
120 */ |
|
121 void CEikFormAnim::UseNoAnimation() |
|
122 { |
|
123 delete iAnimation; |
|
124 iAnimation = NULL; |
|
125 |
|
126 // Do not attempt to create animations in the future |
|
127 iAnimFlags.Clear( EFlagUseAnimation ); |
|
128 |
|
129 // Stop receiving foreground events |
|
130 CCoeEnv* env = CCoeEnv::Static(); |
|
131 env->RemoveForegroundObserver( *this ); |
|
132 } |
|
133 |
|
134 void CEikFormAnim::Play() |
|
135 { |
|
136 if( iAnimation ) |
|
137 { |
|
138 if( EAknsAnimStatePaused == iAnimation->State() ) |
|
139 { |
|
140 NoAnimIfError( iAnimation->Continue() ); |
|
141 } |
|
142 else if( EAknsAnimStateStopped == iAnimation->State() ) |
|
143 { |
|
144 TRAPD( err, DoResizeL( iAnimation->Size(), ETrue ) ); |
|
145 NoAnimIfError( err ); |
|
146 |
|
147 if( KErrNone != err ) |
|
148 return; |
|
149 |
|
150 NoAnimIfError( iAnimation->Start() ); |
|
151 } |
|
152 } |
|
153 } |
|
154 |
|
155 void CEikFormAnim::Pause() |
|
156 { |
|
157 if( iAnimation ) |
|
158 { |
|
159 NoAnimIfError( iAnimation->Pause() ); |
|
160 } |
|
161 } |
|
162 |
|
163 void CEikFormAnim::ChangeHighlightBackground() |
|
164 { |
|
165 // Every time the current list item is changed we need to change the |
|
166 // animation input layer (animated element is the highlight bacground that |
|
167 // can differ between highlight positions). |
|
168 if( iAnimation && iObserver ) |
|
169 { |
|
170 if( iAnimation->State() == EAknsAnimStateStopped ) |
|
171 { |
|
172 // Input layers don't exist when stopped or finished. We need to |
|
173 // resize to create the input layers and to update the output |
|
174 // layer. |
|
175 TRAPD( err, DoResizeL( iAnimation->Size(), EFalse ) ); |
|
176 NoAnimIfError( err ); |
|
177 } |
|
178 else // Either paused, running or finished |
|
179 { |
|
180 // Update the highlight background |
|
181 if( iAnimation->InputRgbGc() ) |
|
182 iObserver->AnimDrawHighlightBackground( *iAnimation->InputRgbGc() ); |
|
183 |
|
184 // We need to update the output frame (otherwise the highlight |
|
185 // would drawn with the old output before the next new animation |
|
186 // frame). |
|
187 NoAnimIfError( iAnimation->UpdateOutput() ); |
|
188 } |
|
189 } |
|
190 } |
|
191 |
|
192 TSize CEikFormAnim::Size() const |
|
193 { |
|
194 if( iAnimation ) |
|
195 return iAnimation->Size(); |
|
196 return TSize( 0, 0 ); |
|
197 } |
|
198 |
|
199 void CEikFormAnim::ReleaseAnimation() |
|
200 { |
|
201 delete iAnimation; |
|
202 iAnimation = NULL; |
|
203 |
|
204 iObserver = NULL; |
|
205 |
|
206 CCoeEnv* env = CCoeEnv::Static(); |
|
207 env->RemoveForegroundObserver( *this ); |
|
208 |
|
209 iAnimFlags.Set( EFlagUseAnimation ); |
|
210 } |
|
211 |
|
212 /** |
|
213 * The application has gained foreground -> animation should be continued. |
|
214 */ |
|
215 void CEikFormAnim::HandleGainingForeground() |
|
216 { |
|
217 // Animation on focused captioned control will receive FocusGained after |
|
218 // gaining foreground -> starting animation is postponed there. |
|
219 } |
|
220 |
|
221 /** |
|
222 * The application lost foreground -> no running animation (even if the |
|
223 * application is partially visible). |
|
224 */ |
|
225 void CEikFormAnim::HandleLosingForeground() |
|
226 { |
|
227 if( iAnimation ) |
|
228 { |
|
229 NoAnimIfError( iAnimation->Stop() ); |
|
230 } |
|
231 } |
|
232 |
|
233 void CEikFormAnim::AnimFrameReady( TInt aError, TInt ) |
|
234 { |
|
235 if( KErrNone != aError ) |
|
236 { |
|
237 // Animation has failed to run -> schedule the animation for |
|
238 // deletion to fall back to normal rendering. |
|
239 PostDeleteAnimation(); |
|
240 } |
|
241 else if( iObserver && iAnimation ) // Frame ok |
|
242 { |
|
243 iObserver->AnimFrameReady(); |
|
244 } |
|
245 } |
|
246 |
|
247 void CEikFormAnim::DoCancel() |
|
248 { |
|
249 // Required method, but not needed |
|
250 } |
|
251 |
|
252 /** |
|
253 * Postponed animation deletion is done here. |
|
254 */ |
|
255 void CEikFormAnim::RunL() |
|
256 { |
|
257 UseNoAnimation(); |
|
258 } |
|
259 |
|
260 /** |
|
261 * Schedules the animation for deletion by activating the extension itself. |
|
262 * Deletion is postponed because in many error/failure occasions the caller has |
|
263 * been animation and direct deletion is possibly not safe (because function |
|
264 * stack would return through the deleted object). |
|
265 */ |
|
266 void CEikFormAnim::PostDeleteAnimation() |
|
267 { |
|
268 TRequestStatus* status = &iStatus; |
|
269 User::RequestComplete( status, KErrNone ); |
|
270 SetActive(); |
|
271 } |
|
272 |
|
273 /** |
|
274 * @param aHilightSize The size of the list cell highlight |
|
275 */ |
|
276 void CEikFormAnim::CreateAnimationL( const TSize& aHighlightSize ) |
|
277 { |
|
278 // Create animation |
|
279 CCoeEnv* env = CCoeEnv::Static(); |
|
280 env->AddForegroundObserverL( *this ); |
|
281 |
|
282 delete iAnimation; |
|
283 iAnimation = NULL; |
|
284 |
|
285 iAnimation = CAknsEffectAnim::NewL( this ); |
|
286 TBool ok = iAnimation->ConstructFromSkinL( KAknsIIDQsnAnimList ); |
|
287 |
|
288 if( !ok ) // Animation for the ID was not found from the skin |
|
289 { |
|
290 User::Leave( KErrNotFound ); |
|
291 } |
|
292 |
|
293 DoResizeL( aHighlightSize, ETrue ); // Apply size & layers |
|
294 } |
|
295 |
|
296 /** |
|
297 * @param aHilightSize The size of the list cell highlight |
|
298 */ |
|
299 void CEikFormAnim::DoResizeL( |
|
300 const TSize& aHighlightSize, TBool aAboutToStart ) |
|
301 { |
|
302 if( !iObserver ) |
|
303 return; |
|
304 |
|
305 iAnimation->BeginConfigInputLayersL( aHighlightSize, aAboutToStart ); |
|
306 |
|
307 if( iAnimation->InputRgbGc() ) |
|
308 iObserver->AnimDrawHighlightBackground( *iAnimation->InputRgbGc() ); |
|
309 |
|
310 iAnimation->EndConfigInputLayersL(); |
|
311 } |