phoneuis/easydialing/src/easydialinglistbox.cpp
branchRCL_3
changeset 9 8871b09be73b
child 15 2a26698d78ba
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phoneuis/easydialing/src/easydialinglistbox.cpp	Fri Feb 19 22:50:26 2010 +0200
@@ -0,0 +1,537 @@
+/*
+* Copyright (c) 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:  Easy dialing list box.
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "easydialinglistbox.h"
+#include "easydialinglistboxview.h"
+#include "easydialinglistboxitemdrawer.h"
+#include "easydialinglistboxdata.h"
+#include "easydialingpanics.h"
+#include "easydialingcontactdatamanager.h"
+#include "easydialingcrkeys.h"
+
+#include <easydialingpluginresources.rsg>
+
+#include <phoneappcommands.hrh>
+#include <phonebook2.mbg>
+#include <phonebook2ece.mbg>
+
+#include <ccappcommlauncherpluginrsc.rsg>
+
+// AvKON and drawing header files
+
+#include <aknpointereventsuppressor.h> 
+#include <aknlongtapdetector.h> // Required for touch
+#include <AknsFrameBackgroundControlContext.h>
+#include <AknInfoPopupNoteController.h>  // tooltips
+
+#include <aknlayoutscalable_apps.cdl.h>
+#include <layoutmetadata.cdl.h>
+#include <gulicon.h>
+#include <centralrepository.h>
+#include <bautils.h>    // for BaflUtils
+
+#include <aknlistloadertfx.h>
+#include <aknlistboxtfxinternal.h>
+#include <aknlistboxtfx.h>
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES  
+
+extern TRect ContactImageBoundingBox( const TRect& aItemRect );
+extern TRect ActionMenuIconBoundingBox(const TRect& aItemRect);
+
+// CONSTANTS
+static const TInt KListBoxMarginWidth = 2;
+static const TInt KMaxVisibleItemsPortrait = 3;
+static const TInt KMaxVisibleItemsLandscape = 2;
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+
+/*
+ * ==============================================================================
+ * 
+ * 
+ * class CEasyDialingListBox
+ * 
+ * 
+ * ==============================================================================
+ */
+
+
+// -----------------------------------------------------------------------------
+// CEasyDialingListBox
+// 
+// -----------------------------------------------------------------------------
+//
+CEasyDialingListBox::CEasyDialingListBox() :
+    CEikFormattedCellListBox()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// ~CEasyDialingListBox
+// 
+// -----------------------------------------------------------------------------
+//
+CEasyDialingListBox::~CEasyDialingListBox()
+    {
+    delete iBGContext;    
+    delete iLongTapDetector;
+    }
+
+// -----------------------------------------------------------------------------
+// ConstructL
+// 
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::ConstructL( TInt aFlags, 
+        CEasyDialingContactDataManager* aContactDataManager )
+    {
+    CEikFormattedCellListBox::ConstructL( NULL, aFlags );
+    
+    iLongTapDetector = CAknLongTapDetector::NewL( this );
+ 
+    CEasyDialingListBoxItemDrawer* drawer = static_cast<CEasyDialingListBoxItemDrawer*> (iItemDrawer);
+    CEasyDialingListBoxData* data = drawer->EasyDialingCellData();
+    data->SetContactDataManager(aContactDataManager);
+    data->SetEDLBXControl(this);
+    
+    iBGContext = CAknsFrameBackgroundControlContext::NewL( KAknsIIDQsnFrPopupSub,
+            Rect(), Rect(), EFalse );
+       
+    // ContactDataManager is accessed from SizeChanged. If list item size
+    // changes -> thumbnail size changes
+    iContactDataManager = aContactDataManager;
+    
+    drawer->SetColors();
+
+    CreateScrollBarFrameL( ETrue );
+    ScrollBarFrame()->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto );
+    }
+
+
+// -----------------------------------------------------------------------------
+// MakeViewClassInstanceL
+// 
+// -----------------------------------------------------------------------------
+//
+CListBoxView* CEasyDialingListBox::MakeViewClassInstanceL()
+    {
+    return (new ( ELeave ) CEasyDialingListBoxView);
+    }
+
+
+// -----------------------------------------------------------------------------
+// ItemDrawer
+// 
+// -----------------------------------------------------------------------------
+//
+CEasyDialingListBoxItemDrawer* CEasyDialingListBox::ItemDrawer() const
+    {
+    return (CEasyDialingListBoxItemDrawer*) iItemDrawer;
+    }
+
+
+// -----------------------------------------------------------------------------
+// FocusChanged
+// 
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::FocusChanged( TDrawNow aDrawNow )
+    {
+    if ( !IsFocused() )
+        {
+        CEasyDialingListBoxView* view = static_cast<CEasyDialingListBoxView*>( iView );
+        view->SetCurrentItemIndexToNone();
+        
+        // Invalidate window area. 
+        // This fixes the drawing problem that the top 
+        // of listbox is not always redrawn on the area that overlaps 
+        // the status pane area. 
+        // TODO: This overlapping no longer happens in 9.2 so this may
+        // now be unnecessary.
+        Window().Invalidate();
+        }
+    CEikFormattedCellListBox::FocusChanged( aDrawNow );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CreateItemDrawerL
+// 
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::CreateItemDrawerL()
+    {
+    CEasyDialingListBoxData* celldata = CEasyDialingListBoxData::NewL();
+    CleanupStack::PushL( celldata );
+    iItemDrawer = new(ELeave) CEasyDialingListBoxItemDrawer(Model(), iEikonEnv->NormalFont(), celldata);
+    CleanupStack::Pop( celldata );  
+    }
+
+
+// -----------------------------------------------------------------------------
+// Draw
+// 
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::Draw(const TRect& aRect) const
+    {
+    MAknListBoxTfxInternal *transApi = CAknListLoader::TfxApiInternal( iItemDrawer->Gc() );
+    if ( transApi )
+        {
+        transApi->SetListType( MAknListBoxTfxInternal::EListBoxTypeMainPane );
+        transApi->BeginRedraw( MAknListBoxTfxInternal::EListView, this->Rect() );
+        }
+    
+    if (!iView->RedrawDisabled() )
+        {
+        TRect clientRect( Rect() );
+        TRect viewRect = iView->ViewRect();
+        
+        if ( transApi )
+            {
+            transApi->StartDrawing( MAknListBoxTfxInternal::EListView );
+            }
+
+        AknsDrawUtils::BackgroundBetweenRects( 
+            AknsUtils::SkinInstance(), 
+            iBGContext, 
+            this, 
+            *iItemDrawer->Gc(), 
+            clientRect, 
+            viewRect );
+        
+        if ( transApi )
+            {
+            transApi->StopDrawing();
+            }
+        }
+    
+    if ( iModel->NumberOfItems() )
+        {
+        // Draw the actual list
+        iView->Draw(&aRect);
+        }
+    if ( transApi )
+        {
+        transApi->EndViewRedraw( aRect );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// HandleResourceChange
+// 
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::HandleResourceChange(TInt aType)
+    {
+    CEikFormattedCellListBox::HandleResourceChange( aType );
+    iSBFrame->VerticalScrollBar()->HandleResourceChange( aType );
+    iSBFrame->DrawScrollBarsNow();
+    ItemDrawer()->SetColors();
+    
+    // Base call to HandleResourceChange justifies the list to even items
+    // on the top. This causes problems when listbox height is not a multiple of
+    // listitem heights. Fix scrolling manually for these cases.
+    TRAP_IGNORE( HandleItemAdditionL() ); // needed to prevent drawing problems
+    TInt scrollIndex = ( IsFocused() ? CurrentItemIndex() : iNumberOfNames - 1 );
+    ScrollToMakeItemVisible( scrollIndex );
+    
+    DrawDeferred();
+    }
+
+
+// -----------------------------------------------------------------------------
+// SizeChanged
+// 
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::SizeChanged()
+    {
+    CEikFormattedCellListBox::SizeChanged();
+    
+    // Set the listbox colors.
+    // For some reason, calling this in HandleResourceChange is not enough, it does
+    // not get called in situation it should.
+    ItemDrawer()->SetColors();
+   
+    // resize scroll bar
+    if ( iSBFrame )
+        {
+        TAknLayoutRect rect;
+        TInt variety = ( Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0 );
+    
+        TAknWindowComponentLayout viewLayout( AknLayoutScalable_Apps::dia3_list_pane( variety ) );
+        rect.LayoutRect( Rect(), viewLayout );
+        TRect viewRect( rect.Rect() );
+        // Add a bit of margin around the view as layout doesn't define any
+        viewRect.Shrink( KListBoxMarginWidth, KListBoxMarginWidth );
+        
+        TAknWindowComponentLayout scrollBarLayout( AknLayoutScalable_Apps::scroll_pane_cp12() );
+        rect.LayoutRect( Rect(), scrollBarLayout );
+        TRect scrollBarRect( rect.Rect() );
+
+        iView->SetViewRect( viewRect );
+        
+        CAknDoubleSpanScrollBar* scrollbar = static_cast <CAknDoubleSpanScrollBar*>( iSBFrame->VerticalScrollBar() );
+
+        scrollbar->SetFixedLayoutRect( scrollBarRect );
+        scrollbar->SetRect( scrollBarRect );
+        
+        TRect viewAndScrollBarRect( viewRect );
+        
+        if ( AknLayoutUtils::LayoutMirrored() )
+            {
+            viewAndScrollBarRect.iTl = scrollBarRect.iTl;
+            }
+        else
+            {
+            viewAndScrollBarRect.iBr = scrollBarRect.iBr;
+            }
+        iBGContext->SetFrameRects( Rect(), viewAndScrollBarRect );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// MopSupplyObject
+// 
+// -----------------------------------------------------------------------------
+//
+TTypeUid::Ptr CEasyDialingListBox::MopSupplyObject( TTypeUid aId )
+    {
+    if ( aId.iUid == MAknsControlContext::ETypeId && iBGContext )
+        {
+        return MAknsControlContext::SupplyMopObject( aId, iBGContext );
+        }
+    return CEikFormattedCellListBox::MopSupplyObject( aId );    
+    }
+
+// -----------------------------------------------------------------------------
+// MakeVisible
+// 
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::MakeVisible( TBool aVisible )
+    {
+    if ( aVisible != IsVisible() )
+        {
+        CEikFormattedCellListBox::MakeVisible( aVisible );
+        if ( iSBFrame )
+            {
+            CEikScrollBar* sb = iSBFrame->GetScrollBarHandle( CEikScrollBar::EVertical );
+            if ( sb )
+                {
+                sb->MakeVisible( aVisible );
+                if ( aVisible )
+                    {
+                    UpdateScrollBarThumbs();
+                    }
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// SetMaxRect
+//
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::SetMaxRect( TRect aMaxRect )
+    {
+    iMaxRect = aMaxRect;
+
+    // Update the list item size according the maximum view rect size
+    TInt variety = ( Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0 );
+    TAknLayoutRect maxViewLayout;
+    maxViewLayout.LayoutRect( aMaxRect, AknLayoutScalable_Apps::dia3_list_pane( variety ) );
+    TRect maxViewRect( maxViewLayout.Rect() );
+    maxViewRect.Shrink( KListBoxMarginWidth, KListBoxMarginWidth ); // layout data doens't include any margins but we have added some
+    
+    TInt maxItemsShown = ( variety ? KMaxVisibleItemsLandscape : KMaxVisibleItemsPortrait );
+    TInt itemHeight = maxViewRect.Height() / maxItemsShown;
+    TRAP_IGNORE( SetItemHeightL( itemHeight ) );
+
+    // Calculate new thumbnail rect from item size
+    TSize itemSize( maxViewRect.Width(), itemHeight );
+    TRect thumbnailRect = ContactImageBoundingBox( itemSize );
+    iContactDataManager->SetThumbnailSize( thumbnailRect.Size() ); // reloads thumbnails if the new size is different from old one
+
+    // Inform listbox data class about changed list item size
+    ItemDrawer()->EasyDialingCellData()->HandleItemSizeChange();
+    }
+
+// -----------------------------------------------------------------------------
+// SetRectToNumberOfItems
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::SetRectToNumberOfItems( TInt aNumberOfNames ) 
+    {
+    iNumberOfNames = aNumberOfNames;
+
+    TRect listboxRect( iMaxRect );
+    
+    // Make listbox smaller if maximum size is not needed to show
+    // all list items.
+    TInt requiredHeight = GetHeightBasedOnNumberOfItems( iNumberOfNames );
+    if ( requiredHeight < listboxRect.Height() )
+        {
+        // Shrink rect height so that bottom of the rect doesn't move
+        listboxRect.iTl.iY += ( listboxRect.Height() - requiredHeight );
+        }
+    
+    SetRect( listboxRect );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// SetFocusedWithKeyEventL
+// -----------------------------------------------------------------------------
+//
+TKeyResponse CEasyDialingListBox::SetFocusedWithKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aType )
+    {
+    TKeyResponse keyResponse = EKeyWasNotConsumed;
+    TInt keyCode = aKeyEvent.iCode;
+            
+    // Disable redrawing temporarily.
+    // This is because OfferKeyEventL puts the focus to the wrong item,
+    // and we don't want to show it flashing there.
+    // Make sure that no leave happens before redraw is enabled again.
+    iView->SetDisableRedraw( ETrue );
+        
+    TRAP_IGNORE( keyResponse = OfferKeyEventL( aKeyEvent, aType ) );
+    
+    TInt itemToFocus = ( keyCode == EKeyUpArrow ? iNumberOfNames - 1 : 0 );
+    ScrollToMakeItemVisible( itemToFocus );
+    SetCurrentItemIndex( itemToFocus );
+        
+    iView->SetDisableRedraw( EFalse );
+    
+    DrawDeferred();
+    
+    return keyResponse;
+    }
+
+
+// -----------------------------------------------------------------------------
+// GetHeightBasedOnNumberOfItems
+// 
+// -----------------------------------------------------------------------------
+//
+TInt CEasyDialingListBox::GetHeightBasedOnNumberOfItems( TInt aNum ) const
+    {
+    return ( ItemHeight()*aNum + KListBoxMarginWidth*2 ); 
+    }
+
+
+// -----------------------------------------------------------------------------
+// CurrentContactDataIndex
+// 
+// -----------------------------------------------------------------------------
+//
+TInt CEasyDialingListBox::CurrentContactDataIndex()
+    {
+    if ( CurrentItemIndex() >= 0 ) 
+        {
+        TPtrC itemText = Model()->ItemText( CurrentItemIndex() );
+        TPtrC indexText;
+        
+        TInt error = TextUtils::ColumnText( indexText , 0, &itemText );
+        __ASSERT_DEBUG( error == KErrNone, EasyDialingPanic( EEasyDialingPanicInvalidListBoxModelString ) );
+
+        TUint id( 0 );
+        TLex lex( indexText );
+        error = lex.Val( id, EHex );
+        __ASSERT_DEBUG( error == KErrNone, EasyDialingPanic( EEasyDialingPanicInvalidListBoxModelString ) );
+        
+        return id;
+        }
+    else 
+        {
+        return KErrNotFound;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CurrentContactLinkLC
+// 
+// -----------------------------------------------------------------------------
+//
+HBufC8* CEasyDialingListBox::CurrentContactLinkLC()
+    {
+    TInt index = CurrentContactDataIndex();
+    return iContactDataManager->ContactLinkLC( index );
+    }
+
+
+// -----------------------------------------------------------------------------
+// HandleLongTapEventL
+// Callback from CAknLongTapDetector.
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::HandleLongTapEventL( const TPoint& /*aPenEventLocation*/, 
+                                               const TPoint& /*aPenEventScreenLocation*/ )
+    {
+    ReportListBoxEventL( static_cast<MEikListBoxObserver::TListBoxEvent>
+            ( KEasyDialingContactLongTapped ) );
+    iPointerLongPressHandled = ETrue;
+    }
+
+
+// -----------------------------------------------------------------------------
+// HandlePointerEventL
+// Pointer event handling within the EasyDialingListBox.
+// -----------------------------------------------------------------------------
+//
+void CEasyDialingListBox::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+    {
+    // Button down event starts new pointer press. Reset flags at this point.
+    if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
+        {
+        iPointerLongPressHandled = EFalse;
+        }
+    
+    iLongTapDetector->PointerEventL(aPointerEvent);
+    if ( iPointerLongPressHandled )
+        {
+        // No further handling is made after long tap on list item
+        // has been detected.
+        return;
+        }
+
+    CEikFormattedCellListBox::HandlePointerEventL( aPointerEvent );
+    }
+
+
+// end of file
+