//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //============================================================================= #include "cbase.h" #include #include #include #include #include #include #include #include #include #include #include "buypreset_listbox.h" // memdbgon must be the last include file in a .cpp file!!! #include using namespace vgui; #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif //-------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------- BuyPresetListBox::BuyPresetListBox( vgui::Panel *parent, char const *panelName ) : Panel( parent, panelName ) { m_visibleIndex = 0; m_lastSize = 0; SetBounds( 0, 0, 100, 100 ); m_vbar = new ScrollBar(this, "PanelListPanelVScroll", true); m_vbar->SetBounds( 0, 0, 20, 20 ); m_vbar->SetVisible(true); 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); if( IsProportional() ) { int width, height; int sw,sh; surface()->GetProportionalBase( width, height ); GetHudSize(sw, sh); // resize scrollbar, etc m_iScrollbarSize = static_cast( static_cast( SCROLLBAR_SIZE )*( static_cast( sw )/ static_cast( width ))); m_iDefaultHeight = static_cast( static_cast( DEFAULT_HEIGHT )*( static_cast( sw )/ static_cast( width ))); m_iPanelBuffer = static_cast( static_cast( PANELBUFFER )*( static_cast( sw )/ static_cast( width ))); } else { m_iScrollbarSize = SCROLLBAR_SIZE; m_iDefaultHeight = DEFAULT_HEIGHT; m_iPanelBuffer = PANELBUFFER; } } //-------------------------------------------------------------------------------------------------------------- BuyPresetListBox::~BuyPresetListBox() { // free data from table DeleteAllItems(); } //-------------------------------------------------------------------------------------------------------------- /** * Passes commands up to the parent */ void BuyPresetListBox::OnCommand( const char *command ) { GetParent()->OnCommand( command ); } //-------------------------------------------------------------------------------------------------------------- /** * Scrolls the list according to the mouse wheel movement */ void BuyPresetListBox::OnMouseWheeled(int delta) { int scale = 3; if ( m_items.Count() ) { Panel *panel = m_items[0].panel; if ( panel ) { scale = panel->GetTall() + m_iPanelBuffer; } } int val = m_vbar->GetValue(); val -= (delta * scale); m_vbar->SetValue(val); } //-------------------------------------------------------------------------------------------------------------- /** * Computes vertical pixels needed by listbox contents */ int BuyPresetListBox::computeVPixelsNeeded( void ) { int pixels = 0; int i; for ( i = 0; i < m_items.Count(); i++ ) { Panel *panel = m_items[i].panel; if ( !panel ) continue; int w, h; panel->GetSize( w, h ); pixels += m_iPanelBuffer; // add in buffer. between items. pixels += h; } pixels += m_iPanelBuffer; // add in buffer below last item return pixels; } //-------------------------------------------------------------------------------------------------------------- /** * Adds an item to the end of the listbox. UserData is assumed to be a pointer that can be freed by the listbox if non-NULL. */ int BuyPresetListBox::AddItem( vgui::Panel *panel, void * userData ) { assert(panel); DataItem item = { panel, userData }; panel->SetParent( m_pPanelEmbedded ); m_items.AddToTail( item ); InvalidateLayout(); return m_items.Count(); } //-------------------------------------------------------------------------------------------------------------- /** * Exchanges two items in the listbox */ void BuyPresetListBox::SwapItems( int index1, int index2 ) { if ( index1 < 0 || index2 < 0 || index1 >= m_items.Count() || index2 >= m_items.Count() ) { return; } DataItem temp = m_items[index1]; m_items[index1] = m_items[index2]; m_items[index2] = temp; InvalidateLayout(); } //-------------------------------------------------------------------------------------------------------------- /** * Returns the number of items in the listbox */ int BuyPresetListBox::GetItemCount( void ) const { return m_items.Count(); } //-------------------------------------------------------------------------------------------------------------- /** * Returns the panel in the given index, or NULL */ Panel * BuyPresetListBox::GetItemPanel(int index) const { if ( index < 0 || index >= m_items.Count() ) return NULL; return m_items[index].panel; } //-------------------------------------------------------------------------------------------------------------- /** * Returns the userData in the given index, or NULL */ void * BuyPresetListBox::GetItemUserData(int index) { if ( index < 0 || index >= m_items.Count() ) { return NULL; } return m_items[index].userData; } //-------------------------------------------------------------------------------------------------------------- /** * Sets the userData in the given index */ void BuyPresetListBox::SetItemUserData( int index, void * userData ) { if ( index < 0 || index >= m_items.Count() ) return; m_items[index].userData = userData; } //-------------------------------------------------------------------------------------------------------------- /** * Removes an item from the table (changing the indices of all following items), deleting the panel and userData */ void BuyPresetListBox::RemoveItem(int index) { if ( index < 0 || index >= m_items.Count() ) return; DataItem item = m_items[index]; if ( item.panel ) { item.panel->MarkForDeletion(); } if ( item.userData ) { delete item.userData; } m_items.Remove( index ); InvalidateLayout(); } //-------------------------------------------------------------------------------------------------------------- /** * clears the listbox, deleting all panels and userData */ void BuyPresetListBox::DeleteAllItems() { while ( m_items.Count() ) { RemoveItem( 0 ); } // move the scrollbar to the top of the list m_vbar->SetValue(0); InvalidateLayout(); } //-------------------------------------------------------------------------------------------------------------- /** * Handles Count changes */ void BuyPresetListBox::OnSizeChanged(int wide, int tall) { BaseClass::OnSizeChanged(wide, tall); InvalidateLayout(); } //-------------------------------------------------------------------------------------------------------------- /** * Positions listbox items, etc after internal changes */ void BuyPresetListBox::PerformLayout() { int wide, tall; GetSize( wide, tall ); int vpixels = computeVPixelsNeeded(); int visibleIndex = m_visibleIndex; //!! need to make it recalculate scroll positions m_vbar->SetVisible(true); m_vbar->SetEnabled(false); m_vbar->SetRange( 0, (MAX( 0, vpixels - tall + m_iDefaultHeight )) ); m_vbar->SetRangeWindow( m_iDefaultHeight ); m_vbar->SetButtonPressedScrollValue( m_iDefaultHeight ); // standard height of labels/buttons etc. m_vbar->SetPos(wide - m_iScrollbarSize, 1); m_vbar->SetSize(m_iScrollbarSize, tall - 2); m_visibleIndex = visibleIndex; int top = MAX( 0, m_vbar->GetValue() ); m_pPanelEmbedded->SetPos( 1, -top ); m_pPanelEmbedded->SetSize( wide-m_iScrollbarSize -2, vpixels ); // Now lay out the controls on the embedded panel int y = 0; int h = 0; int totalh = 0; int i; for ( i = 0; i < m_items.Count(); i++, y += h ) { // add in a little buffer between panels y += m_iPanelBuffer; DataItem item = m_items[i]; h = item.panel->GetTall(); totalh += h; item.panel->SetBounds( 8, y, wide - m_iScrollbarSize - 8 - 8, h ); item.panel->InvalidateLayout(); } if ( m_visibleIndex >= 0 && m_visibleIndex < m_items.Count() ) { int vpos = 0; int tempWide, tempTall; GetSize( tempWide, tempTall ); int vtop, vbottom; m_vbar->GetRange( vtop, vbottom ); int tempTop = MAX( 0, m_vbar->GetValue() ); // top pixel in the embedded panel int bottom = tempTop + tempTall - 2; int itemTop, itemLeft, itemBottom, itemRight; m_items[m_visibleIndex].panel->GetBounds( itemLeft, itemTop, itemRight, itemBottom ); itemBottom += itemTop; itemRight += itemLeft; if ( itemTop < tempTop ) { // item's top is too high vpos -= ( tempTop - itemTop ); m_vbar->SetValue(vpos); OnSliderMoved(vpos); } else if ( itemBottom > bottom ) { // item's bottom is too low vpos += ( itemBottom - bottom ); m_vbar->SetValue(vpos); OnSliderMoved(vpos); } } if ( m_lastSize == vpixels ) { m_visibleIndex = -1; } m_lastSize = vpixels; } //-------------------------------------------------------------------------------------------------------------- /** * Try to ensure that the given index is visible */ void BuyPresetListBox::MakeItemVisible( int index ) { m_visibleIndex = index; m_lastSize = 0; } //-------------------------------------------------------------------------------------------------------------- /** * Loads colors, fonts, etc */ void BuyPresetListBox::ApplySchemeSettings(IScheme *pScheme) { BaseClass::ApplySchemeSettings(pScheme); SetBgColor(GetSchemeColor("BuyPresetListBox.BgColor", GetBgColor(), pScheme)); SetBorder(pScheme->GetBorder("BrowserBorder")); m_vbar->SetBorder(pScheme->GetBorder("BrowserBorder")); PerformLayout(); } //-------------------------------------------------------------------------------------------------------------- /** * Handles slider being dragged */ void BuyPresetListBox::OnSliderMoved( int position ) { InvalidateLayout(); Repaint(); } //-------------------------------------------------------------------------------------------------------------- /** * Moves slider to the top */ void BuyPresetListBox::MoveScrollBarToTop() { m_vbar->SetValue(0); OnSliderMoved(0); }