|
|
//========= Copyright 1996-2005, 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;
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
PanelListPanel::PanelListPanel( vgui::Panel *parent, char const *panelName ) : Panel( 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
m_bShowScrollBar = true; m_bAllowMouseWheel = true; m_bOverrideChildPanelWidth = true;
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; // Skip hidden items
if ( !panel->IsVisible() ) continue;
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 ); panel->SetVisible( true );
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 ]; }
//-----------------------------------------------------------------------------
// Purpose: Returns the number of visible item panels
//-----------------------------------------------------------------------------
int PanelListPanel::GetVisibleItemCount() { int iTotal = 0; for ( int i = 0 ; i < GetItemCount() ; ++i ) { Panel *panel = GetItemPanel( i ); if (panel && panel->IsVisible()) iTotal++; } return iTotal; }
//-----------------------------------------------------------------------------
// 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 ) { delete m_DataItems[i].panel; } }
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->SetVisible( GetShowScrollbar() ); 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( 1, -top ); m_pPanelEmbedded->SetSize( wide - m_vbar->GetWide() - 2, vpixels );
int sliderPos = m_vbar->GetValue(); // 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++ ) { DATAITEM &item = m_DataItems[ m_SortedItems[i] ]; if ( !item.panel || !item.panel->IsVisible() ) continue;
int iCurrentColumn = i % m_iNumColumns;
// add in a little buffer between panels
if ( iCurrentColumn == 0 ) y += m_iPanelBuffer;
if ( h < item.panel->GetTall() ) h = item.panel->GetTall();
if (totalh >= sliderPos) { if ( item.labelPanel ) { item.labelPanel->SetBounds( 0, y, m_iFirstColumnWidth, item.panel->GetTall() ); } item.panel->SetBounds(xpos + iCurrentColumn * iColumnWidth, y, m_bOverrideChildPanelWidth ? iColumnWidth : item.panel->GetWide(), 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) { if (!m_bAllowMouseWheel) return;
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(); }
void PanelListPanel::ApplySettings( KeyValues *inResourceData ) { BaseClass::ApplySettings( inResourceData );
SetShowScrollBar(inResourceData->GetBool("showScrollBar", true)); AllowMouseWheel(inResourceData->GetBool("allowMouseWheel", true)); OverrideChildPanelWidth(inResourceData->GetBool("setChildPanelWidth", true)); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PanelListPanel::GetSettings( KeyValues *outResourceData ) { BaseClass::GetSettings( outResourceData ); outResourceData->SetBool("showScrollBar", m_bShowScrollBar); outResourceData->SetBool("allowMouseWheel", m_bShowScrollBar); outResourceData->SetBool("overrideChildPanelWidth", m_bOverrideChildPanelWidth); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *PanelListPanel::GetDescription() { static char buf[1024]; Q_snprintf(buf, sizeof(buf), "%s, bool showScrollBar, bool allowMouseWheel, bool overrideChildPanelWidth", BaseClass::GetDescription()); return buf; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PanelListPanel::SetShowScrollBar( bool bShow ) { m_bShowScrollBar = bShow; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PanelListPanel::AllowMouseWheel( bool bAllow ) { m_bAllowMouseWheel = bAllow; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void PanelListPanel::OverrideChildPanelWidth( bool bOverride ) { m_bOverrideChildPanelWidth = bOverride; }
void PanelListPanel::SetItemVisible( int nItemID, bool bVisible ) { if ( !m_DataItems.IsValidIndex(nItemID) ) return;
m_DataItems[nItemID].panel->SetVisible( bVisible ); InvalidateLayout(); }
bool PanelListPanel::IsItemVisible( int nItemID ) const { if ( !m_DataItems.IsValidIndex(nItemID) ) return false; return m_DataItems[nItemID].panel->IsVisible(); }
void PanelListPanel::HideAllItems() { FOR_EACH_LL( m_DataItems, i ) { if ( m_DataItems[i].panel ) { m_DataItems[i].panel->SetVisible( false ); } } InvalidateLayout(); }
|