//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "vgui_grid.h" #include #include // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.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( (Panel *)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(); int w, h; GetSize( w, h ); int xx, yy; GetPos( xx, yy ); // 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 = m_RowOffsets[ row ] + m_Heights[ row ] + m_ySpacing; if (cell->m_bUnderline) { vgui::surface()->DrawSetColor(cell->m_UnderlineColor[0], cell->m_UnderlineColor[1], cell->m_UnderlineColor[2], cell->m_UnderlineColor[3]); vgui::surface()->DrawFilledRect(x, 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; }