messagingappbase/msgeditor/viewsrc/MsgAttachmentControl.cpp
changeset 0 72b543305e3a
child 66 fc3320e39880
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/msgeditor/viewsrc/MsgAttachmentControl.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1170 @@
+/*
+* Copyright (c) 2002 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:  MsgAttachmentControl implementation
+*
+*/
+
+
+
+// ========== INCLUDE FILES ================================
+
+#include <barsread.h>                      // for TResourceReader
+#include <txtrich.h>                       // for CRichText
+
+#include <eikenv.h>                        // for CEikonEnv
+#include <eikappui.h>                      // for CEikAppUi
+#include <eikedwin.h>                      // for TClipboardFunc
+#include <eiklabel.h>
+
+#include <AknUtils.h>                      // for AknUtils
+#include <aknbutton.h>                     // for CAknButton
+
+#include <MsgAttachmentModel.h>
+#include <MsgAttachmentInfo.h>
+
+#include <gulicon.h>
+#include <AknsUtils.h>
+#include <AknsConstants.h>
+#include <aknlayoutscalable_apps.cdl.h>
+
+#include <data_caging_path_literals.hrh>
+#include <msgeditor.mbg>
+
+#ifdef RD_TACTILE_FEEDBACK
+#include <touchfeedback.h>
+#endif 
+
+#include "MsgAttachmentControl.h"             // for CMsgAttachmentControl
+#include "MsgExpandableControlEditor.h"       // for CMsgExpandableControlEditor
+#include "MsgBaseControlObserver.h"        // for MMsgBaseControlObserver
+#include "MsgEditorView.h"
+#include "MsgEditorPanic.h"                // for CMsgEditor panics
+#include "MsgEditorCommon.h"               // for KArabicSemicolon
+#include "MsgEditorCustomDraw.h"           // for CMsgEditorCustomDraw
+
+// ========== EXTERNAL DATA STRUCTURES =====================
+
+// ========== EXTERNAL FUNCTION PROTOTYPES =================
+
+// ========== CONSTANTS ====================================
+
+// Default color for EAknsCIQsnIconColorsCG13 group icons
+const TInt KDefaultAttachmentColor = 215; 
+
+// ========== MACROS =======================================
+
+// ========== LOCAL CONSTANTS AND MACROS ===================
+
+const TInt KAttachmentArrayGranularity = 10;
+
+_LIT( KAttachmentListSeparator, ", " );
+_LIT( KIconMbmFile, "msgeditor.mbm" );
+_LIT( KStripList, "\x000A\x000D\x2029\x2028\x0085" );
+
+const TText KZeroWidthJoiner = 0x200D;
+const TText KLRMarker = 0x200E;
+const TText KRLMarker = 0x200F;
+
+const TInt KScrollStartDelay = 1500000; // 1,5 s
+const TInt KScrollEndDelay = 500000;    // 0,5 s
+const TInt KScrollRestartDelay = 3000000; // 3 s.
+const TInt KScrollTickDelay = 135000; // 0,135s
+const TInt KScrollJumpAreaDivider = 15;
+
+// ========== MODULE DATA STRUCTURES =======================
+
+// ========== LOCAL FUNCTION PROTOTYPES ====================
+
+// ========== LOCAL FUNCTIONS ==============================
+
+// ========== MEMBER FUNCTIONS =============================
+
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::CMsgAttachmentControl
+//
+// Constructor.
+// ---------------------------------------------------------
+//
+CMsgAttachmentControl::CMsgAttachmentControl( 
+                                    MMsgBaseControlObserver& aBaseControlObserver,
+                                    CMsgEditorView& aView ) : 
+    CMsgExpandableControl( aBaseControlObserver ),
+    iScrollPos( EScrollPosBeginning )
+    {
+    iControlType = EMsgAttachmentControl;
+    iControlId = EMsgComponentIdAttachment;
+    
+    SetMopParent( &aView );
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::ConstructL
+//
+// 2nd phase constructor. After base class initialization creates
+// attachment array that holds the attachment name strings. Empty
+// caption control is also created for base class purposes. NOTE! This is 
+// something that would be good to get rid off. Initializes editor control
+// and sets itself as it's edwin event, edwin size event and
+// control event observer. Creates editor is set as readonly and cursor is
+// hidden. Focus must stop to this control when navigating. No formatting
+// is allowed. Label icon and if pen input (i.e. touch screen) is enabled
+// then also button are created. Initializes marquee scroll timer and
+// layout related parameters.
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::ConstructL()
+    {
+    BaseConstructL();  // Sets margins only.
+    
+    iAttachmentArray = new( ELeave ) CDesCArrayFlat( KAttachmentArrayGranularity );
+
+    // Create empty caption. (Needed by base class.)
+    iCaption = new( ELeave ) CEikLabel;
+
+    // Create editor.
+    iEditor = new( ELeave ) CMsgExpandableControlEditor( this, 
+                                                         iControlModeFlags, 
+                                                         iBaseControlObserver );
+    iEditor->SetControlType(iControlType);   
+    iEditor->ConstructL();
+    iEditor->SetObserver( this );
+    iEditor->SetEdwinSizeObserver( this );
+    iEditor->AddEdwinObserverL( this );
+    iEditor->SetReadOnly( ETrue );
+    iEditor->AddFlagToUserFlags( CEikEdwin::EAvkonDisableCursor );
+    
+    iControlModeFlags |= EMsgControlModeForceFocusStop;
+    
+    SetPlainTextMode( ETrue );
+    
+    iLabelIcon = CreateAttachmentIconsL();
+    
+#ifdef RD_SCALABLE_UI_V2
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        CreateButtonL();
+        }
+#endif // RD_SCALABLE_UI_V2
+    
+    iScrollTimer = CPeriodic::NewL( EPriorityNormal );
+    
+    ResolveLayoutsL();
+    }
+
+// ----------------------------------------------------------------------------
+// CMsgAttachmentControl::NewL
+// Symbian two phased constructor
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMsgAttachmentControl* CMsgAttachmentControl::NewL( 
+                                                MMsgBaseControlObserver& aBaseControlObserver,
+                                                CMsgEditorView& aView )
+    {
+    CMsgAttachmentControl* self = new( ELeave ) CMsgAttachmentControl( aBaseControlObserver,
+                                                                       aView );
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::~CMsgAttachmentControl
+//
+// Destructor.
+// ---------------------------------------------------------
+//
+CMsgAttachmentControl::~CMsgAttachmentControl()
+    {
+    if ( iAttachmentArray )
+        {
+        iAttachmentArray->Reset();
+        }
+        
+    delete iAttachmentArray;
+    delete iLabelIcon;
+    delete iScrollTimer;
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::AppendAttachmentL
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgAttachmentControl::AppendAttachmentL( const TDesC& aName )
+    {
+    InsertAttachmentL( aName, Count() );
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::InsertAttachmentL
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgAttachmentControl::InsertAttachmentL( const TDesC& aName, TInt aIndex )
+    {
+    AddToAttachmentArrayL( aName, aIndex );
+    
+    UpdateControlL();
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::AddAttachmentL
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgAttachmentControl::AddAttachmentsL( const MDesCArray& aNames )
+    {
+    Reset();
+    
+    for ( TInt i = 0; i < aNames.MdcaCount(); i++ )
+        {
+        AddToAttachmentArrayL( aNames.MdcaPoint( i ), Count() );
+        }
+        
+    UpdateControlL();
+    }
+
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::AddAttachmentL
+//
+//
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgAttachmentControl::AddAttachmentsL( const CMsgAttachmentModel& aModel )
+    {
+    Reset();
+    
+    TParse* parser = new( ELeave ) TParse ;
+    CleanupStack::PushL( parser );
+    
+    for ( TInt i = 0; i < aModel.NumberOfItems(); i++ )
+        {
+        parser->Set( aModel.AttachmentInfoAt( i ).FileName(),NULL, NULL );
+        AddToAttachmentArrayL( parser->NameAndExt(), Count() );
+        }
+    
+    CleanupStack::PopAndDestroy( parser ); 
+    UpdateControlL();
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::RemoveAttachmentL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgAttachmentControl::RemoveAttachmentL( const TDesC& aName )
+    {
+    HBufC* convertedFileName = AknTextUtils::ConvertFileNameL( aName );
+    CleanupStack::PushL( convertedFileName );
+    
+    TPtr convertedFileNamePtr = convertedFileName->Des();
+    
+    AknTextUtils::StripCharacters( convertedFileNamePtr, KAknStripListControlChars );
+    
+    TInt pos( KErrNotFound );
+    if ( iAttachmentArray->Find( *convertedFileName, pos ) == 0 )
+        {
+        RemoveAttachmentL( pos );
+        }
+    
+    CleanupStack::PopAndDestroy( convertedFileName );
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::RemoveAttachmentL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgAttachmentControl::RemoveAttachmentL( TInt aIndex )
+    {
+    iAttachmentArray->Delete( aIndex );
+    UpdateControlL();
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::Reset
+//
+// from CMsgBaseControl.
+// Same as above but non-leaving version.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgAttachmentControl::Reset()
+    {
+    if ( iAttachmentArray )
+        {
+        iAttachmentArray->Reset();
+        }
+    if ( iEditor )
+        {
+        iEditor->Reset();
+        }
+    }
+
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::Count
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMsgAttachmentControl::Count() const
+    {
+    return iAttachmentArray->MdcaCount();
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::Attachment
+// ---------------------------------------------------------
+//
+EXPORT_C TPtrC CMsgAttachmentControl::Attachment( TInt aIndex ) const
+    {
+    return iAttachmentArray->MdcaPoint( aIndex );
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::ConstructFromResourceL
+//
+// Creates this control from resource.
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::ConstructFromResourceL( TInt aResourceId )
+    {
+    TResourceReader reader;
+    iCoeEnv->CreateResourceReaderLC( reader, aResourceId );
+
+    // Read some information about control from resource.
+    ReadControlPropertiesFromResourceL( reader );
+    
+    ConstructL();
+    
+    CleanupStack::PopAndDestroy();  // reader
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::EditPermission
+//
+// Checks and returns control's edit permissions. Edit permissions are needed
+// to check in order to know whether some key press is allowed to pass
+// to the control or not.
+// ---------------------------------------------------------
+//
+TUint32 CMsgAttachmentControl::EditPermission() const
+    {
+    return CMsgBaseControl::EMsgEditNone;
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::NotifyViewEvent
+//
+// Builds up text fields for the control i.e. reads verified recipients and
+// creates corresponding text fields for them.
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::NotifyViewEvent( TMsgViewEvent aEvent, TInt aParam )
+    {
+    if ( IsReadOnly() )
+        {
+        aParam |= EMsgViewEventAutoHighlight;
+        }
+
+    if ( aEvent != EMsgViewEventSetCursorFirstPos &&
+         aEvent != EMsgViewEventSetCursorLastPos )
+        {
+        CMsgExpandableControl::NotifyViewEvent( aEvent, aParam );
+        }
+    }
+
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::PrepareForReadOnly
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::PrepareForReadOnly( TBool aReadOnly )
+    {
+    if ( aReadOnly )
+        {
+        TRAP_IGNORE( iEditor->SetHighlightStyleL( EEikEdwinHighlightLink ) );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::CountComponentControls
+//
+// Returns a number of controls.
+// ---------------------------------------------------------
+//
+TInt CMsgAttachmentControl::CountComponentControls() const
+    {
+    TInt result( 1 );
+    
+    if ( iButton )
+        {
+        result++;
+        }
+        
+    return result;
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::ComponentControl
+//
+// Returns a control of index aIndex.
+// ---------------------------------------------------------
+//
+CCoeControl* CMsgAttachmentControl::ComponentControl( TInt aIndex ) const
+    {
+    CCoeControl* result = NULL;
+    switch ( aIndex )
+        {
+        case 0:
+            {
+            result = iEditor;
+            break;
+            }
+        case 1:
+            {
+            result = iButton;
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+        
+    return result;
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::OfferKeyEventL
+//
+// Handles key events. The most of the keys are passed to the control editor.
+// ---------------------------------------------------------
+//
+TKeyResponse CMsgAttachmentControl::OfferKeyEventL(
+    const TKeyEvent& /*aKeyEvent*/, TEventCode /*aType*/ )
+    {
+    return EKeyWasNotConsumed;
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::HandleResourceChange
+//
+// Handles resouce change events. Event are passed to the base
+// class and if layout has been switched new layouts are resolved
+// from LAF.
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::HandleResourceChange( TInt aType )
+    {
+    TRAP_IGNORE( 
+        {
+        DoHandleResourceChangeBeforeL( aType );
+    
+        CMsgExpandableControl::HandleResourceChange( aType );
+        
+        DoHandleResourceChangeAfterL( aType );
+        } );    
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::HandlePointerEventL
+//
+// Pointer event handling is disabled on editor
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::HandlePointerEventL( const TPointerEvent& aPointerEvent )
+    {
+    if ( !iEditor->Rect().Contains( aPointerEvent.iPosition ) )
+        {
+        CMsgExpandableControl::HandlePointerEventL( aPointerEvent );
+        }
+#ifdef RD_TACTILE_FEEDBACK 
+    else if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
+        {
+        MTouchFeedback* feedback = MTouchFeedback::Instance();
+        if ( feedback )
+            {
+            feedback->InstantFeedback( this, ETouchFeedbackBasic );                        
+            }                                     
+        }
+#endif
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::FocusChanged
+//
+// This is called when the focus of the control is changed.
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::FocusChanged( TDrawNow aDrawNow )
+    {
+    CMsgExpandableControl::FocusChanged( aDrawNow );
+        
+    if ( IsReadOnly() )
+        {
+        TRAP_IGNORE( UpdateFocusL() );
+        }
+    
+    if ( iAutomaticScrolling )
+        {
+        StopAutomaticScrolling();
+        
+        if ( IsFocused() )
+            {
+            StartAutomaticScrolling( KScrollStartDelay );
+            }
+        else
+            {
+            // Reset text to the beginning when focus is lost.
+            iScrollPos = EScrollPosBeginning;
+            TRAP_IGNORE( SetTextForEditorL( EFalse, ETrue ) );                
+            
+            // Reset the text view to it's original position.
+            iEditor->TextView()->SetLeftTextMargin( 0 );
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::Draw
+// Attachment icon is drawn to the line indicated by LAF x 
+// coordinate and controls current y coordinate. 
+// Attachment icon is also centered vertically to current 
+// control height.
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::Draw( const TRect& /*aRect*/ ) const
+    {
+    if ( !iButton )
+        {
+        TPoint tlc( iIconLayout.Rect().iTl.iX, Position().iY );
+        tlc.iY += ( Size().iHeight - iIconLayout.Rect().Size().iHeight ) / 2;
+    
+        SystemGc().BitBltMasked( tlc,
+                                 iLabelIcon->Bitmap(), 
+                                 iIconLayout.Rect().Size(),
+                                 iLabelIcon->Mask(),
+                                 EFalse );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::ActivateL
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::ActivateL()
+    {
+    CMsgExpandableControl::ActivateL();
+    
+    // Needs to be called after CEikEdwin::ActivateL as
+    // panics if CEikEdwin::iTextView is not present
+    iEditor->SetWordWrapL( EFalse );
+    
+    // Cursor is set to the beginning of text.
+    iEditor->SetCursorPosL( 0, EFalse );
+    
+    if ( iEditor->TextView() )
+        {
+        const CFont* font = iEditorLayout.Font();
+        TInt scrollJump( font->WidthZeroInPixels() );
+        if ( scrollJump == 0 )
+            {
+            // Font gave us invalid scrollJump have to make
+            // estimate according to scroll area.
+            scrollJump = iEditorLayout.TextRect().Width() / KScrollJumpAreaDivider;
+            }
+        iEditor->TextView()->SetHorizontalScrollJump( scrollJump );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::UpdateControlL
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::UpdateControlL()
+    {
+    SetTextForEditorL( ETrue, ETrue );
+    
+    if ( iScrollTimer->IsActive() )
+        {
+        // Restart scrolling when attachment list is modified.
+        iScrollPos = EScrollPosBeginning;
+        StartAutomaticScrolling( KScrollStartDelay );        
+        }
+    
+    DrawDeferred();
+    iControlModeFlags |= EMsgControlModeModified;
+    }
+
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::SetTextForEditorL
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::SetTextForEditorL( TBool aContentChanged, TBool aClipText )
+    {
+    TInt count = iAttachmentArray->Count();
+    TInt length = 0;
+    
+    for ( TInt i = 0; i < count; i++ )
+        {
+        length += iAttachmentArray->MdcaPoint( i ).Length();
+        length += KAttachmentListSeparator().Length();
+        }
+
+    HBufC* buf = HBufC::NewLC( length );
+    TPtr temp = buf->Des();
+    
+    for ( TInt j = 0; j < count; j++ )
+        {
+        temp.Append( iAttachmentArray->MdcaPoint( j ) );
+        if ( j < count - 1 )
+            {
+            temp.Append( KAttachmentListSeparator );
+            }
+        }
+        
+    const CFont* font = iEditorLayout.Font();
+
+    TInt clipWidth = 0;
+    
+    if ( iEditor->TextView() ) 
+        {
+        clipWidth = iEditor->TextView()->ViewRect().Width();
+        }
+    else
+        {
+        clipWidth = iEditorLayout.TextRect().Width();
+        }
+    
+    TBool enableAutomaticScrolling( ETrue );
+    if ( temp.Length() == 0 )
+        {
+        // Disable all processing if field is empty.
+        enableAutomaticScrolling = EFalse;
+        aContentChanged = EFalse;
+        }
+        
+    if ( aContentChanged )
+        {
+        // Attachment array has been updated.
+        TInt fits = font->TextCount( temp, clipWidth );
+
+        if ( fits >= temp.Length() )
+            {
+            // All text fits to the field. No automatic scrolling.
+            enableAutomaticScrolling = EFalse;
+            }
+        }
+    
+    if ( enableAutomaticScrolling )
+        {
+        EnableAutomaticScrolling();
+        
+        if ( aClipText )
+            {
+            ClipTextL( temp, clipWidth );
+            }
+        }
+    else
+        {
+        DisableAutomaticScrolling();
+        }
+    
+    // Replaces old text with new text.
+    iEditor->SetTextL( buf );
+
+    if ( IsActivated() && iEditor->CursorPos() != 0 )
+        {
+        // Cursor is set to the beginning of text.
+        // Should not be called for non-activated control.
+        iEditor->SetCursorPosL( 0, EFalse );
+        }        
+    
+    CleanupStack::PopAndDestroy( buf );
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::ResolveLayoutsL
+// 
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::ResolveLayoutsL()
+    {
+    TAknLayoutRect msgTextPane;
+    msgTextPane.LayoutRect( MsgEditorCommons::MsgDataPane(),
+                            AknLayoutScalable_Apps::msg_text_pane( 0 ).LayoutLine() );
+
+    TAknLayoutRect msgHeaderPane;
+    msgHeaderPane.LayoutRect( msgTextPane.Rect(),
+                              AknLayoutScalable_Apps::msg_header_pane().LayoutLine() );
+    
+    iIconLayout.LayoutRect( msgHeaderPane.Rect(),
+                            AknLayoutScalable_Apps::msg_header_pane_g1().LayoutLine() );
+    
+    CMsgExpandableControl::ResolveLayoutsL();
+        
+    if ( iButton )
+        {
+        iButton->SetSize( iButton->Size() );
+        }
+    else
+        {
+        User::LeaveIfError( AknIconUtils::SetSize( iLabelIcon->Bitmap(), 
+                                                   iIconLayout.Rect().Size() ) );
+        }
+     if ( iEditor->MsgEditorCustomDraw() )
+        {
+            iEditor->MsgEditorCustomDraw()->ResolveLayouts();
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::CreateAttachmentIconsL
+// ---------------------------------------------------------
+//
+CGulIcon* CMsgAttachmentControl::CreateAttachmentIconsL()
+    {
+    TParse fileParse;
+    fileParse.Set( KIconMbmFile, &KDC_APP_BITMAP_DIR, NULL );
+    
+    CFbsBitmap* bitmap = NULL;
+    CFbsBitmap* mask = NULL;
+    
+    AknsUtils::CreateColorIconLC( AknsUtils::SkinInstance(),
+                                  KAknsIIDQgnIndiMceAttach,
+                                  KAknsIIDQsnIconColors,
+                                  EAknsCIQsnIconColorsCG13,
+                                  bitmap, 
+                                  mask,
+                                  fileParse.FullName(), 
+                                  EMbmMsgeditorQgn_indi_mce_attach,
+                                  EMbmMsgeditorQgn_indi_mce_attach_mask,
+                                  AKN_LAF_COLOR( KDefaultAttachmentColor ) ); 
+    
+    CGulIcon* result = CGulIcon::NewL( bitmap, mask ); // Ownership transferred
+    CleanupStack::Pop( 2 ); // bitmap, mask
+    
+    return result;
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::CreateButtonL
+// ---------------------------------------------------------
+//
+#ifdef RD_SCALABLE_UI_V2
+void CMsgAttachmentControl::CreateButtonL()
+    {
+    delete iButton;
+    iButton = NULL;
+    
+    CGulIcon* buttonIcon = CGulIcon::NewL( iLabelIcon->Bitmap(), iLabelIcon->Mask() );
+    buttonIcon->SetBitmapsOwnedExternally( ETrue ); // bitmaps owned by iLabelIcon
+    
+    CleanupStack::PushL( buttonIcon );
+    
+    iButton = CAknButton::NewL( buttonIcon,
+                                NULL,
+                                NULL,
+                                NULL,
+                                KNullDesC,
+                                KNullDesC,
+                                KAknButtonSizeFitText,
+                                0 );
+        
+    CleanupStack::Pop( buttonIcon ); // buttonIcon owned by iButton
+    
+    iButton->SetIconScaleMode( EAspectRatioPreserved );
+    
+    iButton->SetObserver( this );
+    
+    if ( DrawableWindow() )
+        {
+        iButton->SetContainerWindowL( Window() );
+        iButton->ActivateL();
+        }
+    }
+#else
+void CMsgAttachmentControl::CreateButtonL()
+    {
+    }
+#endif // RD_SCALABLE_UI_V2
+
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::DoScrollTextL
+// ---------------------------------------------------------
+//
+TInt CMsgAttachmentControl::DoScrollTextL( TAny* aObject )
+    {
+    // cast, and call non-static function
+    CMsgAttachmentControl* control = static_cast<CMsgAttachmentControl*>( aObject );
+    TRAPD( error ,control->ScrollTextL() );
+    if ( error != KErrNone )
+        {
+        control->StopAutomaticScrolling();
+        User::Leave( error );
+        }
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::ScrollTextL
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::ScrollTextL()
+    {
+    TBool scrollText( ETrue );
+    if ( iScrollPos == EScrollPosBeginning )
+        {
+        SetTextForEditorL( EFalse, EFalse );
+        }
+    else if ( iScrollPos == EScrollPosEnd )
+        {
+        // Indicates that text has been scrolled to the end and should be restarted.
+        SetTextForEditorL( EFalse, ETrue );
+        iScrollPos = EScrollPosBeginning;
+        scrollText = EFalse;
+        
+        // Reset the text view to it's original position.
+        iEditor->TextView()->SetLeftTextMargin( 0 );
+        DrawNow();
+        
+        StartAutomaticScrolling( KScrollRestartDelay );
+        }
+    
+    if ( scrollText )
+        {
+        TInt scrolledPixels = iEditor->TextView()->ScrollDisplayL( TCursorPosition::EFRight );
+        if ( scrolledPixels == 0 )
+            {
+            // Indicates that text has been scrolled to the end. 
+            iScrollPos = EScrollPosEnd;
+            StartAutomaticScrolling( KScrollEndDelay ); 
+            }
+        else
+            {
+            iScrollPos = EScrollPosOther;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::DisableAutomaticScrolling
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::DisableAutomaticScrolling()
+    {
+    iAutomaticScrolling = EFalse;    
+    StopAutomaticScrolling();
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::EnableAutomaticScrolling
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::EnableAutomaticScrolling()
+    {
+    iAutomaticScrolling = ETrue;
+    
+    if ( !iScrollTimer->IsActive() && 
+         IsFocused() )
+        {
+        StartAutomaticScrolling( KScrollStartDelay );
+        }
+    }
+
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::StartAutomaticScrolling
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::StartAutomaticScrolling( TInt aStartDelay )
+    {
+    StopAutomaticScrolling();
+    iScrollTimer->Start( aStartDelay,
+                         KScrollTickDelay,
+                         TCallBack( DoScrollTextL, this ) );
+    }
+        
+// ---------------------------------------------------------
+// CMsgAttachmentControl::StopAutomaticScrolling
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::StopAutomaticScrolling()
+    {
+    iScrollTimer->Cancel();
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::ClipTextL
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::ClipTextL( TPtr aText, TInt aClipWidth )
+    {
+    const CFont* font = iEditorLayout.Font();
+    
+    TInt fits = font->TextCount( aText, aClipWidth );
+        
+    if ( fits < aText.Length() )
+        {
+        // Clipping is actually done only if text is at the beginning.
+        TInt ellipsisWidth = font->CharWidthInPixels( KEllipsis );
+
+        fits = font->TextCount( aText, aClipWidth - ellipsisWidth );
+        
+        // Work out the text directionality before the truncation point.
+        // First put the text in reverse order and then call
+        // TBidiText::TextDirectionality. This effectively tells the
+        // directionality of the last strongly directional character
+        // in the text.
+        HBufC* temp = aText.Left( fits ).AllocL();
+        TPtr tempPtr = temp->Des();
+
+        TInt i = 0;
+        TInt j = tempPtr.Length() - 1;
+        while ( i < j )
+            {
+            TText t = tempPtr[i];
+            tempPtr[i++] = tempPtr[j];
+            tempPtr[j--] = t;
+            }
+        
+        TBidiText::TDirectionality dir = TBidiText::TextDirectionality( tempPtr );
+
+        delete temp;
+
+        TText dirMarker = ( dir == TBidiText::ERightToLeft ) ? KRLMarker : 
+                                                               KLRMarker;
+        
+        // Insert zero width joiner if necessary to get the correct glyph form
+        // before truncation.
+        TText lastChar = aText[fits - 1];
+        TText next = aText[fits];
+        
+        TInt ellipsisPos = fits;
+        
+        if ( CFont::CharactersJoin( lastChar, KZeroWidthJoiner ) &&
+             CFont::CharactersJoin( lastChar, next ) )
+            {
+            aText[fits] = KZeroWidthJoiner;
+            ellipsisPos++;
+            }
+            
+        aText.SetMax();
+        
+        aText[ellipsisPos] = KEllipsis;    
+
+        // Inserting direction marker after the ellipsis ensures that
+        // the ellipsis is shown on the correct side of the text
+        // before it.
+        aText[ellipsisPos + 1] = dirMarker;
+
+        aText.SetLength( ellipsisPos + 2 );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::UpdateFocusL
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::UpdateFocusL()
+    {
+    TCharFormat charFormat;
+    TCharFormatMask applyMask;
+
+    iEditor->RichText()->GetCharFormat( charFormat,
+                                        applyMask,
+                                        0,
+                                        iEditor->TextLength() );
+            
+    if ( !IsFocused() )
+        {
+        TRgb textColor( KRgbBlack );
+        AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), 
+                                   textColor, 
+                                   KAknsIIDQsnTextColors, 
+                                   EAknsCIQsnTextColorsCG6 );
+                                   
+        charFormat.iFontPresentation.iTextColor = textColor;
+        applyMask.SetAttrib( EAttColor );               
+        
+        charFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightNone;
+        applyMask.SetAttrib( EAttFontHighlightStyle );
+        }
+    else
+        {
+        TRgb textColor( KRgbWhite );
+        AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), 
+                                   textColor, 
+                                   KAknsIIDQsnHighlightColors, 
+                                   EAknsCIQsnTextColorsCG3 );
+                                   
+        charFormat.iFontPresentation.iTextColor = textColor;
+        applyMask.SetAttrib( EAttColor );               
+           
+        TRgb highlightColor( KRgbBlue );
+        AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), 
+                                   highlightColor, 
+                                   KAknsIIDQsnHighlightColors, 
+                                   EAknsCIQsnHighlightColorsCG1 );
+                                   
+        charFormat.iFontPresentation.iHighlightColor = highlightColor;
+        applyMask.SetAttrib( EAttFontHighlightColor );
+
+        charFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightNormal;
+        applyMask.SetAttrib( EAttFontHighlightStyle );
+        }
+    
+    iEditor->RichText()->ApplyCharFormatL( charFormat,
+                                           applyMask,
+                                           0,
+                                           iEditor->TextLength() );    
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::DoHandleResourceChangeBeforeL
+//
+// Contains functionality that base class handle resource change 
+// is depending on to be completed before it can be executed properly.
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::DoHandleResourceChangeBeforeL( TInt aType )
+    {
+    switch( aType )
+        {
+        case KEikDynamicLayoutVariantSwitch:
+            {
+#ifdef RD_SCALABLE_UI_V2
+            if ( AknLayoutUtils::PenEnabled() )
+                {
+                if ( !iButton )
+                    {
+                    CreateButtonL();
+                    }
+                }
+            else
+                {
+                delete iButton;
+                iButton = NULL;
+                }
+#endif // RD_SCALABLE_UI_V2
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::DoHandleResourceChangeAfterL
+//
+// Contains functionality that is dependant of base class handle
+// resource change to complete before these can be executed properly.
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::DoHandleResourceChangeAfterL( TInt aType )
+    {
+    switch( aType )
+        {
+        case KEikDynamicLayoutVariantSwitch:
+            {
+            StopAutomaticScrolling();
+            iScrollPos = EScrollPosBeginning;
+            SetTextForEditorL( EFalse, ETrue );  
+            
+            break;
+            }
+        case KAknsMessageSkinChange:
+            {
+            CGulIcon* icon = CreateAttachmentIconsL();
+            CleanupStack::PushL( icon );
+            
+            if ( iButton )
+                {
+                CGulIcon* buttonIcon = CGulIcon::NewL( icon->Bitmap(), icon->Mask() );
+                buttonIcon->SetBitmapsOwnedExternally( ETrue ); // bitmaps owned by iLabelIcon
+    
+                iButton->State()->SetIcon( buttonIcon ); // buttonIcon ownership transferred
+                }
+            
+            // Make the change here as button will take the old size from
+            // old icons that must be still valid when setting to button icon.
+            delete iLabelIcon;
+            iLabelIcon = icon;
+            
+            CleanupStack::Pop( icon );
+            
+            ResolveLayoutsL();
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::AddToAttachmentArrayL
+// ---------------------------------------------------------
+//
+void CMsgAttachmentControl::AddToAttachmentArrayL( const TDesC& aName, TInt aIndex )
+    {
+    HBufC* convertedFileName = 
+                AknTextUtils::ConvertFileNameL( aName );
+    CleanupStack::PushL( convertedFileName );
+    
+    TPtr convertedFileNamePtr = convertedFileName->Des();
+    
+    AknTextUtils::StripCharacters( convertedFileNamePtr, KStripList );
+    
+    iAttachmentArray->InsertL( aIndex, *convertedFileName );
+    
+    CleanupStack::PopAndDestroy( convertedFileName );
+    }
+
+// ---------------------------------------------------------
+// CMsgAttachmentControl::LayoutButton
+// ---------------------------------------------------------
+//    
+void CMsgAttachmentControl::LayoutButton()
+    {
+#ifdef RD_SCALABLE_UI_V2
+    CMsgExpandableControl::LayoutButton();
+    
+    if ( iButton )
+        {
+        TMargins8 margins;
+        TRect buttonRect = iButtonLayout.Rect();
+        TRect iconRect = iIconLayout.Rect();
+        margins.iTop = iconRect.iTl.iY - buttonRect.iTl.iY;
+        margins.iBottom = buttonRect.iBr.iY - iconRect.iBr.iY;
+        margins.iLeft = iconRect.iTl.iX - buttonRect.iTl.iX;
+        margins.iRight = buttonRect.iBr.iX - iconRect.iBr.iX;
+        
+        iButton->SetMargins( margins );
+        }
+#endif // RD_SCALABLE_UI_V2
+    }
+
+
+//  End of File