Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

589 lines
14 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=============================================================================
// Valve includes
#include "tier1/KeyValues.h"
#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"
// Local includes
#include "dualpanellist.h"
// Last include
#include "tier0/memdbgon.h"
//=============================================================================
//
//=============================================================================
CDualPanelList::CDualPanelList( vgui::Panel *pParent, char const *pszPanelName )
: vgui::Panel( pParent, pszPanelName )
, m_pScrollBar( NULL )
{
SetBounds( 0, 0, 100, 100 );
if ( false )
{
m_pScrollBar = new vgui::ScrollBar( this, "CDualPanelListVScroll", true );
m_pScrollBar->AddActionSignalTarget( this );
}
m_pPanelEmbedded = new vgui::EditablePanel( this, "PanelListEmbedded" );
m_pPanelEmbedded->SetBounds( 0, 0, 20, 20 );
m_pPanelEmbedded->SetPaintBackgroundEnabled( false );
m_pPanelEmbedded->SetPaintBorderEnabled( false );
m_iFirstColumnWidth = 100; // default width
m_nNumColumns = 1; // 1 column by default
if ( false && IsProportional() )
{
m_iDefaultHeight = vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), DEFAULT_HEIGHT );
m_iPanelBuffer = vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), PANELBUFFER );
}
else
{
m_iDefaultHeight = DEFAULT_HEIGHT;
m_iPanelBuffer = PANELBUFFER;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CDualPanelList::~CDualPanelList()
{
// free data from table
DeleteAllItems();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::SetVerticalBufferPixels( int buffer )
{
m_iPanelBuffer = buffer;
InvalidateLayout();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CDualPanelList::ComputeVPixelsNeeded()
{
int iCurrentItem = 0;
int iLargestH = 0;
int nPixels = 0;
for ( int i = 0; i < m_SortedItems.Count(); i++ )
{
Panel *pPanel = m_DataItems[ m_SortedItems[i] ].panel;
if ( !pPanel || !pPanel->IsVisible() )
continue;
if ( pPanel->IsLayoutInvalid() )
{
pPanel->InvalidateLayout( true );
}
int iCurrentColumn = iCurrentItem % m_nNumColumns;
int w, h;
pPanel->GetSize( w, h );
if ( iLargestH < h )
iLargestH = h;
if ( iCurrentColumn == 0 )
nPixels += m_iPanelBuffer; // add in buffer. between rows.
if ( iCurrentColumn >= m_nNumColumns - 1 )
{
nPixels += iLargestH;
iLargestH = 0;
}
iCurrentItem++;
}
// Add in remaining largest height
nPixels += iLargestH;
nPixels += m_iPanelBuffer; // add in buffer below last item
/*
nPixels = 0;
for ( int i = 0; i < m_SortedItems.Count(); ++i )
{
Panel *pPanel = m_DataItems[ m_SortedItems[i] ].panel;
if ( !pPanel )
continue;
int nWide = 0;
int nHeight = 0;
pPanel->GetSize( nWide, nHeight );
nPixels += nHeight;
}
*/
return nPixels;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
vgui::Panel *CDualPanelList::GetCellRenderer( int row )
{
if ( !m_SortedItems.IsValidIndex(row) )
return NULL;
Panel *panel = m_DataItems[ m_SortedItems[row] ].panel;
return panel;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CDualPanelList::AddItem( vgui::Panel *labelPanel, vgui::Panel *panel)
{
Assert(panel);
if ( labelPanel )
{
labelPanel->SetParent( m_pPanelEmbedded );
}
panel->SetParent( m_pPanelEmbedded );
int itemID = m_DataItems.AddToTail();
CDataItem &newitem = m_DataItems[itemID];
newitem.labelPanel = labelPanel;
newitem.panel = panel;
m_SortedItems.AddToTail(itemID);
InvalidateLayout();
return itemID;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CDualPanelList::GetItemCount() const
{
return m_DataItems.Count();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CDualPanelList::GetItemIDFromRow( int nRow ) const
{
if ( nRow < 0 || nRow >= GetItemCount() )
return m_DataItems.InvalidIndex();
return m_SortedItems[ nRow ];
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CDualPanelList::FirstItem() const
{
return m_DataItems.Head();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CDualPanelList::NextItem( int nItemID ) const
{
return m_DataItems.Next( nItemID );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CDualPanelList::InvalidItemID() const
{
return m_DataItems.InvalidIndex();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
vgui::Panel *CDualPanelList::GetItemLabel(int nItemID)
{
if ( !m_DataItems.IsValidIndex( nItemID ) )
return NULL;
return m_DataItems[nItemID].labelPanel;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
vgui::Panel *CDualPanelList::GetItemPanel( int nItemID )
{
if ( !m_DataItems.IsValidIndex( nItemID ) )
return NULL;
return m_DataItems[nItemID].panel;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CDualPanelList::IsItemVisible( int nItemID ) const
{
if ( !m_DataItems.IsValidIndex( nItemID ) )
return true;
return m_DataItems[nItemID].IsVisible();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::SetItemVisible( int nItemID, bool bVisible )
{
if ( !m_DataItems.IsValidIndex( nItemID ) )
return;
m_DataItems[nItemID].SetVisible( bVisible );
InvalidateLayout();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::RemoveItem( int nItemID )
{
if ( !m_DataItems.IsValidIndex( nItemID ) )
return;
CDataItem &item = m_DataItems[nItemID];
if ( item.panel )
{
item.panel->MarkForDeletion();
}
if ( item.labelPanel )
{
item.labelPanel->MarkForDeletion();
}
m_DataItems.Remove( nItemID );
m_SortedItems.FindAndRemove( nItemID );
InvalidateLayout();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::DeleteAllItems()
{
FOR_EACH_LL( m_DataItems, i )
{
if ( m_DataItems[i].panel )
{
delete m_DataItems[i].panel;
}
}
m_DataItems.RemoveAll();
m_SortedItems.RemoveAll();
InvalidateLayout();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::RemoveAll()
{
m_DataItems.RemoveAll();
m_SortedItems.RemoveAll();
// m_pScrollBar->SetValue( 0 );
InvalidateLayout();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::OnSizeChanged( int nWide, int nTall )
{
BaseClass::OnSizeChanged( nWide, nTall );
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::PerformLayout()
{
int nWide, nTall;
GetSize( nWide, nTall );
int vpixels = ComputeVPixelsNeeded();
int top = 0;
if ( m_pScrollBar )
{
m_pScrollBar->SetRange( 0, vpixels );
m_pScrollBar->SetRangeWindow( nTall );
m_pScrollBar->SetButtonPressedScrollValue( nTall / 4 ); // standard height of labels/buttons etc.
m_pScrollBar->SetPos( nWide - m_pScrollBar->GetWide() - 2, 0 );
m_pScrollBar->SetSize( m_pScrollBar->GetWide(), nTall - 2 );
top = m_pScrollBar->GetValue();
}
m_pPanelEmbedded->SetPos( 1, -top );
if ( m_pScrollBar )
{
m_pPanelEmbedded->SetSize( nWide - m_pScrollBar->GetWide() - 2, vpixels );
}
else
{
m_pPanelEmbedded->SetSize( nWide - 2, vpixels );
}
SetSize( nWide, vpixels );
/*
bool bScrollbarVisible = true;
// If we're supposed to automatically hide the scrollbar when unnecessary, check it now
if ( m_bAutoHideScrollbar )
{
bScrollbarVisible = (m_pPanelEmbedded->GetTall() > nTall);
}
m_pScrollBar->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 = ( nWide - xpos - 12 ) / m_nNumColumns;
if ( m_pScrollBar )
{
iColumnWidth = ( nWide - xpos - m_pScrollBar->GetWide() - 12 ) / m_nNumColumns;
}
for ( int i = 0; i < m_SortedItems.Count(); i++ )
{
CDataItem &item = m_DataItems[ m_SortedItems[i] ];
if ( !item.IsVisible() )
continue;
int iCurrentColumn = i % m_nNumColumns;
// add in a little buffer between panels
if ( iCurrentColumn == 0 )
y += m_iPanelBuffer;
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_nNumColumns - 1 )
{
y += h;
totalh += h;
h = 0;
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::ApplySchemeSettings( vgui::IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
SetBorder( pScheme->GetBorder( "ButtonDepressedBorder" ) );
SetBgColor( GetSchemeColor( "ListPanel.BgColor", GetBgColor(), pScheme ) );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::OnSliderMoved( int /* nPosition */ )
{
InvalidateLayout();
Repaint();
}
/*
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::MoveScrollBarToTop()
{
m_pScrollBar->SetValue( 0 );
}
*/
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::SetFirstColumnWidth( int nWidth )
{
m_iFirstColumnWidth = nWidth;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CDualPanelList::GetFirstColumnWidth()
{
return m_iFirstColumnWidth;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::SetNumColumns( int nNumColumns )
{
m_nNumColumns = nNumColumns;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CDualPanelList::GetNumColumns()
{
return m_nNumColumns;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::OnMouseWheeled( int nDelta )
{
if ( !m_pScrollBar )
return;
int nVal = m_pScrollBar->GetValue();
nVal -= ( nDelta * DEFAULT_HEIGHT );
m_pScrollBar->SetValue( nVal );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::SetSelectedPanel( vgui::Panel *pPanel )
{
if ( pPanel != m_hSelectedItem )
{
// notify the panels of the selection change
if ( m_hSelectedItem )
{
PostMessage( m_hSelectedItem.Get(), new KeyValues( "PanelSelected", "state", 0 ) );
}
if ( pPanel )
{
PostMessage( pPanel, new KeyValues( "PanelSelected", "state", 1 ) );
}
m_hSelectedItem = pPanel;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
vgui::Panel *CDualPanelList::GetSelectedPanel()
{
return m_hSelectedItem;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDualPanelList::ScrollToItem( int nItemNumber )
{
if ( !m_pScrollBar || !m_pScrollBar->IsVisible() )
return;
CDataItem& item = m_DataItems[ m_SortedItems[ nItemNumber ] ];
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_pScrollBar->SetValue( y );
InvalidateLayout();
}