Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

399 lines
7.4 KiB

//========= Copyright <EFBFBD> 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include <assert.h>
#include "vgui_grid.h"
using namespace vgui;
#define AssertCheck(expr, msg) \
if(!(expr))\
{\
assert(!msg);\
return 0;\
}
// ------------------------------------------------------------------------------ //
// CGrid::CGridEntry.
// ------------------------------------------------------------------------------ //
CGrid::CGridEntry::CGridEntry()
{
m_pPanel = NULL;
m_bUnderline = false;
}
CGrid::CGridEntry::~CGridEntry()
{
}
// ------------------------------------------------------------------------------ //
// CGrid.
// ------------------------------------------------------------------------------ //
CGrid::CGrid()
{
Clear();
}
CGrid::~CGrid()
{
Term();
}
bool CGrid::SetDimensions(int xCols, int yRows)
{
Term();
m_GridEntries = new CGridEntry[xCols * yRows];
m_Widths = new int[xCols*2 + yRows*2];
m_Heights = m_Widths + xCols;
m_ColOffsets = m_Heights + yRows;
m_RowOffsets = m_ColOffsets + xCols;
if(!m_GridEntries || !m_Widths)
{
Term();
return false;
}
memset(m_Widths, 0, sizeof(int) * (xCols*2 + yRows*2));
m_xCols = xCols;
m_yRows = yRows;
return true;
}
void CGrid::Term()
{
delete [] m_GridEntries;
delete [] m_Widths;
Clear();
}
Panel* CGrid::GetEntry(int x, int y)
{
return GridEntry(x, y)->m_pPanel;
}
bool CGrid::SetEntry(int x, int y, Panel *pPanel)
{
CGridEntry *pEntry = GridEntry(x, y);
if(!pEntry)
return false;
if(pEntry->m_pPanel)
pEntry->m_pPanel->setParent(NULL);
pEntry->m_pPanel = pPanel;
if(pPanel)
pPanel->setParent(this);
m_bDirty = true;
return true;
}
int CGrid::GetXSpacing()
{
return m_xSpacing;
}
int CGrid::GetYSpacing()
{
return m_ySpacing;
}
void CGrid::SetSpacing(int xSpacing, int ySpacing)
{
if(xSpacing != m_xSpacing)
{
m_xSpacing = xSpacing;
CalcColOffsets(0);
m_bDirty = true;
}
if(ySpacing != m_ySpacing)
{
m_ySpacing = ySpacing;
CalcRowOffsets(0);
m_bDirty = true;
}
}
bool CGrid::SetColumnWidth(int iColumn, int width)
{
AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::SetColumnWidth : invalid location specified");
m_Widths[iColumn] = width;
CalcColOffsets(iColumn+1);
m_bDirty = true;
return true;
}
bool CGrid::SetRowHeight(int iRow, int height)
{
AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::SetColumnWidth : invalid location specified");
m_Heights[iRow] = height;
CalcRowOffsets(iRow+1);
m_bDirty = true;
return true;
}
int CGrid::GetColumnWidth(int iColumn)
{
AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::GetColumnWidth: invalid location specified");
return m_Widths[iColumn];
}
int CGrid::GetRowHeight(int iRow)
{
AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::GetRowHeight: invalid location specified");
return m_Heights[iRow];
}
int CGrid::CalcFitColumnWidth(int iColumn)
{
AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::CalcFitColumnWidth: invalid location specified");
int maxSize = 0;
for(int i=0; i < m_yRows; i++)
{
Panel *pPanel = GridEntry(iColumn, i)->m_pPanel;
if(!pPanel)
continue;
int w, h;
pPanel->getSize(w,h);
if(w > maxSize)
maxSize = w;
}
return maxSize;
}
int CGrid::CalcFitRowHeight(int iRow)
{
AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::CalcFitRowHeight: invalid location specified");
int maxSize = 0;
for(int i=0; i < m_xCols; i++)
{
Panel *pPanel = GridEntry(i, iRow)->m_pPanel;
if(!pPanel)
continue;
int w, h;
pPanel->getSize(w,h);
if(h > maxSize)
maxSize = h;
}
return maxSize;
}
void CGrid::AutoSetRowHeights()
{
for(int i=0; i < m_yRows; i++)
SetRowHeight(i, CalcFitRowHeight(i));
}
bool CGrid::GetEntryBox(
int col, int row, int &x, int &y, int &w, int &h)
{
AssertCheck(col >= 0 && col < m_xCols && row >= 0 && row < m_yRows, "CGrid::GetEntryBox: invalid location specified");
x = m_ColOffsets[col];
w = m_Widths[col];
y = m_RowOffsets[row];
h = m_Heights[row];
return true;
}
bool CGrid::CopyColumnWidths(CGrid *pOther)
{
if(!pOther || pOther->m_xCols != m_xCols)
return false;
for(int i=0; i < m_xCols; i++)
m_Widths[i] = pOther->m_Widths[i];
CalcColOffsets(0);
m_bDirty = true;
return true;
}
void CGrid::RepositionContents()
{
for(int x=0; x < m_xCols; x++)
{
for(int y=0; y < m_yRows; y++)
{
Panel *pPanel = GridEntry(x,y)->m_pPanel;
if(!pPanel)
continue;
pPanel->setBounds(
m_ColOffsets[x],
m_RowOffsets[y],
m_Widths[x],
m_Heights[y]);
}
}
m_bDirty = false;
}
int CGrid::CalcDrawHeight()
{
if(m_yRows > 0)
{
return m_RowOffsets[m_yRows-1] + m_Heights[m_yRows - 1] + m_ySpacing;
}
else
{
return 0;
}
}
void CGrid::paint()
{
if(m_bDirty)
RepositionContents();
Panel::paint();
// walk the grid looking for underlined rows
int x = 0, y = 0;
for (int row = 0; row < m_yRows; row++)
{
CGridEntry *cell = GridEntry(0, row);
y += cell->m_pPanel->getTall() + m_ySpacing;
if (cell->m_bUnderline)
{
drawSetColor(cell->m_UnderlineColor[0], cell->m_UnderlineColor[1], cell->m_UnderlineColor[2], cell->m_UnderlineColor[3]);
drawFilledRect(0, y - (cell->m_iUnderlineOffset + 1), getWide(), y - cell->m_iUnderlineOffset);
}
}
}
void CGrid::paintBackground()
{
Panel::paintBackground();
}
//-----------------------------------------------------------------------------
// Purpose: sets underline color for a particular row
//-----------------------------------------------------------------------------
void CGrid::SetRowUnderline(int row, bool enabled, int offset, int r, int g, int b, int a)
{
CGridEntry *cell = GridEntry(0, row);
cell->m_bUnderline = enabled;
if (enabled)
{
cell->m_iUnderlineOffset = offset;
cell->m_UnderlineColor[0] = r;
cell->m_UnderlineColor[1] = g;
cell->m_UnderlineColor[2] = b;
cell->m_UnderlineColor[3] = a;
}
}
void CGrid::Clear()
{
m_xCols = m_yRows = 0;
m_Widths = NULL;
m_GridEntries = NULL;
m_xSpacing = m_ySpacing = 0;
m_bDirty = false;
}
CGrid::CGridEntry* CGrid::GridEntry(int x, int y)
{
AssertCheck(x >= 0 && x < m_xCols && y >= 0 && y < m_yRows, "CGrid::GridEntry: invalid location specified");
return &m_GridEntries[y*m_xCols + x];
}
void CGrid::CalcColOffsets(int iStart)
{
int cur = m_xSpacing;
if(iStart != 0)
cur += m_ColOffsets[iStart-1] + m_Widths[iStart-1];
for(int i=iStart; i < m_xCols; i++)
{
m_ColOffsets[i] = cur;
cur += m_Widths[i] + m_xSpacing;
}
}
void CGrid::CalcRowOffsets(int iStart)
{
int cur = m_ySpacing;
if(iStart != 0)
cur += m_RowOffsets[iStart-1];
for(int i=iStart; i < m_yRows; i++)
{
m_RowOffsets[i] = cur;
cur += m_Heights[i] + m_ySpacing;
}
}
bool CGrid::getCellAtPoint(int worldX, int worldY, int &row, int &col)
{
row = -1; col = -1;
for(int x=0; x < m_xCols; x++)
{
for(int y=0; y < m_yRows; y++)
{
Panel *pPanel = GridEntry(x,y)->m_pPanel;
if (!pPanel)
continue;
if (pPanel->isWithin(worldX, worldY))
{
col = x;
row = y;
return true;
}
}
}
return false;
}