//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: Basic button control // // $NoKeywords: $ //=============================================================================// #include #include #include #include #include #include #include #include #include #include #include #include #include // memdbgon must be the last include file in a .cpp file!!! #include using namespace vgui; // DMX serializer fields. BEGIN_DMXELEMENT_UNPACK_NAMESPACE_SIMPLE( vgui, Button ) DMXELEMENT_UNPACK_FIELD( "default foreground color", "255 255 255 255", Color, _defaultFgColor ) END_DMXELEMENT_UNPACK_NAMESPACE( vgui, Button, s_pUnpackParams ) // global list of all the names of all the sounds played by buttons CUtlSymbolTable g_ButtonSoundNames; DECLARE_BUILD_FACTORY_DEFAULT_TEXT( Button, Button ); //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- Button::Button(Panel *parent, const char *panelName, const char *text, Panel *pActionSignalTarget, const char *pCmd ) : Label(parent, panelName, text) { Init(); if ( pActionSignalTarget && pCmd ) { AddActionSignalTarget( pActionSignalTarget ); SetCommand( pCmd ); } } //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- Button::Button(Panel *parent, const char *panelName, const wchar_t *wszText, Panel *pActionSignalTarget, const char *pCmd ) : Label(parent, panelName, wszText) { Init(); if ( pActionSignalTarget && pCmd ) { AddActionSignalTarget( pActionSignalTarget ); SetCommand( pCmd ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::Init() { _buttonFlags.SetFlag( USE_CAPTURE_MOUSE | BUTTON_BORDER_ENABLED ); _mouseClickMask = 0; _actionMessage = NULL; _defaultBorder = NULL; _depressedBorder = NULL; _keyFocusBorder = NULL; m_bSelectionStateSaved = false; m_sArmedSoundName = UTL_INVAL_SYMBOL; m_sDepressedSoundName = UTL_INVAL_SYMBOL; m_sReleasedSoundName = UTL_INVAL_SYMBOL; SetTextInset(6, 0); SetMouseClickEnabled( MOUSE_LEFT, true ); SetButtonActivationType(ACTIVATE_ONPRESSEDANDRELEASED); // labels have this off by default, but we need it on SetPaintBackgroundEnabled( true ); _paint = true; REGISTER_COLOR_AS_OVERRIDABLE( _defaultFgColor, "defaultFgColor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _defaultBgColor, "defaultBgColor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _armedFgColor, "armedFgColor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _armedBgColor, "armedBgColor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _depressedFgColor, "depressedFgColor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _depressedBgColor, "depressedBgColor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _keyboardFocusColor, "keyboardFocusColor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _blinkFgColor, "blinkFgColor_override" ); } //----------------------------------------------------------------------------- // Purpose: Destructor //----------------------------------------------------------------------------- Button::~Button() { if (_actionMessage) { _actionMessage->deleteThis(); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::SetButtonActivationType(ActivationType_t activationType) { _activationType = activationType; } //----------------------------------------------------------------------------- // Purpose: Set button border attribute enabled. //----------------------------------------------------------------------------- void Button::SetButtonBorderEnabled( bool state ) { if ( state != _buttonFlags.IsFlagSet( BUTTON_BORDER_ENABLED ) ) { _buttonFlags.SetFlag( BUTTON_BORDER_ENABLED, state ); InvalidateLayout(false); } } //----------------------------------------------------------------------------- // Purpose: Set button selected state. //----------------------------------------------------------------------------- void Button::SetSelected( bool state ) { if ( _buttonFlags.IsFlagSet( SELECTED ) != state ) { _buttonFlags.SetFlag( SELECTED, state ); RecalculateDepressedState(); InvalidateLayout(false); } } void Button::SetBlink( bool state ) { if ( _buttonFlags.IsFlagSet( BLINK ) != state ) { _buttonFlags.SetFlag( BLINK, state ); RecalculateDepressedState(); InvalidateLayout(false); } } //----------------------------------------------------------------------------- // Purpose: Set button force depressed state. //----------------------------------------------------------------------------- void Button::ForceDepressed(bool state) { if ( _buttonFlags.IsFlagSet( FORCE_DEPRESSED ) != state ) { _buttonFlags.SetFlag( FORCE_DEPRESSED, state ); RecalculateDepressedState(); InvalidateLayout(false); } } //----------------------------------------------------------------------------- // Purpose: Set button depressed state with respect to the force depressed state. //----------------------------------------------------------------------------- void Button::RecalculateDepressedState( void ) { bool newState; if (!IsEnabled()) { newState = false; } else { newState = _buttonFlags.IsFlagSet( FORCE_DEPRESSED ) ? true : (_buttonFlags.IsFlagSet(ARMED) && _buttonFlags.IsFlagSet( SELECTED ) ); } _buttonFlags.SetFlag( DEPRESSED, newState ); } //----------------------------------------------------------------------------- // Purpose: Sets whether or not the button captures all mouse input when depressed // Defaults to true // Should be set to false for things like menu items where there is a higher-level mouse capture //----------------------------------------------------------------------------- void Button::SetUseCaptureMouse( bool state ) { _buttonFlags.SetFlag( USE_CAPTURE_MOUSE, state ); } //----------------------------------------------------------------------------- // Purpose: Check if mouse capture is enabled. // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool Button::IsUseCaptureMouseEnabled( void ) { return _buttonFlags.IsFlagSet( USE_CAPTURE_MOUSE ); } //----------------------------------------------------------------------------- // Purpose: Set armed state. //----------------------------------------------------------------------------- void Button::SetArmed(bool state) { if ( _buttonFlags.IsFlagSet( ARMED ) != state ) { _buttonFlags.SetFlag( ARMED, state ); RecalculateDepressedState(); InvalidateLayout(false); // play any sounds specified if (state && m_sArmedSoundName != UTL_INVAL_SYMBOL) { surface()->PlaySound(g_ButtonSoundNames.String(m_sArmedSoundName)); } } } //----------------------------------------------------------------------------- // Purpose: Check armed state //----------------------------------------------------------------------------- bool Button::IsArmed() { return _buttonFlags.IsFlagSet( ARMED ); } KeyValues *Button::GetActionMessage() { return _actionMessage->MakeCopy(); } void Button::PlayButtonReleasedSound() { // check for playing a transition sound if ( m_sReleasedSoundName != UTL_INVAL_SYMBOL ) { surface()->PlaySound( g_ButtonSoundNames.String( m_sReleasedSoundName ) ); } } //----------------------------------------------------------------------------- // Purpose: Activate a button click. //----------------------------------------------------------------------------- void Button::DoClick() { SetSelected(true); FireActionSignal(); PlayButtonReleasedSound(); SetSelected(false); } //----------------------------------------------------------------------------- // Purpose: Check selected state //----------------------------------------------------------------------------- bool Button::IsSelected() { return _buttonFlags.IsFlagSet( SELECTED ); } //----------------------------------------------------------------------------- // Purpose: Check depressed state //----------------------------------------------------------------------------- bool Button::IsDepressed() { return _buttonFlags.IsFlagSet( DEPRESSED ); } bool Button::IsBlinking( void ) { return _buttonFlags.IsFlagSet( BLINK ); } //----------------------------------------------------------------------------- // Drawing focus box? //----------------------------------------------------------------------------- bool Button::IsDrawingFocusBox() { return _buttonFlags.IsFlagSet( DRAW_FOCUS_BOX ); } void Button::DrawFocusBox( bool bEnable ) { _buttonFlags.SetFlag( DRAW_FOCUS_BOX, bEnable ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::NavigateTo() { BaseClass::NavigateTo(); SetArmed( true ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::NavigateFrom() { BaseClass::NavigateFrom(); SetArmed( false ); } //----------------------------------------------------------------------------- // Purpose: Paint button on screen //----------------------------------------------------------------------------- void Button::Paint(void) { if ( !ShouldPaint() ) return; BaseClass::Paint(); if ( HasFocus() && IsEnabled() && IsDrawingFocusBox() ) { int x0, y0, x1, y1; int wide, tall; GetSize(wide, tall); x0 = 3, y0 = 3, x1 = wide - 4 , y1 = tall - 2; DrawFocusBorder(x0, y0, x1, y1); } } //----------------------------------------------------------------------------- // Purpose: Perform graphical layout of button. //----------------------------------------------------------------------------- void Button::PerformLayout() { // reset our border SetBorder( GetBorder(_buttonFlags.IsFlagSet( DEPRESSED ), _buttonFlags.IsFlagSet( ARMED ), _buttonFlags.IsFlagSet( SELECTED ), HasFocus() ) ); // set our color SetFgColor(GetButtonFgColor()); SetBgColor(GetButtonBgColor()); BaseClass::PerformLayout(); } //----------------------------------------------------------------------------- // Purpose: Get button foreground color // Output : Color //----------------------------------------------------------------------------- Color Button::GetButtonFgColor() { if ( !_buttonFlags.IsFlagSet( BLINK ) ) { if (_buttonFlags.IsFlagSet( DEPRESSED )) return _depressedFgColor; if (_buttonFlags.IsFlagSet( ARMED )) return _armedFgColor; return _defaultFgColor; } Color cBlendedColor; if (_buttonFlags.IsFlagSet( DEPRESSED )) cBlendedColor = _depressedFgColor; else if (_buttonFlags.IsFlagSet( ARMED )) cBlendedColor = _armedFgColor; else cBlendedColor = _defaultFgColor; float fBlink = ( sinf( system()->GetTimeMillis() * 0.01f ) + 1.0f ) * 0.5f; if ( _buttonFlags.IsFlagSet( BLINK ) ) { cBlendedColor[ 0 ] = (float)cBlendedColor[ 0 ] * fBlink + (float)_blinkFgColor[ 0 ] * ( 1.0f - fBlink ); cBlendedColor[ 1 ] = (float)cBlendedColor[ 1 ] * fBlink + (float)_blinkFgColor[ 1 ] * ( 1.0f - fBlink ); cBlendedColor[ 2 ] = (float)cBlendedColor[ 2 ] * fBlink + (float)_blinkFgColor[ 2 ] * ( 1.0f - fBlink ); cBlendedColor[ 3 ] = (float)cBlendedColor[ 3 ] * fBlink + (float)_blinkFgColor[ 3 ] * ( 1.0f - fBlink ); } return cBlendedColor; } //----------------------------------------------------------------------------- // Purpose: Get button background color //----------------------------------------------------------------------------- Color Button::GetButtonBgColor() { if (_buttonFlags.IsFlagSet( DEPRESSED )) return _depressedBgColor; if (_buttonFlags.IsFlagSet( ARMED )) return _armedBgColor; return _defaultBgColor; } //----------------------------------------------------------------------------- // Purpose: Called when key focus is received //----------------------------------------------------------------------------- void Button::OnSetFocus() { InvalidateLayout(false); BaseClass::OnSetFocus(); } //----------------------------------------------------------------------------- // Purpose: Respond when focus is killed //----------------------------------------------------------------------------- void Button::OnKillFocus() { InvalidateLayout(false); BaseClass::OnKillFocus(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::ApplySchemeSettings(IScheme *pScheme) { BaseClass::ApplySchemeSettings(pScheme); // get the borders we need _defaultBorder = pScheme->GetBorder("ButtonBorder"); _depressedBorder = pScheme->GetBorder("ButtonDepressedBorder"); _keyFocusBorder = pScheme->GetBorder("ButtonKeyFocusBorder"); _defaultFgColor = GetSchemeColor("Button.TextColor", Color(255, 255, 255, 255), pScheme); _defaultBgColor = GetSchemeColor("Button.BgColor", Color(0, 0, 0, 255), pScheme); _armedFgColor = GetSchemeColor("Button.ArmedTextColor", _defaultFgColor, pScheme); _armedBgColor = GetSchemeColor("Button.ArmedBgColor", _defaultBgColor, pScheme); _depressedFgColor = GetSchemeColor("Button.DepressedTextColor", _defaultFgColor, pScheme); _depressedBgColor = GetSchemeColor("Button.DepressedBgColor", _defaultBgColor, pScheme); _keyboardFocusColor = GetSchemeColor("Button.FocusBorderColor", Color(0,0,0,255), pScheme); _blinkFgColor = GetSchemeColor("Button.BlinkColor", Color(255, 155, 0, 255), pScheme); InvalidateLayout(); } //----------------------------------------------------------------------------- // Purpose: Set default button colors. //----------------------------------------------------------------------------- void Button::SetDefaultColor(Color fgColor, Color bgColor) { if (!(_defaultFgColor == fgColor && _defaultBgColor == bgColor)) { _defaultFgColor = fgColor; _defaultBgColor = bgColor; InvalidateLayout(false); } } //----------------------------------------------------------------------------- // Purpose: Set armed button colors //----------------------------------------------------------------------------- void Button::SetArmedColor(Color fgColor, Color bgColor) { if (!(_armedFgColor == fgColor && _armedBgColor == bgColor)) { _armedFgColor = fgColor; _armedBgColor = bgColor; InvalidateLayout(false); } } //----------------------------------------------------------------------------- // Purpose: Set depressed button colors //----------------------------------------------------------------------------- void Button::SetDepressedColor(Color fgColor, Color bgColor) { if (!(_depressedFgColor == fgColor && _depressedBgColor == bgColor)) { _depressedFgColor = fgColor; _depressedBgColor = bgColor; InvalidateLayout(false); } } //----------------------------------------------------------------------------- // Purpose: Set blink button color //----------------------------------------------------------------------------- void Button::SetBlinkColor(Color fgColor) { if (!(_blinkFgColor == fgColor)) { _blinkFgColor = fgColor; InvalidateLayout(false); } } //----------------------------------------------------------------------------- // Purpose: Set default button border attributes. //----------------------------------------------------------------------------- void Button::SetDefaultBorder(IBorder *border) { _defaultBorder = border; InvalidateLayout(false); } //----------------------------------------------------------------------------- // Purpose: Set depressed button border attributes. //----------------------------------------------------------------------------- void Button::SetDepressedBorder(IBorder *border) { _depressedBorder = border; InvalidateLayout(false); } //----------------------------------------------------------------------------- // Purpose: Set key focus button border attributes. //----------------------------------------------------------------------------- void Button::SetKeyFocusBorder(IBorder *border) { _keyFocusBorder = border; InvalidateLayout(false); } //----------------------------------------------------------------------------- // Purpose: Get button border attributes. //----------------------------------------------------------------------------- IBorder *Button::GetBorder(bool depressed, bool armed, bool selected, bool keyfocus) { if ( _buttonFlags.IsFlagSet( BUTTON_BORDER_ENABLED ) ) { // raised buttons with no armed state if (depressed) return _depressedBorder; if (keyfocus) return _keyFocusBorder; if (IsEnabled() && _buttonFlags.IsFlagSet( DEFAULT_BUTTON )) return _keyFocusBorder; return _defaultBorder; } else { // flat buttons that raise if (depressed) return _depressedBorder; if (armed) return _defaultBorder; } return _defaultBorder; } //----------------------------------------------------------------------------- // Purpose: sets this button to be the button that is accessed by default // when the user hits ENTER or SPACE //----------------------------------------------------------------------------- void Button::SetAsCurrentDefaultButton(int state) { bool bState = state ? true : false; if ( _buttonFlags.IsFlagSet( DEFAULT_BUTTON ) != bState ) { _buttonFlags.SetFlag( DEFAULT_BUTTON, bState ); if ( bState ) { // post a message up notifying our nav group that we're now the default button if (GetVParent()) { KeyValues *msg = new KeyValues("CurrentDefaultButtonSet"); msg->SetInt("button", ToHandle() ); ivgui()->PostMessage(GetVParent(), msg, GetVPanel()); } } InvalidateLayout(); Repaint(); } } //----------------------------------------------------------------------------- // Purpose: sets this button to be the button that is accessed by default // when the user hits ENTER or SPACE //----------------------------------------------------------------------------- void Button::SetAsDefaultButton(int state) { bool bState = state ? true : false; if ( _buttonFlags.IsFlagSet( DEFAULT_BUTTON ) != bState ) { _buttonFlags.SetFlag( DEFAULT_BUTTON, bState ); if ( bState ) { // post a message up notifying our nav group that we're now the default button if (GetVParent()) { KeyValues *msg = new KeyValues("DefaultButtonSet"); msg->SetInt("button", ToHandle() ); ivgui()->PostMessage(GetVParent(), msg, GetVPanel()); } } InvalidateLayout(); Repaint(); } } //----------------------------------------------------------------------------- // Purpose: sets rollover sound //----------------------------------------------------------------------------- void Button::SetArmedSound(const char *sound) { if (sound) { m_sArmedSoundName = g_ButtonSoundNames.AddString(sound); } else { m_sArmedSoundName = UTL_INVAL_SYMBOL; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::SetDepressedSound(const char *sound) { if (sound) { m_sDepressedSoundName = g_ButtonSoundNames.AddString(sound); } else { m_sDepressedSoundName = UTL_INVAL_SYMBOL; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::SetReleasedSound(const char *sound) { if (sound) { m_sReleasedSoundName = g_ButtonSoundNames.AddString(sound); } else { m_sReleasedSoundName = UTL_INVAL_SYMBOL; } } inline int Button::MouseCodeToMask( MouseCode code ) { // MouseCodes do not start at zero. Make them start at zero before trying to fit them into a 32 bit mask.. // Otherwise, you would be trying to set bit 107 of an integer, and that would be bad. const int recode = code - MOUSE_FIRST; AssertMsg1( recode >= 0 && recode < 32, "MouseCode %d is invalid and cannot fit into a 32-bit mask\n", code ); return 1 << recode ; } //----------------------------------------------------------------------------- // Purpose: Set button to be mouse clickable or not. //----------------------------------------------------------------------------- void Button::SetMouseClickEnabled(MouseCode code,bool state) { if (state) { _mouseClickMask |= MouseCodeToMask(code); //set bit to 1 } else { _mouseClickMask &= ~MouseCodeToMask(code); //set bit to 0 } } //----------------------------------------------------------------------------- // Purpose: Check if button is mouse clickable //----------------------------------------------------------------------------- bool Button::IsMouseClickEnabled(MouseCode code) { if ( _mouseClickMask & MouseCodeToMask(code) ) { return true; } return false; } //----------------------------------------------------------------------------- // Purpose: sets the command to send when the button is pressed //----------------------------------------------------------------------------- void Button::SetCommand( const char *command ) { SetCommand(new KeyValues("Command", "command", command)); } //----------------------------------------------------------------------------- // Purpose: sets the message to send when the button is pressed //----------------------------------------------------------------------------- void Button::SetCommand( KeyValues *message ) { // delete the old message if (_actionMessage) { _actionMessage->deleteThis(); } _actionMessage = message; } //----------------------------------------------------------------------------- // Purpose: Peeks at the message to send when button is pressed // Input : - // Output : KeyValues //----------------------------------------------------------------------------- KeyValues *Button::GetCommand() { return _actionMessage; } //----------------------------------------------------------------------------- // Purpose: Message targets that the button has been pressed //----------------------------------------------------------------------------- void Button::FireActionSignal() { // message-based action signal if (_actionMessage) { // see if it's a url if ( !stricmp(_actionMessage->GetName(), "command") ) { char const *szCommand = _actionMessage->GetString("command", ""); if ( !strnicmp( szCommand, "url ", strlen("url ")) && strstr(szCommand, "://") ) { // it's a command to launch a url, run it system()->ShellExecute("open", _actionMessage->GetString("command", " ") + 4); } if ( szCommand[0] == '#' && szCommand[1] == '#' ) { szCommand += 2; if ( char const *szEnd = Q_strstr( szCommand, "##" ) ) { KeyValues *pFixedCmd = _actionMessage->MakeCopy(); char *chBuffer = ( char * ) stackalloc( szEnd - szCommand + 1 ); Q_snprintf( chBuffer, szEnd - szCommand + 1, "%.*s", szEnd - szCommand, szCommand ); pFixedCmd->SetString( "command", chBuffer ); PostActionSignal( pFixedCmd ); return; } } } PostActionSignal(_actionMessage->MakeCopy()); } } //----------------------------------------------------------------------------- // Purpose: gets info about the button //----------------------------------------------------------------------------- bool Button::RequestInfo(KeyValues *outputData) { if (!stricmp(outputData->GetName(), "CanBeDefaultButton")) { outputData->SetInt("result", CanBeDefaultButton() ? 1 : 0); return true; } else if (!stricmp(outputData->GetName(), "GetState")) { outputData->SetInt("state", IsSelected()); return true; } else if ( !stricmp( outputData->GetName(), "GetCommand" )) { if ( _actionMessage ) { outputData->SetString( "command", _actionMessage->GetString( "command", "" ) ); } else { outputData->SetString( "command", "" ); } return true; } return BaseClass::RequestInfo(outputData); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool Button::CanBeDefaultButton(void) { return true; } //----------------------------------------------------------------------------- // Purpose: Get control settings for editing //----------------------------------------------------------------------------- void Button::GetSettings( KeyValues *outResourceData ) { BaseClass::GetSettings(outResourceData); if (_actionMessage) { outResourceData->SetString("command", _actionMessage->GetString("command", "")); } outResourceData->SetInt("default", _buttonFlags.IsFlagSet( DEFAULT_BUTTON ) ); if ( m_bSelectionStateSaved ) { outResourceData->SetInt( "selected", IsSelected() ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::ApplySettings( KeyValues *inResourceData ) { BaseClass::ApplySettings(inResourceData); const char *cmd = inResourceData->GetString("command", ""); if (*cmd) { // add in the command SetCommand(cmd); } // set default button state int defaultButton = inResourceData->GetInt("default"); if (defaultButton && CanBeDefaultButton()) { SetAsDefaultButton(true); } // saved selection state int iSelected = inResourceData->GetInt( "selected", -1 ); if ( iSelected != -1 ) { SetSelected( iSelected != 0 ); m_bSelectionStateSaved = true; } const char *sound = inResourceData->GetString("sound_armed", ""); if (*sound) { SetArmedSound(sound); } sound = inResourceData->GetString("sound_depressed", ""); if (*sound) { SetDepressedSound(sound); } sound = inResourceData->GetString("sound_released", ""); if (*sound) { SetReleasedSound(sound); } } //----------------------------------------------------------------------------- // Purpose: Describes editing details //----------------------------------------------------------------------------- const char *Button::GetDescription( void ) { static char buf[1024]; Q_snprintf(buf, sizeof(buf), "%s, string command, int default", BaseClass::GetDescription()); return buf; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::OnSetState(int state) { SetSelected(state ? true : false ); Repaint(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::OnCursorEntered() { if (IsEnabled()) { NavigateTo(); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::OnCursorExited() { if ( !_buttonFlags.IsFlagSet( BUTTON_KEY_DOWN ) ) { NavigateFrom(); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::OnMousePressed(MouseCode code) { if (!IsEnabled()) return; if (!IsMouseClickEnabled(code)) return; if (_activationType == ACTIVATE_ONPRESSED) { if ( IsKeyBoardInputEnabled() ) { RequestFocus(); } DoClick(); return; } // play activation sound if (m_sDepressedSoundName != UTL_INVAL_SYMBOL) { surface()->PlaySound(g_ButtonSoundNames.String(m_sDepressedSoundName)); } if (IsUseCaptureMouseEnabled() && _activationType == ACTIVATE_ONPRESSEDANDRELEASED) { { if ( IsKeyBoardInputEnabled() ) { RequestFocus(); } SetSelected(true); Repaint(); } // lock mouse input to going to this button input()->SetMouseCapture(GetVPanel()); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::OnMouseDoublePressed(MouseCode code) { OnMousePressed(code); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::OnMouseReleased(MouseCode code) { // ensure mouse capture gets released if (IsUseCaptureMouseEnabled()) { input()->SetMouseCapture(NULL); } if (_activationType == ACTIVATE_ONPRESSED) return; if (!IsMouseClickEnabled(code)) return; if (!IsSelected() && _activationType == ACTIVATE_ONPRESSEDANDRELEASED) return; // it has to be both enabled and (mouse over the button or using a key) to fire if ( IsEnabled() && ( GetVPanel() == input()->GetMouseOver() || _buttonFlags.IsFlagSet( BUTTON_KEY_DOWN ) ) ) { DoClick(); } else { SetSelected(false); } // make sure the button gets unselected Repaint(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::OnKeyCodePressed(KeyCode code) { KeyCode localCode = GetBaseButtonCode( code ); if( ( localCode == KEY_XBUTTON_A ) && IsEnabled() ) { SetArmed( true ); _buttonFlags.SetFlag( BUTTON_KEY_DOWN ); if( _activationType != ACTIVATE_ONRELEASED ) { DoClick(); } } else if (code == KEY_SPACE || code == KEY_ENTER) { SetArmed(true); _buttonFlags.SetFlag( BUTTON_KEY_DOWN ); OnMousePressed(MOUSE_LEFT); if (IsUseCaptureMouseEnabled()) // undo the mouse capture since its a fake mouse click! { input()->SetMouseCapture(NULL); } } else { _buttonFlags.ClearFlag( BUTTON_KEY_DOWN ); BaseClass::OnKeyCodePressed( code ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void Button::OnKeyCodeReleased( KeyCode keycode ) { vgui::KeyCode code = GetBaseButtonCode( keycode ); if ( _buttonFlags.IsFlagSet( BUTTON_KEY_DOWN ) && ( code == KEY_XBUTTON_A || code == KEY_XBUTTON_START ) ) { SetArmed( true ); if( _activationType != ACTIVATE_ONPRESSED ) { DoClick(); } } else if (_buttonFlags.IsFlagSet( BUTTON_KEY_DOWN ) && (code == KEY_SPACE || code == KEY_ENTER)) { SetArmed(true); OnMouseReleased(MOUSE_LEFT); } else { BaseClass::OnKeyCodeReleased( keycode ); } _buttonFlags.ClearFlag( BUTTON_KEY_DOWN ); if ( !IsGameConsole() ) { SetArmed(false); } } //----------------------------------------------------------------------------- // Purpose: Override this to draw different focus border //----------------------------------------------------------------------------- void Button::DrawFocusBorder(int tx0, int ty0, int tx1, int ty1) { surface()->DrawSetColor(_keyboardFocusColor); DrawDashedLine(tx0, ty0, tx1, ty0+1, 1, 1); // top DrawDashedLine(tx0, ty0, tx0+1, ty1, 1, 1); // left DrawDashedLine(tx0, ty1-1, tx1, ty1, 1, 1); // bottom DrawDashedLine(tx1-1, ty0, tx1, ty1, 1, 1); // right } //----------------------------------------------------------------------------- // Purpose: Size the object to its button and text. - only works from in ApplySchemeSettings or PerformLayout() //----------------------------------------------------------------------------- void Button::SizeToContents() { int wide, tall; GetContentSize(wide, tall); SetSize(wide + Label::Content, tall + Label::Content); } void Button::GetSizerMinimumSize(int &wide, int &tall) { GetContentSize(wide, tall); wide += Label::Content; tall += Label::Content; }