--- /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 <AknsDrawUtils.h>
+
+#include <gfxtranseffect/gfxtranseffect.h>
+#include <akntransitionutils.h>
+#include <avkondomainpskeys.h>
+#include <e32property.h>
+
+// 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; ii<aMaxLines; ii++ )
+ {
+ iLines->At( 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; ii<aLines; ii++)
+ {
+ TAknPhedViewLine& line = iLines->At(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; ii<iNumLines; ii++ )
+ {
+ if ( iLines->At(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; ii<iNumLines; ii++ )
+ {
+ if ( iLines->At( 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; ii<iNumLines; ii++ )
+ {
+ iLines->At( 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; ii<iNumLines; ii++ )
+ {
+ TAknPhedViewLine& line = iLines->At( 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