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.

431 lines
8.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // ListBoxEx.cpp : implementation file
  9. //
  10. #include "stdafx.h"
  11. #include "hammer.h"
  12. #include "ListBoxEx.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include <tier0/memdbgon.h>
  15. /////////////////////////////////////////////////////////////////////////////
  16. // CListBoxEx
  17. CListBoxEx::CListBoxEx()
  18. {
  19. Items.SetSize(16);
  20. nItems = 0;
  21. iItemHeight = -1;
  22. dwStyle = 0;
  23. bControlActive = FALSE;
  24. bIgnoreChange = FALSE;
  25. }
  26. CListBoxEx::~CListBoxEx()
  27. {
  28. }
  29. BEGIN_MESSAGE_MAP(CListBoxEx, CListBox)
  30. //{{AFX_MSG_MAP(CListBoxEx)
  31. ON_WM_LBUTTONDOWN()
  32. ON_CONTROL_REFLECT(LBN_SELCHANGE, OnSelchange)
  33. ON_WM_LBUTTONUP()
  34. ON_WM_CHAR()
  35. //}}AFX_MSG_MAP
  36. END_MESSAGE_MAP()
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CListBoxEx message handlers
  39. void CListBoxEx::SetStyle(DWORD dwStyle_)
  40. {
  41. this->dwStyle = dwStyle_;
  42. }
  43. void CListBoxEx::AddItem(char *pszCaption, int iEditType, PVOID pData,
  44. int iRangeMin, int iRangeMax, const char * pszHelp)
  45. {
  46. LBEXTITEMSTRUCT lbis;
  47. memset(&lbis, 0, sizeof lbis);
  48. strcpy(lbis.szCaption, pszCaption);
  49. lbis.pszSaveCaption = pszCaption;
  50. lbis.iEditType = iEditType;
  51. switch(iEditType)
  52. {
  53. case lbeYesNo:
  54. case lbeOnOff:
  55. lbis.iDataType = lbdBool;
  56. lbis.iDataValue = PINT(pData)[0];
  57. break;
  58. case lbeInteger:
  59. lbis.iDataType = lbdInteger;
  60. lbis.iDataValue = PINT(pData)[0];
  61. break;
  62. case lbeTexture:
  63. case lbeString:
  64. lbis.iDataType = lbdString;
  65. strcpy(lbis.szDataString, LPCTSTR(pData));
  66. break;
  67. case lbeChoices:
  68. lbis.iDataType = lbdString;
  69. lbis.pChoices = NULL;
  70. break;
  71. }
  72. lbis.pSaveTo = pData;
  73. lbis.iRangeMin = iRangeMin;
  74. lbis.iRangeMax = iRangeMax;
  75. lbis.pszHelp = pszHelp;
  76. Items[nItems++] = lbis;
  77. AddString(""); // trick windows! muahaha
  78. }
  79. void CListBoxEx::SetItemChoices(int iItem, CStringArray * pChoices,
  80. int iDefaultChoice)
  81. {
  82. LBEXTITEMSTRUCT& lbis = Items[iItem];
  83. lbis.pChoices = pChoices;
  84. lbis.iDataValue = iDefaultChoice;
  85. V_strcpy_safe( lbis.szDataString, pChoices->GetAt( iDefaultChoice ) );
  86. }
  87. void CListBoxEx::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  88. {
  89. if(iItemHeight == -1)
  90. {
  91. CDC *pDC = GetDC();
  92. TEXTMETRIC tm;
  93. pDC->GetOutputTextMetrics(&tm);
  94. iItemHeight = tm.tmHeight + 4;
  95. CRect r;
  96. GetClientRect(r);
  97. iCaptionWidthPixels = r.Width() / 2;
  98. ReleaseDC(pDC);
  99. }
  100. lpMeasureItemStruct->itemHeight = iItemHeight;
  101. }
  102. void CListBoxEx::GetItemText(int iItem, char *pszText)
  103. {
  104. LBEXTITEMSTRUCT& lbis = Items[iItem];
  105. switch(lbis.iDataType)
  106. {
  107. case lbdBool:
  108. if(lbis.iEditType == lbeYesNo)
  109. strcpy(pszText, lbis.iDataValue ? "Yes" : "No");
  110. else
  111. strcpy(pszText, lbis.iDataValue ? "On" : "Off");
  112. break;
  113. case lbdString:
  114. strcpy(pszText, lbis.szDataString);
  115. break;
  116. case lbdInteger:
  117. ltoa(lbis.iDataValue, pszText, 10);
  118. break;
  119. }
  120. }
  121. void CListBoxEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  122. {
  123. CDC dc;
  124. dc.Attach(lpDrawItemStruct->hDC);
  125. dc.SaveDC();
  126. RECT& r = lpDrawItemStruct->rcItem;
  127. if(lpDrawItemStruct->itemID != -1 &&
  128. (lpDrawItemStruct->itemAction == ODA_DRAWENTIRE ||
  129. lpDrawItemStruct->itemAction == ODA_SELECT))
  130. {
  131. LBEXTITEMSTRUCT& item = Items[lpDrawItemStruct->itemID];
  132. dc.SetROP2(R2_COPYPEN);
  133. int iBackIndex = COLOR_WINDOW;
  134. int iForeIndex = COLOR_WINDOWTEXT;
  135. BOOL bDrawCaptionOnly = FALSE;
  136. if(lpDrawItemStruct->itemAction == ODA_SELECT &&
  137. (lpDrawItemStruct->itemState & ODS_SELECTED))
  138. {
  139. iBackIndex = COLOR_HIGHLIGHT;
  140. iForeIndex = COLOR_HIGHLIGHTTEXT;
  141. bDrawCaptionOnly = item.iDataType != lbdBool ? TRUE : FALSE;
  142. }
  143. // draw background
  144. CBrush brush;
  145. brush.CreateSolidBrush(GetSysColor(iBackIndex));
  146. if(0)//!bDrawCaptionOnly)
  147. dc.FillRect(&r, &brush);
  148. else
  149. {
  150. CRect r2(&r);
  151. r2.right = iCaptionWidthPixels;
  152. dc.FillRect(r2, &brush);
  153. }
  154. // first, draw text
  155. dc.SetTextColor(GetSysColor(iForeIndex));
  156. dc.SetBkColor(GetSysColor(iBackIndex));
  157. dc.TextOut(r.left + 1, r.top+ 1, item.szCaption,
  158. strlen(item.szCaption));
  159. if(!bDrawCaptionOnly)
  160. {
  161. // draw value ..
  162. char szText[128];
  163. GetItemText(lpDrawItemStruct->itemID, szText);
  164. dc.TextOut(r.left + iCaptionWidthPixels + 1, r.top + 1,
  165. szText, strlen(szText));
  166. }
  167. // draw border.
  168. CPen pen(PS_SOLID, 1, RGB(200, 200, 200));
  169. dc.SelectObject(pen);
  170. dc.MoveTo(r.left, r.bottom-1);
  171. dc.LineTo(r.right, r.bottom-1);
  172. dc.MoveTo(r.left + iCaptionWidthPixels, r.top);
  173. dc.LineTo(r.left + iCaptionWidthPixels, r.bottom-1);
  174. }
  175. else if(lpDrawItemStruct->itemAction == ODA_FOCUS)
  176. {
  177. dc.DrawFocusRect(&r);
  178. }
  179. dc.RestoreDC(-1);
  180. }
  181. void CListBoxEx::OnLButtonDown(UINT nFlags, CPoint point)
  182. {
  183. BOOL bOutside;
  184. int iItem = ItemFromPoint(point, bOutside);
  185. LBEXTITEMSTRUCT& lbis = Items[iItem];
  186. if(lbis.iDataType == lbdBool)
  187. {
  188. // toggle bool field
  189. lbis.iDataValue = !lbis.iDataValue;
  190. }
  191. CListBox::OnLButtonDown(nFlags, point);
  192. }
  193. int CListBoxEx::CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
  194. {
  195. return 0;
  196. }
  197. void CListBoxEx::CreateEditControl()
  198. {
  199. if(IsWindow(EditCtrl.m_hWnd))
  200. return;
  201. // create edit control
  202. int iItem = GetCurSel();
  203. if(iItem == LB_ERR)
  204. return;
  205. LBEXTITEMSTRUCT& lbis = Items[iItem];
  206. if(lbis.iEditType != lbeString &&
  207. lbis.iEditType != lbeInteger &&
  208. lbis.iEditType != lbeTexture)
  209. return;
  210. CRect r;
  211. GetItemRect(iItem, r);
  212. r.InflateRect(-1, -1);
  213. r.left += iCaptionWidthPixels;
  214. // create edit ctrl
  215. EditCtrl.Create(ES_LEFT | ES_LOWERCASE | WS_VISIBLE | WS_TABSTOP, r, this,
  216. IDC_EDITPARAMETER);
  217. // set font
  218. HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  219. if (hFont == NULL)
  220. hFont = (HFONT)GetStockObject(ANSI_VAR_FONT);
  221. EditCtrl.SendMessage(WM_SETFONT, (WPARAM)hFont);
  222. // set current text in edit ctrl
  223. char szBuf[128];
  224. GetItemText(iItem, szBuf);
  225. EditCtrl.SetWindowText(szBuf);
  226. EditCtrl.SetForegroundWindow();
  227. EditCtrl.SetSel(0, -1);
  228. bControlActive = TRUE;
  229. iControlItem = iItem;
  230. }
  231. void CListBoxEx::CreateComboControl()
  232. {
  233. if(IsWindow(ComboCtrl.m_hWnd))
  234. return;
  235. // create edit control
  236. int iItem = GetCurSel();
  237. if(iItem == LB_ERR)
  238. return;
  239. LBEXTITEMSTRUCT& lbis = Items[iItem];
  240. if(lbis.iEditType != lbeChoices)
  241. return;
  242. CRect r;
  243. GetItemRect(iItem, r);
  244. r.left += iCaptionWidthPixels;
  245. r.bottom += 80;
  246. // create combo ctrl
  247. ComboCtrl.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST |
  248. WS_TABSTOP, r, this, IDC_EDITPARAMETER);
  249. // set font
  250. HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  251. if (hFont == NULL)
  252. hFont = (HFONT)GetStockObject(ANSI_VAR_FONT);
  253. ComboCtrl.SendMessage(WM_SETFONT, (WPARAM)hFont);
  254. // add strings to combo ctrl
  255. CStringArray * pChoices = lbis.pChoices;
  256. Assert(pChoices);
  257. for(int i = 0; i < pChoices->GetSize(); i++)
  258. ComboCtrl.AddString(pChoices->GetAt(i));
  259. // set current selection in combo ctrl
  260. ComboCtrl.SetCurSel(lbis.iDataValue);
  261. ComboCtrl.SetForegroundWindow();
  262. bControlActive = TRUE;
  263. iControlItem = iItem;
  264. }
  265. void CListBoxEx::DestroyControls()
  266. {
  267. // get rid of window if there is one
  268. if(::IsWindow(EditCtrl.m_hWnd))
  269. {
  270. EditCtrl.DestroyWindow();
  271. }
  272. if(::IsWindow(ComboCtrl.m_hWnd))
  273. {
  274. ComboCtrl.DestroyWindow();
  275. }
  276. bControlActive = FALSE;
  277. }
  278. void CListBoxEx::OnSelchange()
  279. {
  280. if(bControlActive)
  281. {
  282. // on combobox/edit controls, save string back to data
  283. LBEXTITEMSTRUCT& lbis = Items[iControlItem];
  284. if(lbis.iEditType == lbeChoices)
  285. {
  286. ComboCtrl.GetLBText(ComboCtrl.GetCurSel(), lbis.szDataString);
  287. lbis.iDataValue = ComboCtrl.GetCurSel();
  288. }
  289. else if(lbis.iDataType == lbdString)
  290. {
  291. EditCtrl.GetWindowText(lbis.szDataString, 128);
  292. }
  293. else if(lbis.iDataType == lbdInteger)
  294. {
  295. EditCtrl.GetWindowText(lbis.szDataString, 128);
  296. lbis.iDataValue = atoi(lbis.szDataString);
  297. }
  298. }
  299. DestroyControls();
  300. int iCurItem = GetCurSel();
  301. LBEXTITEMSTRUCT& lbis = Items[iCurItem];
  302. if(lbis.iEditType == lbeChoices)
  303. {
  304. CreateComboControl();
  305. }
  306. else
  307. {
  308. CreateEditControl();
  309. }
  310. }
  311. void CListBoxEx::OnLButtonUp(UINT nFlags, CPoint point)
  312. {
  313. CListBox::OnLButtonUp(nFlags, point);
  314. int iItem = GetCurSel();
  315. if(iItem == LB_ERR)
  316. return;
  317. LBEXTITEMSTRUCT& lbis = Items[iItem];
  318. if(lbis.iDataType == lbdBool)
  319. {
  320. lbis.iDataValue = !lbis.iDataValue;
  321. Invalidate();
  322. }
  323. }
  324. void CListBoxEx::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  325. {
  326. CListBox::OnChar(nChar, nRepCnt, nFlags);
  327. return;
  328. int iItem = GetCurSel();
  329. if(iItem == LB_ERR)
  330. return;
  331. LBEXTITEMSTRUCT& lbis = Items[iItem];
  332. switch(nChar)
  333. {
  334. case VK_RETURN:
  335. if(!(nFlags & 0x8000))
  336. break;
  337. if(lbis.iDataType == lbdBool)
  338. {
  339. // toggle bool field
  340. lbis.iDataValue = !lbis.iDataValue;
  341. Invalidate();
  342. }
  343. else if(lbis.iEditType == lbeChoices)
  344. {
  345. CreateComboControl();
  346. }
  347. else if(lbis.iEditType == lbeString ||
  348. lbis.iEditType == lbeInteger ||
  349. lbis.iEditType == lbeTexture)
  350. {
  351. CreateEditControl();
  352. }
  353. break;
  354. }
  355. }