|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <vgui_controls/ProgressBar.h>
#include <vgui_controls/Controls.h>
#include <vgui/ILocalize.h>
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include <KeyValues.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( ProgressBar );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ProgressBar::ProgressBar(Panel *parent, const char *panelName) : Panel(parent, panelName) { _progress = 0.0f; m_pszDialogVar = NULL; SetSegmentInfo( 4, 8 ); SetBarInset( 4 ); SetMargin( 0 ); m_iProgressDirection = PROGRESS_EAST; }
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
ProgressBar::~ProgressBar() { delete [] m_pszDialogVar; }
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void ProgressBar::SetSegmentInfo( int gap, int width ) { _segmentGap = gap; _segmentWide = width; }
//-----------------------------------------------------------------------------
// Purpose: returns the number of segment blocks drawn
//-----------------------------------------------------------------------------
int ProgressBar::GetDrawnSegmentCount() { int wide, tall; GetSize(wide, tall); int segmentTotal = wide / (_segmentGap + _segmentWide); return (int)(segmentTotal * _progress); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ProgressBar::PaintBackground() { int wide, tall; GetSize(wide, tall);
surface()->DrawSetColor(GetBgColor()); surface()->DrawFilledRect(0, 0, wide, tall); }
void ProgressBar::PaintSegment( int &x, int &y, int tall, int wide ) { switch( m_iProgressDirection ) { case PROGRESS_EAST: x += _segmentGap; surface()->DrawFilledRect(x, y, x + _segmentWide, y + tall - (y * 2)); x += _segmentWide; break;
case PROGRESS_WEST: x -= _segmentGap + _segmentWide; surface()->DrawFilledRect(x, y, x + _segmentWide, y + tall - (y * 2)); break;
case PROGRESS_NORTH: y -= _segmentGap + _segmentWide; surface()->DrawFilledRect(x, y, x + wide - (x * 2), y + _segmentWide ); break;
case PROGRESS_SOUTH: y += _segmentGap; surface()->DrawFilledRect(x, y, x + wide - (x * 2), y + _segmentWide ); y += _segmentWide; break; } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ProgressBar::Paint() { int wide, tall; GetSize(wide, tall);
// gaps
int segmentTotal = 0, segmentsDrawn = 0; int x = 0, y = 0;
switch( m_iProgressDirection ) { case PROGRESS_WEST: wide -= 2 * m_iBarMargin; x = wide - m_iBarMargin; y = m_iBarInset; segmentTotal = wide / (_segmentGap + _segmentWide); segmentsDrawn = (int)(segmentTotal * _progress); break;
case PROGRESS_EAST: wide -= 2 * m_iBarMargin; x = m_iBarMargin; y = m_iBarInset; segmentTotal = wide / (_segmentGap + _segmentWide); segmentsDrawn = (int)(segmentTotal * _progress); break;
case PROGRESS_NORTH: tall -= 2 * m_iBarMargin; x = m_iBarInset; y = tall - m_iBarMargin; segmentTotal = tall / (_segmentGap + _segmentWide); segmentsDrawn = (int)(segmentTotal * _progress); break;
case PROGRESS_SOUTH: tall -= 2 * m_iBarMargin; x = m_iBarInset; y = m_iBarMargin; segmentTotal = tall / (_segmentGap + _segmentWide); segmentsDrawn = (int)(segmentTotal * _progress); break; }
surface()->DrawSetColor(GetFgColor()); for (int i = 0; i < segmentsDrawn; i++) { PaintSegment( x, y, tall, wide ); } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ProgressBar::SetProgress(float progress) { if (progress != _progress) { // clamp the progress value within the range
if (progress < 0.0f) { progress = 0.0f; } else if (progress > 1.0f) { progress = 1.0f; }
_progress = progress; Repaint(); } }
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
float ProgressBar::GetProgress() { return _progress; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ProgressBar::ApplySchemeSettings(IScheme *pScheme) { Panel::ApplySchemeSettings(pScheme);
SetFgColor(GetSchemeColor("ProgressBar.FgColor", pScheme)); SetBgColor(GetSchemeColor("ProgressBar.BgColor", pScheme)); SetBorder(pScheme->GetBorder("ButtonDepressedBorder")); }
//-----------------------------------------------------------------------------
// Purpose: utility function for calculating a time remaining string
//-----------------------------------------------------------------------------
bool ProgressBar::ConstructTimeRemainingString(wchar_t *output, int outputBufferSizeInBytes, float startTime, float currentTime, float currentProgress, float lastProgressUpdateTime, bool addRemainingSuffix) { Assert(lastProgressUpdateTime <= currentTime); output[0] = 0;
// calculate pre-extrapolation values
float timeElapsed = lastProgressUpdateTime - startTime; float totalTime = timeElapsed / currentProgress;
// calculate seconds
int secondsRemaining = (int)(totalTime - timeElapsed); if (lastProgressUpdateTime < currentTime) { // old update, extrapolate
float progressRate = currentProgress / timeElapsed; float extrapolatedProgress = progressRate * (currentTime - startTime); float extrapolatedTotalTime = (currentTime - startTime) / extrapolatedProgress; secondsRemaining = (int)(extrapolatedTotalTime - timeElapsed); } // if there's some time, make sure it's at least one second left
if ( secondsRemaining == 0 && ( ( totalTime - timeElapsed ) > 0 ) ) { secondsRemaining = 1; }
// calculate minutes
int minutesRemaining = 0; while (secondsRemaining >= 60) { minutesRemaining++; secondsRemaining -= 60; }
char minutesBuf[16]; Q_snprintf(minutesBuf, sizeof( minutesBuf ), "%d", minutesRemaining); char secondsBuf[16]; Q_snprintf(secondsBuf, sizeof( secondsBuf ), "%d", secondsRemaining);
if (minutesRemaining > 0) { wchar_t unicodeMinutes[16]; g_pVGuiLocalize->ConvertANSIToUnicode(minutesBuf, unicodeMinutes, sizeof( unicodeMinutes )); wchar_t unicodeSeconds[16]; g_pVGuiLocalize->ConvertANSIToUnicode(secondsBuf, unicodeSeconds, sizeof( unicodeSeconds ));
const char *unlocalizedString = "#vgui_TimeLeftMinutesSeconds"; if (minutesRemaining == 1 && secondsRemaining == 1) { unlocalizedString = "#vgui_TimeLeftMinuteSecond"; } else if (minutesRemaining == 1) { unlocalizedString = "#vgui_TimeLeftMinuteSeconds"; } else if (secondsRemaining == 1) { unlocalizedString = "#vgui_TimeLeftMinutesSecond"; }
char unlocString[64]; Q_strncpy(unlocString, unlocalizedString,sizeof( unlocString )); if (addRemainingSuffix) { Q_strncat(unlocString, "Remaining", sizeof(unlocString ), COPY_ALL_CHARACTERS); } g_pVGuiLocalize->ConstructString(output, outputBufferSizeInBytes, g_pVGuiLocalize->Find(unlocString), 2, unicodeMinutes, unicodeSeconds);
} else if (secondsRemaining > 0) { wchar_t unicodeSeconds[16]; g_pVGuiLocalize->ConvertANSIToUnicode(secondsBuf, unicodeSeconds, sizeof( unicodeSeconds ));
const char *unlocalizedString = "#vgui_TimeLeftSeconds"; if (secondsRemaining == 1) { unlocalizedString = "#vgui_TimeLeftSecond"; } char unlocString[64]; Q_strncpy(unlocString, unlocalizedString,sizeof(unlocString)); if (addRemainingSuffix) { Q_strncat(unlocString, "Remaining",sizeof(unlocString), COPY_ALL_CHARACTERS); } g_pVGuiLocalize->ConstructString(output, outputBufferSizeInBytes, g_pVGuiLocalize->Find(unlocString), 1, unicodeSeconds); } else { return false; } return true; }
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void ProgressBar::SetBarInset( int pixels ) { m_iBarInset = pixels; }
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
int ProgressBar::GetBarInset( void ) { return m_iBarInset; }
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void ProgressBar::SetMargin( int pixels ) { m_iBarMargin = pixels; }
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
int ProgressBar::GetMargin() { return m_iBarMargin; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ProgressBar::ApplySettings(KeyValues *inResourceData) { _progress = inResourceData->GetFloat("progress", 0.0f);
const char *dialogVar = inResourceData->GetString("variable", ""); if (dialogVar && *dialogVar) { m_pszDialogVar = new char[strlen(dialogVar) + 1]; strcpy(m_pszDialogVar, dialogVar); }
BaseClass::ApplySettings(inResourceData); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ProgressBar::GetSettings(KeyValues *outResourceData) { BaseClass::GetSettings(outResourceData); outResourceData->SetFloat("progress", _progress );
if (m_pszDialogVar) { outResourceData->SetString("variable", m_pszDialogVar); } }
//-----------------------------------------------------------------------------
// Purpose: Returns a string description of the panel fields for use in the UI
//-----------------------------------------------------------------------------
const char *ProgressBar::GetDescription( void ) { static char buf[1024]; _snprintf(buf, sizeof(buf), "%s, string progress, string variable", BaseClass::GetDescription()); return buf; }
//-----------------------------------------------------------------------------
// Purpose: updates progress bar bases on values
//-----------------------------------------------------------------------------
void ProgressBar::OnDialogVariablesChanged(KeyValues *dialogVariables) { if (m_pszDialogVar) { int val = dialogVariables->GetInt(m_pszDialogVar, -1); if (val >= 0.0f) { SetProgress(val / 100.0f); } } }
DECLARE_BUILD_FACTORY( ContinuousProgressBar );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ContinuousProgressBar::ContinuousProgressBar(Panel *parent, const char *panelName) : ProgressBar(parent, panelName) { _prevProgress = -1.f; m_colorGain = Color( 100, 255, 100, 255 ); m_colorLoss = Color( 200, 45, 45, 255 ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ContinuousProgressBar::SetPrevProgress( float progress ) { if ( progress == _prevProgress ) return;
_prevProgress = ( progress == -1.f ) ? progress : clamp( progress, 0.f, 1.f ); Repaint(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ContinuousProgressBar::Paint() { int x = 0, y = 0; int wide, tall; GetSize(wide, tall);
surface()->DrawSetColor( GetFgColor() );
bool bUsePrev = _prevProgress >= 0.f; bool bGain = _progress > _prevProgress;
switch( m_iProgressDirection ) { case PROGRESS_EAST: if ( bUsePrev ) { if ( bGain ) { surface()->DrawFilledRect( x, y, x + (int)( wide * _prevProgress ), y + tall );
// Delta
surface()->DrawSetColor( m_colorGain ); surface()->DrawFilledRect( x + (int)( wide * _prevProgress ), y, x + (int)( wide * _progress ), y + tall ); break; } else { // Delta
surface()->DrawSetColor( m_colorLoss ); surface()->DrawFilledRect( x + (int)( wide * _progress ), y, x + (int)( wide * _prevProgress ), y + tall ); } } surface()->DrawSetColor( GetFgColor() ); surface()->DrawFilledRect( x, y, x + (int)( wide * _progress ), y + tall ); break;
case PROGRESS_WEST: if ( bUsePrev ) { if ( bGain ) { surface()->DrawFilledRect( x + (int)( wide * ( 1.0f - _prevProgress ) ), y, x + wide, y + tall );
// Delta
surface()->DrawSetColor( m_colorGain ); surface()->DrawFilledRect( x + (int)( wide * ( 1.0f - _progress ) ), y, x + (int)( wide * ( 1.0f - _prevProgress ) ), y + tall ); break; } else { // Delta
surface()->DrawSetColor( m_colorLoss ); surface()->DrawFilledRect( x + (int)( wide * ( 1.0f - _prevProgress ) ), y, x + (int)( wide * ( 1.0f - _progress ) ), y + tall ); } } surface()->DrawSetColor( GetFgColor() ); surface()->DrawFilledRect( x + (int)( wide * ( 1.0f - _progress ) ), y, x + wide, y + tall ); break;
case PROGRESS_NORTH: if ( bUsePrev ) { if ( bGain ) { surface()->DrawFilledRect( x, y + (int)( tall * ( 1.0f - _prevProgress ) ), x + wide, y + tall );
// Delta
surface()->DrawSetColor( m_colorGain ); surface()->DrawFilledRect( x, y + (int)( tall * ( 1.0f - _progress ) ), x + wide, y + (int)( tall * ( 1.0f - _prevProgress ) ) ); break; } else { // Delta
surface()->DrawSetColor( m_colorLoss ); surface()->DrawFilledRect( x, y + (int)( tall * ( 1.0f - _prevProgress ) ), x + wide, y + (int)( tall * ( 1.0f - _progress ) ) ); } } surface()->DrawSetColor( GetFgColor() ); surface()->DrawFilledRect( x, y + (int)( tall * ( 1.0f - _progress ) ), x + wide, y + tall ); break;
case PROGRESS_SOUTH: if ( bUsePrev ) { if ( bGain ) { surface()->DrawFilledRect( x, y, x + wide, y + (int)( tall * ( 1.0f - _progress ) ) );
// Delta
surface()->DrawSetColor( m_colorGain ); surface()->DrawFilledRect( x, y + (int)( tall * ( 1.0f - _progress ) ), x + wide, y + (int)( tall * ( 1.0f - _prevProgress ) ) ); break; } else { // Delta
surface()->DrawSetColor( m_colorLoss ); surface()->DrawFilledRect( x, y + (int)( tall * ( 1.0f - _prevProgress ) ), x + wide, y + (int)( tall * ( 1.0f - _progress ) ) ); } } surface()->DrawSetColor( GetFgColor() ); surface()->DrawFilledRect( x, y, x + wide, y + (int)( tall * _progress ) ); break; } }
|