javauis/coreui_akn/src/startupscreen/startscreencontainer.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 21 Jun 2010 15:32:50 +0300
branchRCL_3
changeset 21 4376525cdefb
parent 17 0fd27995241b
permissions -rw-r--r--
Revision: v2.1.30 Kit: 2010125

/*
 * Copyright (c) 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: The CCoeControl for the start screen.
 *
 */

#include <aknlayoutscalable_apps.cdl.h>
#include <data_caging_path_literals.hrh>
#include <AknsDrawUtils.h>
#include <AknUtils.h>
#ifdef RD_JAVA_S60_RELEASE_9_2
#include <alf/alfdrawer.h>
#endif // RD_JAVA_S60_RELEASE_9_2

#include "startscreencontainer.h"
#include "startscreen.h"
#include "logger.h"
#include "eswt.h"

const int KStartScreenTimeLimit = 10000; // miliseconds
const int KStartScreenFadeTimeLimit = 3000; // miliseconds
const int KStartScreenFadeTreshold = 500; // miliseconds

CStartScreenContainer* CStartScreenContainer::NewL(
    java::ui::JavaUiAvkonAppUi& appUi,
    const java::ui::CoreUiParams& coreUiParams)
{
    JELOG2(EJavaUI);
    CStartScreenContainer* self = new(ELeave) CStartScreenContainer(appUi,
            coreUiParams);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
}

CStartScreenContainer::~CStartScreenContainer()
{
    JELOG2(EJavaUI);

    if (!mAppUi.destroying()) 
    {
        if (HidesIndicators())
        {
            ShowIndicators(ETrue);
        }
    }

    mFader.FadeBehindPopup(this, this, EFalse);
    mAppUi.RemoveFromStack(this);

    if (mStartScreenTimer)
    {
        mStartScreenTimer->Stop();
        delete mStartScreenTimer;
        mStartScreenTimer = 0;
    }
    if (mStartScreen)
    {
        delete mStartScreen;
        mStartScreen = 0;
    }
    if (mCba)
    {
        delete mCba;
        mCba = 0;
    }
    if (mBgContext)
    {
        delete mBgContext;
        mBgContext = 0;
    }
}

void CStartScreenContainer::HandleForeground(bool aForeground)
{
    JELOG2(EJavaUI);

    if (!aForeground)
    {
        if (!mCba)
        {
            mStartScreenTimer->Pause();
        }
    }
    else
    {
        if (!mCba)
        {
            mStartScreenTimer->Start();
        }
    }
}

void CStartScreenContainer::ShowExitScreen()
{
     TRAP_IGNORE(DoShowExitScreenL());
}

void CStartScreenContainer::DoShowExitScreenL()
{
    JELOG2(EJavaUI);

    TRect rect;
    AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, rect);

    // Turn CBA on
    TRAPD(err, mCba = CEikButtonGroupContainer::NewL(
                          CEikButtonGroupContainer::ECba,
                          CEikButtonGroupContainer::EHorizontal,
                          &mAppUi,
                          0,
                          CEikButtonGroupContainer::EAddToStack));
    if (err != KErrNone)
    {
        ELOG1(EJavaUI, "CStartScreenContainer::ShowExitScreen, "
              "CEikButtonGroupContainer::NewL failed: %d", err);
        return;
    }
    mCba->SetBoundingRect(rect);

    // Show "Exit" RSK on CBA
    TRAP(err, mCba->SetCommandSetL(R_AVKON_SOFTKEYS_EXIT));
    if (err != KErrNone)
    {
        ELOG1(EJavaUI, "CStartScreenContainer::ShowExitScreen, "
              "CEikButtonGroupContainer::SetCommandSetL failed: %d", err);
    }

    // Create background, as we stop being transparent
    if (!mBgContext)
    {
        mBgContext = CAknsBasicBackgroundControlContext::NewL(KAknsIIDQsnBgScreen,
                     rect, ETrue);
    }

    // Add to stack if not already added.
    if (!mStartScreen || mStartScreen->IsEmpty())
    {
        SetRect(rect);
        mAppUi.AddToStackL(this);
        ActivateL();
        MakeVisible(ETrue);
    }

    // Stop fading behind if user defined start screen.
    if (mStartScreen && mStartScreen->Type() == CStartScreen::EStartScreenUserDefined)
    {
        mFader.FadeBehindPopup(this, this, EFalse);
        DrawDeferred();
    }

    // Show the status pane (title pane)
    CEikStatusPane* pane = mAppUi.StatusPane();
    pane->MakeVisible(ETrue);
    if (HidesIndicators())
        ShowIndicators(EFalse);

    // Push behind SP and CBA
    Window().SetOrdinalPosition(0, -1);

    mExitScreenOn = ETrue;
}

void CStartScreenContainer::AsyncSaveL(TCallBack aCallBack)
{
    if (!mStartScreen || mStartScreen->Type() != CStartScreen::EStartScreenAutomatic)
    {
        aCallBack.CallBack();
        return;
    }

    // Save the new start time if going over the treshold.
    TTime time;
    time.UniversalTime();
    TInt64 newTime = time.Int64() - mAppUi.startupTime();
    newTime /= 1000; // from microseconds to miliseconds
    if (mStartTimeKnown)
    {
        if (mFaded)
        {
            // The application started in more than 3 seconds.
            // Override only if lower than 2.5 seconds.
            if (newTime + KStartScreenFadeTreshold < KStartScreenFadeTimeLimit)
                mStartScreen->SaveStartupTime(newTime);
        }
        else
        {
            // The application started in less than 3 seconds.
            // Override only if higher than 3.5 seconds.
            if (newTime - KStartScreenFadeTreshold > KStartScreenFadeTimeLimit)
                mStartScreen->SaveStartupTime(newTime);
        }
    }
    else
    {
        mStartScreen->SaveStartupTime(newTime);
    }

    // Take away the start screen, to uncover the app's UI.
    HideL();

    // Ensure the app's UI is flushed to the screen and take the screenshot.
    FlushScreenL();
    mStartScreen->AsyncSaveScreenL(aCallBack);
}

void CStartScreenContainer::HideL()
{
    mFaded = EFalse;

    // The application is starting to draw so no need for exit screen.
    if (mStartScreenTimer)
    {
        mStartScreenTimer->Stop();
    }

    // If the exit screen has been shown, hide the CBA
    if (mCba)
    {
        mCba->MakeVisible(EFalse);
    }

    // Keep the window on the screen but lower the z-order
    // The following lines of code must stay in this order!
    FlushScreenL();
    Window().SetOrdinalPosition(0, ESwtWinPriorityInactiveTopShell);
    DrawNow();
}

TBool CStartScreenContainer::HidesIndicators() const
{
#ifdef RD_JAVA_S60_RELEASE_9_2
    return (mStartScreen && mStartScreen->Type() == CStartScreen::EStartScreenAutomatic);
#else
    return EFalse;
#endif
}

void CStartScreenContainer::Draw(const TRect& aRect) const
{
    JELOG2(EJavaUI);
    CWindowGc& gc = SystemGc();
    if (mBgContext)
    {
        AknsDrawUtils::Background(AknsUtils::SkinInstance(), mBgContext, this, gc, aRect);
    }
    if (mStartScreen)
    {
        mStartScreen->Draw(gc, Rect());
    }
    if (mFaded)
    {
        TRgb col(0, 0, 0);
        col.SetAlpha(125);
        gc.SetBrushColor(col);
        gc.SetPenStyle(CGraphicsContext::ENullPen);
        gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
        gc.DrawRect(Rect());
    }
}

void CStartScreenContainer::HandleResourceChange(TInt aType)
{
    JELOG2(EJavaUI);
    CCoeControl::HandleResourceChange(aType);

    if (aType == KEikDynamicLayoutVariantSwitch)
    {
        TRect rect;
        AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, rect);
        SetRect(rect);
        if (mBgContext)
        {
            mBgContext->SetRect(rect);
        }

        if (mStartScreen)
        {
            mStartScreen->HandleResolutionChange();
            if (!mExitScreenOn)
            {
                MakeVisible(!mStartScreen->IsEmpty());
            }
        }

        DrawDeferred();
    }
}

TInt CStartScreenContainer::CountFadedComponents()
{
    return 1;
}

CCoeControl* CStartScreenContainer::FadedComponent(TInt /*aIndex*/)
{
    return this;
}

CStartScreenContainer::CStartScreenContainer(java::ui::JavaUiAvkonAppUi& appUi,
        const java::ui::CoreUiParams& coreUiParams)
        : CCoeControl()
        , mAppUi(appUi)
        , mCoreUiParams(coreUiParams)
{
    JELOG2(EJavaUI);
}

void CStartScreenContainer::ConstructL()
{
    JELOG2(EJavaUI);

    mStartScreenTimer = CStartScreenTimer::NewL(*this);
    mStartScreenTimer->Start();

    CreateWindowL();
    SetMopParent(&mAppUi);

    // The start screen window needs to be on top of the ui,
    // in order to hide the quirks of ui initialization.
    Window().SetOrdinalPosition(0, 10);

    TRect rect;
    AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, rect);

    TBool transparent = EFalse;
    if (mCoreUiParams.getScreenMode() == java::ui::MIDLET_DEFINED_SCREEN ||
            mCoreUiParams.getScreenMode() == java::ui::USER_DEFINED_SCREEN)
    {
        // User defined start screen.
        TRAPD(err,
              mStartScreen = CStartScreen::NewL(CStartScreen::EStartScreenUserDefined,
                                                mCoreUiParams));
        if (KErrNone != err)
        {
            ELOG1(EJavaUI, "CStartScreenContainer::ConstructL, "
                  "CStartScreen::NewL failed: %d", err);
        }
        else
        {
            // There is no point in having empty user defined start screen.
            if (mStartScreen->IsEmpty())
            {
                delete mStartScreen;
                mStartScreen = 0;
            }
        }

        if (mStartScreen)
        {
            RWindow& window = Window();

            // Try to enable window transparency
            if (CAknEnv::Static()->TransparencyEnabled())
            {
                window.SetRequiredDisplayMode(EColor16MA);
                if (window.SetTransparencyAlphaChannel() == KErrNone)
                {
                    window.SetBackgroundColor(~0);
                    transparent = ETrue;
                }
            }

            // If the user start image is fullscreen, no need for fading behind
            TSize imgSize = mStartScreen->Size();
            if (imgSize.iWidth < rect.Width() || imgSize.iHeight < rect.Height())
            {
                mFader.FadeBehindPopup(this, this, ETrue);
            }

            if (!transparent)
            {
                mBgContext = CAknsBasicBackgroundControlContext::NewL(KAknsIIDQsnBgScreen,
                             rect, ETrue);
            }
        }
    }

    if (!mStartScreen)
    {
        // Automatic start screen
        mStartScreen = CStartScreen::NewL(CStartScreen::EStartScreenAutomatic,
                                          mCoreUiParams);
        if (!mStartScreen->IsEmpty())
        {
            TInt64 period = mStartScreen->LoadStartupTime();
            if (period > 0)
            {
                mStartTimeKnown = ETrue;
                if (period > KStartScreenFadeTimeLimit)
                {
                    // Possible alternative, but too dark:
                    // Window().SetFaded(ETrue, RWindowTreeNode::EFadeWindowOnly);
                    mFaded = ETrue;
                }
            }
        }
    }

    if (HidesIndicators())
        ShowIndicators(EFalse);

    if (mStartScreen && !mStartScreen->IsEmpty())
    {
        SetRect(rect);
        mAppUi.AddToStackL(this);
        ActivateL();
        MakeVisible(ETrue);
    }
    else
    {
        MakeVisible(EFalse);
    }
}

void CStartScreenContainer::ShowIndicator(CEikStatusPane* aSp, TInt aId, TBool aVisible)
{
    TUid uid = TUid::Uid(aId);
    CEikStatusPaneBase::TPaneCapabilities subPane = aSp->PaneCapabilities(uid);
    if (subPane.IsPresent() && subPane.IsAppOwned())
    {
        CCoeControl* ctrl = NULL;
        TRAP_IGNORE(ctrl = aSp->ControlL(uid));
        if (ctrl)
        {
            ctrl->MakeVisible(aVisible);
        }
    }
}

void CStartScreenContainer::ShowIndicators(TBool aVisible)
{
    CEikStatusPane* sp = mAppUi.StatusPane();
    if (!sp)
        return;

    ShowIndicator(sp, EEikStatusPaneUidSignal, aVisible);
    ShowIndicator(sp, EEikStatusPaneUidBattery, aVisible);
    ShowIndicator(sp, EEikStatusPaneUidIndic, aVisible);
    ShowIndicator(sp, EEikStatusPaneUidMessage, aVisible);
    ShowIndicator(sp, EEikStatusPaneUidClock, aVisible);
    ShowIndicator(sp, EEikStatusPaneUidDigitalClock, aVisible);

    if (aVisible)
        sp->DrawNow();
}

void CStartScreenContainer::FlushScreenL()
{
#ifdef RD_JAVA_S60_RELEASE_9_2
    CAlfDrawer* drawer = CAlfDrawer::NewL();
    CleanupStack::PushL(drawer);
    TInt err = drawer->Finish();
    CleanupStack::PopAndDestroy(drawer);

    if (KErrNone != err)
    {
        // Try again
        ELOG1(EJavaUI, "CStartScreenContainer::FlushScreenL, "
              "CAlfDrawer::Finish failed: %d", err);
        iEikonEnv->WsSession().Flush();
        iEikonEnv->WsSession().Finish();
    }
#else
    iEikonEnv->WsSession().Flush();
    iEikonEnv->WsSession().Finish();
#endif // RD_JAVA_S60_RELEASE_9_2
}

CStartScreenTimer* CStartScreenTimer::NewL(CStartScreenContainer& aSc)
{
    JELOG2(EJavaUI);

    CStartScreenTimer* self = new(ELeave) CStartScreenTimer(aSc);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
}

CStartScreenTimer::~CStartScreenTimer()
{
    JELOG2(EJavaUI);
    Cancel();
}

void CStartScreenTimer::Start()
{
    JELOG2(EJavaUI);
    // Converting secs to micro secs.
    mTimerStartTime.HomeTime();
    if (!IsActive())
    {
        TInt timerVal = (TInt)(mTimerValue.Int64());
        if (timerVal > 0)
        {
            After(timerVal);
        }
        else
        {
            mSc.ShowExitScreen();
        }
    }
}

void CStartScreenTimer::Pause()
{
    JELOG2(EJavaUI);
    if (IsActive())
    {
        TTime currentTime;
        currentTime.HomeTime();
        TTimeIntervalMicroSeconds delta(currentTime.MicroSecondsFrom(
                                            mTimerStartTime));
        mTimerValue = mTimerValue.Int64() - delta.Int64();
        Stop();
    }
}

void CStartScreenTimer::Stop()
{
    JELOG2(EJavaUI);
    if (IsActive())
        Cancel();
}

void CStartScreenTimer::RunL()
{
    JELOG2(EJavaUI);
    mSc.ShowExitScreen();
}

void CStartScreenTimer::DoCancel()
{
    CTimer::DoCancel();
}

CStartScreenTimer::CStartScreenTimer(
    CStartScreenContainer& aSc) :
        CTimer(CActive::EPriorityStandard), mSc(aSc), mTimerValue(
            KStartScreenTimeLimit * 1000)

{
    JELOG2(EJavaUI);
    CActiveScheduler::Add(this);
}

void CStartScreenTimer::ConstructL()
{
    JELOG2(EJavaUI);
    CTimer::ConstructL();
}