--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/msgeditor/viewsrc/MsgExpandableControlEditor.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1323 @@
+/*
+* 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: MsgExpandableControlEditor implementation
+*
+*/
+
+
+
+// ========== INCLUDE FILES ================================
+
+#include <eikappui.h> // for CEikAppUi
+#include <eikenv.h> // for CEikonEnv
+#include <txtrich.h> // for CRichText
+#include <baclipb.h> // for CClipboard
+#include <gulfont.h> // for TLogicalFont
+#include <AknUtils.h> // for AknUtils
+#include <barsread.h> // for TResourceReader
+#include <ItemFinder.h> // for automatic highlight
+
+#include <AknUtils.h>
+#include <AknsUtils.h>
+#include <AknSettingCache.h>
+#include <AknsConstants.h>
+#include <applayout.cdl.h> // LAF
+#include <aknlayoutscalable_apps.cdl.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <AknsFrameBackgroundControlContext.h> // FrameBackgroundControlContext
+#include <AknsDrawUtils.h>
+
+#include "MsgEditorCommon.h" //
+#include "MsgExpandableControlEditor.h" // for CMsgExpandableControlEditor
+#include "MsgExpandableControl.h" // for CMsgExpandableControl
+#include "MsgBaseControl.h" // for TMsgEditPermissionFlags
+#include "MsgBaseControlObserver.h" // for MMsgBaseControlObserver
+#include "MsgEditorPanic.h" // for MsgEditor panics
+#include "MsgEditorLogging.h"
+#include "MsgEditorCustomDraw.h" // for CMsgEditorCustomDraw
+
+// ========== EXTERNAL DATA STRUCTURES =====================
+
+// ========== EXTERNAL FUNCTION PROTOTYPES =================
+
+// ========== CONSTANTS ====================================
+
+// ========== MACROS =======================================
+
+// ========== LOCAL CONSTANTS AND MACROS ===================
+// OPEN:
+const TInt KEdwinTopMargin = 0;
+const TInt KEdwinBottomMargin = 0;
+const TInt KEdwinLeftMargin = 0;
+const TInt KEdwinRightMargin = 0;
+const TInt KExpFullFormattingLength = 500;
+
+// ========== MODULE DATA STRUCTURES =======================
+
+// ========== LOCAL FUNCTION PROTOTYPES ====================
+
+// ========== LOCAL FUNCTIONS ==============================
+
+// ========== MEMBER FUNCTIONS =============================
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CMsgExpandableControlEditor
+//
+// Constructor.
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgExpandableControlEditor::CMsgExpandableControlEditor(
+ TUint32& aFlags,
+ MMsgBaseControlObserver* aBaseControlObserver)
+ :
+ CEikRichTextEditor( TGulBorder::ENone ),
+ iFlags( aFlags ),
+ iBaseControlObserver( aBaseControlObserver )
+ {
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CMsgExpandableControlEditor
+//
+// Constructor.
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgExpandableControlEditor::CMsgExpandableControlEditor(
+ const CCoeControl* aParent,
+ TUint32& aFlags,
+ MMsgBaseControlObserver* aBaseControlObserver )
+ :
+ CEikRichTextEditor( TGulBorder::ENone ),
+ iParentControl( aParent ),
+ iFlags( aFlags ),
+ iBaseControlObserver( aBaseControlObserver )
+ {
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::~CMsgExpandableControlEditor
+//
+// Destructor.
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgExpandableControlEditor::~CMsgExpandableControlEditor()
+ {
+ delete iItemFinder;
+ delete iFrameBgContext;
+ delete iCustomDraw;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::ConstructL
+//
+// Constructs and initializes this editor.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::ConstructL()
+ {
+ TInt edwinFlags = ENoHorizScrolling |
+ ENoAutoSelection |
+ EWidthInPixels |
+ EAllowUndo |
+ EResizable |
+ EPasteAsPlainText;
+
+ iFlags = EMsgControlModeDoNotDrawFrameBgContext;
+ ResolveLayouts();
+
+ /*if ( iBaseControlObserver &&
+ !iBaseControlObserver->ViewInitialized() )
+ {
+ SetSuppressFormatting( ETrue );
+ }*/
+
+ TInt numberOfLines( 0 );
+
+ if ( iFlags & EMsgControlModeSizeFixedToOneLine )
+ {
+ // make control fixed size and allow horizontal scrolling.
+ edwinFlags &= ~EResizable;
+ edwinFlags &= ~ENoHorizScrolling;
+ numberOfLines = 1;
+ }
+
+ CEikRichTextEditor::ConstructL(
+ iParentControl,
+ numberOfLines,
+ iMaxNumberOfChars,
+ edwinFlags );
+
+ // Emoticon support for MMS Subject field
+ AddFlagToUserFlags(EAvkonEnableSmileySupport);
+
+ // Both global text editor and edwin have it's own formatting layers.
+ // CEikRichTextEditor::ConstructL call will set global formatting layers
+ // into use for text. This is not correct as edwin formatting layers
+ // will hold correct formatting values. Below calls will set edwin
+ // formatting layers into use and prevent client based formatting from
+ // being based on incorrect formatting layer.
+ SetParaFormatLayer( iEikonEnv->SystemParaFormatLayerL()->CloneL() );
+ SetCharFormatLayer( iEikonEnv->SystemCharFormatLayerL()->CloneL() );
+
+ SetUpperFullFormattingLength( KExpFullFormattingLength );
+
+ SetMaximumHeight( MsgEditorCommons::MaxBodyHeight() );
+
+ // Set the wrap width to be that of the current header text pane.
+ // This will make the formatting of text safer if it is performed
+ // before the editor has ever had SetSize() called. WrapWidth is
+ // usually set in HandleSizeChanged()
+ if ( iLayout )
+ {
+ iLayout->SetWrapWidth( iTextLayout.TextRect().Width() );
+ }
+
+ // TODO: Get from LAF or something... Currently
+ // all of these are zero. OK?!
+ TMargins8 edwinMargins;
+ edwinMargins.iTop = KEdwinTopMargin;
+ edwinMargins.iBottom = KEdwinBottomMargin;
+ edwinMargins.iLeft = KEdwinLeftMargin;
+ edwinMargins.iRight = KEdwinRightMargin;
+ SetBorderViewMargins( edwinMargins );
+
+ iBgContext = AknsDrawUtils::ControlContext( this );
+
+ // NOTE: iItemFinder can be created by derived class if needed.
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::ConstructFromResourceL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::ConstructFromResourceL(
+ TResourceReader& aReader )
+ {
+ // This used to be font id. Not used anymore. Have to read it, though.
+ /*TInt fontId =*/ aReader.ReadInt32();
+
+ ConstructL();
+
+ if ( !IsReadOnly() )
+ {
+ ReadAknResourceL( aReader );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::SetAndGetSizeL
+//
+// Sets size for this editor. Height of given size aSize may change if the
+// editor contains text.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::SetAndGetSizeL( TSize& aSize )
+ {
+ TSize controlSize( aSize.iWidth, aSize.iHeight );
+
+ if( TextLayout() && TextLayout()->IsFormattingBand() )
+ {
+ // Partial formatting on-going -> needs whole body height
+ //controlSize.iHeight = MaximumHeight();
+ }
+ else
+ {
+ TInt position( 0 );
+ AknLayoutUtils::GetEdwinVerticalPositionAndHeightFromLines(
+ controlSize.iHeight,
+ AknLayoutScalable_Apps::msg_header_pane_t2( 0 ).LayoutLine(),
+ MsgEditorCommons::MsgBaseLineDelta(),
+ iNumberOfLines,
+ position,
+ controlSize.iHeight );
+ }
+ controlSize.iHeight +=iEditortop;
+ if ( controlSize != iSize )
+ {
+ // This may change the height if the content has changed.
+ SetSize( controlSize );
+ }
+
+ aSize = controlSize;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CheckEditPermission
+//
+// Checks and returns control's edit permissions.
+// ---------------------------------------------------------
+//
+EXPORT_C TUint32 CMsgExpandableControlEditor::CheckEditPermission() const
+ {
+ TUint32 editPermission( CMsgBaseControl::EMsgEditNone );
+
+ if ( CanUndo() )
+ {
+ editPermission |= CMsgBaseControl::EMsgEditUndo;
+ }
+
+ if ( Selection().Length() )
+ {
+ // Selection is on
+ editPermission |= CMsgBaseControl::EMsgEditCopy;
+ if ( !IsReadOnly() )
+ {
+ editPermission |= CMsgBaseControl::EMsgEditCut;
+ }
+ if ( Selection().Length() == TextLength() )
+ {
+ editPermission |= CMsgBaseControl::EMsgEditUnSelectAll;
+ }
+ }
+
+ if ( TextLength() )
+ {
+ editPermission |= CMsgBaseControl::EMsgEditSelectAll;
+ }
+
+ editPermission |= CMsgBaseControl::EMsgEditPaste;
+
+ return editPermission;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CursorInFirstLine
+//
+// Checks if the cursor is on the first line and return ETrue if it is.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableControlEditor::CursorInFirstLine()
+ {
+ TBool cursorOnFirstLine = EFalse;
+ TBool posFormatted = iLayout->PosIsFormatted( 0 );
+ if ( iTextView && posFormatted )
+ {
+ TTmDocPos docPos;
+ iTextView->GetCursorPos( docPos );
+ TTmDocPosSpec docPosSpec( docPos );
+ TTmPosInfo2 posInfo;
+ TTmLineInfo lineInfo;
+ if ( iLayout->FindDocPos( docPosSpec, posInfo, &lineInfo ) )
+ {
+ cursorOnFirstLine = ( lineInfo.iLineNumber == 0 );
+ }
+ }
+ return cursorOnFirstLine;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CursorInLastLine
+//
+// Checks if the cursor is on the last line and return ETrue if it is.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableControlEditor::CursorInLastLine()
+ {
+ TBool cursorOnLastLine = EFalse;
+ TBool posFormatted = iLayout->PosIsFormatted( TextLength() );
+
+ if ( iTextView && posFormatted )
+ {
+ TInt numOfLines = iLayout->NumFormattedLines();
+ if ( numOfLines )
+ {
+ TTmDocPos docPos;
+ iTextView->GetCursorPos( docPos );
+ TTmDocPosSpec docPosSpec( docPos );
+ TTmPosInfo2 posInfo;
+ TTmLineInfo lineInfo;
+ if ( iLayout->FindDocPos( docPosSpec, posInfo, &lineInfo ) )
+ {
+ cursorOnLastLine = ( lineInfo.iLineNumber == numOfLines - 1 );
+ }
+ }
+ else
+ {
+ // Editor is empty.
+ cursorOnLastLine = ETrue;
+ }
+ }
+
+ return cursorOnLastLine;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::IsFirstLineVisible
+//
+// Checks if first text line is visible.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableControlEditor::IsFirstLineVisible()
+ {
+ if( TextLayout() )
+ {
+ TPoint dummy;
+ if( TextLayout()->PosInBand( 0, dummy ) )
+ {
+ if( iTextView )
+ {
+ TTmDocPos docPos( 0, ETrue );
+ TTmDocPosSpec docPosSpec( docPos );
+ TTmPosInfo2 posInfo;
+ TTmLineInfo lineInfo;
+
+ if ( iLayout->FindDocPos( docPosSpec, posInfo, &lineInfo ) )
+ {
+ // posInfo.iEdge specifies coordinate position of
+ // intersection of the character edge with the baseline.
+ TInt fontTop = posInfo.iEdge.iY - TextFont()->AscentInPixels();
+ return ( fontTop >= 0 && fontTop <= MsgEditorCommons::EditorViewHeigth() );
+ }
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::IsLastLineVisible
+//
+// Checks if last text line is visible.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableControlEditor::IsLastLineVisible()
+ {
+ if( TextLayout() )
+ {
+ TPoint dummy;
+ if( TextLayout()->PosInBand( TextLength(),dummy ) )
+ {
+ if ( iTextView )
+ {
+ TTmDocPos docPos( TextLength(), EFalse );
+ TTmDocPosSpec docPosSpec( docPos );
+ TTmPosInfo2 posInfo;
+ TTmLineInfo lineInfo;
+
+ if ( iLayout->FindDocPos( docPosSpec, posInfo, &lineInfo ) )
+ {
+ return ( posInfo.iEdge.iY >= 0 &&
+ posInfo.iEdge.iY <= MsgEditorCommons::EditorViewHeigth() );
+ }
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CurrentLineRect
+//
+// Returns the current control rect.
+// ---------------------------------------------------------
+//
+EXPORT_C TRect CMsgExpandableControlEditor::CurrentLineRectL()
+ {
+ if ( !iTextView )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ TTmDocPos docPos;
+ iTextView->GetCursorPos( docPos );
+ iTextView->FinishBackgroundFormattingL();
+
+ TInt cursorPos = Min( docPos.iPos, TextLength() );
+
+ if ( !iLayout->PosIsFormatted( cursorPos ) )
+ {
+ iTextView->SetDocPosL( cursorPos, Selection().Length() ); // after this cursorPos should be formatted
+ ForceScrollBarUpdateL();
+ }
+
+ TRect cursorPosRect;
+
+ if ( iTextView->IsPictureFrameSelected( cursorPosRect, cursorPos ) )
+ {
+ cursorPosRect.Move( TPoint( 0, -iTextView->ViewRect().iTl.iY ) );
+ }
+ else
+ {
+ TTmDocPosSpec docPosSpec( docPos );
+ TTmPosInfo2 posInfo;
+ TTmLineInfo lineInfo;
+ if ( iLayout->FindDocPos( docPosSpec, posInfo, &lineInfo ) )
+ {
+ cursorPosRect = lineInfo.iInnerRect;
+ }
+ //TODO: else what?! We should never get to else branch...
+ }
+
+ return cursorPosRect;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::DefaultHeight
+//
+// Returns a default one line height of the editor.
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMsgExpandableControlEditor::DefaultHeight() const
+ {
+ return DefaultHeight( EFalse );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::ClipboardL
+//
+// Handles a clipboard operation.
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::ClipboardL(
+ CEikEdwin::TClipboardFunc aClipboardFunc )
+ {
+ __ASSERT_DEBUG( iTextView, Panic( EMsgNoTextView ) );
+
+ CEikRichTextEditor::ClipboardL( aClipboardFunc );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CcpuCanCut
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableControlEditor::CcpuCanCut() const
+ {
+ TUint32 editPermission = CheckEditPermission();
+
+ if ( iBaseControlObserver )
+ {
+ TRAP_IGNORE(
+ {
+ if ( iBaseControlObserver->HandleEditObserverEventRequestL( this, EMsgDenyCut ) )
+ {
+ editPermission &= ~CMsgBaseControl::EMsgEditCut;
+ }
+ } );
+ }
+
+ return editPermission & CMsgBaseControl::EMsgEditCut;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CcpuCanCopy
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableControlEditor::CcpuCanCopy() const
+ {
+ TUint32 editPermission = CheckEditPermission();
+
+ if (iBaseControlObserver)
+ {
+ TRAP_IGNORE(
+ {
+ if ( iBaseControlObserver->HandleEditObserverEventRequestL( this, EMsgDenyCopy ) )
+ {
+ editPermission &= ~CMsgBaseControl::EMsgEditCopy;
+ }
+ } );
+ }
+
+ return editPermission & CMsgBaseControl::EMsgEditCopy;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CcpuCanPaste
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableControlEditor::CcpuCanPaste() const
+ {
+ TUint32 editPermission = CheckEditPermission();
+
+ if ( !CEikEdwin::CcpuCanPaste() )
+ {
+ editPermission &= ~CMsgBaseControl::EMsgEditPaste;
+ }
+
+ if ( iBaseControlObserver )
+ {
+ TRAP_IGNORE(
+ {
+ if ( iBaseControlObserver->HandleEditObserverEventRequestL( this, EMsgDenyPaste ) )
+ {
+ editPermission &= ~CMsgBaseControl::EMsgEditPaste;
+ }
+ } );
+ }
+
+ return editPermission & CMsgBaseControl::EMsgEditPaste;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CcpuCanUndo
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableControlEditor::CcpuCanUndo() const
+ {
+ return CheckEditPermission() & CMsgBaseControl::EMsgEditUndo;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CcpuCutL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::CcpuCutL()
+ {
+ CEikRichTextEditor::ClipboardL( ECut );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CcpuCopyL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::CcpuCopyL()
+ {
+ CEikRichTextEditor::ClipboardL( ECopy );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CcpuPasteL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::CcpuPasteL()
+ {
+ CEikRichTextEditor::ClipboardL( EPaste );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::CcpuUndoL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::CcpuUndoL()
+ {
+ UndoL();
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::SetMaxNumberOfChars
+//
+// Sets maximun number of characters.
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::SetMaxNumberOfChars( TInt aMaxNumberOfChars )
+ {
+ iMaxNumberOfChars = aMaxNumberOfChars;
+ if ( Text() )
+ {
+ SetTextLimit( iMaxNumberOfChars );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::SetTextContentL
+//
+// Sets aText content for the editor.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::SetTextContentL( CRichText& aText )
+ {
+ MEBLOGGER_ENTERFN("CMsgExpandableControlEditor::SetTextContentL");
+
+ MEBLOGGER_WRITE("#1");
+ MEBLOGGER_WRITE_TIMESTAMP("");
+
+ if ( IsPlainTextMode() )
+ {
+ CRichText* richText = RichText();
+
+ MEBLOGGER_WRITEF( _L( "MEB: SetTextContentL: Copying text, length %d" ), aText.DocumentLength() );
+
+ // Ignore the original formatting on plain text mode and set the
+ // new rich text object to use current formatting parameters.
+ aText.SetGlobalParaFormat( richText->GlobalParaFormatLayer() );
+ aText.SetGlobalCharFormat( richText->GlobalCharFormatLayer() );
+
+ CEikEdwin::CopyDocumentContentL( aText, *richText );
+ TInt documentLength = richText->DocumentLength();
+
+ MEBLOGGER_WRITEF( _L( "MEB: SetTextContentL: Copied text, length %d" ), documentLength );
+
+ if ( iMaxNumberOfChars &&
+ documentLength > iMaxNumberOfChars )
+ {
+ richText->DeleteL( iMaxNumberOfChars, documentLength - iMaxNumberOfChars );
+ documentLength = richText->DocumentLength();
+ }
+
+ const TChar LF( 0x0A );
+ const TChar CR( 0x0D );
+
+ TInt i = 0;
+ while ( i < documentLength )
+ {
+ TPtrC ptr = richText->Read( i, 1 );
+ TInt remove = 0;
+ TBool addParDeli = EFalse;
+ if ( ptr.Locate( CEditableText::EPictureCharacter ) != KErrNotFound )
+ {
+ remove++;
+ }
+ else if ( ptr.Locate( CR ) != KErrNotFound )
+ {
+ // "CR"
+ remove++;
+ addParDeli = ETrue;
+ if ( i < documentLength - 1 &&
+ aText.Read( i + 1, 1 ).Locate( LF ) != KErrNotFound )
+ {
+ // "CR+LF"
+ remove++;
+ }
+ }
+ else if ( ptr.Locate( LF ) != KErrNotFound )
+ {
+ // "LF"
+ remove++;
+ addParDeli = ETrue;
+ }
+
+ if ( remove )
+ {
+ MEBLOGGER_WRITEF( _L( "MEB: SetTextContentL: removing %d characters" ), remove );
+ richText->DeleteL( i, remove );
+ MEBLOGGER_WRITEF( _L( "MEB: SetTextContentL: removed %d characters" ), remove );
+ documentLength -= remove;
+ if ( addParDeli )
+ {
+ MEBLOGGER_WRITEF( _L( "MEB: SetTextContentL: Inserting paragraph delimeter" ) );
+ richText->InsertL( i, CEditableText::EParagraphDelimiter );
+ MEBLOGGER_WRITEF( _L( "MEB: SetTextContentL: Inserted paragraph delimeter" ) );
+ documentLength++;
+ i++;
+ }
+ }
+ else
+ {
+ i++;
+ }
+ }
+ }
+ else
+ {
+ CopyDocumentContentL( aText, *GlobalText() );
+ }
+
+ SetAmountToFormatL( ETrue );
+
+ MEBLOGGER_WRITE("#2");
+ MEBLOGGER_WRITE_TIMESTAMP("");
+
+ MEBLOGGER_LEAVEFN("CMsgExpandableControlEditor::SetTextContentL");
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::MinimumDefaultHeight
+//
+// Returns a minimum one line height of the editor.
+// ---------------------------------------------------------
+//
+TInt CMsgExpandableControlEditor::MinimumDefaultHeight() const
+ {
+ return DefaultHeight( ETrue );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::Reset
+//
+// Clear contents.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::Reset()
+ {
+ if ( iTextView )
+ {
+ TInt documentLength = RichText()->DocumentLength();
+
+ RichText()->Reset();
+
+ iTextView->SetPendingSelection( TCursorSelection( 0, 0 ) );
+ TRAP_IGNORE( iTextView->HandleInsertDeleteL( TCursorSelection( 0, 0 ),
+ documentLength ) );
+ }
+ else
+ {
+ RichText()->Reset();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::SetBaseControlObserver
+//
+// Sets base control observer.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::SetBaseControlObserver(
+ MMsgBaseControlObserver& aBaseControlObserver )
+ {
+ iBaseControlObserver = &aBaseControlObserver;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::OfferKeyEventL
+//
+// Handles key event.
+// ---------------------------------------------------------
+//
+EXPORT_C TKeyResponse CMsgExpandableControlEditor::OfferKeyEventL(
+ const TKeyEvent& aKeyEvent, TEventCode aType)
+ {
+ if ( IsReadOnly() )
+ {
+ TCursorPosition::TMovementType movetype;
+
+ switch ( aKeyEvent.iCode )
+ {
+ case EKeyUpArrow:
+ movetype = TCursorPosition::EFPageUp;
+ break;
+
+ case EKeyDownArrow:
+ movetype = TCursorPosition::EFPageDown;
+ break;
+
+ default:
+ return CEikRichTextEditor::OfferKeyEventL( aKeyEvent, aType );
+ }
+
+ iTextView->MoveCursorL( movetype, EFalse );
+
+ return EKeyWasConsumed;
+ }
+ else
+ {
+ return CEikRichTextEditor::OfferKeyEventL( aKeyEvent, aType );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::HandleResourceChange
+//
+// Sets correct highlight extension.
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::HandleResourceChange( TInt aType )
+ {
+ if ( aType == KEikDynamicLayoutVariantSwitch )
+ {
+ ResolveLayouts();
+ LayoutEdwin();
+
+ TRAP_IGNORE(
+ {
+ if ( iTextView )
+ {
+ TCursorSelection currentSelection = iTextView->Selection() ;
+
+ if ( currentSelection.Length() > 0 )
+ {
+ iTextView->SetSelectionL( currentSelection );
+ }
+ else
+ {
+ iTextView->SetDocPosL( currentSelection.iCursorPos, EFalse );
+ }
+ }
+ } );
+ }
+
+ CEikRichTextEditor::HandleResourceChange( aType );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::IsPlainTextMode
+//
+// Checks if the plain text mode is on and returns ETrue if it is.
+// ---------------------------------------------------------
+//
+TBool CMsgExpandableControlEditor::IsPlainTextMode() const
+ {
+ return iFlags & EMsgControlModePlainTextMode;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::LayoutEdwin
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::LayoutEdwin()
+ {
+ 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() );
+
+ TRect parentRect( msgHeaderPane.Rect() );
+ parentRect.Move( 0, iParentControl->Position().iY );
+
+ DoLayoutEdwin( parentRect,
+ AknLayoutScalable_Apps::msg_header_pane_t2( 0 ).LayoutLine() );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::DoLayoutEdwin
+//
+// Performs the layout setting for edwin according to the given
+// parameters. Used from LayoutEdwin or some of it's derived versions.
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::DoLayoutEdwin( const TRect& aEdwinParent,
+ const TAknTextLineLayout& aLayout )
+ {
+ TPoint position( iPosition );
+
+ // Layout edwin as two lines to get the base line delta override activated.
+ TInt lineNumber( 0 );
+ AknLayoutUtils::LayoutEdwin( this,
+ aEdwinParent,
+ aLayout,
+ 2,
+ MsgEditorCommons::MsgBaseLineDelta(),
+ EAknsCIQsnTextColorsCG6,
+ lineNumber );
+
+ // Resize the edwin to the correct size. Also set the original position.
+ TInt notUsed( 0 );
+ TInt height( 0 );
+ AknLayoutUtils::GetEdwinVerticalPositionAndHeightFromLines(
+ aEdwinParent.Size().iHeight,
+ aLayout,
+ MsgEditorCommons::MsgBaseLineDelta(),
+ iNumberOfLines,
+ notUsed,
+ height );
+
+ TRect editorRect( position, TSize( iSize.iWidth, height ) );
+ SetRect( editorRect );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::AdjustLineHeightL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::AdjustLineHeightL()
+ {
+ // nop
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::TextFont
+// ---------------------------------------------------------
+//
+EXPORT_C const CFont* CMsgExpandableControlEditor::TextFont() const
+ {
+ return iTextLayout.Font();
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::DefaultHeight
+// ---------------------------------------------------------
+//
+TInt CMsgExpandableControlEditor::DefaultHeight( TBool /*aOneToOne*/ ) const
+ {
+ return TextFont()->HeightInPixels();
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::VirtualHeight
+//
+// Returns approximate height of text. In band formatting mode
+// we have to calculate the average chars per line and
+// average line in view values by ourself as we might get called
+// in a callback when edwin does not contain up-to-date values.
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMsgExpandableControlEditor::VirtualHeight()
+ {
+ TInt heightInPixels( 0 );
+ TInt msgBaseLineDelta( MsgEditorCommons::MsgBaseLineDelta() );
+
+ if ( iLayout->IsFormattingBand() )
+ {
+ TInt docLength = iLayout->DocumentLength();
+
+ TInt avgCharsPerLine = iLayout->FormattedLength() / iLayout->NumFormattedLines();
+ TInt avgLinesInViewRect= Max( 1, iTextView->ViewRect().Height() *
+ iLayout->NumFormattedLines() /
+ iLayout->FormattedHeightInPixels() );
+
+ const TInt approxTotalLines = Max( docLength / avgCharsPerLine,
+ iText->ParagraphCount() );
+ const TInt approxLineHeight = iTextView->ViewRect().Height() / avgLinesInViewRect;
+ heightInPixels = approxTotalLines * approxLineHeight;
+ }
+ else
+ {
+ if ( iTextView )
+ {
+ // Force formatting to complete so that
+ // correct height can be retrieved.
+ TRAP_IGNORE( iTextView->FinishBackgroundFormattingL() );
+ }
+
+ heightInPixels = iLayout->FormattedHeightInPixels();
+ }
+
+ heightInPixels = Max( heightInPixels, iLayout->FormattedHeightInPixels() );
+ MsgEditorCommons::RoundToPreviousLine( heightInPixels, msgBaseLineDelta );
+
+ return heightInPixels;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::VirtualVisibleTop
+//
+// Returns a topmost visible text position. In band formatting mode
+// we have to calculate the average chars per line value
+// by ourself as we might get called in a callback when edwin
+// does not contain up-to-date value.
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMsgExpandableControlEditor::VirtualVisibleTop()
+ {
+ TInt ret( 0 );
+
+ TInt msgBaseLineDelta( MsgEditorCommons::MsgBaseLineDelta() );
+
+ if ( iLayout->IsFormattingBand() )
+ {
+ TInt avgCharsPerLine = iLayout->FormattedLength() / iLayout->NumFormattedLines();
+
+ TInt topLeftDocPos = iLayout->FirstDocPosFullyInBand();
+ TInt approxTopVisibleLine = topLeftDocPos / avgCharsPerLine;
+
+ if ( approxTopVisibleLine == 0 &&
+ topLeftDocPos > 0 )
+ {
+ ret = iLayout->PixelsAboveBand();
+ }
+ else
+ {
+ TInt avgLinesInViewRect= Max( 1, iTextView->ViewRect().Height() *
+ iLayout->NumFormattedLines() /
+ iLayout->FormattedHeightInPixels() );
+
+ TInt approxLineHeight = iTextView->ViewRect().Height() / avgLinesInViewRect;
+ ret = approxTopVisibleLine * approxLineHeight;
+ }
+ }
+ else
+ {
+ // Round to the last full line height. Division removes the fraction since
+ // result is integer (i.e. non floating point value).
+ ret = iLayout->PixelsAboveBand();
+ }
+
+ ret = Max( ret, iLayout->PixelsAboveBand() );
+ MsgEditorCommons::RoundToPreviousLine( ret, msgBaseLineDelta );
+
+ return ret;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::ActivateL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::ActivateL()
+ {
+ if ( IsActivated() )
+ {
+ return;
+ }
+
+ TInt cursorPos = 0;
+
+ if ( iTextView )
+ {
+ cursorPos = CursorPos();
+ }
+
+ LayoutEdwin();
+ SetTextSkinColorIdL();
+
+ CEikRichTextEditor::ActivateL();
+
+ iTextView->SetDocPosL( cursorPos );
+ if ( !iCustomDraw )
+ {
+ // Swap the custom drawer to our own to show text lines.
+ const MFormCustomDraw* customDraw = TextLayout()->CustomDraw();
+
+ iCustomDraw = CMsgEditorCustomDraw::NewL( customDraw, this, iControlType);
+
+ TextLayout()->SetCustomDraw( iCustomDraw );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::ItemFinder
+// ---------------------------------------------------------
+//
+EXPORT_C CItemFinder* CMsgExpandableControlEditor::ItemFinder() const
+ {
+ return iItemFinder;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::FocusChanged
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableControlEditor::FocusChanged( TDrawNow aDrawNow )
+ {
+ CEikEdwin::FocusChanged( aDrawNow );
+
+ TRAP_IGNORE( DoFocusChangedL() );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::DoFocusChangedL
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::DoFocusChangedL()
+ {
+ SetTextSkinColorIdL();
+
+ if( ! ( iFlags & EMsgControlModeDoNotDrawFrameBgContext ) &&
+ ! static_cast<const CMsgBaseControl*>( iParentControl )->IsReadOnly() )
+ {
+ if( IsFocused( ) )
+ {
+ // The focus arrives so lets so the frame
+ // It is drawn between the outer and inner rects
+ TRect outer, inner;
+ OuterAndInnerRects( outer, inner );
+
+ if( !iFrameBgContext )
+ {
+ iFrameBgContext =
+ CAknsFrameBackgroundControlContext::NewL( KAknsIIDQsnFrInput,
+ outer,
+ inner,
+ EFalse );
+ iFrameBgContext->SetParentContext( iBgContext );
+ }
+ else
+ {
+ iFrameBgContext->SetFrameRects( outer, inner );
+ }
+ SetSkinBackgroundControlContextL( iFrameBgContext );
+ }
+ else
+ { // Focus leaves so lets remove the skin bg control contex
+ SetSkinBackgroundControlContextL( iBgContext );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::HandleFrameSizeChangeL
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::HandleFrameSizeChangeL()
+ {
+ if( IsFocused( ) )
+ {
+ // We have focus so lets resize the frame context
+ if( ! (iFlags & EMsgControlModeDoNotDrawFrameBgContext ) &&
+ ! static_cast<const CMsgBaseControl*>( iParentControl )->IsReadOnly() )
+ {
+ // The size of the frame has changed so lets find out
+ // the outer and inner rects again
+ TRect outer, inner;
+ OuterAndInnerRects( outer, inner );
+
+ if( !iFrameBgContext )
+ {
+ iFrameBgContext =
+ CAknsFrameBackgroundControlContext::NewL( KAknsIIDQsnFrInput,
+ outer,
+ inner,
+ EFalse );
+ iFrameBgContext->SetParentContext( iBgContext );
+ }
+
+ iFrameBgContext->SetFrameRects( outer, inner );
+ SetSkinBackgroundControlContextL( iFrameBgContext );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::OuterAndInnerRects
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::OuterAndInnerRects( TRect& aOuter, TRect& aInner )
+ {
+ TRect rect( Rect( ) );
+ TRect focused ( iParentControl->Rect( ) );
+
+ // If we are out of screen, start it just from the baseline offset
+ TInt top = MsgEditorCommons::MsgBaseLineOffset();
+ if ( focused.iTl.iY < top )
+ {
+ focused.iTl.iY = top;
+ }
+ TInt maxBodyHeight( MsgEditorCommons::EditorViewHeigth() );
+ if ( focused.iBr.iY > maxBodyHeight )
+ {
+ focused.iBr.iY = maxBodyHeight;
+ }
+
+ aOuter.SetRect( rect.iTl.iX-1,
+ focused.iTl.iY,
+ rect.iBr.iX,
+ focused.iBr.iY );
+
+ TAknLayoutRect tl;
+ TAknLayoutRect br;
+ tl.LayoutRect( aOuter, AknLayoutScalable_Avkon::input_focus_pane_g2().LayoutLine() );
+ br.LayoutRect( aOuter, AknLayoutScalable_Avkon::input_focus_pane_g5().LayoutLine() );
+
+ aInner.SetRect( aOuter.iTl.iX - 1,
+ aOuter.iTl.iY + tl.Rect().Height(),
+ aOuter.iBr.iX,
+ aOuter.iBr.iY - br.Rect().Height() );
+ }
+
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::ResolveLayouts
+//
+//
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::ResolveLayouts()
+ {
+ 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() );
+
+ iTextLayout.LayoutText( msgHeaderPane.Rect(),
+ AknLayoutScalable_Apps::msg_header_pane_t2( 0 ).LayoutLine() );
+ TRect dataPane = MsgEditorCommons::MsgDataPane();
+
+
+ TAknTextLineLayout editorLineLayout;
+ TAknLayoutText editorLayout;
+
+ editorLineLayout = AknLayoutScalable_Apps::msg_header_pane_t2( 0 ).LayoutLine();
+
+ editorLayout.LayoutText( msgHeaderPane.Rect(), editorLineLayout );
+
+ iEditortop = editorLayout.TextRect().iTl.iY - msgHeaderPane.Rect().iTl.iY;
+ if ( iCustomDraw )
+ {
+ iCustomDraw->ResolveLayouts();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::PrepareForReadOnlyL
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::PrepareForReadOnlyL( TBool aReadOnly )
+ {
+ if ( IsReadOnly() == aReadOnly )
+ {
+ return;
+ }
+
+ SetReadOnly( aReadOnly );
+ SetTextSkinColorIdL();
+
+ if ( aReadOnly )
+ {
+ AddFlagToUserFlags( CEikEdwin::EAvkonDisableCursor );
+ }
+ else
+ {
+ RemoveFlagFromUserFlags( CEikEdwin::EAvkonDisableCursor );
+ }
+
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::SetTextSkinColorIdL
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::SetTextSkinColorIdL()
+ {
+ TAknsQsnTextColorsIndex colorId = EAknsCIQsnTextColorsCG6;
+ if ( !IsReadOnly() && IsFocused() )
+ {
+ colorId = EAknsCIQsnTextColorsCG8;
+ }
+
+ CEikEdwin::SetTextSkinColorIdL( colorId );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::IsCursorVisibleL
+// ---------------------------------------------------------
+//
+TBool CMsgExpandableControlEditor::IsCursorVisibleL()
+ {
+ TBool result = EFalse;
+ if ( iTextView )
+ {
+ TPoint cursorPos;
+
+ if ( iTextView->DocPosToXyPosL( CursorPos(), cursorPos ) &&
+ iTextView->ViewRect().Contains( cursorPos ) )
+ {
+ result = ETrue;
+ }
+ }
+ return result;
+ }
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::MsgEditorCustomDraw
+// ---------------------------------------------------------
+//
+CMsgEditorCustomDraw* CMsgExpandableControlEditor::MsgEditorCustomDraw() const
+ {
+ return iCustomDraw;
+ }
+
+
+// ---------------------------------------------------------
+// CMsgExpandableControlEditor::SetControlType
+// ---------------------------------------------------------
+//
+void CMsgExpandableControlEditor::SetControlType(TInt actrltype)
+ {
+ iControlType = actrltype;
+ }
+// End of File