diff -r 000000000000 -r 72b543305e3a messagingappbase/msgeditor/viewsrc/MsgAttachmentControl.cpp --- /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 // for TResourceReader +#include // for CRichText + +#include // for CEikonEnv +#include // for CEikAppUi +#include // for TClipboardFunc +#include + +#include // for AknUtils +#include // for CAknButton + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef RD_TACTILE_FEEDBACK +#include +#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( 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