--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/msgeditor/viewsrc/MsgExpandableTextEditorControl.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,524 @@
+/*
+* Copyright (c) 2007 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: MsgExpandableTextEditorControl implementation
+*
+*/
+
+
+
+// ========== INCLUDE FILES ================================
+
+#include <eikenv.h> // for CEikonEnv
+#include <eikedwin.h> // for TClipboardFunc
+#include <txtrich.h> // for CRichText
+#include <AknUtils.h> // for AknUtils
+#include <aknenv.h> // for CAknEnv
+#include <AknDef.h>
+
+
+#include "MsgExpandableTextEditorControl.h"
+#include "MsgEditorCommon.h" //
+#include "MsgExpandableControlEditor.h" // for CMsgExpandableControlEditor
+#include "MsgBaseControlObserver.h" // for MMsgBaseControlObserver
+#include "MsgEditorPanic.h" // for CMsgEditor panics
+#include "MsgEditorLogging.h"
+
+// ========== EXTERNAL DATA STRUCTURES =====================
+
+// ========== EXTERNAL FUNCTION PROTOTYPES =================
+
+// ========== CONSTANTS ====================================
+
+// ========== MACROS =======================================
+
+// ========== LOCAL CONSTANTS AND MACROS ===================
+const TInt KCursorPosNotSet = -1;
+
+// ========== MODULE DATA STRUCTURES =======================
+
+// ========== LOCAL FUNCTION PROTOTYPES ====================
+
+// ========== LOCAL FUNCTIONS ==============================
+
+// ========== MEMBER FUNCTIONS =============================
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::CMsgExpandableTextEditorControl
+//
+// Constructor.
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgExpandableTextEditorControl::CMsgExpandableTextEditorControl() :
+ iCursorPos( KCursorPosNotSet )
+ {
+ SetComponentsToInheritVisibility( ETrue );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControl::CMsgExpandableControl
+//
+// Constructor.
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgExpandableTextEditorControl::CMsgExpandableTextEditorControl( MMsgBaseControlObserver& aBaseControlObserver ) :
+ CMsgBaseControl( aBaseControlObserver ),
+ iCursorPos( KCursorPosNotSet )
+ {
+ SetComponentsToInheritVisibility( ETrue );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::~CMsgExpandableTextEditorControl
+//
+// Destructor.
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgExpandableTextEditorControl::~CMsgExpandableTextEditorControl()
+ {
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::SetPlainTextMode
+//
+// Sets the plain text mode on or off.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableTextEditorControl::SetPlainTextMode( TBool aMode )
+ {
+ if ( aMode )
+ {
+ iControlModeFlags |= EMsgControlModePlainTextMode;
+ }
+ else
+ {
+ iControlModeFlags &= ~EMsgControlModePlainTextMode;
+ }
+
+ iEditor->SetAllowPictures( !( iControlModeFlags & EMsgControlModePlainTextMode ) );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableControl::IsPlainTextMode
+//
+// Checks if the plain text mode is on and returns ETrue if it is.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableTextEditorControl::IsPlainTextMode() const
+ {
+ return iControlModeFlags & EMsgControlModePlainTextMode;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::TextContent
+//
+// Returns a reference to text content of the editor.
+// ---------------------------------------------------------
+//
+EXPORT_C CRichText& CMsgExpandableTextEditorControl::TextContent() const
+ {
+ return *iEditor->RichText();
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::CopyDocumentContentL
+//
+// Copies aInText to aOutText.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableTextEditorControl::CopyDocumentContentL( CGlobalText& aInText,
+ CGlobalText& aOutText )
+ {
+ iEditor->CopyDocumentContentL( aInText, aOutText );
+ iControlModeFlags |= EMsgControlModeModified;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::SetMaxNumberOfChars
+//
+// Sets maximun number of characters.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableTextEditorControl::SetMaxNumberOfChars( TInt aMaxNumberOfChars )
+ {
+ iEditor->SetMaxNumberOfChars( aMaxNumberOfChars );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::SetCursorPosL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableTextEditorControl::SetCursorPosL( TInt aCursorPos )
+ {
+ if ( iEditor &&
+ IsActivated() &&
+ ( iEditor->CursorPos() != aCursorPos ||
+ !iEditor->IsCursorVisibleL() ) )
+ {
+ iEditor->SetCursorPosL( aCursorPos, EFalse );
+ iBaseControlObserver->HandleBaseControlEventRequestL( this,
+ EMsgEnsureCorrectFormPosition,
+ 0 );
+ }
+ iCursorPos = aCursorPos;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::ActivateL
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableTextEditorControl::ActivateL()
+ {
+ CMsgBaseControl::ActivateL();
+
+ if ( iCursorPos != KCursorPosNotSet )
+ {
+ SetCursorPosL( iCursorPos );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::ScrollL
+//
+// Tries to scroll the given amount of pixels. Restrict scroll
+// to top of lines is switched off to allow better scrolling of
+// text view. Otherwise scrolling would be limited to top of
+// the text lines. Margin pixels are scrolled "away" when control reaches
+// the end.
+// ---------------------------------------------------------
+//
+#ifdef RD_SCALABLE_UI_V2
+EXPORT_C TInt CMsgExpandableTextEditorControl::ScrollL( TInt aPixelsToScroll, TMsgScrollDirection aDirection )
+ {
+ TInt pixelsToScroll( 0 );
+
+ CTextLayout* textLayout = iEditor->TextLayout();
+
+ if ( aDirection == EMsgScrollDown )
+ {
+ // Negative pixels means scrolling down.
+ pixelsToScroll = -aPixelsToScroll;
+ }
+ else
+ {
+ // Positive pixels means scrolling up.
+ pixelsToScroll = aPixelsToScroll;
+ }
+
+ if ( pixelsToScroll != 0 )
+ {
+ iEditor->TextView()->ScrollDisplayPixelsL( pixelsToScroll );
+
+ if ( Abs( pixelsToScroll ) % iLineHeight != 0 )
+ {
+ pixelsToScroll = Abs( pixelsToScroll ) - ( Size().iHeight - iEditor->Size().iHeight );
+ }
+
+ }
+
+ return Abs( pixelsToScroll );
+ }
+#else
+EXPORT_C TInt CMsgExpandableTextEditorControl::ScrollL( TInt /*aPixelsToScroll*/, TMsgScrollDirection /*aDirection*/ )
+ {
+ return 0;
+ }
+#endif // RD_SCALABLE_UI_V2
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::CurrentLineRect
+//
+// Returns the current control rect.
+// ---------------------------------------------------------
+//
+EXPORT_C TRect CMsgExpandableTextEditorControl::CurrentLineRect()
+ {
+ TRect lineRect( 0, 0, 0, 0 );
+ TRAPD( ret, lineRect = iEditor->CurrentLineRectL() );
+ if ( ret != KErrNone )
+ {
+ return lineRect;
+ }
+
+ TRect ctrlRect( Rect() );
+
+ lineRect.iTl.iX = ctrlRect.iTl.iX;
+ lineRect.iBr.iX = ctrlRect.iBr.iX;
+ // "lineRect" is relative to "ctrlRect" -> Move needed
+ lineRect.Move( TPoint( 0, iPosition.iY ) );
+
+ // "lineRect" should never be outside the "ctrlRect"
+ // There seems to be a bug in Edwin when layouting is
+ // changed from "full" to "partial". In this case the
+ // "lineRect" might get outside "ctrlRect". This
+ // causes false alarm and unwanted scrolling in
+ // CMsgEditorView::EnsureCorrectFormPosition.
+ // -> Has to make sure lineRect won't get outside ctrlRect
+
+ if ( lineRect.iBr.iY > ctrlRect.iBr.iY )
+ {
+ lineRect.Move( TPoint( 0, ctrlRect.iBr.iY - lineRect.iBr.iY ) );
+ }
+
+ return lineRect;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::SetBaseControlObserver
+//
+// Sets base control observer.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableTextEditorControl::SetBaseControlObserver( MMsgBaseControlObserver& aBaseControlObserver )
+ {
+ CMsgBaseControl::SetBaseControlObserver( aBaseControlObserver );
+ iEditor->SetBaseControlObserver( aBaseControlObserver );
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::ClipboardL
+//
+// Handles clipboard operation.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableTextEditorControl::ClipboardL( TMsgClipboardFunc /*aFunc*/ )
+ {
+ // changed to do nothing because
+ // CMsgExpandableControlEditor::Ccpu???? functions handle
+ // clipboard operations now.
+ }
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::EditL
+//
+// Handles editing operation.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableTextEditorControl::EditL( TMsgEditFunc aFunc )
+ {
+ TUint32 editPermission = EditPermission();
+
+ switch ( aFunc )
+ {
+ case EMsgUndo:
+ {
+ if ( editPermission & EMsgEditUndo )
+ {
+ iEditor->UndoL();
+ }
+ break;
+ }
+ case EMsgSelectAll:
+ {
+ if ( editPermission & EMsgEditSelectAll )
+ {
+ iEditor->SelectAllL();
+ HandleControlEventL( this, MCoeControlObserver::EEventStateChanged );
+ }
+ break;
+ }
+ default:
+ {
+ __ASSERT_DEBUG( EFalse, Panic( EMsgIncorrectEditFunction ) );
+ break;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::EditPermission
+//
+// Returns edit permission flags.
+// ---------------------------------------------------------
+//
+EXPORT_C TUint32 CMsgExpandableTextEditorControl::EditPermission() const
+ {
+ return iEditor->CheckEditPermission();
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::IsCursorLocation
+//
+// Checks if the cursor location is on the topmost or downmost position
+// depending on aLocation and returns ETrue if it is.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableTextEditorControl::IsCursorLocation( TMsgCursorLocation aLocation ) const
+ {
+ switch ( aLocation )
+ {
+ case EMsgTop:
+ {
+ return iEditor->CursorInFirstLine();
+ }
+ case EMsgBottom:
+ {
+ return iEditor->CursorInLastLine();
+ }
+ default:
+ {
+ return EFalse;
+ }
+ }
+ }
+
+
+// CMsgExpandableTextEditorControl::VirtualHeight
+//
+// Returns approximate height of the control.
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMsgExpandableTextEditorControl::VirtualHeight()
+ {
+ return iEditor->VirtualHeight();
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::VirtualVisibleTop
+//
+// Returns a topmost visible text position. Queries the visible top
+// from editor and adds control top position differences (= top margin )
+// into it if control is not visible.
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMsgExpandableTextEditorControl::VirtualVisibleTop()
+ {
+ return iEditor->VirtualVisibleTop();
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::HandleControlEventL
+//
+// Handles state change event from text editor. Checks whether form
+// updating is needed. This is needed atleast when subject field
+// is visible at the last row of the view and word is typed using T9
+// so that line is changed in the middle of it. Without this check
+// the view is not updated correctly.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableTextEditorControl::HandleControlEventL( CCoeControl* aControl,
+ TCoeEvent aEventType )
+ {
+ if ( aControl == iEditor &&
+ aEventType == MCoeControlObserver::EEventStateChanged )
+ {
+ iBaseControlObserver->HandleBaseControlEventRequestL( this,
+ EMsgEnsureCorrectFormPosition,
+ 0 );
+ iControlModeFlags |= EMsgControlModeModified;
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::HandleEdwinSizeEventL
+//
+// Handles expandable text editor size event. These event are send only when
+// the editor height changes. First desirable heigh is limited to maximum
+// body height. This is needed as edwin will report values larger than
+// maximum height. After this a change delta between current and desired
+// heights is calculated. This is rounded to the next full baseline.
+// If editor height is wanted to reduce and there is still unshown content
+// then the content is scrolled downward so that it becomes visible. In this
+// case the editor or control height is not changed. If editor height is
+// wanted to increase or all the content is current shown then
+// control and editor heights are changed. If body max height flag
+// is specified for control then the control height is always set to maximum.
+// After heights have been changed base control observer (CMsgEditorView)
+// is notified.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgExpandableTextEditorControl::HandleEdwinSizeEventL( CEikEdwin* /*aEdwin*/,
+ TEdwinSizeEvent aEventType,
+ TSize aDesirableEdwinSize )
+ {
+ if ( aEventType == EEventSizeChanging )
+ {
+ MEBLOGGER_ENTERFN("CMsgExpandableTextEditorControl::HandleEdwinSizeEventL");
+
+ aDesirableEdwinSize.iHeight = Min( aDesirableEdwinSize.iHeight, iMaxBodyHeight );
+
+ TInt delta = aDesirableEdwinSize.iHeight - iEditor->Size().iHeight;
+ MsgEditorCommons::RoundToNextLine( delta, iLineHeight );
+
+ if ( delta < 0 &&
+ iEditor->VirtualHeight() > iMaxBodyHeight )
+ {
+ ScrollL( delta, EMsgScrollDown );
+ iBaseControlObserver->HandleBaseControlEventRequestL( this,
+ EMsgUpdateScrollbar,
+ delta );
+ }
+ else if ( delta ||
+ iControlModeFlags & EMsgControlModeForceSizeUpdate )
+ {
+ if ( iControlModeFlags & EMsgControlModeBodyMaxHeight )
+ {
+ aDesirableEdwinSize.iHeight = iEditor->MaximumHeight();
+ }
+
+ // Performs the real size change if height has really changed
+ // or if forced size change is set.
+ iSize.iHeight = aDesirableEdwinSize.iHeight;
+ MsgEditorCommons::RoundToNextLine( iSize.iHeight, iLineHeight );
+
+ if ( delta != 0 )
+ {
+ iEditor->SetAndGetSizeL( aDesirableEdwinSize );
+ }
+
+ iBaseControlObserver->HandleBaseControlEventRequestL( this,
+ EMsgHeightChanged,
+ delta );
+ }
+
+ MEBLOGGER_LEAVEFN("CMsgExpandableTextEditorControl::HandleEdwinSizeEventL");
+
+ if ( delta < 0 )
+ {
+ return ETrue;
+ }
+ }
+
+ return EFalse;
+ }
+
+// ---------------------------------------------------------
+// CMsgExpandableTextEditorControl::HandleEdwinEventL
+//
+// Handles events from expandable text editor. Navigation and format
+// change events are handled.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgExpandableTextEditorControl::HandleEdwinEventL( CEikEdwin* aEdwin,
+ TEdwinEvent aEventType)
+ {
+ if ( aEventType == MEikEdwinObserver::EEventNavigation && aEdwin->TextView() )
+ {
+ // When cursor is in beginning of text and left key is pressed,
+ // FEP places cursor to the end of text. This scrolls end of text
+ // to be visible. With pen support this needs to be handled always since
+ // select & drag scrolling might change the text position so that form updating
+ // is needed.
+ iBaseControlObserver->HandleBaseControlEventRequestL( this,
+ EMsgEnsureCorrectFormPosition,
+ 0 );
+ }
+ else if ( aEventType == MEikEdwinObserver::EEventFormatChanged )
+ {
+ iBaseControlObserver->HandleBaseControlEventRequestL( this,
+ EMsgEnsureCorrectFormPosition,
+ 0 );
+ }
+ }
+
+
+// End of File