javauis/lcdui_akn/lcdui/src/CMIDTicker.cpp
branchRCL_3
changeset 19 04becd199f91
child 60 6c158198356e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/lcdui/src/CMIDTicker.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,1235 @@
+/*
+* Copyright (c) 2006 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:  Implementation of the Ticker component
+*
+*/
+
+
+#include <eikenv.h>
+#include <coecntrl.h>
+#include <coeccntx.h>
+#include <coecobs.h>
+// needed API for iAvkonAppUi
+#include <aknappui.h>
+#include <AknsUtils.h>
+#include <aknconsts.h>
+
+//#include <aknlayoutdef.h>
+//#include <aknlayout.lag>
+// CAknLayoutFont API for font layouting
+#include <AknLayoutFont.h>
+
+#include <aknenv.h>
+// CAknIndicatorContainer API for updating text capacity indicator
+#include <AknIndicatorContainer.h>
+// MAknEditingStateIndicator API for updating text capacity indicator
+// and setting state to edit indicators
+#include <aknEditStateIndicator.h>
+#include <aknnavi.h>
+// CAknNavigationDecorator* iNaviDecorator
+#include <aknnavide.h>
+
+#include <AknsDrawUtils.h>
+#include <j2me/jdebug.h>
+#include "CMIDTicker.h"
+// needed for setting and removing displayables (iDisplayableRArray)
+#include "CMIDDisplayable.h"
+// CMIDUtils::MapJavaToETextChars in CMIDScrollingText::SetTextL
+#include "CMIDUtils.h"
+#include "CMIDUIManager.h"
+
+/**
+ * To enable ticker tracing, uncomment the follwing two lines and link
+ * to estlib.lib:
+ *
+ *#include <stdio.h>
+ *#define TRACE_TICKER 1
+ */
+
+/** Time between each tick.*/
+const TInt KTickPeriod = 40000;
+
+/** Scrolling width in pixels where increment increases*/
+const TInt KScrollingWidthLimit = 200;
+
+/** Increment values for two different scrolling widths*/
+const TInt KOnePixel = 1;
+const TInt KTwoPixels = 2;
+
+_LIT(KLeftSquareBracket, "[");
+_LIT(KRightSquareBracket, "]");
+_LIT(KTextCapacity, "(999) ");
+
+_LIT(KLeftSmalllBracket, "(");
+_LIT(KRightSmallBracket, ")");
+
+#ifdef _DEBUG
+#define DEBUG_ARG(x) x
+#else
+#define DEBUG_ARG(x)
+#endif
+
+//
+// Private helper functions
+//
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CleanupTicker(TAny* aTicker)
+{
+    static_cast< CMIDTicker* >(aTicker)->Dispose();
+}
+
+
+// ---------------------------------------------------------------------------
+// Return the navi pane container. The method trapped should not leave.
+// ---------------------------------------------------------------------------
+//
+CAknNavigationControlContainer* NaviContainerL()
+{
+    CEikStatusPane *sp = iAvkonAppUi->StatusPane();
+    CAknNavigationControlContainer* naviC =
+        static_cast<CAknNavigationControlContainer*>(sp->ControlL(TUid::Uid(EEikStatusPaneUidNavi)));
+
+    return naviC;
+}
+
+// ---------------------------------------------------------------------------
+// Return a text layout defined in the platform LAF
+// for text to be shown in the navi pane. According to the
+// type of navi pane control the text layout may be different.
+// We have chosen to use the same layout as the edit indicator
+// text (the text showing how many chars are left in an editor).
+// To use the layout used by navi pane labels use
+// Navi_pane_texts_Line_1. This layout information determines the
+// font and the text color. Text positioning is not taken from
+// layout, the text is vertically centered and scrolled horizontally
+// instead, h aligned to the left or right of the navi pane according
+// to the directionality.
+// ---------------------------------------------------------------------------
+//
+const TAknTextLineLayout Layout()
+{
+    return AknLayout::Small_status_pane_texts_Line_1(0);
+}
+
+// ---------------------------------------------------------------------------
+// Return the text alignment according to locale alignment
+// ---------------------------------------------------------------------------
+//
+CGraphicsContext::TTextAlign TextAlign()
+{
+    return AknLayoutUtils::LayoutMirrored() ? CGraphicsContext::ERight : CGraphicsContext::ELeft;
+}
+
+//
+// class CMIDTickerController
+//
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CMIDNaviPaneController* CMIDNaviPaneController::NewL()
+{
+    CMIDNaviPaneController* self=new(ELeave) CMIDNaviPaneController();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CMIDNaviPaneController::~CMIDNaviPaneController()
+{
+    delete iTickerTimer;
+    iTickerTimer = NULL;
+    delete iEditCapacityText;
+    iTickerObservers.Close();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CMIDNaviPaneController::CMIDNaviPaneController()
+{
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::ConstructL()
+{
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::UpdateTextInputIndicatorL(TInt aCount)
+{
+    delete iEditCapacityText;
+    iEditCapacityText = NULL;
+
+    if (aCount >= 0 && aCount <= 999)
+    {
+        const CFont* font = AknLayoutUtils::FontFromId(Layout().FontId());
+        TBuf<10> text;
+
+        text.Append(KLeftSmalllBracket);
+        text.AppendNum(aCount);
+        text.Append(KRightSmallBracket);
+
+        // set text localized (non Latin numbers)
+        AknTextUtils::LanguageSpecificNumberConversion(text);
+
+        iEditCapacityText = TBidiText::NewL(text,1);
+        iEditCapacityText->WrapText(font->TextWidthInPixels(KTextCapacity), *font, NULL);
+
+        AddEditCapacityTextToNaviPaneL();
+    }
+    else
+    {
+        // to prevent panic if state indicator is NULL (it can happen when 3rd party FEP is active)
+        MAknEditingStateIndicator* indicator = CAknEnv::Static()->EditingStateIndicator();
+        if (indicator)
+        {
+            indicator->IndicatorContainer()->SetIndicatorState(
+                TUid::Uid(EAknNaviPaneEditorIndicatorMessageLength),
+                EAknIndicatorStateOff);
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBidiText* CMIDNaviPaneController::EditCapacityText() const
+{
+    return iEditCapacityText;
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::AddTickerObserverL(
+    MMIDTickerObserver* aObserver)
+{
+    ASSERT(aObserver);
+    if (iTickerObservers.Find(aObserver) == KErrNotFound)
+    {
+        User::LeaveIfError(iTickerObservers.Append(aObserver));
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::RemoveTickerObserver(
+    MMIDTickerObserver* aObserver)
+{
+    ASSERT(aObserver);
+    TInt index = iTickerObservers.Find(aObserver);
+    if (index != KErrNotFound)
+    {
+        iTickerObservers.Remove(index);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::SetTickerL(CMIDTicker* aTicker)
+{
+    if (!iTickerTimer && !aTicker)
+    {
+        // CMIDTickerTimer instance is created only when
+        // a ticker object is set
+        return;
+    }
+    if (!iTickerTimer)
+    {
+        iTickerTimer = CMIDTickerTimer::NewL(this);
+    }
+    iTickerTimer->SetTickerL(aTicker);
+}
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::ShowTickerL(TBool aShow)
+{
+    if (iTickerTimer)
+    {
+        iTickerTimer->ShowTickerL(aShow);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::PauseTickerL(
+    TInt aInterval, MMIDTickerObserver* aPausingObserver)
+{
+    if (aInterval > 0)
+    {
+        // Set last observer to pause the ticker
+        iPausingObserver = aPausingObserver;
+    }
+    if (iTickerTimer)
+    {
+        iTickerTimer->PauseTickerL(aInterval, aPausingObserver);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::TickerChangedL(CMIDTicker* aTicker, TTickerEvent aEvent)
+{
+    if (iTickerTimer)
+    {
+        iTickerTimer->TickerChangedL(aTicker, aEvent);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::LayoutTickerL()
+{
+    if (iTickerTimer)
+    {
+        iTickerTimer->LayoutTickerL();
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::ResetTickerScrollingSpeedL()
+{
+    if (iTickerTimer)
+    {
+        iTickerTimer->ResetScrollingSpeedL();
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::NotifyTickerObservers(TBool aShowing)
+{
+    TInt numObservers = iTickerObservers.Count();
+    for (TInt index = 0; index < numObservers; index++)
+    {
+        iTickerObservers[ index ]->TickerShowing(aShowing);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDNaviPaneController::AddEditCapacityTextToNaviPaneL()
+{
+    if (iEditCapacityText != NULL &&
+            (!iTickerTimer ||
+             !iTickerTimer->iEnabled ||
+             !iTickerTimer->iTicker))
+    {
+        // to prevent panic if state indicator is NULL (it can happen when 3rd party FEP is active)
+        MAknEditingStateIndicator* indicator = CAknEnv::Static()->EditingStateIndicator();
+        if (indicator)
+        {
+            indicator->IndicatorContainer()->SetIndicatorState(
+                TUid::Uid(EAknNaviPaneEditorIndicatorMessageLength), EAknIndicatorStateOn);
+            indicator->IndicatorContainer()->SetIndicatorValueL(
+                TUid::Uid(EAknNaviPaneEditorIndicatorMessageLength), iEditCapacityText->Text());
+        }
+    }
+}
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CMIDTickerTimer* CMIDTickerTimer::NewL(CMIDNaviPaneController* aController)
+{
+    CMIDTickerTimer* self=new(ELeave) CMIDTickerTimer(aController);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CMIDTickerTimer::~CMIDTickerTimer()
+{
+    DEBUG("CMIDTickerTimer::~CMIDTickerTimer - calling StopL");
+    TRAPD(ignore,StopL());
+    if (ignore != KErrNone)
+    {
+        DEBUG_INT("CMIDTickerTimer::~CMIDTickerTimer - Exception from StopL. Error = %d", ignore);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CMIDTickerTimer::CMIDTickerTimer(CMIDNaviPaneController* aCtrl)
+        : CTimer(CActive::EPriorityHigh)
+        , iCtrl(aCtrl)
+        , iTicker(NULL)
+        , iEnabled(EFalse)
+        , iIncrement(KOnePixel)
+{
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::ConstructL()
+{
+    CTimer::ConstructL();
+    ResetScrollingSpeedL();
+    CActiveScheduler::Add(this);
+}
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::RunL()
+{
+    if (iIsPaused)
+    {
+        iIsPaused = EFalse;
+        StartL();
+        return;
+    }
+
+    if (iTicker)
+    {
+        iTicker->TickL(iIncrement);
+        Kick();
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::TickerChangedL(
+    CMIDTicker* aTicker, CMIDNaviPaneController::TTickerEvent aEvent)
+{
+    ASSERT(aTicker == iTicker);
+    (void)aTicker; // Just to suppress warning in release build
+    switch (aEvent)
+    {
+    case CMIDNaviPaneController::ENone:
+    case CMIDNaviPaneController::EModelChanged:
+        // ignore
+        break;
+    case CMIDNaviPaneController::ETextChanged:
+        break;
+
+    case CMIDNaviPaneController::EPositionChanged:
+        iTicker->RenderL();
+        break;
+    }
+}
+
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::ShowTickerL(TBool aShow)
+{
+    if (aShow)
+    {
+        StartL();
+    }
+    else
+    {
+        StopL();
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::SetTickerL(CMIDTicker* aTicker)
+{
+    if (iTicker != aTicker)
+    {
+        if (iTicker)
+        {
+            iTicker->StopL();
+            iTicker->SetController(NULL);
+            iTicker->RemoveRef();
+        }
+
+        iTicker = aTicker;
+
+        if (iTicker)
+        {
+            iTicker->AddRef();
+            iTicker->SetController(iCtrl);
+        }
+    }
+    else
+    {
+        if (iTicker)
+        {
+            iTicker->PauseL();
+        }
+    }
+
+    // If the ticker is paused for textfield and textbox and displayable is changed
+    // cancel the pause timer and  start the ticker
+    if (iIsPaused)
+    {
+        Cancel();
+    }
+
+    CheckedStart();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::PauseTickerL(TInt aInterval, MMIDTickerObserver* aPausingObserver)
+{
+    if (aInterval <= 0)
+    {
+        if (iCtrl->iPausingObserver == aPausingObserver)
+        { //only last requesting pausing observer can annulate request
+            iIsPaused = EFalse;
+            StartL();
+        }
+    }
+    else
+    {
+        PauseL();
+        After(aInterval);
+        iIsPaused = ETrue;
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::StartL()
+{
+    Cancel();
+
+    iEnabled = ETrue;
+    iCtrl->NotifyTickerObservers(iEnabled && iTicker);
+
+    if (iTicker)
+    {
+        iTicker->StartL();
+    }
+
+    iCtrl->iPausingObserver = NULL;
+    iIsPaused = EFalse;
+
+    CheckedStart();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::PauseL()
+{
+    Cancel();
+
+    iEnabled = EFalse;
+    iCtrl->NotifyTickerObservers(iEnabled);
+
+    if (iTicker)
+    {
+        iTicker->PauseL();
+    }
+
+    iCtrl->AddEditCapacityTextToNaviPaneL();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::StopL()
+{
+    iEnabled = EFalse;
+    iCtrl->NotifyTickerObservers(iEnabled);
+
+    if (iTicker)
+    {
+        iTicker->StopL();
+    }
+
+    iCtrl->AddEditCapacityTextToNaviPaneL();
+
+    Cancel();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::CheckedStart()
+{
+    if (!iEnabled)
+    {
+        return;
+    }
+    if (NULL == iTicker)
+    {
+        return;
+    }
+
+    if (!IsActive())
+    {
+        Kick();
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::Kick()
+{
+    ASSERT(iEnabled);
+    ASSERT(iTicker);
+    if (!IsActive())
+    {
+        After(KTickPeriod);
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::LayoutTickerL()
+{
+    ResetScrollingSpeedL();
+    if (iTicker)
+    {
+        iTicker->LayoutL();
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTickerTimer::ResetScrollingSpeedL()
+{
+    if (CMIDScrollingText::ScrollingWidthL() <= KScrollingWidthLimit)
+    {
+        iIncrement = KOnePixel;
+    }
+    else
+    {
+        iIncrement = KTwoPixels;
+    }
+}
+
+//
+// class CMIDTicker
+//
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+MMIDTicker* CMIDTicker::NewL(const TDesC& aText)
+{
+    CMIDTicker* ticker = new(ELeave) CMIDTicker;
+    CleanupStack::PushL(TCleanupItem(CleanupTicker, ticker));
+    ticker->ConstructL(aText);
+    CleanupStack::Pop();
+    return ticker;
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CMIDTicker::CMIDTicker() :
+        iRefCount(1)
+{
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CMIDTicker::~CMIDTicker()
+{
+    DEBUG("CMIDTicker::~CMIDTicker - calling StopL and RemoveDisplayableFromArrayL");
+    TRAPD(ignore, StopL(); RemoveDisplayableFromArrayL(NULL));
+    if (ignore != KErrNone)
+    {
+        DEBUG_INT("CMIDTicker::~CMIDTicker - Exception from StopL or RemoveDisplayableFromArrayL. Error = %d", ignore);
+    }
+    iDisplayableRArray.Reset();
+    iDisplayableRArray.Close();
+
+    delete iNaviDecorator;
+    iNaviScrollingText = NULL; //deleted by navi decorator
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::ConstructL(const TDesC& aText)
+{
+    CAknNavigationControlContainer* naviC = NaviContainerL();
+
+    iNaviScrollingText = CMIDScrollingText::NewL(this,aText);
+    iNaviScrollingText->SetContainerWindowL(*naviC);
+    iNaviScrollingText->SetExtent(TPoint(0,0), naviC->Size());
+
+    iNaviDecorator = CAknNavigationDecorator::NewL(naviC, iNaviScrollingText, CAknNavigationDecorator::ENotSpecified);
+    iNaviDecorator->SetContainerWindowL(*naviC);
+    iNaviDecorator->MakeScrollButtonVisible(EFalse);
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::Dispose()
+{
+    if (iController)
+    {
+        TRAPD(ignore, iController->SetTickerL(NULL));
+        if (ignore != KErrNone)
+        {
+            DEBUG_INT("CMIDTicker::Dispose - Exception from CMIDNaviPaneController::SetTickerL(NULL). Error = %d", ignore);
+        }
+    }
+    delete this;
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::SetTextL(const TDesC& aText)
+{
+    iNaviScrollingText->SetTextL(aText);
+}
+
+void CMIDTicker::AddRef()
+{
+    ++iRefCount;
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::RemoveRef()
+{
+    ASSERT(iRefCount);
+    --iRefCount;
+    if (0 == iRefCount)
+    {
+        delete this;
+    }
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::SetDisplayableL(CMIDDisplayable* aDisplayable, TInt aAdd)
+{
+    ASSERT(aDisplayable);
+
+    if (aAdd)
+    { //KAddDisplayable:
+        iDisplayableRArray.Append(aDisplayable);
+    }
+    else
+    {
+        RemoveDisplayableFromArrayL(aDisplayable);
+    }
+}
+
+// ---------------------------------------------------------------------------
+// if aDisplayable is not null then remove it
+// if aDisplayable is NULL mean remove all
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::RemoveDisplayableFromArrayL(CMIDDisplayable* aDisplayable)
+{
+    // if aDisplayable is not null then remove it.
+    if (aDisplayable)
+    {
+        TInt index = iDisplayableRArray.Find(aDisplayable);
+        if (index != KErrNotFound)
+        {
+            CMIDDisplayable* displayable = iDisplayableRArray[index];
+            iDisplayableRArray.Remove(index);
+            displayable->SetTickerL(NULL);
+        }
+    }
+    else
+    {// if aDisplayable is null mean remove all
+        TInt count = iDisplayableRArray.Count();
+        for (TInt ii = 0; ii<count; ii++)
+        {
+            // Always remove the Zeroth element as we are removing
+            // the element array size is changing (reducing).
+            CMIDDisplayable* displayable = iDisplayableRArray[0]; // index zero is required
+            iDisplayableRArray.Remove(0);// index zero is required
+            displayable->SetTickerL(NULL);
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+// Start the ticker: we must disable any edit indicators (this is done by observers
+// but there is an observer, CDateFieldItem, which uses an editor (CEikMfne) which is not
+// FEP aware and hence cannot disable the edit indicators at the right time. So we have to
+// do it in here instead. The push the navi decorator on the navi pane. This will assure
+// our scrolling text will be drawn. */
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::StartL()
+{
+    if (iNaviScrollingText->Size() == TSize(0,0))
+    {
+        iNaviScrollingText->SetExtent(TPoint(0,0), NaviContainerL()->Size());
+        iNaviScrollingText->UpdateTickerLayoutL();
+    }
+
+    // to prevent panic if state indicator is NULL (it can happen when 3rd party FEP is active)
+    MAknEditingStateIndicator* indicator = CAknEnv::Static()->EditingStateIndicator();
+    if (indicator)
+    {
+        indicator->SetState(EStateNone);
+    }
+    NaviContainerL()->PushL(*iNaviDecorator);
+    iNaviScrollingText->SetPaused(EFalse);
+}
+
+// ---------------------------------------------------------------------------
+// Pause the ticker, inform ScrollingText about pause mode, and remove our
+// navi decorator from the navi pane. */
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::PauseL()
+{
+    iNaviScrollingText->SetPaused(ETrue);
+    NaviContainerL()->Pop(iNaviDecorator);
+}
+
+
+// ---------------------------------------------------------------------------
+// Stop the ticker: just remove our navi decorator from the navi pane. */
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::StopL()
+{
+    NaviContainerL()->Pop(iNaviDecorator);
+    iNaviScrollingText->SetPaused(EFalse);
+}
+
+// ---------------------------------------------------------------------------
+// The text position is updated every tick, this achieves text scrolling. */
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::TickL(TInt aIncrement)
+{
+    iNaviScrollingText->UpdateTextPositionL(aIncrement);
+}
+
+void CMIDTicker::SetController(CMIDNaviPaneController* aController)
+{
+    iController = aController;
+}
+
+CMIDNaviPaneController* CMIDTicker::Controller() const
+{
+    return iController;
+}
+
+void CMIDTicker::ReportEventL(CMIDNaviPaneController::TTickerEvent aEvent)
+{
+    if (iController)
+    {
+        iController->TickerChangedL(this, aEvent);
+    }
+}
+
+// ---------------------------------------------------------------------------
+// Relayout ScrollingText, cancel pause mode.
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::LayoutL()
+{
+    iNaviScrollingText->SetPaused(EFalse);
+    iNaviScrollingText->UpdateTickerLayoutL();
+}
+
+// ---------------------------------------------------------------------------
+// Redraw the status pane (out scrolling text is transparent so we need
+// the status pane to draw the navi pane background for us)
+// ---------------------------------------------------------------------------
+//
+void CMIDTicker::RenderL()
+{
+    iAvkonAppUi->StatusPane()->DrawNow();
+}
+
+//
+// CMIDScrollingText
+//
+
+CMIDScrollingText* CMIDScrollingText::NewL(CMIDTicker* aParent, const TDesC& aText)
+{
+    CMIDScrollingText* self = new(ELeave) CMIDScrollingText(aParent);
+    CleanupStack::PushL(self);
+    self->ConstructL(aText);
+    CleanupStack::Pop(self);
+    return self;
+}
+
+CMIDScrollingText::~CMIDScrollingText()
+{
+    delete iPictographInterface;
+    delete iText;
+}
+
+void CMIDScrollingText::UpdateTickerLayoutL()
+{
+    const CFont* font = AknLayoutUtils::FontFromId(Layout().FontId());
+    const CAknLayoutFont* layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull(font);
+
+    if (layoutFont)
+    {
+        iBaseLineOffset = (iSize.iHeight - layoutFont->TextPaneHeight())/2 + layoutFont->TextPaneTopToBaseline();
+    }
+    else
+    {
+        iBaseLineOffset = (iSize.iHeight - font->HeightInPixels())/2 + font->AscentInPixels();
+    }
+
+    iTextWidth = font->TextWidthInPixels(iText->Text());
+
+    if (!iPaused)
+    {
+        InitialiseScrollingTextPosition();
+    }
+}
+
+void CMIDScrollingText::SetPaused(TBool aPause)
+{
+    iPaused = aPause;
+}
+
+void CMIDScrollingText::SetTextL(const TDesC& aText)
+{
+    HBufC* buf = aText.AllocL();
+    CMIDUtils::MapJavaToETextChars(buf,EFalse);
+    delete iText;
+    iText = NULL;
+    iText = TBidiText::NewL(buf->Des(),1);
+
+    UpdateTickerLayoutL();
+}
+
+// ---------------------------------------------------------------------------
+// Static method returning an estimate of the scrolling width -
+// this must be the same for all tickers
+// ---------------------------------------------------------------------------
+//
+TInt CMIDScrollingText::ScrollingWidthL()
+{
+    const CFont* font = AknLayoutUtils::FontFromId(Layout().FontId());
+
+    TInt w = NaviContainerL()->Size().iWidth;
+    w -= (font->TextWidthInPixels(KLeftSquareBracket) + font->TextWidthInPixels(KRightSquareBracket));
+
+    return w;
+}
+
+CMIDScrollingText::CMIDScrollingText(CMIDTicker* aParent) : iParent(aParent)
+{
+}
+
+void CMIDScrollingText::ConstructL(const TDesC& aText)
+{
+    SetTextL(aText);
+
+    iPictographInterface = CAknPictographInterface::NewL(*this,*this);
+}
+
+// ---------------------------------------------------------------------------
+// Draw the text. Either "[ ... ]" or "(999) [ .. ]" where ... or .. is the
+// scrolling text. Or if device is Right to Left: either "[ ... ]" or "[..] (999)" */
+// ---------------------------------------------------------------------------
+//
+void CMIDScrollingText::Draw(const TRect& aRect) const
+{
+    TAknTextLineLayout layout = Layout();
+
+    CMIDNaviPaneController* controller = iParent->Controller();
+    const CFont* font = AknLayoutUtils::FontFromId(layout.FontId());
+    CWindowGc& gc = SystemGc();
+
+    gc.SetPenColor(TextColor());
+    gc.UseFont(font);
+
+
+    //draw edit capacity text, eg "(999)" if needed
+    if (controller && controller->EditCapacityText() != NULL)
+    {
+        gc.DrawText(controller->EditCapacityText()->Text(), aRect, iBaseLineOffset, TextAlign(), 0);
+    }
+
+    //draw "["
+    gc.DrawText(KLeftSquareBracket, TPoint(LeftTextPosition(font)
+                                           - font->TextWidthInPixels(KLeftSquareBracket),iBaseLineOffset));
+
+    //draw "]"
+    gc.DrawText(KRightSquareBracket,TPoint(RightTextPosition(font),iBaseLineOffset));
+
+
+    //clip area for scrolling text
+    gc.SetClippingRect(TRect(TPoint(LeftTextPosition(font), 0), TPoint(RightTextPosition(font), iSize.iHeight)));
+
+    //draw scrolling text
+    iText->WrapText(iTextWidth, *font,0);
+    if (iPictographInterface)
+    {
+        MAknPictographDrawer* aknPictographDrawer = iPictographInterface->Interface();
+        aknPictographDrawer->DrawText(gc, *font, iText->DisplayText(),
+                                      TPoint(iTextPosition,iBaseLineOffset));
+    }
+    else
+    {
+        iText->DrawText(gc, TPoint(iTextPosition,iBaseLineOffset));
+    }
+
+    gc.CancelClippingRect();
+}
+
+void CMIDScrollingText::HandleResourceChange(TInt aType)
+{
+    CCoeControl::HandleResourceChange(aType);
+    if (aType==KEikDynamicLayoutVariantSwitch || aType == KEikColorResourceChange)
+    {
+        if (aType == KEikDynamicLayoutVariantSwitch && iParent && iParent->Controller())
+        {//change scrolling velocity if needed
+            DEBUG("CMIDScrollingText::HandleResourceChange - calling iParent->Controller()->ResetScrollingSpeedL");
+
+            TRAPD(ignore, iParent->Controller()->ResetTickerScrollingSpeedL());
+            if (ignore != KErrNone)
+            {
+                DEBUG_INT("CMIDScrollingText::HandleResourceChange - Exception from iParent->Controller()->ResetScrollingSpeedL. Error = %d", ignore);
+            }
+        }
+
+        //reset position and layout
+        iPaused = false;
+        DEBUG("CMIDScrollingText::HandleResourceChange - calling UpdateTickerLayoutL");
+        TRAPD(ignore,UpdateTickerLayoutL());
+        if (ignore != KErrNone)
+        {
+            DEBUG_INT("CMIDScrollingText::HandleResourceChange - Exception from UpdateTickerLayoutL. Error = %d", ignore);
+        }
+
+        //and finally draw
+        DrawNow();
+    }
+}
+
+void CMIDScrollingText::SizeChanged()
+{
+    // call parent implementation
+    CCoeControl::SizeChanged();
+
+    // update layout
+    TRAP_IGNORE(UpdateTickerLayoutL());
+}
+
+void CMIDScrollingText::DrawPictographArea()
+{
+    // Does nothing - Ticker is updating himself
+}
+
+// ---------------------------------------------------------------------------
+// Scroll the text of aScrollAmount, the direction depends on the text directionality. The min
+// and max text position are given by LeftTextPosition() and RightTextPosition().
+// ---------------------------------------------------------------------------
+//
+void CMIDScrollingText::UpdateTextPositionL(TInt aScrollAmount)
+{
+    const CFont* font = AknLayoutUtils::FontFromId(Layout().FontId());
+
+    if (iPaused)
+    {
+        return;
+    }
+
+    if (iText->Directionality() == TBidiText::ELeftToRight)
+    {
+        iTextPosition -= aScrollAmount;
+        if (iTextPosition < LeftTextPosition(font) - iTextWidth)
+        {
+            iTextPosition = RightTextPosition(font);
+        }
+    }
+    else
+    {
+        iTextPosition += aScrollAmount;
+        if (iTextPosition > RightTextPosition(font))
+        {
+            iTextPosition = LeftTextPosition(font) - iTextWidth;
+        }
+    }
+
+    iParent->ReportEventL(CMIDNaviPaneController::EPositionChanged);
+}
+
+
+// ---------------------------------------------------------------------------
+// The text color, this is taken from the layout + any skinning should be taken into account.
+// ---------------------------------------------------------------------------
+//
+inline TRgb CMIDScrollingText::TextColor() const
+{
+    TRgb color = AKN_LAF_COLOR(Layout().iC);
+
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    // Ignore error, color is not updated if it not found from the skin
+    AknsUtils::GetCachedColor(skin, color, KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG2);
+
+    return color;
+}
+
+// ---------------------------------------------------------------------------
+// The space needed to draw "(999) " in pixels.
+// ---------------------------------------------------------------------------
+//
+inline TInt CMIDScrollingText::EditCapacityWidth(const CFont* aFont) const
+{
+    CMIDNaviPaneController* controller = iParent->Controller();
+
+    if (controller && controller->EditCapacityText() != NULL)
+    {
+        return aFont->TextWidthInPixels(KTextCapacity);
+    }
+    return 0;
+}
+
+// ---------------------------------------------------------------------------
+// The left position for scrolling text. According to the device directionality
+// we must add or not the edit capacity width.
+// ---------------------------------------------------------------------------
+//
+inline TInt CMIDScrollingText::LeftTextPosition(const CFont* aFont) const
+{
+    return aFont->TextWidthInPixels(KLeftSquareBracket) +
+           (TextAlign() == CGraphicsContext::ELeft ? EditCapacityWidth(aFont) : 0);
+}
+
+// ---------------------------------------------------------------------------
+// The right position for scrolling text. According to the device directionality
+// must add or not the edit capacity width.
+// ---------------------------------------------------------------------------
+//
+inline TInt CMIDScrollingText::RightTextPosition(const CFont* aFont) const
+{
+    return iSize.iWidth - aFont->TextWidthInPixels(KRightSquareBracket) -
+           (TextAlign() == CGraphicsContext::ELeft ? 0 : EditCapacityWidth(aFont));
+}
+
+// ---------------------------------------------------------------------------
+// Sets the initial scrolling text position
+// ---------------------------------------------------------------------------
+//
+void CMIDScrollingText::InitialiseScrollingTextPosition()
+{
+    const CFont* font = AknLayoutUtils::FontFromId(Layout().FontId());
+    if (iText->Directionality() == TBidiText::ELeftToRight)
+    {
+        iTextPosition = RightTextPosition(font);
+    }
+    else
+    {
+        iTextPosition = LeftTextPosition(font) - iTextWidth;
+    }
+}
+
+// End of File
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+