//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ============ // // Purpose: // // $NoKeywords: $ //============================================================================= #include #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; }