Team Fortress 2 Source Code as on 22/4/2020
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.

410 lines
7.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "vgui_grid.h"
  9. #include <vgui_controls/Controls.h>
  10. #include <vgui/ISurface.h>
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. using namespace vgui;
  14. #define AssertCheck(expr, msg) \
  15. if(!(expr))\
  16. {\
  17. assert(!msg);\
  18. return 0;\
  19. }
  20. // ------------------------------------------------------------------------------ //
  21. // CGrid::CGridEntry.
  22. // ------------------------------------------------------------------------------ //
  23. CGrid::CGridEntry::CGridEntry()
  24. {
  25. m_pPanel = NULL;
  26. m_bUnderline = false;
  27. }
  28. CGrid::CGridEntry::~CGridEntry()
  29. {
  30. }
  31. // ------------------------------------------------------------------------------ //
  32. // CGrid.
  33. // ------------------------------------------------------------------------------ //
  34. CGrid::CGrid()
  35. {
  36. Clear();
  37. }
  38. CGrid::~CGrid()
  39. {
  40. Term();
  41. }
  42. bool CGrid::SetDimensions(int xCols, int yRows)
  43. {
  44. Term();
  45. m_GridEntries = new CGridEntry[xCols * yRows];
  46. m_Widths = new int[xCols*2 + yRows*2];
  47. m_Heights = m_Widths + xCols;
  48. m_ColOffsets = m_Heights + yRows;
  49. m_RowOffsets = m_ColOffsets + xCols;
  50. if(!m_GridEntries || !m_Widths)
  51. {
  52. Term();
  53. return false;
  54. }
  55. memset(m_Widths, 0, sizeof(int) * (xCols*2 + yRows*2));
  56. m_xCols = xCols;
  57. m_yRows = yRows;
  58. return true;
  59. }
  60. void CGrid::Term()
  61. {
  62. delete [] m_GridEntries;
  63. delete [] m_Widths;
  64. Clear();
  65. }
  66. Panel* CGrid::GetEntry(int x, int y)
  67. {
  68. return GridEntry(x, y)->m_pPanel;
  69. }
  70. bool CGrid::SetEntry(int x, int y, Panel *pPanel)
  71. {
  72. CGridEntry *pEntry = GridEntry(x, y);
  73. if(!pEntry)
  74. return false;
  75. if (pEntry->m_pPanel)
  76. {
  77. pEntry->m_pPanel->SetParent( (Panel *)NULL );
  78. }
  79. pEntry->m_pPanel = pPanel;
  80. if (pPanel)
  81. {
  82. pPanel->SetParent(this);
  83. }
  84. m_bDirty = true;
  85. return true;
  86. }
  87. int CGrid::GetXSpacing()
  88. {
  89. return m_xSpacing;
  90. }
  91. int CGrid::GetYSpacing()
  92. {
  93. return m_ySpacing;
  94. }
  95. void CGrid::SetSpacing(int xSpacing, int ySpacing)
  96. {
  97. if(xSpacing != m_xSpacing)
  98. {
  99. m_xSpacing = xSpacing;
  100. CalcColOffsets(0);
  101. m_bDirty = true;
  102. }
  103. if(ySpacing != m_ySpacing)
  104. {
  105. m_ySpacing = ySpacing;
  106. CalcRowOffsets(0);
  107. m_bDirty = true;
  108. }
  109. }
  110. bool CGrid::SetColumnWidth(int iColumn, int width)
  111. {
  112. AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::SetColumnWidth : invalid location specified");
  113. m_Widths[iColumn] = width;
  114. CalcColOffsets(iColumn+1);
  115. m_bDirty = true;
  116. return true;
  117. }
  118. bool CGrid::SetRowHeight(int iRow, int height)
  119. {
  120. AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::SetColumnWidth : invalid location specified");
  121. m_Heights[iRow] = height;
  122. CalcRowOffsets(iRow+1);
  123. m_bDirty = true;
  124. return true;
  125. }
  126. int CGrid::GetColumnWidth(int iColumn)
  127. {
  128. AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::GetColumnWidth: invalid location specified");
  129. return m_Widths[iColumn];
  130. }
  131. int CGrid::GetRowHeight(int iRow)
  132. {
  133. AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::GetRowHeight: invalid location specified");
  134. return m_Heights[iRow];
  135. }
  136. int CGrid::CalcFitColumnWidth(int iColumn)
  137. {
  138. AssertCheck(iColumn >= 0 && iColumn < m_xCols, "CGrid::CalcFitColumnWidth: invalid location specified");
  139. int maxSize = 0;
  140. for(int i=0; i < m_yRows; i++)
  141. {
  142. Panel *pPanel = GridEntry(iColumn, i)->m_pPanel;
  143. if(!pPanel)
  144. continue;
  145. int w, h;
  146. pPanel->GetSize(w,h);
  147. if(w > maxSize)
  148. maxSize = w;
  149. }
  150. return maxSize;
  151. }
  152. int CGrid::CalcFitRowHeight(int iRow)
  153. {
  154. AssertCheck(iRow >= 0 && iRow < m_yRows, "CGrid::CalcFitRowHeight: invalid location specified");
  155. int maxSize = 0;
  156. for(int i=0; i < m_xCols; i++)
  157. {
  158. Panel *pPanel = GridEntry(i, iRow)->m_pPanel;
  159. if(!pPanel)
  160. continue;
  161. int w, h;
  162. pPanel->GetSize(w,h);
  163. if(h > maxSize)
  164. maxSize = h;
  165. }
  166. return maxSize;
  167. }
  168. void CGrid::AutoSetRowHeights()
  169. {
  170. for(int i=0; i < m_yRows; i++)
  171. SetRowHeight(i, CalcFitRowHeight(i));
  172. }
  173. bool CGrid::GetEntryBox(
  174. int col, int row, int &x, int &y, int &w, int &h)
  175. {
  176. AssertCheck(col >= 0 && col < m_xCols && row >= 0 && row < m_yRows, "CGrid::GetEntryBox: invalid location specified");
  177. x = m_ColOffsets[col];
  178. w = m_Widths[col];
  179. y = m_RowOffsets[row];
  180. h = m_Heights[row];
  181. return true;
  182. }
  183. bool CGrid::CopyColumnWidths(CGrid *pOther)
  184. {
  185. if(!pOther || pOther->m_xCols != m_xCols)
  186. return false;
  187. for(int i=0; i < m_xCols; i++)
  188. m_Widths[i] = pOther->m_Widths[i];
  189. CalcColOffsets(0);
  190. m_bDirty = true;
  191. return true;
  192. }
  193. void CGrid::RepositionContents()
  194. {
  195. for(int x=0; x < m_xCols; x++)
  196. {
  197. for(int y=0; y < m_yRows; y++)
  198. {
  199. Panel *pPanel = GridEntry(x,y)->m_pPanel;
  200. if(!pPanel)
  201. continue;
  202. pPanel->SetBounds(
  203. m_ColOffsets[x],
  204. m_RowOffsets[y],
  205. m_Widths[x],
  206. m_Heights[y]);
  207. }
  208. }
  209. m_bDirty = false;
  210. }
  211. int CGrid::CalcDrawHeight()
  212. {
  213. if(m_yRows > 0)
  214. {
  215. return m_RowOffsets[m_yRows-1] + m_Heights[m_yRows - 1] + m_ySpacing;
  216. }
  217. else
  218. {
  219. return 0;
  220. }
  221. }
  222. void CGrid::Paint()
  223. {
  224. if(m_bDirty)
  225. RepositionContents();
  226. Panel::Paint();
  227. int w, h;
  228. GetSize( w, h );
  229. int xx, yy;
  230. GetPos( xx, yy );
  231. // walk the grid looking for underlined rows
  232. int x = 0, y = 0;
  233. for (int row = 0; row < m_yRows; row++)
  234. {
  235. CGridEntry *cell = GridEntry(0, row);
  236. y = m_RowOffsets[ row ] + m_Heights[ row ] + m_ySpacing;
  237. if (cell->m_bUnderline)
  238. {
  239. vgui::surface()->DrawSetColor(cell->m_UnderlineColor[0], cell->m_UnderlineColor[1], cell->m_UnderlineColor[2], cell->m_UnderlineColor[3]);
  240. vgui::surface()->DrawFilledRect(x, y - (cell->m_iUnderlineOffset + 1), GetWide(), y - cell->m_iUnderlineOffset);
  241. }
  242. }
  243. }
  244. void CGrid::PaintBackground()
  245. {
  246. Panel::PaintBackground();
  247. }
  248. //-----------------------------------------------------------------------------
  249. // Purpose: sets underline color for a particular row
  250. //-----------------------------------------------------------------------------
  251. void CGrid::SetRowUnderline(int row, bool enabled, int offset, int r, int g, int b, int a)
  252. {
  253. CGridEntry *cell = GridEntry(0, row);
  254. cell->m_bUnderline = enabled;
  255. if (enabled)
  256. {
  257. cell->m_iUnderlineOffset = offset;
  258. cell->m_UnderlineColor[0] = r;
  259. cell->m_UnderlineColor[1] = g;
  260. cell->m_UnderlineColor[2] = b;
  261. cell->m_UnderlineColor[3] = a;
  262. }
  263. }
  264. void CGrid::Clear()
  265. {
  266. m_xCols = m_yRows = 0;
  267. m_Widths = NULL;
  268. m_GridEntries = NULL;
  269. m_xSpacing = m_ySpacing = 0;
  270. m_bDirty = false;
  271. }
  272. CGrid::CGridEntry* CGrid::GridEntry(int x, int y)
  273. {
  274. AssertCheck(x >= 0 && x < m_xCols && y >= 0 && y < m_yRows, "CGrid::GridEntry: invalid location specified");
  275. return &m_GridEntries[y*m_xCols + x];
  276. }
  277. void CGrid::CalcColOffsets(int iStart)
  278. {
  279. int cur = m_xSpacing;
  280. if(iStart != 0)
  281. cur += m_ColOffsets[iStart-1] + m_Widths[iStart-1];
  282. for(int i=iStart; i < m_xCols; i++)
  283. {
  284. m_ColOffsets[i] = cur;
  285. cur += m_Widths[i] + m_xSpacing;
  286. }
  287. }
  288. void CGrid::CalcRowOffsets(int iStart)
  289. {
  290. int cur = m_ySpacing;
  291. if(iStart != 0)
  292. cur += m_RowOffsets[iStart-1];
  293. for(int i=iStart; i < m_yRows; i++)
  294. {
  295. m_RowOffsets[i] = cur;
  296. cur += m_Heights[i] + m_ySpacing;
  297. }
  298. }
  299. bool CGrid::GetCellAtPoint(int worldX, int worldY, int &row, int &col)
  300. {
  301. row = -1; col = -1;
  302. for(int x=0; x < m_xCols; x++)
  303. {
  304. for(int y=0; y < m_yRows; y++)
  305. {
  306. Panel *pPanel = GridEntry(x,y)->m_pPanel;
  307. if (!pPanel)
  308. continue;
  309. if (pPanel->IsWithin(worldX, worldY))
  310. {
  311. col = x;
  312. row = y;
  313. return true;
  314. }
  315. }
  316. }
  317. return false;
  318. }