Counter Strike : Global Offensive Source Code
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.

426 lines
12 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <stdarg.h>
  8. #include <stdio.h>
  9. #include <vgui/IInput.h>
  10. #include <vgui/IPanel.h>
  11. #include <vgui/IScheme.h>
  12. #include <vgui/ISystem.h>
  13. #include <vgui/IVGui.h>
  14. #include <vgui/KeyCode.h>
  15. #include <keyvalues.h>
  16. #include <vgui_controls/FocusNavGroup.h>
  17. #include <vgui_controls/Image.h>
  18. #include <vgui_controls/RadioButton.h>
  19. #include <vgui_controls/TextImage.h>
  20. #include <vgui_controls/Controls.h>
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include <tier0/memdbgon.h>
  23. using namespace vgui;
  24. enum direction
  25. {
  26. UP = -1,
  27. DOWN = 1,
  28. };
  29. //-----------------------------------------------------------------------------
  30. // Purpose: Check box image
  31. //-----------------------------------------------------------------------------
  32. class RadioImage : public Image
  33. {
  34. public:
  35. RadioImage(RadioButton *radioButton)
  36. {
  37. _radioButton = radioButton;
  38. _font = INVALID_FONT;
  39. SetSize(20, 13);
  40. }
  41. virtual void ApplySchemeSettings(IScheme *pScheme, bool proportional)
  42. {
  43. _bgColor = _radioButton->GetSchemeColor("CheckButton.BgColor", Color(150, 150, 150, 0), pScheme);
  44. _borderColor1 = _radioButton->GetSchemeColor("CheckButton.Border1", Color(20, 20, 20, 0), pScheme);
  45. _borderColor2 = _radioButton->GetSchemeColor("CheckButton.Border2", Color(90, 90, 90, 0), pScheme);
  46. _checkColor = _radioButton->GetSchemeColor("CheckButton.Check", Color(20, 20, 20, 0), pScheme);
  47. _font = pScheme->GetFont("Marlett", proportional);
  48. }
  49. virtual void Paint()
  50. {
  51. DrawSetTextFont(_font);
  52. // draw background
  53. if (_radioButton->IsEnabled())
  54. {
  55. DrawSetTextColor(_bgColor);
  56. }
  57. else
  58. {
  59. DrawSetTextColor(_radioButton->GetBgColor());
  60. }
  61. DrawPrintChar(0, 1, 'n');
  62. // draw border circl
  63. DrawSetTextColor(_borderColor1);
  64. DrawPrintChar(0, 1, 'j');
  65. DrawSetTextColor(_borderColor2);
  66. DrawPrintChar(0, 1, 'k');
  67. // draw selected check
  68. if (_radioButton->IsSelected())
  69. {
  70. DrawSetTextColor(_checkColor);
  71. DrawPrintChar(0, 1, 'h');
  72. }
  73. }
  74. private:
  75. RadioButton *_radioButton;
  76. Color _borderColor1;
  77. Color _borderColor2;
  78. Color _checkColor;
  79. Color _bgColor;
  80. HFont _font;
  81. };
  82. DECLARE_BUILD_FACTORY_DEFAULT_TEXT( RadioButton, RadioButton );
  83. //-----------------------------------------------------------------------------
  84. // Purpose: Create a radio button.
  85. //-----------------------------------------------------------------------------
  86. RadioButton::RadioButton(Panel *parent, const char *panelName, const char *text) : ToggleButton(parent, panelName, text)
  87. {
  88. SetContentAlignment(a_west);
  89. // create the image
  90. _radioBoxImage = new RadioImage(this);
  91. _oldTabPosition = 0;
  92. _subTabPosition = 0;
  93. SetTextImageIndex(1);
  94. SetImageAtIndex(0, _radioBoxImage, 0);
  95. SetButtonActivationType(ACTIVATE_ONPRESSED);
  96. }
  97. //-----------------------------------------------------------------------------
  98. // Purpose: Destructor
  99. //-----------------------------------------------------------------------------
  100. RadioButton::~RadioButton()
  101. {
  102. delete _radioBoxImage;
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Purpose: Apply resource file scheme.
  106. //-----------------------------------------------------------------------------
  107. void RadioButton::ApplySchemeSettings(IScheme *pScheme)
  108. {
  109. BaseClass::ApplySchemeSettings(pScheme);
  110. _radioBoxImage->ApplySchemeSettings(pScheme, IsProportional());
  111. SetFgColor(GetSchemeColor("RadioButton.TextColor", pScheme));
  112. _selectedFgColor = GetSchemeColor("RadioButton.SelectedTextColor", GetSchemeColor("ControlText", pScheme), pScheme);
  113. SetDefaultColor( GetFgColor(), GetBgColor() );
  114. SetArmedColor( GetSchemeColor("RadioButton.ArmedTextColor", pScheme), GetButtonArmedBgColor() );
  115. SetContentAlignment(a_west);
  116. // reloading the scheme wipes out lists of images
  117. SetImageAtIndex(0, _radioBoxImage, 0);
  118. // don't draw a background
  119. SetPaintBackgroundEnabled(false);
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Purpose: Get the border style of the button, Radio buttons have no border
  123. //-----------------------------------------------------------------------------
  124. IBorder *RadioButton::GetBorder(bool depressed, bool armed, bool selected, bool keyfocus)
  125. {
  126. return NULL;
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Purpose: Get the tab position of the radio button with the set of radio buttons
  130. // A group of RadioButtons must have the same TabPosition, with [1, n] subtabpositions
  131. //-----------------------------------------------------------------------------
  132. int RadioButton::GetSubTabPosition()
  133. {
  134. return _subTabPosition;
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose: Get the tab position of the radio button with the set of radio buttons
  138. // A group of RadioButtons must have the same TabPosition, with [1, n] subtabpositions
  139. //-----------------------------------------------------------------------------
  140. void RadioButton::SetSubTabPosition(int position)
  141. {
  142. _subTabPosition = position;
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Purpose: Return the RadioButton's real tab position (its Panel one changes)
  146. //-----------------------------------------------------------------------------
  147. int RadioButton::GetRadioTabPosition()
  148. {
  149. return _oldTabPosition;
  150. }
  151. //-----------------------------------------------------------------------------
  152. // Purpose: Set the radio button checked. When a radio button is checked, a
  153. // message is sent to all other radio buttons in the same group so
  154. // they will become unchecked.
  155. //-----------------------------------------------------------------------------
  156. void RadioButton::SetSelected(bool state)
  157. {
  158. if (state == true)
  159. {
  160. if (!IsEnabled())
  161. return;
  162. // restore our tab position
  163. SetTabPosition(_oldTabPosition);
  164. // send a message saying we've signed on
  165. KeyValues *msg = new KeyValues("RadioButtonChecked");
  166. msg->SetPtr("panel", this);
  167. msg->SetInt("tabposition", _oldTabPosition);
  168. // send a message to all other panels on the same level as heirarchy,
  169. // so that other radio buttons know to shut off
  170. VPANEL radioParent = GetVParent();
  171. if (radioParent)
  172. {
  173. for (int i = 0; i < ipanel()->GetChildCount(radioParent); i++)
  174. {
  175. VPANEL child = ipanel()->GetChild(radioParent, i);
  176. if (child != GetVPanel())
  177. {
  178. ivgui()->PostMessage(child, msg->MakeCopy(), GetVPanel());
  179. }
  180. }
  181. }
  182. RequestFocus();
  183. PostActionSignal(msg);
  184. }
  185. else
  186. {
  187. // remove ourselves from the tab order
  188. if (GetTabPosition())
  189. {
  190. _oldTabPosition = GetTabPosition();
  191. }
  192. SetTabPosition(0);
  193. }
  194. InvalidateLayout();
  195. Repaint();
  196. ToggleButton::SetSelected(state);
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Purpose: Set up the text color before doing normal layout
  200. //-----------------------------------------------------------------------------
  201. void RadioButton::PerformLayout()
  202. {
  203. if (IsSelected())
  204. {
  205. SetFgColor(_selectedFgColor);
  206. }
  207. else
  208. {
  209. SetFgColor(GetButtonFgColor());
  210. }
  211. BaseClass::PerformLayout();
  212. }
  213. //-----------------------------------------------------------------------------
  214. // Purpose: Apply resource settings including button state and text color.
  215. //-----------------------------------------------------------------------------
  216. void RadioButton::ApplySettings(KeyValues *inResourceData)
  217. {
  218. ToggleButton::ApplySettings(inResourceData);
  219. SetTextColorState(CS_NORMAL);
  220. _subTabPosition = inResourceData->GetInt("SubTabPosition");
  221. _oldTabPosition = inResourceData->GetInt("TabPosition");
  222. SetImageAtIndex(0, _radioBoxImage, 0);
  223. }
  224. //-----------------------------------------------------------------------------
  225. // Purpose: Get resource settings including button state, text color, and subTabPosition
  226. //-----------------------------------------------------------------------------
  227. void RadioButton::GetSettings(KeyValues *outResourceData)
  228. {
  229. ToggleButton::GetSettings(outResourceData);
  230. outResourceData->SetInt("SubTabPosition", _subTabPosition);
  231. outResourceData->SetInt("TabPosition", GetRadioTabPosition());
  232. }
  233. //-----------------------------------------------------------------------------
  234. // Purpose: Describe editing details
  235. //-----------------------------------------------------------------------------
  236. const char *RadioButton::GetDescription( void )
  237. {
  238. static char buf[1024];
  239. Q_snprintf(buf, sizeof(buf), "%s, int SubTabPosition", BaseClass::GetDescription());
  240. return buf;
  241. }
  242. //-----------------------------------------------------------------------------
  243. // Purpose: When a radio button is checked, all other radio buttons
  244. // in the same group become unchecked.
  245. //-----------------------------------------------------------------------------
  246. void RadioButton::OnRadioButtonChecked(int tabPosition)
  247. {
  248. // make sure we're in the same tab group
  249. if (tabPosition != _oldTabPosition)
  250. return;
  251. // wouldn't be sent to us from ourselves, so another radio button has taken over
  252. SetSelected(false);
  253. }
  254. //-----------------------------------------------------------------------------
  255. // Purpose: Draws the selection rectangle
  256. //-----------------------------------------------------------------------------
  257. void RadioButton::Paint()
  258. {
  259. BaseClass::Paint();
  260. /*
  261. if (HasFocus())
  262. {
  263. int tx0, ty0, tx1, ty1;
  264. _textImage->GetPos(tx0, ty0);
  265. _textImage->GetSize(tx1, ty1);
  266. DrawFocusBorder(tx0, ty0, tx0 + tx1, ty0 + ty1);
  267. }
  268. */
  269. }
  270. //-----------------------------------------------------------------------------
  271. // Purpose:
  272. //-----------------------------------------------------------------------------
  273. void RadioButton::DoClick()
  274. {
  275. SetSelected(true);
  276. }
  277. //-----------------------------------------------------------------------------
  278. // Purpose: Handle arrow key movement
  279. //-----------------------------------------------------------------------------
  280. void RadioButton::OnKeyCodeTyped(KeyCode code)
  281. {
  282. switch (code)
  283. {
  284. case KEY_ENTER:
  285. case KEY_SPACE:
  286. {
  287. if (!IsSelected())
  288. {
  289. SetSelected(true);
  290. }
  291. else
  292. {
  293. Panel::OnKeyCodeTyped(code);
  294. }
  295. }
  296. break;
  297. case KEY_DOWN:
  298. case KEY_RIGHT:
  299. {
  300. RadioButton *bestRadio = FindBestRadioButton( DOWN );
  301. if (bestRadio)
  302. {
  303. bestRadio->SetSelected(true);
  304. }
  305. }
  306. break;
  307. case KEY_UP:
  308. case KEY_LEFT:
  309. {
  310. RadioButton *bestRadio = FindBestRadioButton( UP );
  311. if (bestRadio)
  312. {
  313. bestRadio->SetSelected(true);
  314. }
  315. }
  316. break;
  317. default:
  318. BaseClass::OnKeyCodeTyped(code);
  319. break;
  320. }
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Purpose: Find the correct radio button to move to.
  324. // Input : direction - the direction we are moving, up or down.
  325. //-----------------------------------------------------------------------------
  326. RadioButton *RadioButton::FindBestRadioButton(int direction)
  327. {
  328. RadioButton *bestRadio = NULL;
  329. int highestRadio = 0;
  330. Panel *pr = GetParent();
  331. if (pr)
  332. {
  333. // find the radio button to go to next
  334. for (int i = 0; i < pr->GetChildCount(); i++)
  335. {
  336. RadioButton *child = dynamic_cast<RadioButton *>(pr->GetChild(i));
  337. if (child && child->GetRadioTabPosition() == _oldTabPosition)
  338. {
  339. if (child->GetSubTabPosition() == _subTabPosition + direction)
  340. {
  341. bestRadio = child;
  342. break;
  343. }
  344. if ( (child->GetSubTabPosition() == 0) && (direction == DOWN) )
  345. {
  346. bestRadio = child;
  347. continue;
  348. }
  349. else if ( (child->GetSubTabPosition() > highestRadio) && (direction == UP) )
  350. {
  351. bestRadio = child;
  352. highestRadio = bestRadio->GetSubTabPosition();
  353. continue;
  354. }
  355. if (!bestRadio)
  356. {
  357. bestRadio = child;
  358. }
  359. }
  360. }
  361. if (bestRadio)
  362. {
  363. bestRadio->RequestFocus();
  364. }
  365. InvalidateLayout();
  366. Repaint();
  367. }
  368. return bestRadio;
  369. }