calendarui/views/src/calenweeklistbox.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 15 Jul 2010 18:37:27 +0300
branchRCL_3
changeset 59 aba12c885d83
parent 0 f979ecb2b13e
permissions -rw-r--r--
Revision: 201025 Kit: 2010127

/*
* Copyright (c) 2002 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:  CCalenWeekListbox is the class that customizes drawing
 *                part of CEikFormattedCellListBox.
 *
*/

//debug
#include "calendarui_debug.h"

//  INCLUDE FILES
#include "calenweeklistbox.h"

#include "calendrawutils.h"
#include <calenagendautils.h>
#include "calenweekcallback.h"
#include "calenweekcontainer.h"
#include "calenweekdata.h"
#include "calenweeklistboxdata.h"
#include "calenweeklistboxitemdrawer.h"
#include "calenweeklistboxview.h"
#include "calenweeklistboxlayout.h"

#include <AknLayoutFont.h>
#include <aknlists.h>
#include <AknIconUtils.h>
#include <AknsControlContext.h>
#include <AknsDrawUtils.h>
#include <AknUtils.h>
#include <gulicon.h>
#include <calenviewutils.h>
#include <aknlayoutscalable_apps.cdl.h>

// ======== LOCAL FUNCTIONS ========

// ---------------------------------------------------------
// SetupWeekHourCellL
// Sets subcell properties for week hour cell
// ---------------------------------------------------------
//
static void SetupWeekHourCellL( CFormattedCellListBoxItemDrawer* aItemDrawer, TWeekListBoxLayout& aWeekLayout)
    {
    TRACE_ENTRY_POINT;
    
    TInt KSubCell = 0; // hour cell is first subcell 

    TAknLayoutText hourTextLayout = aWeekLayout.HourTextLayout();
    TRect subCellRect = aWeekLayout.HourSubCellRect_in_ListItemRect();
    // We use text rect from layout as subcell rect, so margins are zero! 
    TMargins margins = { 0, 0, 0, 0 };

    const CFont* font = hourTextLayout.Font();
    // Baseline calculation idea is copied fromTAknLayoutText::LayoutText 
    const CAknLayoutFont* layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( font );
    TInt baseline = 0;
    if ( layoutFont )
        {
        baseline = layoutFont->TextPaneTopToBaseline();
        }
    else
        {
        baseline = font->AscentInPixels();
        }

    // Set subcell properties
    aItemDrawer->FormattedCellData()->SetSubCellFontL(       KSubCell, font );
    aItemDrawer->FormattedCellData()->SetSubCellMarginsL(    KSubCell, margins );
    aItemDrawer->FormattedCellData()->SetSubCellAlignmentL(  KSubCell, hourTextLayout.Align() );
    aItemDrawer->FormattedCellData()->SetSubCellPositionL(   KSubCell, subCellRect.iTl );
    aItemDrawer->FormattedCellData()->SetSubCellSizeL(       KSubCell, subCellRect.Size() );
    aItemDrawer->FormattedCellData()->SetSubCellBaselinePosL(KSubCell, baseline );

    // Set colors
    TRgb textColor = hourTextLayout.Color();

    AknsUtils::GetCachedColor(AknsUtils::SkinInstance(), textColor,
                              KAknsIIDQsnTextColors,
                              EAknsCIQsnTextColorsCG23);

    CFormattedCellListBoxData::TColors colors;

    //FIXME: this is hack for extended skinning. It seems to be difficult to pass and use
    // correct colors in LBItemDrawer and LBData. 
    aItemDrawer->SetTextColor( textColor ); 

    colors.iText = textColor;
    colors.iBack = aItemDrawer->BackColor();
    colors.iHighlightedText = aItemDrawer->HighlightedTextColor();
    colors.iHighlightedBack = aItemDrawer->HighlightedBackColor();
    aItemDrawer->FormattedCellData()->SetSubCellColorsL( KSubCell, colors );
    
    TRACE_EXIT_POINT;
    }


// ---------------------------------------------------------
// SetupWeekGridCellL
// Sets subcell properties for week grid cells 
// ---------------------------------------------------------
//
static void SetupWeekGridCellL(CFormattedCellListBoxData* aListboxData,
                               TInt aSubcellIndex, // Subcell index
                               TRect aSubcellRect // subcell rect relative to list item
    )
    {
    TRACE_ENTRY_POINT;
    
    // As week grid subcell doesn't have margins, it is easy to setup 
    TMargins margins = { 0, 0, 0, 0 };
    aListboxData->SetSubCellMarginsL(  aSubcellIndex, margins); 
    aListboxData->SetGraphicsSubCellL( aSubcellIndex, ETrue); 
    aListboxData->SetSubCellPositionL( aSubcellIndex, aSubcellRect.iTl);
    aListboxData->SetSubCellSizeL(     aSubcellIndex, aSubcellRect.Size());
    aListboxData->SetSubCellAlignmentL(aSubcellIndex, CGraphicsContext::ECenter);
    
    TRACE_EXIT_POINT;
    }


// ================= MEMBER FUNCTIONS =======================

// C++ default constructor can NOT contain any code, that
// might leave.
//
CCalenWeekListbox::CCalenWeekListbox(CCalenWeekContainer& aWeekContainer)
    : iWeekContainer( aWeekContainer )
    {
    TRACE_ENTRY_POINT;
    TRACE_EXIT_POINT;
    }

// Symbian OS default constructor can leave.
void CCalenWeekListbox::ConstructL(
    const CCoeControl* aParent    
    )
    {
    TRACE_ENTRY_POINT;
    
    CEikFormattedCellListBox::ConstructL(aParent, 0);
    CCalenWeekLBData* data =
        static_cast<CCalenWeekLBData*>( ItemDrawer()->FormattedCellData() );
    data->SetHighlightAnimBackgroundDrawer( static_cast<CCalenWeekLBView*>(iView) );
    
    TRACE_EXIT_POINT;
    }


// Destructor
CCalenWeekListbox::~CCalenWeekListbox()
    {
    TRACE_ENTRY_POINT;
    TRACE_EXIT_POINT;
    }

// ---------------------------------------------------------
// CCalenWeekListbox::SetCursorObserver
// Set cursor handling class
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCalenWeekListbox::SetCursorObserver
(MCalenWeekCursorObserver* aCursorObsever)  // A observer pointer
    {
    TRACE_ENTRY_POINT;
    
    iCursorObsever = aCursorObsever;
    
    TRACE_EXIT_POINT;
    }

// ---------------------------------------------------------
// CCalenWeekListbox::SetStartDay
// Set the start of a week
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCalenWeekListbox::SetStartDay(TTime aStartDay)
    {
    TRACE_ENTRY_POINT;
    
    iStartDay = aStartDay;
    
    TRACE_EXIT_POINT;
    }

// ---------------------------------------------------------
// CCalenWeekListbox::OfferKeyEventL
// handles key events.
// (other items were commented in a header).
// ---------------------------------------------------------
//
TKeyResponse CCalenWeekListbox::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
    {
    TRACE_ENTRY_POINT;
    
    TKeyResponse res(EKeyWasNotConsumed);
    TBool mirrored(AknLayoutUtils::LayoutMirrored());

    if (aType == EEventKey)
        {
        switch(aKeyEvent.iCode)
            {
            case EKeyLeftArrow:
                if (mirrored)
                    {
                    HandleRightArrowKeyL(CListBoxView::ENoSelection);
                    }
                else
                    {
                    HandleLeftArrowKeyL(CListBoxView::ENoSelection);
                    }
                res = EKeyWasConsumed;
                break;
            case EKeyRightArrow:
                if (mirrored)
                    {
                    HandleLeftArrowKeyL(CListBoxView::ENoSelection);
                    }
                else
                    {
                    HandleRightArrowKeyL(CListBoxView::ENoSelection);
                    }
                res = EKeyWasConsumed;
                break; 
            case EKeyUpArrow:
#ifdef SUPPORT_NAVISCROLL_EVENTS
            case EKeyPrevious:
#endif
                res = CEikListBox::OfferKeyEventL(aKeyEvent, aType);
                if (iCursorObsever)
                    {
                    iCursorObsever->CursorMovedL(
                        MCalenWeekCursorObserver::ECalenUp);
                    }
                break;
            case EKeyDownArrow:
#ifdef SUPPORT_NAVISCROLL_EVENTS
            case EKeyNext:
#endif
                res = CEikListBox::OfferKeyEventL(aKeyEvent, aType);
                if (iCursorObsever)
                    {
                    iCursorObsever->CursorMovedL(
                        MCalenWeekCursorObserver::ECalenDown);
                    }
                break;
           default:
                res = CEikListBox::OfferKeyEventL(aKeyEvent, aType);
                break;
            }
        }
    
    TRACE_EXIT_POINT;
    return res;
    }

TTypeUid::Ptr CCalenWeekListbox::MopSupplyObject(TTypeUid aId)
    {
    TRACE_ENTRY_POINT;
    
    // FormattedCellListBox function skipped intentioanlly as it intercepts
    // background contexts (and we want to provide our own BG context).
    if( aId.iUid == MAknsControlContext::ETypeId )
        {
        MAknsControlContext* cc = AknsDrawUtils::ControlContextOfParent( this );
        if ( cc )
            {
            TRACE_EXIT_POINT;
            return MAknsControlContext::SupplyMopObject( aId, cc );
            }
        }
    
    TRACE_EXIT_POINT;
    return CCoeControl::MopSupplyObject( aId );
    }

// ---------------------------------------------------------
// CCalenWeekListbox::SetupLayoutL
// Set all cell data
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCalenWeekListbox::SetupLayoutL()
    {
    TRACE_ENTRY_POINT;
    
    TRect rect = iWeekContainer.ReducePreview( iWeekContainer.Rect() );
    TWeekListBoxLayout lay( iWeekContainer.UseInfobar(), 
                            iWeekContainer.UseToolbar(),
                            iWeekContainer.UsePreview(),
                            rect
                            );

    SetItemHeightL( lay.ListItemHeight() );

    // Hour subcell layout
    SetupWeekHourCellL( ItemDrawer(), lay );

    // Grid subcell layouts
    CFormattedCellListBoxData* listBoxData = ItemDrawer()->FormattedCellData();
    for (TInt loop(1); loop < KCalenDaysInWeek + 1; ++loop)
        {
        TRect gridCellRect = lay.GridSubCellRect_in_ListItemRect(loop - 1);
        SetupWeekGridCellL( listBoxData, loop, gridCellRect );
        }

    // Icon sizes
    TInt KFirst = 0; // just fetch layout for first item 
    TRect firstCellRect = lay.GridSubCellRect_in_ListItemRect(KFirst);
    TAknLayoutRect iconLayout;
    TInt layoutVariant = lay.LayoutVariantIndex(TWeekListBoxLayout::ECellCaleWeekPaneG2);
    iconLayout.LayoutRect( firstCellRect /*P:cell_cale_week_pane*/,
                           AknLayoutScalable_Apps::cell_cale_week_pane_g2(layoutVariant).LayoutLine() );
    CalenDrawUtils::SetIconSizes(
        iconLayout, ItemDrawer()->FormattedCellData()->IconArray());

   // Colors and misc stuff
    SetSubcellColorsL();

    CCalenWeekLBData* celData = static_cast<CCalenWeekLBData*>( ItemDrawer()->FormattedCellData() );
    celData->SetCelCount( KCalenDaysInWeek + 1 );
    celData->SetVariantIndex(layoutVariant);
    
    TRACE_EXIT_POINT;
    }

// ---------------------------------------------------------
// CCalenWeekListbox::SetSubcellColorsL
// Set a Background color for all subcells
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCalenWeekListbox::SetSubcellColorsL() const
    {
    TRACE_ENTRY_POINT;
    
    // FIXME: investigate, if this is needed anymore at all. 
    for (TInt loop(0); loop < KCalenDaysInWeek; ++loop)
        {
        CFormattedCellListBoxItemDrawer* itemDrawer = ItemDrawer();
        CFormattedCellListBoxData::TColors colors;
        colors.iText = itemDrawer->TextColor();
        colors.iBack = itemDrawer->BackColor();
        colors.iHighlightedText = itemDrawer->HighlightedTextColor();
        colors.iHighlightedBack = itemDrawer->HighlightedBackColor();
        itemDrawer->FormattedCellData()->SetSubCellColorsL(loop + 1, colors);
        }
    
    TRACE_EXIT_POINT;
    }

// ---------------------------------------------------------
// CCalenWeekListbox::CreateItemDrawerL
// Create CColumnListBoxData and CColumnListBoxItemDrawer.
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCalenWeekListbox::CreateItemDrawerL()
    {
    TRACE_ENTRY_POINT;
    
    CCalenWeekLBData* listboxData = CCalenWeekLBData::NewL();
    CleanupStack::PushL( listboxData );
    iItemDrawer = new(ELeave) CCalenWeekListBoxItemDrawer(
        Model(), 
        iEikonEnv->NormalFont(),
        listboxData);
    CleanupStack::Pop();    // listboxData
    
    TRACE_EXIT_POINT;
    }

// ---------------------------------------------------------
// CCalenWeekListbox::MakeViewClassInstanceL
// Create ListBoxView class
// (other items were commented in a header).
// ---------------------------------------------------------
//
CListBoxView* CCalenWeekListbox::MakeViewClassInstanceL()
    {
    TRACE_ENTRY_POINT;
    
    TRACE_EXIT_POINT;
    return (new(ELeave) CCalenWeekLBView);
    }

// ---------------------------------------------------------
// CCalenWeekListbox::HandleLeftArrowKeyL
// Called when Left arrow key was pressed
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCalenWeekListbox::HandleLeftArrowKeyL(CListBoxView::TSelectionMode aSelectionMode)
    {
    TRACE_ENTRY_POINT;
    
    TKeyResponse res(EKeyWasNotConsumed);
    if (iCursorObsever)
        {
        res = iCursorObsever->CursorMovedL(MCalenWeekCursorObserver::ECalenLeft);
        }
    if (res == EKeyWasNotConsumed)
        {
        iView->MoveCursorL(CListBoxView::ECursorPreviousColumn, 
                           aSelectionMode);
        ClearMatchBuffer();
        }
    
    TRACE_EXIT_POINT;
    }

// ---------------------------------------------------------
// CCalenWeekListbox::HandleRightArrowKeyL
// Called when Right arrow key was pressed
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCalenWeekListbox::HandleRightArrowKeyL(CListBoxView::TSelectionMode aSelectionMode)
    {
    TRACE_ENTRY_POINT;
    
    TKeyResponse res(EKeyWasNotConsumed);
    if (iCursorObsever)
        {
        res = iCursorObsever->CursorMovedL(MCalenWeekCursorObserver::ECalenRight);
        }
    if (res == EKeyWasNotConsumed)
        {
        iView->MoveCursorL(CListBoxView::ECursorNextColumn, aSelectionMode);
        ClearMatchBuffer();
        }
    
    TRACE_EXIT_POINT;
    }

// ---------------------------------------------------------
// CCalenWeekListbox::SizeChanged
// Initilizes ListBox cell
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCalenWeekListbox::SizeChanged()
    {
    TRACE_ENTRY_POINT;
    
    AknListBoxLayouts::SetupStandardFormListbox( ItemDrawer() );

    PIM_TRAPD_HANDLE( SetupLayoutL() );

    CEikFormattedCellListBox::SizeChanged();
    
    TRACE_EXIT_POINT;
    }

// ---------------------------------------------------------
// CCalenWeekListbox::SetBgContext
// 
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCalenWeekListbox::SetBgContext(MAknsControlContext* aCc)
    {
    TRACE_ENTRY_POINT;
    
    iBgContext = aCc;
    
    TRACE_EXIT_POINT;
    }

TRect CCalenWeekListbox::LayoutRect() const
    {
    TRACE_ENTRY_POINT;
    
    TRect rect = iWeekContainer.ReducePreview( iWeekContainer.Rect() ); 
    TWeekListBoxLayout weekLayout(  iWeekContainer.UseInfobar(), 
                                    iWeekContainer.UseToolbar(), 
                                    iWeekContainer.UsePreview(),
                                    rect );
    
    TRACE_EXIT_POINT;
    return weekLayout.ListBoxRect();
    }


// ---------------------------------------------------------
// CCalenWeekListbox::IsValidPointer
// Checks if pointer event happened in valid area
// (other items were commented in a header).
// ---------------------------------------------------------
//
TBool CCalenWeekListbox::IsValidPointer(TPoint aPos)
    {
    TRACE_ENTRY_POINT;
    
    TWeekListBoxLayout lay( iWeekContainer.UseInfobar(), 
                            iWeekContainer.UseToolbar(),
                            iWeekContainer.UsePreview(),
                            // iWeekContainer.Rect()
                            iWeekContainer.ReducePreview(iWeekContainer.Rect()));
    
    TRACE_EXIT_POINT;
    return lay.WeekGridRect().Contains(aPos);
    }

// ---------------------------------------------------------
// CCalenWeekListbox::PointerEventColumn
// Calculates new column from pointer event (touch ui)
// (other items were commented in a header).
// ---------------------------------------------------------
//
TInt CCalenWeekListbox::PointerEventColumn(TPoint aPos)
    {
    TRACE_ENTRY_POINT;
    
    TRect rect = iWeekContainer.ReducePreview( iWeekContainer.Rect() );
    TWeekListBoxLayout lay( iWeekContainer.UseInfobar(), 
                            iWeekContainer.UseToolbar(),
                            iWeekContainer.UsePreview(),
                            rect );

    TInt cellWidth(lay.WeekGridRect().Width() / KCalenDaysInWeek);
    if((lay.WeekGridRect().Width() % KCalenDaysInWeek) > KCalenDaysInWeek/2)
        {
        ++cellWidth;
        }

    TRACE_EXIT_POINT;
    return  ((aPos.iX - lay.WeekGridRect().iTl.iX) / cellWidth);
    }

// ---------------------------------------------------------
// CCalenWeekListbox::HandlePointerEventL
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCalenWeekListbox::HandlePointerEventL(const TPointerEvent& aPointerEvent)
    {
    TRACE_ENTRY_POINT;
    
    if(AknLayoutUtils::PenEnabled())
        {
        TInt newColumn = PointerEventColumn(aPointerEvent.iPosition);
        TInt pointerIndex(-1);
        TBool isItem (View()->XYPosToItemIndex(aPointerEvent.iPosition, pointerIndex));
        
        if(!isItem) // to handle scroll if drag out side of listbox
            CEikListBox::HandlePointerEventL(aPointerEvent);
        else if(newColumn >= 0 && newColumn < KCalenDaysInWeek)
            {
            iCursorObsever->PointerMovedL(newColumn);
            CEikListBox::HandlePointerEventL(aPointerEvent);
            }
        }
    
    TRACE_EXIT_POINT;
    }


// End of File