javauis/lcdui_akn/lcdui/src/CMIDMenuHandler.cpp
branchRCL_3
changeset 19 04becd199f91
child 60 6c158198356e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/lcdui/src/CMIDMenuHandler.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,469 @@
+/*
+* 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"
+
+
+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);
+
+    RWsSession  wsSession = CCoeEnv::Static()->WsSession();
+    TWsEvent event;
+
+    // Check the current Display type if it is canvas enable the
+    // multiple key events, other wise disable it.
+    MMIDComponent* component = iDisplayable->Component();
+    MMIDComponent::TType type = component->Type();
+
+    if (type == MMIDComponent::ECanvas)
+        event.SetType(EEnableMultipleKeyPressedEvent); // set event type enable multiple key pressed event
+    else
+        event.SetType(EDisableMultipleKeyPressedEvent); // set event type disable multiple key pressed event
+    event.SetTimeNow(); // set the event time
+    event.SetHandle(wsSession.WsHandle()); // set window server handle
+    wsSession.SendEventToAllWindowGroups(event);
+}
+
+
+// -----------------------------------------------------------------------------
+// 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