mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-07 17:29:36 +00:00
1
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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 );
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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"));
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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 );
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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" );
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user