//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #define PROTECTED_THINGS_DISABLE #include #include #include #include #include #include #include #include #include // memdbgon must be the last include file in a .cpp file!!! #include 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; 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() <= 1 ) ) { // 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 ); int nItemCount = OnCheckMenuItemCount(); Color clr = GetButtonFgColor(); if ( !IsEnabled() || nItemCount <= 1 ) { clr = GetDisabledFgColor1(); } m_pDropMenuImage->SetColor( clr ); int drawX = GetWide() - contentW - 2; surface()->DrawSetColor( clr ); 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() <= 1 ) ) { SetButtonActivationType(ACTIVATE_ONPRESSEDANDRELEASED); SetUseCaptureMouse(true); } else { SetButtonActivationType(ACTIVATE_ONPRESSED); SetUseCaptureMouse(false); } } Menu *MenuButton::GetMenu() { Assert( m_pMenu ); return m_pMenu; }