This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions

View File

@ -0,0 +1,460 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <vgui_controls/AnalogBar.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( AnalogBar );
#define ANALOG_BAR_HOME_SIZE 4
#define ANALOG_BAR_HOME_GAP 2
#define ANALOG_BAR_LESS_TALL ( ANALOG_BAR_HOME_SIZE + ANALOG_BAR_HOME_GAP )
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
AnalogBar::AnalogBar(Panel *parent, const char *panelName) : Panel(parent, panelName)
{
_analogValue = 0.0f;
m_pszDialogVar = NULL;
SetSegmentInfo( 2, 6 );
SetBarInset( 0 );
m_iAnalogValueDirection = PROGRESS_EAST;
m_fHomeValue = 2.0f;
m_HomeColor = GetFgColor();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
AnalogBar::~AnalogBar()
{
delete [] m_pszDialogVar;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void AnalogBar::SetSegmentInfo( int gap, int width )
{
_segmentGap = gap;
_segmentWide = width;
}
//-----------------------------------------------------------------------------
// Purpose: returns the number of segment blocks drawn
//-----------------------------------------------------------------------------
int AnalogBar::GetDrawnSegmentCount()
{
int wide, tall;
GetSize(wide, tall);
int segmentTotal = wide / (_segmentGap + _segmentWide);
return (int)(segmentTotal * _analogValue);
}
//-----------------------------------------------------------------------------
// Purpose: returns the total number of segment blocks drawn (active and inactive)
//-----------------------------------------------------------------------------
int AnalogBar::GetTotalSegmentCount()
{
int wide, tall;
GetSize(wide, tall);
int segmentTotal = wide / (_segmentGap + _segmentWide);
return segmentTotal;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void AnalogBar::PaintBackground()
{
// Don't draw a background
}
void AnalogBar::PaintSegment( int &x, int &y, int tall, int wide, Color color, bool bHome )
{
switch( m_iAnalogValueDirection )
{
case PROGRESS_EAST:
x += _segmentGap;
if ( bHome )
{
surface()->DrawSetColor( GetHomeColor() );
surface()->DrawFilledRect(x, y, x + _segmentWide, y + ANALOG_BAR_HOME_SIZE );
surface()->DrawFilledRect(x, y + tall - (y * 2) - ANALOG_BAR_HOME_SIZE, x + _segmentWide, y + tall - (y * 2) );
}
surface()->DrawSetColor( color );
surface()->DrawFilledRect(x, y + ANALOG_BAR_LESS_TALL, x + _segmentWide, y + tall - (y * 2) - ANALOG_BAR_LESS_TALL );
x += _segmentWide;
break;
case PROGRESS_WEST:
x -= _segmentGap + _segmentWide;
if ( bHome )
{
surface()->DrawSetColor( GetHomeColor() );
surface()->DrawFilledRect(x, y, x + _segmentWide, y + ANALOG_BAR_HOME_SIZE );
surface()->DrawFilledRect(x, y + tall - (y * 2) - ANALOG_BAR_HOME_SIZE, x + _segmentWide, y + tall - (y * 2) );
}
surface()->DrawSetColor( color );
surface()->DrawFilledRect(x, y + ANALOG_BAR_LESS_TALL, x + _segmentWide, y + tall - (y * 2) - ANALOG_BAR_LESS_TALL );
break;
case PROGRESS_NORTH:
y -= _segmentGap + _segmentWide;
if ( bHome )
{
surface()->DrawSetColor( GetHomeColor() );
surface()->DrawFilledRect(x, y, x + ANALOG_BAR_HOME_SIZE, y + _segmentWide );
surface()->DrawFilledRect(x + wide - (x * 2) - ANALOG_BAR_HOME_SIZE, y, x + wide - (x * 2), y + _segmentWide );
}
surface()->DrawSetColor( color );
surface()->DrawFilledRect(x + ANALOG_BAR_LESS_TALL, y, x + wide - (x * 2) - ANALOG_BAR_LESS_TALL, y + _segmentWide);
break;
case PROGRESS_SOUTH:
y += _segmentGap;
if ( bHome )
{
surface()->DrawSetColor( GetHomeColor() );
surface()->DrawFilledRect(x, y, x + ANALOG_BAR_HOME_SIZE, y + _segmentWide );
surface()->DrawFilledRect(x + wide - (x * 2) - ANALOG_BAR_HOME_SIZE, y, x + wide - (x * 2), y + _segmentWide );
}
surface()->DrawSetColor( color );
surface()->DrawFilledRect(x + ANALOG_BAR_LESS_TALL, y, x + wide - (x * 2) - ANALOG_BAR_LESS_TALL, y + _segmentWide);
y += _segmentWide;
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void AnalogBar::Paint()
{
int wide, tall;
GetSize(wide, tall);
// gaps
int segmentTotal = 0, segmentsDrawn = 0;
int x = 0, y = 0;
switch( m_iAnalogValueDirection )
{
case PROGRESS_WEST:
x = wide;
y = m_iBarInset;
segmentTotal = wide / (_segmentGap + _segmentWide);
segmentsDrawn = (int)(segmentTotal * _analogValue + 0.5f);
break;
case PROGRESS_EAST:
x = 0;
y = m_iBarInset;
segmentTotal = wide / (_segmentGap + _segmentWide);
segmentsDrawn = (int)(segmentTotal * _analogValue + 0.5f);
break;
case PROGRESS_NORTH:
x = m_iBarInset;
y = tall;
segmentTotal = tall / (_segmentGap + _segmentWide);
segmentsDrawn = (int)(segmentTotal * _analogValue + 0.5f);
break;
case PROGRESS_SOUTH:
x = m_iBarInset;
y = 0;
segmentTotal = tall / (_segmentGap + _segmentWide);
segmentsDrawn = (int)(segmentTotal * _analogValue + 0.5f);
break;
}
int iHomeIndex = (int)( segmentTotal * m_fHomeValue + 0.5f ) - 1;
if ( iHomeIndex < 0 )
iHomeIndex = 0;
for (int i = 0; i < segmentsDrawn; i++)
PaintSegment( x, y, tall, wide, GetFgColor(), i == iHomeIndex );
for (int i = segmentsDrawn; i < segmentTotal; i++)
PaintSegment( x, y, tall, wide, GetBgColor(), i == iHomeIndex );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void AnalogBar::SetAnalogValue(float analogValue)
{
if (analogValue != _analogValue)
{
// clamp the analogValue value within the range
if (analogValue < 0.0f)
{
analogValue = 0.0f;
}
else if (analogValue > 1.0f)
{
analogValue = 1.0f;
}
_analogValue = analogValue;
Repaint();
}
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
float AnalogBar::GetAnalogValue()
{
return _analogValue;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void AnalogBar::ApplySchemeSettings(IScheme *pScheme)
{
Panel::ApplySchemeSettings(pScheme);
SetBgColor( Color( 255 - GetFgColor().r(), 255 - GetFgColor().g(), 255 - GetFgColor().b(), GetFgColor().a() ) );
}
//-----------------------------------------------------------------------------
// Purpose: utility function for calculating a time remaining string
//-----------------------------------------------------------------------------
bool AnalogBar::ConstructTimeRemainingString(wchar_t *output, int outputBufferSizeInBytes, float startTime, float currentTime, float currentAnalogValue, float lastAnalogValueUpdateTime, bool addRemainingSuffix)
{
Assert( outputBufferSizeInBytes >= sizeof(output[0]) );
Assert(lastAnalogValueUpdateTime <= currentTime);
output[0] = 0;
// calculate pre-extrapolation values
float timeElapsed = lastAnalogValueUpdateTime - startTime;
float totalTime = timeElapsed / currentAnalogValue;
// calculate seconds
int secondsRemaining = (int)(totalTime - timeElapsed);
if (lastAnalogValueUpdateTime < currentTime)
{
// old update, extrapolate
float analogValueRate = currentAnalogValue / timeElapsed;
float extrapolatedAnalogValue = analogValueRate * (currentTime - startTime);
float extrapolatedTotalTime = (currentTime - startTime) / extrapolatedAnalogValue;
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 AnalogBar::SetBarInset( int pixels )
{
m_iBarInset = pixels;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
int AnalogBar::GetBarInset( void )
{
return m_iBarInset;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void AnalogBar::ApplySettings(KeyValues *inResourceData)
{
_analogValue = inResourceData->GetFloat("analogValue", 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 AnalogBar::GetSettings(KeyValues *outResourceData)
{
BaseClass::GetSettings(outResourceData);
outResourceData->SetFloat("analogValue", _analogValue );
if (m_pszDialogVar)
{
outResourceData->SetString("variable", m_pszDialogVar);
}
}
//-----------------------------------------------------------------------------
// Purpose: Returns a string description of the panel fields for use in the UI
//-----------------------------------------------------------------------------
const char *AnalogBar::GetDescription( void )
{
static char buf[1024];
_snprintf(buf, sizeof(buf), "%s, string analogValue, string variable", BaseClass::GetDescription());
return buf;
}
//-----------------------------------------------------------------------------
// Purpose: updates analogValue bar bases on values
//-----------------------------------------------------------------------------
void AnalogBar::OnDialogVariablesChanged(KeyValues *dialogVariables)
{
if (m_pszDialogVar)
{
int val = dialogVariables->GetInt(m_pszDialogVar, -1);
if (val >= 0.0f)
{
SetAnalogValue(val / 100.0f);
}
}
}
DECLARE_BUILD_FACTORY( ContinuousAnalogBar );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ContinuousAnalogBar::ContinuousAnalogBar(Panel *parent, const char *panelName) : AnalogBar(parent, panelName)
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ContinuousAnalogBar::Paint()
{
int x = 0, y = 0;
int wide, tall;
GetSize(wide, tall);
surface()->DrawSetColor(GetFgColor());
switch( m_iAnalogValueDirection )
{
case PROGRESS_EAST:
surface()->DrawFilledRect( x, y, x + (int)( wide * _analogValue ), y + tall );
break;
case PROGRESS_WEST:
surface()->DrawFilledRect( x + (int)( wide * ( 1.0f - _analogValue ) ), y, x + wide, y + tall );
break;
case PROGRESS_NORTH:
surface()->DrawFilledRect( x, y + (int)( tall * ( 1.0f - _analogValue ) ), x + wide, y + tall );
break;
case PROGRESS_SOUTH:
surface()->DrawFilledRect( x, y, x + wide, y + (int)( tall * _analogValue ) );
break;
}
}

View File

@ -0,0 +1,216 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#define PROTECTED_THINGS_DISABLE
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include <vgui/ISystem.h>
#include <vgui/IImage.h>
#include <vgui/IVGui.h>
#include <KeyValues.h>
#include <vgui_controls/AnimatingImagePanel.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( AnimatingImagePanel );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
AnimatingImagePanel::AnimatingImagePanel(Panel *parent, const char *name) : Panel(parent, name)
{
m_iCurrentImage = 0;
m_iFrameTimeMillis = 100; // 10Hz frame rate
m_iNextFrameTime = 0;
m_pImageName = NULL;
m_bFiltered = false;
m_bScaleImage = false;
m_bAnimating = false;
ivgui()->AddTickSignal(GetVPanel());
}
//-----------------------------------------------------------------------------
// Purpose: Layout the panel for drawing.
//-----------------------------------------------------------------------------
void AnimatingImagePanel::PerformLayout()
{
Panel::PerformLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Add an image to the end of the list of animations
//-----------------------------------------------------------------------------
void AnimatingImagePanel::AddImage(IImage *image)
{
m_Frames.AddToTail(image);
if ( !m_bScaleImage && image != NULL )
{
int wide,tall;
image->GetSize(wide,tall);
SetSize(wide,tall);
}
}
//-----------------------------------------------------------------------------
// Purpose: Load a set of animations by name.
// Input:
// baseName: is the name of the animations without their frame number or
// file extension, (e.g. c1.tga becomes just c.)
// framecount: number of frames in the animation
//-----------------------------------------------------------------------------
void AnimatingImagePanel::LoadAnimation(const char *baseName, int frameCount)
{
m_Frames.RemoveAll();
for (int i = 1; i <= frameCount; i++)
{
char imageName[512];
Q_snprintf(imageName, sizeof( imageName ), "%s%d", baseName, i);
AddImage(scheme()->GetImage(imageName, m_bFiltered));
}
}
//-----------------------------------------------------------------------------
// Purpose: Draw the current image
//-----------------------------------------------------------------------------
void AnimatingImagePanel::PaintBackground()
{
if ( m_Frames.IsValidIndex( m_iCurrentImage ) && m_Frames[m_iCurrentImage] != NULL )
{
IImage *pImage = m_Frames[m_iCurrentImage];
surface()->DrawSetColor( 255, 255, 255, 255 );
pImage->SetPos(0, 0);
if ( m_bScaleImage )
{
// Image size is stored in the bitmap, so temporarily set its size
// to our panel size and then restore after we draw it.
int imageWide, imageTall;
pImage->GetSize( imageWide, imageTall );
int wide, tall;
GetSize( wide, tall );
pImage->SetSize( wide, tall );
pImage->SetColor( Color( 255,255,255,255 ) );
pImage->Paint();
pImage->SetSize( imageWide, imageTall );
}
else
{
pImage->Paint();
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Called every frame the panel is visible
//-----------------------------------------------------------------------------
void AnimatingImagePanel::OnTick()
{
if (m_bAnimating && system()->GetTimeMillis() >= m_iNextFrameTime)
{
m_iNextFrameTime = system()->GetTimeMillis() + m_iFrameTimeMillis;
m_iCurrentImage++;
if (!m_Frames.IsValidIndex(m_iCurrentImage))
{
m_iCurrentImage = 0;
}
Repaint();
}
}
//-----------------------------------------------------------------------------
// Purpose: Get control settings for editing
// Output: outResourceData- a set of keyvalues of imagenames.
//-----------------------------------------------------------------------------
void AnimatingImagePanel::GetSettings(KeyValues *outResourceData)
{
BaseClass::GetSettings(outResourceData);
if (m_pImageName)
{
outResourceData->SetString("image", m_pImageName);
}
}
//-----------------------------------------------------------------------------
// Purpose: Applies resource settings
//-----------------------------------------------------------------------------
void AnimatingImagePanel::ApplySettings(KeyValues *inResourceData)
{
BaseClass::ApplySettings(inResourceData);
const char *imageName = inResourceData->GetString("image", NULL);
if (imageName)
{
m_bScaleImage = ( inResourceData->GetInt( "scaleImage", 0 ) == 1 );
delete [] m_pImageName;
int len = Q_strlen(imageName) + 1;
m_pImageName = new char[len];
Q_strncpy(m_pImageName, imageName, len);
// add in the command
LoadAnimation(m_pImageName, inResourceData->GetInt("frames"));
}
m_iFrameTimeMillis = inResourceData->GetInt( "anim_framerate", 100 );
}
//-----------------------------------------------------------------------------
// Purpose: Get editing details
//-----------------------------------------------------------------------------
const char *AnimatingImagePanel::GetDescription()
{
static char buf[1024];
Q_snprintf(buf, sizeof(buf), "%s, string image", BaseClass::GetDescription());
return buf;
}
//-----------------------------------------------------------------------------
// Purpose: Starts the image doing its animation
//-----------------------------------------------------------------------------
void AnimatingImagePanel::StartAnimation()
{
m_bAnimating = true;
// ivgui()->AddTickSignal(GetVPanel());
}
//-----------------------------------------------------------------------------
// Purpose: Stops the images animation
//-----------------------------------------------------------------------------
void AnimatingImagePanel::StopAnimation()
{
m_bAnimating = false;
// ivgui()->RemoveTickSignal(GetVPanel());
}
//-----------------------------------------------------------------------------
// Purpose: Resets the animation to the start of the sequence.
//-----------------------------------------------------------------------------
void AnimatingImagePanel::ResetAnimation(int frame)
{
if(m_Frames.IsValidIndex(frame))
{
m_iCurrentImage = frame;
}
else
{
m_iCurrentImage = 0;
}
Repaint();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,364 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#include "vgui_controls/BitmapImagePanel.h"
#include "vgui/ISurface.h"
#include "vgui/IScheme.h"
#include "vgui/IBorder.h"
#include "KeyValues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
using namespace vgui;
//-----------------------------------------------------------------------------
/**
* Simple utility function to allocate memory and duplicate a string
*/
static inline char *CloneString( const char *str )
{
char *cloneStr = new char [ strlen(str)+1 ];
strcpy( cloneStr, str );
return cloneStr;
}
DECLARE_BUILD_FACTORY_DEFAULT_TEXT( CBitmapImagePanel, BitmapImagePanel );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CBitmapImagePanel::CBitmapImagePanel( Panel *parent, char const *panelName,
char const *filename /*= NULL*/ ) : Panel( parent, panelName )
{
m_pImage = NULL;
SetBounds( 0, 0, 100, 100 );
m_pszImageName = NULL;
m_pszColorName = NULL;
m_hardwareFiltered = false;
m_preserveAspectRatio = false;
m_contentAlignment = Label::a_center;
if ( filename && filename[ 0 ] )
{
m_pImage = scheme()->GetImage( filename, NULL );
m_pszImageName = CloneString( filename );
}
m_bgColor = Color(255, 255, 255, 255);
}
CBitmapImagePanel::~CBitmapImagePanel()
{
delete [] m_pszImageName;
delete [] m_pszColorName;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBitmapImagePanel::ComputeImagePosition(int &x, int &y, int &w, int &h)
{
if (!m_pImage)
{
x = y = w = h = 0;
return;
}
if ( !m_preserveAspectRatio )
{
x = y = 0;
GetSize( w, h );
return;
}
int panelWide, panelTall;
GetSize( panelWide, panelTall );
int imageWide, imageTall;
m_pImage->GetSize( imageWide, imageTall );
if ( panelWide > 0 && panelTall > 0 && imageWide > 0 && imageTall > 0 )
{
float xScale = (float)panelWide / (float)imageWide;
float yScale = (float)panelTall / (float)imageTall;
float scale = min( xScale, yScale );
w = (int) (imageWide * scale);
h = (int) (imageTall * scale);
switch (m_contentAlignment)
{
case Label::a_northwest:
x = y = 0;
break;
case Label::a_north:
x = (panelWide - w) / 2;
y = 0;
break;
case Label::a_northeast:
x = (panelWide - w);
y = 0;
break;
case Label::a_west:
x = 0;
y = (panelTall - h) / 2;
break;
case Label::a_center:
x = (panelWide - w) / 2;
y = (panelTall - h) / 2;
break;
case Label::a_east:
x = (panelWide - w);
y = (panelTall - h) / 2;
break;
case Label::a_southwest:
x = (panelWide - w);
y = 0;
break;
case Label::a_south:
x = (panelWide - w);
y = (panelTall - h) / 2;
break;
case Label::a_southeast:
x = (panelWide - w);
y = (panelTall - h);
break;
default:
x = y = 0;
break;
}
}
else
{
x = y = 0;
w = panelWide;
h = panelTall;
return;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBitmapImagePanel::PaintBorder()
{
int x, y, w, h;
ComputeImagePosition(x, y, w, h);
IBorder *pBorder = GetBorder();
if ( pBorder )
pBorder->Paint( x, y, x+w, y+h, -1, 0, 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBitmapImagePanel::PaintBackground()
{
if (!m_pImage)
return;
int x, y, w, h;
ComputeImagePosition(x, y, w, h);
m_pImage->SetPos(x, y);
m_pImage->SetSize( w, h );
m_pImage->SetColor( m_bgColor );
surface()->DrawSetColor( m_bgColor );
m_pImage->Paint();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBitmapImagePanel::setTexture( char const *filename, bool hardwareFiltered )
{
m_hardwareFiltered = hardwareFiltered;
if ( m_pszImageName )
{
delete[] m_pszImageName;
m_pszImageName = NULL;
}
if ( filename && filename[ 0 ] )
{
m_pImage = scheme()->GetImage( filename, m_hardwareFiltered );
m_pszImageName = CloneString( filename );
}
else
{
m_pImage = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBitmapImagePanel::SetContentAlignment(Label::Alignment alignment)
{
m_contentAlignment=alignment;
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Gets control settings for editing
//-----------------------------------------------------------------------------
void CBitmapImagePanel::GetSettings(KeyValues *outResourceData)
{
BaseClass::GetSettings(outResourceData);
if (m_pszImageName)
{
outResourceData->SetString("image", m_pszImageName);
}
if (m_pszColorName)
{
outResourceData->SetString("imagecolor", m_pszColorName);
}
const char *alignmentString = "";
switch ( m_contentAlignment )
{
case Label::a_northwest: alignmentString = "north-west"; break;
case Label::a_north: alignmentString = "north"; break;
case Label::a_northeast: alignmentString = "north-east"; break;
case Label::a_center: alignmentString = "center"; break;
case Label::a_east: alignmentString = "east"; break;
case Label::a_southwest: alignmentString = "south-west"; break;
case Label::a_south: alignmentString = "south"; break;
case Label::a_southeast: alignmentString = "south-east"; break;
case Label::a_west:
default: alignmentString = "center"; break;
}
outResourceData->SetString( "imageAlignment", alignmentString );
outResourceData->SetInt("preserveAspectRatio", m_preserveAspectRatio);
outResourceData->SetInt("filtered", m_hardwareFiltered);
}
//-----------------------------------------------------------------------------
// Purpose: Applies designer settings from res file
//-----------------------------------------------------------------------------
void CBitmapImagePanel::ApplySettings(KeyValues *inResourceData)
{
if ( m_pszImageName )
{
delete[] m_pszImageName;
m_pszImageName = NULL;
}
if ( m_pszColorName )
{
delete[] m_pszColorName;
m_pszColorName = NULL;
}
const char *imageName = inResourceData->GetString("image", "");
if (*imageName)
{
setTexture( imageName );
}
const char *colorName = inResourceData->GetString("imagecolor", "");
if (*colorName)
{
m_pszColorName = CloneString( colorName );
InvalidateLayout(false,true); // force ApplySchemeSettings to run
}
const char *keyString = inResourceData->GetString("imageAlignment", "");
if (keyString && *keyString)
{
int align = -1;
if ( !stricmp(keyString, "north-west") )
{
align = Label::a_northwest;
}
else if ( !stricmp(keyString, "north") )
{
align = Label::a_north;
}
else if ( !stricmp(keyString, "north-east") )
{
align = Label::a_northeast;
}
else if ( !stricmp(keyString, "west") )
{
align = Label::a_west;
}
else if ( !stricmp(keyString, "center") )
{
align = Label::a_center;
}
else if ( !stricmp(keyString, "east") )
{
align = Label::a_east;
}
else if ( !stricmp(keyString, "south-west") )
{
align = Label::a_southwest;
}
else if ( !stricmp(keyString, "south") )
{
align = Label::a_south;
}
else if ( !stricmp(keyString, "south-east") )
{
align = Label::a_southeast;
}
if ( align != -1 )
{
SetContentAlignment( (Label::Alignment)align );
}
}
keyString = inResourceData->GetString("preserveAspectRatio", "");
if (keyString && *keyString)
{
m_preserveAspectRatio = atoi( keyString ) != 0;
}
keyString = inResourceData->GetString("filtered", "");
if (keyString && *keyString)
{
m_hardwareFiltered = atoi( keyString ) != 0;
}
BaseClass::ApplySettings(inResourceData);
}
//-----------------------------------------------------------------------------
// Purpose: load the image, this is done just before this control is displayed
//-----------------------------------------------------------------------------
void CBitmapImagePanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings(pScheme);
if ( m_pszColorName )
{
setImageColor( pScheme->GetColor( m_pszColorName, m_bgColor ) );
}
}
//-----------------------------------------------------------------------------
// Purpose: Describes editing details
//-----------------------------------------------------------------------------
const char *CBitmapImagePanel::GetDescription()
{
static char buf[1024];
_snprintf(buf, sizeof(buf), "%s, string image, string imagecolor, alignment imageAlignment, int preserveAspectRatio, int filtered", BaseClass::GetDescription());
return buf;
}

View File

@ -0,0 +1,104 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Helper for the CHudElement class to add themselves to the list of hud elements
//
// $NoKeywords: $
//=============================================================================//
#include "vgui/IVGui.h"
#include "vgui_controls/MessageMap.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
// Start with empty list
CBuildFactoryHelper *CBuildFactoryHelper::m_sHelpers = NULL;
//-----------------------------------------------------------------------------
// Purpose: Constructs a panel factory
// Input : pfnCreate - fn Ptr to a function which generates a panel
//-----------------------------------------------------------------------------
CBuildFactoryHelper::CBuildFactoryHelper( char const *className, PANELCREATEFUNC func )
{
// Make this fatal
if ( HasFactory( className ) )
{
Error( "CBuildFactoryHelper: Factory for '%s' already exists!!!!\n", className );
}
//List is empty, or element belongs at front, insert here
m_pNext = m_sHelpers;
m_sHelpers = this;
Assert( func );
m_CreateFunc = func;
Assert( className );
m_pClassName = className;
}
//-----------------------------------------------------------------------------
// Purpose: Returns next object in list
// Output : CBuildFactoryHelper
//-----------------------------------------------------------------------------
CBuildFactoryHelper *CBuildFactoryHelper::GetNext( void )
{
return m_pNext;
}
char const *CBuildFactoryHelper::GetClassName() const
{
return m_pClassName;
}
vgui::Panel *CBuildFactoryHelper::CreatePanel()
{
if ( !m_CreateFunc )
return NULL;
return ( *m_CreateFunc )();
}
// private static meethod
bool CBuildFactoryHelper::HasFactory( char const *className )
{
CBuildFactoryHelper *p = m_sHelpers;
while ( p )
{
if ( !Q_stricmp( className, p->GetClassName() ) )
return true;
p = p->GetNext();
}
return false;
}
// static method
vgui::Panel *CBuildFactoryHelper::InstancePanel( char const *className )
{
CBuildFactoryHelper *p = m_sHelpers;
while ( p )
{
if ( !Q_stricmp( className, p->GetClassName() ) )
return p->CreatePanel();
p = p->GetNext();
}
return NULL;
}
// static method
void CBuildFactoryHelper::GetFactoryNames( CUtlVector< char const * >& list )
{
list.RemoveAll();
CBuildFactoryHelper *p = m_sHelpers;
while ( p )
{
list.AddToTail( p->GetClassName() );
p = p->GetNext();
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,216 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdarg.h>
#include <stdio.h>
#include <vgui/ISurface.h>
#include <vgui/IScheme.h>
#include <KeyValues.h>
#include <vgui_controls/Image.h>
#include <vgui_controls/CheckButton.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
void CheckImage::Paint()
{
DrawSetTextFont(GetFont());
// draw background
if (_CheckButton->IsEnabled() && _CheckButton->IsCheckButtonCheckable() )
{
DrawSetTextColor(_bgColor);
}
else
{
DrawSetTextColor(_CheckButton->GetDisabledBgColor());
}
DrawPrintChar(0, 1, 'g');
// draw border box
DrawSetTextColor(_borderColor1);
DrawPrintChar(0, 1, 'e');
DrawSetTextColor(_borderColor2);
DrawPrintChar(0, 1, 'f');
// draw selected check
if (_CheckButton->IsSelected())
{
if ( !_CheckButton->IsEnabled() )
{
DrawSetTextColor( _CheckButton->GetDisabledFgColor() );
}
else
{
DrawSetTextColor(_checkColor);
}
DrawPrintChar(0, 2, 'b');
}
}
DECLARE_BUILD_FACTORY_DEFAULT_TEXT( CheckButton, CheckButton );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CheckButton::CheckButton(Panel *parent, const char *panelName, const char *text) : ToggleButton(parent, panelName, text)
{
SetContentAlignment(a_west);
m_bCheckButtonCheckable = true;
m_bUseSmallCheckImage = false;
// create the image
_checkBoxImage = new CheckImage(this);
SetTextImageIndex(1);
SetImageAtIndex(0, _checkBoxImage, CHECK_INSET);
_selectedFgColor = Color( 196, 181, 80, 255 );
_disabledFgColor = Color(130, 130, 130, 255);
_disabledBgColor = Color(62, 70, 55, 255);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CheckButton::~CheckButton()
{
delete _checkBoxImage;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CheckButton::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
m_bUseSmallCheckImage = inResourceData->GetBool( "smallcheckimage", false );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CheckButton::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetDefaultColor( GetSchemeColor("CheckButton.TextColor", pScheme), GetBgColor() );
_checkBoxImage->_bgColor = GetSchemeColor("CheckButton.BgColor", Color(62, 70, 55, 255), pScheme);
_checkBoxImage->_borderColor1 = GetSchemeColor("CheckButton.Border1", Color(20, 20, 20, 255), pScheme);
_checkBoxImage->_borderColor2 = GetSchemeColor("CheckButton.Border2", Color(90, 90, 90, 255), pScheme);
_checkBoxImage->_checkColor = GetSchemeColor("CheckButton.Check", Color(20, 20, 20, 255), pScheme);
_selectedFgColor = GetSchemeColor("CheckButton.SelectedTextColor", GetSchemeColor("ControlText", pScheme), pScheme);
_disabledFgColor = GetSchemeColor("CheckButton.DisabledFgColor", Color(130, 130, 130, 255), pScheme);
_disabledBgColor = GetSchemeColor("CheckButton.DisabledBgColor", Color(62, 70, 55, 255), pScheme);
Color bgArmedColor = GetSchemeColor( "CheckButton.ArmedBgColor", Color(62, 70, 55, 255), pScheme);
SetArmedColor( GetFgColor(), bgArmedColor );
Color bgDepressedColor = GetSchemeColor( "CheckButton.DepressedBgColor", Color(62, 70, 55, 255), pScheme);
SetDepressedColor( GetFgColor(), bgDepressedColor );
_highlightFgColor = GetSchemeColor( "CheckButton.HighlightFgColor", Color(62, 70, 55, 255), pScheme);
SetContentAlignment(Label::a_west);
_checkBoxImage->SetFont( pScheme->GetFont( m_bUseSmallCheckImage ? "MarlettSmall" : "Marlett", IsProportional()) );
_checkBoxImage->ResizeImageToContent();
SetImageAtIndex(0, _checkBoxImage, CHECK_INSET);
// don't draw a background
SetPaintBackgroundEnabled(false);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
IBorder *CheckButton::GetBorder(bool depressed, bool armed, bool selected, bool keyfocus)
{
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Check the button
//-----------------------------------------------------------------------------
void CheckButton::SetSelected(bool state )
{
if (m_bCheckButtonCheckable)
{
// send a message saying we've been checked
KeyValues *msg = new KeyValues("CheckButtonChecked", "state", (int)state);
PostActionSignal(msg);
BaseClass::SetSelected(state);
}
}
//-----------------------------------------------------------------------------
// Purpose: sets whether or not the state of the check can be changed
//-----------------------------------------------------------------------------
void CheckButton::SetCheckButtonCheckable(bool state)
{
m_bCheckButtonCheckable = state;
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Gets a different foreground text color if we are selected
//-----------------------------------------------------------------------------
#ifdef _X360
Color CheckButton::GetButtonFgColor()
{
if (HasFocus())
{
return _selectedFgColor;
}
return BaseClass::GetButtonFgColor();
}
#else
Color CheckButton::GetButtonFgColor()
{
if ( IsArmed() )
{
return _highlightFgColor;
}
if (IsSelected())
{
return _selectedFgColor;
}
return BaseClass::GetButtonFgColor();
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CheckButton::OnCheckButtonChecked(Panel *panel)
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CheckButton::SetHighlightColor(Color fgColor)
{
if ( _highlightFgColor != fgColor )
{
_highlightFgColor = fgColor;
InvalidateLayout(false);
}
}

View File

@ -0,0 +1,212 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include <vgui_controls/CheckButtonList.h>
#include <vgui_controls/CheckButton.h>
#include <vgui_controls/ScrollBar.h>
#include <KeyValues.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CheckButtonList::CheckButtonList(Panel *parent, const char *name) : BaseClass(parent, name)
{
m_pScrollBar = new ScrollBar(this, NULL, true);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CheckButtonList::~CheckButtonList()
{
RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose: adds a check button to the list
//-----------------------------------------------------------------------------
int CheckButtonList::AddItem(const char *itemText, bool startsSelected, KeyValues *userData)
{
CheckItem_t newItem;
newItem.checkButton = new vgui::CheckButton(this, NULL, itemText);
newItem.checkButton->SetSilentMode( true );
newItem.checkButton->SetSelected(startsSelected);
newItem.checkButton->SetSilentMode( false );
newItem.checkButton->AddActionSignalTarget(this);
newItem.userData = userData;
InvalidateLayout();
return m_CheckItems.AddToTail(newItem);
}
//-----------------------------------------------------------------------------
// Purpose: clears the list
//-----------------------------------------------------------------------------
void CheckButtonList::RemoveAll()
{
for (int i = 0; i < m_CheckItems.Count(); i++)
{
m_CheckItems[i].checkButton->MarkForDeletion();
if (m_CheckItems[i].userData)
{
m_CheckItems[i].userData->deleteThis();
}
}
m_CheckItems.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose: returns the number of items in list that are checked
//-----------------------------------------------------------------------------
int CheckButtonList::GetCheckedItemCount()
{
int count = 0;
for (int i = 0; i < m_CheckItems.Count(); i++)
{
if (m_CheckItems[i].checkButton->IsSelected())
{
count++;
}
}
return count;
}
//-----------------------------------------------------------------------------
// Purpose: lays out buttons
//-----------------------------------------------------------------------------
void CheckButtonList::PerformLayout()
{
BaseClass::PerformLayout();
// get sizes
int x = 4, y = 4, wide = GetWide() - ((x * 2) + m_pScrollBar->GetWide()), tall = 22;
// set scrollbar
int totalHeight = y + (m_CheckItems.Count() * tall);
if (totalHeight > GetTall())
{
m_pScrollBar->SetRange(0, totalHeight + 1);
m_pScrollBar->SetRangeWindow(GetTall());
m_pScrollBar->SetVisible(true);
m_pScrollBar->SetBounds(GetWide() - 21, 0, 19, GetTall() - 2);
SetPaintBorderEnabled(true);
y -= m_pScrollBar->GetValue();
}
else
{
m_pScrollBar->SetVisible(false);
SetPaintBorderEnabled(false);
}
// position the items
for (int i = 0; i < m_CheckItems.Count(); i++)
{
CheckButton *btn = m_CheckItems[i].checkButton;
btn->SetBounds(x, y, wide, tall);
y += tall;
}
}
//-----------------------------------------------------------------------------
// Purpose: Sets the border on the window
//-----------------------------------------------------------------------------
void CheckButtonList::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetBorder(pScheme->GetBorder("ButtonDepressedBorder"));
}
//-----------------------------------------------------------------------------
// Purpose: iteration
//-----------------------------------------------------------------------------
bool CheckButtonList::IsItemIDValid(int itemID)
{
return m_CheckItems.IsValidIndex(itemID);
}
//-----------------------------------------------------------------------------
// Purpose: iteration
//-----------------------------------------------------------------------------
int CheckButtonList::GetHighestItemID()
{
return m_CheckItems.Count() - 1;
}
//-----------------------------------------------------------------------------
// Purpose: iteration
//-----------------------------------------------------------------------------
KeyValues *CheckButtonList::GetItemData(int itemID)
{
return m_CheckItems[itemID].userData;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
int CheckButtonList::GetItemCount()
{
return m_CheckItems.Count();
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
bool CheckButtonList::IsItemChecked(int itemID)
{
return m_CheckItems[itemID].checkButton->IsSelected();
}
//-----------------------------------------------------------------------------
// Purpose: Sets the state of the check button
//-----------------------------------------------------------------------------
void CheckButtonList::SetItemCheckable(int itemID, bool state)
{
m_CheckItems[itemID].checkButton->SetCheckButtonCheckable(state);
}
//-----------------------------------------------------------------------------
// Purpose: Forwards up check button selected message
//-----------------------------------------------------------------------------
void CheckButtonList::OnCheckButtonChecked( KeyValues *pParams )
{
vgui::Panel *pPanel = (vgui::Panel *)pParams->GetPtr( "panel" );
int c = m_CheckItems.Count();
for ( int i = 0; i < c; ++i )
{
if ( pPanel == m_CheckItems[i].checkButton )
{
KeyValues *kv = new KeyValues( "CheckButtonChecked", "itemid", i );
kv->SetInt( "state", pParams->GetInt( "state" ) );
PostActionSignal( kv );
break;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: updates from scrollbar movement
//-----------------------------------------------------------------------------
void CheckButtonList::OnScrollBarSliderMoved()
{
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Mouse wheeled
//-----------------------------------------------------------------------------
void CheckButtonList::OnMouseWheeled(int delta)
{
int val = m_pScrollBar->GetValue();
val -= (delta * 15);
m_pScrollBar->SetValue(val);
}

View File

@ -0,0 +1,353 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <vgui_controls/CircularProgressBar.h>
#include <vgui_controls/Controls.h>
#include <vgui/ILocalize.h>
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include <KeyValues.h>
#include "mathlib/mathlib.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( CircularProgressBar );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CircularProgressBar::CircularProgressBar(Panel *parent, const char *panelName)
: ProgressBar(parent, panelName)
, m_bReverseProgress( false )
{
m_iProgressDirection = CircularProgressBar::PROGRESS_CW;
for ( int i = 0; i < NUM_PROGRESS_TEXTURES; i++ )
{
m_nTextureId[i] = -1;
m_pszImageName[i] = NULL;
m_lenImageName[i] = 0;
}
m_iStartSegment = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CircularProgressBar::~CircularProgressBar()
{
for ( int i = 0; i < NUM_PROGRESS_TEXTURES; i++ )
{
if ( vgui::surface() && m_nTextureId[i] )
{
vgui::surface()->DestroyTextureID( m_nTextureId[i] );
m_nTextureId[i] = -1;
}
delete [] m_pszImageName[i];
m_lenImageName[i] = 0;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CircularProgressBar::ApplySettings(KeyValues *inResourceData)
{
for ( int i = 0; i < NUM_PROGRESS_TEXTURES; i++ )
{
delete [] m_pszImageName[i];
m_pszImageName[i] = NULL;
m_lenImageName[i] = 0;
}
const char *imageName = inResourceData->GetString("fg_image", "");
if (*imageName)
{
SetFgImage( imageName );
}
imageName = inResourceData->GetString("bg_image", "");
if (*imageName)
{
SetBgImage( imageName );
}
BaseClass::ApplySettings( inResourceData );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CircularProgressBar::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetFgColor(GetSchemeColor("CircularProgressBar.FgColor", pScheme));
SetBgColor(GetSchemeColor("CircularProgressBar.BgColor", pScheme));
SetBorder(NULL);
for ( int i = 0; i < NUM_PROGRESS_TEXTURES; i++ )
{
if ( m_pszImageName[i] && strlen( m_pszImageName[i] ) > 0 )
{
if ( m_nTextureId[i] == -1 )
{
m_nTextureId[i] = surface()->CreateNewTextureID();
}
surface()->DrawSetTextureFile( m_nTextureId[i], m_pszImageName[i], true, false);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: sets an image by file name
//-----------------------------------------------------------------------------
void CircularProgressBar::SetImage(const char *imageName, progress_textures_t iPos)
{
const char *pszDir = "vgui/";
int len = Q_strlen(imageName) + 1;
len += strlen(pszDir);
if ( m_pszImageName[iPos] && ( m_lenImageName[iPos] < len ) )
{
// If we already have a buffer, but it is too short, then free the buffer
delete [] m_pszImageName[iPos];
m_pszImageName[iPos] = NULL;
m_lenImageName[iPos] = 0;
}
if ( !m_pszImageName[iPos] )
{
m_pszImageName[iPos] = new char[ len ];
m_lenImageName[iPos] = len;
}
Q_snprintf( m_pszImageName[iPos], len, "%s%s", pszDir, imageName );
InvalidateLayout(false, true); // force applyschemesettings to run
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CircularProgressBar::PaintBackground()
{
// If we don't have a Bg image, use the foreground
int iTextureID = m_nTextureId[PROGRESS_TEXTURE_BG] != -1 ? m_nTextureId[PROGRESS_TEXTURE_BG] : m_nTextureId[PROGRESS_TEXTURE_FG];
vgui::surface()->DrawSetTexture( iTextureID );
vgui::surface()->DrawSetColor( GetBgColor() );
int wide, tall;
GetSize(wide, tall);
vgui::surface()->DrawTexturedRect( 0, 0, wide, tall );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CircularProgressBar::Paint()
{
float flProgress = GetProgress();
float flEndAngle;
flEndAngle = m_bReverseProgress ? ( 1.0 - flProgress ) : flProgress;
flEndAngle = m_iProgressDirection == PROGRESS_CCW ? ( 1.0 - flEndAngle ) : flEndAngle;
DrawCircleSegment( GetFgColor(), flEndAngle, ( m_iProgressDirection == PROGRESS_CW ) );
}
typedef struct
{
float minProgressRadians;
float vert1x;
float vert1y;
float vert2x;
float vert2y;
int swipe_dir_x;
int swipe_dir_y;
} circular_progress_segment_t;
namespace vgui
{
// This defines the properties of the 8 circle segments
// in the circular progress bar.
circular_progress_segment_t Segments[8] =
{
{ 0.0, 0.5, 0.0, 1.0, 0.0, 1, 0 },
{ M_PI * 0.25, 1.0, 0.0, 1.0, 0.5, 0, 1 },
{ M_PI * 0.5, 1.0, 0.5, 1.0, 1.0, 0, 1 },
{ M_PI * 0.75, 1.0, 1.0, 0.5, 1.0, -1, 0 },
{ M_PI, 0.5, 1.0, 0.0, 1.0, -1, 0 },
{ M_PI * 1.25, 0.0, 1.0, 0.0, 0.5, 0, -1 },
{ M_PI * 1.5, 0.0, 0.5, 0.0, 0.0, 0, -1 },
{ M_PI * 1.75, 0.0, 0.0, 0.5, 0.0, 1, 0 },
};
};
#define SEGMENT_ANGLE ( M_PI / 4 )
// function to draw from A to B degrees, with a direction
// we draw starting from the top ( 0 progress )
void CircularProgressBar::DrawCircleSegment( Color c, float flEndProgress, bool bClockwise )
{
if ( m_nTextureId[PROGRESS_TEXTURE_FG] == -1 )
return;
int wide, tall;
GetSize(wide, tall);
float flWide = (float)wide;
float flTall = (float)tall;
float flHalfWide = (float)wide / 2;
float flHalfTall = (float)tall / 2;
vgui::surface()->DrawSetTexture( m_nTextureId[PROGRESS_TEXTURE_FG] );
vgui::surface()->DrawSetColor( c );
// if we want to progress CCW, reverse a few things
if ( !bClockwise )
{
float flEndProgressRadians = flEndProgress * M_PI * 2;
int i;
for ( i=0;i<8;i++ )
{
float segmentRadiansMin = Segments[i].minProgressRadians;
float segmentRadiansMax = segmentRadiansMin + SEGMENT_ANGLE;
if ( flEndProgressRadians < segmentRadiansMax )
{
vgui::Vertex_t v[3];
// vert 0 is ( 0.5, 0.5 )
v[0].m_Position.Init( flHalfWide, flHalfTall );
v[0].m_TexCoord.Init( 0.5f, 0.5f );
float flInternalProgress = segmentRadiansMax - flEndProgressRadians;
if ( flInternalProgress < SEGMENT_ANGLE )
{
// Calc how much of this slice we should be drawing
flInternalProgress = SEGMENT_ANGLE - flInternalProgress;
if ( i % 2 == 1 )
{
flInternalProgress = SEGMENT_ANGLE - flInternalProgress;
}
float flTan = tan(flInternalProgress);
float flDeltaX, flDeltaY;
if ( i % 2 == 1 )
{
flDeltaX = ( flHalfWide - flHalfTall * flTan ) * Segments[i].swipe_dir_x;
flDeltaY = ( flHalfTall - flHalfWide * flTan ) * Segments[i].swipe_dir_y;
}
else
{
flDeltaX = flHalfTall * flTan * Segments[i].swipe_dir_x;
flDeltaY = flHalfWide * flTan * Segments[i].swipe_dir_y;
}
v[1].m_Position.Init( Segments[i].vert1x * flWide + flDeltaX, Segments[i].vert1y * flTall + flDeltaY );
v[1].m_TexCoord.Init( Segments[i].vert1x + ( flDeltaX / flHalfWide ) * 0.5, Segments[i].vert1y + ( flDeltaY / flHalfTall ) * 0.5 );
}
else
{
// full segment, easy calculation
v[1].m_Position.Init( flHalfWide + flWide * ( Segments[i].vert1x - 0.5 ), flHalfTall + flTall * ( Segments[i].vert1y - 0.5 ) );
v[1].m_TexCoord.Init( Segments[i].vert1x, Segments[i].vert1y );
}
// vert 2 is ( Segments[i].vert1x, Segments[i].vert1y )
v[2].m_Position.Init( flHalfWide + flWide * ( Segments[i].vert2x - 0.5 ), flHalfTall + flTall * ( Segments[i].vert2y - 0.5 ) );
v[2].m_TexCoord.Init( Segments[i].vert2x, Segments[i].vert2y );
vgui::surface()->DrawTexturedPolygon( 3, v );
}
}
return;
}
float flEndProgressRadians = flEndProgress * M_PI * 2;
int cur_wedge = m_iStartSegment;
for ( int i=0;i<8;i++ )
{
if ( flEndProgressRadians > Segments[cur_wedge].minProgressRadians)
{
vgui::Vertex_t v[3];
// vert 0 is ( 0.5, 0.5 )
v[0].m_Position.Init( flHalfWide, flHalfTall );
v[0].m_TexCoord.Init( 0.5f, 0.5f );
float flInternalProgress = flEndProgressRadians - Segments[cur_wedge].minProgressRadians;
if ( flInternalProgress < SEGMENT_ANGLE )
{
// Calc how much of this slice we should be drawing
if ( i % 2 == 1 )
{
flInternalProgress = SEGMENT_ANGLE - flInternalProgress;
}
float flTan = tan(flInternalProgress);
float flDeltaX, flDeltaY;
if ( i % 2 == 1 )
{
flDeltaX = ( flHalfWide - flHalfTall * flTan ) * Segments[i].swipe_dir_x;
flDeltaY = ( flHalfTall - flHalfWide * flTan ) * Segments[i].swipe_dir_y;
}
else
{
flDeltaX = flHalfTall * flTan * Segments[i].swipe_dir_x;
flDeltaY = flHalfWide * flTan * Segments[i].swipe_dir_y;
}
v[2].m_Position.Init( Segments[i].vert1x * flWide + flDeltaX, Segments[i].vert1y * flTall + flDeltaY );
v[2].m_TexCoord.Init( Segments[i].vert1x + ( flDeltaX / flHalfWide ) * 0.5, Segments[i].vert1y + ( flDeltaY / flHalfTall ) * 0.5 );
}
else
{
// full segment, easy calculation
v[2].m_Position.Init( flHalfWide + flWide * ( Segments[i].vert2x - 0.5 ), flHalfTall + flTall * ( Segments[i].vert2y - 0.5 ) );
v[2].m_TexCoord.Init( Segments[i].vert2x, Segments[i].vert2y );
}
// vert 2 is ( Segments[i].vert1x, Segments[i].vert1y )
v[1].m_Position.Init( flHalfWide + flWide * ( Segments[i].vert1x - 0.5 ), flHalfTall + flTall * ( Segments[i].vert1y - 0.5 ) );
v[1].m_TexCoord.Init( Segments[i].vert1x, Segments[i].vert1y );
vgui::surface()->DrawTexturedPolygon( 3, v );
}
cur_wedge++;
if ( cur_wedge >= 8)
cur_wedge = 0;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,160 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "vgui_controls/ControllerMap.h"
#include "vgui/ISurface.h"
#include "vgui/KeyCode.h"
#include "KeyValues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
struct keystring_t
{
int code;
const char *name;
};
static const keystring_t s_ControllerButtons[] = { { KEY_XBUTTON_UP, "KEY_XBUTTON_UP" },
{ KEY_XBUTTON_DOWN, "KEY_XBUTTON_DOWN" },
{ KEY_XBUTTON_LEFT, "KEY_XBUTTON_LEFT" },
{ KEY_XBUTTON_RIGHT, "KEY_XBUTTON_RIGHT" },
{ KEY_XBUTTON_START, "KEY_XBUTTON_START" },
{ KEY_XBUTTON_BACK, "KEY_XBUTTON_BACK" },
{ KEY_XBUTTON_STICK1, "KEY_XBUTTON_STICK1" },
{ KEY_XBUTTON_STICK2, "KEY_XBUTTON_STICK2" },
{ KEY_XBUTTON_A, "KEY_XBUTTON_A" },
{ KEY_XBUTTON_B, "KEY_XBUTTON_B" },
{ KEY_XBUTTON_X, "KEY_XBUTTON_X" },
{ KEY_XBUTTON_Y, "KEY_XBUTTON_Y" },
{ KEY_XBUTTON_LEFT_SHOULDER, "KEY_XBUTTON_LEFT_SHOULDER" },
{ KEY_XBUTTON_RIGHT_SHOULDER, "KEY_XBUTTON_RIGHT_SHOULDER" },
{ KEY_XBUTTON_LTRIGGER, "KEY_XBUTTON_LTRIGGER" },
{ KEY_XBUTTON_RTRIGGER, "KEY_XBUTTON_RTRIGGER" },
{ KEY_XSTICK1_UP, "KEY_XSTICK1_UP" },
{ KEY_XSTICK1_DOWN, "KEY_XSTICK1_DOWN" },
{ KEY_XSTICK1_LEFT, "KEY_XSTICK1_LEFT" },
{ KEY_XSTICK1_RIGHT, "KEY_XSTICK1_RIGHT" },
{ KEY_XSTICK2_UP, "KEY_XSTICK2_UP" },
{ KEY_XSTICK2_DOWN, "KEY_XSTICK2_DOWN" },
{ KEY_XSTICK2_LEFT, "KEY_XSTICK2_LEFT" },
{ KEY_XSTICK2_RIGHT, "KEY_XSTICK2_RIGHT" } };
//-----------------------------------------------------------------------------
// Purpose: for the UtlMap
//-----------------------------------------------------------------------------
bool lessFunc( const int &lhs, const int &rhs )
{
return lhs < rhs;
}
//-----------------------------------------------------------------------------
// Purpose: converts a button name string to the equivalent keycode
//-----------------------------------------------------------------------------
int StringToButtonCode( const char *name )
{
for ( int i = 0; i < ARRAYSIZE( s_ControllerButtons ); ++i )
{
if ( !Q_stricmp( s_ControllerButtons[i].name, name ) )
return s_ControllerButtons[i].code;
}
return -1;
}
//-----------------------------------------------------------------------------
// Purpose: intercepts the keycode from its parent, and handles it according to
// the button map. If the keycode isn't handled, it gets passed on to the parent.
//-----------------------------------------------------------------------------
void CControllerMap::OnKeyCodeTyped( vgui::KeyCode code )
{
int idx = m_buttonMap.Find( code );
if ( idx != m_buttonMap.InvalidIndex() )
{
GetParent()->OnCommand( m_buttonMap[idx].cmd.String() );
}
else
{
// Disable input before forwarding the message
// so it doesn't feed back here again.
SetKeyBoardInputEnabled( false );
GetParent()->OnKeyCodeTyped( code );
SetKeyBoardInputEnabled( true );
}
}
//-----------------------------------------------------------------------------
// Purpose: constructor
//-----------------------------------------------------------------------------
CControllerMap::CControllerMap( vgui::Panel *parent, const char *name ) : BaseClass( parent, name )
{
m_buttonMap.SetLessFunc( lessFunc );
}
//-----------------------------------------------------------------------------
// Purpose: sets up the button/command bindings
//-----------------------------------------------------------------------------
void CControllerMap::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
// loop through all the data adding items to the menu
for (KeyValues *dat = inResourceData->GetFirstSubKey(); dat != NULL; dat = dat->GetNextKey())
{
if ( !Q_stricmp( dat->GetName(), "button" ) )
{
const char *buttonName = dat->GetString( "name", "" );
int keycode = StringToButtonCode( buttonName );
if ( keycode != -1 )
{
button_t b;
b.cmd = CUtlSymbol( dat->GetString( "command", "" ) );
// text and icon are optional - their existence means this button
// should be displayed in the footer panel.
const char *helpText = dat->GetString( "text", NULL );
if ( helpText )
{
b.text = CUtlSymbol( helpText );
b.icon = CUtlSymbol( dat->GetString( "icon", NULL ) );
}
m_buttonMap.Insert( keycode, b );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: gets the help text for a binding, if it exists
//-----------------------------------------------------------------------------
const char *CControllerMap::GetBindingText( int idx )
{
CUtlSymbol s = m_buttonMap[idx].text;
if ( s.IsValid() )
{
return s.String();
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: gets the icon for a binding, if it exists
//-----------------------------------------------------------------------------
const char *CControllerMap::GetBindingIcon( int idx )
{
CUtlSymbol s = m_buttonMap[idx].icon;
if ( s.IsValid() )
{
return s.String();
}
return NULL;
}
DECLARE_BUILD_FACTORY( CControllerMap );

View File

@ -0,0 +1,594 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#define PROTECTED_THINGS_DISABLE
#include <vgui_controls/Button.h>
#include <vgui_controls/ComboBox.h>
#include <vgui_controls/DirectorySelectDialog.h>
#include <vgui_controls/TreeView.h>
#include <vgui_controls/ImageList.h>
#include <vgui_controls/MessageBox.h>
#include <vgui/Cursor.h>
#include <KeyValues.h>
#include <vgui/IInput.h>
#include <vgui/ISurface.h>
#include <vgui/ISystem.h>
#include <filesystem.h>
#ifdef WIN32
#include <direct.h>
#include <stdio.h>
#include <io.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DirectoryTreeView::DirectoryTreeView(DirectorySelectDialog *parent, const char *name) : TreeView(parent, name)
{
m_pParent = parent;
}
void DirectoryTreeView::GenerateChildrenOfNode(int itemIndex)
{
m_pParent->GenerateChildrenOfDirectoryNode(itemIndex);
}
//-----------------------------------------------------------------------------
// Purpose: Used to prompt the user to create a directory
//-----------------------------------------------------------------------------
class CreateDirectoryDialog : public Frame
{
DECLARE_CLASS_SIMPLE(CreateDirectoryDialog, Frame);
public:
CreateDirectoryDialog(Panel *parent, const char *defaultCreateDirName) : BaseClass(parent, NULL)
{
SetSize(320, 100);
SetSizeable(false);
SetTitle("Choose directory name", false);
MoveToCenterOfScreen();
m_pOKButton = new Button(this, "OKButton", "#vgui_ok");
m_pCancelButton = new Button(this, "OKButton", "#vgui_cancel");
m_pNameEntry = new TextEntry(this, "NameEntry");
m_pOKButton->SetCommand("OK");
m_pCancelButton->SetCommand("Close");
m_pNameEntry->SetText(defaultCreateDirName);
m_pNameEntry->RequestFocus();
m_pNameEntry->SelectAllText(true);
// If some other window was hogging the input focus, then we have to hog it or else we'll never get input.
m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface();
if ( m_PrevAppFocusPanel )
vgui::input()->SetAppModalSurface( GetVPanel() );
}
~CreateDirectoryDialog()
{
if ( m_PrevAppFocusPanel )
vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel );
}
virtual void PerformLayout()
{
BaseClass::PerformLayout();
m_pNameEntry->SetBounds(24, 32, GetWide() - 48, 24);
m_pOKButton->SetBounds(GetWide() - 176, 64, 72, 24);
m_pCancelButton->SetBounds(GetWide() - 94, 64, 72, 24);
}
virtual void OnCommand(const char *command)
{
if (!stricmp(command, "OK"))
{
PostActionSignal(new KeyValues("CreateDirectory", "dir", GetControlString("NameEntry")));
Close();
}
else
{
BaseClass::OnCommand(command);
}
}
virtual void OnClose()
{
BaseClass::OnClose();
MarkForDeletion();
}
private:
vgui::Button *m_pOKButton;
vgui::Button *m_pCancelButton;
vgui::TextEntry *m_pNameEntry;
vgui::VPANEL m_PrevAppFocusPanel;
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
DirectorySelectDialog::DirectorySelectDialog(vgui::Panel *parent, const char *title) : Frame(parent, NULL)
{
SetTitle(title, true);
SetSize(320, 360);
SetMinimumSize(300, 240);
m_szCurrentDir[0] = 0;
m_szDefaultCreateDirName[0] = 0;
m_pDirTree = new DirectoryTreeView(this, "DirTree");
m_pDriveCombo = new ComboBox(this, "DriveCombo", 6, false);
m_pCancelButton = new Button(this, "CancelButton", "#VGui_Cancel");
m_pSelectButton = new Button(this, "SelectButton", "#VGui_Select");
m_pCreateButton = new Button(this, "CreateButton", "#VGui_CreateFolder");
m_pCancelButton->SetCommand("Cancel");
m_pSelectButton->SetCommand("Select");
m_pCreateButton->SetCommand("Create");
}
//-----------------------------------------------------------------------------
// Purpose: lays out controls
//-----------------------------------------------------------------------------
void DirectorySelectDialog::PerformLayout()
{
BaseClass::PerformLayout();
// lay out all the controls
m_pDriveCombo->SetBounds(24, 30, GetWide() - 48, 24);
m_pDirTree->SetBounds(24, 64, GetWide() - 48, GetTall() - 128);
m_pCreateButton->SetBounds(24, GetTall() - 48, 104, 24);
m_pSelectButton->SetBounds(GetWide() - 172, GetTall() - 48, 72, 24);
m_pCancelButton->SetBounds(GetWide() - 96, GetTall() - 48, 72, 24);
}
//-----------------------------------------------------------------------------
// Purpose: lays out controls
//-----------------------------------------------------------------------------
void DirectorySelectDialog::ApplySchemeSettings(IScheme *pScheme)
{
ImageList *imageList = new ImageList(false);
imageList->AddImage(scheme()->GetImage("Resource/icon_folder", false));
imageList->AddImage(scheme()->GetImage("Resource/icon_folder_selected", false));
m_pDirTree->SetImageList(imageList, true);
BaseClass::ApplySchemeSettings(pScheme);
}
//-----------------------------------------------------------------------------
// Purpose: Move the start string forward until we hit a slash and return the
// the first character past the trailing slash
//-----------------------------------------------------------------------------
inline const char *MoveToNextSubDir( const char *pStart, int *nCount )
{
int nMoved = 0;
// Move past pre-pended slash
if ( pStart[nMoved] == '\\' )
{
nMoved++;
}
// Move past the current block of text until we've hit the next path seperator (or end)
while ( pStart[nMoved] != '\\' && pStart[nMoved] != '\0' )
{
nMoved++;
}
// Move past trailing slash
if ( pStart[nMoved] == '\\' )
{
nMoved++;
}
// Give back a count if they've supplied a pointer
if ( nCount != NULL )
{
*nCount = nMoved;
}
// The beginning of the next string, past slash
return (pStart+nMoved);
}
//-----------------------------------------------------------------------------
// Purpose: Walk through our directory structure given a path as our guide, while expanding
// and populating the nodes of the tree view to match
// Input : *path - path (with drive letter) to show
//-----------------------------------------------------------------------------
void DirectorySelectDialog::ExpandTreeToPath( const char *lpszPath, bool bSelectFinalDirectory /*= true*/ )
{
// Make sure our slashes are correct!
char workPath[MAX_PATH];
Q_strncpy( workPath, lpszPath, sizeof(workPath) );
Q_FixSlashes( workPath );
// Set us to the work drive
SetStartDirectory( workPath );
// Check that the path is valid
if ( workPath[0] == '\0' || DoesDirectoryHaveSubdirectories( m_szCurrentDrive, "" ) == false )
{
// Failing, start in C:
SetStartDirectory( "C:\\" );
}
// Start at the root of our tree
int nItemIndex = m_pDirTree->GetRootItemIndex();
// Move past the drive letter to the first subdir
int nPathPos = 0;
const char *lpszSubDirName = MoveToNextSubDir( workPath, &nPathPos );
const char *lpszLastSubDirName = NULL;
int nPathIncr = 0;
char subDirName[MAX_PATH];
// While there are subdirectory names present, expand and populate the tree with their subdirectories
while ( lpszSubDirName[0] != '\0' )
{
// Move our string pointer forward while keeping where our last subdir started off
lpszLastSubDirName = lpszSubDirName;
lpszSubDirName = MoveToNextSubDir( lpszSubDirName, &nPathIncr );
// Get the span between the last subdir and the new one
Q_StrLeft( lpszLastSubDirName, nPathIncr, subDirName, sizeof(subDirName) );
Q_StripTrailingSlash( subDirName );
// Increment where we are in the string for use later
nPathPos += nPathIncr;
// Run through the list and expand to our currently selected directory
for ( int i = 0; i < m_pDirTree->GetNumChildren( nItemIndex ); i++ )
{
// Get the child and data for it
int nChild = m_pDirTree->GetChild( nItemIndex, i );
KeyValues *pValues = m_pDirTree->GetItemData( nChild );
// See if this matches
if ( Q_stricmp( pValues->GetString( "Text" ), subDirName ) == 0 )
{
// This is the new root item
nItemIndex = nChild;
// Get the full path (starting from the drive letter) up to our current subdir
Q_strncpy( subDirName, workPath, nPathPos );
Q_AppendSlash( subDirName, sizeof(subDirName) );
// Expand the tree node and populate its subdirs for our next iteration
ExpandTreeNode( subDirName, nItemIndex );
break;
}
}
}
// Select our last directory if we've been asked to (and it's valid)
if ( bSelectFinalDirectory && m_pDirTree->IsItemIDValid( nItemIndex ) )
{
// If we don't call this once before selecting an item, the tree will not be properly expanded
// before it calculates how to show the selected item in the view
PerformLayout();
// Select that item
m_pDirTree->AddSelectedItem( nItemIndex, true );
}
}
//-----------------------------------------------------------------------------
// Purpose: sets where it should start searching
//-----------------------------------------------------------------------------
void DirectorySelectDialog::SetStartDirectory(const char *path)
{
strncpy(m_szCurrentDir, path, sizeof(m_szCurrentDir));
strncpy(m_szCurrentDrive, path, sizeof(m_szCurrentDrive));
m_szCurrentDrive[sizeof(m_szCurrentDrive) - 1] = 0;
char *firstSlash = strstr(m_szCurrentDrive, "\\");
if (firstSlash)
{
firstSlash[1] = 0;
}
BuildDirTree();
BuildDriveChoices();
// update state of create directory button
int selectedIndex = m_pDirTree->GetFirstSelectedItem();
if (m_pDirTree->IsItemIDValid(selectedIndex))
{
m_pCreateButton->SetEnabled(true);
}
else
{
m_pCreateButton->SetEnabled(false);
}
}
//-----------------------------------------------------------------------------
// Purpose: sets what name should show up by default in the create directory dialog
//-----------------------------------------------------------------------------
void DirectorySelectDialog::SetDefaultCreateDirectoryName(const char *defaultCreateDirName)
{
strncpy(m_szDefaultCreateDirName, defaultCreateDirName, sizeof(m_szDefaultCreateDirName));
m_szDefaultCreateDirName[sizeof(m_szDefaultCreateDirName) - 1] = 0;
}
//-----------------------------------------------------------------------------
// Purpose: opens the dialog
//-----------------------------------------------------------------------------
void DirectorySelectDialog::DoModal()
{
input()->SetAppModalSurface(GetVPanel());
BaseClass::Activate();
MoveToCenterOfScreen();
}
//-----------------------------------------------------------------------------
// Purpose: Builds drive choices
//-----------------------------------------------------------------------------
void DirectorySelectDialog::BuildDriveChoices()
{
m_pDriveCombo->DeleteAllItems();
char drives[256] = { 0 };
int len = system()->GetAvailableDrives(drives, sizeof(drives));
char *pBuf = drives;
KeyValues *kv = new KeyValues("drive");
for (int i = 0; i < len / 4; i++)
{
kv->SetString("drive", pBuf);
int itemID = m_pDriveCombo->AddItem(pBuf, kv);
if (!stricmp(pBuf, m_szCurrentDrive))
{
m_pDriveCombo->ActivateItem(itemID);
}
pBuf += 4;
}
kv->deleteThis();
}
//-----------------------------------------------------------------------------
// Purpose: Builds the base tree directory
//-----------------------------------------------------------------------------
void DirectorySelectDialog::BuildDirTree()
{
// clear current tree
m_pDirTree->RemoveAll();
// add in a root
int rootIndex = m_pDirTree->AddItem(new KeyValues("root", "Text", m_szCurrentDrive), -1);
// build first level of the tree
ExpandTreeNode(m_szCurrentDrive, rootIndex);
// start the root expanded
m_pDirTree->ExpandItem(rootIndex, true);
}
//-----------------------------------------------------------------------------
// Purpose: expands a path
//-----------------------------------------------------------------------------
void DirectorySelectDialog::ExpandTreeNode(const char *path, int parentNodeIndex)
{
// set the small wait cursor
surface()->SetCursor(dc_waitarrow);
// get all the subfolders of the current drive
char searchString[512];
sprintf(searchString, "%s*.*", path);
FileFindHandle_t h;
const char *pFileName = g_pFullFileSystem->FindFirstEx( searchString, NULL, &h );
for ( ; pFileName; pFileName = g_pFullFileSystem->FindNext( h ) )
{
if ( !Q_stricmp( pFileName, ".." ) || !Q_stricmp( pFileName, "." ) )
continue;
KeyValues *kv = new KeyValues("item");
kv->SetString("Text", pFileName);
// set the folder image
kv->SetInt("Image", 1);
kv->SetInt("SelectedImage", 1);
kv->SetInt("Expand", DoesDirectoryHaveSubdirectories(path, pFileName));
m_pDirTree->AddItem(kv, parentNodeIndex);
}
g_pFullFileSystem->FindClose( h );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool DirectorySelectDialog::DoesDirectoryHaveSubdirectories(const char *path, const char *dir)
{
char searchString[512];
sprintf(searchString, "%s%s\\*.*", path, dir);
FileFindHandle_t h;
const char *pFileName = g_pFullFileSystem->FindFirstEx( searchString, NULL, &h );
for ( ; pFileName; pFileName = g_pFullFileSystem->FindNext( h ) )
{
char szFullPath[ MAX_PATH ];
Q_snprintf( szFullPath, sizeof(szFullPath), "%s\\%s", path, pFileName );
Q_FixSlashes( szFullPath );
if ( g_pFullFileSystem->IsDirectory( szFullPath ) )
{
g_pFullFileSystem->FindClose( h );
return true;
}
}
g_pFullFileSystem->FindClose( h );
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Generates the children for the specified node
//-----------------------------------------------------------------------------
void DirectorySelectDialog::GenerateChildrenOfDirectoryNode(int nodeIndex)
{
// generate path
char path[512];
GenerateFullPathForNode(nodeIndex, path, sizeof(path));
// expand out
ExpandTreeNode(path, nodeIndex);
}
//-----------------------------------------------------------------------------
// Purpose: creates the full path for a node
//-----------------------------------------------------------------------------
void DirectorySelectDialog::GenerateFullPathForNode(int nodeIndex, char *path, int pathBufferSize)
{
// get all the nodes
CUtlLinkedList<int, int> nodes;
nodes.AddToTail(nodeIndex);
int parentIndex = nodeIndex;
while (1)
{
parentIndex = m_pDirTree->GetItemParent(parentIndex);
if (parentIndex == -1)
break;
nodes.AddToHead(parentIndex);
}
// walk the nodes, adding to the path
path[0] = 0;
bool bFirst = true;
FOR_EACH_LL( nodes, i )
{
KeyValues *kv = m_pDirTree->GetItemData( nodes[i] );
strcat(path, kv->GetString("Text"));
if (!bFirst)
{
strcat(path, "\\");
}
bFirst = false;
}
}
//-----------------------------------------------------------------------------
// Purpose: Handles combo box changes
//-----------------------------------------------------------------------------
void DirectorySelectDialog::OnTextChanged()
{
KeyValues *kv = m_pDriveCombo->GetActiveItemUserData();
if (!kv)
return;
const char *newDrive = kv->GetString("drive");
if (stricmp(newDrive, m_szCurrentDrive))
{
// drive changed, reset
SetStartDirectory(newDrive);
}
}
//-----------------------------------------------------------------------------
// Purpose: creates a directory
//-----------------------------------------------------------------------------
void DirectorySelectDialog::OnCreateDirectory(const char *dir)
{
int selectedIndex = m_pDirTree->GetFirstSelectedItem();
if (m_pDirTree->IsItemIDValid(selectedIndex))
{
char fullPath[512];
GenerateFullPathForNode(selectedIndex, fullPath, sizeof(fullPath));
// create the new directory underneath
strcat(fullPath, dir);
if (_mkdir(fullPath) == 0)
{
// add new path to tree view
KeyValues *kv = new KeyValues("item");
kv->SetString("Text", dir);
// set the folder image
kv->SetInt("Image", 1);
kv->SetInt("SelectedImage", 1);
int itemID = m_pDirTree->AddItem(kv, selectedIndex);
// select the item
m_pDirTree->AddSelectedItem( itemID, true );
}
else
{
// print error message
MessageBox *box = new MessageBox("#vgui_CreateDirectoryFail_Title", "#vgui_CreateDirectoryFail_Info");
box->DoModal(this);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: dialog closes
//-----------------------------------------------------------------------------
void DirectorySelectDialog::OnClose()
{
BaseClass::OnClose();
MarkForDeletion();
}
//-----------------------------------------------------------------------------
// Purpose: handles button commands
//-----------------------------------------------------------------------------
void DirectorySelectDialog::OnCommand(const char *command)
{
if (!stricmp(command, "Cancel"))
{
Close();
}
else if (!stricmp(command, "Select"))
{
// path selected
int selectedIndex = m_pDirTree->GetFirstSelectedItem();
if (m_pDirTree->IsItemIDValid(selectedIndex))
{
char fullPath[512];
GenerateFullPathForNode(selectedIndex, fullPath, sizeof(fullPath));
PostActionSignal(new KeyValues("DirectorySelected", "dir", fullPath));
Close();
}
}
else if (!stricmp(command, "Create"))
{
int selectedIndex = m_pDirTree->GetFirstSelectedItem();
if (m_pDirTree->IsItemIDValid(selectedIndex))
{
CreateDirectoryDialog *dlg = new CreateDirectoryDialog(this, m_szDefaultCreateDirName);
dlg->AddActionSignalTarget(this);
dlg->Activate();
}
}
else
{
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose: Update the text in the combo
//-----------------------------------------------------------------------------
void DirectorySelectDialog::OnTreeViewItemSelected()
{
int selectedIndex = m_pDirTree->GetFirstSelectedItem();
if (!m_pDirTree->IsItemIDValid(selectedIndex))
{
m_pCreateButton->SetEnabled(false);
return;
}
m_pCreateButton->SetEnabled(true);
// build the string
char fullPath[512];
GenerateFullPathForNode(selectedIndex, fullPath, sizeof(fullPath));
int itemID = m_pDriveCombo->GetActiveItem();
m_pDriveCombo->UpdateItem(itemID, fullPath, NULL);
m_pDriveCombo->SetText(fullPath);
}

View File

@ -0,0 +1,41 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/IScheme.h>
#include <vgui_controls/Divider.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
DECLARE_BUILD_FACTORY( Divider );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
Divider::Divider(Panel *parent, const char *name) : Panel(parent, name)
{
SetSize(128, 2);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
Divider::~Divider()
{
}
//-----------------------------------------------------------------------------
// Purpose: sets up the border as the line to draw as a divider
//-----------------------------------------------------------------------------
void Divider::ApplySchemeSettings(IScheme *pScheme)
{
SetBorder(pScheme->GetBorder("ButtonDepressedBorder"));
BaseClass::ApplySchemeSettings(pScheme);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,114 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include <stdarg.h>
#include <stdio.h>
#include <vgui/ISurface.h>
#include <vgui/IScheme.h>
#include <KeyValues.h>
#include <vgui_controls/Image.h>
#include <vgui_controls/ExpandButton.h>
#include <vgui_controls/TextImage.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( ExpandButton );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ExpandButton::ExpandButton( Panel *parent, const char *panelName ) : ToggleButton( parent, panelName, "" )
{
m_bExpandable = true;
m_hFont = INVALID_FONT;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
ExpandButton::~ExpandButton()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ExpandButton::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
m_Color = GetSchemeColor( "ExpandButton.Color", pScheme );
m_hFont = pScheme->GetFont("Marlett", IsProportional() );
// don't draw a background
SetPaintBackgroundEnabled(false);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
IBorder *ExpandButton::GetBorder(bool depressed, bool armed, bool selected, bool keyfocus)
{
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Expand the button
//-----------------------------------------------------------------------------
void ExpandButton::SetSelected(bool state)
{
if ( m_bExpandable && ( state != IsSelected() ) )
{
// send a message saying we've been checked
KeyValues *msg = new KeyValues("Expanded", "state", (int)state);
PostActionSignal(msg);
BaseClass::SetSelected(state);
}
}
//-----------------------------------------------------------------------------
// Purpose: sets whether or not the state of the check can be changed
//-----------------------------------------------------------------------------
void ExpandButton::SetExpandable(bool state)
{
m_bExpandable = state;
Repaint();
}
void ExpandButton::Paint()
{
surface()->DrawSetTextFont( m_hFont );
wchar_t code = IsSelected( ) ? L'6' : L'4';
wchar_t pString[2] = { code, 0 };
// draw selected check
int tw, th, w, h;
GetSize( w, h );
surface()->GetTextSize( m_hFont, pString, tw, th );
surface()->DrawSetTextColor( m_Color );
surface()->DrawSetTextPos( ( w - tw ) / 2, ( h - th ) / 2 );
surface()->DrawUnicodeChar( code );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ExpandButton::OnExpanded(Panel *panel)
{
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,497 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// This is a helper class designed to help with the chains of modal dialogs
// encountered when trying to open or save a particular file
//
//=============================================================================
#include "vgui_controls/FileOpenStateMachine.h"
#include "tier1/KeyValues.h"
#include "vgui_controls/FileOpenDialog.h"
#include "vgui_controls/MessageBox.h"
#include "vgui_controls/perforcefilelistframe.h"
#include "vgui_controls/savedocumentquery.h"
#include "filesystem.h"
#include "p4lib/ip4.h"
#include "tier2/tier2.h"
#include "tier0/icommandline.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
FileOpenStateMachine::FileOpenStateMachine( vgui::Panel *pParent, IFileOpenStateMachineClient *pClient ) : BaseClass( pParent, "FileOpenStateMachine" )
{
m_pClient = pClient;
m_CompletionState = SUCCESSFUL;
m_CurrentState = STATE_NONE;
m_pContextKeyValues = NULL;
SetVisible( false );
}
FileOpenStateMachine::~FileOpenStateMachine()
{
CleanUpContextKeyValues();
}
//-----------------------------------------------------------------------------
// Cleans up keyvalues
//-----------------------------------------------------------------------------
void FileOpenStateMachine::CleanUpContextKeyValues()
{
if ( m_pContextKeyValues )
{
m_pContextKeyValues->deleteThis();
m_pContextKeyValues = NULL;
}
}
//-----------------------------------------------------------------------------
// Returns the state machine completion state
//-----------------------------------------------------------------------------
FileOpenStateMachine::CompletionState_t FileOpenStateMachine::GetCompletionState()
{
return m_CompletionState;
}
//-----------------------------------------------------------------------------
// Utility to set the completion state
//-----------------------------------------------------------------------------
void FileOpenStateMachine::SetCompletionState( FileOpenStateMachine::CompletionState_t state )
{
m_CompletionState = state;
if ( m_CompletionState == IN_PROGRESS )
return;
m_CurrentState = STATE_NONE;
KeyValues *kv = new KeyValues( "FileStateMachineFinished" );
kv->SetInt( "completionState", m_CompletionState );
kv->SetInt( "wroteFile", m_bWroteFile );
kv->SetString( "fullPath", m_FileName.Get() );
kv->SetString( "fileType", m_bIsOpeningFile ? m_OpenFileType.Get() : m_SaveFileType.Get() );
if ( m_pContextKeyValues )
{
kv->AddSubKey( m_pContextKeyValues );
m_pContextKeyValues = NULL;
}
PostActionSignal( kv );
}
//-----------------------------------------------------------------------------
// Called by the message box in OverwriteFileDialog
//-----------------------------------------------------------------------------
void FileOpenStateMachine::OnOverwriteFile( )
{
CheckOutDialog( );
}
void FileOpenStateMachine::OnCancelOverwriteFile( )
{
SetCompletionState( FILE_NOT_OVERWRITTEN );
}
//-----------------------------------------------------------------------------
// Shows the overwrite existing file dialog
//-----------------------------------------------------------------------------
void FileOpenStateMachine::OverwriteFileDialog( )
{
if ( !g_pFullFileSystem->FileExists( m_FileName ) )
{
CheckOutDialog( );
return;
}
m_CurrentState = STATE_SHOWING_OVERWRITE_DIALOG;
char pBuf[1024];
Q_snprintf( pBuf, sizeof(pBuf), "File already exists. Overwrite it?\n\n\"%s\"\n", m_FileName.Get() );
vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Overwrite Existing File?", pBuf, GetParent() );
pMessageBox->AddActionSignalTarget( this );
pMessageBox->SetOKButtonVisible( true );
pMessageBox->SetOKButtonText( "Yes" );
pMessageBox->SetCancelButtonVisible( true );
pMessageBox->SetCancelButtonText( "No" );
pMessageBox->SetCloseButtonVisible( false );
pMessageBox->SetCommand( new KeyValues( "OverwriteFile" ) );
pMessageBox->SetCancelCommand( new KeyValues( "CancelOverwriteFile" ) );
pMessageBox->DoModal();
}
//-----------------------------------------------------------------------------
// Used to open a particular file in perforce, and deal with all the lovely dialogs
//-----------------------------------------------------------------------------
void FileOpenStateMachine::OnFileSelectionCancelled()
{
if ( m_CurrentState == STATE_SHOWING_SAVE_DIALOG )
{
SetCompletionState( FILE_SAVE_NAME_NOT_SPECIFIED );
return;
}
if ( m_CurrentState == STATE_SHOWING_OPEN_DIALOG )
{
SetCompletionState( FILE_OPEN_NAME_NOT_SPECIFIED );
return;
}
Assert(0);
}
//-----------------------------------------------------------------------------
// Used to open a particular file in perforce, and deal with all the lovely dialogs
//-----------------------------------------------------------------------------
void FileOpenStateMachine::OnFileSelected( KeyValues *pKeyValues )
{
if ( m_CurrentState == STATE_SHOWING_SAVE_DIALOG )
{
m_FileName = pKeyValues->GetString( "fullpath" );
const char *pFilterInfo = pKeyValues->GetString( "filterinfo" );
if ( pFilterInfo )
{
m_SaveFileType = pFilterInfo;
}
OverwriteFileDialog();
return;
}
if ( m_CurrentState == STATE_SHOWING_OPEN_DIALOG )
{
m_FileName = pKeyValues->GetString( "fullpath" );
const char *pFilterInfo = pKeyValues->GetString( "filterinfo" );
if ( pFilterInfo )
{
m_OpenFileType = pFilterInfo;
}
ReadFile( );
return;
}
Assert(0);
}
//-----------------------------------------------------------------------------
// Writes the file out
//-----------------------------------------------------------------------------
void FileOpenStateMachine::WriteFile()
{
m_CurrentState = STATE_WRITING_FILE;
if ( !m_pClient->OnWriteFileToDisk( m_FileName, m_SaveFileType, m_pContextKeyValues ) )
{
SetCompletionState( ERROR_WRITING_FILE );
return;
}
m_bWroteFile = true;
if ( m_bShowPerforceDialogs )
{
m_CurrentState = STATE_SHOWING_PERFORCE_ADD_DIALOG;
ShowPerforceQuery( GetParent(), m_FileName, this, NULL, PERFORCE_ACTION_FILE_ADD );
return;
}
if ( !m_bIsOpeningFile )
{
SetCompletionState( SUCCESSFUL );
return;
}
OpenFileDialog();
}
//-----------------------------------------------------------------------------
// Called by the message box in MakeFileWriteableDialog
//-----------------------------------------------------------------------------
void FileOpenStateMachine::OnMakeFileWriteable( )
{
if ( !g_pFullFileSystem->SetFileWritable( m_FileName, true ) )
{
SetCompletionState( ERROR_MAKING_FILE_WRITEABLE );
return;
}
WriteFile();
}
void FileOpenStateMachine::OnCancelMakeFileWriteable( )
{
SetCompletionState( FILE_NOT_MADE_WRITEABLE );
}
//-----------------------------------------------------------------------------
// Shows the make file writeable dialog
//-----------------------------------------------------------------------------
void FileOpenStateMachine::MakeFileWriteableDialog( )
{
// If the file is writeable, write it!
if ( !g_pFullFileSystem->FileExists( m_FileName ) || g_pFullFileSystem->IsFileWritable( m_FileName ) )
{
WriteFile();
return;
}
// If it's in perforce, and not checked out, then we must abort.
bool bIsInPerforce = p4->IsFileInPerforce( m_FileName );
bool bIsOpened = ( p4->GetFileState( m_FileName ) != P4FILE_UNOPENED );
if ( bIsInPerforce && !bIsOpened )
{
SetCompletionState( FILE_NOT_CHECKED_OUT );
return;
}
m_CurrentState = STATE_SHOWING_MAKE_FILE_WRITEABLE_DIALOG;
char pBuf[1024];
Q_snprintf( pBuf, sizeof(pBuf), "Encountered read-only file. Should it be made writeable?\n\n\"%s\"\n", m_FileName.Get() );
vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Make File Writeable?", pBuf, GetParent() );
pMessageBox->AddActionSignalTarget( this );
pMessageBox->SetOKButtonVisible( true );
pMessageBox->SetOKButtonText( "Yes" );
pMessageBox->SetCancelButtonVisible( true );
pMessageBox->SetCancelButtonText( "No" );
pMessageBox->SetCloseButtonVisible( false );
pMessageBox->SetCommand( new KeyValues( "MakeFileWriteable" ) );
pMessageBox->SetCancelCommand( new KeyValues( "CancelMakeFileWriteable" ) );
pMessageBox->DoModal();
}
//-----------------------------------------------------------------------------
// Called when ShowPerforceQuery completes
//-----------------------------------------------------------------------------
void FileOpenStateMachine::OnPerforceQueryCompleted( KeyValues *pKeyValues )
{
if ( m_CurrentState == STATE_SHOWING_CHECK_OUT_DIALOG )
{
if ( pKeyValues->GetInt( "operationPerformed" ) == 0 )
{
SetCompletionState( FILE_NOT_CHECKED_OUT );
return;
}
MakeFileWriteableDialog();
return;
}
if ( m_CurrentState == STATE_SHOWING_PERFORCE_ADD_DIALOG )
{
if ( !m_bIsOpeningFile )
{
SetCompletionState( SUCCESSFUL );
return;
}
OpenFileDialog();
return;
}
Assert(0);
}
//-----------------------------------------------------------------------------
// Used to open a particular file in perforce, and deal with all the lovely dialogs
//-----------------------------------------------------------------------------
void FileOpenStateMachine::CheckOutDialog( )
{
if ( m_bShowPerforceDialogs )
{
m_CurrentState = STATE_SHOWING_CHECK_OUT_DIALOG;
ShowPerforceQuery( GetParent(), m_FileName, this, NULL, PERFORCE_ACTION_FILE_EDIT );
return;
}
WriteFile();
}
//-----------------------------------------------------------------------------
// These 3 messages come from the savedocumentquery dialog
//-----------------------------------------------------------------------------
void FileOpenStateMachine::OnSaveFile()
{
if ( !m_FileName[0] || !Q_IsAbsolutePath( m_FileName ) )
{
m_CurrentState = STATE_SHOWING_SAVE_DIALOG;
FileOpenDialog *pDialog = new FileOpenDialog( GetParent(), "Save As", false );
m_pClient->SetupFileOpenDialog( pDialog, false, m_SaveFileType, m_pContextKeyValues );
pDialog->SetDeleteSelfOnClose( true );
pDialog->AddActionSignalTarget( this );
pDialog->DoModal( );
return;
}
CheckOutDialog( );
}
void FileOpenStateMachine::OnMarkNotDirty()
{
if ( !m_bIsOpeningFile )
{
SetCompletionState( SUCCESSFUL );
return;
}
// Jump right to opening the file
OpenFileDialog( );
}
void FileOpenStateMachine::OnCancelSaveDocument()
{
SetCompletionState( FILE_SAVE_CANCELLED );
}
//-----------------------------------------------------------------------------
// Show the save document query dialog
//-----------------------------------------------------------------------------
void FileOpenStateMachine::ShowSaveQuery( )
{
m_CurrentState = STATE_SHOWING_SAVE_DIRTY_FILE_DIALOG;
ShowSaveDocumentQuery( GetParent(), m_FileName, m_SaveFileType, 0, this, NULL );
}
//-----------------------------------------------------------------------------
// Used to save a specified file, and deal with all the lovely dialogs
//-----------------------------------------------------------------------------
void FileOpenStateMachine::SaveFile( KeyValues *pContextKeyValues, const char *pFileName, const char *pFileType, int nFlags )
{
CleanUpContextKeyValues();
SetCompletionState( IN_PROGRESS );
m_pContextKeyValues = pContextKeyValues;
m_FileName = pFileName;
m_SaveFileType = pFileType;
m_OpenFileType = NULL;
m_OpenFileName = NULL;
// Clear the P4 dialog flag for SDK users and licensees without Perforce
if ( CommandLine()->FindParm( "-nop4" ) )
{
nFlags &= ~FOSM_SHOW_PERFORCE_DIALOGS;
}
m_bShowPerforceDialogs = ( nFlags & FOSM_SHOW_PERFORCE_DIALOGS ) != 0;
m_bShowSaveQuery = ( nFlags & FOSM_SHOW_SAVE_QUERY ) != 0;
m_bIsOpeningFile = false;
m_bWroteFile = false;
if ( m_bShowSaveQuery )
{
ShowSaveQuery();
return;
}
OnSaveFile();
}
//-----------------------------------------------------------------------------
// Reads the file in
//-----------------------------------------------------------------------------
void FileOpenStateMachine::ReadFile()
{
m_CurrentState = STATE_READING_FILE;
if ( !m_pClient->OnReadFileFromDisk( m_FileName, m_OpenFileType, m_pContextKeyValues ) )
{
SetCompletionState( ERROR_READING_FILE );
return;
}
SetCompletionState( SUCCESSFUL );
}
//-----------------------------------------------------------------------------
// Shows the open file dialog
//-----------------------------------------------------------------------------
void FileOpenStateMachine::OpenFileDialog( )
{
m_CurrentState = STATE_SHOWING_OPEN_DIALOG;
if ( m_OpenFileName.IsEmpty() )
{
FileOpenDialog *pDialog = new FileOpenDialog( GetParent(), "Open", true );
m_pClient->SetupFileOpenDialog( pDialog, true, m_OpenFileType, m_pContextKeyValues );
pDialog->SetDeleteSelfOnClose( true );
pDialog->AddActionSignalTarget( this );
pDialog->DoModal( );
}
else
{
m_FileName = m_OpenFileName;
ReadFile();
}
}
//-----------------------------------------------------------------------------
// Opens a file, saves an existing one if necessary
//-----------------------------------------------------------------------------
void FileOpenStateMachine::OpenFile( const char *pOpenFileType, KeyValues *pContextKeyValues, const char *pSaveFileName, const char *pSaveFileType, int nFlags )
{
CleanUpContextKeyValues();
SetCompletionState( IN_PROGRESS );
m_pContextKeyValues = pContextKeyValues;
m_FileName = pSaveFileName;
m_SaveFileType = pSaveFileType;
m_OpenFileType = pOpenFileType;
m_OpenFileName = NULL;
m_bShowPerforceDialogs = ( nFlags & FOSM_SHOW_PERFORCE_DIALOGS ) != 0;
m_bShowSaveQuery = ( nFlags & FOSM_SHOW_SAVE_QUERY ) != 0;
m_bIsOpeningFile = true;
m_bWroteFile = false;
if ( m_bShowSaveQuery )
{
ShowSaveQuery();
return;
}
OpenFileDialog();
}
//-----------------------------------------------------------------------------
// Version of OpenFile that skips browsing for a particular file to open
//-----------------------------------------------------------------------------
void FileOpenStateMachine::OpenFile( const char *pOpenFileName, const char *pOpenFileType, KeyValues *pContextKeyValues, const char *pSaveFileName, const char *pSaveFileType, int nFlags )
{
CleanUpContextKeyValues();
SetCompletionState( IN_PROGRESS );
m_pContextKeyValues = pContextKeyValues;
m_FileName = pSaveFileName;
m_SaveFileType = pSaveFileType;
m_OpenFileType = pOpenFileType;
m_bShowPerforceDialogs = ( nFlags & FOSM_SHOW_PERFORCE_DIALOGS ) != 0;
m_bShowSaveQuery = ( nFlags & FOSM_SHOW_SAVE_QUERY ) != 0;
m_bIsOpeningFile = true;
m_bWroteFile = false;
m_OpenFileName = pOpenFileName;
if ( m_bShowSaveQuery )
{
ShowSaveQuery();
return;
}
OpenFileDialog();
}

View File

@ -0,0 +1,433 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <assert.h>
#include <vgui/ISurface.h>
#include <vgui/IVGui.h>
#include <vgui/IPanel.h>
#include <vgui/VGUI.h>
#include <KeyValues.h>
#include <tier0/dbg.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/FocusNavGroup.h>
#include <vgui_controls/Panel.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input : *panel - parent panel
//-----------------------------------------------------------------------------
FocusNavGroup::FocusNavGroup(Panel *panel) : _mainPanel(panel)
{
_currentFocus = NULL;
_topLevelFocus = false;
_defaultButton = NULL;
_currentDefaultButton = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
FocusNavGroup::~FocusNavGroup()
{
}
//-----------------------------------------------------------------------------
// Purpose: Sets the focus to the previous panel in the tab order
// Input : *panel - panel currently with focus
//-----------------------------------------------------------------------------
bool FocusNavGroup::RequestFocusPrev(VPANEL panel)
{
if(panel==0)
return false;
_currentFocus = NULL;
int newPosition = 9999999;
if (panel)
{
newPosition = ipanel()->GetTabPosition(panel);
}
bool bFound = false;
bool bRepeat = true;
Panel *best = NULL;
while (1)
{
newPosition--;
if (newPosition > 0)
{
int bestPosition = 0;
// look for the next tab position
for (int i = 0; i < _mainPanel->GetChildCount(); i++)
{
Panel *child = _mainPanel->GetChild(i);
if (child && child->IsVisible() && child->IsEnabled() && child->GetTabPosition())
{
int tabPosition = child->GetTabPosition();
if (tabPosition == newPosition)
{
// we've found the right tab
best = child;
bestPosition = newPosition;
// don't loop anymore since we've found the correct panel
break;
}
else if (tabPosition < newPosition && tabPosition > bestPosition)
{
// record the match since this is the closest so far
bestPosition = tabPosition;
best = child;
}
}
}
if (!bRepeat)
break;
if (best)
break;
}
else
{
// reset new position for next loop
newPosition = 9999999;
}
// haven't found an item
if (!_topLevelFocus)
{
// check to see if we should push the focus request up
if (_mainPanel->GetVParent() && _mainPanel->GetVParent() != surface()->GetEmbeddedPanel())
{
// we're not a top level panel, so forward up the request instead of looping
if (ipanel()->RequestFocusPrev(_mainPanel->GetVParent(), _mainPanel->GetVPanel()))
{
bFound = true;
SetCurrentDefaultButton(NULL);
break;
}
}
}
// not found an item, loop back
newPosition = 9999999;
bRepeat = false;
}
if (best)
{
_currentFocus = best->GetVPanel();
best->RequestFocus(-1);
bFound = true;
if (!CanButtonBeDefault(best->GetVPanel()))
{
if (_defaultButton)
{
SetCurrentDefaultButton(_defaultButton);
}
else
{
SetCurrentDefaultButton(NULL);
// we need to ask the parent to set its default button
if (_mainPanel->GetVParent())
{
ivgui()->PostMessage(_mainPanel->GetVParent(), new KeyValues("FindDefaultButton"), NULL);
}
}
}
else
{
SetCurrentDefaultButton(best->GetVPanel());
}
}
return bFound;
}
//-----------------------------------------------------------------------------
// Purpose: Sets the focus to the previous panel in the tab order
// Input : *panel - panel currently with focus
//-----------------------------------------------------------------------------
bool FocusNavGroup::RequestFocusNext(VPANEL panel)
{
// basic recursion guard, in case user has set up a bad focus hierarchy
static int stack_depth = 0;
stack_depth++;
_currentFocus = NULL;
int newPosition = 0;
if (panel)
{
newPosition = ipanel()->GetTabPosition(panel);
}
bool bFound = false;
bool bRepeat = true;
Panel *best = NULL;
while (1)
{
newPosition++;
int bestPosition = 999999;
// look for the next tab position
for (int i = 0; i < _mainPanel->GetChildCount(); i++)
{
Panel *child = _mainPanel->GetChild(i);
if ( !child )
continue;
if (child && child->IsVisible() && child->IsEnabled() && child->GetTabPosition())
{
int tabPosition = child->GetTabPosition();
if (tabPosition == newPosition)
{
// we've found the right tab
best = child;
bestPosition = newPosition;
// don't loop anymore since we've found the correct panel
break;
}
else if (tabPosition > newPosition && tabPosition < bestPosition)
{
// record the match since this is the closest so far
bestPosition = tabPosition;
best = child;
}
}
}
if (!bRepeat)
break;
if (best)
break;
// haven't found an item
// check to see if we should push the focus request up
if (!_topLevelFocus)
{
if (_mainPanel->GetVParent() && _mainPanel->GetVParent() != surface()->GetEmbeddedPanel())
{
// we're not a top level panel, so forward up the request instead of looping
if (stack_depth < 15)
{
if (ipanel()->RequestFocusNext(_mainPanel->GetVParent(), _mainPanel->GetVPanel()))
{
bFound = true;
SetCurrentDefaultButton(NULL);
break;
}
// if we find one then we break, otherwise we loop
}
}
}
// loop back
newPosition = 0;
bRepeat = false;
}
if (best)
{
_currentFocus = best->GetVPanel();
best->RequestFocus(1);
bFound = true;
if (!CanButtonBeDefault(best->GetVPanel()))
{
if (_defaultButton)
{
SetCurrentDefaultButton(_defaultButton);
}
else
{
SetCurrentDefaultButton(NULL);
// we need to ask the parent to set its default button
if (_mainPanel->GetVParent())
{
ivgui()->PostMessage(_mainPanel->GetVParent(), new KeyValues("FindDefaultButton"), NULL);
}
}
}
else
{
SetCurrentDefaultButton(best->GetVPanel());
}
}
stack_depth--;
return bFound;
}
//-----------------------------------------------------------------------------
// Purpose: sets the panel that owns this FocusNavGroup to be the root in the focus traversal heirarchy
//-----------------------------------------------------------------------------
void FocusNavGroup::SetFocusTopLevel(bool state)
{
_topLevelFocus = state;
}
//-----------------------------------------------------------------------------
// Purpose: sets panel which receives input when ENTER is hit
//-----------------------------------------------------------------------------
void FocusNavGroup::SetDefaultButton(Panel *panel)
{
VPANEL vpanel = panel ? panel->GetVPanel() : NULL;
if ( vpanel == _defaultButton.Get() )
return;
// Assert(CanButtonBeDefault(vpanel));
_defaultButton = vpanel;
SetCurrentDefaultButton(_defaultButton);
}
//-----------------------------------------------------------------------------
// Purpose: sets panel which receives input when ENTER is hit
//-----------------------------------------------------------------------------
void FocusNavGroup::SetCurrentDefaultButton(VPANEL panel, bool sendCurrentDefaultButtonMessage)
{
if (panel == _currentDefaultButton.Get())
return;
if ( sendCurrentDefaultButtonMessage && _currentDefaultButton.Get() != 0)
{
ivgui()->PostMessage(_currentDefaultButton, new KeyValues("SetAsCurrentDefaultButton", "state", 0), NULL);
}
_currentDefaultButton = panel;
if ( sendCurrentDefaultButtonMessage && _currentDefaultButton.Get() != 0)
{
ivgui()->PostMessage(_currentDefaultButton, new KeyValues("SetAsCurrentDefaultButton", "state", 1), NULL);
}
}
//-----------------------------------------------------------------------------
// Purpose: sets panel which receives input when ENTER is hit
//-----------------------------------------------------------------------------
VPANEL FocusNavGroup::GetCurrentDefaultButton()
{
return _currentDefaultButton;
}
//-----------------------------------------------------------------------------
// Purpose: sets panel which receives input when ENTER is hit
//-----------------------------------------------------------------------------
VPANEL FocusNavGroup::GetDefaultButton()
{
return _defaultButton;
}
//-----------------------------------------------------------------------------
// Purpose: finds the panel which is activated by the specified key
// Input : code - the keycode of the hotkey
// Output : Panel * - NULL if no panel found
//-----------------------------------------------------------------------------
Panel *FocusNavGroup::FindPanelByHotkey(wchar_t key)
{
for (int i = 0; i < _mainPanel->GetChildCount(); i++)
{
Panel *child = _mainPanel->GetChild(i);
if ( !child )
continue;
Panel *hot = child->HasHotkey(key);
if (hot && hot->IsVisible() && hot->IsEnabled())
{
return hot;
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Panel *FocusNavGroup::GetDefaultPanel()
{
for (int i = 0; i < _mainPanel->GetChildCount(); i++)
{
Panel *child = _mainPanel->GetChild(i);
if ( !child )
continue;
if (child->GetTabPosition() == 1)
{
return child;
}
}
return NULL; // no specific panel set
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Panel *FocusNavGroup::GetCurrentFocus()
{
return _currentFocus ? ipanel()->GetPanel(_currentFocus, vgui::GetControlsModuleName()) : NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Sets the current focus
//-----------------------------------------------------------------------------
VPANEL FocusNavGroup::SetCurrentFocus(VPANEL focus, VPANEL defaultPanel)
{
_currentFocus = focus;
// if we haven't found a default panel yet, let's see if we know of one
if (defaultPanel == 0)
{
// can this focus itself by the default
if (CanButtonBeDefault(focus))
{
defaultPanel = focus;
}
else if (_defaultButton) // do we know of a default button
{
defaultPanel = _defaultButton;
}
}
SetCurrentDefaultButton(defaultPanel);
return defaultPanel;
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if the specified panel can be the default
//-----------------------------------------------------------------------------
bool FocusNavGroup::CanButtonBeDefault(VPANEL panel)
{
if( panel == 0 )
return false;
KeyValues *data = new KeyValues("CanBeDefaultButton");
bool bResult = false;
if (ipanel()->RequestInfo(panel, data))
{
bResult = (data->GetInt("result") == 1);
}
data->deleteThis();
return bResult;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,308 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include <math.h>
#include <vgui_controls/GraphPanel.h>
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include <vgui/IVGui.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( GraphPanel );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
GraphPanel::GraphPanel(Panel *parent, const char *name) : BaseClass(parent, name)
{
m_flDomainSize = 100.0f;
m_flLowRange = 0.0f;
m_flHighRange = 1.0f;
m_bUseDynamicRange = true;
m_flMinDomainSize = 0.0f;
m_flMaxDomainSize = 0.0f;
m_bMaxDomainSizeSet = false;
// rendering, need to pull these from scheme/res file
m_iGraphBarWidth = 2;
m_iGraphBarGapWidth = 2;
}
//-----------------------------------------------------------------------------
// Purpose: domain settings (x-axis settings)
//-----------------------------------------------------------------------------
void GraphPanel::SetDisplayDomainSize(float size)
{
m_flDomainSize = size;
// set the max domain size if it hasn't been set yet
if (!m_bMaxDomainSizeSet)
{
SetMaxDomainSize(size);
}
}
//-----------------------------------------------------------------------------
// Purpose: sets the smallest domain that will be displayed
//-----------------------------------------------------------------------------
void GraphPanel::SetMinDomainSize(float size)
{
m_flMinDomainSize = size;
}
//-----------------------------------------------------------------------------
// Purpose: sets the samples to keep
//-----------------------------------------------------------------------------
void GraphPanel::SetMaxDomainSize(float size)
{
m_flMaxDomainSize = size;
m_bMaxDomainSizeSet = true;
}
//-----------------------------------------------------------------------------
// Purpose: range settings (y-axis settings)
//-----------------------------------------------------------------------------
void GraphPanel::SetUseFixedRange(float lowRange, float highRange)
{
m_bUseDynamicRange = false;
m_flLowRange = lowRange;
m_flHighRange = highRange;
}
//-----------------------------------------------------------------------------
// Purpose: Sets the graph to dynamically determine the range
//-----------------------------------------------------------------------------
void GraphPanel::SetUseDynamicRange(float *rangeList, int numRanges)
{
m_bUseDynamicRange = true;
m_RangeList.CopyArray(rangeList, numRanges);
}
//-----------------------------------------------------------------------------
// Purpose: Gets the currently displayed range
//-----------------------------------------------------------------------------
void GraphPanel::GetDisplayedRange(float &lowRange, float &highRange)
{
lowRange = m_flLowRange;
highRange = m_flHighRange;
}
//-----------------------------------------------------------------------------
// Purpose: adds an item to the end of the list
//-----------------------------------------------------------------------------
void GraphPanel::AddItem(float sampleEnd, float sampleValue)
{
if (m_Samples.Count() && m_Samples[m_Samples.Tail()].value == sampleValue)
{
// collapse identical samples
m_Samples[m_Samples.Tail()].sampleEnd = sampleEnd;
}
else
{
// add to the end of the samples list
Sample_t item;
item.value = sampleValue;
item.sampleEnd = sampleEnd;
m_Samples.AddToTail(item);
}
// see if this frees up any samples past the end
if (m_bMaxDomainSizeSet)
{
float freePoint = sampleEnd - m_flMaxDomainSize;
while (m_Samples[m_Samples.Head()].sampleEnd < freePoint)
{
m_Samples.Remove(m_Samples.Head());
}
}
/*
// see the max number of samples necessary to display this information reasonably precisely
static const int MAX_LIKELY_GRAPH_WIDTH = 800;
int maxSamplesNeeded = 2 * MAX_LIKELY_GRAPH_WIDTH / (m_iGraphBarWidth + m_iGraphBarGapWidth);
if (m_Samples.Count() > 2)
{
// see if we can collapse some items
float highestSample = m_Samples[m_Samples.Tail()].sampleEnd;
// iterate the items
// always keep the head around so we have something to go against
int sampleIndex = m_Samples.Next(m_Samples.Head());
int nextSampleIndex = m_Samples.Next(sampleIndex);
while (m_Samples.IsInList(nextSampleIndex))
{
// calculate what sampling precision is actually needed to display this data
float distanceFromEnd = highestSample - m_Samples[sampleIndex].sampleEnd;
// if (distanceFromEnd < m_flDomainSize)
// break;
//!! this calculation is very incorrect
float minNeededSampleSize = distanceFromEnd / (m_flMinDomainSize * maxSamplesNeeded);
float sampleSize = m_Samples[nextSampleIndex].sampleEnd - m_Samples[sampleIndex].sampleEnd;
if (sampleSize < minNeededSampleSize)
{
// collapse the item into the next index
m_Samples[nextSampleIndex].value = 0.5f * (m_Samples[nextSampleIndex].value + m_Samples[sampleIndex].value);
// remove the item from the list
m_Samples.Remove(sampleIndex);
// move to the next item
sampleIndex = nextSampleIndex;
nextSampleIndex = m_Samples.Next(sampleIndex);
}
else
{
// this item didn't need collapsing, so assume the next item won't
break;
}
}
}
*/
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: returns number of items that can be displayed
//-----------------------------------------------------------------------------
int GraphPanel::GetVisibleItemCount()
{
return GetWide() / (m_iGraphBarWidth + m_iGraphBarGapWidth);
}
//-----------------------------------------------------------------------------
// Purpose: lays out the graph
//-----------------------------------------------------------------------------
void GraphPanel::PerformLayout()
{
BaseClass::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose: draws the graph
//-----------------------------------------------------------------------------
void GraphPanel::Paint()
{
if (!m_Samples.Count())
return;
// walk from right to left drawing the resampled data
int sampleIndex = m_Samples.Tail();
int x = GetWide() - (m_iGraphBarWidth + m_iGraphBarGapWidth);
// calculate how big each sample should be
float sampleSize = m_flDomainSize / GetVisibleItemCount();
// calculate where in the domain we start resampling
float resampleStart = m_Samples[sampleIndex].sampleEnd - sampleSize;
// always resample from a sample point that is a multiple of the sampleSize
resampleStart -= (float)fmod(resampleStart, sampleSize);
// bar size multiplier
float barSizeMultiplier = GetTall() / (m_flHighRange - m_flLowRange);
// set render color
surface()->DrawSetColor(GetFgColor());
// recalculate the sample range for dynamic resizing
float flMinValue = m_Samples[m_Samples.Head()].value;
float flMaxValue = m_Samples[m_Samples.Head()].value;
// iterate the bars to draw
while (x > 0 && m_Samples.IsInList(sampleIndex))
{
// move back the drawing point
x -= (m_iGraphBarWidth + m_iGraphBarGapWidth);
// collect the samples
float value = 0.0f;
float maxValue = 0.0f;
int samplesTouched = 0;
int prevSampleIndex = m_Samples.Previous(sampleIndex);
while (m_Samples.IsInList(prevSampleIndex))
{
// take the value
value += m_Samples[sampleIndex].value;
samplesTouched++;
// do some work to calculate the sample range
if (m_Samples[sampleIndex].value < flMinValue)
{
flMinValue = m_Samples[sampleIndex].value;
}
if (m_Samples[sampleIndex].value > flMaxValue)
{
flMaxValue = m_Samples[sampleIndex].value;
}
if (m_Samples[sampleIndex].value > maxValue)
{
maxValue = m_Samples[sampleIndex].value;
}
if (resampleStart < m_Samples[prevSampleIndex].sampleEnd)
{
// we're out of the sampling range, we need to move on to the next sample
sampleIndex = prevSampleIndex;
prevSampleIndex = m_Samples.Previous(sampleIndex);
}
else
{
// we're done with this resample
// move back the resample start
resampleStart -= sampleSize;
// draw the current item
break;
}
}
// draw the item
// show the max value in the sample, not the average
int size = (int)(maxValue * barSizeMultiplier);
// int size = (int)((value * barSizeMultiplier) / samplesTouched);
surface()->DrawFilledRect(x, GetTall() - size, x + m_iGraphBarWidth, GetTall());
}
// calculate our final range (for use next frame)
if (m_bUseDynamicRange)
{
flMinValue = 0;
// find the range that fits
for (int i = 0; i < m_RangeList.Count(); i++)
{
if (m_RangeList[i] > flMaxValue)
{
flMaxValue = m_RangeList[i];
break;
}
}
m_flLowRange = flMinValue;
m_flHighRange = flMaxValue;
}
}
//-----------------------------------------------------------------------------
// Purpose: sets up colors
//-----------------------------------------------------------------------------
void GraphPanel::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetFgColor(GetSchemeColor("GraphPanel.FgColor", pScheme));
SetBgColor(GetSchemeColor("GraphPanel.BgColor", pScheme));
SetBorder(pScheme->GetBorder("ButtonDepressedBorder"));
}

1794
vgui2/vgui_controls/HTML.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,282 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <Color.h>
#include <vgui/IPanel.h>
#include <vgui/ISurface.h>
#include <vgui_controls/Image.h>
#include <vgui_controls/Controls.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Conctructor. Start with default position and default color.
//-----------------------------------------------------------------------------
Image::Image()
{
SetPos(0,0);
SetSize(0,0);
SetColor(Color(255,255,255,255));
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
Image::~Image()
{
}
//-----------------------------------------------------------------------------
// Purpose: Set the position of the image, you need to reset this every time you
// call Paint()
//-----------------------------------------------------------------------------
void Image::SetPos(int x,int y)
{
_pos[0]=x;
_pos[1]=y;
}
//-----------------------------------------------------------------------------
// Purpose: Get the position of the image
//-----------------------------------------------------------------------------
void Image::GetPos(int& x,int& y)
{
x=_pos[0];
y=_pos[1];
}
//-----------------------------------------------------------------------------
// Purpose: Get the size of the image
//-----------------------------------------------------------------------------
void Image::GetSize(int &wide, int &tall)
{
wide = _size[0];
tall = _size[1];
}
//-----------------------------------------------------------------------------
// Purpose: Gets the size of the image contents (by default the set size)
//-----------------------------------------------------------------------------
void Image::GetContentSize(int &wide, int &tall)
{
GetSize(wide, tall);
}
//-----------------------------------------------------------------------------
// Purpose: Set the size of the image
//-----------------------------------------------------------------------------
void Image::SetSize(int wide, int tall)
{
_size[0]=wide;
_size[1]=tall;
}
//-----------------------------------------------------------------------------
// Purpose: Set the draw color using a Color struct.
//-----------------------------------------------------------------------------
void Image::DrawSetColor(Color col)
{
surface()->DrawSetColor(col[0], col[1], col[2], col[3]);
}
//-----------------------------------------------------------------------------
// Purpose: Set the draw color using RGBA ints
//-----------------------------------------------------------------------------
void Image::DrawSetColor(int r,int g,int b,int a)
{
surface()->DrawSetColor(r,g,b,a);
}
//-----------------------------------------------------------------------------
// Purpose: Draw a filled rectangle
//-----------------------------------------------------------------------------
void Image::DrawFilledRect(int x0,int y0,int x1,int y1)
{
x0+=_pos[0];
y0+=_pos[1];
x1+=_pos[0];
y1+=_pos[1];
surface()->DrawFilledRect(x0,y0,x1,y1);
}
//-----------------------------------------------------------------------------
// Purpose: Draw an outlined rectangle
//-----------------------------------------------------------------------------
void Image::DrawOutlinedRect(int x0,int y0,int x1,int y1)
{
x0+=_pos[0];
y0+=_pos[1];
x1+=_pos[0];
y1+=_pos[1];
surface()->DrawOutlinedRect(x0,y0,x1,y1);
}
//-----------------------------------------------------------------------------
// Purpose: Draw a line between two points
//-----------------------------------------------------------------------------
void Image::DrawLine(int x0,int y0,int x1,int y1)
{
x0+=_pos[0];
y0+=_pos[1];
x1+=_pos[0];
y1+=_pos[1];
surface()->DrawLine(x0,y0,x1,y1);
}
//-----------------------------------------------------------------------------
// Purpose: Draw a line between a list of 'numPoints' points
//-----------------------------------------------------------------------------
void Image::DrawPolyLine(int *px, int *py, int numPoints)
{
// update the positions to be relative to this panel
for(int i=0;i<numPoints;i++)
{
px[i] += _pos[0];
py[i] += _pos[1];
}
surface()->DrawPolyLine(px, py, numPoints);
}
//-----------------------------------------------------------------------------
// Purpose: Set the font
//-----------------------------------------------------------------------------
void Image::DrawSetTextFont(HFont font)
{
surface()->DrawSetTextFont(font);
}
//-----------------------------------------------------------------------------
// Purpose: Set the text color using a color struct
//-----------------------------------------------------------------------------
void Image::DrawSetTextColor(Color sc)
{
surface()->DrawSetTextColor(sc[0], sc[1], sc[2], sc[3]);
}
//-----------------------------------------------------------------------------
// Purpose: Set the text color useing RGBA ints
//-----------------------------------------------------------------------------
void Image::DrawSetTextColor(int r,int g,int b,int a)
{
surface()->DrawSetTextColor(r,g,b,a);
}
//-----------------------------------------------------------------------------
// Purpose: Set the text position
//-----------------------------------------------------------------------------
void Image::DrawSetTextPos(int x,int y)
{
x+=_pos[0];
y+=_pos[1];
surface()->DrawSetTextPos(x,y);
}
//-----------------------------------------------------------------------------
// Purpose: Draw a text string
//-----------------------------------------------------------------------------
void Image::DrawPrintText(const wchar_t *str,int strlen)
{
surface()->DrawPrintText(str, strlen);
}
//-----------------------------------------------------------------------------
// Purpose: Draw a text string at the given coords.
//-----------------------------------------------------------------------------
void Image::DrawPrintText(int x, int y, const wchar_t *str, int strlen)
{
x += _pos[0];
y += _pos[1];
surface()->DrawSetTextPos(x, y);
surface()->DrawPrintText(str, strlen);
}
//-----------------------------------------------------------------------------
// Purpose: Draw a character
//-----------------------------------------------------------------------------
void Image::DrawPrintChar(wchar_t ch)
{
surface()->DrawUnicodeChar(ch);
}
//-----------------------------------------------------------------------------
// Purpose: Draw a character at the given coords
//-----------------------------------------------------------------------------
void Image::DrawPrintChar(int x, int y, wchar_t ch)
{
x+=_pos[0];
y+=_pos[1];
surface()->DrawSetTextPos(x, y);
surface()->DrawUnicodeChar(ch);
}
//-----------------------------------------------------------------------------
// Purpose: Set a texture
//-----------------------------------------------------------------------------
void Image::DrawSetTexture(int id)
{
surface()->DrawSetTexture(id);
}
//-----------------------------------------------------------------------------
// Purpose: Draw a rectangle filled with the current texture
//-----------------------------------------------------------------------------
void Image::DrawTexturedRect(int x0,int y0,int x1,int y1)
{
surface()->DrawTexturedRect(x0,y0,x1,y1);
}
//-----------------------------------------------------------------------------
// Purpose: Paint the contents of the image on screen.
// You must call this explicitly each frame.
//-----------------------------------------------------------------------------
void Image::Paint()
{
}
//-----------------------------------------------------------------------------
// Purpose: Set the current color using a color struct
//-----------------------------------------------------------------------------
void Image::SetColor(Color color)
{
_color=color;
DrawSetTextColor(color); // now update the device context underneath us :)
}
//-----------------------------------------------------------------------------
// Purpose: Get the current color as a color struct
//-----------------------------------------------------------------------------
Color Image::GetColor()
{
return _color;
}
bool Image::Evict()
{
return false;
}
int Image::GetNumFrames()
{
return 0;
}
void Image::SetFrame( int nFrame )
{
}
HTexture Image::GetID()
{
return 0;
}

View File

@ -0,0 +1,106 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/VGUI.h>
#include <Color.h>
#include <vgui_controls/ImageList.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: blank image, intentially draws nothing
//-----------------------------------------------------------------------------
class BlankImage : public IImage
{
public:
virtual void Paint() {}
virtual void SetPos(int x, int y) {}
virtual void GetContentSize(int &wide, int &tall) { wide = 0; tall = 0; }
virtual void GetSize(int &wide, int &tall) { wide = 0; tall = 0; }
virtual void SetSize(int wide, int tall) {}
virtual void SetColor(Color col) {}
virtual bool Evict() { return false; }
virtual int GetNumFrames() { return 0; }
virtual void SetFrame( int nFrame ) {}
virtual HTexture GetID() { return 0; }
virtual void SetRotation( int iRotation ) { return; };
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ImageList::ImageList(bool deleteImagesWhenDone)
{
m_bDeleteImagesWhenDone = deleteImagesWhenDone;
AddImage(new BlankImage());
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
ImageList::~ImageList()
{
if (m_bDeleteImagesWhenDone)
{
// delete all the images, except for the first image (which is always the blank image)
for (int i = 1; i < m_Images.Count(); i++)
{
delete m_Images[i];
}
}
}
//-----------------------------------------------------------------------------
// Purpose: adds a new image to the list, returning the index it was placed at
//-----------------------------------------------------------------------------
int ImageList::AddImage(vgui::IImage *image)
{
return m_Images.AddToTail(image);
}
//-----------------------------------------------------------------------------
// Purpose: sets an image at a specified index, growing and adding NULL images if necessary
//-----------------------------------------------------------------------------
void ImageList::SetImageAtIndex(int index, vgui::IImage *image)
{
// allocate more images if necessary
while (m_Images.Count() <= index)
{
m_Images.AddToTail(NULL);
}
m_Images[index] = image;
}
//-----------------------------------------------------------------------------
// Purpose: returns the number of images
//-----------------------------------------------------------------------------
int ImageList::GetImageCount()
{
return m_Images.Count();
}
//-----------------------------------------------------------------------------
// Purpose: gets an image, imageIndex is of range [0, GetImageCount)
//-----------------------------------------------------------------------------
vgui::IImage *ImageList::GetImage(int imageIndex)
{
return m_Images[imageIndex];
}
//-----------------------------------------------------------------------------
// Purpose: returns true if an index is valid
//-----------------------------------------------------------------------------
bool ImageList::IsValidIndex(int imageIndex)
{
return m_Images.IsValidIndex(imageIndex);
}

View File

@ -0,0 +1,475 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#include <vgui/IBorder.h>
#include <vgui/ISurface.h>
#include <vgui/IScheme.h>
#include <vgui/IBorder.h>
#include <KeyValues.h>
#include <vgui_controls/ImagePanel.h>
#include <vgui_controls/Image.h>
#include <vgui_controls/Controls.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( ImagePanel );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ImagePanel::ImagePanel(Panel *parent, const char *name) : Panel(parent, name)
{
m_pImage = NULL;
m_pszImageName = NULL;
m_pszFillColorName = NULL;
m_pszDrawColorName = NULL; // HPE addition
m_bCenterImage = false;
m_bScaleImage = false;
m_bTileImage = false;
m_bTileHorizontally = false;
m_bTileVertically = false;
m_bPositionImage = true;
m_fScaleAmount = 0.0f;
m_FillColor = Color(0, 0, 0, 0);
m_DrawColor = Color(255,255,255,255);
m_iRotation = ROTATED_UNROTATED;
SetImage( m_pImage );
REGISTER_COLOR_AS_OVERRIDABLE( m_FillColor, "fillcolor_override" );
REGISTER_COLOR_AS_OVERRIDABLE( m_DrawColor, "drawcolor_override" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ImagePanel::~ImagePanel()
{
delete [] m_pszImageName;
delete [] m_pszFillColorName;
delete [] m_pszDrawColorName; // HPE addition
}
//-----------------------------------------------------------------------------
// Purpose: handles size changing
//-----------------------------------------------------------------------------
void ImagePanel::OnSizeChanged(int newWide, int newTall)
{
BaseClass::OnSizeChanged(newWide, newTall);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ImagePanel::SetImage(IImage *image)
{
m_pImage = image;
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: sets an image by file name
//-----------------------------------------------------------------------------
void ImagePanel::SetImage(const char *imageName)
{
if ( imageName && m_pszImageName && V_stricmp( imageName, m_pszImageName ) == 0 )
return;
int len = Q_strlen(imageName) + 1;
delete [] m_pszImageName;
m_pszImageName = new char[ len ];
Q_strncpy(m_pszImageName, imageName, len );
InvalidateLayout(false, true); // force applyschemesettings to run
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
IImage *ImagePanel::GetImage()
{
return m_pImage;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Color ImagePanel::GetDrawColor( void )
{
return m_DrawColor;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ImagePanel::SetDrawColor( Color drawColor )
{
m_DrawColor = drawColor;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ImagePanel::PaintBackground()
{
if (m_FillColor[3] > 0)
{
// draw the specified fill color
int wide, tall;
GetSize(wide, tall);
surface()->DrawSetColor(m_FillColor);
surface()->DrawFilledRect(0, 0, wide, tall);
}
if ( m_pImage )
{
//=============================================================================
// HPE_BEGIN:
// [pfreese] Color should be always set from GetDrawColor(), not just when
// scaling is true (see previous code)
//=============================================================================
// surface()->DrawSetColor( 255, 255, 255, GetAlpha() );
m_pImage->SetColor( GetDrawColor() );
m_pImage->SetRotation( m_iRotation );
//=============================================================================
// HPE_END
//=============================================================================
if ( m_bPositionImage )
{
if ( m_bCenterImage )
{
int wide, tall;
GetSize(wide, tall);
int imageWide, imageTall;
m_pImage->GetSize( imageWide, imageTall );
if ( m_bScaleImage && m_fScaleAmount > 0.0f )
{
imageWide = static_cast<int>( static_cast<float>(imageWide) * m_fScaleAmount );
imageTall = static_cast<int>( static_cast<float>(imageTall) * m_fScaleAmount );
}
m_pImage->SetPos( (wide - imageWide) / 2, (tall - imageTall) / 2 );
}
else
{
m_pImage->SetPos(0, 0);
}
}
if (m_bScaleImage)
{
// Image size is stored in the bitmap, so temporarily set its size
// to our panel size and then restore after we draw it.
int imageWide, imageTall;
m_pImage->GetSize( imageWide, imageTall );
if ( m_fScaleAmount > 0.0f )
{
float wide, tall;
wide = static_cast<float>(imageWide) * m_fScaleAmount;
tall = static_cast<float>(imageTall) * m_fScaleAmount;
m_pImage->SetSize( static_cast<int>(wide), static_cast<int>(tall) );
}
else
{
int wide, tall;
GetSize( wide, tall );
m_pImage->SetSize( wide, tall );
}
m_pImage->Paint();
m_pImage->SetSize( imageWide, imageTall );
}
else if ( m_bTileImage || m_bTileHorizontally || m_bTileVertically )
{
int wide, tall;
GetSize(wide, tall);
int imageWide, imageTall;
m_pImage->GetSize( imageWide, imageTall );
int y = 0;
while ( y < tall )
{
int x = 0;
while (x < wide)
{
m_pImage->SetPos(x,y);
m_pImage->Paint();
x += imageWide;
if ( !m_bTileHorizontally )
break;
}
y += imageTall;
if ( !m_bTileVertically )
break;
}
if ( m_bPositionImage )
{
m_pImage->SetPos(0, 0);
}
}
else
{
m_pImage->SetColor( GetDrawColor() );
m_pImage->Paint();
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Gets control settings for editing
//-----------------------------------------------------------------------------
void ImagePanel::GetSettings(KeyValues *outResourceData)
{
BaseClass::GetSettings(outResourceData);
if (m_pszImageName)
{
outResourceData->SetString("image", m_pszImageName);
}
if (m_pszFillColorName)
{
outResourceData->SetString("fillcolor", m_pszFillColorName);
}
//=============================================================================
// HPE_BEGIN:
// [pfreese] Added support for specifying drawcolor
//=============================================================================
if (m_pszDrawColorName)
{
outResourceData->SetString("drawcolor", m_pszDrawColorName);
}
//=============================================================================
// HPE_END
//=============================================================================
if (GetBorder())
{
outResourceData->SetString("border", GetBorder()->GetName());
}
outResourceData->GetInt("positionImage", m_bPositionImage );
outResourceData->SetInt("scaleImage", m_bScaleImage);
outResourceData->SetFloat("scaleAmount", m_fScaleAmount);
outResourceData->SetInt("tileImage", m_bTileImage);
outResourceData->SetInt("tileHorizontally", m_bTileHorizontally);
outResourceData->SetInt("tileVertically", m_bTileVertically);
}
//-----------------------------------------------------------------------------
// Purpose: Applies designer settings from res file
//-----------------------------------------------------------------------------
void ImagePanel::ApplySettings(KeyValues *inResourceData)
{
delete [] m_pszImageName;
delete [] m_pszFillColorName;
delete [] m_pszDrawColorName; // HPE addition
m_pszImageName = NULL;
m_pszFillColorName = NULL;
m_pszDrawColorName = NULL; // HPE addition
m_bPositionImage = inResourceData->GetInt("positionImage", 1);
m_bScaleImage = inResourceData->GetInt("scaleImage", 0);
m_fScaleAmount = inResourceData->GetFloat("scaleAmount", 0.0f);
m_bTileImage = inResourceData->GetInt("tileImage", 0);
m_bTileHorizontally = inResourceData->GetInt("tileHorizontally", m_bTileImage);
m_bTileVertically = inResourceData->GetInt("tileVertically", m_bTileImage);
m_iRotation = inResourceData->GetInt( "rotation", ROTATED_UNROTATED );
const char *imageName = inResourceData->GetString("image", "");
if ( *imageName )
{
SetImage( imageName );
}
const char *pszFillColor = inResourceData->GetString("fillcolor", "");
if (*pszFillColor)
{
int r = 0, g = 0, b = 0, a = 255;
int len = Q_strlen(pszFillColor) + 1;
m_pszFillColorName = new char[ len ];
Q_strncpy( m_pszFillColorName, pszFillColor, len );
if (sscanf(pszFillColor, "%d %d %d %d", &r, &g, &b, &a) >= 3)
{
// it's a direct color
m_FillColor = Color(r, g, b, a);
}
else
{
IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
m_FillColor = pScheme->GetColor(pszFillColor, Color(0, 0, 0, 0));
}
}
//=============================================================================
// HPE_BEGIN:
// [pfreese] Added support for specifying drawcolor
//=============================================================================
const char *pszDrawColor = inResourceData->GetString("drawcolor", "");
if (*pszDrawColor)
{
int r = 255, g = 255, b = 255, a = 255;
int len = Q_strlen(pszDrawColor) + 1;
m_pszDrawColorName = new char[ len ];
Q_strncpy( m_pszDrawColorName, pszDrawColor, len );
if (sscanf(pszDrawColor, "%d %d %d %d", &r, &g, &b, &a) >= 3)
{
// it's a direct color
m_DrawColor = Color(r, g, b, a);
}
else
{
IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
m_DrawColor = pScheme->GetColor(pszDrawColor, Color(255, 255, 255, 255));
}
}
//=============================================================================
// HPE_END
//=============================================================================
const char *pszBorder = inResourceData->GetString("border", "");
if (*pszBorder)
{
IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
SetBorder(pScheme->GetBorder(pszBorder));
}
BaseClass::ApplySettings(inResourceData);
}
//-----------------------------------------------------------------------------
// Purpose: load the image, this is done just before this control is displayed
//-----------------------------------------------------------------------------
void ImagePanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings(pScheme);
if ( m_pszImageName && strlen( m_pszImageName ) > 0 )
{
SetImage(scheme()->GetImage(m_pszImageName, m_bScaleImage));
}
}
//-----------------------------------------------------------------------------
// Purpose: Describes editing details
//-----------------------------------------------------------------------------
const char *ImagePanel::GetDescription()
{
static char buf[1024];
_snprintf(buf, sizeof(buf), "%s, string image, string border, string fillcolor, bool scaleImage", BaseClass::GetDescription());
return buf;
}
//-----------------------------------------------------------------------------
// Purpose: sets whether or not the image should scale to fit the size of the ImagePanel (defaults to false)
//-----------------------------------------------------------------------------
void ImagePanel::SetShouldScaleImage( bool state )
{
m_bScaleImage = state;
}
//-----------------------------------------------------------------------------
// Purpose: gets whether or not the image should be scaled to fit the size of the ImagePanel
//-----------------------------------------------------------------------------
bool ImagePanel::GetShouldScaleImage()
{
return m_bScaleImage;
}
//-----------------------------------------------------------------------------
// Purpose: used in conjunction with setting that the image should scale and defines an absolute scale amount
//-----------------------------------------------------------------------------
void ImagePanel::SetScaleAmount( float scale )
{
m_fScaleAmount = scale;
}
float ImagePanel::GetScaleAmount( void )
{
return m_fScaleAmount;
}
//-----------------------------------------------------------------------------
// Purpose: set the color to fill with, if no Image is specified
//-----------------------------------------------------------------------------
void ImagePanel::SetFillColor( Color col )
{
m_FillColor = col;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
Color ImagePanel::GetFillColor()
{
return m_FillColor;
}
char *ImagePanel::GetImageName()
{
return m_pszImageName;
}
bool ImagePanel::EvictImage()
{
if ( !m_pImage )
{
// nothing to do
return false;
}
if ( !scheme()->DeleteImage( m_pszImageName ) )
{
// no eviction occured, could have an outstanding reference
return false;
}
// clear out our cached concept of it
// as it may change
// the next SetImage() will re-establish
m_pImage = NULL;
delete [] m_pszImageName;
m_pszImageName = NULL;
return true;
}
int ImagePanel::GetNumFrames()
{
if ( !m_pImage )
{
return 0;
}
return m_pImage->GetNumFrames();
}
void ImagePanel::SetFrame( int nFrame )
{
if ( !m_pImage )
{
return;
}
return m_pImage->SetFrame( nFrame );
}

View File

@ -0,0 +1,236 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include <vgui_controls/InputDialog.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/TextEntry.h>
#include "tier1/KeyValues.h"
#include "vgui/IInput.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
BaseInputDialog::BaseInputDialog( vgui::Panel *parent, const char *title ) :
BaseClass( parent, NULL )
{
m_pContextKeyValues = NULL;
SetDeleteSelfOnClose( true );
SetTitle(title, true);
SetSize(320, 180);
SetSizeable( false );
m_pCancelButton = new Button(this, "CancelButton", "#VGui_Cancel");
m_pOKButton = new Button(this, "OKButton", "#VGui_OK");
m_pCancelButton->SetCommand("Cancel");
m_pOKButton->SetCommand("OK");
m_pOKButton->SetAsDefaultButton( true );
if ( parent )
{
AddActionSignalTarget( parent );
}
}
BaseInputDialog::~BaseInputDialog()
{
CleanUpContextKeyValues();
}
//-----------------------------------------------------------------------------
// Purpose: Cleans up the keyvalues
//-----------------------------------------------------------------------------
void BaseInputDialog::CleanUpContextKeyValues()
{
if ( m_pContextKeyValues )
{
m_pContextKeyValues->deleteThis();
m_pContextKeyValues = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void BaseInputDialog::DoModal( KeyValues *pContextKeyValues )
{
CleanUpContextKeyValues();
m_pContextKeyValues = pContextKeyValues;
BaseClass::DoModal();
}
//-----------------------------------------------------------------------------
// Purpose: lays out controls
//-----------------------------------------------------------------------------
void BaseInputDialog::PerformLayout()
{
BaseClass::PerformLayout();
int w, h;
GetSize( w, h );
// lay out all the controls
int topy = IsSmallCaption() ? 15 : 30;
int halfw = w / 2;
PerformLayout( 12, topy, w - 24, h - 100 );
m_pOKButton->SetBounds( halfw - 84, h - 30, 72, 24 );
m_pCancelButton->SetBounds( halfw + 12, h - 30, 72, 24 );
}
//-----------------------------------------------------------------------------
// Purpose: handles button commands
//-----------------------------------------------------------------------------
void BaseInputDialog::OnCommand(const char *command)
{
KeyValues *kv = NULL;
if ( !stricmp( command, "OK" ) )
{
kv = new KeyValues( "InputCompleted" );
kv->SetPtr( "dialog", this );
}
else if ( !stricmp( command, "Cancel" ) )
{
kv = new KeyValues( "InputCanceled" );
}
else
{
BaseClass::OnCommand( command );
return;
}
if ( m_pContextKeyValues )
{
kv->AddSubKey( m_pContextKeyValues );
m_pContextKeyValues = NULL;
}
PostActionSignal( kv );
CloseModal();
}
//-----------------------------------------------------------------------------
// Purpose: Utility dialog, used to ask yes/no questions of the user
//-----------------------------------------------------------------------------
InputMessageBox::InputMessageBox( vgui::Panel *parent, const char *title, char const *prompt )
: BaseClass( parent, title )
{
SetSize( 320, 120 );
m_pPrompt = new Label( this, "Prompt", prompt );
}
InputMessageBox::~InputMessageBox()
{
}
void InputMessageBox::PerformLayout( int x, int y, int w, int h )
{
m_pPrompt->SetBounds( x, y, w, 24 );
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
InputDialog::InputDialog(vgui::Panel *parent, const char *title, char const *prompt, char const *defaultValue /*=""*/ ) :
BaseClass(parent, title)
{
SetSize( 320, 120 );
m_pPrompt = new Label( this, "Prompt", prompt );
m_pInput = new TextEntry( this, "Text" );
m_pInput->SetText( defaultValue );
m_pInput->SelectAllText( true );
m_pInput->RequestFocus();
}
InputDialog::~InputDialog()
{
}
//-----------------------------------------------------------------------------
// Sets the dialog to be multiline
//-----------------------------------------------------------------------------
void InputDialog::SetMultiline( bool state )
{
m_pInput->SetMultiline( state );
m_pInput->SetCatchEnterKey( state );
}
//-----------------------------------------------------------------------------
// Allow numeric input only
//-----------------------------------------------------------------------------
void InputDialog::AllowNumericInputOnly( bool bOnlyNumeric )
{
if ( m_pInput )
{
m_pInput->SetAllowNumericInputOnly( bOnlyNumeric );
}
}
//-----------------------------------------------------------------------------
// Purpose: lays out controls
//-----------------------------------------------------------------------------
void InputDialog::PerformLayout( int x, int y, int w, int h )
{
m_pPrompt->SetBounds( x, y, w, 24 );
m_pInput ->SetBounds( x, y + 30, w, m_pInput->IsMultiline() ? h - 30 : 24 );
}
//-----------------------------------------------------------------------------
// Purpose: handles button commands
//-----------------------------------------------------------------------------
void InputDialog::OnCommand(const char *command)
{
// overriding OnCommand for backwards compatability
// it'd be nice at some point to find all uses of InputDialog and just use BaseInputDialog's OnCommand
if (!stricmp(command, "OK"))
{
int nTextLength = m_pInput->GetTextLength() + 1;
char* txt = (char*)_alloca( nTextLength * sizeof(char) );
m_pInput->GetText( txt, nTextLength );
KeyValues *kv = new KeyValues( "InputCompleted", "text", txt );
if ( m_pContextKeyValues )
{
kv->AddSubKey( m_pContextKeyValues );
m_pContextKeyValues = NULL;
}
PostActionSignal( kv );
CloseModal();
}
else if (!stricmp(command, "Cancel"))
{
KeyValues *kv = new KeyValues( "InputCanceled" );
if ( m_pContextKeyValues )
{
kv->AddSubKey( m_pContextKeyValues );
m_pContextKeyValues = NULL;
}
PostActionSignal( kv );
CloseModal();
}
else
{
BaseClass::OnCommand(command);
}
}

View File

@ -0,0 +1,355 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "vgui_controls/KeyBindingHelpDialog.h"
#include "vgui_controls/ListPanel.h"
#include "vgui/ISurface.h"
#include "vgui/IVGui.h"
#include "vgui/ILocalize.h"
#include "vgui/IInput.h"
#include "vgui/ISystem.h"
#include "KeyValues.h"
#include "vgui/Cursor.h"
#include "tier1/utldict.h"
#include "vgui_controls/KeyBoardEditorDialog.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
using namespace vgui;
// If the user holds the key bound to help down for this long, then the dialog will stay on automatically
#define KB_HELP_CONTINUE_SHOWING_TIME 1.0
static bool BindingLessFunc( KeyValues * const & lhs, KeyValues * const &rhs )
{
KeyValues *p1, *p2;
p1 = const_cast< KeyValues * >( lhs );
p2 = const_cast< KeyValues * >( rhs );
return ( Q_stricmp( p1->GetString( "Action" ), p2->GetString( "Action" ) ) < 0 ) ? true : false;
}
CKeyBindingHelpDialog::CKeyBindingHelpDialog( Panel *parent, Panel *panelToView, KeyBindingContextHandle_t handle, KeyCode code, int modifiers )
: BaseClass( parent, "KeyBindingHelpDialog" ),
m_Handle( handle ),
m_KeyCode( code ),
m_Modifiers( modifiers ),
m_bPermanent( false )
{
Assert( panelToView );
m_hPanel = panelToView;
m_pList = new ListPanel( this, "KeyBindings" );
m_pList->SetIgnoreDoubleClick( true );
m_pList->AddColumnHeader(0, "Action", "#KBEditorBindingName", 175, 0);
m_pList->AddColumnHeader(1, "Binding", "#KBEditorBinding", 175, 0);
m_pList->AddColumnHeader(2, "Description", "#KBEditorDescription", 300, 0);
LoadControlSettings( "resource/KeyBindingHelpDialog.res" );
if ( panelToView && panelToView->GetName() && panelToView->GetName()[0] )
{
SetTitle( panelToView->GetName(), true );
}
else
{
SetTitle( "#KBHelpDialogTitle", true );
}
SetSmallCaption( true );
SetMinimumSize( 400, 400 );
SetMinimizeButtonVisible( false );
SetMaximizeButtonVisible( false );
SetSizeable( true );
SetMoveable( true );
SetMenuButtonVisible( false );
SetVisible( true );
MoveToCenterOfScreen();
PopulateList();
m_flShowTime = system()->GetCurrentTime();
ivgui()->AddTickSignal( GetVPanel(), 0 );
input()->SetAppModalSurface( GetVPanel() );
}
CKeyBindingHelpDialog::~CKeyBindingHelpDialog()
{
if ( input()->GetAppModalSurface() == GetVPanel() )
{
input()->SetAppModalSurface( 0 );
}
}
void CKeyBindingHelpDialog::OnTick()
{
BaseClass::OnTick();
bool keyStillDown = IsHelpKeyStillBeingHeld();
double curtime = system()->GetCurrentTime();
double elapsed = curtime - m_flShowTime;
// After a second of holding the key, releasing the key will close the dialog
if ( elapsed > KB_HELP_CONTINUE_SHOWING_TIME )
{
if ( !keyStillDown )
{
MarkForDeletion();
return;
}
}
// Otherwise, if they tapped the key within a second and now have released...
else if ( !keyStillDown )
{
// Continue showing dialog indefinitely
ivgui()->RemoveTickSignal( GetVPanel() );
m_bPermanent = true;
}
}
// The key originally bound to help was pressed
void CKeyBindingHelpDialog::HelpKeyPressed()
{
// Don't kill while editor is being shown...
if ( m_hKeyBindingsEditor.Get() )
return;
if ( m_bPermanent )
{
MarkForDeletion();
}
}
bool CKeyBindingHelpDialog::IsHelpKeyStillBeingHeld()
{
bool keyDown = input()->IsKeyDown( m_KeyCode );
if ( !keyDown )
return false;
bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT));
bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT));
int modifiers = 0;
if ( shift )
{
modifiers |= MODIFIER_SHIFT;
}
if ( ctrl )
{
modifiers |= MODIFIER_CONTROL;
}
if ( alt )
{
modifiers |= MODIFIER_ALT;
}
if ( modifiers != m_Modifiers )
{
return false;
}
return true;
}
void CKeyBindingHelpDialog::OnCommand( char const *cmd )
{
if ( !Q_stricmp( cmd, "OK" ) ||
!Q_stricmp( cmd, "cancel" ) ||
!Q_stricmp( cmd, "Close" ) )
{
MarkForDeletion();
}
else if ( !Q_stricmp( cmd, "edit" ) )
{
// Show the keybindings edit dialog
if ( m_hKeyBindingsEditor.Get() )
{
delete m_hKeyBindingsEditor.Get();
}
// Don't delete panel if H key is released...
m_hKeyBindingsEditor = new CKeyBoardEditorDialog( this, m_hPanel, m_Handle );
m_hKeyBindingsEditor->DoModal();
ivgui()->RemoveTickSignal( GetVPanel() );
m_bPermanent = true;
}
else
{
BaseClass::OnCommand( cmd );
}
}
void CKeyBindingHelpDialog::OnKeyCodeTyped(vgui::KeyCode code)
{
BaseClass::OnKeyCodeTyped( code );
}
void CKeyBindingHelpDialog::GetMappingList( Panel *panel, CUtlVector< PanelKeyBindingMap * >& maps )
{
PanelKeyBindingMap *map = panel->GetKBMap();
while ( map )
{
maps.AddToTail( map );
map = map->baseMap;
}
}
void CKeyBindingHelpDialog::AnsiText( char const *token, char *out, size_t buflen )
{
out[ 0 ] = 0;
wchar_t *str = g_pVGuiLocalize->Find( token );
if ( !str )
{
Q_strncpy( out, token, buflen );
}
else
{
g_pVGuiLocalize->ConvertUnicodeToANSI( str, out, buflen );
}
}
struct ListInfo_t
{
PanelKeyBindingMap *m_pMap;
Panel *m_pPanel;
};
void CKeyBindingHelpDialog::PopulateList()
{
m_pList->DeleteAllItems();
int i, j;
CUtlVector< ListInfo_t > maps;
vgui::Panel *pPanel = m_hPanel;
while ( pPanel->IsKeyBindingChainToParentAllowed() )
{
PanelKeyBindingMap *map = pPanel->GetKBMap();
while ( map )
{
int k;
int c = maps.Count();
for ( k = 0; k < c; ++k )
{
if ( maps[k].m_pMap == map )
break;
}
if ( k == c )
{
int iMap = maps.AddToTail( );
maps[iMap].m_pMap = map;
maps[iMap].m_pPanel = pPanel;
}
map = map->baseMap;
}
pPanel = pPanel->GetParent();
if ( !pPanel )
break;
}
CUtlRBTree< KeyValues *, int > sorted( 0, 0, BindingLessFunc );
// add header item
int c = maps.Count();
for ( i = 0; i < c; ++i )
{
PanelKeyBindingMap *m = maps[ i ].m_pMap;
pPanel = maps[i].m_pPanel;
Assert( m );
int bindings = m->boundkeys.Count();
for ( j = 0; j < bindings; ++j )
{
BoundKey_t *kbMap = &m->boundkeys[ j ];
Assert( kbMap );
// Create a new: blank item
KeyValues *item = new KeyValues( "Item" );
// Fill in data
char loc[ 128 ];
Q_snprintf( loc, sizeof( loc ), "#%s", kbMap->bindingname );
char ansi[ 256 ];
AnsiText( loc, ansi, sizeof( ansi ) );
item->SetString( "Action", ansi );
item->SetWString( "Binding", Panel::KeyCodeModifiersToDisplayString( (KeyCode)kbMap->keycode, kbMap->modifiers ) );
// Find the binding
KeyBindingMap_t *bindingMap = pPanel->LookupBinding( kbMap->bindingname );
if ( bindingMap &&
bindingMap->helpstring )
{
AnsiText( bindingMap->helpstring, ansi, sizeof( ansi ) );
item->SetString( "Description", ansi );
}
item->SetPtr( "Item", kbMap );
sorted.Insert( item );
}
// Now try and find any "unbound" keys...
int mappings = m->entries.Count();
for ( j = 0; j < mappings; ++j )
{
KeyBindingMap_t *kbMap = &m->entries[ j ];
// See if it's bound
CUtlVector< BoundKey_t * > list;
pPanel->LookupBoundKeys( kbMap->bindingname, list );
if ( list.Count() > 0 )
continue;
// Not bound, add a placeholder entry
// Create a new: blank item
KeyValues *item = new KeyValues( "Item" );
// fill in data
char loc[ 128 ];
Q_snprintf( loc, sizeof( loc ), "#%s", kbMap->bindingname );
char ansi[ 256 ];
AnsiText( loc, ansi, sizeof( ansi ) );
item->SetString( "Action", ansi );
item->SetWString( "Binding", L"" );
if ( kbMap->helpstring )
{
AnsiText( kbMap->helpstring, ansi, sizeof( ansi ) );
item->SetString( "Description", ansi );
}
item->SetPtr( "Unbound", kbMap );
sorted.Insert( item );
}
}
for ( j = sorted.FirstInorder() ; j != sorted.InvalidIndex(); j = sorted.NextInorder( j ) )
{
KeyValues *item = sorted[ j ];
// Add to list
m_pList->AddItem( item, 0, false, false );
item->deleteThis();
}
sorted.RemoveAll();
}

View File

@ -0,0 +1,849 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "vgui_controls/KeyBoardEditorDialog.h"
#include "vgui_controls/ListPanel.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/TextEntry.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"
#include "vgui/IVGui.h"
#include "vgui/ILocalize.h"
#include "KeyValues.h"
#include "vgui/Cursor.h"
#include "tier1/utldict.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
using namespace vgui;
static char *CopyString( const char *in )
{
if ( !in )
return NULL;
int len = strlen( in );
char *n = new char[ len + 1 ];
Q_strncpy( n, in, len + 1 );
return n;
}
CKeyBoardEditorPage::SaveMapping_t::SaveMapping_t() : map( 0 )
{
}
CKeyBoardEditorPage::SaveMapping_t::SaveMapping_t( const SaveMapping_t& src )
{
map = src.map;
current = src.current;
original = src.original;
}
//-----------------------------------------------------------------------------
// Purpose: Special list subclass to handle drawing of trap mode prompt on top of
// lists client area
//-----------------------------------------------------------------------------
class VControlsListPanel : public ListPanel
{
DECLARE_CLASS_SIMPLE( VControlsListPanel, ListPanel );
public:
// Construction
VControlsListPanel( vgui::Panel *parent, const char *listName );
virtual ~VControlsListPanel();
// Start/end capturing
virtual void StartCaptureMode(vgui::HCursor hCursor = NULL);
virtual void EndCaptureMode(vgui::HCursor hCursor = NULL);
virtual bool IsCapturing();
// Set which item should be associated with the prompt
virtual void SetItemOfInterest(int itemID);
virtual int GetItemOfInterest();
virtual void OnMousePressed(vgui::MouseCode code);
virtual void OnMouseDoublePressed(vgui::MouseCode code);
KEYBINDING_FUNC( clearbinding, KEY_DELETE, 0, OnClearBinding, 0, 0 );
private:
void ApplySchemeSettings(vgui::IScheme *pScheme );
// Are we showing the prompt?
bool m_bCaptureMode;
// If so, where?
int m_nClickRow;
// Font to use for showing the prompt
vgui::HFont m_hFont;
// panel used to edit
class CInlineEditPanel *m_pInlineEditPanel;
int m_iMouseX, m_iMouseY;
};
//-----------------------------------------------------------------------------
// Purpose: panel used for inline editing of key bindings
//-----------------------------------------------------------------------------
class CInlineEditPanel : public vgui::Panel
{
DECLARE_CLASS_SIMPLE( CInlineEditPanel, vgui::Panel );
public:
CInlineEditPanel() : vgui::Panel(NULL, "InlineEditPanel")
{
}
virtual void Paint()
{
int wide, tall;
GetSize(wide, tall);
// Draw a white rectangle around that cell
vgui::surface()->DrawSetColor( 63, 63, 63, 255 );
vgui::surface()->DrawFilledRect( 0, 0, wide, tall );
vgui::surface()->DrawSetColor( 0, 255, 0, 255 );
vgui::surface()->DrawOutlinedRect( 0, 0, wide, tall );
}
virtual void OnKeyCodeTyped(KeyCode code)
{
// forward up
if (GetParent())
{
GetParent()->OnKeyCodeTyped(code);
}
}
virtual void ApplySchemeSettings(IScheme *pScheme)
{
Panel::ApplySchemeSettings(pScheme);
SetBorder(pScheme->GetBorder("DepressedButtonBorder"));
}
void OnMousePressed(vgui::MouseCode code)
{
// forward up mouse pressed messages to be handled by the key options
if (GetParent())
{
GetParent()->OnMousePressed(code);
}
}
};
//-----------------------------------------------------------------------------
// Purpose: Construction
//-----------------------------------------------------------------------------
VControlsListPanel::VControlsListPanel( vgui::Panel *parent, const char *listName ) : BaseClass( parent, listName )
{
m_bCaptureMode = false;
m_nClickRow = 0;
m_pInlineEditPanel = new CInlineEditPanel();
m_hFont = INVALID_FONT;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
VControlsListPanel::~VControlsListPanel()
{
m_pInlineEditPanel->MarkForDeletion();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void VControlsListPanel::ApplySchemeSettings(IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
m_hFont = pScheme->GetFont("DefaultVerySmall", IsProportional() );
}
//-----------------------------------------------------------------------------
// Purpose: Start capture prompt display
//-----------------------------------------------------------------------------
void VControlsListPanel::StartCaptureMode( HCursor hCursor )
{
m_bCaptureMode = true;
EnterEditMode(m_nClickRow, 1, m_pInlineEditPanel);
input()->SetMouseFocus(m_pInlineEditPanel->GetVPanel());
input()->SetMouseCapture(m_pInlineEditPanel->GetVPanel());
if (hCursor)
{
m_pInlineEditPanel->SetCursor(hCursor);
// save off the cursor position so we can restore it
vgui::input()->GetCursorPos( m_iMouseX, m_iMouseY );
}
}
void VControlsListPanel::OnClearBinding()
{
if ( m_bCaptureMode )
return;
if ( GetItemOfInterest() < 0 )
return;
PostMessage( GetParent()->GetVPanel(), new KeyValues( "ClearBinding", "item", GetItemOfInterest() ) );
}
//-----------------------------------------------------------------------------
// Purpose: Finish capture prompt display
//-----------------------------------------------------------------------------
void VControlsListPanel::EndCaptureMode( HCursor hCursor )
{
m_bCaptureMode = false;
input()->SetMouseCapture(NULL);
LeaveEditMode();
RequestFocus();
input()->SetMouseFocus(GetVPanel());
if (hCursor)
{
m_pInlineEditPanel->SetCursor(hCursor);
surface()->SetCursor(hCursor);
if ( hCursor != dc_none )
{
vgui::input()->SetCursorPos ( m_iMouseX, m_iMouseY );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Set active row column
//-----------------------------------------------------------------------------
void VControlsListPanel::SetItemOfInterest(int itemID)
{
m_nClickRow = itemID;
}
//-----------------------------------------------------------------------------
// Purpose: Retrieve row, column of interest
//-----------------------------------------------------------------------------
int VControlsListPanel::GetItemOfInterest()
{
return m_nClickRow;
}
//-----------------------------------------------------------------------------
// Purpose: returns true if we're currently waiting to capture a key
//-----------------------------------------------------------------------------
bool VControlsListPanel::IsCapturing( void )
{
return m_bCaptureMode;
}
//-----------------------------------------------------------------------------
// Purpose: Forwards mouse pressed message up to keyboard page when in capture
//-----------------------------------------------------------------------------
void VControlsListPanel::OnMousePressed(vgui::MouseCode code)
{
if (IsCapturing())
{
// forward up mouse pressed messages to be handled by the key options
if (GetParent())
{
GetParent()->OnMousePressed(code);
}
}
else
{
BaseClass::OnMousePressed(code);
}
}
//-----------------------------------------------------------------------------
// Purpose: input handler
//-----------------------------------------------------------------------------
void VControlsListPanel::OnMouseDoublePressed( vgui::MouseCode code )
{
int c = GetSelectedItemsCount();
if ( c > 0 )
{
// enter capture mode
OnKeyCodeTyped(KEY_ENTER);
}
else
{
BaseClass::OnMouseDoublePressed(code);
}
}
CKeyBoardEditorPage::CKeyBoardEditorPage( Panel *parent, Panel *panelToEdit, KeyBindingContextHandle_t handle )
: BaseClass( parent, "KeyBoardEditorPage" ),
m_pPanel( panelToEdit ),
m_Handle( handle )
{
Assert( m_pPanel );
m_pList = new VControlsListPanel( this, "KeyBindings" );
m_pList->SetIgnoreDoubleClick( true );
m_pList->AddColumnHeader(0, "Action", "#KBEditorBindingName", 175, 0);
m_pList->AddColumnHeader(1, "Binding", "#KBEditorBinding", 175, 0);
m_pList->AddColumnHeader(2, "Description", "#KBEditorDescription", 300, 0);
LoadControlSettings( "resource/KeyBoardEditorPage.res" );
SaveMappings();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : -
//-----------------------------------------------------------------------------
CKeyBoardEditorPage::~CKeyBoardEditorPage()
{
int c = m_Save.Count();
for ( int i = 0 ; i < c; ++i )
{
delete m_Save[ i ];
}
m_Save.RemoveAll();
}
void CKeyBoardEditorPage::ApplySchemeSettings( IScheme *scheme )
{
BaseClass::ApplySchemeSettings( scheme );
PopulateList();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : -
//-----------------------------------------------------------------------------
void CKeyBoardEditorPage::SaveMappings()
{
Assert( m_Save.Count() == 0 );
CUtlVector< PanelKeyBindingMap * > maps;
GetMappingList( m_pPanel, maps );
// add header item
int c = maps.Count();
for ( int i = 0; i < c; ++i )
{
PanelKeyBindingMap *m = maps[ i ];
SaveMapping_t *sm = new SaveMapping_t;
sm->map = m;
sm->current = m->boundkeys;
sm->original = m->boundkeys;
m_Save.AddToTail( sm );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : -
//-----------------------------------------------------------------------------
void CKeyBoardEditorPage::UpdateCurrentMappings()
{
int c = m_Save.Count();
for ( int i = 0 ; i < c; ++i )
{
PanelKeyBindingMap *m = m_Save[ i ]->map;
Assert( m );
m_Save[ i ]->current = m->boundkeys;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : -
//-----------------------------------------------------------------------------
void CKeyBoardEditorPage::RestoreMappings()
{
int c = m_Save.Count();
for ( int i = 0; i < c; ++i )
{
SaveMapping_t *sm = m_Save[ i ];
sm->current = sm->original;
}
}
void CKeyBoardEditorPage::ApplyMappings()
{
int c = m_Save.Count();
for ( int i = 0; i < c; ++i )
{
SaveMapping_t *sm = m_Save[ i ];
sm->map->boundkeys = sm->current;
}
}
//-----------------------------------------------------------------------------
// Purpose: User clicked on item: remember where last active row/column was
//-----------------------------------------------------------------------------
void CKeyBoardEditorPage::ItemSelected()
{
int c = m_pList->GetSelectedItemsCount();
if ( c > 0 )
{
m_pList->SetItemOfInterest( m_pList->GetSelectedItem( 0 ) );
}
}
void CKeyBoardEditorPage::BindKey( KeyCode code )
{
bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT));
bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT));
int modifiers = 0;
if ( shift )
{
modifiers |= MODIFIER_SHIFT;
}
if ( ctrl )
{
modifiers |= MODIFIER_CONTROL;
}
if ( alt )
{
modifiers |= MODIFIER_ALT;
}
int r = m_pList->GetItemOfInterest();
// Retrieve clicked row and column
m_pList->EndCaptureMode(dc_arrow);
// Find item for this row
KeyValues *item = m_pList->GetItem(r);
if ( item )
{
BoundKey_t *kbMap = reinterpret_cast< BoundKey_t * >( item->GetPtr( "Item", 0 ) );
if ( kbMap )
{
KeyBindingMap_t *binding = m_pPanel->LookupBindingByKeyCode( code, modifiers );
if ( binding && Q_stricmp( kbMap->bindingname, binding->bindingname ) )
{
// Key is already rebound!!!
Warning( "Can't bind to '%S', key is already bound to '%s'\n",
Panel::KeyCodeToDisplayString( code ), binding->bindingname );
return;
}
kbMap->keycode = code;
kbMap->modifiers = modifiers;
PopulateList();
}
KeyBindingMap_t *bindingMap = reinterpret_cast< KeyBindingMap_t * >( item->GetPtr( "Unbound", 0 ) );
if ( bindingMap )
{
KeyBindingMap_t *binding = m_pPanel->LookupBindingByKeyCode( code, modifiers );
if ( binding && Q_stricmp( bindingMap->bindingname, binding->bindingname ) )
{
// Key is already rebound!!!
Warning( "Can't bind to '%S', key is already bound to '%s'\n",
Panel::KeyCodeToDisplayString( code ), binding->bindingname );
return;
}
// Need to add to current entries
m_pPanel->AddKeyBinding( bindingMap->bindingname, code, modifiers );
UpdateCurrentMappings();
PopulateList();
}
}
}
void CKeyBoardEditorPage::OnPageHide()
{
if ( m_pList->IsCapturing() )
{
// Cancel capturing
m_pList->EndCaptureMode(dc_arrow);
}
}
//-----------------------------------------------------------------------------
// Purpose: binds double-clicking or hitting enter in the keybind list to changing the key
//-----------------------------------------------------------------------------
void CKeyBoardEditorPage::OnKeyCodeTyped(vgui::KeyCode code)
{
switch ( code )
{
case KEY_ENTER:
{
if ( !m_pList->IsCapturing() )
{
OnCommand( "ChangeKey" );
}
else
{
BindKey( code );
}
}
break;
case KEY_LSHIFT:
case KEY_RSHIFT:
case KEY_LALT:
case KEY_RALT:
case KEY_LCONTROL:
case KEY_RCONTROL:
{
// Swallow these
break;
}
break;
default:
{
if ( m_pList->IsCapturing() )
{
BindKey( code );
}
else
{
BaseClass::OnKeyCodeTyped(code);
}
}
}
}
void CKeyBoardEditorPage::OnCommand( char const *cmd )
{
if ( !m_pList->IsCapturing() && !Q_stricmp( cmd, "ChangeKey" ) )
{
m_pList->StartCaptureMode(dc_blank);
}
else
{
BaseClass::OnCommand( cmd );
}
}
void CKeyBoardEditorPage::OnSaveChanges()
{
ApplyMappings();
}
void CKeyBoardEditorPage::OnRevert()
{
RestoreMappings();
PopulateList();
}
void CKeyBoardEditorPage::OnUseDefaults()
{
m_pPanel->RevertKeyBindingsToDefault();
UpdateCurrentMappings();
PopulateList();
}
void CKeyBoardEditorPage::GetMappingList( Panel *panel, CUtlVector< PanelKeyBindingMap * >& maps )
{
PanelKeyBindingMap *map = panel->GetKBMap();
while ( map )
{
maps.AddToTail( map );
map = map->baseMap;
}
}
static bool BindingLessFunc( KeyValues * const & lhs, KeyValues * const &rhs )
{
KeyValues *p1, *p2;
p1 = const_cast< KeyValues * >( lhs );
p2 = const_cast< KeyValues * >( rhs );
return ( Q_stricmp( p1->GetString( "Action" ), p2->GetString( "Action" ) ) < 0 ) ? true : false;
}
void CKeyBoardEditorPage::AnsiText( char const *token, char *out, size_t buflen )
{
out[ 0 ] = 0;
wchar_t *str = g_pVGuiLocalize->Find( token );
if ( !str )
{
Q_strncpy( out, token, buflen );
}
else
{
g_pVGuiLocalize->ConvertUnicodeToANSI( str, out, buflen );
}
}
void CKeyBoardEditorPage::PopulateList()
{
m_pList->DeleteAllItems();
int i, j;
CUtlRBTree< KeyValues *, int > sorted( 0, 0, BindingLessFunc );
// add header item
int c = m_Save.Count();
for ( i = 0; i < c; ++i )
{
SaveMapping_t* sm = m_Save[ i ];
PanelKeyBindingMap *m = sm->map;
Assert( m );
int bindings = sm->current.Count();
for ( j = 0; j < bindings; ++j )
{
BoundKey_t *kbMap = &sm->current[ j ];
Assert( kbMap );
// Create a new: blank item
KeyValues *item = new KeyValues( "Item" );
// Fill in data
char loc[ 128 ];
Q_snprintf( loc, sizeof( loc ), "#%s", kbMap->bindingname );
char ansi[ 256 ];
AnsiText( loc, ansi, sizeof( ansi ) );
item->SetString( "Action", ansi );
item->SetWString( "Binding", Panel::KeyCodeModifiersToDisplayString( (KeyCode)kbMap->keycode, kbMap->modifiers ) );
// Find the binding
KeyBindingMap_t *bindingMap = m_pPanel->LookupBinding( kbMap->bindingname );
if ( bindingMap &&
bindingMap->helpstring )
{
AnsiText( bindingMap->helpstring, ansi, sizeof( ansi ) );
item->SetString( "Description", ansi);
}
item->SetPtr( "Item", kbMap );
sorted.Insert( item );
}
// Now try and find any "unbound" keys...
int mappings = m->entries.Count();
for ( j = 0; j < mappings; ++j )
{
KeyBindingMap_t *kbMap = &m->entries[ j ];
// See if it's bound
CUtlVector< BoundKey_t * > list;
m_pPanel->LookupBoundKeys( kbMap->bindingname, list );
if ( list.Count() > 0 )
continue;
// Not bound, add a placeholder entry
// Create a new: blank item
KeyValues *item = new KeyValues( "Item" );
// fill in data
char loc[ 128 ];
Q_snprintf( loc, sizeof( loc ), "#%s", kbMap->bindingname );
char ansi[ 256 ];
AnsiText( loc, ansi, sizeof( ansi ) );
item->SetString( "Action", ansi );
item->SetWString( "Binding", L"" );
if ( kbMap->helpstring )
{
AnsiText( kbMap->helpstring, ansi, sizeof( ansi ) );
item->SetString( "Description", ansi );
}
item->SetPtr( "Unbound", kbMap );
sorted.Insert( item );
}
}
for ( j = sorted.FirstInorder() ; j != sorted.InvalidIndex(); j = sorted.NextInorder( j ) )
{
KeyValues *item = sorted[ j ];
// Add to list
m_pList->AddItem( item, 0, false, false );
item->deleteThis();
}
sorted.RemoveAll();
}
void CKeyBoardEditorPage::OnClearBinding( int item )
{
// Find item for this row
KeyValues *kv = m_pList->GetItem(item );
if ( !kv )
{
return;
}
BoundKey_t *kbMap = reinterpret_cast< BoundKey_t * >( kv->GetPtr( "Item", 0 ) );
if ( !kbMap )
{
return;
}
kbMap->keycode = KEY_NONE;
kbMap->modifiers = 0;
PopulateList();
}
CKeyBoardEditorSheet::CKeyBoardEditorSheet( Panel *parent, Panel *panelToEdit, KeyBindingContextHandle_t handle )
: BaseClass( parent, "KeyBoardEditorSheet" ),
m_bSaveToExternalFile( false ),
m_Handle( handle ),
m_SaveFileName( UTL_INVAL_SYMBOL ),
m_SaveFilePathID( UTL_INVAL_SYMBOL )
{
m_hPanel = panelToEdit;
SetSmallTabs( true );
// Create this sheet and add the subcontrols
CKeyBoardEditorPage *active = NULL;
int subCount = Panel::GetPanelsWithKeyBindingsCount( handle );
for ( int i = 0; i < subCount; ++i )
{
Panel *p = Panel::GetPanelWithKeyBindings( handle, i );
if ( !p )
continue;
// Don't display panels with no keymappings
if ( p->GetKeyMappingCount() == 0 )
continue;
CKeyBoardEditorPage *newPage = new CKeyBoardEditorPage( this, p, handle );
AddPage( newPage, p->GetName() );
if ( p == panelToEdit )
{
active = newPage;
}
}
if ( active )
{
SetActivePage( active );
}
LoadControlSettings( "resource/KeyBoardEditorSheet.res" );
}
void CKeyBoardEditorSheet::SetKeybindingsSaveFile( char const *filename, char const *pathID /*= 0*/ )
{
Assert( filename );
m_bSaveToExternalFile = true;
m_SaveFileName = filename;
if ( pathID != NULL )
{
m_SaveFilePathID = pathID;
}
else
{
m_SaveFilePathID = UTL_INVAL_SYMBOL;
}
}
void CKeyBoardEditorSheet::OnSaveChanges()
{
int c = GetNumPages();
for ( int i = 0 ; i < c; ++i )
{
CKeyBoardEditorPage *page = static_cast< CKeyBoardEditorPage * >( GetPage( i ) );
page->OnSaveChanges();
}
if ( m_bSaveToExternalFile )
{
m_hPanel->SaveKeyBindingsToFile( m_Handle, m_SaveFileName.String(), m_SaveFilePathID.IsValid() ? m_SaveFilePathID.String() : NULL );
}
else
{
m_hPanel->SaveKeyBindings( m_Handle );
}
}
void CKeyBoardEditorSheet::OnRevert()
{
int c = GetNumPages();
for ( int i = 0 ; i < c; ++i )
{
CKeyBoardEditorPage *page = static_cast< CKeyBoardEditorPage * >( GetPage( i ) );
page->OnRevert();
}
}
void CKeyBoardEditorSheet::OnUseDefaults()
{
int c = GetNumPages();
for ( int i = 0 ; i < c; ++i )
{
CKeyBoardEditorPage *page = static_cast< CKeyBoardEditorPage * >( GetPage( i ) );
page->OnUseDefaults();
}
}
CKeyBoardEditorDialog::CKeyBoardEditorDialog( Panel *parent, Panel *panelToEdit, KeyBindingContextHandle_t handle )
: BaseClass( parent, "KeyBoardEditorDialog" )
{
m_pSave = new Button( this, "Save", "#KBEditorSave", this, "save" );
m_pCancel = new Button( this, "Cancel", "#KBEditorCancel", this, "cancel" );
m_pRevert = new Button( this, "Revert", "#KBEditorRevert", this, "revert" );
m_pUseDefaults = new Button( this, "Defaults", "#KBEditorUseDefaults", this, "defaults" );
m_pKBEditor = new CKeyBoardEditorSheet( this, panelToEdit, handle );
LoadControlSettings( "resource/KeyBoardEditorDialog.res" );
SetTitle( "#KBEditorTitle", true );
SetSmallCaption( true );
SetMinimumSize( 640, 200 );
SetMinimizeButtonVisible( false );
SetMaximizeButtonVisible( false );
SetSizeable( true );
SetMoveable( true );
SetMenuButtonVisible( false );
SetVisible( true );
MoveToCenterOfScreen();
}
void CKeyBoardEditorDialog::OnCommand( char const *cmd )
{
if ( !Q_stricmp( cmd, "save" ) )
{
m_pKBEditor->OnSaveChanges();
MarkForDeletion();
}
else if ( !Q_stricmp( cmd, "cancel" ) ||
!Q_stricmp( cmd, "Close" ) )
{
m_pKBEditor->OnRevert();
MarkForDeletion();
}
else if ( !Q_stricmp( cmd, "revert" ) )
{
m_pKBEditor->OnRevert();
}
else if ( !Q_stricmp( cmd, "defaults" ) )
{
m_pKBEditor->OnUseDefaults();
}
else
{
BaseClass::OnCommand( cmd );
}
}
void CKeyBoardEditorDialog::SetKeybindingsSaveFile( char const *filename, char const *pathID /*= 0*/ )
{
m_pKBEditor->SetKeybindingsSaveFile( filename, pathID );
}

View File

@ -0,0 +1,98 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "vgui_controls/pch_vgui_controls.h"
#include <vgui_controls/KeyRepeat.h>
// memdbgon must be the last include file in a .cpp file
#include "tier0/memdbgon.h"
using namespace vgui;
vgui::KeyCode g_iCodesForAliases[FM_NUM_KEYREPEAT_ALIASES] =
{
KEY_XBUTTON_UP,
KEY_XBUTTON_DOWN,
KEY_XBUTTON_LEFT,
KEY_XBUTTON_RIGHT,
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CKeyRepeatHandler::KeyDown( vgui::KeyCode code )
{
int iIndex = GetIndexForCode(code);
if ( iIndex == -1 )
return;
if ( m_bAliasDown[ iIndex ] )
return;
Reset();
m_bAliasDown[ iIndex ] = true;
m_flNextKeyRepeat = system()->GetCurrentTime() + 0.4;
m_bHaveKeyDown = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CKeyRepeatHandler::KeyUp( vgui::KeyCode code )
{
int iIndex = GetIndexForCode(code);
if ( iIndex == -1 )
return;
m_bAliasDown[ GetIndexForCode(code) ] = false;
m_bHaveKeyDown = false;
for ( int i = 0; i < FM_NUM_KEYREPEAT_ALIASES; i++ )
{
if ( m_bAliasDown[i] )
{
m_bHaveKeyDown = true;
break;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
vgui::KeyCode CKeyRepeatHandler::KeyRepeated( void )
{
if ( IsPC() )
return BUTTON_CODE_NONE;
if ( !m_bHaveKeyDown )
return BUTTON_CODE_NONE;
if ( m_flNextKeyRepeat < system()->GetCurrentTime() )
{
for ( int i = 0; i < FM_NUM_KEYREPEAT_ALIASES; i++ )
{
if ( m_bAliasDown[i] )
{
m_flNextKeyRepeat = system()->GetCurrentTime() + m_flRepeatTimes[i];
return g_iCodesForAliases[i];
}
}
}
return BUTTON_CODE_NONE;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CKeyRepeatHandler::SetKeyRepeatTime( vgui::KeyCode code, float flRepeat )
{
int iIndex = GetIndexForCode(code);
Assert( iIndex != -1 );
m_flRepeatTimes[ iIndex ] = flRepeat;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2751
vgui2/vgui_controls/Menu.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,252 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/IInput.h>
#include <vgui/IPanel.h>
#include <vgui/IScheme.h>
#include <vgui/IBorder.h>
#include <vgui/ISurface.h>
#include <vgui/KeyCode.h>
#include <KeyValues.h>
#include <vgui_controls/MenuBar.h>
#include <vgui_controls/MenuButton.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/Controls.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
enum
{
MENUBARINDENT = 4, // indent from top and bottom of panel.
};
DECLARE_BUILD_FACTORY( MenuBar );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
MenuBar::MenuBar(Panel *parent, const char *panelName) :
Panel(parent, panelName),
m_nRightEdge( 0 )
{
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
MenuBar::~MenuBar()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void MenuBar::AddButton(MenuButton *button)
{
button->SetParent(this);
button->AddActionSignalTarget(this);
m_pMenuButtons.AddToTail(button);
}
//-----------------------------------------------------------------------------
// This will add the menu to the menu bar
//-----------------------------------------------------------------------------
void MenuBar::AddMenu( const char *pButtonName, Menu *pMenu )
{
MenuButton *pMenuButton = new MenuButton(this, pButtonName, pButtonName);
pMenuButton->SetMenu(pMenu);
AddButton(pMenuButton);
}
//-----------------------------------------------------------------------------
// Purpose: Handle key presses, Activate shortcuts
//-----------------------------------------------------------------------------
void MenuBar::OnKeyCodeTyped(KeyCode code)
{
switch(code)
{
case KEY_RIGHT:
{
// iterate the menu items looking for one that is open
// if we find one open, open the one to the right
for (int i = 0; i < m_pMenuButtons.Count() - 1; i++)
{
MenuButton *panel = m_pMenuButtons[i];
if (panel->IsDepressed())
{
m_pMenuButtons[i]->DoClick();
m_pMenuButtons[i+1]->DoClick();
break;
}
}
break;
}
case KEY_LEFT:
{
// iterate the menu items looking for one that is open
// if we find one open, open the one to the left
for (int i = 1; i < m_pMenuButtons.Count(); i++)
{
MenuButton *panel = m_pMenuButtons[i];
if (panel->IsDepressed())
{
m_pMenuButtons[i]->DoClick();
m_pMenuButtons[i-1]->DoClick();
break;
}
}
break;
}
default:
{
break;
}
}
// don't chain back
}
//-----------------------------------------------------------------------------
// Purpose: Handle key presses, Activate shortcuts
// Input : code -
//-----------------------------------------------------------------------------
void MenuBar::OnKeyTyped(wchar_t unichar)
{
if (unichar)
{
// iterate the menu items looking for one with the matching hotkey
for (int i = 0; i < m_pMenuButtons.Count(); i++)
{
MenuButton *panel = m_pMenuButtons[i];
if (panel->IsVisible())
{
Panel *hot = panel->HasHotkey(unichar);
if (hot)
{
// post a message to the menuitem telling it it's hotkey was pressed
PostMessage(hot, new KeyValues("Hotkey"));
return;
}
}
}
}
// don't chain back
}
void MenuBar::Paint()
{
IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
for ( int i = 0; i < m_pMenuButtons.Count(); i++)
{
if (!m_pMenuButtons[i]->IsArmed())
m_pMenuButtons[i]->SetDefaultBorder(NULL);
else
{
m_pMenuButtons[i]->SetDefaultBorder(pScheme->GetBorder( "ButtonBorder"));
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Message map
//-----------------------------------------------------------------------------
void MenuBar::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
// get the borders we need
SetBorder(pScheme->GetBorder("ButtonBorder"));
// get the background color
SetBgColor(pScheme->GetColor( "MenuBar.BgColor", GetBgColor() ));
}
//-----------------------------------------------------------------------------
// Purpose: Reformat according to the new layout
//-----------------------------------------------------------------------------
void MenuBar::PerformLayout()
{
int nBarWidth, nBarHeight;
GetSize( nBarWidth, nBarHeight );
// Now position + resize all buttons
int x = MENUBARINDENT;
for ( int i = 0; i < m_pMenuButtons.Count(); ++i )
{
int nWide, nTall;
m_pMenuButtons[i]->GetContentSize(nWide, nTall);
m_pMenuButtons[i]->SetPos( x, MENUBARINDENT );
m_pMenuButtons[i]->SetSize( nWide + Label::Content, nBarHeight - 2 * MENUBARINDENT );
x += nWide + MENUBARINDENT;
}
m_nRightEdge = x;
}
//-----------------------------------------------------------------------------
// Purpose: Get the size of the menus in the bar (so other children can be added to menu bar)
// Input : w -
// int&h -
//-----------------------------------------------------------------------------
void MenuBar::GetContentSize( int& w, int&h )
{
w = m_nRightEdge + 2;
h = GetTall();
}
//-----------------------------------------------------------------------------
// Purpose: Message map
//-----------------------------------------------------------------------------
void MenuBar::OnMenuClose()
{
RequestFocus();
}
//-----------------------------------------------------------------------------
// Purpose: Message map
//-----------------------------------------------------------------------------
void MenuBar::OnCursorEnteredMenuButton(int VPanel)
{
VPANEL menuButton = (VPANEL)VPanel;
// see if we had a menu open
for ( int i = 0; i < m_pMenuButtons.Count(); i++)
{
// one of our buttons was pressed.
if (m_pMenuButtons[i]->IsDepressed())
{
int oldbutton = i;
// now see if menuButton is one of ours.
for ( int j = 0; j < m_pMenuButtons.Count(); j++)
{
MenuButton *button = static_cast<MenuButton *>(ipanel()->GetPanel(menuButton, GetModuleName()));
// it is one of ours.
if ( button == m_pMenuButtons[j])
{
// if its a different button than the one we already had open,
if (j != oldbutton)
{
// close this menu and open the one we just entered
m_pMenuButtons[oldbutton]->DoClick();
button->DoClick();
}
}
}
}
}
}

View File

@ -0,0 +1,351 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#define PROTECTED_THINGS_DISABLE
#include <vgui/IPanel.h>
#include <vgui/IInput.h>
#include <vgui/ISurface.h>
#include <KeyValues.h>
#include <vgui/IVGui.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/MenuButton.h>
#include <vgui_controls/Menu.h>
#include <vgui_controls/TextImage.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY_DEFAULT_TEXT( MenuButton, MenuButton );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
MenuButton::MenuButton(Panel *parent, const char *panelName, const char *text) : Button(parent, panelName, text)
{
m_pMenu = NULL;
m_iDirection = Menu::DOWN;
m_pDropMenuImage = NULL;
m_nImageIndex = -1;
_openOffsetY = 0;
m_bDropMenuButtonStyle = true; // set to true so SetDropMenuButtonStyle() forces real init.
SetDropMenuButtonStyle( false );
SetUseCaptureMouse( false );
SetButtonActivationType( ACTIVATE_ONPRESSED );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
MenuButton::~MenuButton()
{
delete m_pDropMenuImage;
}
//-----------------------------------------------------------------------------
// Purpose: attaches a menu to the menu button
//-----------------------------------------------------------------------------
void MenuButton::SetMenu(Menu *menu)
{
m_pMenu = menu;
if (menu)
{
m_pMenu->SetVisible(false);
m_pMenu->AddActionSignalTarget(this);
m_pMenu->SetParent(this);
}
}
//-----------------------------------------------------------------------------
// Purpose: Never draw a focus border
//-----------------------------------------------------------------------------
void MenuButton::DrawFocusBorder(int tx0, int ty0, int tx1, int ty1)
{
}
//-----------------------------------------------------------------------------
// Purpose: Sets the direction from the menu button the menu should open
//-----------------------------------------------------------------------------
void MenuButton::SetOpenDirection(Menu::MenuDirection_e direction)
{
m_iDirection = direction;
}
//-----------------------------------------------------------------------------
// Purpose: hides the menu
//-----------------------------------------------------------------------------
void MenuButton::HideMenu(void)
{
if (!m_pMenu)
return;
// hide the menu
m_pMenu->SetVisible(false);
// unstick the button
BaseClass::ForceDepressed(false);
Repaint();
OnHideMenu(m_pMenu);
}
//-----------------------------------------------------------------------------
// Purpose: Called when the menu button loses focus; hides the menu
//-----------------------------------------------------------------------------
void MenuButton::OnKillFocus( KeyValues *pParams )
{
VPANEL hPanel = (VPANEL)pParams->GetPtr( "newPanel" );
if ( m_pMenu && !m_pMenu->HasFocus() && hPanel != m_pMenu->GetVPanel() )
{
HideMenu();
}
BaseClass::OnKillFocus();
}
//-----------------------------------------------------------------------------
// Purpose: Called when the menu is closed
//-----------------------------------------------------------------------------
void MenuButton::OnMenuClose()
{
HideMenu();
PostActionSignal(new KeyValues("MenuClose"));
}
//-----------------------------------------------------------------------------
// Purpose: Sets the offset from where menu would normally be placed
// Only is used if menu is ALIGN_WITH_PARENT
//-----------------------------------------------------------------------------
void MenuButton::SetOpenOffsetY(int yOffset)
{
_openOffsetY = yOffset;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool MenuButton::CanBeDefaultButton(void)
{
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Handles hotkey accesses
//-----------------------------------------------------------------------------
void MenuButton::DoClick()
{
if ( IsDropMenuButtonStyle() &&
m_pDropMenuImage )
{
int mx, my;
// force the menu to appear where the mouse button was pressed
input()->GetCursorPos( mx, my );
ScreenToLocal( mx, my );
int contentW, contentH;
m_pDropMenuImage->GetContentSize( contentW, contentH );
int drawX = GetWide() - contentW - 2;
if ( mx <= drawX || !OnCheckMenuItemCount() )
{
// Treat it like a "regular" button click
BaseClass::DoClick();
return;
}
}
if ( !m_pMenu )
{
return;
}
// menu is already visible, hide the menu
if (m_pMenu->IsVisible())
{
HideMenu();
return;
}
// do nothing if menu is not enabled
if (!m_pMenu->IsEnabled())
{
return;
}
// force the menu to compute required width/height
m_pMenu->PerformLayout();
// Now position it so it can fit in the workspace
m_pMenu->PositionRelativeToPanel(this, m_iDirection, _openOffsetY );
// make sure we're at the top of the draw order (and therefore our children as well)
MoveToFront();
// notify
OnShowMenu(m_pMenu);
// keep the button depressed
BaseClass::ForceDepressed(true);
// show the menu
m_pMenu->SetVisible(true);
// bring to focus
m_pMenu->RequestFocus();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void MenuButton::OnKeyCodeTyped(KeyCode code)
{
bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT));
bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT));
if (!shift && !ctrl && !alt)
{
switch (code)
{
case KEY_ENTER:
{
if ( !IsDropMenuButtonStyle() )
{
DoClick();
}
break;
}
}
}
BaseClass::OnKeyCodeTyped(code);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void MenuButton::OnCursorEntered()
{
Button::OnCursorEntered();
// post a message to the parent menu.
// forward the message on to the parent of this menu.
KeyValues *msg = new KeyValues ("CursorEnteredMenuButton");
// tell the parent this menuitem is the one that was entered so it can open the menu if it wants
msg->SetInt("VPanel", GetVPanel());
ivgui()->PostMessage(GetVParent(), msg, NULL);
}
// This style is like the IE "back" button where the left side acts like a regular button, the the right side has a little
// combo box dropdown indicator and presents and submenu
void MenuButton::SetDropMenuButtonStyle( bool state )
{
bool changed = m_bDropMenuButtonStyle != state;
m_bDropMenuButtonStyle = state;
if ( !changed )
return;
if ( state )
{
m_pDropMenuImage = new TextImage( "u" );
IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
m_pDropMenuImage->SetFont(pScheme->GetFont("Marlett", IsProportional()));
// m_pDropMenuImage->SetContentAlignment(Label::a_west);
// m_pDropMenuImage->SetTextInset(3, 0);
m_nImageIndex = AddImage( m_pDropMenuImage, 0 );
}
else
{
ResetToSimpleTextImage();
delete m_pDropMenuImage;
m_pDropMenuImage = NULL;
m_nImageIndex = -1;
}
}
void MenuButton::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
if ( m_pDropMenuImage )
{
SetImageAtIndex( 1, m_pDropMenuImage, 0 );
}
}
void MenuButton::PerformLayout()
{
BaseClass::PerformLayout();
if ( !IsDropMenuButtonStyle() )
return;
Assert( m_nImageIndex >= 0 );
if ( m_nImageIndex < 0 || !m_pDropMenuImage )
return;
int w, h;
GetSize( w, h );
int contentW, contentH;
m_pDropMenuImage->ResizeImageToContent();
m_pDropMenuImage->GetContentSize( contentW, contentH );
SetImageBounds( m_nImageIndex, w - contentW - 2, contentW );
}
bool MenuButton::IsDropMenuButtonStyle() const
{
return m_bDropMenuButtonStyle;
}
void MenuButton::Paint(void)
{
BaseClass::Paint();
if ( !IsDropMenuButtonStyle() )
return;
int contentW, contentH;
m_pDropMenuImage->GetContentSize( contentW, contentH );
m_pDropMenuImage->SetColor( IsEnabled() ? GetButtonFgColor() : GetDisabledFgColor1() );
int drawX = GetWide() - contentW - 2;
surface()->DrawSetColor( IsEnabled() ? GetButtonFgColor() : GetDisabledFgColor1() );
surface()->DrawFilledRect( drawX, 3, drawX + 1, GetTall() - 3 );
}
void MenuButton::OnCursorMoved( int x, int y )
{
BaseClass::OnCursorMoved( x, y );
if ( !IsDropMenuButtonStyle() )
return;
int contentW, contentH;
m_pDropMenuImage->GetContentSize( contentW, contentH );
int drawX = GetWide() - contentW - 2;
if ( x <= drawX || !OnCheckMenuItemCount() )
{
SetButtonActivationType(ACTIVATE_ONPRESSEDANDRELEASED);
SetUseCaptureMouse(true);
}
else
{
SetButtonActivationType(ACTIVATE_ONPRESSED);
SetUseCaptureMouse(false);
}
}
Menu *MenuButton::GetMenu()
{
Assert( m_pMenu );
return m_pMenu;
}

View File

@ -0,0 +1,647 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/IScheme.h>
#include <vgui/IVGui.h>
#include "vgui/ISurface.h"
#include <KeyValues.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/Menu.h>
#include <vgui_controls/MenuItem.h>
#include <vgui_controls/TextImage.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Check box image
//-----------------------------------------------------------------------------
class MenuItemCheckImage : public TextImage
{
public:
MenuItemCheckImage(MenuItem *item) : TextImage( "g" )
{
_menuItem = item;
SetSize(20, 13);
}
virtual void Paint()
{
DrawSetTextFont(GetFont());
// draw background
DrawSetTextColor(_menuItem->GetBgColor());
DrawPrintChar(0, 0, 'g');
// draw check
if (_menuItem->IsChecked())
{
if (_menuItem->IsEnabled())
{
DrawSetTextColor(_menuItem->GetButtonFgColor());
DrawPrintChar(0, 2, 'a');
}
else if (!_menuItem->IsEnabled())
{
// draw disabled version, with embossed look
// offset image
DrawSetTextColor(_menuItem->GetDisabledFgColor1());
DrawPrintChar(1, 3, 'a');
// overlayed image
DrawSetTextColor(_menuItem->GetDisabledFgColor2());
DrawPrintChar(0, 2, 'a');
}
}
}
private:
MenuItem *_menuItem;
};
DECLARE_BUILD_FACTORY_DEFAULT_TEXT( MenuItem, MenuItem );
//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input: parent - the parent of this menu item, usually a menu
// text - the name of the menu item as it appears in the menu
// cascadeMenu - if this item triggers the opening of a cascading menu
// provide a pointer to it.
// MenuItems cannot be both checkable and trigger a cascade menu.
//-----------------------------------------------------------------------------
MenuItem::MenuItem(Menu *parent, const char *panelName, const char *text, Menu *cascadeMenu, bool checkable) : Button(parent, panelName, text)
{
m_pCascadeMenu = cascadeMenu;
m_bCheckable = checkable;
SetButtonActivationType(ACTIVATE_ONRELEASED);
m_pUserData = NULL;
m_pCurrentKeyBinding = NULL;
// only one arg should be passed in.
Assert (!(cascadeMenu && checkable));
Init();
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input: parent - the parent of this menu item, usually a menu
// text - the name of the menu item as it appears in the menu
// cascadeMenu - if this item triggers the opening of a cascading menu
// provide a pointer to it.
// MenuItems cannot be both checkable and trigger a cascade menu.
//-----------------------------------------------------------------------------
MenuItem::MenuItem(Menu *parent, const char *panelName, const wchar_t *wszText, Menu *cascadeMenu, bool checkable) : Button(parent, panelName, wszText)
{
m_pCascadeMenu = cascadeMenu;
m_bCheckable = checkable;
SetButtonActivationType(ACTIVATE_ONRELEASED);
m_pUserData = NULL;
m_pCurrentKeyBinding = NULL;
// only one arg should be passed in.
Assert (!(cascadeMenu && checkable));
Init();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
MenuItem::~MenuItem()
{
delete m_pCascadeMenu;
delete m_pCascadeArrow;
delete m_pCheck;
if (m_pUserData)
{
m_pUserData->deleteThis();
}
delete m_pCurrentKeyBinding;
}
//-----------------------------------------------------------------------------
// Purpose: Basic initializer
//-----------------------------------------------------------------------------
void MenuItem::Init( void )
{
m_pCascadeArrow = NULL;
m_pCheck = NULL;
if (m_pCascadeMenu)
{
m_pCascadeMenu->SetParent(this);
m_pCascadeArrow = new TextImage("4"); // this makes a right pointing arrow.
m_pCascadeMenu->AddActionSignalTarget(this);
}
else if (m_bCheckable)
{
// move the text image over so we have room for the check
SetTextImageIndex(1);
m_pCheck = new MenuItemCheckImage(this);
SetImageAtIndex(0, m_pCheck, CHECK_INSET);
SetChecked(false);
}
SetButtonBorderEnabled( false );
SetUseCaptureMouse( false );
SetContentAlignment( Label::a_west );
// note menus handle all the sizing of menuItem panels
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Menu *MenuItem::GetParentMenu()
{
return (Menu *)GetParent();
}
//-----------------------------------------------------------------------------
// Purpose: Layout the Textimage and the Arrow part of the menuItem
//-----------------------------------------------------------------------------
void MenuItem::PerformLayout()
{
Button::PerformLayout();
// make the arrow image match the button layout.
// this will make it brighten and dim like the menu buttons.
if (m_pCascadeArrow)
{
m_pCascadeArrow->SetColor(GetButtonFgColor());
}
}
//-----------------------------------------------------------------------------
// Purpose: Close the cascading menu if we have one.
//-----------------------------------------------------------------------------
void MenuItem::CloseCascadeMenu()
{
if (m_pCascadeMenu)
{
if (m_pCascadeMenu->IsVisible())
{
m_pCascadeMenu->SetVisible(false);
}
// disarm even if menu wasn't visible!
SetArmed(false);
}
}
//-----------------------------------------------------------------------------
// Purpose: Handle cursor moving in a menuItem.
//-----------------------------------------------------------------------------
void MenuItem::OnCursorMoved(int x, int y)
{
// if menu is in keymode and we moved the mouse
// highlight this item
if (GetParentMenu()->GetMenuMode() == Menu::KEYBOARD)
{
OnCursorEntered();
}
// chain up to parent
CallParentFunction(new KeyValues("OnCursorMoved", "x", x, "y", y));
}
//-----------------------------------------------------------------------------
// Purpose: Handle mouse cursor entering a menuItem.
//-----------------------------------------------------------------------------
void MenuItem::OnCursorEntered()
{
// post a message to the parent menu.
// forward the message on to the parent of this menu.
KeyValues *msg = new KeyValues ("CursorEnteredMenuItem");
// tell the parent this menuitem is the one that was entered so it can highlight it
msg->SetInt("VPanel", GetVPanel());
ivgui()->PostMessage(GetVParent(), msg, NULL);
}
//-----------------------------------------------------------------------------
// Purpose: Handle mouse cursor exiting a menuItem.
//-----------------------------------------------------------------------------
void MenuItem::OnCursorExited()
{
// post a message to the parent menu.
// forward the message on to the parent of this menu.
KeyValues *msg = new KeyValues ("CursorExitedMenuItem");
// tell the parent this menuitem is the one that was entered so it can unhighlight it
msg->SetInt("VPanel", GetVPanel());
ivgui()->PostMessage(GetVParent(), msg, NULL);
}
//-----------------------------------------------------------------------------
// Purpose: Handle mouse cursor exiting a menuItem.
//-----------------------------------------------------------------------------
void MenuItem::OnKeyCodeReleased(KeyCode code)
{
if (GetParentMenu()->GetMenuMode() == Menu::KEYBOARD && m_pCascadeMenu)
{
return;
}
// only disarm if we are not opening a cascading menu using keys.
Button::OnKeyCodeReleased(code);
}
//-----------------------------------------------------------------------------
// Purpose: Highlight a menu item
// Menu item buttons highlight if disabled, but won't activate.
//-----------------------------------------------------------------------------
void MenuItem::ArmItem()
{
// close all other menus
GetParentMenu()->CloseOtherMenus(this);
// arm the menuItem.
Button::SetArmed(true);
// When you have a submenu with no scroll bar the menu
// border will not be drawn correctly. This fixes it.
Menu *parent = GetParentMenu();
if ( parent )
{
parent->ForceCalculateWidth();
}
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Unhighlight a menu item
//-----------------------------------------------------------------------------
void MenuItem::DisarmItem()
{
// normal behaviour is that the button becomes unarmed
// do not unarm if there is a cascading menu. CloseCascadeMenu handles this.
// and the menu handles it since we close at different times depending
// on whether menu is handling mouse or key events.
if (!m_pCascadeMenu)
{
Button::OnCursorExited();
}
// When you have a submenu with no scroll bar the menu
// border will not be drawn correctly. This fixes it.
Menu *parent = GetParentMenu();
if ( parent )
{
parent->ForceCalculateWidth();
}
Repaint();
}
bool MenuItem::IsItemArmed()
{
return Button::IsArmed();
}
//-----------------------------------------------------------------------------
// Purpose: Pass kill focus events up to parent, This will tell all panels
// in the hierarchy to hide themselves, and enables cascading menus to
// all disappear on selecting an item at the end of the tree.
//-----------------------------------------------------------------------------
void MenuItem::OnKillFocus()
{
GetParentMenu()->OnKillFocus();
}
//-----------------------------------------------------------------------------
// Purpose: fire the menu item as if it has been selected and
// Tell the owner that it is closing
//-----------------------------------------------------------------------------
void MenuItem::FireActionSignal()
{
// cascading menus items don't trigger the parent menu to disappear
// (they trigger the cascading menu to open/close when cursor is moved over/off them)
if (!m_pCascadeMenu)
{
KeyValues *kv = new KeyValues("MenuItemSelected");
kv->SetPtr("panel", this);
ivgui()->PostMessage(GetVParent(), kv, GetVPanel());
// ivgui()->PostMessage(GetVParent(), new KeyValues("MenuItemSelected"), GetVPanel());
Button::FireActionSignal();
// toggle the check next to the item if it is checkable
if (m_bCheckable)
{
SetChecked( !m_bChecked );
}
}
else
{
// if we are in keyboard mode, open the child menu.
if (GetParentMenu()->GetMenuMode() == Menu::KEYBOARD)
{
OpenCascadeMenu();
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Opens the cascading menu.
//-----------------------------------------------------------------------------
void MenuItem::OpenCascadeMenu()
{
if (m_pCascadeMenu)
{
// perform layout on menu, this way it will open in the right spot
// if the window's been moved
m_pCascadeMenu->PerformLayout();
m_pCascadeMenu->SetVisible(true);
m_pCascadeMenu->MoveToFront();
}
}
//-----------------------------------------------------------------------------
// Purpse: Return true if this item triggers a cascading menu
//-----------------------------------------------------------------------------
bool MenuItem::HasMenu()
{
return (m_pCascadeMenu != NULL);
}
//-----------------------------------------------------------------------------
// Purpose: Apply the resource scheme to the menu.
//-----------------------------------------------------------------------------
void MenuItem::ApplySchemeSettings(IScheme *pScheme)
{
// chain back first
Button::ApplySchemeSettings(pScheme);
// get color settings
SetDefaultColor(GetSchemeColor("Menu.TextColor", GetFgColor(), pScheme), GetSchemeColor("Menu.BgColor", GetBgColor(), pScheme));
SetArmedColor(GetSchemeColor("Menu.ArmedTextColor", GetFgColor(), pScheme), GetSchemeColor("Menu.ArmedBgColor", GetBgColor(), pScheme));
SetDepressedColor(GetSchemeColor("Menu.ArmedTextColor", GetFgColor(), pScheme), GetSchemeColor("Menu.ArmedBgColor", GetBgColor(), pScheme));
SetTextInset(atoi(pScheme->GetResourceString("Menu.TextInset")), 0);
// reload images since applyschemesettings in label wipes them out.
if ( m_pCascadeArrow )
{
m_pCascadeArrow->SetFont(pScheme->GetFont("Marlett", IsProportional() ));
m_pCascadeArrow->ResizeImageToContent();
AddImage(m_pCascadeArrow, 0);
}
else if (m_bCheckable)
{
( static_cast<MenuItemCheckImage *>(m_pCheck) )->SetFont( pScheme->GetFont("Marlett", IsProportional()));
SetImageAtIndex(0, m_pCheck, CHECK_INSET);
( static_cast<MenuItemCheckImage *>(m_pCheck) )->ResizeImageToContent();
}
if ( m_pCurrentKeyBinding )
{
m_pCurrentKeyBinding->SetFont(pScheme->GetFont("Default", IsProportional() ));
m_pCurrentKeyBinding->ResizeImageToContent();
}
// Have the menu redo the layout
// Get the parent to resize
Menu * parent = GetParentMenu();
if ( parent )
{
parent->ForceCalculateWidth();
}
}
//-----------------------------------------------------------------------------
// Purpose: Return the size of the text portion of the label.
// for normal menu items this is the same as the label size, but for
// cascading menus it gives you the size of the text portion only, without
// the arrow.
//-----------------------------------------------------------------------------
void MenuItem::GetTextImageSize(int &wide, int &tall)
{
GetTextImage()->GetSize(wide, tall);
}
//-----------------------------------------------------------------------------
// Purpose: Set the size of the text portion of the label.
// For normal menu items this is the same as the label size, but for
// cascading menus it sizes textImage portion only, without
// the arrow.
//-----------------------------------------------------------------------------
void MenuItem::SetTextImageSize(int wide, int tall)
{
GetTextImage()->SetSize(wide, tall);
}
//-----------------------------------------------------------------------------
// Purpose: Return the size of the arrow portion of the label.
// If the menuItem is not a cascading menu, 0 is returned.
//-----------------------------------------------------------------------------
void MenuItem::GetArrowImageSize(int &wide, int &tall)
{
wide = 0, tall = 0;
if (m_pCascadeArrow)
{
m_pCascadeArrow->GetSize(wide, tall);
return;
}
}
//-----------------------------------------------------------------------------
// Purpose: Return the size of the check portion of the label.
//-----------------------------------------------------------------------------
void MenuItem::GetCheckImageSize(int &wide, int &tall)
{
wide = 0, tall = 0;
if (m_pCheck)
{
// resize the image to the contents size
( static_cast<MenuItemCheckImage *>(m_pCheck) )->ResizeImageToContent();
m_pCheck->GetSize(wide, tall);
// include the inset for the check, since nobody but us know about the inset
wide += CHECK_INSET;
return;
}
}
//-----------------------------------------------------------------------------
// Purpose: Return a the menu that this menuItem contains
// This is useful when the parent menu's commands must be
// sent through all menus that are open as well (like hotkeys)
//-----------------------------------------------------------------------------
Menu *MenuItem::GetMenu()
{
return m_pCascadeMenu;
}
//-----------------------------------------------------------------------------
// Purpose: Get the border style for the button. Menu items have no border so
// return null.
//-----------------------------------------------------------------------------
IBorder *MenuItem::GetBorder(bool depressed, bool armed, bool selected, bool keyfocus)
{
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Set the menu to key mode if a child menu goes into keymode
//-----------------------------------------------------------------------------
void MenuItem::OnKeyModeSet()
{
// send the message to this parent in case this is a cascading menu
ivgui()->PostMessage(GetVParent(), new KeyValues("KeyModeSet"), GetVPanel());
}
//-----------------------------------------------------------------------------
// Purpose: Return if this menuitem is checkable or not
// This is used by menus to perform the layout properly.
//-----------------------------------------------------------------------------
bool MenuItem::IsCheckable()
{
return m_bCheckable;
}
//-----------------------------------------------------------------------------
// Purpose: Return if this menuitem is checked or not
//-----------------------------------------------------------------------------
bool MenuItem::IsChecked()
{
return m_bChecked;
}
//-----------------------------------------------------------------------------
// Purpose: Set the checked state of a checkable menuitem
// Does nothing if item is not checkable
//-----------------------------------------------------------------------------
void MenuItem::SetChecked(bool state)
{
if (m_bCheckable)
{
m_bChecked = state;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool MenuItem::CanBeDefaultButton(void)
{
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
KeyValues *MenuItem::GetUserData()
{
if ( HasMenu() )
{
return m_pCascadeMenu->GetItemUserData( m_pCascadeMenu->GetActiveItem() );
}
else
{
return m_pUserData;
}
}
//-----------------------------------------------------------------------------
// Purpose: sets the user data
//-----------------------------------------------------------------------------
void MenuItem::SetUserData(const KeyValues *kv)
{
if (m_pUserData)
{
m_pUserData->deleteThis();
m_pUserData = NULL;
}
if ( kv )
{
m_pUserData = kv->MakeCopy();
}
}
//-----------------------------------------------------------------------------
// Purpose: Passing in NULL removes this object
// Input : *keyName -
//-----------------------------------------------------------------------------
void MenuItem::SetCurrentKeyBinding( char const *keyName )
{
if ( !keyName )
{
delete m_pCurrentKeyBinding;
m_pCurrentKeyBinding = NULL;
return;
}
if ( !m_pCurrentKeyBinding )
{
m_pCurrentKeyBinding = new TextImage( keyName );
}
else
{
char curtext[ 256 ];
m_pCurrentKeyBinding->GetText( curtext, sizeof( curtext ) );
if ( !Q_strcmp( curtext, keyName ) )
return;
m_pCurrentKeyBinding->SetText( keyName );
}
InvalidateLayout( false, true );
}
#define KEYBINDING_INSET 5
void MenuItem::Paint()
{
BaseClass::Paint();
if ( !m_pCurrentKeyBinding )
return;
int w, h;
GetSize( w, h );
int iw, ih;
m_pCurrentKeyBinding->GetSize( iw, ih );
int x = w - iw - KEYBINDING_INSET;
int y = ( h - ih ) / 2;
if ( IsEnabled() )
{
m_pCurrentKeyBinding->SetPos( x, y );
m_pCurrentKeyBinding->SetColor( GetButtonFgColor() );
m_pCurrentKeyBinding->Paint();
}
else
{
m_pCurrentKeyBinding->SetPos( x + 1 , y + 1 );
m_pCurrentKeyBinding->SetColor( GetDisabledFgColor1() );
m_pCurrentKeyBinding->Paint();
surface()->DrawFlushText();
m_pCurrentKeyBinding->SetPos( x, y );
m_pCurrentKeyBinding->SetColor( GetDisabledFgColor2() );
m_pCurrentKeyBinding->Paint();
}
}
void MenuItem::GetContentSize( int& cw, int &ch )
{
BaseClass::GetContentSize( cw, ch );
if ( !m_pCurrentKeyBinding )
return;
int iw, ih;
m_pCurrentKeyBinding->GetSize( iw, ih );
cw += iw + KEYBINDING_INSET;
ch = max( ch, ih );
}

View File

@ -0,0 +1,395 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/ISurface.h>
#include <KeyValues.h>
#include <vgui/IInput.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/MessageBox.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
vgui::Panel *MessageBox_Factory()
{
return new MessageBox("MessageBox", "MessageBoxText");
}
DECLARE_BUILD_FACTORY_CUSTOM( MessageBox, MessageBox_Factory );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
MessageBox::MessageBox(const char *title, const char *text, Panel *parent) : Frame(parent, NULL, false)
{
SetTitle(title, true);
m_pMessageLabel = new Label(this, NULL, text);
Init();
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
MessageBox::MessageBox(const wchar_t *wszTitle, const wchar_t *wszText, Panel *parent) : Frame(parent, NULL, false)
{
SetTitle(wszTitle, true);
m_pMessageLabel = new Label(this, NULL, wszText);
Init();
}
//-----------------------------------------------------------------------------
// Purpose: Constructor Helper
//-----------------------------------------------------------------------------
void MessageBox::Init()
{
SetDeleteSelfOnClose(true);
m_pFrameOver = NULL;
m_bShowMessageBoxOverCursor = false;
SetMenuButtonResponsive(false);
SetMinimizeButtonVisible(false);
SetCloseButtonVisible(false);
SetSizeable(false);
m_pOkButton = new Button(this, NULL, "#MessageBox_OK");
m_pOkButton->SetCommand( "OnOk" );
m_pOkButton->AddActionSignalTarget(this);
m_pCancelButton = new Button(this, NULL, "#MessageBox_Cancel");
m_pCancelButton->SetCommand( "OnCancel" );
m_pCancelButton->AddActionSignalTarget(this);
m_pCancelButton->SetVisible( false );
m_OkCommand = m_CancelCommand = NULL;
m_bNoAutoClose = false;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
MessageBox::~MessageBox()
{
if ( m_OkCommand )
{
m_OkCommand->deleteThis();
}
if ( m_CancelCommand )
{
m_CancelCommand->deleteThis();
}
}
//-----------------------------------------------------------------------------
// Shows the message box over the cursor
//-----------------------------------------------------------------------------
void MessageBox::ShowMessageBoxOverCursor( bool bEnable )
{
m_bShowMessageBoxOverCursor = bEnable;
}
//-----------------------------------------------------------------------------
// Purpose: size the message label properly
//-----------------------------------------------------------------------------
void MessageBox::OnCommand( const char *pCommand )
{
if ( vgui::input()->GetAppModalSurface() == GetVPanel() )
{
vgui::input()->ReleaseAppModalSurface();
}
if ( !Q_stricmp( pCommand, "OnOk" ) )
{
if ( m_OkCommand )
{
PostActionSignal(m_OkCommand->MakeCopy());
}
}
else if ( !Q_stricmp( pCommand, "OnCancel" ) )
{
if ( m_CancelCommand )
{
PostActionSignal(m_CancelCommand->MakeCopy());
}
}
if ( !m_bNoAutoClose )
{
OnShutdownRequest();
}
}
//-----------------------------------------------------------------------------
// Purpose: size the message label properly
//-----------------------------------------------------------------------------
void MessageBox::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
int wide, tall;
m_pMessageLabel->GetContentSize(wide, tall);
m_pMessageLabel->SetSize(wide, tall);
wide += 100;
tall += 100;
SetSize(wide, tall);
if ( m_bShowMessageBoxOverCursor )
{
PlaceUnderCursor();
return;
}
// move to the middle of the screen
if ( m_pFrameOver )
{
int frameX, frameY;
int frameWide, frameTall;
m_pFrameOver->GetPos(frameX, frameY);
m_pFrameOver->GetSize(frameWide, frameTall);
SetPos((frameWide - wide) / 2 + frameX, (frameTall - tall) / 2 + frameY);
}
else
{
int swide, stall;
surface()->GetScreenSize(swide, stall);
// put the dialog in the middle of the screen
SetPos((swide - wide) / 2, (stall - tall) / 2);
}
}
//-----------------------------------------------------------------------------
// Purpose: Put the message box into a modal state
// Does not suspend execution - use addActionSignal to get return value
//-----------------------------------------------------------------------------
void MessageBox::DoModal(Frame* pFrameOver)
{
ShowWindow(pFrameOver);
/*
// move to the middle of the screen
// get the screen size
int wide, tall;
// get our dialog size
GetSize(wide, tall);
if (pFrameOver)
{
int frameX, frameY;
int frameWide, frameTall;
pFrameOver->GetPos(frameX, frameY);
pFrameOver->GetSize(frameWide, frameTall);
SetPos((frameWide - wide) / 2 + frameX, (frameTall - tall) / 2 + frameY);
}
else
{
int swide, stall;
surface()->GetScreenSize(swide, stall);
// put the dialog in the middle of the screen
SetPos((swide - wide) / 2, (stall - tall) / 2);
}
SetVisible( true );
SetEnabled( true );
MoveToFront();
if (m_pOkButton->IsVisible())
m_pOkButton->RequestFocus();
else // handle message boxes with no button
RequestFocus();
*/
input()->SetAppModalSurface(GetVPanel());
}
void MessageBox::ShowWindow(Frame *pFrameOver)
{
m_pFrameOver = pFrameOver;
SetVisible( true );
SetEnabled( true );
MoveToFront();
if ( m_pOkButton->IsVisible() )
{
m_pOkButton->RequestFocus();
}
else // handle message boxes with no button
{
RequestFocus();
}
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Put the text and OK buttons in correct place
//-----------------------------------------------------------------------------
void MessageBox::PerformLayout()
{
int x, y, wide, tall;
GetClientArea(x, y, wide, tall);
wide += x;
tall += y;
int boxWidth, boxTall;
GetSize(boxWidth, boxTall);
int oldWide, oldTall;
m_pOkButton->GetSize(oldWide, oldTall);
int btnWide, btnTall;
m_pOkButton->GetContentSize(btnWide, btnTall);
btnWide = max(oldWide, btnWide + 10);
btnTall = max(oldTall, btnTall + 10);
m_pOkButton->SetSize(btnWide, btnTall);
int btnWide2 = 0, btnTall2 = 0;
if ( m_pCancelButton->IsVisible() )
{
m_pCancelButton->GetSize(oldWide, oldTall);
m_pCancelButton->GetContentSize(btnWide2, btnTall2);
btnWide2 = max(oldWide, btnWide2 + 10);
btnTall2 = max(oldTall, btnTall2 + 10);
m_pCancelButton->SetSize(btnWide2, btnTall2);
}
boxWidth = max(boxWidth, m_pMessageLabel->GetWide() + 100);
boxWidth = max(boxWidth, (btnWide + btnWide2) * 2 + 30);
SetSize(boxWidth, boxTall);
GetSize(boxWidth, boxTall);
m_pMessageLabel->SetPos((wide/2)-(m_pMessageLabel->GetWide()/2) + x, y + 5 );
if ( !m_pCancelButton->IsVisible() )
{
m_pOkButton->SetPos((wide/2)-(m_pOkButton->GetWide()/2) + x, tall - m_pOkButton->GetTall() - 15);
}
else
{
m_pOkButton->SetPos((wide/4)-(m_pOkButton->GetWide()/2) + x, tall - m_pOkButton->GetTall() - 15);
m_pCancelButton->SetPos((3*wide/4)-(m_pOkButton->GetWide()/2) + x, tall - m_pOkButton->GetTall() - 15);
}
BaseClass::PerformLayout();
GetSize(boxWidth, boxTall);
}
//-----------------------------------------------------------------------------
// Purpose: Set a string command to be sent when the OK button is pressed.
//-----------------------------------------------------------------------------
void MessageBox::SetCommand(const char *command)
{
if (m_OkCommand)
{
m_OkCommand->deleteThis();
}
m_OkCommand = new KeyValues("Command", "command", command);
}
//-----------------------------------------------------------------------------
// Purpose: Sets the command
//-----------------------------------------------------------------------------
void MessageBox::SetCommand(KeyValues *command)
{
if (m_OkCommand)
{
m_OkCommand->deleteThis();
}
m_OkCommand = command;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void MessageBox::OnShutdownRequest()
{
// Shutdown the dialog
PostMessage(this, new KeyValues("Close"));
}
//-----------------------------------------------------------------------------
// Purpose: Set the visibility of the OK button.
//-----------------------------------------------------------------------------
void MessageBox::SetOKButtonVisible(bool state)
{
m_pOkButton->SetVisible(state);
}
//-----------------------------------------------------------------------------
// Purpose: Sets the Text on the OK button
//-----------------------------------------------------------------------------
void MessageBox::SetOKButtonText(const char *buttonText)
{
m_pOkButton->SetText(buttonText);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Sets the Text on the OK button
//-----------------------------------------------------------------------------
void MessageBox::SetOKButtonText(const wchar_t *wszButtonText)
{
m_pOkButton->SetText(wszButtonText);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Cancel button (off by default)
//-----------------------------------------------------------------------------
void MessageBox::SetCancelButtonVisible(bool state)
{
m_pCancelButton->SetVisible(state);
InvalidateLayout();
}
void MessageBox::SetCancelButtonText(const char *buttonText)
{
m_pCancelButton->SetText(buttonText);
InvalidateLayout();
}
void MessageBox::SetCancelButtonText(const wchar_t *wszButtonText)
{
m_pCancelButton->SetText(wszButtonText);
InvalidateLayout();
}
void MessageBox::SetCancelCommand( KeyValues *command )
{
if (m_CancelCommand)
{
m_CancelCommand->deleteThis();
}
m_CancelCommand = command;
}
//-----------------------------------------------------------------------------
// Purpose: Toggles visibility of the close box.
//-----------------------------------------------------------------------------
void MessageBox::DisableCloseButton(bool state)
{
BaseClass::SetCloseButtonVisible(state);
m_bNoAutoClose = true;
}

View File

@ -0,0 +1,361 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "vgui_controls/MessageDialog.h"
#include "vgui/ILocalize.h"
#include "vgui/ISurface.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// CMessageDialog
//-----------------------------------------------------------------------------
CMessageDialog::CMessageDialog( vgui::Panel *pParent, const uint nType, const char *pTitle, const char *pMsg, const char *pCmdA, const char *pCmdB, vgui::Panel *pCreator, bool bShowActivity )
: BaseClass( pParent, "MessageDialog" )
{
SetSize( 500, 200 );
SetDeleteSelfOnClose( true );
SetTitleBarVisible( false );
SetCloseButtonVisible( false );
SetSizeable( false );
m_pControlSettings = NULL;
m_pCreator = pCreator ? pCreator : pParent;
m_nType = nType;
m_pTitle = new vgui::Label( this, "TitleLabel", pTitle );
m_pMsg = new vgui::Label( this, "MessageLabel", pMsg );
m_pAnimatingPanel = new vgui::AnimatingImagePanel( this, "AnimatingPanel" );
m_bShowActivity = bShowActivity;
if ( nType & MD_SIMPLEFRAME )
{
SetPaintBackgroundEnabled( true );
m_pBackground = NULL;
}
else
{
m_pBackground = new vgui::ImagePanel( this, "Background" );
if ( nType & MD_WARNING )
{
m_pBackground->SetName( "WarningBackground" );
}
else if ( nType & MD_ERROR )
{
m_pBackground->SetName( "ErrorBackground" );
}
}
Q_memset( m_pCommands, 0, sizeof( m_pCommands ) );
Q_memset( m_Buttons, 0, sizeof( m_Buttons ) );
if ( pCmdA )
{
const int len = Q_strlen( pCmdA ) + 1;
m_pCommands[BTN_A] = (char*)malloc( len );
Q_strncpy( m_pCommands[BTN_A], pCmdA, len );
}
if ( pCmdB )
{
const int len = Q_strlen( pCmdB ) + 1;
m_pCommands[BTN_B] = (char*)malloc( len );
Q_strncpy( m_pCommands[BTN_B], pCmdB, len );
}
// invalid until pressed
m_ButtonPressed = BTN_INVALID;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CMessageDialog::~CMessageDialog()
{
if ( m_ButtonPressed != BTN_INVALID && ( m_nType & MD_COMMANDAFTERCLOSE ) )
{
// caller wants the command sent after closure
m_pCreator->OnCommand( m_pCommands[m_ButtonPressed] );
}
else if ( m_nType & MD_COMMANDONFORCECLOSE )
{
// caller wants the command sent after closure
m_pCreator->OnCommand( m_pCommands[BTN_A] );
}
for ( int i = 0; i < MAX_BUTTONS; ++i )
{
free( m_pCommands[i] );
m_pCommands[i] = NULL;
delete m_Buttons[i].pIcon;
delete m_Buttons[i].pText;
}
delete m_pTitle;
m_pTitle = NULL;
delete m_pMsg;
m_pMsg = NULL;
delete m_pBackground;
m_pBackground = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Set the keyvalues to pass to LoadControlSettings()
//-----------------------------------------------------------------------------
void CMessageDialog::SetControlSettingsKeys( KeyValues *pKeys )
{
m_pControlSettings = pKeys;
}
//-----------------------------------------------------------------------------
// Purpose: Create a new button
//-----------------------------------------------------------------------------
void CMessageDialog::CreateButtonLabel( ButtonLabel_s *pButton, const char *pIcon, const char *pText )
{
pButton->nWide = m_ButtonIconLabelSpace;
pButton->bCreated = true;
pButton->pIcon = new vgui::Label( this, "icon", pIcon );
SETUP_PANEL( pButton->pIcon );
pButton->pIcon->SetFont( m_hButtonFont );
pButton->pIcon->SizeToContents();
pButton->nWide += pButton->pIcon->GetWide();
pButton->pText = new vgui::Label( this, "text", pText );
SETUP_PANEL( pButton->pText );
pButton->pText->SetFont( m_hTextFont );
pButton->pText->SizeToContents();
pButton->pText->SetFgColor( m_ButtonTextColor );
pButton->nWide += pButton->pText->GetWide();
}
//-----------------------------------------------------------------------------
// Purpose: Create and arrange the panel button labels according to the dialog type
//-----------------------------------------------------------------------------
void CMessageDialog::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
LoadControlSettings( "resource/UI/MessageDialog.res", "GAME", m_pControlSettings );
m_hButtonFont = pScheme->GetFont( "GameUIButtons" );
m_hTextFont = pScheme->GetFont( "MenuLarge" );
if ( m_nType & MD_OK )
{
CreateButtonLabel( &m_Buttons[BTN_A], "#GameUI_Icons_A_BUTTON", "#GameUI_OK" );
}
else if ( m_nType & MD_CANCEL )
{
CreateButtonLabel( &m_Buttons[BTN_B], "#GameUI_Icons_B_BUTTON", "#GameUI_Cancel" );
}
else if ( m_nType & MD_OKCANCEL )
{
CreateButtonLabel( &m_Buttons[BTN_A], "#GameUI_Icons_A_BUTTON", "#GameUI_OK" );
CreateButtonLabel( &m_Buttons[BTN_B], "#GameUI_Icons_B_BUTTON", "#GameUI_Cancel" );
}
else if ( m_nType & MD_YESNO )
{
CreateButtonLabel( &m_Buttons[BTN_A], "#GameUI_Icons_A_BUTTON", "#GameUI_Yes" );
CreateButtonLabel( &m_Buttons[BTN_B], "#GameUI_Icons_B_BUTTON", "#GameUI_No" );
}
// count the buttons and add up their widths
int cButtons = 0;
int nTotalWide = 0;
for ( int i = 0; i < MAX_BUTTONS; ++i )
{
if ( m_Buttons[i].bCreated )
{
++cButtons;
nTotalWide += m_Buttons[i].nWide;
}
}
// make sure text and icons are center-aligned vertically with each other
int nButtonTall = vgui::surface()->GetFontTall( m_hButtonFont );
int nTextTall = vgui::surface()->GetFontTall( m_hTextFont );
int nVerticalAdjust = ( nButtonTall - nTextTall ) / 2;
// position the buttons with even horizontal spacing
int xpos = 0;
int ypos = GetTall() - max( nButtonTall, nTextTall ) - m_ButtonMargin;
int nSpacing = ( GetWide() - nTotalWide ) / ( cButtons + 1 );
for ( int i = 0; i < MAX_BUTTONS; ++i )
{
if ( m_Buttons[i].bCreated )
{
xpos += nSpacing;
m_Buttons[i].pIcon->SetPos( xpos, ypos );
xpos += m_Buttons[i].pIcon->GetWide() + m_ButtonIconLabelSpace;
m_Buttons[i].pText->SetPos( xpos, ypos + nVerticalAdjust );
xpos += m_Buttons[i].pText->GetWide();
}
}
m_clrNotSimpleBG = pScheme->GetColor( "MessageDialog.MatchmakingBG", Color( 200, 184, 151, 255 ) );
m_clrNotSimpleBGBlack = pScheme->GetColor( "MessageDialog.MatchmakingBGBlack", Color( 52, 48, 55, 255 ) );
if ( !m_bShowActivity )
{
if ( m_pAnimatingPanel )
{
if ( m_pAnimatingPanel->IsVisible() )
{
m_pAnimatingPanel->SetVisible( false );
}
m_pAnimatingPanel->StopAnimation();
}
}
else
{
if ( m_pAnimatingPanel )
{
if ( !m_pAnimatingPanel->IsVisible() )
{
m_pAnimatingPanel->SetVisible( true );
}
m_pAnimatingPanel->StartAnimation();
}
}
MoveToCenterOfScreen();
if ( m_bShowActivity && m_ActivityIndent )
{
// If we're animating, we push our text label in, and reduce its width
int iX,iY,iW,iH;
m_pMsg->GetBounds( iX, iY, iW, iH );
m_pMsg->SetBounds( iX + m_ActivityIndent, iY, max(0,iW-m_ActivityIndent), iH );
}
// Invalidate the scheme on our message label so that it recalculates
// its line breaks in case it was resized when we loaded our .res file.
m_pMsg->InvalidateLayout( false, true );
}
//-----------------------------------------------------------------------------
// Purpose: Create and arrange the panel button labels according to the dialog type
//-----------------------------------------------------------------------------
void CMessageDialog::ApplySettings( KeyValues *inResourceData )
{
BaseClass::ApplySettings( inResourceData );
m_pTitle->SetFgColor( inResourceData->GetColor( "titlecolor" ) );
m_pMsg->SetFgColor( inResourceData->GetColor( "messagecolor" ) );
m_ButtonTextColor = inResourceData->GetColor( "buttontextcolor" );
m_FooterTall = inResourceData->GetInt( "footer_tall", 0 );
m_ButtonMargin = inResourceData->GetInt( "button_margin", 25 );
m_ButtonIconLabelSpace = inResourceData->GetInt( "button_separator", 10 );
m_ActivityIndent = inResourceData->GetInt( "activity_indent", 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
uint CMessageDialog::GetType( void )
{
return m_nType;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMessageDialog::DoCommand( int button )
{
if ( button == BTN_INVALID || ( m_nType & MD_COMMANDONFORCECLOSE ) )
{
return;
}
if ( m_pCommands[button] )
{
m_ButtonPressed = button;
if ( !( m_nType & MD_COMMANDAFTERCLOSE ) )
{
// caller wants the command sent before closure
m_pCreator->OnCommand( m_pCommands[m_ButtonPressed] );
}
m_pCreator->OnCommand( "ReleaseModalWindow" );
Close();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMessageDialog::OnKeyCodePressed( vgui::KeyCode code )
{
if ( m_ButtonPressed != BTN_INVALID || GetAlpha() != 255 )
{
// inhibit any further key activity or during transitions
return;
}
switch ( GetBaseButtonCode( code ) )
{
case KEY_XBUTTON_A:
case STEAMCONTROLLER_A:
DoCommand( BTN_A );
break;
case KEY_XBUTTON_B:
case STEAMCONTROLLER_B:
DoCommand( BTN_B );
break;
default:
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMessageDialog::PaintBackground( void )
{
int wide, tall;
GetSize( wide, tall );
if ( !( m_nType & MD_SIMPLEFRAME ) )
{
int nAlpha = GetAlpha();
m_clrNotSimpleBG[3] = nAlpha;
m_clrNotSimpleBGBlack[3] = nAlpha;
DrawBox( 0, 0, wide, tall, m_clrNotSimpleBGBlack, 1.0f );
DrawBox( 0, 0, wide, tall - m_FooterTall, m_clrNotSimpleBG, 1.0f );
return;
}
Color col = GetBgColor();
DrawBox( 0, 0, wide, tall, col, 1.0f );
// offset the inset by title
int titleX, titleY, titleWide, titleTall;
m_pTitle->GetBounds( titleX, titleY, titleWide, titleTall );
int y = titleY + titleTall;
// draw an inset
Color darkColor;
darkColor.SetColor( 0.70f * (float)col.r(), 0.70f * (float)col.g(), 0.70f * (float)col.b(), col.a() );
vgui::surface()->DrawSetColor( darkColor );
vgui::surface()->DrawFilledRect( 8, y, wide - 8, tall - 8 );
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,476 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "vgui/MouseCode.h"
#include "vgui/IInput.h"
#include "vgui/IScheme.h"
#include "vgui/ISurface.h"
#include "vgui_controls/EditablePanel.h"
#include "vgui_controls/ScrollBar.h"
#include "vgui_controls/Label.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/Controls.h"
#include "vgui_controls/PanelListPanel.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( PanelListPanel );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
PanelListPanel::PanelListPanel( vgui::Panel *parent, char const *panelName ) : EditablePanel( parent, panelName )
{
SetBounds( 0, 0, 100, 100 );
m_vbar = new ScrollBar(this, "PanelListPanelVScroll", true);
m_vbar->SetVisible(false);
m_vbar->AddActionSignalTarget( this );
m_pPanelEmbedded = new EditablePanel(this, "PanelListEmbedded");
m_pPanelEmbedded->SetBounds(0, 0, 20, 20);
m_pPanelEmbedded->SetPaintBackgroundEnabled( false );
m_pPanelEmbedded->SetPaintBorderEnabled(false);
m_iFirstColumnWidth = 100; // default width
m_iNumColumns = 1; // 1 column by default
if ( IsProportional() )
{
m_iDefaultHeight = scheme()->GetProportionalScaledValueEx( GetScheme(), DEFAULT_HEIGHT );
m_iPanelBuffer = scheme()->GetProportionalScaledValueEx( GetScheme(), PANELBUFFER );
}
else
{
m_iDefaultHeight = DEFAULT_HEIGHT;
m_iPanelBuffer = PANELBUFFER;
}
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
PanelListPanel::~PanelListPanel()
{
// free data from table
DeleteAllItems();
}
void PanelListPanel::SetVerticalBufferPixels( int buffer )
{
m_iPanelBuffer = buffer;
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: counts the total vertical pixels
//-----------------------------------------------------------------------------
int PanelListPanel::ComputeVPixelsNeeded()
{
int iCurrentItem = 0;
int iLargestH = 0;
int pixels = 0;
for ( int i = 0; i < m_SortedItems.Count(); i++ )
{
Panel *panel = m_DataItems[ m_SortedItems[i] ].panel;
if ( !panel )
continue;
if ( panel->IsLayoutInvalid() )
{
panel->InvalidateLayout( true );
}
int iCurrentColumn = iCurrentItem % m_iNumColumns;
int w, h;
panel->GetSize( w, h );
if ( iLargestH < h )
iLargestH = h;
if ( iCurrentColumn == 0 )
pixels += m_iPanelBuffer; // add in buffer. between rows.
if ( iCurrentColumn >= m_iNumColumns - 1 )
{
pixels += iLargestH;
iLargestH = 0;
}
iCurrentItem++;
}
// Add in remaining largest height
pixels += iLargestH;
pixels += m_iPanelBuffer; // add in buffer below last item
return pixels;
}
//-----------------------------------------------------------------------------
// Purpose: Returns the panel to use to render a cell
//-----------------------------------------------------------------------------
Panel *PanelListPanel::GetCellRenderer( int row )
{
if ( !m_SortedItems.IsValidIndex(row) )
return NULL;
Panel *panel = m_DataItems[ m_SortedItems[row] ].panel;
return panel;
}
//-----------------------------------------------------------------------------
// Purpose: adds an item to the view
// data->GetName() is used to uniquely identify an item
// data sub items are matched against column header name to be used in the table
//-----------------------------------------------------------------------------
int PanelListPanel::AddItem( Panel *labelPanel, Panel *panel )
{
Assert(panel);
if ( labelPanel )
{
labelPanel->SetParent( m_pPanelEmbedded );
}
panel->SetParent( m_pPanelEmbedded );
int itemID = m_DataItems.AddToTail();
DATAITEM &newitem = m_DataItems[itemID];
newitem.labelPanel = labelPanel;
newitem.panel = panel;
m_SortedItems.AddToTail(itemID);
InvalidateLayout();
return itemID;
}
//-----------------------------------------------------------------------------
// Purpose: iteration accessor
//-----------------------------------------------------------------------------
int PanelListPanel::GetItemCount() const
{
return m_DataItems.Count();
}
int PanelListPanel::GetItemIDFromRow( int nRow ) const
{
if ( nRow < 0 || nRow >= GetItemCount() )
return m_DataItems.InvalidIndex();
return m_SortedItems[ nRow ];
}
//-----------------------------------------------------------------------------
// Iteration. Use these until they return InvalidItemID to iterate all the items.
//-----------------------------------------------------------------------------
int PanelListPanel::FirstItem() const
{
return m_DataItems.Head();
}
int PanelListPanel::NextItem( int nItemID ) const
{
return m_DataItems.Next( nItemID );
}
int PanelListPanel::InvalidItemID() const
{
return m_DataItems.InvalidIndex( );
}
//-----------------------------------------------------------------------------
// Purpose: returns label panel for this itemID
//-----------------------------------------------------------------------------
Panel *PanelListPanel::GetItemLabel(int itemID)
{
if ( !m_DataItems.IsValidIndex(itemID) )
return NULL;
return m_DataItems[itemID].labelPanel;
}
//-----------------------------------------------------------------------------
// Purpose: returns label panel for this itemID
//-----------------------------------------------------------------------------
Panel *PanelListPanel::GetItemPanel(int itemID)
{
if ( !m_DataItems.IsValidIndex(itemID) )
return NULL;
return m_DataItems[itemID].panel;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PanelListPanel::RemoveItem(int itemID)
{
if ( !m_DataItems.IsValidIndex(itemID) )
return;
DATAITEM &item = m_DataItems[itemID];
if ( item.panel )
{
item.panel->MarkForDeletion();
}
if ( item.labelPanel )
{
item.labelPanel->MarkForDeletion();
}
m_DataItems.Remove(itemID);
m_SortedItems.FindAndRemove(itemID);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: clears and deletes all the memory used by the data items
//-----------------------------------------------------------------------------
void PanelListPanel::DeleteAllItems()
{
FOR_EACH_LL( m_DataItems, i )
{
if ( m_DataItems[i].panel )
{
m_DataItems[i].panel->MarkForDeletion();
m_DataItems[i].panel = NULL;
}
}
m_DataItems.RemoveAll();
m_SortedItems.RemoveAll();
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: clears and deletes all the memory used by the data items
//-----------------------------------------------------------------------------
void PanelListPanel::RemoveAll()
{
m_DataItems.RemoveAll();
m_SortedItems.RemoveAll();
// move the scrollbar to the top of the list
m_vbar->SetValue(0);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PanelListPanel::OnSizeChanged(int wide, int tall)
{
BaseClass::OnSizeChanged(wide, tall);
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: relayouts out the panel after any internal changes
//-----------------------------------------------------------------------------
void PanelListPanel::PerformLayout()
{
int wide, tall;
GetSize( wide, tall );
int vpixels = ComputeVPixelsNeeded();
m_vbar->SetRange( 0, vpixels );
m_vbar->SetRangeWindow( tall );
m_vbar->SetButtonPressedScrollValue( tall / 4 ); // standard height of labels/buttons etc.
m_vbar->SetPos( wide - m_vbar->GetWide() - 2, 0 );
m_vbar->SetSize( m_vbar->GetWide(), tall - 2 );
int top = m_vbar->GetValue();
m_pPanelEmbedded->SetPos( 0, -top );
m_pPanelEmbedded->SetSize( wide - m_vbar->GetWide(), vpixels ); // scrollbar will sit on top (zpos set explicitly)
bool bScrollbarVisible = true;
// If we're supposed to automatically hide the scrollbar when unnecessary, check it now
if ( m_bAutoHideScrollbar )
{
bScrollbarVisible = (m_pPanelEmbedded->GetTall() > tall);
}
m_vbar->SetVisible( bScrollbarVisible );
// Now lay out the controls on the embedded panel
int y = 0;
int h = 0;
int totalh = 0;
int xpos = m_iFirstColumnWidth + m_iPanelBuffer;
int iColumnWidth = ( wide - xpos - m_vbar->GetWide() - 12 ) / m_iNumColumns;
for ( int i = 0; i < m_SortedItems.Count(); i++ )
{
int iCurrentColumn = i % m_iNumColumns;
// add in a little buffer between panels
if ( iCurrentColumn == 0 )
y += m_iPanelBuffer;
DATAITEM &item = m_DataItems[ m_SortedItems[i] ];
if ( h < item.panel->GetTall() )
h = item.panel->GetTall();
if ( item.labelPanel )
{
item.labelPanel->SetBounds( 0, y, m_iFirstColumnWidth, item.panel->GetTall() );
}
item.panel->SetBounds( xpos + iCurrentColumn * iColumnWidth, y, iColumnWidth, item.panel->GetTall() );
if ( iCurrentColumn >= m_iNumColumns - 1 )
{
y += h;
totalh += h;
h = 0;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: scheme settings
//-----------------------------------------------------------------------------
void PanelListPanel::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetBorder(pScheme->GetBorder("ButtonDepressedBorder"));
SetBgColor(GetSchemeColor("ListPanel.BgColor", GetBgColor(), pScheme));
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PanelListPanel::OnSliderMoved( int position )
{
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PanelListPanel::MoveScrollBarToTop()
{
m_vbar->SetValue(0);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PanelListPanel::SetFirstColumnWidth( int width )
{
m_iFirstColumnWidth = width;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
int PanelListPanel::GetFirstColumnWidth()
{
return m_iFirstColumnWidth;
}
void PanelListPanel::SetNumColumns( int iNumColumns )
{
m_iNumColumns = iNumColumns;
}
int PanelListPanel::GetNumColumns( void )
{
return m_iNumColumns;
}
//-----------------------------------------------------------------------------
// Purpose: moves the scrollbar with the mousewheel
//-----------------------------------------------------------------------------
void PanelListPanel::OnMouseWheeled(int delta)
{
int val = m_vbar->GetValue();
val -= (delta * DEFAULT_HEIGHT);
m_vbar->SetValue(val);
}
//-----------------------------------------------------------------------------
// Purpose: selection handler
//-----------------------------------------------------------------------------
void PanelListPanel::SetSelectedPanel( Panel *panel )
{
if ( panel != m_hSelectedItem )
{
// notify the panels of the selection change
if ( m_hSelectedItem )
{
PostMessage( m_hSelectedItem.Get(), new KeyValues("PanelSelected", "state", 0) );
}
if ( panel )
{
PostMessage( panel, new KeyValues("PanelSelected", "state", 1) );
}
m_hSelectedItem = panel;
}
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
Panel *PanelListPanel::GetSelectedPanel()
{
return m_hSelectedItem;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PanelListPanel::ScrollToItem( int itemNumber )
{
if (!m_vbar->IsVisible())
{
return;
}
DATAITEM& item = m_DataItems[ m_SortedItems[ itemNumber ] ];
if ( !item.panel )
return;
int x, y;
item.panel->GetPos( x, y );
int lx, ly;
lx = x;
ly = y;
m_pPanelEmbedded->LocalToScreen( lx, ly );
ScreenToLocal( lx, ly );
int h = item.panel->GetTall();
if ( ly >= 0 && ly + h < GetTall() )
return;
m_vbar->SetValue( y );
InvalidateLayout();
}

View File

@ -0,0 +1,278 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Contains a list of files, determines their perforce status
//
// $NoKeywords: $
//===========================================================================//
#include <vgui_controls/PerforceFileExplorer.h>
#include <vgui_controls/PerforceFileList.h>
#include <vgui_controls/ComboBox.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/Tooltip.h>
#include "tier1/KeyValues.h"
#include "vgui/ISystem.h"
#include "filesystem.h"
#include <ctype.h>
#include "p4lib/ip4.h"
#include "tier2/tier2.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
PerforceFileExplorer::PerforceFileExplorer( Panel *pParent, const char *pPanelName ) :
BaseClass( pParent, pPanelName )
{
m_pFileList = new PerforceFileList( this, "PerforceFileList" );
// Get the list of available drives and put them in a menu here.
// Start with the directory we are in.
m_pFullPathCombo = new ComboBox( this, "FullPathCombo", 8, false );
m_pFullPathCombo->GetTooltip()->SetTooltipFormatToSingleLine();
char pFullPath[MAX_PATH];
g_pFullFileSystem->GetCurrentDirectory( pFullPath, sizeof(pFullPath) );
SetCurrentDirectory( pFullPath );
m_pFullPathCombo->AddActionSignalTarget( this );
m_pFolderUpButton = new Button(this, "FolderUpButton", "", this);
m_pFolderUpButton->GetTooltip()->SetText( "#FileOpenDialog_ToolTip_Up" );
m_pFolderUpButton->SetCommand( new KeyValues( "FolderUp" ) );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
PerforceFileExplorer::~PerforceFileExplorer()
{
}
//-----------------------------------------------------------------------------
// Inherited from Frame
//-----------------------------------------------------------------------------
void PerforceFileExplorer::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
m_pFolderUpButton->AddImage( scheme()->GetImage( "resource/icon_folderup", false), -3 );
}
//-----------------------------------------------------------------------------
// Inherited from Frame
//-----------------------------------------------------------------------------
void PerforceFileExplorer::PerformLayout()
{
BaseClass::PerformLayout();
int x, y, w, h;
GetClientArea( x, y, w, h );
m_pFullPathCombo->SetBounds( x, y + 6, w - 30, 24 );
m_pFolderUpButton->SetBounds( x + w - 24, y + 6, 24, 24 );
m_pFileList->SetBounds( x, y + 36, w, h - 36 );
}
//-----------------------------------------------------------------------------
// Sets the current directory
//-----------------------------------------------------------------------------
void PerforceFileExplorer::SetCurrentDirectory( const char *pFullPath )
{
if ( !pFullPath )
return;
while ( isspace( *pFullPath ) )
{
++pFullPath;
}
if ( !pFullPath[0] )
return;
m_CurrentDirectory = pFullPath;
m_CurrentDirectory.StripTrailingSlash();
m_CurrentDirectory.FixSlashes();
PopulateFileList();
PopulateDriveList();
char pCurrentDirectory[ MAX_PATH ];
m_pFullPathCombo->GetText( pCurrentDirectory, sizeof(pCurrentDirectory) );
if ( Q_stricmp( m_CurrentDirectory.Get(), pCurrentDirectory ) )
{
char pNewDirectory[ MAX_PATH ];
Q_snprintf( pNewDirectory, sizeof(pNewDirectory), "%s\\", m_CurrentDirectory.Get() );
m_pFullPathCombo->SetText( pNewDirectory );
m_pFullPathCombo->GetTooltip()->SetText( pNewDirectory );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PerforceFileExplorer::PopulateDriveList()
{
char pFullPath[MAX_PATH * 4];
char pSubDirPath[MAX_PATH * 4];
Q_strncpy( pFullPath, m_CurrentDirectory.Get(), sizeof( pFullPath ) );
Q_strncpy( pSubDirPath, m_CurrentDirectory.Get(), sizeof( pSubDirPath ) );
m_pFullPathCombo->DeleteAllItems();
// populate the drive list
char buf[512];
int len = system()->GetAvailableDrives(buf, 512);
char *pBuf = buf;
for (int i=0; i < len / 4; i++)
{
m_pFullPathCombo->AddItem(pBuf, NULL);
// is this our drive - add all subdirectories
if ( !_strnicmp( pBuf, pFullPath, 2 ) )
{
int indent = 0;
char *pData = pFullPath;
while (*pData)
{
if (*pData == '\\')
{
if (indent > 0)
{
memset(pSubDirPath, ' ', indent);
memcpy(pSubDirPath+indent, pFullPath, pData-pFullPath+1);
pSubDirPath[indent+pData-pFullPath+1] = 0;
m_pFullPathCombo->AddItem( pSubDirPath, NULL );
}
indent += 2;
}
pData++;
}
}
pBuf += 4;
}
}
//-----------------------------------------------------------------------------
// Purpose: Fill the filelist with the names of all the files in the current directory
//-----------------------------------------------------------------------------
void PerforceFileExplorer::PopulateFileList()
{
// clear the current list
m_pFileList->RemoveAllFiles();
// Create filter string
char pFullFoundPath[MAX_PATH];
char pFilter[MAX_PATH+3];
Q_snprintf( pFilter, sizeof(pFilter), "%s\\*.*", m_CurrentDirectory.Get() );
// Find all files on disk
FileFindHandle_t h;
const char *pFileName = g_pFullFileSystem->FindFirstEx( pFilter, NULL, &h );
for ( ; pFileName; pFileName = g_pFullFileSystem->FindNext( h ) )
{
if ( !Q_stricmp( pFileName, ".." ) || !Q_stricmp( pFileName, "." ) )
continue;
if ( !Q_IsAbsolutePath( pFileName ) )
{
Q_snprintf( pFullFoundPath, sizeof(pFullFoundPath), "%s\\%s", m_CurrentDirectory.Get(), pFileName );
pFileName = pFullFoundPath;
}
int nItemID = m_pFileList->AddFile( pFileName, true );
m_pFileList->RefreshPerforceState( nItemID, true, NULL );
}
g_pFullFileSystem->FindClose( h );
// Now find all files in perforce
CUtlVector<P4File_t> &fileList = p4->GetFileList( m_CurrentDirectory );
int nCount = fileList.Count();
for ( int i = 0; i < nCount; ++i )
{
pFileName = p4->String( fileList[i].m_sLocalFile );
if ( !pFileName[0] )
continue;
int nItemID = m_pFileList->FindFile( pFileName );
bool bFileExists = true;
if ( nItemID == m_pFileList->InvalidItemID() )
{
// If it didn't find it, the file must not exist
// since it already would have added it above
bFileExists = false;
nItemID = m_pFileList->AddFile( pFileName, false, fileList[i].m_bDir );
}
m_pFileList->RefreshPerforceState( nItemID, bFileExists, &fileList[i] );
}
m_pFileList->SortList();
}
//-----------------------------------------------------------------------------
// Purpose: Handle an item in the Drive combo box being selected
//-----------------------------------------------------------------------------
void PerforceFileExplorer::OnTextChanged( KeyValues *kv )
{
Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
// first check which control had its text changed!
if ( pPanel == m_pFullPathCombo )
{
char pCurrentDirectory[ MAX_PATH ];
m_pFullPathCombo->GetText( pCurrentDirectory, sizeof(pCurrentDirectory) );
SetCurrentDirectory( pCurrentDirectory );
return;
}
}
//-----------------------------------------------------------------------------
// Called when the file list was doubleclicked
//-----------------------------------------------------------------------------
void PerforceFileExplorer::OnItemDoubleClicked()
{
if ( m_pFileList->GetSelectedItemsCount() != 1 )
return;
int nItemID = m_pFileList->GetSelectedItem( 0 );
if ( m_pFileList->IsDirectoryItem( nItemID ) )
{
const char *pDirectoryName = m_pFileList->GetFile( nItemID );
SetCurrentDirectory( pDirectoryName );
}
}
//-----------------------------------------------------------------------------
// Called when the folder up button was hit
//-----------------------------------------------------------------------------
void PerforceFileExplorer::OnFolderUp()
{
char pUpDirectory[MAX_PATH];
Q_strncpy( pUpDirectory, m_CurrentDirectory.Get(), sizeof(pUpDirectory) );
Q_StripLastDir( pUpDirectory, sizeof(pUpDirectory) );
Q_StripTrailingSlash( pUpDirectory );
// This occurs at the root directory
if ( !Q_stricmp( pUpDirectory, "." ) )
return;
SetCurrentDirectory( pUpDirectory );
}

View File

@ -0,0 +1,570 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Contains a list of files, determines their perforce status
//
// $NoKeywords: $
//===========================================================================//
#include <vgui_controls/PerforceFileList.h>
#include <vgui_controls/ListPanel.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/ImageList.h>
#include "tier1/KeyValues.h"
#include <vgui/ISurface.h>
#include "filesystem.h"
#include "p4lib/ip4.h"
#include "tier2/tier2.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
static int ListFileNameSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
{
NOTE_UNUSED( pPanel );
bool dir1 = item1.kv->GetInt("directory") == 1;
bool dir2 = item2.kv->GetInt("directory") == 1;
// if they're both not directories of files, return if dir1 is a directory (before files)
if ( dir1 != dir2 )
{
return dir1 ? -1 : 1;
}
const char *string1 = item1.kv->GetString("text");
const char *string2 = item2.kv->GetString("text");
// YWB: Mimic windows behavior where filenames starting with numbers are sorted based on numeric part
int num1 = Q_atoi( string1 );
int num2 = Q_atoi( string2 );
if ( num1 != 0 &&
num2 != 0 )
{
if ( num1 < num2 )
return -1;
else if ( num1 > num2 )
return 1;
}
// Push numbers before everything else
if ( num1 != 0 )
{
return -1;
}
// Push numbers before everything else
if ( num2 != 0 )
{
return 1;
}
return Q_stricmp( string1, string2 );
}
static int ListBaseStringSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2, char const *fieldName )
{
bool dir1 = item1.kv->GetInt("directory") == 1;
bool dir2 = item2.kv->GetInt("directory") == 1;
// if they're both not directories of files, return if dir1 is a directory (before files)
if (dir1 != dir2)
{
return -1;
}
const char *string1 = item1.kv->GetString(fieldName);
const char *string2 = item2.kv->GetString(fieldName);
int cval = Q_stricmp(string1, string2);
if ( cval == 0 )
{
// Use filename to break ties
return ListFileNameSortFunc( pPanel, item1, item2 );
}
return cval;
}
static int ListBaseIntegerSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2, char const *fieldName )
{
bool dir1 = item1.kv->GetInt("directory") == 1;
bool dir2 = item2.kv->GetInt("directory") == 1;
// if they're both not directories of files, return if dir1 is a directory (before files)
if (dir1 != dir2)
{
return -1;
}
int i1 = item1.kv->GetInt(fieldName);
int i2 = item2.kv->GetInt(fieldName);
if ( i1 == i2 )
{
// Use filename to break ties
return ListFileNameSortFunc( pPanel, item1, item2 );
}
return ( i1 < i2 ) ? -1 : 1;
}
static int ListFileSizeSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
{
return ListBaseIntegerSortFunc( pPanel, item1, item2, "filesizeint" );
}
static int ListFileAttributesSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
{
return ListBaseStringSortFunc( pPanel, item1, item2, "attributes" );
}
static int ListFileTypeSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
{
return ListBaseStringSortFunc( pPanel, item1, item2, "type" );
}
//-----------------------------------------------------------------------------
// Dictionary of start dir contexts
//-----------------------------------------------------------------------------
struct ColumnInfo_t
{
char const *columnName;
char const *columnText;
int startingWidth;
int minWidth;
int maxWidth;
int flags;
SortFunc *pfnSort;
Label::Alignment alignment;
};
static ColumnInfo_t g_ColInfo[] =
{
{ "text", "#PerforceFileList_Col_Name", 175, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileNameSortFunc , Label::a_west },
{ "type", "#PerforceFileList_Col_Type", 150, 20, 10000, 0, &ListFileTypeSortFunc , Label::a_west },
{ "in_perforce", "#PerforceFileList_Col_InPerforce", 50, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileAttributesSortFunc , Label::a_west },
{ "synched", "#PerforceFileList_Col_Synched", 50, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileAttributesSortFunc , Label::a_west },
{ "checked_out", "#PerforceFileList_Col_Checked_Out", 50, 20, 10000, ListPanel::COLUMN_UNHIDABLE, &ListFileAttributesSortFunc , Label::a_west },
{ "attributes", "#PerforceFileList_Col_Attributes", 50, 20, 10000, ListPanel::COLUMN_HIDDEN, &ListFileAttributesSortFunc , Label::a_west },
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
PerforceFileList::PerforceFileList( Panel *pParent, const char *pPanelName ) :
BaseClass( pParent, pPanelName )
{
SetMultiselectEnabled( false );
m_bShowDeletedFiles = false;
// list panel
for ( int i = 0; i < ARRAYSIZE( g_ColInfo ); ++i )
{
const ColumnInfo_t& info = g_ColInfo[ i ];
AddColumnHeader( i, info.columnName, info.columnText, info.startingWidth, info.minWidth, info.maxWidth, info.flags );
SetSortFunc( i, info.pfnSort );
SetColumnTextAlignment( i, info.alignment );
}
SetSortColumn( 0 );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
PerforceFileList::~PerforceFileList()
{
}
//-----------------------------------------------------------------------------
// Purpose: Apply scheme settings
//-----------------------------------------------------------------------------
void PerforceFileList::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings( pScheme );
ImageList *pImageList = new ImageList( false );
pImageList->AddImage( scheme()->GetImage( "resource/icon_file", false ) );
pImageList->AddImage( scheme()->GetImage( "resource/icon_folder", false ) );
pImageList->AddImage( scheme()->GetImage( "resource/icon_folder_selected", false ) );
SetImageList( pImageList, true );
}
//-----------------------------------------------------------------------------
// Toggle showing deleted files or not
//-----------------------------------------------------------------------------
void PerforceFileList::ShowDeletedFiles( bool bShowDeletedFiles )
{
if ( m_bShowDeletedFiles != bShowDeletedFiles )
{
m_bShowDeletedFiles = bShowDeletedFiles;
for ( int i = FirstItem(); i != InvalidItemID(); i = NextItem( i ) )
{
KeyValues *pKeyValues = GetItem( i );
if ( !pKeyValues->GetInt( "deleted", 0 ) )
continue;
SetItemVisible( i, m_bShowDeletedFiles );
}
}
}
//-----------------------------------------------------------------------------
// Add a directory to the directory list, returns client spec
//-----------------------------------------------------------------------------
void PerforceFileList::AddItemToDirectoryList( const char *pFullPath, int nItemID, bool bIsDirectory )
{
char pDirectoryBuf[MAX_PATH];
Q_ExtractFilePath( pFullPath, pDirectoryBuf, sizeof(pDirectoryBuf) );
Q_StripTrailingSlash( pDirectoryBuf );
pFullPath = pDirectoryBuf;
DirectoryInfo_t *pInfo;
UtlSymId_t i = m_Directories.Find( pFullPath );
if ( i != m_Directories.InvalidIndex() )
{
pInfo = &m_Directories[i];
}
else
{
char pClientSpec[MAX_PATH];
if ( !p4->GetClientSpecForDirectory( pFullPath, pClientSpec, sizeof(pClientSpec) ) )
{
pClientSpec[0] = 0;
}
pInfo = &m_Directories[ pFullPath ];
pInfo->m_ClientSpec = pClientSpec;
}
pInfo->m_ItemIDs.AddToTail( nItemID );
}
//-----------------------------------------------------------------------------
// Add a file to the file list.
//-----------------------------------------------------------------------------
int PerforceFileList::AddFileToFileList( const char *pFullPath, bool bExistsOnDisk )
{
bool bIsFileWriteable = bExistsOnDisk ? g_pFullFileSystem->IsFileWritable( pFullPath, NULL ) : true;
// add the file to the list
KeyValues *kv = new KeyValues("item");
const char *pRelativePath = Q_UnqualifiedFileName( pFullPath );
kv->SetString( "text", pRelativePath );
kv->SetString( "fullpath", pFullPath );
kv->SetInt( "image", 1 );
IImage *pImage = surface()->GetIconImageForFullPath( pFullPath );
if ( pImage )
{
kv->SetPtr( "iconImage", (void *)pImage );
}
kv->SetInt( "imageSelected", 1 );
kv->SetInt( "directory", 0 );
// These are computed by Refresh
kv->SetInt( "in_perforce", 0 );
kv->SetInt( "synched", 0 );
kv->SetInt( "checked_out", 0 );
kv->SetInt( "deleted", 0 );
wchar_t pFileType[ 80 ];
g_pFullFileSystem->GetFileTypeForFullPath( pFullPath, pFileType, sizeof( pFileType ) );
kv->SetWString( "type", pFileType );
kv->SetString( "attributes", bIsFileWriteable ? "" : "R" );
int nItemID = AddItem( kv, 0, false, false );
kv->deleteThis();
AddItemToDirectoryList( pFullPath, nItemID, false );
return nItemID;
}
//-----------------------------------------------------------------------------
// Add a directory to the file list.
//-----------------------------------------------------------------------------
int PerforceFileList::AddDirectoryToFileList( const char *pFullPath, bool bExistsOnDisk )
{
KeyValues *kv = new KeyValues("item");
const char *pRelativePath = Q_UnqualifiedFileName( pFullPath );
kv->SetString( "text", pRelativePath );
kv->SetString( "fullpath", pFullPath );
kv->SetPtr( "iconImage", (void *)NULL );
kv->SetInt( "image", 2 );
kv->SetInt( "imageSelected", 3 );
kv->SetInt( "directory", 1 );
// These are computed by Refresh
kv->SetInt( "in_perforce", 0 );
kv->SetInt( "synched", 0 );
kv->SetInt( "checked_out", 0 );
kv->SetInt( "deleted", 0 );
kv->SetString( "type", "#PerforceFileList_FileType_Folder" );
kv->SetString( "attributes", "D" );
int nItemID = AddItem(kv, 0, false, false);
kv->deleteThis();
AddItemToDirectoryList( pFullPath, nItemID, true );
return nItemID;
}
//-----------------------------------------------------------------------------
// Add a file or directory to the file list.
//-----------------------------------------------------------------------------
int PerforceFileList::AddFile( const char *pFullPath, int nFileExists, int nIsDirectory )
{
if ( !pFullPath )
return InvalidItemID();
if ( !Q_IsAbsolutePath( pFullPath ) )
{
Warning( "Absolute paths required for PerforceFileList::AddFile!\n"
"\"%s\" is not an abolute path", pFullPath );
return InvalidItemID();
}
char pFixedPath[MAX_PATH];
Q_strncpy( pFixedPath, pFullPath, sizeof(pFixedPath) );
Q_FixSlashes( pFixedPath );
// Check to see if the file is on disk
int nItemID = -1;
bool bFileExists, bIsDirectory;
if ( nFileExists < 0 )
{
bFileExists = g_pFullFileSystem->FileExists( pFixedPath ) ;
}
else
{
bFileExists = ( nFileExists != 0 );
}
if ( nIsDirectory < 0 )
{
if ( bFileExists )
{
bIsDirectory = g_pFullFileSystem->IsDirectory( pFixedPath );
}
else
{
int nLen = Q_strlen( pFixedPath );
bIsDirectory = ( pFixedPath[nLen-1] == CORRECT_PATH_SEPARATOR );
}
}
else
{
bIsDirectory = ( nIsDirectory != 0 );
}
if ( bIsDirectory )
{
nItemID = AddDirectoryToFileList( pFixedPath, bFileExists );
}
else
{
nItemID = AddFileToFileList( pFixedPath, bFileExists );
}
return nItemID;
}
//-----------------------------------------------------------------------------
// Remove all files from the list
//-----------------------------------------------------------------------------
void PerforceFileList::RemoveAllFiles()
{
RemoveAll();
m_Directories.Clear();
}
//-----------------------------------------------------------------------------
// Finds a file in the p4 list
//-----------------------------------------------------------------------------
static P4File_t *FindFileInPerforceList( const char *pFileName, CUtlVector<P4File_t> &fileList, bool *pFound )
{
int nCount = fileList.Count();
for ( int i = 0; i < nCount; ++i )
{
if ( pFound[i] )
continue;
const char *pPerforceFileName = p4->String( fileList[i].m_sLocalFile );
if ( !Q_stricmp( pPerforceFileName, pFileName ) )
{
pFound[i] = true;
return &fileList[i];
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Refresh perforce information
//-----------------------------------------------------------------------------
void PerforceFileList::RefreshPerforceState( int nItemID, bool bFileExists, P4File_t *pFileInfo )
{
KeyValues *kv = GetItem( nItemID );
bool bIsSynched = false;
bool bIsFileInPerforce = (pFileInfo != NULL);
if ( bIsFileInPerforce )
{
if ( pFileInfo->m_bDeleted != bFileExists )
{
bIsSynched = ( pFileInfo->m_bDeleted || ( pFileInfo->m_iHeadRevision == pFileInfo->m_iHaveRevision ) );
}
}
else
{
bIsSynched = !bFileExists;
}
bool bIsDeleted = bIsFileInPerforce && !bFileExists && pFileInfo->m_bDeleted;
kv->SetInt( "in_perforce", bIsFileInPerforce );
kv->SetInt( "synched", bIsSynched );
kv->SetInt( "checked_out", bIsFileInPerforce && ( pFileInfo->m_eOpenState != P4FILE_UNOPENED ) );
kv->SetInt( "deleted", bIsDeleted );
if ( bIsDeleted )
{
SetItemVisible( nItemID, m_bShowDeletedFiles );
}
}
//-----------------------------------------------------------------------------
// Refresh perforce information
//-----------------------------------------------------------------------------
void PerforceFileList::Refresh()
{
/*
// Slow method.. does too many perforce operations
for ( int i = FirstItem(); i != InvalidItemID(); i = NextItem( i ) )
{
const char *pFile = GetFile( i );
P4File_t fileInfo;
bool bIsFileInPerforce = p4->GetFileInfo( pFile, &fileInfo );
bool bFileExists = g_pFullFileSystem->FileExists( pFile );
RefreshPerforceState( i, bFileExists, bIsFileInPerforce ? &fileInfo : NULL );
}
*/
// NOTE: Reducing the # of perforce calls is important for performance
int nCount = m_Directories.GetNumStrings();
for ( int i = 0; i < nCount; ++i )
{
const char *pDirectory = m_Directories.String(i);
DirectoryInfo_t *pInfo = &m_Directories[i];
// Retrives files, uses faster method to avoid finding clientspec
CUtlVector<P4File_t> &fileList = p4->GetFileListUsingClientSpec( pDirectory, pInfo->m_ClientSpec );
int nFileCount = fileList.Count();
bool *pFound = (bool*)_alloca( nFileCount * sizeof(bool) );
memset( pFound, 0, nFileCount * sizeof(bool) );
int nItemCount = pInfo->m_ItemIDs.Count();
for ( int j = 0; j < nItemCount; ++j )
{
int nItemID = pInfo->m_ItemIDs[j];
const char *pFileName = GetFile( nItemID );
bool bFileExists = g_pFullFileSystem->FileExists( pFileName );
P4File_t *pFileInfo = FindFileInPerforceList( pFileName, fileList, pFound );
RefreshPerforceState( nItemID, bFileExists, pFileInfo );
}
}
}
//-----------------------------------------------------------------------------
// Is a particular list item a directory?
//-----------------------------------------------------------------------------
bool PerforceFileList::IsDirectoryItem( int nItemID )
{
KeyValues *kv = GetItem( nItemID );
return kv->GetInt( "directory", 0 ) != 0;
}
//-----------------------------------------------------------------------------
// Returns the file associated with a particular item ID
//-----------------------------------------------------------------------------
const char *PerforceFileList::GetFile( int nItemID )
{
KeyValues *kv = GetItem( nItemID );
Assert( kv );
return kv->GetString( "fullpath", "<no file>" );
}
//-----------------------------------------------------------------------------
// Find the item ID associated with a particular file
//-----------------------------------------------------------------------------
int PerforceFileList::FindFile( const char *pFullPath )
{
for ( int i = FirstItem(); i != InvalidItemID(); i = NextItem( i ) )
{
const char *pFile = GetFile( i );
if ( !Q_stricmp( pFile, pFullPath ) )
return i;
}
return InvalidItemID();
}
//-----------------------------------------------------------------------------
// Is a file already in the list?
//-----------------------------------------------------------------------------
bool PerforceFileList::IsFileInList( const char *pFullPath )
{
return ( FindFile( pFullPath ) != InvalidItemID() );
}
//-----------------------------------------------------------------------------
// Purpose: Double-click: expand folders
//-----------------------------------------------------------------------------
void PerforceFileList::OnMouseDoublePressed( MouseCode code )
{
if ( code == MOUSE_LEFT )
{
// select the item
OnMousePressed(code);
// post a special message
if ( GetSelectedItemsCount() > 0 )
{
PostActionSignal( new KeyValues("ItemDoubleClicked" ) );
}
return;
}
BaseClass::OnMouseDoublePressed( code );
}

View File

@ -0,0 +1,521 @@
//========= 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;
}
}

View File

@ -0,0 +1,360 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/IInput.h>
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui/ISystem.h>
#include <vgui/IVGui.h>
#include <KeyValues.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/ProgressBar.h>
#include <vgui_controls/ProgressBox.h>
#include <stdio.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ProgressBox::ProgressBox(const char *title, const char *text, const char *pszUnknownTimeString, Panel *parent) : Frame(parent, NULL, parent ? false : true)
{
// save off the non-localized title, since we may need to dynamically localize it (on progress updates)
const wchar_t *ws = g_pVGuiLocalize->Find(title);
if (ws)
{
wcsncpy(m_wszTitleString, ws, sizeof(m_wszTitleString) / sizeof(wchar_t));
}
else
{
g_pVGuiLocalize->ConvertANSIToUnicode(title, m_wszTitleString, sizeof(m_wszTitleString));
}
m_pMessageLabel = new Label(this, NULL, pszUnknownTimeString);
ws = g_pVGuiLocalize->Find(text);
if (ws)
{
wcsncpy(m_wcsInfoString, ws, sizeof(m_wcsInfoString) / sizeof(wchar_t));
}
else
{
m_wcsInfoString[0] = 0;
}
ws = g_pVGuiLocalize->Find(pszUnknownTimeString);
if (ws)
{
wcsncpy(m_wszUnknownTimeString, ws, sizeof(m_wszUnknownTimeString) / sizeof(wchar_t));
}
else
{
m_wszUnknownTimeString[0] = 0;
}
Init();
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ProgressBox::ProgressBox(const wchar_t *wszTitle, const wchar_t *wszText, const wchar_t *wszUnknownTimeString, Panel *parent) : Frame(parent, NULL, parent ? false : true)
{
wcsncpy(m_wszTitleString, wszTitle, sizeof(m_wszTitleString) / sizeof(wchar_t));
m_pMessageLabel = new Label(this, NULL, wszUnknownTimeString);
wcsncpy(m_wcsInfoString, wszText, sizeof(m_wcsInfoString) / sizeof(wchar_t));
wcsncpy(m_wszUnknownTimeString, wszUnknownTimeString, sizeof(m_wszUnknownTimeString) / sizeof(wchar_t));
Init();
}
//-----------------------------------------------------------------------------
// Purpose: Constructor Helper
//-----------------------------------------------------------------------------
void ProgressBox::Init()
{
m_pProgressBar = new ProgressBar(this, NULL);
m_pProgressBar->SetVisible(false);
m_pCancelButton = new Button(this, NULL, "#VGui_Cancel");
m_pCancelButton->SetSize(72, 24);
m_pCancelButton->SetCommand("Cancel");
SetMenuButtonResponsive(false);
SetMinimizeButtonVisible(false);
SetCancelButtonVisible(false);
SetSizeable(false);
SetSize(384, 128);
m_flCurrentProgress = 0.0f;
m_flFirstProgressUpdate = -0.1f;
m_flLastProgressUpdate = 0.0f;
// mark ourselves as needed ticked once a second, to force us to repaint
ivgui()->AddTickSignal(GetVPanel(), 1000);
UpdateTitle();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
ProgressBox::~ProgressBox()
{
}
//-----------------------------------------------------------------------------
// Purpose: resize the message label
//-----------------------------------------------------------------------------
void ProgressBox::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
int wide, tall;
m_pMessageLabel->GetContentSize(wide, tall);
SetSize(384, tall + 92);
m_pMessageLabel->SetSize(344, tall);
}
//-----------------------------------------------------------------------------
// Purpose: Put the message box into a modal state
// Does not suspend execution - use addActionSignal to get return value
//-----------------------------------------------------------------------------
void ProgressBox::DoModal(Frame *pFrameOver)
{
ShowWindow(pFrameOver);
input()->SetAppModalSurface(GetVPanel());
}
//-----------------------------------------------------------------------------
// Purpose: Activates the window
//-----------------------------------------------------------------------------
void ProgressBox::ShowWindow(Frame *pFrameOver)
{
// move to the middle of the screen
// get the screen size
int wide, tall;
// get our dialog size
GetSize(wide, tall);
if (pFrameOver)
{
int frameX, frameY;
int frameWide, frameTall;
pFrameOver->GetPos(frameX, frameY);
pFrameOver->GetSize(frameWide, frameTall);
SetPos((frameWide - wide) / 2 + frameX, (frameTall - tall) / 2 + frameY);
}
else
{
int swide, stall;
surface()->GetScreenSize(swide, stall);
// put the dialog in the middle of the screen
SetPos((swide - wide) / 2, (stall - tall) / 2);
}
BaseClass::Activate();
}
//-----------------------------------------------------------------------------
// Purpose: Put the text and OK buttons in correct place
//-----------------------------------------------------------------------------
void ProgressBox::PerformLayout()
{
int x, y, wide, tall;
GetClientArea(x, y, wide, tall);
wide += x;
tall += y;
int leftEdge = x + 16;
m_pMessageLabel->SetPos(leftEdge, y + 12);
m_pProgressBar->SetPos(leftEdge, y + 14 + m_pMessageLabel->GetTall() + 2);
m_pProgressBar->SetSize(wide - 44, 24);
if (m_pCancelButton->IsVisible())
{
// make room for cancel
int px, py, pw, pt;
int offs = m_pCancelButton->GetWide();
m_pProgressBar->GetBounds(px, py, pw, pt);
m_pCancelButton->SetPos(px + pw - offs, py);
m_pProgressBar->SetSize(pw - offs - 10, pt);
}
BaseClass::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose: updates progress bar, range [0, 1]
//-----------------------------------------------------------------------------
void ProgressBox::SetProgress(float progress)
{
Assert(progress >= 0.0f && progress <= 1.0f);
m_pProgressBar->SetProgress(progress);
m_pProgressBar->SetVisible(true);
// only update progress timings if the progress has actually changed
if (progress != m_flCurrentProgress)
{
// store off timings for calculating time remaining
if (m_flFirstProgressUpdate < 0.0f)
{
m_flFirstProgressUpdate = (float)system()->GetFrameTime();
}
m_flCurrentProgress = progress;
m_flLastProgressUpdate = (float)system()->GetFrameTime();
UpdateTitle();
}
}
//-----------------------------------------------------------------------------
// Purpose: sets the info text
//-----------------------------------------------------------------------------
void ProgressBox::SetText(const char *text)
{
m_pMessageLabel->SetText(text);
}
//-----------------------------------------------------------------------------
// Purpose: Updates the dialog title text
//-----------------------------------------------------------------------------
void ProgressBox::UpdateTitle()
{
// update progress text
wchar_t unicode[256];
wchar_t completion[64];
if ((int)(m_flCurrentProgress * 100.0f) > 0)
{
_snwprintf(completion, sizeof(completion) / sizeof(wchar_t), L"- %d%% complete", (int)(m_flCurrentProgress * 100.0f));
}
else
{
completion[0] = 0;
}
g_pVGuiLocalize->ConstructString(unicode, sizeof(unicode), m_wszTitleString, 1, completion);
SetTitle(unicode, true);
}
//-----------------------------------------------------------------------------
// Purpose: called every render
//-----------------------------------------------------------------------------
void ProgressBox::OnThink()
{
// calculate the progress made
if (m_flFirstProgressUpdate >= 0.0f && m_wcsInfoString[0])
{
wchar_t timeRemaining[128];
if (ProgressBar::ConstructTimeRemainingString(timeRemaining, sizeof(timeRemaining), m_flFirstProgressUpdate, (float)system()->GetFrameTime(), m_flCurrentProgress, m_flLastProgressUpdate, true))
{
wchar_t unicode[256];
g_pVGuiLocalize->ConstructString(unicode, sizeof(unicode), m_wcsInfoString, 1, timeRemaining);
m_pMessageLabel->SetText(unicode);
}
else
{
m_pMessageLabel->SetText(m_wszUnknownTimeString);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Forces us to repaint once per second
//-----------------------------------------------------------------------------
void ProgressBox::OnTick()
{
if (m_flFirstProgressUpdate >= 0.0f)
{
Repaint();
}
BaseClass::OnTick();
}
//-----------------------------------------------------------------------------
// Purpose: Handles ESC closing dialog
//-----------------------------------------------------------------------------
void ProgressBox::OnCommand(const char *command)
{
if (!stricmp(command, "Cancel"))
{
OnCancel();
}
else
{
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose: close button pressed
//-----------------------------------------------------------------------------
void ProgressBox::OnCloseFrameButtonPressed()
{
OnCancel();
}
//-----------------------------------------------------------------------------
// Purpose: Deletes self when closed
//-----------------------------------------------------------------------------
void ProgressBox::OnClose()
{
BaseClass::OnClose();
// modal surface is released on deletion
MarkForDeletion();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ProgressBox::OnShutdownRequest()
{
// Shutdown the dialog
PostMessage(this, new KeyValues("Command", "command", "Cancel"));
}
//-----------------------------------------------------------------------------
// Purpose: On update cancelled
//-----------------------------------------------------------------------------
void ProgressBox::OnCancel()
{
// post a message that we've been cancelled
PostActionSignal(new KeyValues("ProgressBoxCancelled"));
// close this dialog
Close();
}
//-----------------------------------------------------------------------------
// Purpose: Toggles visibility of the close box.
//-----------------------------------------------------------------------------
void ProgressBox::SetCancelButtonVisible(bool state)
{
BaseClass::SetCloseButtonVisible(state);
m_pCancelButton->SetVisible(state);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ProgressBox::SetCancelButtonEnabled(bool state)
{
m_pCancelButton->SetEnabled(state);
BaseClass::SetCloseButtonVisible(state);
InvalidateLayout();
Repaint();
}

View File

@ -0,0 +1,303 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/KeyCode.h>
#include <KeyValues.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/PropertyDialog.h>
#include <vgui_controls/PropertySheet.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
PropertyDialog::PropertyDialog(Panel *parent, const char *panelName) : Frame(parent, panelName)
{
// create the property sheet
_propertySheet = new PropertySheet(this, "Sheet");
_propertySheet->AddActionSignalTarget(this);
_propertySheet->SetTabPosition(1);
// add the buttons
_okButton = new Button(this, "OKButton", "#PropertyDialog_OK");
_okButton->AddActionSignalTarget(this);
_okButton->SetTabPosition(2);
_okButton->SetCommand("OK");
GetFocusNavGroup().SetDefaultButton(_okButton);
_cancelButton = new Button(this, "CancelButton", "#PropertyDialog_Cancel");
_cancelButton->AddActionSignalTarget(this);
_cancelButton->SetTabPosition(3);
_cancelButton->SetCommand("Cancel");
_applyButton = new Button(this, "ApplyButton", "#PropertyDialog_Apply");
_applyButton->AddActionSignalTarget(this);
_applyButton->SetTabPosition(4);
_applyButton->SetVisible(false); // default to not visible
_applyButton->SetEnabled(false); // default to not enabled
_applyButton->SetCommand("Apply");
SetSizeable(false);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
PropertyDialog::~PropertyDialog()
{
}
//-----------------------------------------------------------------------------
// Purpose: Returns a pointer to the PropertySheet this dialog encapsulates
// Output : PropertySheet *
//-----------------------------------------------------------------------------
PropertySheet *PropertyDialog::GetPropertySheet()
{
return _propertySheet;
}
//-----------------------------------------------------------------------------
// Purpose: Gets a pointer to the currently active page.
// Output : Panel
//-----------------------------------------------------------------------------
Panel *PropertyDialog::GetActivePage()
{
return _propertySheet->GetActivePage();
}
//-----------------------------------------------------------------------------
// Purpose: Wrapped function
//-----------------------------------------------------------------------------
void PropertyDialog::AddPage(Panel *page, const char *title)
{
_propertySheet->AddPage(page, title);
}
//-----------------------------------------------------------------------------
// Purpose: reloads the data in all the property page
//-----------------------------------------------------------------------------
void PropertyDialog::ResetAllData()
{
_propertySheet->ResetAllData();
}
//-----------------------------------------------------------------------------
// Purpose: Applies any changes
//-----------------------------------------------------------------------------
void PropertyDialog::ApplyChanges()
{
OnCommand("Apply");
}
//-----------------------------------------------------------------------------
// Purpose: Sets up the sheet
//-----------------------------------------------------------------------------
void PropertyDialog::PerformLayout()
{
BaseClass::PerformLayout();
int iBottom = m_iSheetInsetBottom;
if ( IsProportional() )
{
iBottom = scheme()->GetProportionalScaledValueEx( GetScheme(), iBottom );
}
int x, y, wide, tall;
GetClientArea(x, y, wide, tall);
_propertySheet->SetBounds(x, y, wide, tall - iBottom);
// move the buttons to the bottom-right corner
int xpos = x + wide - 80;
int ypos = tall + y - 28;
if (_applyButton->IsVisible())
{
_applyButton->SetBounds(xpos, ypos, 72, 24);
xpos -= 80;
}
if (_cancelButton->IsVisible())
{
_cancelButton->SetBounds(xpos, ypos, 72, 24);
xpos -= 80;
}
_okButton->SetBounds(xpos, ypos, 72, 24);
_propertySheet->InvalidateLayout(); // tell the propertysheet to redraw!
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Handles command text from the buttons
//-----------------------------------------------------------------------------
void PropertyDialog::OnCommand(const char *command)
{
if (!stricmp(command, "OK"))
{
if ( OnOK(false) )
{
OnCommand("Close");
}
_applyButton->SetEnabled(false);
}
else if (!stricmp(command, "Cancel"))
{
OnCancel();
Close();
}
else if (!stricmp(command, "Apply"))
{
OnOK(true);
_applyButton->SetEnabled(false);
InvalidateLayout();
}
else
{
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose: called when the Cancel button is pressed
//-----------------------------------------------------------------------------
void PropertyDialog::OnCancel()
{
// designed to be overridden
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : code -
//-----------------------------------------------------------------------------
void PropertyDialog::OnKeyCodeTyped(KeyCode code)
{
// this has been removed, since it conflicts with how we use the escape key in the game
// if (code == KEY_ESCAPE)
// {
// OnCommand("Cancel");
// }
// else
{
BaseClass::OnKeyCodeTyped(code);
}
}
//-----------------------------------------------------------------------------
// Purpose: Command handler
//-----------------------------------------------------------------------------
bool PropertyDialog::OnOK(bool applyOnly)
{
// the sheet should have the pages apply changes before we tell the world
_propertySheet->ApplyChanges();
// this should tell anybody who's watching us that we're done
PostActionSignal(new KeyValues("ApplyChanges"));
// default to closing
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Overrides build mode so it edits the sub panel
//-----------------------------------------------------------------------------
void PropertyDialog::ActivateBuildMode()
{
// no subpanel, no build mode
EditablePanel *panel = dynamic_cast<EditablePanel *>(GetActivePage());
if (!panel)
return;
panel->ActivateBuildMode();
}
//-----------------------------------------------------------------------------
// Purpose: sets the text on the OK/Cancel buttons, overriding the default
//-----------------------------------------------------------------------------
void PropertyDialog::SetOKButtonText(const char *text)
{
_okButton->SetText(text);
}
//-----------------------------------------------------------------------------
// Purpose: sets the text on the OK/Cancel buttons, overriding the default
//-----------------------------------------------------------------------------
void PropertyDialog::SetCancelButtonText(const char *text)
{
_cancelButton->SetText(text);
}
//-----------------------------------------------------------------------------
// Purpose: sets the text on the apply buttons, overriding the default
//-----------------------------------------------------------------------------
void PropertyDialog::SetApplyButtonText(const char *text)
{
_applyButton->SetText(text);
}
//-----------------------------------------------------------------------------
// Purpose: changes the visibility of the buttons
//-----------------------------------------------------------------------------
void PropertyDialog::SetOKButtonVisible(bool state)
{
_okButton->SetVisible(state);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: changes the visibility of the buttons
//-----------------------------------------------------------------------------
void PropertyDialog::SetCancelButtonVisible(bool state)
{
_cancelButton->SetVisible(state);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: changes the visibility of the buttons
//-----------------------------------------------------------------------------
void PropertyDialog::SetApplyButtonVisible(bool state)
{
_applyButton->SetVisible(state);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: when a sheet changes, enable the apply button
//-----------------------------------------------------------------------------
void PropertyDialog::OnApplyButtonEnable()
{
if (_applyButton->IsEnabled())
return;
EnableApplyButton(true);
}
//-----------------------------------------------------------------------------
// Purpose: enable/disable the apply button
//-----------------------------------------------------------------------------
void PropertyDialog::EnableApplyButton(bool bEnable)
{
_applyButton->SetEnabled(bEnable);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PropertyDialog::RequestFocus(int direction)
{
_propertySheet->RequestFocus(direction);
}

View File

@ -0,0 +1,114 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "vgui/IScheme.h"
#include "vgui/KeyCode.h"
#include "vgui/ISurface.h"
#include "KeyValues.h"
#include "vgui_controls/PropertyPage.h"
#include "vgui_controls/Controls.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
PropertyPage::PropertyPage(Panel *parent, const char *panelName) : EditablePanel(parent, panelName)
{
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
PropertyPage::~PropertyPage()
{
}
//-----------------------------------------------------------------------------
// Purpose: Called when page is loaded. Data should be reloaded from document into controls.
//-----------------------------------------------------------------------------
void PropertyPage::OnResetData()
{
}
//-----------------------------------------------------------------------------
// Purpose: Called when the OK / Apply button is pressed. Changed data should be written into document.
//-----------------------------------------------------------------------------
void PropertyPage::OnApplyChanges()
{
}
//-----------------------------------------------------------------------------
// Purpose: Designed to be overriden
//-----------------------------------------------------------------------------
void PropertyPage::OnPageShow()
{
}
//-----------------------------------------------------------------------------
// Purpose: Designed to be overriden
//-----------------------------------------------------------------------------
void PropertyPage::OnPageHide()
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pageTab -
//-----------------------------------------------------------------------------
void PropertyPage::OnPageTabActivated(Panel *pageTab)
{
_pageTab = pageTab;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PropertyPage::OnKeyCodeTyped(KeyCode code)
{
switch (code)
{
// left and right only get propogated to parents if our tab has focus
case KEY_RIGHT:
{
if (_pageTab != 0 && _pageTab->HasFocus())
BaseClass::OnKeyCodeTyped(code);
break;
}
case KEY_LEFT:
{
if (_pageTab != 0 && _pageTab->HasFocus())
BaseClass::OnKeyCodeTyped(code);
break;
}
default:
BaseClass::OnKeyCodeTyped(code);
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PropertyPage::SetVisible(bool state)
{
if (IsVisible() && !state)
{
// if we're going away and we have a current button, get rid of it
if (GetFocusNavGroup().GetCurrentDefaultButton())
{
GetFocusNavGroup().SetCurrentDefaultButton(NULL);
}
}
BaseClass::SetVisible(state);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,222 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
// This class is a message box that has two buttons, ok and cancel instead of
// just the ok button of a message box. We use a message box class for the ok button
// and implement another button here.
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/KeyCode.h>
#include <vgui_controls/QueryBox.h>
#include <vgui_controls/TextImage.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
QueryBox::QueryBox(const char *title, const char *queryText, vgui::Panel *parent) : MessageBox(title, queryText,parent)
{
SetDeleteSelfOnClose(true);
m_pCancelButton = new Button(this, "CancelButton", "#QueryBox_Cancel");
m_pCancelButton->SetCommand("Cancel");
m_pOkButton->SetCommand("OK");
m_pCancelCommand = NULL;
m_pOkCommand = NULL;
m_pOkButton->SetTabPosition(1);
m_pCancelButton->SetTabPosition(2);
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
QueryBox::QueryBox(const wchar_t *wszTitle, const wchar_t *wszQueryText,vgui::Panel *parent) : MessageBox(wszTitle, wszQueryText,parent)
{
SetDeleteSelfOnClose(true);
m_pCancelButton = new Button(this, "CancelButton", "#QueryBox_Cancel");
m_pCancelButton->SetCommand("Cancel");
m_pOkButton->SetCommand("OK");
m_pCancelCommand = NULL;
m_pOkCommand = NULL;
m_pOkButton->SetTabPosition(1);
m_pCancelButton->SetTabPosition(2);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
QueryBox::~QueryBox()
{
delete m_pCancelButton;
if ( m_pOkCommand )
{
m_pOkCommand->deleteThis();
}
if ( m_pCancelCommand )
{
m_pCancelCommand->deleteThis();
}
}
//-----------------------------------------------------------------------------
// Purpose: Layout the window for drawing
//-----------------------------------------------------------------------------
void QueryBox::PerformLayout()
{
BaseClass::PerformLayout();
int boxWidth, boxTall;
GetSize(boxWidth, boxTall);
int x, y, wide, tall;
GetClientArea(x, y, wide, tall);
wide += x;
tall += y;
int oldWide, oldTall;
m_pCancelButton->GetSize(oldWide, oldTall);
int btnWide, btnTall;
m_pCancelButton->GetContentSize(btnWide, btnTall);
btnWide = max(oldWide, btnWide + 10);
btnTall = max(oldTall, btnTall + 10);
m_pCancelButton->SetSize(btnWide, btnTall);
//nt boxWidth, boxTall;
GetSize(boxWidth, boxTall);
// wide = max(wide, btnWide * 2 + 100);
// SetSize(wide, tall);
m_pOkButton->SetPos((wide/2)-(m_pOkButton->GetWide())-1 + x, tall - m_pOkButton->GetTall() - 15);
m_pCancelButton->SetPos((wide/2) + x+16, tall - m_pCancelButton->GetTall() - 15);
}
//-----------------------------------------------------------------------------
// Purpose: Handles command text from the buttons
// Deletes self when closed
//-----------------------------------------------------------------------------
void QueryBox::OnCommand(const char *command)
{
if (!stricmp(command, "OK"))
{
OnCommand("Close");
if ( m_pOkCommand )
{
PostActionSignal(m_pOkCommand->MakeCopy());
}
}
else if (!stricmp(command, "Cancel"))
{
OnCommand("Close");
if (m_pCancelCommand)
{
PostActionSignal(m_pCancelCommand->MakeCopy());
}
}
BaseClass::OnCommand(command);
}
//-----------------------------------------------------------------------------
// Purpose: Set the keyvalues to send when ok button is hit
//-----------------------------------------------------------------------------
void QueryBox::SetOKCommand(KeyValues *keyValues)
{
if ( m_pOkCommand )
{
m_pOkCommand->deleteThis();
}
m_pOkCommand = keyValues;
}
//-----------------------------------------------------------------------------
// Purpose: Set a value of the ok command
//-----------------------------------------------------------------------------
void QueryBox::SetOKCommandValue(const char *keyName, int value)
{
if ( !m_pOkCommand )
{
m_pOkCommand = new KeyValues("Command");
}
m_pOkCommand->SetInt(keyName, value);
}
//-----------------------------------------------------------------------------
// Purpose: Set the keyvalues to send when the cancel button is hit
//-----------------------------------------------------------------------------
void QueryBox::SetCancelCommand(KeyValues *keyValues)
{
if ( m_pCancelCommand )
{
m_pCancelCommand->deleteThis();
}
m_pCancelCommand = keyValues;
}
//-----------------------------------------------------------------------------
// Purpose: Sets the cancel button text
//-----------------------------------------------------------------------------
void QueryBox::SetCancelButtonText(const char* buttonText)
{
m_pCancelButton->SetText(buttonText);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Sets the cancel button text
//-----------------------------------------------------------------------------
void QueryBox::SetCancelButtonText(const wchar_t* wszButtonText)
{
m_pCancelButton->SetText(wszButtonText);
InvalidateLayout();
}
void QueryBox::OnKeyCodeTyped( KeyCode code )
{
if ( code == KEY_ESCAPE )
{
OnCommand("Cancel");
}
else
{
Frame::OnKeyCodeTyped(code);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void QueryBox::OnKeyCodePressed( KeyCode code )
{
if ( code == KEY_XBUTTON_B )
{
OnCommand("Cancel");
}
else
{
Frame::OnKeyCodePressed(code);
}
}

View File

@ -0,0 +1,425 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdarg.h>
#include <stdio.h>
#include <vgui/IInput.h>
#include <vgui/IPanel.h>
#include <vgui/IScheme.h>
#include <vgui/ISystem.h>
#include <vgui/IVGui.h>
#include <vgui/KeyCode.h>
#include <KeyValues.h>
#include <vgui_controls/FocusNavGroup.h>
#include <vgui_controls/Image.h>
#include <vgui_controls/RadioButton.h>
#include <vgui_controls/TextImage.h>
#include <vgui_controls/Controls.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
enum direction
{
UP = -1,
DOWN = 1,
};
//-----------------------------------------------------------------------------
// Purpose: Check box image
//-----------------------------------------------------------------------------
void RadioImage::Paint()
{
DrawSetTextFont(GetFont());
// draw background
if (_radioButton->IsEnabled())
{
DrawSetTextColor(_bgColor);
}
else
{
DrawSetTextColor(_radioButton->GetBgColor());
}
DrawPrintChar(0, 1, 'n');
// draw border circl
DrawSetTextColor(_borderColor1);
DrawPrintChar(0, 1, 'j');
DrawSetTextColor(_borderColor2);
DrawPrintChar(0, 1, 'k');
// draw selected check
if (_radioButton->IsSelected())
{
DrawSetTextColor(_checkColor);
DrawPrintChar(0, 1, 'h');
}
}
DECLARE_BUILD_FACTORY_DEFAULT_TEXT( RadioButton, RadioButton );
//-----------------------------------------------------------------------------
// Purpose: Create a radio button.
//-----------------------------------------------------------------------------
RadioButton::RadioButton(Panel *parent, const char *panelName, const char *text) : ToggleButton(parent, panelName, text)
{
SetContentAlignment(a_west);
// create the image
_radioBoxImage = new RadioImage(this);
_oldTabPosition = 0;
_subTabPosition = 0;
SetTextImageIndex(1);
SetImageAtIndex(0, _radioBoxImage, 0);
SetButtonActivationType(ACTIVATE_ONPRESSED);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
RadioButton::~RadioButton()
{
delete _radioBoxImage;
}
//-----------------------------------------------------------------------------
// Purpose: Apply resource file scheme.
//-----------------------------------------------------------------------------
void RadioButton::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
_radioBoxImage->_bgColor = GetSchemeColor("CheckButton.BgColor", Color(150, 150, 150, 0), pScheme);
_radioBoxImage->_borderColor1 = GetSchemeColor("CheckButton.Border1", Color(20, 20, 20, 0), pScheme);
_radioBoxImage->_borderColor2 = GetSchemeColor("CheckButton.Border2", Color(90, 90, 90, 0), pScheme);
_radioBoxImage->_checkColor = GetSchemeColor("CheckButton.Check", Color(20, 20, 20, 0), pScheme);
SetFgColor(GetSchemeColor("RadioButton.TextColor", pScheme));
_selectedFgColor = GetSchemeColor("RadioButton.SelectedTextColor", GetSchemeColor("ControlText", pScheme), pScheme);
SetDefaultColor( GetFgColor(), GetBgColor() );
SetArmedColor( GetSchemeColor("RadioButton.ArmedTextColor", pScheme), GetButtonArmedBgColor() );
SetContentAlignment(a_west);
// reloading the scheme wipes out lists of images
HFont hFont = pScheme->GetFont("MarlettSmall", IsProportional());
if ( hFont == INVALID_FONT )
{
// fallback to Marlett if MarlettSmall isn't found
hFont = pScheme->GetFont("Marlett", IsProportional());
}
_radioBoxImage->SetFont( hFont );
_radioBoxImage->ResizeImageToContent();
SetImageAtIndex(0, _radioBoxImage, 0);
// don't draw a background
SetPaintBackgroundEnabled(false);
}
//-----------------------------------------------------------------------------
// Purpose: Get the border style of the button, Radio buttons have no border
//-----------------------------------------------------------------------------
IBorder *RadioButton::GetBorder(bool depressed, bool armed, bool selected, bool keyfocus)
{
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Get the tab position of the radio button with the set of radio buttons
// A group of RadioButtons must have the same TabPosition, with [1, n] subtabpositions
//-----------------------------------------------------------------------------
int RadioButton::GetSubTabPosition()
{
return _subTabPosition;
}
//-----------------------------------------------------------------------------
// Purpose: Get the tab position of the radio button with the set of radio buttons
// A group of RadioButtons must have the same TabPosition, with [1, n] subtabpositions
//-----------------------------------------------------------------------------
void RadioButton::SetSubTabPosition(int position)
{
_subTabPosition = position;
}
//-----------------------------------------------------------------------------
// Purpose: Return the RadioButton's real tab position (its Panel one changes)
//-----------------------------------------------------------------------------
int RadioButton::GetRadioTabPosition()
{
return _oldTabPosition;
}
//-----------------------------------------------------------------------------
// Purpose: Set the radio button checked. When a radio button is checked, a
// message is sent to all other radio buttons in the same group so
// they will become unchecked.
//-----------------------------------------------------------------------------
void RadioButton::SetSelected(bool state)
{
InternalSetSelected( state, true );
}
void RadioButton::InternalSetSelected(bool state, bool bFireEvents)
{
if (state == true)
{
if (!IsEnabled())
return;
// restore our tab position
SetTabPosition(_oldTabPosition);
// Should we send notifications?
if ( bFireEvents )
{
// send a message
KeyValues *msg = new KeyValues("RadioButtonChecked");
msg->SetPtr("panel", this);
msg->SetInt("tabposition", _oldTabPosition);
// send a message to all other panels on the same level as heirarchy,
// so that other radio buttons know to shut off
VPANEL radioParent = GetVParent();
if (radioParent)
{
for (int i = 0; i < ipanel()->GetChildCount(radioParent); i++)
{
VPANEL child = ipanel()->GetChild(radioParent, i);
if (child != GetVPanel())
{
ivgui()->PostMessage(child, msg->MakeCopy(), GetVPanel());
}
}
}
RequestFocus();
PostActionSignal(msg);
}
}
else
{
// remove ourselves from the tab order
if (GetTabPosition())
{
_oldTabPosition = GetTabPosition();
}
SetTabPosition(0);
}
InvalidateLayout();
Repaint();
ToggleButton::SetSelected(state);
}
//-----------------------------------------------------------------------------
// Purpose: Set the selection state without firing any events
//-----------------------------------------------------------------------------
void RadioButton::SilentSetSelected(bool state)
{
InternalSetSelected( state, false );
}
//-----------------------------------------------------------------------------
// Purpose: Set up the text color before doing normal layout
//-----------------------------------------------------------------------------
void RadioButton::PerformLayout()
{
if (IsSelected())
{
SetFgColor(_selectedFgColor);
}
else
{
SetFgColor(GetButtonFgColor());
}
BaseClass::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Apply resource settings including button state and text color.
//-----------------------------------------------------------------------------
void RadioButton::ApplySettings(KeyValues *inResourceData)
{
ToggleButton::ApplySettings(inResourceData);
SetTextColorState(CS_NORMAL);
_subTabPosition = inResourceData->GetInt("SubTabPosition");
_oldTabPosition = inResourceData->GetInt("TabPosition");
SetImageAtIndex(0, _radioBoxImage, 0);
}
//-----------------------------------------------------------------------------
// Purpose: Get resource settings including button state, text color, and subTabPosition
//-----------------------------------------------------------------------------
void RadioButton::GetSettings(KeyValues *outResourceData)
{
ToggleButton::GetSettings(outResourceData);
outResourceData->SetInt("SubTabPosition", _subTabPosition);
outResourceData->SetInt("TabPosition", GetRadioTabPosition());
}
//-----------------------------------------------------------------------------
// Purpose: Describe editing details
//-----------------------------------------------------------------------------
const char *RadioButton::GetDescription( void )
{
static char buf[1024];
Q_snprintf(buf, sizeof(buf), "%s, int SubTabPosition", BaseClass::GetDescription());
return buf;
}
//-----------------------------------------------------------------------------
// Purpose: When a radio button is checked, all other radio buttons
// in the same group become unchecked.
//-----------------------------------------------------------------------------
void RadioButton::OnRadioButtonChecked(int tabPosition)
{
// make sure we're in the same tab group
if (tabPosition != _oldTabPosition)
return;
// wouldn't be sent to us from ourselves, so another radio button has taken over
SetSelected(false);
}
//-----------------------------------------------------------------------------
// Purpose: Draws the selection rectangle
//-----------------------------------------------------------------------------
void RadioButton::Paint()
{
BaseClass::Paint();
/*
if (HasFocus())
{
int tx0, ty0, tx1, ty1;
_textImage->GetPos(tx0, ty0);
_textImage->GetSize(tx1, ty1);
DrawFocusBorder(tx0, ty0, tx0 + tx1, ty0 + ty1);
}
*/
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void RadioButton::DoClick()
{
SetSelected(true);
}
//-----------------------------------------------------------------------------
// Purpose: Handle arrow key movement
//-----------------------------------------------------------------------------
void RadioButton::OnKeyCodeTyped(KeyCode code)
{
switch (code)
{
case KEY_ENTER:
case KEY_SPACE:
{
if (!IsSelected())
{
SetSelected(true);
}
else
{
Panel::OnKeyCodeTyped(code);
}
}
break;
case KEY_DOWN:
case KEY_RIGHT:
{
RadioButton *bestRadio = FindBestRadioButton( DOWN );
if (bestRadio)
{
bestRadio->SetSelected(true);
}
}
break;
case KEY_UP:
case KEY_LEFT:
{
RadioButton *bestRadio = FindBestRadioButton( UP );
if (bestRadio)
{
bestRadio->SetSelected(true);
}
}
break;
default:
BaseClass::OnKeyCodeTyped(code);
break;
}
}
//-----------------------------------------------------------------------------
// Purpose: Find the correct radio button to move to.
// Input : direction - the direction we are moving, up or down.
//-----------------------------------------------------------------------------
RadioButton *RadioButton::FindBestRadioButton(int direction)
{
RadioButton *bestRadio = NULL;
int highestRadio = 0;
Panel *pr = GetParent();
if (pr)
{
// find the radio button to go to next
for (int i = 0; i < pr->GetChildCount(); i++)
{
RadioButton *child = dynamic_cast<RadioButton *>(pr->GetChild(i));
if (child && child->GetRadioTabPosition() == _oldTabPosition)
{
if (child->GetSubTabPosition() == _subTabPosition + direction)
{
bestRadio = child;
break;
}
if ( (child->GetSubTabPosition() == 0) && (direction == DOWN) )
{
bestRadio = child;
continue;
}
else if ( (child->GetSubTabPosition() > highestRadio) && (direction == UP) )
{
bestRadio = child;
highestRadio = bestRadio->GetSubTabPosition();
continue;
}
if (!bestRadio)
{
bestRadio = child;
}
}
}
if (bestRadio)
{
bestRadio->RequestFocus();
}
InvalidateLayout();
Repaint();
}
return bestRadio;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,200 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <vgui_controls/RotatingProgressBar.h>
#include <vgui/IVGui.h>
#include <vgui/ILocalize.h>
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include <KeyValues.h>
#include "mathlib/mathlib.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( RotatingProgressBar );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
RotatingProgressBar::RotatingProgressBar(Panel *parent, const char *panelName) : ProgressBar(parent, panelName)
{
m_flStartRadians = 0;
m_flEndRadians = 0;
m_flLastAngle = 0;
m_nTextureId = -1;
m_pszImageName = NULL;
m_flTickDelay = 30;
ivgui()->AddTickSignal(GetVPanel(), m_flTickDelay );
SetPaintBorderEnabled(false);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
RotatingProgressBar::~RotatingProgressBar()
{
if ( vgui::surface() && m_nTextureId != -1 )
{
vgui::surface()->DestroyTextureID( m_nTextureId );
m_nTextureId = -1;
}
delete [] m_pszImageName;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void RotatingProgressBar::ApplySettings(KeyValues *inResourceData)
{
const char *imageName = inResourceData->GetString("image", "");
if (*imageName)
{
SetImage( imageName );
}
// Find min and max rotations in radians
m_flStartRadians = DEG2RAD(inResourceData->GetFloat( "start_degrees", 0 ) );
m_flEndRadians = DEG2RAD( inResourceData->GetFloat( "end_degrees", 0 ) );
// Start at 0 progress
m_flLastAngle = m_flStartRadians;
// approach speed is specified in degrees per second.
// convert to radians per 1/30th of a second
float flDegressPerSecond = DEG2RAD( inResourceData->GetFloat( "approach_speed", 360.0 ) ); // default is super fast
m_flApproachSpeed = flDegressPerSecond * ( m_flTickDelay / 1000.0f ); // divide by number of frames in a second
m_flRotOriginX = inResourceData->GetFloat( "rot_origin_x_percent", 0.5f );
m_flRotOriginY = inResourceData->GetFloat( "rot_origin_y_percent", 0.5f );
m_flRotatingX = inResourceData->GetFloat( "rotating_x", 0 );
m_flRotatingY = inResourceData->GetFloat( "rotating_y", 0 );
m_flRotatingWide = inResourceData->GetFloat( "rotating_wide", 0 );
m_flRotatingTall = inResourceData->GetFloat( "rotating_tall", 0 );
BaseClass::ApplySettings( inResourceData );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void RotatingProgressBar::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
if ( m_pszImageName && strlen( m_pszImageName ) > 0 )
{
if ( m_nTextureId == -1 )
{
m_nTextureId = surface()->CreateNewTextureID();
}
surface()->DrawSetTextureFile( m_nTextureId, m_pszImageName, true, false);
}
}
//-----------------------------------------------------------------------------
// Purpose: sets an image by file name
//-----------------------------------------------------------------------------
void RotatingProgressBar::SetImage(const char *imageName)
{
if ( m_pszImageName )
{
delete [] m_pszImageName;
m_pszImageName = NULL;
}
const char *pszDir = "vgui/";
int len = Q_strlen(imageName) + 1;
len += strlen(pszDir);
m_pszImageName = new char[ len ];
Q_snprintf( m_pszImageName, len, "%s%s", pszDir, imageName );
InvalidateLayout(false, true); // force applyschemesettings to run
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void RotatingProgressBar::PaintBackground()
{
// No background
}
//-----------------------------------------------------------------------------
// Purpose: Update event when we aren't drawing so we don't get huge sweeps
// when we start drawing it
//-----------------------------------------------------------------------------
void RotatingProgressBar::OnTick( void )
{
float flDesiredAngle = RemapVal( GetProgress(), 0.0, 1.0, m_flStartRadians, m_flEndRadians );
m_flLastAngle = Approach( flDesiredAngle, m_flLastAngle, m_flApproachSpeed );
BaseClass::OnTick();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void RotatingProgressBar::Paint()
{
// we have an image that we rotate based on the progress,
// where '0' is not rotated,'90' is rotated 90 degrees to the right.
// Image is rotated around its center.
// desired rotation is GetProgress() ( 0.0 -> 1.0 ) mapped into
// ( m_flStartDegrees -> m_flEndDegrees )
vgui::surface()->DrawSetTexture( m_nTextureId );
vgui::surface()->DrawSetColor( Color(255,255,255,255) );
int wide, tall;
GetSize( wide, tall );
float mid_x = m_flRotatingX + m_flRotOriginX * m_flRotatingWide;
float mid_y = m_flRotatingY + m_flRotOriginY * m_flRotatingTall;
Vertex_t vert[4];
vert[0].Init( Vector2D( m_flRotatingX, m_flRotatingY ), Vector2D(0,0) );
vert[1].Init( Vector2D( m_flRotatingX+m_flRotatingWide, m_flRotatingY ), Vector2D(1,0) );
vert[2].Init( Vector2D( m_flRotatingX+m_flRotatingWide, m_flRotatingY+m_flRotatingTall ), Vector2D(1,1) );
vert[3].Init( Vector2D( m_flRotatingX, m_flRotatingY+m_flRotatingTall ), Vector2D(0,1) );
float flCosA = cos(m_flLastAngle);
float flSinA = sin(m_flLastAngle);
// rotate each point around (mid_x, mid_y) by flAngle radians
for ( int i=0;i<4;i++ )
{
Vector2D result;
// subtract the (x,y) we're rotating around, we'll add it on at the end.
vert[i].m_Position.x -= mid_x;
vert[i].m_Position.y -= mid_y;
result.x = ( vert[i].m_Position.x * flCosA - vert[i].m_Position.y * flSinA ) + mid_x;
result.y = ( vert[i].m_Position.x * flSinA + vert[i].m_Position.y * flCosA ) + mid_y;
vert[i].m_Position = result;
}
vgui::surface()->DrawTexturedPolygon( 4, vert );
}

View File

@ -0,0 +1,266 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#include <vgui/IBorder.h>
#include <vgui/ISurface.h>
#include <vgui/IScheme.h>
#include <vgui/IBorder.h>
#include <KeyValues.h>
#include <vgui_controls/ScalableImagePanel.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( ScalableImagePanel );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ScalableImagePanel::ScalableImagePanel(Panel *parent, const char *name) : Panel(parent, name)
{
m_iSrcCornerHeight = 0;
m_iSrcCornerWidth = 0;
m_iCornerHeight = 0;
m_iCornerWidth = 0;
m_pszImageName = NULL;
m_pszDrawColorName = NULL;
m_DrawColor = Color(255,255,255,255);
m_flCornerWidthPercent = 0;
m_flCornerHeightPercent = 0;
m_iTextureID = surface()->CreateNewTextureID();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ScalableImagePanel::~ScalableImagePanel()
{
delete [] m_pszImageName;
delete [] m_pszDrawColorName;
if ( vgui::surface() && m_iTextureID != -1 )
{
vgui::surface()->DestroyTextureID( m_iTextureID );
m_iTextureID = -1;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScalableImagePanel::SetImage(const char *imageName)
{
if ( *imageName )
{
char szImage[MAX_PATH];
const char *pszDir = "vgui/";
int len = Q_strlen(imageName) + 1;
len += strlen(pszDir);
Q_snprintf( szImage, len, "%s%s", pszDir, imageName );
if ( m_pszImageName && V_stricmp( szImage, m_pszImageName ) == 0 )
return;
delete [] m_pszImageName;
m_pszImageName = new char[ len ];
Q_strncpy(m_pszImageName, szImage, len );
}
else
{
delete [] m_pszImageName;
m_pszImageName = NULL;
}
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScalableImagePanel::PaintBackground()
{
int wide, tall;
GetSize(wide, tall);
surface()->DrawSetColor( m_DrawColor.r(), m_DrawColor.g(), m_DrawColor.b(), GetAlpha() );
surface()->DrawSetTexture( m_iTextureID );
int x = 0;
int y = 0;
float uvx = 0;
float uvy = 0;
float uvw = 0, uvh = 0;
float drawW, drawH;
int row, col;
for ( row=0;row<3;row++ )
{
x = 0;
uvx = 0;
if ( row == 0 || row == 2 )
{
//uvh - row 0 or 2, is src_corner_height
uvh = m_flCornerHeightPercent;
drawH = m_iCornerHeight;
}
else
{
//uvh - row 1, is tall - ( 2 * src_corner_height ) ( min 0 )
uvh = max( 1.f - 2.f * m_flCornerHeightPercent, 0.0f );
drawH = max( 0, ( tall - 2 * m_iCornerHeight ) );
}
for ( col=0;col<3;col++ )
{
if ( col == 0 || col == 2 )
{
//uvw - col 0 or 2, is src_corner_width
uvw = m_flCornerWidthPercent;
drawW = m_iCornerWidth;
}
else
{
//uvw - col 1, is wide - ( 2 * src_corner_width ) ( min 0 )
uvw = max( 1.f - 2.f * m_flCornerWidthPercent, 0.0f );
drawW = max( 0, ( wide - 2 * m_iCornerWidth ) );
}
Vector2D uv11( uvx, uvy );
Vector2D uv21( uvx+uvw, uvy );
Vector2D uv22( uvx+uvw, uvy+uvh );
Vector2D uv12( uvx, uvy+uvh );
vgui::Vertex_t verts[4];
verts[0].Init( Vector2D( x, y ), uv11 );
verts[1].Init( Vector2D( x+drawW, y ), uv21 );
verts[2].Init( Vector2D( x+drawW, y+drawH ), uv22 );
verts[3].Init( Vector2D( x, y+drawH ), uv12 );
vgui::surface()->DrawTexturedPolygon( 4, verts );
x += drawW;
uvx += uvw;
}
y += drawH;
uvy += uvh;
}
vgui::surface()->DrawSetTexture(0);
}
//-----------------------------------------------------------------------------
// Purpose: Gets control settings for editing
//-----------------------------------------------------------------------------
void ScalableImagePanel::GetSettings(KeyValues *outResourceData)
{
BaseClass::GetSettings(outResourceData);
if (m_pszDrawColorName)
{
outResourceData->SetString("drawcolor", m_pszDrawColorName);
}
outResourceData->SetInt("src_corner_height", m_iSrcCornerHeight);
outResourceData->SetInt("src_corner_width", m_iSrcCornerWidth);
outResourceData->SetInt("draw_corner_height", m_iCornerHeight);
outResourceData->SetInt("draw_corner_width", m_iCornerWidth);
if (m_pszImageName)
{
outResourceData->SetString("image", m_pszImageName);
}
}
//-----------------------------------------------------------------------------
// Purpose: Applies designer settings from res file
//-----------------------------------------------------------------------------
void ScalableImagePanel::ApplySettings(KeyValues *inResourceData)
{
BaseClass::ApplySettings(inResourceData);
delete [] m_pszDrawColorName;
m_pszDrawColorName = NULL;
const char *pszDrawColor = inResourceData->GetString("drawcolor", "");
if (*pszDrawColor)
{
int r = 0, g = 0, b = 0, a = 255;
int len = Q_strlen(pszDrawColor) + 1;
m_pszDrawColorName = new char[ len ];
Q_strncpy( m_pszDrawColorName, pszDrawColor, len );
if (sscanf(pszDrawColor, "%d %d %d %d", &r, &g, &b, &a) >= 3)
{
// it's a direct color
m_DrawColor = Color(r, g, b, a);
}
else
{
IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
m_DrawColor = pScheme->GetColor(pszDrawColor, Color(0, 0, 0, 0));
}
}
m_iSrcCornerHeight = inResourceData->GetInt( "src_corner_height" );
m_iSrcCornerWidth = inResourceData->GetInt( "src_corner_width" );
m_iCornerHeight = inResourceData->GetInt( "draw_corner_height" );
m_iCornerWidth = inResourceData->GetInt( "draw_corner_width" );
if ( IsProportional() )
{
// scale the x and y up to our screen co-ords
m_iCornerHeight = scheme()->GetProportionalScaledValueEx(GetScheme(), m_iCornerHeight);
m_iCornerWidth = scheme()->GetProportionalScaledValueEx(GetScheme(), m_iCornerWidth);
}
const char *imageName = inResourceData->GetString("image", "");
SetImage( imageName );
InvalidateLayout();
}
void ScalableImagePanel::PerformLayout( void )
{
if ( m_pszImageName )
{
surface()->DrawSetTextureFile( m_iTextureID, m_pszImageName, true, false);
}
// get image dimensions, compare to m_iSrcCornerHeight, m_iSrcCornerWidth
int wide,tall;
surface()->DrawGetTextureSize( m_iTextureID, wide, tall );
m_flCornerWidthPercent = ( wide > 0 ) ? ( (float)m_iSrcCornerWidth / (float)wide ) : 0;
m_flCornerHeightPercent = ( tall > 0 ) ? ( (float)m_iSrcCornerHeight / (float)tall ) : 0;
}
//-----------------------------------------------------------------------------
// Purpose: Describes editing details
//-----------------------------------------------------------------------------
const char *ScalableImagePanel::GetDescription()
{
static char buf[1024];
_snprintf(buf, sizeof(buf), "%s string image, int src_corner_height, int src_corner_width, int draw_corner_height, int draw_corner_width", BaseClass::GetDescription());
return buf;
}

View File

@ -0,0 +1,802 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <assert.h>
#include <vgui/IScheme.h>
#include <vgui/ISystem.h>
#include <vgui/IInput.h>
#include <vgui/IImage.h>
#include <KeyValues.h>
#include <vgui_controls/ScrollBar.h>
#include <vgui_controls/ScrollBarSlider.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/ImagePanel.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
namespace
{
enum
{ // scroll bar will scroll a little, then continuous scroll like in windows
SCROLL_BAR_DELAY = 400, // default delay for all scroll bars
SCROLL_BAR_SPEED = 50, // this is how fast the bar scrolls when you hold down the arrow button
SCROLLBAR_DEFAULT_WIDTH = 17,
};
//-----------------------------------------------------------------------------
// Purpose: Scroll bar button-the arrow button that moves the slider up and down.
//-----------------------------------------------------------------------------
class ScrollBarButton : public Button
{
public:
ScrollBarButton(Panel *parent, const char *panelName, const char *text) : Button(parent, panelName, text)
{
SetButtonActivationType(ACTIVATE_ONPRESSED);
SetContentAlignment(Label::a_center);
}
void OnMouseFocusTicked()
{
// pass straight up to parent
CallParentFunction(new KeyValues("MouseFocusTicked"));
}
virtual void ApplySchemeSettings(IScheme *pScheme)
{
Button::ApplySchemeSettings(pScheme);
SetFont(pScheme->GetFont("Marlett", IsProportional() ));
SetDefaultBorder(pScheme->GetBorder("ScrollBarButtonBorder"));
SetDepressedBorder(pScheme->GetBorder("ScrollBarButtonDepressedBorder"));
SetDefaultColor(GetSchemeColor("ScrollBarButton.FgColor", pScheme), GetSchemeColor("ScrollBarButton.BgColor", pScheme));
SetArmedColor(GetSchemeColor("ScrollBarButton.ArmedFgColor", pScheme), GetSchemeColor("ScrollBarButton.ArmedBgColor", pScheme));
SetDepressedColor(GetSchemeColor("ScrollBarButton.DepressedFgColor", pScheme), GetSchemeColor("ScrollBarButton.DepressedBgColor", pScheme));
}
// Don't request focus.
// This will keep cursor focus in main window in text entry windows.
virtual void OnMousePressed(MouseCode code)
{
if (!IsEnabled())
return;
if (!IsMouseClickEnabled(code))
return;
if (IsUseCaptureMouseEnabled())
{
{
SetSelected(true);
Repaint();
}
// lock mouse input to going to this button
input()->SetMouseCapture(GetVPanel());
}
}
virtual void OnMouseReleased(MouseCode code)
{
if (!IsEnabled())
return;
if (!IsMouseClickEnabled(code))
return;
if (IsUseCaptureMouseEnabled())
{
{
SetSelected(false);
Repaint();
}
// lock mouse input to going to this button
input()->SetMouseCapture(NULL);
}
if( input()->GetMouseOver() == GetVPanel() )
{
SetArmed( true );
}
}
};
}
vgui::Panel *ScrollBar_Vertical_Factory()
{
return new ScrollBar(NULL, NULL, true );
}
vgui::Panel *ScrollBar_Horizontal_Factory()
{
return new ScrollBar(NULL, NULL, false );
}
DECLARE_BUILD_FACTORY_CUSTOM_ALIAS( ScrollBar, ScrollBar_Vertical, ScrollBar_Vertical_Factory );
DECLARE_BUILD_FACTORY_CUSTOM_ALIAS( ScrollBar, ScrollBar_Horizontal, ScrollBar_Horizontal_Factory );
// Default is a horizontal one
DECLARE_BUILD_FACTORY_CUSTOM( ScrollBar, ScrollBar_Horizontal_Factory );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ScrollBar::ScrollBar(Panel *parent, const char *panelName, bool vertical) : Panel(parent, panelName)
{
_slider=null;
_button[0]=null;
_button[1]=null;
_scrollDelay = SCROLL_BAR_DELAY;
_respond = true;
m_pUpArrow = NULL;
m_pLine = NULL;
m_pDownArrow = NULL;
m_pBox = NULL;
m_bNoButtons = false;
m_pOverriddenButtons[0] = NULL;
m_pOverriddenButtons[1] = NULL;
if (vertical)
{
// FIXME: proportional changes needed???
SetSlider(new ScrollBarSlider(NULL, "Slider", true));
SetButton(new ScrollBarButton(NULL, "UpButton", "t"), 0);
SetButton(new ScrollBarButton(NULL, "DownButton", "u"), 1);
_button[0]->SetTextInset(0, 1);
_button[1]->SetTextInset(0, -1);
SetSize(SCROLLBAR_DEFAULT_WIDTH, 64);
}
else
{
SetSlider(new ScrollBarSlider(NULL, NULL, false));
SetButton(new ScrollBarButton(NULL, NULL, "w"), 0);
SetButton(new ScrollBarButton(NULL, NULL, "4"), 1);
_button[0]->SetTextInset(0, 0);
_button[1]->SetTextInset(0, 0);
SetSize(64, SCROLLBAR_DEFAULT_WIDTH);
}
Panel::SetPaintBorderEnabled(true);
Panel::SetPaintBackgroundEnabled(false);
Panel::SetPaintEnabled(true);
SetButtonPressedScrollValue(20);
SetBlockDragChaining( true );
Validate();
}
//-----------------------------------------------------------------------------
// Purpose: sets up the width of the scrollbar according to the scheme
//-----------------------------------------------------------------------------
void ScrollBar::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
const char *resourceString = pScheme->GetResourceString("ScrollBar.Wide");
if (resourceString)
{
int value = atoi(resourceString);
if (IsProportional())
{
value = scheme()->GetProportionalScaledValueEx(GetScheme(), value);
}
if (_slider && _slider->IsVertical())
{
// we're vertical, so reset the width
SetSize( value, GetTall() );
}
else
{
// we're horizontal, so the width means the height
SetSize( GetWide(), value );
}
}
UpdateButtonsForImages();
}
//-----------------------------------------------------------------------------
// Purpose: Set the slider's Paint border enabled.
//-----------------------------------------------------------------------------
void ScrollBar::SetPaintBorderEnabled(bool state)
{
if ( _slider )
{
_slider->SetPaintBorderEnabled( state );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBar::SetPaintBackgroundEnabled(bool state)
{
if ( _slider )
{
_slider->SetPaintBackgroundEnabled( state );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBar::SetPaintEnabled(bool state)
{
if ( _slider )
{
_slider->SetPaintEnabled( state );
}
}
//-----------------------------------------------------------------------------
// Purpose: Layout the scroll bar and buttons on screen
//-----------------------------------------------------------------------------
void ScrollBar::PerformLayout()
{
if (_slider)
{
int wide, tall;
GetPaintSize(wide,tall);
if(_slider->IsVertical())
{
if ( m_bNoButtons )
{
_slider->SetBounds(0, 0, wide, tall + 1);
}
else
{
_slider->SetBounds(0, wide, wide, tall-(wide*2)+1);
_button[0]->SetBounds(0,0, wide, wide );
_button[1]->SetBounds(0,tall-wide ,wide, wide );
}
}
else
{
if ( m_bNoButtons )
{
_slider->SetBounds(tall, 0, wide, tall + 1);
}
else
{
_slider->SetBounds(tall, -1, wide-(tall*2)+1, tall + 1 );
_button[0]->SetBounds(0, 0, tall, tall);
_button[1]->SetBounds(wide-tall, 0, tall, tall);
}
}
// Place the images over the appropriate controls
int x,y;
if ( m_pUpArrow )
{
_button[0]->GetBounds( x,y,wide,tall );
m_pUpArrow->SetBounds( x,y,wide,tall );
}
if ( m_pDownArrow )
{
_button[1]->GetBounds( x,y,wide,tall );
m_pDownArrow->SetBounds( x,y,wide,tall );
}
if ( m_pLine )
{
_slider->GetBounds( x,y,wide,tall );
m_pLine->SetBounds( x,y,wide,tall );
}
if ( m_pBox )
{
m_pBox->SetBounds( 0, wide, wide, wide );
}
_slider->MoveToFront();
// after resizing our child, we should remind it to perform a layout
_slider->InvalidateLayout();
UpdateSliderImages();
}
if ( m_bAutoHideButtons )
{
SetScrollbarButtonsVisible( _slider->IsSliderVisible() );
}
// get tooltips to draw
Panel::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Set the value of the scroll bar slider.
//-----------------------------------------------------------------------------
void ScrollBar::SetValue(int value)
{
_slider->SetValue(value);
}
//-----------------------------------------------------------------------------
// Purpose: Get the value of the scroll bar slider.
//-----------------------------------------------------------------------------
int ScrollBar::GetValue()
{
return _slider->GetValue();
}
//-----------------------------------------------------------------------------
// Purpose: Set the range of the scroll bar slider.
// This the range of numbers the slider can scroll through.
//-----------------------------------------------------------------------------
void ScrollBar::SetRange(int min,int max)
{
_slider->SetRange(min,max);
}
//-----------------------------------------------------------------------------
// Purpose: Gets the range of the scroll bar slider.
// This the range of numbers the slider can scroll through.
//-----------------------------------------------------------------------------
void ScrollBar::GetRange(int &min, int &max)
{
_slider->GetRange(min, max);
}
//-----------------------------------------------------------------------------
// Purpose: Send a message when the slider is moved.
// Input : value -
//-----------------------------------------------------------------------------
void ScrollBar::SendSliderMoveMessage(int value)
{
PostActionSignal(new KeyValues("ScrollBarSliderMoved", "position", value));
}
//-----------------------------------------------------------------------------
// Purpose: Called when the Slider is dragged by the user
// Input : value -
//-----------------------------------------------------------------------------
void ScrollBar::OnSliderMoved(int value)
{
SendSliderMoveMessage(value);
UpdateSliderImages();
}
//-----------------------------------------------------------------------------
// Purpose: Check if the scrollbar is vertical (true) or horizontal (false)
//-----------------------------------------------------------------------------
bool ScrollBar::IsVertical()
{
return _slider->IsVertical();
}
//-----------------------------------------------------------------------------
// Purpose: Check if the the scrollbar slider has full range.
// Normally if you have a scroll bar and the range goes from a to b and
// the slider is sized to c, the range will go from a to b-c.
// This makes it so the slider goes from a to b fully.
//-----------------------------------------------------------------------------
bool ScrollBar::HasFullRange()
{
return _slider->HasFullRange();
}
//-----------------------------------------------------------------------------
// Purpose: Setup the indexed scroll bar button with the input params.
//-----------------------------------------------------------------------------
//LEAK: new and old slider will leak
void ScrollBar::SetButton(Button *button, int index)
{
if(_button[index]!=null)
{
_button[index]->SetParent((Panel *)NULL);
}
_button[index]=button;
_button[index]->SetParent(this);
_button[index]->AddActionSignalTarget(this);
_button[index]->SetCommand(new KeyValues("ScrollButtonPressed", "index", index));
Validate();
}
//-----------------------------------------------------------------------------
// Purpose: Return the indexed scroll bar button
//-----------------------------------------------------------------------------
Button* ScrollBar::GetButton(int index)
{
return _button[index];
}
//-----------------------------------------------------------------------------
// Purpose: Set up the slider.
//-----------------------------------------------------------------------------
//LEAK: new and old slider will leak
void ScrollBar::SetSlider(ScrollBarSlider *slider)
{
if(_slider!=null)
{
_slider->SetParent((Panel *)NULL);
}
_slider=slider;
_slider->AddActionSignalTarget(this);
_slider->SetParent(this);
Validate();
}
//-----------------------------------------------------------------------------
// Purpose: Return a pointer to the slider.
//-----------------------------------------------------------------------------
ScrollBarSlider *ScrollBar::GetSlider()
{
return _slider;
}
Button *ScrollBar::GetDepressedButton( int iIndex )
{
if ( iIndex == 0 )
return ( m_pOverriddenButtons[0] ? m_pOverriddenButtons[0] : _button[0] );
return ( m_pOverriddenButtons[1] ? m_pOverriddenButtons[1] : _button[1] );
}
//-----------------------------------------------------------------------------
// Purpose: Scrolls in response to clicking and holding on up or down arrow
// The idea is to have the slider move one step then delay a bit and then
// the bar starts moving at normal speed. This gives a stepping feeling
// to just clicking an arrow once.
//-----------------------------------------------------------------------------
void ScrollBar::OnMouseFocusTicked()
{
int direction = 0;
// top button is down
if ( GetDepressedButton(0)->IsDepressed() )
{
direction = -1;
}
// bottom top button is down
else if (GetDepressedButton(1)->IsDepressed())
{
direction = 1;
}
// a button is down
if ( direction != 0 )
{
RespondToScrollArrow(direction);
if (_scrollDelay < system()->GetTimeMillis())
{
_scrollDelay = system()->GetTimeMillis() + SCROLL_BAR_SPEED;
_respond = true;
}
else
{
_respond = false;
}
}
// a button is not down.
else
{
// if neither button is down keep delay at max
_scrollDelay = system()->GetTimeMillis() + SCROLL_BAR_DELAY;
_respond = true;
}
}
//-----------------------------------------------------------------------------
// Purpose: move scroll bar in response to the first button
// Input: button and direction to move scroll bar when that button is pressed
// direction can only by +/- 1
// Output: whether button is down or not
//-----------------------------------------------------------------------------
void ScrollBar::RespondToScrollArrow(int const direction)
{
if (_respond)
{
int newValue = _slider->GetValue() + (direction * _buttonPressedScrollValue);
_slider->SetValue(newValue);
SendSliderMoveMessage(newValue);
}
}
//-----------------------------------------------------------------------------
// Purpose: Trigger layout changes when the window size is changed.
//-----------------------------------------------------------------------------
void ScrollBar::OnSizeChanged(int wide, int tall)
{
InvalidateLayout();
_slider->InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Set how far the scroll bar slider moves when a scroll bar button is
// pressed.
//-----------------------------------------------------------------------------
void ScrollBar::SetButtonPressedScrollValue(int value)
{
_buttonPressedScrollValue=value;
}
//-----------------------------------------------------------------------------
// Purpose: Set the range of the rangewindow. This is how many
// lines are displayed at one time
// in the window the scroll bar is attached to.
// This also controls the size of the slider, its size is proportional
// to the number of lines displayed / total number of lines.
//-----------------------------------------------------------------------------
void ScrollBar::SetRangeWindow(int rangeWindow)
{
_slider->SetRangeWindow(rangeWindow);
}
//-----------------------------------------------------------------------------
// Purpose: Get the range of the rangewindow. This is how many
// lines are displayed at one time
// in the window the scroll bar is attached to.
// This also controls the size of the slider, its size is proportional
// to the number of lines displayed / total number of lines.
//-----------------------------------------------------------------------------
int ScrollBar::GetRangeWindow()
{
return _slider->GetRangeWindow();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBar::Validate()
{
if ( _slider != null )
{
int buttonOffset = 0;
for( int i=0; i<2; i++ )
{
if( _button[i] != null )
{
if( _button[i]->IsVisible() )
{
if( _slider->IsVertical() )
{
buttonOffset += _button[i]->GetTall();
}
else
{
buttonOffset += _button[i]->GetWide();
}
}
}
}
_slider->SetButtonOffset(buttonOffset);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBar::SetScrollbarButtonsVisible(bool visible)
{
for( int i=0; i<2; i++ )
{
if( _button[i] != null )
{
_button[i]->SetShouldPaint( visible );
_button[i]->SetEnabled( visible );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBar::UseImages( const char *pszUpArrow, const char *pszDownArrow, const char *pszLine, const char *pszBox )
{
if ( pszUpArrow )
{
if ( !m_pUpArrow )
{
m_pUpArrow = new vgui::ImagePanel( this, "UpArrow" );
if ( m_pUpArrow )
{
m_pUpArrow->SetImage( pszUpArrow );
m_pUpArrow->SetShouldScaleImage( true );
m_pUpArrow->SetFgColor( Color( 255, 255, 255, 255 ) );
m_pUpArrow->SetAlpha( 255 );
m_pUpArrow->SetZPos( -1 );
}
}
m_pUpArrow->SetImage( pszUpArrow );
m_pUpArrow->SetRotation( IsVertical() ? ROTATED_UNROTATED : ROTATED_CLOCKWISE_90 );
}
else if ( m_pUpArrow )
{
m_pUpArrow->MarkForDeletion();
m_pUpArrow = NULL;
}
if ( pszDownArrow )
{
if ( !m_pDownArrow )
{
m_pDownArrow = new vgui::ImagePanel( this, "DownArrow" );
if ( m_pDownArrow )
{
m_pDownArrow->SetShouldScaleImage( true );
m_pDownArrow->SetFgColor( Color( 255, 255, 255, 255 ) );
m_pDownArrow->SetAlpha( 255 );
m_pDownArrow->SetZPos( -1 );
}
}
m_pDownArrow->SetImage( pszDownArrow );
m_pDownArrow->SetRotation( IsVertical() ? ROTATED_UNROTATED : ROTATED_CLOCKWISE_90 );
}
else if ( m_pDownArrow )
{
m_pDownArrow->MarkForDeletion();
m_pDownArrow = NULL;
}
if ( pszLine )
{
if ( !m_pLine )
{
m_pLine = new ImagePanel( this, "Line" );
if ( m_pLine )
{
m_pLine->SetShouldScaleImage( true );
m_pLine->SetZPos( -1 );
}
}
m_pLine->SetImage( pszLine );
m_pLine->SetRotation( IsVertical() ? ROTATED_UNROTATED : ROTATED_CLOCKWISE_90 );
}
else if ( m_pLine )
{
m_pLine->MarkForDeletion();
m_pLine = NULL;
}
if ( pszBox )
{
if ( !m_pBox )
{
m_pBox = new ImagePanel( this, "Box" );
if ( m_pBox )
{
m_pBox->SetShouldScaleImage( true );
m_pBox->SetZPos( -1 );
}
}
m_pBox->SetImage( pszBox );
m_pBox->SetRotation( IsVertical() ? ROTATED_UNROTATED : ROTATED_CLOCKWISE_90 );
}
else if ( m_pBox )
{
m_pBox->MarkForDeletion();
m_pBox = NULL;
}
UpdateButtonsForImages();
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBar::UpdateButtonsForImages( void )
{
// Turn off parts of our drawing based on which images we're replacing it with
if ( m_pUpArrow || m_pDownArrow )
{
SetScrollbarButtonsVisible( false );
_button[0]->SetPaintBorderEnabled( false );
_button[1]->SetPaintBorderEnabled( false );
m_bAutoHideButtons = false;
}
if ( m_pLine || m_pBox )
{
SetPaintBackgroundEnabled( false );
SetPaintBorderEnabled( false );
if ( _slider )
{
_slider->SetPaintEnabled( false );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBar::UpdateSliderImages( void )
{
if ( m_pUpArrow && m_pDownArrow )
{
// set the alpha on the up arrow
int nMin, nMax;
GetRange( nMin, nMax );
int nScrollPos = GetValue();
int nRangeWindow = GetRangeWindow();
int nBottom = nMax - nRangeWindow;
if ( nBottom < 0 )
{
nBottom = 0;
}
// set the alpha on the up arrow
int nAlpha = ( nScrollPos - nMin <= 0 ) ? 90 : 255;
m_pUpArrow->SetAlpha( nAlpha );
// set the alpha on the down arrow
nAlpha = ( nScrollPos >= nBottom ) ? 90 : 255;
m_pDownArrow->SetAlpha( nAlpha );
}
if ( m_pLine && m_pBox )
{
ScrollBarSlider *pSlider = GetSlider();
if ( pSlider && pSlider->GetRangeWindow() > 0 )
{
int x, y, w, t, min, max;
m_pLine->GetBounds( x, y, w, t );
// If our slider needs layout, force it to do it now
if ( pSlider->IsLayoutInvalid() )
{
pSlider->InvalidateLayout( true );
}
pSlider->GetNobPos( min, max );
if ( IsVertical() )
{
m_pBox->SetBounds( x, y + min, w, ( max - min ) );
}
else
{
m_pBox->SetBounds( x + min, 0, (max-min), t );
}
}
}
}
void ScrollBar::ApplySettings( KeyValues *pInResourceData )
{
BaseClass::ApplySettings( pInResourceData );
m_bNoButtons = pInResourceData->GetBool( "nobuttons", false );
KeyValues *pSliderKV = pInResourceData->FindKey( "Slider" );
if ( pSliderKV && _slider )
{
_slider->ApplySettings( pSliderKV );
}
KeyValues *pDownButtonKV = pInResourceData->FindKey( "DownButton" );
if ( pDownButtonKV && _button[0] )
{
_button[0]->ApplySettings( pDownButtonKV );
}
KeyValues *pUpButtonKV = pInResourceData->FindKey( "UpButton" );
if ( pUpButtonKV && _button[0] )
{
_button[1]->ApplySettings( pUpButtonKV );
}
}

View File

@ -0,0 +1,606 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#define PROTECTED_THINGS_DISABLE
#include <vgui/IBorder.h>
#include <vgui/IInput.h>
#include <vgui/ISystem.h>
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include <vgui/MouseCode.h>
#include <KeyValues.h>
#include <vgui_controls/ScrollBarSlider.h>
#include <vgui_controls/Controls.h>
#include <math.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// The ScrollBarSlider is the scroll bar nob that moves up and down in through a range.
//-----------------------------------------------------------------------------
ScrollBarSlider::ScrollBarSlider(Panel *parent, const char *panelName, bool vertical) : Panel(parent, panelName)
{
_vertical=vertical;
_dragging=false;
_value=0;
_range[0]=0;
_range[1]=0;
_rangeWindow=0;
_buttonOffset=0;
_ScrollBarSliderBorder=NULL;
RecomputeNobPosFromValue();
SetBlockDragChaining( true );
}
//-----------------------------------------------------------------------------
// Purpose: Set the size of the ScrollBarSlider nob
//-----------------------------------------------------------------------------
void ScrollBarSlider::SetSize(int wide,int tall)
{
BaseClass::SetSize(wide,tall);
RecomputeNobPosFromValue();
}
//-----------------------------------------------------------------------------
// Purpose: Whether the scroll bar is vertical (true) or not (false)
//-----------------------------------------------------------------------------
bool ScrollBarSlider::IsVertical()
{
return _vertical;
}
//-----------------------------------------------------------------------------
// Purpose: Set the ScrollBarSlider value of the nob.
//-----------------------------------------------------------------------------
void ScrollBarSlider::SetValue(int value)
{
int oldValue = _value;
if (value > _range[1] - _rangeWindow)
{
// note our scrolling range must take into acount _rangeWindow
value = _range[1] - _rangeWindow;
}
if (value < _range[0])
{
value = _range[0];
}
_value = value;
RecomputeNobPosFromValue();
if (_value != oldValue)
{
SendScrollBarSliderMovedMessage();
}
}
//-----------------------------------------------------------------------------
// Purpose: Get the ScrollBarSlider value of the nob.
//-----------------------------------------------------------------------------
int ScrollBarSlider::GetValue()
{
return _value;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBarSlider::PerformLayout()
{
RecomputeNobPosFromValue();
BaseClass::PerformLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Given the value of the ScrollBarSlider, adjust the ends of the nob.
//-----------------------------------------------------------------------------
void ScrollBarSlider::RecomputeNobPosFromValue()
{
int wide, tall;
GetPaintSize(wide, tall);
float fwide = (float)( wide - 1 );
float ftall = (float)( tall - 1 );
float frange = (float)(_range[1] -_range[0]);
float fvalue = (float)(_value - _range[0]);
float frangewindow = (float)(_rangeWindow);
float fper = ( frange != frangewindow ) ? fvalue / ( frange-frangewindow ) : 0;
// Msg( "fwide: %f ftall: %f frange: %f fvalue: %f frangewindow: %f fper: %f\n",
// fwide, ftall, frange, fvalue, frangewindow, fper );
if ( frangewindow > 0 )
{
if ( frange <= 0.0 )
{
frange = 1.0;
}
float width, length;
if (_vertical)
{
width = fwide;
length = ftall;
}
else
{
width = ftall;
length = fwide;
}
// our size is proportional to frangewindow/frange
// the scroll bar nob's length reflects the amount of stuff on the screen
// vs the total amount of stuff we could scroll through in window
// so if a window showed half its contents and the other half is hidden the
// scroll bar's length is half the window.
// if everything is on the screen no nob is displayed
// frange is how many 'lines' of stuff we can display
// frangewindow is how many 'lines' are in the display window
// proportion of whole window that is on screen
float proportion = frangewindow / frange;
float fnobsize = length * proportion;
if ( fnobsize < width ) fnobsize = (float)width;
float freepixels = length - fnobsize;
float firstpixel = freepixels * fper;
_nobPos[0] = (int)( firstpixel );
_nobPos[1] = (int)( firstpixel + fnobsize );
if ( _nobPos[1] > length )
{
_nobPos[0] = (int)( length - fnobsize );
_nobPos[1] = (int)length;
}
}
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Get the ScrollBarSlider value using the location of the nob ends.
//-----------------------------------------------------------------------------
void ScrollBarSlider::RecomputeValueFromNobPos()
{
int wide, tall;
GetPaintSize(wide, tall);
float fwide = (float)( wide - 1 );
float ftall = (float)( tall - 1 );
float frange = (float)( _range[1] - _range[0] );
float fvalue = (float)( _value - _range[0] );
float fnob = (float)_nobPos[0];
float frangewindow = (float)(_rangeWindow);
if ( frangewindow > 0 )
{
if ( frange <= 0.0 )
{
frange = 1.0;
}
// set local width and length
float width, length;
if ( _vertical )
{
width = fwide;
length = ftall;
}
else
{
width = ftall;
length = fwide;
}
// calculate the size of the nob
float proportion = frangewindow / frange;
float fnobsize = length * proportion;
if ( fnobsize < width )
{
fnobsize = width;
}
// Our scroll bar actually doesnt scroll through all frange lines in the truerange, we
// actually only scroll through frange-frangewindow number of lines so we must take that
// into account when we calculate the value
// convert to our local size system
// Make sure we don't divide by zero
if ( length - fnobsize == 0 )
{
fvalue = 0.0f;
}
else
{
fvalue = (frange - frangewindow) * ( fnob / ( length - fnobsize ) );
}
}
// check to see if we should just snap to the bottom
if (fabs(fvalue + _rangeWindow - _range[1]) < (0.01f * frange))
{
// snap to the end
_value = _range[1] - _rangeWindow;
}
else
{
// Take care of rounding issues.
_value = (int)( fvalue + _range[0] + 0.5);
}
// Clamp final result
_value = ( _value < (_range[1] - _rangeWindow) ) ? _value : (_range[1] - _rangeWindow);
if (_value < _range[0])
{
_value = _range[0];
}
}
//-----------------------------------------------------------------------------
// Purpose: Check if the ScrollBarSlider can move through one or more pixels per
// unit of its range.
//-----------------------------------------------------------------------------
bool ScrollBarSlider::HasFullRange()
{
int wide, tall;
GetPaintSize(wide, tall);
float frangewindow = (float)(_rangeWindow);
float checkAgainst = 0;
if(_vertical)
{
checkAgainst = (float)tall;
}
else
{
checkAgainst = (float)wide;
}
if ( frangewindow > 0 )
{
if( frangewindow <= ( checkAgainst + _buttonOffset ) )
{
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Inform other watchers that the ScrollBarSlider was moved
//-----------------------------------------------------------------------------
void ScrollBarSlider::SendScrollBarSliderMovedMessage()
{
// send a changed message
PostActionSignal(new KeyValues("ScrollBarSliderMoved", "position", _value));
}
//-----------------------------------------------------------------------------
// Purpose: Return true if this slider is actually drawing itself
//-----------------------------------------------------------------------------
bool ScrollBarSlider::IsSliderVisible( void )
{
int itemRange = _range[1] - _range[0];
// Don't draw nob, no items in list
if ( itemRange <= 0 )
return false ;
// Not enough range
if ( itemRange <= _rangeWindow )
return false;
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBarSlider::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetFgColor(GetSchemeColor("ScrollBarSlider.FgColor", pScheme));
SetBgColor(GetSchemeColor("ScrollBarSlider.BgColor", pScheme));
IBorder *newBorder = pScheme->GetBorder("ScrollBarSliderBorder");
if ( newBorder )
{
_ScrollBarSliderBorder = newBorder;
}
else
{
_ScrollBarSliderBorder = pScheme->GetBorder("ButtonBorder");
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBarSlider::ApplySettings( KeyValues *pInResourceData )
{
BaseClass::ApplySettings( pInResourceData );
const char *pButtonBorderName = pInResourceData->GetString( "ButtonBorder", NULL );
if ( pButtonBorderName )
{
_ScrollBarSliderBorder = vgui::scheme()->GetIScheme( GetScheme() )->GetBorder( pButtonBorderName );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBarSlider::Paint()
{
int wide,tall;
GetPaintSize(wide,tall);
if ( !IsSliderVisible() )
return;
Color col = GetFgColor();
surface()->DrawSetColor(col);
if (_vertical)
{
if ( GetPaintBackgroundType() == 2 )
{
DrawBox( 1, _nobPos[0], wide - 2, _nobPos[1] - _nobPos[0], col, 1.0f );
}
else
{
// Nob
surface()->DrawFilledRect(1, _nobPos[0], wide - 2, _nobPos[1]);
}
// border
if (_ScrollBarSliderBorder)
{
_ScrollBarSliderBorder->Paint(0, _nobPos[0], wide, _nobPos[1]);
}
}
else
{
// horizontal nob
surface()->DrawFilledRect(_nobPos[0], 1, _nobPos[1], tall - 2 );
// border
if (_ScrollBarSliderBorder)
{
_ScrollBarSliderBorder->Paint(_nobPos[0] - 1, 1, _nobPos[1], tall );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBarSlider::PaintBackground()
{
// BaseClass::PaintBackground();
int wide,tall;
GetPaintSize(wide,tall);
surface()->DrawSetColor(GetBgColor());
surface()->DrawFilledRect(0, 0, wide-1, tall-1);
}
//-----------------------------------------------------------------------------
// Purpose: Set the range of the ScrollBarSlider
//-----------------------------------------------------------------------------
void ScrollBarSlider::SetRange(int min,int max)
{
if(max<min)
{
max=min;
}
if(min>max)
{
min=max;
}
_range[0]=min;
_range[1]=max;
// update the value (forces it within the range)
SetValue( _value );
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Get the range values of the ScrollBarSlider
//-----------------------------------------------------------------------------
void ScrollBarSlider::GetRange(int& min,int& max)
{
min=_range[0];
max=_range[1];
}
//-----------------------------------------------------------------------------
// Purpose: Respond to cursor movements, we only care about clicking and dragging
//-----------------------------------------------------------------------------
void ScrollBarSlider::OnCursorMoved(int x,int y)
{
if (!_dragging)
{
return;
}
// input()->GetCursorPos(x, y);
// ScreenToLocal(x, y);
int wide, tall;
GetPaintSize(wide, tall);
if (_vertical)
{
_nobPos[0] = _nobDragStartPos[0] + (y - _dragStartPos[1]);
_nobPos[1] = _nobDragStartPos[1] + (y - _dragStartPos[1]);
if (_nobPos[1] > tall)
{
_nobPos[0] = tall - (_nobPos[1] - _nobPos[0]);
_nobPos[1] = tall;
SetValue( _range[1] - _rangeWindow );
}
}
else
{
_nobPos[0] = _nobDragStartPos[0] + (x - _dragStartPos[0]);
_nobPos[1] = _nobDragStartPos[1] + (x - _dragStartPos[0]);
if (_nobPos[1] > wide)
{
_nobPos[0] = wide - (_nobPos[1] - _nobPos[0]);
_nobPos[1] = wide;
}
}
if (_nobPos[0] < 0)
{
_nobPos[1] = _nobPos[1] - _nobPos[0];
_nobPos[0] = 0;
SetValue(0);
}
InvalidateLayout(); // not invalidatelayout - because it won't draw while we're scrolling the slider
RecomputeValueFromNobPos();
// Repaint();
SendScrollBarSliderMovedMessage();
}
//-----------------------------------------------------------------------------
// Purpose: Respond to mouse clicks on the ScrollBarSlider
//-----------------------------------------------------------------------------
void ScrollBarSlider::OnMousePressed(MouseCode code)
{
int x,y;
input()->GetCursorPos(x,y);
ScreenToLocal(x,y);
if (_vertical)
{
if ((y >= _nobPos[0]) && (y < _nobPos[1]))
{
_dragging = true;
input()->SetMouseCapture(GetVPanel());
_nobDragStartPos[0] = _nobPos[0];
_nobDragStartPos[1] = _nobPos[1];
_dragStartPos[0] = x;
_dragStartPos[1] = y;
}
else if (y < _nobPos[0])
{
// jump the bar up by the range window
int val = GetValue();
val -= _rangeWindow;
SetValue(val);
}
else if (y >= _nobPos[1])
{
// jump the bar down by the range window
int val = GetValue();
val += _rangeWindow;
SetValue(val);
}
}
else
{
if((x >= _nobPos[0]) && (x < _nobPos[1]))
{
_dragging = true;
input()->SetMouseCapture(GetVPanel());
_nobDragStartPos[0] = _nobPos[0];
_nobDragStartPos[1] = _nobPos[1];
_dragStartPos[0] = x;
_dragStartPos[1] = y;
}
else if (x < _nobPos[0])
{
// jump the bar up by the range window
int val = GetValue();
val -= _rangeWindow;
SetValue(val);
}
else if (x >= _nobPos[1])
{
// jump the bar down by the range window
int val = GetValue();
val += _rangeWindow;
SetValue(val);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Treat double clicks as single clicks
//-----------------------------------------------------------------------------
void ScrollBarSlider::OnMouseDoublePressed(MouseCode code)
{
OnMousePressed(code);
}
//-----------------------------------------------------------------------------
// Purpose: Stop looking for mouse events when mouse is up.
//-----------------------------------------------------------------------------
void ScrollBarSlider::OnMouseReleased(MouseCode code)
{
_dragging = false;
input()->SetMouseCapture(null);
}
//-----------------------------------------------------------------------------
// Purpose: Get the position of the ends of the ScrollBarSlider.
//-----------------------------------------------------------------------------
void ScrollBarSlider::GetNobPos(int& min, int& max)
{
min=_nobPos[0];
max=_nobPos[1];
}
//-----------------------------------------------------------------------------
// Purpose: Set the number of lines visible in the window the ScrollBarSlider is attached to
//-----------------------------------------------------------------------------
void ScrollBarSlider::SetRangeWindow(int rangeWindow)
{
_rangeWindow = rangeWindow;
}
//-----------------------------------------------------------------------------
// Purpose: Get the number of lines visible in the window the ScrollBarSlider is attached to
//-----------------------------------------------------------------------------
int ScrollBarSlider::GetRangeWindow()
{
return _rangeWindow;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ScrollBarSlider::SetButtonOffset(int buttonOffset)
{
_buttonOffset = buttonOffset;
}

View File

@ -0,0 +1,86 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "vgui_controls/ScrollableEditablePanel.h"
#include "vgui_controls/ScrollBar.h"
#include "vgui_controls/ScrollBarSlider.h"
#include "vgui_controls/Button.h"
#include "KeyValues.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
using namespace vgui;
ScrollableEditablePanel::ScrollableEditablePanel( vgui::Panel *pParent, vgui::EditablePanel *pChild, const char *pName ) :
BaseClass( pParent, pName )
{
m_pChild = pChild;
m_pChild->SetParent( this );
m_pScrollBar = new vgui::ScrollBar( this, "VerticalScrollBar", true );
m_pScrollBar->SetWide( 16 );
m_pScrollBar->SetAutoResize( PIN_TOPRIGHT, AUTORESIZE_DOWN, 0, 0, -16, 0 );
m_pScrollBar->AddActionSignalTarget( this );
}
void ScrollableEditablePanel::ApplySettings( KeyValues *pInResourceData )
{
BaseClass::ApplySettings( pInResourceData );
KeyValues *pScrollbarKV = pInResourceData->FindKey( "Scrollbar" );
if ( pScrollbarKV )
{
m_pScrollBar->ApplySettings( pScrollbarKV );
}
}
void ScrollableEditablePanel::PerformLayout()
{
BaseClass::PerformLayout();
m_pChild->SetWide( GetWide() - m_pScrollBar->GetWide() );
m_pScrollBar->SetRange( 0, m_pChild->GetTall() );
m_pScrollBar->SetRangeWindow( GetTall() );
if ( m_pScrollBar->GetSlider() )
{
m_pScrollBar->GetSlider()->SetFgColor( GetFgColor() );
}
if ( m_pScrollBar->GetButton(0) )
{
m_pScrollBar->GetButton(0)->SetFgColor( GetFgColor() );
}
if ( m_pScrollBar->GetButton(1) )
{
m_pScrollBar->GetButton(1)->SetFgColor( GetFgColor() );
}
}
//-----------------------------------------------------------------------------
// Called when the scroll bar moves
//-----------------------------------------------------------------------------
void ScrollableEditablePanel::OnScrollBarSliderMoved()
{
InvalidateLayout();
int nScrollAmount = m_pScrollBar->GetValue();
m_pChild->SetPos( 0, -nScrollAmount );
}
//-----------------------------------------------------------------------------
// respond to mouse wheel events
//-----------------------------------------------------------------------------
void ScrollableEditablePanel::OnMouseWheeled(int delta)
{
int val = m_pScrollBar->GetValue();
val -= (delta * 50);
m_pScrollBar->SetValue( val );
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,954 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#define PROTECTED_THINGS_DISABLE
#include <vgui/MouseCode.h>
#include <KeyValues.h>
#include <vgui/IBorder.h>
#include <vgui/IInput.h>
#include <vgui/ISystem.h>
#include <vgui/IScheme.h>
#include <vgui/ISurface.h>
#include <vgui/ILocalize.h>
#include <vgui_controls/Slider.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/TextImage.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( Slider );
static const float NOB_SIZE = 8.0f;
//-----------------------------------------------------------------------------
// Purpose: Create a slider bar with ticks underneath it
//-----------------------------------------------------------------------------
Slider::Slider(Panel *parent, const char *panelName ) : BaseClass(parent, panelName)
{
m_bIsDragOnRepositionNob = false;
_dragging = false;
_value = 0;
_range[0] = 0;
_range[1] = 0;
_buttonOffset = 0;
_sliderBorder = NULL;
_insetBorder = NULL;
m_nNumTicks = 10;
_leftCaption = NULL;
_rightCaption = NULL;
_subrange[ 0 ] = 0;
_subrange[ 1 ] = 0;
m_bUseSubRange = false;
m_bInverted = false;
SetThumbWidth( 8 );
RecomputeNobPosFromValue();
AddActionSignalTarget(this);
SetBlockDragChaining( true );
}
// This allows the slider to behave like it's larger than what's actually being drawn
//-----------------------------------------------------------------------------
// Purpose:
// Input : bEnable -
// 0 -
// 100 -
//-----------------------------------------------------------------------------
void Slider::SetSliderThumbSubRange( bool bEnable, int nMin /*= 0*/, int nMax /*= 100*/ )
{
m_bUseSubRange = bEnable;
_subrange[ 0 ] = nMin;
_subrange[ 1 ] = nMax;
}
//-----------------------------------------------------------------------------
// Purpose: Set the size of the slider bar.
// Warning less than 30 pixels tall and everything probably won't fit.
//-----------------------------------------------------------------------------
void Slider::OnSizeChanged(int wide,int tall)
{
BaseClass::OnSizeChanged(wide,tall);
RecomputeNobPosFromValue();
}
//-----------------------------------------------------------------------------
// Purpose: Set the value of the slider to one of the ticks.
//-----------------------------------------------------------------------------
void Slider::SetValue(int value, bool bTriggerChangeMessage)
{
int oldValue=_value;
if ( _range[0] < _range[1] )
{
if(value<_range[0])
{
value=_range[0];
}
if(value>_range[1])
{
value=_range[1];
}
}
else
{
if(value<_range[1])
{
value=_range[1];
}
if(value>_range[0])
{
value=_range[0];
}
}
_value = value;
RecomputeNobPosFromValue();
if (_value != oldValue && bTriggerChangeMessage)
{
SendSliderMovedMessage();
}
}
//-----------------------------------------------------------------------------
// Purpose: Return the value of the slider
//-----------------------------------------------------------------------------
int Slider::GetValue()
{
return _value;
}
//-----------------------------------------------------------------------------
// Purpose: Layout the slider before drawing it on screen.
//-----------------------------------------------------------------------------
void Slider::PerformLayout()
{
BaseClass::PerformLayout();
RecomputeNobPosFromValue();
if (_leftCaption)
{
_leftCaption->ResizeImageToContent();
}
if (_rightCaption)
{
_rightCaption->ResizeImageToContent();
}
}
//-----------------------------------------------------------------------------
// Purpose: Move the nob on the slider in response to changing its value.
//-----------------------------------------------------------------------------
void Slider::RecomputeNobPosFromValue()
{
//int wide,tall;
//GetPaintSize(wide,tall);
int x, y, wide, tall;
GetTrackRect( x, y, wide, tall );
float usevalue = _value;
int *userange = &_range[ 0 ];
if ( m_bUseSubRange )
{
userange = &_subrange[ 0 ];
usevalue = clamp( _value, _subrange[ 0 ], _subrange[ 1 ] );
}
float fwide=(float)wide;
float frange=(float)(userange[1] -userange[0]);
float fvalue=(float)(usevalue -userange[0]);
float fper = (frange != 0.0f) ? fvalue / frange : 0.0f;
if ( m_bInverted )
fper = 1.0f - fper;
float freepixels = fwide - _nobSize;
float leftpixel = (float)x;
float firstpixel = leftpixel + freepixels * fper + 0.5f;
_nobPos[0]=(int)( firstpixel );
_nobPos[1]=(int)( firstpixel + _nobSize );
int rightEdge = x + wide;
if(_nobPos[1]> rightEdge )
{
_nobPos[0]=rightEdge-((int)_nobSize);
_nobPos[1]=rightEdge;
}
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Sync the slider's value up with the nob's position.
//-----------------------------------------------------------------------------
void Slider::RecomputeValueFromNobPos()
{
int value = EstimateValueAtPos( _nobPos[ 0 ], 0 );
SetValue( value );
}
int Slider::EstimateValueAtPos( int localMouseX, int /*localMouseY*/ )
{
int x, y, wide, tall;
GetTrackRect( x, y, wide, tall );
int *userange = &_range[ 0 ];
if ( m_bUseSubRange )
{
userange = &_subrange[ 0 ];
}
float fwide = (float)wide;
float fvalue = (float)( _value - userange[0] );
float fnob = (float)( localMouseX - x );
float freepixels = fwide - _nobSize;
// Map into reduced range
fvalue = freepixels != 0.0f ? fnob / freepixels : 0.0f;
return (int) (RemapVal( fvalue, 0.0, 1.0, userange[0], userange[1] ));
}
void Slider::SetInverted( bool bInverted )
{
m_bInverted = bInverted;
}
//-----------------------------------------------------------------------------
// Purpose: Send a message to interested parties when the slider moves
//-----------------------------------------------------------------------------
void Slider::SendSliderMovedMessage()
{
// send a changed message
KeyValues *pParams = new KeyValues("SliderMoved", "position", _value);
pParams->SetPtr( "panel", this );
PostActionSignal( pParams );
}
//-----------------------------------------------------------------------------
// Purpose: Send a message to interested parties when the user begins dragging the slider
//-----------------------------------------------------------------------------
void Slider::SendSliderDragStartMessage()
{
// send a message
KeyValues *pParams = new KeyValues("SliderDragStart", "position", _value);
pParams->SetPtr( "panel", this );
PostActionSignal( pParams );
}
//-----------------------------------------------------------------------------
// Purpose: Send a message to interested parties when the user ends dragging the slider
//-----------------------------------------------------------------------------
void Slider::SendSliderDragEndMessage()
{
// send a message
KeyValues *pParams = new KeyValues("SliderDragEnd", "position", _value);
pParams->SetPtr( "panel", this );
PostActionSignal( pParams );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Slider::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetFgColor(GetSchemeColor("Slider.NobColor", pScheme));
// this line is useful for debugging
//SetBgColor(GetSchemeColor("0 0 0 255"));
m_TickColor = pScheme->GetColor( "Slider.TextColor", GetFgColor() );
m_TrackColor = pScheme->GetColor( "Slider.TrackColor", GetFgColor() );
#ifdef _X360
m_DepressedBgColor = GetSchemeColor("Slider.NobFocusColor", pScheme);
#endif
m_DisabledTextColor1 = pScheme->GetColor( "Slider.DisabledTextColor1", GetFgColor() );
m_DisabledTextColor2 = pScheme->GetColor( "Slider.DisabledTextColor2", GetFgColor() );
_sliderBorder = pScheme->GetBorder("ButtonBorder");
_insetBorder = pScheme->GetBorder("ButtonDepressedBorder");
if ( _leftCaption )
{
_leftCaption->SetFont(pScheme->GetFont("DefaultVerySmall", IsProportional() ));
}
if ( _rightCaption )
{
_rightCaption->SetFont(pScheme->GetFont("DefaultVerySmall", IsProportional() ));
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Slider::GetSettings(KeyValues *outResourceData)
{
BaseClass::GetSettings(outResourceData);
char buf[256];
if (_leftCaption)
{
_leftCaption->GetUnlocalizedText(buf, sizeof(buf));
outResourceData->SetString("leftText", buf);
}
if (_rightCaption)
{
_rightCaption->GetUnlocalizedText(buf, sizeof(buf));
outResourceData->SetString("rightText", buf);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Slider::ApplySettings(KeyValues *inResourceData)
{
BaseClass::ApplySettings(inResourceData);
const char *left = inResourceData->GetString("leftText", NULL);
const char *right = inResourceData->GetString("rightText", NULL);
int thumbWidth = inResourceData->GetInt("thumbwidth", 0);
if (thumbWidth != 0)
{
SetThumbWidth(thumbWidth);
}
SetTickCaptions(left, right);
int nNumTicks = inResourceData->GetInt( "numTicks", -1 );
if ( nNumTicks >= 0 )
{
SetNumTicks( nNumTicks );
}
int nCurrentRange[2];
GetRange( nCurrentRange[0], nCurrentRange[1] );
KeyValues *pRangeMin = inResourceData->FindKey( "rangeMin", false );
KeyValues *pRangeMax = inResourceData->FindKey( "rangeMax", false );
bool bDoClamp = false;
if ( pRangeMin )
{
_range[0] = inResourceData->GetInt( "rangeMin" );
bDoClamp = true;
}
if ( pRangeMax )
{
_range[1] = inResourceData->GetInt( "rangeMax" );
bDoClamp = true;
}
if ( bDoClamp )
{
ClampRange();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *Slider::GetDescription()
{
static char buf[1024];
Q_snprintf(buf, sizeof(buf), "%s, string leftText, string rightText", BaseClass::GetDescription());
return buf;
}
//-----------------------------------------------------------------------------
// Purpose: Get the rectangle to draw the slider track in.
//-----------------------------------------------------------------------------
void Slider::GetTrackRect( int& x, int& y, int& w, int& h )
{
int wide, tall;
GetPaintSize( wide, tall );
x = 0;
y = 8;
w = wide - (int)_nobSize;
h = 4;
}
//-----------------------------------------------------------------------------
// Purpose: Draw everything on screen
//-----------------------------------------------------------------------------
void Slider::Paint()
{
DrawTicks();
DrawTickLabels();
// Draw nob last so it draws over ticks.
DrawNob();
}
//-----------------------------------------------------------------------------
// Purpose: Draw the ticks below the slider.
//-----------------------------------------------------------------------------
void Slider::DrawTicks()
{
int x, y;
int wide,tall;
GetTrackRect( x, y, wide, tall );
// Figure out how to draw the ticks
// GetPaintSize( wide, tall );
float fwide = (float)wide;
float freepixels = fwide - _nobSize;
float leftpixel = _nobSize / 2.0f;
float pixelspertick = freepixels / ( m_nNumTicks );
y += (int)_nobSize;
int tickHeight = 5;
if (IsEnabled())
{
surface()->DrawSetColor( m_TickColor ); //vgui::Color( 127, 140, 127, 255 ) );
for ( int i = 0; i <= m_nNumTicks; i++ )
{
int xpos = (int)( leftpixel + i * pixelspertick );
surface()->DrawFilledRect( xpos, y, xpos + 1, y + tickHeight );
}
}
else
{
surface()->DrawSetColor( m_DisabledTextColor1 ); //vgui::Color( 127, 140, 127, 255 ) );
for ( int i = 0; i <= m_nNumTicks; i++ )
{
int xpos = (int)( leftpixel + i * pixelspertick );
surface()->DrawFilledRect( xpos+1, y+1, xpos + 2, y + tickHeight + 1 );
}
surface()->DrawSetColor( m_DisabledTextColor2 ); //vgui::Color( 127, 140, 127, 255 ) );
for ( int i = 0; i <= m_nNumTicks; i++ )
{
int xpos = (int)( leftpixel + i * pixelspertick );
surface()->DrawFilledRect( xpos, y, xpos + 1, y + tickHeight );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Draw Tick labels under the ticks.
//-----------------------------------------------------------------------------
void Slider::DrawTickLabels()
{
int x, y;
int wide,tall;
GetTrackRect( x, y, wide, tall );
// Figure out how to draw the ticks
// GetPaintSize( wide, tall );
y += (int)NOB_SIZE + 4;
// Draw Start and end range values
if (IsEnabled())
surface()->DrawSetTextColor( m_TickColor ); //vgui::Color( 127, 140, 127, 255 ) );
else
surface()->DrawSetTextColor( m_DisabledTextColor1 ); //vgui::Color( 127, 140, 127, 255 ) );
if ( _leftCaption != NULL )
{
_leftCaption->SetPos(0, y);
if (IsEnabled())
{
_leftCaption->SetColor( m_TickColor );
}
else
{
_leftCaption->SetColor( m_DisabledTextColor1 );
}
_leftCaption->Paint();
}
if ( _rightCaption != NULL)
{
int rwide, rtall;
_rightCaption->GetSize(rwide, rtall);
_rightCaption->SetPos((int)(wide - rwide) , y);
if (IsEnabled())
{
_rightCaption->SetColor( m_TickColor );
}
else
{
_rightCaption->SetColor( m_DisabledTextColor1 );
}
_rightCaption->Paint();
}
}
//-----------------------------------------------------------------------------
// Purpose: Draw the nob part of the slider.
//-----------------------------------------------------------------------------
void Slider::DrawNob()
{
// horizontal nob
int x, y;
int wide,tall;
GetTrackRect( x, y, wide, tall );
Color col = GetFgColor();
#ifdef _X360
if(HasFocus())
{
col = m_DepressedBgColor;
}
#endif
surface()->DrawSetColor(col);
int nobheight = 16;
surface()->DrawFilledRect(
_nobPos[0],
y + tall / 2 - nobheight / 2,
_nobPos[1],
y + tall / 2 + nobheight / 2);
// border
if (_sliderBorder)
{
_sliderBorder->Paint(
_nobPos[0],
y + tall / 2 - nobheight / 2,
_nobPos[1],
y + tall / 2 + nobheight / 2);
}
}
//-----------------------------------------------------------------------------
// Purpose: Set the text labels of the Start and end ticks.
//-----------------------------------------------------------------------------
void Slider::SetTickCaptions( const char *left, const char *right )
{
if (left)
{
if (_leftCaption)
{
_leftCaption->SetText(left);
}
else
{
_leftCaption = new TextImage(left);
}
}
if (right)
{
if (_rightCaption)
{
_rightCaption->SetText(right);
}
else
{
_rightCaption = new TextImage(right);
}
}
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Set the text labels of the Start and end ticks.
//-----------------------------------------------------------------------------
void Slider::SetTickCaptions( const wchar_t *left, const wchar_t *right )
{
if (left)
{
if (_leftCaption)
{
_leftCaption->SetText(left);
}
else
{
_leftCaption = new TextImage(left);
}
}
if (right)
{
if (_rightCaption)
{
_rightCaption->SetText(right);
}
else
{
_rightCaption = new TextImage(right);
}
}
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: Draw the slider track
//-----------------------------------------------------------------------------
void Slider::PaintBackground()
{
BaseClass::PaintBackground();
int x, y;
int wide,tall;
GetTrackRect( x, y, wide, tall );
surface()->DrawSetColor( m_TrackColor );
surface()->DrawFilledRect( x, y, x + wide, y + tall );
if (_insetBorder)
{
_insetBorder->Paint( x, y, x + wide, y + tall );
}
}
//-----------------------------------------------------------------------------
// Purpose: Set the range of the slider.
//-----------------------------------------------------------------------------
void Slider::SetRange(int min,int max)
{
_range[0]=min;
_range[1]=max;
ClampRange();
}
//-----------------------------------------------------------------------------
// Purpose: Sanity check and clamp the range if necessary.
//-----------------------------------------------------------------------------
void Slider::ClampRange()
{
if ( _range[0] < _range[1] )
{
if(_value<_range[0])
{
SetValue( _range[0], false );
}
else if( _value>_range[1])
{
SetValue( _range[1], false );
}
}
else
{
if(_value<_range[1])
{
SetValue( _range[1], false );
}
else if( _value>_range[0])
{
SetValue( _range[0], false );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Get the max and min values of the slider
//-----------------------------------------------------------------------------
void Slider::GetRange(int& min,int& max)
{
min=_range[0];
max=_range[1];
}
//-----------------------------------------------------------------------------
// Purpose: Respond when the cursor is moved in our window if we are clicking
// and dragging.
//-----------------------------------------------------------------------------
void Slider::OnCursorMoved(int x,int y)
{
if(!_dragging)
{
return;
}
// input()->GetCursorPos(x,y);
input()->GetCursorPosition( x, y );
ScreenToLocal(x,y);
// int wide,tall;
// GetPaintSize(wide,tall);
int _x, _y, wide, tall;
GetTrackRect( _x, _y, wide, tall );
_nobPos[0]=_nobDragStartPos[0]+(x-_dragStartPos[0]);
_nobPos[1]=_nobDragStartPos[1]+(x-_dragStartPos[0]);
int rightEdge = _x +wide;
int unclamped = _nobPos[ 0 ];
if(_nobPos[1]>rightEdge)
{
_nobPos[0]=rightEdge-(_nobPos[1]-_nobPos[0]);
_nobPos[1]=rightEdge;
}
if(_nobPos[0]<_x)
{
int offset = _x - _nobPos[0];
_nobPos[1]=_nobPos[1]-offset;
_nobPos[0]=0;
}
int value = EstimateValueAtPos( unclamped, 0 );
SetValue( value );
// RecomputeValueFromNobPos();
Repaint();
SendSliderMovedMessage();
}
//-----------------------------------------------------------------------------
// Purpose: If you click on the slider outside of the nob, the nob jumps
// to the click position, and if this setting is enabled, the nob
// is then draggable from the new position until the mouse is released
// Input : state -
//-----------------------------------------------------------------------------
void Slider::SetDragOnRepositionNob( bool state )
{
m_bIsDragOnRepositionNob = state;
}
bool Slider::IsDragOnRepositionNob() const
{
return m_bIsDragOnRepositionNob;
}
bool Slider::IsDragged( void ) const
{
return _dragging;
}
//-----------------------------------------------------------------------------
// Purpose: Respond to mouse presses. Trigger Record staring positon.
//-----------------------------------------------------------------------------
void Slider::OnMousePressed(MouseCode code)
{
int x,y;
if (!IsEnabled())
return;
// input()->GetCursorPos(x,y);
input()->GetCursorPosition( x, y );
ScreenToLocal(x,y);
RequestFocus();
bool startdragging = false, bPostDragStartSignal = false;
if ((x >= _nobPos[0]) && (x < _nobPos[1]))
{
startdragging = true;
bPostDragStartSignal = true;
}
else
{
// we clicked elsewhere on the slider; move the nob to that position
int min, max;
GetRange(min, max);
if ( m_bUseSubRange )
{
min = _subrange[ 0 ];
max = _subrange[ 1 ];
}
// int wide = GetWide();
int _x, _y, wide, tall;
GetTrackRect( _x, _y, wide, tall );
if ( wide > 0 )
{
float frange = ( float )( max - min );
float clickFrac = clamp( ( float )( x - _x ) / (float)( wide - 1 ), 0.0f, 1.0f );
float value = (float)min + clickFrac * frange;
startdragging = IsDragOnRepositionNob();
if ( startdragging )
{
_dragging = true; // Required when as
SendSliderDragStartMessage();
}
SetValue( ( int )( value + 0.5f ) );
}
}
if ( startdragging )
{
// drag the nob
_dragging = true;
input()->SetMouseCapture(GetVPanel());
_nobDragStartPos[0] = _nobPos[0];
_nobDragStartPos[1] = _nobPos[1];
_dragStartPos[0] = x;
_dragStartPos[1] = y;
}
if ( bPostDragStartSignal )
SendSliderDragStartMessage();
}
//-----------------------------------------------------------------------------
// Purpose: Just handle double presses like mouse presses
//-----------------------------------------------------------------------------
void Slider::OnMouseDoublePressed(MouseCode code)
{
OnMousePressed(code);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
#ifdef _X360
void Slider::OnKeyCodePressed(KeyCode code)
{
switch ( GetBaseButtonCode( code ) )
{
case KEY_XBUTTON_LEFT:
case KEY_XSTICK1_LEFT:
case KEY_XSTICK2_LEFT:
SetValue(GetValue() - 1);
break;
case KEY_XBUTTON_RIGHT:
case KEY_XSTICK1_RIGHT:
case KEY_XSTICK2_RIGHT:
SetValue(GetValue() + 1);
break;
default:
BaseClass::OnKeyCodePressed(code);
break;
}
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Handle key presses
//-----------------------------------------------------------------------------
void Slider::OnKeyCodeTyped(KeyCode code)
{
switch (code)
{
// for now left and right arrows just open or close submenus if they are there.
case KEY_LEFT:
case KEY_DOWN:
{
int val = GetValue();
SetValue(val-1);
break;
}
case KEY_RIGHT:
case KEY_UP:
{
int val = GetValue();
SetValue(val+1);
break;
}
case KEY_PAGEDOWN:
{
int min, max;
GetRange(min, max);
float range = (float) max-min;
float pertick = range/m_nNumTicks;
int val = GetValue();
SetValue(val - (int) pertick);
break;
}
case KEY_PAGEUP:
{
int min, max;
GetRange(min, max);
float range = (float) max-min;
float pertick = range/m_nNumTicks;
int val = GetValue();
SetValue(val + (int) pertick);
break;
}
case KEY_HOME:
{
int min, max;
GetRange(min, max);
SetValue(min);
break;
}
case KEY_END:
{
int min, max;
GetRange(min, max);
SetValue(max);
break;
}
default:
BaseClass::OnKeyCodeTyped(code);
break;
}
}
//-----------------------------------------------------------------------------
// Purpose: Stop dragging when the mouse is released.
//-----------------------------------------------------------------------------
void Slider::OnMouseReleased(MouseCode code)
{
if ( _dragging )
{
_dragging=false;
input()->SetMouseCapture(null);
}
if ( IsEnabled() )
{
SendSliderDragEndMessage();
}
}
//-----------------------------------------------------------------------------
// Purpose: Get the nob's position (the ends of each side of the nob)
//-----------------------------------------------------------------------------
void Slider::GetNobPos(int& min, int& max)
{
min=_nobPos[0];
max=_nobPos[1];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Slider::SetButtonOffset(int buttonOffset)
{
_buttonOffset=buttonOffset;
}
void Slider::SetThumbWidth( int width )
{
_nobSize = (float)width;
}
//-----------------------------------------------------------------------------
// Purpose: Set the number of ticks that appear under the slider.
//-----------------------------------------------------------------------------
void Slider::SetNumTicks( int ticks )
{
m_nNumTicks = ticks;
}

View File

@ -0,0 +1,765 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include <vgui/IScheme.h>
#include <vgui/Cursor.h>
#include <vgui/IInput.h>
#include <vgui_controls/Splitter.h>
#include "tier1/KeyValues.h"
#include <limits.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
enum
{
SPLITTER_HANDLE_WIDTH = 4
};
//-----------------------------------------------------------------------------
// Splitter handle
//-----------------------------------------------------------------------------
namespace vgui
{
class SplitterHandle : public Panel
{
DECLARE_CLASS_SIMPLE( SplitterHandle, Panel );
public:
SplitterHandle( Splitter *parent, const char *name, SplitterMode_t mode, int nIndex );
~SplitterHandle();
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual void OnMousePressed( MouseCode code );
virtual void OnMouseReleased( MouseCode code );
virtual void OnCursorMoved( int x, int y );
virtual void OnMouseDoublePressed( MouseCode code );
private:
SplitterMode_t m_nMode;
int m_nIndex;
bool m_bDragging;
};
} // end namespace vgui
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
SplitterHandle::SplitterHandle( Splitter *parent, const char *name, SplitterMode_t mode, int nIndex ) : BaseClass( parent, name )
{
int w, h;
parent->GetSize( w, h );
if ( mode == SPLITTER_MODE_HORIZONTAL )
{
SetSize( w, SPLITTER_HANDLE_WIDTH );
SetCursor( dc_sizens );
}
else
{
SetSize( SPLITTER_HANDLE_WIDTH, h );
SetCursor( dc_sizewe );
}
SetVisible( true );
SetPaintBackgroundEnabled( false );
SetPaintEnabled( false );
SetPaintBorderEnabled( true );
m_bDragging = false;
m_nIndex = nIndex;
m_nMode = mode;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
SplitterHandle::~SplitterHandle()
{
}
//-----------------------------------------------------------------------------
// Scheme settings
//-----------------------------------------------------------------------------
void SplitterHandle::ApplySchemeSettings(IScheme *pScheme)
{
// Cache off background color stored in SetSplitterColor
Color c = GetBgColor();
SetBorder(pScheme->GetBorder("ButtonDepressedBorder"));
BaseClass::ApplySchemeSettings(pScheme);
SetBgColor( c );
}
//-----------------------------------------------------------------------------
// Capture mouse when dragging
//-----------------------------------------------------------------------------
void SplitterHandle::OnMousePressed(MouseCode code)
{
if ( !m_bDragging )
{
input()->SetMouseCapture(GetVPanel());
m_bDragging = true;
}
}
//-----------------------------------------------------------------------------
// Release mouse capture when finished dragging
//-----------------------------------------------------------------------------
void SplitterHandle::OnMouseReleased(MouseCode code)
{
if ( m_bDragging )
{
input()->SetMouseCapture(NULL);
m_bDragging = false;
}
}
//-----------------------------------------------------------------------------
// While dragging, update the splitter position
//-----------------------------------------------------------------------------
void SplitterHandle::OnCursorMoved(int x, int y)
{
if (m_bDragging)
{
input()->GetCursorPos( x, y );
Splitter *pSplitter = assert_cast<Splitter*>( GetParent() );
pSplitter->ScreenToLocal( x,y );
pSplitter->SetSplitterPosition( m_nIndex, (m_nMode == SPLITTER_MODE_HORIZONTAL) ? y : x );
}
}
//-----------------------------------------------------------------------------
// Double-click: make both panels on either side of the splitter equal size
//-----------------------------------------------------------------------------
void SplitterHandle::OnMouseDoublePressed( MouseCode code )
{
Splitter *pSplitter = assert_cast<Splitter*>( GetParent() );
pSplitter->EvenlyRespaceSplitters();
}
//-----------------------------------------------------------------------------
// Returns a panel that chains user configs
//-----------------------------------------------------------------------------
namespace vgui
{
class SplitterChildPanel : public EditablePanel
{
DECLARE_CLASS_SIMPLE( SplitterChildPanel, EditablePanel );
public:
SplitterChildPanel( Panel *parent, const char *panelName ) : BaseClass( parent, panelName )
{
SetPaintBackgroundEnabled( false );
SetPaintEnabled( false );
SetPaintBorderEnabled( false );
}
virtual ~SplitterChildPanel() {}
// Children may have user config settings
bool HasUserConfigSettings()
{
return true;
}
};
} // end namespace vgui
//-----------------------------------------------------------------------------
//
// Splitter panel
//
//-----------------------------------------------------------------------------
vgui::Panel *Splitter_V_Factory()
{
return new Splitter( NULL, NULL, SPLITTER_MODE_VERTICAL, 1 );
}
vgui::Panel *Splitter_H_Factory()
{
return new Splitter( NULL, NULL, SPLITTER_MODE_HORIZONTAL, 1 );
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
Splitter::Splitter( Panel *parent, const char *name, SplitterMode_t mode, int nCount ) : BaseClass( parent, name )
{
Assert( nCount >= 1 );
m_Mode = mode;
SetPaintBackgroundEnabled( false );
SetPaintEnabled( false );
SetPaintBorderEnabled( false );
RecreateSplitters( nCount );
EvenlyRespaceSplitters();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
Splitter::~Splitter()
{
m_Splitters.RemoveAll();
}
void Splitter::RecreateSplitters( int nCount )
{
int i;
int c = m_Splitters.Count();
for ( i = 0; i < c; ++i )
{
delete m_Splitters[ i ].m_pPanel;
delete m_Splitters[ i ].m_pHandle;
}
m_Splitters.RemoveAll();
for ( i = 0; i < (nCount + 1); ++i )
{
char pBuffer[512];
Q_snprintf( pBuffer, sizeof(pBuffer), "child%d", i );
int nIndex = m_Splitters.AddToTail( );
SplitterChildPanel *pEditablePanel = new SplitterChildPanel( this, pBuffer );
m_Splitters[nIndex].m_pPanel = pEditablePanel;
m_Splitters[nIndex].m_bLocked = false;
m_Splitters[nIndex].m_nLockedSize = 0;
}
// We do this in 2 loops so that the first N children are actual child panels
for ( i = 0; i < nCount; ++i )
{
SplitterHandle *pHandle = new SplitterHandle( this, "SplitterHandle", m_Mode, i );
m_Splitters[i].m_pHandle = pHandle;
pHandle->MoveToFront();
}
m_Splitters[nCount].m_pHandle = NULL;
}
//-----------------------------------------------------------------------------
// Sets the splitter color
//-----------------------------------------------------------------------------
void Splitter::SetSplitterColor( Color c )
{
int nCount = m_Splitters.Count() - 1;
if ( c.a() != 0 )
{
for ( int i = 0; i < nCount; ++i )
{
m_Splitters[i].m_pHandle->SetBgColor( c );
m_Splitters[i].m_pHandle->SetPaintBackgroundEnabled( true );
}
}
else
{
for ( int i = 0; i < nCount; ++i )
{
m_Splitters[i].m_pHandle->SetPaintBackgroundEnabled( false );
}
}
}
//-----------------------------------------------------------------------------
// Enables borders on the splitters
//-----------------------------------------------------------------------------
void Splitter::EnableBorders( bool bEnable )
{
int nCount = m_Splitters.Count() - 1;
for ( int i = 0; i < nCount; ++i )
{
m_Splitters[i].m_pHandle->SetPaintBorderEnabled( bEnable );
}
}
//-----------------------------------------------------------------------------
// controls splitters
//-----------------------------------------------------------------------------
int Splitter::GetSplitterCount() const
{
return m_Splitters.Count() - 1;
}
//-----------------------------------------------------------------------------
// controls splitters
//-----------------------------------------------------------------------------
int Splitter::GetSubPanelCount() const
{
return m_Splitters.Count();
}
//-----------------------------------------------------------------------------
// Purpose: Applies resouce settings
//-----------------------------------------------------------------------------
void Splitter::ApplySettings(KeyValues *inResourceData)
{
BaseClass::ApplySettings(inResourceData);
// Look for splitter positions
int nSplitterCount = GetSplitterCount();
for ( int i = 0; i < nSplitterCount; ++i )
{
char pBuffer[512];
Q_snprintf( pBuffer, sizeof(pBuffer), "splitter%d", i );
int nSplitterPos = inResourceData->GetInt( pBuffer , -1 );
if ( nSplitterPos >= 0 )
{
SetSplitterPosition( i, nSplitterPos );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int Splitter::GetPosRange()
{
int w, h;
GetSize( w, h );
int nPosRange = (m_Mode == SPLITTER_MODE_HORIZONTAL) ? h : w;
return nPosRange;
}
//-----------------------------------------------------------------------------
// Locks the size of a particular child in pixels.
//-----------------------------------------------------------------------------
void Splitter::LockChildSize( int nChildIndex, int nSize )
{
Assert( nChildIndex < m_Splitters.Count() );
SplitterInfo_t &info = m_Splitters[nChildIndex];
nSize += SPLITTER_HANDLE_WIDTH;
if ( !info.m_bLocked || (info.m_nLockedSize != nSize) )
{
float flPrevPos = (nChildIndex > 0) ? m_Splitters[nChildIndex-1].m_flPos : 0.0f;
float flOldSize = info.m_flPos - flPrevPos;
float flDelta = nSize - flOldSize;
int nCount = m_Splitters.Count();
for ( int i = nChildIndex; i < nCount-1; ++i )
{
m_Splitters[i].m_flPos += flDelta;
}
m_Splitters[nCount-1].m_flPos = GetPosRange();
info.m_bLocked = true;
info.m_nLockedSize = nSize;
InvalidateLayout();
}
}
void Splitter::UnlockChildSize( int nChildIndex )
{
Assert( nChildIndex < m_Splitters.Count() );
SplitterInfo_t &info = m_Splitters[nChildIndex];
if ( info.m_bLocked )
{
info.m_bLocked = false;
float flPrevPos = (nChildIndex > 0) ? m_Splitters[nChildIndex-1].m_flPos : 0.0f;
float flBelowSize = GetPosRange() - flPrevPos;
int nLockedSize = ComputeLockedSize( nChildIndex + 1 );
int nUnlockedCount = 1;
int nCount = m_Splitters.Count();
for ( int i = nChildIndex + 1; i < nCount; ++i )
{
if ( !m_Splitters[i].m_bLocked )
{
++nUnlockedCount;
}
}
float flUnlockedSize = ( flBelowSize - nLockedSize ) / nUnlockedCount;
for ( int i = nChildIndex; i < nCount; ++i )
{
if ( !m_Splitters[i].m_bLocked )
{
m_Splitters[i].m_flPos = flPrevPos + flUnlockedSize;
}
else
{
m_Splitters[i].m_flPos = flPrevPos + m_Splitters[i].m_nLockedSize;
}
flPrevPos = m_Splitters[i].m_flPos;
}
InvalidateLayout();
}
}
//-----------------------------------------------------------------------------
// Called when size changes
//-----------------------------------------------------------------------------
void Splitter::OnSizeChanged( int newWide, int newTall )
{
BaseClass::OnSizeChanged( newWide, newTall );
// Don't resize if it's degenerate and won't show up anyway...
if ( newTall <= 0 || newWide <= 0 )
return;
int nLockedSize = 0;
float flUnlockedSize = 0.0f;
int nCount = m_Splitters.Count();
float flLastPos = 0.0f;
int nUnlockedCount = 0;
for ( int i = 0; i < nCount; ++i )
{
SplitterInfo_t &info = m_Splitters[i];
if ( info.m_bLocked )
{
nLockedSize += info.m_nLockedSize;
}
else
{
++nUnlockedCount;
flUnlockedSize += info.m_flPos - flLastPos;
}
flLastPos = info.m_flPos;
}
int nNewTotalSize = (m_Mode == SPLITTER_MODE_HORIZONTAL) ? newTall : newWide;
int nNewUnlockedSize = nNewTotalSize - nLockedSize;
if ( nNewUnlockedSize < nUnlockedCount * SPLITTER_HANDLE_WIDTH )
{
nNewUnlockedSize = nUnlockedCount * SPLITTER_HANDLE_WIDTH;
}
float flRatio = nNewUnlockedSize / flUnlockedSize;
float flLastPrevPos = 0.0f;
flLastPos = 0.0f;
for ( int i = 0; i < nCount - 1; ++i )
{
SplitterInfo_t &info = m_Splitters[i];
if ( info.m_bLocked )
{
flLastPrevPos = info.m_flPos;
info.m_flPos = flLastPos + info.m_nLockedSize;
}
else
{
float flNewSize = info.m_flPos - flLastPrevPos;
flNewSize *= flRatio;
flLastPrevPos = info.m_flPos;
info.m_flPos = flLastPos + flNewSize;
}
flLastPos = info.m_flPos;
}
// Clamp the bottom to 1.0
m_Splitters[nCount-1].m_flPos = nNewTotalSize;
}
//-----------------------------------------------------------------------------
// Splitter position
//-----------------------------------------------------------------------------
int Splitter::GetSplitterPosition( int nIndex )
{
return (int)( m_Splitters[nIndex].m_flPos + 0.5f );
}
void Splitter::SetSplitterPosition( int nIndex, int nPos )
{
int nPosRange = GetPosRange();
if ( nPosRange == 0 )
return;
// If we're locked to a sibling, move the previous sibling first
while ( ( nIndex >= 0 ) && m_Splitters[nIndex].m_bLocked )
{
nPos -= m_Splitters[nIndex].m_nLockedSize;
--nIndex;
}
if ( nIndex < 0 )
return;
// Clamp to the valid positional range
int i;
int nMinPos = 0;
for ( i = 0; i < nIndex; ++i )
{
if ( !m_Splitters[i].m_bLocked )
{
nMinPos += SPLITTER_HANDLE_WIDTH;
}
else
{
nMinPos += m_Splitters[i].m_nLockedSize;
}
}
int nMaxPos = nPosRange - SPLITTER_HANDLE_WIDTH;
int c = GetSplitterCount();
for ( i = nIndex + 1; i < c; ++i )
{
if ( !m_Splitters[i].m_bLocked )
{
nMaxPos -= SPLITTER_HANDLE_WIDTH;
}
else
{
nMaxPos -= m_Splitters[i].m_nLockedSize;
}
}
nPos = clamp( nPos, nMinPos, nMaxPos );
m_Splitters[nIndex].m_flPos = nPos;
int p = nPos;
for ( i = nIndex - 1 ; i >= 0; --i )
{
int nMinPrevPos;
int nMaxPrevPos;
if ( !m_Splitters[i+1].m_bLocked )
{
nMinPrevPos = -INT_MAX;
nMaxPrevPos = nPos - SPLITTER_HANDLE_WIDTH;
}
else
{
nMinPrevPos = nMaxPrevPos = p - m_Splitters[i+1].m_nLockedSize;
}
int nCurPos = GetSplitterPosition( i );
if ( nMaxPrevPos < nCurPos || nMinPrevPos > nCurPos )
{
m_Splitters[ i ].m_flPos = nMaxPrevPos;
p = nMaxPrevPos;
}
else
{
p = m_Splitters[ i ].m_flPos;
}
}
for ( i = nIndex + 1 ; i < c; ++i )
{
int nMinNextPos;
int nMaxNextPos;
if ( !m_Splitters[i].m_bLocked )
{
nMinNextPos = nPos + SPLITTER_HANDLE_WIDTH;
nMaxNextPos = INT_MAX;
}
else
{
nMinNextPos = nMaxNextPos = nPos + m_Splitters[i].m_nLockedSize;
}
int nCurPos = GetSplitterPosition( i );
if ( nMinNextPos > nCurPos || nMaxNextPos < nCurPos )
{
m_Splitters[ i ].m_flPos = nMinNextPos;
nPos = nMinNextPos;
}
else
{
nPos = m_Splitters[ i ].m_flPos;
}
}
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Computes the locked size
//-----------------------------------------------------------------------------
int Splitter::ComputeLockedSize( int nStartingIndex )
{
int nLockedSize = 0;
int nCount = m_Splitters.Count();
for ( int i = nStartingIndex; i < nCount; ++i )
{
if ( m_Splitters[i].m_bLocked )
{
nLockedSize += m_Splitters[i].m_nLockedSize;
}
}
return nLockedSize;
}
//-----------------------------------------------------------------------------
// Evenly respaces all the splitters
//-----------------------------------------------------------------------------
void Splitter::EvenlyRespaceSplitters( )
{
int nSplitterCount = GetSubPanelCount();
if ( nSplitterCount == 0 )
return;
int nLockedSize = ComputeLockedSize( 0 );
float flUnlockedSize = (float)( GetPosRange() - nLockedSize );
float flDPos = flUnlockedSize / (float)nSplitterCount;
if ( flDPos < SPLITTER_HANDLE_WIDTH )
{
flDPos = SPLITTER_HANDLE_WIDTH;
}
float flPos = 0.0f;
for ( int i = 0; i < nSplitterCount; ++i )
{
if ( !m_Splitters[i].m_bLocked )
{
flPos += flDPos;
}
else
{
flPos += m_Splitters[i].m_nLockedSize;
}
m_Splitters[i].m_flPos = flPos;
}
InvalidateLayout();
}
void Splitter::RespaceSplitters( float *flFractions )
{
int nSplitterCount = GetSubPanelCount();
if ( nSplitterCount == 0 )
return;
float flPos = 0.0f;
int nPosRange = GetPosRange();
for ( int i = 0; i < nSplitterCount; ++i )
{
flPos += flFractions[i];
m_Splitters[i].m_flPos = flPos * nPosRange;
}
Assert( flPos == 1.0f );
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose: sets user settings
//-----------------------------------------------------------------------------
void Splitter::ApplyUserConfigSettings(KeyValues *userConfig)
{
BaseClass::ApplyUserConfigSettings( userConfig );
// read the splitter sizes
int c = m_Splitters.Count();
float *pFractions = (float*)_alloca( c * sizeof(float) );
float flTotalSize = 0.0f;
for ( int i = 0; i < c; i++ )
{
char name[128];
_snprintf(name, sizeof(name), "%d_splitter_pos", i);
pFractions[i] = userConfig->GetFloat( name, flTotalSize + SPLITTER_HANDLE_WIDTH + 1 );
flTotalSize = pFractions[i];
}
if ( flTotalSize != 0.0f )
{
int nPosRange = GetPosRange();
for ( int i = 0; i < c; ++i )
{
pFractions[i] /= flTotalSize;
m_Splitters[i].m_flPos = pFractions[i] * nPosRange;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: returns user config settings for this control
//-----------------------------------------------------------------------------
void Splitter::GetUserConfigSettings(KeyValues *userConfig)
{
BaseClass::GetUserConfigSettings( userConfig );
// save which columns are hidden
int c = m_Splitters.Count();
for ( int i = 0 ; i < c; i++ )
{
char name[128];
_snprintf(name, sizeof(name), "%d_splitter_pos", i);
userConfig->SetFloat( name, m_Splitters[i].m_flPos );
}
}
//-----------------------------------------------------------------------------
// Called to perform layout
//-----------------------------------------------------------------------------
void Splitter::PerformLayout( )
{
BaseClass::PerformLayout();
int nSplitterCount = GetSubPanelCount();
if ( nSplitterCount == 0 )
return;
int w, h;
GetSize( w, h );
int nLastPos = 0;
for ( int i = 0; i < nSplitterCount; ++i )
{
Panel *pChild = m_Splitters[i].m_pPanel;
SplitterHandle *pHandle = m_Splitters[i].m_pHandle;
int nSplitterPos = (int)( m_Splitters[i].m_flPos + 0.5f );
if ( m_Mode == SPLITTER_MODE_HORIZONTAL )
{
pChild->SetPos( 0, nLastPos );
pChild->SetSize( w, nSplitterPos - nLastPos );
if ( pHandle )
{
pHandle->SetPos( 0, nSplitterPos );
pHandle->SetSize( w, SPLITTER_HANDLE_WIDTH );
}
}
else
{
pChild->SetPos( nLastPos, 0 );
pChild->SetSize( nSplitterPos - nLastPos, h );
if ( pHandle )
{
pHandle->SetPos( nSplitterPos, 0 );
pHandle->SetSize( SPLITTER_HANDLE_WIDTH, h );
}
}
nLastPos = nSplitterPos + SPLITTER_HANDLE_WIDTH;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Splitter::GetSettings( KeyValues *outResourceData )
{
BaseClass::GetSettings( outResourceData );
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,985 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of vgui::TextImage control
//
// $NoKeywords: $
//=============================================================================//
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <malloc.h>
#include <vgui/IPanel.h>
#include <vgui/ISurface.h>
#include <vgui/IScheme.h>
#include <vgui/IInput.h>
#include <vgui/ILocalize.h>
#include <KeyValues.h>
#include <vgui_controls/TextImage.h>
#include <vgui_controls/Controls.h>
#include "tier0/dbg.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
// enable this define if you want unlocalized strings logged to files unfound.txt and unlocalized.txt
// #define LOG_UNLOCALIZED_STRINGS
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
TextImage::TextImage(const char *text) : Image()
{
_utext = NULL;
_textBufferLen = 0;
_font = INVALID_FONT;
_fallbackFont = INVALID_FONT;
_unlocalizedTextSymbol = INVALID_LOCALIZE_STRING_INDEX;
_drawWidth = 0;
_textBufferLen = 0;
_textLen = 0;
m_bWrap = false;
m_bWrapCenter = false;
m_LineBreaks.RemoveAll();
m_LineXIndent.RemoveAll();
m_pwszEllipsesPosition = NULL;
m_bUseFallbackFont = false;
m_bRenderUsingFallbackFont = false;
m_bAllCaps = false;
SetText(text); // set the text.
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
TextImage::TextImage(const wchar_t *wszText) : Image()
{
_utext = NULL;
_textBufferLen = 0;
_font = INVALID_FONT;
_fallbackFont = INVALID_FONT;
_unlocalizedTextSymbol = INVALID_LOCALIZE_STRING_INDEX;
_drawWidth = 0;
_textBufferLen = 0;
_textLen = 0;
m_bWrap = false;
m_bWrapCenter = false;
m_LineBreaks.RemoveAll();
m_LineXIndent.RemoveAll();
m_bUseFallbackFont = false;
m_bRenderUsingFallbackFont = false;
m_bAllCaps = false;
SetText(wszText); // set the text.
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
TextImage::~TextImage()
{
delete [] _utext;
}
//-----------------------------------------------------------------------------
// Purpose: takes the string and looks it up in the localization file to convert it to unicode
//-----------------------------------------------------------------------------
void TextImage::SetText(const char *text)
{
if (!text)
{
text = "";
}
// check for localization
if (*text == '#')
{
// try lookup in localization tables
_unlocalizedTextSymbol = g_pVGuiLocalize->FindIndex(text + 1);
if (_unlocalizedTextSymbol != INVALID_LOCALIZE_STRING_INDEX)
{
wchar_t *unicode = g_pVGuiLocalize->GetValueByIndex(_unlocalizedTextSymbol);
SetText(unicode);
return;
}
else
{
// could not find string
// debug code for logging unlocalized strings
#if defined(LOG_UNLOCALIZED_STRINGS)
if (*text)
{
// write out error to unfound.txt log file
static bool first = true;
FILE *f;
if (first)
{
first = false;
f = fopen("unfound.txt", "wt");
}
else
{
f = fopen("unfound.txt", "at");
}
if (f)
{
fprintf(f, "\"%s\"\n", text);
fclose(f);
}
}
#endif // LOG_UNLOCALIZED_STRINGS
}
}
else
{
// debug code for logging unlocalized strings
#if defined(LOG_UNLOCALIZED_STRINGS)
if (text[0])
{
// setting a label to be ANSI text, write out error to unlocalized.txt log file
static bool first = true;
FILE *f;
if (first)
{
first = false;
f = fopen("unlocalized.txt", "wt");
}
else
{
f = fopen("unlocalized.txt", "at");
}
if (f)
{
fprintf(f, "\"%s\"\n", text);
fclose(f);
}
}
#endif // LOG_UNLOCALIZED_STRINGS
}
// convert the ansi string to unicode and use that
wchar_t unicode[1024];
g_pVGuiLocalize->ConvertANSIToUnicode(text, unicode, sizeof(unicode));
SetText(unicode);
}
//-----------------------------------------------------------------------------
// Purpose: Sets the width that the text can be.
//-----------------------------------------------------------------------------
void TextImage::SetDrawWidth(int width)
{
_drawWidth = width;
m_bRecalculateTruncation = true;
}
//-----------------------------------------------------------------------------
// Purpose: Gets the width that the text can be.
//-----------------------------------------------------------------------------
void TextImage::GetDrawWidth(int &width)
{
width = _drawWidth;
}
//-----------------------------------------------------------------------------
// Purpose: sets unicode text directly
//-----------------------------------------------------------------------------
void TextImage::SetText(const wchar_t *unicode, bool bClearUnlocalizedSymbol)
{
if ( bClearUnlocalizedSymbol )
{
// Clear out unlocalized text symbol so that changing dialog variables
// doesn't stomp over the custom unicode string we're being set to.
_unlocalizedTextSymbol = INVALID_LOCALIZE_STRING_INDEX;
}
if (!unicode)
{
unicode = L"";
}
// reallocate the buffer if necessary
_textLen = (short)wcslen(unicode);
if (_textLen >= _textBufferLen)
{
delete [] _utext;
_textBufferLen = (short)(_textLen + 1);
_utext = new wchar_t[_textBufferLen];
}
m_LineBreaks.RemoveAll();
m_LineXIndent.RemoveAll();
// store the text as unicode
wcscpy(_utext, unicode);
m_bRecalculateTruncation = true;
}
//-----------------------------------------------------------------------------
// Purpose: Gets the text in the textImage
//-----------------------------------------------------------------------------
void TextImage::GetText(char *buffer, int bufferSize)
{
g_pVGuiLocalize->ConvertUnicodeToANSI(_utext, buffer, bufferSize);
if ( m_bAllCaps )
{
// Uppercase all the letters
for ( int i = Q_strlen( buffer ); i >= 0; --i )
{
buffer[ i ] = toupper( buffer[ i ] );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Gets the text in the textImage
//-----------------------------------------------------------------------------
void TextImage::GetText(wchar_t *buffer, int bufLenInBytes)
{
wcsncpy(buffer, _utext, bufLenInBytes / sizeof(wchar_t));
if ( m_bAllCaps )
{
// Uppercase all the letters
for ( int i = Q_wcslen( buffer ) - 1; i >= 0; --i )
{
buffer[ i ] = towupper( buffer[ i ] );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void TextImage::GetUnlocalizedText(char *buffer, int bufferSize)
{
if (_unlocalizedTextSymbol != INVALID_LOCALIZE_STRING_INDEX)
{
const char *text = g_pVGuiLocalize->GetNameByIndex(_unlocalizedTextSymbol);
buffer[0] = '#';
Q_strncpy(buffer + 1, text, bufferSize - 1);
buffer[bufferSize-1] = 0;
}
else
{
GetText(buffer, bufferSize);
}
}
//-----------------------------------------------------------------------------
// Purpose: unlocalized text symbol
//-----------------------------------------------------------------------------
StringIndex_t TextImage::GetUnlocalizedTextSymbol()
{
return _unlocalizedTextSymbol;
}
//-----------------------------------------------------------------------------
// Purpose: Changes the current font
//-----------------------------------------------------------------------------
void TextImage::SetFont(HFont font)
{
_font = font;
m_bRecalculateTruncation = true;
}
//-----------------------------------------------------------------------------
// Purpose: Gets the font of the text.
//-----------------------------------------------------------------------------
HFont TextImage::GetFont()
{
if ( m_bRenderUsingFallbackFont )
{
return _fallbackFont;
}
return _font;
}
//-----------------------------------------------------------------------------
// Purpose: Sets the size of the TextImage. This is directly tied to drawWidth
//-----------------------------------------------------------------------------
void TextImage::SetSize(int wide, int tall)
{
Image::SetSize(wide, tall);
_drawWidth = wide;
m_bRecalculateTruncation = true;
}
//-----------------------------------------------------------------------------
// Purpose: Draw the Image on screen.
//-----------------------------------------------------------------------------
void TextImage::Paint()
{
int wide, tall;
GetSize(wide, tall);
if (!_utext || GetFont() == INVALID_FONT )
return;
if (m_bRecalculateTruncation)
{
if ( m_bWrap || m_bWrapCenter )
{
RecalculateNewLinePositions();
}
RecalculateEllipsesPosition();
}
DrawSetTextColor(GetColor());
HFont font = GetFont();
DrawSetTextFont(font);
int lineHeight = surface()->GetFontTall(font);
float x = 0.0f;
int y = 0;
int iIndent = 0;
int iNextColorChange = 0;
int px, py;
GetPos(px, py);
int currentLineBreak = 0;
if ( m_bWrapCenter && m_LineXIndent.Count() )
{
x = m_LineXIndent[0];
}
for (wchar_t *wsz = _utext; *wsz != 0; wsz++)
{
wchar_t ch = wsz[0];
if ( m_bAllCaps )
{
ch = towupper( ch );
}
if ( m_ColorChangeStream.Count() > iNextColorChange )
{
if ( m_ColorChangeStream[iNextColorChange].textStreamIndex == (wsz - _utext) )
{
DrawSetTextColor( m_ColorChangeStream[iNextColorChange].color );
iNextColorChange++;
}
}
// check for special characters
if ( ch == '\r' || ch <= 8 )
{
// ignore, just use \n for newlines
continue;
}
else if (ch == '\n')
{
// newline
iIndent++;
if ( m_bWrapCenter && iIndent < m_LineXIndent.Count() )
{
x = m_LineXIndent[iIndent];
}
else
{
x = 0;
}
y += lineHeight;
continue;
}
else if (ch == '&')
{
// "&&" means draw a single ampersand, single one is a shortcut character
if (wsz[1] == '&')
{
// just move on and draw the second ampersand
wsz++;
}
else
{
// draw the underline, then continue to the next character without moving forward
#ifdef VGUI_DRAW_HOTKEYS_ENABLED
surface()->DrawSetTextPos(x + px, y + py);
surface()->DrawUnicodeChar('_');
#endif
continue;
}
}
// see if we've hit the truncated portion of the string
if (wsz == m_pwszEllipsesPosition)
{
// string is truncated, draw ellipses
for (int i = 0; i < 3; i++)
{
surface()->DrawSetTextPos(x + px, y + py);
surface()->DrawUnicodeChar('.');
x += surface()->GetCharacterWidth(font, '.');
}
break;
}
if (currentLineBreak != m_LineBreaks.Count())
{
if (wsz == m_LineBreaks[currentLineBreak])
{
// newline
iIndent++;
if ( m_bWrapCenter && iIndent < m_LineXIndent.Count() )
{
x = m_LineXIndent[iIndent];
}
else
{
x = 0;
}
y += lineHeight;
currentLineBreak++;
}
}
// Underlined text wants to draw the spaces anyway
#if USE_GETKERNEDCHARWIDTH
wchar_t chBefore = 0;
wchar_t chAfter = 0;
if ( wsz > _utext )
chBefore = wsz[-1];
chAfter = wsz[1];
float flWide = 0.0f, flabcA = 0.0f;
surface()->GetKernedCharWidth( font, ch, chBefore, chAfter, flWide, flabcA );
if ( ch == L' ' )
x = ceil( x );
surface()->DrawSetTextPos( x + px, y + py);
surface()->DrawUnicodeChar(ch);
x += floor(flWide + 0.6);
#else
surface()->DrawSetTextPos( x + px, y + py);
surface()->DrawUnicodeChar(ch);
x += surface()->GetCharacterWidth(font, ch);
#endif
}
// Useful debugging
/*
DrawSetColor(GetColor());
DrawOutlinedRect( 0,0, _drawWidth, tall );
*/
}
//-----------------------------------------------------------------------------
// Purpose: Get the size of a text string in pixels
//-----------------------------------------------------------------------------
void TextImage::GetTextSize(int &wide, int &tall)
{
wide = 0;
tall = 0;
int maxWide = 0;
const wchar_t *text = _utext;
HFont font = _font;
if ( font == INVALID_FONT )
return;
if ( m_bWrap || m_bWrapCenter )
{
RecalculateNewLinePositions();
}
// For height, use the remapped font
int fontHeight = surface()->GetFontTall(GetFont());
tall = fontHeight;
int textLen = wcslen(text);
for (int i = 0; i < textLen; i++)
{
wchar_t ch = text[i];
// handle stupid special characters, these should be removed
if ( ch == '&' )
{
continue;
}
if ( m_bAllCaps )
{
ch = towupper( ch );
}
#if USE_GETKERNEDCHARWIDTH
wchar_t chBefore = 0;
wchar_t chAfter = 0;
if ( i > 0 )
chBefore = text[i-1];
chAfter = text[i+1];
float flWide = 0.0f, flabcA;
surface()->GetKernedCharWidth( font, text[i], chBefore, chAfter, flWide, flabcA );
if ( text[i] == L' ' )
flWide = ceil( flWide );
wide += floor( flWide + 0.6);
#else
int a, b, c;
surface()->GetCharABCwide(font, ch, a, b, c);
wide += (a + b + c);
#endif
if (ch == '\n')
{
tall += fontHeight;
if(wide>maxWide)
{
maxWide=wide;
}
wide=0; // new line, wide is reset...
}
if ( m_bWrap || m_bWrapCenter )
{
for(int j=0; j<m_LineBreaks.Count(); j++)
{
if ( &text[i] == m_LineBreaks[j] )
{
tall += fontHeight;
if(wide>maxWide)
{
maxWide=wide;
}
wide=0; // new line, wide is reset...
}
}
}
}
#ifdef OSX
wide += 2;
if ( textLen < 3 )
wide += 3;
#endif
if (wide < maxWide)
{
// maxWide only gets set if a newline is in the label
wide = maxWide;
}
}
//-----------------------------------------------------------------------------
// Purpose: Get the size of the text in the image
//-----------------------------------------------------------------------------
void TextImage::GetContentSize(int &wide, int &tall)
{
GetTextSize(wide, tall);
}
//-----------------------------------------------------------------------------
// Purpose: Resize the text image to the content size
//-----------------------------------------------------------------------------
void TextImage::ResizeImageToContent()
{
int wide, tall;
GetContentSize(wide, tall);
SetSize(wide, tall);
}
//-----------------------------------------------------------------------------
// Purpose: Recalculates line breaks
//-----------------------------------------------------------------------------
void TextImage::RecalculateNewLinePositions()
{
HFont font = GetFont();
int charWidth;
int x = 0;
//int wordStartIndex = 0;
wchar_t *wordStartIndex = _utext;
int wordLength = 0;
bool hasWord = false;
bool justStartedNewLine = true;
bool wordStartedOnNewLine = true;
int startChar = 0;
// clear the line breaks list
m_LineBreaks.RemoveAll();
m_LineXIndent.RemoveAll();
// handle the case where this char is a new line, in that case
// we have already taken its break index into account above so skip it.
if (_utext[startChar] == '\r' || _utext[startChar] == '\n')
{
startChar++;
}
// loop through all the characters
for (wchar_t *wsz = &_utext[startChar]; *wsz != 0; wsz++)
{
// handle stupid special characters, these should be removed
// 0x01, 0x02 and 0x03 are color escape characters and should be ignored
if ( ( wsz[0] == '&' || wsz[0] == 0x01 || wsz[0] == 0x02 || wsz[0] == 0x03 ) && wsz[1] != 0 )
{
wsz++;
}
wchar_t ch = wsz[0];
if ( m_bAllCaps )
{
ch = towupper( ch );
}
// line break only on whitespace characters
if (!iswspace(ch))
{
if ( !hasWord )
{
// Start a new word
wordStartIndex = wsz;
hasWord = true;
wordStartedOnNewLine = justStartedNewLine;
wordLength = 0;
}
//else append to the current word
}
else
{
// whitespace/punctuation character
// end the word
hasWord = false;
}
// get the width
#if USE_GETKERNEDCHARWIDTH
wchar_t chBefore = 0;
wchar_t chAfter = 0;
if ( wsz > _utext )
chBefore = wsz[-1];
chAfter = wsz[1];
float flWide = 0.0f, flabcA = 0.0f;
surface()->GetKernedCharWidth( font, ch, chBefore, chAfter, flWide, flabcA );
charWidth = floor( flWide + 0.6 );
#else
charWidth = surface()->GetCharacterWidth(font, ch);
#endif
if (!iswcntrl(ch))
{
justStartedNewLine = false;
}
// check to see if the word is past the end of the line [wordStartIndex, i)
if ((x + charWidth) > _drawWidth || ch == '\r' || ch == '\n')
{
justStartedNewLine = true;
hasWord = false;
if (ch == '\r' || ch == '\n')
{
// set the break at the current character
//don't do this, paint will manually wrap on newline chars
// m_LineBreaks.AddToTail(i);
}
else if (wordStartedOnNewLine)
{
// word is longer than a line, so set the break at the current cursor
m_LineBreaks.AddToTail(wsz);
}
else
{
// set it at the last word Start
m_LineBreaks.AddToTail(wordStartIndex);
// just back to reparse the next line of text
// ywb 8/1/07: Back off one extra char since the 'continue' will increment wsz for us by one in the for loop
wsz = wordStartIndex - 1;
}
// reset word length
wordLength = 0;
x = 0;
continue;
}
// add to the size
x += charWidth;
wordLength += charWidth;
}
RecalculateCenterWrapIndents();
}
//-----------------------------------------------------------------------------
// Purpose: Calculates where the text should be truncated
//-----------------------------------------------------------------------------
void TextImage::RecalculateEllipsesPosition()
{
m_bRecalculateTruncation = false;
m_pwszEllipsesPosition = NULL;
//don't insert ellipses on wrapped strings
if ( m_bWrap || m_bWrapCenter )
return;
// don't truncate strings with newlines
if (wcschr(_utext, '\n') != NULL)
return;
if ( _drawWidth == 0 )
{
int h;
GetSize( _drawWidth, h );
}
for ( int check = 0; check < (m_bUseFallbackFont ? 2 : 1); ++check )
{
HFont font = GetFont();
if ( check == 1 && _fallbackFont != INVALID_FONT )
{
m_pwszEllipsesPosition = NULL;
font = _fallbackFont;
m_bRenderUsingFallbackFont = true;
}
int ellipsesWidth = 3 * surface()->GetCharacterWidth(font, '.');
int x = 0;
for (wchar_t *wsz = _utext; *wsz != 0; wsz++)
{
wchar_t ch = wsz[0];
if ( m_bAllCaps )
{
ch = towupper( ch );
}
// check for special characters
if (ch == '\r')
{
// ignore, just use \n for newlines
continue;
}
else if (ch == '&')
{
// "&&" means draw a single ampersand, single one is a shortcut character
if (wsz[1] == '&')
{
// just move on and draw the second ampersand
wsz++;
}
else
{
continue;
}
}
#if USE_GETKERNEDCHARWIDTH
wchar_t chBefore = 0;
wchar_t chAfter = 0;
if ( wsz > _utext )
chBefore = wsz[-1];
chAfter = wsz[1];
float flWide = 0.0f, flabcA = 0.0f;
surface()->GetKernedCharWidth( font, ch, chBefore, chAfter, flWide, flabcA );
int len = floor( flWide + 0.6 );
#else
int len = surface()->GetCharacterWidth(font, ch);
#endif
// don't truncate the first character
if (wsz == _utext)
{
x += len;
continue;
}
if (x + len + ellipsesWidth > _drawWidth)
{
// potential have an ellipses, see if the remaining characters will fit
int remainingLength = len;
for (const wchar_t *rwsz = wsz + 1; *rwsz != 0; rwsz++)
{
#if USE_GETKERNEDCHARWIDTH
wchar_t chBefore = 0;
wchar_t chAfter = 0;
if ( rwsz > _utext )
chBefore = rwsz[-1];
chAfter = rwsz[1];
float flWide = 0.0f, flabcA = 0.0f;
surface()->GetKernedCharWidth( font, *rwsz, chBefore, chAfter, flWide, flabcA );
int len = floor( flWide + 0.6 );
remainingLength += floor( flWide + 0.6 );
#else
remainingLength += surface()->GetCharacterWidth(font, *rwsz);
#endif
}
if (x + remainingLength > _drawWidth)
{
// looks like we've got an ellipses situation
m_pwszEllipsesPosition = wsz;
break;
}
}
x += len;
}
// Didn't need ellipses...
if ( !m_pwszEllipsesPosition )
break;
}
}
void TextImage::SetWrap( bool bWrap )
{
m_bWrap = bWrap;
}
void TextImage::SetCenterWrap( bool bWrap )
{
m_bWrapCenter = bWrap;
}
void TextImage::SetUseFallbackFont( bool bState, HFont hFallback )
{
m_bUseFallbackFont = bState;
_fallbackFont = hFallback;
}
void TextImage::SetAllCaps( bool bAllCaps )
{
m_bAllCaps = bAllCaps;
}
void TextImage::ResizeImageToContentMaxWidth( int nMaxWidth )
{
_drawWidth = nMaxWidth;
// Since we might have to use the "fallback" font, go ahead and recalc the ellipses state first to see if that's the case
// NOTE: I think there may be a race condition lurking here, but this seems to work.
if ( m_bRecalculateTruncation )
{
if ( m_bWrap || m_bWrapCenter )
{
RecalculateNewLinePositions();
}
RecalculateEllipsesPosition();
}
ResizeImageToContent();
}
//-----------------------------------------------------------------------------
// Purpose: For center wrapping of multi-line text images, determines the indent each line needs to be centered
//-----------------------------------------------------------------------------
void TextImage::RecalculateCenterWrapIndents()
{
m_LineXIndent.RemoveAll();
if ( !m_bWrapCenter )
return;
if (!_utext || GetFont() == INVALID_FONT )
return;
HFont font = GetFont();
int px, py;
GetPos(px, py);
int currentLineBreak = 0;
int iCurLineW = 0;
for (wchar_t *wsz = _utext; *wsz != 0; wsz++)
{
wchar_t ch = wsz[0];
if ( m_bAllCaps )
{
ch = towupper( ch );
}
// check for special characters
if (ch == '\r')
{
// ignore, just use \n for newlines
continue;
}
else if (ch == '\n')
{
int iIdx = m_LineXIndent.AddToTail();
m_LineXIndent[iIdx] = (_drawWidth - iCurLineW) * 0.5;
iCurLineW = 0;
continue;
}
else if (ch == '&')
{
// "&&" means draw a single ampersand, single one is a shortcut character
if (wsz[1] == '&')
{
// just move on and draw the second ampersand
wsz++;
}
else
{
// draw the underline, then continue to the next character without moving forward
continue;
}
}
// Don't need to check ellipses, they're not used when wrapping
if (currentLineBreak != m_LineBreaks.Count())
{
if (wsz == m_LineBreaks[currentLineBreak])
{
int iIdx = m_LineXIndent.AddToTail();
m_LineXIndent[iIdx] = (_drawWidth - iCurLineW) * 0.5;
iCurLineW = 0;
currentLineBreak++;
}
}
#if USE_GETKERNEDCHARWIDTH
wchar_t chBefore = 0;
wchar_t chAfter = 0;
if ( wsz > _utext )
chBefore = wsz[-1];
chAfter = wsz[1];
float flWide = 0.0f, flabcA = 0.0f;
surface()->GetKernedCharWidth( font, ch, chBefore, chAfter, flWide, flabcA );
iCurLineW += floor( flWide + 0.6 );
#else
iCurLineW += surface()->GetCharacterWidth(font, ch);
#endif
}
// Add the final line
int iIdx = m_LineXIndent.AddToTail();
m_LineXIndent[iIdx] = (_drawWidth - iCurLineW) * 0.5;
}
void TextImage::AddColorChange( Color col, int iTextStreamIndex )
{
label_colorchange_t tmpChange;
tmpChange.color = col;
tmpChange.textStreamIndex = iTextStreamIndex;
m_ColorChangeStream.Insert( tmpChange );
}
void TextImage::SetColorChangeStream( CUtlSortVector<label_colorchange_t,CColorChangeListLess> *pUtlVecStream )
{
ClearColorChangeStream();
m_ColorChangeStream = *pUtlVecStream;
}

View File

@ -0,0 +1,102 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/KeyCode.h>
#include <vgui_controls/ToggleButton.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_DEFAULT_TEXT( ToggleButton, ToggleButton );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ToggleButton::ToggleButton(Panel *parent, const char *panelName, const char* text) : Button(parent, panelName, text)
{
SetButtonActivationType(ACTIVATE_ONPRESSED);
}
//-----------------------------------------------------------------------------
// Purpose: Turns double-click into normal click
//-----------------------------------------------------------------------------
void ToggleButton::OnMouseDoublePressed(MouseCode code)
{
OnMousePressed(code);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Color ToggleButton::GetButtonFgColor()
{
if (IsSelected())
{
// highlight the text when depressed
return _selectedColor;
}
else
{
return BaseClass::GetButtonFgColor();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool ToggleButton::CanBeDefaultButton(void)
{
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Toggles the state of the button
//-----------------------------------------------------------------------------
void ToggleButton::DoClick()
{
if (IsSelected())
{
ForceDepressed(false);
}
else if (!IsSelected())
{
ForceDepressed(true);
}
SetSelected(!IsSelected());
FireActionSignal();
// post a button toggled message
KeyValues *msg = new KeyValues("ButtonToggled");
msg->SetInt("state", (int)IsSelected());
PostActionSignal(msg);
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ToggleButton::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
_selectedColor = GetSchemeColor("ToggleButton.SelectedTextColor", pScheme);
}
void ToggleButton::OnKeyCodePressed(KeyCode code)
{
if (code != KEY_ENTER)
{
BaseClass::OnKeyCodePressed(code);
}
}

View File

@ -0,0 +1,478 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/KeyCode.h>
#include <KeyValues.h>
#include "vgui/IInput.h"
#include "vgui/MouseCode.h"
#include "vgui/ISurface.h"
#include <vgui_controls/ToolWindow.h>
#include <vgui_controls/PropertySheet.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
CUtlVector< ToolWindow * > ToolWindow::s_ToolWindows;
//-----------------------------------------------------------------------------
// Purpose:
// Input : -
// Output : int
//-----------------------------------------------------------------------------
int ToolWindow::GetToolWindowCount()
{
return s_ToolWindows.Count();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : index -
// Output : PropertySheet
//-----------------------------------------------------------------------------
ToolWindow *ToolWindow::GetToolWindow( int index )
{
return s_ToolWindows[ index ];
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ToolWindow::ToolWindow(
Panel *parent,
bool contextlabel,
IToolWindowFactory *factory /*= 0*/,
Panel *page /*= NULL*/,
char const *title /*= NULL */,
bool contextMenu /*=false*/,
bool inGlobalList /*= true*/ ) : BaseClass( parent, "ToolWindow" ),
m_pFactory( factory )
{
if ( inGlobalList )
{
s_ToolWindows.AddToTail( this );
}
// create the property sheet
m_pPropertySheet = new PropertySheet(this, "ToolWindowSheet", true );
m_pPropertySheet->ShowContextButtons( contextlabel );
m_pPropertySheet->AddPage( page, title, 0, contextMenu );
m_pPropertySheet->AddActionSignalTarget(this);
m_pPropertySheet->SetSmallTabs( true );
m_pPropertySheet->SetKBNavigationEnabled( false );
SetSmallCaption( true );
SetMenuButtonResponsive(false);
SetMinimizeButtonVisible(false);
SetCloseButtonVisible(true);
SetMoveable( true );
SetSizeable(true);
SetClipToParent( false );
SetVisible( true );
SetDeleteSelfOnClose( true );
SetTitle( "", false );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
ToolWindow::~ToolWindow()
{
// These don't actually kill the children of the property sheet
m_pPropertySheet->RemoveAllPages();
s_ToolWindows.FindAndRemove( this );
}
//-----------------------------------------------------------------------------
// Purpose: Pass through to sheet
// Input : -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool ToolWindow::IsDraggableTabContainer() const
{
return m_pPropertySheet->IsDraggableTab();
}
//-----------------------------------------------------------------------------
// Purpose: Returns a pointer to the PropertySheet this dialog encapsulates
// Output : PropertySheet *
//-----------------------------------------------------------------------------
PropertySheet *ToolWindow::GetPropertySheet()
{
return m_pPropertySheet;
}
//-----------------------------------------------------------------------------
// Purpose: Gets a pointer to the currently active page.
// Output : Panel
//-----------------------------------------------------------------------------
Panel *ToolWindow::GetActivePage()
{
return m_pPropertySheet->GetActivePage();
}
void ToolWindow::SetActivePage( Panel *page )
{
m_pPropertySheet->SetActivePage( page );
}
//-----------------------------------------------------------------------------
// Purpose: Wrapped function
//-----------------------------------------------------------------------------
void ToolWindow::AddPage(Panel *page, const char *title, bool contextMenu)
{
m_pPropertySheet->AddPage(page, title, 0, contextMenu );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *page -
//-----------------------------------------------------------------------------
void ToolWindow::RemovePage( Panel *page )
{
m_pPropertySheet->RemovePage( page );
if ( m_pPropertySheet->GetNumPages() == 0 )
{
MarkForDeletion();
}
}
//-----------------------------------------------------------------------------
// Purpose: Sets up the sheet
//-----------------------------------------------------------------------------
void ToolWindow::PerformLayout()
{
BaseClass::PerformLayout();
int x, y, wide, tall;
GetClientArea(x, y, wide, tall);
m_pPropertySheet->SetBounds(x, y, wide, tall);
m_pPropertySheet->InvalidateLayout(); // tell the propertysheet to redraw!
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Overrides build mode so it edits the sub panel
//-----------------------------------------------------------------------------
void ToolWindow::ActivateBuildMode()
{
// no subpanel, no build mode
EditablePanel *panel = dynamic_cast<EditablePanel *>(GetActivePage());
if (!panel)
return;
panel->ActivateBuildMode();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ToolWindow::RequestFocus(int direction)
{
m_pPropertySheet->RequestFocus(direction);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *factory -
//-----------------------------------------------------------------------------
void ToolWindow::SetToolWindowFactory( IToolWindowFactory *factory )
{
m_pFactory = factory;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : -
// Output : IToolWindowFactory
//-----------------------------------------------------------------------------
IToolWindowFactory *ToolWindow::GetToolWindowFactory()
{
return m_pFactory;
}
//-----------------------------------------------------------------------------
// Purpose: To fill the space left by other tool windows
// Input : edge: 0=all, 1=top, 2=right, 3=bottom, 4=left
// Output :
//-----------------------------------------------------------------------------
void ToolWindow::Grow( int edge, int from_x, int from_y )
{
int status_h = 24;
int menubar_h = 27;
int sw, sh;
surface()->GetScreenSize( sw, sh );
int old_x, old_y, old_w, old_h;
GetBounds( old_x, old_y, old_w, old_h );
int new_x, new_y, new_w, new_h;
new_x = old_x;
new_y = old_y;
new_w = old_w;
new_h = old_h;
int c = GetToolWindowCount();
// grow up
if ( ( edge == 0 ) || ( edge == 1 ) )
{
// first shrink the edge back to the grow point
if ( from_y >= 0 )
{
old_h = old_h - ( from_y - old_y );
old_y = from_y;
}
// now grow the edge as far as it can go
new_h = old_h + ( old_y - menubar_h );
new_y = menubar_h;
for ( int i = 0 ; i < c; ++i )
{
ToolWindow *tw = GetToolWindow( i );
Assert( tw );
if ( ( !tw ) || ( tw == this ) )
continue;
// Get panel bounds
int x, y, w, h;
tw->GetBounds( x, y, w, h );
// grow it
if ( ( ( ( old_x > x ) && ( old_x < x + w ) )
|| ( ( old_x + old_w > x ) && ( old_x + old_w < x + w ) )
|| ( ( old_x <= x ) && old_x + old_w >= x + w ))
&& ( ( old_y >= y + h ) && ( new_y < y + h ) ) )
{
new_h = old_h + ( old_y - ( y + h ) );
new_y = y + h;
}
}
old_h = new_h;
old_y = new_y;
}
// grow right
if ( ( edge == 0 ) || ( edge == 2 ) )
{
// first shrink the edge back to the grow point
if ( from_x >= 0 )
{
old_w = from_x - old_x;
}
// now grow the edge as far as it can go
new_w = sw - old_x;
for ( int i = 0 ; i < c; ++i )
{
ToolWindow *tw = GetToolWindow( i );
Assert( tw );
if ( ( !tw ) || ( tw == this ) )
continue;
// Get panel bounds
int x, y, w, h;
tw->GetBounds( x, y, w, h );
// grow it
if ( ( ( ( old_y > y ) && ( old_y < y + h ) )
|| ( ( old_y + old_h > y ) && ( old_y + old_h < y + h ) )
|| ( ( old_y <= y ) && old_y + old_h >= y + h ))
&& ( ( old_x + old_w <= x ) && ( new_w > x - old_x ) ) )
{
new_w = x - old_x;
}
}
old_w = new_w;
}
// grow down
if ( ( edge == 0 ) || ( edge == 3 ) )
{
// first shrink the edge back to the grow point
if ( from_y >= 0 )
{
old_h = from_y - old_y;
}
// now grow the edge as far as it can go
new_h = sh - old_y - status_h;
for ( int i = 0 ; i < c; ++i )
{
ToolWindow *tw = GetToolWindow( i );
Assert( tw );
if ( ( !tw ) || ( tw == this ) )
continue;
// Get panel bounds
int x, y, w, h;
tw->GetBounds( x, y, w, h );
// grow it
if ( ( ( ( old_x > x ) && ( old_x < x + w ) )
|| ( ( old_x + old_w > x ) && ( old_x + old_w < x + w ) )
|| ( ( old_x <= x ) && old_x + old_w >= x + w ))
&& ( ( old_y + old_h <= y ) && ( new_h > y - old_y ) ) )
{
new_h = y - old_y;
}
}
old_h = new_h;
}
// grow left
if ( ( edge == 0 ) || ( edge == 4 ) )
{
// first shrink the edge back to the grow point
if ( from_x >= 0 )
{
old_w = old_w - ( from_x - old_x );
old_x = from_x;
}
// now grow the edge as far as it can go
new_w = old_w + old_x;
new_x = 0;
for ( int i = 0 ; i < c; ++i )
{
ToolWindow *tw = GetToolWindow( i );
Assert( tw );
if ( ( !tw ) || ( tw == this ) )
continue;
// Get panel bounds
int x, y, w, h;
tw->GetBounds( x, y, w, h );
// grow it
if ( ( ( ( old_y > y ) && ( old_y < y + h ) )
|| ( ( old_y + old_h > y ) && ( old_y + old_h < y + h ) )
|| ( ( old_y <= y ) && old_y + old_h >= y + h ))
&& ( ( old_x >= x + w ) && ( new_x < x + w ) ) )
{
new_w = old_w + ( old_x - ( x + w ) );
new_x = x + w;
}
}
old_w = new_w;
old_x = new_x;
}
// Set panel bounds
SetBounds( new_x, new_y, new_w, new_h );
}
//-----------------------------------------------------------------------------
// Purpose: Calls Grow based on where the mouse is.
// over titlebar: grows all edges ( from mouse pos )
// over edge grab area: grows just that edge
// over corner grab area: grows the two adjacent edges
// Input :
// Output :
//-----------------------------------------------------------------------------
void ToolWindow::GrowFromClick()
{
int mx, my;
input()->GetCursorPos( mx, my );
int esz, csz, brsz, ch;
esz = GetDraggerSize();
csz = GetCornerSize();
brsz = GetBottomRightSize();
ch = GetCaptionHeight();
int x, y, w, h;
GetBounds( x, y, w, h );
// upper right
if ( ( mx > x+w-csz-1 ) && ( my < y+csz ) )
{
Grow(1);
Grow(2);
}
// lower right (the big one)
else if ( ( mx > x+w-brsz-1 ) && ( my > y+h-brsz-1 ) )
{
Grow(2);
Grow(3);
}
// lower left
else if ( ( mx < x+csz ) && ( my > y+h-csz-1 ) )
{
Grow(3);
Grow(4);
}
// upper left
else if ( ( mx < x+csz ) && ( my < y+csz ) )
{
Grow(4);
Grow(1);
}
// top edge
else if ( my < y+esz )
{
Grow(1);
}
// right edge
else if ( mx > x+w-esz-1 )
{
Grow(2);
}
// bottom edge
else if ( my > y+h-esz-1 )
{
Grow(3);
}
// left edge
else if ( mx < x+esz )
{
Grow(4);
}
// otherwise (if over the grab bar), grow all edges (from the clicked point)
else if ( my < y + ch )
{
Grow(0, mx, my);
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : -
// Output :
//-----------------------------------------------------------------------------
void ToolWindow::OnMouseDoublePressed( MouseCode code )
{
GrowFromClick();
}
void ToolWindow::OnMousePressed( MouseCode code )
{
switch ( code )
{
case MOUSE_MIDDLE:
GrowFromClick();
break;
default:
BaseClass::OnMousePressed( code );
}
}

View File

@ -0,0 +1,416 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
// This class is a message box that has two buttons, ok and cancel instead of
// just the ok button of a message box. We use a message box class for the ok button
// and implement another button here.
//=============================================================================//
#include <math.h>
#define PROTECTED_THINGS_DISABLE
#include <vgui/IInput.h>
#include <vgui/ISystem.h>
#include <vgui/ISurface.h>
#include <vgui/IScheme.h>
#include <vgui/IVGui.h>
#include <vgui/IPanel.h>
#include <vgui_controls/Tooltip.h>
#include <vgui_controls/TextEntry.h>
#include <vgui_controls/Controls.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
static vgui::DHANDLE< TextEntry > s_TooltipWindow;
static int s_iTooltipWindowCount = 0;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
BaseTooltip::BaseTooltip(Panel *parent, const char *text)
{
SetText(text);
_displayOnOneLine = false;
_makeVisible = false;
_isDirty = false;
_enabled = true;
_tooltipDelay = 500; // default delay for opening tooltips
_delay = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Reset the tooltip delay timer
//-----------------------------------------------------------------------------
void BaseTooltip::ResetDelay()
{
_isDirty = true;
_delay = system()->GetTimeMillis() + _tooltipDelay;
}
//-----------------------------------------------------------------------------
// Purpose: Set the tooltip delay before a tooltip comes up.
//-----------------------------------------------------------------------------
void BaseTooltip::SetTooltipDelay( int tooltipDelay )
{
_tooltipDelay = tooltipDelay;
}
//-----------------------------------------------------------------------------
// Purpose: Get the tooltip delay before a tooltip comes up.
//-----------------------------------------------------------------------------
int BaseTooltip::GetTooltipDelay()
{
return _tooltipDelay;
}
//-----------------------------------------------------------------------------
// Purpose: Set the tool tip to display on one line only
// Default is multiple lines.
//-----------------------------------------------------------------------------
void BaseTooltip::SetTooltipFormatToSingleLine()
{
_displayOnOneLine = true;
_isDirty = true;
}
//-----------------------------------------------------------------------------
// Purpose: Set the tool tip to display on multiple lines.
//-----------------------------------------------------------------------------
void BaseTooltip::SetTooltipFormatToMultiLine()
{
_displayOnOneLine = false;
_isDirty = true;
}
//-----------------------------------------------------------------------------
// Purpose: Display the tooltip
//-----------------------------------------------------------------------------
void BaseTooltip::ShowTooltip(Panel *currentPanel)
{
_makeVisible = true;
PerformLayout();
}
void BaseTooltip::SetEnabled( bool bState )
{
_enabled = bState;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool BaseTooltip::ShouldLayout( void )
{
if (!_makeVisible)
return false;
if (_delay > system()->GetTimeMillis())
return false;
// We only need to layout when we first become visible
if ( !_isDirty )
return false;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Display the tooltip
//-----------------------------------------------------------------------------
void BaseTooltip::HideTooltip()
{
_makeVisible = false;
_isDirty = true;
}
//-----------------------------------------------------------------------------
// Purpose: Set the tooltip text
//-----------------------------------------------------------------------------
void BaseTooltip::SetText(const char *text)
{
_isDirty = true;
if (!text)
{
text = "";
}
if (m_Text.Size() > 0)
{
m_Text.RemoveAll();
}
for (unsigned int i = 0; i < strlen(text); i++)
{
m_Text.AddToTail(text[i]);
}
m_Text.AddToTail('\0');
if (s_TooltipWindow.Get() && m_pParent == s_TooltipWindow.Get()->GetParent())
{
s_TooltipWindow->SetText(m_Text.Base());
}
}
//-----------------------------------------------------------------------------
// Purpose: Get the tooltip text
//-----------------------------------------------------------------------------
const char *BaseTooltip::GetText()
{
return m_Text.Base();
}
//-----------------------------------------------------------------------------
// Purpose: Position the tool tip
//-----------------------------------------------------------------------------
void BaseTooltip::PositionWindow( Panel *pTipPanel )
{
int iTipW, iTipH;
pTipPanel->GetSize( iTipW, iTipH );
int cursorX, cursorY;
input()->GetCursorPos(cursorX, cursorY);
int wide, tall;
surface()->GetScreenSize(wide, tall);
int iParentX = 0, iParentY = 0;
if ( !pTipPanel->IsPopup() )
{
pTipPanel->GetParent()->GetPos( iParentX, iParentY );
pTipPanel->GetParent()->LocalToScreen( iParentX, iParentY );
}
cursorX -= iParentX;
cursorY -= iParentY;
if (wide - iTipW > cursorX)
{
cursorY += 20;
// menu hanging right
if (tall - iTipH > cursorY)
{
// menu hanging down
pTipPanel->SetPos(cursorX, cursorY);
}
else
{
// menu hanging up
pTipPanel->SetPos(cursorX, cursorY - iTipH - 20);
}
}
else
{
// menu hanging left
if (tall - iTipH > cursorY)
{
// menu hanging down
pTipPanel->SetPos(cursorX - iTipW, cursorY);
}
else
{
// menu hanging up
pTipPanel->SetPos(cursorX - iTipW, cursorY - iTipH - 20 );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
TextTooltip::TextTooltip(Panel *parent, const char *text) : BaseTooltip( parent, text )
{
if (!s_TooltipWindow.Get())
{
s_TooltipWindow = new TextEntry(NULL, "tooltip");
s_TooltipWindow->InvalidateLayout(false, true);
// this bit of hackery is necessary because tooltips don't get ApplySchemeSettings called from their parents
IScheme *pScheme = scheme()->GetIScheme( s_TooltipWindow->GetScheme() );
s_TooltipWindow->SetBgColor(s_TooltipWindow->GetSchemeColor("Tooltip.BgColor", s_TooltipWindow->GetBgColor(), pScheme));
s_TooltipWindow->SetFgColor(s_TooltipWindow->GetSchemeColor("Tooltip.TextColor", s_TooltipWindow->GetFgColor(), pScheme));
s_TooltipWindow->SetBorder(pScheme->GetBorder("ToolTipBorder"));
s_TooltipWindow->SetFont( pScheme->GetFont("DefaultSmall", s_TooltipWindow->IsProportional()));
}
s_iTooltipWindowCount++;
// this line prevents the main window from losing focus
// when a tooltip pops up
s_TooltipWindow->MakePopup(false, true);
s_TooltipWindow->SetKeyBoardInputEnabled( false );
s_TooltipWindow->SetMouseInputEnabled( false );
SetText(text);
s_TooltipWindow->SetText(m_Text.Base());
s_TooltipWindow->SetEditable(false);
s_TooltipWindow->SetMultiline(true);
s_TooltipWindow->SetVisible(false);
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
TextTooltip::~TextTooltip()
{
if (--s_iTooltipWindowCount < 1)
{
if ( s_TooltipWindow.Get() )
{
s_TooltipWindow->MarkForDeletion();
}
s_TooltipWindow = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: Set the tooltip text
//-----------------------------------------------------------------------------
void TextTooltip::SetText(const char *text)
{
BaseTooltip::SetText( text );
if (s_TooltipWindow.Get())
{
s_TooltipWindow->SetText(m_Text.Base());
}
}
//-----------------------------------------------------------------------------
// Purpose: gets the font from the scheme
//-----------------------------------------------------------------------------
void TextTooltip::ApplySchemeSettings(IScheme *pScheme)
{
if ( s_TooltipWindow )
{
s_TooltipWindow->SetFont(pScheme->GetFont("DefaultSmall", s_TooltipWindow->IsProportional()));
}
}
//-----------------------------------------------------------------------------
// Purpose: Display the tooltip
//-----------------------------------------------------------------------------
void TextTooltip::ShowTooltip(Panel *currentPanel)
{
if ( s_TooltipWindow.Get() )
{
int nLen = s_TooltipWindow->GetTextLength();
if ( nLen <= 0 )
{
// Empty tool tip, no need to show it
_makeVisible = false;
return;
}
char *pBuf = (char*)_alloca( nLen+1 );
s_TooltipWindow->GetText( pBuf, nLen+1 );
Panel *pCurrentParent = s_TooltipWindow->GetParent();
_isDirty = _isDirty || ( pCurrentParent != currentPanel );
s_TooltipWindow->SetText( m_Text.Base() );
s_TooltipWindow->SetParent(currentPanel);
}
BaseTooltip::ShowTooltip( currentPanel );
}
//-----------------------------------------------------------------------------
// Purpose: Display the tooltip
//-----------------------------------------------------------------------------
void TextTooltip::PerformLayout()
{
if ( !ShouldLayout() )
return;
// we're ready, just make us visible
if ( !s_TooltipWindow.Get() )
return;
_isDirty = false;
s_TooltipWindow->SetVisible(true);
s_TooltipWindow->MakePopup( false, true );
s_TooltipWindow->SetKeyBoardInputEnabled( false );
s_TooltipWindow->SetMouseInputEnabled( false );
// relayout the textwindow immediately so that we know it's size
//m_pTextEntry->InvalidateLayout(true);
SizeTextWindow();
PositionWindow( s_TooltipWindow );
}
//-----------------------------------------------------------------------------
// Purpose: Size the text window so all the text fits inside it.
//-----------------------------------------------------------------------------
void TextTooltip::SizeTextWindow()
{
if ( !s_TooltipWindow.Get() )
return;
if (_displayOnOneLine)
{
// We want the tool tip to be one line
s_TooltipWindow->SetMultiline(false);
s_TooltipWindow->SetToFullWidth();
}
else
{
// We want the tool tip to be one line
s_TooltipWindow->SetMultiline(false);
s_TooltipWindow->SetToFullWidth();
int wide, tall;
s_TooltipWindow->GetSize( wide, tall );
double newWide = sqrt( (2.0/1) * wide * tall );
double newTall = (1/2) * newWide;
s_TooltipWindow->SetMultiline(true);
s_TooltipWindow->SetSize((int)newWide, (int)newTall );
s_TooltipWindow->SetToFullHeight();
s_TooltipWindow->GetSize( wide, tall );
if (( wide < 100 ) && ( s_TooltipWindow->GetNumLines() == 2) )
{
s_TooltipWindow->SetMultiline(false);
s_TooltipWindow->SetToFullWidth();
}
else
{
while ( (float)wide/(float)tall < 2 )
{
s_TooltipWindow->SetSize( wide + 1, tall );
s_TooltipWindow->SetToFullHeight();
s_TooltipWindow->GetSize( wide, tall );
}
}
s_TooltipWindow->GetSize( wide, tall );
// ivgui()->DPrintf("End Ratio: %f\n", (float)wide/(float)tall);
}
}
//-----------------------------------------------------------------------------
// Purpose: Display the tooltip
//-----------------------------------------------------------------------------
void TextTooltip::HideTooltip()
{
if ( s_TooltipWindow.Get() )
{
s_TooltipWindow->SetVisible(false);
}
BaseTooltip::HideTooltip();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,315 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include <assert.h>
#define PROTECTED_THINGS_DISABLE
#include <vgui/Cursor.h>
#include <vgui/IScheme.h>
#include <vgui/IInput.h>
#include <vgui/IPanel.h>
#include <vgui/ISurface.h>
#include <vgui/KeyCode.h>
#include <KeyValues.h>
#include <vgui/MouseCode.h>
#include <vgui/IBorder.h>
#include <vgui_controls/TreeViewListControl.h>
#include <vgui_controls/ScrollBar.h>
#include <vgui_controls/TextEntry.h>
#include <vgui_controls/TreeView.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/TextImage.h>
#include <vgui_controls/ImageList.h>
#include <vgui_controls/ImagePanel.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
DECLARE_BUILD_FACTORY( CTreeViewListControl );
CTreeViewListControl::CTreeViewListControl( vgui::Panel *pParent, const char *pName ) :
BaseClass( pParent, pName )
{
m_pTree = NULL;
m_BorderColor.SetColor( 255, 255, 255, 255 );
m_TitleBarFont = NULL;
m_TitleBarHeight = 20;
SetPostChildPaintEnabled( true );
}
void CTreeViewListControl::SetTreeView( vgui::TreeView *pTree )
{
m_pTree = pTree;
if ( m_pTree )
{
m_pTree->SetParent( this );
m_pTree->SetPaintBackgroundEnabled( false );
}
InvalidateLayout();
}
vgui::TreeView *CTreeViewListControl::GetTree()
{
return m_pTree;
}
int CTreeViewListControl::GetTitleBarHeight()
{
return m_TitleBarHeight;
}
void CTreeViewListControl::SetTitleBarInfo( vgui::HFont hFont, int titleBarHeight )
{
m_TitleBarFont = hFont;
m_TitleBarHeight = titleBarHeight;
InvalidateLayout();
}
void CTreeViewListControl::SetBorderColor( Color clr )
{
m_BorderColor = clr;
}
void CTreeViewListControl::SetNumColumns( int nColumns )
{
m_Columns.Purge();
m_Columns.SetSize( nColumns );
InvalidateLayout();
}
int CTreeViewListControl::GetNumColumns() const
{
return m_Columns.Count();
}
void CTreeViewListControl::SetColumnInfo( int iColumn, const char *pTitle, int width, int ciFlags )
{
if ( iColumn < 0 || iColumn >= m_Columns.Count() )
{
Assert( false );
return;
}
CColumnInfo *pInfo = &m_Columns[iColumn];
pInfo->m_Title = pTitle;
pInfo->m_Width = width;
pInfo->m_ciFlags = ciFlags;
InvalidateLayout();
}
int CTreeViewListControl::GetNumRows()
{
return m_Rows.Count();
}
int CTreeViewListControl::GetTreeItemAtRow( int iRow )
{
if ( iRow < 0 || iRow >= m_Rows.Count() )
return -1;
else
return m_Rows[iRow];
}
void CTreeViewListControl::GetGridElementBounds( int iColumn, int iRow, int &left, int &top, int &right, int &bottom )
{
left = m_Columns[iColumn].m_Left;
right = m_Columns[iColumn].m_Right;
// vgui doesn't seem to be drawing things exactly right. Like it you draw a line at (0,0) to (100,0),
// then a rectangle from (1,1) to (100,100), it'll overwrite the line at the top.
int treeTopBorder = 0;
IBorder *treeBorder = m_pTree->GetBorder();
if ( treeBorder )
{
int l, t, r, b;
treeBorder->GetInset( l, t, r, b );
treeTopBorder = t;
}
if ( iRow == -1 )
{
top = 1;
bottom = m_TitleBarHeight - 2;
}
else if ( m_pTree )
{
int x, y;
m_pTree->GetPos( x, y );
top = treeTopBorder + m_TitleBarHeight + ( iRow * m_pTree->GetRowHeight() );
bottom = top + m_pTree->GetRowHeight();
}
else
{
left = top = right = bottom = 0;
}
}
void CTreeViewListControl::PerformLayout()
{
RecalculateRows();
RecalculateColumns();
// Reposition the tree view.
if ( m_pTree && m_Columns.Count() > 0 )
{
int left, top, right, bottom;
GetGridElementBounds( 0, -1, left, top, right, bottom );
top = m_TitleBarHeight;
m_pTree->SetBounds( left, top, right - left, GetTall() - top );
}
BaseClass::PerformLayout();
}
void CTreeViewListControl::RecalculateRows()
{
m_Rows.Purge();
if ( !m_pTree || m_pTree->GetRootItemIndex() == -1 )
return;
int iRoot = m_pTree->GetRootItemIndex();
RecalculateRows_R( iRoot );
}
void CTreeViewListControl::RecalculateRows_R( int index )
{
m_Rows.AddToTail( index );
if ( !m_pTree->IsItemExpanded( index ) )
return;
int nChildren = m_pTree->GetNumChildren( index );
for ( int i=0; i < nChildren; i++ )
{
int iChild = m_pTree->GetChild( index, i );
RecalculateRows_R( iChild );
}
}
int CTreeViewListControl::GetScrollBarSize()
{
return 0;
}
void CTreeViewListControl::RecalculateColumns()
{
int rightEdge = GetWide()-1 - GetScrollBarSize();
int x = 0;
int c = m_Columns.Count();
for ( int i=0; i < c; i++ )
{
m_Columns[i].m_Left = x + 1;
int cw = m_Columns[i].m_Width;
if ( i == c - 1 )
{
cw = rightEdge - x - 2;
}
m_Columns[i].m_Right = x + cw - 2;
x += cw;
}
}
void CTreeViewListControl::PostChildPaint()
{
BaseClass::PostChildPaint();
// Draw the grid lines.
vgui::surface()->DrawSetColor( m_BorderColor );
if ( m_Columns.Count() <= 0 )
return;
// Draw the horizontal lines.
int endX = 0;
endX = m_Columns[m_Columns.Count()-1].m_Right + 1;
int bottomY = 0;
for ( int i=0; i < m_Rows.Count(); i++ )
{
int left, top, right, bottom;
GetGridElementBounds( 0, i, left, top, right, bottom );
bottomY = bottom;
vgui::surface()->DrawLine( 0, bottomY, endX, bottomY );
}
// Draw the vertical lines.
int curX = 0;
for ( int i=0; i < m_Columns.Count(); i++ )
{
vgui::surface()->DrawLine( curX, 0, curX, bottomY );
curX += m_Columns[i].m_Width;
}
vgui::surface()->DrawLine( curX, 0, curX, bottomY );
}
void CTreeViewListControl::Paint()
{
BaseClass::Paint();
// Draw the title bars.
DrawTitleBars();
}
void CTreeViewListControl::DrawTitleBars()
{
int rightEdge = GetWide();
for ( int i=0; i < m_Columns.Count(); i++ )
{
int left, top, right, bottom;
GetGridElementBounds( i, -1, left, top, right, bottom );
if ( left >= rightEdge )
continue;
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
vgui::surface()->DrawFilledRect( left, top, right, bottom );
vgui::surface()->DrawSetTextColor( 255, 255, 255, 255 );
const char *pTitleString = m_Columns[i].m_Title.String();
wchar_t unicodeString[1024];
g_pVGuiLocalize->ConvertANSIToUnicode( pTitleString, unicodeString, sizeof(unicodeString) );
int wide, tall;
surface()->GetTextSize( m_TitleBarFont, unicodeString, wide, tall );
surface()->DrawSetTextFont( m_TitleBarFont );
if ( m_Columns[i].m_ciFlags & CTreeViewListControl::CI_HEADER_LEFTALIGN )
{
int midy = (top+bottom)/2;
surface()->DrawSetTextPos( left, midy );
}
else
{
int textRight = min( right, rightEdge );
int midx = (left+textRight)/2;
int midy = (top+bottom)/2;
surface()->DrawSetTextPos( midx - wide/2, midy - tall/2 );
}
surface()->DrawPrintText( unicodeString, strlen( pTitleString ) );
}
}

View File

@ -0,0 +1,158 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdio.h>
#include "vgui/ISurface.h"
#include "vgui/ISystem.h"
#include "vgui/MouseCode.h"
#include "vgui/Cursor.h"
#include "KeyValues.h"
#include "vgui_controls/URLLabel.h"
#include "vgui_controls/TextImage.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
vgui::Panel *URLLabel_Factory()
{
return new URLLabel(NULL, NULL, "URLLabel", NULL);
}
DECLARE_BUILD_FACTORY_CUSTOM( URLLabel, URLLabel_Factory );
//-----------------------------------------------------------------------------
// Purpose: constructor
//-----------------------------------------------------------------------------
URLLabel::URLLabel(Panel *parent, const char *panelName, const char *text, const char *pszURL) : Label(parent, panelName, text)
{
m_pszURL = NULL;
m_bUnderline = false;
m_iURLSize = 0;
if (pszURL && strlen(pszURL) > 0)
{
SetURL(pszURL);
}
}
//-----------------------------------------------------------------------------
// Purpose: unicode constructor
//-----------------------------------------------------------------------------
URLLabel::URLLabel(Panel *parent, const char *panelName, const wchar_t *wszText, const char *pszURL) : Label(parent, panelName, wszText)
{
m_pszURL = NULL;
m_bUnderline = false;
m_iURLSize = 0;
if (pszURL && strlen(pszURL) > 0)
{
SetURL(pszURL);
}
}
//-----------------------------------------------------------------------------
// Purpose: destructor
//-----------------------------------------------------------------------------
URLLabel::~URLLabel()
{
if (m_pszURL)
delete [] m_pszURL;
}
//-----------------------------------------------------------------------------
// Purpose: sets the URL
//-----------------------------------------------------------------------------
void URLLabel::SetURL(const char *pszURL)
{
int iNewURLSize = strlen(pszURL);
if (iNewURLSize > m_iURLSize || !m_pszURL)
{
delete [] m_pszURL;
m_pszURL = new char [iNewURLSize + 1];
}
strcpy(m_pszURL, pszURL);
m_iURLSize = iNewURLSize;
}
//-----------------------------------------------------------------------------
// Purpose: If we were left clicked on, launch the URL
//-----------------------------------------------------------------------------
void URLLabel::OnMousePressed(MouseCode code)
{
if (code == MOUSE_LEFT)
{
if (m_pszURL)
{
system()->ShellExecute("open", m_pszURL);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Applies resouce settings
//-----------------------------------------------------------------------------
void URLLabel::ApplySettings(KeyValues *inResourceData)
{
BaseClass::ApplySettings(inResourceData);
const char *pszURL = inResourceData->GetString("URLText", NULL);
if (pszURL)
{
if (pszURL[0] == '#')
{
// it's a localized url, look it up
const wchar_t *ws = g_pVGuiLocalize->Find(pszURL + 1);
if (ws)
{
char localizedUrl[512];
g_pVGuiLocalize->ConvertUnicodeToANSI(ws, localizedUrl, sizeof(localizedUrl));
SetURL(localizedUrl);
}
}
else
{
SetURL(pszURL);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: saves them to disk
//-----------------------------------------------------------------------------
void URLLabel::GetSettings( KeyValues *outResourceData )
{
BaseClass::GetSettings(outResourceData);
if (m_pszURL)
{
outResourceData->SetString("URLText", m_pszURL);
}
}
//-----------------------------------------------------------------------------
// Purpose: Returns a description of the label string
//-----------------------------------------------------------------------------
const char *URLLabel::GetDescription( void )
{
static char buf[1024];
_snprintf(buf, sizeof(buf), "%s, string URLText", BaseClass::GetDescription());
return buf;
}
//-----------------------------------------------------------------------------
// Purpose: scheme settings
//-----------------------------------------------------------------------------
void URLLabel::ApplySchemeSettings(IScheme *pScheme)
{
// set our font to be underlined by default
// the Label::ApplySchemeSettings() will override it if override set in scheme file
SetFont( pScheme->GetFont( "DefaultUnderline", IsProportional() ) );
BaseClass::ApplySchemeSettings(pScheme);
SetCursor(dc_hand);
}

View File

@ -0,0 +1,720 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <vgui/IVGui.h>
#include <KeyValues.h>
#include <vgui_controls/BuildGroup.h>
#include <vgui_controls/Button.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/WizardPanel.h>
#include <vgui_controls/WizardSubPanel.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
WizardPanel::WizardPanel(Panel *parent, const char *panelName) : Frame(parent, panelName)
{
_currentSubPanel = NULL;
_currentData = new KeyValues("WizardData");
_showButtons = true;
SetSizeable(false);
CreateButtons();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
WizardPanel::~WizardPanel()
{
if (_currentData)
{
_currentData->deleteThis();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::PerformLayout()
{
BaseClass::PerformLayout();
// resize the sub panel to fit in the Client area
int x, y, wide, tall;
GetClientArea(x, y, wide, tall);
if (_currentSubPanel && _currentSubPanel->isNonWizardPanel())
{
// just have the subpanel cover the full size
_currentSubPanel->SetBounds(x, y, wide, tall);
_cancelButton->SetVisible(false);
_prevButton->SetVisible(false);
_nextButton->SetVisible(false);
_finishButton->SetVisible(false);
}
else
{
// make room for the buttons at bottom
if (_currentSubPanel)
{
if( _showButtons )
{
_currentSubPanel->SetBounds(x, y, wide, tall - 35);
}
else
{
_currentSubPanel->SetBounds(x, y, wide, tall);
}
}
// align the buttons to the right hand side
GetSize(wide, tall);
int bwide, btall;
_cancelButton->GetSize(bwide, btall);
x = wide - (20 + bwide);
y = tall - (12 + btall);
_cancelButton->SetPos(x, y);
x -= (20 + bwide);
// only display one of the next or finish buttons (and only if both are visible)
if ( _showButtons )
{
if (_finishButton->IsEnabled() )
{
_nextButton->SetVisible(false);
_finishButton->SetVisible(true);
_finishButton->SetPos(x, y);
}
else
{
_nextButton->SetVisible(true);
_finishButton->SetVisible(false);
_nextButton->SetPos(x, y);
}
}
x -= (1 + bwide);
_prevButton->SetPos(x, y);
ResetDefaultButton();
}
}
//-----------------------------------------------------------------------------
// Purpose: if we don't show buttons then let the sub panel occupy the whole screen
//-----------------------------------------------------------------------------
void WizardPanel::GetClientArea(int &x, int &y, int &wide, int &tall)
{
if( _showButtons )
{
BaseClass::GetClientArea( x, y, wide, tall );
}
else
{
x = 0;
y = 0;
GetSize( wide, tall );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::Run(WizardSubPanel *startPanel)
{
// skip over sub panels if they don't want to be displayed
startPanel = FindNextValidSubPanel(startPanel);
// show it
ActivateNextSubPanel(startPanel);
// make sure we're set up and Run the first panel
Activate();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::ActivateBuildMode()
{
// no subpanel, no build mode
if (!_currentSubPanel)
return;
_currentSubPanel->ActivateBuildMode();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::ResetDefaultButton()
{
// work out which is the default button
if (_nextButton->IsEnabled())
{
_nextButton->SetAsDefaultButton(true);
}
else if (_finishButton->IsEnabled())
{
_finishButton->SetAsDefaultButton(true);
}
else if (_prevButton->IsEnabled())
{
_prevButton->SetAsDefaultButton(true);
}
/* Don't ever set the cancel button as the default, as it is too easy for users to quit the wizard without realizing
else if (_cancelButton->IsEnabled())
{
_cancelButton->SetAsDefaultButton(true);
}
*/
// reset them all (this may not be necessary)
_nextButton->InvalidateLayout();
_prevButton->InvalidateLayout();
_cancelButton->InvalidateLayout();
_finishButton->InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::ResetKeyFocus()
{
// set the focus on the default
FocusNavGroup &navGroup = GetFocusNavGroup();
Panel *def = navGroup.GetDefaultPanel();
if (def)
{
if (def->IsEnabled() && def->IsVisible())
{
def->RequestFocus();
}
else
{
def->RequestFocusNext();
}
}
ResetDefaultButton();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::CreateButtons()
{
_prevButton = new Button(this, "PrevButton", "");
_nextButton = new Button(this, "NextButton", "");
_cancelButton = new Button(this, "CancelButton", "");
_finishButton = new Button(this, "FinishButton", "");
_prevButton->SetCommand(new KeyValues("PrevButton"));
_nextButton->SetCommand(new KeyValues("NextButton"));
_cancelButton->SetCommand(new KeyValues("CancelButton"));
_finishButton->SetCommand(new KeyValues("FinishButton"));
SetNextButtonText(NULL);
SetPrevButtonText(NULL);
SetFinishButtonText(NULL);
SetCancelButtonText(NULL);
_prevButton->SetSize(82, 24);
_nextButton->SetSize(82, 24);
_cancelButton->SetSize(82, 24);
_finishButton->SetSize(82, 24);
}
//-----------------------------------------------------------------------------
// Purpose: clears all previous history
//-----------------------------------------------------------------------------
void WizardPanel::ResetHistory()
{
_subPanelStack.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::ActivateNextSubPanel(WizardSubPanel *subPanel)
{
// get rid of previous panel
WizardSubPanel *prevPanel = _currentSubPanel;
if (prevPanel && prevPanel->ShouldDisplayPanel())
{
// hide
prevPanel->SetVisible(false);
// push onto history stack
_subPanelStack.AddElement(_currentSubPanel);
}
// reenable all buttons, returning them to their default state
_prevButton->SetEnabled(true);
_nextButton->SetEnabled(true);
_cancelButton->SetEnabled(true);
_finishButton->SetEnabled(true);
if ( _showButtons )
{
_prevButton->SetVisible(true);
_cancelButton->SetVisible(true);
}
// set up new subpanel
_currentSubPanel = subPanel;
_currentSubPanel->SetParent(this);
_currentSubPanel->SetVisible(true);
_currentSubPanel->SetWizardPanel(this);
_currentSubPanel->OnDisplayAsNext();
_currentSubPanel->OnDisplay();
_currentSubPanel->InvalidateLayout(false);
SETUP_PANEL( _currentSubPanel );
int wide, tall;
if ( _currentSubPanel->GetDesiredSize(wide, tall) )
{
SetSize(wide, tall);
}
if (!prevPanel)
{
// no previous panel, so disable the back button
_prevButton->SetEnabled(false);
}
_currentSubPanel->RequestFocus();
RecalculateTabOrdering();
InvalidateLayout(false);
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Pops the last panel off the stack and runs it
//-----------------------------------------------------------------------------
void WizardPanel::ActivatePrevSubPanel()
{
_currentSubPanel->SetVisible(false);
WizardSubPanel *prevPanel = NULL;
if (_subPanelStack.GetCount())
{
// check to see if we need to jump back to a previous sub panel
WizardSubPanel *searchPanel = _currentSubPanel->GetPrevSubPanel();
if (searchPanel && _subPanelStack.HasElement(searchPanel))
{
// keep poping the stack till we find it
while (_subPanelStack.GetCount() && prevPanel != searchPanel)
{
prevPanel = _subPanelStack[_subPanelStack.GetCount() - 1];
_subPanelStack.RemoveElementAt(_subPanelStack.GetCount() - 1);
}
}
else
{
// just get the last one
prevPanel = _subPanelStack[_subPanelStack.GetCount() - 1];
_subPanelStack.RemoveElementAt(_subPanelStack.GetCount() - 1);
}
}
if (!prevPanel)
{
ivgui()->DPrintf2("Error: WizardPanel::ActivatePrevSubPanel(): no previous panel to go back to\n");
return;
}
// hide old panel
_currentSubPanel->SetVisible(false);
// reenable all buttons, returning them to their default state
_prevButton->SetEnabled(true);
_nextButton->SetEnabled(true);
_cancelButton->SetEnabled(true);
_finishButton->SetEnabled(true);
// Activate new panel
_currentSubPanel = prevPanel;
_currentSubPanel->RequestFocus();
_currentSubPanel->SetWizardPanel(this);
_currentSubPanel->OnDisplayAsPrev();
_currentSubPanel->OnDisplay();
_currentSubPanel->InvalidateLayout(false);
SETUP_PANEL( _currentSubPanel );
int wide, tall;
if ( _currentSubPanel->GetDesiredSize(wide, tall) )
{
SetSize(wide, tall);
}
// show the previous panel, but don't Activate it (since it should show just what it was previously)
_currentSubPanel->SetVisible(true);
if (!_subPanelStack.GetCount())
{
// no previous panel, so disable the back button
_prevButton->SetEnabled(false);
}
RecalculateTabOrdering();
InvalidateLayout(false);
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose: Sets up the new tab ordering
//-----------------------------------------------------------------------------
void WizardPanel::RecalculateTabOrdering()
{
if (_currentSubPanel)
{
_currentSubPanel->SetTabPosition(1);
}
_prevButton->SetTabPosition(2);
_nextButton->SetTabPosition(3);
_finishButton->SetTabPosition(4);
_cancelButton->SetTabPosition(5);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetNextButtonEnabled(bool state)
{
if (_nextButton->IsEnabled() != state)
{
_nextButton->SetEnabled(state);
InvalidateLayout(false);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetPrevButtonEnabled(bool state)
{
if (_prevButton->IsEnabled() != state)
{
_prevButton->SetEnabled(state);
InvalidateLayout(false);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetFinishButtonEnabled(bool state)
{
if (_finishButton->IsEnabled() != state)
{
_finishButton->SetEnabled(state);
InvalidateLayout(false);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetCancelButtonEnabled(bool state)
{
if (_cancelButton->IsEnabled() != state)
{
_cancelButton->SetEnabled(state);
InvalidateLayout(false);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetNextButtonVisible(bool state)
{
_nextButton->SetVisible(state);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetPrevButtonVisible(bool state)
{
_prevButton->SetVisible(state);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetFinishButtonVisible(bool state)
{
_finishButton->SetVisible(state);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetCancelButtonVisible(bool state)
{
_cancelButton->SetVisible(state);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetNextButtonText(const char *text)
{
if (text)
{
_nextButton->SetText(text);
}
else
{
_nextButton->SetText("#WizardPanel_Next");
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetPrevButtonText(const char *text)
{
if (text)
{
_prevButton->SetText(text);
}
else
{
_prevButton->SetText("#WizardPanel_Back");
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetFinishButtonText(const char *text)
{
if (text)
{
_finishButton->SetText(text);
}
else
{
_finishButton->SetText("#WizardPanel_Finish");
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::SetCancelButtonText(const char *text)
{
if (text)
{
_cancelButton->SetText(text);
}
else
{
_cancelButton->SetText("#WizardPanel_Cancel");
}
}
//-----------------------------------------------------------------------------
// Purpose: Finds the next panel that wants to be shown
//-----------------------------------------------------------------------------
WizardSubPanel *WizardPanel::FindNextValidSubPanel(WizardSubPanel *currentPanel)
{
// skip over sub panels if they don't want to be displayed
while (currentPanel)
{
currentPanel->SetWizardPanel(this);
if (currentPanel->ShouldDisplayPanel())
break;
// ok the panel wants to be skipped, so skip ahead
currentPanel = currentPanel->GetNextSubPanel();
}
return currentPanel;
}
//-----------------------------------------------------------------------------
// Purpose: Advances to the next panel
//-----------------------------------------------------------------------------
void WizardPanel::OnNextButton()
{
if (_currentSubPanel)
{
bool shouldAdvance = _currentSubPanel->OnNextButton();
if (shouldAdvance)
{
WizardSubPanel *nextPanel = FindNextValidSubPanel(_currentSubPanel->GetNextSubPanel());
if (nextPanel)
{
KeyValues *kv = new KeyValues("ActivateNextSubPanel");
kv->SetPtr("panel", nextPanel);
ivgui()->PostMessage(GetVPanel(), kv, GetVPanel());
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Retreats to the previous panel
//-----------------------------------------------------------------------------
void WizardPanel::OnPrevButton()
{
bool shouldRetreat = true;
if (_currentSubPanel)
{
shouldRetreat = _currentSubPanel->OnPrevButton();
}
if (shouldRetreat)
{
ActivatePrevSubPanel();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::OnFinishButton()
{
if (_currentSubPanel && _currentSubPanel->OnFinishButton())
{
// hide ourselves away
BaseClass::OnClose();
// automatically delete ourselves if marked to do so
if (IsAutoDeleteSet())
{
MarkForDeletion();
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardPanel::OnCancelButton()
{
if (_currentSubPanel && _currentSubPanel->OnCancelButton())
{
// hide ourselves away
BaseClass::OnClose();
if (IsAutoDeleteSet())
{
MarkForDeletion();
}
}
}
//-----------------------------------------------------------------------------
// Purpose: command handler for catching escape key presses
//-----------------------------------------------------------------------------
void WizardPanel::OnCommand(const char *command)
{
if (!stricmp(command, "Cancel"))
{
if (_cancelButton->IsEnabled())
{
_cancelButton->DoClick();
}
}
else
{
BaseClass::OnCommand(command);
}
}
//-----------------------------------------------------------------------------
// Purpose: Maps close button to cancel button
//-----------------------------------------------------------------------------
void WizardPanel::OnClose()
{
if (_cancelButton->IsEnabled())
{
_cancelButton->DoClick();
}
else if (_finishButton->IsEnabled())
{
_finishButton->DoClick();
}
// don't chain back
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
KeyValues *WizardPanel::GetWizardData()
{
return _currentData;
}
//-----------------------------------------------------------------------------
// Purpose: whether to show the next,prev,finish and cancel buttons
//-----------------------------------------------------------------------------
void WizardPanel::ShowButtons(bool state)
{
_showButtons = state; // hide the wizard panel buttons
SetNextButtonVisible( state );
SetPrevButtonVisible( state );
SetFinishButtonVisible( state );
SetCancelButtonVisible( state );
}
//-----------------------------------------------------------------------------
// Purpose: filters close buttons
//-----------------------------------------------------------------------------
void WizardPanel::OnCloseFrameButtonPressed()
{
// only allow close if the cancel button is enabled
if (_cancelButton->IsEnabled())
{
BaseClass::OnCloseFrameButtonPressed();
}
}
//-----------------------------------------------------------------------------
// Purpose: returns a page by name
//-----------------------------------------------------------------------------
WizardSubPanel *WizardPanel::GetSubPanelByName(const char *pageName)
{
return dynamic_cast<WizardSubPanel *>(FindChildByName(pageName));
}

View File

@ -0,0 +1,114 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "vgui_controls/WizardPanel.h"
#include "vgui_controls/WizardSubPanel.h"
#include "vgui_controls/BuildGroup.h"
#include "KeyValues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
#include <stdio.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
WizardSubPanel::WizardSubPanel(Panel *parent, const char *panelName) : EditablePanel(parent, panelName), _wizardPanel(NULL)
{
SetVisible(false);
m_iDesiredWide = 0;
m_iDesiredTall = 0;
SetBuildGroup(GetBuildGroup());
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
WizardSubPanel::~WizardSubPanel()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardSubPanel::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetBgColor(GetSchemeColor("WizardSubPanel.BgColor",pScheme));
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardSubPanel::GetSettings( KeyValues *outResourceData )
{
BaseClass::GetSettings(outResourceData);
outResourceData->SetInt("WizardWide", m_iDesiredWide);
outResourceData->SetInt("WizardTall", m_iDesiredTall);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void WizardSubPanel::ApplySettings(KeyValues *inResourceData)
{
// don't adjust visiblity during settings application (since it's our parent who really controls it)
bool bVisible = IsVisible();
BaseClass::ApplySettings(inResourceData);
m_iDesiredWide = inResourceData->GetInt("WizardWide", 0);
m_iDesiredTall = inResourceData->GetInt("WizardTall", 0);
if (GetWizardPanel() && m_iDesiredWide && m_iDesiredTall)
{
GetWizardPanel()->SetSize(m_iDesiredWide, m_iDesiredTall);
}
SetVisible(bVisible);
}
//-----------------------------------------------------------------------------
// Purpose: build mode description
//-----------------------------------------------------------------------------
const char *WizardSubPanel::GetDescription()
{
static char buf[1024];
_snprintf(buf, sizeof(buf), "%s, int WizardWide, int WizardTall", BaseClass::GetDescription());
return buf;
}
//-----------------------------------------------------------------------------
// Purpose: gets the size this subpanel would like the wizard to be
//-----------------------------------------------------------------------------
bool WizardSubPanel::GetDesiredSize(int &wide, int &tall)
{
wide = m_iDesiredWide;
tall = m_iDesiredTall;
return (m_iDesiredWide && m_iDesiredTall);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
KeyValues *WizardSubPanel::GetWizardData()
{
return GetWizardPanel()->GetWizardData();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
WizardSubPanel *WizardSubPanel::GetSiblingSubPanelByName(const char *pageName)
{
return GetWizardPanel()->GetSubPanelByName(pageName);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,72 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include <vgui_controls/Controls.h>
#include <locale.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern int g_nYou_Must_Add_Public_Vgui_Controls_Vgui_ControlsCpp_To_Your_Project;
namespace vgui
{
static char g_szControlsModuleName[256];
//-----------------------------------------------------------------------------
// Purpose: Initializes the controls
//-----------------------------------------------------------------------------
extern "C" { extern int _heapmin(); }
bool VGui_InitInterfacesList( const char *moduleName, CreateInterfaceFn *factoryList, int numFactories )
{
g_nYou_Must_Add_Public_Vgui_Controls_Vgui_ControlsCpp_To_Your_Project = 1;
// If you hit this error, then you need to include memoverride.cpp in the project somewhere or else
// you'll get crashes later when vgui_controls allocates KeyValues and vgui tries to delete them.
#if !defined(NO_MALLOC_OVERRIDE) && defined( WIN32 )
if ( _heapmin() != 1 )
{
Assert( false );
Error( "Must include memoverride.cpp in your project." );
}
#endif
// keep a record of this module name
strncpy(g_szControlsModuleName, moduleName, sizeof(g_szControlsModuleName));
g_szControlsModuleName[sizeof(g_szControlsModuleName) - 1] = 0;
// initialize our locale (must be done for every vgui dll/exe)
// "" makes it use the default locale, required to make iswprint() work correctly in different languages
setlocale(LC_CTYPE, "");
setlocale(LC_TIME, "");
setlocale(LC_COLLATE, "");
setlocale(LC_MONETARY, "");
// NOTE: Vgui expects to use these interfaces which are defined in tier3.lib
if ( !g_pVGui || !g_pVGuiInput || !g_pVGuiPanel ||
!g_pVGuiSurface || !g_pVGuiSchemeManager || !g_pVGuiSystem )
{
Warning( "vgui_controls is missing a required interface!\n" );
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: returns the name of the module this has been compiled into
//-----------------------------------------------------------------------------
const char *GetControlsModuleName()
{
return g_szControlsModuleName;
}
} // namespace vgui

View File

@ -0,0 +1,25 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "tier1/KeyValues.h"
#include <vgui/ISurface.h>
#include <vgui/IScheme.h>
#include <vgui_controls/cvartogglecheckbutton.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
vgui::Panel *Create_CvarToggleCheckButton()
{
return new CvarToggleCheckButton< ConVarRef >( NULL, NULL );
}
DECLARE_BUILD_FACTORY_CUSTOM_ALIAS( CvarToggleCheckButton<ConVarRef>, CvarToggleCheckButton, Create_CvarToggleCheckButton );

View File

@ -0,0 +1,647 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// List of perforce files and operations
//
//=============================================================================
#include "vgui_controls/perforcefilelistframe.h"
#include "tier1/KeyValues.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/ListPanel.h"
#include "vgui_controls/Splitter.h"
#include "vgui_controls/TextEntry.h"
#include "vgui_controls/MessageBox.h"
#include "tier2/tier2.h"
#include "p4lib/ip4.h"
#include "filesystem.h"
#include "vgui/IVGui.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Sort by asset name
//-----------------------------------------------------------------------------
static int __cdecl OperationSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
{
const char *string1 = item1.kv->GetString("operation");
const char *string2 = item2.kv->GetString("operation");
int nRetVal = Q_stricmp( string1, string2 );
if ( nRetVal != 0 )
return nRetVal;
string1 = item1.kv->GetString("filename");
string2 = item2.kv->GetString("filename");
return Q_stricmp( string1, string2 );
}
static int __cdecl FileBrowserSortFunc( vgui::ListPanel *pPanel, const vgui::ListPanelItem &item1, const vgui::ListPanelItem &item2 )
{
const char *string1 = item1.kv->GetString("filename");
const char *string2 = item2.kv->GetString("filename");
return Q_stricmp( string1, string2 );
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
COperationFileListFrame::COperationFileListFrame( vgui::Panel *pParent, const char *pTitle, const char *pColumnHeader, bool bShowDescription, bool bShowOkOnly, int nDialogID ) :
BaseClass( pParent, "PerforceFileList" )
{
m_pText = NULL;
vgui::Panel *pBrowserParent = this;
m_pDescription = NULL;
m_pSplitter = NULL;
if ( bShowDescription )
{
m_pSplitter = new vgui::Splitter( this, "Splitter", vgui::SPLITTER_MODE_HORIZONTAL, 1 );
pBrowserParent = m_pSplitter->GetChild( 0 );
vgui::Panel *pDescParent = m_pSplitter->GetChild( 1 );
m_pDescription = new vgui::TextEntry( pDescParent, "Description" );
m_pDescription->SetMultiline( true );
m_pDescription->SetCatchEnterKey( true );
m_pDescription->SetText( "<enter description here>" );
}
// FIXME: Might be nice to have checkboxes per row
m_pFileBrowser = new vgui::ListPanel( pBrowserParent, "Browser" );
m_pFileBrowser->AddColumnHeader( 0, "operation", "Operation", 52, 0 );
m_pFileBrowser->AddColumnHeader( 1, "filename", pColumnHeader, 128, vgui::ListPanel::COLUMN_RESIZEWITHWINDOW );
m_pFileBrowser->SetSelectIndividualCells( false );
m_pFileBrowser->SetMultiselectEnabled( false );
m_pFileBrowser->SetEmptyListText( "No Perforce Operations" );
m_pFileBrowser->SetDragEnabled( true );
m_pFileBrowser->AddActionSignalTarget( this );
m_pFileBrowser->SetSortFunc( 0, OperationSortFunc );
m_pFileBrowser->SetSortFunc( 1, FileBrowserSortFunc );
m_pFileBrowser->SetSortColumn( 0 );
m_pYesButton = new vgui::Button( this, "YesButton", "Yes", this, "Yes" );
m_pNoButton = new vgui::Button( this, "NoButton", "No", this, "No" );
SetBlockDragChaining( true );
SetDeleteSelfOnClose( true );
if ( bShowDescription )
{
LoadControlSettingsAndUserConfig( "resource/perforcefilelistdescription.res", nDialogID );
}
else
{
LoadControlSettingsAndUserConfig( "resource/perforcefilelist.res", nDialogID );
}
if ( bShowOkOnly )
{
m_pYesButton->SetText( "#MessageBox_OK" );
m_pNoButton->SetVisible( false );
}
m_pContextKeyValues = NULL;
SetTitle( pTitle, false );
}
COperationFileListFrame::~COperationFileListFrame()
{
SaveUserConfig();
CleanUpMessage();
if ( m_pText )
{
delete[] m_pText;
}
}
//-----------------------------------------------------------------------------
// Deletes the message
//-----------------------------------------------------------------------------
void COperationFileListFrame::CleanUpMessage()
{
if ( m_pContextKeyValues )
{
m_pContextKeyValues->deleteThis();
m_pContextKeyValues = NULL;
}
}
//-----------------------------------------------------------------------------
// Performs layout
//-----------------------------------------------------------------------------
void COperationFileListFrame::PerformLayout()
{
BaseClass::PerformLayout();
if ( m_pSplitter )
{
int x, y, w, h;
GetClientArea( x, y, w, h );
y += 6;
h -= 36;
m_pSplitter->SetBounds( x, y, w, h );
}
}
//-----------------------------------------------------------------------------
// Adds files to the frame
//-----------------------------------------------------------------------------
void COperationFileListFrame::ClearAllOperations()
{
m_pFileBrowser->RemoveAll();
}
//-----------------------------------------------------------------------------
// Adds the strings to the list panel
//-----------------------------------------------------------------------------
void COperationFileListFrame::AddOperation( const char *pOperation, const char *pFileName )
{
KeyValues *kv = new KeyValues( "node", "filename", pFileName );
kv->SetString( "operation", pOperation );
m_pFileBrowser->AddItem( kv, 0, false, false );
}
void COperationFileListFrame::AddOperation( const char *pOperation, const char *pFileName, const Color& clr )
{
KeyValues *kv = new KeyValues( "node", "filename", pFileName );
kv->SetString( "operation", pOperation );
kv->SetColor( "cellcolor", clr );
m_pFileBrowser->AddItem( kv, 0, false, false );
}
//-----------------------------------------------------------------------------
// Resizes the operation column to fit the operation text
//-----------------------------------------------------------------------------
void COperationFileListFrame::ResizeOperationColumnToContents()
{
m_pFileBrowser->ResizeColumnToContents( 0 );
}
//-----------------------------------------------------------------------------
// Sets the column header for the 'operation' column
//-----------------------------------------------------------------------------
void COperationFileListFrame::SetOperationColumnHeaderText( const char *pText )
{
m_pFileBrowser->SetColumnHeaderText( 0, pText );
}
//-----------------------------------------------------------------------------
// Adds the strings to the list panel
//-----------------------------------------------------------------------------
void COperationFileListFrame::DoModal( KeyValues *pContextKeyValues, const char *pMessage )
{
m_MessageName = pMessage ? pMessage : "OperationConfirmed";
CleanUpMessage();
m_pContextKeyValues = pContextKeyValues;
m_pFileBrowser->SortList();
if ( m_pNoButton->IsVisible() )
{
m_pYesButton->SetEnabled( m_pFileBrowser->GetItemCount() != 0 );
}
BaseClass::DoModal();
}
//-----------------------------------------------------------------------------
// Retrieves the number of files, the file names, and operations
//-----------------------------------------------------------------------------
int COperationFileListFrame::GetOperationCount()
{
return m_pFileBrowser->GetItemCount();
}
const char *COperationFileListFrame::GetFileName( int i )
{
int nItemId = m_pFileBrowser->GetItemIDFromRow( i );
KeyValues *pKeyValues = m_pFileBrowser->GetItem( nItemId );
return pKeyValues->GetString( "filename" );
}
const char *COperationFileListFrame::GetOperation( int i )
{
int nItemId = m_pFileBrowser->GetItemIDFromRow( i );
KeyValues *pKeyValues = m_pFileBrowser->GetItem( nItemId );
return pKeyValues->GetString( "operation" );
}
//-----------------------------------------------------------------------------
// Retreives the description (only if it was shown)
//-----------------------------------------------------------------------------
const char *COperationFileListFrame::GetDescription()
{
return m_pText;
}
//-----------------------------------------------------------------------------
// Returns the message name
//-----------------------------------------------------------------------------
const char *COperationFileListFrame::CompletionMessage()
{
return m_MessageName;
}
//-----------------------------------------------------------------------------
// On command
//-----------------------------------------------------------------------------
void COperationFileListFrame::OnCommand( const char *pCommand )
{
if ( !Q_stricmp( pCommand, "Yes" ) )
{
if ( m_pDescription )
{
int nLen = m_pDescription->GetTextLength() + 1;
m_pText = new char[ nLen ];
m_pDescription->GetText( m_pText, nLen );
}
KeyValues *pActionKeys;
if ( PerformOperation() )
{
pActionKeys = new KeyValues( CompletionMessage(), "operationPerformed", 1 );
}
else
{
pActionKeys = new KeyValues( CompletionMessage(), "operationPerformed", 0 );
}
if ( m_pContextKeyValues )
{
pActionKeys->AddSubKey( m_pContextKeyValues );
m_pContextKeyValues = NULL;
}
CloseModal();
PostActionSignal( pActionKeys );
return;
}
if ( !Q_stricmp( pCommand, "No" ) )
{
KeyValues *pActionKeys = new KeyValues( CompletionMessage(), "operationPerformed", 0 );
if ( m_pContextKeyValues )
{
pActionKeys->AddSubKey( m_pContextKeyValues );
m_pContextKeyValues = NULL;
}
CloseModal();
PostActionSignal( pActionKeys );
return;
}
BaseClass::OnCommand( pCommand );
}
//-----------------------------------------------------------------------------
//
// Version that does the work of perforce actions
//
//-----------------------------------------------------------------------------
CPerforceFileListFrame::CPerforceFileListFrame( vgui::Panel *pParent, const char *pTitle, const char *pColumnHeader, PerforceAction_t action ) :
BaseClass( pParent, pTitle, pColumnHeader, (action == PERFORCE_ACTION_FILE_SUBMIT), false, OPERATION_DIALOG_ID_PERFORCE )
{
m_Action = action;
}
CPerforceFileListFrame::~CPerforceFileListFrame()
{
}
//-----------------------------------------------------------------------------
// Activates the modal dialog
//-----------------------------------------------------------------------------
void CPerforceFileListFrame::DoModal( KeyValues *pContextKeys, const char *pMessage )
{
BaseClass::DoModal( pContextKeys, pMessage ? pMessage : "PerforceActionConfirmed" );
}
//-----------------------------------------------------------------------------
// Adds a file for open
//-----------------------------------------------------------------------------
void CPerforceFileListFrame::AddFileForOpen( const char *pFullPath )
{
if ( !p4 )
return;
bool bIsInPerforce = p4->IsFileInPerforce( pFullPath );
bool bIsOpened = ( p4->GetFileState( pFullPath ) != P4FILE_UNOPENED );
switch( m_Action )
{
case PERFORCE_ACTION_FILE_ADD:
if ( !bIsInPerforce && !bIsOpened )
{
AddOperation( "Add", pFullPath );
}
break;
case PERFORCE_ACTION_FILE_EDIT:
if ( bIsInPerforce && !bIsOpened )
{
AddOperation( "Edit", pFullPath );
}
break;
case PERFORCE_ACTION_FILE_DELETE:
if ( bIsInPerforce && !bIsOpened )
{
AddOperation( "Delete", pFullPath );
}
break;
}
}
//-----------------------------------------------------------------------------
// Add files to dialog for submit/revert dialogs
//-----------------------------------------------------------------------------
void CPerforceFileListFrame::AddFileForSubmit( const char *pFullPath, P4FileState_t state )
{
if ( state == P4FILE_UNOPENED )
return;
char pBuf[128];
const char *pPrefix = (m_Action == PERFORCE_ACTION_FILE_REVERT) ? "Revert" : "Submit";
switch( state )
{
case P4FILE_OPENED_FOR_ADD:
Q_snprintf( pBuf, sizeof(pBuf), "%s Add", pPrefix );
AddOperation( pBuf, pFullPath );
break;
case P4FILE_OPENED_FOR_EDIT:
Q_snprintf( pBuf, sizeof(pBuf), "%s Edit", pPrefix );
AddOperation( pBuf, pFullPath );
break;
case P4FILE_OPENED_FOR_DELETE:
Q_snprintf( pBuf, sizeof(pBuf), "%s Delete", pPrefix );
AddOperation( pBuf, pFullPath );
break;
case P4FILE_OPENED_FOR_INTEGRATE:
Q_snprintf( pBuf, sizeof(pBuf), "%s Integrate", pPrefix );
AddOperation( pBuf, pFullPath );
break;
}
}
//-----------------------------------------------------------------------------
// Version of AddFile that accepts full paths
//-----------------------------------------------------------------------------
void CPerforceFileListFrame::AddFile( const char *pFullPath )
{
if ( !p4 )
return;
if ( m_Action < PERFORCE_ACTION_FILE_REVERT )
{
// If the file wasn't found on the disk, then abort
if ( g_pFullFileSystem->FileExists( pFullPath, NULL ) )
{
AddFileForOpen( pFullPath );
}
return;
}
// Deal with submit, revert
bool bFileExists = g_pFullFileSystem->FileExists( pFullPath, NULL );
P4FileState_t state = p4->GetFileState( pFullPath );
if ( bFileExists || (state == P4FILE_OPENED_FOR_DELETE) )
{
AddFileForSubmit( pFullPath, state );
}
}
//-----------------------------------------------------------------------------
// Version of AddFile that accepts relative paths + search path ids
//-----------------------------------------------------------------------------
void CPerforceFileListFrame::AddFile( const char *pRelativePath, const char *pPathId )
{
if ( !p4 )
return;
// Deal with add, open, edit
if ( m_Action < PERFORCE_ACTION_FILE_REVERT )
{
// If the file wasn't found on the disk, then abort
if ( g_pFullFileSystem->FileExists( pRelativePath, pPathId ) )
{
char pFullPath[MAX_PATH];
g_pFullFileSystem->RelativePathToFullPath( pRelativePath, pPathId, pFullPath, sizeof( pFullPath ) );
AddFileForOpen( pFullPath );
}
return;
}
// Deal with submit, revert
// First, handle the case where the file exists on the drive
char pFullPath[MAX_PATH];
if ( g_pFullFileSystem->FileExists( pRelativePath, pPathId ) )
{
g_pFullFileSystem->RelativePathToFullPath( pRelativePath, pPathId, pFullPath, sizeof( pFullPath ) );
P4FileState_t state = p4->GetFileState( pFullPath );
AddFileForSubmit( pFullPath, state );
return;
}
// Get the list of opened files, cache it off so we aren't continually reasking
if ( Q_stricmp( pPathId, m_LastOpenedFilePathId ) )
{
p4->GetOpenedFileListInPath( pPathId, m_OpenedFiles );
m_LastOpenedFilePathId = pPathId;
}
// If the file doesn't exist, it was opened for delete.
// Using the client spec of the path, we need to piece together
// the full path; the full path unfortunately is usually ambiguous:
// you can never exactly know which mod it came from.
char pTemp[MAX_PATH];
char pSearchString[MAX_PATH];
Q_strncpy( pSearchString, pRelativePath, sizeof(pSearchString) );
Q_FixSlashes( pSearchString );
int k;
int nOpenedFileCount = m_OpenedFiles.Count();
for ( k = 0; k < nOpenedFileCount; ++k )
{
if ( m_OpenedFiles[k].m_eOpenState != P4FILE_OPENED_FOR_DELETE )
continue;
// Check to see if the end of the local file matches the file
const char *pLocalFile = p4->String( m_OpenedFiles[k].m_sLocalFile );
// This ensures the full path lies under the search path
if ( !g_pFullFileSystem->FullPathToRelativePathEx( pLocalFile, pPathId, pTemp, sizeof(pTemp) ) )
continue;
// The relative paths had better be the same
if ( Q_stricmp( pTemp, pSearchString ) )
continue;
AddFileForSubmit( pLocalFile, m_OpenedFiles[k].m_eOpenState );
break;
}
}
//-----------------------------------------------------------------------------
// Does the perforce operation
//-----------------------------------------------------------------------------
bool CPerforceFileListFrame::PerformOperation( )
{
if ( !p4 )
return false;
int nFileCount = GetOperationCount();
const char **ppFileNames = (const char**)_alloca( nFileCount * sizeof(char*) );
for ( int i = 0; i < nFileCount; ++i )
{
ppFileNames[i] = GetFileName( i );
}
bool bSuccess = false;
switch ( m_Action )
{
case PERFORCE_ACTION_FILE_ADD:
bSuccess = p4->OpenFilesForAdd( nFileCount, ppFileNames );
break;
case PERFORCE_ACTION_FILE_EDIT:
bSuccess = p4->OpenFilesForEdit( nFileCount, ppFileNames );
break;
case PERFORCE_ACTION_FILE_DELETE:
bSuccess = p4->OpenFilesForDelete( nFileCount, ppFileNames );
break;
case PERFORCE_ACTION_FILE_REVERT:
bSuccess = p4->RevertFiles( nFileCount, ppFileNames );
break;
case PERFORCE_ACTION_FILE_SUBMIT:
{
// Ensure a description was added
const char *pDescription = GetDescription();
if ( !pDescription[0] || !Q_stricmp( pDescription, "<enter description here>" ) )
{
vgui::MessageBox *pError = new vgui::MessageBox( "Submission Error!", "Description required for submission.", GetParent() );
pError->SetSmallCaption( true );
pError->DoModal();
return false;
}
else
{
bSuccess = p4->SubmitFiles( nFileCount, ppFileNames, pDescription );
}
}
break;
}
const char *pErrorString = p4->GetLastError();
if ( !bSuccess )
{
vgui::MessageBox *pError = new vgui::MessageBox( "Perforce Error!", pErrorString, GetParent() );
pError->SetSmallCaption( true );
pError->DoModal();
}
#if 0
if ( *pErrorString )
{
if ( V_strstr( pErrorString, "opened for add" ) )
return bSuccess;
if ( V_strstr( pErrorString, "opened for edit" ) )
return bSuccess;
// TODO - figure out the rest of these...
const char *pPrefix = "Perforce has generated the following message which may or may not be an error.\n"
"Please email joe with the text of the message, whether you think it was an error, and what perforce operation you where performing.\n"
"To copy the message, hit ~ to enter the console, where you will find the message reprinted.\n"
"Select the lines of text in the message, right click, select Copy, and then paste into an email message.\n\n";
static int nPrefixLen = V_strlen( pPrefix );
int nErrorStringLength = V_strlen( pErrorString );
char *pMsg = (char*)_alloca( nPrefixLen + nErrorStringLength + 1 );
V_strcpy( pMsg, pPrefix );
V_strcpy( pMsg + nPrefixLen, pErrorString );
vgui::MessageBox *pError = new vgui::MessageBox( "Dubious Perforce Message", pMsg, GetParent() );
pError->SetSmallCaption( true );
pError->DoModal();
}
#endif
return bSuccess;
}
//-----------------------------------------------------------------------------
// Show the perforce query dialog
//-----------------------------------------------------------------------------
void ShowPerforceQuery( vgui::Panel *pParent, const char *pFileName, vgui::Panel *pActionSignalTarget, KeyValues *pKeyValues, PerforceAction_t actionFilter )
{
if ( !p4 )
{
KeyValues *pSpoofKeys = new KeyValues( "PerforceQueryCompleted", "operationPerformed", 1 );
if ( pKeyValues )
{
pSpoofKeys->AddSubKey( pKeyValues );
}
vgui::ivgui()->PostMessage( pActionSignalTarget->GetVPanel(), pSpoofKeys, 0 );
return;
}
// Refresh the current perforce settings
p4->RefreshActiveClient();
PerforceAction_t action = PERFORCE_ACTION_NONE;
const char *pTitle = NULL;
if ( !p4->IsFileInPerforce( pFileName ) )
{
// If the file isn't in perforce, ask to add it
action = PERFORCE_ACTION_FILE_ADD;
pTitle = "Add File to Perforce?";
}
else if ( p4->GetFileState( pFileName ) == P4FILE_UNOPENED )
{
// If the file isn't checked out yet, ask to check it out
action = PERFORCE_ACTION_FILE_EDIT;
pTitle = "Check Out File from Perforce?";
}
if ( ( action == PERFORCE_ACTION_NONE ) || ( ( actionFilter != PERFORCE_ACTION_NONE ) && ( actionFilter != action ) ) )
{
// Spoof a completion event
KeyValues *pSpoofKeys = new KeyValues( "PerforceQueryCompleted", "operationPerformed", 1 );
if ( pKeyValues )
{
pSpoofKeys->AddSubKey( pKeyValues );
}
vgui::ivgui()->PostMessage( pActionSignalTarget->GetVPanel(), pSpoofKeys, 0 );
return;
}
CPerforceFileListFrame *pQuery = new CPerforceFileListFrame( pParent, pTitle, "File", action );
pQuery->AddFile( pFileName );
if ( pActionSignalTarget )
{
pQuery->AddActionSignalTarget( pActionSignalTarget );
}
pQuery->DoModal( pKeyValues, "PerforceQueryCompleted" );
}

View File

@ -0,0 +1,195 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Core Movie Maker UI API
//
//=============================================================================
#include "vgui_controls/savedocumentquery.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/Label.h"
#include "vgui_controls/Frame.h"
#include "vgui/ISurface.h"
#include "vgui/IVGui.h"
#include "tier1/KeyValues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// This dialog asks if you want to save your work
//-----------------------------------------------------------------------------
class CSaveDocumentQuery : public vgui::Frame
{
DECLARE_CLASS_SIMPLE( CSaveDocumentQuery, vgui::Frame );
public:
CSaveDocumentQuery( vgui::Panel *pParent, const char *filename, const char *pFileType, int nContext,
vgui::Panel *pActionSignalTarget = 0, KeyValues *pKeyValues = 0 );
~CSaveDocumentQuery();
// Inherited from vgui::Frame
virtual void OnCommand( char const *cmd );
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
// Put the message box into a modal state
void DoModal();
private:
// Posts commands to the action signal target
void PostCommand( const char *pCommand );
vgui::Label *m_pMessageLabel;
vgui::Button *m_pYesButton;
vgui::Button *m_pNoButton;
vgui::Button *m_pCancelButton;
vgui::Panel *m_pActionSignalTarget;
char m_szFileName[ 256 ];
char m_szFileType[ 256 ];
int m_nContext;
KeyValues* m_pPostSaveKeyValues;
};
//-----------------------------------------------------------------------------
// Show the save document query dialog
//-----------------------------------------------------------------------------
void ShowSaveDocumentQuery( vgui::Panel *pParent, const char *pFileName, const char *pFileType, int nContext, vgui::Panel *pActionSignalTarget, KeyValues *pPostSaveCommand )
{
CSaveDocumentQuery *query = new CSaveDocumentQuery( pParent, pFileName, pFileType, nContext, pActionSignalTarget, pPostSaveCommand );
query->SetSmallCaption( true );
query->DoModal();
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CSaveDocumentQuery::CSaveDocumentQuery( vgui::Panel *pParent, char const *pFileName, const char *pFileType, int nContext, vgui::Panel *pActionSignalTarget, KeyValues *pPostSaveCommand ) :
BaseClass( pParent, "SaveDocumentQuery" ),
m_nContext( nContext ),
m_pActionSignalTarget( pActionSignalTarget )
{
if ( !pFileName || !pFileName[0] )
{
pFileName = "<untitled>";
}
Q_strncpy( m_szFileName, pFileName, sizeof( m_szFileName ) );
Q_strncpy( m_szFileType, pFileType, sizeof( m_szFileType ) );
m_pPostSaveKeyValues = pPostSaveCommand;
SetDeleteSelfOnClose(true);
SetMenuButtonResponsive(false);
SetMinimizeButtonVisible(false);
SetCloseButtonVisible(false);
SetSizeable(false);
SetTitle( "Save Changes", true );
m_pMessageLabel = new Label( this, "FileNameLabel", "" );
m_pYesButton = new Button( this, "Yes", "Yes", this, "yes" );
m_pNoButton = new Button( this, "No", "No", this, "no" );
m_pCancelButton = new Button( this, "Cancel", "Cancel", this, "cancel" );
LoadControlSettings( "resource/ToolSaveDocumentQuery.res" );
m_pMessageLabel->SetText( m_szFileName );
}
CSaveDocumentQuery::~CSaveDocumentQuery()
{
if ( m_pPostSaveKeyValues )
{
m_pPostSaveKeyValues->deleteThis();
m_pPostSaveKeyValues = NULL;
}
}
//-----------------------------------------------------------------------------
// Posts commands to the action signal target
//-----------------------------------------------------------------------------
void CSaveDocumentQuery::PostCommand( const char *pCommand )
{
KeyValues *kv = new KeyValues( pCommand );
vgui::ivgui()->PostMessage( m_pActionSignalTarget->GetVPanel(), kv, 0 );
}
//-----------------------------------------------------------------------------
// Process commands
//-----------------------------------------------------------------------------
void CSaveDocumentQuery::OnCommand( char const *cmd )
{
if ( !Q_stricmp( cmd, "yes" ) )
{
KeyValues *kv = new KeyValues( "OnSaveFile" );
kv->SetString( "filename", m_szFileName );
kv->SetString( "filetype", m_szFileType );
kv->SetInt( "context", m_nContext );
kv->SetPtr( "actionTarget", m_pActionSignalTarget );
if ( m_pPostSaveKeyValues )
{
kv->AddSubKey( m_pPostSaveKeyValues->MakeCopy() );
}
vgui::ivgui()->PostMessage( m_pActionSignalTarget->GetVPanel(), kv, 0 );
MarkForDeletion();
}
else if ( !Q_stricmp( cmd, "no" ) )
{
PostCommand( "OnMarkNotDirty" );
if ( m_pPostSaveKeyValues )
{
vgui::ivgui()->PostMessage( m_pActionSignalTarget->GetVPanel(), m_pPostSaveKeyValues->MakeCopy(), 0 );
}
MarkForDeletion();
}
else if ( !Q_stricmp( cmd, "cancel" ) )
{
PostCommand( "OnCancelSaveDocument" );
MarkForDeletion();
}
else
{
BaseClass::OnCommand( cmd );
}
}
//-----------------------------------------------------------------------------
// Deal with scheme
//-----------------------------------------------------------------------------
void CSaveDocumentQuery::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
int wide, tall;
GetSize( wide, tall );
int swide, stall;
surface()->GetScreenSize(swide, stall);
// put the dialog in the middle of the screen
SetPos((swide - wide) / 2, (stall - tall) / 2);
}
//-----------------------------------------------------------------------------
// Put the message box into a modal state
//-----------------------------------------------------------------------------
void CSaveDocumentQuery::DoModal()
{
SetVisible( true );
SetEnabled( true );
MoveToFront();
RequestFocus();
InvalidateLayout();
}

View File

@ -0,0 +1,212 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "vgui_controls/subrectimage.h"
#include "tier0/dbg.h"
#include "vgui/ISurface.h"
#include "vgui_controls/Controls.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
using namespace vgui;
// Officially the invalid texture ID is zero, but -1 is used in many
// places, and changing it carries some risk. Adding a named constant
// for this file avoids warnings and makes future changes easier.
const HTexture SUBRECT_INVALID_TEXTURE = (HTexture)-1;
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CSubRectImage::CSubRectImage( const char *filename, bool hardwareFiltered, int subx, int suby, int subw, int subh )
{
SetSize( subw, subh );
sub[ 0 ] = subx;
sub[ 1 ] = suby;
sub[ 2 ] = subw;
sub[ 3 ] = subh;
_filtered = hardwareFiltered;
// HACKHACK - force VGUI materials to be in the vgui/ directory
// This needs to be revisited once GoldSRC is grandfathered off.
//!! need to make this work with goldsrc
int size = strlen(filename) + 1 + strlen("vgui/");
_filename = (char *)malloc( size );
Assert( _filename );
Q_snprintf( _filename, size, "vgui/%s", filename );
_id = SUBRECT_INVALID_TEXTURE;
_uploaded = false;
_color = Color(255, 255, 255, 255);
_pos[0] = _pos[1] = 0;
_valid = true;
_wide = subw;
_tall = subh;
ForceUpload();
}
CSubRectImage::~CSubRectImage()
{
if ( vgui::surface() && _id != SUBRECT_INVALID_TEXTURE )
{
vgui::surface()->DestroyTextureID( _id );
_id = SUBRECT_INVALID_TEXTURE;
}
if ( _filename )
{
free( _filename );
}
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void CSubRectImage::GetSize(int &wide, int &tall)
{
wide = _wide;
tall = _tall;
}
//-----------------------------------------------------------------------------
// Purpose: size of the bitmap
//-----------------------------------------------------------------------------
void CSubRectImage::GetContentSize(int &wide, int &tall)
{
wide = 0;
tall = 0;
if (!_valid)
return;
if ( _id != SUBRECT_INVALID_TEXTURE )
{
surface()->DrawGetTextureSize(_id, wide, tall);
}
}
//-----------------------------------------------------------------------------
// Purpose: ignored
//-----------------------------------------------------------------------------
void CSubRectImage::SetSize(int x, int y)
{
_wide = x;
_tall = y;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void CSubRectImage::SetPos(int x, int y)
{
_pos[0] = x;
_pos[1] = y;
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void CSubRectImage::SetColor(Color col)
{
_color = col;
}
//-----------------------------------------------------------------------------
// Purpose: returns the file name of the bitmap
//-----------------------------------------------------------------------------
const char *CSubRectImage::GetName()
{
return _filename;
}
//-----------------------------------------------------------------------------
// Purpose: Renders the loaded image, uploading it if necessary
// Assumes a valid image is always returned from uploading
//-----------------------------------------------------------------------------
void CSubRectImage::Paint()
{
if ( !_valid )
return;
// if we don't have an _id then lets make one
if ( _id == SUBRECT_INVALID_TEXTURE )
{
_id = surface()->CreateNewTextureID();
}
// if we have not uploaded yet, lets go ahead and do so
if ( !_uploaded )
{
ForceUpload();
}
// set the texture current, set the color, and draw the biatch
surface()->DrawSetColor( _color[0], _color[1], _color[2], _color[3] );
surface()->DrawSetTexture( _id );
if ( _wide == 0 || _tall == 0 )
return;
int cw, ch;
GetContentSize( cw, ch );
if ( cw == 0 || ch == 0 )
return;
float s[ 2 ];
float t[ 2 ];
s[ 0 ] = (float)sub[ 0 ] / (float)cw;
s[ 1 ] = (float)(sub[ 0 ]+sub[ 2 ]) / (float)cw;
t[ 0 ] = (float)sub[ 1 ] / (float)ch;
t[ 1 ] = (float)(sub[ 1 ]+sub[ 3 ]) / (float)ch;
surface()->DrawTexturedSubRect(
_pos[0],
_pos[1],
_pos[0] + _wide,
_pos[1] + _tall,
s[ 0 ],
t[ 0 ],
s[ 1 ],
t[ 1 ] );
}
//-----------------------------------------------------------------------------
// Purpose: ensures the bitmap has been uploaded
//-----------------------------------------------------------------------------
void CSubRectImage::ForceUpload()
{
if ( !_valid || _uploaded )
return;
if ( _id == SUBRECT_INVALID_TEXTURE )
{
_id = surface()->CreateNewTextureID( false );
}
surface()->DrawSetTextureFile( _id, _filename, _filtered, false );
_uploaded = true;
_valid = surface()->IsTextureIDValid( _id );
}
//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
HTexture CSubRectImage::GetID()
{
return _id;
}
bool CSubRectImage::IsValid()
{
return _valid;
}

View File

@ -0,0 +1,198 @@
//-----------------------------------------------------------------------------
// VGUI_CONTROLS.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR "..\.."
$Macro GENERATED_PROTO_DIR "generated_proto"
$macro PROTOBUF_LITE 0
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$include "$SRCDIR\vpc_scripts\protobuf_builder.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE;$SRCDIR\thirdparty;$SRCDIR\thirdparty\cef;$GENERATED_PROTO_DIR"
}
}
$Project "vgui_controls"
{
$Folder "Source Files"
{
$File "AnalogBar.cpp"
$File "AnimatingImagePanel.cpp"
$File "AnimationController.cpp"
$File "BitmapImagePanel.cpp"
$File "BuildFactoryHelper.cpp"
$File "BuildGroup.cpp"
$File "BuildModeDialog.cpp"
$File "Button.cpp"
$File "CheckButton.cpp"
$File "CheckButtonList.cpp"
$File "CircularProgressBar.cpp"
$File "ComboBox.cpp"
$File "consoledialog.cpp"
$File "ControllerMap.cpp"
$File "controls.cpp"
$File "CvarToggleCheckButton.cpp"
$File "DirectorySelectDialog.cpp"
$File "Divider.cpp"
$File "EditablePanel.cpp"
$File "ExpandButton.cpp"
$File "FileOpenDialog.cpp"
$File "FileOpenStateMachine.cpp"
$File "$SRCDIR\public\filesystem_helpers.cpp"
$File "FocusNavGroup.cpp"
$File "Frame.cpp"
$File "GraphPanel.cpp"
$File "HTML.cpp"
$File "Image.cpp"
$File "ImageList.cpp"
$File "ImagePanel.cpp"
$File "InputDialog.cpp"
$File "KeyBindingHelpDialog.cpp"
$File "KeyBoardEditorDialog.cpp"
$File "KeyRepeat.cpp"
$File "Label.cpp"
$File "ListPanel.cpp"
$File "ListViewPanel.cpp"
$File "Menu.cpp"
$File "MenuBar.cpp"
$File "MenuButton.cpp"
$File "MenuItem.cpp"
$File "MessageBox.cpp"
$File "MessageDialog.cpp"
$File "Panel.cpp"
$File "PanelListPanel.cpp"
$File "PerforceFileExplorer.cpp"
$File "PerforceFileList.cpp"
$File "perforcefilelistframe.cpp"
$File "ProgressBar.cpp"
$File "ProgressBox.cpp"
$File "PropertyDialog.cpp"
$File "PropertyPage.cpp"
$File "PropertySheet.cpp"
$File "QueryBox.cpp"
$File "RadioButton.cpp"
$File "RichText.cpp"
$File "RotatingProgressBar.cpp"
$File "savedocumentquery.cpp"
$File "ScalableImagePanel.cpp"
$File "ScrollableEditablePanel.cpp"
$File "ScrollBar.cpp"
$File "ScrollBarSlider.cpp"
$File "SectionedListPanel.cpp"
$File "Slider.cpp"
$File "Splitter.cpp"
$File "subrectimage.cpp"
$File "TextEntry.cpp"
$File "TextImage.cpp"
$File "ToggleButton.cpp"
$File "Tooltip.cpp"
$File "ToolWindow.cpp"
$File "TreeView.cpp"
$File "TreeViewListControl.cpp"
$File "URLLabel.cpp"
$File "WizardPanel.cpp"
$File "WizardSubPanel.cpp"
$File "$SRCDIR/vgui2/src/vgui_key_translation.cpp"
}
$Folder "Public Header Files"
{
$File "$SRCDIR\public\vgui_controls\AnalogBar.h"
$File "$SRCDIR\public\vgui_controls\AnimatingImagePanel.h"
$File "$SRCDIR\public\vgui_controls\AnimationController.h"
$File "$SRCDIR\public\vgui_controls\BitmapImagePanel.h"
$File "$SRCDIR\public\vgui_controls\BuildGroup.h"
$File "$SRCDIR\public\vgui_controls\BuildModeDialog.h"
$File "$SRCDIR\public\vgui_controls\Button.h"
$File "$SRCDIR\public\vgui_controls\CheckButton.h"
$File "$SRCDIR\public\vgui_controls\CheckButtonList.h"
$File "$SRCDIR\public\vgui_controls\CircularProgressBar.h"
$File "$SRCDIR\public\Color.h"
$File "$SRCDIR\public\vgui_controls\ComboBox.h"
$File "$SRCDIR\public\vgui_controls\consoledialog.h"
$File "$SRCDIR\public\vgui_controls\ControllerMap.h"
$File "$SRCDIR\public\vgui_controls\Controls.h"
$File "$SRCDIR\public\vgui_controls\CvarToggleCheckButton.h"
$File "$SRCDIR\public\vgui_controls\DialogManager.h"
$File "$SRCDIR\public\vgui_controls\DirectorySelectDialog.h"
$File "$SRCDIR\public\vgui_controls\Divider.h"
$File "$SRCDIR\public\vgui_controls\EditablePanel.h"
$File "$SRCDIR\public\vgui_controls\ExpandButton.h"
$File "$SRCDIR\public\vgui_controls\FileOpenDialog.h"
$File "$SRCDIR\public\vgui_controls\FileOpenStateMachine.h"
$File "$SRCDIR\public\filesystem.h"
$File "$SRCDIR\public\filesystem_helpers.h"
$File "$SRCDIR\public\vgui_controls\FocusNavGroup.h"
$File "$SRCDIR\public\vgui_controls\Frame.h"
$File "$SRCDIR\public\vgui_controls\GraphPanel.h"
$File "$SRCDIR\public\vgui_controls\HTML.h"
$File "$SRCDIR\public\vgui_controls\Image.h"
$File "$SRCDIR\public\vgui_controls\ImageList.h"
$File "$SRCDIR\public\vgui_controls\ImagePanel.h"
$File "$SRCDIR\public\vgui_controls\InputDialog.h"
$File "$SRCDIR\public\tier1\interface.h"
$File "$SRCDIR\public\vgui_controls\KeyBindingHelpDialog.h"
$File "$SRCDIR\public\vgui_controls\KeyBindingMap.h"
$File "$SRCDIR\public\vgui_controls\KeyBoardEditorDialog.h"
$File "$SRCDIR\public\vgui_controls\KeyRepeat.h"
$File "$SRCDIR\public\tier1\KeyValues.h"
$File "$SRCDIR\public\vgui_controls\Label.h"
$File "$SRCDIR\public\vgui_controls\ListPanel.h"
$File "$SRCDIR\public\vgui_controls\ListViewPanel.h"
$File "$SRCDIR\public\tier0\memdbgoff.h"
$File "$SRCDIR\public\tier0\memdbgon.h"
$File "$SRCDIR\public\tier1\mempool.h"
$File "$SRCDIR\public\vgui_controls\Menu.h"
$File "$SRCDIR\public\vgui_controls\MenuBar.h"
$File "$SRCDIR\public\vgui_controls\MenuButton.h"
$File "$SRCDIR\public\vgui_controls\MenuItem.h"
$File "$SRCDIR\public\vgui_controls\MessageBox.h"
$File "$SRCDIR\public\vgui_controls\MessageDialog.h"
$File "$SRCDIR\public\vgui_controls\MessageMap.h"
$File "$SRCDIR\public\vgui_controls\Panel.h"
$File "$SRCDIR\public\vgui_controls\PanelAnimationVar.h"
$File "$SRCDIR\public\vgui_controls\PanelListPanel.h"
$File "$SRCDIR\public\vgui_controls\PerforceFileExplorer.h"
$File "$SRCDIR\public\vgui_controls\PerforceFileList.h"
$File "$SRCDIR\public\vgui_controls\perforcefilelistframe.h"
$File "$SRCDIR\public\vgui_controls\PHandle.h"
$File "$SRCDIR\public\vgui_controls\ProgressBar.h"
$File "$SRCDIR\public\vgui_controls\ProgressBox.h"
$File "$SRCDIR\public\vgui_controls\PropertyDialog.h"
$File "$SRCDIR\public\vgui_controls\PropertyPage.h"
$File "$SRCDIR\public\vgui_controls\PropertySheet.h"
$File "$SRCDIR\public\vgui_controls\QueryBox.h"
$File "$SRCDIR\public\vgui_controls\RadioButton.h"
$File "$SRCDIR\public\vgui_controls\RichText.h"
$File "$SRCDIR\public\vgui_controls\RotatingProgressBar.h"
$File "$SRCDIR\public\vgui_controls\savedocumentquery.h"
$File "$SRCDIR\public\vgui_controls\ScalableImagePanel.h"
$File "$SRCDIR\public\vgui_controls\ScrollableEditablePanel.h"
$File "$SRCDIR\public\vgui_controls\ScrollBar.h"
$File "$SRCDIR\public\vgui_controls\ScrollBarSlider.h"
$File "$SRCDIR\public\vgui_controls\SectionedListPanel.h"
$File "$SRCDIR\public\vgui_controls\Slider.h"
$File "$SRCDIR\public\vgui_controls\Splitter.h"
$File "$SRCDIR\public\vgui_controls\subrectimage.h"
$File "$SRCDIR\public\vgui_controls\TextEntry.h"
$File "$SRCDIR\public\vgui_controls\TextImage.h"
$File "$SRCDIR\public\vgui_controls\ToggleButton.h"
$File "$SRCDIR\public\vgui_controls\Tooltip.h"
$File "$SRCDIR\public\vgui_controls\ToolWindow.h"
$File "$SRCDIR\public\vgui_controls\TreeView.h"
$File "$SRCDIR\public\vgui_controls\TreeViewListControl.h"
$File "$SRCDIR\public\vgui_controls\URLLabel.h"
$File "$SRCDIR\public\tier1\utlmemory.h"
$File "$SRCDIR\public\tier1\utlrbtree.h"
$File "$SRCDIR\public\tier1\utlvector.h"
$File "$SRCDIR\public\vgui_controls\WizardPanel.h"
$File "$SRCDIR\public\vgui_controls\WizardSubPanel.h"
}
}