mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-27 00:26:50 +00:00
590 lines
14 KiB
C++
590 lines
14 KiB
C++
|
//========= 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();
|
||
|
}
|