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