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.

358 lines
9.2 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #define PROTECTED_THINGS_DISABLE
  8. #include <vgui/IPanel.h>
  9. #include <vgui/IInput.h>
  10. #include <vgui/ISurface.h>
  11. #include <keyvalues.h>
  12. #include <vgui/IVGui.h>
  13. #include <vgui_controls/Controls.h>
  14. #include <vgui_controls/MenuButton.h>
  15. #include <vgui_controls/Menu.h>
  16. #include <vgui_controls/TextImage.h>
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include <tier0/memdbgon.h>
  19. using namespace vgui;
  20. DECLARE_BUILD_FACTORY_DEFAULT_TEXT( MenuButton, MenuButton );
  21. //-----------------------------------------------------------------------------
  22. // Purpose: Constructor
  23. //-----------------------------------------------------------------------------
  24. MenuButton::MenuButton(Panel *parent, const char *panelName, const char *text) : Button(parent, panelName, text)
  25. {
  26. m_pMenu = NULL;
  27. m_iDirection = Menu::DOWN;
  28. m_pDropMenuImage = NULL;
  29. m_nImageIndex = -1;
  30. _openOffsetY = 0;
  31. SetDropMenuButtonStyle( false );
  32. SetUseCaptureMouse( false );
  33. SetButtonActivationType( ACTIVATE_ONPRESSED );
  34. }
  35. //-----------------------------------------------------------------------------
  36. // Purpose: Destructor
  37. //-----------------------------------------------------------------------------
  38. MenuButton::~MenuButton()
  39. {
  40. delete m_pDropMenuImage;
  41. }
  42. //-----------------------------------------------------------------------------
  43. // Purpose: attaches a menu to the menu button
  44. //-----------------------------------------------------------------------------
  45. void MenuButton::SetMenu(Menu *menu)
  46. {
  47. m_pMenu = menu;
  48. if (menu)
  49. {
  50. m_pMenu->SetVisible(false);
  51. m_pMenu->AddActionSignalTarget(this);
  52. m_pMenu->SetParent(this);
  53. }
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Purpose: Never draw a focus border
  57. //-----------------------------------------------------------------------------
  58. void MenuButton::DrawFocusBorder(int tx0, int ty0, int tx1, int ty1)
  59. {
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Purpose: Sets the direction from the menu button the menu should open
  63. //-----------------------------------------------------------------------------
  64. void MenuButton::SetOpenDirection(Menu::MenuDirection_e direction)
  65. {
  66. m_iDirection = direction;
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose: hides the menu
  70. //-----------------------------------------------------------------------------
  71. void MenuButton::HideMenu(void)
  72. {
  73. if (!m_pMenu)
  74. return;
  75. // hide the menu
  76. m_pMenu->SetVisible(false);
  77. // unstick the button
  78. BaseClass::ForceDepressed(false);
  79. Repaint();
  80. OnHideMenu(m_pMenu);
  81. }
  82. //-----------------------------------------------------------------------------
  83. // Purpose: Called when the menu button loses focus; hides the menu
  84. //-----------------------------------------------------------------------------
  85. void MenuButton::OnKillFocus( KeyValues *pParams )
  86. {
  87. VPANEL hPanel = (VPANEL)pParams->GetPtr( "newPanel" );
  88. if ( m_pMenu && !m_pMenu->HasFocus() && hPanel != m_pMenu->GetVPanel() )
  89. {
  90. HideMenu();
  91. }
  92. BaseClass::OnKillFocus();
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Purpose: Called when the menu is closed
  96. //-----------------------------------------------------------------------------
  97. void MenuButton::OnMenuClose()
  98. {
  99. HideMenu();
  100. PostActionSignal(new KeyValues("MenuClose"));
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Purpose: Sets the offset from where menu would normally be placed
  104. // Only is used if menu is ALIGN_WITH_PARENT
  105. //-----------------------------------------------------------------------------
  106. void MenuButton::SetOpenOffsetY(int yOffset)
  107. {
  108. _openOffsetY = yOffset;
  109. }
  110. //-----------------------------------------------------------------------------
  111. // Purpose:
  112. //-----------------------------------------------------------------------------
  113. bool MenuButton::CanBeDefaultButton(void)
  114. {
  115. return false;
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Purpose: Handles hotkey accesses
  119. //-----------------------------------------------------------------------------
  120. void MenuButton::DoClick()
  121. {
  122. if ( IsDropMenuButtonStyle() &&
  123. m_pDropMenuImage )
  124. {
  125. int mx, my;
  126. // force the menu to appear where the mouse button was pressed
  127. input()->GetCursorPos( mx, my );
  128. ScreenToLocal( mx, my );
  129. int contentW, contentH;
  130. m_pDropMenuImage->GetContentSize( contentW, contentH );
  131. int drawX = GetWide() - contentW - 2;
  132. if ( mx <= drawX || ( OnCheckMenuItemCount() <= 1 ) )
  133. {
  134. // Treat it like a "regular" button click
  135. BaseClass::DoClick();
  136. return;
  137. }
  138. }
  139. if ( !m_pMenu )
  140. {
  141. return;
  142. }
  143. // menu is already visible, hide the menu
  144. if (m_pMenu->IsVisible())
  145. {
  146. HideMenu();
  147. return;
  148. }
  149. // do nothing if menu is not enabled
  150. if (!m_pMenu->IsEnabled())
  151. {
  152. return;
  153. }
  154. // force the menu to compute required width/height
  155. m_pMenu->PerformLayout();
  156. // Now position it so it can fit in the workspace
  157. m_pMenu->PositionRelativeToPanel(this, m_iDirection, _openOffsetY );
  158. // make sure we're at the top of the draw order (and therefore our children as well)
  159. MoveToFront();
  160. // notify
  161. OnShowMenu(m_pMenu);
  162. // keep the button depressed
  163. BaseClass::ForceDepressed(true);
  164. // show the menu
  165. m_pMenu->SetVisible(true);
  166. // bring to focus
  167. m_pMenu->RequestFocus();
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Purpose:
  171. //-----------------------------------------------------------------------------
  172. void MenuButton::OnKeyCodeTyped(KeyCode code)
  173. {
  174. bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT));
  175. bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
  176. bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT));
  177. if (!shift && !ctrl && !alt)
  178. {
  179. switch (code)
  180. {
  181. case KEY_ENTER:
  182. {
  183. if ( !IsDropMenuButtonStyle() )
  184. {
  185. DoClick();
  186. }
  187. break;
  188. }
  189. }
  190. }
  191. BaseClass::OnKeyCodeTyped(code);
  192. }
  193. //-----------------------------------------------------------------------------
  194. // Purpose:
  195. //-----------------------------------------------------------------------------
  196. void MenuButton::OnCursorEntered()
  197. {
  198. Button::OnCursorEntered();
  199. // post a message to the parent menu.
  200. // forward the message on to the parent of this menu.
  201. KeyValues *msg = new KeyValues ("CursorEnteredMenuButton");
  202. // tell the parent this menuitem is the one that was entered so it can open the menu if it wants
  203. msg->SetInt("VPanel", GetVPanel());
  204. ivgui()->PostMessage(GetVParent(), msg, NULL);
  205. }
  206. // This style is like the IE "back" button where the left side acts like a regular button, the the right side has a little
  207. // combo box dropdown indicator and presents and submenu
  208. void MenuButton::SetDropMenuButtonStyle( bool state )
  209. {
  210. bool changed = m_bDropMenuButtonStyle != state;
  211. m_bDropMenuButtonStyle = state;
  212. if ( !changed )
  213. return;
  214. if ( state )
  215. {
  216. m_pDropMenuImage = new TextImage( "u" );
  217. IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
  218. m_pDropMenuImage->SetFont(pScheme->GetFont("Marlett", IsProportional()));
  219. // m_pDropMenuImage->SetContentAlignment(Label::a_west);
  220. // m_pDropMenuImage->SetTextInset(3, 0);
  221. m_nImageIndex = AddImage( m_pDropMenuImage, 0 );
  222. }
  223. else
  224. {
  225. ResetToSimpleTextImage();
  226. delete m_pDropMenuImage;
  227. m_pDropMenuImage = NULL;
  228. m_nImageIndex = -1;
  229. }
  230. }
  231. void MenuButton::ApplySchemeSettings( IScheme *pScheme )
  232. {
  233. BaseClass::ApplySchemeSettings( pScheme );
  234. if ( m_pDropMenuImage )
  235. {
  236. SetImageAtIndex( 1, m_pDropMenuImage, 0 );
  237. }
  238. }
  239. void MenuButton::PerformLayout()
  240. {
  241. BaseClass::PerformLayout();
  242. if ( !IsDropMenuButtonStyle() )
  243. return;
  244. Assert( m_nImageIndex >= 0 );
  245. if ( m_nImageIndex < 0 || !m_pDropMenuImage )
  246. return;
  247. int w, h;
  248. GetSize( w, h );
  249. int contentW, contentH;
  250. m_pDropMenuImage->ResizeImageToContent();
  251. m_pDropMenuImage->GetContentSize( contentW, contentH );
  252. SetImageBounds( m_nImageIndex, w - contentW - 2, contentW );
  253. }
  254. bool MenuButton::IsDropMenuButtonStyle() const
  255. {
  256. return m_bDropMenuButtonStyle;
  257. }
  258. void MenuButton::Paint(void)
  259. {
  260. BaseClass::Paint();
  261. if ( !IsDropMenuButtonStyle() )
  262. return;
  263. int contentW, contentH;
  264. m_pDropMenuImage->GetContentSize( contentW, contentH );
  265. int nItemCount = OnCheckMenuItemCount();
  266. Color clr = GetButtonFgColor();
  267. if ( !IsEnabled() || nItemCount <= 1 )
  268. {
  269. clr = GetDisabledFgColor1();
  270. }
  271. m_pDropMenuImage->SetColor( clr );
  272. int drawX = GetWide() - contentW - 2;
  273. surface()->DrawSetColor( clr );
  274. surface()->DrawFilledRect( drawX, 3, drawX + 1, GetTall() - 3 );
  275. }
  276. void MenuButton::OnCursorMoved( int x, int y )
  277. {
  278. BaseClass::OnCursorMoved( x, y );
  279. if ( !IsDropMenuButtonStyle() )
  280. return;
  281. int contentW, contentH;
  282. m_pDropMenuImage->GetContentSize( contentW, contentH );
  283. int drawX = GetWide() - contentW - 2;
  284. if ( x <= drawX || ( OnCheckMenuItemCount() <= 1 ) )
  285. {
  286. SetButtonActivationType(ACTIVATE_ONPRESSEDANDRELEASED);
  287. SetUseCaptureMouse(true);
  288. }
  289. else
  290. {
  291. SetButtonActivationType(ACTIVATE_ONPRESSED);
  292. SetUseCaptureMouse(false);
  293. }
  294. }
  295. Menu *MenuButton::GetMenu()
  296. {
  297. Assert( m_pMenu );
  298. return m_pMenu;
  299. }