wvuing/wvuiave/AppSrc/CCAMessageEditor.cpp
branchRCL_3
changeset 13 a941bc465d9f
parent 0 094583676ce7
equal deleted inserted replaced
12:6ca72c0fe49a 13:a941bc465d9f
       
     1 /*
       
     2 * Copyright (c) 2006 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:  Chat client's editor.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "CCAMessageEditor.h"
       
    21 #include "ChatDefinitions.h"
       
    22 #include "CCAMessageExtensionsHandler.h"
       
    23 #include "IMUtils.h"
       
    24 #include "IMDialogUtils.h"
       
    25 #include "mcatapeventobserver.h"
       
    26 
       
    27 #include <eikenv.h>
       
    28 #include <aknutils.h>
       
    29 #include <txtrich.h> // CRichText
       
    30 #include <chatNG.rsg>
       
    31 #include <eikon.rsg>    // R_EIK_EDWIN_CTRL_HOTKEYS & R_EIK_EDWIN_SHIFT_CTRL_HOTKEYS
       
    32 #include <AknsBasicBackgroundControlContext.h>
       
    33 #include "CCAEditIndicator.h"
       
    34 
       
    35 // The Settings have been moved to Cenrep (also retained in the Resource file),
       
    36 // so the enums for keys and central repository header is added here
       
    37 #include 	"VariantKeys.h"
       
    38 // CONSTANTS
       
    39 
       
    40 // TKeyEvent.iCode limit for hotkeys, see DoOfferKeyEvenL in eikedwin.cpp
       
    41 const TInt KChatKeyEventHotkeyLimit = 100;
       
    42 // Buffer descriptor size for
       
    43 // R_EIK_EDWIN_CTRL_HOTKEYS & R_EIK_EDWIN_SHIFT_CTRL_HOTKEYS
       
    44 // see DoOfferKeyEvenL in eikedwin.cpp
       
    45 const TInt KChatResourceBufferSize = 24;
       
    46 
       
    47 // Amount of extra characters every smiley takes in the editor
       
    48 const TInt KChatAddCharsPerSmiley = 2;
       
    49 
       
    50 // ================= MEMBER FUNCTIONS =======================
       
    51 
       
    52 // C++ default constructor can NOT contain any code, that
       
    53 // might leave.
       
    54 //
       
    55 CCAMessageEditor::CCAMessageEditor(
       
    56     CCAMessageExtensionsHandler& aMessageHandler )
       
    57         : iMessageHandler( aMessageHandler )
       
    58     {
       
    59     }
       
    60 
       
    61 // Symbian OS default constructor can leave.
       
    62 void CCAMessageEditor::ConstructL( const CCoeControl* aParent, TInt
       
    63                                    aNumberOfLines, TInt aTextLimit, TInt aEdwinFlags,
       
    64                                    TInt aFontControlFlags,
       
    65                                    TInt aFontNameFlags )
       
    66     {
       
    67 
       
    68     CEikRichTextEditor::ConstructL( aParent, aNumberOfLines, aTextLimit,
       
    69                                     aEdwinFlags, aFontControlFlags, aFontNameFlags );
       
    70     }
       
    71 
       
    72 
       
    73 // Destructor
       
    74 CCAMessageEditor::~CCAMessageEditor()
       
    75     {
       
    76     delete iBgContext;
       
    77     delete iFgContext;
       
    78     delete iClipboardBuffer;
       
    79     }
       
    80 
       
    81 // ---------------------------------------------------------
       
    82 // CCAMessageEditor::NumberOfLines()
       
    83 // This method returns the number of lines if expanded
       
    84 // ---------------------------------------------------------
       
    85 //
       
    86 TInt CCAMessageEditor::NumberOfLines() const
       
    87     {
       
    88     return iNumberOfLines;
       
    89     }
       
    90 
       
    91 
       
    92 // ---------------------------------------------------------
       
    93 // CCAMessageEditor::ResetL()
       
    94 // This method clears the editor
       
    95 // ---------------------------------------------------------
       
    96 //
       
    97 void CCAMessageEditor::ResetL()
       
    98     {
       
    99     iTextView->EnablePictureFrameL( EFalse );
       
   100     TBuf< KTwo > str;
       
   101     str.Zero();
       
   102     SetCursorPosL( 0, EFalse );
       
   103     SetTextL( &str );
       
   104     HandleTextChangedL();
       
   105     }
       
   106 
       
   107 // -----------------------------------------------------------------------------
       
   108 // CCAMessageEditor::SetViewRect
       
   109 // Set view rect.
       
   110 // -----------------------------------------------------------------------------
       
   111 //
       
   112 void CCAMessageEditor::SetViewRect( const TRect& aRect )
       
   113     {
       
   114     iViewRect = aRect;
       
   115     }
       
   116 
       
   117 // -----------------------------------------------------------------------------
       
   118 // CCAMessageEditor::OfferKeyEventL
       
   119 // -----------------------------------------------------------------------------
       
   120 //
       
   121 TKeyResponse CCAMessageEditor::OfferKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aType )
       
   122     {
       
   123     if ( aKeyEvent.iScanCode == EStdKeyYes && aType != EEventKey )
       
   124         {
       
   125         return EKeyWasConsumed;
       
   126         }
       
   127 
       
   128     TInt oldLen = TextLength();
       
   129 
       
   130     if ( TextLength() == MaxLength() )
       
   131         {
       
   132         if (  ( aType == EEventKey &&
       
   133                 ( aKeyEvent.iCode != EKeyBackspace &&
       
   134                   aKeyEvent.iCode < EKeyDelete  )
       
   135               ) ||
       
   136               ( aType == EEventKeyUp &&
       
   137                 aKeyEvent.iScanCode >= '0' &&
       
   138                 aKeyEvent.iScanCode <= '9'
       
   139               )
       
   140            )
       
   141             {
       
   142             HBufC* prompt = iEikonEnv->AllocReadResourceLC(
       
   143                                 R_QTN_CHAT_MAXIMUM_MESSAGE_LENGTH );
       
   144             IMDialogUtils::DisplayInformationNoteL(
       
   145                 *prompt );
       
   146             CleanupStack::PopAndDestroy( prompt );
       
   147 
       
   148             return EKeyWasConsumed;
       
   149             }
       
   150         }
       
   151 
       
   152     TKeyResponse res = EKeyWasNotConsumed;
       
   153 
       
   154     // --------------------
       
   155     // This logic comes from CEikEdwin
       
   156     // We need to handle hot keys cut and copy
       
   157     TBool select = aKeyEvent.iModifiers & EModifierShift;
       
   158     TBool magnify = aKeyEvent.iModifiers & EModifierCtrl;
       
   159     if ( magnify && aKeyEvent.iCode < KChatKeyEventHotkeyLimit
       
   160          && aKeyEvent.iCode != ' ' )
       
   161         {
       
   162         TBuf<KChatResourceBufferSize> buf;
       
   163         if ( select )
       
   164             {
       
   165             iCoeEnv->ReadResourceL( buf, R_EIK_EDWIN_SHIFT_CTRL_HOTKEYS );
       
   166             }
       
   167         else
       
   168             {
       
   169             iCoeEnv->ReadResourceL( buf, R_EIK_EDWIN_CTRL_HOTKEYS );
       
   170             }
       
   171 
       
   172         const TInt ret = buf.Locate( TChar( aKeyEvent.iCode + 'a' - 1 ) );
       
   173         switch ( ret )
       
   174             {
       
   175             case EHotKeyCut:
       
   176                 {
       
   177                 CcpuCutL();
       
   178                 res = EKeyWasConsumed;
       
   179                 break;
       
   180                 }
       
   181             case EHotKeyCopy:
       
   182                 {
       
   183                 CcpuCopyL();
       
   184                 res = EKeyWasConsumed;
       
   185                 break;
       
   186                 }
       
   187             default:
       
   188                 {
       
   189                 // No need to handle other hot keys here
       
   190                 break;
       
   191                 }
       
   192             }
       
   193         }
       
   194     // --------------------
       
   195 
       
   196     if ( res != EKeyWasConsumed )
       
   197         {
       
   198         res = CEikRichTextEditor::OfferKeyEventL( aKeyEvent, aType );
       
   199         }
       
   200 
       
   201     NotifyObserverIfNeededL( oldLen, TextLength() );
       
   202 
       
   203     return res;
       
   204     }
       
   205 
       
   206 // -----------------------------------------------------------------------------
       
   207 // CCAMessageEditor::HandlePointerEventL
       
   208 // -----------------------------------------------------------------------------
       
   209 //
       
   210 void CCAMessageEditor::HandlePointerEventL(
       
   211     const TPointerEvent& aPointerEvent )
       
   212     {
       
   213     TBool eventConsumed = EFalse;
       
   214     if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
       
   215         {
       
   216         // Select smiley if user taps on it
       
   217         TRect pictRect;
       
   218         TPoint pointerPos( aPointerEvent.iPosition );
       
   219         if ( iTextView->GetPictureRectangleL( pointerPos, pictRect ) )
       
   220             {
       
   221             eventConsumed = ETrue;
       
   222             TInt pos = iTextView->XyPosToDocPosL( pointerPos );
       
   223             SetSelectionL( pos, pos + 1 );
       
   224             IgnoreEventsUntilNextPointerUp();
       
   225             }
       
   226         }
       
   227 
       
   228     // If user didn't start stylus down event on smiley,
       
   229     // forward all events to base class
       
   230     if ( !eventConsumed )
       
   231         {
       
   232         CEikRichTextEditor::HandlePointerEventL( aPointerEvent );
       
   233         }
       
   234     }
       
   235 
       
   236 // -----------------------------------------------------------------------------
       
   237 // CCAMessageEditor::CcpuCutL
       
   238 // Handle cut
       
   239 // -----------------------------------------------------------------------------
       
   240 //
       
   241 void CCAMessageEditor::CcpuCutL()
       
   242     {
       
   243     if ( Selection().Length() == 0 )
       
   244         {
       
   245         return;
       
   246         }
       
   247 
       
   248     TInt oldLen = TextLength();
       
   249 
       
   250     // Set up buffer
       
   251     ConstructAndSetUpClipboardBufferL();
       
   252 
       
   253     // Perform cut in buffer
       
   254     iClipboardBuffer->CcpuCutL();
       
   255 
       
   256     // Delete selection from UI
       
   257     TCursorSelection curSel = Selection();
       
   258     TInt delLen = curSel.Length();
       
   259     RichText()->DeleteL( curSel.LowerPos(), delLen );
       
   260     // Create selection for HandleInsertDeleteL
       
   261     TInt delStart = Min( curSel.iAnchorPos, curSel.iCursorPos );
       
   262     TCursorSelection delSel( delStart, delStart );
       
   263     TextView()->HandleInsertDeleteL( delSel, delLen );
       
   264     ClearSelectionL();
       
   265 
       
   266     // Set limit to new. Because smileys take 2-3 characters in string format
       
   267     // so we have to multiply picture count with extra character count to get
       
   268     // possible limit.
       
   269     SetTextLimit( IMUtils::MaxMsgLength() - ( RichText()->PictureCount() *
       
   270                                               KChatAddCharsPerSmiley ) );
       
   271 
       
   272     NotifyObserverIfNeededL( oldLen, TextLength() );
       
   273     }
       
   274 
       
   275 // -----------------------------------------------------------------------------
       
   276 // CCAMessageEditor::CcpuCopyL
       
   277 // Handle copy
       
   278 // -----------------------------------------------------------------------------
       
   279 //
       
   280 void CCAMessageEditor::CcpuCopyL()
       
   281     {
       
   282     // Set up buffer
       
   283     ConstructAndSetUpClipboardBufferL();
       
   284 
       
   285     // Perform copy in buffer
       
   286     iClipboardBuffer->CcpuCopyL();
       
   287     }
       
   288 
       
   289 // -----------------------------------------------------------------------------
       
   290 // CCAMessageEditor::CcpuPasteL
       
   291 // Handle paste
       
   292 // -----------------------------------------------------------------------------
       
   293 //
       
   294 void CCAMessageEditor::CcpuPasteL()
       
   295     {
       
   296     TInt oldLen = TextLength();
       
   297 
       
   298     // Take original cursorpos in memory
       
   299     TInt pos = CursorPos();
       
   300 
       
   301     // Paste
       
   302     CEikRichTextEditor::CcpuPasteL();
       
   303 
       
   304     // Select changed part so we can check it for extensions
       
   305     SetSelectionL( pos, CursorPos() );
       
   306 
       
   307     // Convert strings to extensions
       
   308     iMessageHandler.ConvertSelectionToExtensionL( *this );
       
   309 
       
   310     // Update cursor position.
       
   311     SetCursorPosL( Selection().HigherPos(), EFalse );
       
   312 
       
   313     NotifyObserverIfNeededL( oldLen, TextLength() );
       
   314     }
       
   315 
       
   316 // -----------------------------------------------------------------------------
       
   317 // CCAMessageEditor::SetupSkinContextL
       
   318 // Enable skinning
       
   319 // -----------------------------------------------------------------------------
       
   320 //
       
   321 void CCAMessageEditor::SetupSkinContextL( TBool aForceUpdate /*= EFalse*/ )
       
   322     {
       
   323     TRect screen( 0, 0, 0, 0 );
       
   324 
       
   325     AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen );
       
   326 
       
   327     // If update forced, delete previous skin contexts
       
   328     if ( aForceUpdate )
       
   329         {
       
   330         delete iBgContext;
       
   331         iBgContext = NULL;
       
   332         delete iFgContext;
       
   333         iFgContext = NULL;
       
   334         }
       
   335 
       
   336     if ( !iFgContext && !iBgContext )
       
   337         {
       
   338         iBgContext = CAknsBasicBackgroundControlContext::NewL(
       
   339                          KAknsIIDQsnBgAreaMain, screen, EFalse );
       
   340         iFgContext = CAknsBasicBackgroundControlContext::NewL(
       
   341                          KAknsIIDQsnFrInputCenter, screen, EFalse );
       
   342         iFgContext->SetParentContext( iBgContext );
       
   343         }
       
   344     else
       
   345         {
       
   346         iFgContext->SetRect( screen );
       
   347         }
       
   348 
       
   349     SetSkinBackgroundControlContextL( iFgContext );
       
   350     }
       
   351 
       
   352 TTypeUid::Ptr CCAMessageEditor::MopSupplyObject( TTypeUid aId )
       
   353     {
       
   354     if ( aId.iUid == MAknsControlContext::ETypeId )
       
   355         {
       
   356         return MAknsControlContext::SupplyMopObject( aId, iFgContext );
       
   357         }
       
   358     return CEikRichTextEditor::MopSupplyObject( aId );
       
   359     }
       
   360 
       
   361 // -----------------------------------------------------------------------------
       
   362 // CCAMessageEditor::RefreshEditorL
       
   363 // Called to force refresh of editor contents after inserting a smiley
       
   364 // -----------------------------------------------------------------------------
       
   365 //
       
   366 void CCAMessageEditor::RefreshEditorL()
       
   367     {
       
   368     iTextView->HandleCharEditL( CTextLayout::EFCharacterInsert );
       
   369     }
       
   370 
       
   371 // -----------------------------------------------------------------------------
       
   372 // CCAMessageEditor::SetTapObserver
       
   373 // (other items were commented in a header).
       
   374 // -----------------------------------------------------------------------------
       
   375 //
       
   376 void CCAMessageEditor::SetTapObserver( MCATapEventObserver* aObserver, TUint aId )
       
   377     {
       
   378     iTapObserver = aObserver;
       
   379     iTapControlId = aId;
       
   380     }
       
   381 
       
   382 // -----------------------------------------------------------------------------
       
   383 // CCAMessageEditor::SetMessageEditorObserver
       
   384 // Called to force refresh of editor contents after inserting a smiley
       
   385 // -----------------------------------------------------------------------------
       
   386 //
       
   387 void CCAMessageEditor::SetMessageEditorObserver( MCAMessageEditorObserver* aObserver )
       
   388     {
       
   389     iEditorObserver = aObserver;
       
   390     }
       
   391 
       
   392 // -----------------------------------------------------------------------------
       
   393 // CCAMessageEditor::NotifyObserverIfNeededL
       
   394 // Called to force refresh of editor contents after inserting a smiley
       
   395 // -----------------------------------------------------------------------------
       
   396 //
       
   397 void CCAMessageEditor::NotifyObserverIfNeededL( TInt aOldLen, TInt aCurLen )
       
   398     {
       
   399     if ( iEditorObserver )
       
   400         {
       
   401         if ( !iEditIndicatorActiveObj )
       
   402             {
       
   403             TInt editorFlags = 0;
       
   404 
       
   405             if ( !aCurLen )
       
   406                 {
       
   407                 //dont show the edit indicator if editor is empty
       
   408                 editorFlags = ( AknEdwinFlags() | EAknEditorFlagNoEditIndicators );
       
   409                 }
       
   410             else
       
   411                 {
       
   412                 //show the edit indicator if editor is non-empty
       
   413                 TInt editorFlags = ( AknEdwinFlags() & ~EAknEditorFlagNoEditIndicators );
       
   414                 }
       
   415 
       
   416             SetAknEditorFlags( editorFlags );
       
   417             }
       
   418         if ( aCurLen == 0 && aOldLen > 0 )
       
   419             {
       
   420             iEditorObserver->HandleMessageEditorEventL(
       
   421                 MCAMessageEditorObserver::EEditorContentCleared );
       
   422             return;
       
   423             }
       
   424         if ( aOldLen == 0 && aCurLen > 0 )
       
   425             {
       
   426             iEditorObserver->HandleMessageEditorEventL(
       
   427                 MCAMessageEditorObserver::EEditorFirstContentAdded );
       
   428             return;
       
   429             }
       
   430         }
       
   431     }
       
   432 
       
   433 // -----------------------------------------------------------------------------
       
   434 // CCAMessageEditor::EditObserver
       
   435 // Ignored to prevent odd scrolling
       
   436 // -----------------------------------------------------------------------------
       
   437 //
       
   438 void CCAMessageEditor::EditObserver( TInt /* aStartEdit */, TInt /* aEditLength */ )
       
   439     {
       
   440     // ignored to prevent odd scrolling
       
   441     }
       
   442 
       
   443 // -----------------------------------------------------------------------------
       
   444 // CCAMessageEditor::ConstructAndSetUpClipboardBufferL
       
   445 // Construct if needed and set up clipboard buffer
       
   446 // -----------------------------------------------------------------------------
       
   447 //
       
   448 void CCAMessageEditor::ConstructAndSetUpClipboardBufferL()
       
   449     {
       
   450     if ( !iClipboardBuffer )
       
   451         {
       
   452         // Not yet created, instantiate now
       
   453         iClipboardBuffer = new( ELeave ) CEikEdwin();
       
   454         iClipboardBuffer->ConstructL( AknEdwinFlags() | CEikEdwin::EOwnsWindow,
       
   455                                       1,
       
   456                                       IMUtils::MaxMsgLength(),
       
   457                                       1 );
       
   458         iClipboardBuffer->SetContainerWindowL( *Parent() );
       
   459         //iClipboardBuffer->ActivateL();
       
   460         iClipboardBuffer->CreateTextViewL();
       
   461         iClipboardBuffer->MakeVisible( EFalse );
       
   462         }
       
   463     else
       
   464         {
       
   465         // Clear buffer
       
   466         TInt textLen = iClipboardBuffer->TextLength();
       
   467         iClipboardBuffer->Text()->DeleteL( 0, textLen );
       
   468         TCursorSelection delSel( 0, 0 );
       
   469         iClipboardBuffer->TextView()->HandleInsertDeleteL( delSel, textLen );
       
   470         }
       
   471 
       
   472     // Get converted text
       
   473     TCursorSelection copySel;
       
   474     HBufC* plainText = HBufC::NewLC( IMUtils::MaxMsgLength() );
       
   475     TPtr ptr( plainText->Des() );
       
   476     iMessageHandler.ConvertSelectionToStringL( *this, ptr, copySel, EFalse );
       
   477 
       
   478     // Insert only selected text to buffer
       
   479     HBufC* copiedText =
       
   480         plainText->Mid( copySel.LowerPos(), copySel.Length() ).AllocLC();
       
   481     iClipboardBuffer->SetTextL( copiedText );
       
   482     CleanupStack::PopAndDestroy( 2, plainText );
       
   483     // Select whole buffer
       
   484     iClipboardBuffer->SelectAllL();
       
   485     }
       
   486 
       
   487 
       
   488 // -----------------------------------------------------------------------------
       
   489 // CCAMessageEditor::ShowIndicator
       
   490 // Construct if needed and set up clipboard buffer
       
   491 // -----------------------------------------------------------------------------
       
   492 //
       
   493 void CCAMessageEditor::ShowIndicator()
       
   494     {
       
   495     TInt editorFlags = ( AknEdwinFlags() & ~EAknEditorFlagNoEditIndicators );
       
   496     SetAknEditorFlags( editorFlags );
       
   497     }
       
   498 
       
   499 
       
   500 
       
   501 // -----------------------------------------------------------------------------
       
   502 // CCAMessageEditor::HideIndicator
       
   503 // Construct if needed and set up clipboard buffer
       
   504 // -----------------------------------------------------------------------------
       
   505 //
       
   506 void CCAMessageEditor::HideIndicator()
       
   507     {
       
   508     if ( !TextLength() )
       
   509         {
       
   510         TInt editorFlags = ( AknEdwinFlags() | EAknEditorFlagNoEditIndicators );
       
   511         SetAknEditorFlags( editorFlags );
       
   512         }
       
   513     }
       
   514 
       
   515 
       
   516 // -----------------------------------------------------------------------------
       
   517 // CCAMessageEditor::SetActiveObject
       
   518 // Construct if needed and set up clipboard buffer
       
   519 // -----------------------------------------------------------------------------
       
   520 //
       
   521 
       
   522 void CCAMessageEditor::SetActiveObject( CCAEditIndicator* aActiveObject )
       
   523     {
       
   524     iEditIndicatorActiveObj = 	aActiveObject;
       
   525     }
       
   526 
       
   527 
       
   528 // -----------------------------------------------------------------------------
       
   529 // CCAMessageEditor::ReSetActiveObject
       
   530 // Construct if needed and set up clipboard buffer
       
   531 // -----------------------------------------------------------------------------
       
   532 //
       
   533 void CCAMessageEditor::ReSetActiveObject()
       
   534     {
       
   535     iEditIndicatorActiveObj = NULL;
       
   536     }
       
   537 
       
   538 //  End of File