/*
* Copyright (c) 1997-2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* 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:   List box implementation.
*
*/

  
#include <e32base.h>
#include <e32keys.h>
#include <bamatch.h>
#include <badesca.h>
#include <barsread.h>
#include <eiklbx.h>
#include <eiklbv.h>
#include <eiklbi.h>
#include <eiklbm.h>
#include <eikenv.h>
#include <eiklbx.pan>
#include <gulbordr.h>
#include <eikbutb.h>
#include <coemain.h>
#include <w32std.h>
#include <gulutil.h>
#include <uikon.hrh>
#include <eikkeys.h>
//#include <laflistb.h>
#include <laflbx.h>

#include <eikpanic.h>
#include <eikcmobs.h>

// Needed to use MopGetObject
#include <coemop.h>
#include <eikmenub.h> 
#include <AknLayout.lag>
#include <aknenv.h>
#include <AknDef.h>
#include <AknUtils.h>

#include <aknappui.h>
#include <aknPopup.h>

#include <AknTasHook.h>
// For hash key marking.
#include <e32property.h>
#include <featmgr.h>
#include <centralrepository.h>
#include <cenrepnotifyhandler.h>
#include <AknFepInternalCRKeys.h> // KAknFepHashKeySelection
#include <AvkonInternalCRKeys.h>  // KAknQwertyInputModeActive
#include <aknlayoutscalable_avkon.cdl.h>
#include <aknphysics.h>
#include <aknphysicsobserveriface.h>

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
#include <aknlistboxtfxinternal.h> // LISTBOX EFFECTS IMPLEMENTATION
#include <aknlistloadertfx.h>
#include <aknlistboxtfx.h>
#endif

#include <touchfeedback.h>
#include <akncollection.h>
#include <aknitemactionmenu.h>
#include <aknlongtapdetector.h>
#include <AknPriv.hrh>
#include <aknmarkingmodeobserver.h>
#include "akntrace.h"

// timeout for long keypress used in markable lists
const TInt KLongPressInterval = 600000; // 0,6 seconds
const TInt KEikListBoxPointerRepeatInterval = 100000;  // in micro conds (= 0.1 secod)

// Maximum scroll speed ( max amount of items moved one time )
const TInt KDefaultMaxSpeed = 30;
const TInt KDefaultStepSpeed = 5;
const TInt KEikListBoxInvalidIndex=-1;
//interval time for disable second point event
const TInt KTwoPointerUpEventInterval = 120;    //  120 millisecond ( = 0.12 second )
const TInt KPointerDownAndUpThreshold = 5;
// -----------------------------------------------------------------------------
// If a parent to the supplied control has its Gc set, this function will find 
// it and return it.
// -----------------------------------------------------------------------------
//
LOCAL_C CWindowGc* ReplaceGcWithCustomGc( const CEikListBox* aListBox )
    {
    _AKNTRACE_FUNC_ENTER;
    const CCoeControl* parent = aListBox;
    CWindowGc* customGc;
    while(parent)
        {
        customGc = parent->GetGc();
        if ( customGc )
            {
            CListItemDrawer* itemDrawer = aListBox->View()->ItemDrawer();
            CWindowGc* originalGc = itemDrawer->Gc();
            if ( customGc == originalGc )
            {
                _AKNTRACE_FUNC_EXIT;
                return NULL;
                }
            else
                {
                itemDrawer->SetGc( customGc );
                _AKNTRACE_FUNC_EXIT;
                return originalGc;
                }
            }
        parent = parent->Parent();
        }
    _AKNTRACE_FUNC_EXIT;
    return NULL;
    }

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
// ---------------------------------------------------------------------------
// Helper function that selects list items
// ---------------------------------------------------------------------------
//
LOCAL_C void SelectL( CListBoxView* aView, MAknListBoxTfxInternal* transApi, TInt aIndex, TBool select, TBool force = EFalse )
    {
    _AKNTRACE_FUNC_ENTER;
    if ( aView->ItemIsSelected( aIndex ) == select )
        {
        if ( force || transApi->SetPosition( MAknListBoxTfxInternal::EListItem, aView->ItemPos( aIndex ), aIndex ) != KErrNone )
            {
            aView->DrawItem( aIndex );
            }
        }
    else if ( select )
        {
        if ( aIndex >= aView->TopItemIndex() && aIndex <= aView->BottomItemIndex() )
            {
            aView->SelectItemL( aIndex );
            }
        else if ( !transApi->Exist( MAknListBoxTfxInternal::EListItem, aIndex ) )
            {
            aView->SelectItemL( aIndex );
            }
        else
            {
            TInt topItemIndex = aView->TopItemIndex();
            aView->SetTopItemIndex( aIndex );
            aView->SelectItemL( aIndex );
            aView->SetTopItemIndex( topItemIndex );
            }
        }
    else
        {
        if ( aIndex >= aView->TopItemIndex() && aIndex <= aView->BottomItemIndex() )
            {
            aView->DeselectItem( aIndex );
            }
        else if ( !transApi->Exist( MAknListBoxTfxInternal::EListItem, aIndex ) )
            {
            aView->DeselectItem( aIndex );
            }
        else
            {
            TInt topItemIndex = aView->TopItemIndex();
            aView->SetTopItemIndex( aIndex );
            aView->DeselectItem( aIndex );
            aView->SetTopItemIndex( topItemIndex );
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }

// ---------------------------------------------------------------------------
// Helper function that updates list item selections
// ---------------------------------------------------------------------------
//
LOCAL_C void UpdateSelectionsL( CListBoxView* aView, MAknListBoxTfxInternal* transApi, TInt aHl, TInt aOld, TInt aAnchor, TBool aSelect )
    {
    _AKNTRACE_FUNC_ENTER;
    if ( aHl < aOld )
        {
        // Going up
        if ( aOld <= aAnchor )
            {
            // Going up away
            SelectL( aView, transApi, aOld, aSelect, ETrue );
            for ( TInt i = aOld - 1; i > aHl; i-- )
                {
                SelectL( aView, transApi, i, aSelect );
                }
            SelectL( aView, transApi, aHl, aSelect, ETrue );
            }
        else if ( aHl >= aAnchor )
            {
            // Going up against
            for ( TInt i = aOld; i > aHl; i-- )
                {
                SelectL( aView, transApi, i, !aSelect );
                }
            SelectL( aView, transApi, aHl, aSelect, ETrue );
            }
        else
            {
            // Passing anchor
            for ( TInt i = aOld; i > aAnchor; i-- )
                {
                SelectL( aView, transApi, i, !aSelect );
                }
            for ( TInt i = aAnchor; i >= aHl; i-- )
                {
                SelectL( aView, transApi, i, aSelect );
                }
            }
        for ( TInt i = aView->BottomItemIndex(); i >= aView->TopItemIndex(); i-- )
            {
            if ( i < aHl || i > aOld )
                {
                if ( transApi->SetPosition( MAknListBoxTfxInternal::EListItem, aView->ItemPos( i ), i ) != KErrNone )
                    {
                    aView->DrawItem( i );
                    }
                }
            }
        }
    else if ( aHl >= aOld )
        {
        // Going down
        if ( aOld >= aAnchor )
            {
            // Going down away
            SelectL( aView, transApi, aOld, aSelect, ETrue );
            for ( TInt i = aOld + 1; i < aHl; i++ )
                {
                SelectL( aView, transApi, i, aSelect );
                }
            SelectL( aView, transApi, aHl, aSelect, ETrue );
            }
        else if ( aHl <= aAnchor )
            {
            // Going down against
            for ( TInt i = aOld; i < aHl; i++ )
                {
                SelectL( aView, transApi, i, !aSelect );
                }
            SelectL( aView, transApi, aHl, aSelect, ETrue );
            }
        else
            {
            // Passing anchor
            for ( TInt i = aOld; i < aAnchor; i++ )
                {
                SelectL( aView, transApi, i, !aSelect );
                }
            for ( TInt i = aAnchor; i <= aHl; i++ )
                {
                SelectL( aView, transApi, i, aSelect );
                }
            }
        for ( TInt i = aView->BottomItemIndex(); i >= aView->TopItemIndex(); i-- )
            {
            if ( i > aHl || i < aOld )
                {
                if ( transApi->SetPosition( MAknListBoxTfxInternal::EListItem, aView->ItemPos( i ), i ) != KErrNone )
                    {
                    aView->DrawItem( i );
                    }
                }
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }
#endif // RD_UI_TRANSITION_EFFECTS_LIST

//
// class CMatchBuffer
//

NONSHARABLE_CLASS(CMatchBuffer) : public CBase
    {   
public:
    enum TExtent
        { EFull, EMinimal };
public:
    static CMatchBuffer* NewL(TExtent aExtent);
    ~CMatchBuffer();
    void ConstructMatchBufferL();
public:
    RIncrMatcherBase* iMatchBuffer;
    TInt iPressedIndex; 
    TBool iDragToAnotherItem; 
    };

CMatchBuffer* CMatchBuffer::NewL(TExtent aExtent)
    {
    CMatchBuffer* buffer=new(ELeave) CMatchBuffer;
    if (aExtent==EFull)
        {
        CleanupStack::PushL(buffer);
        buffer->iMatchBuffer=new(ELeave)RIncrMatcherBuf<CEikListBox::KEikMaxMatchingBufferLength>;
        CleanupStack::Pop( buffer );
        }
    return buffer;
    }

CMatchBuffer::~CMatchBuffer()
    {
    delete iMatchBuffer;
    }

void CMatchBuffer::ConstructMatchBufferL()
    {
    iMatchBuffer=new(ELeave)RIncrMatcherBuf<CEikListBox::KEikMaxMatchingBufferLength>;
    }

//
// class CLBMSKCommandObserver
//

NONSHARABLE_CLASS(CLBMSKCommandObserver) : public MEikCommandObserver
    {
public:
    CLBMSKCommandObserver(CEikButtonGroupContainer *aCba, CEikListBox *aListBox);
    void ProcessCommandL(TInt aCommandId);
    CEikButtonGroupContainer *iCba;
    CEikListBox *iListBox;
    TInt iCurrentResource;
    };


CLBMSKCommandObserver::CLBMSKCommandObserver(CEikButtonGroupContainer *aCba, CEikListBox *aListBox)
     : iCba(aCba), iListBox(aListBox)
    {
    }

void CLBMSKCommandObserver::ProcessCommandL(TInt aCommandId)
    {
    switch ( aCommandId )
        {
        case EAknSoftkeyMark:
            {
            TInt index = iListBox->CurrentItemIndex();
            iListBox->View()->SelectItemL(index);
            iCba->SetCommandL(3,R_AVKON_SOFTKEY_UNMARK);
            iCba->DrawNow();
            iCurrentResource = R_AVKON_SOFTKEY_UNMARK;        
            }
            break;
        case EAknSoftkeyUnmark:
            {
            TInt index = iListBox->CurrentItemIndex();
            iListBox->View()->DeselectItem(index);
            iCba->SetCommandL(3,R_AVKON_SOFTKEY_MARK);
            iCba->DrawNow();
            iCurrentResource = R_AVKON_SOFTKEY_MARK;        
            }
            break;
        case EAknSoftkeyShiftMSK:
            {
            iListBox->DoShiftMSKMarkingL();
            }
            break;
        default:
            break;
        }
    }

//
// class CListBoxExt
//

NONSHARABLE_CLASS(CListBoxExt) : public CBase, public MListVisibilityObserver,
    public MCenRepNotifyHandlerCallback,
    public MAknPhysicsObserver,
    public MAknCollection,
    public MAknMarkingCollection,
    public MAknLongTapDetectorCallBack
    {
public:
    static CListBoxExt* NewL(CEikListBox& aListBox);
    ~CListBoxExt();

    // new functions
    void CreateMatchBufferL();
    void CheckCreateBufferL();
    CMatchBuffer* Buffer() const;
    TBool IsMatchBuffer() const;
    void SetReasonForFocusLost(CEikListBox::TReasonForFocusLost aReasonForFocusLost);
    CEikListBox::TReasonForFocusLost ReasonForFocusLost() const;

    /// @since 3.0
    void AddItemChangeObserverL( MListBoxItemChangeObserver* aObserver );
    /// @since 3.0
    TBool RemoveItemChangeObserver( MListBoxItemChangeObserver* aObserver );
    /// @since 3.0
    void FireItemChange(CEikListBox* aListBox);
    
    void CreateMSKObserverL(CEikButtonGroupContainer *aCba, 
                                     CEikListBox *aListBox);
    void RemoveMSKObserver(CEikListBox *aListBox);

    // @since 3.2
    void AddSelectionObserverL( MListBoxSelectionObserver* aObserver );
    TBool RemoveSelectionObserver( MListBoxSelectionObserver* aObserver );
    // Starts the long press timer.
    void StartLongPressTimerL();
    TBool IsInIgnoreRect( const TPoint& aPoint ) const;
    //Tests the item needs to handle all point event or not.
    TBool IsInHandleAllPointEventArray(const TInt aIndex);
public: // from MListVisibilityObserver
    TBool IsVisible() const;
    void SetUpdateScrollBarsColors(TBool aUpdate);
    TBool UpdateScrollBarsColors() const;
public: // from MCenRepNotifyHandlerCallback
    void HandleNotifyInt(TUint32 aId, TInt aNewValue);
    
public: // MAknPhysicsObserver
    virtual void ViewPositionChanged( const TPoint& aNewPosition,
                                      TBool aDrawNow = ETrue,
                                      TUint aFlags = 0 );
    virtual void PhysicEmulationEnded();
    virtual TPoint ViewPosition() const;

// From MAknCollection
    /**
     * Returns the collection state. The state is combination of
     * flags defined in MAknCollection::TStateFlag. 
     *
     * @return  Collection state.
     */
    TUint CollectionState() const;

    /**
     * Notifies that item action menu (CAknItemActionMenu)
     * was closed. 
     */
    void ItemActionMenuClosed();

    /** 
     * Extension function.
     *
     * @param  aExtensionId  Extension id. 
     * @param  a0            First extension method parameter.
     * @param  a1            Second extension method parameter.
     */    
    TInt CollectionExtension( TUint aExtensionId, TAny*& a0, TAny* a1 );

// From MAknMarkingCollection
    /**
     * Sets multiple marking state.
     *
     * @param aActive ETrue if multiple marking should be active.
     */
    void SetMultipleMarkingState( TBool aActive );
    
    /**
     * Returns whether the observer accepts ending of marking mode
     * 
     * @return ETrue if observer accepts exiting marking mode
     */
    TBool ExitMarkingMode();
    
    /**
     * Returns the collection marking state. The state is combination of
     * flags defined in @c TStateFlag. 
     *
     * @return  Collection state.
     */
    TUint MarkingState() const;

    /**
     * Marks the currently selected item.
     */
    void MarkCurrentItemL();
     
    /**
     * Marks all items in the collection.
     */
    void MarkAllL(); 

    /**
     * Unmarks all items in the collection.
     */
    void UnmarkAll();
    
    /*
     * Can current item be marked
     * 
     * @return ETrue if item can be marked
     */
    TBool CurrentItemMarkable();
    
// From MAknLongTapDetectorCallBack
    /**
     * Long tap detector callback 
     *
     * @param aPenEventLocation Long tap event location relative to parent control.
     * @param aPenEventScreenLocation Long tap event location relative to screen.
     */
    void HandleLongTapEventL( const TPoint& aPenEventLocation,
                              const TPoint& aPenEventScreenLocation );

// New single click related methods
    /**
     * Reports collection change event.
     */
    void ReportCollectionChangedEvent();

    /**
     * Enables or disables the highlight 
     * @param aEnabled ETrue to enable EFalse to disable
     * @param aPointerEnabled ETrue if highlight was enabled by pointer event.
     */
    void EnableHighlight( TBool aEnabled, TBool aPointerEnabled = EFalse );

    /**
     * Sets the highlight for the first item visible after single click 
     * is disabled
     */
    void DisableSingleClick();

    /**
     * Enables single click
     */
    void EnableSingleClickL();    
    
    /**
     * Disables item specific menu.
     */
    void DisableItemSpecificMenu();

    /**
     * Sends pointer event to long tap detector if necessary.
     * 
     * @aPointerEvent Pointer event to send to long tap detector.
     */
    void LongTapPointerEventL( const TPointerEvent& aPointerEvent );

    /**
     * Cancels long tap detecting if detector is active.
     */
    void CancelLongTapL();

    /**
     * Enables highlight with key event if listbox is single click enabled.
     * 
     * @param aKeyEvent Received key event.
     * @param aType Key event type.
     * @return ETrue if key should be consumed.
     */
    TBool EnableHighlightWithKeyEventL(
            TInt aTopItemIndex,
            const TKeyEvent& aKeyEvent,
            TEventCode aType );

    /**
     * Returns ETrue if list has currently marked items.
     * 
     * @return ETrue if list has marked items.
     */
    TBool MarkedItems() const;
    
    /**
     * Ignores pointer events until next up event. 
     * 
     * @return ETrue if the pointer event ignore was enabled.
     */
    TBool IgnorePointerEventsUntilUp();

public:
    void InitPhysicsL();
	
    /**
    * Moves the current item cursor in the specified direction. This function 
    * is called by @c CEikListBox in response to user input when physics 
    * is enabled.
     *
    * @return @c ETrue if the event was consumed.
    *
    * @param aCursorMovement The cursor movement to apply. 
    * @param aSelectionMode The selection mode of the calling list box.
    */
    TBool MovePhysicsCursorL(CListBoxView::TCursorMovement aCursorMovement, 
                             CListBoxView::TSelectionMode aSelectionMode);
   
    static TInt HighlightTimerCallback( TAny* aPtr );
	void CheckScrollBarVisibility();
    void StartHighlightTimer();
    void CancelHighlightTimer();
    TBool HighlightTimerActive() const;
    void ImmediateFeedback( TTouchLogicalFeedback aFeedback,
                            TTouchFeedbackType aFeedbackType,
                            const TPointerEvent& aPointerEvent );
    TBool FeedbackEnabledOnUpEvent();
    void SetFlickOngoing( TBool );
    void SetPanningOngoing( TBool );
    TBool FlickOrPanningOngoing();
    TInt ListBottomLimit();
    
private: 
    CListBoxExt(CEikListBox& aListBox);
    void ConstructL();    
    static TInt QwertyModeChangeNotification(TAny* aObj);  
    void HandleQwertyModeChangeNotification();
    // Callback method for long press timer.
    static TInt ReportLongPressL( TAny* aThis );
    // Handles long press.
    void DoHandleLongPressL();
       
private:
    enum {
        EUpdateScrollBarsColors =0x1,
        EMSKKeyDownEventReceived = 0x2,
        EHighlightEnabledByPointer = 0x4
    };

private: 
    NONSHARABLE_CLASS(CSubscriber) : public CActive
        {
    public:
        CSubscriber(TCallBack aCallBack, RProperty& aProperty);
        ~CSubscriber();

    public: // New functions
        void SubscribeL();
        void StopSubscribe();

    private: // from CActive
        void RunL();
        void DoCancel();

    private:
        TCallBack   iCallBack;
        RProperty&  iProperty;
        };    
public:

    // The index of an item, which has received the latest pointer down event.
    // This value is used in pointer up event handling to check whether or
    // not the same item received both down and up events.
    TInt iLastDownTappedItem;

    TInt iEventModifiers;
    TBool iWesternVariant;
    TBool iAknFepHashKeySelection;
    TBool iQwertyMode;
    TBool iMSKObserverEnabled;
    TBool iMSKButtonGroupAlive; // status of buttongroup, which is used for MSK observer
    // these are used for shift, ctrl and hash keys in markable lists    
    CPeriodic* iLongPressTimer; 
    TBool iSelectionModeEnabled;
    TBool iShortHashMark;
    // Contains only references, observers not owned
    RPointerArray<MListBoxSelectionObserver> iSelectionObservers;
    // used in CEikListBox::HandlePointerEventL and
    // CEikListBox::OfferKeyEventL to enable multiselection with hash key
    TBool iShiftKeyPressed;
    // Last stuly down position
    TBool iIsDownOnItem;
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    TBool iSelect;
    TInt iAnchor;
#endif // RD_UI_TRANSITION_EFFECTS_LIST
    TInt iSpeed;
    // Last pointer event pos
    TPoint iLastPoint;

    TInt iMaxSpeed;
    TInt iStepSpeed;
    TInt iInterval;
    CPeriodic* iHighlightTimer;    
    CAknPhysics *iPhysics;
    TPoint iDragStartPosition;
    TPoint iLastPointerPos;
    TBool iClickEventsAllowed;
    TBool iScrolling;
    TSize iViewSize;
    TSize iWorldSize;
    TBool iItemDraggingReported;
    TTime iStartTime;
    TInt iItemsInSingleLine;
    TBool iEffectsEnabled;
    
    TPoint iViewPosition; // Current view position
    TInt iSelectedIndex;
    //Array of items need to handle point event everytime.
    RArray< TInt > iMutiTappingItems;
    // To calculate twice click interval  time on same item.
    TUint32 iListPointUpTime;
    TInt iLastItemIndex;
    
    // Used to disable list scrolling in certain list types.
    TBool iScrollingDisabled;
    
    // Whether or not pen down on item should be reported on highlight
    // timer callback.
    TBool iReportDelayedPenDown;
    
    // Whether or not multiselection should be done on highlight
    // timer callback.
    TBool iDelayedMultiselection;
    
    // Marking mode for multiselection lists is disabled when flicking.
    TBool iMarkingDisabled;
 
    // part of HandlePointerEventL for marking is moved to highlight timer with this flag
    TBool iMarkableListMarking;
    TBool iMarkableListShiftKeyPressed;
    TInt iMarkableListSelectionMode;
   
    // previous top item 
    TInt iPrevTopItemIndex;
    // is flick stopped by down event
    TBool iFlickStopped;
    
    TTouchLogicalFeedback iFeedbackType;
    
    /**
     * Pointer to item action menu.
     * Not own.
     */
    CAknItemActionMenu* iItemActionMenu;    
    
   /**
    * Long tap detector
    */
    CAknLongTapDetector* iLongTapDetector;

   /**
    * Single click mode enabled or not.
    */
    TBool iSingleClickEnabled;

   /**
    * Item that opened the item action menu
    */
    TInt iLongTappedItem;

    /**
     * Marking mode on / off.
     */
    TBool iMarkingModeInUse;
    
    /**
     * Marking mode observer.
     */
    MAknMarkingModeObserver* iMarkingModeObserver;
    
    /**
     * Pointer event to be forwarded to the long tap detector upon
     * highlight timer completion.
     */
    TPointerEvent iDelayedPointerDownEvent;
    
    /**
     * Ordinal position of listbox window, before stylus menu is opened.
     */
    TInt iOldWinPos;

    /**
     * If double click modifier is set on PointerEvent, the event may be ignored
     * in some situation(To prevent extra dialog launched by AO).
     */
    TBool iDoubleClickEventIgnored;
    
private:
    CMatchBuffer* iBuffer;
    CEikListBox& iListBox;
    CEikListBox::TReasonForFocusLost iReasonForFocusLost;
    TInt iFlags;
    // Contains only references, observers not owned
    RPointerArray<MListBoxItemChangeObserver> iItemChangeObservers;

    // For hash key selection.    
    CRepository* iCenRep;
    CCenRepNotifyHandler* iCenRepNotifyHandler;      
    CSubscriber* iQwertyModeStatusSubscriber;
    RProperty iQwertyModeStatusProperty;    
    MEikCommandObserver *iMSKCommandObserver; // this is for markable/multiselection list query
    /**
     * Pointer to the feedback object. Not owned.
     */    
    MTouchFeedback* iFeedback;

    /**
     * Is flick ongoing or not.
     */    
    TBool iFlickOngoing;

    /**
     * Is panning ongoing or not.
     */    
    TBool iPanningOngoing;

    /**
     * Height of the list in pixels.
     */    
    TInt iListBottomLimit;    
    };
    
// CEikListBoxExt    

CListBoxExt* CListBoxExt::NewL( CEikListBox& aListBox )
    { // static
    _AKNTRACE_FUNC_ENTER;
    CListBoxExt* self = new (ELeave) CListBoxExt( aListBox );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    _AKNTRACE_FUNC_EXIT;
    return self;
    }

CListBoxExt::CListBoxExt(CEikListBox& aListBox)
    : iLastDownTappedItem(KErrNotFound), iWesternVariant(ETrue), 
      iAknFepHashKeySelection(EFalse), 
      iQwertyMode(EFalse), iLongPressTimer(NULL), iSelectionModeEnabled(EFalse),
      iLastPoint(0,0), iMaxSpeed( KDefaultMaxSpeed ), iStepSpeed( KDefaultStepSpeed ),
      iInterval( KEikListBoxPointerRepeatInterval ),
      iClickEventsAllowed( ETrue ),
      iWorldSize(0,0),
      iSelectedIndex( KErrNotFound ),
      iListPointUpTime(0),
      iLastItemIndex(-1),
      iItemActionMenu( NULL ),
      iLongTapDetector( NULL ),
      iSingleClickEnabled( iAvkonAppUi->IsSingleClickCompatible() ),
      iLongTappedItem( KErrNotFound ),
      iOldWinPos( KErrNotFound ),
      iListBox(aListBox)
    {
    }

CListBoxExt::~CListBoxExt()
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iItemActionMenu )
        {
        iItemActionMenu->RemoveCollection( *this );
        }
    if ( iLongTapDetector )
        {
        delete iLongTapDetector;
        }

    delete iPhysics;
    delete iHighlightTimer;
    iMutiTappingItems.Close();
    delete iLongPressTimer;    
    FeatureManager::UnInitializeLib();
    iItemChangeObservers.Reset();
    iSelectionObservers.Reset();    
    delete iBuffer;

    // Stop listening CenRep.
    if (iCenRepNotifyHandler)
        {
        iCenRepNotifyHandler->StopListening();
        }
    delete iCenRepNotifyHandler;
    delete iCenRep; 
    
    // Stop subscribe in PubSub
    if (iQwertyModeStatusSubscriber)
        {
        iQwertyModeStatusSubscriber->StopSubscribe();
        }
    iQwertyModeStatusProperty.Close();
    delete iQwertyModeStatusSubscriber;   
    if (iMSKCommandObserver)
        {
        delete iMSKCommandObserver;
        iMSKCommandObserver = NULL;
        }
    _AKNTRACE_FUNC_EXIT;
    }

void CListBoxExt::ConstructL()
    {
    _AKNTRACE_FUNC_ENTER;
    // Check the mode for hash key selection.
    // Eastern (short hash doesn't mark) == Chinese, Japanese or Vietnamese
    // Western (short hash marks) == All others.
    FeatureManager::InitializeLibL();
    if (FeatureManager::FeatureSupported(KFeatureIdChinese)  ||
        FeatureManager::FeatureSupported(KFeatureIdJapanese) || 
        (User::Language() & KAknLanguageMask) == ELangVietnamese)
        {
        iWesternVariant = EFalse;
        }
    
    // Start listening a CenRep key indicating whether hash key selection is active.
    TRAPD(err, iCenRep = CRepository::NewL(KCRUidAknFep));
    if (err == KErrNone)
        {
        iCenRepNotifyHandler = CCenRepNotifyHandler::NewL(*this,
            *iCenRep,
            CCenRepNotifyHandler::EIntKey,
            KAknFepHashKeySelection);

        iCenRepNotifyHandler->StartListeningL();
        iCenRep->Get(KAknFepHashKeySelection, iAknFepHashKeySelection);
        } 
        
    // Start also listening qwerty mode status. Hash key selection is disabled when
    // qwerty mode is active.
    User::LeaveIfError(iQwertyModeStatusProperty.Attach(KCRUidAvkon, 
        KAknQwertyInputModeActive));

    iQwertyModeStatusSubscriber = new (ELeave) CSubscriber(
        TCallBack(QwertyModeChangeNotification, this), iQwertyModeStatusProperty);
        
    iQwertyModeStatusSubscriber->SubscribeL();       
    
    // Get the initial value.
    HandleQwertyModeChangeNotification();
    
    iMSKObserverEnabled = ETrue; // By default listbox handles MSK
    iShortHashMark = EFalse;
    
    iLongPressTimer = CPeriodic::NewL( CActive::EPriorityStandard );    

    if ( CAknPhysics::FeatureEnabled() )
        {
        iPhysics = CAknPhysics::NewL( *this, &iListBox );
        iHighlightTimer = CPeriodic::NewL( CActive::EPriorityStandard );
        }
    iItemsInSingleLine = 1;
    iFeedback = MTouchFeedback::Instance();

    iItemActionMenu = CAknItemActionMenu::RegisterCollectionL( *this, &iListBox );

    if ( !( iListBox.iListBoxFlags & CEikListBox::EDisableItemSpecificMenu )
            && iItemActionMenu )
        {
        iLongTapDetector = CAknLongTapDetector::NewL( this );
        }
    if ( iSingleClickEnabled )
        {
        EnableHighlight( EFalse );
        }
    _AKNTRACE_FUNC_EXIT;
    } 


void CListBoxExt::AddSelectionObserverL(
        MListBoxSelectionObserver* aObserver )
    {
    _AKNTRACE_FUNC_ENTER;
    iSelectionObservers.AppendL( aObserver );
    _AKNTRACE_FUNC_EXIT;
    }

TBool CListBoxExt::RemoveSelectionObserver(
        MListBoxSelectionObserver* aObserver )
    {
    _AKNTRACE_FUNC_ENTER;
    TInt index = iSelectionObservers.Find( aObserver );
    if( KErrNotFound == index )
        {
        _AKNTRACE_FUNC_EXIT;
        return EFalse;
        }

    iSelectionObservers.Remove( index );
    _AKNTRACE_FUNC_EXIT;
    return ETrue;
    }

TPoint CListBoxExt::ViewPosition() const
    {
    return iViewPosition;
    }


// -----------------------------------------------------------------------------
// CListBoxExt::CollectionState
// -----------------------------------------------------------------------------
//
TUint CListBoxExt::CollectionState() const
    {
    _AKNTRACE_FUNC_ENTER;
    TUint state( 0 );
    if ( iListBox.IsVisible()
            && ( !iListBox.DrawableWindow()
            || !iListBox.DrawableWindow()->IsFaded() ) )
        {
        state |= MAknCollection::EStateCollectionVisible;
        }
    if ( iListBox.iItemDrawer )
        {
        TInt drawerFlags( iListBox.iItemDrawer->Flags() );
        if ( !( drawerFlags 
                & CListItemDrawer::ESingleClickDisabledHighlight )
                && !( iFlags & EHighlightEnabledByPointer ) )
            {
            state |=  MAknCollection::EStateHighlightVisible;
            }
        if ( drawerFlags & CListItemDrawer::EDisableHighlight )
            {
            state |= MAknCollection::EStateViewOnly;
            }
        }
    if ( iListBox.iListBoxFlags & CEikListBox::EMultipleSelection )
        {
        state |= MAknCollection::EStateMultipleSelection;
        }
    if ( MarkedItems() )
        {
        state |= MAknCollection::EStateMarkedItems; 
        }
    _AKNTRACE_FUNC_EXIT;
    return state;
    }


// -----------------------------------------------------------------------------
// CListBoxExt::ItemActionMenuClosed
// -----------------------------------------------------------------------------
//
void CListBoxExt::ItemActionMenuClosed()
    {
    if ( iLongTappedItem != KErrNotFound )
        {
        EnableHighlight( EFalse );
        iListBox.iView->DrawItem( iLongTappedItem );
        iLongTappedItem = KErrNotFound;
        iOldWinPos = KErrNotFound;
        }
    }


// -----------------------------------------------------------------------------
// CListBoxExt::CollectionExtension
// -----------------------------------------------------------------------------
//
TInt CListBoxExt::CollectionExtension(
        TUint aExtensionId, TAny*& a0, TAny* /*a1*/ )
    {
    if ( aExtensionId == MAknMarkingCollection::TYPE )
        {
        a0 = static_cast<MAknMarkingCollection*>( this );
        }

    return KErrNone;
    }


// -----------------------------------------------------------------------------
// CListBoxExt::SetMultipleMarkingState
// -----------------------------------------------------------------------------
//
void CListBoxExt::SetMultipleMarkingState( TBool aActive )
    {
    _AKNTRACE_FUNC_ENTER;
    iListBox.SetMarkingMode( aActive );
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CListBoxExt::ExitMarkingMode
// -----------------------------------------------------------------------------
//
TBool CListBoxExt::ExitMarkingMode()
    {
    if ( iListBox.MarkingModeObserver() )
        {
        return iListBox.MarkingModeObserver()->ExitMarkingMode();
        }
    return ETrue;
    }

// -----------------------------------------------------------------------------
// CListBoxExt::MarkingState
// -----------------------------------------------------------------------------
//
TUint CListBoxExt::MarkingState() const
    {
    _AKNTRACE_FUNC_ENTER;
    TUint state( 0 );
    if ( iListBox.MarkingMode() )
        {
        state |= MAknMarkingCollection::EStateMarkingMode;
        if ( MarkedItems() )
            {
            state |= MAknMarkingCollection::EStateMarkedItems;
            }
        if ( iListBox.Model()->NumberOfItems() == 0 )
            {
            state |= MAknMarkingCollection::EStateCollectionEmpty;
            }        
        }
    _AKNTRACE_FUNC_EXIT;
    return state;
    }


// -----------------------------------------------------------------------------
// CListBoxExt::MarkCurrentItemL
// -----------------------------------------------------------------------------
//
void CListBoxExt::MarkCurrentItemL()
    {
    _AKNTRACE_FUNC_ENTER;

    if ( iListBox.MarkingMode() )
        {
        TInt index = iListBox.CurrentItemIndex();
        if ( index >= 0 && 
                !iListBox.iItemDrawer->Properties( index ).IsSelectionHidden() )
            {
            iListBox.View()->SelectItemL( iListBox.CurrentItemIndex() );
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }


// -----------------------------------------------------------------------------
// CListBoxExt::MarkAllL
// -----------------------------------------------------------------------------
//
void CListBoxExt::MarkAllL()
    {
    _AKNTRACE_FUNC_ENTER;

    if ( iListBox.MarkingMode() )
        {       
        for ( TInt i = 0; i < iListBox.Model()->NumberOfItems(); ++i )
            {
            if ( !iListBox.iItemDrawer->Properties( i ).IsSelectionHidden() )
                {
                iListBox.View()->SelectItemL( i );
                }
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }


// -----------------------------------------------------------------------------
// CListBoxExt::UnmarkAll
// -----------------------------------------------------------------------------
//
void CListBoxExt::UnmarkAll()
    {
    _AKNTRACE_FUNC_ENTER;

    if ( iListBox.MarkingMode() )
        {
        iListBox.View()->ClearSelection();
        }

    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CListBoxExt::CurrentItemMarkable
// -----------------------------------------------------------------------------
//
TBool CListBoxExt::CurrentItemMarkable()
    {
    _AKNTRACE_FUNC_ENTER;
    TBool itemCanBeMarked = ETrue;
     TInt index = iListBox.CurrentItemIndex();
     if ( index >= 0 && 
             iListBox.iItemDrawer->Properties( index ).IsSelectionHidden() )
         {
         itemCanBeMarked = EFalse;
         }
    _AKNTRACE_FUNC_EXIT;
    return itemCanBeMarked;
    }


// ---------------------------------------------------------------------------
// CListBoxExt::HandleLongTapEventL
// ---------------------------------------------------------------------------
//
void CListBoxExt::HandleLongTapEventL( const TPoint& /*aPenEventLocation*/, 
                                       const TPoint& aPenEventScreenLocation )
    {
    _AKNTRACE_FUNC_ENTER;
    iLongTappedItem = iLastDownTappedItem;
    iLastDownTappedItem = KErrNotFound;
    iItemActionMenu->ShowMenuL( aPenEventScreenLocation, 0 );
    IgnorePointerEventsUntilUp();
    iOldWinPos = iListBox.DrawableWindow()->OrdinalPosition();
    _AKNTRACE_FUNC_EXIT;
    }


// -----------------------------------------------------------------------------
// CListBoxExt::ReportCollectionChangedEvent
// -----------------------------------------------------------------------------
//
void CListBoxExt::ReportCollectionChangedEvent()
    {
    if ( iItemActionMenu )
        {
        iItemActionMenu->CollectionChanged( *this );
        }
    }


// -----------------------------------------------------------------------------
// CListBoxExt::EnableHighLight
// -----------------------------------------------------------------------------
//
void CListBoxExt::EnableHighlight( TBool aEnabled, TBool aPointerEnabled )
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iListBox.iItemDrawer && iSingleClickEnabled )
        {
        TBool wasEnabled( !( iListBox.iItemDrawer->Flags()
                & CListItemDrawer::ESingleClickDisabledHighlight ) );
        iFlags &= ( ~EHighlightEnabledByPointer );
        if ( aEnabled )
            {
            iListBox.iItemDrawer->ClearFlags(
                    CListItemDrawer::ESingleClickDisabledHighlight );
            if ( aPointerEnabled )
                {
                iFlags |= EHighlightEnabledByPointer;
                }
            }
        else
            {
            iListBox.iItemDrawer->SetFlags(
                    CListItemDrawer::ESingleClickDisabledHighlight );
            }
        if ( !aPointerEnabled
                && ( ( wasEnabled && !aEnabled )
                        || ( !wasEnabled && aEnabled ) ) )
            {
            ReportCollectionChangedEvent();
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CListBoxExt::DisableSingleClick
// -----------------------------------------------------------------------------
//
void CListBoxExt::DisableSingleClick()
    {
    _AKNTRACE_FUNC_ENTER;
    EnableHighlight( ETrue );
	
    if ( iListBox.iView->ViewRect() != TRect() )
        {
        // Set current item index highlighted if it is visible, otherwise
        // the first visible index
        TInt index = iListBox.iView->CurrentItemIndex(); 
        if ( !iListBox.iView->ItemIsVisible( index ) )
            {
            index = iListBox.iView->TopItemIndex();
            if ( iListBox.iView->ItemIsPartiallyVisible( index ) )
                {
                index++; 
                }    
            }
        TRAP_IGNORE( iListBox.UpdateHighlightL( index ) );
        }
    
    DisableItemSpecificMenu();
    if ( iItemActionMenu )
        {
        iItemActionMenu->RemoveCollection( *this );
        iItemActionMenu = NULL;
        }
    iSingleClickEnabled = EFalse;

    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CListBoxExt::EnableSingleClickL
// -----------------------------------------------------------------------------
//
void CListBoxExt::EnableSingleClickL()
    {
    _AKNTRACE_FUNC_ENTER;
    if ( !iLongTapDetector )
        {
        iLongTapDetector = CAknLongTapDetector::NewL( this );
        }
    if ( !iItemActionMenu )
        {
        iItemActionMenu = CAknItemActionMenu::RegisterCollectionL( 
            *this, &iListBox );
        iListBox.iListBoxFlags &= ( ~CEikListBox::EDisableItemSpecificMenu );
        }    
    iSingleClickEnabled = ETrue;
    EnableHighlight( EFalse );
    // iListBox.UpdateHighlightL( iListBox.iView->CurrentItemIndex() );
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CListBoxExt::DisableItemSpecificMenu
// -----------------------------------------------------------------------------
//
void CListBoxExt::DisableItemSpecificMenu()
    {
    _AKNTRACE_FUNC_ENTER;
    
    delete iLongTapDetector;
    iLongTapDetector = NULL;

    iListBox.iListBoxFlags |= CEikListBox::EDisableItemSpecificMenu;

    _AKNTRACE_FUNC_EXIT;
    }


// -----------------------------------------------------------------------------
// CListBoxExt::LongTapPointerEventL
// -----------------------------------------------------------------------------
//
void CListBoxExt::LongTapPointerEventL( const TPointerEvent& aPointerEvent )
    {
    if ( iSingleClickEnabled && iLongTapDetector && iItemActionMenu  )
        {
        // Send event on down only if item specific items were found. 
        // Long tap is also disabled if current item is not marked while
        // there are some marked items or marking mode is active.
        if ( ( !( ( iListBox.MarkingMode() || MarkedItems() )
            && !iListBox.View()->ItemIsSelected( iListBox.CurrentItemIndex() ) )
            || ( iListBox.iListBoxFlags & CEikListBox::EItemSpecificMenuAlwaysShown ) )
            && ( aPointerEvent.iType != TPointerEvent::EButton1Down
            || iItemActionMenu->InitMenuL() ) ) 
            {
            iLongTapDetector->PointerEventL ( aPointerEvent );
            }
        }
    }


// -----------------------------------------------------------------------------
// CListBoxExt::CancelLongTapL
// -----------------------------------------------------------------------------
//
void CListBoxExt::CancelLongTapL()
    {
    if ( iLongTapDetector && iLongTapDetector->IsActive() )
        {
        iLongTapDetector->CancelAnimationL();
        }
    }


// -----------------------------------------------------------------------------
// CListBoxExt::EnableHighlightWithKeyEventL
// -----------------------------------------------------------------------------
//
TBool CListBoxExt::EnableHighlightWithKeyEventL(
        TInt aTopItemIndex,
        const TKeyEvent& aKeyEvent,
        TEventCode aType )
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE( "aTopItemIndex is %d", aTopItemIndex );
    _AKNTRACE( "aKeyEvent.iCode is %d", aKeyEvent.iCode );
    _AKNTRACE( "aType is %d", aType );
    TBool consumeKey( EFalse );
    // With single click first key event enables highlight
    if ( iListBox.iItemDrawer->Flags()
            & CListItemDrawer::ESingleClickDisabledHighlight
            && iSingleClickEnabled )
        {
        TBool enableHighlight( EFalse );
        // Normal case: up, down, enter, msk pressed
        if ( aKeyEvent.iCode == EKeyUpArrow
                || aKeyEvent.iCode == EKeyDownArrow
                || aKeyEvent.iCode == EKeyEnter 
                || aKeyEvent.iCode == EKeyOK )
            {
            consumeKey = ETrue;
            enableHighlight = ETrue;
            }
        else if ( aType == EEventKeyDown
                && aKeyEvent.iScanCode == EStdKeyDevice3 )
            {
            iFlags |= EMSKKeyDownEventReceived;
            }
        // Msk pressed when MSK not visible
        else if ( iFlags & EMSKKeyDownEventReceived
                && aType == EEventKeyUp
                && aKeyEvent.iScanCode == EStdKeyDevice3 )
            {
            iFlags &= ( ~EMSKKeyDownEventReceived );
            enableHighlight = ETrue;
            }
        // Handle also left and right when grid in use.
        else if ( iItemsInSingleLine > 1
                && ( aKeyEvent.iCode == EKeyLeftArrow 
                || aKeyEvent.iCode == EKeyRightArrow ) )
            {
            consumeKey = ETrue;
            enableHighlight = ETrue;
            }
        if ( enableHighlight )
            {
            if ( iListBox.iView->ItemIsPartiallyVisible( aTopItemIndex ) )
                {
                aTopItemIndex++;
                }          
            // Enable marquee
            if ( iListBox.iItemDrawer->Flags() 
                    & CListItemDrawer::EDisableMarquee )
                {
                iListBox.iItemDrawer->
                    ClearFlags( CListItemDrawer::EDisableMarquee );
                }           
            EnableHighlight( ETrue );
            iListBox.UpdateHighlightL( aTopItemIndex );
            }
        }
    _AKNTRACE_FUNC_EXIT;
    return consumeKey;
    }


// -----------------------------------------------------------------------------
// CListBoxExt::MarkedItems
// -----------------------------------------------------------------------------
//
TBool CListBoxExt::MarkedItems() const
    {
    return ( iListBox.iListBoxFlags & CEikListBox::ES60StyleMarkable
            || iListBox.iListBoxFlags & CEikListBox::EMultipleSelection )
            && iListBox.iView && iListBox.SelectionIndexes()->Count() > 0;
    }


// -----------------------------------------------------------------------------
// CListBoxExt::IgnorePointerEventsUntilUp
// -----------------------------------------------------------------------------
//
TBool CListBoxExt::IgnorePointerEventsUntilUp()
    {
    _AKNTRACE_FUNC_ENTER;
    
    // Pointer event ignore must be done for the window-owning
    // control or it doesn't have any effect!
    CCoeControl* windowOwningControl = &iListBox;
        
    while ( windowOwningControl && !windowOwningControl->OwnsWindow() )
        {
        windowOwningControl = windowOwningControl->Parent();
        }

    if ( windowOwningControl )
        {
        windowOwningControl->IgnoreEventsUntilNextPointerUp();   
        }
    _AKNTRACE_FUNC_EXIT;
    return ( windowOwningControl != NULL );
    }


// -----------------------------------------------------------------------------
// CListBoxExt::StartLongPressTimerL
// -----------------------------------------------------------------------------
//
void CListBoxExt::StartLongPressTimerL()
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iLongPressTimer )
        {
        if ( iLongPressTimer->IsActive() )
            {
            iLongPressTimer->Cancel();
            }

        iLongPressTimer->Start( KLongPressInterval, KLongPressInterval,
            TCallBack( ReportLongPressL, this ) );
        }
    _AKNTRACE_FUNC_EXIT;
    }

// -----------------------------------------------------------------------------
// CListBoxExt::ReportLongPressL
// -----------------------------------------------------------------------------
//
TInt CListBoxExt::ReportLongPressL( TAny* aThis )
    {
    _AKNTRACE_FUNC_ENTER;
    static_cast<CListBoxExt*>( aThis )->DoHandleLongPressL();
    _AKNTRACE_FUNC_EXIT;
    return 0;
    }

TBool CListBoxExt::IsInIgnoreRect( const TPoint& aPoint ) const
    {
    TInt offset = AknLayoutScalable_Avkon::aid_value_unit2().LayoutLine().iW / 5;
    TRect rect( iLastPoint.iX - offset, iLastPoint.iY - offset, 
                iLastPoint.iX + offset, iLastPoint.iY + offset ); 
    return rect.Contains( aPoint );
    }
    
TBool CListBoxExt::IsInHandleAllPointEventArray(const TInt aIndex)  
    {
    return iMutiTappingItems.FindInOrder( aIndex ) != KErrNotFound;
    }

// -----------------------------------------------------------------------------
// CListBoxExt::DoHandleLongPressL
// -----------------------------------------------------------------------------
//
void CListBoxExt::DoHandleLongPressL()
    {
    _AKNTRACE_FUNC_ENTER;
    iSelectionModeEnabled = ETrue;
    if ( iLongPressTimer && iLongPressTimer->IsActive() )
        {
        iLongPressTimer->Cancel();
        }
    iListBox.ChangeSelectionMode( ETrue );
    _AKNTRACE_FUNC_EXIT;
    }


void CListBoxExt::CheckCreateBufferL()
    {
    if (!iBuffer)
        iBuffer=CMatchBuffer::NewL(CMatchBuffer::EMinimal);
    }

CMatchBuffer* CListBoxExt::Buffer() const
    {
    return iBuffer;
    }

void CListBoxExt::CreateMatchBufferL()
    {
    _AKNTRACE_FUNC_ENTER;
    if (iBuffer==NULL)
        iBuffer=CMatchBuffer::NewL(CMatchBuffer::EFull);
    else if (iBuffer->iMatchBuffer==NULL)
        iBuffer->ConstructMatchBufferL();
    _AKNTRACE_FUNC_EXIT;
    }

TBool CListBoxExt::IsVisible() const
    {
    return iListBox.IsVisible();
    }

TBool CListBoxExt::IsMatchBuffer() const
    {
    return (iBuffer && iBuffer->iMatchBuffer);
    }

void CListBoxExt::SetReasonForFocusLost(CEikListBox::TReasonForFocusLost aReasonForFocusLost)
    {
    iReasonForFocusLost = aReasonForFocusLost;
    }
 
TInt CListBoxExt::QwertyModeChangeNotification(TAny* aObj)
    {
    _AKNTRACE_FUNC_ENTER;
    if (aObj != NULL)
        {
        static_cast<CListBoxExt*>(aObj)->HandleQwertyModeChangeNotification();
        _AKNTRACE_FUNC_EXIT;
        return KErrNone;
        }
    else
        {
        _AKNTRACE_FUNC_EXIT;
        return KErrArgument;
        }
    }
    
void CListBoxExt::HandleQwertyModeChangeNotification()
    {
    TInt value = 0;
    iQwertyModeStatusProperty.Get(value);
    iQwertyMode = value;
    } 


void CListBoxExt::CreateMSKObserverL(CEikButtonGroupContainer *aCba, CEikListBox *aListBox)
    {
    _AKNTRACE_FUNC_ENTER;
    RemoveMSKObserver(aListBox); // only one observer can be set at a time
    iMSKCommandObserver = new(ELeave)CLBMSKCommandObserver(aCba, aListBox);
    iMSKButtonGroupAlive = ETrue;
    // if UpdateMSKCommandOpserver fails (there already is MSK observer set),
    // iMSKButtonGroupAlive will be set EFalse
    aCba->UpdateMSKCommandObserver(aListBox, iMSKCommandObserver);
    _AKNTRACE_FUNC_EXIT;
    }

void CListBoxExt::RemoveMSKObserver(CEikListBox *aListBox)
    {
    _AKNTRACE_FUNC_ENTER;
    if (iMSKCommandObserver)
        {
        if (iMSKButtonGroupAlive)
            {
            STATIC_CAST(CLBMSKCommandObserver*,iMSKCommandObserver)->iCba->UpdateMSKCommandObserver(aListBox, NULL);
            }
        delete iMSKCommandObserver;
        iMSKCommandObserver = NULL;
        }
    _AKNTRACE_FUNC_EXIT;
    }


// CEikListBoxExt::CSubscriber

CListBoxExt::CSubscriber::CSubscriber(TCallBack aCallBack, RProperty& aProperty)
    : CActive(EPriorityNormal), iCallBack(aCallBack), iProperty(aProperty)
    {
    CActiveScheduler::Add(this);
    }

CListBoxExt::CSubscriber::~CSubscriber()
    {
    Cancel();
    }

void CListBoxExt::CSubscriber::SubscribeL()
    {
    if (!IsActive())
        {
        iProperty.Subscribe(iStatus);
        SetActive();
        }
    }

void CListBoxExt::CSubscriber::StopSubscribe()
    {
    Cancel();
    }
    
void CListBoxExt::CSubscriber::RunL()
    {
    if (iStatus.Int() == KErrNone)
        {
        iCallBack.CallBack();
        SubscribeL();
        }
    }
    
void CListBoxExt::CSubscriber::DoCancel()
    {
    iProperty.Cancel();
    }

// CEikListBox

CEikListBox::TReasonForFocusLost CListBoxExt::ReasonForFocusLost() const
    {
    return iReasonForFocusLost;
    }

void CListBoxExt::AddItemChangeObserverL(
        MListBoxItemChangeObserver* aObserver )
    {
    iItemChangeObservers.AppendL( aObserver );
    }

TBool CListBoxExt::RemoveItemChangeObserver(
        MListBoxItemChangeObserver* aObserver )
    {
    TInt index = iItemChangeObservers.Find( aObserver );
    if( KErrNotFound == index )
        {
        return EFalse;
        }

    iItemChangeObservers.Remove( index );
    return ETrue;
    }

void CListBoxExt::FireItemChange(CEikListBox* aListBox)
    {
    TInt count = iItemChangeObservers.Count();
    for( int i=0; i < count; i++ )
        {
        iItemChangeObservers[i]->ListBoxItemsChanged(aListBox);
        }
    }

void CListBoxExt::SetUpdateScrollBarsColors(TBool aUpdate)
    {
    if (aUpdate)
        iFlags |= EUpdateScrollBarsColors;
    else
        iFlags &= ~EUpdateScrollBarsColors;
    }

TBool CListBoxExt::UpdateScrollBarsColors() const
    {
    return (iFlags&EUpdateScrollBarsColors);
    }

void CListBoxExt::CheckScrollBarVisibility()
    {
    // Kinetic scrolling is disabled if scrollbar is not visible
    if ( iListBox.iSBFrame )
        {
        TBool allowScrolling( iListBox.iSBFrame->ScrollBarVisibility(
            CEikScrollBar::EVertical ) != CEikScrollBarFrame::EOff );
                
        iScrollingDisabled = !allowScrolling;
        }   
    }
    
void CListBoxExt::HandleNotifyInt(TUint32 aId, TInt aNewValue)
    {
    if (aId == KAknFepHashKeySelection)
        {
        iAknFepHashKeySelection = (TBool)aNewValue;
        }
    }


// ---------------------------------------------------------------------------
// Static callback function for the highlight timer. This should draw
// the highlight to the correct item and send the pen down event to the
// listbox observer.
// ---------------------------------------------------------------------------
//
TInt CListBoxExt::HighlightTimerCallback( TAny* aPtr )
    {
    _AKNTRACE_FUNC_ENTER;
    CListBoxExt* me = static_cast<CListBoxExt*>( aPtr );

    if ( me )
        {
        if ( me->iSingleClickEnabled )
            {
            me->EnableHighlight( ETrue, ETrue );
            }

        TRAP_IGNORE( me->iListBox.UpdateHighlightL(
                         me->iLastDownTappedItem ) );
        
        me->ImmediateFeedback( me->iFeedbackType, 
                               TTouchFeedbackType(ETouchFeedbackVibra | ETouchFeedbackAudio),
                               TPointerEvent() ); 
        
        me->CancelHighlightTimer();
        }
    _AKNTRACE_FUNC_EXIT;
    return 0;
    }


// ---------------------------------------------------------------------------
// Starts the highlight timer.
// ---------------------------------------------------------------------------
//
void CListBoxExt::StartHighlightTimer()
    {
    _AKNTRACE_FUNC_ENTER;
    CancelHighlightTimer();

    TTimeIntervalMicroSeconds32 timeout(
        iPhysics->HighlightTimeout() * 1000 );
    iHighlightTimer->Start( 
        timeout,
        timeout,
        TCallBack( CListBoxExt::HighlightTimerCallback, this ) );
    _AKNTRACE_FUNC_EXIT;
    }


// ---------------------------------------------------------------------------
// Cancels the highlight timer and the delayed functions to be run upon
// its completion.
// ---------------------------------------------------------------------------
//
void CListBoxExt::CancelHighlightTimer()
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iHighlightTimer )
        {
        iHighlightTimer->Cancel();
        }
    iReportDelayedPenDown = EFalse;
    iDelayedMultiselection = EFalse;
    _AKNTRACE_FUNC_EXIT;
    }


// ---------------------------------------------------------------------------
// Checks if the highlight timer is currently running.
// ---------------------------------------------------------------------------
//
TBool CListBoxExt::HighlightTimerActive() const
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE_FUNC_EXIT;
    return ( iHighlightTimer && iHighlightTimer->IsActive() );
    }


// ---------------------------------------------------------------------------
// CListBoxExt::ViewPositionChanged
// ---------------------------------------------------------------------------
//
void CListBoxExt::ViewPositionChanged( const TPoint& aNewPosition,
                                       TBool aDrawNow,
                                       TUint /*aFlags*/ )
    {
    _AKNTRACE_FUNC_ENTER;
    TInt delta = iViewPosition.iY - aNewPosition.iY;

#ifdef _DEBUG
    _LIT( KDMsg, "CListBoxExt::ViewPositionChanged, delta = %d, aDrawNow = %d" );
    RDebug::Print( KDMsg, delta, aDrawNow );
#endif // _DEBUG

    iListBox.ScrollView( delta, aDrawNow );
    iViewPosition = aNewPosition;
    _AKNTRACE_FUNC_EXIT;
    }
    

// ---------------------------------------------------------------------------
// CListBoxExt::PhysicEmulationEnded
// ---------------------------------------------------------------------------
//
void CListBoxExt::PhysicEmulationEnded()
    {
    _AKNTRACE_FUNC_ENTER;    
    if ( iScrolling )
        {
        // currently, this is the only way to fix ou1cimx1#375869
        // iViewPosision is changed but we can't provent that
        if ( iListBox.iView->TopItemIndex() == 0 
             && iListBox.iView->ItemOffsetInPixels() > 0 )
            {
            iListBox.ScrollView( -iListBox.iView->ItemOffsetInPixels(), ETrue );
            }        
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
        iListBox.SuspendEffects( EFalse );
#endif // RD_UI_TRANSITION_EFFECTS_LIST
        TRAP_IGNORE( iListBox.ReportListBoxEventL(
                         MEikListBoxObserver::EEventFlickStopped ) );
        }
    
    iScrolling = EFalse;
    iListBox.iView->SetScrolling( iScrolling );
    _AKNTRACE_FUNC_EXIT;
    }


// ---------------------------------------------------------------------------
// CListBoxExt::InitPhysicsL
// ---------------------------------------------------------------------------
//
void CListBoxExt::InitPhysicsL()
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iPhysics )
        {
        // calculate view center based on CEikListBoxView::iTopItemIndex
        TInt topItemIndex = iListBox.iView->TopItemIndex();
        TInt itemHeight = iListBox.iView->ItemHeight();
        TInt numberOfItems = iListBox.iModel->NumberOfItems();

        TSize viewSize( iListBox.iView->ViewRect().Size() );
        TSize worldSize( viewSize.iWidth, itemHeight * numberOfItems );
        
        // grid has several items in one line
        if ( iItemsInSingleLine > 1 )
            {
            worldSize.iHeight = 
                itemHeight * ( numberOfItems / iItemsInSingleLine );
            
            // handle non-full grid row
            if ( numberOfItems % iItemsInSingleLine )
                {
                worldSize.iHeight += itemHeight;
                }
            }
            
        // Reset offset if view's size has changed - this is needed if e.g.
        // HandleResourceChange is overridden by a derived implementation.
        if ( viewSize != iViewSize && iViewSize != TSize( 0, 0 ) )
            {
            iListBox.iView->SetItemOffsetInPixels( 0 );
            }

        TPoint viewCenter( viewSize.iWidth / 2, ( topItemIndex / iItemsInSingleLine ) * itemHeight - iListBox.iView->ItemOffsetInPixels() + ( viewSize.iHeight / 2 ) );

        // Make sure that world's size is always at least view size.
        worldSize.iHeight = Max( worldSize.iHeight, viewSize.iHeight );

        iPhysics->InitPhysicsL( worldSize, viewSize, EFalse );
        
        iWorldSize = worldSize;
        iViewSize = viewSize;
        iViewPosition = viewCenter;

#ifdef _DEBUG
        RDebug::Print( _L( "CListBox::InitPhysicsL, iViewSize = %d, %d" ), iViewSize.iWidth, iViewSize.iHeight );
        RDebug::Print( _L( "CListBox::InitPhysicsL, iViewPosition = %d, %d" ), iViewPosition.iX, iViewPosition.iY );
        RDebug::Print( _L( "CListBox::InitPhysicsL, verticalOffset = %d" ), iListBox.iView->ItemOffsetInPixels() );
#endif // _DEBUG
        iPrevTopItemIndex = iListBox.iView->TopItemIndex();
        iListBottomLimit = worldSize.iHeight;
        }
    _AKNTRACE_FUNC_EXIT;
    }

// ---------------------------------------------------------------------------
// CListBoxExt::MovePhysicsCursorL
// ---------------------------------------------------------------------------
//
TBool CListBoxExt::MovePhysicsCursorL(CListBoxView::TCursorMovement aCursorMovement, 
		                             CListBoxView::TSelectionMode aSelectionMode)
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE( "aCursorMovement = %d, aSelectionMode = %d", 
         aCursorMovement, aSelectionMode );    
    if ( !iPhysics || iScrollingDisabled )
        {
        _AKNTRACE_FUNC_EXIT;
        return EFalse;
        }
                    
    InitPhysicsL();
    TInt curViewPosY = iViewPosition.iY;
    TInt worldHeight = iWorldSize.iHeight;
    TInt viewHeight = iViewSize.iHeight;
    TInt offsetHeight = curViewPosY - ( viewHeight / 2 );
    TInt deltaPixels = 0;
    switch (aCursorMovement)
        {
        case CListBoxView::ECursorNextScreen:
            {
            if ( viewHeight > worldHeight - offsetHeight - viewHeight )
                {
                if ( worldHeight - offsetHeight - viewHeight > 0 )
                    {
                    iListBox.iView->MoveCursorL(CListBoxView::ECursorLastItem, aSelectionMode);
                    }
                break;
                }
            deltaPixels = viewHeight;
            break;
            }
        case CListBoxView::ECursorPrevScreen:
            {
            if ( viewHeight > offsetHeight )
                {
                if ( offsetHeight > 0 )
                    {
                    iListBox.iView->MoveCursorL(CListBoxView::ECursorFirstItem, aSelectionMode);
                    }
                break;
                }
            deltaPixels = -viewHeight;
            break;
            }
        default:
            {
            _AKNTRACE_FUNC_EXIT;
            return EFalse;
            }
        }
   
    if ( deltaPixels != 0 )
        {	
        TPoint newPosition( iViewPosition.iX,
                        deltaPixels + curViewPosY );
        ViewPositionChanged( newPosition );
        }
    _AKNTRACE_FUNC_EXIT;
    return ETrue;
    }

// ---------------------------------------------------------------------------
// CListBoxExt::ImmediateFeedback
// ---------------------------------------------------------------------------
//
void CListBoxExt::ImmediateFeedback( TTouchLogicalFeedback aFeedback,
                                     TTouchFeedbackType aFeedbackType,
                                     const TPointerEvent& aPointerEvent )
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iFeedback )
        {
        iFeedback->InstantFeedback( &iListBox, aFeedback, aFeedbackType, aPointerEvent );
        }
    _AKNTRACE_FUNC_EXIT;
    }

// ---------------------------------------------------------------------------
// Checks whether or not tactile feedback should be given on a pointer
// up event.
// ---------------------------------------------------------------------------
//
TBool CListBoxExt::FeedbackEnabledOnUpEvent()
    {
    _AKNTRACE_FUNC_ENTER;
    TBool enabled( EFalse );
    
    // As there's no pressed down highlight in single click enabled lists,
    // the iLastDownTappedItem is used to track whether or not the pointer
    // up event happened inside the same list item as the pointer down event.
    // Feedback should not be given if the pointer up is received outside of
    // the item that received the pointer down event, or in cases when the
    // list has been dragged or flicked between the pointer down and pointer
    // up events.
    if ( ( iListBox.iItemDrawer->Flags() & CListItemDrawer::EPressedDownState
        || ( iSingleClickEnabled && iLastDownTappedItem != KErrNotFound ) ) &&
        !iFlickStopped )
        {
        enabled = ETrue;
        }

    _AKNTRACE_FUNC_EXIT;
    return enabled;
    }

// ---------------------------------------------------------------------------
// CListBoxExt::SetFlickOngoing
// ---------------------------------------------------------------------------
//
void CListBoxExt::SetFlickOngoing( TBool aFlickOngoing )
    {
    iFlickOngoing = aFlickOngoing;
    }

// ---------------------------------------------------------------------------
// CListBoxExt::SetPanningOngoing
// ---------------------------------------------------------------------------
//
void CListBoxExt::SetPanningOngoing( TBool aPanningOngoing )
    {
    iPanningOngoing = aPanningOngoing;
    }

// ---------------------------------------------------------------------------
// CListBoxExt::FlickOrPanningOngoing
// ---------------------------------------------------------------------------
//
TBool CListBoxExt::FlickOrPanningOngoing()
    {
    return ( iFlickOngoing | iPanningOngoing );
    }

// ---------------------------------------------------------------------------
// CListBoxExt::ListBottomLimit
// ---------------------------------------------------------------------------
//
TInt CListBoxExt::ListBottomLimit()
    {
    return iListBottomLimit;
    }

//
// class CEikListBox
//

const TInt KEikListBoxHNudgeSizeAsFractionOfViewRectWidth = 20; 
// const TInt KEikListBoxBackgroundColor = 15;      later, this will be a data member of the listbox  
const TInt KEikListBoxItemVGap = 6; // to allow a box to be drawn around each item
const TInt KEikListBoxInterItemGap = 2;

GLDEF_C void Panic(TEikListBoxPanic aPanic)
    {
    _LIT(KPanicCat,"EIKON-LISTBOX");
    User::Panic(KPanicCat,aPanic);
    }

EXPORT_C CEikListBox::CEikListBox()
/*DFRD can setup 4 margins (top, bottom, left, right) by setting iHorizontalMargin
to KLafListboxUseLafHorizMargins and iVerticalMargin to KLafListboxUseLafVertMargins.
The DFRD can also use 3 margins by setting either of these 2 values (iHorizonatalMargin
or iVerticalMargin) to another integer.  The application developer can only set 2
margins; iHorizontalMargin and iVerticalMargin*/
    :   iItemEditor(NULL)
    {
    _AKNTRACE_FUNC_ENTER;
    LafListBox::GetDefaultBorder(iBorder);
    iMargins = LafListBox::Margins();

    iItemHeight = iEikonEnv->NormalFont()->HeightInPixels() + KEikListBoxItemVGap;
    iBackColor = iEikonEnv->Color(EColorControlBackground);

    SetComponentsToInheritVisibility(EFalse);
    AKNTASHOOK_ADD( this, "CEikListBox" );
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::SetItemsInSingleLine( TInt aItems )
    {
    if ( iListBoxExt )
        {
        iListBoxExt->iItemsInSingleLine = aItems;
        }
    }


// -----------------------------------------------------------------------------
// CEikListBox::ItemsInSingleLine
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CEikListBox::ItemsInSingleLine() const
    {
    if ( iListBoxExt )
        {
        return iListBoxExt->iItemsInSingleLine;
        }
    
    return 1;
    }

    
EXPORT_C void CEikListBox::UpdateViewColors()
    {
    _AKNTRACE_FUNC_ENTER;
    if(!iView)
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }

    if(IsDimmed())
        {
        iView->SetTextColor(iEikonEnv->ControlColor(EColorControlDimmedText,*this));
        iView->SetBackColor(iEikonEnv->ControlColor(EColorControlDimmedBackground,*this));
        iView->SetMatcherCursorColor(iEikonEnv->ControlColor(EColorControlHighlightBackground,*this));
        }
    else
        {
        iView->SetTextColor(iEikonEnv->ControlColor(EColorControlText,*this));
        iView->SetBackColor(iEikonEnv->ControlColor(EColorControlBackground,*this));
        iView->SetMatcherCursorColor(iEikonEnv->ControlColor(EColorControlDimmedHighlightBackground,*this));
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::UpdateItemDrawerColors()
    {
    _AKNTRACE_FUNC_ENTER;
    if(!iItemDrawer)
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }

    if(IsDimmed())
        {
        iItemDrawer->SetTextColor(iEikonEnv->ControlColor(EColorControlDimmedText,*this));
        iItemDrawer->SetHighlightedTextColor(iEikonEnv->ControlColor(EColorControlDimmedHighlightText,*this));
        iItemDrawer->SetDimmedTextColor(iEikonEnv->ControlColor(EColorControlDimmedText,*this));
        iItemDrawer->SetBackColor(iEikonEnv->ControlColor(EColorControlDimmedBackground,*this));
        iItemDrawer->SetHighlightedBackColor(iEikonEnv->ControlColor(EColorControlDimmedHighlightBackground,*this));
        iItemDrawer->SetDimmedBackColor(iEikonEnv->ControlColor(EColorControlDimmedBackground,*this));
        }
    else
        {
        iItemDrawer->SetTextColor(iEikonEnv->ControlColor(EColorControlText,*this));
        iItemDrawer->SetHighlightedTextColor(iEikonEnv->ControlColor(EColorControlHighlightText,*this));
        iItemDrawer->SetDimmedTextColor(iEikonEnv->ControlColor(EColorControlDimmedText,*this));
        iItemDrawer->SetBackColor(iEikonEnv->ControlColor(EColorControlBackground,*this));
        iItemDrawer->SetHighlightedBackColor(iEikonEnv->ControlColor(EColorControlHighlightBackground,*this));
        iItemDrawer->SetDimmedBackColor(iEikonEnv->ControlColor(EColorControlBackground,*this));
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::FireItemChange()
    {
    if( iListBoxExt )
        {
        iListBoxExt->FireItemChange( this );
        }
    }

EXPORT_C CEikListBox::~CEikListBox()
    {
    _AKNTRACE_FUNC_ENTER;
    AKNTASHOOK_REMOVE();
    if (iCoeEnv && iEikonEnv && iAvkonEnv) 
        iAvkonEnv->RemoveCbaObserver();

    if (iListBoxExt)
        {
        iListBoxExt->RemoveMSKObserver(this);    
        delete iListBoxExt;
        iListBoxExt = NULL;
        }
        
    delete iSBFrame;
    
    if (!(iListBoxFlags & EKeepModel))
        delete iModel;
    
    if (iView)
        delete iView;
    else
        delete iItemDrawer;
    
    if (iLaunchingButton)
        {
        TPointerEvent event;
        event.iType=TPointerEvent::EButton1Up;
        event.iModifiers=0;
        event.iPosition=iLaunchingButton->Position();
        TRAP_IGNORE(iLaunchingButton->HandlePointerEventL(event));
        }
    
    ResetItemEditor();
    _AKNTRACE_FUNC_EXIT;
    }

void CEikListBox::InformMSKButtonGroupDeletion()
    {
    if (iListBoxExt)
        {
        iListBoxExt->iMSKButtonGroupAlive = EFalse;
        }
    }
    
EXPORT_C TBool CEikListBox::ItemExists(TInt aItemIndex) const
    {
    return ((aItemIndex >= 0) && (aItemIndex < iModel->NumberOfItems()));
    }

EXPORT_C void CEikListBox::RestoreCommonListBoxPropertiesL(TResourceReader& aReader)
    {
    _AKNTRACE_FUNC_ENTER;
    aReader.ReadInt8(); // version
    iListBoxFlags = aReader.ReadInt32();  
        
    iRequiredHeightInNumOfItems = aReader.ReadInt16();

    if (! (iListBoxFlags & EPageAtOnceScrolling))
        { // no loop scroll for viewers
        iListBoxFlags |= ELoopScrolling; // All lists will have loop scrolling.
        }

    if (iListBoxFlags & EIncrementalMatching)
        CreateMatchBufferL();
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C MListBoxModel* CEikListBox::Model() const
    {
    return iModel;
    }

EXPORT_C CListBoxView* CEikListBox::View() const
    {
    return iView;
    }

EXPORT_C void CEikListBox::CreateMatchBufferL()
    {
    CheckCreateExtensionL();
    iListBoxExt->CreateMatchBufferL();
    }

EXPORT_C void CEikListBox::SetItemHeightL(TInt aHeight)
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE( "aHeight = %d", aHeight );
    // won't actually leave if the horizontal/vertical scrollbars have both been turned off
    __ASSERT_ALWAYS((aHeight > 0), Panic(EEikPanicListBoxInvalidItemHeightSpecified));
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    TRect lastViewRect( iView->ViewRect() );
#endif
    iItemHeight = aHeight;
    TRect clientRect = iBorder.InnerRect(Rect());
    iView->SetItemHeight(aHeight);
    SetViewRectFromClientRect(clientRect);
    HandleViewRectSizeChangeL();

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    if( iView->ViewRect() != lastViewRect )
        {
        MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( iView->iGc );
        if ( transApi )
            {
            transApi->Remove( MAknListBoxTfxInternal:: EListEverything );
            }
        }
#endif
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C TInt CEikListBox::ItemHeight() const
    {
    return iItemHeight;
    }

EXPORT_C TInt CEikListBox::CalcWidthBasedOnNumOfChars(TInt aNumOfChars) const
    {
    return CalcWidthBasedOnRequiredItemWidth(aNumOfChars * iEikonEnv->NormalFont()->MaxNormalCharWidthInPixels());
    }

EXPORT_C TInt CEikListBox::CalcWidthBasedOnRequiredItemWidth(TInt aTextWidthInPixels) const
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE("aTextWidthInPixels = %d", aTextWidthInPixels);    
    TInt width = aTextWidthInPixels;
    if (iItemDrawer->Flags()&CListItemDrawer::EDrawMarkSelection)
        {
        width += iItemDrawer->MarkColumn() + iItemDrawer->MarkGutter();
        }
    width += (LafListBox::InnerGutter() + ListBoxMargins().iLeft + ListBoxMargins().iRight);
    width += iBorder.SizeDelta().iWidth;
    if (iSBFrame)
        {
#if COMMENTED_FOR_SERIES60_BECAUSE_SCROLLBAR_BREADTH_IS_NONZERO
        if (iSBFrame->VScrollBarVisibility()!=CEikScrollBarFrame::EOff)
            width += CEikScrollBar::DefaultScrollBarBreadth();
#endif
        }
    _AKNTRACE( "width = %d", width );    
    _AKNTRACE_FUNC_EXIT;
    return width;
    }

EXPORT_C TInt CEikListBox::CalcHeightBasedOnNumOfItems(TInt aNumOfItems) const
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE( "aNumOfItems = %d", aNumOfItems );      
    TInt height;
    height = (aNumOfItems * iItemHeight);
    height += (ListBoxMargins().iTop + ListBoxMargins().iBottom);
    height += iBorder.SizeDelta().iHeight;
    if (iSBFrame)
        {
        if (iSBFrame->ScrollBarVisibility(CEikScrollBar::EHorizontal)!=CEikScrollBarFrame::EOff)
            height += CEikScrollBar::DefaultScrollBarBreadth();
        }
    _AKNTRACE( "height = %d", height );  
    _AKNTRACE_FUNC_EXIT;
    return height;
    }

EXPORT_C TSize CEikListBox::MinimumSize()
    {
    _AKNTRACE_FUNC_ENTER;
    TSize size;
    TSize minCellSize(iItemDrawer->MinimumCellSize());
    size.iWidth = minCellSize.iWidth + ListBoxMargins().iLeft + ListBoxMargins().iRight;
    size.iHeight = (ListBoxMargins().iTop + ListBoxMargins().iBottom) + (iRequiredHeightInNumOfItems * minCellSize.iHeight);
    if ((!(iListBoxFlags & EScrollBarSizeExcluded)) && iSBFrame)
        {
        if (iSBFrame->VScrollBarVisibility()!=CEikScrollBarFrame::EOff)
            size.iWidth += CEikScrollBar::DefaultScrollBarBreadth();
        if (iSBFrame->ScrollBarVisibility(CEikScrollBar::EHorizontal)!=CEikScrollBarFrame::EOff)
            size.iHeight += CEikScrollBar::DefaultScrollBarBreadth();
        }
    size += iBorder.SizeDelta();
    _AKNTRACE( "width = %d, height = %d", size.iWidth, size.iHeight ); 
    _AKNTRACE_FUNC_EXIT;
    return size;
    }

EXPORT_C TSize CEikListBox::CalcSizeInPixels(TInt aWidthAsNumOfChars, TInt aHeightAsNumOfItems) const
    {
    return TSize(CalcWidthBasedOnNumOfChars(aWidthAsNumOfChars), CalcHeightBasedOnNumOfItems(aHeightAsNumOfItems));
    }

EXPORT_C CEikScrollBarFrame* CEikListBox::CreateScrollBarFrameL(TBool aPreAlloc)
    {
    return CreateScrollBarFrameL(aPreAlloc, EFalse);
    }

EXPORT_C void CEikListBox::HandleViewRectSizeChangeL()
    {
    _AKNTRACE_FUNC_ENTER;
    iView->CalcBottomItemIndex();
    iView->CalcDataWidth();
    TInt currentItemIndex = iView->CurrentItemIndex();
    TInt totalItems = iModel->NumberOfItems();
    
    if ( ItemExists(currentItemIndex) )
        {
        TInt topItemIndex( iView->TopItemIndex() );
        TInt numberOfItems = iView->NumberOfItemsThatFitInRect( iView->ViewRect() );    
        TInt newTopItemIndex( KEikListBoxInvalidIndex ); 

        // Current item not visible or current item is the last item (not fully visible)
        if ( !iView->ItemIsVisible(currentItemIndex)
        	|| iListBoxExt && iListBoxExt->iPhysics 
        	&& currentItemIndex == ( topItemIndex + numberOfItems - 1 ) )
            {
            if ( iListBoxExt && iListBoxExt->iSingleClickEnabled )
                {
                TInt offset = (iListBoxExt->iWorldSize.iHeight / 2)
                        - iListBoxExt->iViewPosition.iY;
                TInt itemsInRect =
                        iView->NumberOfItemsThatFitInRect( iView->ViewRect() );

                if ( ( iListBoxExt->CollectionState()
                        & MAknCollection::EStateHighlightVisible )
                      || ( ItemsInSingleLine()
                              && ( totalItems <= itemsInRect )
                              && ( offset != 0 ) ) )
                    {
                    newTopItemIndex = iView->CalcNewTopItemIndexSoItemIsVisible( currentItemIndex );
                    }
                else
                    {
                    newTopItemIndex = iView->CalcNewTopItemIndexSoItemIsVisible( topItemIndex );
                    }
                }
            else
                {
                newTopItemIndex = iView->CalcNewTopItemIndexSoItemIsVisible( currentItemIndex );
                }
            }
        else
            {
            // recalculates top index of list when mode be changed            
            if ( (totalItems - topItemIndex) < numberOfItems )
                {
                newTopItemIndex = Max( 0, totalItems - numberOfItems );
                }
            }

        if ( newTopItemIndex > KEikListBoxInvalidIndex 
             && newTopItemIndex < totalItems )
        	{
        	iView->SetTopItemIndex( newTopItemIndex );
            }
        if ( iListBoxExt && iListBoxExt->iPhysics )
            {
            iListBoxExt->InitPhysicsL();
            }
        }
    UpdateScrollBarsL();
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::SizeChanged()
    {
    _AKNTRACE_FUNC_ENTER;
    TRect clientRect = iBorder.InnerRect(Rect());
    SetViewRectFromClientRect(clientRect);
    TRAP_IGNORE(HandleViewRectSizeChangeL());
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C TInt CEikListBox::CountComponentControls() const
    {
    TInt count=CEikBorderedControl::CountComponentControls();
    if (iSBFrame && (iSBFrameOwned == ENotOwnedExternally))
        {
        if(iSBFrame->VerticalScrollBar()) 
           { 
           count+=iSBFrame->CountComponentControls(); 
           }
        }
    return count;
    }

EXPORT_C CCoeControl* CEikListBox::ComponentControl(TInt aIndex) const
    {
    TInt baseCount=CEikBorderedControl::CountComponentControls();
    if (aIndex<baseCount)
        {
        return CEikBorderedControl::ComponentControl(aIndex);
        }
    aIndex-=baseCount;
    if( iSBFrame && iSBFrame->VerticalScrollBar() ) 
        { 
        return iSBFrame->ComponentControl(aIndex); 
        } 
    else
        {
        return NULL;
        }
    }

EXPORT_C void CEikListBox::SetViewRectFromClientRect(const TRect& aClientRect)
    {
    _AKNTRACE_FUNC_ENTER;
    TRect rect(aClientRect);
    rect.SetRect(rect.iTl.iX + ListBoxMargins().iLeft, rect.iTl.iY + ListBoxMargins().iTop,
        rect.iBr.iX - ListBoxMargins().iRight, rect.iBr.iY - ListBoxMargins().iBottom);

    if ( iListBoxExt && iListBoxExt->iPhysics )
        {
        iViewRectHeightAdjustment = 0;
        iView->SetViewRect(rect);
        }
    else
        {
        iItemHeight = iView->ItemSize().iHeight;
        iViewRectHeightAdjustment = AdjustRectHeightToWholeNumberOfItems(rect);
        iView->SetViewRect(rect);
        }
        
    if ( iListBoxExt && 
         (iListBoxExt->iViewSize != rect.Size() ))
        {
        iListBoxExt->iViewSize = rect.Size();
        }    
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::RestoreClientRectFromViewRect(TRect& aClientRect) const
    {
    _AKNTRACE_FUNC_ENTER;
    aClientRect=iView->ViewRect();
    aClientRect.SetRect(aClientRect.iTl.iX - ListBoxMargins().iLeft, aClientRect.iTl.iY - ListBoxMargins().iTop,
        aClientRect.iBr.iX + ListBoxMargins().iRight, aClientRect.iBr.iY + ListBoxMargins().iBottom);
    // height may have been rounded so correct it
    if (!iViewRectHeightAdjustment)
        return;
#ifdef ORIGINAL_UIKON_CODE
    if (iViewRectHeightAdjustment % 2 !=0)
        aClientRect.iBr.iY += 1;
    aClientRect.Grow(0, iViewRectHeightAdjustment/2);
#else // Series60 code
    aClientRect.iBr.iY += iViewRectHeightAdjustment;
#endif
    _AKNTRACE_FUNC_EXIT;
    // aClientRect.iBr.iY += iViewRectHeightAdjustment;
    }

EXPORT_C TInt CEikListBox::AdjustRectHeightToWholeNumberOfItems(TRect& aRect) const
    {
    _AKNTRACE_FUNC_ENTER;
    // round down the height of aRect (if necessary) so that only a whole number of items can be displayed inside the listbox
    // returns the number of pixels reduced.
#ifdef ORIGINAL_UIKON_CODE
    TInt remainder = aRect.Height() % iItemHeight;
    if (remainder != 0) 
        {
        // need to adjust viewRect 
        aRect.Shrink(0, remainder/2);
        if (remainder % 2 != 0)     
            aRect.iBr.iY -= 1;
        // aRect.iBr.iY -= remainder;
        }
#else // Series 60 code
    // To catch places which use this in series 60
    // -- should use derived class version
    // from CAknColumnList or CEikFormattedCellListBox or something else.
    //__ASSERT_DEBUG(0, Panic(0));
    // This is dead code, can be reverted to original once we've tested
    // noone uses this.
    TInt remainder = aRect.Height() % iItemHeight;
    if (remainder != 0)
    {
        aRect.iBr.iY -= remainder;
        }
#endif
    _AKNTRACE_FUNC_EXIT;
    return remainder;
    }

EXPORT_C void CEikListBox::CalculatePopoutRect(TInt aTargetItemIndex, TInt aTargetYPos, TRect& aListBoxRect, TInt aMinHeightInNumOfItems) 
    {
    _AKNTRACE_FUNC_ENTER;
    /*controlling the maximum width, in pixels, of a choice list*/
    if((LafListBox::MaxCellWidthInNumOfPixels() != KLafListBoxNoMaxCellWidth) && (aListBoxRect.Width() > LafListBox::MaxCellWidthInNumOfPixels()))
        {
        aListBoxRect.iBr.iX = aListBoxRect.iTl.iX + LafListBox::MaxCellWidthInNumOfPixels();
        }
    // this function is designed for use by the choice list control
    TInt listBoxHeight = 0;
    TInt listBoxYPos = 0;
    TInt screenHeight = iAvkonAppUi->ApplicationRect().Height(); /*iCoeEnv->ScreenDevice()->SizeInPixels().iHeight;*/
    TInt maxDisplayedItems = (screenHeight - (ListBoxMargins().iTop + ListBoxMargins().iBottom) - iBorder.SizeDelta().iHeight) / iItemHeight;

    /*controlling the maximum number of items displayed in a choice list*/
    if(LafListBox::MaxHeightInNumOfItems() != KLafListBoxNoMaxHeightInNumOfItems)
        {
        maxDisplayedItems = Min(maxDisplayedItems,LafListBox::MaxHeightInNumOfItems());
        }
    TInt desiredHeightInNumOfItems = Max(iModel->NumberOfItems(), aMinHeightInNumOfItems);
    if (desiredHeightInNumOfItems > maxDisplayedItems)
        {
        listBoxHeight = CalcHeightBasedOnNumOfItems(maxDisplayedItems);     
        listBoxYPos = (screenHeight - listBoxHeight) / 2;
        TInt numOfDisplayedItemsAboveTarget = (aTargetYPos-listBoxYPos-ListBoxMargins().iTop)/iItemHeight;
        
        TInt topItemOrdinal=Max(0, (aTargetItemIndex-numOfDisplayedItemsAboveTarget));
        topItemOrdinal=Min(iModel->NumberOfItems()-maxDisplayedItems,topItemOrdinal);
        iView->SetTopItemIndex(iView->TopItemIndex()+topItemOrdinal);
        aListBoxRect.iTl.iY = listBoxYPos;
        aListBoxRect.iBr.iY = listBoxYPos + listBoxHeight;
        return;
        }
    listBoxHeight = CalcHeightBasedOnNumOfItems(desiredHeightInNumOfItems);
    TInt numOfItemsAbove = aTargetItemIndex;
    TInt potentialPixelsAboveTarget = 0;
    if (numOfItemsAbove > 0)
        {
        potentialPixelsAboveTarget = numOfItemsAbove * iItemHeight + ListBoxMargins().iTop + iBorder.Margins().iTop;
        }
    listBoxYPos = aTargetYPos - potentialPixelsAboveTarget;
    if ((listBoxYPos + listBoxHeight) >= screenHeight)
        listBoxYPos = screenHeight - listBoxHeight;
    if (potentialPixelsAboveTarget>aTargetYPos)
        listBoxYPos = 0;
    // find number of items below aTargetItemIndex
    TInt numberOfItemsBelowTarget = 0;
    TInt targetIndex = aTargetItemIndex;
    while (ItemExists(++targetIndex))
        ++numberOfItemsBelowTarget;
    TInt potentialPixelsBelowTarget = 0;
    if (numberOfItemsBelowTarget > 0)
        {
        potentialPixelsBelowTarget = numberOfItemsBelowTarget * iItemHeight + ListBoxMargins().iBottom + iBorder.Margins().iBottom;
        }
    if ((potentialPixelsBelowTarget + iItemHeight) > (screenHeight-aTargetYPos))
        listBoxYPos = screenHeight - listBoxHeight;
    aListBoxRect.iTl.iY = listBoxYPos;
    aListBoxRect.iBr.iY = listBoxYPos + listBoxHeight;
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C TInt CEikListBox::TopItemIndex() const
    {
    _AKNTRACE( "iTopItemIndex = %d", iView->TopItemIndex() );
    __ASSERT_DEBUG(iView, Panic(EEikPanicListBoxNoView));
    return iView->TopItemIndex();
    }

EXPORT_C TInt CEikListBox::BottomItemIndex() const
    {
    _AKNTRACE( "iBottomItemIndex = %d", iView->BottomItemIndex() );
    __ASSERT_DEBUG(iView, Panic(EEikPanicListBoxNoView));
    return iView->BottomItemIndex();
    }

EXPORT_C void CEikListBox::SetTopItemIndex(TInt aItemIndex) const
    {
    _AKNTRACE( "aItemIndex = %d", aItemIndex );
    __ASSERT_DEBUG(iView, Panic(EEikPanicListBoxNoView));
    iView->SetTopItemIndex(aItemIndex);
    UpdateScrollBarThumbs();
    }

EXPORT_C void CEikListBox::AdjustTopItemIndex() const
    {
    _AKNTRACE_FUNC_ENTER;
    TInt maxTopItemIndex=iView->BottomItemIndex() - iView->NumberOfItemsThatFitInRect(iView->ViewRect()) +1;
    maxTopItemIndex=Max(0, maxTopItemIndex);
    if (iView->TopItemIndex() > maxTopItemIndex)
        SetTopItemIndex(maxTopItemIndex);
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C TInt CEikListBox::CurrentItemIndex() const
    {
    _AKNTRACE( "iView->CurrentItemIndex() is %d", iView->CurrentItemIndex() );
    __ASSERT_ALWAYS(iView, Panic(EEikPanicListBoxNoView));
    return iView->CurrentItemIndex();
    }

EXPORT_C void CEikListBox::UpdateCurrentItem(TInt aItemIndex) const
    {
    _AKNTRACE_FUNC_ENTER;
    TInt oldCurrentItemIndex = iView->CurrentItemIndex();
    iView->SetCurrentItemIndex(aItemIndex);
    if ( IsReadyToDraw() )
        {
        iView->DrawItem(oldCurrentItemIndex);
        }
    if (!(iView->ItemIsVisible(aItemIndex)) || iView->ItemIsPartiallyVisible(aItemIndex) )
        {
        SetTopItemIndex(iView->CalcNewTopItemIndexSoItemIsVisible(aItemIndex));
        
        if ( !iView->RedrawDisabled() )
            {           
            DrawNow();
            }
        }
#if NOT_USED_IN_SERIES60
// This is not used in Series 60 because in FIND, we do not want
// selectionindexes to have a list of indexes...
    if (!(iListBoxFlags & EMultipleSelection))
        {
        TRAPD(err,iView->UpdateSelectionL(CListBoxView::ESingleSelection));
        if (err!=KErrNone)
            iEikonEnv->NotifyIdleErrorWhileRedrawing(err);
        }
#endif

    iView->DrawItem(aItemIndex);
    TRAP_IGNORE(UpdateMarkUnmarkMSKL());
    UpdateScrollBarThumbs();
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::SetCurrentItemIndex(TInt aItemIndex) const
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE( "aItemIndex = %d", aItemIndex );
    __ASSERT_ALWAYS(iView, Panic(EEikPanicListBoxNoView));
    TBool redrawDisabled = iView->RedrawDisabled();
    iView->SetDisableRedraw(ETrue);
    UpdateCurrentItem(aItemIndex);
    iView->SetDisableRedraw(redrawDisabled);
    
    if ( iListBoxExt && iListBoxExt->iPhysics && aItemIndex == 0 
             && !iListBoxExt->iScrolling )
        {    
        iView->SetItemOffsetInPixels( 0 );        
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::SetCurrentItemIndexAndDraw(TInt aItemIndex) const
    {
    __ASSERT_ALWAYS(iView, Panic(EEikPanicListBoxNoView));
    UpdateCurrentItem(aItemIndex);
    }

EXPORT_C void CEikListBox::ConstructL(const CCoeControl* aParent,TInt aFlags)
    {
    _AKNTRACE_FUNC_ENTER;
    iListBoxFlags = aFlags;
    if (! (iListBoxFlags & EPageAtOnceScrolling))
        { // no loop scroll for viewers
        iListBoxFlags |= ELoopScrolling; // All lists will have loop scrolling.
        }
    if (aParent)
        SetContainerWindowL(*aParent);
    else
        {
        CreateWindowL(aParent);

        if ( CAknEnv::Static()->TransparencyEnabled() )
            {
            Window().SetRequiredDisplayMode( EColor16MA );
            TInt err = Window().SetTransparencyAlphaChannel();

            if ( err == KErrNone )
                {
                Window().SetBackgroundColor(~0);
                }
            }

        EnableDragEvents();
        Window().SetPointerGrab(ETrue);
        }
    if (iListBoxFlags & EPopout)
        {
        if (!LafListBox::FadeBehind())
            DrawableWindow()->EnableBackup();
        LafListBox::GetDefaultPopoutBorder(iBorder);
        }
    if (iListBoxFlags & EIncrementalMatching)
        CreateMatchBufferL();
    CreateViewL();
    
    if(iItemDrawer && (iItemDrawer->MinimumCellSize().iHeight != 0))
        iItemHeight = iItemDrawer->MinimumCellSize().iHeight;

    CheckCreateExtensionL();
    
    if ( iListBoxExt->iLongTapDetector
            && iListBoxFlags & EDisableItemSpecificMenu )
        {
        delete iListBoxExt->iLongTapDetector;
        iListBoxExt->iLongTapDetector = NULL;
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::ConstructL(MListBoxModel* aListBoxModel,CListItemDrawer* aListItemDrawer,const CCoeControl* aParent,TInt aFlags)
    {
    _AKNTRACE_FUNC_ENTER;
    __ASSERT_DEBUG(aListBoxModel!=NULL,Panic(EEikPanicListBoxInvalidModelSpecified));
    __ASSERT_DEBUG(aListItemDrawer!=NULL,Panic(EEikPanicListBoxInvalidItemDrawerSpecified));
    iModel = aListBoxModel;
    iItemDrawer = aListItemDrawer;
    ConstructL(aParent,aFlags);
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::ConstructL(MListBoxModel* aListBoxModel, CListItemDrawer* aListItemDrawer, const CCoeControl* aParent, TGulBorder aBorder, TInt aFlags)
    {
    _AKNTRACE_FUNC_ENTER;
    iBorder = aBorder;
    CEikListBox::ConstructL(aListBoxModel, aListItemDrawer, aParent, aFlags);
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::SetListBoxObserver(MEikListBoxObserver* aObserver)
    {
    iListBoxObserver = aObserver;
    }

EXPORT_C void CEikListBox::SetContainerWindowL(const CCoeControl& aParent)
    {
    _AKNTRACE_FUNC_ENTER;
    if ((iListBoxFlags & ECreateOwnWindow) || (iListBoxFlags & EPopout))
        {
        CreateWindowL(&aParent);
        if (iListBoxFlags & EPopout)
            DrawableWindow()->EnableBackup();
        }
    else
        CCoeControl::SetContainerWindowL(aParent);
    EnableDragEvents();
    Window().SetPointerGrab(ETrue);
    
    if ( iListBoxExt && iListBoxExt->iPhysics )
        {
        iListBoxExt->iPhysics->UpdateViewWindowControl();
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C CListBoxView* CEikListBox::MakeViewClassInstanceL()
    {
    return (new(ELeave) CListBoxView);
    }

EXPORT_C void CEikListBox::CreateViewL()
    {
    _AKNTRACE_FUNC_ENTER;
    // assert that the model and item drawer aren't null
    if (iView)
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    iView = MakeViewClassInstanceL();
    iView->ConstructL(iModel, iItemDrawer, iEikonEnv->ScreenDevice(), &(iEikonEnv->RootWin()), &Window(), Rect(), iItemHeight);
    iView->iExtension->iListBox = this;    

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    // LISTBOX EFFECTS IMPLEMENTATION
    //
    // Creates a CTfxGc and replaces the original CWindowGc with that gc.
    //
    CWindowGc* transGc = CAknListLoader::CreateTfxGc( *this );
    if( transGc )
        {
        iView->iGc = transGc;
        iView->ItemDrawer()->SetGc(transGc);
        }
    // END OF LISTBOX EFFECTS IMPLEMENTATION
#endif // RD_UI_TRANSITION_EFFECTS_LIST

    if (iListBoxFlags & EIncrementalMatching)
        {
        iView->SetMatcherCursor(ETrue);
        if(IsDimmed())
            iView->SetMatcherCursorColor(EColorControlHighlightBackground);
        else
            iView->SetMatcherCursorColor(EColorControlDimmedHighlightBackground);
        }
    iItemDrawer->SetVerticalInterItemGap(KEikListBoxItemVGap);
    if (iListBoxFlags & EMultipleSelection) iItemDrawer->SetDrawMark(ETrue);
    if (ItemExists(0))
        SetCurrentItemIndex(0);
    CheckCreateExtensionL();
    
    if ( iListBoxExt && iListBoxExt->iPhysics )
        {
        iView->iExtension->iScrollingDisabled = EFalse;
        }
    
    iView->SetVisibilityObserver(iListBoxExt);
    if ( iListBoxFlags & EPaintedSelection )
        {
        iView->SetPaintedSelection( ETrue );
        iItemDrawer->SetDrawMark( EFalse );
        iItemDrawer->SetFlags( CListItemDrawer::EPaintedSelection );
        }
    if (iListBoxFlags & EDisableHighlight)
    {
    iItemDrawer->SetFlags( CListItemDrawer::EDisableHighlight );
    }

    if ( iListBoxExt && iListBoxExt->iSingleClickEnabled )
        {
        iListBoxExt->EnableHighlight( EFalse );
        iListBoxExt->ReportCollectionChangedEvent();
        }    
        
    UpdateViewColors();
    UpdateItemDrawerColors();
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::DrawMatcherCursor() const
    {
    if (!IsMatchBuffer())
        return;
    TInt currentItemIndex = iView->CurrentItemIndex();
    if (ItemExists(currentItemIndex)) 
        {
        if (! iView->ItemIsVisible(currentItemIndex))
            ScrollToMakeItemVisible(currentItemIndex);
        iView->DrawMatcherCursor();
        }
    }

EXPORT_C TInt CEikListBox::InterItemGap()
    { // static
    return KEikListBoxInterItemGap;
    }


EXPORT_C void CEikListBox::DrawItem( TInt aItemIndex ) const
    {
    _AKNTRACE_FUNC_ENTER;
    if ( !IsReadyToDraw() )
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }

    __ASSERT_ALWAYS( iView, Panic( EEikPanicListBoxNoView ) );
    
    TBool viewScrolled = EFalse;
    if ( iView->ItemIsPartiallyVisible( aItemIndex ) ||
         !iView->ItemIsVisible( aItemIndex ) )
        {
        viewScrolled = iView->ScrollToMakeItemVisible( aItemIndex );
        }

    if ( !viewScrolled )
        {
        iView->DrawItem( aItemIndex );
        }
    else
        {
        UpdateScrollBarThumbs();
        }
    _AKNTRACE_FUNC_EXIT;
    }


EXPORT_C void CEikListBox::ScrollToMakeItemVisible(TInt aItemIndex) const 
    {
    _AKNTRACE_FUNC_ENTER;
    __ASSERT_ALWAYS(iView, Panic(EEikPanicListBoxNoView));
    TBool scrollingTookPlace = iView->ScrollToMakeItemVisible(aItemIndex);
    if (scrollingTookPlace)
        UpdateScrollBarThumbs();
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::RedrawItem( TInt aItemIndex )
    {
    _AKNTRACE_FUNC_ENTER;
    if (!IsReadyToDraw())
        {
        _AKNTRACE_FUNC_EXIT;        
        return;
        }
    __ASSERT_ALWAYS(iView, Panic(EEikPanicListBoxNoView));
    if ( iView->ItemIsVisible( aItemIndex ) )
        {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
        MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( iView->iGc );

        TBool redraw = !IsBackedUp() && ( transApi == NULL || transApi->EffectsDisabled() );
#else
        TBool redraw = !IsBackedUp();
#endif // RD_UI_TRANSITION_EFFECTS_LIST

        if ( redraw )
            {
            TRect redrawRect( 
                iView->ItemPos( aItemIndex ), 
                iItemDrawer->ItemCellSize() );
            redrawRect.Intersection( iView->ViewRect() );

            Window().Invalidate( redrawRect );
            Window().BeginRedraw( redrawRect );
            }

        iView->DrawItem( aItemIndex );

        if ( redraw )
            {
            Window().EndRedraw();
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::ActivateL()
    {
    _AKNTRACE_FUNC_ENTER;
    CCoeControl::ActivateL();
    UpdateScrollBarThumbs();

    CEikButtonGroupContainer *cba;
    MopGetObject(cba);
    
    if (!cba) 
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    
    if (iListBoxFlags & EEnterMarks)
        {
        // Unfortunately, we need to do this here. It belongs to 
        // CAknSelectionListDialog, but we need this change also 
        // to code that does not yet use CAknSelectionListDialog.
        TRAP_IGNORE(iAvkonEnv->CreateCbaObserverL(cba, this));
        }
    if ( iListBoxExt && iListBoxExt->iMSKObserverEnabled &&
        ( (iListBoxFlags & EShiftEnterMarks) ||
          (iListBoxFlags & EEnterMarks) ) )
        {
        TRAP_IGNORE(iListBoxExt->CreateMSKObserverL(cba, this));
        TRAP_IGNORE(UpdateMarkUnmarkMSKL());
        }
    _AKNTRACE_FUNC_EXIT;
    }


EXPORT_C void CEikListBox::Draw(const TRect& aRect) const
    {
    _AKNTRACE_FUNC_ENTER;
    // If a parent has a custom gc, draw listbox using that gc
    CWindowGc* replacedGc = ReplaceGcWithCustomGc( this );
    
    CWindowGc* gc = iItemDrawer->Gc();
    TGulBorder::TColors borderColors;
    iBorder.Draw(*gc, Rect(), borderColors);

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( iView->iGc );
    if ( transApi )
        {
        transApi->BeginRedraw( MAknListBoxTfxInternal::EListView, View()->ViewRect() );
        transApi->StartDrawing( MAknListBoxTfxInternal::EListView );
        }
#endif // RD_UI_TRANSITION_EFFECTS_LIST


    ClearMargins(); 
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    if ( transApi )
        {
        transApi->StopDrawing();
        }
#endif // RD_UI_TRANSITION_EFFECTS_LIST
    iView->Draw(&aRect);

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    if ( transApi )
        {
        transApi->EndViewRedraw( aRect );
        }
#endif // RD_UI_TRANSITION_EFFECTS_LIST

    if ( replacedGc )
        {
        // Stop using the custom gc
        iItemDrawer->SetGc( replacedGc );
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::ClearMargins() const
    {
     if (!iView->RedrawDisabled())
         {
         CWindowGc* gc = iItemDrawer->Gc();
         if (gc)
     {
     TRect viewRect=iView->ViewRect();
     TRect clientRect;
     RestoreClientRectFromViewRect(clientRect);
             gc->SetBrushColor(iBackColor);
             DrawUtils::ClearBetweenRects(*gc, clientRect, viewRect);
             }
         }
    }

EXPORT_C void CEikListBox::UpdateScrollBarsL()
    {
    _AKNTRACE_FUNC_ENTER;
    if (!iSBFrame)
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    TEikScrollBarModel hSbarModel;
    TEikScrollBarModel vSbarModel;
    TRect rect=iView->ViewRect();
//#ifdef NOT_NEEDED_IN_SERIES60
    if (!(iListBoxFlags & EScrollBarSizeExcluded))
        {
        // Ignore scrollbars presence to set the model, Scrollbar Frame will change it as required
        rect = iBorder.InnerRect(Rect());
        rect.SetRect(rect.iTl.iX + ListBoxMargins().iLeft, rect.iTl.iY + ListBoxMargins().iTop,
            rect.iBr.iX - ListBoxMargins().iRight, rect.iBr.iY - ListBoxMargins().iBottom);
        AdjustRectHeightToWholeNumberOfItems(rect);
        // rect is now viewRect when ignoring scrollbars
        }
//#endif
    TInt itemHeight = iView->ItemHeight();
    TSize viewSize( iView->ViewRect().Size() );
    
    if (iSBFrame->VScrollBarVisibility()!=CEikScrollBarFrame::EOff)
        {
        if (!(iListBoxFlags & EPageAtOnceScrolling))
            {
            if (iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan)
                {
                // For EDoubleSpan type scrollbar
				vSbarModel.iThumbPosition = iView->TopItemIndex()*iView->ItemHeight() - iView->ItemOffsetInPixels();
                }
            else
                {
                // For EArrowHead type scrollbar
                vSbarModel.iThumbPosition = iView->CurrentItemIndex();
                }
            vSbarModel.iScrollSpan = iModel->NumberOfItems()*iView->ItemHeight();
           }
        else
            { // Viewer
			vSbarModel.iThumbPosition = iView->TopItemIndex()*iView->ItemHeight() - iView->ItemOffsetInPixels();
			vSbarModel.iScrollSpan = iModel->NumberOfItems()*iView->ItemHeight();
            }
        if ( vSbarModel.iScrollSpan == viewSize.iHeight )
            {
            vSbarModel.iThumbSpan = viewSize.iHeight;
            }
        else
            {
            vSbarModel.iThumbSpan = viewSize.iHeight - viewSize.iHeight % 2;            
            }
//#ifdef NOT_NEEDED_IN_SERIES60
        if ( IsActivated() )
            {            
            if (vSbarModel.iScrollSpan-vSbarModel.iThumbPosition<vSbarModel.iThumbSpan)
                {
                vSbarModel.iThumbPosition=Max(0,vSbarModel.iScrollSpan-vSbarModel.iThumbSpan);
                // This call causes redraw that should not be done in SizeChanged phase.
                iView->ScrollToMakeItemVisible(vSbarModel.iThumbPosition/iView->ItemHeight()); // force a scroll if neccessary
                }
            }
//#endif
        }
    if (iSBFrame->ScrollBarVisibility(CEikScrollBar::EHorizontal)!=CEikScrollBarFrame::EOff)
        {
        iView->CalcDataWidth();
        hSbarModel.iThumbPosition = iView->HScrollOffset();
        hSbarModel.iScrollSpan = iView->DataWidth();
        hSbarModel.iThumbSpan = iView->VisibleWidth(rect);
        }

    if (iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan)
        {
        // For EDoubleSpan type scrollbar        
        TAknDoubleSpanScrollBarModel hDsSbarModel( hSbarModel );
        TAknDoubleSpanScrollBarModel vDsSbarModel( vSbarModel );
              
        TRect clientRect = Rect();      
        TRect inclusiveRect = Rect();
        TEikScrollBarFrameLayout layout;
        layout.iTilingMode=TEikScrollBarFrameLayout::EInclusiveRectConstant;
        layout.SetClientMargin(0);
        layout.SetInclusiveMargin(0);
        if(iSBFrameOwned == EOwnedExternally)
            iSBFrame->Tile(&hDsSbarModel, &vDsSbarModel);
        else
            {
            TBool sizeChanged=EFalse;
            sizeChanged=iSBFrame->TileL(&hDsSbarModel, &vDsSbarModel, clientRect, inclusiveRect, layout);
            if (sizeChanged)
                {               
                iSBFrame->DrawScrollBarsDeferred();
                }
            }
        }
    else
        {
        // For EArrowHead type scrollbar
        TRect clientRect;
        RestoreClientRectFromViewRect(clientRect);
        TRect inclusiveRect=Rect();
        TEikScrollBarFrameLayout layout;
        CreateScrollBarFrameLayout(layout);
        TBool sizeChanged=iSBFrame->TileL(&hSbarModel, &vSbarModel, clientRect, inclusiveRect, layout);
        if ( iListBoxExt && iListBoxExt->UpdateScrollBarsColors() )
            UpdateScrollBarsColors();
        if (!sizeChanged)
            return;
        // else size of client/inclusive rect has changed
        if (layout.iTilingMode==TEikScrollBarFrameLayout::EClientRectConstant)
            SetSizeWithoutNotification(inclusiveRect.Size());
        else
            {
            SetViewRectFromClientRect(clientRect);
            ClearMargins();
            }        
        }
    
    if ( iListBoxExt )
        {    
        iListBoxExt->CheckScrollBarVisibility();
        }
    
    AdjustTopItemIndex();
    _AKNTRACE_FUNC_EXIT;
    }
                                                            
EXPORT_C void CEikListBox::CreateScrollBarFrameLayout(TEikScrollBarFrameLayout& aLayout)    const
    {
    _AKNTRACE_FUNC_ENTER;
    aLayout.iInclusiveMargin=iBorder.Margins();

    aLayout.iClientMargin.iTop=ListBoxMargins().iTop;
    aLayout.iClientMargin.iBottom=ListBoxMargins().iBottom;
    aLayout.iClientMargin.iLeft=ListBoxMargins().iLeft;
    aLayout.iClientMargin.iRight=ListBoxMargins().iRight;

    aLayout.iClientAreaGranularity=TSize(HorizScrollGranularityInPixels(), iItemHeight); 
    aLayout.iTilingMode=(!(iListBoxFlags & EScrollBarSizeExcluded))? TEikScrollBarFrameLayout::EInclusiveRectConstant : TEikScrollBarFrameLayout::EClientRectConstant;
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C TInt CEikListBox::HorizScrollGranularityInPixels() const
    {
    return 1; // horiz scroll bar model set in pixels for standard listbox
    }

EXPORT_C void CEikListBox::Reset()
    {
    _AKNTRACE_FUNC_ENTER;
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( iView->iGc );
    if ( transApi )
        {
        transApi->Remove( MAknListBoxTfxInternal:: EListEverything );
        }
#endif // RD_UI_TRANSITION_EFFECTS_LIST

    ((CListBoxView::CSelectionIndexArray*)iView->SelectionIndexes())->Reset();
    iView->SetTopItemIndex(0);
    iView->SetCurrentItemIndex(0);
    iView->ClearSelectionAnchorAndActiveIndex();
    iView->SetHScrollOffset(0);

    FireItemChange();
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::AddItemChangeObserverL(
        MListBoxItemChangeObserver* aObserver )
    {
    _AKNTRACE_FUNC_ENTER;
    if( !aObserver )
        {
        User::Leave( KErrArgument );
        }

    CheckCreateExtensionL();
    iListBoxExt->AddItemChangeObserverL( aObserver );
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C TBool CEikListBox::RemoveItemChangeObserver(
        MListBoxItemChangeObserver* aObserver )
    {
    _AKNTRACE_FUNC_ENTER;
    if( !iListBoxExt )
        {
        _AKNTRACE_FUNC_EXIT;
        return EFalse;
        }
    _AKNTRACE_FUNC_EXIT;
    return iListBoxExt->RemoveItemChangeObserver( aObserver );
    }

EXPORT_C void CEikListBox::AddSelectionObserverL( MListBoxSelectionObserver* aObserver )
    {
    _AKNTRACE_FUNC_ENTER;
    if( !aObserver )
        {
        User::Leave( KErrArgument );
        }

    CheckCreateExtensionL();
    iListBoxExt->AddSelectionObserverL( aObserver );
    _AKNTRACE_FUNC_EXIT;
    }
    
EXPORT_C void CEikListBox::RemoveSelectionObserver( MListBoxSelectionObserver* aObserver )
    {
    _AKNTRACE_FUNC_ENTER;
    if( iListBoxExt )
        {
        iListBoxExt->RemoveSelectionObserver( aObserver );
        }
    _AKNTRACE_FUNC_EXIT;
    }

void CEikListBox::ChangeSelectionMode( TBool aEnable )
    // Nonexported helper function.
    {
    _AKNTRACE_FUNC_ENTER;
    // UI Spec does not mention this, but it is reasonable not to
    // change selection mode on unmarkable item.
    TInt index = CurrentItemIndex();
    if ( index >= 0 && aEnable 
         && iItemDrawer->Properties(index).IsSelectionHidden() )
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    
    CEikButtonGroupContainer *bgc;
    CCoeControl* MSK( NULL );
    CEikCba* cba( NULL );
    CONST_CAST( CEikListBox*,this )->MopGetObject( bgc );
    if ( !bgc )
        {
        _AKNTRACE_FUNC_EXIT;
        return; // No bgc -> no cba -> nothing can be done here (and no need to inform observers)
        }
        
    cba = ( static_cast<CEikCba*>( bgc->ButtonGroup() ) ); // downcast from MEikButtonGroup

    if ( !cba )
        {
        _AKNTRACE_FUNC_EXIT;
        return; // No cba -> nothing can be done here (and no need to inform observers)
        }

    MSK = cba->Control( 3 ); // MSK's position is 3

    TInt newResourceId( NULL );
    if ( MSK && View()->ItemIsSelected( CurrentItemIndex() ) )
        {
        newResourceId = R_AVKON_SOFTKEY_UNMARK;
        }
    if ( MSK && !View()->ItemIsSelected( CurrentItemIndex() ) )
        {
        newResourceId = R_AVKON_SOFTKEY_MARK;
        }

    if ( aEnable && newResourceId )
        {
        TRAPD( err, bgc->AddCommandToStackL( 3, newResourceId ) );
        // in case of error, don't inform observers
        // marking still works even MSK isn't changed
        if ( err )
            {
            if ( iListBoxExt )
                {
                iListBoxExt->iSelectionModeEnabled = EFalse;
                }
            _AKNTRACE_FUNC_EXIT;
            return;
            }
        cba->DrawNow();
        if ( iListBoxExt )
            {
            iListBoxExt->iSelectionModeEnabled = ETrue;
            }
        }

    // remove stacked MSK
    if( !aEnable && iListBoxExt && iListBoxExt->iSelectionModeEnabled )
        {
        if( ( MSK && cba->ControlId( MSK ) == EAknSoftkeyMark ) ||
            ( MSK && cba->ControlId( MSK ) == EAknSoftkeyUnmark ) )
            {
            bgc->RemoveCommandFromStack( 3, cba->ControlId( MSK ) );
            }
        iListBoxExt->iSelectionModeEnabled = EFalse; // just in case
        }
    if ( iListBoxExt )
        {
        TInt count = iListBoxExt->iSelectionObservers.Count();
        for ( int i=0; i < count; i++ )
            {
            iListBoxExt->iSelectionObservers[i]->SelectionModeChanged( this, aEnable );
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }


void CEikListBox::HandleItemRemovalWithoutSelectionsL()
    // Nonexported helper function.
    {
    _AKNTRACE_FUNC_ENTER;
    // this will force update of physics parameters next time when list is panned
    iView->SetItemOffsetInPixels( 0 );
    iView->SetFlags(CListBoxView::EItemCountModified);
    iView->CalcDataWidth();
    iView->CalcBottomItemIndex();
    UpdateScrollBarsL();
    UpdateScrollBarThumbs();
    iView->ClearFlags(CListBoxView::EItemCountModified);


    if ( iListBoxExt && iListBoxExt->iLongTappedItem != KErrNotFound )
        {
        iListBoxExt->EnableHighlight( EFalse );
        }

    FireItemChange();
    
    if ( iListBoxExt && iListBoxExt->iPhysics )
        {
        iListBoxExt->InitPhysicsL();
        }    
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::HandleItemRemovalL(CArrayFix<TInt> &aArrayOfOldIndexes)
    // NOTE, This algorithm cannot handle position of the list highlight
    // nor can it update the topitemindex correctly.
    {
    _AKNTRACE_FUNC_ENTER;
    TKeyArrayFix key(0,ECmpTInt);
    aArrayOfOldIndexes.Sort(key);

    // remove removed items from selection index array
    TInt changedcount = aArrayOfOldIndexes.Count();
    for(TInt iii=0;iii<changedcount;iii++)
        {
        iView->DeselectItem(aArrayOfOldIndexes.At(iii));
        }

    // decrease selectionindexes. Does not change their order, so resorting
    // the array is not necessary
    CListBoxView::CSelectionIndexArray* array = CONST_CAST(CListBoxView::CSelectionIndexArray*,iView->SelectionIndexes());
    TInt selectioncount = array->Count();
    TInt removedcount = aArrayOfOldIndexes.Count();
    for(TInt ii = 0;ii<removedcount;ii++)
        {
        for(TInt i=0;i<selectioncount;i++)
            {
            // since we deselected the item, its not possible that
            // the removed item is still in selectionindexes array.
            __ASSERT_DEBUG(array->At(i) != aArrayOfOldIndexes.At(ii), Panic(EEikPanicOutOfRange));
            if (array->At(i) > aArrayOfOldIndexes.At(ii))
                {
                (*array)[i]-=1;
                }
            }
        }
 
    HandleItemRemovalWithoutSelectionsL();
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::HandleItemAdditionL(CArrayFix<TInt> &aArrayOfNewIndexesAfterAddition)
    // NOTE, This algorithm cannot handle position of the list highlight
    // nor can it update the topitemindex correctly.
    {
    _AKNTRACE_FUNC_ENTER;
    // Updates selectionindexes array

    // Sort indexes first
    TKeyArrayFix key(0,ECmpTInt);
    aArrayOfNewIndexesAfterAddition.Sort(key);
    
    // increase selectionindexes.
    CListBoxView::CSelectionIndexArray* array = CONST_CAST(CListBoxView::CSelectionIndexArray*,iView->SelectionIndexes());
    TInt selectioncount = array->Count();
    TInt newindexcount = aArrayOfNewIndexesAfterAddition.Count();
    for(TInt ii = 0;ii<newindexcount;ii++)
        {
        for(TInt i=0;i<selectioncount;i++)
            {
            if (array->At(i) >= aArrayOfNewIndexesAfterAddition.At(ii))
                {
                (*array)[i]+=1;
                }
            }
        }

    // other features that does not depend on the items added.
    HandleItemAdditionL();
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::HandleItemAdditionL()
    {
    _AKNTRACE_FUNC_ENTER;
    __ASSERT_DEBUG( iView, Panic( EEikPanicListBoxNoView ) );
    //fix the bug EGGO-7SQA4S and EVSG-7TD9WZ     
    TInt curItemIndex = iView->CurrentItemIndex();
    if(curItemIndex >= 0 && curItemIndex < iModel->NumberOfItems() )
      {
      TInt newTopItemIndex = iView->CalcNewTopItemIndexSoItemIsVisible( curItemIndex );
      iView->SetTopItemIndex( newTopItemIndex );
      }
    iView->SetFlags(CListBoxView::EItemCountModified);
    // following breaks lists in square layout, not needed in SERIES60?
    //iView->CalcDataWidth();
    iView->CalcBottomItemIndex();
    UpdateScrollBarsL();
    UpdateScrollBarThumbs();
    if (IsReadyToDraw()) DrawDeferred();
    iView->ClearFlags(CListBoxView::EItemCountModified);

    FireItemChange();
    
    if ( iListBoxExt )
        {    
        iListBoxExt->CheckScrollBarVisibility();
        // Physics engine world size needs to be updated here, otherwise aknphysics 
        // cone observer may block pointer events on new items. this can happen 
        // when item addition inserts new row to taskswapper's grid and reuses list in Common Dialog
        if ( iListBoxExt->iPhysics )
            {
            iListBoxExt->InitPhysicsL();
            }
        }     
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::HandleItemRemovalL()
    {
    // Should be called after one or more items have been removed from the model
    // It is up to the application to then make sure that the current item index is set to an appropriate value and to redraw the listbox
    _AKNTRACE_FUNC_ENTER;
    ((CListBoxView::CSelectionIndexArray*)iView->SelectionIndexes())->Reset();
    HandleItemRemovalWithoutSelectionsL();
    _AKNTRACE_FUNC_EXIT;
    // Please do not add anything here. Add them to the HandleItemRemovalWithoutSelectionsL().
    }

EXPORT_C const CArrayFix<TInt>* CEikListBox::SelectionIndexes() const
    {
    return iView->SelectionIndexes();
    }

EXPORT_C void CEikListBox::SetSelectionIndexesL(CListBoxView::CSelectionIndexArray* aArrayOfSelectionIndexes)
    {
    if (! aArrayOfSelectionIndexes)
        iView->ClearSelection();
    else
        iView->SetSelectionIndexesL(aArrayOfSelectionIndexes);
    }

void CEikListBox::HorizontalScroll(TInt aScrollAmountInPixels)
    {
    iView->HScroll(aScrollAmountInPixels);
    if (iSBFrame)
        {
        if (iSBFrame->ScrollBarVisibility(CEikScrollBar::EHorizontal)!=CEikScrollBarFrame::EOff)
            iSBFrame->MoveThumbsBy(aScrollAmountInPixels, 0);
        }
    }

EXPORT_C void CEikListBox::HandleLeftArrowKeyL(CListBoxView::TSelectionMode /*aSelectionMode*/)
    {
    HorizontalScroll(-(iView->ViewRect().Width() / KEikListBoxHNudgeSizeAsFractionOfViewRectWidth));
    }


EXPORT_C void CEikListBox::HandleRightArrowKeyL(CListBoxView::TSelectionMode /*aSelectionMode*/)
    {
    HorizontalScroll((iView->ViewRect().Width() / KEikListBoxHNudgeSizeAsFractionOfViewRectWidth));
    }
//#define KEY_DEBUG

#if defined(_DEBUG) && defined(KEY_DEBUG)
#define __KeyDebug(b,text) { _LIT(blah, "LbxKeys %d:%d:%c%c%c " ## L ## text); RDebug::Print(blah, aKeyEvent.iCode, aKeyEvent.iScanCode, shiftKeyPressed ? 's' : '_', enterKeyPressed ? 'e' : '_', aType == EEventKey ? 'K' : (aType == EEventKeyDown ? 'D' : (aType == EEventKeyUp ? 'U' : '_'))); }
#else
#define __KeyDebug(b,text)
#endif


EXPORT_C TKeyResponse CEikListBox::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {
    _AKNTRACE_FUNC_ENTER;
    TKeyEvent keyEvent=aKeyEvent;
    keyEvent.iCode=LafListBox::MapKeyCode(aKeyEvent,aType);
    _AKNTRACE_FUNC_EXIT;
    return DoOfferKeyEventL(keyEvent,aType);
    }

TBool IsSelectionMarkKeys(TInt aCode, TInt aScanCode, TBool aWesternVariant)
    {
    return aCode == EKeyUpArrow   || 
           aCode == EKeyDownArrow ||
           aCode == EKeyOK        ||
        /* aCode == EKeyEnter     || */
           (aCode == 0 && aScanCode == EStdKeyLeftShift)  ||
           (aCode == 0 && aScanCode == EStdKeyRightShift) ||           
           (aCode == 0 && aScanCode == EStdKeyRightCtrl)  ||
           (!aWesternVariant && (aCode == 0 && aScanCode == EStdKeyHash));
    }

TKeyResponse CEikListBox::DoOfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {
    _AKNTRACE_FUNC_ENTER;
    TInt topItemIndex = iView->TopItemIndex();
    if (ItemExists(topItemIndex) == EFalse)
        {
        return (aKeyEvent.iScanCode == EStdKeyYes ? EKeyWasNotConsumed:EKeyWasConsumed);
        }
        
    TInt code = aKeyEvent.iCode;

    // With single click first key event enables highlight
    if ( iListBoxExt && iListBoxExt->EnableHighlightWithKeyEventL(
            topItemIndex, aKeyEvent, aType ) )
        {
        _AKNTRACE_FUNC_EXIT;
        return EKeyWasConsumed;
        }
    
    (void)aType; // to prevent a warning.

    TBool shiftKeyPressed = (aKeyEvent.iModifiers & EModifierShift) ||
                            (aKeyEvent.iModifiers & EModifierLeftShift) ||
                            (aKeyEvent.iModifiers & EModifierRightShift);

    // Downpressed hash key already generates shift modifier and
    // in Chinese variant hash (shift) + movement/MSK should not mark
    if ( iListBoxExt &&
         iListBoxExt->iWesternVariant == EFalse &&
         iListBoxExt->iAknFepHashKeySelection )
        {
        shiftKeyPressed = EFalse;
        }

    TBool controlKeyPressed = (aKeyEvent.iModifiers & EModifierCtrl) || 
                              (aKeyEvent.iModifiers & EModifierRightCtrl);  
    TInt oldCurrentItemIndex = iView->CurrentItemIndex();
    
    TBool enterKeyPressed=EFalse;
    TBool escapeKeyPressed=EFalse;
    TBool sideBarKeyPressed=EFalse;
    TBool switchMSK=EFalse; // for mark/unmark in selection lists
    
    // if we have markable list and either shift, ctrl or hash is long pressed
    // down, we will enter selection (marking) mode, where MSK is Mark/Unmark
    if( iListBoxExt && (iListBoxFlags & EMultipleSelection) &&
        (iListBoxFlags & EShiftEnterMarks) &&
         aType == EEventKeyDown &&
         ( (iListBoxExt->iWesternVariant &&
            iListBoxExt->iAknFepHashKeySelection && 
            iListBoxExt->iQwertyMode == EFalse && 
            aKeyEvent.iScanCode == EStdKeyHash)  ||
         aKeyEvent.iScanCode == EStdKeyLeftShift ||
         aKeyEvent.iScanCode == EStdKeyRightShift ||
         aKeyEvent.iScanCode == EStdKeyLeftCtrl ||
         aKeyEvent.iScanCode == EStdKeyRightCtrl ) )
        {
        iListBoxExt->StartLongPressTimerL();
        iListBoxExt->iShortHashMark = ETrue;        
        iListBoxExt->iShiftKeyPressed = ETrue;        
        }

    if( iListBoxExt && (iListBoxFlags & EMultipleSelection) &&
        (iListBoxFlags & EShiftEnterMarks) &&
         aType == EEventKeyUp &&
         ( (iListBoxExt->iWesternVariant &&
            iListBoxExt->iAknFepHashKeySelection && 
            iListBoxExt->iQwertyMode == EFalse && 
            aKeyEvent.iScanCode == EStdKeyHash)  ||
         aKeyEvent.iScanCode == EStdKeyLeftShift ||
         aKeyEvent.iScanCode == EStdKeyRightShift ||
         aKeyEvent.iScanCode == EStdKeyLeftCtrl ||
         aKeyEvent.iScanCode == EStdKeyRightCtrl ) )
        {
        iListBoxExt->iShiftKeyPressed = EFalse;
        if ( iListBoxExt->iLongPressTimer &&
             iListBoxExt->iLongPressTimer->IsActive() )
            {
            iListBoxExt->iLongPressTimer->Cancel();
            }
        if( iListBoxExt->iSelectionModeEnabled )
            {
            ChangeSelectionMode( EFalse );
            iListBoxExt->iSelectionModeEnabled = EFalse;
            View()->ClearSelectionAnchorAndActiveIndex();
            }
        }


    // SERIES60 LAF
    CListBoxView::TSelectionMode selectionMode = CListBoxView::ENoSelection;
    if (iListBoxFlags & EMultipleSelection)
        {
        if ((shiftKeyPressed || controlKeyPressed) && iListBoxFlags & EShiftEnterMarks && aType == EEventKey)
            {
            __KeyDebug(ETrue, "shift + enter marks");
            View()->SetAnchor(View()->CurrentItemIndex());
            selectionMode = CListBoxView::EDisjointMarkSelection;
            }
        else
            {
            selectionMode = CListBoxView::ENoSelection;
            UpdateMarkUnmarkMSKL();
            if ( iListBoxExt 
                 && IsSelectionMarkKeys( code, aKeyEvent.iScanCode, iListBoxExt->iWesternVariant ) ) 
                {
                __KeyDebug(ETrue, "SelectionMarkKey")
                View()->ClearSelectionAnchorAndActiveIndex();
                }
            }
        }


    // CAknGrid marking is implemeted in avkon.dll. But we still need to disable short
    // hash mark in here.
    if ( iListBoxExt && iListBoxFlags & EMultipleSelection && 
         iListBoxFlags & EShiftEnterMarks && aType == EEventKeyUp )
        {
        if ( aKeyEvent.iScanCode == EStdKeyLeftArrow ||
             aKeyEvent.iScanCode == EStdKeyUpArrow ||
             aKeyEvent.iScanCode == EStdKeyRightArrow ||
             aKeyEvent.iScanCode == EStdKeyDownArrow )
            {
            iListBoxExt->iShortHashMark = EFalse;
            }
        // for some applications this is the only way to catch marking with MSK
        if ( aKeyEvent.iScanCode == EStdKeyDevice3 )
            {
            iListBoxExt->iShortHashMark = EFalse;
            }
        }


    TInt oldMatcherCursorPos = iView->MatcherCursorPos();
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    // LISTBOX EFFECTS IMPLEMENTATION
    // 
    // Fetch internal listbox transition API.
    //
    MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( iView->iGc );
#endif //RD_UI_TRANSITION_EFFECTS_LIST
    
    switch (code)
        {
        case EKeyPrevious:
            {
            _AKNTRACE( "EKeyPrevious" );
            const TBool disableRedraw = aKeyEvent.iRepeats;
            
            TBool redrawDisabled = iView->RedrawDisabled();
            if ( disableRedraw )
                {
                iView->SetDisableRedraw(ETrue);
                }
            
            TInt count = 1 + aKeyEvent.iRepeats;
            TInt currentItemIndex = iView->CurrentItemIndex();
            if( ( currentItemIndex - count) < 0)
                {
                count = currentItemIndex;
                //  moveto = CListBoxView::ECursorLastItem;
                }
            if ( !count )
                {
                  count = 1;
                }  


            for ( TInt ii = 0; ii < count; ii++ )
                {
                CListBoxView::TCursorMovement moveto = CListBoxView::ECursorPreviousItem;
                if (iListBoxFlags & EPageAtOnceScrolling) 
                    { 
                    moveto = CListBoxView::ECursorPrevScreen; 
                    }

                TInt currentItemIndex = iView->CurrentItemIndex();
                if(!(iListBoxFlags & EPopout) && (currentItemIndex==0 || currentItemIndex==-1))
                    {
                    if (iListBoxFlags & ELoopScrolling)
                        {
                        moveto = CListBoxView::ECursorLastItem;
                        }
                    else
                        {
                        break;
                        }
                    }
                iView->MoveCursorL(moveto, selectionMode);
                ClearMatchBuffer();
                }

            if ( disableRedraw )
                {
                iView->SetDisableRedraw(redrawDisabled);
                if ( !redrawDisabled )
                    {
                    DrawNow();
                    }
                }
                
            if (iListBoxFlags & EMultipleSelection)
                {
                switchMSK = ETrue; // we need to check MSK later
                }
            }
            if(AknLayoutUtils::PenEnabled())
                {
                // update scroll bar thumbs here, because it is needed when scrolled.   
                UpdateScrollBarThumbs();
                }
            break;
        case EKeyNext:
            {
            _AKNTRACE( "EKeyNext" );
            const TBool disableRedraw = aKeyEvent.iRepeats;
            TBool redrawDisabled = iView->RedrawDisabled();
            if ( disableRedraw )
                {
                iView->SetDisableRedraw(ETrue);
                }
            
            TInt count = 1 + aKeyEvent.iRepeats;
            TInt currentItemIndex = iView->CurrentItemIndex();
            if(currentItemIndex + count > Model()->NumberOfItems()-1 )
                {
                count = ( Model()->NumberOfItems() - 1 ) - currentItemIndex;
                }
            if ( !count )
                {
                  count = 1;
                }  

            
            for ( TInt ii = 0; ii < count; ii++ )
                {
                CListBoxView::TCursorMovement moveto = CListBoxView::ECursorNextItem;
                if (iListBoxFlags & EPageAtOnceScrolling) 
                    { 
                    moveto = CListBoxView::ECursorNextScreen; 
                    }
                
                TInt currentItemIndex = iView->CurrentItemIndex();
                if(!(iListBoxFlags & EPopout) && 
                    (currentItemIndex==Model()->NumberOfItems()-1 || currentItemIndex==-1))
                    {
                    if (iListBoxFlags & ELoopScrolling)
                        {
                        moveto = CListBoxView::ECursorFirstItem;
                        }
                    else
                        {
                        break;
                        }
                    }
                iView->MoveCursorL(moveto, selectionMode);
                ClearMatchBuffer();
                }

            if ( disableRedraw )
                {
                iView->SetDisableRedraw(redrawDisabled);
                if ( !redrawDisabled )
                    {
                    DrawNow();
                    }
                }
                
            if (iListBoxFlags & EMultipleSelection)
                {
                switchMSK = ETrue; // we need to check MSK later
                }
            }
            if(AknLayoutUtils::PenEnabled())
                {
                // update scroll bar thumbs here, because it is needed when scrolled.   
                UpdateScrollBarThumbs();
                }
            break;
        case EKeyApplicationF:
            // avkonenv can send these events to listbox.
            // CR PKEA-4YSASZ
            _AKNTRACE( "EKeyApplicationF" );
            if (SelectionIndexes()->Count()==0)
                {
                TInt currentItem = View()->CurrentItemIndex();
                if (currentItem >= 0)
                    {
                    View()->SelectItemL(currentItem);
                    }
                }
            _AKNTRACE_FUNC_EXIT;
            return EKeyWasConsumed;
        case EKeyUpArrow:
            {
            _AKNTRACE( "EKeyUpArrow" );
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
            // LISTBOX EFFECTS IMPLEMENTATION
            // 
            // Set type of momement
            //
            if ( transApi )
                {
                transApi->SetMoveType( MAknListBoxTfxInternal::EListMoveUp );
                }
#endif //RD_UI_TRANSITION_EFFECTS_LIST

            // Note, in Series 60  we always eat uparrow and downarrow 
            // in lists, even though it does not really change list state.
            CListBoxView::TCursorMovement moveto = CListBoxView::ECursorPreviousItem;
            if (iListBoxFlags & EPageAtOnceScrolling) 
                { 
                moveto = CListBoxView::ECursorPrevScreen; 
                }
            if(!(iListBoxFlags & EPopout) && (oldCurrentItemIndex==0 || oldCurrentItemIndex==-1))
                {
                if (iListBoxFlags& ELoopScrolling)
                    {
                    moveto = CListBoxView::ECursorLastItem;
                    }
                else if ( ScrollingDisabled() && topItemIndex == 0 )
                    {
                    _AKNTRACE_FUNC_EXIT;
                    return( EKeyWasConsumed );
                    }
                }
		
            if ( ScrollingDisabled() 
                || ( iListBoxExt && !iListBoxExt->MovePhysicsCursorL( moveto, selectionMode ) ) )
                {
                iView->MoveCursorL(moveto, selectionMode);
                }
            ClearMatchBuffer();
            if( iListBoxFlags & EMultipleSelection )
                {
                switchMSK = ETrue; // we need to check MSK later
                }
            }
            if( AknLayoutUtils::PenEnabled() )
                {
                // update scroll bar thumbs here, because it is needed when scrolled.   
                UpdateScrollBarThumbs();
                }
            break;
        case EKeyDownArrow:
            {
            _AKNTRACE( "EKeyDownArrow" );
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
            // LISTBOX EFFECTS IMPLEMENTATION
            // 
            // Set type of momement
            //
            if ( transApi )
                {
                transApi->SetMoveType( MAknListBoxTfxInternal::EListMoveDown );
                }
#endif //RD_UI_TRANSITION_EFFECTS_LIST
            
            CListBoxView::TCursorMovement moveto = CListBoxView::ECursorNextItem;
            if (iListBoxFlags & EPageAtOnceScrolling)  
                { 
                moveto = CListBoxView::ECursorNextScreen; 
                }
            if(!(iListBoxFlags & EPopout) && 
                (oldCurrentItemIndex==Model()->NumberOfItems()-1 || oldCurrentItemIndex==-1))
                {
                if (iListBoxFlags & ELoopScrolling)
                    {
                    moveto = CListBoxView::ECursorFirstItem;
                    }
                else if ( ScrollingDisabled() && ( topItemIndex != 0 ) )
                    {
                    _AKNTRACE_FUNC_EXIT;
                    return(EKeyWasConsumed);    
                    }
                }

            if ( ScrollingDisabled() 
                || ( iListBoxExt && !iListBoxExt->MovePhysicsCursorL( moveto, selectionMode ) ) )
                {
                iView->MoveCursorL(moveto, selectionMode);
                }
            ClearMatchBuffer();
            if (iListBoxFlags & EMultipleSelection)
                {
                switchMSK = ETrue; // we need to check MSK later
                }
            }
            if(AknLayoutUtils::PenEnabled())
                {
                // update scroll bar thumbs here, because it is needed when scrolled.   
                UpdateScrollBarThumbs();
                }
            break;
        case EKeyEnter:
        case EKeyOK:
            {
            _AKNTRACE( "EKeyEnter or EKeyOK" );
            if (aKeyEvent.iRepeats != 0) 
                {
                break;
                }
            // Series 60  case where ok or shift+ok is pressed
            if (iListBoxFlags & EMultipleSelection)
                {
                if ((shiftKeyPressed || controlKeyPressed) && iListBoxFlags & EShiftEnterMarks 
                    || iListBoxFlags & EEnterMarks)
                    {
                    __KeyDebug(ETrue, "shift+ok or ok in markable/multiselection");

                    iView->UpdateSelectionL(CListBoxView::EDisjointSelection);
                    iListBoxFlags |= EStateChanged;
                    switchMSK = ETrue;
                    break;
                    }
            
                // Markable list CR JLEO-4VQJ75
                if (!shiftKeyPressed && iListBoxFlags & EShiftEnterMarks)
                    { 
                    // enter key pressed on markable list without shift
                    if ( SelectionIndexes()->Count() > 0 && !MarkingMode() )
                        { 
                        // when there's marked items, should open options menu.
                        __KeyDebug(ETrue, "ok without shift => ok options menu");

                        CEikMenuBar *bar;
                        MopGetObject(bar);
                        if (bar) 
                            {
                            bar->TryDisplayMenuBarL();
                            }
                        _AKNTRACE_FUNC_EXIT;
                        return EKeyWasConsumed;
                        }
                    }
                }

            // Series 60  ok key
            __KeyDebug(ETrue, "open item");
            enterKeyPressed = ETrue;
            }
            break;
        default:
            if (iListBoxFlags & EIncrementalMatching) 
                {
                if (TChar(aKeyEvent.iCode).IsPrint())
                    {
                    MatchTypedCharL(aKeyEvent.iCode);
                    }
                else
                    {
                    _AKNTRACE_FUNC_EXIT;
                    return (aKeyEvent.iScanCode == EStdKeyYes ? 
                        EKeyWasNotConsumed : EKeyWasConsumed);
                    }
                }
            break;
        }
    //
    // Switch/case ends here
    //
    if(switchMSK)
        {
        if( iListBoxExt && selectionMode == CListBoxView::EDisjointMarkSelection )
            {
             // if hash and either up or down pressed -> no short marking
            iListBoxExt->iShortHashMark = EFalse;
            }
        UpdateMarkUnmarkMSKL();
        }

    if(!AknLayoutUtils::PenEnabled())
        {
        // do update only when needed and in correct place. (prevents flicker). 
        // This place is called three times for every button event (down, key-event and up)     
        UpdateScrollBarThumbs();
        }

    if (oldCurrentItemIndex != iView->CurrentItemIndex())
        {
        iListBoxFlags |= EStateChanged;
        DrawMatcherCursor();
        }
    else if (oldMatcherCursorPos != iView->MatcherCursorPos() && IsMatchBuffer())
        {
        DrawMatcherCursor();
        }

    if (iListBoxFlags & EStateChanged)
        {
        ReportEventL(MCoeControlObserver::EEventStateChanged);
        iListBoxFlags &= (~EStateChanged);
        }

    if (enterKeyPressed)
        {
        ReportListBoxEventL(MEikListBoxObserver::EEventEnterKeyPressed);
        if (iListBoxFlags & EPopout)
            {
            ReportEventL(MCoeControlObserver::EEventRequestExit);
            }
        }

    if (escapeKeyPressed || sideBarKeyPressed)
        {
        if (iListBoxFlags & EPopout)
            {
            ReportEventL(MCoeControlObserver::EEventRequestCancel);
            }
        }

    if (sideBarKeyPressed)
        {
        _AKNTRACE_FUNC_EXIT;
        return(EKeyWasNotConsumed);
        }
        
    // This code block watches for hash key presses, and simulates shift + ok 
    // if short hash key presses are used for selections. The events are simulated 
    // only if a markable list is active, otherwise the simulated event might open 
    // the selected item, which we don't want.    
    if((iListBoxFlags & EMultipleSelection) && (iListBoxFlags & EShiftEnterMarks) &&
        iListBoxExt && iListBoxExt->iWesternVariant &&
        iListBoxExt->iAknFepHashKeySelection && 
        iListBoxExt->iQwertyMode == EFalse && 
        aType == EEventKeyUp && aKeyEvent.iScanCode == EStdKeyHash &&
        IsFocused() )
        {
        if( iListBoxExt->iShortHashMark )
            {
            TKeyEvent keyEvent;
            keyEvent.iCode = EKeyDevice3;
            keyEvent.iScanCode = EStdKeyDevice3;
            keyEvent.iRepeats = 0;
            keyEvent.iModifiers = EModifierShift;             
            CCoeEnv::Static()->SimulateKeyEventL(keyEvent, EEventKey);
            }
        else
            {
            // some items has been un/marked with hash+up or down
            // so don't do short hash mark - just clear selection mode
            View()->ClearSelectionAnchorAndActiveIndex();
            }
        }
    
    if ( aKeyEvent.iScanCode == EStdKeyYes )
        {
        _AKNTRACE( "EStdKeyYes" );
        _AKNTRACE_FUNC_EXIT;
        return EKeyWasNotConsumed;
        }
    _AKNTRACE_FUNC_EXIT;    
    return(EKeyWasConsumed);
    }

void CEikListBox::UpdateMarkUnmarkMSKL() const
    {
    // for markable lists if MSK is either mark/unmark
    // and highlighted item has changed, try to switch
    // MSK according to item's selection state
    _AKNTRACE_FUNC_ENTER;
    CEikButtonGroupContainer *bgc;
    CCoeControl* MSK(NULL);
    CEikCba* cba(NULL);
    CONST_CAST(CEikListBox*,this)->MopGetObject(bgc);
    if ( bgc )
        {
        cba = ( static_cast<CEikCba*>( bgc->ButtonGroup() ) ); // downcast from MEikButtonGroup
        if ( cba )
            {
            MSK = cba->Control(3); // MSK's position is 3
            }
        }
    TInt newResourceId(NULL);
    if ( MSK && ( cba->ControlId( MSK ) == EAknSoftkeyMark ) &&
        View()->ItemIsSelected( CurrentItemIndex() ) )
        {
        newResourceId = R_AVKON_SOFTKEY_UNMARK;
        }
    if ( MSK && ( cba->ControlId( MSK ) == EAknSoftkeyUnmark ) &&
        !View()->ItemIsSelected( CurrentItemIndex() ) )
        {
        newResourceId = R_AVKON_SOFTKEY_MARK;
        }

    if ( newResourceId )
        {
        bgc->SetCommandL( 3,newResourceId );
        cba->DrawNow();
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::UpdateScrollBarThumbs() const
    {
    _AKNTRACE_FUNC_ENTER;
    if (!iSBFrame)
        {
        _AKNTRACE_FUNC_EXIT;        
        return;
        }
    TInt hThumbPos=iView->HScrollOffset();
    TInt vThumbPos=iView->CurrentItemIndex();

    if ((iListBoxFlags & EPageAtOnceScrolling) || (iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan))
        {
        TInt delta = iView->ItemHeight() + iView->ItemOffsetInPixels();
        vThumbPos = iView->TopItemIndex()*iView->ItemHeight() - iView->ItemOffsetInPixels();
        }

    iSBFrame->MoveHorizThumbTo(hThumbPos);
    iSBFrame->MoveVertThumbTo(vThumbPos);
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::ReportListBoxEventL(MEikListBoxObserver::TListBoxEvent aEvent)
    {
    _AKNTRACE_FUNC_ENTER;
    switch ( aEvent )
        {
        case MEikListBoxObserver::EEventFlickStarted:
        case MEikListBoxObserver::EEventPanningStarted:
            {
            if ( iListBoxExt && ( iListBoxExt->iWorldSize.iHeight 
                    <= iListBoxExt->iViewSize.iHeight ) )
                {
                return; 
                }
            iItemDrawer->SetFlags( CListItemDrawer::EDisableMarquee );
            if ( iListBoxExt )
                { 
                if ( aEvent == MEikListBoxObserver::EEventFlickStarted )
                    {
                    iListBoxExt->SetFlickOngoing( ETrue );
                    }
                else 
                    {
                    iListBoxExt->SetPanningOngoing( ETrue );
                    }
                }
            break;
            }
            
        case MEikListBoxObserver::EEventFlickStopped:
        case MEikListBoxObserver::EEventPanningStopped:
            {
            if ( iListBoxExt && ( iListBoxExt->iWorldSize.iHeight 
                    <= iListBoxExt->iViewSize.iHeight ) )
                {
                return; 
                }
            iItemDrawer->ClearFlags( CListItemDrawer::EDisableMarquee );
            if ( iListBoxExt )
                { 
                if ( aEvent == MEikListBoxObserver::EEventFlickStopped )
                    {   
                    iListBoxExt->SetFlickOngoing( EFalse );                    
                    }
                else 
                    {
                    iListBoxExt->SetPanningOngoing( EFalse );
                    }
                }            
            break;
            }
        }
    
    if ( iListBoxObserver )
        {
        TBool allowed = ETrue;

        if ( iListBoxExt && iListBoxExt->iPhysics
             && aEvent != MEikListBoxObserver::EEventFlickStopped )
            {
            allowed = iListBoxExt->iClickEventsAllowed;
            }

        if ( MarkingMode() && allowed )
            {
            switch ( aEvent )
                {
                case MEikListBoxObserver::EEventItemSingleClicked:
                case MEikListBoxObserver::EEventEnterKeyPressed:
                    {                   
                    TInt index = CurrentItemIndex();
                    if ( index >= 0 && 
                         !iItemDrawer->Properties(index).IsSelectionHidden() )
                        {
                        iView->ToggleItemL( iView->CurrentItemIndex() );
                        }
                    
                    allowed = EFalse;
                    }
                    break;
                    
                default:
                    break;
                }
            }
        
        if ( allowed )
            {
            iListBoxObserver->HandleListBoxEventL(this, aEvent);
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C TInt CEikListBox::HorizontalNudgeValue() const
    {
    return (iView->ViewRect().Width() / KEikListBoxHNudgeSizeAsFractionOfViewRectWidth);
    }

EXPORT_C CEikScrollBarFrame* const CEikListBox::ScrollBarFrame()
    { 
    return iSBFrame;
    }

EXPORT_C void CEikListBox::SetScrollBarFrame(CEikScrollBarFrame* aScrollBarFrame, TScrollBarOwnerShip aOwnerShip)
    {
    if (iSBFrameOwned == ENotOwnedExternally) { delete iSBFrame; iSBFrame = 0; }
    iSBFrame = aScrollBarFrame; 
    iSBFrameOwned = aOwnerShip;
    }


// ---------------------------------------------------------------------------
// Scrolls the view by the given amount of pixels while keeping the
// physics parameters up-to-date.
// ---------------------------------------------------------------------------
//
EXPORT_C void CEikListBox::HandlePhysicsScrollEventL( TInt aDeltaPixels )
    {    
    _AKNTRACE_FUNC_ENTER;
    if ( iListBoxExt && iListBoxExt->iPhysics )
        {
        iListBoxExt->InitPhysicsL();
        
        TPoint newPosition( iListBoxExt->iViewPosition.iX,
                            aDeltaPixels + iListBoxExt->iViewPosition.iY );
        iListBoxExt->ViewPositionChanged( newPosition );
        }
    _AKNTRACE_FUNC_EXIT;
    }


EXPORT_C void CEikListBox::HandleScrollEventL(CEikScrollBar* aScrollBar,TEikScrollEvent aEventType)
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iListBoxExt && iListBoxExt->iSingleClickEnabled )
        {
        iListBoxExt->EnableHighlight( EFalse );
        iView->DrawItem( iView->CurrentItemIndex() );
        }

    // When the scrollbar is scrolling, marquee will be disabled 
    // temporarily for performance reason. And before leaving this function,
    // this flag must be cleaned.
    iItemDrawer->SetFlags( CListItemDrawer::EDisableMarquee );

    TInt oldThumbPos = (aEventType & KEikScrollEventBarMask) ? iView->HScrollOffset() : iView->TopItemIndex();
    TInt newThumbPos = aScrollBar->ThumbPosition();
    
    TInt pageSize = 0;    
    TInt maxThumbPos = 0;
    
    if ( aScrollBar->Model()->ScrollBarModelType() == 
         TEikScrollBarModel::EAknDoubleSpanScrollBarModel )
        {
        const TAknDoubleSpanScrollBarModel* dblSpanModel = 
            static_cast<const TAknDoubleSpanScrollBarModel*>( 
                aScrollBar->Model() );
        pageSize = dblSpanModel->WindowSize();
        maxThumbPos = dblSpanModel->ScrollSpan() - 
            dblSpanModel->WindowSize();
        }
    else
        {
        pageSize = aScrollBar->Model()->iThumbSpan;
        maxThumbPos = aScrollBar->Model()->MaxThumbPos();
        }  
    
    TBool update = ETrue; // for the case EEikScrollThumbRelease so that after it there is now update.
    TInt newThumbPosBeforeCorrecting = newThumbPos;

    switch (aEventType & KEikScrollEventBarMask)
        { 
    case KEikScrollEventFromHBar:
        switch (aEventType)
            {
        case EEikScrollLeft:
            newThumbPos -= HorizontalNudgeValue();
            break;
        case EEikScrollRight:
            newThumbPos += HorizontalNudgeValue();
            break;
        case EEikScrollPageLeft:
            newThumbPos -= pageSize;
            break;
        case EEikScrollPageRight:
            newThumbPos += pageSize;
            break;
        case EEikScrollThumbDragHoriz:
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
            SuspendEffects( ETrue );
#endif // RD_UI_TRANSITION_EFFECTS_LIST
            if(AknLayoutUtils::PenEnabled())
                {
                break;
                }
        case EEikScrollThumbReleaseHoriz:
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
            SuspendEffects( EFalse );
#endif // RD_UI_TRANSITION_EFFECTS_LIST
            // in the case of drag events, the scrollbar automatically updates its thumb pos...
            if(AknLayoutUtils::PenEnabled())
                {
                update = EFalse;            
                }
            break;
        default:
            break;
            }
        newThumbPos = Max(0, Min(newThumbPos, maxThumbPos));
        iView->HScroll(newThumbPos - oldThumbPos);
        if (aEventType != EEikScrollThumbDragHoriz)
            aScrollBar->SetModelThumbPosition(iView->HScrollOffset());
        break;
        
    case KEikScrollEventFromVBar:
        switch (aEventType)
            {
        case EEikScrollUp:
                if ( oldThumbPos == 0  && (iListBoxFlags & ELoopScrolling))
                    {
                    newThumbPos = maxThumbPos;              
                    }
            break;
                
        case EEikScrollDown:
                if ( oldThumbPos == maxThumbPos && (iListBoxFlags & ELoopScrolling) )
                    {
                    newThumbPos = 0;                
                    }
            break;
                
        case EEikScrollPageUp:
            break;
                
        case EEikScrollPageDown:
            break;
                
        case EEikScrollThumbDragVert:
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
            SuspendEffects( ETrue );
#endif // RD_UI_TRANSITION_EFFECTS_LIST
            if(AknLayoutUtils::PenEnabled())
                {
                break;
                }
        case EEikScrollThumbReleaseVert:
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
            SuspendEffects( EFalse );
#endif // RD_UI_TRANSITION_EFFECTS_LIST
            // in the case of drag events, the scrollbar automatically updates its thumb pos...
            if(AknLayoutUtils::PenEnabled())
                {
                update = EFalse;            
                }
            break;
                
        default:
            break;
            }           
            
        newThumbPos = Max(0, Min(newThumbPos, maxThumbPos));
        
        if ( (!AknLayoutUtils::PenEnabled()) || update )
            {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
            MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal(
                                                                    iView->iGc );
            TBool effects = transApi && !transApi->EffectsDisabled();

            if ( effects )
                {
                transApi->SetMoveType( newThumbPos < oldThumbPos ?
                                       MAknListBoxTfxInternal::EListScrollUp :
                                       MAknListBoxTfxInternal::EListScrollDown );
                }
#endif
            
        if ( iListBoxExt && iListBoxExt->iPhysics )
            {
            iListBoxExt->InitPhysicsL();
            TInt deltaPixels = newThumbPos;
    
#ifdef _DEBUG
                RDebug::Print( _L( "CListBox::HandleScrollEventL, deltaPixels = %d" ), deltaPixels );
#endif // _DEBUG
            
            TPoint newPosition( iListBoxExt->iViewPosition.iX, deltaPixels + iView->ViewRect().Height() / 2 );
            iListBoxExt->ViewPositionChanged( newPosition );            
            }
        else
            {
            iView->VScrollTo(newThumbPos/iView->ItemHeight());
            }

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
            if ( effects )
                {
                transApi->Draw( Rect() );
                }
#endif
            if (aEventType != EEikScrollThumbDragVert)
                {               
                aScrollBar->SetModelThumbPosition(iView->TopItemIndex()*iView->ItemHeight() - iView->ItemOffsetInPixels());
                }
            }
        
        // If the event has changed thumb position, then update scroll bar
        // unless physics is used. In that case thumb is updated via 
        // CEikListBox::ScrollView.
        if ( AknLayoutUtils::PenEnabled() 
             && newThumbPos != newThumbPosBeforeCorrecting 
             && iListBoxExt && !iListBoxExt->iPhysics )
            {
            UpdateScrollBarThumbs();
            }
        }
    iItemDrawer->ClearFlags(CListItemDrawer::EDisableMarquee);
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::HandleDragEventL(TPoint aPointerPos)
    {
    // return immediately if kinetic scrolling is enabled, this needs to be modified afterwards
    _AKNTRACE_FUNC_ENTER;
    if ( iListBoxExt && iListBoxExt->iPhysics )
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    
    if (!(iListBoxFlags & ELeftDownInViewRect))
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    
    TRect viewRect(iView->ViewRect());
    if( !AknLayoutUtils::PenEnabled() )
        {
        // We do not want highlight to move when dragged left/rightside of lists
        if ((aPointerPos.iX > viewRect.iBr.iX) || (aPointerPos.iX < viewRect.iTl.iX))
            {
            aPointerPos.iX = viewRect.iTl.iX;
            }
        }
    TInt itemIndex( 0 );
    TBool pointerIsOverAnItem = iView->XYPosToItemIndex(aPointerPos, itemIndex);
    CListBoxView::TSelectionMode selectionMode = CListBoxView::ENoSelection;
    TInt oldCurrentItemIndex = iView->CurrentItemIndex();
    TInt oldTopItemIndex = iView->TopItemIndex();
    TInt oldBottomItemIndex = iView->BottomItemIndex();
    TInt topItemIndex ( oldTopItemIndex );
    TInt bottomItemIndex( oldBottomItemIndex );
    TInt interval = iListBoxExt->iInterval;
    TInt speed = 0;
    const TInt KBrakeL1 = 5;
    const TInt KBrakeL2 = 10;
    TInt lastItem = iModel->NumberOfItems() - 1;
    TInt yDistance = aPointerPos.iY - iListBoxExt->iLastPoint.iY;
    if(pointerIsOverAnItem && (itemIndex == oldBottomItemIndex) && yDistance > 0 )
        {
        speed = 1;
        }
    else if(pointerIsOverAnItem && (itemIndex == oldTopItemIndex) && yDistance < 0 )
        {
        speed = -1;
        }
    else if( pointerIsOverAnItem && 
             oldTopItemIndex < itemIndex && 
             oldBottomItemIndex > itemIndex )
        {
        // highlight the item
        speed = 0;    
        }
    else if (aPointerPos.iY < viewRect.iTl.iY)
        {
        speed = - Min((( viewRect.iTl.iY + ItemHeight()) - aPointerPos.iY ) 
                                    / ( ItemHeight() / 2 ) * iListBoxExt->iStepSpeed, 
                                    iListBoxExt->iMaxSpeed );
        if ( oldTopItemIndex <= KBrakeL1 )
        {
            speed = -1;
        }
        else if ( oldTopItemIndex + speed < KBrakeL1)
        {
            speed = KBrakeL1 - oldTopItemIndex;
            }
        }
    else if (aPointerPos.iY > viewRect.iBr.iY)
                {
        speed = Min(( aPointerPos.iY - ( viewRect.iBr.iY - ItemHeight())) 
                                  / (ItemHeight() / 2) * iListBoxExt->iStepSpeed, 
                                  iListBoxExt->iMaxSpeed );
        if ( oldBottomItemIndex >= iModel->NumberOfItems() - 1 - KBrakeL1 )
                    {
            speed = 1;
                }
        else if ( oldBottomItemIndex + speed > lastItem - KBrakeL1 )
            {
            speed = lastItem - oldBottomItemIndex - KBrakeL1;
            }
        }
    // Brake level 2
    if ( ( speed < 0 && oldTopItemIndex + speed < KBrakeL2 )
         || ( speed > 0 && oldBottomItemIndex + speed > lastItem - KBrakeL2 ))
        {
        interval *= 2;        
        }
            
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal(
                                                                iView->iGc );
    TBool effects = transApi && !transApi->EffectsDisabled();
#ifdef RD_UI_TRANSITION_EFFECTS_TOUCH_P2
    TBool edge = EFalse;
#endif // RD_UI_TRANSITION_EFFECTS_TOUCH_P2
#endif // RD_UI_TRANSITION_EFFECTS_LIST
    if ( !ItemExists( oldTopItemIndex + speed ) ||
         !ItemExists( oldBottomItemIndex + speed))
        {
        speed = 0;
        }
    iListBoxExt->iSpeed = speed;
    if ( speed != 0 )
        {
        topItemIndex = oldTopItemIndex + speed;
        
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
        if ( !effects )
            {
#endif // RD_UI_TRANSITION_EFFECTS_LIST
        iView->SetTopItemIndex( topItemIndex );
        UpdateScrollBarThumbs();
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
            }
#endif // RD_UI_TRANSITION_EFFECTS_LIST
        if ( pointerIsOverAnItem ) 
            {
            Window().RequestPointerRepeatEvent(interval, 
                                               viewRect );
            }
        // Pointer outside of list
        else
            {
            TRect screenRect(TPoint(-1000, -1000), TPoint(1000, 1000));
            TRect ignoreDragRect;
            
            if ( AknLayoutUtils::PenEnabled() &&
            ( (aPointerPos.iY < viewRect.iTl.iY) || (aPointerPos.iY > viewRect.iBr.iY) ) && 
            !( (aPointerPos.iX > viewRect.iBr.iX) || (aPointerPos.iX < viewRect.iTl.iX) ) ) 
                {
                if (aPointerPos.iY < viewRect.iTl.iY)
                    {
                    ignoreDragRect.SetRect( screenRect.iTl, 
                                            TPoint(screenRect.iBr.iX, viewRect.iTl.iY ));
                    }
                else
                    {
                    ignoreDragRect.SetRect( TPoint( screenRect.iTl.iX, viewRect.iBr.iY), 
                                            screenRect.iBr );
                    }
                }
            else if ( !AknLayoutUtils::PenEnabled() &&
              ((aPointerPos.iY < viewRect.iTl.iY) || (aPointerPos.iY > viewRect.iBr.iY)) )
                {
                if (aPointerPos.iY < viewRect.iTl.iY)
                    {
                    ignoreDragRect.SetRect( screenRect.iTl, 
                                            TPoint( screenRect.iBr.iX, viewRect.iTl.iY ));
                    }
                else
                    {
                    ignoreDragRect.SetRect( TPoint( screenRect.iTl.iX, viewRect.iBr.iY), 
                                            screenRect.iBr);
                    }
                }
            Window().RequestPointerRepeatEvent( interval, 
                                                ignoreDragRect );
            }
            
        pointerIsOverAnItem = iView->XYPosToItemIndex(aPointerPos, itemIndex);
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
        if ( effects )
            {
            bottomItemIndex = topItemIndex + oldBottomItemIndex - oldTopItemIndex;
            }
        else
            {
#endif // RD_UI_TRANSITION_EFFECTS_LIST
            topItemIndex = iView->TopItemIndex();
            bottomItemIndex = iView->BottomItemIndex();
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
            }
#endif // RD_UI_TRANSITION_EFFECTS_LIST
        // When scrolling don't focus first / last item unless it's really
        // the first / last item of the list
        if ( speed > 0 /*&& itemIndex == bottomItemIndex*/ )
            {
            if ( ItemExists ( bottomItemIndex +1 ) )
                {
                itemIndex = bottomItemIndex - 1;
                }
                else
                {
                itemIndex = bottomItemIndex;
#ifdef RD_UI_TRANSITION_EFFECTS_TOUCH_P2
                edge = ETrue;
#endif // RD_UI_TRANSITION_EFFECTS_TOUCH_P2
                }
            }
        if ( speed < 0 /*&& itemIndex == topItemIndex*/ )
            {
            if ( ItemExists ( topItemIndex -1 ) )
                {
                itemIndex = topItemIndex + 1;
                }
                else
                {
                itemIndex = topItemIndex;                    
#ifdef RD_UI_TRANSITION_EFFECTS_TOUCH_P2
                edge = ETrue;
#endif // RD_UI_TRANSITION_EFFECTS_TOUCH_P2
                }
            }
        
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
        if ( speed != 0 && !effects )
#else
        if(speed != 0)
#endif // RD_UI_TRANSITION_EFFECTS_LIST
            {
            SetCurrentItemIndex(itemIndex);
            DrawNow();
            }
            
        }
    
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    if ( effects )
        {
        if ( AknLayoutUtils::PenEnabled() &&
             ( iListBoxFlags & ES60StyleMultiselection || 
                ((iListBoxFlags & ES60StyleMarkable) && 
                ( (iListBoxExt->iEventModifiers & EModifierShift) ||
                  (iListBoxExt->iEventModifiers & EModifierCtrl) ))))
            {
            if ( speed == 0 )
                {
                if ( itemIndex == oldCurrentItemIndex )
                    {
                    _AKNTRACE_FUNC_EXIT;
                    return;
                    }
                transApi->SetMoveType( MAknListBoxTfxInternal::EListDrag );
                transApi->BeginRedraw( MAknListBoxTfxInternal::EListNotSpecified,
                                       viewRect );
                iView->SetTopItemIndex( topItemIndex );
                iView->SetItemIndex( itemIndex );
                UpdateSelectionsL( iView, transApi, itemIndex, oldCurrentItemIndex, iListBoxExt->iAnchor, iListBoxExt->iSelect );
                }
#ifdef RD_UI_TRANSITION_EFFECTS_TOUCH_P2
            else if ( edge )
                {
                transApi->SetMoveType( MAknListBoxTfxInternal::EListHitBorder );
                transApi->BeginRedraw( MAknListBoxTfxInternal::EListNotSpecified,
                                       viewRect );
                iView->SetTopItemIndex( topItemIndex );
                iView->SetItemIndex( itemIndex );
                UpdateSelectionsL( iView, transApi, itemIndex, oldCurrentItemIndex, iListBoxExt->iAnchor, iListBoxExt->iSelect );
                }
#endif // RD_UI_TRANSITION_EFFECTS_TOUCH_P2
            else
                {
                transApi->SetMoveType( MAknListBoxTfxInternal::EListDrag );
                transApi->BeginRedraw( MAknListBoxTfxInternal::EListNotSpecified,
                                       viewRect );
                iView->SetTopItemIndex( topItemIndex );
                iView->SetItemIndex( itemIndex );
                UpdateSelectionsL( iView, transApi, itemIndex, oldCurrentItemIndex, iListBoxExt->iAnchor, iListBoxExt->iSelect );
                }            
            }
#ifdef RD_UI_TRANSITION_EFFECTS_TOUCH_P2
        else if ( edge || iListBoxExt->iSpeed == 0 )
#else
        else if ( iListBoxExt->iSpeed == 0 )
#endif
            {
#ifdef RD_UI_TRANSITION_EFFECTS_TOUCH_P2
            if ( iListBoxExt->iSpeed == 0 )
                {
#endif // RD_UI_TRANSITION_EFFECTS_TOUCH_P2
                if ( itemIndex == oldCurrentItemIndex || itemIndex < 0 )
                    {
                    // If itemIndex didn't change or itemIndex doesn't
                    // exist, just return
                    _AKNTRACE_FUNC_EXIT;
                    return;
                    }
                transApi->SetMoveType( MAknListBoxTfxInternal::EListDrag );
#ifdef RD_UI_TRANSITION_EFFECTS_TOUCH_P2
                }
            else
                {
                transApi->SetMoveType( MAknListBoxTfxInternal::EListHitBorder );
                }
#endif // RD_UI_TRANSITION_EFFECTS_TOUCH_P2
            transApi->BeginRedraw( MAknListBoxTfxInternal::EListNotSpecified,
                                   viewRect );
            iView->SetTopItemIndex( topItemIndex );
            iView->SetItemIndex( itemIndex );
            iView->DrawItem( itemIndex );
            iView->DrawItem( oldCurrentItemIndex );
            for ( TInt i = iView->TopItemIndex(); i <= iView->BottomItemIndex(); i++ )
                {
                if ( i != itemIndex && i != oldCurrentItemIndex &&
                     transApi->SetPosition( MAknListBoxTfxInternal::EListItem, iView->ItemPos( i ), i ) != KErrNone )
                    {
                    iView->DrawItem( i );
                    }
                }
            }
        else
            {
            transApi->SetMoveType( MAknListBoxTfxInternal::EListDrag );
            transApi->BeginRedraw( MAknListBoxTfxInternal::EListNotSpecified,
                                   viewRect );
            iView->SetItemIndex( itemIndex );
                iView->DrawItem( oldCurrentItemIndex );
            iView->SetTopItemIndex( topItemIndex );
            transApi->SetPosition( MAknListBoxTfxInternal::EListHighlight, iView->ItemPos( itemIndex ) );
            for ( TInt i = iView->TopItemIndex(); i <= iView->BottomItemIndex(); i++ )
                {
                iView->DrawItem( i );
                }
            }
        transApi->SetPosition( MAknListBoxTfxInternal::EListHighlight, iView->ItemPos( itemIndex ) );
        UpdateScrollBarThumbs();
        if ( AknLayoutUtils::PenEnabled() )
            {
            MTouchFeedback* feedback = MTouchFeedback::Instance();
            // drag feedback, also for viewers
            TBool feedbackNeeded = !(iListBoxFlags & EPageAtOnceScrolling) // editor case
                                || (oldTopItemIndex != topItemIndex || oldBottomItemIndex != bottomItemIndex); // viewer case
            if ( feedback && feedbackNeeded )
                {
                feedback->InstantFeedback( ETouchFeedbackSensitive );
                }
            ReportListBoxEventL( MEikListBoxObserver::EEventItemDraggingActioned );
            }

        transApi->EndRedraw( MAknListBoxTfxInternal::EListNotSpecified );
        _AKNTRACE_FUNC_EXIT;
        return;
        }
#endif // RD_UI_TRANSITION_EFFECTS_LIST

    if (pointerIsOverAnItem)
        {
        // drag event occurred within the listbox
        if ( itemIndex == oldCurrentItemIndex )
            {
            _AKNTRACE_FUNC_EXIT;
            return;
            }
        if ( AknLayoutUtils::PenEnabled() &&
             ( iListBoxFlags & ES60StyleMultiselection || 
                ((iListBoxFlags & ES60StyleMarkable) && 
                ( (iListBoxExt->iEventModifiers & EModifierShift) ||
                  (iListBoxExt->iEventModifiers & EModifierCtrl) ))))
            {
            iView->VerticalMoveToItemL( itemIndex, CListBoxView::EPenMultiselection );
            iListBoxFlags |= EStateChanged;
            }
        else               
            {
            iView->VerticalMoveToItemL( itemIndex, selectionMode );
            UpdateMarkUnmarkMSKL(); 
            }
        UpdateScrollBarThumbs();
        }
    else if (viewRect.Contains(aPointerPos))
        {
        // find item nearest to the pointer pos and make that the current item
        if( iListBoxExt->iIsDownOnItem )
            {
            if( yDistance>0 && itemIndex != oldBottomItemIndex )
                {
                iView->SetCurrentItemIndex( oldBottomItemIndex );
                }
            else if( yDistance<0 && itemIndex != oldTopItemIndex )
                {
                iView->SetCurrentItemIndex( oldTopItemIndex );
                }
            DrawDeferred();
            }
        }
    else if ( AknLayoutUtils::PenEnabled() &&
              ( (aPointerPos.iY < viewRect.iTl.iY) || (aPointerPos.iY > viewRect.iBr.iY) ) && 
              !( (aPointerPos.iX > viewRect.iBr.iX) || (aPointerPos.iX < viewRect.iTl.iX) ) &&
              // Scroll when stulying donw on item other than empty area.
              iListBoxExt->iIsDownOnItem ) 
        {
        // drag event occurred outside the listbox's viewRect

        if ( iListBoxFlags & ES60StyleMultiselection || 
            ((iListBoxFlags & ES60StyleMarkable) && 
                ( (iListBoxExt->iEventModifiers & EModifierShift) ||
                  (iListBoxExt->iEventModifiers & EModifierCtrl) )))
            {
            iView->SetCurrentItemIndex(itemIndex);
            iView->UpdateSelectionL(CListBoxView::EPenMultiselection);          
            iListBoxFlags |= EStateChanged;
            }
        }
    else if ( !AknLayoutUtils::PenEnabled() &&
              ((aPointerPos.iY < viewRect.iTl.iY) || (aPointerPos.iY > viewRect.iBr.iY)) ) 
        {
        // drag event occurred outside the listbox's viewRect
        TRect screenRect(TPoint(-1000, -1000), TPoint(1000, 1000));
        TRect ignoreDragRect;
        TInt oldTopItemIndex = iView->TopItemIndex();
        TInt oldBottomItemIndex = iView->BottomItemIndex();
        if (aPointerPos.iY < viewRect.iTl.iY)
            {
            ignoreDragRect.SetRect(screenRect.iTl, TPoint(screenRect.iBr.iX, viewRect.iTl.iY));
            itemIndex = ItemExists(oldTopItemIndex-1) ? (oldTopItemIndex-1) : oldTopItemIndex;
            }
        else
            {
            ignoreDragRect.SetRect(TPoint(screenRect.iTl.iX, viewRect.iBr.iY), screenRect.iBr);
            itemIndex = ItemExists(oldBottomItemIndex+1) ? (oldBottomItemIndex+1) : oldBottomItemIndex;
            }
 
        SetCurrentItemIndexAndDraw(itemIndex);
        UpdateScrollBarThumbs();
        Window().RequestPointerRepeatEvent( interval, ignoreDragRect);
        }

    if (itemIndex != oldCurrentItemIndex)
        {
        iView->UpdateSelectionL(selectionMode);
 
        if(AknLayoutUtils::PenEnabled())
            {
            MTouchFeedback* feedback = MTouchFeedback::Instance();
            // drag feedback, also for viewers
            TBool feedbackNeeded = !(iListBoxFlags & EPageAtOnceScrolling) // editor case
                                || (oldTopItemIndex != topItemIndex || oldBottomItemIndex != bottomItemIndex); // viewer case
            if ( feedback && feedbackNeeded )
                {
                feedback->InstantFeedback( ETouchFeedbackSensitive );
                }

            ReportListBoxEventL(MEikListBoxObserver::EEventItemDraggingActioned);
            }
 
        iListBoxFlags |= EStateChanged;
        if (IsMatchBuffer())
            {
            ClearMatchBuffer();
            DrawMatcherCursor();
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }

// The function EnableRedraw was declared but never put to use.
//LOCAL_C void EnableRedraw(TAny* aPtr)
//    {
//    CListBoxView& lbv=*(CListBoxView*)aPtr;
//    lbv.SetDisableRedraw(EFalse);
//    }

EXPORT_C void* CEikListBox::ExtensionInterface( TUid /*aInterface*/ )
    {
    return NULL;
    }

EXPORT_C void CEikListBox::HandlePointerEventL(const TPointerEvent& aPointerEvent)
    {
    _AKNTRACE_FUNC_ENTER;

    CheckCreateBufferL(); // don't need to create the full matching buffer here - only the iPressedIndex
    TInt itemIndex( KErrNotFound );
    TPoint pointerPos(aPointerEvent.iPosition);
    TBool pointerIsOverAnItem = iView->XYPosToItemIndex(pointerPos, itemIndex);
    TInt oldCurrentItemIndex;    
    TBool listEmpty = !ItemExists( iView->TopItemIndex() );
    
    // Handle empty list area events
    if ( aPointerEvent.iType == TPointerEvent::EButton1Up &&
            !iListBoxExt->iScrolling && !iListBoxExt->iIsDownOnItem )
        {
        if ( listEmpty )
            {
            // No items, empty list was clicked
            ReportListBoxEventL( MEikListBoxObserver::EEventEmptyListClicked );
            _AKNTRACE_FUNC_EXIT;
            return;
            }
        else if ( !pointerIsOverAnItem )
            {
            // Items exist, empty list area was clicked
            ReportListBoxEventL( MEikListBoxObserver::EEventEmptyAreaClicked );
            _AKNTRACE_FUNC_EXIT;
            return;
            }        
        }     
    else if ( listEmpty )
        {
        // Return always if list empty to avoid tactile feedback
        _AKNTRACE_FUNC_EXIT;
        return;
        }

    if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
        {
        if ( iListBoxExt->iSingleClickEnabled && 
             itemIndex != iView->CurrentItemIndex() )
            {
            iListBoxExt->EnableHighlight( EFalse );
            iView->DrawItem( iView->CurrentItemIndex() );
            }

        iListBoxExt->iFeedbackType = ETouchFeedbackList;
        iListBoxExt->iDoubleClickEventIgnored = EFalse;
        
        if ( !iListBoxExt->iSingleClickEnabled &&
            itemIndex != iView->CurrentItemIndex() )
            {
            iListBoxExt->iFeedbackType = ETouchFeedbackSensitiveList;
            }

        if ( iListBoxExt->iPhysics &&
             iListBoxExt->iPhysics->OngoingPhysicsAction() == CAknPhysics::EAknPhysicsActionFlicking )
            {
            iListBoxExt->iFeedbackType = ETouchFeedbackList;
            }
        }
    iListBoxExt->iEventModifiers = aPointerEvent.iModifiers;
    CListBoxView::TSelectionMode selectionMode = CListBoxView::ENoSelection;
    TBool shiftKeyPressed = EFalse;
    TBool controlKeyPressed = EFalse;

    if (iListBoxFlags & EMultipleSelection)
        {
        // determine selection mode
        if ( iListBoxExt->iShiftKeyPressed )
            {
            shiftKeyPressed = ETrue;
            }
        else
            {
            shiftKeyPressed = (aPointerEvent.iModifiers) & EModifierShift;
            }
        controlKeyPressed = (aPointerEvent.iModifiers) & EModifierCtrl;
        if (shiftKeyPressed)    
            selectionMode = CListBoxView::EContiguousSelection;
        else if (controlKeyPressed)
            selectionMode = CListBoxView::EDisjointSelection;
        }

    TBool s60StyleMultiselection = EFalse;
    TBool s60StyleMarkable = EFalse;

    if (iListBoxFlags & ENoExtendedSelection)
        {
        controlKeyPressed = ETrue;
        selectionMode = CListBoxView::EDisjointSelection;
        }
        
    if (iListBoxFlags & ES60StyleMultiselection )
        {
        s60StyleMultiselection = ETrue;
        selectionMode = CListBoxView::EDisjointSelection;
        }
    else if (iListBoxFlags & ES60StyleMarkable )
        {
        s60StyleMarkable = ETrue;
        }
        
    if ( (aPointerEvent.iModifiers&EModifierDoubleClick)
         && pointerIsOverAnItem && selectionMode == CListBoxView::ENoSelection
         && ( !iListBoxExt->IsInHandleAllPointEventArray( itemIndex ) ))
    {
    // Do not return here if S60StyleMultiselection is used
    if ( !(iListBoxFlags & ES60StyleMultiselection) &&
          !(iListBoxFlags & ES60StyleMarkable) )
        {
        iListBoxExt->iEventModifiers = 0;
        }
    
    if(Buffer()->iPressedIndex == itemIndex)
        {
        Buffer()->iPressedIndex = KEikListBoxInvalidIndex;
        iListBoxExt->iDoubleClickEventIgnored = ETrue;
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    }
    
    TBool simulateOkKey = EFalse;
    
    TBool hasPhysics = ( iListBoxExt && iListBoxExt->iPhysics );
    TBool wasFlicking = EFalse;

    if ( hasPhysics )
        {
        if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
            {
            wasFlicking = ( iListBoxExt->iPhysics
                    && iListBoxExt->iPhysics->OngoingPhysicsAction() ==
                    CAknPhysics::EAknPhysicsActionFlicking );
            }
        if ( HandlePhysicsPointerEventL( aPointerEvent ) )
            {
            _AKNTRACE_FUNC_EXIT;
            return;
            }
        }
                
    switch (aPointerEvent.iType)
        {
        case TPointerEvent::EButton1Down:
            _AKNTRACE("TPointerEvent::EButton1Down");
            // For drag outside listbox
            iListBoxExt->iIsDownOnItem = pointerIsOverAnItem;
            iListBoxExt->iLastPoint = pointerPos;

            // update index of the last down tapped item
            iListBoxExt->iLastDownTappedItem = itemIndex;

            if ((! (Rect().Contains(aPointerEvent.iPosition))) && (iListBoxFlags & EPopout)) 
                {
                ReportEventL(MCoeControlObserver::EEventRequestCancel);
                iListBoxExt->iEventModifiers = 0;
                _AKNTRACE_FUNC_EXIT;
                return;
                }
            if (iView->ViewRect().Contains(aPointerEvent.iPosition))
                iListBoxFlags|=ELeftDownInViewRect;
            else
                {
                iListBoxExt->iEventModifiers = 0;
                _AKNTRACE_FUNC_EXIT;
                return;
                }
        
            oldCurrentItemIndex = iView->CurrentItemIndex();
            Buffer()->iDragToAnotherItem = EFalse; 
            if (pointerIsOverAnItem)
                {
                // check if pressed in the same position, if not reset pressed
                Buffer()->iPressedIndex = (itemIndex==oldCurrentItemIndex ? itemIndex : KEikListBoxInvalidIndex);

                if ( !hasPhysics && !iListBoxExt->iSingleClickEnabled )
                    {
                    iItemDrawer->ClearFlags ( CListItemDrawer::EDisableHighlight );
                    }

                if ( !hasPhysics || !iListBoxExt->HighlightTimerActive() )
                    {   
                    // If single click mode is enabled and no physics enabled,
                    // set highlight visible on pointer down.
                    if ( iListBoxExt->iSingleClickEnabled )
                        {
                        // If flick was stopped - give only tactile feedback
                        if ( !wasFlicking )
                            {
                            iListBoxExt->EnableHighlight( ETrue, ETrue );
                            UpdateHighlightL( itemIndex );
                            CCoeEnv::Static()->WsSession().Finish();
                            }

                        if ( !( ( iListBoxFlags & EViewerFlag ) && 
                                ( iListBoxFlags & EDisableItemSpecificMenu ) ) )
                            {
                            iListBoxExt->ImmediateFeedback( 
                                iListBoxExt->iFeedbackType,
                                TTouchFeedbackType( ETouchFeedbackVibra | 
                                ETouchFeedbackAudio ),
                                aPointerEvent );
                            }

                        if ( !wasFlicking )
                            {
                            ReportListBoxEventL( 
                                    MEikListBoxObserver::EEventPenDownOnItem );
                            iListBoxExt->LongTapPointerEventL( aPointerEvent );
                            }
                        }
                    else
                        {
                        if( itemIndex == oldCurrentItemIndex )
                            {
                            if( !( ( iListBoxFlags & EViewerFlag ) && 
                                    ( iListBoxFlags & EDisableItemSpecificMenu ) ) )
                                {
                                iListBoxExt->ImmediateFeedback( 
							                                   iListBoxExt->iFeedbackType,
														       TTouchFeedbackType( ETouchFeedbackVibra | 
														       ETouchFeedbackAudio ),
														       aPointerEvent );
                               }
							}
                        ReportListBoxEventL( 
                                MEikListBoxObserver::EEventPenDownOnItem );    
                        }
                    }
                else
                    {
                    iListBoxExt->iReportDelayedPenDown = ETrue;
                    iListBoxExt->iDelayedPointerDownEvent = aPointerEvent;
                    }
 
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
                    if ( itemIndex != oldCurrentItemIndex )
                        {
                        MAknListBoxTfxInternal* transApi =
                                    CAknListLoader::TfxApiInternal( iView->iGc );
                        if ( transApi && !transApi->EffectsDisabled() )
                            {
                            transApi->SetMoveType( MAknListBoxTfxInternal::EListTap );
                            }
                        }
#endif
                if ( !( iListBoxFlags & EMultipleSelection ) 
                        || MarkingMode() )
                    {
                    if (itemIndex == oldCurrentItemIndex)
                        {
                        iItemDrawer->SetFlags( CListItemDrawer::EPressedDownState );
                        iView->DrawItem( itemIndex );

                        iListBoxExt->iEventModifiers = 0;
                        _AKNTRACE_FUNC_EXIT;
                        return;
                        }
                    
                    if ( !hasPhysics )
                        {
                        iView->SetItemIndex(itemIndex);
                        iView->DrawItem(oldCurrentItemIndex);
                        iView->DrawItem(itemIndex);
                        }
                    
                    iListBoxFlags |= EStateChanged;
                    }
                else if ( s60StyleMultiselection )
                    {
                    if ( !hasPhysics || !iListBoxExt->HighlightTimerActive() )
                        {
                        iItemDrawer->SetFlags( CListItemDrawer::EPressedDownState );

                        iView->SetItemIndex(itemIndex);
                        iView->DrawItem(oldCurrentItemIndex);
                        iView->DrawItem(itemIndex);
                        iListBoxFlags |= EStateChanged;
                        Buffer()->iPressedIndex = itemIndex;

                        if ( !hasPhysics )
                            {
                            ReportEventL(MCoeControlObserver::EEventStateChanged);
                            }
                        
                        ReportListBoxEventL(MEikListBoxObserver::EEventItemClicked);
                        }
                    else
                        {
                        iListBoxExt->iDelayedMultiselection = ETrue;
                        }
                    }
                else if ( s60StyleMarkable )
                    {
                    if ( !hasPhysics )
                        {
                        iView->SetItemIndex( itemIndex );
                        }
                    else
                        { // shift key will be handled in highlight timer
                        iListBoxExt->iMarkableListMarking = ETrue; 
                        if ( shiftKeyPressed )
                            {
                            iListBoxExt->iMarkableListShiftKeyPressed = ETrue;
                            // EPenMultiSelection moved to timer callback
                            // CListBoxView::EPenMultiselection;
                            selectionMode = CListBoxView::ENoSelection;
                            }
                        else
                            {
                            iListBoxExt->iMarkableListShiftKeyPressed = EFalse;
                            }
                        }

                    if ( itemIndex == oldCurrentItemIndex )
                        {
                        if ( shiftKeyPressed )
                            {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
                            iListBoxExt->iAnchor = oldCurrentItemIndex;
                            iListBoxExt->iSelect =
                                !iView->ItemIsSelected( iView->CurrentItemIndex() );
#endif // RD_UI_TRANSITION_EFFECTS_LIST

                            iView->SetAnchor( oldCurrentItemIndex );                      
                            iView->UpdateSelectionL( CListBoxView::EChangeMarkMode );
                            selectionMode = CListBoxView::EPenMultiselection;
                            iItemDrawer->SetFlags( CListItemDrawer::EPressedDownState );
                            }
                        else
                            {
                            iView->SetAnchor( itemIndex - 1 );

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
                            iListBoxExt->iAnchor = itemIndex - 1;
#endif // RD_UI_TRANSITION_EFFECTS_LIST
                            }
                        }

                    if ( !hasPhysics )
                        {
                        iView->DrawItem( oldCurrentItemIndex );
                        }

                    iView->UpdateSelectionL( selectionMode );
                    iListBoxFlags |= EStateChanged;

                    if ( !hasPhysics )
                        {
                        iView->DrawItem( itemIndex );
                        }
                    }
                else    // multiple selection listbox
                    {
                    if ((itemIndex == oldCurrentItemIndex) && (iView->ItemIsSelected(itemIndex)) && (! controlKeyPressed))
                        {
                        iItemDrawer->SetFlags( CListItemDrawer::EPressedDownState );
                        iView->DrawItem( itemIndex );
                        iListBoxExt->iEventModifiers = 0;
                        _AKNTRACE_FUNC_EXIT;
                        return;
                        }

                    if ( !hasPhysics )
                        {
                        iView->SetItemIndex(itemIndex);
                        iView->DrawItem(oldCurrentItemIndex);
                        }
                    
                    iView->UpdateSelectionL(selectionMode);
                    iListBoxFlags |= EStateChanged;
                    } 
                if (itemIndex != oldCurrentItemIndex)
                    {
                    iListBoxFlags |= EStateChanged;
                    // Fixed for TSW error ETLN-7T2CSR.
                    if ( !hasPhysics && IsMatchBuffer() )
                        {
                        ClearMatchBuffer();
                        DrawMatcherCursor();
                        }
                    }
                else
                    {
                    iItemDrawer->SetFlags( 
                        CListItemDrawer::EPressedDownState );
                    iView->DrawItem( itemIndex ); 
                    }
                }
            break;
            
        case TPointerEvent::EButton1Up:
            _AKNTRACE("TPointerEvent::EButton1Up");
            if ( iListBoxExt->FeedbackEnabledOnUpEvent() && 
			     iListBoxExt->iClickEventsAllowed && 
				 ( !( ( iListBoxFlags & EViewerFlag ) && 
				 ( iListBoxFlags & EDisableItemSpecificMenu ) ) )&& 
				 ( iListBoxExt->iLastDownTappedItem == itemIndex ) && 
				 ( !iListBoxExt->iDoubleClickEventIgnored ) && 
				 itemIndex == iView->CurrentItemIndex() )
                {
                TTouchLogicalFeedback fbType = ETouchFeedbackList;
                if ( iListBoxFlags & ES60StyleMultiselection 
                      || iListBoxFlags & EMultipleSelection )
                    {
                    fbType = ETouchFeedbackCheckbox;
                    }
                iListBoxExt->ImmediateFeedback( fbType,
                                                ETouchFeedbackVibra,
                                                aPointerEvent );
                }
            if ((! (Rect().Contains(aPointerEvent.iPosition))) && (iListBoxFlags & EPopout)) 
                {
                ReportEventL(MCoeControlObserver::EEventRequestCancel);
                iListBoxExt->iEventModifiers = 0;
                _AKNTRACE_FUNC_EXIT;
                return;
                }
            if (!(iListBoxFlags & ELeftDownInViewRect))
                {
                iListBoxExt->iEventModifiers = 0;
                _AKNTRACE_FUNC_EXIT;
                return;
                }
                
            if (iListBoxFlags & EStateChanged)
                {
                iListBoxFlags &= (~EStateChanged);
                if ( !s60StyleMultiselection )
                    {
                    ReportEventL(MCoeControlObserver::EEventStateChanged);
                    UpdateMarkUnmarkMSKL();
                    }
                }
            iListBoxFlags&=(~ELeftDownInViewRect);
            if (pointerIsOverAnItem)
                {
                TUint32 lastPointUpTime = iListBoxExt->iListPointUpTime;
                iListBoxExt->iListPointUpTime = User::NTickCount();

                TInt lastItemIndex = iListBoxExt->iLastItemIndex;
                iListBoxExt->iLastItemIndex = itemIndex;

                if ( ( iListBoxExt->iListPointUpTime - lastPointUpTime < KTwoPointerUpEventInterval )
                     && lastItemIndex == itemIndex
                     && ( !iListBoxExt->IsInHandleAllPointEventArray( itemIndex ) )
                     && !hasPhysics )
                {
                    iListBoxExt->iLastItemIndex = KEikListBoxInvalidIndex;
                    _AKNTRACE_FUNC_EXIT;
                    return;
                }

                if ( !hasPhysics )
                    {
                    iListBoxExt->LongTapPointerEventL( aPointerEvent );
                    }
                if ( !s60StyleMultiselection )
                    {
                    if ( !iListBoxExt->iSingleClickEnabled &&
                         itemIndex == iListBoxExt->iLastDownTappedItem )
                        {
                        ReportListBoxEventL(MEikListBoxObserver::EEventItemClicked);
                        }
                    else if ( itemIndex == iListBoxExt->iLastDownTappedItem )
                        {
                        // Single click item activation
                        iListBoxExt->EnableHighlight( EFalse );
                        UpdateHighlightL( itemIndex );
                        ReportListBoxEventL( 
                            MEikListBoxObserver::EEventItemSingleClicked );
                        _AKNTRACE_FUNC_EXIT;
                        return;
                        }
                    }
                // Due to the feature of capactior panel, the pointer position
                // may change between pointer down and up during user click 
                // action. When the click position is between two items 
                // and flick or drag event is not performed, the item index may
                // change unwanted, so we make a threshold for this situation.
                else if ( s60StyleMultiselection && !Buffer()->iDragToAnotherItem
                         && ( iListBoxExt->iLastDownTappedItem == itemIndex
                         || ( iListBoxExt->iLastDownTappedItem != KErrNotFound 
                         && Abs( iListBoxExt->iLastPointerPos.iY - aPointerEvent.iPosition.iY ) < KPointerDownAndUpThreshold ) ) )
                    {
                    iListBoxFlags |= EStateChanged;
                    Buffer()->iPressedIndex = itemIndex;
                    iView->SetAnchor(itemIndex-1); // zero indexed
                    iView->UpdateSelectionL(selectionMode);
                    ReportEventL(MCoeControlObserver::EEventStateChanged);

                    // Single click item activation
                    if ( iListBoxExt->iSingleClickEnabled )
                        {
                        iListBoxExt->EnableHighlight( EFalse );
                        UpdateHighlightL( itemIndex );
                        ReportListBoxEventL( 
                            MEikListBoxObserver::EEventItemSingleClicked );
                        }
                    else
                        {
                        ReportListBoxEventL(MEikListBoxObserver::EEventItemClicked);
                        }

                    UpdateMarkUnmarkMSKL();
                    }

                if ((iListBoxFlags & EPopout) && (!(shiftKeyPressed || controlKeyPressed)))
                    ReportEventL(MCoeControlObserver::EEventRequestExit);
                else if ((Buffer()->iPressedIndex != KEikListBoxInvalidIndex) &&
                        (itemIndex==Buffer()->iPressedIndex) &&
                        ( !Buffer()->iDragToAnotherItem ) && 
                        (selectionMode == CListBoxView::ENoSelection))
                    {
                    if ( iAvkonAppUi->IsTouchCompatible() )
                        {
                        //In some cases, listbox will be blocked here for dialog(such as launch out a CAknQueryDialog).
                        //And then, if App does not wait for dialog's back, and deletes container of listbox directly,
                        //iListBoxExt will be a null point.
                        iListBoxExt->iEventModifiers = 0;

                        // Clear pressed highlight and redraw item
                        iItemDrawer->ClearFlags( CListItemDrawer::EPressedDownState );
                        UpdateHighlightL( itemIndex );
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
                        MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( iView->iGc );
                        if ( transApi && !transApi->EffectsDisabled() )
                            {
                            DrawNow();
                            }
#endif //RD_UI_TRANSITION_EFFECTS_LIST
                        if ( !iListBoxExt->iSingleClickEnabled )
                            {
                            ReportListBoxEventL(MEikListBoxObserver::EEventItemDoubleClicked);
                            }
                        _AKNTRACE_FUNC_EXIT;
                        return;
                        }
                    else
                        {
                        simulateOkKey = ETrue;
                        }
                    }
                else
                    {
                    Buffer()->iPressedIndex=KEikListBoxInvalidIndex;
                    }
                }
            iItemDrawer->ClearFlags( CListItemDrawer::EPressedDownState );
            iView->DrawItem( iView->CurrentItemIndex() );            
            iListBoxExt->iIsDownOnItem = EFalse;         
            break;
            
        case TPointerEvent::EDrag:
            _AKNTRACE("TPointerEvent::EDrag");
            // CAUTION: on hw, drag is too easy. Add a threshold for it.
            if ( iListBoxExt->IsInIgnoreRect( pointerPos ) )
                {
                break;
                }

            if ( !hasPhysics && ( itemIndex != iView->CurrentItemIndex() ) )
                {
                // If single click mode is enabled, make sure that 
                // highlight is cleared when dragging to other item.
                if ( iListBoxExt->iSingleClickEnabled )
                    {
                    iListBoxExt->EnableHighlight( EFalse );
                    iListBoxExt->iLastDownTappedItem = KErrNotFound;
                    
                    // Cancel long tap animation 
                    iListBoxExt->CancelLongTapL();

                    }
                else
                    {
                    iItemDrawer->SetFlags( CListItemDrawer::EDisableHighlight );
                    }
                ReportListBoxEventL( MEikListBoxObserver::EEventItemDraggingActioned );
                }
            
            if( ( Buffer()->iPressedIndex != KEikListBoxInvalidIndex ) 
                && ( Buffer()->iPressedIndex != itemIndex)
                )
                {
                Buffer()->iDragToAnotherItem = ETrue;

                if ( !hasPhysics && 
                        ( iItemDrawer->Flags() & CListItemDrawer::EPressedDownState ) )
                    {
                    iItemDrawer->ClearFlags( CListItemDrawer::EPressedDownState );
                    iView->DrawItem( iView->CurrentItemIndex() );
                    }
                }
        
            if( static_cast<CAknAppUi*>(iEikonEnv->EikAppUi())->IsFaded() && !IsFocused() )
                {
                iListBoxFlags&=(~ELeftDownInViewRect);
                _AKNTRACE_FUNC_EXIT;
                return;
                }
            if ( !s60StyleMultiselection )
                {
                HandleDragEventL(pointerPos);
                }
            else
                {
                // selection mode needs to be disabled in multiselection lists
                // since dragging is not supported
                iListBoxFlags &= ~ES60StyleMultiselection;
                HandleDragEventL( pointerPos );
                iListBoxFlags |= ES60StyleMultiselection;
                }            
            break;
            
        case TPointerEvent::EButtonRepeat:
            _AKNTRACE("TPointerEvent::EButtonRepeat");
            // CAUTION: on hw, drag is too easy. Add a threshold for it.
            if ( iListBoxExt->IsInIgnoreRect( pointerPos ) )
                {
                break;
                }
            
            // make sure that highlight is cleared when dragging to other item.
            if ( !hasPhysics && itemIndex != iView->CurrentItemIndex() )
                {
                if ( iListBoxExt->iSingleClickEnabled )
                    {
                    iListBoxExt->EnableHighlight( EFalse );
                    iListBoxExt->iLastDownTappedItem = KErrNotFound;
                    }
                else
                    {
                    iItemDrawer->SetFlags( CListItemDrawer::EDisableHighlight );
                    }
                }
            
            if (!(iListBoxFlags & ELeftDownInViewRect))
                {
                iListBoxExt->iEventModifiers = 0;
                _AKNTRACE_FUNC_EXIT;
                return;
                }

            if ( !s60StyleMultiselection )
                {
                HandleDragEventL(pointerPos);
                }
            else
                {
                // selection mode needs to be disabled in multiselection lists
                // since dragging is not supported
                iListBoxFlags &= ~ES60StyleMultiselection;
                HandleDragEventL( pointerPos );
                iListBoxFlags |= ES60StyleMultiselection;
                }            
            break;
            
        default:
            break;
        }
        
    iListBoxExt->iEventModifiers = 0;
    
    if ( simulateOkKey )
        {
        TKeyEvent keyEvent;
        keyEvent.iCode = EKeyOK;
        keyEvent.iScanCode = EStdKeyDevice3;// EStdKeyOK;
        keyEvent.iRepeats = 0;
        keyEvent.iModifiers = 0;
        CCoeEnv::Static()->SimulateKeyEventL( keyEvent, EEventKey );
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::SimulateArrowKeyEventL(TKeyCode aKeyCode)
    {
    TKeyEvent keyEvent;
    keyEvent.iCode = aKeyCode;
    if (iListBoxFlags & EMultipleSelection)
        keyEvent.iModifiers = EModifierShift;
    OfferKeyEventL(keyEvent, EEventKey);
    }

EXPORT_C void CEikListBox::ClearSelection()
    {
    __ASSERT_DEBUG(iView, Panic(EEikPanicListBoxNoView));
    iView->ClearSelection();
    }

EXPORT_C void CEikListBox::FocusChanged(TDrawNow aDrawNow)
    {
    _AKNTRACE_FUNC_ENTER;
    if (iListBoxFlags & EEnterMarks || iListBoxFlags & EShiftEnterMarks )
        {
        CEikButtonGroupContainer *cba;
        MopGetObject(cba);
        // CR PKEA-4YSASZ
        // Unfortunately, we need to do this here. It belongs to 
        // CAknSelectionListDialog, but we need this change also 
        // to code that does not yet use CAknSelectionListDialog.
        if (cba && IsFocused())
            {
            if (iListBoxFlags & EEnterMarks)
                {
                TRAP_IGNORE(iAvkonEnv->CreateCbaObserverL(cba, this));
                }
            if (iListBoxExt && iListBoxExt->iMSKObserverEnabled)
                {
                TRAP_IGNORE(iListBoxExt->CreateMSKObserverL(cba, this));
                }
            }
        else
            {
            if (iListBoxFlags & EEnterMarks)
                {
                iAvkonEnv->RemoveCbaObserver();
                }
            if (iListBoxExt)
                {
                iListBoxExt->RemoveMSKObserver(this);
                }
            }
        }
        
    if (IsFocused())
        {
        // Some client does not let list get button1up, so we do it there...
        if ( iItemDrawer->Flags() & CListItemDrawer::EPressedDownState )
            {
            iItemDrawer->ClearFlags( CListItemDrawer::EPressedDownState );
            DrawItem( iView->CurrentItemIndex() );
            }        
        iView->SetEmphasized(ETrue);
        // This is needed or dialog pages do not work correctly.
        // See for example multi-item fetch.
        UpdateScrollBarThumbs();

        if (IsMatchBuffer())
            iView->DrawMatcherCursor();
        if ( iListBoxFlags & EPaintedSelection ) // added
            {
            TRAP_IGNORE(iView->SelectItemL(CurrentItemIndex()));
            }
        }
    else
        {
        // switch off selection (marking) mode when we lose focus
        // this also corrects situation, where FEP-menu is launched
        // and thus listbox doesn't receive shift up event
        if ( iListBoxExt )
            {
            if ((iListBoxFlags & EMultipleSelection) && (iListBoxFlags & EShiftEnterMarks))
                {
                iListBoxExt->iShiftKeyPressed = EFalse;
                if (iListBoxExt->iLongPressTimer && iListBoxExt->iLongPressTimer->IsActive())
                    {
                    iListBoxExt->iLongPressTimer->Cancel();
                    }
                ChangeSelectionMode(EFalse);
                iListBoxExt->iSelectionModeEnabled = EFalse;
                }
            
            // Cancel long tap detecting if focus is lost
            iListBoxExt->CancelLongTapL();
            }
    
        iView->SetEmphasized(EFalse);
        iView->HideMatcherCursor();
        
        if ( iItemEditor && 
            ( iListBoxFlags & EPaintedSelection ) && 
            ( iListBoxExt && iListBoxExt->ReasonForFocusLost() == EFocusLostToExternalControl ) )
            {
            iView->DeselectItem(CurrentItemIndex());
            }
        }
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    // LISTBOX EFFECTS IMPLEMENTATION
    if ( aDrawNow && !CAknListLoader::TfxApiInternal( iView->iGc ) )
#else
    if (aDrawNow)
#endif //RD_UI_TRANSITION_EFFECTS_LIST
        {
        // redraw items affected by change in emphasis
        TInt numOfSelectedItems = iView->SelectionIndexes()->Count();
        TInt selectionIndex = 0;
        for (TInt i = 0; i < numOfSelectedItems; i++)
            {
            selectionIndex = (*(iView->SelectionIndexes()))[i];
            if (ItemExists(selectionIndex))
                    iView->DrawItem(selectionIndex);
            }
       }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::SetDimmed(TBool aDimmed)
    {
    // should panic if view does not exist
    CCoeControl::SetDimmed(aDimmed);
    iView->SetDimmed(aDimmed);
    HandleResourceChange(KEikMessageColorSchemeChange);
    }

EXPORT_C void CEikListBox::ClearMatchBuffer() const
    {
    if(IsMatchBuffer())
        {
        iView->SetMatcherCursorPos(0);
        MatchBuffer()->Clear();
        }
    }

//
// Shortcut support functions (no default implementation available)
//
EXPORT_C TInt CEikListBox::ShortcutValueForNextList() 
    { 
    //__ASSERT_DEBUG(0,Panic(EEikPanicInvalidUseOfListBoxShortcuts)); 
    return 0;
    }
EXPORT_C void CEikListBox::SetShortcutValueFromPrevList(TInt /*aValue*/) 
    {
    //__ASSERT_DEBUG(0,Panic(EEikPanicInvalidUseOfListBoxShortcuts));
    }

// pop-up positioning support
EXPORT_C TRect CEikListBox::HighlightRect() const
    {
    TPoint topLeft( View()->ItemPos( CurrentItemIndex() ) );
    topLeft += iAvkonAppUi->ClientRect().iTl;

    TRect rect( topLeft, iItemDrawer->ItemCellSize() );

    return rect;
    }

EXPORT_C TBool CEikListBox::BackgroundDrawingSuppressed() const
    {
    if ( iItemDrawer )
        {
        TInt flags = iItemDrawer->Flags();
        
        return ( flags & CListItemDrawer::EDrawWholeBackground ) 
                && ( flags & CListItemDrawer::EBackgroundDrawn );
        }
        
    return EFalse;
    }

// Series 60  needs this to control the state machine that determines how
// shortcuts work.
EXPORT_C TBool CEikListBox::LastCharMatched() const
    {
    return iLastCharMatched;
    }

EXPORT_C void CEikListBox::MatchTypedCharL(TUint aCode)
    {
    _AKNTRACE_FUNC_ENTER;
    iLastCharMatched = EFalse;
    if (iListBoxFlags&ENoFirstLetterMatching)
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    const MDesCArray* matchableTextArray = iModel->MatchableTextArray();
    if (! matchableTextArray)
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    if (IsMatchBuffer())
        {
        TInt matcherCursorPos = iView->MatcherCursorPos();
        if (MatchBuffer()->MatchLength() == KEikMaxMatchingBufferLength)
            {
            _AKNTRACE_FUNC_EXIT;
            return;
            }
        MatchBuffer()->AppendChar(aCode);
        TInt selectedItemIndex;
        TInt ret = MatchBuffer()->FirstMatchingIndexF(selectedItemIndex, *matchableTextArray);
        if (ret == KErrNone)
            {
            ++matcherCursorPos;
/*
            if (matcherCursorPos >= matchableTextArray->MdcaPoint(selectedItemIndex).Length())
                {
                iListBoxExt->iBuffer->iMatchBuffer->DeleteLastChar();
                --matcherCursorPos;
                }
*/
            iView->VerticalMoveToItemL(selectedItemIndex, CListBoxView::ESingleSelection);
            // SetCurrentItemIndexAndDraw(selectedItemIndex);
            iView->SetMatcherCursorPos(matcherCursorPos);
            iLastCharMatched = ETrue;
            }
        else   // No match with buf with new letter: discard new char
            {       
            iLastCharMatched = EFalse;      
            MatchBuffer()->DeleteLastChar();
            }
        }
    else
        {
        // do first later matching here
        TChar matchCharacter(aCode);
        matchCharacter.Fold();
        TInt currentItemIndex = iView->CurrentItemIndex();   
        TChar firstCharOfItem;
        TBool foundMatch = EFalse;
        TInt itemIndex = currentItemIndex + 1;
        // look for match, starting at item below the current one
        while ((itemIndex != currentItemIndex) && !foundMatch)
            {
            // if end of list reached, restart search from the beginning of the list
            if (ItemExists(itemIndex) == EFalse)
                {
                itemIndex = 0;
                if (itemIndex == currentItemIndex)
                    {
                    foundMatch = ETrue;
                    break;
                    }
                }
            TPtrC buf=matchableTextArray->MdcaPoint(itemIndex);
            if (buf.Length())
                {
                firstCharOfItem = buf[0];
                firstCharOfItem.Fold();
                if (matchCharacter == firstCharOfItem)
                    {
                    foundMatch = ETrue;
                    break;
                    }
                }
            ++itemIndex;
            }
        if (foundMatch)
            {
            iLastCharMatched = ETrue;
            // SetCurrentItemIndexAndDraw(itemIndex);
            iView->VerticalMoveToItemL(itemIndex, CListBoxView::ESingleSelection);
        }
        }
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikListBox::UndoLastChar()
    {
    __ASSERT_DEBUG(MatchBuffer(), Panic(EEikPanicListBoxNoMatchBuffer));
    __ASSERT_DEBUG(iModel->MatchableTextArray(), Panic(EEikPanicListBoxNoMatchTextArray));
    iView->SetMatcherCursorPos(iView->MatcherCursorPos() - 1);
    MatchBuffer()->DeleteLastChar();
    TInt selectedItemIndex;
    const MDesCArray* matchableTextArray = iModel->MatchableTextArray(); 
    TInt retcode = MatchBuffer()->FirstMatchingIndexF(selectedItemIndex, *matchableTextArray);
    if (!retcode)
        SetCurrentItemIndexAndDraw(selectedItemIndex);
    }

EXPORT_C void CEikListBox::SetLaunchingButton(CEikButtonBase* aButton)
    {
    iLaunchingButton=aButton;
    }

EXPORT_C TCoeInputCapabilities CEikListBox::InputCapabilities() const
    {
    if (iListBoxFlags&EIncrementalMatching)
        return TCoeInputCapabilities(TCoeInputCapabilities::ENavigation|TCoeInputCapabilities::EAllText);
    if (iListBoxFlags&ENoFirstLetterMatching)
        return TCoeInputCapabilities(TCoeInputCapabilities::ENavigation);
    return TCoeInputCapabilities(TCoeInputCapabilities::ENavigation|TCoeInputCapabilities::EAllText/*,1*/);
    }

/**
*   @ since uikon_1.2
*   A method which returns a TMargins object for the list box.
*   The TMargins object has 4 values, one for each side of the list box.
*   Depending on use of the Laf, the DFRD can program 2, 3 or 4 margins ...
*   ... but although the application developer can see up to 4 different margins ...
*   ... they can only set 2 (ie. iHorizontalMargin and iVerticalMargin)
*/
EXPORT_C TMargins8 CEikListBox::ListBoxMargins() const
    {
    /*
    TMargins margins;
    if(iHorizontalMargin == KLafListBoxUseLafHorizMargins) // if the Laf is being used
    {
        margins.iLeft = LafListBox::LeftMargin();
        margins.iRight = LafListBox::RightMargin();
        }
    else
        {
        // SERIES60 LAF
        margins.iLeft=HorizontalMargin();
        margins.iRight=0;
        // END OF SERIES60 LAF
        }
    if(iVerticalMargin == KLafListBoxUseLafVertMargins) // if the Laf is being used
        {
        margins.iTop = LafListBox::TopMargin();
        margins.iBottom = LafListBox::BottomMargin();
    }
    else
        {
        // SERIES60 LAF
        margins.iTop=VerticalMargin();
        margins.iBottom = 0;
        // END OF SERIES60 LAF

        // Old implementation (not good for Series 60)
        //margins.iTop=margins.iBottom=VerticalMargin();
        //
     
        }
    */
    // SERIES60 LAF
    TMargins8 margins = iMargins ;
    margins.iTop=TInt8(VerticalMargin());
    margins.iBottom = 0;
    margins.iLeft=TInt8(HorizontalMargin());
    margins.iRight = 0;
    // END OF SERIES60 LAF
    return margins;
    }

/**
*   @ deprecated
*   Use CEikListBox::ListBoxMargins() instead, to get more accurate values,
*   as use of this method may cause a single pixel error if the laf
*   is being used, due to the bit shifting involved
*/
EXPORT_C TInt CEikListBox::HorizontalMargin() const
    {
    return ((iMargins.iLeft + iMargins.iRight) >> 1);
    }

/**
*   @ deprecated
*   Use CEikListBox::ListBoxMargins() instead, to get more accurate values,
*   as use of this method may cause a single pixel error if the laf
*   is being used, due to the bit shifting involved
*/
EXPORT_C TInt CEikListBox::VerticalMargin() const
    {
    return ((iMargins.iTop + iMargins.iBottom) >> 1);
    }

EXPORT_C void CEikListBox::SetVerticalMargin(TInt aMargin)
    {
    iMargins.iTop = iMargins.iBottom = (TInt8) aMargin;
    }

EXPORT_C void CEikListBox::SetHorizontalMargin(TInt aMargin)
    {
    iMargins.iLeft = iMargins.iRight = (TInt8) aMargin;
    }

EXPORT_C RIncrMatcherBase* CEikListBox::MatchBuffer() const
    {
    if(CONST_CAST(CEikListBox*,this)->CheckCreateExtension() && Buffer())
        return Buffer()->iMatchBuffer;
    return NULL;
    }

EXPORT_C TInt CEikListBox::ViewRectHeightAdjustment() const
    {
    return iViewRectHeightAdjustment;
    }

EXPORT_C void CEikListBox::SetViewRectHeightAdjustment(TInt aAdjustment)
    {
    iViewRectHeightAdjustment = aAdjustment;
    }

EXPORT_C TRgb CEikListBox::BackColor() const
    {
    return iBackColor;
    }

EXPORT_C TInt CEikListBox::VerticalInterItemGap() const
    {
    return KEikListBoxItemVGap;
//  return ListBoxLaf()->LBxItemVGap();
    }

/**
 * Gets the list of logical colors employed in the drawing of the control,
 * paired with an explanation of how they are used. Appends the list to aColorUseList.
 *
 * @since ER5U 
 */
EXPORT_C void CEikListBox::GetColorUseListL(CArrayFix<TCoeColorUse>& aColorUseList) const
    {
    CEikBorderedControl::GetColorUseListL(aColorUseList);
    LafListBox::GetColorUseListL(aColorUseList);
    }

/**
 * Handles a change to the control's resources of type aType
 * which are shared across the environment, e.g. colors or fonts.
 *
 * @since ER5U 
 */
EXPORT_C void CEikListBox::HandleResourceChange(TInt aType)
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE( "aType = %d", aType );
    CEikBorderedControl::HandleResourceChange(aType);
    
    if(aType==KEikDynamicLayoutVariantSwitch)
        {    
        if( iListBoxExt && iListBoxExt->iPhysics )
            {
            //stop flicking 
            iListBoxExt->iPhysics->StopPhysics();

            //If touch down and hold view,
            //kinetic scrolling should not be started after rotate screen.
            iListBoxFlags &= ( ~ELeftDownInViewRect );
            }
        
        if ( iView )
            {
            iView->SetItemOffsetInPixels( 0 );            
            }
        
        // make sure that highlight is removed and long tap is canceled 
        // on layout switch, if single click is enabled and there is 
        // pointer down on any item
        if ( iListBoxExt && iListBoxExt->iSingleClickEnabled 
             && iListBoxExt->iLastDownTappedItem != KErrNotFound )
            {                   
            iListBoxExt->EnableHighlight( EFalse );
            iListBoxExt->CancelLongTapL();
            }              
                      
        SizeChanged();

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
        MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( iView->iGc );
        if ( transApi )
            {
            transApi->Remove( MAknListBoxTfxInternal:: EListEverything );
            }
#endif
        }

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal( iView->iGc );
#endif // RD_UI_TRANSITION_EFFECTS_LIST

    if ( aType == KEikMessageColorSchemeChange || aType == KAknsMessageSkinChange )
        {
        if ( !CAknEnv::Static()->TransparencyEnabled() && OwnsWindow())
            {
            Window().SetBackgroundColor(iEikonEnv->ControlColor(EColorControlBackground,*this));
            }
        iBackColor=iEikonEnv->ControlColor(IsDimmed() ? 
                                    EColorControlDimmedBackground : EColorControlBackground,*this);
        UpdateViewColors();
        UpdateItemDrawerColors();

        // store the value of virtical offset as it will be 0 in SizeChange,
        // that will affect view position in skin changed, which is a bug.
        TInt oldOffset = 0; 
        if ( iView )
            {
            oldOffset = iView->ItemOffsetInPixels();
            }
        // TODO: check if this call is real need here. 
        SizeChanged();
        if ( oldOffset !=0 && iView )
            {
            iView->SetItemOffsetInPixels( oldOffset );
            UpdateScrollBarThumbs();
            }
        // this methord is empty.
        UpdateScrollBarsColors();
        
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
        if ( transApi )
            {
            transApi->Remove( MAknListBoxTfxInternal:: EListEverything );
            }
        }
    else if ( transApi && aType == KEikMessageUnfadeWindows && IsReadyToDraw() )
        {
        DrawDeferred();
#endif // RD_UI_TRANSITION_EFFECTS_LIST
        }
        
    switch ( aType )
        {
        case KEikMessageWindowsFadeChange:
            {
            if ( iListBoxExt )
                {
                iListBoxExt->ReportCollectionChangedEvent();
                }
            } // fall through
        case KEikMessageUnfadeWindows:
        case KEikMessageFadeAllWindows:
            {
            // Some client does not let list get button1up, so we do it there...
            iItemDrawer->ClearFlags( CListItemDrawer::EPressedDownState );
            TInt index = View()->CurrentItemIndex();
            TBool enabled( !( iItemDrawer->Flags()
                & CListItemDrawer::ESingleClickDisabledHighlight ) );
            if ( index != KErrNotFound && enabled )
            	{
                Window().Invalidate( TRect( View()->ItemPos(index), 
                                    iItemDrawer->ItemCellSize() ) );
            	}
            break;
            }
        case KEikDynamicLayoutVariantSwitch:
        case KEikMessageColorSchemeChange:
        case KAknsMessageSkinChange:
            DrawDeferred();
            break;

        case KAknMessageFocusLost:
            {
            // Do not remove highlight if window ordinal position has changed
            // during the time when stylus menu is open
            if ( iListBoxExt && iListBoxExt->iSingleClickEnabled &&
                 ( iListBoxExt->iOldWinPos == KErrNotFound ||
                   iListBoxExt->iOldWinPos == 
                   DrawableWindow()->OrdinalPosition() ) )
                {
                TBool enabled( iItemDrawer && !( iItemDrawer->Flags()
                    & CListItemDrawer::ESingleClickDisabledHighlight ) );
                           
                if ( enabled )
                    {
                    iListBoxExt->EnableHighlight( EFalse );
                    if ( iView && IsVisible() )
                        {
                        iView->DrawItem( CurrentItemIndex() );
                        }
                    }
                }
            }
            break;
        }
    _AKNTRACE_FUNC_EXIT;
    }

void CEikListBox::UpdateScrollBarsColors()
    {
    }

void CEikListBox::UpdateScrollBarColors(CEikScrollBar* /*aScrollBar*/)
    {
    }

//-----------------------------------------------------------
// CEikListBox::IsMultiselection()
// Returns true if ES60StyleMultiselection flag is on
//-----------------------------------------------------------
EXPORT_C TBool CEikListBox::IsMultiselection()
    {
    /* note, that this method is very misleading. To have this method
    * return true, you need to construct your listbox with
    * EAknListBoxPointerMultiselectionList flag, not with
    * EAknListBoxMultipleSelection as ES60StyleMultiselection might
    * suggest. However, to make multiselection work, you need
    * to or those flags together...
    */
    return (iListBoxFlags & ES60StyleMultiselection );     
    }
  
//-----------------------------------------------------------
// CEikListBox::EventModifiers()
// Returns pointerevent modifiers.
//-----------------------------------------------------------  
EXPORT_C TInt CEikListBox::EventModifiers()
    {
    if (iListBoxExt)
        {
        return iListBoxExt->iEventModifiers;
        }
    return NULL;
    }

EXPORT_C void CEikListBox::CEikListBox_Reserved()
    {}

TBool CEikListBox::CheckCreateExtension()
    {
    TInt err=KErrNone;
    if (!iListBoxExt)
        {
        TRAP(err,iListBoxExt=CListBoxExt::NewL(*this));
        }
    return err==KErrNone;
    }

void CEikListBox::CheckCreateExtensionL()
    {
    if (!iListBoxExt)
        iListBoxExt=CListBoxExt::NewL(*this);
    }

void CEikListBox::CheckCreateBufferL()
    {
    CheckCreateExtensionL();
    iListBoxExt->CheckCreateBufferL();
    }

CMatchBuffer* CEikListBox::Buffer() const
    {
    if(CONST_CAST(CEikListBox*,this)->CheckCreateExtension())
        return iListBoxExt->Buffer();
    return NULL;
    }

EXPORT_C TBool CEikListBox::IsMatchBuffer() const
    {
    return (CONST_CAST(CEikListBox*,this)->CheckCreateExtension() && iListBoxExt->IsMatchBuffer());
    }

EXPORT_C void CEikListBox::SetReasonForFocusLostL(TReasonForFocusLost aReasonForFocusLost)
    {
    CheckCreateExtensionL();
    iListBoxExt->SetReasonForFocusLost(aReasonForFocusLost);
    }

EXPORT_C CEikListBox::TReasonForFocusLost CEikListBox::ReasonForFocusLostL()
    {
    CheckCreateExtensionL();
    return iListBoxExt->ReasonForFocusLost();
    }

/**
 * Sets the item editor to aEditor and transfers ownership.
 *
 * @since ER5U
 */
EXPORT_C void CEikListBox::SetItemEditor(MEikListBoxEditor* aEditor)
    {
    if (iItemEditor)
        iItemEditor->Release();
    iItemEditor=aEditor;
    }

/**
 * Deletes and NULLs the item editor.
 *
 * @since ER5U
 */
EXPORT_C void CEikListBox::ResetItemEditor()
    {
    if (iItemEditor)
        iItemEditor->Release();
    iItemEditor=NULL;
    }

/**
 * Returns a pointer to the item editor. Does not imply transfer of ownership.
 *
 * @since ER5U
 */
EXPORT_C MEikListBoxEditor* CEikListBox::ItemEditor()
    {
    return iItemEditor;
    }

/**
 * Creates an item editor, if one does not already exist, and starts editing the
 * current item up to a maximum length of aMaxLength characters. Also reports an
 * EEventEditingStarted event to any list box observer by default.
 *
 * @since ER5U
 */
EXPORT_C void CEikListBox::EditItemL(TInt aMaxLength)
    {
    _AKNTRACE_FUNC_ENTER;
    CEikListBoxTextEditor* itemEditor = STATIC_CAST(CEikListBoxTextEditor*,ItemEditor());
    if ( !itemEditor || (itemEditor && !(itemEditor->Editor())) )
        {
        SetItemEditor(new(ELeave) CEikListBoxTextEditor(Model()));
        itemEditor = STATIC_CAST(CEikListBoxTextEditor*,ItemEditor());
        const TInt index = View()->CurrentItemIndex();
        itemEditor->SetFont( ((CTextListItemDrawer*)iItemDrawer)->Font(index) );
        TRect rect = TRect( View()->ItemPos( index ), View()->ItemSize() );
        rect.iTl.iX += LafListBox::InnerGutter();
        if (iItemDrawer->Flags()&CListItemDrawer::EDrawMarkSelection)
            {
            rect.iTl.iX += iItemDrawer->MarkColumn() + iItemDrawer->MarkGutter();
            }
        if ( iListBoxExt )
            {
            iListBoxExt->SetReasonForFocusLost(EFocusLostToInternalEditor);
            }
        itemEditor->StartEditingL(*this,rect,index,aMaxLength);
        if ( iListBoxExt )
            {
            iListBoxExt->SetReasonForFocusLost(EFocusLostToExternalControl);
            }
        ReportListBoxEventL( MEikListBoxObserver::EEventEditingStarted );
        }
    _AKNTRACE_FUNC_EXIT;
    }

/**
 * Stops editing and deletes the item editor, reporting an EEventEditingStopped event
 * to any list box observer. Updates the list box model if aUpdateModel is ETrue.
 *
 * @since ER5U
 */
EXPORT_C void CEikListBox::StopEditingL( TBool aUpdateModel )
    {
    MEikListBoxEditor* editor = ItemEditor();
    if ( editor )
        {
        if ( aUpdateModel ) editor->UpdateModelL();
        editor->StopEditingL();
        ResetItemEditor();
        ReportListBoxEventL( MEikListBoxObserver::EEventEditingStopped );
        }
    }

EXPORT_C CEikScrollBarFrame* CEikListBox::CreateScrollBarFrameL(TBool aPreAlloc, TBool aRemote)
    {
    // CEikListBox creates a window owning scroll bar by default. This causes
    // scroll bar flicker during listbox open when transparency is enabled.
    // With CAknPopupList the listbox and scroll bar are created outside of
    // the CAknPopupList component. In order not to have to change source
    // code of all CAknPopupList users to create a non window owning scroll
    // bar, the default is changed for this case.
    _AKNTRACE_FUNC_ENTER;
    TBool windowOwning = ETrue;
    if (Parent())
        {
        CAknPopupList* popupList;
        Parent()->MopGetObjectNoChaining(popupList);
        if (popupList)
            {
            windowOwning = EFalse;
            }
        }
    _AKNTRACE_FUNC_EXIT;
    return CreateScrollBarFrameL(aPreAlloc, aRemote, windowOwning);
    }

EXPORT_C CEikScrollBarFrame* CEikListBox::CreateScrollBarFrameL(TBool aPreAlloc, TBool aRemote, TBool aWindowOwning)
    {
    _AKNTRACE_FUNC_ENTER;
    if (!iSBFrame)
        {
        iSBFrame=new(ELeave) CEikScrollBarFrame(this, this, aPreAlloc, ETrue); 
        
        // Check which type of scrollbar is to be shown
        if (AknLayoutUtils::DefaultScrollBarType(iAvkonAppUi) == CEikScrollBarFrame::EDoubleSpan)
            {
            iSBFrame->CreateDoubleSpanScrollBarsL(aWindowOwning, aRemote, ETrue, EFalse);

            if ( CAknEnv::Static()->TransparencyEnabled() && iListBoxExt && iListBoxExt->iPhysics )
                {
                iSBFrame->DrawBackground(EFalse,EFalse);
                }
            }

        if (CheckCreateExtension())
            iListBoxExt->SetUpdateScrollBarsColors(ETrue);
        if(aRemote)
            iSBFrameOwned = EOwnedExternally;
        else
            iSBFrameOwned = ENotOwnedExternally;
        }
    _AKNTRACE_FUNC_EXIT;
    return iSBFrame;
    }

EXPORT_C void CEikListBox::EnableMSKObserver(TBool aEnable)
    {
    _AKNTRACE_FUNC_ENTER;
    if (iListBoxExt)
        {
        if (aEnable == EFalse)
            {
            iListBoxExt->RemoveMSKObserver(this); // remove disabled observer
            }
        else
            {
            if (iListBoxFlags & EEnterMarks || iListBoxFlags & EShiftEnterMarks)
                {
                CEikButtonGroupContainer *cba;
                MopGetObject(cba);
                if (cba)
                    {
                    TRAP_IGNORE(iListBoxExt->CreateMSKObserverL(cba, this));
                    TRAP_IGNORE(UpdateMarkUnmarkMSKL());
                    }
                }
            }
        iListBoxExt->iMSKObserverEnabled = aEnable;
        }
    _AKNTRACE_FUNC_EXIT;
    }
    
void CEikListBox::DoShiftMSKMarkingL()
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iListBoxExt && iListBoxExt->iWesternVariant &&
        ( iListBoxFlags & EShiftEnterMarks || iListBoxFlags & EEnterMarks ) )
        {
        // if the user marks item with hash+MSK, releasing MSK should not
        // do the marking again
        iListBoxExt->iShortHashMark = EFalse;

        iView->UpdateSelectionL(CListBoxView::EDisjointSelection);
        ReportEventL(MCoeControlObserver::EEventStateChanged);
        UpdateMarkUnmarkMSKL();
        }
    _AKNTRACE_FUNC_EXIT;
    }


// ---------------------------------------------------------------------------
// Disables the kinetic scrolling functionality in the list.
// ---------------------------------------------------------------------------
//
EXPORT_C void CEikListBox::DisableScrolling( TBool aDisabled )
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iListBoxExt )
        {
        iListBoxExt->iScrollingDisabled = aDisabled;
        iView->iExtension->iScrollingDisabled = aDisabled;
        
        if ( aDisabled && iListBoxExt->iPhysics )
            {
            delete iListBoxExt->iPhysics;
            iListBoxExt->iPhysics = NULL;
            iView->SetItemOffsetInPixels( 0 );
            }
        else if ( !aDisabled && !iListBoxExt->iPhysics && CAknPhysics::FeatureEnabled() )
            {
            iListBoxExt->iPhysics = CAknPhysics::NewL( *iListBoxExt, this);      
            }
        }
    _AKNTRACE_FUNC_EXIT;
    }


// ---------------------------------------------------------------------------
// Checks if the kinetic scrolling functionality is disabled in the list.
// ---------------------------------------------------------------------------
//
EXPORT_C TBool CEikListBox::ScrollingDisabled()
    {
    if ( iListBoxExt )
        {
        return !iListBoxExt->iPhysics || iListBoxExt->iScrollingDisabled;
        }
    else
        {
        return ETrue;
        }
    }


EXPORT_C void CEikListBox::SetPointerEventFilterDisabledL( const CArrayFix<TInt>& aItemIndexes )
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iListBoxExt )
        {
        iListBoxExt->iMutiTappingItems.Reset();
    
        for(TInt i=0; i<aItemIndexes.Count(); i++ )
            {
            iListBoxExt->iMutiTappingItems.InsertInOrderL( aItemIndexes.At(i) ); 
            } 
        }
    _AKNTRACE_FUNC_EXIT;
    }


// ---------------------------------------------------------------------------
// CEikListBox::SuspendEffects
// ---------------------------------------------------------------------------
//
EXPORT_C void CEikListBox::SuspendEffects( TBool aSuspend )
    {
    _AKNTRACE_FUNC_ENTER;
    TBool effectsEnabled = EFalse;
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    MAknListBoxTfxInternal* transApi = CAknListLoader::TfxApiInternal(
            iView->ItemDrawer()->Gc() );

    effectsEnabled = transApi && !transApi->EffectsDisabled();
#endif    
    // Record effect's state before those are suspended so that calling this
    // method doesn't turn effects on if they were disabled already.
    if ( iListBoxExt )
        {
        if ( effectsEnabled && !iListBoxExt->iEffectsEnabled )
            {
            iListBoxExt->iEffectsEnabled = ETrue;
            }
        
        if ( !aSuspend )
            {
            aSuspend = !iListBoxExt->iEffectsEnabled;
            }
        }
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
    
    MAknListBoxTfx* tfxApi = CAknListLoader::TfxApi( iView->ItemDrawer()->Gc() );
    
    if (  aSuspend && effectsEnabled && tfxApi )
        {
        tfxApi->EnableEffects( EFalse );
        }
    else if ( !aSuspend && !effectsEnabled && tfxApi )
        {
        tfxApi->EnableEffects( ETrue );
        }
#endif// RD_UI_TRANSITION_EFFECTS_LIST
    _AKNTRACE_FUNC_EXIT;
    }


// ---------------------------------------------------------------------------
// Disables the single click functionality in the list.
// ---------------------------------------------------------------------------
//
EXPORT_C void CEikListBox::DisableSingleClick( TBool aDisabled )
    {
    _AKNTRACE_FUNC_ENTER;    
    if ( aDisabled && 
         iListBoxExt && 
    	 iListBoxExt->iSingleClickEnabled && 
    	 iItemDrawer )
        {
        iListBoxExt->DisableSingleClick(); 
        iItemDrawer->ClearFlags( CListItemDrawer::ESingleClickEnabled);
        }
    else if ( !aDisabled &&
              iListBoxExt &&
              !iListBoxExt->iSingleClickEnabled &&
              iItemDrawer )
        {
        TRAP_IGNORE( iListBoxExt->EnableSingleClickL() );
        iItemDrawer->SetFlags( CListItemDrawer::ESingleClickEnabled );
        }
    _AKNTRACE_FUNC_EXIT;
    }


// ---------------------------------------------------------------------------
// CEikListBox::DisableItemSpecificMenu
// ---------------------------------------------------------------------------
//
EXPORT_C void CEikListBox::DisableItemSpecificMenu()
    {
    _AKNTRACE_FUNC_ENTER;
    if ( iListBoxExt )
        {
        iListBoxExt->DisableItemSpecificMenu();
        }
    _AKNTRACE_FUNC_EXIT;
    }

// ---------------------------------------------------------------------------
// CEikListBox::IsHighlightEnabled
// ---------------------------------------------------------------------------
//
EXPORT_C TBool CEikListBox::IsHighlightEnabled()
    {
    _AKNTRACE_FUNC_ENTER;	
    TBool enabled( EFalse ); 
    if ( !( iItemDrawer->Flags() & CListItemDrawer::EDisableHighlight ) )
        {
        if ( iListBoxExt && iListBoxExt->iSingleClickEnabled )
            {
            enabled = !( iItemDrawer->Flags()
                & CListItemDrawer::ESingleClickDisabledHighlight ); 
            }
        else 
            {
            enabled = ETrue;
            }
        }
    _AKNTRACE_FUNC_EXIT;
    return enabled; 
    }


// ---------------------------------------------------------------------------
// CEikListBox::SetMarkingMode
// ---------------------------------------------------------------------------
//
EXPORT_C void CEikListBox::SetMarkingMode( TBool aEnable )
    {
    if ( iListBoxExt && iListBoxExt->iSingleClickEnabled && 
            ( iListBoxFlags & CEikListBox::ES60StyleMarkable ) )
        {
        if ( iListBoxExt->iMarkingModeInUse != aEnable ) 
            {
            if ( aEnable )
                {
                iView->ItemDrawer()->SetFlags( 
                        CListItemDrawer::EMarkingModeEnabled );
                }
            else
                {
                iView->ItemDrawer()->ClearFlags( 
                        CListItemDrawer::EMarkingModeEnabled );
            
                if ( iView->SelectionIndexes()->Count() > 0 )
                    {
                    iView->ClearSelection( EFalse );
                    }
                }

            iListBoxExt->iMarkingModeInUse = aEnable;
            DrawDeferred();
            }

        if ( MarkingModeObserver() )
            {
            MarkingModeObserver()->MarkingModeStatusChanged( aEnable );
            }
        }
    }


// ---------------------------------------------------------------------------
// CEikListBox::SetMarkingModeObserver
// ---------------------------------------------------------------------------
//
EXPORT_C void CEikListBox::SetMarkingModeObserver( 
        MAknMarkingModeObserver* aObserver )
    {
    if ( iListBoxExt )
        {
        iListBoxExt->iMarkingModeObserver = aObserver;
        }
    }


void CEikListBox::ScrollView( const TInt aOffset, TBool aDrawNow )
	{
	_AKNTRACE_FUNC_ENTER;
#ifdef _DEBUG
	RDebug::Print( _L( "CEikListBox::ScrollView, aOffset = %d, aDrawNow = %d" ), aOffset, aDrawNow );
#endif // _DEBUG	
	
	if ( iListBoxExt && aOffset != 0 )
	    {
        TInt itemHeight = iView->ItemHeight();
        TInt viewHeight = iView->ViewRect().Size().iHeight;
        TInt itemsInSingleLine = iListBoxExt->iItemsInSingleLine;
        TInt oldListTopPos = ( iView->TopItemIndex() / itemsInSingleLine ) * itemHeight 
            - iView->ItemOffsetInPixels();
        TInt newListTopPos = oldListTopPos - aOffset;
        
        // calculate new top item index and offset
        TInt newTopItemIndex = ( newListTopPos / itemHeight ) * itemsInSingleLine;
        TInt newTopItemIndexBck = newTopItemIndex;
        if ( newTopItemIndex >= Model()->NumberOfItems() )
            {
            newTopItemIndexBck = Model()->NumberOfItems() - 1;
            newTopItemIndex = Model()->NumberOfItems();
            }

        // feedback during flicking and panning
        TInt newListBottomPos = newListTopPos + viewHeight;
        
        TInt newListLastItemPos = ( Model()->NumberOfItems()/itemsInSingleLine ) * itemHeight - newListTopPos;
        if ( newTopItemIndex != iListBoxExt->iPrevTopItemIndex )
            {
            iListBoxExt->iPrevTopItemIndex = newTopItemIndex;
            if( iListBoxExt->FlickOrPanningOngoing() )
                {
                if( ( newListBottomPos < iListBoxExt->ListBottomLimit() && newListTopPos > 0 ) || 
                    ( newListBottomPos >= iListBoxExt->ListBottomLimit() ) ||
                    ( newListTopPos <= 0 && newListTopPos + viewHeight >= 0 && newListLastItemPos > viewHeight ) )
                    {
                    if ( CAknPhysics::EAknPhysicsActionFlicking == iListBoxExt->iPhysics->OngoingPhysicsAction() || 
                         CAknPhysics::EAknPhysicsActionBouncing == iListBoxExt->iPhysics->OngoingPhysicsAction() )
                        {
                        iListBoxExt->ImmediateFeedback( ETouchFeedbackSensitiveList,
                                                        TTouchFeedbackType( ETouchFeedbackVibra ),
                                                        TPointerEvent() );
                        }
                    else if ( CAknPhysics::EAknPhysicsActionDragging == iListBoxExt->iPhysics->OngoingPhysicsAction() )
                        {
                        iListBoxExt->ImmediateFeedback( ETouchFeedbackSensitiveList,
                                                        TTouchFeedbackType( ETouchFeedbackVibra | ETouchFeedbackAudio ),
                                                        TPointerEvent() );
                        }
                    }
                }
            }
        newTopItemIndex = newTopItemIndexBck;
        if ( newTopItemIndex < 0 )
            {
            newTopItemIndex = 0;
            }
        
        // Top item index should always be the first item index in a row.
        TInt notFirstInRow = newTopItemIndex % itemsInSingleLine;
    
        if ( notFirstInRow > 0 )
            {
            newTopItemIndex -= notFirstInRow;
            }
        
        TInt offset = ( newTopItemIndex / itemsInSingleLine ) * itemHeight - newListTopPos;
    
        iView->SetItemOffsetInPixels( offset );
#ifdef _DEBUG
        RDebug::Print( _L( "CEikListBox::ScrollView, newTopItemIndex = %d" ), newTopItemIndex );
#endif // _DEBUG
        iView->SetTopItemIndex( newTopItemIndex );
        }

    if ( aDrawNow )
        {
        TRect rect(Rect());
        
        // list position changed
        if ( iListBoxExt && iListBoxExt->FlickOrPanningOngoing() )
            {
            iItemDrawer->SetFlags( CListItemDrawer::EDrawWholeBackground );
            }

        UpdateScrollBarThumbs();
        DrawNow();

        if (iSBFrame && iSBFrame->VerticalScrollBar() && !iSBFrame->VerticalScrollBar()->OwnsWindow())
            {
            TRect srect( iSBFrame->VerticalScrollBar()->Rect() );
            if ( !srect.Intersects( rect ))
                {
                iSBFrame->DrawScrollBarsNow();                
                }
            }

        if ( iListBoxExt )
            {
            iItemDrawer->ClearFlags( CListItemDrawer::EDrawWholeBackground 
                    | CListItemDrawer::EBackgroundDrawn );
            }
        }        
    _AKNTRACE_FUNC_EXIT;
	}


// ---------------------------------------------------------------------------
// Handles pointer events if physics are enabled.
// ---------------------------------------------------------------------------
//
TBool CEikListBox::HandlePhysicsPointerEventL( const TPointerEvent& aPointerEvent )
    {
    _AKNTRACE_FUNC_ENTER;
    _AKNTRACE( "aPointerEvent.iType = %d", aPointerEvent.iType );
    if ( iListBoxExt->iPhysics->OngoingPhysicsAction() == CAknPhysics::EAknPhysicsActionBouncing )
        {  
        // Block scrolling events outside listbox area.
        if ( iListBoxExt->IgnorePointerEventsUntilUp() )
            {
            _AKNTRACE_FUNC_EXIT;
            return ETrue;
            }
        }

    TBool blockEvent = EFalse;
    
    TBool allowDragEvent( ( iListBoxFlags & ELeftDownInViewRect ) && !iListBoxExt->iScrollingDisabled );

    
    switch ( aPointerEvent.iType )
        {
        case TPointerEvent::EButton1Down:
            {
            TInt tappedItemIndex = KErrNotFound;
            iListBoxExt->iItemDraggingReported = EFalse;
            
            // If list is tapped while flicking then EEventItemClicked etc are not sent
            if ( iListBoxExt->iPhysics->OngoingPhysicsAction() == CAknPhysics::EAknPhysicsActionFlicking )
                {
                iListBoxExt->iClickEventsAllowed = EFalse;
                if ( iItemDrawer->Flags() & CListItemDrawer::EPressedDownState )
                    {
                    iItemDrawer->ClearFlags( CListItemDrawer::EPressedDownState ); 
                    }
                
                // Multiselection list tapped while flicking.
                // Just move the highlight, pressed down highlight and
                // item marking are ignored.     
                if ( iListBoxFlags & ES60StyleMultiselection )
                    {
                    iListBoxExt->iIsDownOnItem =
                        iView->XYPosToItemIndex( aPointerEvent.iPosition,
                                                 tappedItemIndex );
                    if ( iListBoxExt->iIsDownOnItem )
                        {
                        iListBoxExt->iLastDownTappedItem = tappedItemIndex;
                        iListBoxExt->iMarkingDisabled = ETrue;
                        iListBoxFlags|=ELeftDownInViewRect;                        
                        blockEvent = ETrue;
                        iListBoxExt->ImmediateFeedback( 
                            ETouchFeedbackList,
                            TTouchFeedbackType( ETouchFeedbackVibra | 
                            ETouchFeedbackAudio ),
                            aPointerEvent );
                        }
                    }
                }
            else
                {
                iListBoxExt->iClickEventsAllowed = ETrue;
                }
            
            if ( iView->XYPosToItemIndex( aPointerEvent.iPosition, tappedItemIndex ) )
                {
                // Start highlight timer if needed
                if ( tappedItemIndex != iView->CurrentItemIndex() ||
                     iListBoxExt->iSingleClickEnabled )
                    {                   
                    if ( !iListBoxExt->iSingleClickEnabled )
                        {
                        iListBoxExt->StartHighlightTimer();
                        }                    
                    else if ( !( iItemDrawer->Flags() & CListItemDrawer::EDisableMarquee ) )
                        {
                        // Disable marquee
                        iItemDrawer->SetFlags( CListItemDrawer::EDisableMarquee );
                        }
                    }
                }

            iListBoxExt->iPhysics->StopPhysics();
            iListBoxExt->iPhysics->ResetFriction();
            iListBoxExt->iDragStartPosition = aPointerEvent.iPosition;
            iListBoxExt->iLastPointerPos = aPointerEvent.iPosition;
            iListBoxExt->iScrolling = EFalse;
            iListBoxExt->InitPhysicsL();
            iListBoxExt->iStartTime.HomeTime();
            }
            break;
        case TPointerEvent::EButtonRepeat: // fall through
        case TPointerEvent::EDrag:
            {
            if ( allowDragEvent )
                {
                TPoint drag( iListBoxExt->iDragStartPosition - aPointerEvent.iPosition );

                TInt currentItemIndex = iView->CurrentItemIndex();
                TInt touchedItemIndex( KErrNotFound );

                if ( Abs( drag.iY ) > iListBoxExt->iPhysics->DragThreshold() &&
                        !iListBoxExt->iScrolling )
                    {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
                    SuspendEffects( ETrue );
#endif // RD_UI_TRANSITION_EFFECTS_LIST
                    iListBoxExt->iScrolling = ETrue;
                    iListBoxExt->CancelHighlightTimer();

                    // Cancel long tap detecting
                    iListBoxExt->CancelLongTapL();
                    // Remove highlight if single click enabled
                    if ( iListBoxExt->iSingleClickEnabled )
                        {
                        iListBoxExt->EnableHighlight( EFalse );
                        iListBoxExt->iLastDownTappedItem = KErrNotFound;
                        iView->SetItemIndex( 0 );
                        }

                    if ( iView->ItemIsVisible( currentItemIndex ) )
                        {
                        iItemDrawer->ClearFlags( CListItemDrawer::EPressedDownState );
                        iView->DrawItem( currentItemIndex );
                        }
                    
                    ReportListBoxEventL( MEikListBoxObserver::EEventPanningStarted );
                    }
                else if ( !iListBoxExt->iScrolling &&
                          iView->XYPosToItemIndex( aPointerEvent.iPosition, touchedItemIndex ) )
                    {
                    // Don't send the dragging actioned event if the
                    // highlight timer hasn't yet completed as in that case
                    // the current item index isn't updated yet.
                    if ( currentItemIndex != touchedItemIndex &&
                         !iListBoxExt->iItemDraggingReported &&
                         !iListBoxExt->HighlightTimerActive() )
                        {
                        iListBoxExt->iItemDraggingReported = ETrue;
                        ReportListBoxEventL( MEikListBoxObserver::EEventItemDraggingActioned );
                        }
                    }
                if ( iItemDrawer->Flags() & CListItemDrawer::EPressedDownState
                          && !iView->ItemIsVisible( currentItemIndex ) )
                    {
                    iItemDrawer->ClearFlags( CListItemDrawer::EPressedDownState );
                    }
                
                if ( iListBoxExt->iScrolling )
                    {
                    iListBoxExt->iPhysics->RegisterPanningPosition( 
                        TPoint( 0, iListBoxExt->iLastPointerPos.iY - aPointerEvent.iPosition.iY ) );

#ifdef _DEBUG
                    RDebug::Print( _L( "CEikListBox::HandlePhysicsPointerEventL, newViewPosition.iX = %d, iY = %d" ), iListBoxExt->iViewPosition.iX, iListBoxExt->iViewPosition.iY );
                    RDebug::Print( _L( "CEikListBox::HandlePhysicsPointerEventL, iListBoxExt->iLastPointerPos.iY = %d" ), iListBoxExt->iLastPointerPos.iY );
                    RDebug::Print( _L( "CEikListBox::HandlePhysicsPointerEventL, aPointerEvent.iPosition.iY = %d" ), aPointerEvent.iPosition.iY );
#endif // _DEBUG
    
                    blockEvent = ETrue;
                    }
    
                iListBoxExt->iLastPointerPos = aPointerEvent.iPosition;
                }
            }
            break;
        
        case TPointerEvent::EButton1Up:
            {          
            if ( iListBoxFlags & ES60StyleMultiselection 
                 && iListBoxExt->iMarkingDisabled )
                {
                // Allow marking again on next up event.
                iListBoxExt->iMarkingDisabled = EFalse;
                blockEvent = ETrue;
                }
            
            // update selected item in case highlight timer is still running
            if ( iListBoxExt->HighlightTimerActive() )
                {
                // Must cancel highlight timer directly instead of using
                // CListBoxExt::CancelHighlightTimer(), because it will
                // also clear the flags used in the highlight timer
                // callback function.
                iListBoxExt->iHighlightTimer->Cancel();
                CListBoxExt::HighlightTimerCallback( iListBoxExt );
                }
                
            TPoint drag( iListBoxExt->iDragStartPosition - aPointerEvent.iPosition );

            iListBoxExt->LongTapPointerEventL( aPointerEvent );
            
            if (  allowDragEvent &&
                 iListBoxExt->iPhysics->StartPhysics( drag, iListBoxExt->iStartTime ) )
                {
                iListBoxExt->CancelLongTapL();

                if ( !iListBoxExt->iScrolling )
                    {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
                    SuspendEffects( ETrue );
#endif // RD_UI_TRANSITION_EFFECTS_LIST
                    iItemDrawer->ClearFlags( CListItemDrawer::EPressedDownState );
                    iView->DrawItem( iView->CurrentItemIndex() );
                    iListBoxExt->iScrolling = ETrue;
                    }
                else
                    {
                    ReportListBoxEventL( MEikListBoxObserver::EEventPanningStopped );
                    }
                
                blockEvent = ETrue;

                // Clearing ELeftDownInViewRect should be done by rest code in
                // CEikListBox::HandlePointerEventL, but since the event is 
                // blocked, do it here
                iListBoxFlags&=(~ELeftDownInViewRect);

                ReportListBoxEventL( MEikListBoxObserver::EEventFlickStarted );
                }
            else
                {
                iListBoxExt->iScrolling = EFalse;
                }

            if ( iListBoxExt->iSingleClickEnabled
                     && iListBoxExt->iLongTappedItem == KErrNotFound ) 
                {
                iListBoxExt->EnableHighlight( EFalse );
                TInt itemIndex( 0 );
                if ( !iView->XYPosToItemIndex(
                        aPointerEvent.iPosition, itemIndex ) )
                    {
                    iListBoxExt->iLastDownTappedItem = KErrNotFound;
                    }
                }
            }
            iListBoxExt->iIsDownOnItem = EFalse;
            break;
            
        default:
            break;
        }

    iView->SetScrolling( iListBoxExt->iScrolling );
    _AKNTRACE_FUNC_EXIT;
    return blockEvent;
    }


// ---------------------------------------------------------------------------
// Draws the highlight to the current item.
// ---------------------------------------------------------------------------
//
void CEikListBox::UpdateHighlightL( TInt aItemIndex )
    {
    _AKNTRACE_FUNC_ENTER;
    TInt oldCurrentItemIndex = iView->CurrentItemIndex();

    if ( iListBoxExt && iListBoxExt->iReportDelayedPenDown 
        && !iListBoxExt->iScrolling )
        {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
        if ( aItemIndex != oldCurrentItemIndex )
            {
            MAknListBoxTfxInternal* transApi =
                        CAknListLoader::TfxApiInternal( iView->iGc );
            if ( transApi && !transApi->EffectsDisabled() )
                {
                transApi->SetMoveType( MAknListBoxTfxInternal::EListTap );
                }
            }
#endif
        iView->SetItemIndex( aItemIndex );
        ReportListBoxEventL(
            MEikListBoxObserver::EEventPenDownOnItem );
        
        // The long tap animation should start after the highlight has
        // been made visible.
        iListBoxExt->LongTapPointerEventL(
            iListBoxExt->iDelayedPointerDownEvent );
        }

    if ( iListBoxExt && iListBoxExt->iDelayedMultiselection )
        {
        iItemDrawer->SetFlags( CListItemDrawer::EPressedDownState );
        }
    
    iView->SetItemIndex( aItemIndex );

    if ( iListBoxExt && iListBoxExt->iMarkableListMarking )
        {
        if ( iListBoxExt->iMarkableListShiftKeyPressed )
           {
#ifdef RD_UI_TRANSITION_EFFECTS_LIST
           iListBoxExt->iAnchor = oldCurrentItemIndex;
           iListBoxExt->iSelect =
               !iView->ItemIsSelected( iView->CurrentItemIndex() );
#endif // RD_UI_TRANSITION_EFFECTS_LIST

           iView->SetAnchor( oldCurrentItemIndex );
           iView->UpdateSelectionL( CListBoxView::EChangeMarkMode );
           iItemDrawer->SetFlags( CListItemDrawer::EPressedDownState );
           iView->UpdateSelectionL( CListBoxView::EPenMultiselection );
           }
      else
           {
           iView->SetAnchor( aItemIndex - 1 );

#ifdef RD_UI_TRANSITION_EFFECTS_LIST
           iListBoxExt->iAnchor = aItemIndex - 1;
#endif // RD_UI_TRANSITION_EFFECTS_LIST
           }

        iListBoxExt->iMarkableListMarking = EFalse;
        }

    iView->DrawItem( oldCurrentItemIndex );
    iView->DrawItem( aItemIndex );
    
    if ( iListBoxExt && iListBoxExt->iDelayedMultiselection )
        {
        iListBoxFlags |= EStateChanged;
        Buffer()->iPressedIndex = aItemIndex;
        }

    ReportEventL( MCoeControlObserver::EEventStateChanged );
    _AKNTRACE_FUNC_EXIT;
    }


// ---------------------------------------------------------------------------
// CEikListBox::MarkingMode
// ---------------------------------------------------------------------------
//
TBool CEikListBox::MarkingMode() const
    {
    TBool markingModeInUse = EFalse;
    
    if ( iListBoxExt )
        {
        markingModeInUse = iListBoxExt->iMarkingModeInUse;
        }
    
    return markingModeInUse;
    }


// ---------------------------------------------------------------------------
// CEikListBox::MarkingModeObserver
// ---------------------------------------------------------------------------
//
MAknMarkingModeObserver* CEikListBox::MarkingModeObserver()
    {
    MAknMarkingModeObserver* observer = NULL;
    
    if ( iListBoxExt )
        {
        observer = iListBoxExt->iMarkingModeObserver;
        }
    
    return observer;
    }


// ---------------------------------------------------------------------------
// Sets this control as visible or invisible.
// ---------------------------------------------------------------------------
//
EXPORT_C void CEikListBox::MakeVisible( TBool aVisible )
    {
    CEikBorderedControl::MakeVisible( aVisible );
    if ( iListBoxExt )
        {
        if ( !aVisible )
            {
            iListBoxExt->EnableHighlight( EFalse );
            }
        else
            {
            iListBoxExt->ReportCollectionChangedEvent();
            }
        }
    }

//
// class CEikSnakingListBox
//

EXPORT_C CEikSnakingListBox::CEikSnakingListBox()
    {
    AKNTASHOOK_ADD( this, "CEikSnakingListBox" );
    }

EXPORT_C CEikSnakingListBox::~CEikSnakingListBox()
    {
    AKNTASHOOK_REMOVE();
    }

EXPORT_C CListBoxView* CEikSnakingListBox::MakeViewClassInstanceL() 
    {
    return (new(ELeave) CSnakingListBoxView);
    }

EXPORT_C TInt CEikSnakingListBox::ColumnWidth() const
    {
    __ASSERT_DEBUG(iView, Panic(EEikPanicListBoxNoView));
    return ((CSnakingListBoxView*)iView)->ColumnWidth();
    }

EXPORT_C void CEikSnakingListBox::SetColumnWidth(TInt aColumnWidth)
    {
    __ASSERT_DEBUG(iView, Panic(EEikPanicListBoxNoView));
    ((CSnakingListBoxView*)iView)->SetColumnWidth(aColumnWidth);
    }

EXPORT_C void CEikSnakingListBox::HandleLeftArrowKeyL(CListBoxView::TSelectionMode aSelectionMode)
    {
    iView->MoveCursorL(CListBoxView::ECursorPreviousColumn, aSelectionMode);
    ClearMatchBuffer();
    }

EXPORT_C void CEikSnakingListBox::HandleRightArrowKeyL(CListBoxView::TSelectionMode aSelectionMode)
    {
    iView->MoveCursorL(CListBoxView::ECursorNextColumn, aSelectionMode);
    ClearMatchBuffer();
    }

EXPORT_C TInt CEikSnakingListBox::HorizontalNudgeValue() const
    {
    return 1;   // scroll horizontal by one column when the left/right scroll arrows (i.e. the nudge buttons) are tapped
    }

EXPORT_C TInt CEikSnakingListBox::HorizScrollGranularityInPixels() const
    {
    return ColumnWidth(); // horiz scrollbar model set in columns for snaking list box
    }

EXPORT_C void CEikSnakingListBox::SetTopItemIndex(TInt aItemIndex) const
    {
    __ASSERT_DEBUG(iView, Panic(EEikPanicListBoxNoView));
    iView->SetTopItemIndex(aItemIndex);
    }

EXPORT_C void CEikSnakingListBox::HandleViewRectSizeChangeL()
    {
    _AKNTRACE_FUNC_ENTER;
    iView->CalcBottomItemIndex();
    TInt oldTopItemIndex = TopItemIndex();
    TInt newTopItemIndex = TopItemIndex();
    TInt currentItemIndex = CurrentItemIndex();
    TInt numOfItemsPerColumn = 0;   
    UpdateScrollBarsL();
    numOfItemsPerColumn = iView->ViewRect().Height() / iItemHeight;
    numOfItemsPerColumn = Max(1, numOfItemsPerColumn);
    if (currentItemIndex != oldTopItemIndex)
        {
        TInt colIndexOfTargetItem = currentItemIndex / numOfItemsPerColumn;
        TInt numOfColsThatFitInViewRect = iView->VisibleWidth(iView->ViewRect());
        TInt adjustment = newTopItemIndex % numOfItemsPerColumn;
        if (adjustment != 0)
            // adjust newTopItemIndex till it refers to the index of an item at the top of a column
            newTopItemIndex -= adjustment;
        TInt newBottomItemIndex = newTopItemIndex + (numOfColsThatFitInViewRect * numOfItemsPerColumn) - 1;
        if (currentItemIndex < newTopItemIndex)
            newTopItemIndex = colIndexOfTargetItem * numOfItemsPerColumn;
        else if (currentItemIndex > newBottomItemIndex)
            {
            TInt colIndexOfNewBottomItem = colIndexOfTargetItem;
            TInt colIndexOfNewTopItem = colIndexOfNewBottomItem - (numOfColsThatFitInViewRect - 1);
            newTopItemIndex = colIndexOfNewTopItem * numOfItemsPerColumn;
            }
        }
    else if ((newTopItemIndex != 0) && (numOfItemsPerColumn != 0))
        {
        TInt adjustment = newTopItemIndex % numOfItemsPerColumn;
        if (adjustment != 0)
            // adjust newTopItemIndex till it refers to the index of an item at the top of a column
            newTopItemIndex -= adjustment;
        }
    SetTopItemIndex(newTopItemIndex);
    iView->CalcDataWidth();
    UpdateScrollBarsL();
    iView->CalcBottomItemIndex();
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikSnakingListBox::SizeChanged()
    {
    TRect clientRect = iBorder.InnerRect(Rect());
    SetViewRectFromClientRect(clientRect);
    TRAP_IGNORE(HandleViewRectSizeChangeL());
    }

EXPORT_C void CEikSnakingListBox::AdjustTopItemIndex() const
    {
    _AKNTRACE_FUNC_ENTER;
    // assumes we know # of items in the model
    TInt numOfItemsPerCol = iView->ViewRect().Height() / iItemHeight;
    numOfItemsPerCol = Max(1, numOfItemsPerCol);
    TInt numOfVisCols = iView->VisibleWidth(iView->ViewRect());
    TInt numOfItems = iModel->NumberOfItems();
    TInt colIndexOfRightmostCol = numOfItems / numOfItemsPerCol;
    TInt maxTopItemIndex = Max (0, (colIndexOfRightmostCol - (numOfVisCols - 1)) * numOfItemsPerCol);
    if (iView->TopItemIndex() > maxTopItemIndex)
        SetTopItemIndex(maxTopItemIndex);
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikSnakingListBox::HandleDragEventL(TPoint aPointerPos)
    {
    _AKNTRACE_FUNC_ENTER;
    if (!(iListBoxFlags & ELeftDownInViewRect))
        {
        _AKNTRACE_FUNC_EXIT;
        return;
        }
    TRect ignoreDragRect(TPoint(aPointerPos.iX-20, aPointerPos.iY-20), TPoint(aPointerPos.iX+20, aPointerPos.iY+20));
    TRect viewRect(iView->ViewRect());
    TInt itemIndex;
    TBool pointerIsOverAnItem = iView->XYPosToItemIndex(aPointerPos, itemIndex);
    // SERIES60 LAF
#if 1 
    CListBoxView::TSelectionMode selectionMode = CListBoxView::ENoSelection;
#else
    CListBoxView::TSelectionMode selectionMode = (iListBoxFlags & EMultipleSelection) ? CListBoxView::EContiguousSelection : CListBoxView::ESingleSelection;
#endif
    // END OF SERIES60 LAF
    TInt oldCurrentItemIndex = iView->CurrentItemIndex();
    TRect currentItemRect(iView->ItemPos(oldCurrentItemIndex), iView->ItemSize(oldCurrentItemIndex));
    if (pointerIsOverAnItem)
        {
        // drag event occurred within the listbox
        iView->SetCurrentItemIndex(itemIndex);
        if (itemIndex != oldCurrentItemIndex) 
            {
            iView->SetCurrentItemIndex(itemIndex);
            iView->DrawItem(oldCurrentItemIndex);
            iView->UpdateSelectionL(selectionMode);
            iView->DrawItem(itemIndex);
            }
        }
    else if ((aPointerPos.iX < viewRect.iTl.iX) || (aPointerPos.iX > viewRect.iBr.iX))
        {
        // drag event occurred outside the listbox's viewRect
        if (aPointerPos.iX < viewRect.iTl.iX)
            iView->MoveCursorL(CListBoxView::ECursorPreviousColumn, selectionMode);
        else if (aPointerPos.iX > viewRect.iBr.iX)
            iView->MoveCursorL(CListBoxView::ECursorNextColumn, selectionMode);
        MoveToNextOrPreviousItemL(aPointerPos);     
        UpdateScrollBarThumbs();
        Window().RequestPointerRepeatEvent(KEikListBoxPointerRepeatInterval, ignoreDragRect);
//      Window().RequestPointerRepeatEvent(ListBoxLaf()->LBxPointerRepeatInterval(), ignoreDragRect);
        }
    else
        {
        // find item nearest to the pointer pos and make that the current item
        if (viewRect.Contains(aPointerPos))
            {
            }
        else
            {
            if (aPointerPos.iX > currentItemRect.iBr.iX)
                iView->MoveCursorL(CListBoxView::ECursorNextColumn, selectionMode);
            else if (aPointerPos.iX < currentItemRect.iTl.iX)
                iView->MoveCursorL(CListBoxView::ECursorPreviousColumn, selectionMode);
            MoveToNextOrPreviousItemL(aPointerPos);
            UpdateScrollBarThumbs();
            Window().RequestPointerRepeatEvent(KEikListBoxPointerRepeatInterval, ignoreDragRect);
//          Window().RequestPointerRepeatEvent(ListBoxLaf()->LBxPointerRepeatInterval(), ignoreDragRect);
            }
        }
    if (iView->CurrentItemIndex() != oldCurrentItemIndex)
        {
        iListBoxFlags |= EStateChanged;
        if (IsMatchBuffer())
            {
            ClearMatchBuffer();
            DrawMatcherCursor();
            }
        }
    }

EXPORT_C void CEikSnakingListBox::MoveToNextOrPreviousItemL(TPoint aPointerPos)
    {
    // AVKON LAF
#if 1
    CListBoxView::TSelectionMode selectionMode = CListBoxView::ENoSelection;
#else
    CListBoxView::TSelectionMode selectionMode = (iListBoxFlags & EMultipleSelection) ? CListBoxView::EContiguousSelection : CListBoxView::ESingleSelection;
#endif
    // END OF AVKON LAF
    TInt cix = iView->CurrentItemIndex();
    TRect currentItemRect(iView->ItemPos(cix), iView->ItemSize(cix));
    TInt numOfRows =  ((CSnakingListBoxView*)iView)->NumberOfItemsPerColumn();
    TBool currItemIsInLastRow = ((cix % numOfRows) == (numOfRows-1));
    TBool currItemIsLastItem = (cix == (iModel->NumberOfItems()-1));
    TBool currItemIsInFirstRow = ((cix % numOfRows) == 0);
    if ((aPointerPos.iY > currentItemRect.iBr.iY) && (! (currItemIsInLastRow || currItemIsLastItem)))
        iView->MoveCursorL(CListBoxView::ECursorNextItem, selectionMode);
    else if ((aPointerPos.iY < currentItemRect.iTl.iY) && (! currItemIsInFirstRow))
        iView->MoveCursorL(CListBoxView::ECursorPreviousItem, selectionMode);
    _AKNTRACE_FUNC_EXIT;
    }

EXPORT_C void CEikSnakingListBox::RestoreClientRectFromViewRect(TRect& aClientRect) const
    {
    aClientRect=iView->ViewRect();
    aClientRect.SetRect(aClientRect.iTl.iX - ListBoxMargins().iLeft, aClientRect.iTl.iY - ListBoxMargins().iTop,
        aClientRect.iBr.iX + ListBoxMargins().iRight, aClientRect.iBr.iY + ListBoxMargins().iBottom);
    if (!ViewRectHeightAdjustment())
        return;
    aClientRect.iBr.iY += ViewRectHeightAdjustment();
    }

EXPORT_C TInt CEikSnakingListBox::AdjustRectHeightToWholeNumberOfItems(TRect& aRect) const
    {
    TInt remainder = aRect.Height() % iItemHeight;
    if (remainder != 0) 
        aRect.iBr.iY -= remainder;
    return remainder;
    }

/**
 * Gets the list of logical colors employed in the drawing of the control,
 * paired with an explanation of how they are used. Appends the list to aColorUseList.
 *
 * @since ER5U 
 */
EXPORT_C void CEikSnakingListBox::GetColorUseListL(CArrayFix<TCoeColorUse>& /*aColorUseList*/) const
    {
    }

/**
 * Handles a change to the control's resources of type aType
 * which are shared across the environment, e.g. colors or fonts.
 *
 * @since ER5U 
 */
EXPORT_C void CEikSnakingListBox::HandleResourceChange(TInt aType)
    {
    CCoeControl::HandleResourceChange(aType);
    }

EXPORT_C void CEikSnakingListBox::HandlePointerEventL(const TPointerEvent& aPointerEvent) 
    { 
    CEikListBox::HandlePointerEventL(aPointerEvent); 
    }

EXPORT_C void* CEikSnakingListBox::ExtensionInterface( TUid /*aInterface*/ )
    {
    return NULL;
    }

EXPORT_C void CEikSnakingListBox::Reserved_1()
    {}

EXPORT_C void CEikSnakingListBox::Reserved_2()
    {}

EXPORT_C void CEikSnakingListBox::CEikListBox_Reserved()
    {}
