KiCad PCB EDA Suite
Loading...
Searching...
No Matches
std_bitmap_button.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KICAD, a free EDA CAD application.
3 *
4 * Copyright (C) 2016 Anil8735(https://stackoverflow.com/users/3659387/anil8753)
5 * from https://stackoverflow.com/a/37274011
6 * Copyright (C) 2020-2023 Kicad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
27#include <wx/button.h>
28#include <wx/dcclient.h>
29#include <wx/menu.h>
30#include <wx/renderer.h>
31#include <wx/settings.h>
32#include <wx/version.h>
33#include <kiplatform/ui.h>
34
35
36STD_BITMAP_BUTTON::STD_BITMAP_BUTTON( wxWindow* aParent, wxWindowID aId,
37 const wxBitmap& aDummyBitmap, const wxPoint& aPos,
38 const wxSize& aSize, int aStyle ) :
39 wxPanel( aParent, aId, aPos, aSize, aStyle, wxS( "StdBitmapButton" ) )
40{
41 if( aSize == wxDefaultSize )
42 {
43 wxSize defaultSize = wxButton::GetDefaultSize( aParent );
44 SetMinSize( wxSize( defaultSize.GetWidth() + 1, defaultSize.GetHeight() + 1 ) );
45 }
46
47 Bind( wxEVT_PAINT, &STD_BITMAP_BUTTON::OnPaint, this );
48 Bind( wxEVT_LEFT_UP, &STD_BITMAP_BUTTON::OnLeftButtonUp, this );
49 Bind( wxEVT_LEFT_DOWN, &STD_BITMAP_BUTTON::OnLeftButtonDown, this );
50 Bind( wxEVT_KILL_FOCUS, &STD_BITMAP_BUTTON::OnKillFocus, this );
51 Bind( wxEVT_LEAVE_WINDOW, &STD_BITMAP_BUTTON::OnMouseLeave, this );
52 Bind( wxEVT_ENTER_WINDOW, &STD_BITMAP_BUTTON::OnMouseEnter, this );
53
54 Bind( wxEVT_SYS_COLOUR_CHANGED,
55 wxSysColourChangedEventHandler( STD_BITMAP_BUTTON::onThemeChanged ),
56 this );
57}
58
59
61{
62}
63
64
65void STD_BITMAP_BUTTON::onThemeChanged( wxSysColourChangedEvent &aEvent )
66{
67 Refresh();
68}
69
70
71void STD_BITMAP_BUTTON::SetBitmap( const wxBitmapBundle& aBmp )
72{
73 m_bitmap = aBmp;
74
75#ifndef __WXMSW__
76 wxSize size = m_bitmap.GetDefaultSize();
77#else
78 wxSize size = m_bitmap.GetPreferredBitmapSizeFor( this );
79#endif
80
81 SetMinSize( wxSize( size.GetWidth() + 8, size.GetHeight() + 8 ) );
82}
83
84
85void STD_BITMAP_BUTTON::OnKillFocus( wxFocusEvent& aEvent )
86{
87 if( m_stateButton != 0 )
88 {
89 m_stateButton = 0;
90 Refresh();
91 }
92
93 aEvent.Skip();
94}
95
96
97void STD_BITMAP_BUTTON::OnMouseLeave( wxMouseEvent& aEvent )
98{
99 if( m_stateButton != 0 )
100 {
101 m_stateButton = 0;
102 Refresh();
103 }
104
105 aEvent.Skip();
106}
107
108
109void STD_BITMAP_BUTTON::OnMouseEnter( wxMouseEvent& aEvent )
110{
111 if( m_stateButton != wxCONTROL_CURRENT )
112 {
113 m_stateButton = wxCONTROL_CURRENT;
114 Refresh();
115 }
116
117 aEvent.Skip();
118}
119
120
121void STD_BITMAP_BUTTON::OnLeftButtonUp( wxMouseEvent& aEvent )
122{
123 m_stateButton = 0;
124
125 Refresh();
126
127 wxEvtHandler* pEventHandler = GetEventHandler();
128 wxASSERT( pEventHandler );
129
130 pEventHandler->CallAfter(
131 [=]()
132 {
133 wxCommandEvent evt( wxEVT_BUTTON, GetId() );
134 evt.SetEventObject( this );
135 GetEventHandler()->ProcessEvent( evt );
136 } );
137
138 aEvent.Skip();
139}
140
141
142void STD_BITMAP_BUTTON::OnLeftButtonDown( wxMouseEvent& aEvent )
143{
144 m_stateButton = wxCONTROL_PRESSED;
145 Refresh();
146
147 aEvent.Skip();
148}
149
150
151void STD_BITMAP_BUTTON::OnPaint( wxPaintEvent& WXUNUSED( aEvent ) )
152{
153 wxPaintDC dc( this );
154 wxSize size = GetSize();
155
156#ifdef __WXMAC__
157 auto drawBackground =
158 [&]( wxRect aRect )
159 {
160 // wxWidgets doesn't have much support for dark mode on OSX; none of the
161 // system colours return the right values, nor does wxRendererNative draw
162 // the borders correctly. So we add some empirically chosen hacks here.
163
164 // NOTE: KEEP THESE HACKS IN SYNC WITH SPLIT_BUTTON
165
166 wxColor fg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT );
167 wxColor bg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
168
169 aRect.width += 1;
170 aRect.height += 1;
171
173 {
174 bg = bg.ChangeLightness( m_bIsEnable ? 130 : 120 );
175 dc.SetBrush( bg );
176 dc.SetPen( bg );
177 }
178 else
179 {
180 bg = bg.ChangeLightness( m_bIsEnable ? 200 : 160 );
181 dc.SetBrush( bg );
182 fg = fg.ChangeLightness( 180 );
183 dc.SetPen( fg );
184 }
185
186 dc.DrawRoundedRectangle( aRect, aRect.height / 4.0 );
187 };
188#endif
189
190 wxRect r1;
191 r1.x = 0;
192 r1.y = 0;
193 r1.width = size.GetWidth();
194 r1.height = size.GetHeight();
195
196#ifdef __WXMAC__
197 // wxRendereNative doesn't handle dark mode on OSX.
198 drawBackground( r1 );
199#else
200 #ifdef __WXMSW__
201 r1.width += 1;
202 #endif
203
204 wxRendererNative::Get().DrawPushButton( this, dc, r1, m_stateButton );
205#endif
206
207 if( m_bitmap.IsOk() )
208 {
209#ifndef __WXMSW__
210 wxSize bmpSize = m_bitmap.GetDefaultSize();
211#else
212 wxSize bmpSize = m_bitmap.GetPreferredBitmapSizeFor( this );
213#endif
214
215 r1.x = ( size.GetWidth() - bmpSize.GetWidth() ) / 2;
216
217 if( r1.x < 0 )
218 r1.x = 0;
219
220 r1.y += ( size.GetHeight() - bmpSize.GetHeight() ) / 2;
221
222 wxBitmap bm = m_bitmap.GetBitmapFor( this );
223
224 if( !m_bIsEnable )
225 bm.ConvertToDisabled();
226
227 dc.DrawBitmap( bm, r1.x, r1.y, true );
228 }
229}
230
231
232bool STD_BITMAP_BUTTON::Enable( bool aEnable )
233{
234 m_bIsEnable = aEnable;
235 wxPanel::Enable( m_bIsEnable );
236
237 if( m_bIsEnable && m_stateButton == wxCONTROL_DISABLED )
238 {
239 m_stateButton = 0;
240 Refresh();
241 }
242
243 if( !m_bIsEnable && m_stateButton != wxCONTROL_DISABLED )
244 {
245 m_stateButton = wxCONTROL_DISABLED;
246 Refresh();
247 }
248
249 return aEnable;
250}
void OnPaint(wxPaintEvent &WXUNUSED(aEvent))
void OnKillFocus(wxFocusEvent &aEvent)
void OnLeftButtonDown(wxMouseEvent &aEvent)
wxBitmapBundle m_bitmap
bool Enable(bool aEnable=true) override
void OnMouseEnter(wxMouseEvent &aEvent)
void SetBitmap(const wxBitmapBundle &aBmp)
void onThemeChanged(wxSysColourChangedEvent &aEvent)
STD_BITMAP_BUTTON(wxWindow *aParent, wxWindowID aId, const wxBitmap &aDummyBitmap, const wxPoint &aPos=wxDefaultPosition, const wxSize &aSize=wxDefaultSize, int aStyle=0)
void OnLeftButtonUp(wxMouseEvent &aEvent)
void OnMouseLeave(wxMouseEvent &aEvent)
static const wxSize defaultSize(FRAME_T aFrameType)
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition: gtk/ui.cpp:48
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...