Separate focus from hover state in BITMAP_BUTTON, trigger after mouse down+up

Fixes https://gitlab.com/kicad/code/kicad/-/issues/8556
Adds AcceptDragInAsClick() to maintain support for use in toolbar palettes
This commit is contained in:
david-beinder 2021-06-07 20:17:00 +02:00 committed by Jon Evans
parent db276909ba
commit da833ad7dd
4 changed files with 53 additions and 13 deletions

View File

@ -130,6 +130,7 @@ void ACTION_TOOLBAR_PALETTE::AddAction( const TOOL_ACTION& aAction )
button->SetDisabledBitmap( disabledBmp ); button->SetDisabledBitmap( disabledBmp );
button->SetPadding( padding ); button->SetPadding( padding );
button->SetToolTip( aAction.GetDescription() ); button->SetToolTip( aAction.GetDescription() );
button->AcceptDragInAsClick();
m_buttons[aAction.GetUIId()] = button; m_buttons[aAction.GetUIId()] = button;

View File

@ -34,7 +34,8 @@ BITMAP_BUTTON::BITMAP_BUTTON( wxWindow* aParent, wxWindowID aId, const wxPoint&
const wxSize& aSize, int aStyles ) : const wxSize& aSize, int aStyles ) :
wxPanel( aParent, aId, aPos, aSize, aStyles ), wxPanel( aParent, aId, aPos, aSize, aStyles ),
m_buttonState( 0 ), m_buttonState( 0 ),
m_padding( 0 ) m_padding( 0 ),
m_acceptDraggedInClicks( false )
{ {
if( aSize == wxDefaultSize ) if( aSize == wxDefaultSize )
SetMinSize( wxButton::GetDefaultSize() ); SetMinSize( wxButton::GetDefaultSize() );
@ -42,10 +43,10 @@ BITMAP_BUTTON::BITMAP_BUTTON( wxWindow* aParent, wxWindowID aId, const wxPoint&
Bind( wxEVT_PAINT, &BITMAP_BUTTON::OnPaint, this ); Bind( wxEVT_PAINT, &BITMAP_BUTTON::OnPaint, this );
Bind( wxEVT_LEFT_UP, &BITMAP_BUTTON::OnLeftButtonUp, this ); Bind( wxEVT_LEFT_UP, &BITMAP_BUTTON::OnLeftButtonUp, this );
Bind( wxEVT_LEFT_DOWN, &BITMAP_BUTTON::OnLeftButtonDown, this ); Bind( wxEVT_LEFT_DOWN, &BITMAP_BUTTON::OnLeftButtonDown, this );
Bind( wxEVT_LEAVE_WINDOW, &BITMAP_BUTTON::OnLeave, this ); Bind( wxEVT_LEAVE_WINDOW, &BITMAP_BUTTON::OnMouseLeave, this );
Bind( wxEVT_ENTER_WINDOW, &BITMAP_BUTTON::OnEnter, this ); Bind( wxEVT_ENTER_WINDOW, &BITMAP_BUTTON::OnMouseEnter, this );
Bind( wxEVT_KILL_FOCUS, &BITMAP_BUTTON::OnLeave, this ); Bind( wxEVT_KILL_FOCUS, &BITMAP_BUTTON::OnKillFocus, this );
Bind( wxEVT_SET_FOCUS, &BITMAP_BUTTON::OnEnter, this ); Bind( wxEVT_SET_FOCUS, &BITMAP_BUTTON::OnSetFocus, this );
} }
@ -76,20 +77,40 @@ void BITMAP_BUTTON::SetDisabledBitmap( const wxBitmap& aBmp )
} }
void BITMAP_BUTTON::OnLeave( wxEvent& aEvent ) void BITMAP_BUTTON::AcceptDragInAsClick( bool aAcceptDragIn )
{ {
clearFlag( wxCONTROL_CURRENT ); m_acceptDraggedInClicks = aAcceptDragIn;
Refresh(); }
void BITMAP_BUTTON::OnMouseLeave( wxEvent& aEvent )
{
clearFlag( wxCONTROL_CURRENT | wxCONTROL_PRESSED );
Refresh();
aEvent.Skip(); aEvent.Skip();
} }
void BITMAP_BUTTON::OnEnter( wxEvent& aEvent ) void BITMAP_BUTTON::OnMouseEnter( wxEvent& aEvent )
{ {
setFlag( wxCONTROL_CURRENT ); setFlag( wxCONTROL_CURRENT );
Refresh(); Refresh();
aEvent.Skip();
}
void BITMAP_BUTTON::OnKillFocus( wxEvent& aEvent )
{
clearFlag( wxCONTROL_FOCUSED );
Refresh();
aEvent.Skip();
}
void BITMAP_BUTTON::OnSetFocus( wxEvent& aEvent )
{
setFlag( wxCONTROL_FOCUSED );
Refresh();
aEvent.Skip(); aEvent.Skip();
} }
@ -97,7 +118,9 @@ void BITMAP_BUTTON::OnEnter( wxEvent& aEvent )
void BITMAP_BUTTON::OnLeftButtonUp( wxMouseEvent& aEvent ) void BITMAP_BUTTON::OnLeftButtonUp( wxMouseEvent& aEvent )
{ {
// Only create a button event when the control is enabled // Only create a button event when the control is enabled
if( !hasFlag( wxCONTROL_DISABLED ) ) // and only accept clicks that came without prior mouse-down if configured
if( !hasFlag( wxCONTROL_DISABLED ) &&
( m_acceptDraggedInClicks || hasFlag( wxCONTROL_PRESSED | wxCONTROL_FOCUSED ) ) )
{ {
wxEvtHandler* pEventHandler = GetEventHandler(); wxEvtHandler* pEventHandler = GetEventHandler();
wxASSERT( pEventHandler ); wxASSERT( pEventHandler );
@ -145,7 +168,7 @@ void BITMAP_BUTTON::OnPaint( wxPaintEvent& aEvent )
dc.SetBrush( wxBrush( highlightColor.ChangeLightness( darkMode ? 20 : 150 ) ) ); dc.SetBrush( wxBrush( highlightColor.ChangeLightness( darkMode ? 20 : 150 ) ) );
dc.DrawRectangle( rect ); dc.DrawRectangle( rect );
} }
else if( hasFlag( wxCONTROL_CURRENT ) ) else if( hasFlag( wxCONTROL_CURRENT | wxCONTROL_FOCUSED ) )
{ {
dc.SetPen( wxPen( highlightColor ) ); dc.SetPen( wxPen( highlightColor ) );
dc.SetBrush( wxBrush( highlightColor.ChangeLightness( darkMode ? 40 : 170 ) ) ); dc.SetBrush( wxBrush( highlightColor.ChangeLightness( darkMode ? 40 : 170 ) ) );

View File

@ -80,9 +80,18 @@ public:
*/ */
void Check( bool aCheck = true ); void Check( bool aCheck = true );
/**
* Accept mouse-up as click even if mouse-down happened outside of the control
*
* @param aAcceptDragIn is true to allow drag in, false to ignore lone mouse-up events
*/
void AcceptDragInAsClick( bool aAcceptDragIn = true );
protected: protected:
void OnLeave( wxEvent& aEvent ); void OnMouseLeave( wxEvent& aEvent );
void OnEnter( wxEvent& aEvent ); void OnMouseEnter( wxEvent& aEvent );
void OnKillFocus( wxEvent& aEvent );
void OnSetFocus( wxEvent& aEvent );
void OnLeftButtonUp( wxMouseEvent& aEvent ); void OnLeftButtonUp( wxMouseEvent& aEvent );
void OnLeftButtonDown( wxMouseEvent& aEvent ); void OnLeftButtonDown( wxMouseEvent& aEvent );
void OnPaint( wxPaintEvent& aEvent ); void OnPaint( wxPaintEvent& aEvent );
@ -117,6 +126,9 @@ private:
///< Size without the padding ///< Size without the padding
wxSize m_unadjustedMinSize; wxSize m_unadjustedMinSize;
///< Accept mouse-up as click even if mouse-down happened outside of the control
bool m_acceptDraggedInClicks;
}; };
#endif /*BITMAP_BUTTON_H_*/ #endif /*BITMAP_BUTTON_H_*/

View File

@ -63,6 +63,10 @@ void PANEL_KICAD_LAUNCHER::CreateLaunchers()
auto handler = auto handler =
[&]( wxEvent& aEvent ) [&]( wxEvent& aEvent )
{ {
// Defocus the button because leaving the large buttons
// focused after a click looks out of place in the launcher
GetParent()->SetFocus();
OPT_TOOL_EVENT evt = aAction.MakeEvent(); OPT_TOOL_EVENT evt = aAction.MakeEvent();
evt->SetHasPosition( false ); evt->SetHasPosition( false );
m_toolManager->ProcessEvent( *evt ); m_toolManager->ProcessEvent( *evt );