PanelList cpp

From Valve Developer Community
Jump to: navigation, search
Dead End - Icon.png
This article has no Wikipedia icon links to other VDC articles. Please help improve this article by adding links Wikipedia icon that are relevant to the context within the existing text.
January 2024
///////////  Copyright © 2007, Mark Chandler. All rights reserved.  ///////////
//
// Description:
//
//
//	Mark Chandler 2007 [email protected]
//
////////////////////////////////////////////////////////////////////////////////

#include "cbase.h"
#include "pd_panel_list.h"

////////////////////////////////////////////////////////////////////////////////
//	Constructor
////////////////////////////////////////////////////////////////////////////////
PD_PanelList::PD_PanelList(Panel *parent, const char *name) : Panel(parent, name)
{
	this->SetPaintBackgroundEnabled( false );
	this->SetPaintBackgroundType( 0 );
	this->SetPaintBorderEnabled(true);

	this->SetKeyBoardInputEnabled( true );

	m_pScrollBar = new vgui::ScrollBar( this, "Scrollbar", true);
	m_pScrollBar->AddActionSignalTarget(this);

	m_pSelImage = new PD_BasePanel( this, "SelectImage");

	m_iMargen = 5;
	m_iGroupMargen = 20;
	m_iSelected =-1;
	m_iHeight = 20;
	m_iMaxSliderVal = 0;

	m_pSelImage->SetVisible( false );
	m_pSelImage->bgColor = new Color(50, 100, 255, 125) ;
	m_pSelImage->SetZPos(100);
	m_pSelImage->AddActionSignalTarget(this);
	updateSize();

	m_bHeaderDisabled = false;
	m_bShowSelected = true;
	m_bFixedSize = true;
	m_bRejectSliderMove = false;
	m_bPaintBg = true;
}

////////////////////////////////////////////////////////////////////////////////
//	Destructor
////////////////////////////////////////////////////////////////////////////////
PD_PanelList::~PD_PanelList()
{

}

int PD_PanelList::AddPanel( Panel* pPanel, bool isSelectable)
{
	return AddPanel(pPanel, NULL, isSelectable);
}

int PD_PanelList::AddPanel( Panel* pPanel, char* header,  bool isSelectable)
{
	int headId = -1;

	if (header!=NULL)
	{
		headId = FindHeaderUsingIdent(header);
		if (headId == -1)	//if header doesnt exsist make it
		{
			vgui::Panel* pPanel=new PD_HeaderPanel(this, header);
			pPanel->SetZPos(25);

			headId = m_pHeaderList.AddToTail(pPanel);
		}
	}

	int id = FindItemUsingIdent(pPanel->GetName());

	if (id != -1)
		return -1;

	pPanel->SetParent( this );

	pPanel->SetVisible(true);
	pPanel->SetPaintBackgroundEnabled( true );
	pPanel->SetPaintBackgroundType( 0 );
	pPanel->SetPaintBorderEnabled(true);
	pPanel->AddActionSignalTarget(this);
	pPanel->SetZPos(50);

	panelInfo* newPanel= new panelInfo;
	newPanel->iHeader = headId;
	newPanel->pPanel = pPanel;
	newPanel->isSelectable = isSelectable;

	int index = m_pPanelList.AddToTail( newPanel );

	ResetAllChildPos();

	//Msg("Scroll bar range is: %d\n", range);
	return index;
}

void PD_PanelList::ResetAllChildPos(  )
{
	m_iSelected = 0;

	if (m_bHeaderDisabled)
	{	
		int heightCount = 0;
		int iLastHeight=0;

		for(int i = 0; i < m_pPanelList.Count();i++)
		{
			vgui::Panel *pItem = m_pPanelList[i]->pPanel;
			int x,y;
			int tall=0;
	
			if (i <= 0)
			{
				if (m_bFixedSize)
					y=-1*(m_iHeight + m_iMargen);
				else
					y=-1*m_iMargen;
			}
			else
			{
				m_pPanelList[i-1]->pPanel->GetPos(x,y);
			}

			int ypos=y + m_iMargen +m_iMargen;

			if (m_bFixedSize)
			{
				ypos += m_iHeight;
				tall = m_iHeight;
			}
			else
			{
				ypos += iLastHeight;
				tall = m_pPanelList[i]->pPanel->GetTall();
				iLastHeight = tall;
				heightCount += tall;
			}

			pItem->SetBounds(m_iMargen, ypos, GetWide()-m_iMargen-m_iMargen-m_pScrollBar->GetWide(), tall);
			
		}

		for(int i = 0; i < m_pHeaderList.Count();i++)
		{
			m_pHeaderList[i]->SetVisible(false);
		}

		if (m_bFixedSize)
			m_iMaxSliderVal = m_pPanelList.Count()*m_iHeight+m_pPanelList.Count()*m_iMargen+m_iMargen;
		else
			m_iMaxSliderVal = heightCount + m_pPanelList.Count()*m_iMargen + m_iMargen;

		m_pScrollBar->SetRange(0, m_iMaxSliderVal);

	}
	else
	{
		int maxGroups = m_pHeaderList.Count();

		//Msg("maxGroups is %d\n", maxGroups);

		if (maxGroups==0)
			return;

		for (int i=0; i<maxGroups; i++)
		{
			//Msg("I is %d\n", i);

			int count=0;
			int heightCount=0;
			for (int j=0; j<m_pPanelList.Count(); j++ )
			{
				//Msg("%d: [%d] == [%d]\n",j, m_pPanelList[j]->iHeader , i);
				if (m_pPanelList[j]->iHeader == i)
				{
					heightCount += m_pPanelList[j]->pPanel->GetTall();
					count++;
				}
			}

			//Msg("I is %d, Count is %d\n", i, count);

			int x,y;
			if (i <= 0)
			{
				x=0;
				y=-1*m_iGroupMargen + m_iMargen;
			}
			else
			{
				m_pHeaderList[i-1]->GetPos(x,y);
				y += m_pHeaderList[i-1]->GetTall();
			}

			//Msg("I is %d\n", i);

			int tall =0;

			if (m_bFixedSize)
				tall = (count+1)*m_iMargen + count*m_iHeight + TITLEHIEGHT;
			else
				tall = (count+1)*m_iMargen + heightCount + TITLEHIEGHT;

			int ypos = y + m_iGroupMargen;

	
			if (m_pHeaderList[i])
			{
				m_pHeaderList[i]->SetVisible(true);
				m_pHeaderList[i]->SetBounds(m_iMargen, ypos, GetWide()-(m_iMargen*2)-m_pScrollBar->GetWide(), tall);
			}
	
			int lastypos =0;
			int iLastHeight=0;

			if (m_bFixedSize)
				lastypos = ypos + -1*(m_iHeight) + TITLEHIEGHT;
			else
				lastypos = ypos + TITLEHIEGHT;

			for (int j=0; j<m_pPanelList.Count(); j++ )
			{
				if (m_pPanelList[j]->iHeader == i)
				{
					vgui::Panel *pItem = m_pPanelList[j]->pPanel;

					int ypos = 0;
					if (m_bFixedSize)
						ypos = lastypos + m_iMargen + m_iHeight;
					else
						ypos = lastypos + m_iMargen + iLastHeight;

					lastypos = ypos;
					

					if (m_bFixedSize)
						pItem->SetBounds(m_iMargen*2, ypos, GetWide()-(m_iMargen*4)-m_pScrollBar->GetWide(), m_iHeight);
					else
					{
						iLastHeight = pItem->GetTall();
						pItem->SetBounds(m_iMargen*2, ypos, GetWide()-(m_iMargen*4)-m_pScrollBar->GetWide(), iLastHeight);
					}
				}
			}
		}

		m_iMaxSliderVal = 0;
		for (int i=0; i<maxGroups; i++)
		{
			m_iMaxSliderVal+=m_pHeaderList[i]->GetTall();
		}
		m_iMaxSliderVal+=m_iGroupMargen;

		m_pScrollBar->SetRange(0, m_iMaxSliderVal);
	}

}

void PD_PanelList::SetSelected( int index )
{
	if (index >= 0 && index < m_pPanelList.Count() && m_pPanelList[index]->isSelectable == true)
		m_iSelected = index;
}

void PD_PanelList::SetMargen( int amount )
{
	if (this->IsProportional())
		m_iMargen = scheme()->GetProportionalScaledValue(amount); 
	else
		m_iMargen = amount;
	
	updateSize();
}

void PD_PanelList::SetHeight( int amount )
{
	if (this->IsProportional())
		m_iHeight = scheme()->GetProportionalScaledValue(amount); 
	else
		m_iHeight = amount;
	
	updateSize();
}

void PD_PanelList::PurgeAll( void )
{
	for (int x=0; x<m_pPanelList.Count(); x++)
	{
		delete m_pPanelList[x]->pPanel;
	}

	//for (int x=0; x<m_pHeaderList.Count(); x++)
	//{
	//	delete m_pHeaderList[x];
	//}

	m_pPanelList.PurgeAndDeleteElements();
	m_pHeaderList.PurgeAndDeleteElements();
	m_iSelected =-1;
	m_pScrollBar->SetRange(0,0);
	m_iMaxSliderVal = 0;
}

void PD_PanelList::Reset()
{

}

void PD_PanelList::OnSizeChanged(int newWide, int newTall)
{
	m_pScrollBar->SetBounds(newWide-m_pScrollBar->GetWide(), 0, m_pScrollBar->GetWide(),  newTall);

	for(int i = 0; i < m_pPanelList.Count();i++)
	{
		m_pPanelList[i]->pPanel->SetWide(newWide-m_iMargen-m_iMargen-m_pScrollBar->GetWide());
	}

	m_pScrollBar->SetRangeWindow(GetTall()-m_iMargen-m_iMargen);

	ResetAllChildPos();
}

void PD_PanelList::OnThink( void )
{
	Update();
	BaseClass::OnThink();
}

void PD_PanelList::OnCommand(char* command)
{
	//Msg("Panel List Command: %s\n", command);
	if (strcmp(command,"UpdatePos")==0)
	{
		ResetAllChildPos();
	}
	else if ( GetVParent() )
	{
		KeyValues *msg = new KeyValues("Command");
		msg->SetString("command", command);	
		PostActionSignal( msg );
	};

}

void PD_PanelList::OnRequestUpdate(const char* PanelName)
{
	ResetAllChildPos();
	//OnItemClicked( PanelName );
}
void PD_PanelList::Update( void )
{
	if (!m_pPanelList.Count())
		return;

	int range = m_pPanelList.Count()*m_iHeight+m_pPanelList.Count()*m_iMargen+m_iMargen;
	if (range < GetTall())
		m_pScrollBar->SetEnabled( false );
	else
		m_pScrollBar->SetEnabled(true);
}

void PD_PanelList::OnSliderMoved(int value)
{
	if (m_bRejectSliderMove)
	{
		m_bRejectSliderMove=false;
		return;
	}

	//Msg("Moving to: %d [%d] [%d]\n", value, m_iMaxSliderVal, GetTall());
	if (value < 0)
		value = 0;

	if (value > m_iMaxSliderVal)
		value = m_iMaxSliderVal;

	int x,y;

	if (m_bHeaderDisabled == true)
		m_pPanelList[0]->pPanel->GetPos(x, y);
	else
		m_pHeaderList[0]->GetPos(x, y);

	int ammount =  -1*(value+(y-m_iMargen));

	//stops an loop happning where moveby updates slider and makes it move again.
	m_bRejectSliderMove = true;

	MoveBy(ammount, true );
}

void PD_PanelList::ResetSelected()
{
	if (m_iSelected != -1 && m_bShowSelected)
	{
		int x,y;
		m_pPanelList[m_iSelected]->pPanel->GetPos(x,y);

		m_pSelImage->SetVisible( true );

		int tall=m_iMargen+m_iMargen;

		if (m_bFixedSize)
			tall += m_iHeight;
		else
			tall += m_pPanelList[m_iSelected]->pPanel->GetTall();

		m_pSelImage->SetBounds(m_iMargen, y-m_iMargen, GetWide()-m_pScrollBar->GetWide()-m_iMargen-m_iMargen,  tall);
	}
	else
	{
		m_pSelImage->SetVisible( false );
	}
}

void PD_PanelList::UpdateSelected()
{
	// make sure selected is allways shown
	if (m_iSelected != -1)
	{
		int x,y;
		m_pPanelList[m_iSelected]->pPanel->GetPos(x,y);

		if (m_bFixedSize)
		{
			if (y+m_iHeight > GetTall())	
				MoveBy( -1 *((y+m_iHeight+m_iMargen) - GetTall()));
		}
		else
		{
			int tall = m_pPanelList[m_iSelected]->pPanel->GetTall();
			//Msg("Im %d tall\n", tall);
			if (y+tall+m_iMargen > GetTall())	
				MoveBy( -1 *((y+tall+m_iMargen) - GetTall()));
		}

		if (y < 0)
			MoveBy( -y + m_iMargen );

	}

	ResetSelected();
	InvalidateLayout();
}

void PD_PanelList::MoveBy( int amount, bool slider )
{
	int x,y;
	for (int i=0; i<m_pPanelList.Count(); i++)
	{
		m_pPanelList[i]->pPanel->GetPos(x, y);
		m_pPanelList[i]->pPanel->SetPos(x, y+amount);
	}

	for (int i=0; i<m_pHeaderList.Count(); i++)
	{
		m_pHeaderList[i]->GetPos(x, y);
		m_pHeaderList[i]->SetPos(x, y+amount);
	}

	if (!slider)
	{
		m_pPanelList[0]->pPanel->GetPos(x, y);
		m_pScrollBar->SetValue(abs(y-m_iMargen));
	}

	ResetSelected();
	InvalidateLayout();
}

#define BORDERWIDTH 1

void PD_PanelList::Paint()
{
	BaseClass::Paint();
	PaintBorder();
}

void PD_PanelList::PaintBackground()
{
	if (!m_bPaintBg)
		return;

	int wide, tall;
	GetSize(wide, tall);

	vgui::surface()->DrawSetColor(Color(120,120,120,255));
	vgui::surface()->DrawFilledRect(0, 0, wide, tall);
}

void PD_PanelList::PaintBorder()
{
	int wide, tall;
	GetSize(wide, tall);

	int sw = m_pScrollBar->GetWide();

	surface()->DrawSetColor( Color(0,200,255,255) );

	////draw top
	surface()->DrawFilledRect(BORDERWIDTH, 0, wide-sw, BORDERWIDTH);

	//draw bottom
	surface()->DrawFilledRect(BORDERWIDTH, tall-BORDERWIDTH, wide-sw, tall);

	//draw left
	surface()->DrawFilledRect(0, 0, BORDERWIDTH, tall);

	//draw right
	//surface()->DrawFilledRect(wide-BORDERWIDTH-BORDERINSTEP, captionHeight+1, wide-BORDERINSTEP, tall);
}

void PD_PanelList::updateSize( void )
{
	OnSizeChanged(GetWide(), GetTall());
}

int PD_PanelList::FindItemUsingIdent(const char *pszIdent)
{
	for(int i = 0; i < m_pPanelList.Count();i++)
	{
		vgui::Panel *pItem = m_pPanelList[i]->pPanel;
		if(pItem == NULL)
			continue;

		if(strcmp(pszIdent,pItem->GetName())==0)
			return i;

		//Msg("Comparing: [%s], [%s]\n", pszIdent,pItem->GetName());
	}
	return -1;
}

int PD_PanelList::FindHeaderUsingIdent(const char *pszIdent)
{
	for(int i = 0; i < m_pHeaderList.Count();i++)
	{
		vgui::Panel *pItem = m_pHeaderList[i];
		//headerInfo* pItem = m_pHeaderList[i];
		if(pItem == NULL)
			continue;

		if(strcmp(pszIdent,pItem->GetName())==0)
			return i;

		//Msg("Comparing: [%s], [%s]\n", pszIdent,pItem->GetName());
	}
	return -1;
}

void PD_PanelList::PrintLoc()
{
	for(int i = 0; i < m_pPanelList.Count();i++)
	{
		int x,y;
		m_pPanelList[i]->pPanel->GetPos(x,y);
		Msg("Panel %d, X:%d, Y:%d\n",i,x,y);	
	}
}

void PD_PanelList::OnKeyCodeTyped(KeyCode code)
{
	//Msg("KeyCode %d\n", code);
	if ( code == KEY_W || code == KEY_UP)
	{
		if (m_pPanelList.Count() > 0)
		{
			if (m_iSelected == -1)
				SetSelected(0);

			if (m_iSelected != 0)
				SetSelected(m_iSelected-1);
		}
		else
		{
			m_iSelected=-1;
		}

		UpdateSelected();
	}
	else if ( code == KEY_S || code == KEY_DOWN)
	{
		if (m_pPanelList.Count() > 0)
		{
			if (m_iSelected < m_pPanelList.Count()-1)
				SetSelected(m_iSelected+1);
		}
		else
		{
			m_iSelected=-1;
		}
		UpdateSelected();
	}
	//ShowSelected();
}

void PD_PanelList::OnCursorMoved( int x, int y)
{
}

void PD_PanelList::OnMouseWheeled(int delta)
{
	delta*=-1;
	if (m_pPanelList.Count() > 0)
	{
		if (m_iSelected == -1)
			m_iSelected = 0;
		else if ((m_iSelected + delta) >= 0 && (m_iSelected +delta) < m_pPanelList.Count())
			SetSelected(m_iSelected+delta);
	}
	else
	{
		m_iSelected=-1;
	}
	UpdateSelected();
}

void PD_PanelList::OnSetSelected(const char* name)
{
		OnItemClicked(name);
}

void PD_PanelList::OnItemClicked(const char* name)
{
	int id = FindItemUsingIdent( name );

	SetSelected(id);
	UpdateSelected();
}

void PD_PanelList::OnItemDoubleClicked(const char* name)
{
	//SetSelected(FindItemUsingIdent(name));

	KeyValues *msg = new KeyValues("Command");
	msg->SetString("command", "Select");	
	PostActionSignal( msg );

	//PostActionSignal(new KeyValues("ItemDoubleClick","name", this->GetName()));
}

//void PD_PanelList::OnMouseDoublePressed(MouseCode code)
//{
//	Msg("Mouse clicked\n");
//}

/////////////////////////////////////////////////////////////////////////////////////////////////////

PD_HeaderPanel::PD_HeaderPanel(Panel *parent, const char *name) : PD_BasePanel(parent, name)
{

	m_pTitleBG = new vgui::ImagePanel(this, "TitleBG");
	m_pTitleBG->SetFillColor(Color(255,255,0,255));
	m_pTitleBG->SetShouldScaleImage( true );

	m_pBodyBG = new vgui::ImagePanel(this, "BodyBG");
	m_pBodyBG->SetFillColor(Color(255,0,255,0));
	m_pBodyBG->SetVisible( false );

	m_pTitle = new vgui::Label(this, "TitleLabel", "[title]");
	m_pTitle->SetMouseInputEnabled(false);

	m_bNeedsUpdate = true;
	Q_strncpy(m_szTitle,"NULL NAME", 256);

	OnSizeChanged(GetWide(), GetTall());
}

void PD_HeaderPanel::OnThink( void )
{
	if (m_bNeedsUpdate)
	{
		m_pTitleBG->SetImage( HEADERIMG );

		m_pTitle->SetText(GetName());
		//m_pTitle->SetFgColor(Color(0,0,0,255));

		m_bNeedsUpdate = false;
	}
}

void PD_HeaderPanel::PaintBackground()
{
	return;

	//int wide, tall;
	//GetSize(wide, tall);
	//vgui::surface()->DrawSetColor(Color(120,120,120,255));
	//vgui::surface()->DrawFilledRect(0, 0, wide, tall);
}

void PD_HeaderPanel::OnSizeChanged(int newWide, int newTall)
{
	m_pTitle->SetBounds( 10, 0, newWide, TITLEHIEGHT);

	m_pTitleBG->SetBounds(0,0,newWide, TITLEHIEGHT);
	m_pBodyBG->SetBounds(0,TITLEHIEGHT,newWide, newTall-TITLEHIEGHT);
}
Wikipedia - Letter.png
This article has not been added to any content Wikipedia icon categories. Please help out by Wikipedia icon adding categories.
January 2024