--- /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
+