|
1 /* |
|
2 * Copyright (c) 2002 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: |
|
15 * Implementation of CAknProgressDialog. |
|
16 * |
|
17 */ |
|
18 |
|
19 // AknProgressDialog.cpp: implementation of the CAknProgressDialog class. |
|
20 // |
|
21 ////////////////////////////////////////////////////////////////////// |
|
22 |
|
23 #include <AknProgressDialog.h> |
|
24 #include <aknprogresstimer.h> |
|
25 #include <aknnotecontrol.h> |
|
26 #include <eikenv.h> |
|
27 #include <eikappui.h> |
|
28 #include <eikcba.h> |
|
29 #include <avkon.hrh> |
|
30 #include "aknnoteattributes.h" |
|
31 #include <akninputblock.h> |
|
32 |
|
33 |
|
34 #ifdef RD_UI_TRANSITION_EFFECTS_POPUPS |
|
35 #include <gfxtranseffect/gfxtranseffect.h> |
|
36 #include <akntransitionutils.h> |
|
37 #endif |
|
38 |
|
39 #include <AknTasHook.h> // for testability hooks |
|
40 NONSHARABLE_CLASS(CAknProgressDialog::CCancelWhileHidden) : public CBase, public MAknInputBlockCancelHandler |
|
41 { |
|
42 public: |
|
43 static CCancelWhileHidden* NewL(CAknProgressDialog* aAknProgressDialog); |
|
44 ~CCancelWhileHidden(); |
|
45 private: // from MAknInputBlockCancelHandler |
|
46 void AknInputBlockCancel(); |
|
47 private: |
|
48 CCancelWhileHidden(CAknProgressDialog* aAknProgressDialog); |
|
49 void ConstructL(); |
|
50 private: |
|
51 CAknProgressDialog* iAknProgressDialog; |
|
52 CAknInputBlock* iBlock; |
|
53 }; |
|
54 |
|
55 CAknProgressDialog::CCancelWhileHidden* CAknProgressDialog::CCancelWhileHidden::NewL(CAknProgressDialog* aAknProgressDialog) |
|
56 { |
|
57 CCancelWhileHidden* self = new(ELeave) CCancelWhileHidden(aAknProgressDialog); |
|
58 CleanupStack::PushL(self); |
|
59 self->ConstructL(); |
|
60 CleanupStack::Pop(self); |
|
61 return self; |
|
62 } |
|
63 |
|
64 CAknProgressDialog::CCancelWhileHidden::~CCancelWhileHidden() |
|
65 { |
|
66 if (iBlock) |
|
67 iBlock->SetCancelHandler(NULL); |
|
68 delete iBlock; |
|
69 } |
|
70 |
|
71 void CAknProgressDialog::CCancelWhileHidden::AknInputBlockCancel() |
|
72 { |
|
73 TKeyEvent key; |
|
74 key.iRepeats=0; |
|
75 key.iCode=EKeyEscape; |
|
76 key.iModifiers=0; |
|
77 key.iScanCode = EStdKeyNull; |
|
78 iAknProgressDialog->OfferKeyEventL(key, EEventKey); |
|
79 } |
|
80 |
|
81 CAknProgressDialog::CCancelWhileHidden::CCancelWhileHidden(CAknProgressDialog* aAknProgressDialog) |
|
82 : iAknProgressDialog(aAknProgressDialog) |
|
83 { |
|
84 } |
|
85 |
|
86 void CAknProgressDialog::CCancelWhileHidden::ConstructL() |
|
87 { |
|
88 iBlock = CAknInputBlock::NewCancelHandlerLC(this); |
|
89 CleanupStack::Pop(iBlock); |
|
90 } |
|
91 |
|
92 |
|
93 const TInt KMinProcessTimeToShowDialog = 2000; // 0.002 sec |
|
94 const TInt KMinTimeDialogOnScreen = 1500000; // 1.5 sec |
|
95 |
|
96 ////////////////////////////////////////////////////////////////////// |
|
97 // Construction/Destruction |
|
98 ////////////////////////////////////////////////////////////////////// |
|
99 |
|
100 EXPORT_C CAknProgressDialog::CAknProgressDialog(TInt aFinalValue,TInt anIncrement, |
|
101 TInt anInterval,CEikDialog** aSelfPtr) : |
|
102 CAknNoteDialog(aSelfPtr),iInternalTimerControl(ETrue) |
|
103 { |
|
104 #ifdef RD_UI_TRANSITION_EFFECTS_POPUPS |
|
105 GfxTransEffect::Register( this, KGfxWaitNoteControlUid ); |
|
106 #endif |
|
107 iModel.iFinalValue = aFinalValue; |
|
108 iModel.iHundreths = anInterval; |
|
109 iModel.iIncrement = anIncrement; |
|
110 iModel.iRunning = EFalse; |
|
111 AKNTASHOOK_ADD( this, "CAknProgressDialog" ); |
|
112 } |
|
113 |
|
114 EXPORT_C CAknProgressDialog::CAknProgressDialog(CEikDialog** aSelfPtr) : |
|
115 CAknNoteDialog(aSelfPtr),iInternalTimerControl(EFalse) |
|
116 { |
|
117 #ifdef RD_UI_TRANSITION_EFFECTS_POPUPS |
|
118 GfxTransEffect::Register( this, KGfxWaitNoteControlUid ); |
|
119 #endif |
|
120 AKNTASHOOK_ADD( this, "CAknProgressDialog" ); |
|
121 } |
|
122 |
|
123 EXPORT_C CAknProgressDialog::CAknProgressDialog(CEikDialog** aSelfPtr, |
|
124 TBool aVisibilityDelayOff) |
|
125 : CAknNoteDialog(aSelfPtr), |
|
126 iVisibilityDelayOff( aVisibilityDelayOff ), |
|
127 iInternalTimerControl(EFalse) |
|
128 { |
|
129 #ifdef RD_UI_TRANSITION_EFFECTS_POPUPS |
|
130 GfxTransEffect::Register( this, KGfxWaitNoteControlUid ); |
|
131 #endif |
|
132 AKNTASHOOK_ADD( this, "CAknProgressDialog" ); |
|
133 } |
|
134 |
|
135 EXPORT_C CAknProgressDialog::~CAknProgressDialog() |
|
136 { |
|
137 AKNTASHOOK_REMOVE(); |
|
138 if ( iInternalTimerControl ) |
|
139 { |
|
140 PlayTone(); |
|
141 } |
|
142 iEikonEnv->RemoveFromStack(this); |
|
143 delete iCancelWhileHidden; |
|
144 delete iProgressTimer; |
|
145 delete iProgressDialogTimer; |
|
146 } |
|
147 |
|
148 EXPORT_C void CAknProgressDialog::PreLayoutDynInitL() |
|
149 { |
|
150 //If the progress bar is to be controlled externally, it won't be updated |
|
151 //through this dialog class |
|
152 if (iInternalTimerControl) |
|
153 { |
|
154 CAknNoteControl* note = NoteControl(); |
|
155 if (!iProgressTimer) |
|
156 { |
|
157 iProgressTimer = new (ELeave) CAknProgressTimer; |
|
158 iProgressTimer->ConstructL(&iModel,note,TCallBack(StaticDeleteL,this)); |
|
159 } |
|
160 } |
|
161 |
|
162 TransferControlAttributes(); |
|
163 |
|
164 // Key events should be reveived even when invisible |
|
165 MEikButtonGroup* cba = ButtonGroupContainer().ButtonGroup(); |
|
166 STATIC_CAST( CEikCba*, cba)->SetButtonGroupFlags( cba->ButtonGroupFlags() | |
|
167 EAknCBAFlagRespondWhenInvisible ); |
|
168 } |
|
169 |
|
170 |
|
171 TInt CAknProgressDialog::DialogTimerCallback(TAny* aPtr) |
|
172 { |
|
173 return STATIC_CAST(CAknProgressDialog*, aPtr)->DialogTimerEvent(); |
|
174 } |
|
175 |
|
176 TInt CAknProgressDialog::DialogTimerEvent() |
|
177 { |
|
178 switch ( iState ) |
|
179 { |
|
180 case EProcessOnDisplayOff: |
|
181 { |
|
182 #ifdef RD_UI_TRANSITION_EFFECTS_POPUPS |
|
183 TBool doTransEffect = !IsVisible(); |
|
184 GfxTransEffect::Abort(); |
|
185 //register even if we don't do effect now so we can get one when closing dialog |
|
186 GfxTransEffect::Register( this, KGfxWaitNoteControlUid ); |
|
187 TBool rsWasEnabled( EFalse ); |
|
188 |
|
189 if ( doTransEffect ) |
|
190 { |
|
191 CAknTransitionUtils::SetData(EDontAnimateBitmaps, (TAny*)this); |
|
192 if( !CAknEnv::Static()->TransparencyEnabled() && Window().IsRedrawStoreEnabled() ) |
|
193 { |
|
194 rsWasEnabled = ETrue; |
|
195 // disable redrawstore during transition to avoid |
|
196 // drawing problems behind FSW |
|
197 Window().EnableRedrawStore( EFalse ); |
|
198 } |
|
199 |
|
200 CAknTransitionUtils::SetAllParents(this); |
|
201 GfxTransEffect::Begin(this, KGfxControlAppearAction); |
|
202 GfxTransEffect::NotifyExternalState(ECaptureComponentsBegin, (const TDesC8*)this); |
|
203 } |
|
204 #endif // RD_UI_TRANSITION_EFFECTS_POPUPS |
|
205 |
|
206 // Display dialog |
|
207 iState = EProcessOnDisplayOn; |
|
208 ControlAttributes()->InvalidateLayout(); |
|
209 Layout(); |
|
210 CEikDialog::SlideDialog(); // this does nothing is sliding is disabled |
|
211 DrawableWindow()->SetOrdinalPosition(0); |
|
212 MakeVisible(ETrue); |
|
213 CCoeControl* cba = ButtonGroupContainer().ButtonGroup()->AsControl(); |
|
214 iEikonEnv->RemoveFromStack(cba); |
|
215 __ASSERT_DEBUG_NO_LEAVE(iEikonEnv->EikAppUi()->AddToStackL(cba, ECoeStackPriorityCba, ECoeStackFlagRefusesFocus)); // Won't fail since we just removed it (and array will not reallocate) |
|
216 cba->DrawableWindow()->SetOrdinalPosition(0); |
|
217 cba->MakeVisible(ETrue); |
|
218 ReportUserActivity(); |
|
219 PlayTone(); |
|
220 delete iCancelWhileHidden; |
|
221 iCancelWhileHidden = NULL; |
|
222 |
|
223 #ifdef RD_UI_TRANSITION_EFFECTS_POPUPS |
|
224 if ( doTransEffect ) |
|
225 { |
|
226 TRect demarcation; |
|
227 CAknTransitionUtils::GetDemarcation(CAknTransitionUtils::EPopup, |
|
228 demarcation); |
|
229 GfxTransEffect::SetDemarcation(this, demarcation); |
|
230 |
|
231 GfxTransEffect::NotifyExternalState(ECaptureComponentsEnd, (const TDesC8*)this); |
|
232 GfxTransEffect::End(this); |
|
233 |
|
234 if( !CAknEnv::Static()->TransparencyEnabled() && rsWasEnabled ) |
|
235 { |
|
236 // if redrawstore was on before transition, |
|
237 // enable it again |
|
238 Window().EnableRedrawStore( ETrue ); |
|
239 } |
|
240 CAknTransitionUtils::RemoveData(EDontAnimateBitmaps); |
|
241 } |
|
242 #endif // RD_UI_TRANSITION_EFFECTS_POPUPS |
|
243 break; |
|
244 } |
|
245 case EProcessOnDisplayOn: |
|
246 iState = EProcessOnDisplayOnCanBeDismissed; |
|
247 delete iProgressDialogTimer; |
|
248 iProgressDialogTimer = NULL; |
|
249 break; |
|
250 case EProcessOffDisplayOff: |
|
251 case EProcessOffDisplayOn: |
|
252 delete iProgressDialogTimer; |
|
253 iProgressDialogTimer = NULL; |
|
254 ReportUserActivity(); |
|
255 PlayTone(); |
|
256 TRAP_IGNORE(TryExitL( EAknSoftkeyDone )); |
|
257 break; |
|
258 default: |
|
259 delete iProgressDialogTimer; |
|
260 iProgressDialogTimer = NULL; |
|
261 } |
|
262 return KErrNone; |
|
263 } |
|
264 |
|
265 EXPORT_C void CAknProgressDialog::ProcessFinishedL() |
|
266 { |
|
267 switch ( iState ) |
|
268 { |
|
269 case EProcessOnDisplayOff: |
|
270 case EProcessOnDisplayOnCanBeDismissed: |
|
271 iState = EProcessOffDisplayOff; |
|
272 delete iProgressDialogTimer; |
|
273 iProgressDialogTimer = NULL; |
|
274 ReportUserActivity(); |
|
275 PlayTone(); |
|
276 TryExitL( EAknSoftkeyDone ); |
|
277 break; |
|
278 case EProcessOnDisplayOn: |
|
279 iState = EProcessOffDisplayOn; |
|
280 break; |
|
281 default: |
|
282 break; |
|
283 } |
|
284 } |
|
285 |
|
286 EXPORT_C TInt CAknProgressDialog::RunLD() |
|
287 { |
|
288 CAknNoteControl* note = NoteControl(); |
|
289 note->CreateProgressBarL(); |
|
290 |
|
291 if (iInternalTimerControl) |
|
292 { |
|
293 if ( ((iModel.iFinalValue/iModel.iIncrement*iModel.iHundreths)*10000) < KMinProcessTimeToShowDialog ) |
|
294 { |
|
295 CleanupStack::Pop(); // this |
|
296 TryExitL( EAknSoftkeyDone ); |
|
297 return 0; |
|
298 } |
|
299 iState = EProcessOnDisplayOn; |
|
300 iModel.iRunning = ETrue; |
|
301 iEikonEnv->EikAppUi()->AddToStackL(this,ECoeStackPriorityDialog,ECoeStackFlagRefusesAllKeys); |
|
302 return (CAknNoteDialog::RunLD()); |
|
303 } |
|
304 |
|
305 iProgressDialogTimer = CPeriodic::NewL(CActive::EPriorityStandard); |
|
306 if ( !iVisibilityDelayOff ) |
|
307 { |
|
308 //TR deregister since we'll show this transition in callback |
|
309 #ifdef RD_UI_TRANSITION_EFFECTS_POPUPS |
|
310 GfxTransEffect::Deregister( this ); |
|
311 #endif |
|
312 iState = EProcessOnDisplayOff; |
|
313 // start timer |
|
314 iProgressDialogTimer->Start(TTimeIntervalMicroSeconds32(KMinProcessTimeToShowDialog), |
|
315 TTimeIntervalMicroSeconds32(KMinTimeDialogOnScreen), |
|
316 TCallBack(DialogTimerCallback, this) ); |
|
317 // Make the dialog unvisible |
|
318 ButtonGroupContainer().MakeVisible(EFalse); |
|
319 MakeVisible(EFalse); |
|
320 // Add to stack to capture key events. This prevents user to continue working while |
|
321 // the dialog is unvisible |
|
322 iEikonEnv->EikAppUi()->AddToStackL(this,ECoeStackPriorityDialog); |
|
323 // Allow detection and cancellation as a dialog while hidden |
|
324 delete iCancelWhileHidden; |
|
325 iCancelWhileHidden = NULL; |
|
326 iCancelWhileHidden = CCancelWhileHidden::NewL(this); |
|
327 } |
|
328 else |
|
329 { |
|
330 MakeVisible( ETrue ); |
|
331 ButtonGroupContainer().MakeVisible( ETrue ); |
|
332 |
|
333 iState = EProcessOnDisplayOn; |
|
334 // start timer |
|
335 iProgressDialogTimer->Start(TTimeIntervalMicroSeconds32(KMinTimeDialogOnScreen), |
|
336 TTimeIntervalMicroSeconds32(KMinTimeDialogOnScreen), |
|
337 TCallBack(DialogTimerCallback, this) ); |
|
338 |
|
339 iEikonEnv->EikAppUi()->AddToStackL(this,ECoeStackPriorityDialog,ECoeStackFlagRefusesAllKeys); |
|
340 } |
|
341 |
|
342 return CAknNoteDialog::RunLD(); |
|
343 } |
|
344 |
|
345 EXPORT_C CEikProgressInfo* CAknProgressDialog::GetProgressInfoL() |
|
346 { |
|
347 CAknNoteControl* note = NoteControl(); |
|
348 if ( !(note->GetProgressInfo()) ) |
|
349 { |
|
350 note->CreateProgressBarL(); |
|
351 } |
|
352 return note->GetProgressInfo(); |
|
353 } |
|
354 |
|
355 EXPORT_C TKeyResponse CAknProgressDialog::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) |
|
356 { |
|
357 if ( aType != EEventKey ) |
|
358 { |
|
359 return CAknNoteDialog::OfferKeyEventL(aKeyEvent,aType); |
|
360 } |
|
361 |
|
362 TInt cmdLeft = ButtonGroupContainer().ButtonGroup()->CommandId(0); |
|
363 TInt cmdRight = ButtonGroupContainer().ButtonGroup()->CommandId(2); |
|
364 if ( iState != EProcessOnDisplayOff ) |
|
365 { |
|
366 // If left softkey is empty, disable ok key |
|
367 if ( aKeyEvent.iCode == EKeyOK && |
|
368 ( cmdLeft == 0 || cmdLeft == EAknSoftkeyEmpty ) ) |
|
369 { |
|
370 return EKeyWasConsumed; |
|
371 } |
|
372 // If LSK and RSK are both empty, let note ignores enter key. |
|
373 if (cmdLeft == EAknSoftkeyEmpty && cmdRight== EAknSoftkeyEmpty && |
|
374 aKeyEvent.iCode == EKeyEnter) |
|
375 { |
|
376 return EKeyWasConsumed; |
|
377 } |
|
378 |
|
379 return CEikDialog::OfferKeyEventL(aKeyEvent,aType); |
|
380 } |
|
381 else |
|
382 { // a dialog should ALWAYS be dismissed on the escape key. |
|
383 if (aType == EEventKey && aKeyEvent.iCode == EKeyEscape) |
|
384 return CEikDialog::OfferKeyEventL(aKeyEvent,aType); |
|
385 return EKeyWasConsumed; |
|
386 } |
|
387 } |
|
388 |
|
389 EXPORT_C TBool CAknProgressDialog::OkToExitL(TInt aButtonId) |
|
390 { |
|
391 // if dialog is invisible and app isn't exiting, eg during view switch, |
|
392 // don't stop the progress dialog - it's most likely part of some |
|
393 // asynchronous operation. |
|
394 if ((iState == EProcessOnDisplayOff && !CAknEnv::AppWithShutterRunning()) || |
|
395 aButtonId == EAknSoftkeyEmpty ) |
|
396 { |
|
397 delete iCancelWhileHidden; |
|
398 iCancelWhileHidden = NULL; |
|
399 return EFalse; |
|
400 } |
|
401 if ( iCallback ) |
|
402 { |
|
403 iCallback->DialogDismissedL(aButtonId); |
|
404 } |
|
405 return ETrue; |
|
406 } |
|
407 |
|
408 //------------------------------------------------------------------------------------- |
|
409 // CAknProgressDialog::HandlePointerEventL() |
|
410 // Empty implementation to overwrite the implementation of CAknNoteDialog. |
|
411 // CAknNoteDialog closes it self when up pointer event is captured. This |
|
412 // should not. |
|
413 //------------------------------------------------------------------------------------- |
|
414 // |
|
415 EXPORT_C void CAknProgressDialog::HandlePointerEventL(const TPointerEvent& /*aPointerEvent*/ ) |
|
416 { |
|
417 // Empty overwriting of function |
|
418 } |
|
419 |
|
420 EXPORT_C void* CAknProgressDialog::ExtensionInterface( TUid /*aInterface*/ ) |
|
421 { |
|
422 return NULL; |
|
423 } |
|
424 |
|
425 EXPORT_C void CAknProgressDialog::SetCallback(MProgressDialogCallback* aCallback) |
|
426 { |
|
427 iCallback = aCallback; |
|
428 } |
|
429 |
|
430 EXPORT_C void CAknProgressDialog::CEikDialog_Reserved_1() |
|
431 { |
|
432 } |
|
433 |
|
434 EXPORT_C void CAknProgressDialog::CEikDialog_Reserved_2() |
|
435 { |
|
436 } |
|
437 |
|
438 EXPORT_C void CAknProgressDialog::CAknNoteDialog_Reserved() |
|
439 { |
|
440 } |
|
441 |
|
442 // End of File |