chxavnavipanecontrol.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 802 行 · 第 1/2 页

CPP
802
字号
/*============================================================================*
 *
 * (c) 1995-2002 RealNetworks, Inc. Patents pending. All rights reserved.
 *
 *============================================================================*/

/*

   Description: 

   draws and manages navi pane area; display comprises a status area at the
   left and a timer area at the right; the status area displays status text
   or status images

*/

#include <aknutils.h>
#include "chxavmisc.h"
#include "chxavcleanupstack.h"
#include "chxavcleanstring.h"
#include "hxsym_debug.h"
#include "hxsym_leaveutil.h"
#include "realplayer.mbg"
#include "chxavnavipanecontrol.h"

namespace
{
_LIT(KEllipse, "...");
const TUint KTimerTextMaxChars = 10;
const TUint k_msStatusBlinkInterval = 700;
const TUint k_msAnimateEllipseInterval = 800;

const TUint CX_PANE_LEFT_BORDER             = 0;
const TUint CX_PAUSE_INDIC_RIGHT_BORDER     = 4;
const TUint CX_MUTE_INDIC_RIGHT_BORDER      = 4;
const TUint CX_STATUS_TEXT_RIGHT_BORDER     = 2;
const TUint CX_PANE_RIGHT_BORDER            = 2;
const TUint CX_TIMER_TEXT_RIGHT_BORDER      = 2;

// control ids
enum
{   
    CID_TIMER_TEXT = 1,
    CID_STATUS_TEXT,
    CID_ELLIPSE_TEXT
};



////////////////////////////////////////////
// (re) initialize image control; create control
// if not created yet; position defaults to parent 
// left, vertically centered
void InitStatusImage
(
refptr<CEikImage>& spImageOut,
const CCoeControl& parentControl,
bool bVisible, 
TInt idxImage, 
TInt idxMask
)
{
    if(!spImageOut)
    {
        spImageOut = new (ELeave) CEikImage();
        spImageOut->SetContainerWindowL(parentControl);
    }

    const TRect& rcParent = parentControl.Rect();

    // set the images from image file
    TFileName* pImageFilePath = CHXAvFile::AllocAppFolderPathL(CHXAvUtil::KImagesMBMName);
    AUTO_PUSH_POP_DEL(pImageFilePath);
    spImageOut->CreatePictureFromFileL(*pImageFilePath, idxImage, idxMask);

    TRect rc;
    TSize size = spImageOut->MinimumSize();

    // set image top-left
    rc.iTl.iX = rcParent.iTl.iX;
    
    // center vertically
    rc.iTl.iY = (rcParent.Height() - size.iHeight) / 2;
    
    // set and update image rect
    rc.SetSize(size);
    spImageOut->SetRect(rc);

    spImageOut->MakeVisible(bVisible);
    spImageOut->ActivateL();

}

} // ns anon


////////////////////////////////
//
CHXAvNaviPaneControl* CHXAvNaviPaneControl::NewL(CHXAvPlayer* pPlayer, const CCoeControl& parent)
{
    CHXAvNaviPaneControl* pSelf = new(ELeave) CHXAvNaviPaneControl();
    AUTO_PUSH_POP(pSelf);
    pSelf->ConstructL(pPlayer, parent);
    return pSelf;
}

////////////////////////////////////////
//
CHXAvNaviPaneControl::CHXAvNaviPaneControl()
: m_bBlinkIsVisible(false)
, m_bHideTimerForStatusText(false)
, m_bNeedRefresh(false)
, m_ellipseCount(0)
{
}


////////////////////////////////////////
//
CHXAvNaviPaneControl::~CHXAvNaviPaneControl()
{
    if(m_spPlayer)
    {
        m_spPlayer->GetPlayerState().RemoveObserver(this);
    }

}


////////////////////////////
//
void CHXAvNaviPaneControl::ConstructL(CHXAvPlayer* pPlayer, const CCoeControl& parent)
{
  
    m_spPlayer = pPlayer;
    m_spPlayer->GetPlayerState().AddObserver(this);

    SetContainerWindowL(parent);
    TRect rc(parent.Rect());
    SetRect(rc);

    // save this; we want to draw over whole navi control (see SizeChanged)
    m_rcParent = rc;

    // XXXLCM move blink and animate logic to subclass of text control!

    // blink callback for pause indicator
    const CHXAvCommand& cmdToggle =
        MakeCommand(this, &CHXAvNaviPaneControl::ToggleStatusBlinkAndDraw);
    m_cbBlink.ConstructL(cmdToggle);

    // animate callback for ellipses (e.g., connecting...)
    const CHXAvCommand& cmdAnimate =
        MakeCommand(this, &CHXAvNaviPaneControl::OnAnimateEllipseTick);
    m_cbAnimateEllipse.ConstructL(cmdAnimate);
    
  
    //
    // play state image (pause indicator)
    //
    InitStatusImage(m_spPlayStateImage, *this, false,
        EMbmRealplayerQgn_indi_paused, EMbmRealplayerQgn_indi_paused_mask);
 
    //
    // vol state image (mute indicator)
    //
    InitStatusImage(m_spVolStateImage, *this, m_spPlayer->IsMuted(),
        EMbmRealplayerVol_mute,EMbmRealplayerVol_mute_mask);

    //
    // live state images
    //
    InitStatusImage(m_spLiveStateOnImage, *this, false,
        EMbmRealplayerQgn_indi_live_enabled, EMbmRealplayerQgn_indi_live_enabled_mask);
    InitStatusImage(m_spLiveStateOffImage, *this, false,
        EMbmRealplayerQgn_indi_live_disabled, EMbmRealplayerQgn_indi_live_disabled_mask);
    
    //
    // timer text
    //
   
    m_spTimerText = CHXAvTextControl::NewL(*this, CID_TIMER_TEXT);
    m_spTimerText->SetTruncateWithEllipsis(false);
    m_spTimerText->SetJustification(CGraphicsContext::ERight);
    m_spTimerText->SetTextColor(KRgbWhite);
    //m_spTimerText->SetBackgroundColor(TRgb(0,0,225));
    //NumberPlain5 (very small and rectangular)
    m_spTimerText->UpdateFont(LatinBold12());

    //
    // status text
    //
    m_spStatusText = CHXAvTextControl::NewL(*this, CID_STATUS_TEXT);
    m_spStatusText->SetTextColor(KRgbWhite);
    m_spStatusText->UpdateFont(LatinPlain12());
    m_spStatusText->MakeVisible(EFalse);

    //
    // ellipse following (part of) status text
    //
    m_spEllipseText = CHXAvTextControl::NewL(*this, CID_ELLIPSE_TEXT);
    m_spEllipseText->SetTextColor(KRgbWhite);
    m_spEllipseText->UpdateFont(LatinPlain12());
    m_spEllipseText->MakeVisible(EFalse);

    // position controls that never change size/location unless parent rect changes
    DoStaticLayout();

    // temporary rects (adjusted as text is displayed)
    m_spTimerText->SetRect(rc);
    m_spStatusText->SetRect(rc);

    m_bNeedRefresh = true;
   
}

////////////////////////////////////////////////////
//
void CHXAvNaviPaneControl::SizeChanged()
{
    // navi control container re-sizes us (a decorator) to fit within
    // its window; this is the parent rect size less space for scroll
    // arrows; we want to draw over the area where the scroll arrows would
    // go (we never use them), so we ignore our true rect (XXXLCM nicer 
    // if we could just turn off scroll arrows)
 
    // if( constructed ) { DoStaticLayout(); } // no!
}

////////////////////////////////////////////////
//
// layout controls in their proper positions; vertical positions should be set
// during construction and never change; henceforth, these positions never change
//
void CHXAvNaviPaneControl::DoStaticLayout()
{
    // {pause indic}{mute indic}{timer text}{live status}

    TRect rcRegion = m_rcParent; //Rect();

    // pause indicator goes at far left (plus border)
    TPoint ptPause = m_spPlayStateImage->Position();
    ptPause.iX = CX_PANE_LEFT_BORDER;
    m_spPlayStateImage->SetPosition(ptPause);

    // mute image goes just to right of pause indicator (plus border)
    TPoint ptMute = m_spVolStateImage->Position();
    ptMute.iX = m_spPlayStateImage->Rect().iBr.iX + CX_PAUSE_INDIC_RIGHT_BORDER;
    m_spVolStateImage->SetPosition(ptMute);

    // live status images go at far right (minus right border)
    TPoint ptLiveState = m_spLiveStateOnImage->Position();
    ptLiveState.iX = rcRegion.iBr.iX - (m_spLiveStateOnImage->Size().iWidth + CX_PANE_RIGHT_BORDER);
    m_spLiveStateOnImage->SetPosition(ptLiveState);
    m_spLiveStateOffImage->SetPosition(ptLiveState);

}

////////////////////////////////////////////////////
// calculate max area available for timer text
void CHXAvNaviPaneControl::GetTimerTextMaxArea(TRect& rc)
{

    bool bLiveStateVisible = (m_spLiveStateOnImage->IsVisible() || m_spLiveStateOffImage->IsVisible());

    // area (between left-most visible image and right-most visible image) goes to timer text
    rc = m_rcParent;
    if( bLiveStateVisible )
    {
        rc.iBr.iX = m_spLiveStateOnImage->Position().iX - CX_TIMER_TEXT_RIGHT_BORDER;
    }
    else
    {
        rc.iBr.iX -= CX_PANE_RIGHT_BORDER;
    }

    rc.iTl.iX = m_spPlayStateImage->Rect().iBr.iX + CX_PAUSE_INDIC_RIGHT_BORDER;

    HX_ASSERT(rc.iTl.iX < rc.iBr.iX);
    
}

    

////////////////////////////////////////////////////
// update status text to reflect player state and show
// if necessary; hide or show status images
//
// timer text should be updated first
//
void CHXAvNaviPaneControl::UpdateStatusAreaL()
{    
    const CHXAvPlayerState& state = m_spPlayer->GetPlayerState(); 
    DPRINTF(SYMP_INFO, ("CHXAvNaviPaneControl::UpdateStatusAreaL(): state = '%s'\n", dbg::State(state.GetState())));
    
    HBufC* pbuff = 0;

    bool bAnimateEllipse = false;
    
    switch(state.GetState())
    {
    case CHXAvPlayerState::Connecting:
        HX_ASSERT(m_spPlayer->IsRemotePlayback());
        HX_ASSERT(!m_spPlayer->HasPresStarted());
        pbuff = CHXAvStringUtils::AllocResTextL(R_AVP_ST_CONNECTING);
        bAnimateEllipse = true;
	break; 
    case CHXAvPlayerState::Playing:
        {
            // only show buffering messages for remote clips
            if(m_spPlayer->IsRemotePlayback())
            {
                TInt resId;
                switch(state.GetBufferingState())
                {
                    // show 'loading' when first buffering and after a seek
                    case CHXAvPlayerState::BufferLoad:
                    case CHXAvPlayerState::BufferSeek:
	                resId = R_AVP_ST_LOADING_FORMAT;
	                break;
                    // show 'communicating' when buffering after congestion
                    case CHXAvPlayerState::BufferPlain:
                        resId = R_AVP_ST_BUFFERING_FORMAT;
                        break;
                    default:
                        resId = -1;
                        break;
                }
                if(resId != -1)
                {
                    pbuff = CHXAvStringUtils::AllocResFormatTextL(resId, state.GetLastBufferPercent());
                }
            }
        }
	break;
    default:
        //
	// no status text for this state
        //
        // note: we can be in a buffering sub-state while paused and/or seeking, but
        // we opt not to show a buffering message in these cases because it results
        // in a nicer user experience
        //
	break;
    }
    


    if(pbuff)
    {
        AUTO_PUSH_POP_DEL(pbuff);

        //
        // Ideally we want clip timer text to remain visible to right of 
        // status text. However, if status text is too long, we hide the
        // clip timer text rather than partially obscure it (which looks bad)
        //

        // width of status text
        const CFont* pFont = m_spStatusText->GetFont();
        TInt cxStatus = CX_PANE_LEFT_BORDER + pFont->TextWidthInPixels(*pbuff) + CX_STATUS_TEXT_RIGHT_BORDER;

        // width of ellipse
        TInt cxEllipse = 0;
        if(bAnimateEllipse)
        {
            pFont = m_spStatusText->GetFont();
            cxEllipse += pFont->TextWidthInPixels(KEllipse);
        }
            

        // width needed to display status and timer text
        TInt cxNeeded =  cxStatus + cxEllipse + m_spTimerText->Size().iWidth + CX_TIMER_TEXT_RIGHT_BORDER;
        TInt cxAvail = m_rcParent.Width();
        if( cxNeeded > cxAvail )
        {
            // not enough room to show status and timer text
            m_bHideTimerForStatusText = true;
        }

        // status text starts at far left
        TRect rcStatus = m_rcParent;
        rcStatus.iTl.iX += CX_PANE_LEFT_BORDER;
        rcStatus.SetWidth(cxStatus);

        // set and show status text
        UpdateRectHelper(m_spStatusText.Ptr(), rcStatus);
        UpdateTextHelper(m_spStatusText.Ptr(), *pbuff);
        UpdateVisibilityHelper(m_spStatusText.Ptr(), true);

        if(bAnimateEllipse)
        {
            // set and show ellipses after status
            HX_ASSERT(cxEllipse > 0);
         
            TRect rcEllipse(rcStatus.iBr.iX, rcStatus.iTl.iY, rcStatus.iBr.iX + cxEllipse, rcStatus.iBr.iY);
            UpdateRectHelper(m_spEllipseText.Ptr(), rcEllipse);
            // start with empty ellipse - animation will fill it out as time goes by
            UpdateTextHelper(m_spEllipseText.Ptr(), _L("")); 
            m_ellipseCount = 0;
        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?