uifw/EikStd/coctlsrc/aknstyluspopupmenuphysicshandler.cpp
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
child 14 3320e4e6e8bb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/EikStd/coctlsrc/aknstyluspopupmenuphysicshandler.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,428 @@
+/*
+* Copyright (c) 2009 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:   AknStylusPopUpMenu physics handler
+*
+*/
+
+
+#include <stdlib.h>
+#include <aknphysics.h>
+#include <aknphysicsobserveriface.h>
+#include <AknUtils.h>
+
+#include <touchfeedback.h>
+#include "aknstyluspopupmenuphysicshandler.h"
+#include "aknstyluspopupmenucontent.h"
+
+const TInt KNoItemSelected( -1 ); 
+
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::NewL
+// ---------------------------------------------------------------------------
+//
+ CAknStylusPopUpMenuPhysicsHandler* CAknStylusPopUpMenuPhysicsHandler::NewL(
+    CAknStylusPopUpMenuContent* aPopUpMenuContent )
+    {
+    CAknStylusPopUpMenuPhysicsHandler* self = 
+        CAknStylusPopUpMenuPhysicsHandler::NewLC( aPopUpMenuContent );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::NewLC
+// ---------------------------------------------------------------------------
+//
+CAknStylusPopUpMenuPhysicsHandler* CAknStylusPopUpMenuPhysicsHandler::NewLC( 
+    CAknStylusPopUpMenuContent* aPopUpMenuContent )
+    {
+    CAknStylusPopUpMenuPhysicsHandler* self 
+        = new ( ELeave ) CAknStylusPopUpMenuPhysicsHandler( aPopUpMenuContent );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::~CAknStylusPopUpMenuPhysicsHandler
+// ---------------------------------------------------------------------------
+//
+CAknStylusPopUpMenuPhysicsHandler::~CAknStylusPopUpMenuPhysicsHandler()
+    {
+    delete iPhysics;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::HandlePointerEventL
+// ---------------------------------------------------------------------------
+//
+void CAknStylusPopUpMenuPhysicsHandler::HandlePointerEventL( const TPointerEvent& aPointerEvent )
+    {
+
+    // EButton1Down
+    if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
+        {
+        
+        TBool wasScrolling = ( iPhysics->OngoingPhysicsAction() != 
+            CAknPhysics::EAknPhysicsActionNone );
+        
+        iPosition = aPointerEvent.iPosition;
+        iStartPosition = aPointerEvent.iPosition;
+
+        StopPhysics();
+        iStartTime.HomeTime();
+        iPanningActivated = EFalse;
+        iPressedDown = ETrue;
+                
+        
+        // if pointer event (EButton1Down) inside items rect, launch higlight timer
+        // if content was not flicking, set also item to be selected
+        
+        TPoint adjustedPosition( aPointerEvent.iPosition + TPoint(0, Offset() ) );
+        TInt item = iPopUpMenuContent->ContainingItem( adjustedPosition );
+        if ( item != KNoItemSelected )
+            {
+            if ( !wasScrolling )
+                {
+                SetHighlight( item );
+                CCoeEnv::Static()->WsSession().Finish();
+                }
+
+            MTouchFeedback* feedback = MTouchFeedback::Instance();
+            if ( feedback )
+                {
+                feedback->InstantFeedback( NULL,
+                                           ETouchFeedbackList,
+                                           aPointerEvent );
+                }
+            }
+        }
+    
+    // EDrag    
+   
+    if ( aPointerEvent.iType == TPointerEvent::EDrag )
+        {
+        TInt distanceFromStart( iStartPosition.iY - aPointerEvent.iPosition.iY );
+        
+        if ( !iPanningActivated && Abs( distanceFromStart ) > DragThreshold() )
+            {
+            iPanningActivated = ETrue;
+            iPosition = aPointerEvent.iPosition;
+
+            // clear highlight
+            iPopUpMenuContent->SetHighlight( KNoItemSelected );
+            }
+			
+        if ( iPanningActivated )
+            {
+            TInt deltaY( iPosition.iY - aPointerEvent.iPosition.iY );
+            iPosition = aPointerEvent.iPosition;
+            iPhysics->RegisterPanningPosition( TPoint( 0, deltaY ) );
+            }
+        }
+
+    // EButton1Up   
+   
+    if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
+        {
+        iPressedDown = EFalse;              
+        TPoint adjustedPosition( aPointerEvent.iPosition + TPoint(0, Offset() ) );
+        TInt item = iPopUpMenuContent->ContainingItem( adjustedPosition );
+        if ( item != KNoItemSelected )
+            {
+        MTouchFeedback* feedback = MTouchFeedback::Instance();
+        if ( feedback )
+            {
+                feedback->InstantFeedback( NULL,
+                                           ETouchFeedbackList,
+                                           ETouchFeedbackVibra,
+                                           aPointerEvent );
+                }
+            }
+ 
+        TPoint distance( 0, iStartPosition.iY - aPointerEvent.iPosition.iY );
+        if ( iPhysics->StartPhysics( distance, iStartTime ) )
+            {
+            return;
+            }
+            
+        // select item 
+        if ( !iPanningActivated && 
+                iPopUpMenuContent->CurrentItem() != KNoItemSelected )
+            {
+            if ( iViewRect.Contains( aPointerEvent.iPosition ) )
+                {
+                iPopUpMenuContent->SelectItem( 
+                        iPopUpMenuContent->CurrentItem() );
+                }
+            else 
+                {
+                // Clear highlight
+                SetHighlight( KNoItemSelected );
+                }
+            }
+        }
+   }
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::SetViewRect
+// ---------------------------------------------------------------------------
+//
+void CAknStylusPopUpMenuPhysicsHandler::SetViewRect( const TRect& aRect )
+    {
+    iViewRect = aRect;
+    }
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::SetItemHeight
+// ---------------------------------------------------------------------------
+//
+void CAknStylusPopUpMenuPhysicsHandler::SetItemHeight( TInt aItemHeight )
+    {
+    iItemHeight = aItemHeight;
+    }
+    
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::SetWorldHeight
+// ---------------------------------------------------------------------------
+//
+void CAknStylusPopUpMenuPhysicsHandler::SetWorldHeight( TInt aWorldHeight )
+    {
+    iWorldHeight = aWorldHeight;
+    }
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::Offset
+// ---------------------------------------------------------------------------
+//
+TInt CAknStylusPopUpMenuPhysicsHandler::Offset() const 
+    {
+    if ( iItemHeight == 0 )
+        {
+        return 0;
+        }
+        
+    if ( iScrollIndex < 0 )
+        {
+        return iScrollIndex;
+        }
+    
+    if ( iScrollIndex >= iWorldHeight - iViewRect.Height() )
+        {
+        return iScrollIndex - ( iWorldHeight - iViewRect.Height() );
+        }   
+    
+    return iScrollIndex % iItemHeight;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::InitPhysicsL
+// ---------------------------------------------------------------------------
+//   
+void CAknStylusPopUpMenuPhysicsHandler::InitPhysicsL()
+    {
+    TSize worldSize( iViewRect.Width(), iWorldHeight );
+    TSize viewSize( iViewRect.Width(), iViewRect.Height() );
+    
+    iPhysics->InitPhysicsL( worldSize, viewSize, EFalse );
+    iPhysics->UpdateViewWindowControl( iPopUpMenuContent );
+    }
+    
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::HandleScrollEvent
+// ---------------------------------------------------------------------------
+//     
+void CAknStylusPopUpMenuPhysicsHandler::HandleScrollEvent( TInt aNewScrollIndex )
+    {
+    iScrollIndex = aNewScrollIndex;
+    ScrollView();                        
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::Reset
+// ---------------------------------------------------------------------------
+//
+void CAknStylusPopUpMenuPhysicsHandler::Reset()
+    {
+    iPrevOffset = -1;
+    iPrevTopmostItem = -1;
+    iScrollIndex = 0;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::ViewPositionChanged
+// ---------------------------------------------------------------------------
+//
+void CAknStylusPopUpMenuPhysicsHandler::ViewPositionChanged(
+    const TPoint& aNewPosition,
+    TBool aDrawNow,
+    TUint /*aFlags*/ )
+    {
+    if ( !iPopUpMenuContent->IsVisible() )
+    	{
+    	return;
+    	}    
+    iScrollIndex = aNewPosition.iY - iViewRect.Height() / 2;
+    
+    ScrollView( aDrawNow );
+    }
+    
+    
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::PhysicEmulationEnded
+// ---------------------------------------------------------------------------
+//    
+void CAknStylusPopUpMenuPhysicsHandler::PhysicEmulationEnded()
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::ViewPosition
+// ---------------------------------------------------------------------------
+//    
+TPoint CAknStylusPopUpMenuPhysicsHandler::ViewPosition() const
+    {
+    return TPoint( iViewRect.Width() / 2, iScrollIndex + iViewRect.Height() / 2 ); 
+    }
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::CAknStylusPopUpMenuPhysicsHandler
+// ---------------------------------------------------------------------------
+//
+CAknStylusPopUpMenuPhysicsHandler::CAknStylusPopUpMenuPhysicsHandler( 
+    CAknStylusPopUpMenuContent* aPopUpMenuContent )
+    :
+    iPopUpMenuContent( aPopUpMenuContent ),
+    iPhysics( NULL ),
+    iPrevOffset( -1 ),
+    iPrevTopmostItem( -1 ),
+    iOffsetItemCount( 0 )
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CAknStylusPopUpMenuPhysicsHandler::ConstructL()
+    {
+    iPhysics = CAknPhysics::NewL( *this, iPopUpMenuContent );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::DragThreshold
+// ---------------------------------------------------------------------------
+//     
+TInt CAknStylusPopUpMenuPhysicsHandler::DragThreshold()
+    {
+    return iPhysics->DragThreshold();
+    }
+
+
+
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::SetHighlight
+// ---------------------------------------------------------------------------
+//     
+void CAknStylusPopUpMenuPhysicsHandler::SetHighlight( TInt aItem )
+    {
+    iPopUpMenuContent->SetHighlight( aItem );
+    }
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::ScrollView
+// ---------------------------------------------------------------------------
+//     
+void CAknStylusPopUpMenuPhysicsHandler::ScrollView( TBool aDrawNow )
+    {
+    if ( iItemHeight != 0 )
+        {
+        TInt scrollIndex( Min( iScrollIndex, iWorldHeight - iViewRect.Height() ) );
+        TInt topmostItem( scrollIndex / iItemHeight );
+        
+        // Update view based on topmostItem and offset.
+        // Offset is retrieved from Physics handler by PopupMenuContent
+        // inside this function call.
+        
+        // Update only if topmost item or offset changed 
+        if ( aDrawNow &&
+             ( topmostItem != iPrevTopmostItem || Offset() != iPrevOffset ) )
+            {
+            iPopUpMenuContent->UpdateView( topmostItem );
+            }
+
+        iPrevOffset = Offset();
+        iPrevTopmostItem = topmostItem;    
+        
+        //when appear or dispear a tiem,a feedback was given.
+        if ( abs( iPrevOffset ) <= iViewRect.Height()
+              && ( iPrevOffset/iItemHeight ) != iOffsetItemCount )
+            {
+            if ( iPhysics )
+                {
+                TTouchFeedbackType feedbackType = ETouchFeedbackVibra;
+                switch( iPhysics->OngoingPhysicsAction() )
+                    {
+                    case CAknPhysics::EAknPhysicsActionDragging:
+                        {
+                        feedbackType = static_cast<TTouchFeedbackType>
+                                  ( ETouchFeedbackVibra | ETouchFeedbackAudio );
+                        }
+                    case CAknPhysics::EAknPhysicsActionFlicking:
+                    case CAknPhysics::EAknPhysicsActionBouncing:
+                        {
+                        MTouchFeedback* feedback = MTouchFeedback::Instance();
+                        if ( feedback )
+                            {
+                            feedback->InstantFeedback( iPopUpMenuContent,
+                                                    ETouchFeedbackSensitiveList,
+                                                    feedbackType,
+                                                    TPointerEvent() );
+                            }
+                        break;
+                        }
+                    default:
+                        break;
+                    }
+                }
+            }
+        iOffsetItemCount = iPrevOffset/iItemHeight;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAknStylusPopUpMenuPhysicsHandler::StopPhysics
+// ---------------------------------------------------------------------------
+//
+void CAknStylusPopUpMenuPhysicsHandler::StopPhysics()
+    {
+    iPhysics->StopPhysics();
+    iPhysics->ResetFriction();
+    }