/*
* Copyright (c) 2009 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:
*
*/
// INCLUDE FILES
#include <ganes/HgList.h>
#include <ganes/HgItem.h>
#include "HgLayoutData.h"
#include "HgDrawUtils.h"
#include "HgScrollbar.h"
#include <aknphysics.h>
#include "HgConstants.h"
#include "HgMarquee.h"
#include <AknIconUtils.h>
#include <avkon.mbg>
#include <AknUtils.h> //AknLayoutUtils
#include <gdi.h> // CFont
#include <AknsUtils.h>
#include <AknsDrawUtils.h>
#include <AknsConstants.h>
#include <AknsFrameBackgroundControlContext.h>
#include <gulicon.h>
#include <layoutmetadata.cdl.h>
#include <aknlayoutscalable_avkon.cdl.h>
// UI Constants
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CHgList::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CHgList::ConstructL (const TRect& aRect, RWsSession* aSession )
{
// Inherited classes might use some custom layout data, so lets use the
// default one only if not yet initialized.
if( !iLayoutData )
iLayoutData = CHgListLayoutData::NewL();
CHgScroller::ConstructL( aRect, aSession );
// Activate the window, which makes it ready to be drawn
ActivateL ( );
}
// -----------------------------------------------------------------------------
// CHgList::CHgList()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CHgList::CHgList( TInt aItemCount,
CGulIcon* aDefaultIcon )
: CHgScroller( aItemCount, aDefaultIcon ),
iColor( KRgbBlack ),
iColorBack( AKN_LAF_COLOR( 0 ) ),
iHighlightedColor( KRgbBlack ),
iHighlightedColorBack( AKN_LAF_COLOR( 0 ) )
{
SetFlags(EHgScrollerSearchWithQWERTY); // Set QWERTY search on
}
// -----------------------------------------------------------------------------
// CHgList::~CHgList()
// Destructor.
// -----------------------------------------------------------------------------
//
EXPORT_C CHgList::~CHgList ( )
{
delete iLayoutData;
}
// -----------------------------------------------------------------------------
// CHgList::InitItemsL()
// -----------------------------------------------------------------------------
//
void CHgList::InitItemsL()
{
for(TInt i = 0; i < iItemCount; ++i)
{
iItems.Append(CHgItem::NewL());
}
}
// -----------------------------------------------------------------------------
// CHgList::DrawHighlight()
// Called by Draw function to draw the higlighted item effect.
// -----------------------------------------------------------------------------
//
void CHgList::DrawHighlight( const TRect& aRect, TRgb& aTextColor ) const
{
// Init drawing options
TRect outerRect( aRect );
TRect innerRect( aRect );
innerRect.Shrink(KListHighlightInnerRectShrink,KListHighlightInnerRectShrink);
CWindowGc& gc = SystemGc();
// Draw "selected item" rect for the row. Bitmaps to draw the rect are feched from
// current skin instance.
if( HasHighlight() )
{
if( iPointerDown && !iPanning && iFocusedIndex != KErrNotFound && iSelectionToFocusedItem )
{
AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(),
gc,
outerRect,
innerRect,
KAknsIIDQsnFrListPressed,
KAknsIIDQsnFrListCenterPressed );
}
else
{
AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(),
gc,
outerRect,
innerRect,
KAknsIIDQsnFrList,
KAknsIIDQsnFrListCenter );
}
aTextColor = iHighlightedColor;
}
else if( iPointerDown && !iPanning )
{
AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(),
gc,
outerRect,
innerRect,
KAknsIIDQsnFrList,
KAknsIIDQsnFrListCenter );
}
}
// -----------------------------------------------------------------------------
// CHgList::HandleSizeChanged()
// Called by framework when the view size is changed.
// -----------------------------------------------------------------------------
//
void CHgList::HandleSizeChanged ( )
{
iLandscapeScrolling = EFalse; // list always scrolls in portrait mode
iRows = iItemCount;
// Resolve colors for normal and higlighted items
if ( AknsUtils::AvkonSkinEnabled() )
{
// this does not modify color unless it gets a correct one
// no real need to check errors
AknsUtils::GetCachedColor(
AknsUtils::SkinInstance(),
iColor,
KAknsIIDQsnTextColors,
EAknsCIQsnTextColorsCG6 );
AknsUtils::GetCachedColor(
AknsUtils::SkinInstance(),
iHighlightedColor,
KAknsIIDQsnTextColors,
EAknsCIQsnTextColorsCG10 );
}
iLayoutData->SetBaseLayout(AknLayoutScalable_Avkon::list_gen_pane(0));
if( iFlags & CHgScroller::EHgScrollerFlatStatusPane )
{
iListOffset = TPoint(0,0);
}
else
{
TAknLayoutRect foobar;
foobar.LayoutRect(Rect(), AknLayoutScalable_Avkon::listscroll_gen_pane(0));
iWidth = foobar.Rect().Width();
iHeight = foobar.Rect().Height();
iListOffset = foobar.Rect().iTl;
}
}
// -----------------------------------------------------------------------------
// CHgList::DoDraw()
// -----------------------------------------------------------------------------
//
void CHgList::DoDraw(const TRect& /*aRect*/ ) const
{
// Calculate the displacement. How much of the first row is showing.
TInt ydiff = (iViewPosition.iY-(iHeight/2))%(iRowHeight);
CWindowGc& gc = SystemGc();
if( iItemCount == 0 )
{
if( iEmptyText )
iDrawUtils->DrawEmptyText(gc, Rect(), *iEmptyText, iColor);
}
else
{
// Get the row rect
TAknLayoutRect layout;
layout.LayoutRect(ListRect(), iLayoutData->ItemLayout());
ResetClippingRect(gc);
// Draw rows
for(TInt i = iCurrentRow; i < iRows && i < iItems.Count(); ++i)
{
// Topleft position of the row.
TPoint point(
0,
((i-iCurrentRow)*iRowHeight) - ydiff);
if( i < 0 || point.iY < iListOffset.iY - layout.Rect().Height() )
continue; // Not a real row
else if( point.iY + iListOffset.iY > iHeight )
break; // Row is now showing on the screen, we can stop.
TRect rect(layout.Rect());
// Move to correct y-position
rect.Move(point);
DrawItem( i, rect );
if( i!= iItems.Count() - 1)
AknListUtils::DrawSeparator( gc, rect, iColor );
}
gc.CancelClippingRect();
}
}
void CHgList::ResetClippingRect( CWindowGc& aGc ) const
{
if( !(iFlags & CHgScroller::EHgScrollerFlatStatusPane) )
aGc.SetClippingRect( TRect(iListOffset, TSize(iWidth, iHeight+2)) );
}
// -----------------------------------------------------------------------------
// CHgList::TotalSize()
// -----------------------------------------------------------------------------
//
TSize CHgList::TotalSize() const
{
return TSize( iWidth, iRows*iRowHeight );
}
// -----------------------------------------------------------------------------
// CHgList::GetSelected()
// -----------------------------------------------------------------------------
//
TInt CHgList::GetSelected( TPoint aPosition ) const
{
// Real position is current screen pos + world pos
TInt y = aPosition.iY + (iViewPosition.iY - (iHeight/2)) - iListOffset.iY;
y /= iRowHeight;
return y >= iItems.Count() || y < 0 ? KErrNotFound : y;
}
// -----------------------------------------------------------------------------
// CHgList::DoHandleKeyEvent()
// -----------------------------------------------------------------------------
//
TBool CHgList::DoHandleKeyEvent(const TKeyEvent& aKeyEvent)
{
TBool ret = ETrue;
switch( aKeyEvent.iCode )
{
case EKeyUpArrow:
HandleUpArrow();
break;
case EKeyDownArrow:
HandleDownArrow();
break;
case EKeyLeftArrow:
case EKeyRightArrow:
default:
ret = EFalse;
break;
}
return ret;
}
// -----------------------------------------------------------------------------
// CHgList::HandleDownArrow()
// -----------------------------------------------------------------------------
//
void CHgList::HandleDownArrow()
{
if( iSelectedIndex == KErrNotFound )
{
SelectDefaultItem();
}
else
{
if( iSelectedIndex <= iRows - 1 )
{
const TInt nextIndex = iSelectedIndex == (iRows - 1) ?
0 : iSelectedIndex + 1;
if( iSelectionMode == ESelectionMark )
{
Mark( iSelectedIndex );
Mark( nextIndex );
}
else if( iSelectionMode == ESelectionUnMark )
{
UnMark( iSelectedIndex );
UnMark( nextIndex );
}
iSelectedIndex = nextIndex;
FitSelectionToView();
SelectionChanged();
DrawDeferred();
}
}
}
// -----------------------------------------------------------------------------
// CHgList::HandleUpArrow()
// -----------------------------------------------------------------------------
//
void CHgList::HandleUpArrow()
{
if( iSelectedIndex == KErrNotFound )
{
SelectDefaultItem();
}
else
{
if( iSelectedIndex >= 0 )
{
const TInt nextIndex = iSelectedIndex == 0 ?
iRows - 1 : iSelectedIndex - 1;
if( iSelectionMode == ESelectionMark )
{
Mark( iSelectedIndex );
Mark( nextIndex );
}
else if( iSelectionMode == ESelectionUnMark )
{
UnMark( iSelectedIndex );
UnMark( nextIndex );
}
iSelectedIndex = nextIndex;
FitSelectionToView();
SelectionChanged();
DrawDeferred();
}
}
}
// -----------------------------------------------------------------------------
// CHgList::FitSelectionToView()
// -----------------------------------------------------------------------------
//
void CHgList::FitSelectionToView()
{
FitRowToView( iSelectedIndex );
}
// -----------------------------------------------------------------------------
// CHgList::ListRect()
// -----------------------------------------------------------------------------
//
TRect CHgList::ListRect() const
{
TRect rect(iListOffset, TSize(iWidth,iHeight));
if(!iScrollbar->IsStatic())
{
TAknLayoutRect areaaftersb;
areaaftersb.LayoutRect(rect, iLayoutData->BaseLayout());
rect = areaaftersb.Rect();
}
return rect;
}
// -----------------------------------------------------------------------------
// CHgList::SelectDefaultItem()
// -----------------------------------------------------------------------------
//
void CHgList::SelectDefaultItem()
{
if( iCurrentRow >= 0 && iCurrentRow < iItems.Count() )
{
iSelectedIndex = iCurrentRow;
FitSelectionToView();
SelectionChanged();
DrawDeferred();
}
}
TInt CHgList::CurrentIndex()
{
return iCurrentRow;
}
TBool CHgList::IsDisplayed( TInt aIndex )
{
TInt start = CurrentIndex();
TInt rowsPerView = ItemsOnScreen();
if( (iViewPosition.iY-(iHeight/2))%(iRowHeight) )
++rowsPerView;
TInt end = start + rowsPerView;
return aIndex >= start && aIndex <= end;
}
// -----------------------------------------------------------------------------
// CHgList::FitTopItemToView()
// -----------------------------------------------------------------------------
//
void CHgList::FitTopItemToView( TInt aIndex )
{
// Higlighted item is set to top of the list
TInt newPos = aIndex*iRowHeight + iHeight/2;
if( ItemsOnScreen() >= iItems.Count() )
{
newPos = iHeight/2;
}
else
{
const TInt endMid = TotalSize().iHeight - iHeight/2;
if( newPos > endMid )
{
// We are presenting last items in the list
newPos = endMid;
}
}
iViewPosition.iY = newPos;
HandleViewPositionChanged();
}
// End of File