--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imstutils/imconversationview/imcvuiapp/src/cimcvappmessageflowhandler.cpp Tue Feb 02 10:12:18 2010 +0200
@@ -0,0 +1,416 @@
+/*
+* Copyright (c) 2007-2008 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: Message flow handler class
+*
+*/
+
+
+// INCLUDE FILES
+#include <coemain.h>
+
+#include "cimcvappmessageflowhandler.h"
+#include "mimcvenginemessagecontainer.h"
+#include "cimcvenginecontextobserver.h"
+#include "mimcvenginemessagesreadinterface.h"
+#include "imcvlogger.h"
+#include "cimcvappui.h"
+#include "cimcvengine.h"
+#include "mimcvenginechatinterface.h"
+
+
+// CONSTANTS
+const TInt KMilliToMicro = 1000; // multiplier for converting milliseconds to microseconds
+
+const TInt KTimeIntervalSlow = 2000; // slowest message speed (in milliseconds)
+const TInt KTimeIntervalFast = 200; // fastest message speed (in milliseconds)
+
+const TInt KTimeIntervalOpen = 0; // message fetching speed when opening the view
+const TInt KInitialMessages = 3; // fetch n messages at once when opening the view
+
+const TInt KSettingValueMin = 1; // minimum value for flow control setting
+const TInt KSettingValueMax = 3; // maximum value for flow control setting
+
+const TInt KIMFeatBackgroundGroupOpening = 0x00000008;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CIMCVAppMessageFlowHandler::CIMCVAppMessageFlowHandler
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CIMCVAppMessageFlowHandler::CIMCVAppMessageFlowHandler( MIMCVEngineMessageContainer& aMessageContainer,
+ MIMCVEngineMessageReadInterface& aReadInterface,CIMCVEngine& aActiveEngine )
+ : CTimer( EPriorityStandard ),
+ iMessages( aMessageContainer ),
+ iReadInterface( aReadInterface ),
+ iActiveEngine( aActiveEngine ),
+ iFetchMessages( ETrue )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CCAMessageFlowHandler::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CIMCVAppMessageFlowHandler* CIMCVAppMessageFlowHandler::NewL(
+ MIMCVEngineMessageContainer& aMessageContainer,
+ MIMCVEngineMessageReadInterface& aReadInterface,
+ CIMCVEngine& aActiveEngine,
+ TBool aScrollOver )
+ {
+ CIMCVAppMessageFlowHandler* self = new( ELeave ) CIMCVAppMessageFlowHandler(
+ aMessageContainer,
+ aReadInterface ,
+ aActiveEngine );
+
+ CleanupStack::PushL( self );
+ self->ConstructL( aScrollOver );
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+// -----------------------------------------------------------------------------
+// CIMCVAppMessageFlowHandler::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppMessageFlowHandler::ConstructL( TBool aScrollOver )
+ {
+ // construct base class
+ CTimer::ConstructL();
+
+ // for getting chat interface from CIMCVAPPAppUi
+ iActiveEngine.ChatInterface().RegisterChatListObserver(this);
+
+ // and observe changes
+ iReadInterface.SetObserver( this );
+ iReadInterface.SetActive(ETrue);
+
+ // fetch flow control value from settings
+ UpdateTimeIntervalL();
+
+ if ( aScrollOver )
+ {
+ iBgOpeningMode = EFalse;
+ }
+ else
+ {
+ iBgOpeningMode = 0 & KIMFeatBackgroundGroupOpening;
+ }
+
+ // start the timer if there are messages
+ iInitialMsgCount = iReadInterface.MessageCount();
+ if( iInitialMsgCount + iReadInterface.UnreadCount() > 0 )
+ {
+ // lock the buffer
+ iReadInterface.Lock( ETrue );
+
+ // use faster timer when constructing
+ iTimeInterval = KTimeIntervalOpen * KMilliToMicro;
+ After( iTimeInterval );
+ }
+ }
+
+
+// Destructor
+CIMCVAppMessageFlowHandler::~CIMCVAppMessageFlowHandler()
+ {
+ // for getting chat interface from CIMCVAPPAppUi
+ iActiveEngine.ChatInterface().UnregisterChatListObserver(this);
+
+ if ( !iChatDeleted )
+ {
+ iReadInterface.SetActive(EFalse);
+ iReadInterface.SetObserver( NULL );
+ iReadInterface.Lock( EFalse );
+ }
+ Cancel();
+ }
+
+
+// -----------------------------------------------------------------------------
+// CIMCVAppMessageFlowHandler::FetchMessages
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppMessageFlowHandler::FetchMessages( TBool aFetch )
+ {
+ TBool reallyInBg =
+ CCoeEnv::Static()->RootWin().OrdinalPosition() == 0 ? EFalse : ETrue;
+
+ if ( !reallyInBg && !aFetch )
+ {
+ // Application is not really in background, this can happen
+ // if key lock is activated while application is in foreground
+ aFetch = ETrue;
+ }
+
+ iFetchMessages = aFetch;
+ if( iFetchMessages && !iChatDeleted )
+ {
+ // we're allowed to fetch messages again
+ if( iReadInterface.UnreadCount() > 0 && !IsActive() )
+ {
+ // there are some unread messages
+ // => start the timer (if not active already)
+ After( iTimeInterval );
+ }
+ }
+
+ else if( iMsgIndex < iInitialMsgCount )
+ {
+ Cancel();
+ After( iTimeInterval );
+ return;
+ }
+ else
+ {
+ // we're not allowed to fetch new messages any more, so cancel the timer
+ Cancel();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppMessageFlowHandler::HandleMessageEvent
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppMessageFlowHandler::HandleMessageEvent( TMessageEventType aEvent,
+ TInt aIndex )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppMessageFlowHandler::HandleMessageEvent event %d, \
+ index %d"), aEvent, aIndex );
+ switch( aEvent )
+ {
+ case ENewMessage:
+ {
+ if( !IsActive() && iFetchMessages )
+ {
+ // if not active, start timer
+ After( iTimeInterval );
+ }
+
+ if ( IsOpening() && iBgOpeningMode )
+ {
+ // New message during opening phase
+ iNewMsgWhileOpening = ETrue;
+ }
+
+ // otherwise do nothing as timer fetches the messages
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppMessageFlowHandler::RunL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppMessageFlowHandler::RunL()
+ {
+ TBool messages( ETrue );
+ TBool opening = IsOpening();
+
+ // If we're opening the view, fetch KInitialMessages at a time, otherwise just one
+ TInt count( opening ? KInitialMessages : 1 );
+
+ while( count-- > 0 && messages )
+ {
+ if ( iBgOpeningMode && opening )
+ {
+ // Opening the chat with background message fetching.
+ // Perform steps in following order:
+ // 1. Add possible new messages that are received during
+ // the opening phase to the end of chat normally
+ // 2. Insert unread messages to the beginning of chat
+
+ if ( iNewMsgWhileOpening && iFetchMessages )
+ {
+ // Add the new message now
+ iMessages.AddMessageL( iReadInterface.ReadNextUnread() );
+
+ iNewMsgWhileOpening = EFalse;
+ }
+ else if ( iReadInterface.UnreadCount() > 0 && iFetchMessages )
+ {
+ // Insert unread messages, insert in last-to-first order
+ iAddedUnreadMsgs++;
+
+ iMessages.InsertMessageL(
+ iReadInterface.ReadUnreadFromIndex(
+ iReadInterface.MessageCount()
+ + iReadInterface.UnreadCount()
+ - iAddedUnreadMsgs ) );
+
+
+ }
+
+ else
+ {
+ // Check if the initial speed was active
+ if ( opening )
+ {
+ UpdateTimeIntervalL();
+ }
+ messages = EFalse;
+ iReadInterface.Lock( EFalse );
+ }
+ }
+ else
+ {
+ // Functionality in opening in releases 3.1 and earlier
+ // and normal functionality when the chat is already fully opened
+ // and new messages are received.
+
+ // Add unread messages in first-to-last order
+ if ( iReadInterface.UnreadCount() > 0 )
+ {
+ // Add unread messages
+ iMessages.AddMessageL( iReadInterface.ReadNextUnread() );
+
+ }
+ else
+ {
+ // Check if the initial speed was active
+ if ( opening )
+ {
+ UpdateTimeIntervalL();
+ }
+ messages = EFalse;
+ iReadInterface.Lock( EFalse );
+ }
+ }
+ }
+
+ // And restart timer if needed
+ if ( messages )
+ {
+ Cancel();
+ After( iTimeInterval );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppMessageFlowHandler::RunError
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CIMCVAppMessageFlowHandler::RunError( TInt aError )
+ {
+ IM_CV_LOGS(TXT("CIMCVAppMessageFlowHandler::RunError (%d)"), aError );
+
+ // Something leaved in RunL
+ if( aError == KErrNoMemory )
+ {
+ // inform user about low memory
+ CActiveScheduler::Current()->Error( aError );
+ }
+
+ if( IsActive() )
+ {
+ // stop processing messages
+ Cancel();
+ }
+
+ return KErrNone;
+ }
+
+
+
+// -----------------------------------------------------------------------------
+// CIMCVAppMessageFlowHandler::UpdateTimeIntervalL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppMessageFlowHandler::UpdateTimeIntervalL()
+ {
+ // codescanner warning can be ignored
+ TInt flowSetting( 10 );
+
+ // flowSetting is from KSettingValueMin to KSettingValueMax
+ TInt range( KSettingValueMax - KSettingValueMin );
+ TInt newRange( KTimeIntervalFast - KTimeIntervalSlow );
+
+ // convert it to a range from KTimeIntervalSlow to KTimeIntervalFast
+ TInt flowSpeed( (flowSetting-KSettingValueMin)*newRange / range );
+
+ // update the end point
+ flowSpeed += KTimeIntervalSlow;
+
+ // validate the result
+ if( flowSpeed > KTimeIntervalSlow )
+ {
+ flowSpeed = KTimeIntervalSlow;
+ }
+
+ if( flowSpeed < KTimeIntervalFast )
+ {
+ flowSpeed = KTimeIntervalFast;
+ }
+
+ // and convert from milliseconds to microseconds
+ iTimeInterval = flowSpeed * KMilliToMicro;
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppMessageFlowHandler::IsOpening
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CIMCVAppMessageFlowHandler::IsOpening() const
+ {
+ return iTimeInterval ==
+ TTimeIntervalMicroSeconds32( KTimeIntervalOpen * KMilliToMicro );
+ }
+
+// -----------------------------------------------------------------------------
+// CIMCVAppMessageFlowHandler: HandleChatListEvent
+// -----------------------------------------------------------------------------
+//
+void CIMCVAppMessageFlowHandler::HandleChatListEvent( TInt /*aServiceId*/, TChatListEventType aEvent,
+ MIMCVEngineMessageReadInterface* /*aContainerInfo*/
+ )
+ {
+
+ switch (aEvent)
+ {
+ case EChatItemAdded:
+ {
+ break;
+ }
+
+ case EChatItemDeleted:
+ {
+ iChatDeleted = ETrue;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ }
+
+// End of File