diff -r f5050f1da672 -r 04becd199f91 javauis/lcdui_akn/lcdui/src/CMIDAlertDialog.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/lcdui_akn/lcdui/src/CMIDAlertDialog.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,615 @@ +/* +* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Alert dialog implementation for Series 60 +* +*/ + + +#include "CMIDAlert.h" +#include "CMIDAlertDialog.h" +#include "CMIDDisplayable.h" +#include "CMIDCommandList.h" +#include "CMIDUtils.h" + +// using TAlertDialogLineId enumeration +#include "lcdui.hrh" +// macros definitions for resources +#include + +// using CAknBitmapAnimation and CBitmapAnimClientData +// - in CheckAndSetAnimationModeL and UpdateGaugeInAlertL functions +// for animation in gauge +#include +#include +// using CEikCaptionedControl +// - in CheckAndSetAnimationModeL and UpdateGaugeInAlertL functions +#include + +#include +#include + +// macros definitions for outputing logs +#include + +#ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK +#include +#endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK + + +/** This macro is executed each time a trapped call returns an error code different than KErrNone */ +#undef TRAP_INSTRUMENTATION_LEAVE +#define TRAP_INSTRUMENTATION_LEAVE(aResult) DEBUG_INT2("In CMIDDisplayable.cpp, trapped method was called at line %D and got exception %D", __LINE__, aResult); + + +/** CMIDAlertDialog::CMIDAlertDialog */ +CMIDAlertDialog* CMIDAlertDialog::NewL(CMIDAlert* aAlert,CMIDDisplayable* aDisplayable) +{ + CMIDAlertDialog* self = new(ELeave) CMIDAlertDialog(aAlert, aDisplayable); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; +} +// +CMIDAlertDialog::CMIDAlertDialog(CMIDAlert* aAlert, CMIDDisplayable* aDisplayable) : + iParent(aAlert), iDisplayable(aDisplayable) +{ + iGaugeResourceType = EPopupFormUnknown; + +} + +/** CMIDAlertDialog::~CMIDAlertDialog */ +CMIDAlertDialog::~CMIDAlertDialog() +{ + if (iGauge) + { + iGauge->SetGaugeListenerFromAlert(NULL); + iGauge = NULL; + } +} + +/** CMIDAlertDialog::PreLayoutDynInitL */ +void CMIDAlertDialog::PreLayoutDynInitL() +{ + // Check if there is a gauge.... and create it... + // NOTE: the type and properties need to be set here also... + CAknPopupForm::PreLayoutDynInitL(); +} + +/** When showing dialogs set their CBA into CMIDDisplayable and then use +the logic of CMIDDisplayable::InitializeCbasL() to set the correct CBA +commands. However modeless dialogs always have empty CBAs. When not +showing we must reset the parent CBAs. +*/ +void CMIDAlertDialog::UpdateCbasL() +{ + if (iShowing) + { + iDisplayable->SetCba(&ButtonGroupContainer()); + + if (iParent->IsModal()) + { + iDisplayable->InitializeCbasL(); + } + else + { + ButtonGroupContainer().SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY); + } + + CCoeControl* cba = ButtonGroupContainer().ButtonGroup()->AsControl(); + cba->DrawableWindow()->SetOrdinalPosition(0); + cba->MakeVisible(ETrue); + cba->DrawNow(); + } + else + { + //restore parent CBAs + iDisplayable->SetCba(iDisplayable->MenuHandler()->Cba()); + } +} + +/** CMIDAlertDialog::PostLayoutDynInitL */ +void CMIDAlertDialog::PostLayoutDynInitL() +{ + CAknPopupForm::PostLayoutDynInitL(); + // Above call is starting the animation. In case of updating gauge + // we will stop it and midlet will update it later. + CheckAndSetAnimationModeL(); +} + +/** CMIDAlertDialog::InsertGaugeIntoDialogL + Insert/remove the gauge in Alert */ +void CMIDAlertDialog::InsertGaugeIntoDialogL() +{ + DEBUG("CMIDAlertDialog::InsertGaugeIntoDialogL <"); + + TBool skipVisibilityChange = EFalse; + + // skipping disabling visibility change in case of error + // where incremental update type gauge wasn't show + if (iGauge) + { + if (iGauge->GetIndefiniteState() == MMIDGauge::EIncrementalUpdating + && iShowing == EFalse) + { + skipVisibilityChange = ETrue; + } + } + + if (!skipVisibilityChange) + { + DisableVisibilityChange(ETrue); + } + + + TInt gaugeVal = iGauge ? iGauge->GetValue() : -1; + + //remove any existing gauge + if (iGaugeResourceType != EPopupFormUnknown) + { + DeleteControl(iGaugeResourceType); + iGaugeResourceType = EPopupFormUnknown; + } + + //add the new gauge + if (iGauge) + { + iGauge->SetGaugeListenerFromAlert(this); + DEBUG("CMIDAlertDialog::InsertGaugeIntoDialogL - InsertControlL()"); + + if (iGauge->GetMaxValue() > 0) + { // definite type Gauge + // progressbar adding + InsertControlL(0, R_MIDP_ALERT_PROGI_LINE, EFalse); + iGaugeResourceType = EPopupFormProgbar; + iGauge->UpdateProgressInfo(CAknPopupForm::ProgressInfo()); + } + else + { + iGaugeResourceType = EPopupFormWaitAnim; + switch (iGauge->GetIndefiniteState()) + { + case MMIDGauge::EContinuousIdle: // continuous idle + { //r_midp_alert_wait_animation_continouse_idle_line + InsertControlL(0, R_MIDP_ALERT_WAIT_ANIMATION_CONTINUOUS_IDLE_LINE, ETrue); + break; + } + case MMIDGauge::EContinuousRunning: // continuous running + { + InsertControlL(0, R_MIDP_ALERT_WAIT_ANIMATION_CONTINUOUS_RUNNING_LINE, ETrue); + break; + } + case MMIDGauge::EIncrementalUpdating: //incremental updating + { + InsertControlL(0, R_MIDP_ALERT_WAIT_BAR_INCREM_LINE, ETrue); + break; + } + case MMIDGauge::EIncrementalIdle: //incremental idle + { + InsertControlL(0, R_MIDP_ALERT_WAIT_BAR_INCREM_IDLE_LINE, ETrue); + break; + } + default: + ASSERT(EFalse); + break; + } + } + } + + DEBUG("CMIDAlertDialog::InsertGaugeIntoDialogL - UpdateGaugeInAlertL()"); + + UpdateGaugeInAlertL(gaugeVal); + + // skipping enabling visibility change in case of error + // where incremental update type gauge wasn't show + if (!skipVisibilityChange) + { + DisableVisibilityChange(EFalse); + } + + DEBUG("CMIDAlertDialog::InsertGaugeIntoDialogL >"); +} + +/** CMIDAlertDialog::CheckAndSetAnimationMode */ +void CMIDAlertDialog::CheckAndSetAnimationModeL() +{ + DEBUG("CMIDAlertDialog::CheckAndSetAnimationModeL <"); + + TBitFlags flags = Flags(); + if (iGauge && (iGauge->GetIndefiniteState() == MMIDGauge::EIncrementalUpdating) + && flags.IsSet(EPopupFormWaitAnim)) + { + CCoeControl* coe = GetControlByControlTypeL(EPopupFormWaitAnim)->iControl; + CAknBitmapAnimation* ani = REINTERPRET_CAST(CAknBitmapAnimation*, coe); + + + DEBUG("CMIDAlertDialog::CheckAndSetAnimationModeL - CancelAnimation()"); + ani->CancelAnimation(); + + CBitmapAnimClientData* animClientData = ani->BitmapAnimData(); + iGaugeFrameCount = animClientData->FrameArray().Count(); + + // A non-interactive Gauge that has indefinite range will exist in one of four states: + // continuous-idle, incremental-idle, continuous-running, or incremental-updating. + // These states are intended to indicate to the user that some level of activity is + // occurring. With incremental-updating, progress can be indicated to the user even + // though there is no known endpoint to the activity. + if (iGauge->GetMaxValue() < 0) + { //CBitmapAnimClientData::TPlayMode:: + DEBUG("CMIDAlertDialog::CheckAndSetAnimationModeL - SetPlayModeL()"); + ani->Animation().SetPlayModeL(CBitmapAnimClientData::ECycle); + iIncrementalFrameCounter = 0; + DEBUG("CMIDAlertDialog::CheckAndSetAnimationModeL - SetFrameIndexL()"); + ani->SetFrameIndexL(iIncrementalFrameCounter++); + } + } + DEBUG("CMIDAlertDialog::CheckAndSetAnimationModeL >"); +} + + +/** +*/ +void CMIDAlertDialog::UpdateGaugeInAlertL(TInt aValue) +{ + if (iGauge && aValue >= 0 && + (iGauge->GetIndefiniteState() == MMIDGauge::EIncrementalUpdating || + iGauge->GetMaxValue() > 0)) + { + TBitFlags flags = Flags(); + if (flags.IsSet(EPopupFormWaitAnim)) + { + CCoeControl* coe = GetControlByControlTypeL(EPopupFormWaitAnim)->iControl; + CAknBitmapAnimation* ani = REINTERPRET_CAST(CAknBitmapAnimation*, coe); + if (iGaugeFrameCount < 1) + iGaugeFrameCount = 1; + ani->SetFrameIndexL(iIncrementalFrameCounter++ % iGaugeFrameCount); + } + else + { + // draw and update the progress bar + SetProgressBarAndDraw(aValue); + //draw of Alert + DrawDeferred(); + } + } +} + + +void CMIDAlertDialog::GaugeTypeInAlertChangedL() +{ + // create new gauge type in wait dialog + InsertGaugeIntoDialogL(); + CheckAndSetAnimationModeL(); + + // redraw gauge + DrawDeferred(); +} + +/** If the alert is timed (not modal) and if we receive a valid key event then +we dismiss the dialog. Otherwise we pass on the key event to CAknPopupForm, +which will take care of scrolling text for example. @see CMIDUtils::IgnoreKeyEvent() +for key events that are ignored (eg. flip open or flip close key events. */ +TKeyResponse CMIDAlertDialog::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) +{ + //DEBUG START + if (aType == EEventKeyDown) + { + DEBUG_INT2("CMIDAlertDialog::OfferKeyEventL - key down, scan code %d key code %d", + aKeyEvent.iScanCode, aKeyEvent.iCode); + } + else if (aType == EEventKey) + { + DEBUG_INT2("CMIDAlertDialog::OfferKeyEventL - key event, scan code %d key code %d", + aKeyEvent.iScanCode, aKeyEvent.iCode); + } + else if (aType == EEventKeyUp) + { + DEBUG_INT2("CMIDAlertDialog::OfferKeyEventL - key up, scan code %d key code %d", + aKeyEvent.iScanCode, aKeyEvent.iCode); + } + //DEBUG END + + if (!iParent->IsModal() && (aType == EEventKey) && !CMIDUtils::IgnoreKeyEvent(aKeyEvent.iCode)) + { // if not modal then pressing any valid key should dismiss it + iParent->TryToDismissDialog(); + return EKeyWasConsumed; + } + //Enter_Key have a same function as Selection key. +#ifdef RD_JAVA_S60_RELEASE_9_2 + if (iParent->IsModal() && (aType == EEventKey) && (aKeyEvent.iCode == EKeyEnter || aKeyEvent.iCode == EKeyDevice3)) +#else + if (iParent->IsModal() && (aType == EEventKey) && aKeyEvent.iCode == EKeyEnter) +#endif // RD_JAVA_S60_RELEASE_9_2 + { + OkToExitL(iDisplayable->MainCommandList()->CommandOffset()); + return EKeyWasConsumed; + } + return CAknPopupForm::OfferKeyEventL(aKeyEvent, aType); +} + +/** Modal dialogs must let the displayable handle commands whereas modeless +dialogs can just exit on any key (including a CBA key). However we cannot +exit directly, we must post a java side event and wait for the java request +to dismiss the dialog. This is why we return EFalse. */ +TBool CMIDAlertDialog::OkToExitL(TInt aCommandId) +{ + if (iParent->IsModal()) + { + TInt offset = iDisplayable->MainCommandList()->CommandOffset(); + + if (aCommandId == EAknSoftkeyOptions) // 3000 + { + iDisplayable->MenuHandler()->ProcessCommandL(EAknSoftkeyOptions); + } + else if (aCommandId - offset < 0) // aCommandId value is over 3000 - used by MSK + { + iDisplayable->ProcessCommandL(aCommandId); + } + else // aCommandId value is 7000 and over - used by LSK, RSK and EnterKey + { + CMIDCommand* tempCmd = NULL; + CMIDCommand* command = NULL; + TBool isMaped = EFalse; + TInt mapedCnt = ENone; + TInt mapedId = ENone; + + // number of all commands + TInt numberOfCommands = iDisplayable->CommandCount(); + // number of Ok and Item commands + TInt numberOfOkOptionsCommands = iDisplayable->NumCommandsForOkOptionsMenu(); + // command ID which is get from aCommandId + TInt commandId = aCommandId - offset; + + if (numberOfCommands > 0) + { + // Go through every midlet command, and save its ID if maped + // and also count maped commands. + for (TInt i = 0; i < numberOfCommands; i++) + { + tempCmd = iDisplayable->MainCommandList()->At(i).iCommand; + if (tempCmd->IsMappedToSoftKey()) + { + mapedId = i; + isMaped = ETrue; + mapedCnt++; + } + } + + // If there are more than one maped command (LSK & RSK maped) + // or maped command is different than commandId (EnterKey used), + // set CMIDCommand command with this command, which index + // is the same as commandId value. + if (mapedCnt > 1 || mapedId != commandId) + { + command = iDisplayable->MainCommandList()->At(commandId).iCommand; + } + else // Else if there are one or zero command maped. + { + if (isMaped) // One command maped. + { + command = iDisplayable->MainCommandList()->At(mapedId).iCommand; + } + else // Zero commands maped. + { + command = iDisplayable->MainCommandList()->At(0).iCommand; + } + } + + // type of the command + TInt commandType = command->CommandType(); + + // If there aren't any EExit, EBack, ECancel and EStop + // command mapped and there are still some commands + // show menu, else process with maped command. + if (commandType != MMIDCommand::EExit && + commandType != MMIDCommand::EBack && + commandType != MMIDCommand::ECancel && + commandType != MMIDCommand::EStop && + numberOfOkOptionsCommands > 1) + { + iDisplayable->MenuHandler()->ShowMenuL(CMIDMenuHandler::EOkMenu); + } + else + { + iDisplayable->ProcessCommandL(aCommandId); + } + } + } + } + else + { + iParent->TryToDismissDialog(); + } + + //The dialog can only be dismissed java side or else we'll end + //up with the alert displayed and no dialog + return EFalse; +} + +/** */ +void CMIDAlertDialog::SetGaugeL(CMIDGaugeItem* aGauge) +{ + DEBUG("CMIDAlertDialog::SetGaugeL <"); + + if (iGauge) + { + iGauge->SetGaugeListenerFromAlert(NULL); + } + iGauge = (CMIDNonInteractiveGauge*)(aGauge); + + DEBUG("CMIDAlertDialog::SetGaugeL - InsertGaugeIntoDialogL"); + InsertGaugeIntoDialogL(); + + DEBUG("CMIDAlertDialog::SetGaugeL - CheckAndSetAnimationModeL"); + CheckAndSetAnimationModeL(); + + DrawDeferred(); + DEBUG("CMIDAlertDialog::SetGaugeL >"); +} + +/** Show a pre-created dialog. Dialogs are created as soon +as Alerts are created java side. This is not necessarily when +the dialog must be displayed. */ +void CMIDAlertDialog::ShowL(TBool aShow) +{ + if (aShow != iShowing) + { + if (aShow) + { + iShowing = ETrue; + RouseSleepingDialog(); + +#ifdef RD_SCALABLE_UI_V2 + SetPointerCapture(ETrue); +#endif + } + else + { + ExitSleepingDialog(); + +#ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK + if (iButtonDownReceived) + { + //do feedback if alert was closed by tapping + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if (feedback) + { + feedback->InstantFeedback(ETouchFeedbackPopUp); + } + } +#endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK + +#ifdef RD_SCALABLE_UI_V2 + SetPointerCapture(EFalse); + iButtonDownReceived = EFalse; +#endif + iShowing = EFalse; //attention: iShowing must be true when dismissing + // a dialog or else MakeVisible() won't execute and + // we won't update the fader's stack, @see MakeVisible() + } + + UpdateCbasL(); + } +} + +/** Because CAknPopupForm calls MakeVisible(ETrue) in several +places, including LayoutAndDraw() and because we don't want to +become visible when we are not showing, we had to override the +MakeVisible() method and pass on the call only when we are +showing. Also, CMIDAlert can disable temporarily the MakeVisible +calls by setting iVisibilityChangeDisabled via DisableVisibilityChange(). +This is because when we call SetTitle() or SetImage() we must insert +or remove controls into the dialog and popup form does MakeVisible(EFalse) +and then MakeVisible(ETrue) after the control has been added or removed. +This results in an unpleasant appearing and disappearing of the dialog +because we add or remove more than one control. */ +void CMIDAlertDialog::MakeVisible(TBool aVisible) +{ + if (iShowing && !iVisibilityChangeDisabled) + { + if (aVisible) + { + //re-layouting done just before dialog is shown + //to be sure layout is correct in CAknPopupForm + CAknPopupForm::SizeChanged(); + } + CAknPopupForm::MakeVisible(aVisible); + } +} + + +#ifdef RD_SCALABLE_UI_V2 +/** + * Closes timed alert on EButton1Up event. Detecting long taps is done through + * CMIDAlert::TryDetectLongTapL. + */ +void CMIDAlertDialog::HandlePointerEventL(const TPointerEvent& aPointerEvent) +{ + if (AknLayoutUtils::PenEnabled()) + { + // Long tap may be canceled by dragging pointer out of alert area, + // need to make sure that events are forwarded to long tap detector in this case. + if ((AlertRegionContains(aPointerEvent.iPosition) || + aPointerEvent.iType != TPointerEvent::EButton1Down) && + iParent->TryDetectLongTapL(aPointerEvent)) + { + return; + } + + switch (aPointerEvent.iType) + { + case TPointerEvent::EButton1Down: + iButtonDownReceived = ETrue; + break; + case TPointerEvent::EButton1Up: + if (!iParent->IsModal() && iButtonDownReceived) + { + iParent->TryToDismissDialog(); + } + break; + case TPointerEvent::EDrag: + break; + default: + break; + } + + } +} +#endif + + +/** Disable the MakeVisible() calls. See @MakeVisible() */ +void CMIDAlertDialog::DisableVisibilityChange(TBool aDisable) +{ + iVisibilityChangeDisabled = aDisable; +} + +/** We disable unnecessary layout operation in an attempt to optimise because of + defect OULM-6K4C2X. This would not be needed if CAknPopupForm::InsertControlL() + would not call LayoutAndDraw() every time and also CAknPopupForm::SetSizeAndPosition() + results in the execution of SizeChanged() 3 times. So a lot of layout operations get + in the way of performance. */ +void CMIDAlertDialog::SizeChanged() +{ + if (!iVisibilityChangeDisabled || iShowing) + { + CAknPopupForm::SizeChanged(); + } +} + +void CMIDAlertDialog::HandleResourceChange(TInt aType) +{ + if (aType == KEikDynamicLayoutVariantSwitch) + { + LayoutAndDraw(); + + TRAP_IGNORE(InsertGaugeIntoDialogL(); CheckAndSetAnimationModeL();); + + DrawDeferred(); + } + else + { + CAknPopupForm::HandleResourceChange(aType); + } +} + +#ifdef RD_SCALABLE_UI_V2 +TBool CMIDAlertDialog::AlertRegionContains(const TPoint& aPoint) +{ + return (aPoint.iX >= 0 && aPoint.iX <= iSize.iWidth && + aPoint.iY >= 0 && aPoint.iY <= iSize.iHeight); +} +#endif + +// End of File