diff -r c84cf270c54f -r 8871b09be73b phoneuis/easydialing/src/easydialinglistbox.cpp --- /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 + +#include +#include +#include + +#include + +// AvKON and drawing header files + +#include +#include // Required for touch +#include +#include // tooltips + +#include +#include +#include +#include +#include // for BaflUtils + +#include +#include +#include + +// 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 (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( 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 ( 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 + ( 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 +