--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/lcdui/src/CMIDMenuHandler.cpp Wed Sep 01 12:33:18 2010 +0100
@@ -0,0 +1,472 @@
+/*
+* Copyright (c) 2003-2008 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: Menu pane handling, common across all Displayables.
+*
+*/
+
+
+// INCLUDE FILES
+// CEikonEnv API for iEkonEnv :
+// - to retrieving CEikAppUi
+// - to obtain device screen size
+#include <eikenv.h>
+// API for iAppUi
+#include <eikappui.h>
+// API for iMenuBar
+#include <eikmenub.h>
+#include <e32cmn.h>
+#include <AknUtils.h>
+// using constants for soft keys
+#include <avkon.hrh>
+// mocros for avkon resources
+#include <avkon.rsg>
+// macros for resources
+#include <lcdui.rsg>
+// API needed for iDisplayable and iDefaultDisplayable members
+#include "CMIDDisplayable.h"
+#include "CMIDCanvas.h"
+#include "CMIDMenuHandler.h"
+// CMIDTickerController API for iTickerController (stored in tls structure)
+#include "CMIDTicker.h"
+// for setting key decoder in tls
+#include "CMIDKeyDecoder.h"
+#include "lcdui.h"
+#include <j2me/jdebug.h>
+#include "CMIDUIManager.h"
+#include "coreuiavkonlcdui.h"
+#include "coreuiappui.h"
+
+
+const TInt KResolutionStringLength = 4;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+// -----------------------------------------------------------------------------
+// CMIDMenuHandler::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CMIDMenuHandler* CMIDMenuHandler::NewL(MMIDEnv& aEnv)
+{
+ CMIDMenuHandler* self = new(ELeave) CMIDMenuHandler(aEnv);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+
+ return self;
+}
+
+// -----------------------------------------------------------------------------
+// CMIDMenuHandler::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CMIDMenuHandler::ConstructL()
+{
+ iAppUi = iEikEnv.EikAppUi();
+ iMenuBar = new(ELeave) CEikMenuBar;
+ iMenuBar->ConstructL(this, 0, R_MIDP_MENUBAR_DEFAULT);
+
+ iCba = CEikButtonGroupContainer::NewL(CEikButtonGroupContainer::ECba,
+ CEikButtonGroupContainer::EHorizontal,
+ this,
+ R_AVKON_SOFTKEYS_EMPTY);
+#ifdef RD_JAVA_S60_RELEASE_9_2
+ static_cast<CEikCba*>(iCba->ButtonGroup())->EnableItemSpecificSoftkey(EFalse);
+#endif
+ const TSize screenSize = iEikEnv.ScreenDevice()->SizeInPixels();
+ iCba->SetBoundingRect(TRect(screenSize));
+ iViewRect = iAppUi->ClientRect();
+ iCba->ReduceRect(iViewRect);
+ iAppUi->AddToStackL(iMenuBar,ECoeStackPriorityMenu,ECoeStackFlagRefusesFocus);
+ SetScalingFactors();
+}
+
+
+void CMIDMenuHandler::HideMenuIfVisible()
+{
+ if (iMenuBar->IsDisplayed())
+ {
+ iMenuBar->StopDisplayingMenuBar();
+ }
+}
+
+void CMIDMenuHandler::UpdateMenuIfVisibleL()
+{
+ if (iMenuBar->IsDisplayed())
+ { // Menu is currently displayed
+
+ iMenuBar->StopDisplayingMenuBar();
+
+ ShowMenuL(iMenuType);
+ }
+}
+
+
+// C++ default constructor
+CMIDMenuHandler::CMIDMenuHandler(MMIDEnv& aEnv)
+ : iEnv(aEnv)
+ ,iEikEnv(*(CEikonEnv::Static()))
+{
+}
+
+// Destructor
+CMIDMenuHandler::~CMIDMenuHandler()
+{
+ HideMenuIfVisible();
+ if (iAppUi)
+ {
+ iAppUi->RemoveFromStack(iMenuBar);
+ }
+ delete iMenuBar;
+ delete iCba;
+ iMenuItems.Reset();
+}
+
+// -----------------------------------------------------------------------------
+// CMIDMenuHandler::ShowMenuL
+//
+// @see DynInitMenuPaneL()
+// -----------------------------------------------------------------------------
+//
+void CMIDMenuHandler::ShowMenuL(const TMenuType& aType)
+{
+ if (iDisplayable && aType != ENoMenu && !iAttemptingToDisplayMenu)
+ {
+ iMenuType = aType;
+ iDisplayable->CreateMenuItemsL(iMenuType, iMenuItems);
+
+ // Set the CEikMenuBar type according to internal type
+ if (aType == EOptionsMenu)
+ {
+ iMenuBar->SetMenuType(CEikMenuBar::EMenuOptions);
+ }
+ else if (aType == EOkMenu || aType == EHelpMenu || aType == EScreenAndHelpMenu)
+ {
+ iMenuBar->SetMenuType(CEikMenuBar::EMenuContext);
+ }
+
+ // If there is anything to show, open the menu
+ if (iMenuItems.Count() > 0 && !iMenuBar->IsDisplayed())
+ {
+ iAttemptingToDisplayMenu = ETrue;
+ iMenuBar->TryDisplayMenuBarL();
+ }
+ // Reset the menu type always to options menu just in case
+ iMenuBar->SetMenuType(CEikMenuBar::EMenuOptions);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CMIDMenuHandler::MenuItemsCount
+//
+//
+// -----------------------------------------------------------------------------
+//
+TUint CMIDMenuHandler::MenuItemsCount() const
+{
+ return iMenuItems.Count();
+}
+
+// -----------------------------------------------------------------------------
+// CMIDMenuHandler::SetDisplayable
+//
+//
+// -----------------------------------------------------------------------------
+//
+void CMIDMenuHandler::SetDisplayable(CMIDDisplayable* aDisplayable)
+{
+ iDisplayable = aDisplayable;
+
+ if (iDisplayable)
+ {
+ SendMultipleKeyPressedEvent();
+ }
+}
+// -----------------------------------------------------------------------------
+// CMIDMenuHandler::SendMultipleKeyPressedEventL
+//
+//
+// -----------------------------------------------------------------------------
+//
+void CMIDMenuHandler::SendMultipleKeyPressedEvent()
+{
+ ASSERT(iDisplayable);
+ java::ui::CoreUiAvkonAppUi* appUi =
+ java::ui::CoreUiAvkonLcdui::getInstance().getJavaUiAppUi();
+ if (appUi)
+ {
+ MMIDComponent* component = iDisplayable->Component();
+ if (component)
+ {
+ if (component->Type() == MMIDComponent::ECanvas)
+ {
+ appUi->glueSetKeyBlockMode(ENoKeyBlock);
+ }
+ else
+ {
+ appUi->glueSetKeyBlockMode(EDefaultBlockMode);
+ }
+ }
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CMIDMenuHandler::ProcessCommandL
+//
+//
+// -----------------------------------------------------------------------------
+//
+void CMIDMenuHandler::ProcessCommandL(TInt aCommandId)
+{
+ HideMenuIfVisible();
+
+ //
+ if (aCommandId == EAknSoftkeyExit)
+ {
+ iAppUi->HandleCommandL(EEikCmdExit);
+ return;
+ }
+
+ if (aCommandId == EEikCmdCanceled)
+ {
+ return;
+ }
+
+ if (aCommandId == EAknSoftkeyOptions)
+ {
+ ShowMenuL(EOptionsMenu);
+ return;
+ }
+
+ if (aCommandId == EStdKeyDevice3)
+ {
+ ShowMenuL(EOkMenu);
+ return;
+ }
+
+ if (iDisplayable)
+ {
+ iDisplayable->ProcessCommandL(aCommandId);
+ }
+}
+
+// -----------------------------------------------------------------------------
+// CMIDMenuHandler::SetEmphasis
+//
+//
+// -----------------------------------------------------------------------------
+//
+void CMIDMenuHandler::SetEmphasis(CCoeControl* aMenuControl,TBool aEmphasis)
+{
+ if (!iDisplayable)
+ {
+ return;
+ }
+
+ if (aEmphasis)
+ {
+ if (MMIDComponent::ECanvas == iDisplayable->Component()->Type())
+ {
+ iEnv.PostMidletEvent(EBackground);
+ }
+ }
+ else
+ {
+ if (MMIDComponent::ECanvas == iDisplayable->Component()->Type())
+ {
+ iEnv.PostMidletEvent(EForeground);
+ }
+ }
+
+ iAppUi->UpdateStackedControlFlags(aMenuControl, aEmphasis? 0: ECoeStackFlagRefusesFocus,
+ ECoeStackFlagRefusesFocus);
+ iAppUi->HandleStackChanged();
+}
+
+// -----------------------------------------------------------------------------
+// CMIDMenuHandler::DynInitMenuPaneL
+//
+//
+// -----------------------------------------------------------------------------
+void CMIDMenuHandler::DynInitMenuPaneL(TInt aResourceId, CEikMenuPane* aMenuPane)
+{
+ if (aResourceId == R_MIDP_MENUPANE_DISPLAYABLE)
+ {
+ TInt numItems = iMenuItems.Count();
+ for (TInt i = 0; i < numItems; i++)
+ {
+ aMenuPane->AddMenuItemL(iMenuItems[i]);
+ }
+
+ iAttemptingToDisplayMenu = EFalse;
+ }
+
+}
+
+
+/** SetScalingFactors
+
+ Sets MIDlet's original size and target size resolutions if those are defined in JAD or manifest.
+ If attribute is missing or it's not defined correctly, the value will be 0,0.
+ This value is later used as an "error value".
+ @param -
+ @return -
+
+ */
+void CMIDMenuHandler::SetScalingFactors()
+{
+ TPtrC orgSize;
+ // If JAD attribute Nokia-MIDlet-Original-Display-Size is defined, it will be used to scale Canvas.
+ if (iEnv.MidletAttribute(LcduiMidletAttributes::KAttribOrigDisplaySize, orgSize) == KErrNone)
+ {
+ iOrgMIDletScrSize = DesToTSize(orgSize);
+ TPtrC targetSize;
+ // If JAD attribute Nokia-MIDlet-Original-Display-Size and Nokia-MIDlet-Target-Display-Size are defined,
+ // those will be used to scale Canvas.
+ // If Nokia-MIDlet-Target-Display-Size is invalid, Canvas will still be scaled,
+ // if Nokia-MIDlet-Original-Display-Size is correct.
+ if (iOrgMIDletScrSize.iHeight != 0 && iOrgMIDletScrSize.iWidth != 0 &&
+ iEnv.MidletAttribute(LcduiMidletAttributes::KAttribTargetDisplaySize,
+ targetSize) == KErrNone)
+ {
+ iTargetMIDletScrSize = DesToTSize(targetSize);
+ }
+
+ // Load Nokia-MIDlet-allow-scaling-on-orientation-switch attribute
+ // setting. This attribute is valid only when original MIDlet size
+ // is defined.
+ if (iOrgMIDletScrSize.iHeight != 0 && iOrgMIDletScrSize.iWidth != 0)
+ {
+ iScaleMIDletOnOrientSwitch = iEnv.MidletAttributeIsSetToVal(
+ LcduiMidletAttributes::KAttribAllowScalingOnOrientationSwitch,
+ LcduiMidletAttributeValues::KTrueValue);
+ }
+ }
+}
+
+/** DesToTSize
+
+ Utility to parse TPtrC to TSize.
+ This util is made for graphics scaling feature.
+ @param TPtrC
+ @return TSize
+
+ */
+TSize CMIDMenuHandler::DesToTSize(TPtrC scrSize)
+{
+ TSize newSize;
+ TSize errorSize(0, 0);
+ TInt newIntWidth;
+ TInt newIntHeight;
+ // Assumed max. 9999 pixels in width.
+ TBuf<KResolutionStringLength> newWidth;
+ // Assumed max. 9999 pixels in height.
+ TBuf<KResolutionStringLength> newHeight;
+ TChar tmpChar;
+ _LIT(lComma, ",");
+ TChar comma(',');
+
+ // The digits of width and height must be divided by comma
+ if (scrSize.Find(lComma) != KErrNotFound)
+ {
+ TLex16 lex(scrSize);
+ while (lex.Peek() != comma)
+ {
+ tmpChar = lex.Get();
+ if (tmpChar.IsDigit() && newWidth.Length() < KResolutionStringLength)
+ {
+ newWidth.Append(tmpChar);
+ }
+ else if (!tmpChar.IsSpace())
+ {
+ // If character is not digit or space
+ return errorSize;
+ }
+ }
+ lex.Get();
+ while (!lex.Eos())
+ {
+ tmpChar = lex.Get();
+ if (tmpChar.IsDigit() && newHeight.Length() < KResolutionStringLength)
+ {
+ newHeight.Append(tmpChar);
+ }
+ else if (!tmpChar.IsSpace())
+ {
+ // If character is not digit or space
+ return errorSize;
+ }
+ }
+
+ // Width and height must have at least one digit each
+ if (newWidth.Length() > 0 && newHeight.Length() > 0)
+ {
+ TLex16 widthLex(newWidth);
+ widthLex.Val(newIntWidth);
+ TLex16 heightLex(newHeight);
+ heightLex.Val(newIntHeight);
+ newSize.SetSize(TInt(newIntWidth), TInt(newIntHeight));
+ return newSize;
+ }
+ }
+ // If there is no comma between the digits or there is no digits in width or height
+ return errorSize;
+}
+
+TSize CMIDMenuHandler::GetScreenSize() const
+{
+ // It get size of screen from iEikEnv's screen device.
+ const CEikonEnv* env = &iEikEnv;
+ return env->ScreenDevice()->SizeInPixels();
+}
+
+TBool CMIDMenuHandler::IsScalingEnabled() const
+{
+ //If iOrgMIDletScrSize has been initialized then scaling is on.
+ //It's enough to check either height or width only.
+ return (iOrgMIDletScrSize.iHeight != 0);
+}
+
+TBool CMIDMenuHandler::IsScalingEffectiveInCurrentScreen() const
+{
+ if (IsScalingEnabled())
+ {
+ TRect screen;
+ AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, screen);
+ TSize screenSize = screen.Size();
+
+ TSize origResolution = iOrgMIDletScrSize;
+ if (iScaleMIDletOnOrientSwitch)
+ {
+ // ensure that origResolution and screenSize are in portrait
+ origResolution = TSize(Min(iOrgMIDletScrSize.iHeight, iOrgMIDletScrSize.iWidth),
+ Max(iOrgMIDletScrSize.iHeight, iOrgMIDletScrSize.iWidth));
+ screenSize = TSize(Min(screen.Height(), screen.Width()),
+ Max(screen.Height(), screen.Width()));
+ }
+
+ // If origResolution and screenSize are different, then
+ // scaling is effective.
+ return (screenSize.iHeight != origResolution.iHeight ||
+ screenSize.iWidth != origResolution.iWidth);
+ }
+ else
+ {
+ return EFalse;
+ }
+}
+// End of File