//========= Copyright © 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; }