diff -r 000000000000 -r 2f259fa3e83a uifw/AvKon/src/AknPhedView.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AvKon/src/AknPhedView.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,1037 @@ +/* +* Copyright (c) 2002 - 2008 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 "AknPhedView.h" +#include "AknPhoneNumberEditor.h" + +#include + +#include +#include +#include +#include + +// Helper class that monitor redirection changes +class CRedirectionListener : public CBase, public MAknTransitionUtilsObserver + { +private: + TInt AknTransitionCallback( TInt aEvent, TInt aState, + const TDesC8* /*aParams*/ ) + { + if ( aEvent == CAknTransitionUtils::EEventWsBufferRedirection ) + { + iRedirected = aState; + if ( iCursorEnabled ) + { + if ( iRedirected ) + { + if ( iWg && iCursorStatus ) + { + iWg->CancelTextCursor(); + } + iCursorStatus = EFalse; + } + else + { + iOwner.EnableCursor(); + } + } + } + return 0; + } + +public: + CRedirectionListener( CAknPhedView& aOwner ) : iOwner( aOwner ) + { + iRedirected = 0; + TInt serverrunning; + TInt ret=RProperty::Get( KPSUidAvkonDomain, KAknTfxServerStatus, + serverrunning ); + if(KErrNone == ret && ETfxSrvRunning == serverrunning) + { + RProperty::Get( KPSUidAvkonDomain, KAknTfxServerRedirectionStatus, + iRedirected ); + iRedirected &= ETfxScreenRedirected; + } + } + inline void EnableCursor() + { + iCursorEnabled = ETrue; + } + void DisableCursor() + { + if ( iWg && iCursorStatus ) + { + iWg->CancelTextCursor(); + } + iCursorEnabled = EFalse; + iCursorStatus = EFalse; + } + void UpdateCursor( const TTextCursor& aCursor ) + { + TInt redirected=0; // init the value + //judge the server status, if server is not running, it is no need to get redirect value. + TInt serverrunning; + TInt ret=RProperty::Get( KPSUidAvkonDomain, KAknTfxServerStatus, + serverrunning ); + + if(KErrNone == ret && ETfxSrvRunning == serverrunning) + { + ret=RProperty::Get( KPSUidAvkonDomain, KAknTfxServerRedirectionStatus, + redirected ); + + if( KErrNone != ret) + redirected = 0; + + redirected &= ETfxScreenRedirected; + if ( redirected != iRedirected && redirected ) + { + AknTransitionCallback( CAknTransitionUtils::EEventWsBufferRedirection, + 1, NULL ); + return; + } + } + + iRedirected = redirected; + + if ( iCursorEnabled && iWg && iWindow && !iRedirected ) + { + iWg->SetTextCursor( *iWindow, + iOwner.CursorPosition() + TPoint( -1, 0 ), + aCursor ); + iCursorStatus = ETrue; + } + } + + inline void SetWindows( RWindowGroup* aWg, RWindowBase* aWindow ) + { + iWg = aWg; + iWindow = aWindow; + } + +private: + TBool iRedirected; + TBool iCursorEnabled; + TBool iCursorStatus; + RWindowGroup* iWg; + RWindowBase* iWindow; + CAknPhedView& iOwner; + }; + +enum TAknPhedViewPanic + { + EFormatNullLines, + EFormatTooManyLines, + EFormatTooFewLines, + EEventNullLines, + ELineNoCursor + }; + +void PhedViewPanic( TAknPhedViewPanic aPanic ) + { + _LIT( KAknPhedView,"AknPhedView" ); + User::Panic( KAknPhedView, aPanic ); + } + + + +TAknPhedViewLine::TAknPhedViewLine() + { + Mem::FillZ( this, sizeof( *this ) ); + iCursor = CAknPhedView::KNoPos; + SetRedrawRequired(); + } + +void TAknPhedViewLine::SetFormat( const CFont* aFont, const TRect& aRect, TInt aBaseline ) + { + iFont = aFont; + iRect = aRect; + SetTruncation( iTruncation ); + iBaseline = aBaseline; + } + +TRect TAknPhedViewLine::Rect() const + { + return iRect; + } + +void TAknPhedViewLine::SetLeftPos( TInt aPos ) + { + SetRedrawRequired(); + iLeftPos = aPos; + + if ( InRange(aPos, iModel->Length(), 0 ) ) + { + if( iLeftPos > 0 && iLeftPos < iModel->Length() && iModel->Language() ) + { + if ( iModel->ReverseText( iLeftPos ).Length() == + iModel->ReverseText( iLeftPos - 1 ).Length() && !iLeftLine ) + { + iLeftPos++; + } + else if ( iModel->ReverseText( iLeftPos ).Length() == + iModel->ReverseText( iLeftPos - 1 ).Length() && iLeftLine ) + { + iLeftPos--; + } + } + // count characters that will fit to the right of this new left position + iRightPos = iLeftPos - CountChars( MaxText(), IsTruncatedLeft(), + !iRightLine, iLeftPos ); + if( iRightPos > 0 && iRightPos < iModel->Length() && iModel->Language() ) + { + if ( iModel->ReverseText( iRightPos ).Length() == + iModel->ReverseText( iRightPos + 1 ).Length() ) + { + iRightPos++; + } + } + + } + else + { + iRightPos = aPos; + } + + // propogate change of left hand side to right hand neighbor + if ( iRightLine ) + iRightLine->SetLeftPos( iRightPos ); + } + +void TAknPhedViewLine::SetRightPos( TInt aPos ) + { + SetRedrawRequired(); + TInt nLength = iModel->Length(); + + iRightPos = aPos; + + if ( InRange( aPos, nLength, 0 ) ) + { + if( iRightPos > 0 && iRightPos < iModel->Length() && iModel->Language() ) + { + + if ( iModel->ReverseText( iRightPos ).Length() == + iModel->ReverseText( iRightPos +1 ).Length() ) + { + iRightPos++; + } + } + + // count characters that will fit to the left of this new right position + iLeftPos = iRightPos + CountChars( MaxReverseText(), + IsTruncatedRight(), + !iLeftLine, + iMirror.Mirror( iRightPos ) ); + if( iLeftPos > 0 && iLeftPos < iModel->Length() && iModel->Language() ) + { + if ( iModel->ReverseText( iLeftPos ).Length() == + iModel->ReverseText( iLeftPos - 1 ).Length() && !iLeftLine ) + { + iLeftPos++; + } + else if ( iModel->ReverseText( iLeftPos ).Length() == + iModel->ReverseText( iLeftPos - 1 ).Length() && iLeftLine ) + { + iLeftPos--; + } + } + } + else + { + iLeftPos = aPos; + } + + // propogate change of right hand side to left hand neighbor + if ( iLeftLine ) + iLeftLine->SetRightPos( iLeftPos ); + } + +TBool TAknPhedViewLine::HandleTextChange( TInt aStart, TInt aEnd ) + { + // If the text change happens somewhere to the right of my LHS, handle it. + TBool handled = EFalse; + if ( aStart == aEnd && !iLeftLine && aStart > iLeftPos) + { + iLeftPos = aStart; + } + if ( !iRightLine && iRightPos > aStart ) + { + iRightPos = aStart; + } + + TInt chars = CountChars( MaxReverseText(), + IsTruncatedRight(), + !iLeftLine, + iMirror.Mirror( iRightPos ) ); + if( iLeftPos < chars ) + { + iLeftPos = chars; + } + + if ( iLeftPos >= aStart || ( !iLeftLine && aStart > iLeftPos ) ) + { + if( iRightLine ) + { + iRightLine->SetLeftPos( Max( iRightPos - 1, iRightLine->LeftPos() ) ); + TAknPhedViewLine * firstLine = this; + while ( firstLine->iRightLine ) + { + firstLine = firstLine->iRightLine; + } + firstLine->SetRightPos( firstLine->RightPos() ); + } + else + { + SetRightPos( iRightPos ); + } + handled = ETrue; + } + else if ( !iLeftLine || iLeftLine->LineWidth() == 0 ) + { + SetLeftPos( aEnd ); + } + return handled; + } + +TBool TAknPhedViewLine::HandleCursorChange( TInt aCursor ) + { + // cursor rule: cursor goes on bottom most line that can contain it (order is + // specified by loop order in CAknPhedView::CursorChangeFormat). + if ( LineContains( aCursor ) ) + { + iCursor = aCursor; + return ETrue; + } + else + { + iCursor = CAknPhedView::KNoPos; + return EFalse; + } + } + +void TAknPhedViewLine::HandleSelectionChange( TInt aLeft, TInt aRight ) + { + if (InRange( iLeftPos, aLeft, aRight ) || LineContains( aLeft ) || aLeft == aRight ) + { + SetRedrawRequired(); + } + } + +TInt TAknPhedViewLine::CountChars( const TDesC& aDes, + TBool aStartTruncated, + TBool aAllowEndTruncation, + TInt aCharsToEnd) const + { + // reduce width for start truncation + TInt width = iRect.Width(); + if ( aStartTruncated ) + { + width -= TruncationWidth(); + } + + TInt chars = TextCountWithTranslation( aDes, width ); + + if ( aAllowEndTruncation && chars < aCharsToEnd ) + { + // reduce with for end truncation and recalculate number of chars that will fit + width -= TruncationWidth(); + chars = TextCountWithTranslation( aDes, width ); + } + + return chars; + } + +void TAknPhedViewLine::SetTruncation( const TDesC& aTruncation ) + { + SetRedrawRequired(); + iTruncation.Set( aTruncation ); + if ( iFont ) + iTruncationWidth = TextWidthInPixelsWithTranslation( iTruncation ); + } + +TBool TAknPhedViewLine::HasSelection() const + { + return SelectionStart() != CAknPhedView::KNoPos; + } + +TInt TAknPhedViewLine::SelectionStart() const + { + TInt start = CAknPhedView::KNoPos; + if ( iModel->SelectionExists() ) + { + // This line has selection in it if there is a definite overlap between + // the line and the selection + TInt leftMark = iMirror.LeftMark(); + TInt rightMark = iMirror.RightMark(); + if ( InRange( iRightPos, leftMark-1, rightMark ) ) + start = iRightPos; + else if ( InRange( rightMark, iLeftPos-1, iRightPos ) ) + start = rightMark; + } + return start; + } + +TInt TAknPhedViewLine::SelectionEnd() const + { + TInt end = CAknPhedView::KNoPos; + if ( iModel->SelectionExists() ) + { + // This line has selection in it if there is a definite overlap between + // the line and the selection + TInt leftMark = iMirror.LeftMark(); + TInt rightMark = iMirror.RightMark(); + if ( InRange(iLeftPos, leftMark, rightMark+1 ) ) + end = iLeftPos; + else if ( InRange( leftMark, iLeftPos, iRightPos+1 ) ) + end = leftMark; + } + return end; + } + +TInt TAknPhedViewLine::CursorPosToXPos( TInt aCursorPos ) const + { + TInt xPos = iRect.iBr.iX; + if ( IsTruncatedRight() ) + xPos -= TruncationWidth(); + xPos -= TextWidthInPixelsWithTranslation( ReverseText().Left( aCursorPos - iRightPos ) ); + return --xPos; + } + +TInt TAknPhedViewLine::XPosToCursorPos( TInt aXPos ) const + { + if ( IsTruncatedRight() ) + aXPos += TruncationWidth(); + TInt cursor = iRightPos + TextCountWithTranslation( ReverseText(), iRect.iBr.iX - aXPos ); + + // cursor rule: Cursor can not be beyond the left end of the line + if ( cursor > iLeftPos ) + cursor = iLeftPos; + + // cursor rule: Cursor should not be on the right end of a line, except the rightmost line + if ( cursor == iRightPos && cursor < iLeftPos && iRightLine ) + cursor++; + + return cursor; + } + +void TAknPhedViewLine::Draw( CWindowGc& aGc, MAknsSkinInstance* aSkin, + MAknsControlContext* aContext, const CCoeControl* aControl ) const + { + TBool useSkin = AknsDrawUtils::Background( aSkin, aContext, aControl, + aGc, iRect ); + // set up colors and styles + if( useSkin ) + { + aGc.SetBrushStyle( CGraphicsContext::ENullBrush ); + } + else + { + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + } + aGc.SetPenStyle( CGraphicsContext::ESolidPen ); + aGc.SetPenColor( KRgbBlack ); + aGc.SetBrushColor( KRgbWhite ); + + // draw the text, including truncation + TRect rect = iRect; + TInt baseline = Baseline() - iRect.iTl.iY; + + if ( IsTruncatedRight() ) + { + DrawText( aGc, iTruncation, baseline, rect ); + } + if ( IsTruncatedLeft() ) + { + TInt textWidth = iFont->TextWidthInPixels( Text() ); + TInt truncationWidth = iFont->TextWidthInPixels( iTruncation ); + + if ( textWidth + truncationWidth > rect.Width() && Text().Length() >= 1 ) + { + TPtrC text( Text() ); + DrawText(aGc, text.Right( text.Length() - 1 ), baseline, rect ); + } + else + { + DrawText( aGc, Text(), baseline, rect ); + } + DrawText( aGc, iTruncation, baseline, rect ); + } + else + { + DrawText( aGc, Text(), baseline, rect ); + } + + + // blank the rest of the line + if( !useSkin ) + { + aGc.SetPenStyle( CGraphicsContext::ENullPen ); + aGc.DrawRect( rect ); + } + + // invert any selection by xoring with white + if ( HasSelection() ) + { + DrawHighlightText( aGc, useSkin ); + } + + iRedraw = EFalse; + } + +void TAknPhedViewLine::DrawText( CGraphicsContext& aGc, + const TDesC& aText, + TInt aBaseline, + TRect& aRect) const + { + TRgb color = KRgbBlack; + AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), color, + KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG51 ); + aGc.SetPenColor( color ); + // This function shifts the RHS of aRect left by the width of the text drawn. + // It temporarily limits the draw rectangle to the text width to prevent flicker. + TPtr buf( TranslatedText( aText ) ); + + TInt width = iFont->TextWidthInPixels( buf ); + TInt x = aRect.iTl.iX; + aRect.iTl.iX = aRect.iBr.iX - width; + + + aGc.DrawText( buf, aRect, aBaseline, CGraphicsContext::ERight ); + aRect.iBr.iX -= width; + aRect.iTl.iX = x; + } + +void TAknPhedViewLine::DrawTextWithTranslation( CGraphicsContext& aGc, + const TDesC& aText, + TInt aBaseline, + TRect& aRect ) const + { + TRgb color; + color = KRgbBlack; + AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), color, + KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG51 ); + aGc.SetPenColor( color ); + TPtr buf( TranslatedText( aText ) ); + aGc.DrawText( buf, aRect, aBaseline, CGraphicsContext::ERight ); + } + +TInt TAknPhedViewLine::TextCountWithTranslation( const TDesC& aText, TInt aWidth ) const + { + TPtr buf( TranslatedText( aText ) ); + return iFont->TextCount( buf, aWidth ); + } + +TInt TAknPhedViewLine::TextWidthInPixelsWithTranslation( const TDesC& aText ) const + { + TPtr buf( TranslatedText( aText ) ); + return iFont->TextWidthInPixels( buf ); + } + +TPoint TAknPhedViewLine::CursorPosition() const + { + __ASSERT_DEBUG( iCursor != CAknPhedView::KNoPos, PhedViewPanic( ELineNoCursor ) ); + return TPoint( CursorPosToXPos( iCursor ), Baseline() ); + } + +// --------------------------------------------------------------------------- +// TAknPhedViewLine::DrawHighlightText +// --------------------------------------------------------------------------- +// +void TAknPhedViewLine::DrawHighlightText( CGraphicsContext& aGc, + TBool aUseSkin ) const + { + TInt baseline = Baseline() - iRect.iTl.iY; + TRect rect( iRect ); + rect.iBr.iX = CursorPosToXPos( SelectionStart() ); + rect.iTl.iX = CursorPosToXPos( SelectionEnd() ); + + TRgb penColor( KRgbWhite ); + TRgb brushColor( KRgbBlue ); + if ( aUseSkin ) + { + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + AknsUtils::GetCachedColor( skin, penColor, KAknsIIDQsnTextColors, + EAknsCIQsnTextColorsCG24); + AknsUtils::GetCachedColor( skin, brushColor, KAknsIIDQsnHighlightColors, + EAknsCIQsnHighlightColorsCG2 ); + } + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.SetBrushColor( brushColor ); + aGc.DrawRect( rect ); + aGc.SetPenStyle( CGraphicsContext::ESolidPen ); + aGc.SetPenColor( penColor ); + TInt selStart( iModel->LeftMark() ); + TInt endPos( iModel->Length() - SelectionStart() ); + TInt startPos( iModel->Length() - SelectionEnd() ); + TPtrC text( TranslatedText( iModel->Selection().Mid( startPos - selStart, + endPos - startPos ) ) ); + aGc.DrawText( text, rect, baseline, CGraphicsContext::ERight ); + } + +TPtr TAknPhedViewLine::TranslatedText( const TDesC& aText ) const + { + TPtr buf( iModel->TranslationBuffer() ); + // to make sure that the buffer does not overflow. + TInt maxLength = buf.MaxLength(); + buf.Copy( aText.Left( maxLength ) ); + // this routine will not expand the contents of the buffer: + AknTextUtils::DisplayTextLanguageSpecificNumberConversion( buf ); + return buf; + } + +CAknPhedView::CAknPhedView( CAknPhedModel* aModel ) : iModel( aModel ) + { + iMirror.SetPhedModel( iModel ); + iMirror.SetObserver( this ); + } + +CAknPhedView::~CAknPhedView() + { + CRedirectionListener* listener = ( CRedirectionListener* ) + CAknTransitionUtils::GetData( (TInt) this ); + if ( listener ) + { + CAknTransitionUtils::RemoveObserver( listener, + CAknTransitionUtils::EEventWsBufferRedirection ); + CAknTransitionUtils::RemoveData( (TInt) this ); + delete listener; + } + delete iLines; + delete iTruncation; + } + +void CAknPhedView::ConstructL( TInt aMaxLines, const TDesC& aTruncation ) + { + iTruncation = aTruncation.AllocL(); + iLines = new(ELeave) CAknPhedViewLineArray( aMaxLines ); + iLines->ResizeL(aMaxLines); + for ( TInt ii=0; iiAt( ii ).SetModel( iModel ); + iLines->At( ii ).SetTruncation( *iTruncation ); + } + // Create listener that listen for redirection changes + CRedirectionListener* listener = new (ELeave) CRedirectionListener( *this ); + User::LeaveIfError( CAknTransitionUtils::SetData( (TInt) this, + (TDesC8*) listener ) ); + User::LeaveIfError( CAknTransitionUtils::AddObserver( listener, + CAknTransitionUtils::EEventWsBufferRedirection ) ); + } + +void CAknPhedView::SetFormat( TInt aLines, + const CFont* aFont, + const TRect& aRect, + TInt aBottomBaselineOffset, + TInt aBaselineSeparation) + { + __ASSERT_DEBUG(iLines, PhedViewPanic(EFormatNullLines)); + __ASSERT_DEBUG(aLines <= iLines->Count(), PhedViewPanic(EFormatTooManyLines)); + __ASSERT_DEBUG(aLines > 0, PhedViewPanic(EFormatTooFewLines)); + + iNumLines = aLines; + iFont = aFont; + iRect = aRect; + + TRect rect(aRect); + TInt baseline(rect.iBr.iY - aBottomBaselineOffset); + for (TInt ii=0; iiAt(ii); + + // give each line a part of the rectangle aBaselineSeparation high + if ( iNumLines > 1) + { + rect.iTl.iY = rect.iBr.iY - aBaselineSeparation; + } + line.SetFormat(aFont, rect, baseline); + rect.iBr.iY = rect.iTl.iY; + baseline -= aBaselineSeparation; + + SetConnectingLines(line, ii); + } + + SetCursorFormat(aFont); + + FullFormat(); + } + +void CAknPhedView::SetConnectingLines(TAknPhedViewLine& aLine, TInt aLineNum) + { + // connect up lines. Line 0 is the bottom line. + aLine.SetLeftLine(aLineNum >= iNumLines-1 ? NULL : &iLines->At(aLineNum+1)); + aLine.SetRightLine(aLineNum <= 0 ? NULL : &iLines->At(aLineNum - 1)); + } + +void CAknPhedView::HandlePhedDataEvent( const TAknPhedDataEvent& aEvent, + CAknPhedModel* /*aPhedData*/) + { + __ASSERT_DEBUG( iLines, PhedViewPanic( EEventNullLines ) ); + + if ( aEvent.TextChanged() ) + { + TInt start; + TInt end; + aEvent.TextChangeRange( start, end ); + TextChangeFormat( start, end ); + } + // text change handling also repositions cursor, so don't handle it twice + else if ( aEvent.CursorChanged() ) + { + CursorChangeFormat( iMirror.CursorPosition() ); + } + + if ( aEvent.SelectionChanged() ) + { + SelectionChangeFormat( iMirror.LeftMark(), iMirror.RightMark() ); + } + + // report that the editor has changed to the containing control, so that it + // can report to it's observer. + if ( iChangeReceiver ) + iChangeReceiver->StateChanged(); + } + +void CAknPhedView::FullFormat() + { + TextChangeFormat( 0, iModel->Length() ); + SelectionChangeFormat( iMirror.LeftMark(), iMirror.RightMark() ); + } + +void CAknPhedView::TextChangeFormat( TInt aStart, TInt aEnd ) + { + // Let the lines handle the change. + // Stops after the first line able to handle the change, because it will tell the rest + for ( TInt ii=0; iiAt(ii).HandleTextChange( aStart, aEnd ) ) + break; + } + + // Make as much text fit on screen, to the RHS as possible + TAknPhedViewLine& leftLine = iLines->At( iNumLines-1 ); + TAknPhedViewLine& rightLine = iLines->At( 0 ); + if ( rightLine.IsTruncatedRight() && !leftLine.IsTruncatedLeft() && aStart <0 ) + { + SetLeftPos( 0 ); + } + if ( rightLine.IsTruncatedRight() && !leftLine.IsTruncatedLeft() ) + { + SetLeftPos(leftLine.LeftPos()); + } + + // Cursor positioning must be affected by all that + CursorChangeFormat( iMirror.CursorPosition() ); + } + +void CAknPhedView::CursorChangeFormat( TInt aCursor ) + { + if ( aCursor < 0 ) + { + return; + } + // Shift the text so that the cursor appears on the screen + TAknPhedViewLine& leftLine = iLines->At( iNumLines-1 ); + TAknPhedViewLine& rightLine = iLines->At( 0 ); + + if ( aCursor < rightLine.RightPos() ) + { + rightLine.SetRightPos( aCursor ); + } + else if ( aCursor >= leftLine.LeftPos() && leftLine.LineWidth() != 0 && + leftLine.IsTruncatedLeft() ) + { + + // cursor rule: cursor should not be a LHS of left truncated line + if ( aCursor == iModel->Length() ) + SetLeftPos( aCursor ); + else + SetLeftPos( aCursor+1 ); + } + else if ( aCursor >= leftLine.LeftPos() ) + { + SetLeftPos( aCursor ); + } + // Tell each line about the cursor. + // Bottom most line to handle the event claims the cursor + for ( TInt ii=0; iiAt( ii ).HandleCursorChange( aCursor ) ) + { + iCursorLine = ii; + aCursor = KNoPos; + } + } + + UpdateCursor(); + } + +void CAknPhedView::SelectionChangeFormat( TInt aLeft, TInt aRight ) + { + // Tell each line about the selection change + for ( TInt ii=0; iiAt( ii ).HandleSelectionChange( aLeft, aRight ); + } + } + +void CAknPhedView::Draw( CWindowGc& aGc, TBool aRedrawAll, + const CCoeControl* aControl ) const + { + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext( aControl ); + + aGc.UseFont( iFont ); + for ( TInt ii=0; iiAt( ii ); + if ( aRedrawAll || line.IsRedrawRequired() ) + { + line.Draw( aGc, skin, cc, aControl ); + } + } + aGc.DiscardFont(); + } + +void CAknPhedView::MoveCursorToLine( TInt aLineNo, TInt aTargetCursorPos ) + { + // Used by up and down cursor move functions. Scroll one line if necessary + if ( aLineNo < 0 ) + { + TAknPhedViewLine& line = iLines->At( 0 ); + line.SetLeftPos(line.RightPos()); + iMirror.SetCompensatedCursorPosition(line.XPosToCursorPos(aTargetCursorPos)); + line.SetRightPos( line.RightPos() ); + } + else if ( aLineNo >= iNumLines ) + { + TAknPhedViewLine& line = iLines->At( iNumLines-1 ); + line.SetRightPos( line.LeftPos() ); + iMirror.SetCompensatedCursorPosition(line.XPosToCursorPos(aTargetCursorPos)); + SetLeftPos( line.LeftPos() ); + } + else + { + iMirror.SetCompensatedCursorPosition( + iLines->At( aLineNo ).XPosToCursorPos( aTargetCursorPos ) ); + } + + UpdateCursor(); + } + + +TBool CAknPhedView::CursorUp( TInt aTargetCursorPos ) + { + // cursor rule: if at top LHS, wrap to bottom RHS, otherwise up one line + if ( iMirror.CursorPosition() == iModel->Length() ) + { + // This code should be setting the real cursor position, but there is + // a bug in the real cursor position function, in that it works in "compensated/formatted" space. + iMirror.SetCompensatedCursorPosition(0); + return EFalse; + } + else + { + MoveCursorToLine( iCursorLine + 1, aTargetCursorPos ); + return ( iMirror.CursorPosition() != iModel->Length() ); + } + } + +TBool CAknPhedView::CursorDown( TInt aTargetCursorPos ) + { + // cursor rule: if at bottom RHS, wrap to top LHS, otherwise down one line + if ( iMirror.CursorPosition() == 0 ) + { + // This code depends on the fact that there is a bug in the real cursor + // position function, in that it works in "compensated/formatted" space. + iMirror.SetRealCursorPosition(iModel->Length()); + return EFalse; + } + else + { + MoveCursorToLine( iCursorLine - 1, aTargetCursorPos ); + return ( iMirror.CursorPosition() != 0 ); + } + } + +TBool CAknPhedView::SelectUp( TInt aTargetCursorPos ) + { + TInt anchor = iModel->AnchorPosition(); + TBool targetPosUsed = CursorUp( aTargetCursorPos ); + iModel->SetAnchorPosition( anchor ); + return targetPosUsed; + } + +TBool CAknPhedView::SelectDown( TInt aTargetCursorPos ) + { + TInt anchor = iModel->AnchorPosition(); + TBool targetPosUsed = CursorDown( aTargetCursorPos ); + iModel->SetAnchorPosition( anchor ); + return targetPosUsed; + } + +void CAknPhedView::EnableCursor() + { + CRedirectionListener* listener = ( CRedirectionListener* ) + CAknTransitionUtils::GetData( (TInt) this ); + listener->EnableCursor(); + UpdateCursor(); + } + +void CAknPhedView::DisableCursor() + { + CRedirectionListener* listener = ( CRedirectionListener* ) + CAknTransitionUtils::GetData( (TInt) this ); + listener->DisableCursor(); + } + +void CAknPhedView::UpdateCursor() + { + CRedirectionListener* listener = ( CRedirectionListener* ) + CAknTransitionUtils::GetData( (TInt) this ); + listener->UpdateCursor( iCursor ); + } + +void CAknPhedView::SetWindows( RWindowGroup* aWg, RWindowBase* aWindow ) + { + CRedirectionListener* listener = ( CRedirectionListener* ) + CAknTransitionUtils::GetData( (TInt) this ); + listener->SetWindows( aWg, aWindow ); + } + +TPoint CAknPhedView::CursorPosition() const + { + return iLines->At( iCursorLine ).CursorPosition(); + } + +void CAknPhedView::SetCursorFormat( const CFont* aFont ) + { + iCursor.iType = TTextCursor::ETypeRectangle; + iCursor.iHeight = AknLayoutUtils::CursorHeightFromFont( aFont->FontSpecInTwips() ); + iCursor.iAscent = AknLayoutUtils::CursorAscentFromFont( aFont->FontSpecInTwips() ); + iCursor.iWidth = AknLayoutUtils::CursorWidthFromFont ( aFont->FontSpecInTwips() ); + iCursor.iFlags = 0; + iCursor.iColor = KRgbWhite; + } + +TBool CAknPhedView::IsTruncated() const + { + return iLines->At( 0 ).IsTruncatedRight() || iLines->At( iNumLines-1 ).IsTruncatedLeft(); + } + +void CAknPhedView::SetLeftPos( TInt aPos ) + { + iLines->At( iNumLines-1 ).SetLeftPos( aPos ); + + // format rule: always justify to bottom right, if not truncated + TAknPhedViewLine& rightLine = iLines->At( 0 ); + if ( !rightLine.IsTruncated() ) + { + rightLine.SetRightPos( 0 ); + } + } + +void CAknPhedView::SetChangeReceiver( CAknPhoneNumberEditor* aChangeReceiver ) + { + iChangeReceiver = aChangeReceiver; + } + +TRect CAknPhedView::Rect() const + { + return iRect; + } + +TInt CAknPhedView::CursorLine() const + { + return iCursorLine; + } + +// --------------------------------------------------------------------------- +// CAknPhedView::GetCursorPosByPoint +// --------------------------------------------------------------------------- +// +TInt CAknPhedView::GetCursorPosByPoint( const TPoint& aPt ) + { + TInt posLine = -1, cursor = -1; + //check which line the pointer position is within. + for ( TInt i = 0; i < iNumLines; i++ ) + { + if ( iLines->At( i ).Rect().Contains( aPt ) ) + { + posLine = i; + break; + } + } + if ( posLine < 0 ) + { + // if pointer position is out of right border of line but its + // Y coordinates is within range of the line, the iRightPos of + // the line should be returned to preserve the selection made + // by user, otherwise a negative value will be returned. + TInt rectBrX = iLines->At( 0 ).Rect().iBr.iX; + if ( aPt.iX > rectBrX ) + { + for ( TInt i = 0; i < iNumLines; i++ ) + { + TInt topY = iLines->At( i ).Rect().iTl.iY; + TInt bottomY = iLines->At( i ).Rect().iBr.iY; + if ( aPt.iY >= topY && aPt.iY <= bottomY ) + { + posLine = i; + break; + } + } + if ( posLine >= 0 && iLines->At( posLine ).LineWidth() > 0 ) + { + TInt rightPos = iLines->At( posLine ).RightPos(); + cursor = iModel->Length() - rightPos; + } + } + return cursor; + } + // only handle pointer event when the line has data + if ( iLines->At( posLine ).LineWidth() > 0) + { + iCursorLine = posLine; + TInt pos = iLines->At( iCursorLine ).XPosToCursorPos( aPt.iX ); + cursor = iModel->Length() - pos; + + const TReal32 KHalfRatio = 0.5; + TInt rightX = iLines->At( iCursorLine ).CursorPosToXPos( pos ); + TInt leftX = iLines->At( iCursorLine ).CursorPosToXPos( pos + 1 ); + TInt rightPos = iLines->At( iCursorLine ).RightPos(); + TInt leftPos = iLines->At( iCursorLine ).LeftPos(); + if ( aPt.iX < iLines->At( iCursorLine ).CursorPosToXPos( leftPos ) + && aPt.iX > 0 ) + { + return cursor; + } + + if ( aPt.iX > rightX && rightPos > 0 ) + { + leftX = rightX; + rightX = iLines->At( iCursorLine ).Rect().iBr.iX; + cursor++; + } + if ( ( aPt.iX - leftX ) < ( ( rightX - leftX ) * KHalfRatio ) ) + { + cursor--; + } + } + return cursor; + } + +// End of File