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 + -
显示快捷键?