uifw/AvKon/src/AknPhedModel.cpp
changeset 0 2f259fa3e83a
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 #include "AknPhedModel.h"
       
    19 #include "NumberGrouping.h"
       
    20 
       
    21 #include <e32svr.h>
       
    22 #include <AknUtils.h>
       
    23 
       
    24 const TInt KExtraSpaceForGroupedNumber = 6;
       
    25 
       
    26 //
       
    27 // CAknPhedBuffer
       
    28 //
       
    29 CAknPhedScratchBuffer::CAknPhedScratchBuffer() :iPtr(0,0)
       
    30 	{
       
    31 	}
       
    32 
       
    33 CAknPhedScratchBuffer::~CAknPhedScratchBuffer()
       
    34 	{
       
    35 	delete iBuf;
       
    36 	}
       
    37 
       
    38 void CAknPhedScratchBuffer::ConstructL(TInt aMaxLen)
       
    39 	{
       
    40 	iBuf = HBufC::NewL(aMaxLen + KExtraSpaceForGroupedNumber);
       
    41 	iPtr.Set(iBuf->Des());
       
    42 	}
       
    43 
       
    44 
       
    45 
       
    46 //
       
    47 // CAknPhedModel
       
    48 //
       
    49 CAknPhedModel* CAknPhedModel::NewL( TInt aMaxLen )
       
    50     {
       
    51     CAknPhedModel* self = new( ELeave ) CAknPhedModel;
       
    52     CleanupStack::PushL( self );
       
    53     self->ConstructL( aMaxLen );
       
    54     CleanupStack::Pop( self );
       
    55     return self;
       
    56     }
       
    57 
       
    58 CAknPhedModel::~CAknPhedModel()
       
    59     {
       
    60     delete iNumberGroupingBuffer;
       
    61 	delete iBuf;
       
    62     }
       
    63 
       
    64 void CAknPhedModel::SetText( const TDesC& aText )
       
    65     {
       
    66     StartEvent();
       
    67 
       
    68     // delete all existing text
       
    69     TInt len = iRealLength;
       
    70     DeleteLeft( len, len );
       
    71 
       
    72     // insert the new text
       
    73     SetRealCursorPosition( 0 );
       
    74     Insert( aText );
       
    75 
       
    76     ReportEvent(MPhedDataObserver::TAknPhedDataEvent(
       
    77                 MPhedDataObserver::TAknPhedDataEvent::EText, 
       
    78                 0,
       
    79                 iNumberGroupingBuffer->Length() ) );
       
    80     }
       
    81 
       
    82 void CAknPhedModel::Insert( TText aChar )
       
    83     {
       
    84     StartEvent();
       
    85     ClearAnySelection();
       
    86 
       
    87     TInt nOldCursorPos = CursorPosition();
       
    88 
       
    89     // buffer full rule: Text overflows off the left hand side of the buffer
       
    90     TInt maxLength = MaxDisplayLength();
       
    91     if ( iRealLength == maxLength )
       
    92         {
       
    93         if (nOldCursorPos == 0)
       
    94             {
       
    95             ReportEvent( MPhedDataObserver::TAknPhedDataEvent() );
       
    96             return;
       
    97             }
       
    98         else
       
    99             {
       
   100             DeleteLeft( 1 );
       
   101             SetRealCursorPosition( iRealCursor - 1 );
       
   102             }
       
   103         }
       
   104         
       
   105     iNumberGroupingBuffer->Insert( iRealCursor, aChar );
       
   106     ++iRealLength;
       
   107     iNumberGroupingBuffer->FormattedNumber();
       
   108     SetRealCursorPosition( iRealCursor + 1 );
       
   109     if ( Length() > maxLength )
       
   110         {
       
   111         DeleteLeft( 1 );
       
   112         SetRealCursorPosition( iRealCursor - 1 );
       
   113         ReportEvent(MPhedDataObserver::TAknPhedDataEvent(
       
   114         MPhedDataObserver::TAknPhedDataEvent::EText, 
       
   115         CursorPosition(),                                  
       
   116         CursorPosition() ) );
       
   117         }
       
   118     else 
       
   119         {
       
   120         ReportEvent( MPhedDataObserver::TAknPhedDataEvent(
       
   121                 MPhedDataObserver::TAknPhedDataEvent::EText, 
       
   122                 nOldCursorPos,                                  
       
   123                 CursorPosition() ) );
       
   124         }                
       
   125     
       
   126     }
       
   127 
       
   128 void CAknPhedModel::DeleteLeft()
       
   129     {
       
   130     if( !ClearAnySelection() && iRealCursor > 0 )
       
   131         {
       
   132         StartEvent();
       
   133 
       
   134         TInt nOldCursorPos = CursorPosition();
       
   135 
       
   136         DeleteLeft(iRealCursor);
       
   137         
       
   138         SetRealCursorPosition( iRealCursor - 1 );
       
   139         ReportEvent( MPhedDataObserver::TAknPhedDataEvent(
       
   140                 MPhedDataObserver::TAknPhedDataEvent::EText, 
       
   141                 CursorPosition(),                               
       
   142                 CursorPosition() ) );
       
   143         }
       
   144         
       
   145     }
       
   146 
       
   147 void CAknPhedModel::DeleteLeft( TInt aIndex, TInt aCount )
       
   148     {
       
   149     aIndex--;   // delete char to the left
       
   150 
       
   151     for ( TInt ii = 0; ii < aCount; ++ii )
       
   152         {
       
   153         iNumberGroupingBuffer->Delete( aIndex - ii );
       
   154         --iRealLength;
       
   155         }
       
   156     }   
       
   157 
       
   158 TPtrC CAknPhedModel::Selection() const
       
   159     { 
       
   160     TInt nFrom = LeftMark();
       
   161     TInt nTo = nFrom + SelectionWidth();
       
   162 
       
   163     if(!nTo) nTo = iRealLength;
       
   164     
       
   165     return iNumberGroupingBuffer->Selection( nFrom, nTo );
       
   166     }
       
   167 
       
   168 void CAknPhedModel::Cut( TDes& aCutText )
       
   169     {
       
   170     aCutText = Selection();
       
   171     ClearAnySelection();
       
   172     }
       
   173 
       
   174 void CAknPhedModel::Copy( TDes& aCopiedText ) const
       
   175     {
       
   176     aCopiedText = Selection();
       
   177     }
       
   178 
       
   179 void CAknPhedModel::Paste( const TDesC& aText )
       
   180     {
       
   181     ClearAnySelection();
       
   182     Insert( aText );
       
   183     }
       
   184 
       
   185 TInt CAknPhedModel::Language()  const   
       
   186     {
       
   187     TInt language = iNumberGroupingBuffer->Language();
       
   188     language &= KAknLanguageMask;  
       
   189     TInt forceLanguage = iNumberGroupingBuffer->iForceLanguage;
       
   190     forceLanguage &= KAknLanguageMask; 
       
   191     
       
   192     return ( ELangAmerican == language || 
       
   193              ELangAmerican == forceLanguage)
       
   194             ? ELangAmerican : ELangTest;
       
   195     }
       
   196 
       
   197 TInt CAknPhedModel::Compensate( TInt aRealPosition ) const
       
   198 {
       
   199     TInt nCompensated = 0;
       
   200     if ( Language() )
       
   201     	{
       
   202     if( iCursorDirection == EUp )
       
   203         nCompensated = aRealPosition + Spaces( 0, aRealPosition );
       
   204     else if( iCursorDirection == EDown )
       
   205         nCompensated = aRealPosition + Spaces( 0, aRealPosition + 1 );    
       
   206     	}
       
   207     else
       
   208     	{
       
   209     	nCompensated = aRealPosition;
       
   210     	}
       
   211     return nCompensated;
       
   212 }
       
   213 
       
   214 TInt CAknPhedModel::Uncompensate( TInt aCompensatedPosition ) const
       
   215 {
       
   216     TInt nUncompensated = 0;
       
   217     if ( Language() )
       
   218     	{
       
   219     if( iCursorDirection == EUp )
       
   220         nUncompensated = aCompensatedPosition - Spaces( aCompensatedPosition - 1 );
       
   221     else if( iCursorDirection == EDown )
       
   222         nUncompensated = aCompensatedPosition - Spaces( aCompensatedPosition );    
       
   223     	}
       
   224     else
       
   225     	{
       
   226     	nUncompensated = aCompensatedPosition;
       
   227     	}
       
   228     return nUncompensated;
       
   229 }
       
   230 
       
   231 TInt CAknPhedModel::SetRealCursorPosition( TInt aCursorPos )
       
   232     {
       
   233     StartEvent();
       
   234     if ( SelectionExists() )
       
   235         {
       
   236         // selection is lost, so report a selection change event
       
   237         StartEvent();
       
   238         ReportEvent( MPhedDataObserver::TAknPhedDataEvent(
       
   239                      MPhedDataObserver::TAknPhedDataEvent::ESelection ) );
       
   240         }
       
   241 
       
   242     iRealCursor = iRealAnchor = aCursorPos;
       
   243 
       
   244     ReportEvent( MPhedDataObserver::TAknPhedDataEvent(
       
   245                  MPhedDataObserver::TAknPhedDataEvent::ECursor ) );
       
   246     
       
   247     return iRealCursor;
       
   248     }
       
   249 
       
   250 TInt CAknPhedModel::SetCompensatedCursorPosition( TInt aCursorPos )
       
   251     {
       
   252     StartEvent();
       
   253     if ( SelectionExists() )
       
   254         {
       
   255         // selection is lost, so report a selection change event
       
   256         StartEvent();
       
   257         ReportEvent( MPhedDataObserver::TAknPhedDataEvent(
       
   258                      MPhedDataObserver::TAknPhedDataEvent::ESelection ) );
       
   259         }
       
   260 
       
   261     iRealCursor = iRealAnchor = Uncompensate( aCursorPos );
       
   262 
       
   263     ReportEvent( MPhedDataObserver::TAknPhedDataEvent(
       
   264                  MPhedDataObserver::TAknPhedDataEvent::ECursor ) );
       
   265     
       
   266     return iRealCursor;
       
   267     }
       
   268 
       
   269 TInt CAknPhedModel::SetAnchorPosition(TInt aAnchorPos)
       
   270     { 
       
   271     StartEvent();
       
   272 
       
   273     iRealAnchor = aAnchorPos;
       
   274 
       
   275     ReportEvent( MPhedDataObserver::TAknPhedDataEvent(
       
   276                  MPhedDataObserver::TAknPhedDataEvent::ESelection ) );
       
   277 
       
   278     return iRealAnchor;
       
   279     }
       
   280 
       
   281 
       
   282 TInt CAknPhedModel::CursorLeft()
       
   283     {
       
   284      // cursor rule: cursor left -> left of selection or left with wrap to RHS
       
   285     if ( SelectionExists() )
       
   286         return SetRealCursorPosition( LeftMark() );
       
   287     else if (iRealCursor > 0)
       
   288         {
       
   289         return SetRealCursorPosition( iRealCursor - 1 );
       
   290         }
       
   291     else
       
   292         return SetRealCursorPosition( iRealLength );
       
   293     }
       
   294 
       
   295 TInt CAknPhedModel::CursorRight()
       
   296     {
       
   297     // cursor rule: cursor right -> right of selection or right with wrap to LHS
       
   298     if ( SelectionExists() )
       
   299         return SetRealCursorPosition( RightMark() );
       
   300     else if ( iRealCursor < iRealLength )
       
   301         return SetRealCursorPosition( iRealCursor + 1 );
       
   302     else
       
   303         return SetRealCursorPosition( 0 );
       
   304     }
       
   305 
       
   306 void CAknPhedModel::ConstructL( TInt aMaxLen )
       
   307     {
       
   308     iBuf = new(ELeave) CAknPhedScratchBuffer;
       
   309    	iBuf->ConstructL(aMaxLen);
       
   310 
       
   311     // Construct the number grouping engine with the reversed buffer support turned on
       
   312     iNumberGroupingBuffer = CPNGNumberGrouping::NewL( aMaxLen, ETrue );
       
   313     
       
   314     iSelection.Set( KNullDesC );
       
   315     iCursorDirection = EUp;
       
   316 
       
   317     iCount = 0;
       
   318     }
       
   319 
       
   320 void CAknPhedModel::Insert( const TDesC& aText )
       
   321     {
       
   322     StartEvent();
       
   323     TInt len = aText.Length();
       
   324     for ( TInt ii=0; ii<len; ii++ )
       
   325         {
       
   326         Insert( aText[ii] );
       
   327         }
       
   328 
       
   329     if ( len && iRealCursor > 0 )
       
   330         {
       
   331         // report a text event if anything actually got inserted
       
   332         ReportEvent( MPhedDataObserver::TAknPhedDataEvent(
       
   333                      MPhedDataObserver::TAknPhedDataEvent::EText, 
       
   334                      Max( 0, CursorPosition() - len ),             
       
   335                      CursorPosition() ) );         
       
   336         }
       
   337     else
       
   338         {
       
   339         // otherwise report nothing
       
   340         ReportEvent( MPhedDataObserver::TAknPhedDataEvent() );
       
   341         }
       
   342     }
       
   343 
       
   344 TBool CAknPhedModel::ClearAnySelection()
       
   345     {
       
   346     if ( SelectionExists() )
       
   347         {
       
   348         StartEvent();
       
   349         TInt left = LeftMark(); 
       
   350         TInt right = RightMark();
       
   351 
       
   352         DeleteLeft( right, SelectionWidth() );
       
   353         iNumberGroupingBuffer->FormattedNumber();
       
   354         
       
   355         SetRealCursorPosition( left );
       
   356                 
       
   357         ReportEvent( MPhedDataObserver::TAknPhedDataEvent(
       
   358                      MPhedDataObserver::TAknPhedDataEvent::EText, 
       
   359                      CursorPosition(), 
       
   360                      left ) );
       
   361         
       
   362         return ETrue;
       
   363         }
       
   364     return EFalse;
       
   365     }
       
   366 
       
   367 void CAknPhedModel::StartEvent()
       
   368     {
       
   369     // Events can be nested, so that one combined event is reported for each external operation
       
   370     if (iEventDepth == 0)
       
   371         iEvent.Reset();
       
   372     
       
   373     iEventDepth++;
       
   374     }
       
   375 
       
   376 void CAknPhedModel::ReportEvent( const MPhedDataObserver::TAknPhedDataEvent& aEvent )
       
   377     {
       
   378     // Combine this event with any other nested event and report the lot if the
       
   379     // nesting is finished
       
   380     iEvent.Add( aEvent ); 
       
   381     iEventDepth--;
       
   382     
       
   383     if ( iEventDepth == 0 && iObserver && 
       
   384          ( iEvent.TextChanged() || iEvent.CursorChanged() || iEvent.SelectionChanged() ) )
       
   385         {
       
   386         // safety subtlty: event is reported as the very last thing in case the caller
       
   387         // does something stupid, like leave.
       
   388         iObserver->HandlePhedDataEvent( iEvent, this );
       
   389         }
       
   390     }
       
   391 
       
   392 void CAknPhedModel::SelectMove( TInt aInc )
       
   393     {
       
   394     // selection rule: selection cursor wraps LHS <-> RHS
       
   395     iRealCursor = iRealCursor + aInc;
       
   396 
       
   397     if ( iRealCursor < 0 )
       
   398         iRealCursor = iRealLength;
       
   399     else if ( iRealCursor > iRealLength )
       
   400         iRealCursor =  0;
       
   401     
       
   402     StartEvent();
       
   403     ReportEvent( MPhedDataObserver::TAknPhedDataEvent(
       
   404                  MPhedDataObserver::TAknPhedDataEvent::ESelection | 
       
   405                  MPhedDataObserver::TAknPhedDataEvent::ECursor ) );
       
   406     }
       
   407 
       
   408 TBool CAknPhedModel::CursorPositionIsSpace()
       
   409 {
       
   410     TInt nCursorPosition = CursorPosition();
       
   411 
       
   412     if( nCursorPosition != Length() )
       
   413         return iNumberGroupingBuffer->IsSpace( nCursorPosition );
       
   414     else
       
   415         return EFalse;
       
   416 }
       
   417 
       
   418 TInt CAknPhedModel::Spaces( TInt aFromPos, TInt aToPos ) const
       
   419 {
       
   420     TInt spacesCount = 0;
       
   421     TInt toPos = aToPos;
       
   422     
       
   423     for( TInt i = aFromPos; i <= toPos; ++i )
       
   424     {
       
   425         if( iNumberGroupingBuffer->IsSpace( i ) )
       
   426         {
       
   427             ++spacesCount;
       
   428             ++toPos;            
       
   429         }
       
   430     }   
       
   431     
       
   432     return spacesCount;
       
   433 }
       
   434 
       
   435 TInt CAknPhedModel::Spaces( TInt aToPos ) const
       
   436 {
       
   437     TInt spacesCount = 0;
       
   438     TInt toPos = aToPos;
       
   439     
       
   440     for( TInt i = 0; i <= toPos; ++i )
       
   441     {
       
   442         if( iNumberGroupingBuffer->IsSpace( i ) )
       
   443         {
       
   444             ++spacesCount;            
       
   445         }
       
   446     }   
       
   447     
       
   448     return spacesCount;
       
   449 }
       
   450 //
       
   451 // MPhedDataObserver::TAknPhedDataEvent
       
   452 //
       
   453 void MPhedDataObserver::TAknPhedDataEvent::Add( const TAknPhedDataEvent& aEvent )
       
   454     {
       
   455     if ( aEvent.TextChanged() )
       
   456         {
       
   457         if ( TextChanged() )
       
   458             {
       
   459             if ( iStart > aEvent.iStart )
       
   460                 iStart = aEvent.iStart;
       
   461             if ( iEnd < aEvent.iEnd )
       
   462                 iEnd = aEvent.iEnd;
       
   463             }
       
   464         else
       
   465             {
       
   466             iStart = aEvent.iStart;
       
   467             iEnd = aEvent.iEnd;
       
   468             }
       
   469         }
       
   470 
       
   471     iType |= aEvent.iType;
       
   472     }
       
   473 
       
   474 
       
   475 //
       
   476 // TAknPhedDataMirror
       
   477 //
       
   478 void TAknPhedDataMirror::HandlePhedDataEvent( const TAknPhedDataEvent& aEvent, 
       
   479                                               CAknPhedModel* aPhedData )
       
   480     {
       
   481     // The mirror reverses event positioning from the model
       
   482     if ( iObserver )
       
   483         {
       
   484         TInt start;
       
   485         TInt end;
       
   486         aEvent.TextChangeRange( start, end );
       
   487         TAknPhedDataEvent event( aEvent.Type(), Mirror( end ), Mirror( start ) );
       
   488         iObserver->HandlePhedDataEvent( event, aPhedData );
       
   489         }
       
   490     }
       
   491 
       
   492 TInt TAknPhedDataMirror::Compensate( TInt aMirrorPosition ) const
       
   493     { 
       
   494     TInt Compensated ;
       
   495     if ( iPhed->Language() )
       
   496     	{
       
   497         Compensated = aMirrorPosition - iPhed->Spaces( 0, iPhed->iRealCursor );
       
   498     	}
       
   499     else
       
   500     	{
       
   501     	Compensated = aMirrorPosition;
       
   502     	}
       
   503     return Compensated; 
       
   504     }
       
   505 
       
   506 // End of File
       
   507