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.
351 lines
9.2 KiB
351 lines
9.2 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#define PROTECTED_THINGS_DISABLE |
|
|
|
#include <vgui/IPanel.h> |
|
#include <vgui/IInput.h> |
|
#include <vgui/ISurface.h> |
|
#include <KeyValues.h> |
|
#include <vgui/IVGui.h> |
|
|
|
#include <vgui_controls/Controls.h> |
|
#include <vgui_controls/MenuButton.h> |
|
#include <vgui_controls/Menu.h> |
|
#include <vgui_controls/TextImage.h> |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
|
|
using namespace vgui; |
|
|
|
DECLARE_BUILD_FACTORY_DEFAULT_TEXT( MenuButton, MenuButton ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
MenuButton::MenuButton(Panel *parent, const char *panelName, const char *text) : Button(parent, panelName, text) |
|
{ |
|
m_pMenu = NULL; |
|
m_iDirection = Menu::DOWN; |
|
m_pDropMenuImage = NULL; |
|
m_nImageIndex = -1; |
|
_openOffsetY = 0; |
|
m_bDropMenuButtonStyle = true; // set to true so SetDropMenuButtonStyle() forces real init. |
|
|
|
SetDropMenuButtonStyle( false ); |
|
SetUseCaptureMouse( false ); |
|
SetButtonActivationType( ACTIVATE_ONPRESSED ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Destructor |
|
//----------------------------------------------------------------------------- |
|
MenuButton::~MenuButton() |
|
{ |
|
delete m_pDropMenuImage; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: attaches a menu to the menu button |
|
//----------------------------------------------------------------------------- |
|
void MenuButton::SetMenu(Menu *menu) |
|
{ |
|
m_pMenu = menu; |
|
|
|
if (menu) |
|
{ |
|
m_pMenu->SetVisible(false); |
|
m_pMenu->AddActionSignalTarget(this); |
|
m_pMenu->SetParent(this); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Never draw a focus border |
|
//----------------------------------------------------------------------------- |
|
void MenuButton::DrawFocusBorder(int tx0, int ty0, int tx1, int ty1) |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Sets the direction from the menu button the menu should open |
|
//----------------------------------------------------------------------------- |
|
void MenuButton::SetOpenDirection(Menu::MenuDirection_e direction) |
|
{ |
|
m_iDirection = direction; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: hides the menu |
|
//----------------------------------------------------------------------------- |
|
void MenuButton::HideMenu(void) |
|
{ |
|
if (!m_pMenu) |
|
return; |
|
|
|
// hide the menu |
|
m_pMenu->SetVisible(false); |
|
|
|
// unstick the button |
|
BaseClass::ForceDepressed(false); |
|
Repaint(); |
|
|
|
OnHideMenu(m_pMenu); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Called when the menu button loses focus; hides the menu |
|
//----------------------------------------------------------------------------- |
|
void MenuButton::OnKillFocus( KeyValues *pParams ) |
|
{ |
|
VPANEL hPanel = (VPANEL)pParams->GetPtr( "newPanel" ); |
|
if ( m_pMenu && !m_pMenu->HasFocus() && hPanel != m_pMenu->GetVPanel() ) |
|
{ |
|
HideMenu(); |
|
} |
|
BaseClass::OnKillFocus(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Called when the menu is closed |
|
//----------------------------------------------------------------------------- |
|
void MenuButton::OnMenuClose() |
|
{ |
|
HideMenu(); |
|
PostActionSignal(new KeyValues("MenuClose")); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Sets the offset from where menu would normally be placed |
|
// Only is used if menu is ALIGN_WITH_PARENT |
|
//----------------------------------------------------------------------------- |
|
void MenuButton::SetOpenOffsetY(int yOffset) |
|
{ |
|
_openOffsetY = yOffset; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool MenuButton::CanBeDefaultButton(void) |
|
{ |
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Handles hotkey accesses |
|
//----------------------------------------------------------------------------- |
|
void MenuButton::DoClick() |
|
{ |
|
if ( IsDropMenuButtonStyle() && |
|
m_pDropMenuImage ) |
|
{ |
|
int mx, my; |
|
// force the menu to appear where the mouse button was pressed |
|
input()->GetCursorPos( mx, my ); |
|
ScreenToLocal( mx, my ); |
|
|
|
int contentW, contentH; |
|
m_pDropMenuImage->GetContentSize( contentW, contentH ); |
|
int drawX = GetWide() - contentW - 2; |
|
if ( mx <= drawX || !OnCheckMenuItemCount() ) |
|
{ |
|
// Treat it like a "regular" button click |
|
BaseClass::DoClick(); |
|
return; |
|
} |
|
} |
|
|
|
if ( !m_pMenu ) |
|
{ |
|
return; |
|
} |
|
|
|
// menu is already visible, hide the menu |
|
if (m_pMenu->IsVisible()) |
|
{ |
|
HideMenu(); |
|
return; |
|
} |
|
|
|
// do nothing if menu is not enabled |
|
if (!m_pMenu->IsEnabled()) |
|
{ |
|
return; |
|
} |
|
// force the menu to compute required width/height |
|
m_pMenu->PerformLayout(); |
|
|
|
// Now position it so it can fit in the workspace |
|
m_pMenu->PositionRelativeToPanel(this, m_iDirection, _openOffsetY ); |
|
|
|
// make sure we're at the top of the draw order (and therefore our children as well) |
|
MoveToFront(); |
|
|
|
// notify |
|
OnShowMenu(m_pMenu); |
|
|
|
// keep the button depressed |
|
BaseClass::ForceDepressed(true); |
|
|
|
// show the menu |
|
m_pMenu->SetVisible(true); |
|
|
|
// bring to focus |
|
m_pMenu->RequestFocus(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void MenuButton::OnKeyCodeTyped(KeyCode code) |
|
{ |
|
bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT)); |
|
bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL)); |
|
bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT)); |
|
|
|
if (!shift && !ctrl && !alt) |
|
{ |
|
switch (code) |
|
{ |
|
case KEY_ENTER: |
|
{ |
|
if ( !IsDropMenuButtonStyle() ) |
|
{ |
|
DoClick(); |
|
} |
|
break; |
|
} |
|
} |
|
} |
|
BaseClass::OnKeyCodeTyped(code); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void MenuButton::OnCursorEntered() |
|
{ |
|
Button::OnCursorEntered(); |
|
// post a message to the parent menu. |
|
// forward the message on to the parent of this menu. |
|
KeyValues *msg = new KeyValues ("CursorEnteredMenuButton"); |
|
// tell the parent this menuitem is the one that was entered so it can open the menu if it wants |
|
msg->SetInt("VPanel", GetVPanel()); |
|
ivgui()->PostMessage(GetVParent(), msg, NULL); |
|
} |
|
|
|
// This style is like the IE "back" button where the left side acts like a regular button, the the right side has a little |
|
// combo box dropdown indicator and presents and submenu |
|
void MenuButton::SetDropMenuButtonStyle( bool state ) |
|
{ |
|
bool changed = m_bDropMenuButtonStyle != state; |
|
m_bDropMenuButtonStyle = state; |
|
if ( !changed ) |
|
return; |
|
|
|
if ( state ) |
|
{ |
|
m_pDropMenuImage = new TextImage( "u" ); |
|
IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); |
|
m_pDropMenuImage->SetFont(pScheme->GetFont("Marlett", IsProportional())); |
|
// m_pDropMenuImage->SetContentAlignment(Label::a_west); |
|
// m_pDropMenuImage->SetTextInset(3, 0); |
|
m_nImageIndex = AddImage( m_pDropMenuImage, 0 ); |
|
} |
|
else |
|
{ |
|
ResetToSimpleTextImage(); |
|
delete m_pDropMenuImage; |
|
m_pDropMenuImage = NULL; |
|
m_nImageIndex = -1; |
|
} |
|
} |
|
|
|
void MenuButton::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
if ( m_pDropMenuImage ) |
|
{ |
|
SetImageAtIndex( 1, m_pDropMenuImage, 0 ); |
|
} |
|
} |
|
|
|
|
|
void MenuButton::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
if ( !IsDropMenuButtonStyle() ) |
|
return; |
|
|
|
Assert( m_nImageIndex >= 0 ); |
|
if ( m_nImageIndex < 0 || !m_pDropMenuImage ) |
|
return; |
|
|
|
int w, h; |
|
GetSize( w, h ); |
|
|
|
int contentW, contentH; |
|
m_pDropMenuImage->ResizeImageToContent(); |
|
m_pDropMenuImage->GetContentSize( contentW, contentH ); |
|
|
|
SetImageBounds( m_nImageIndex, w - contentW - 2, contentW ); |
|
} |
|
|
|
bool MenuButton::IsDropMenuButtonStyle() const |
|
{ |
|
return m_bDropMenuButtonStyle; |
|
} |
|
|
|
void MenuButton::Paint(void) |
|
{ |
|
BaseClass::Paint(); |
|
|
|
if ( !IsDropMenuButtonStyle() ) |
|
return; |
|
|
|
int contentW, contentH; |
|
m_pDropMenuImage->GetContentSize( contentW, contentH ); |
|
m_pDropMenuImage->SetColor( IsEnabled() ? GetButtonFgColor() : GetDisabledFgColor1() ); |
|
|
|
int drawX = GetWide() - contentW - 2; |
|
|
|
surface()->DrawSetColor( IsEnabled() ? GetButtonFgColor() : GetDisabledFgColor1() ); |
|
surface()->DrawFilledRect( drawX, 3, drawX + 1, GetTall() - 3 ); |
|
} |
|
|
|
void MenuButton::OnCursorMoved( int x, int y ) |
|
{ |
|
BaseClass::OnCursorMoved( x, y ); |
|
|
|
if ( !IsDropMenuButtonStyle() ) |
|
return; |
|
|
|
int contentW, contentH; |
|
m_pDropMenuImage->GetContentSize( contentW, contentH ); |
|
int drawX = GetWide() - contentW - 2; |
|
if ( x <= drawX || !OnCheckMenuItemCount() ) |
|
{ |
|
SetButtonActivationType(ACTIVATE_ONPRESSEDANDRELEASED); |
|
SetUseCaptureMouse(true); |
|
} |
|
else |
|
{ |
|
SetButtonActivationType(ACTIVATE_ONPRESSED); |
|
SetUseCaptureMouse(false); |
|
} |
|
} |
|
|
|
Menu *MenuButton::GetMenu() |
|
{ |
|
Assert( m_pMenu ); |
|
return m_pMenu; |
|
} |