diff -r 84d9eb65b26f -r 2981cb3aa489 messagingappbase/msgeditor/viewsrc/MsgExpandableTextEditorControl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingappbase/msgeditor/viewsrc/MsgExpandableTextEditorControl.cpp Wed Nov 03 09:52:46 2010 +0530 @@ -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 // for CEikonEnv +#include // for TClipboardFunc +#include // for CRichText +#include // for AknUtils +#include // for CAknEnv +#include + + +#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