fep/aknfep/UiPlugins/AknFepUiInterface/AvkonImpl/src/AknFepUiAvkonCtrlCandidatePane.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 15 Sep 2010 12:34:44 +0300
branchRCL_3
changeset 50 5a1685599b76
parent 44 ecbabf52600f
child 56 8152b1f1763a
permissions -rw-r--r--
Revision: 201035 Kit: 201036

/*
* Copyright (c) 2002-2004 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:           
*       Provides the CAknFepUICtrlCandidatePane methods.
*
*/












#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <uikon/eikdefmacros.h>
#endif
#include <eiklabel.h>
#include <AknsDrawUtils.h>
#include <AknBidiTextUtils.h> 
#include <AknsUtils.h>
#include <AknIconUtils.h>
#include <coecntrl.h>
#include <aknfepuictrls.mbg>
#include <skinlayout.cdl.h>
#include <aknlayoutscalable_avkon.cdl.h>

#include "AknFepUiInterfacePanic.h"
#include "AknFepUIAvkonCtrlCandidatePane.h"
#include "aknfepchineseuidataconv.h"
#include "aknfepuilayoutdatamgr.h"
#include "AknFepUiInputStateBase.h"
#include "AknFepUIAvkonCtrlCandidateCharacter.h"
#include "data_caging_path_literals.hrh"

const TInt CandidateCountLeft = 10;
const TInt DibertHeight = 480;
const TInt ShowAboveCharacter = -1;
const TInt ShowBellowCharacter = 1;

_LIT(KFepUiControlsBitmapFile, "aknfepuictrls.mbm");

CAknFepUICtrlCandidatePane* CAknFepUICtrlCandidatePane::NewL( RWindow& aParent, 
															  CAknFepUiLayoutDataMgr* aLafDataMgr, 
															  MAknFepChineseUiMgr* aMgr )
    {
    CAknFepUICtrlCandidatePane* self = new(ELeave) CAknFepUICtrlCandidatePane( aLafDataMgr, aMgr );
    CleanupStack::PushL(self);
    self->ConstructL(aParent);
    CleanupStack::Pop();
    return self;
    }

CAknFepUICtrlCandidatePane::~CAknFepUICtrlCandidatePane()
    {
    delete iCtrlScroll;
    delete iPreview;
    if(iCandidateArray)
    	{
    	iCandidateArray->Reset();
		delete iCandidateArray;
    	}
    iCandidateLabelArray.ResetAndDestroy();
    iCandidateModeArray.Reset();
    iPages.Reset();
    }

const TDesC& CAknFepUICtrlCandidatePane::TextBuffer() const
    {
    return iBuffer;
    }

void CAknFepUICtrlCandidatePane::SetCandidateBuffer(const TDesC& aBuffer)
    {
    TInt newLength = aBuffer.Length();
    TInt oldLength = iBuffer.Length();
    if(newLength > EMaxCandidates)
        {
        newLength = EMaxCandidates;
        }
    if(newLength - 1 < iSelected)
        {
        // as far as the client is concerned, they have removed the character that was selected
        // therefore we must now hide the selected candidate, although the highlighting
        // state remains unchanged
		iCandidateLabelArray[iSelected]->SetHighlight( EFalse );
        }
    else
        {
        if(iHighlighted)
            {
            // make sure that the candidate is visible, as the selection is now
            // within a visible range (it might have been hidden last time
            // the buffer was set)
			iCandidateLabelArray[iSelected]->SetHighlight( ETrue );
            }
        }

    TPtrC newText = aBuffer.Left(newLength);
    TPtr ptr = iBuffer.Des();
    if(ptr != newText)
        {
        for(TInt i = 0; i < newLength; i++)
            {
            TBool valueChanged = ETrue;
            TPtrC newChar = aBuffer.Mid(i, EOneCandidate);
            if(i < oldLength)
                {
                TPtrC oldChar = iBuffer.Mid(i, EOneCandidate);
                if(newChar == oldChar)
                    {
                    valueChanged = EFalse;
                    }
                }
            // only update and redraw label background if the value has changed
            if(valueChanged)
                {
                // we have already allocated enough memory for this
				CAknFepUICtrlCandidateCharacter* candidateLabel = iCandidateLabelArray[i];
                candidateLabel->SetText( newChar );
                }
            }
        ptr.Copy(newText);
        LayoutLabels();
        iVisibleCount = newLength;
        UpdateLabelVisibility();
        }
    }

CDesCArrayFlat* CAknFepUICtrlCandidatePane::CandidateArray(void)
    {
    return iCandidateArray;
    }

void CAknFepUICtrlCandidatePane::SetCandidateBuffer(void)
    {
    if(iPages.Count() == 0)
        {
        return;
        }
    TPage curPage = iPages[iCurDisplayPage];
    iVisibleCount = curPage.iEndIndex - curPage.iStartIndex + 1;

    if(iVisibleCount - 1 < iSelected)
        {
		iCandidateLabelArray[iSelected]->SetHighlight( EFalse );
        }
    else
        {
        if(iHighlighted)
            {
			iCandidateLabelArray[iSelected]->SetHighlight( ETrue );
            }
        }

    TBufC<EPhraseLength> buf;
    TPtr newText = buf.Des();

    for(TInt i = 0; i < iVisibleCount; i ++)
        {
		CAknFepUICtrlCandidateCharacter* candidateLabel = iCandidateLabelArray[i];
        const TDesC* txtLabel = candidateLabel->Text();
        newText = (*iCandidateArray)[curPage.iStartIndex + i];

        if (( txtLabel->Compare(newText) != 0 ))
            {
            // we have already allocated enough memory for this
            TRAP_IGNORE( candidateLabel->SetText( newText ));
            }

        if ( i < iVisibleCount )
            {
            // only redraw labels that are visible
            TRect rect = candidateLabel->Rect();
            Window().Invalidate( rect );
            }
        }
    LayoutLabels();
    DrawDeferred();
    UpdateLabelVisibility();
    }

void CAknFepUICtrlCandidatePane::SetHighlighted(TBool aHighlighted)
    {
    if(!COMPARE_BOOLS(iHighlighted, aHighlighted))
        {
        iHighlighted = aHighlighted;
        iCandidateLabelArray[iSelected]->SetHighlight( aHighlighted );
        }
    }

TBool CAknFepUICtrlCandidatePane::Highlighted() const
    {
    return iHighlighted;
    }

void CAknFepUICtrlCandidatePane::SetCandidateMode(TInt aIndex, TCandidateMode aMode)
    {
    __ASSERT_DEBUG(aIndex < EMaxCandidates, AknFepUiInterfacePanic(EAknFepUiInterfacePanicAttemptedSetModeOutsideMaxCandidates));
    __ASSERT_DEBUG(aIndex >= 0, AknFepUiInterfacePanic(EAknFepUiInterfacePanicAttemptedSetModeOutsideMaxCandidates));

    TCandidateMode oldMode = iCandidateModeArray[aIndex];
    if(oldMode != aMode)
        {
        iCandidateModeArray[aIndex] = aMode;
        
        // only do drawing if visible
        if(aIndex < iVisibleCount)
            {
            LayoutLabel(aIndex);
            if(iSelected == aIndex && iHighlighted)
                {
                }
            else
                {
				CAknFepUICtrlCandidateCharacter* candidateLabel = iCandidateLabelArray[aIndex];
                TRect rect = candidateLabel->Rect();
                Window().Invalidate(rect);
                }
            }
        }
    }

CAknFepUICtrlCandidatePane::TCandidateMode CAknFepUICtrlCandidatePane::CandidateMode(TInt aIndex)
    {
    return iCandidateModeArray[aIndex];
    }

TBool CAknFepUICtrlCandidatePane::IsShowHorizontalScrollArrows() const
    {
    return EFalse;
    }

void CAknFepUICtrlCandidatePane::ShowHorizontalScrollArrows(TBool /*aValue*/)
    {
    // Left & right arrow are not need, so do nothing.
    }

void CAknFepUICtrlCandidatePane::ShowUpScrollArrows(TBool aValue)
    {
	// call function of scroll pane to show/hide up arrow.
	iCtrlScroll->ShowUpScrollArrows( aValue );
    }
    
void CAknFepUICtrlCandidatePane::ShowDownScrollArrows(TBool aValue)
    {
	// call function of scroll pane to show/hide down arrow.
	iCtrlScroll->ShowDownScrollArrows( aValue );
    }
    
void CAknFepUICtrlCandidatePane::ShowLeftScrollArrows(TBool /*aValue*/)
    {
	// Left arrow is not need, so do nothing.
    }
        
void CAknFepUICtrlCandidatePane::ShowRightScrollArrows(TBool /*aValue*/)
    {
	// Right arrow is not need, so do nothing.
    }

TBool CAknFepUICtrlCandidatePane::IsShowVerticalScrollArrows() const
    {
	// call function of scroll pane to get scroll state
    return iCtrlScroll->IsShowVerticalScrollArrows();
    }

void CAknFepUICtrlCandidatePane::ShowVerticalScrollArrows(TBool aValue)
    {
	// call function of scroll pane to set scroll state
	iCtrlScroll->ShowVerticalScrollArrows( aValue );
    }

TInt CAknFepUICtrlCandidatePane::VisibleCandidateCount() const
    {
    return iVisibleCount;
    }

void CAknFepUICtrlCandidatePane::SetVisibleCandidateCount(TInt aCount)
    {
    __ASSERT_DEBUG(aCount > 0, AknFepUiInterfacePanic(EAknFepUiInterfacePanicNewVisibleCountExceedsRange));
    __ASSERT_DEBUG(aCount <= EMaxCandidates, AknFepUiInterfacePanic(EAknFepUiInterfacePanicNewVisibleCountExceedsRange));
    if(iVisibleCount != aCount)
        {
        if(aCount - 1 < iSelected)
            {
            // automatically move the selection to be at the end of the new
            // candidate buffer
            SelectIndex(aCount - 1); // ignore return code
            }
        iVisibleCount = aCount;
        UpdateLabelVisibility();
        }
    }

TBool CAknFepUICtrlCandidatePane::SelectFirstPhrase()
    {
    if(iVisibleCount >= 1)
        {
        return SelectIndex(0,EFalse);
        }
    else
        {
        return EFalse;
        }
    }

TBool CAknFepUICtrlCandidatePane::SelectFirst()
    {
    if(iBuffer.Length())
        {
        return SelectIndex(0);
        }
    else
        {
        return EFalse;
        }
    }

TBool CAknFepUICtrlCandidatePane::SelectLastPhrase()
    {
    if(iVisibleCount > 1)
        {
        return SelectIndex(iVisibleCount - 1);
        }
    else
        {
        return EFalse;
        }
    }

TBool CAknFepUICtrlCandidatePane::SelectLast()
    {
    TInt length = iBuffer.Length();
    if(length)
        {
        TInt index = length < iVisibleCount ? length : iVisibleCount;
        return SelectIndex(index - 1);
        }
    else
        {
        return EFalse;
        }
    }

TBool CAknFepUICtrlCandidatePane::SelectNext()
    {
    if(iSelected < iVisibleCount - 1)
        {
        return SelectIndex(iSelected + 1);
        }
    else if( iSelected == iVisibleCount - 1 )
    	{
		return SelectIndex(0);
    	}
    else
        {
        return EFalse;
        }
    }

TBool CAknFepUICtrlCandidatePane::SelectPrev()
    {
    if(iSelected > 0)
        {
        return SelectIndex(iSelected - 1);
        }
    else if( iSelected == 0 )
    	{
        return SelectIndex( iVisibleCount - 1 );
        }
    else
        {
        return EFalse;
        }
    }

TBool CAknFepUICtrlCandidatePane::SelectIndex(TInt aIndex, TBool /*selected*/ )
    {
    if( aIndex + 1 > iVisibleCount || aIndex < 0 )
        {
        return EFalse;
        }

    if ( iSelected != aIndex )
    	{
		iCandidateLabelArray[iSelected]->SetHighlight( EFalse );
    	}
    
    if ( iPointDown || iHighlighted )
    	{
		iCandidateLabelArray[aIndex]->SetHighlight( ETrue );
		
    	}
        iSelected = aIndex;

    return ETrue;
    }

TInt CAknFepUICtrlCandidatePane::SelectedIndex() const
    {
    return iSelected;
    }

TPtrC CAknFepUICtrlCandidatePane::CurrentPhraseCandidate() const
    {
    __ASSERT_DEBUG(iSelected >= 0, AknFepUiInterfacePanic(EAknFepUiInterfacePanicCurrentSelectionOutsideVisibleCandidates));
    if(iVisibleCount > iSelected)
        {
        return *(iCandidateLabelArray[iSelected]->Text());
        }
    else
        {
        return TPtrC();
        }
    }

TPtrC CAknFepUICtrlCandidatePane::CurrentCandidate() const
    {
    __ASSERT_DEBUG(iSelected >= 0, AknFepUiInterfacePanic(EAknFepUiInterfacePanicCurrentSelectionOutsideVisibleCandidates));
    if(iBuffer.Length() > iSelected)
        {
        return iBuffer.Mid(iSelected, EOneCandidate);
        }
    else
        {
        return TPtrC();
        }
    }

TInt CAknFepUICtrlCandidatePane::LabelTextWidthInPixels( TInt aIndex)
    {
    TAknLayoutText layoutText;
    TAknTextLineLayout candidatePaneLayoutText = 
        CAknFepChineseUIDataConv::AnyToTextLine(iLafDataMgr->RequestData( ECharacterTextLayout ));
       
    layoutText.LayoutText(Rect(), candidatePaneLayoutText);

    const CFont* font = layoutText.Font();

    TInt labelWidthInPixels = 0;
    if(font)
        {
        const TDesC* txtLabel = iCandidateLabelArray[aIndex]->Text();
        if(txtLabel->Length() != 0)
            {
            labelWidthInPixels = font->TextWidthInPixels(*txtLabel);
            }
        }
    return labelWidthInPixels;
    }
void CAknFepUICtrlCandidatePane::SetPaneLayout(CAknFepUICtrlContainerChinese::TPaneLayout aPaneLayout)
    {
    iPaneLayout = aPaneLayout;
    }
    
void CAknFepUICtrlCandidatePane::SplitPhraseCandidatesIntoPages()
    {
    iPages.Reset();
    iUnpagedIndex = 0;
    
    InternalSpilitPhraseCandidate();
    
    if( iPages.Count() == 0 )
        {
        iVisibleCount = 0;
        }
    else
        {
        iCurDisplayPage = 0;
        SetVisibleCandidateCount(iPages[0].iEndIndex - iPages[0].iStartIndex + 1);
        }
    }
    
void CAknFepUICtrlCandidatePane::NextCandidatePage(void)
    {
    if(iCurDisplayPage == (iPages.Count() - 1))
        {
        if( iUnpagedIndex < iCandidateArray->Count() )
            {
            //continue page
            InternalSpilitPhraseCandidate();
            iCurDisplayPage++;
            }
        else
            {
            iCurDisplayPage = 0;
            }
        }
    else
        {
        iCurDisplayPage ++;
        }
    // For fix bug of when the count of character in the last page is less than
    // the previous page of the last page. And then select the last character of 
    // the previous page of the last page, and select next page. First of the last 
    // page is not refreshed.
    iCandidateLabelArray[iSelected]->SetHighlight( EFalse );
    iSelected = 0;
    }

void CAknFepUICtrlCandidatePane::PreviousCandidatePage(void)
    {
    if(iCurDisplayPage == 0)
        {
        iCurDisplayPage = iPages.Count() - 1;
        }
    else
        {
        iCurDisplayPage --;
        }
    }

void CAknFepUICtrlCandidatePane::SizeChanged()
    {
    LayoutContainedControls();
    }

TInt CAknFepUICtrlCandidatePane::CountComponentControls() const
    {
    TInt count = 0;
    count += iCandidateLabelArray.Count();

    CCoeControl* controls[] =
        {
        iCtrlScroll,
        iPreview
        } ;

    for (TUint ii = 0 ; ii < (sizeof(controls) / sizeof(CCoeControl*)) ; ii++)
        {
        if(controls[ii])
            {
            count++ ;
            }   
        }
    return count ;
    }

CCoeControl* CAknFepUICtrlCandidatePane::ComponentControl(TInt aIndex) const
    {
    TInt candidateCount = iCandidateLabelArray.Count();

    if(aIndex < candidateCount)
        {
        // because this method is const, the const [] operator is selected
        // which means that the pointer is const, so have to cast away constness
        // - a possible alternative is to make the array mutable?
        return CONST_CAST(CAknFepUICtrlCandidateCharacter*, iCandidateLabelArray[aIndex]);
        }
    aIndex -= candidateCount;

    CCoeControl* controls[] =
        {
       // iCandidateSelected,
        iCtrlScroll,
        iPreview
        } ;

    for (TUint ii = 0; (ii < sizeof(controls) / sizeof(CCoeControl*)) ; ii++)
        {
        if (controls[ii] && aIndex-- == 0)
            {
            return controls[ii] ;
            }
        }
    // shouldn't be called while no components.
    return NULL ;
    }

void CAknFepUICtrlCandidatePane::ConstructL(RWindow& aParent)
    {
    SetContainerWindowL(aParent);

    TBuf<EOneCandidate> ordinal;
    for(TInt i = 0; i < EMaxCandidates; i++)
        {
        CAknFepUICtrlCandidateCharacter* candidateLabel = CAknFepUICtrlCandidateCharacter::NewL( aParent, this );
        CleanupStack::PushL(candidateLabel);
        candidateLabel->SetContainerWindowL(aParent);
        // ownership is passed, unless allocation is unsuccessful, in which case we still have it on the stack
        User::LeaveIfError(iCandidateLabelArray.Append(candidateLabel));
        CleanupStack::Pop(); // candidateLabel

        User::LeaveIfError(iCandidateModeArray.Append(ECandidateModeNormal));
        }

    iCandidateArray = new(ELeave) CDesCArrayFlat(1);
    
    // scroll part
    iCtrlScroll = CAknFepUICtrlCandidateScroll::NewL( aParent, this );
    iCtrlScroll->SetMopParent(this);
    
    // character preview
    iPreview = CAknFepPreview::NewL( aParent );
    }

CAknFepUICtrlCandidatePane::CAknFepUICtrlCandidatePane(CAknFepUiLayoutDataMgr* aLafDataMgr, MAknFepChineseUiMgr* aMgr )
    :
    iPaneLayout(CAknFepUICtrlContainerChinese::ELayoutCandidate),
    iHighlighted(EFalse),
    iCurDisplayPage(0),
    iChineseUiMgr(aMgr),
    iPointDown( EFalse )
    {
    iLafDataMgr = aLafDataMgr;
    }

void CAknFepUICtrlCandidatePane::LayoutContainedControls()
    {
    LayoutLabels();
    LayoutScroll();
    }

void CAknFepUICtrlCandidatePane::LayoutLabel(TInt aIndex)
    {
    __ASSERT_DEBUG(aIndex >= 0, AknFepUiInterfacePanic(EAknFepUiInterfacePanicAttemptedLayoutOutsideVisibleCount));
    __ASSERT_DEBUG(aIndex < iVisibleCount, AknFepUiInterfacePanic(EAknFepUiInterfacePanicAttemptedLayoutOutsideVisibleCount));
    TRect rect = Rect();
    CAknFepUICtrlCandidateCharacter* candidateLabel = iCandidateLabelArray[aIndex];
    TAknWindowLineLayout layoutCandidateItem = 
        CAknFepChineseUIDataConv::AnyToWindowLine( iLafDataMgr->RequestData(ECharacterLayout));
    TAknTextLineLayout candidateLayout = 
        CAknFepChineseUIDataConv::AnyToTextLine( iLafDataMgr->RequestData(ECharacterTextLayout));
    
    // layout candidate label
    TAknLayoutRect layoutRectCandidateItem;
    layoutRectCandidateItem.LayoutRect( rect,layoutCandidateItem );
    TRect rectCandidateItem = layoutRectCandidateItem.Rect();
    if ( aIndex > 0 )
	    {
	    rectCandidateItem.iTl.iX = iCandidateLabelArray[aIndex - 1]->Rect().iBr.iX;
        }

    TAknLayoutText layoutText;
    layoutText.LayoutText( rectCandidateItem, candidateLayout );
    TInt interval = candidateLayout.il + candidateLayout.ir;

    TInt width = LabelTextWidthInPixels( aIndex );
    TInt minwidth = layoutRectCandidateItem.Rect().Width() - interval ;    
    if ( width < minwidth )
    	{
		width = minwidth;
    	}    
    rectCandidateItem.SetWidth( width + interval );
    candidateLabel->SetRect( rectCandidateItem );

    // override colours if skin data present
    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    TRgb candidateLabelTextColor = layoutText.Color();

    AknsUtils::GetCachedColor(skin, candidateLabelTextColor, 
                              KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG19);

    TRAP_IGNORE(
        candidateLabel->OverrideColorL(EColorLabelText, candidateLabelTextColor);
        );
    }

void CAknFepUICtrlCandidatePane::LayoutLabels()
    {
    for(TInt i = 0; i < iVisibleCount; i++)
        {
        LayoutLabel(i);
        }
    }
void CAknFepUICtrlCandidatePane::LayoutScroll()
    {
    TAknWindowLineLayout scrolllayout =  CAknFepChineseUIDataConv::AnyToWindowLine( iLafDataMgr->RequestData(EScrollLayout));
    AknLayoutUtils::LayoutControl( iCtrlScroll, Rect(), scrolllayout );
    }

void CAknFepUICtrlCandidatePane::UpdateLabelVisibility()
    {
    TInt number = 0;
    // only show the labels corresponding to candidates that have been set
    if(iPages.Count() != 0)
        {
        number = iPages[iCurDisplayPage].iEndIndex - iPages[iCurDisplayPage].iStartIndex + 1;
        }
    else
        {
        number = iBuffer.Length();
        }

    if(number > iVisibleCount)
        {
        number =  iVisibleCount;
        }
    for(TInt i = 0; i < EMaxCandidates; i++)
        {
        CAknFepUICtrlCandidateCharacter* candidateLabel = iCandidateLabelArray[i];
        if(i < number)
            {
            candidateLabel->MakeVisible(ETrue);
            }
        else
            {
            candidateLabel->MakeVisible(EFalse);
            }
        }
    }

void CAknFepUICtrlCandidatePane::ResetCandidateState()
    {
    iPages.Reset();
    }

void CAknFepUICtrlCandidatePane::DrawBackground(const TRect& aRect) const
    {
    // instead of drawing one blank rectangle over each of the 20 labels,
    // just draw one big rectangle covering the entire pane
    CWindowGc& gc = SystemGc();
    TRgb background = AKN_LAF_COLOR(0);
    gc.SetBrushColor(background);
    gc.Clear(aRect);
    }

void CAknFepUICtrlCandidatePane::InternalSpilitPhraseCandidate()
    {
    //__ASSERT_DEBUG(aStartIndex + aCount <= iCandidateArray->Count());
    
    TInt phraseCandidateNum = iCandidateArray->Count();
    if( phraseCandidateNum == iUnpagedIndex )
        {
        //nothing need to be paged
        return;
        }
        
    TPage curPage;
    TInt index = iUnpagedIndex;
    CAknFepUICtrlCandidateCharacter* candidateLabel;
    
    curPage.iStartIndex = index;
    curPage.iEndIndex = index;
    TInt candidateLeftNum = phraseCandidateNum - index > EMaxCandidates? 
                            EMaxCandidates : phraseCandidateNum - index;

    TAknWindowLineLayout layoutCandidateItem = 
        CAknFepChineseUIDataConv::AnyToWindowLine( iLafDataMgr->RequestData(ECharacterLayout));
    TAknWindowLineLayout candidateRect = 
        CAknFepChineseUIDataConv::AnyToWindowLine( iLafDataMgr->RequestData(EScrollLayout));
    
    TAknTextLineLayout candidateLayout = 
        CAknFepChineseUIDataConv::AnyToTextLine( iLafDataMgr->RequestData(ECharacterTextLayout));
    
    TInt interval = candidateLayout.il + candidateLayout.ir;
    // avoid accessing layout data member
    TAknLayoutRect layoutRect;
    layoutRect.LayoutRect(Rect(),layoutCandidateItem);
    TRect rectLayoutCandidateItem = layoutRect.Rect();
    TAknLayoutText layoutText;
    layoutText.LayoutText(rectLayoutCandidateItem,candidateLayout);
    TRect rectText = Rect();  
    TInt distance = rectText.iTl.iX - rectLayoutCandidateItem.iTl.iX + rectText.iBr.iX - rectLayoutCandidateItem.iBr.iX;
    rectLayoutCandidateItem.iBr.iX += distance - candidateRect.iW;

    TInt i = 0;     

    const TInt candidateWidth = rectLayoutCandidateItem.Width();
    for ( i = 0; i < candidateLeftNum; i ++ )
        {
        // Initialization
        candidateLabel = iCandidateLabelArray[i];
        // labelWidth in the font
        const CFont* font = layoutText.Font();
        TPtrC newText = (*iCandidateArray)[iUnpagedIndex + i];
        TInt labelWidth = font->TextWidthInPixels( newText );
        labelWidth = interval + ( labelWidth > layoutText.TextRect().Width() ? labelWidth : layoutText.TextRect().Width());
        if ( labelWidth > candidateWidth )
            {
            TBufC<EPhraseLength+10> buf1;
            TPtr text( buf1.Des() );
            
            AknBidiTextUtils::ConvertToVisualAndClip(newText, text, *font, 
                candidateWidth, candidateWidth,
                AknBidiTextUtils::EImplicit,0xFFFF);
            
            iCandidateArray->Delete( iUnpagedIndex + i );
            TRAP_IGNORE(
            {
            iCandidateArray->InsertL( iUnpagedIndex + i, text );
            candidateLabel->SetText(text);
            });
            	
            }
        else
            {
            TRAP_IGNORE( candidateLabel->SetText(newText));
            rectLayoutCandidateItem.iTl.iX += labelWidth;
            }
        if (rectLayoutCandidateItem.iTl.iX > rectLayoutCandidateItem.iBr.iX)
            {
            if (index>0)
                {
                curPage.iEndIndex = index - 1;
                }
            else
                {
                curPage.iEndIndex = index;
                }

            iPages.Append(curPage);
            break;
            }
        else
            {
            index ++;
            }
        
        if( i == EMaxCandidates -1 )
        	{
            curPage.iEndIndex = index - 1;
            iPages.Append(curPage);
            break;
        	}
        
        }
        
    if( i >= candidateLeftNum )
        {
        curPage.iEndIndex = index - 1;
        iPages.Append(curPage);
        }
        
    iUnpagedIndex = index;      
    }

TBool CAknFepUICtrlCandidatePane::IsFirstPage()
    {
    return iCurDisplayPage == 0;
    }

TBool CAknFepUICtrlCandidatePane::IsLastPage()
    {
	if( iPages.Count() == 0 )
		{
		return ETrue;
		}
	else if( iCandidateArray->Count() == iUnpagedIndex )
        {
        return iCurDisplayPage == iPages.Count() - 1;
        }
    return EFalse;
    }

void CAknFepUICtrlCandidatePane::SetInVisiable()
    {
	iCandidateLabelArray[iSelected]->SetHighlight( EFalse );
	TRAP_IGNORE( iPreview->HideL());
    for (TInt i = 0; i < EMaxCandidates; i ++)
        {
		CAknFepUICtrlCandidateCharacter* candidateLabel = iCandidateLabelArray[i];
        candidateLabel->MakeVisible(EFalse);
        }
    }

TBool CAknFepUICtrlCandidatePane::NeedGetNewCandidatePage()
    {
    return (iCandidateArray->Count() - iUnpagedIndex < CandidateCountLeft);

    }

void CAknFepUICtrlCandidatePane::Enable(TBool aEnable)
	{
	if (!aEnable)
		{
		for (TInt i=0; i<iVisibleCount; i++)
			{
			iCandidateLabelArray[i]->SetText( KNullDesC );
			}
		TRAP_IGNORE( HidePreviewL();)
		iCandidateArray->Reset();
		iVisibleCount = 0;
		DrawNow();
		}
	}

void CAknFepUICtrlCandidatePane::FepUIClosePressed()
	{
	// Click close to close container
	if ( iChineseUiMgr )
		{
		iChineseUiMgr->CloseContainer();
		}
	}

void CAknFepUICtrlCandidatePane::SetFepUiState( MAknFepUiStateCtrl* aFepUiState )
    {
	iFepUiState = aFepUiState;
    }

void CAknFepUICtrlCandidatePane::HidePreviewL()
	{
	if( iPreview && iPreview->IsVisible())
		{
		iPreview->HideL();
		}
	}
void CAknFepUICtrlCandidatePane::HandlePointerEventL( const TPointerEvent & aPointerEvent )
	{
	CCoeControl::HandlePointerEventL( aPointerEvent );
    // Press will pop up preview
	if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
		{
		for ( TInt i = 0; i < iVisibleCount; i++ )
            {
	        if ( iCandidateLabelArray[i]->Rect().Contains( aPointerEvent.iPosition ))
		        {
				iPointDown = ETrue;
                SelectIndex( i );
	            const TDesC* txtLabel = iCandidateLabelArray[i]->Text();
	            TPoint point = iCandidateLabelArray[i]->PositionRelativeToScreen();
	            TRect rect( point, iCandidateLabelArray[i]->Size());
	            // if container is show on top, the preview should show bellow the character
	            // else the preview should show above the character.
	            TInt bottom = ShowAboveCharacter;
	            if ( point.iY < iCandidateLabelArray[i]->Rect().iBr.iY )
	                {
				    bottom = ShowBellowCharacter;
	                }
	            rect.Move( 0, (iCandidateLabelArray[i]->Size().iHeight ) * bottom );
	            iPreview->ShowL( rect, *txtLabel );
	            break;
	    	    }	        
            }
        }
	// Up will submit text
	else if ( aPointerEvent.iType == TPointerEvent::EButton1Up && iPointDown )
		{
		iPointDown = EFalse;
	    for ( TInt i = 0; i < iVisibleCount; i++ )
	        {
		    if ( iCandidateLabelArray[i]->Rect().Contains( aPointerEvent.iPosition ))
			    {
			    if ( iChineseUiMgr )
			        {
			        const TDesC* text = iCandidateLabelArray[i]->Text();	    
			        iChineseUiMgr->SubmitSelectedTextL( *text );			        
			        }
			    break;
			    }
	        }
	    if( iPreview->IsVisible())
	    	{
			iPreview->HideL();
	    	}
	    
	    if( !iHighlighted )
	    	{
			iCandidateLabelArray[iSelected]->SetHighlight( iHighlighted );
	    	}
		}
	// Drag out of candidate pane, hide preview
	else if ( aPointerEvent.iType == TPointerEvent::EDrag && iPointDown )
		{
	    TBool bContain = EFalse;
		for ( TInt i = 0; ( !bContain ) && ( i < iVisibleCount ); i++ )
		    {
			if ( iCandidateLabelArray[i]->Rect().Contains( aPointerEvent.iPosition ))
				{
				TBool bSameIndex = ( i == iSelected );
				SelectIndex( i );
				if ( !bSameIndex )
					{
					const TDesC* txtLabel = iCandidateLabelArray[i]->Text();
					TPoint point = iCandidateLabelArray[i]->PositionRelativeToScreen();
					TRect rect( point, iCandidateLabelArray[i]->Size());
					TInt bottom = ShowAboveCharacter;
					// If container is moved to top,
					// then pop up preview below the character
					if ( point.iY < iCandidateLabelArray[i]->Rect().iBr.iY )
						{
						bottom = ShowBellowCharacter;
						}
					rect.Move( 0, (iCandidateLabelArray[i]->Size().iHeight ) * bottom );
					iPreview->ShowL( rect, *txtLabel );
					}
				bContain = ETrue;
				break;
			    }
		    }
		if ( !bContain )
			{
			iPreview->HideL();
			iCandidateLabelArray[iSelected]->SetHighlight( iHighlighted );	
			if( !iHighlighted )
				{
				iSelected = 0;
				}
			}
		else if( bContain && !iPreview->IsVisible())
			{
			const TDesC* txtLabel = iCandidateLabelArray[iSelected]->Text();
			TPoint point = iCandidateLabelArray[iSelected]->PositionRelativeToScreen();
			TRect rect( point, iCandidateLabelArray[iSelected]->Size());
			TInt bottom = ShowAboveCharacter;
			// If container is moved to top,
			// then pop up preview below the character
			if ( point.iY < iCandidateLabelArray[iSelected]->Rect().iBr.iY )
				{
				bottom = ShowBellowCharacter;
				}
			rect.Move( 0, (iCandidateLabelArray[iSelected]->Size().iHeight ) * bottom );
			iPreview->ShowL( rect, *txtLabel );
			}
		}
	else
		{
		// do nothing
		}
	}

CAknFepPreview* CAknFepPreview::NewL( RWindowTreeNode& aParent )
	{
	CAknFepPreview* self = new(ELeave) CAknFepPreview;
    CleanupStack::PushL(self);
    self->ConstructL( aParent );
    CleanupStack::Pop();
    return self;
	}

CAknFepPreview::~CAknFepPreview()
	{
	delete iPreviewLabel;
	}

void CAknFepPreview::Draw( const TRect& /*aRect*/ ) const
	{
    CWindowGc& gc = SystemGc();
	
	MAknsSkinInstance* skin = AknsUtils::SkinInstance();
	TRect outerRect;
	TRect innerRect;
	CalculateFrameRects( outerRect, innerRect );
	gc.SetBrushColor( KRgbGray );
	// draw the whole frame background according to the containing context, which in this case
	// is the candidate pane, to avoid corner drawing mess and to cope with masked grid frame centre
	MAknsControlContext* cc = AknsDrawUtils::ControlContext(this);
	AknsDrawUtils::DrawFrame( skin, gc, outerRect, innerRect,
							  KAknsIIDQsnFrInputCharPreview, KAknsIIDDefault ); 	
	}

void CAknFepPreview::SizeChanged()
	{
    TRect rect = Rect();
    TAknTextLineLayout candidateLayout = AknLayoutScalable_Avkon::cell_hyb_candi_pane_t1(0);
    // Get preview rect and font. 
    TAknLayoutText layoutText;
    layoutText.LayoutText( rect, candidateLayout );
    TRect rectText = layoutText.TextRect();
    const CFont* font = layoutText.Font();

    iPreviewLabel->SetRect( rectText );
    iPreviewLabel->SetFont( font );
    // override with skin text color
    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    
    TRgb labelTextColor;
    AknsUtils::GetCachedColor( skin, labelTextColor, 
                               KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG11 );

    TRAP_IGNORE( 
    		iPreviewLabel->OverrideColorL(EColorLabelText, labelTextColor);	 )
	}

void CAknFepPreview::ShowL( TRect& aRect, const TDesC& aCharacter )
	{
	SetRect( aRect );

	iPreviewLabel->SetTextL( aCharacter );
	MakeVisible( ETrue );
	RWindow& window = Window();
	window.SetOrdinalPosition( 0, ECoeWinPriorityAlwaysAtFront + 100 );
	DrawNow();
	}

void CAknFepPreview::HideL()
	{
	MakeVisible( EFalse );
	iPreviewLabel->SetTextL( KNullDesC );
	DrawNow();
	}

TInt CAknFepPreview::CountComponentControls() const
	{
    CCoeControl* controls[] = 
        {
        iPreviewLabel
        };
    TInt count = 0;
    for ( TUint ii = 0 ; ii < (sizeof(controls) / sizeof(CCoeControl*)); ii++ )
        {
        if ( controls[ii] )
            {
            count++;
            }   
        }

    return count ;
	}

CCoeControl* CAknFepPreview::ComponentControl(TInt aIndex) const
	{
    CCoeControl* controls[] = 
        {
        iPreviewLabel
        };

    for ( TUint ii = 0; (ii < sizeof(controls) / sizeof(CCoeControl*)); ii++ )
        {
        if ( controls[ii] && aIndex-- == 0 )
            {
            return controls[ii];
            }
        }
    // shouldn't be called while no components.
    return NULL ;
	}

CAknFepPreview::CAknFepPreview()
	{
	}

void CAknFepPreview::ConstructL( RWindowTreeNode& /*aParent */)
	{
	RWindowGroup& wg = CCoeEnv::Static()->RootWin();
	CreateWindowL( wg );
	RWindow& window = Window();
	iPreviewLabel = new( ELeave ) CEikLabel;
	iPreviewLabel->SetContainerWindowL( window );
	iPreviewLabel->SetLabelAlignment( ELayoutAlignCenter );	
	iPreviewLabel->SetMopParent( this );
	window.SetRequiredDisplayMode( EColor16MA );
	window.SetTransparencyAlphaChannel();
	window.SetOrdinalPosition( 0, ECoeWinPriorityAlwaysAtFront + 100 );
	window.SetFaded( EFalse, RWindowTreeNode::EFadeIncludeChildren ); 
	// Enable receive drag event.
	Window().PointerFilter( EPointerFilterDrag, 0 );
	MakeVisible( EFalse );
	ActivateL();
	}

void CAknFepPreview::CalculateFrameRects(TRect& aOuterRect, TRect& aInnerRect) const
	{
	TRect windowRect = Rect();

	TAknLayoutRect topLeft;
	topLeft.LayoutRect( windowRect, SkinLayout::Highlight_skin_placing__grid__Line_2());

	TAknLayoutRect bottomRight;
	bottomRight.LayoutRect( windowRect, SkinLayout::Highlight_skin_placing__grid__Line_5());

	aOuterRect = TRect( topLeft.Rect().iTl, bottomRight.Rect().iBr );
	aInnerRect = TRect( topLeft.Rect().iBr, bottomRight.Rect().iTl );
	}

CAknFepUICtrlCandidateScroll* CAknFepUICtrlCandidateScroll::NewL(
							RWindowTreeNode& aParent, MAknFepUIEventObserver* aObserver )
	{
	CAknFepUICtrlCandidateScroll* self = new(ELeave) CAknFepUICtrlCandidateScroll;
    CleanupStack::PushL(self);
    self->ConstructL( aParent, aObserver );
    CleanupStack::Pop();
    return self;
	}

CAknFepUICtrlCandidateScroll::~CAknFepUICtrlCandidateScroll()
	{
	// delete bitmaps
	delete iScrollCloseBitmap;
	delete iScrollCloseBitmapMask; 
    delete iNaviArrowBitmapUp;
    delete iNaviArrowBitmapUpMask;
    delete iNaviArrowBitmapDown;
    delete iNaviArrowBitmapDownMask;
	}

void CAknFepUICtrlCandidateScroll::SizeChanged()
	{
	LayoutIcon();
	}

void CAknFepUICtrlCandidateScroll::Draw( const TRect& /*aRect*/ ) const
	{
    CWindowGc& gc = SystemGc();
	MAknsSkinInstance* skin = AknsUtils::SkinInstance();

	// draw the whole frame background according to the containing context, which in this case
	// is the candidate pane, to avoid corner drawing mess and to cope with masked grid frame centre
	MAknsControlContext* cc = AknsDrawUtils::ControlContext(this);
	TRect rect = Rect();
	
	// Draw scroll background
	AknsDrawUtils::DrawBackground( skin, cc, this, gc,
								   rect.iTl, rect, KAknsDrawParamDefault );

	// Draw close Rects
	if ( iShowClose )
		{
		TRect outerRect;
		TRect innerRect;
		CalculateCloseRects( outerRect, innerRect );
		AknsDrawUtils::DrawFrame( skin, gc, outerRect, innerRect,
								  KAknsIIDQsnFrKeypadButtonFrNormal, KAknsIIDDefault ); 
		// Draw close bitmap
		iIndiFepClose.DrawImage( gc, 
								 iScrollCloseBitmap, 
								 iScrollCloseBitmapMask );
		}
	
	// Draw Up arrow & Down arrow
	if ( iShowVerticalScrollArrows )
	    {
	    if ( iShowUpScrollArrows )
	        {
	        iIndiFepArrowUp.DrawImage( gc,
	                                   iNaviArrowBitmapUp, 
	                                   iNaviArrowBitmapUpMask );
	        }
	            
	    if ( iShowDownScrollArrows )
	        {
	        iIndiFepArrowDown.DrawImage( gc, 
	                                     iNaviArrowBitmapDown, 
	                                     iNaviArrowBitmapDownMask );
	        }
	    }
	}

void CAknFepUICtrlCandidateScroll::HandlePointerEventL( const TPointerEvent & aPointerEvent )
	{
	// Close area is click will close the container
	if ( iObServer != NULL && iIndiFepClose.Rect().Contains( aPointerEvent.iPosition ))
		{
		iObServer->FepUIClosePressed();
		}
	}

void CAknFepUICtrlCandidateScroll::ShowUpScrollArrows(TBool aValue)
    {
	// Update the up arrow if needed
    if ( iShowUpScrollArrows != aValue )
        {
        iShowUpScrollArrows = aValue;
        TRect rect = iIndiFepArrowUp.Rect();
        Window().Invalidate(rect);
        }
    }
    
void CAknFepUICtrlCandidateScroll::ShowDownScrollArrows( TBool aValue )
    {
	// Update the down arrow if needed
    if ( iShowDownScrollArrows != aValue )
        {
        iShowDownScrollArrows = aValue;
        TRect rect = iIndiFepArrowDown.Rect();
        Window().Invalidate(rect);
        }        
    }

void CAknFepUICtrlCandidateScroll::ShowVerticalScrollArrows( TBool aValue )
    {
    // If the state is changed, the arrows will be redrawn in the new state.
    if(!COMPARE_BOOLS(iShowVerticalScrollArrows, aValue))
        {
        iShowVerticalScrollArrows = aValue;
        //TRect rect = iIndiFepArrowUp.Rect();
        DrawDeferred();
        //rect = iIndiFepArrowDown.Rect();
        //Window().Invalidate(rect);
        }
    }

TBool CAknFepUICtrlCandidateScroll::IsShowVerticalScrollArrows() const
    {
    return iShowVerticalScrollArrows;
    }

void CAknFepUICtrlCandidateScroll::ConstructL( RWindowTreeNode& aParent, 
											   MAknFepUIEventObserver* aObserver )
	{
    CreateWindowL( aParent );
    ConstructBitmapsL();    
    iObServer = aObserver; 
    
    TRect rect;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, rect );
    // Dibert will not need close button
    iShowClose = rect.Height() == DibertHeight ? EFalse : ETrue;
    
	}

void CAknFepUICtrlCandidateScroll::ConstructBitmapsL()
	{
    MAknsSkinInstance* skin = AknsUtils::SkinInstance();  
    
    TFileName bmpFile;
    bmpFile.Copy(_L("z:"));
    bmpFile.Append( KDC_BITMAP_DIR );
    bmpFile.Append( KFepUiControlsBitmapFile );  

    // Create close bitmap
    AknsUtils::CreateColorIconL( skin,
 							     KAknsIIDQgnGrafFepCandiListClose,
 							     KAknsIIDQsnIconColors,
 							     EAknsCIQsnIconColorsCG20,
 							     iScrollCloseBitmap,
 							     iScrollCloseBitmapMask,
 							     bmpFile,
 							     EMbmAknfepuictrlsQgn_indi_input_candi_list_close,
 							     EMbmAknfepuictrlsQgn_indi_input_candi_list_close_mask,
 							     AKN_LAF_COLOR( 0 )); 
    
    // Create Up bitmap
    AknsUtils::CreateColorIconL( skin,
                                 KAknsIIDQgnIndiFepArrowUp,
                                 KAknsIIDQsnIconColors,
                                 EAknsCIQsnIconColorsCG20,
                                 iNaviArrowBitmapUp,
                                 iNaviArrowBitmapUpMask,
                                 bmpFile,
                                 EMbmAknfepuictrlsQgn_indi_fep_arrow_up,
                                 EMbmAknfepuictrlsQgn_indi_fep_arrow_up_mask,
                                 AKN_LAF_COLOR( 0 ));
    
    // Create Down bitmap
    AknsUtils::CreateColorIconL( skin,
                                 KAknsIIDQgnIndiFepArrowDown,
                                 KAknsIIDQsnIconColors,
                                 EAknsCIQsnIconColorsCG20,
                                 iNaviArrowBitmapDown,
                                 iNaviArrowBitmapDownMask,
                                 bmpFile,
                                 EMbmAknfepuictrlsQgn_indi_fep_arrow_down,
                                 EMbmAknfepuictrlsQgn_indi_fep_arrow_down_mask,
                                 AKN_LAF_COLOR( 0 )); 
	}

CAknFepUICtrlCandidateScroll::CAknFepUICtrlCandidateScroll()
: iShowVerticalScrollArrows(EFalse),
  iShowUpScrollArrows(ETrue),
  iShowDownScrollArrows(ETrue),
  iShowClose(ETrue)
	{	
	}

void CAknFepUICtrlCandidateScroll::LayoutIcon()
	{
    TRect rect = Rect();
    // layout arrow up
    TAknWindowLineLayout arrowUpLayout = AknLayoutScalable_Avkon::cell_hyb_candi_scroll_pane_g1(0);
    iIndiFepArrowUp.LayoutRect( rect, arrowUpLayout );    
    AknIconUtils::SetSize(iNaviArrowBitmapUp, iIndiFepArrowUp.Rect().Size());
    
    // layout arrow down
    TAknWindowLineLayout arrowDownLayout = AknLayoutScalable_Avkon::cell_hyb_candi_scroll_pane_g2(0);
    iIndiFepArrowDown.LayoutRect( rect, arrowDownLayout );    
    AknIconUtils::SetSize( iNaviArrowBitmapDown, iIndiFepArrowDown.Rect().Size());
    
    // layout close
    TAknWindowLineLayout closeLayout = AknLayoutScalable_Avkon::cell_hyb_candi_scroll_pane_g3(0);
    iIndiFepClose.LayoutRect( rect, closeLayout );
    AknIconUtils::SetSize( iScrollCloseBitmap, iIndiFepClose.Rect().Size());   
    }

void CAknFepUICtrlCandidateScroll::CalculateCloseRects(TRect& aOuterRect, TRect& aInnerRect) const
	{
	TRect windowRect = iIndiFepClose.Rect();

	TAknLayoutRect topLeft;
	topLeft.LayoutRect( windowRect, SkinLayout::Highlight_skin_placing__grid__Line_2());

	TAknLayoutRect bottomRight;
	bottomRight.LayoutRect( windowRect, SkinLayout::Highlight_skin_placing__grid__Line_5());

	aOuterRect = TRect( topLeft.Rect().iTl, bottomRight.Rect().iBr );
	aInnerRect = TRect( topLeft.Rect().iBr, bottomRight.Rect().iTl );
	}

// End of file