uifw/AvKon/aknhlist/src/akntreelistphysicshandler.cpp
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
child 14 3320e4e6e8bb
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  AknTreeListView physics handler
       
    15 *
       
    16 */
       
    17 
       
    18 #include <aknphysics.h>
       
    19 #include <aknphysicsobserveriface.h>
       
    20 #include <babitflags.h>
       
    21 #include <eiksbobs.h>
       
    22 #include <eikon.hrh> // EKeyOK
       
    23 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
    24 #include <aknlistloadertfx.h>
       
    25 #include <aknlistboxtfx.h>
       
    26 #endif // RD_UI_TRANSITION_EFFECTS_LIST
       
    27 
       
    28 #include <touchfeedback.h>
       
    29 
       
    30 #include "akntree.h"
       
    31 #include "akntreelistview.h"
       
    32 #include "akntreelistphysicshandler.h"
       
    33 #include "akntreelist.h"
       
    34 #include "akntrace.h" // trace
       
    35 
       
    36 // Tree list view physics handler flag definitions.
       
    37 enum TAknTreeListPhysicsHandlerFlags
       
    38     {
       
    39     // pressed-down highlight should be drawn to focused item
       
    40     EFlagPDHighlightToFocusedItem,
       
    41     // pressed-down highlight should be drawn to nonfocused item
       
    42     EFlagPDHighlightToNonFocusedItem,
       
    43     EFlagButtonUpReceived,
       
    44     EFlagUpdatingView
       
    45     };
       
    46 
       
    47 
       
    48 
       
    49 // ======== MEMBER FUNCTIONS ========
       
    50 
       
    51 // ---------------------------------------------------------------------------
       
    52 // CAknTreeListPhysicsHandler::NewL
       
    53 // ---------------------------------------------------------------------------
       
    54 //
       
    55 CAknTreeListPhysicsHandler* CAknTreeListPhysicsHandler::NewL(
       
    56     CAknTreeListView* aTreeListView,
       
    57     CAknTree* aTree,
       
    58     RArray<TAknTreeListViewItem>* aItems )
       
    59     {
       
    60     CAknTreeListPhysicsHandler* self = 
       
    61         CAknTreeListPhysicsHandler::NewLC( aTreeListView, aTree, aItems );
       
    62     CleanupStack::Pop( self );
       
    63     return self;
       
    64     }
       
    65 
       
    66 
       
    67 // ---------------------------------------------------------------------------
       
    68 // CAknTreeListPhysicsHandler::NewLC
       
    69 // ---------------------------------------------------------------------------
       
    70 //
       
    71 CAknTreeListPhysicsHandler* CAknTreeListPhysicsHandler::NewLC( 
       
    72     CAknTreeListView* aTreeListView,
       
    73     CAknTree* aTree,
       
    74     RArray<TAknTreeListViewItem>* aItems )
       
    75     {
       
    76     CAknTreeListPhysicsHandler* self 
       
    77         = new ( ELeave ) CAknTreeListPhysicsHandler( 
       
    78             aTreeListView, aTree, aItems );
       
    79     CleanupStack::PushL( self );
       
    80     self->ConstructL();
       
    81     return self;
       
    82     }
       
    83 
       
    84 
       
    85 // ---------------------------------------------------------------------------
       
    86 // CAknTreeListPhysicsHandler::~CAknTreeListPhysicsHandler
       
    87 // ---------------------------------------------------------------------------
       
    88 //
       
    89 CAknTreeListPhysicsHandler::~CAknTreeListPhysicsHandler()
       
    90     {
       
    91     delete iHighlightTimer;
       
    92     delete iPhysics;
       
    93     }
       
    94 
       
    95 
       
    96 // ---------------------------------------------------------------------------
       
    97 // CAknTreeListPhysicsHandler::HandlePointerEventL
       
    98 // ---------------------------------------------------------------------------
       
    99 //
       
   100 void CAknTreeListPhysicsHandler::HandlePointerEventL(
       
   101     const TPointerEvent& aPointerEvent, const TInt& aViewLevel,
       
   102     TBool aMarking, TBool aShiftPressed, TBool aCtrlPressed )
       
   103     {
       
   104     _AKNTRACE_FUNC_ENTER;
       
   105     if ( aPointerEvent.iType == TPointerEvent::EButton1Down && iEnableEvents )
       
   106         {
       
   107         iEventsBlocked = EFalse;
       
   108         iEnableEvents = EFalse;
       
   109         }
       
   110     if ( iEventsBlocked )
       
   111         {
       
   112         _AKNTRACE("CAknTreeListPhysicsHandler::%s Return due to event blocked", __FUNCTION__);
       
   113         _AKNTRACE_FUNC_EXIT;
       
   114 	    return;
       
   115         }
       
   116     
       
   117     // Panning/flicking logic    
       
   118 
       
   119     // EButton1Down
       
   120 
       
   121     TBool wasFlicking( EFalse );
       
   122     TBool wasScrolling = ( iPhysics->OngoingPhysicsAction() != 
       
   123         CAknPhysics::EAknPhysicsActionNone );
       
   124 
       
   125     if ( aPointerEvent.iType == TPointerEvent::EButton1Down &&
       
   126         iViewRect.Contains( aPointerEvent.iPosition ) )
       
   127         {
       
   128         iPenDown = ETrue;
       
   129         if ( iPhysics->OngoingPhysicsAction() == CAknPhysics::EAknPhysicsActionFlicking )
       
   130             {
       
   131             // flicking was ongoing when content stopped
       
   132             if ( iFeedback )
       
   133                 {
       
   134                 iFeedback->InstantFeedback( ETouchFeedbackBasic );
       
   135                 }
       
   136             wasFlicking = ETrue;
       
   137             }
       
   138         
       
   139         iFlags.Clear( EFlagButtonUpReceived );
       
   140         iPosition = aPointerEvent.iPosition;
       
   141         iStartPosition = aPointerEvent.iPosition;
       
   142 
       
   143         iPhysics->StopPhysics();
       
   144         iPhysics->ResetFriction();
       
   145     
       
   146         iStartTime.HomeTime();
       
   147         iHighlightTimer->Cancel();
       
   148         
       
   149         iItemToBeFocused = NULL;
       
   150         iIndexToBeFocused = -1;
       
   151         iItemToBeSelected = NULL;
       
   152         
       
   153         iPanningActivated = EFalse;
       
   154 
       
   155         iPlayFeedbackOnUp = EFalse;
       
   156 
       
   157         // Check if marquee needs to be disabled
       
   158         if ( iTreeListView->SingleClickEnabled()
       
   159                 && iTree->IsMarqueeOn() )
       
   160             {
       
   161             iTree->EnableMarquee( EFalse );
       
   162             }
       
   163            
       
   164         iEmptyAreaClicked = EmptyAreaClicked( aPointerEvent.iPosition ); 
       
   165         }
       
   166     
       
   167     // EDrag    
       
   168    
       
   169     if ( aPointerEvent.iType == TPointerEvent::EDrag )
       
   170         {
       
   171         TInt distanceFromStart( iStartPosition.iY - aPointerEvent.iPosition.iY );
       
   172         
       
   173         if ( !iPanningActivated && Abs( distanceFromStart ) > DragThreshold() )
       
   174             {
       
   175 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
   176             MAknListBoxTfx* tfxApi = CAknListLoader::TfxApi( iTfxGc );
       
   177 
       
   178             if ( tfxApi )
       
   179                 {
       
   180                 tfxApi->EnableEffects( EFalse );
       
   181                 }
       
   182 #endif // RD_UI_TRANSITION_EFFECTS_LIST
       
   183 
       
   184             iPanningActivated = ETrue;
       
   185             iEmptyAreaClicked = EFalse;        
       
   186             
       
   187             iHighlightTimer->Cancel();
       
   188             iItemToBeFocused = NULL;
       
   189             iItemToBeSelected = NULL;
       
   190             iIndexToBeFocused = -1;
       
   191             iTreeListView->SetPressedDownState( EFalse );
       
   192             iPosition = aPointerEvent.iPosition;
       
   193 
       
   194             _AKNTRACE(
       
   195                 "CAknTreeListPhysicsHandler::[%s] Report EEventPanningStarted",
       
   196                 __FUNCTION__);
       
   197 
       
   198 			if ( iTreeListView->SingleClickEnabled() )
       
   199                 {
       
   200                 iTreeListView->EnableHighlight( EFalse );
       
   201                 iTreeListView->CancelLongTapDetectorL();
       
   202                 }
       
   203 
       
   204             iTreeListView->ReportTreeListEvent( 
       
   205                 MAknTreeListObserver::EEventPanningStarted,
       
   206                 KAknTreeIIDNone );
       
   207             }
       
   208 
       
   209         if ( iPanningActivated )
       
   210             {
       
   211             TInt deltaY( iPosition.iY - aPointerEvent.iPosition.iY );
       
   212             iPosition = aPointerEvent.iPosition;
       
   213 
       
   214             TPoint deltaPoint( 0, deltaY );
       
   215             _AKNTRACE(
       
   216                 "CAknTreeListPhysicsHandler::[%s] Panning deltaPoint.iY = %d",
       
   217                 __FUNCTION__, deltaY );
       
   218             iPhysics->RegisterPanningPosition( deltaPoint );
       
   219             }
       
   220         else if ( iTreeListView->SingleClickEnabled() )
       
   221             {
       
   222             iTreeListView->LongTapPointerEventL( aPointerEvent );
       
   223             }        
       
   224         }
       
   225 
       
   226     // EButton1Up   
       
   227    
       
   228     if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
       
   229         {
       
   230         iTreeListView->SetPressedDownState( EFalse );
       
   231         if ( iTreeListView->SingleClickEnabled() && !aMarking )
       
   232             {
       
   233             iHighlightTimer->Cancel();
       
   234             iTreeListView->EnableHighlight( EFalse );
       
   235             iTreeListView->LongTapPointerEventL( aPointerEvent );
       
   236             }
       
   237         iFlags.Set( EFlagButtonUpReceived );
       
   238         iTreeListView->DrawDeferred();
       
   239 
       
   240         TInt distance = iStartPosition.iY - aPointerEvent.iPosition.iY;
       
   241         TPoint drag( 0, distance );
       
   242 
       
   243         if ( iPhysics->StartPhysics( drag, iStartTime ) )
       
   244             {
       
   245             if ( iPanningActivated )
       
   246                 {
       
   247                 _AKNTRACE(
       
   248                     "CAknTreeListPhysicsHandler::[%s] Report EEventPanningStopped",
       
   249                     __FUNCTION__);
       
   250                 iTreeListView->ReportTreeListEvent( 
       
   251                     MAknTreeListObserver::EEventPanningStopped,
       
   252                     KAknTreeIIDNone );
       
   253                 }
       
   254 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
   255             // Transitions are already suspended if listbox was panned.
       
   256             if ( !iPanningActivated )
       
   257                 {
       
   258                 MAknListBoxTfx* tfxApi = CAknListLoader::TfxApi( iTfxGc );
       
   259 
       
   260                 if ( tfxApi )
       
   261                     {
       
   262                     tfxApi->EnableEffects( EFalse );
       
   263                     }
       
   264                 }
       
   265 #endif // RD_UI_TRANSITION_EFFECTS_LIST
       
   266             
       
   267             if ( iPhysics->OngoingPhysicsAction() == CAknPhysics::EAknPhysicsActionFlicking )
       
   268                 {
       
   269                 iItemToBeFocused = NULL;
       
   270                 iItemToBeSelected = NULL;
       
   271                 iIndexToBeFocused = -1;
       
   272                 iHighlightTimer->Cancel();
       
   273                 }
       
   274                   
       
   275             if ( iItemToBeSelected != NULL )
       
   276                 {
       
   277                 iTreeListView->SelectItem( iItemToBeSelected );
       
   278                 iItemToBeSelected = NULL;
       
   279                 }     
       
   280             _AKNTRACE(
       
   281                 "CAknTreeListPhysicsHandler::[%s] Report EEventFlickStarted",
       
   282                 __FUNCTION__);
       
   283             iTreeListView->ReportTreeListEvent( 
       
   284                 MAknTreeListObserver::EEventFlickStarted,
       
   285                 KAknTreeIIDNone );
       
   286             _AKNTRACE_FUNC_EXIT;
       
   287             return;
       
   288             }
       
   289 
       
   290         if ( iPlayFeedbackOnUp )
       
   291             {
       
   292             // touch down has occured on an item, which requires feedback
       
   293             // also on up event -> play basic list feedback
       
   294             if ( iFeedback )
       
   295                  {
       
   296                  TTouchLogicalFeedback fbType = ETouchFeedbackList;
       
   297                  if ( iItemToBeSelected != NULL )
       
   298                      {
       
   299                      if ( iItemToBeSelected->IsLeaf() && iItemToBeSelected->IsMarkable() )
       
   300                          {
       
   301                          fbType = ETouchFeedbackCheckbox;
       
   302                          }
       
   303                      else if ( iItemToBeSelected->Node() != NULL )
       
   304                          {
       
   305                          if ( iItemToBeSelected->Node()->ChildCount() == 0 && 
       
   306                                  iItemToBeSelected->Node()->IsMarkable() )
       
   307                              {
       
   308                              fbType = ETouchFeedbackCheckbox;
       
   309                              }
       
   310                          }
       
   311                      iFeedback->InstantFeedback( iTreeListView, 
       
   312                                                  fbType,
       
   313                                                  ETouchFeedbackVibra,
       
   314                                                  aPointerEvent );
       
   315                      }
       
   316                  
       
   317                  }
       
   318             }
       
   319 
       
   320         if ( iItemToBeSelected != NULL && !aMarking)
       
   321             {
       
   322             iTreeListView->SelectItem( iItemToBeSelected );
       
   323             iItemToBeSelected = NULL;
       
   324             }
       
   325 
       
   326         if ( iItemToBeSelected == NULL && iEmptyAreaClicked )
       
   327             {
       
   328             if ( iTree->VisibleItemCount() > 0 )
       
   329                 {
       
   330                 iTreeListView->ReportTreeListEvent( 
       
   331                             MAknTreeListObserver::EEmptyAreaClicked,
       
   332                             KAknTreeIIDNone );
       
   333                 }
       
   334             else
       
   335                 {
       
   336                 iTreeListView->ReportTreeListEvent( 
       
   337                             MAknTreeListObserver::EEmptyListClicked,
       
   338                             KAknTreeIIDNone );                
       
   339                 }
       
   340             }       
       
   341         }
       
   342     
       
   343     // Item handling logic    
       
   344 
       
   345     TPoint adjustedPosition( aPointerEvent.iPosition );
       
   346     adjustedPosition.iY += Offset();
       
   347 
       
   348     for ( TInt ii = 0; ii < iItems->Count(); ++ii )
       
   349         {
       
   350         CAknTreeItem* item = (*iItems)[ii].Item();
       
   351     
       
   352         if ( item && (*iItems)[ii].Rect().Contains( adjustedPosition ) )
       
   353             {        
       
   354             if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
       
   355                 {            
       
   356                 // Marking mode 
       
   357                 if ( aMarking )
       
   358                     {
       
   359                     TBool drawNow = ( item == iTreeListView->FocusedItem() );    
       
   360                     if ( aShiftPressed )
       
   361                         {
       
   362                         iTreeListView->MarkItems( iTreeListView->FocusedItem(), item,
       
   363                             !item->IsMarked(), drawNow );
       
   364                         }
       
   365                     else if ( aCtrlPressed )
       
   366                         {
       
   367                         iTreeListView->MarkItem( item, !item->IsMarked(), drawNow );
       
   368                         }
       
   369                     }  
       
   370                 else if ( iTreeListView->SingleClickEnabled() 
       
   371                           && !wasFlicking  )                    
       
   372                     {
       
   373                     iItemToBeSelected = item;             
       
   374                     iTreeListView->SetFocusedItem( item, ii, EFalse );
       
   375                     // Start long tap detector 
       
   376                     if ( !iTreeListView->HasMarkedItemsL() )
       
   377                         {
       
   378                         iTreeListView->LongTapPointerEventL( aPointerEvent );
       
   379                         }
       
   380                     }
       
   381                 if ( ii != iTreeListView->FocusedItemIndex() )
       
   382                     {
       
   383                     iItemToBeFocused = item;
       
   384                     iIndexToBeFocused = ii;
       
   385                     // node will be collapsed/expanded only if flicking was not ongoing
       
   386                     if ( item->Node() && !wasFlicking )
       
   387                         {
       
   388                         iItemToBeSelected = item;
       
   389                         // Pressed down highlight to nonfocused item
       
   390                         iFlags.Set( EFlagPDHighlightToNonFocusedItem );                            
       
   391                         }
       
   392                     // touch down on non-focused item, while not flicking
       
   393                     if ( iFeedback && !wasFlicking )
       
   394                         {
       
   395                         if ( item->Node() )
       
   396                             {
       
   397                             // item is a non-focused node, play basic list
       
   398                             // feedback
       
   399                             iFeedback->InstantFeedback( iTreeListView, 
       
   400                                                         ETouchFeedbackList );
       
   401                             
       
   402                             // next up event causes for the node to collapse,
       
   403                             // play feedback on up event
       
   404                             iPlayFeedbackOnUp = ETrue;
       
   405                             }
       
   406                         else
       
   407                             {
       
   408                             // item is a non-focused leaf, play sensitive 
       
   409                             // feedback
       
   410                             iFeedback->InstantFeedback( iTreeListView, 
       
   411                                                         ETouchFeedbackSensitiveList );
       
   412                             }
       
   413                         }
       
   414                     }
       
   415                  // item will be selected only if flicking was not ongoing   
       
   416                  else if ( !wasFlicking )
       
   417                     {
       
   418                     iItemToBeSelected = item;
       
   419                     // Pressed down highlight to focused item
       
   420                     iFlags.Set( EFlagPDHighlightToFocusedItem );
       
   421                     // touch down on focused item, while not flicking
       
   422                     if ( iFeedback )
       
   423                         {
       
   424                         iFeedback->InstantFeedback( iTreeListView,
       
   425                                                     ETouchFeedbackList );
       
   426                         
       
   427                         // next up event cause an action on the screen,
       
   428                         // play feedback on up event
       
   429                         iPlayFeedbackOnUp = ETrue;
       
   430                         }
       
   431                     }
       
   432                 if ( !aMarking )
       
   433                     {
       
   434                     // timer will be launched everytime, but not
       
   435                     // if flicking was ongoing AND it was stopped by tapping 
       
   436                     // to highlighted item or to folder (=node)   
       
   437                     if ( !( wasFlicking && iItemToBeSelected != NULL ) )
       
   438                         {
       
   439                         LaunchHighlightTimer( wasScrolling );
       
   440                         }
       
   441                     }
       
   442                 else
       
   443                     {
       
   444                     // Pressed down highlight or highlight timer 
       
   445                     // are not used in marking mode.
       
   446                     SetHighlight();   
       
   447                     }
       
   448                 }
       
   449             (*iItems)[ii].HandlePointerEventL( aPointerEvent, aViewLevel,
       
   450                 iTreeListView->Indention(), iTreeListView->IndentionWidth() );
       
   451             }
       
   452         }
       
   453     _AKNTRACE_FUNC_EXIT;
       
   454     }
       
   455 
       
   456 // ---------------------------------------------------------------------------
       
   457 // CAknTreeListPhysicsHandler::HandleScrollEventL
       
   458 // ---------------------------------------------------------------------------
       
   459 //
       
   460 void CAknTreeListPhysicsHandler::HandleScrollEventL( 
       
   461     TEikScrollEvent aEventType, const TInt& aThumbPosition )
       
   462     {
       
   463     switch ( aEventType )
       
   464         {
       
   465         case EEikScrollUp:
       
   466         case EEikScrollDown:
       
   467         case EEikScrollPageUp:
       
   468         case EEikScrollPageDown:
       
   469         case EEikScrollThumbDragVert:
       
   470             {
       
   471             iScrollIndex = aThumbPosition;
       
   472             ScrollView( ETrue );
       
   473             }
       
   474         // fall through
       
   475         default:
       
   476             {
       
   477             StopPhysics();
       
   478             }
       
   479         }
       
   480     }
       
   481 
       
   482 // -----------------------------------------------------------------------------
       
   483 // CAknTreeListPhysicsHandler::HandleKeyEvent
       
   484 // -----------------------------------------------------------------------------
       
   485 //
       
   486 void CAknTreeListPhysicsHandler::HandleKeyEvent( TInt aKeyCode )
       
   487     {
       
   488    
       
   489     if ( aKeyCode != EKeyLeftArrow && aKeyCode != EKeyRightArrow &&
       
   490          aKeyCode != EKeyUpArrow && aKeyCode != EKeyDownArrow && 
       
   491          aKeyCode != EKeyEnter && aKeyCode != EKeyOK )
       
   492         {
       
   493         return;
       
   494         }  
       
   495         
       
   496     TInt lastItem = LastVisibleItemIndex();  
       
   497     TInt firstItem = FirstVisibleItemIndex();
       
   498     TInt focusedItem = iTreeListView->FocusedItemIndex();   
       
   499     
       
   500     // Offset used in drawing
       
   501     TInt panningOffset = Offset();
       
   502     // When physics is activated view contains partial items 
       
   503     TInt viewOffset(
       
   504         iItemHeight * ( lastItem - firstItem + 1 ) - iViewRect.Height() + iListTopOffset );
       
   505         
       
   506     // Handle list top item  
       
   507     if ( panningOffset != 0 && ( firstItem == focusedItem || 
       
   508          firstItem == focusedItem + 1 ) )
       
   509         {
       
   510         iScrollIndex -= panningOffset;
       
   511         ScrollView( EFalse );
       
   512         }   
       
   513     // Handle list bottom item   
       
   514     else if ( panningOffset != viewOffset && ( lastItem == focusedItem || 
       
   515          lastItem == focusedItem - 1 ) )
       
   516         {
       
   517         iScrollIndex -= panningOffset - viewOffset;   
       
   518         ScrollView( EFalse );
       
   519         }                                     
       
   520     }
       
   521    
       
   522 // ---------------------------------------------------------------------------
       
   523 // CAknTreeListPhysicsHandler::SetViewRect
       
   524 // ---------------------------------------------------------------------------
       
   525 //
       
   526 void CAknTreeListPhysicsHandler::SetViewRect( const TRect& aRect )
       
   527     {
       
   528     iViewRect = aRect;
       
   529 
       
   530     // Calculate list top offset
       
   531    	TRect firstItemRect( ( *iItems )[ 0 ].Rect() );
       
   532 	if ( iViewRect.iTl.iY < firstItemRect.iTl.iY )
       
   533 	    {
       
   534 	    iListTopOffset = firstItemRect.iTl.iY - iViewRect.iTl.iY;
       
   535 	    }
       
   536     }
       
   537     
       
   538     
       
   539 // ---------------------------------------------------------------------------
       
   540 // CAknTreeListPhysicsHandler::ViewRect
       
   541 // ---------------------------------------------------------------------------
       
   542 //
       
   543 TRect CAknTreeListPhysicsHandler::ViewRect() const
       
   544     {
       
   545     return iViewRect;
       
   546     }
       
   547 
       
   548 
       
   549 // ---------------------------------------------------------------------------
       
   550 // CAknTreeListPhysicsHandler::SetItemHeight
       
   551 // ---------------------------------------------------------------------------
       
   552 //
       
   553 void CAknTreeListPhysicsHandler::SetItemHeight( const TInt& aHeight )
       
   554     {
       
   555     if( iScrollIndex > 0 && iItemHeight > 0 && aHeight != iItemHeight )
       
   556         {
       
   557         iScrollIndex = ( iScrollIndex / iItemHeight ) * aHeight;
       
   558         }
       
   559     iItemHeight = aHeight;
       
   560     }
       
   561 
       
   562 
       
   563 // ---------------------------------------------------------------------------
       
   564 // Offset
       
   565 // ---------------------------------------------------------------------------
       
   566 //
       
   567 TInt CAknTreeListPhysicsHandler::Offset() const 
       
   568 	{
       
   569 	if ( iItemHeight == 0)
       
   570 	    {
       
   571 	    return 0;
       
   572 	    }
       
   573 	    
       
   574 	TInt currentLine = iScrollIndex / iItemHeight;
       
   575 	    
       
   576 	if ( currentLine < 0)
       
   577         {
       
   578         return iScrollIndex % iItemHeight + iItemHeight * currentLine;
       
   579         }
       
   580     else if ( currentLine >= iTree->VisibleItemCount() )
       
   581         {
       
   582         return iScrollIndex - ( iItemHeight * ( iTree->VisibleItemCount() - 1 ) );
       
   583         }
       
   584     return iScrollIndex % iItemHeight;
       
   585 	}
       
   586 
       
   587 
       
   588 // ---------------------------------------------------------------------------
       
   589 // InitPhysicsL
       
   590 // ---------------------------------------------------------------------------
       
   591 //   
       
   592 void CAknTreeListPhysicsHandler::InitPhysicsL()
       
   593     {
       
   594 	TSize totalSize( iViewRect.Width(), WorldHeight() );
       
   595 	TSize viewSize( iViewRect.Width(), iViewRect.Height() );
       
   596 	
       
   597 	iPhysics->InitPhysicsL( totalSize, viewSize, EFalse );
       
   598 	
       
   599 	if ( iScrollIndex < 0 )
       
   600 	    {
       
   601 	    iScrollIndex = 0;
       
   602 	    ScrollView( EFalse );
       
   603 	    }
       
   604     }
       
   605 
       
   606 
       
   607 // ---------------------------------------------------------------------------
       
   608 // CAknTreeListPhysicsHandler::ResetEventBlockingStatus
       
   609 // ---------------------------------------------------------------------------
       
   610 //
       
   611 void CAknTreeListPhysicsHandler::ResetEventBlockingStatus()
       
   612     {
       
   613     iEventsBlocked = EFalse;
       
   614     iEnableEvents = EFalse;
       
   615     }
       
   616 
       
   617 
       
   618 // ---------------------------------------------------------------------------
       
   619 // GetVScrollbarParams
       
   620 // ---------------------------------------------------------------------------
       
   621 //     
       
   622 void CAknTreeListPhysicsHandler::GetVScrollbarParams( TInt& aThumbSpan, 
       
   623                                                       TInt& aThumbPos, 
       
   624                                                       TInt& aScrollSpan )
       
   625     {
       
   626     aThumbSpan = iViewRect.Height() - iViewRect.Height() % 2;	
       
   627     aThumbPos = iScrollIndex;
       
   628 
       
   629     TInt span1( aThumbPos + aThumbSpan );
       
   630     TInt totalHeight( iTree->VisibleItemCount() * iItemHeight );
       
   631     TInt span2( totalHeight - aThumbSpan );
       
   632    
       
   633     aScrollSpan = Max( Min( span1, span2 ), totalHeight );
       
   634     }
       
   635 
       
   636 
       
   637 // ---------------------------------------------------------------------------
       
   638 // FocusedItemVisible
       
   639 // ---------------------------------------------------------------------------
       
   640 //     
       
   641 TBool CAknTreeListPhysicsHandler::FocusedItemVisible(
       
   642     const TInt& aFocusedIndex ) const
       
   643     {
       
   644     TBool visible( EFalse );
       
   645     if ( aFocusedIndex > -1 && aFocusedIndex < iItems->Count() )
       
   646         {
       
   647         visible = ETrue;
       
   648         TInt topY( ( *iItems )[ aFocusedIndex ].Rect().iTl.iY - Offset() );
       
   649         TInt bottomY( ( *iItems )[ aFocusedIndex ].Rect().iBr.iY - Offset() );
       
   650         if ( bottomY < iViewRect.iTl.iY || topY > iViewRect.iBr.iY )
       
   651             {
       
   652             visible = EFalse;
       
   653             }
       
   654         }
       
   655     return visible;
       
   656     }
       
   657 
       
   658 
       
   659 // ---------------------------------------------------------------------------
       
   660 // FirstVisibleItemIndex
       
   661 // ---------------------------------------------------------------------------
       
   662 //     
       
   663 TInt CAknTreeListPhysicsHandler::FirstVisibleItemIndex() const
       
   664     {
       
   665     TInt firstItemIndex( -1 );
       
   666     if ( iItems->Count() )
       
   667         {
       
   668         firstItemIndex = 0;
       
   669         TBool firstItemFound( EFalse );
       
   670         while ( firstItemIndex < iItems->Count() && !firstItemFound )
       
   671             {
       
   672             TInt bottomY( 
       
   673                 ( *iItems )[ firstItemIndex ].Rect().iBr.iY - Offset() );
       
   674             if ( bottomY < iViewRect.iTl.iY )
       
   675                 {
       
   676                 firstItemIndex++;
       
   677                 }
       
   678             else
       
   679                 {
       
   680                 firstItemFound = ETrue;
       
   681                 break;
       
   682                 }
       
   683             }
       
   684         if ( !firstItemFound )
       
   685             {
       
   686             firstItemIndex = 0;
       
   687             }
       
   688         }
       
   689     return firstItemIndex;
       
   690     }
       
   691 
       
   692 
       
   693 // ---------------------------------------------------------------------------
       
   694 // LastVisibleItemIndex
       
   695 // ---------------------------------------------------------------------------
       
   696 //     
       
   697 TInt CAknTreeListPhysicsHandler::LastVisibleItemIndex() const
       
   698     {
       
   699     TInt lastItemIndex( -1 );
       
   700     if ( iItems->Count() )
       
   701         {
       
   702         lastItemIndex = iItems->Count() - 1;
       
   703         TBool lastItemFound( EFalse );
       
   704         while ( lastItemIndex > -1 && !lastItemFound )
       
   705             {
       
   706             TInt topY( ( *iItems )[ lastItemIndex ].Rect().iTl.iY - Offset() );
       
   707             if ( topY > iViewRect.iBr.iY )
       
   708                 {
       
   709                 lastItemIndex--;
       
   710                 }
       
   711             else
       
   712                 {
       
   713                 lastItemFound = ETrue;
       
   714                 break;
       
   715                 }
       
   716             }
       
   717         }
       
   718     return lastItemIndex;
       
   719     }
       
   720 
       
   721 
       
   722 // ---------------------------------------------------------------------------
       
   723 // UpdateScrollIndex
       
   724 // ---------------------------------------------------------------------------
       
   725 //     
       
   726 void CAknTreeListPhysicsHandler::UpdateScrollIndex( const TBool& aScrollTop )
       
   727     {
       
   728     // Do nothing if handler itself is updating the view
       
   729     if ( iFlags.IsSet( EFlagUpdatingView ) )
       
   730         {
       
   731         return;
       
   732         }
       
   733         
       
   734     TInt first( 0 );
       
   735     TInt scrollOffset( 0 );
       
   736     TInt previousScrollIndex( iScrollIndex );
       
   737 
       
   738     // Check that scroll index is within worldSizeLimit
       
   739     TInt worldSizeLimit( WorldHeight() - iViewRect.Height() );
       
   740     if ( worldSizeLimit < iScrollIndex && worldSizeLimit > 0 )
       
   741         {
       
   742         iScrollIndex = worldSizeLimit;
       
   743         }
       
   744         
       
   745     // Adjusting scroll index according to first visible item
       
   746     if ( aScrollTop )
       
   747         {
       
   748         first = FirstVisibleItemIndex();
       
   749         }
       
   750 
       
   751     // Adjusting scroll index according to last visible item
       
   752     else
       
   753         {
       
   754         scrollOffset = iViewRect.Height();
       
   755         first = iItems->Count() - 1;
       
   756         while ( scrollOffset > iItemHeight && first >= 0 )
       
   757             {
       
   758             scrollOffset -= iItemHeight;
       
   759             first--;
       
   760             }
       
   761         }
       
   762 
       
   763     if ( first >= 0 && first < iItems->Count() )
       
   764         {
       
   765         // First visible item index of the whole item list
       
   766         TInt topIndex( iTree->VisibleItemIndex( (*iItems)[ first ].Item() ) );
       
   767         TInt currentIndex( iScrollIndex / iItemHeight );
       
   768         
       
   769         // Scrollindex needs updating
       
   770         if ( topIndex != currentIndex || scrollOffset != 0 )
       
   771             {
       
   772             iScrollIndex = topIndex * iItemHeight + scrollOffset;
       
   773             
       
   774             // Check that scroll index is within boundaries.
       
   775             if ( iScrollIndex < 0 )
       
   776                 {
       
   777                 iScrollIndex = 0;
       
   778                 }
       
   779             else if ( iScrollIndex > worldSizeLimit )
       
   780                 {
       
   781                 if ( worldSizeLimit < 0 ) 
       
   782                     {
       
   783                     // if worldSizeLimit<0, means the world height is less than view rect, no scroll needed,
       
   784                     // it is safe to set iScrollIndex to 0
       
   785                     iScrollIndex = 0;
       
   786                     }
       
   787                 else
       
   788                     {
       
   789                     iScrollIndex = worldSizeLimit;
       
   790                     }
       
   791                 }
       
   792 
       
   793             // Update view if needed
       
   794             if ( previousScrollIndex != iScrollIndex )
       
   795                 {
       
   796                 ScrollView( EFalse );                
       
   797                 }
       
   798             }
       
   799         }
       
   800     }
       
   801 
       
   802 
       
   803 // ---------------------------------------------------------------------------
       
   804 // ViewPositionChanged
       
   805 // ---------------------------------------------------------------------------
       
   806 //
       
   807 void CAknTreeListPhysicsHandler::ViewPositionChanged(
       
   808     const TPoint& aNewPosition,
       
   809     TBool aDrawNow,
       
   810     TUint /*aFlags*/ )
       
   811     {
       
   812     iScrollIndex = aNewPosition.iY - iViewRect.Height() / 2;
       
   813     TTouchFeedbackType feedbackType = ETouchFeedbackVibra;
       
   814     if ( iPhysics->OngoingPhysicsAction() 
       
   815         == CAknPhysics::EAknPhysicsActionDragging )
       
   816         {
       
   817         feedbackType = static_cast<TTouchFeedbackType>(ETouchFeedbackAudio | ETouchFeedbackVibra);
       
   818         }
       
   819     if ( iPhysics->OngoingPhysicsAction() 
       
   820             == CAknPhysics::EAknPhysicsActionBouncing )
       
   821         {
       
   822         iEventsBlocked = ETrue;
       
   823         iEnableEvents = EFalse;
       
   824         }
       
   825     else
       
   826         {
       
   827         ResetEventBlockingStatus();
       
   828         }
       
   829 
       
   830     TInt viewBottom = aNewPosition.iY + iViewRect.Height() - iViewRect.Height() / 2;
       
   831     if ( iPenDown )
       
   832         {
       
   833         iPenDown = EFalse;
       
   834         if ( iScrollIndex <= iListTopOffset - iItemHeight )
       
   835             {
       
   836             iOldTopItem = -1;
       
   837             }
       
   838         else
       
   839             {
       
   840             iOldTopItem = ( iScrollIndex - iListTopOffset ) / iItemHeight;
       
   841             if ( iOldTopItem >= iTree->VisibleItemCount() )
       
   842                 {
       
   843                 iOldTopItem = iTree->VisibleItemCount();
       
   844                 }
       
   845             }
       
   846         
       
   847         if ( viewBottom < iListTopOffset )
       
   848             {
       
   849             iOldBottomItem = -1;
       
   850             }
       
   851         else
       
   852             {
       
   853             iOldBottomItem = ( viewBottom - iListTopOffset ) / iItemHeight;
       
   854             if ( iOldBottomItem >= iTree->VisibleItemCount() )
       
   855                 {
       
   856                 iOldBottomItem = iTree->VisibleItemCount();
       
   857                 }
       
   858             }
       
   859         }
       
   860     else
       
   861         {
       
   862         TInt bottomItem, upperItem;
       
   863         if ( iScrollIndex <= iListTopOffset - iItemHeight )
       
   864             {
       
   865             upperItem = -1;
       
   866             }
       
   867         else
       
   868             {
       
   869             upperItem = ( iScrollIndex - iListTopOffset ) / iItemHeight;
       
   870             if ( upperItem >= iTree->VisibleItemCount() )
       
   871                 {
       
   872                 upperItem = iTree->VisibleItemCount();
       
   873                 }
       
   874             }
       
   875         if ( viewBottom < iListTopOffset )
       
   876             {
       
   877             bottomItem = -1;
       
   878             }
       
   879         else
       
   880             {
       
   881             bottomItem = ( viewBottom - iListTopOffset ) / iItemHeight;
       
   882             if ( bottomItem >= iTree->VisibleItemCount() )
       
   883                 {
       
   884                 bottomItem = iTree->VisibleItemCount();
       
   885                 }
       
   886             }
       
   887         if ( upperItem == -1 )
       
   888             {
       
   889             if ( bottomItem != iOldBottomItem )
       
   890                 {
       
   891                 if ( bottomItem != iTree->VisibleItemCount() - 1 )
       
   892                     iFeedback->InstantFeedback( iTreeListView,
       
   893                                                 ETouchFeedbackSensitiveList,
       
   894                                                 feedbackType,
       
   895                                                 TPointerEvent() );
       
   896                 }
       
   897             }
       
   898         else if ( bottomItem == iTree->VisibleItemCount() )
       
   899             {
       
   900             if ( upperItem != iOldTopItem )
       
   901                 {
       
   902                 iFeedback->InstantFeedback( iTreeListView,
       
   903                                             ETouchFeedbackSensitiveList,
       
   904                                             feedbackType,
       
   905                                             TPointerEvent() );
       
   906                 }
       
   907             }
       
   908         else if ( upperItem >= 0 || bottomItem < iTree->VisibleItemCount() )
       
   909             {
       
   910             if ( upperItem < iOldTopItem || bottomItem > iOldBottomItem )
       
   911                 {
       
   912                 iFeedback->InstantFeedback( iTreeListView,
       
   913                                             ETouchFeedbackSensitiveList,
       
   914                                             feedbackType,
       
   915                                             TPointerEvent() );
       
   916                 }
       
   917             }
       
   918             iOldTopItem = upperItem;
       
   919             iOldBottomItem = bottomItem;
       
   920         }
       
   921     ScrollView( aDrawNow );
       
   922     }
       
   923     
       
   924     
       
   925 // ---------------------------------------------------------------------------
       
   926 // PhysicEmulationEnded
       
   927 // ---------------------------------------------------------------------------
       
   928 //    
       
   929 void CAknTreeListPhysicsHandler::PhysicEmulationEnded()
       
   930     {
       
   931     iEnableEvents = ETrue;
       
   932     _AKNTRACE("CAknTreeListPhysicsHandler::%s Report EEventFlickStopped",
       
   933               __FUNCTION__);
       
   934     iTreeListView->ReportTreeListEvent( 
       
   935         MAknTreeListObserver::EEventFlickStopped, 
       
   936         KAknTreeIIDNone );
       
   937 #ifdef RD_UI_TRANSITION_EFFECTS_LIST
       
   938     MAknListBoxTfx* tfxApi = CAknListLoader::TfxApi( iTfxGc );
       
   939 
       
   940     if ( tfxApi )
       
   941         {
       
   942         tfxApi->EnableEffects( ETrue );
       
   943         }
       
   944 #endif // RD_UI_TRANSITION_EFFECTS_LIST
       
   945     }
       
   946 
       
   947 
       
   948 
       
   949 // ---------------------------------------------------------------------------
       
   950 // CAknTreeListPhysicsHandler::ViewPosition
       
   951 // ---------------------------------------------------------------------------
       
   952 //    
       
   953 TPoint CAknTreeListPhysicsHandler::ViewPosition() const
       
   954     {
       
   955     TPoint viewPosition( iViewRect.Width() / 2, 
       
   956                          iScrollIndex + iViewRect.Height() / 2 ); 
       
   957     return viewPosition;
       
   958     }
       
   959 
       
   960 
       
   961 // ---------------------------------------------------------------------------
       
   962 // CAknTreeListPhysicsHandler::SetGc
       
   963 // ---------------------------------------------------------------------------
       
   964 //    
       
   965 void CAknTreeListPhysicsHandler::SetGc( CWindowGc* aGc )
       
   966     {
       
   967     iTfxGc = aGc;
       
   968     }
       
   969 
       
   970 
       
   971 // ---------------------------------------------------------------------------
       
   972 // CAknTreeListPhysicsHandler::CAknTreeListPhysicsHandler
       
   973 // ---------------------------------------------------------------------------
       
   974 //
       
   975 CAknTreeListPhysicsHandler::CAknTreeListPhysicsHandler( 
       
   976     CAknTreeListView* aTreeListView,
       
   977     CAknTree* aTree,
       
   978     RArray<TAknTreeListViewItem>* aItems )
       
   979     :
       
   980     iPhysics( NULL ),
       
   981     iHighlightTimer( NULL ),
       
   982     iTree( aTree ),
       
   983     iTreeListView( aTreeListView ),
       
   984     iItems( aItems ), 
       
   985     iPlayFeedbackOnUp( EFalse )
       
   986     {
       
   987     }
       
   988 
       
   989 
       
   990 // ---------------------------------------------------------------------------
       
   991 // CAknTreeListPhysicsHandler::ConstructL
       
   992 // ---------------------------------------------------------------------------
       
   993 //
       
   994 void CAknTreeListPhysicsHandler::ConstructL()
       
   995     {
       
   996     iPhysics = CAknPhysics::NewL( *this, iTreeListView );
       
   997     iHighlightTimer = CPeriodic::NewL( CActive::EPriorityStandard );
       
   998     iFeedback = MTouchFeedback::Instance();
       
   999     }
       
  1000 
       
  1001 
       
  1002 // ---------------------------------------------------------------------------
       
  1003 // DragThreshold
       
  1004 // ---------------------------------------------------------------------------
       
  1005 //     
       
  1006 TInt CAknTreeListPhysicsHandler::DragThreshold()
       
  1007     {
       
  1008     return iPhysics->DragThreshold();
       
  1009     }
       
  1010 
       
  1011 
       
  1012 // ---------------------------------------------------------------------------
       
  1013 // LaunchHighlightTimer
       
  1014 // ---------------------------------------------------------------------------
       
  1015 //
       
  1016 void CAknTreeListPhysicsHandler::LaunchHighlightTimer( TBool aWasScrolling )
       
  1017     {
       
  1018     if ( !aWasScrolling )
       
  1019         {
       
  1020         HighlightTimerCallback( this );
       
  1021         CCoeEnv::Static()->WsSession().Finish();
       
  1022         }
       
  1023     else
       
  1024         {
       
  1025         TInt highlightTimeout = iPhysics->HighlightTimeout() * 1000;
       
  1026 
       
  1027         iHighlightTimer->Start( 
       
  1028             TTimeIntervalMicroSeconds32( highlightTimeout ),
       
  1029             TTimeIntervalMicroSeconds32( highlightTimeout ), 
       
  1030             TCallBack( HighlightTimerCallback, this ) );
       
  1031         }
       
  1032     }
       
  1033 
       
  1034 
       
  1035 // ---------------------------------------------------------------------------
       
  1036 // HighlightTimerCallback
       
  1037 // ---------------------------------------------------------------------------
       
  1038 //     
       
  1039 TInt CAknTreeListPhysicsHandler::HighlightTimerCallback( TAny* aPtr )
       
  1040     {
       
  1041     CAknTreeListPhysicsHandler* handler = 
       
  1042         static_cast<CAknTreeListPhysicsHandler*>( aPtr );
       
  1043     if ( handler && handler->iTreeListView )
       
  1044         {
       
  1045         if ( handler->iTreeListView->SingleClickEnabled() 
       
  1046              && !handler->iEnableEvents )
       
  1047             {
       
  1048             handler->iTreeListView->EnableHighlight(ETrue);
       
  1049             }
       
  1050         // Pressed down highlight if item still pressed down
       
  1051         if ( !handler->iFlags.IsSet( EFlagButtonUpReceived )
       
  1052             && handler->iFlags.IsSet( EFlagPDHighlightToFocusedItem ) )
       
  1053             {
       
  1054             handler->iTreeListView->SetPressedDownState( ETrue );
       
  1055             handler->iTreeListView->DrawNow();
       
  1056             }
       
  1057         else 
       
  1058             {
       
  1059             // Pressed down highlight if item still pressed down
       
  1060             if ( !handler->iFlags.IsSet( EFlagButtonUpReceived ) 
       
  1061                 && handler->iFlags.IsSet( EFlagPDHighlightToNonFocusedItem ) )
       
  1062                 {
       
  1063                 handler->iTreeListView->SetPressedDownState( ETrue );
       
  1064                 }
       
  1065             handler->SetHighlight();
       
  1066             }
       
  1067         handler->iFlags.Clear( EFlagPDHighlightToFocusedItem );
       
  1068         handler->iFlags.Clear( EFlagPDHighlightToNonFocusedItem );
       
  1069         }
       
  1070     return NULL;
       
  1071     }
       
  1072 
       
  1073 
       
  1074 // ---------------------------------------------------------------------------
       
  1075 // SetHighlight
       
  1076 // ---------------------------------------------------------------------------
       
  1077 //     
       
  1078 void CAknTreeListPhysicsHandler::SetHighlight()
       
  1079     {
       
  1080     iHighlightTimer->Cancel();
       
  1081     if ( iItemToBeFocused )
       
  1082         {
       
  1083         iTreeListView->SetHighlight( iItemToBeFocused, iIndexToBeFocused );
       
  1084         iItemToBeFocused = NULL;
       
  1085         }
       
  1086     }
       
  1087 
       
  1088 
       
  1089 // ---------------------------------------------------------------------------
       
  1090 // ScrollView
       
  1091 // ---------------------------------------------------------------------------
       
  1092 //     
       
  1093 void CAknTreeListPhysicsHandler::ScrollView( TBool aDrawNow )
       
  1094     {
       
  1095     iFlags.Set( EFlagUpdatingView );
       
  1096     if ( iPreviousIndex != iScrollIndex )
       
  1097         {
       
  1098         iPreviousIndex = iScrollIndex;
       
  1099         TInt currentLine = iScrollIndex / iItemHeight;           
       
  1100       
       
  1101         TInt line = currentLine;            
       
  1102         if ( currentLine < 0 )
       
  1103             {
       
  1104             line = 0;
       
  1105             }
       
  1106         else if ( currentLine >= iTree->VisibleItemCount() )
       
  1107             {
       
  1108             line = iTree->VisibleItemCount() - 1;
       
  1109             }
       
  1110 
       
  1111         iTreeListView->UpdateTreeListView( line, aDrawNow );
       
  1112         }
       
  1113     iFlags.Clear( EFlagUpdatingView );
       
  1114     }
       
  1115 
       
  1116 
       
  1117 // ---------------------------------------------------------------------------
       
  1118 // CAknTreeListPhysicsHandler::StopPhysics
       
  1119 // ---------------------------------------------------------------------------
       
  1120 //
       
  1121 void CAknTreeListPhysicsHandler::StopPhysics()
       
  1122     {
       
  1123     iPhysics->StopPhysics();
       
  1124     iPhysics->ResetFriction();
       
  1125     }
       
  1126 
       
  1127 
       
  1128 // ---------------------------------------------------------------------------
       
  1129 // CAknTreeListPhysicsHandler::WorldHeight
       
  1130 // ---------------------------------------------------------------------------
       
  1131 //
       
  1132 TInt CAknTreeListPhysicsHandler::WorldHeight()
       
  1133     {
       
  1134    	return iTree->VisibleItemCount() * iItemHeight + iListTopOffset;
       
  1135     }
       
  1136 
       
  1137 
       
  1138 // ---------------------------------------------------------------------------
       
  1139 // CAknTreeListPhysicsHandler::EmptyAreaClicked
       
  1140 // ---------------------------------------------------------------------------
       
  1141 //
       
  1142 TBool CAknTreeListPhysicsHandler::EmptyAreaClicked( TPoint aPosition )
       
  1143     { 
       
  1144     if ( aPosition.iY <= WorldHeight() )
       
  1145         {
       
  1146         return EFalse;
       
  1147         }
       
  1148     return ETrue;
       
  1149     }
       
  1150 
       
  1151