2022-12-13 20:47:28 +00:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KICAD, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2016 Anil8735(https://stackoverflow.com/users/3659387/anil8753)
|
|
|
|
* from https://stackoverflow.com/a/37274011
|
2023-06-03 20:41:56 +00:00
|
|
|
* Copyright (C) 2020-2023 Kicad Developers, see AUTHORS.txt for contributors.
|
2022-12-13 20:47:28 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <widgets/std_bitmap_button.h>
|
|
|
|
#include <wx/button.h>
|
|
|
|
#include <wx/dcclient.h>
|
|
|
|
#include <wx/menu.h>
|
|
|
|
#include <wx/renderer.h>
|
|
|
|
#include <wx/settings.h>
|
2024-02-04 20:25:03 +00:00
|
|
|
#include <wx/textctrl.h>
|
2023-01-17 04:14:38 +00:00
|
|
|
#include <wx/version.h>
|
2022-12-13 20:47:28 +00:00
|
|
|
#include <kiplatform/ui.h>
|
|
|
|
|
|
|
|
|
|
|
|
STD_BITMAP_BUTTON::STD_BITMAP_BUTTON( wxWindow* aParent, wxWindowID aId,
|
|
|
|
const wxBitmap& aDummyBitmap, const wxPoint& aPos,
|
|
|
|
const wxSize& aSize, int aStyle ) :
|
2023-01-17 04:14:38 +00:00
|
|
|
wxPanel( aParent, aId, aPos, aSize, aStyle, wxS( "StdBitmapButton" ) )
|
2022-12-13 20:47:28 +00:00
|
|
|
{
|
|
|
|
if( aSize == wxDefaultSize )
|
|
|
|
{
|
2024-02-04 20:25:03 +00:00
|
|
|
#ifndef __WXMSW__
|
2023-08-22 18:32:25 +00:00
|
|
|
wxSize defaultSize = wxButton::GetDefaultSize( aParent );
|
2024-02-04 20:25:03 +00:00
|
|
|
defaultSize.IncBy( 1 );
|
|
|
|
#else
|
|
|
|
// wxButton::GetDefaultSize does not work on Windows, it's based on some archiac
|
|
|
|
// ascii text size logic that does not hold true in modern Windows at hi dpi scaling
|
|
|
|
// instead spawn a button, grab it's size and then toss it :D
|
|
|
|
wxButton* dummyButton = new wxButton( this, wxID_ANY );
|
|
|
|
dummyButton->SetLabelText( "Z" );
|
|
|
|
|
|
|
|
wxSize defaultSize = dummyButton->GetSize();
|
|
|
|
dummyButton->Hide();
|
|
|
|
delete dummyButton;
|
|
|
|
#endif
|
|
|
|
SetMinSize( defaultSize );
|
2022-12-13 20:47:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Bind( wxEVT_PAINT, &STD_BITMAP_BUTTON::OnPaint, this );
|
|
|
|
Bind( wxEVT_LEFT_UP, &STD_BITMAP_BUTTON::OnLeftButtonUp, this );
|
|
|
|
Bind( wxEVT_LEFT_DOWN, &STD_BITMAP_BUTTON::OnLeftButtonDown, this );
|
|
|
|
Bind( wxEVT_KILL_FOCUS, &STD_BITMAP_BUTTON::OnKillFocus, this );
|
|
|
|
Bind( wxEVT_LEAVE_WINDOW, &STD_BITMAP_BUTTON::OnMouseLeave, this );
|
|
|
|
Bind( wxEVT_ENTER_WINDOW, &STD_BITMAP_BUTTON::OnMouseEnter, this );
|
|
|
|
|
2023-01-17 04:14:38 +00:00
|
|
|
Bind( wxEVT_SYS_COLOUR_CHANGED,
|
2022-12-13 20:47:28 +00:00
|
|
|
wxSysColourChangedEventHandler( STD_BITMAP_BUTTON::onThemeChanged ),
|
|
|
|
this );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
STD_BITMAP_BUTTON::~STD_BITMAP_BUTTON()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void STD_BITMAP_BUTTON::onThemeChanged( wxSysColourChangedEvent &aEvent )
|
|
|
|
{
|
|
|
|
Refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-06-03 15:32:36 +00:00
|
|
|
void STD_BITMAP_BUTTON::SetBitmap( const wxBitmapBundle& aBmp )
|
2022-12-13 20:47:28 +00:00
|
|
|
{
|
|
|
|
m_bitmap = aBmp;
|
2023-06-03 20:41:56 +00:00
|
|
|
|
2023-06-09 12:58:52 +00:00
|
|
|
#ifndef __WXMSW__
|
2023-06-03 20:41:56 +00:00
|
|
|
wxSize size = m_bitmap.GetDefaultSize();
|
2024-02-04 20:25:03 +00:00
|
|
|
|
|
|
|
SetMinSize( wxSize( size.GetWidth() + 8, size.GetHeight() + 8 ) );
|
2023-06-03 20:41:56 +00:00
|
|
|
#else
|
|
|
|
wxSize size = m_bitmap.GetPreferredBitmapSizeFor( this );
|
2024-02-04 20:25:03 +00:00
|
|
|
size.IncBy( 8 ); // padding
|
2022-12-13 20:47:28 +00:00
|
|
|
|
2024-02-04 20:25:03 +00:00
|
|
|
// Now adjust the min size but don't reduce it
|
|
|
|
wxSize minSize = GetMinSize();
|
|
|
|
|
|
|
|
// only change the width
|
|
|
|
// we want to keep the height at the original determined button height
|
|
|
|
// or else forms will get funny
|
|
|
|
// additionally we prefer to make the button square
|
|
|
|
if( size.GetWidth() > minSize.GetHeight() )
|
|
|
|
minSize.SetWidth( size.GetWidth() );
|
|
|
|
else
|
|
|
|
minSize.SetWidth( minSize.GetHeight() );
|
|
|
|
|
|
|
|
SetMinSize( minSize );
|
|
|
|
#endif
|
2022-12-13 20:47:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void STD_BITMAP_BUTTON::OnKillFocus( wxFocusEvent& aEvent )
|
|
|
|
{
|
2022-12-27 23:55:09 +00:00
|
|
|
if( m_stateButton != 0 )
|
|
|
|
{
|
|
|
|
m_stateButton = 0;
|
|
|
|
Refresh();
|
|
|
|
}
|
2022-12-13 20:47:28 +00:00
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void STD_BITMAP_BUTTON::OnMouseLeave( wxMouseEvent& aEvent )
|
|
|
|
{
|
2022-12-27 23:55:09 +00:00
|
|
|
if( m_stateButton != 0 )
|
|
|
|
{
|
|
|
|
m_stateButton = 0;
|
|
|
|
Refresh();
|
|
|
|
}
|
2022-12-13 20:47:28 +00:00
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void STD_BITMAP_BUTTON::OnMouseEnter( wxMouseEvent& aEvent )
|
|
|
|
{
|
2022-12-27 23:55:09 +00:00
|
|
|
if( m_stateButton != wxCONTROL_CURRENT )
|
|
|
|
{
|
|
|
|
m_stateButton = wxCONTROL_CURRENT;
|
|
|
|
Refresh();
|
|
|
|
}
|
2022-12-13 20:47:28 +00:00
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void STD_BITMAP_BUTTON::OnLeftButtonUp( wxMouseEvent& aEvent )
|
|
|
|
{
|
|
|
|
m_stateButton = 0;
|
|
|
|
|
|
|
|
Refresh();
|
|
|
|
|
|
|
|
wxEvtHandler* pEventHandler = GetEventHandler();
|
|
|
|
wxASSERT( pEventHandler );
|
|
|
|
|
|
|
|
pEventHandler->CallAfter(
|
2024-04-16 11:11:50 +00:00
|
|
|
[this]()
|
2022-12-13 20:47:28 +00:00
|
|
|
{
|
|
|
|
wxCommandEvent evt( wxEVT_BUTTON, GetId() );
|
|
|
|
evt.SetEventObject( this );
|
|
|
|
GetEventHandler()->ProcessEvent( evt );
|
|
|
|
} );
|
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void STD_BITMAP_BUTTON::OnLeftButtonDown( wxMouseEvent& aEvent )
|
|
|
|
{
|
|
|
|
m_stateButton = wxCONTROL_PRESSED;
|
|
|
|
Refresh();
|
|
|
|
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void STD_BITMAP_BUTTON::OnPaint( wxPaintEvent& WXUNUSED( aEvent ) )
|
|
|
|
{
|
|
|
|
wxPaintDC dc( this );
|
|
|
|
wxSize size = GetSize();
|
|
|
|
|
|
|
|
#ifdef __WXMAC__
|
|
|
|
auto drawBackground =
|
|
|
|
[&]( wxRect aRect )
|
|
|
|
{
|
|
|
|
// wxWidgets doesn't have much support for dark mode on OSX; none of the
|
|
|
|
// system colours return the right values, nor does wxRendererNative draw
|
|
|
|
// the borders correctly. So we add some empirically chosen hacks here.
|
|
|
|
|
2022-12-14 12:57:40 +00:00
|
|
|
// NOTE: KEEP THESE HACKS IN SYNC WITH SPLIT_BUTTON
|
|
|
|
|
2022-12-13 20:47:28 +00:00
|
|
|
wxColor fg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT );
|
|
|
|
wxColor bg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
|
|
|
|
|
|
|
|
aRect.width += 1;
|
|
|
|
aRect.height += 1;
|
|
|
|
|
|
|
|
if( KIPLATFORM::UI::IsDarkTheme() )
|
|
|
|
{
|
|
|
|
bg = bg.ChangeLightness( m_bIsEnable ? 130 : 120 );
|
|
|
|
dc.SetBrush( bg );
|
|
|
|
dc.SetPen( bg );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bg = bg.ChangeLightness( m_bIsEnable ? 200 : 160 );
|
|
|
|
dc.SetBrush( bg );
|
|
|
|
fg = fg.ChangeLightness( 180 );
|
|
|
|
dc.SetPen( fg );
|
|
|
|
}
|
|
|
|
|
2022-12-26 23:09:43 +00:00
|
|
|
dc.DrawRoundedRectangle( aRect, aRect.height / 4.0 );
|
2022-12-13 20:47:28 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
wxRect r1;
|
|
|
|
r1.x = 0;
|
|
|
|
r1.y = 0;
|
|
|
|
r1.width = size.GetWidth();
|
|
|
|
r1.height = size.GetHeight();
|
|
|
|
|
|
|
|
#ifdef __WXMAC__
|
|
|
|
// wxRendereNative doesn't handle dark mode on OSX.
|
|
|
|
drawBackground( r1 );
|
|
|
|
#else
|
2022-12-26 23:09:43 +00:00
|
|
|
#ifdef __WXMSW__
|
|
|
|
r1.width += 1;
|
|
|
|
#endif
|
|
|
|
|
2022-12-13 20:47:28 +00:00
|
|
|
wxRendererNative::Get().DrawPushButton( this, dc, r1, m_stateButton );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if( m_bitmap.IsOk() )
|
|
|
|
{
|
2023-06-15 03:14:07 +00:00
|
|
|
#ifndef __WXMSW__
|
2023-06-03 20:41:56 +00:00
|
|
|
wxSize bmpSize = m_bitmap.GetDefaultSize();
|
|
|
|
#else
|
2023-06-03 15:32:36 +00:00
|
|
|
wxSize bmpSize = m_bitmap.GetPreferredBitmapSizeFor( this );
|
2023-06-03 20:41:56 +00:00
|
|
|
#endif
|
2023-06-03 15:32:36 +00:00
|
|
|
|
|
|
|
r1.x = ( size.GetWidth() - bmpSize.GetWidth() ) / 2;
|
2022-12-13 20:47:28 +00:00
|
|
|
|
|
|
|
if( r1.x < 0 )
|
|
|
|
r1.x = 0;
|
|
|
|
|
2023-06-03 15:32:36 +00:00
|
|
|
r1.y += ( size.GetHeight() - bmpSize.GetHeight() ) / 2;
|
|
|
|
|
|
|
|
wxBitmap bm = m_bitmap.GetBitmapFor( this );
|
|
|
|
|
|
|
|
if( !m_bIsEnable )
|
|
|
|
bm.ConvertToDisabled();
|
2022-12-13 20:47:28 +00:00
|
|
|
|
2023-06-03 15:32:36 +00:00
|
|
|
dc.DrawBitmap( bm, r1.x, r1.y, true );
|
2022-12-13 20:47:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool STD_BITMAP_BUTTON::Enable( bool aEnable )
|
|
|
|
{
|
|
|
|
m_bIsEnable = aEnable;
|
|
|
|
wxPanel::Enable( m_bIsEnable );
|
|
|
|
|
2022-12-27 23:55:09 +00:00
|
|
|
if( m_bIsEnable && m_stateButton == wxCONTROL_DISABLED )
|
|
|
|
{
|
2022-12-13 20:47:28 +00:00
|
|
|
m_stateButton = 0;
|
2022-12-27 23:55:09 +00:00
|
|
|
Refresh();
|
|
|
|
}
|
2022-12-13 20:47:28 +00:00
|
|
|
|
2022-12-27 23:55:09 +00:00
|
|
|
if( !m_bIsEnable && m_stateButton != wxCONTROL_DISABLED )
|
|
|
|
{
|
|
|
|
m_stateButton = wxCONTROL_DISABLED;
|
|
|
|
Refresh();
|
|
|
|
}
|
2022-12-13 20:47:28 +00:00
|
|
|
|
|
|
|
return aEnable;
|
|
|
|
}
|