uifw/EikStd/coctlsrc/aknstyluspopupmenu.cpp
branchRCL_3
changeset 56 d48ab3b357f1
parent 55 aecbbf00d063
child 64 85902f042028
--- a/uifw/EikStd/coctlsrc/aknstyluspopupmenu.cpp	Tue Aug 31 15:28:30 2010 +0300
+++ b/uifw/EikStd/coctlsrc/aknstyluspopupmenu.cpp	Wed Sep 01 12:16:19 2010 +0100
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* Copyright (c) 2005-2010 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"
@@ -24,7 +24,9 @@
 #include <eikapp.h>
 #include <aknappui.h>
 #include <AknDef.h>
-
+#include <touchfeedback.h>
+#include <akntranseffect.h>
+#include <akntransitionutils.h>
 #include "aknstyluspopupmenu.h"
 #include "aknstyluspopupmenucontent.h"
 
@@ -44,11 +46,13 @@
 //
 CAknStylusPopUpMenu::CAknStylusPopUpMenu( MEikMenuObserver* aObserver, 
     const TPoint& aPoint,
-    CAknPreviewPopUpController* aPopup ) 
+    CAknPreviewPopUpController* aPopup,
+    const TInt aFlags )
     : iPosition ( aPoint ),
      iMenuObserver( aObserver ),
      iPreviewPopup( aPopup ),
-     iPositionType( EPositionTypeLeftTop )
+     iPositionType( EPositionTypeLeftTop ),
+     iModeFlags ( aFlags )
     {
     }
 
@@ -81,6 +85,24 @@
     return self;
     }
 
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenu::NewL
+// ---------------------------------------------------------------------------
+//
+CAknStylusPopUpMenu* CAknStylusPopUpMenu::NewL( MEikMenuObserver* aObserver,
+        const TPoint& aPoint,
+        CAknPreviewPopUpController* aPopup,
+        const TInt aFlags )
+    {
+    CAknStylusPopUpMenu* self = new ( ELeave ) CAknStylusPopUpMenu( aObserver,
+                                                                    aPoint,
+                                                                    aPopup,
+                                                                    aFlags );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
 
 // ---------------------------------------------------------------------------
 // CAknStylusPopUpMenu::NewL
@@ -119,6 +141,10 @@
 //
 CAknStylusPopUpMenu::~CAknStylusPopUpMenu()
     {
+    if ( iContent )
+        {
+        iContent->SetObserver(NULL);
+        }
     if ( iIsDeleted )
         {
         *iIsDeleted = ETrue;
@@ -172,23 +198,56 @@
 //
 EXPORT_C void CAknStylusPopUpMenu::ShowMenu()
     {
-    TRAPD( err, 
-           iController = CAknPreviewPopUpController::NewL( *iContent,
-                   CAknPreviewPopUpController::ELayoutSubMenu | 
-                   CAknPreviewPopUpController::EAutoMirror |
-                   CAknPreviewPopUpController::EDontClose ) );
-    if ( err )
+    // if contoller exists, re-use it .
+    if ( !iController )
         {
-        return;
-        }
+        TInt err ( KErrNone );
+
+        if ( iModeFlags & EConsumeKeyEvents )
+            {
+            TRAP( err, iController = CAknPreviewPopUpController::NewL(
+                    *iContent,
+                    CAknPreviewPopUpController::ELayoutSubMenu |
+                    CAknPreviewPopUpController::EAutoMirror |
+                    CAknPreviewPopUpController::EDontClose |
+                    CAknPreviewPopUpController::EConsumeKeys ) );
+            }
+        else
+            {
+            TRAP( err, iController = CAknPreviewPopUpController::NewL(
+                    *iContent,
+                    CAknPreviewPopUpController::ELayoutSubMenu |
+                    CAknPreviewPopUpController::EAutoMirror |
+                    CAknPreviewPopUpController::EDontClose ) );
+            }
+        if ( err )
+            {
+            return;
+            }
             
-    iController->SetPopUpShowDelay( KDefaultPopUpShowDelay );
-    iController->SetPopUpHideDelay( KDefaultPopUpHideDelay );
-    iContent->Parent()->DrawableWindow()->SetNonFading(ETrue);
+        iController->SetPopUpShowDelay( KDefaultPopUpShowDelay );
+        iController->SetPopUpHideDelay( KDefaultPopUpHideDelay );
+        }
     
     TSize size(iController->Size());
     iController->ShowPopUp();
-
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        MTouchFeedback* feedback = MTouchFeedback::Instance();
+        if ( feedback )
+            {
+            TTouchLogicalFeedback feedbackType = ETouchFeedbackPopUp;
+            if ( CAknTransitionUtils::TransitionsEnabled( AknTransEffect::EComponentTransitionsOff ) )
+                {
+                feedbackType = ETouchFeedbackOptionsMenuOpened;
+                }
+            feedback->InstantFeedback(
+                    iContent,
+                    feedbackType,
+                    ETouchFeedbackVibra,
+                    TPointerEvent() );
+            }
+        }
     if ( size.iWidth == 0 && size.iHeight == 0 )
         {
         if ( iPositionType != KErrNotFound )
@@ -223,7 +282,8 @@
 // CAknStylusPopUpMenu::SetPosition 
 // ---------------------------------------------------------------------------
 //
-EXPORT_C void CAknStylusPopUpMenu::SetPosition( const TPoint& aPoint, TPositionType aPosType )
+EXPORT_C void CAknStylusPopUpMenu::SetPosition( const TPoint& aPoint,
+                                                TPositionType aPosType )
     {
     TPoint adjustedPoint( aPoint );
     if ( !iController )
@@ -232,41 +292,106 @@
         iPositionType = aPosType;
         return;
         }
+
     iController->UpdateContentSize(); 
     TSize menuSize = iController->Size();
-	// calculate to right-top corner by aPosType and popup menu size
+
+	// Calculate the position to right-top corner by aPosType and
+    // popup menu size. Add also a margin between the screen borders and the
+    // popup if the popup is too close to screen border.
+    TBool layoutMirrored( AknLayoutUtils::LayoutMirrored() );
+    TRect screenRect;
+    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen,
+                                       screenRect );
+    
+    // Margin is read from the popup window's layout data
+    // (left parameter used).
+    TAknWindowLineLayout popupWindowLayout(
+        AknLayoutScalable_Avkon::popup_touch_menu_window( 0 ).LayoutLine() );
+    TInt windowMargin = layoutMirrored ? popupWindowLayout.ir :
+                                         popupWindowLayout.il;
+
     switch ( aPosType )	
         {
-        case EPositionTypeRightTop: 
+        case EPositionTypeRightTop:
+            {
             break;
+            }
+
         case EPositionTypeLeftTop:
-            if( AknLayoutUtils::LayoutMirrored() ) 
+            {
+            if ( !layoutMirrored ) 
                 {
-                adjustedPoint.iX -= menuSize.iWidth;
+                adjustedPoint.iX += menuSize.iWidth;
                 }
-            else
+
+            break;
+            }
+
+        case EPositionTypeRightBottom:
+            {
+            adjustedPoint.iY -= menuSize.iHeight;
+
+            break;
+            }
+
+        case EPositionTypeLeftBottom:
+            {
+            if ( !layoutMirrored ) 
                 {
                 adjustedPoint.iX += menuSize.iWidth;
                 }
-            break;   
-        case EPositionTypeRightBottom:
+
             adjustedPoint.iY -= menuSize.iHeight;
+
+            break;
+            }
+
+        default:
+            {
             break;
-        case EPositionTypeLeftBottom: 
-            if( AknLayoutUtils::LayoutMirrored() ) 
-                {
-                adjustedPoint.iX -= menuSize.iWidth;
-                }
-            else
-                {
-                adjustedPoint.iX += menuSize.iWidth;
-                }
-            adjustedPoint.iY -= menuSize.iHeight;
-            break;    
-        default:
-            break;  
+            }
+        }
+
+    // Check if margins need to be added.
+    TInt xLeftPos( layoutMirrored ? adjustedPoint.iX :
+                                    adjustedPoint.iX - menuSize.iWidth );
+    TInt xRightPos( layoutMirrored ? adjustedPoint.iX + menuSize.iWidth :
+                                     adjustedPoint.iX );
+    TInt xPosRightMargin( screenRect.iBr.iX - windowMargin );
+    TInt xPosBottomMargin( screenRect.iBr.iY - windowMargin );
+
+    if ( xLeftPos < windowMargin )
+        {
+        // Too close to the left side of the screen.
+        adjustedPoint.iX = windowMargin + menuSize.iWidth;
+        }
+    else if ( xRightPos > xPosRightMargin )
+        {
+        // Too close to the right side of the screen.
+        if ( layoutMirrored )
+            {
+            // In mirrored layout a left-top position must be provided
+            // for the preview popup controller.
+            adjustedPoint.iX = xPosRightMargin - menuSize.iWidth;
+            }
+        else
+            {
+            adjustedPoint.iX = xPosRightMargin;
+            }
+        }
+
+    if ( adjustedPoint.iY < windowMargin )
+        {
+        // Too close to the top border of the screen.
+        adjustedPoint.iY = windowMargin;
+        }
+    else if ( adjustedPoint.iY + menuSize.iHeight > xPosBottomMargin )
+        {
+        // Too close to the bottom border of the screen.
+        adjustedPoint.iY = xPosBottomMargin - menuSize.iHeight;
+        }
     
-        }
     iPosition = adjustedPoint;           
     iController->SetPosition( adjustedPoint ); 
     }
@@ -312,19 +437,26 @@
 
         if ( iMenuObserver )
             {
+            TBool isAlreadySet = iFlags.IsSet( EIdleDisabled );
+
             iFlags.Set( EIdleDisabled );
             TBool isDeleted = EFalse;
             iIsDeleted = &isDeleted;
 
+            CleanupStack::PushL( TCleanupItem( CleanLocalRef, this ) );
             iMenuObserver->ProcessCommandL( iContent->CurrentCommandId() );
-
+            CleanupStack::Pop();
+            
             if ( isDeleted )
                 {
                 return;
                 }
 
             iIsDeleted = NULL;
-            iFlags.Clear( EIdleDisabled );
+            if( !isAlreadySet )
+                {
+                iFlags.Clear( EIdleDisabled );
+                }
             }
 
         StartControllerIdleL();
@@ -335,6 +467,7 @@
             {
             iPreviewPopup->HidePopUp();
             }
+
         if ( iController )
             {
             iController->HidePopUp();
@@ -346,9 +479,16 @@
         {
         if ( iMenuObserver )
             {
+            TBool isAlreadySet = iFlags.IsSet( EIdleDisabled );
+
             iFlags.Set( EIdleDisabled );
             iMenuObserver->ProcessCommandL( KErrCancel );
-            iFlags.Clear( EIdleDisabled );
+
+            if( !isAlreadySet )
+                {
+                iFlags.Clear( EIdleDisabled );
+                }
+
             }
 
         StartControllerIdleL();
@@ -379,6 +519,20 @@
         }
     }
 
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenu::HideMenu
+// ---------------------------------------------------------------------------
+//
+void CAknStylusPopUpMenu::HideMenu()
+    {
+    if ( iController )
+        {
+        iController->HidePopUp();
+        }
+    }
+
+
 // -----------------------------------------------------------------------------
 // CAknStylusPopUpMenu::StartControllerIdleL
 // -----------------------------------------------------------------------------
@@ -424,3 +578,12 @@
         iController = NULL;
         }
     }
+
+// -----------------------------------------------------------------------------
+// CAknStylusPopUpMenu::CleanLocalRef
+// -----------------------------------------------------------------------------
+//
+void CAknStylusPopUpMenu::CleanLocalRef( TAny* aParam )
+    {
+    static_cast<CAknStylusPopUpMenu*>( aParam )->iIsDeleted = NULL;
+    }