//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ // // Purpose: // // $NoKeywords: $ //============================================================================= #include "vgui_listbox.h" using namespace vgui; CListBox::CListBox() : Panel( 0, 0, 0, 0 ), m_ItemsPanel( 0, 0, 0, 0 ), m_ScrollBar( 0, 0, 0, 0, true ), m_Slider( 0, 0, 10, 40, true ) { m_Signal.m_pListBox = this; m_ItemsPanel.setParent( this ); m_ItemsPanel.setBgColor( 0, 0, 0, 255 ); m_Slider.setRangeWindow( 50 ); m_Slider.setRangeWindowEnabled( true ); m_ScrollBar.setParent( this ); m_ScrollBar.addIntChangeSignal( &m_Signal ); m_ScrollBar.setSlider( &m_Slider ); m_ScrollBar.setButtonPressedScrollValue( 1 ); m_Items.m_pNext = m_Items.m_pPrev = &m_Items; m_ItemOffset = 0; m_iScrollMax = -1; } CListBox::~CListBox() { Term(); } void CListBox::Init() { Term(); } void CListBox::Term() { m_ItemOffset = 0; // Free the LBItems. LBItem *pNext; for( LBItem *pItem =m_Items.m_pNext; pItem != &m_Items; pItem = pNext ) { pItem->m_pPanel->setParent( NULL ); // detach the panel from us pNext = pItem->m_pNext; delete pItem; } m_Items.m_pPrev = m_Items.m_pNext = &m_Items; } void CListBox::AddItem( Panel *panel ) { // Add the item. LBItem *pItem = new LBItem; if( !pItem ) return; pItem->m_pPanel = panel; pItem->m_pPanel->setParent( &m_ItemsPanel ); pItem->m_pPrev = m_Items.m_pPrev; pItem->m_pNext = &m_Items; pItem->m_pNext->m_pPrev = pItem->m_pPrev->m_pNext = pItem; m_ScrollBar.setRange( 0, GetScrollMax() ); m_Slider.setRangeWindow( 50 ); m_Slider.setRangeWindowEnabled( true ); InternalLayout(); } int CListBox::GetNumItems() { int count = 0; for( LBItem *pItem = m_Items.m_pNext; pItem != &m_Items; pItem = pItem->m_pNext ) ++count; return count; } int CListBox::GetItemWidth() { int wide, tall; m_ItemsPanel.getSize( wide, tall ); return wide; } int CListBox::GetScrollPos() { return m_ItemOffset; } void CListBox::SetScrollPos( int pos ) { int maxItems = GetScrollMax(); if( maxItems < 0 ) return; m_ItemOffset = ( pos < 0 ) ? 0 : ( ( pos > maxItems ) ? maxItems : pos ); InternalLayout(); } void CListBox::setPos( int x, int y ) { Panel::setPos( x, y ); InternalLayout(); } void CListBox::setSize( int wide, int tall ) { Panel::setSize( wide, tall ); InternalLayout(); } void CListBox::setPixelScroll( int value ) { m_ItemOffset = m_ScrollBar.getValue(); InternalLayout(); } void CListBox::InternalLayout() { int x, y, wide, tall; getBounds( x, y, wide, tall ); // Reposition the main panel and the scrollbar. m_ItemsPanel.setBounds( 0, 0, wide - 15, tall ); m_ScrollBar.setBounds( wide - 15, 0, 15, tall ); bool bNeedScrollbar = false; // Reposition the items. int curItem = 0; int curY = 0; int maxItem = GetScrollMax(); for( LBItem *pItem = m_Items.m_pNext; pItem != &m_Items; pItem = pItem->m_pNext ) { if( curItem < m_ItemOffset ) { pItem->m_pPanel->setVisible( false ); bNeedScrollbar = true; } else if( curItem >= maxItem ) { // item is past the end of the items we care about pItem->m_pPanel->setVisible( false ); } else { pItem->m_pPanel->setVisible( true ); int itemWidth, itemHeight; pItem->m_pPanel->getSize( itemWidth, itemHeight ); // Don't change the item's height but change its width to fit the listbox. pItem->m_pPanel->setBounds( 0, curY, wide, itemHeight ); curY += itemHeight; if( curY > tall ) { bNeedScrollbar = true; } } ++curItem; } m_ScrollBar.setVisible( bNeedScrollbar ); repaint(); } void CListBox::paintBackground() { } void CListBox::SetScrollRange( int maxScroll ) { m_iScrollMax = maxScroll; m_ScrollBar.setRange( 0, maxScroll ); InternalLayout(); } int CListBox::GetScrollMax() { if( m_iScrollMax < 0 ) { return GetNumItems() - 1; } return m_iScrollMax; }