photosgallery/viewframework/views/cloudview/src/glxcloudviewcontrol.cpp
changeset 2 7d9067c6fcb1
parent 0 4e91876724a2
child 9 6b87b143d312
--- a/photosgallery/viewframework/views/cloudview/src/glxcloudviewcontrol.cpp	Thu Jan 07 12:46:23 2010 +0200
+++ b/photosgallery/viewframework/views/cloudview/src/glxcloudviewcontrol.cpp	Mon Jan 18 20:19:20 2010 +0200
@@ -33,7 +33,7 @@
 #include <alf/alfdisplay.h> // For CAlfDisplay
 #include <alf/ialfscrollbarmodel.h> // For alfScrollbar model
 #include <aknlayoutscalable_uiaccel.cdl.h>
-
+#include <aknphysics.h> // For Kinetic Scrolling
 #include <glxuiutility.h>
 #include <glxgeneraluiutilities.h>
 #include <glxuistd.h>
@@ -65,8 +65,9 @@
 const TInt KRightmargin = 20;
 const TInt KMinTagSize = 77;
 const TInt KTagScreenHeight = 460;
-const TInt KDragHoldTime = 500;
-
+const TReal KBoundaryMargin = 0.1; //10% = 10/100 = 0.1 
+const TInt KFastCloudMovement = 100; //Transition time to move cloud view
+const TInt KSlowCloudMovement = 1000; //Transition time to move cloud view
 
 // ---------------------------------------------------------------------------
 // Two-phased constructor.
@@ -142,7 +143,7 @@
     iParentLayout = CAlfLayout::AddNewL(*this, aAnchorLayout);                    
     iTagScreenWidth = rect.Width() - iScrollPaneHandle.iW - KRightmargin;
 
-    if (GlxGeneralUiUtilities::IsLandscape())
+    if(IsLandscape())
         {	
         iTagScreenHeight = rect.Height();	
         }
@@ -194,6 +195,8 @@
         }
     //get touch feedback instance
     iTouchFeedback = MTouchFeedback::Instance(); 
+    iPhysics = CAknPhysics::NewL(*this, NULL);
+    InitPhysicsL();
     }
 
 
@@ -206,10 +209,10 @@
     TRACER("GLX_CLOUD::CGlxCloudViewControl::VisualLayoutUpdated");
     TRect rect;
     AknLayoutUtils::LayoutMetricsRect (AknLayoutUtils::EMainPane, rect);
-    if ( (rect.Width() != iTagScreenWidth) && ( rect.Height () != iScreenHeight))
+    if ((rect.Width() != (iTagScreenWidth + iScrollPaneHandle.iW + KRightmargin)) || (rect.Height() != iScreenHeight))
         {
         //set the new screen dimensions
-        UpdateLayoutL();
+        TRAP_IGNORE(UpdateLayoutL());
         }
     }
 
@@ -237,6 +240,7 @@
         iUiUtility->Close ();
         }	
     delete iEmptyText;
+    delete iPhysics;
     }
 
 // --------------------------------------------------------------------------- 
@@ -408,7 +412,7 @@
     iViewPortLayout->SetSize(TAlfRealSize(iTagScreenWidth,iTagScreenHeight), 0);
     iViewPortSize.iWidth = iTagScreenWidth;
     iViewPortSize.iHeight = iTagScreenHeight;	
-    iViewPortLayout->SetViewportPos(TAlfRealPoint(0, 0),1000);
+    iViewPortLayout->SetViewportPos(TAlfRealPoint(0, 0), KSlowCloudMovement);
 
     iViewPortPosition.iX =0;
     iViewPortPosition.iY =0;
@@ -475,7 +479,7 @@
 
             case EKeyDownArrow:
                 {              
-                if(iCloudInfo.Count() >1 )
+                if (iCloudInfo.Count() > 1)
                     {
                     HandleKeyDownL ();
                     consumed = ETrue;
@@ -594,35 +598,6 @@
         //if its a pointer event
         consumed = HandlePointerEventL(aEvent);
         }
-    else if( aEvent.IsCustomEvent() )
-        {
-        if(aEvent.CustomParameter() == ECustomEventFocusDragScroll)
-            {
-            //dragging down
-            if( iIsDragging == 1 )
-                {
-                if(iFocusRowIndex!=iCloudInfo.Count()-1)
-                    {
-                    SetRelativeFocusL(iFocusRowIndex+1);
-                    iFocusRowIndex = RowNumber (iMediaList.FocusIndex ()); 
-                    // iScrollDirection = 0;               
-                    MoveDownIfRequired();  
-                    }
-                }
-            //dragging up
-            else if(iIsDragging == 2)
-                {
-                if(iFocusRowIndex!=0)
-                    {
-                    SetRelativeFocusL(iFocusRowIndex-1);
-                    iFocusRowIndex = RowNumber (iMediaList.FocusIndex ()); 
-                    // iScrollDirection = 0;               
-                    MoveUpIfRequired();  
-                    }
-                }
-            }
-        consumed = EFalse;
-        }
     return consumed;
     }
 
@@ -663,10 +638,9 @@
 
     // If the last item is focused and if we are navigating downwards,then set the
     // focus to first element.
-    if( iFocusRowIndex == iCloudInfo.Count()-1 )
-        {   
-        iMediaList.SetFocusL (NGlxListDefs::EAbsolute,
-                0); 
+    if (iFocusRowIndex == iCloudInfo.Count() - 1)
+        {
+        iMediaList.SetFocusL(NGlxListDefs::EAbsolute, 0);
         }
 
     //else set the focus to the item which is in the next row,that overlaps with midpoint of the 
@@ -818,6 +792,7 @@
         UpdateRowDataL (); //updates the row data and reassigns font sizes and draw the layout on screen.
         }
 
+    InitPhysicsL();
     }
 
 
@@ -859,6 +834,7 @@
             DisplayEmptyCloudViewL();
             }
         }
+    InitPhysicsL();
     }
 
 // ---------------------------------------------------------------------------
@@ -910,6 +886,8 @@
             }
         //generate row structures and draw rows on screen
         UpdateRowDataL ();
+
+        InitPhysicsL();
         }
     }
 
@@ -1336,7 +1314,7 @@
         {
         iViewPortPosition.iY = iViewPortVirtualSize.iHeight - iViewPortSize.iHeight;
         }
-    iViewPortLayout->SetViewportPos (iViewPortPosition,1000); 
+    iViewPortLayout->SetViewportPos(iViewPortPosition, KSlowCloudMovement);
     iScrollEventData.mViewStartPos = iViewPortPosition.iY;
     Scroll();  
     //CalculateBubleMidPoint ();   
@@ -1371,7 +1349,7 @@
         {
         iViewPortPosition.iY = 0;
         }     
-    iViewPortLayout->SetViewportPos (iViewPortPosition,1000); 
+    iViewPortLayout->SetViewportPos(iViewPortPosition, KSlowCloudMovement);
     iScrollEventData.mViewStartPos = iViewPortPosition.iY;
     if(iScrollBarWidget)
         {
@@ -1434,8 +1412,21 @@
     TRACER("GLX_CLOUD::CGlxCloudViewControl::HandlePointerEventL");
     CAlfVisual* tappedvisual = aEvent.Visual();	
     TBool consumed = EFalse;
+    
     if(aEvent.PointerEvent().iType == TPointerEvent::EButton1Down)
         {	
+        //reset variables & Physics simulator 
+        iPhysics->StopPhysics();
+        iPhysics->ResetFriction();
+        iDragging = EFalse;
+        iPhysicsStarted = EFalse;
+        iStartTime.HomeTime();
+        iViewDragged = EFalse;
+        Display()->Roster().SetPointerEventObservers(
+                EAlfPointerEventReportDrag + EAlfPointerEventReportLongTap
+                        + EAlfPointerEventReportUnhandled, *this);
+        Display()->Roster().DisableLongTapEventsWhenDragging(*this);
+
         if(tappedvisual)
             {
             for(TInt index=0;index<iLayout->Count();index++)
@@ -1445,19 +1436,53 @@
                 if(layoutvisual == tappedvisual)
                     {
                     TInt focus = iMediaList.FocusIndex();
-                    //if the visual is already focused then for next tap open the next view
-                    if( focus == index )
+                    if (index != focus)
                         {
-                        iTouchFeedback->InstantFeedback( ETouchFeedbackBasic );
-                        iObserverEnterKeyEvent.HandleEnterKeyEventL( (TInt)EAknCmdOpen );		    			
-                        consumed = ETrue;
+                        iTouchFeedback->InstantFeedback(ETouchFeedbackBasic);
+                        iMediaList.SetFocusL(NGlxListDefs::EAbsolute, index);
+                        SetFocusColor();
                         }
-                    else if( index!= focus )
+                    consumed = ETrue;
+                    break;
+                    }
+                }
+            }
+        }
+    else if (aEvent.PointerEvent().iType == TPointerEvent::EDrag)
+        {
+        GLX_LOG_INFO("GLX_CLOUD :: CGlxCloudViewControl::HandlePointerEventL(EDrag) event");
+        iTouchFeedback->InstantFeedback(ETouchFeedbackBasic);
+
+        consumed = HandleDragL(aEvent.PointerEvent());
+        }
+    else if (aEvent.PointerUp())
+        {
+        Display()->Roster().SetPointerEventObservers(0, *this);
+        consumed = ETrue;
+
+        //Check if dragging actually happened using iViewDragged 
+        if (iDragging && iViewDragged)
+            {
+            iDragging = EFalse;
+            TPoint drag = iStart - aEvent.PointerEvent().iPosition;
+            iPhysics->StartPhysics(drag, iStartTime);
+            iPhysicsStarted = ETrue;
+            }
+        //If dragging not happened consider it as Tapped event
+        else if (tappedvisual && !iViewDragged)
+            {
+            for (TInt index = 0; index < iLayout->Count(); index++)
+                {
+                CAlfVisual* layoutvisual = &(iLayout->Visual(index));
+                //if the tapped visual is same as the visual in the layout then focus that visual
+                if (layoutvisual == tappedvisual)
+                    {
+                    TInt focus = iMediaList.FocusIndex();
+                    if (index != focus)
                         {
                         iTouchFeedback->InstantFeedback( ETouchFeedbackBasic );
                         TInt focusrowindex = iFocusRowIndex;
-                        iMediaList.SetFocusL (NGlxListDefs::EAbsolute,
-                                index);
+                        iMediaList.SetFocusL(NGlxListDefs::EAbsolute, index);
                         SetFocusColor();
                         iFocusRowIndex = RowNumber (iMediaList.FocusIndex ());
                         if( iFocusRowIndex > focusrowindex)
@@ -1473,29 +1498,15 @@
                             MoveUpIfRequired();                 
                             }
                         }
+
+                    iTouchFeedback->InstantFeedback(ETouchFeedbackBasic);
+                    iObserverEnterKeyEvent.HandleEnterKeyEventL((TInt) EAknCmdOpen);
                     consumed = ETrue;
-                    Display()->Roster().SetPointerEventObservers( EAlfPointerEventReportDrag 
-                            + EAlfPointerEventReportLongTap 
-                            + EAlfPointerEventReportUnhandled, *this );
-                    Display()->Roster().DisableLongTapEventsWhenDragging(*this);
                     break;
                     }
                 }
             }
-        }			
-
-    else if (aEvent.PointerEvent().iType == TPointerEvent::EDrag)
-        {
-        GLX_LOG_INFO("GLX_CLOUD :: CGlxCloudViewControl::HandlePointerEventL(EDrag) event");
-        iTouchFeedback->InstantFeedback( ETouchFeedbackBasic );
-        consumed =  HandleDragL(aEvent.PointerEvent());
-        }
-    else if (aEvent.PointerUp())
-        {
-        
-        Env().CancelCustomCommands(this,ECustomEventFocusDragScroll);
-        Display()->Roster().SetPointerEventObservers(0, *this);
-        consumed =  ETrue;
+        iViewDragged = EFalse;
         }
     return consumed;
     }
@@ -1506,59 +1517,65 @@
 //
 TBool CGlxCloudViewControl::HandleDragL(const TPointerEvent& aPointerEvent)
     {
-    TRACER("GLX_CLOUD::CGlxCloudViewControl::HandleDragL");
-    TBool consumed = EFalse;
-    TInt itemindex = GetAbsoluteIndex(aPointerEvent.iPosition);
-    TInt focus = iMediaList.FocusIndex();
-    TInt focusrowindex = iFocusRowIndex;
+    TBool consumed(EFalse);
+    
+    // If Physics Emulation is going on, no need to entertain drag event
+    if (iPhysicsStarted)
+        return consumed;
 
-    //if index is not NULL then focus the tag and move the viewport down if necessary
-    if ( itemindex != KErrNotFound )
+    //Simply ignore the first drag event as there is huge difference between position 
+    //coordinates in drag event and corordinates in normal pointer down / up events  
+    if (!iDragging)
         {
-        if (focus != itemindex )
-            {
-            iTouchFeedback->InstantFeedback( ETouchFeedbackSensitive );
-            iMediaList.SetFocusL (NGlxListDefs::EAbsolute,itemindex);			
-            iFocusRowIndex = RowNumber (iMediaList.FocusIndex ());
-            GLX_LOG_INFO1("GLX_CLOUD :: CGlxCloudViewControl::HandleDragL,focusrowindex = %d",iFocusRowIndex);
-            if( iFocusRowIndex > focusrowindex)
-                {
-                GLX_LOG_INFO("GLX_CLOUD :: CGlxCloudViewControl::HandleDragL,b4 movedown");
-                iScrollDirection = 0;
-                MoveDownIfRequired(); 				
-                }
-            else if( iFocusRowIndex < focusrowindex )
-                {
-                GLX_LOG_INFO("GLX_CLOUD :: CGlxCloudViewControl::HandleDragL,b4 moveup");
-                iScrollDirection = 1;
-                MoveUpIfRequired();					
-                }			
-            }
-        consumed = ETrue;
+        //Note the current position for future reference
+        iStart = aPointerEvent.iPosition;
+        iPrev = iStart; 
+        iDragging = ETrue;
+        return consumed;
         }
 
-    TRect screenstartrect;
-    //the starting rect of the visible screen
-    screenstartrect.SetRect(0,0,iTagScreenWidth,2*KRowHeight);
+    TRect rect;
+    AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, rect);
+    TInt cntrlTopYLimit = rect.iTl.iY;
+    TInt cntrlBottomYLimit = rect.iBr.iY;
+    TInt delta = iPrev.iY - aPointerEvent.iPosition.iY;
 
-    TRect screenendrect;
-    //the end rect of the visible screen
-    screenendrect.SetRect(0,(iTagScreenHeight-(2*KRowHeight)),iTagScreenWidth,iTagScreenHeight);
+    //Check for physics threshold, before regidterting drag corordinates
+    TInt deltaAbs = delta < 0 ? -delta : delta;
+    TBool panning = deltaAbs >= iPhysics->DragThreshold();
+    if (panning)
+        {
+        TPoint deltaPt = iPrev - aPointerEvent.iPosition;
+        iPhysics->RegisterPanningPosition(deltaPt);
+        iPrev = aPointerEvent.iPosition;
+        iViewDragged = ETrue;
+        }
+    consumed = ETrue;
 
-    //dragging down
-    if(screenendrect.Contains(aPointerEvent.iPosition))
-        {            
-        iIsDragging = 1;            
-        Env().Send(TAlfCustomEventCommand(ECustomEventFocusDragScroll,
-                this),KDragHoldTime);
+    //Calculate margin after which we might get pointer out of screen, and we might not 
+    //get further pointer events. Also This is currently only 10% of total delta we can find, 
+    //to get margin corresponding to movement of user flicking speed
+    //This implies higher speed - higher margin
+    //Lower speed - 0 margin
+    TInt deltaMargin = deltaAbs * KBoundaryMargin;
+
+    //Code to predict future movement if same delta movement we might get in future
+    //For flick event down - If the movement goes below screen, start physics
+    //or For flick event up - If the movement goes above screen, start physics 
+    if (((delta < 0) && (aPointerEvent.iPosition.iY - delta >= cntrlBottomYLimit - deltaMargin))
+            || ((delta > 0) && (aPointerEvent.iPosition.iY - delta <= cntrlTopYLimit + deltaMargin)))
+        {
+        iPhysicsStarted = ETrue;
         }
-    //dragging up
-    else if  (screenstartrect.Contains(aPointerEvent.iPosition))
+
+    //If found that possibly in next move it might go out of bounds, start physics
+    //emulation
+    if (iPhysicsStarted && iDragging)
         {
-        iIsDragging = 2;             
-        Env().Send(TAlfCustomEventCommand(ECustomEventFocusDragScroll,
-                this),KDragHoldTime);
-        }        
+        TPoint drag = iStart - aPointerEvent.iPosition;
+        iPhysics->StartPhysics(drag, iStartTime);
+        iDragging = EFalse;
+        }
 
     return consumed;
     }
@@ -1684,6 +1701,8 @@
                         TInt steps = TInt(aEvent.CustomEventData());
                         UpdateScrollBar(steps,EFalse);                        
                         Scroll();                       
+                        iPhysics->StopPhysics();
+
                         status = EEventHandled; 
                         }
                         break;                   
@@ -1692,7 +1711,8 @@
                         GLX_LOG_INFO("GLX_CLOUD :: CGlxCloudViewControl::offerEvent(EEventScrollPageUp) event");                       
                         UpdateScrollBar(-iScrollEventData.mViewLength); 
                         Scroll();                        
-                        status = EEventHandled;    		    	    
+                        iPhysics->StopPhysics();
+                        status = EEventHandled;
                         }
                         break;
                     case EEventScrollPageDown:
@@ -1700,6 +1720,7 @@
                         GLX_LOG_INFO("GLX_CLOUD :: CGlxCloudViewControl::offerEvent(EEventScrollPageDown) event");                       
                         UpdateScrollBar(iScrollEventData.mViewLength); 
                         Scroll();
+                        iPhysics->StopPhysics();
                         status = EEventHandled; 		    	    
                         }
                         break;                    
@@ -1755,7 +1776,7 @@
     iScrollbarElement->offerEvent(*(iScrollBarWidget->control()),customevent);
     GLX_LOG_INFO1("GLX_CLOUD ::CGlxCloudViewControl::Scroll(),position %d ",iScrollEventData.mViewStartPos);
     iViewPortPosition.iY = iScrollEventData.mViewStartPos;
-    iViewPortLayout->SetViewportPos (iViewPortPosition,1000);  
+    iViewPortLayout->SetViewportPos(iViewPortPosition, KSlowCloudMovement);
     }
 
 // ---------------------------------------------------------------------------
@@ -1820,12 +1841,12 @@
     {
     TRect rect;
     AknLayoutUtils::LayoutMetricsRect (AknLayoutUtils::EMainPane, rect);
-    if ( (rect.Width() != iTagScreenWidth) && ( rect.Height () != iScreenHeight))
+    if ((rect.Width() != (iTagScreenWidth + iScrollPaneHandle.iW + KRightmargin)) || (rect.Height() != iScreenHeight))
         {
         //set the new screen dimensions
         iScreenHeight=rect.Height();
        iTagScreenWidth = rect.Width()- iScrollPaneHandle.iW - KRightmargin;
-        if (GlxGeneralUiUtilities::IsLandscape())
+        if(IsLandscape())
             {   
             iTagScreenHeight = rect.Height();   
             }
@@ -1842,8 +1863,79 @@
             FetchAttributeFromCacheL();
             //generate row structures and draw rows on screen
             UpdateRowDataL ();                                    
+
+            InitPhysicsL();
             }
         }
     }
+
+// ---------------------------------------------------------------------------
+// InitPhysicsL() 
+// ---------------------------------------------------------------------------
+//
+void CGlxCloudViewControl::InitPhysicsL()
+    {
+    //Update physics with new total layout, viewable size and our landscape mode 
+    iPhysics->InitPhysicsL(TSize(iViewPortVirtualSize.iWidth,
+            iViewPortVirtualSize.iHeight), TSize(iTagScreenWidth,
+            iTagScreenHeight), EFalse);
+
+    //Note: Physics viewposition must always be mid of viewable screen size to get best result
+    //I learned the hard way
+    iViewPosition.SetXY(iTagScreenWidth / 2, iTagScreenHeight / 2);
+    }
+
+// ---------------------------------------------------------------------------
+// ViewPositionChanged() 
+// ---------------------------------------------------------------------------
+//
+void CGlxCloudViewControl::ViewPositionChanged(const TPoint& aNewPosition,
+        TBool aDrawNow, TUint /*aFlags*/)
+    {
+    iViewPosition = aNewPosition;
+    iViewPortPosition.iY = iViewPosition.iY - iTagScreenHeight / 2;
+    if (aDrawNow)
+        {
+        iViewPortLayout->SetViewportPos(iViewPortPosition, KFastCloudMovement);
         
+        iScrollEventData.mViewStartPos = iViewPortPosition.iY;
+        Scroll();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// PhysicEmulationEnded() 
+// ---------------------------------------------------------------------------
+//
+void CGlxCloudViewControl::PhysicEmulationEnded()
+    {
+    iPhysicsStarted = EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// ViewPosition() 
+// ---------------------------------------------------------------------------
+//
+TPoint CGlxCloudViewControl::ViewPosition() const
+    {
+    return iViewPosition;
+    }
+
+// ---------------------------------------------------------------------------
+// IsLandscape() 
+// ---------------------------------------------------------------------------
+//
+TBool CGlxCloudViewControl::IsLandscape()
+    {
+    TRect rect;
+    AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, rect);
+    if(rect.Width() > rect.Height())
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
 //End of file