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
5 years ago
|
//========= 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;
|
||
|
}
|