diff -r 000000000000 -r 8466d47a6819 meetingrequest/mrgui/mrfieldbuilderpluginextension/src/cesmrviewerattendeesfield.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/meetingrequest/mrgui/mrfieldbuilderpluginextension/src/cesmrviewerattendeesfield.cpp Thu Dec 17 08:39:21 2009 +0200 @@ -0,0 +1,628 @@ +/* +* Copyright (c) 2007-2009 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: ESMR UI Container class +* +*/ + +#include "cesmrviewerattendeesfield.h" + +#include "mesmrlistobserver.h" +#include "cesmrborderlayer.h" +#include "cesmrrichtextlink.h" +#include "esmrfieldbuilderdef.h" +#include "cesmrlayoutmgr.h" +#include "cmrlabel.h" +#include "nmrlayoutmanager.h" + +#include +#include +#include +#include +#include +#include +#include "cmrlistpane.h" + +// DEBUG +#include "emailtrace.h" + +using namespace ESMRLayout; + +// CONSTANTS +/// Unnamed namespace for local definitions +namespace { // codescanner::namespace + +_LIT( KNewLine, "\f" ); +const TInt KMaxLineCount = 4; +const TInt KNumberOfComponents = 2; +const TInt KMargin = 5; + +static void RPointerArrayResetAndDestroy( TAny* aPtr ) + { + static_cast*>( aPtr )->ResetAndDestroy(); + } + +} // namespace + + +// ======== MEMBER FUNCTIONS ======== + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::NewL +// ----------------------------------------------------------------------------- +// +CESMRViewerAttendeesField* CESMRViewerAttendeesField::NewL( + CCalAttendee::TCalRole aRole ) + { + FUNC_LOG; + CESMRViewerAttendeesField* self = + new (ELeave) CESMRViewerAttendeesField( aRole ); + CleanupStack::PushL ( self ); + self->ConstructL ( ); + CleanupStack::Pop ( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::ConstructL +// ----------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::ConstructL( ) + { + FUNC_LOG; + + SetFieldId ( (iRole == CCalAttendee::EReqParticipant) ? EESMRFieldAttendee + : EESMRFieldOptAttendee ); + + iTitle = CMRLabel::NewL(); + iTitle->SetParent( this ); + + iRichTextViewer = CESMRRichTextViewer::NewL (this ); + iRichTextViewer->SetEdwinSizeObserver ( this ); + iRichTextViewer->SetLinkObserver (this ); + iRichTextViewer->SetParent( this ); + + HBufC* label = StringLoader::LoadLC (iRole == CCalAttendee::EReqParticipant ? + R_QTN_MEET_REQ_LABEL_REQUIRED : R_QTN_MEET_REQ_LABEL_OPT ); + iTitle->SetTextL ( *label ); + + CleanupStack::PopAndDestroy( label ); + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::InitializeL +// ----------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::InitializeL() + { + FUNC_LOG; + TAknLayoutText layoutText = + NMRLayoutManager::GetLayoutText( Rect(), + NMRLayoutManager::EMRTextLayoutMultiRowTextEditor ); + iRichTextViewer->SetFontL( layoutText.Font(), iLayout ); + UpdateAttendeesListL(); + //wake up current contact menu selection by calling this + iRichTextViewer->FocusChanged( ENoDrawNow ); + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::SetOutlineFocusL +// ----------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::SetOutlineFocusL( TBool aFocus ) + { + FUNC_LOG; + CESMRField::SetOutlineFocusL( aFocus ); + iRichTextViewer->SetFocus( aFocus ); + + if ( aFocus ) + { + SetMiddleSoftKeyVisible( ETrue ); + } + else + { + TInt oldShowAttendees = iShowAllAttendees; + iShowAllAttendees = EFalse; + if (oldShowAttendees != iShowAllAttendees) + { + UpdateAttendeesListL(); + } + } + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::InternalizeL +// ----------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::InternalizeL( MESMRCalEntry& aEntry ) + { + FUNC_LOG; + CCalEntry& entry = aEntry.Entry(); + RPointerArray& attendees = entry.AttendeesL(); + iCalAttendees.ReserveL(attendees.Count()); + for (TInt i=0; iRoleL() == iRole ) + { + iCalAttendees.AppendL( attendee ); + } + } + + UpdateAttendeesListL(); + + if ( iRichTextViewer->TextLength() > 0 ) + { + //wake up current contact menu selection by calling this + iRichTextViewer->FocusChanged( ENoDrawNow ); + } + else + { + iObserver->RemoveControl( iFieldId ); + } + iDisableRedraw = ETrue; + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::GetMinimumVisibleVerticalArea +// ----------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::GetMinimumVisibleVerticalArea( + TInt& aUpper, TInt& aLower) + { + FUNC_LOG; + aLower = iRichTextViewer->CurrentLineNumber() * iRichTextViewer->RowHeight() + iTitle->Size().iHeight; + aUpper = aLower - iRichTextViewer->RowHeight() - iTitle->Size().iHeight; + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::ListObserverSet +// ----------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::ListObserverSet( ) + { + FUNC_LOG; + iRichTextViewer->SetListObserver( iObserver ); + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::SizeChanged +// ----------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::SizeChanged( ) + { + FUNC_LOG; + // Store iRichTextViewer original width. + TInt richTextViewerWidth = iRichTextViewer->Size().iWidth; + + // Get field's rect + TRect rect( Rect() ); + + // First row for title + TAknLayoutRect rowLayoutRect = + NMRLayoutManager::GetFieldRowLayoutRect( rect, 1 ); + TRect rowRect = rowLayoutRect.Rect(); + + // Layout title to first row's rect + TAknTextComponentLayout titleLayout = + NMRLayoutManager::GetTextComponentLayout( + NMRLayoutManager::EMRTextLayoutText ); + AknLayoutUtils::LayoutLabel( iTitle, rect, titleLayout ); + // Color should be overrided after layouting + // If this function leaves we'll have to use default color + TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL( + *iTitle, + EColorLabelText, + KRgbBlack )); + + // Move upper left corner below first line and get second row's rect. + rect.iTl.iY += rowRect.Height(); + rowLayoutRect = + NMRLayoutManager::GetFieldRowLayoutRect( rect, 2 ); + rowRect = rowLayoutRect.Rect(); + + // Get default 1 row editor rect. + TAknLayoutText viewerLayoutText = + NMRLayoutManager::GetLayoutText( rowRect, + NMRLayoutManager::EMRTextLayoutMultiRowTextEditor ); + TRect viewerRect = viewerLayoutText.TextRect(); + // Resize resize it's height according to actual height required by edwin. + viewerRect.Resize( 0, iExpandedSize.iHeight - viewerRect.Height() ); + iRichTextViewer->SetRect( viewerRect ); + + // Update AttendeesList only if iRichTextViewer width was changed. + // This happens when screen orientation changes e.g. This check + // also prevents recursive calls to UpdateAttendeesListL since + // it causes edwin size changed event. + if ( iRichTextViewer->Size().iWidth != richTextViewerWidth ) + { + // Ignore leave, there's nothing we can do if leave occurs. + TRAP_IGNORE( UpdateAttendeesListL() ); + //wake up current contact menu selection by calling this + iRichTextViewer->FocusChanged(ENoDrawNow); + } + + DrawDeferred(); + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::OfferKeyEventL +// ----------------------------------------------------------------------------- +// +TKeyResponse CESMRViewerAttendeesField::OfferKeyEventL( const TKeyEvent& aEvent, + TEventCode aType ) + { + FUNC_LOG; + TKeyResponse response = EKeyWasNotConsumed; + response = iRichTextViewer->OfferKeyEventL ( aEvent, aType ); + + //track up and down events to change MSK + if ( aType == EEventKey ) + { + if ( aEvent.iScanCode == EStdKeyUpArrow + || aEvent.iScanCode == EStdKeyDownArrow ) + { + const CESMRRichTextLink* link = + iRichTextViewer->GetSelectedLink ( ); + if( link ) + { + if (link->Type() == CESMRRichTextLink::ETypeShowAll ) + { + ChangeMiddleSoftKeyL( + EESMRCmdShowAllAttendees, R_QTN_MEET_REQ_SHOW_ALL); + } + else + { + RestoreMiddleSoftKeyL(); + SetMiddleSoftKeyVisible( ETrue ); + } + } + } + } + + return response; + } + +// --------------------------------------------------------------------------- +// CESMRViewerAttendeesField::SetContainerWindowL() +// --------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::SetContainerWindowL( + const CCoeControl& aContainer ) + { + CESMRField::SetContainerWindowL( aContainer ); + iRichTextViewer->SetContainerWindowL( aContainer ); + } + +// --------------------------------------------------------------------------- +// CESMRViewerAttendeesField::MinimumSize() +// --------------------------------------------------------------------------- +// +TSize CESMRViewerAttendeesField::MinimumSize() + { + // Parent rect will be list area later --> no need to calculate it manually. + TRect parentRect = Parent()->Rect(); + TRect contentRect = NMRLayoutManager::GetLayoutRect( + parentRect, NMRLayoutManager::EMRLayoutListArea ).Rect(); + // We have two lines; title and richtextviewer. + TRect fieldRect = + NMRLayoutManager::GetFieldLayoutRect( contentRect, 2 ).Rect(); + // Get row size for second row (richtext viewer). + TRect rowRect = + NMRLayoutManager::GetFieldRowLayoutRect( fieldRect, 2 ).Rect(); + // Get size for default 1 line editor. + TRect viewerRect = NMRLayoutManager::GetLayoutText( + rowRect, + NMRLayoutManager::EMRTextLayoutMultiRowTextEditor ).TextRect(); + // Adjust field size so that there's room for expandable editor. + fieldRect.Resize( 0, iExpandedSize.iHeight - viewerRect.Height() ); + return fieldRect.Size(); + } + +// --------------------------------------------------------------------------- +// CESMRViewerAttendeesField::ExecuteGenericCommandL() +// --------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::ExecuteGenericCommandL( TInt aCommand ) + { + FUNC_LOG; + switch ( aCommand ) + { + case EESMRCmdClipboardCopy: + { + iRichTextViewer->CopyCurrentLinkValueToClipBoardL(); + break; + } + case EESMRCmdShowAllAttendees: + { + iShowAllAttendees = ETrue; + UpdateAttendeesListL(); + + RestoreMiddleSoftKeyL(); + //wake up current contact menu selection by calling this + iRichTextViewer->FocusChanged(ENoDrawNow); + break; + } + case EAknSoftkeySelect: + { + iRichTextViewer->LinkSelectedL(); + break; + } + default: + // do nothing for now.. + break; + } + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::HandleEdwinSizeEventL +// ----------------------------------------------------------------------------- +// +TBool CESMRViewerAttendeesField::HandleEdwinSizeEventL(CEikEdwin* /*aEdwin*/, + TEdwinSizeEvent /*aType*/, TSize aSize ) + { + FUNC_LOG; + iExpandedSize = aSize; + if ( iObserver && iDisableRedraw ) + { + iObserver->ControlSizeChanged ( this ); + } + return iDisableRedraw; + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::HandleRichTextLinkSelection +// ----------------------------------------------------------------------------- +// +TBool CESMRViewerAttendeesField::HandleRichTextLinkSelection( + const CESMRRichTextLink* aLink ) + { + FUNC_LOG; + if ( aLink->Type() == CESMRRichTextLink::ETypeShowAll ) + { + iShowAllAttendees = ETrue; + TRAPD( err, UpdateAttendeesListL() ); + + if ( err == KErrNone ) + { + return ETrue; + } + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::CountComponentControls +// ----------------------------------------------------------------------------- +// +TInt CESMRViewerAttendeesField::CountComponentControls( ) const + { + FUNC_LOG; + TInt count = KNumberOfComponents; + return count; + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::ComponentControl +// ----------------------------------------------------------------------------- +// +CCoeControl* CESMRViewerAttendeesField::ComponentControl( TInt aInd ) const + { + FUNC_LOG; + switch ( aInd ) + { + case 0: + { + return iTitle; + } + case 1: + { + return iRichTextViewer; + } + default: + { + return NULL; + } + } + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::~CESMRViewerAttendeesField +// ----------------------------------------------------------------------------- +// +CESMRViewerAttendeesField::~CESMRViewerAttendeesField( ) + { + FUNC_LOG; + delete iTitle; + delete iRichTextViewer; + iCalAttendees.Reset(); + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::CESMRViewerAttendeesField +// ----------------------------------------------------------------------------- +// +CESMRViewerAttendeesField::CESMRViewerAttendeesField( + CCalAttendee::TCalRole aRole ) : + iRole( aRole) + { + FUNC_LOG; + //do nothing + } + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::ClipTextLC +// ----------------------------------------------------------------------------- +// +HBufC* CESMRViewerAttendeesField::ClipTextLC( + const TDesC& aText, const CFont& aFont, TInt aWidth ) + { + FUNC_LOG; + HBufC* text = HBufC::NewLC( aText.Length() + KAknBidiExtraSpacePerLine ); + TPtr textPtr = text->Des(); + AknBidiTextUtils::ConvertToVisualAndClip( + aText, textPtr, aFont, aWidth, aWidth ); + return text; + } + + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::UpdateAttendeesListL +// ----------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::UpdateAttendeesListL() + { + FUNC_LOG; + RBuf buffer; // codescanner::resourcenotoncleanupstack + buffer.CleanupClosePushL(); + + iRichTextViewer->SetMargins( KMargin ); + + TSize oldSize = Size(); + + TRect rect( Rect() ); + TAknLayoutText layoutText = + NMRLayoutManager::GetLayoutText( rect, + NMRLayoutManager::EMRTextLayoutMultiRowTextEditor ); + TRect viewerRect = layoutText.TextRect(); + TInt maxLineWidth = viewerRect.Size().iWidth; + const CFont* font = layoutText.Font(); + + if ( maxLineWidth > 0 ) // control size is set + { + TInt linkCount = iCalAttendees.Count(); + TBool notAllShown(EFalse); + if ( !iShowAllAttendees ) + { + linkCount = Min(KMaxLineCount, iCalAttendees.Count() ); + notAllShown = ( linkCount != iCalAttendees.Count() ); + } + + RPointerArray attendeeLinks; // codescanner::resourcenotoncleanupstack + TCleanupItem arrayCleanup( RPointerArrayResetAndDestroy, &attendeeLinks ); + CleanupStack::PushL( arrayCleanup ); + attendeeLinks.ReserveL( linkCount ); + + for ( TInt i = 0; i < linkCount; ++i ) + { + CCalAttendee* attendee = iCalAttendees[i]; + + // Attendee email address. + TPtrC addr = attendee->Address(); + // Attendee common name. + TPtrC name = attendee->CommonName(); + // Actual text to be added to attendee field (email or common name). + TPtrC text = addr; + + // If attendee has common name, use it instead. + if ( name.Length() > 0 ) + { + text.Set( name ); + } + + HBufC* clippedTextHBufC = ClipTextLC( text, *font, maxLineWidth ); + TPtr clippedText = clippedTextHBufC->Des(); + clippedText.Trim(); + + if ( clippedText.Length() > 0 ) + { + CESMRRichTextLink* link = CESMRRichTextLink::NewL( + buffer.Length(), + clippedText.Length() + + KAddressDelimeterSemiColon().Length(), + addr, + CESMRRichTextLink::ETypeEmail, + CESMRRichTextLink::ETriggerKeyRight ); + CleanupStack::PushL( link ); + attendeeLinks.AppendL( link ); + CleanupStack::Pop( link ); + + // Append text and semicolon to buffer. + buffer.ReAllocL( buffer.Length() + + clippedText.Length() + + KAddressDelimeterSemiColon().Length() + + KNewLine().Length() ); + buffer.Append( clippedText ); + buffer.Append( KAddressDelimeterSemiColon ); + buffer.Append( KNewLine ); + } + + CleanupStack::PopAndDestroy( clippedTextHBufC ); + } + + // If there are more lines in use than KMaxLineCount and + // we don't want to show all attendees, leave only + // KMaxLineCount-1 attendees and add 'show all' + // link to the end. + if ( notAllShown ) + { + // Create and append 'show all' link. + CESMRRichTextLink* showAllLink; + HBufC* showAllBuf = StringLoader::LoadLC( R_QTN_MEET_REQ_SHOW_ALL ); + buffer.ReAllocL( buffer.Length() + + showAllBuf->Length() ); + showAllLink = CESMRRichTextLink::NewL( buffer.Length ( ), + showAllBuf->Length(), KNullDesC, + CESMRRichTextLink::ETypeShowAll, + CESMRRichTextLink::ETriggerKeyOk ); + buffer.Append( *showAllBuf ); + CleanupStack::PopAndDestroy( showAllBuf ); + CleanupStack::PushL( showAllLink ); + attendeeLinks.AppendL( showAllLink ); + CleanupStack::Pop( showAllLink ); + } + + // Remove unnecessary new line from the end of buffer. + else if ( buffer.Length() >= KNewLine().Length() ) + { + buffer.SetLength( buffer.Length() - KNewLine().Length() ); + } + + if ( buffer.Length() > 0 ) + { + iRichTextViewer->SetTextL( &buffer ); + + // Add all links to iRichTextViewer. + while ( attendeeLinks.Count() > 0 ) + { + CESMRRichTextLink* link = attendeeLinks[0]; + CleanupStack::PushL( link ); + attendeeLinks.Remove( 0 ); + iRichTextViewer->AddLinkL( link ); + CleanupStack::Pop( link ); + } + } + + CleanupStack::PopAndDestroy( &attendeeLinks ); + + TSize newSize = Size(); + if (oldSize != newSize) + { + CMRListPane* parent = static_cast(Parent()); + parent->SizeChanged(); + } + } + CleanupStack::PopAndDestroy( &buffer ); + } + + +// ----------------------------------------------------------------------------- +// CESMRViewerAttendeesField::HandlePointerEventL +// ----------------------------------------------------------------------------- +// +void CESMRViewerAttendeesField::HandlePointerEventL(const TPointerEvent& aPointerEvent) + { + CCoeControl::HandlePointerEventL(aPointerEvent); + } +// End of file +