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 The 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, see <https://www.gnu.org/licenses/>.
20 */
21
23#include <wx/button.h>
24#include <wx/dcclient.h>
25#include <wx/menu.h>
26#include <wx/renderer.h>
27#include <wx/settings.h>
28#include <wx/textctrl.h>
29#include <wx/version.h>
30#include <kiplatform/ui.h>
31
32
33STD_BITMAP_BUTTON::STD_BITMAP_BUTTON( wxWindow* aParent, wxWindowID aId,
34 const wxBitmap& aDummyBitmap, const wxPoint& aPos,
35 const wxSize& aSize, int aStyle ) :
36 wxPanel( aParent, aId, aPos, aSize, aStyle, wxS( "StdBitmapButton" ) )
37{
38 if( aSize == wxDefaultSize )
39 {
40 wxSize defaultSize = wxButton::GetDefaultSize( aParent );
41
42#ifndef __WXMSW__
43 defaultSize.IncBy( 1 );
44#endif
45 SetMinSize( defaultSize );
46 }
47
48 Bind( wxEVT_PAINT, &STD_BITMAP_BUTTON::OnPaint, this );
49 Bind( wxEVT_LEFT_UP, &STD_BITMAP_BUTTON::OnLeftButtonUp, this );
50 Bind( wxEVT_LEFT_DOWN, &STD_BITMAP_BUTTON::OnLeftButtonDown, this );
51 Bind( wxEVT_KILL_FOCUS, &STD_BITMAP_BUTTON::OnKillFocus, this );
52 Bind( wxEVT_LEAVE_WINDOW, &STD_BITMAP_BUTTON::OnMouseLeave, this );
53 Bind( wxEVT_ENTER_WINDOW, &STD_BITMAP_BUTTON::OnMouseEnter, this );
54
55 Bind( wxEVT_SYS_COLOUR_CHANGED,
56 wxSysColourChangedEventHandler( STD_BITMAP_BUTTON::onThemeChanged ),
57 this );
58}
59
60
62{
63 Unbind( wxEVT_PAINT, &STD_BITMAP_BUTTON::OnPaint, this );
64 Unbind( wxEVT_LEFT_UP, &STD_BITMAP_BUTTON::OnLeftButtonUp, this );
65 Unbind( wxEVT_LEFT_DOWN, &STD_BITMAP_BUTTON::OnLeftButtonDown, this );
66 Unbind( wxEVT_KILL_FOCUS, &STD_BITMAP_BUTTON::OnKillFocus, this );
67 Unbind( wxEVT_LEAVE_WINDOW, &STD_BITMAP_BUTTON::OnMouseLeave, this );
68 Unbind( wxEVT_ENTER_WINDOW, &STD_BITMAP_BUTTON::OnMouseEnter, this );
69
70 Unbind( wxEVT_SYS_COLOUR_CHANGED,
71 wxSysColourChangedEventHandler( STD_BITMAP_BUTTON::onThemeChanged ), this );
72}
73
74
75void STD_BITMAP_BUTTON::onThemeChanged( wxSysColourChangedEvent &aEvent )
76{
77 Refresh();
78}
79
80
81void STD_BITMAP_BUTTON::SetBitmap( const wxBitmapBundle& aBmp )
82{
83 m_bitmap = aBmp;
84
85#ifndef __WXMSW__
86 wxSize size = m_bitmap.GetDefaultSize();
87
88 SetMinSize( wxSize( size.GetWidth() + 8, size.GetHeight() + 8 ) );
89#else
90 wxSize size = m_bitmap.GetPreferredBitmapSizeFor( this );
91 size.IncBy( 8 ); // padding
92
93 // Now adjust the min size but don't reduce it
94 wxSize minSize = GetMinSize();
95
96 // only change the width
97 // we want to keep the height at the original determined button height
98 // or else forms will get funny
99 // additionally we prefer to make the button square
100 if( size.GetWidth() > minSize.GetHeight() )
101 minSize.SetWidth( size.GetWidth() );
102 else
103 minSize.SetWidth( minSize.GetHeight() );
104
105 SetMinSize( minSize );
106#endif
107
108 Refresh();
109}
110
111
112void STD_BITMAP_BUTTON::OnKillFocus( wxFocusEvent& aEvent )
113{
114 if( m_stateButton != 0 )
115 {
116 m_stateButton = 0;
117 Refresh();
118 }
119
120 aEvent.Skip();
121}
122
123
124void STD_BITMAP_BUTTON::OnMouseLeave( wxMouseEvent& aEvent )
125{
126 if( m_stateButton != 0 )
127 {
128 m_stateButton = 0;
129 Refresh();
130 }
131
132 aEvent.Skip();
133}
134
135
136void STD_BITMAP_BUTTON::OnMouseEnter( wxMouseEvent& aEvent )
137{
138 if( m_stateButton != wxCONTROL_CURRENT )
139 {
140 m_stateButton = wxCONTROL_CURRENT;
141 Refresh();
142 }
143
144 aEvent.Skip();
145}
146
147
148void STD_BITMAP_BUTTON::OnLeftButtonUp( wxMouseEvent& aEvent )
149{
150 m_stateButton = 0;
151
152 Refresh();
153
154 wxEvtHandler* pEventHandler = GetEventHandler();
155 wxCHECK( pEventHandler, /* void */ );
156
157 pEventHandler->CallAfter(
158 [this]()
159 {
160 wxCommandEvent evt( wxEVT_BUTTON, GetId() );
161 evt.SetEventObject( this );
162 GetEventHandler()->ProcessEvent( evt );
163 } );
164
165 aEvent.Skip();
166}
167
168
169void STD_BITMAP_BUTTON::OnLeftButtonDown( wxMouseEvent& aEvent )
170{
171 m_stateButton = wxCONTROL_PRESSED;
172 Refresh();
173
174 aEvent.Skip();
175}
176
177
178void STD_BITMAP_BUTTON::OnPaint( wxPaintEvent& WXUNUSED( aEvent ) )
179{
180 wxPaintDC dc( this );
181 wxSize size = GetSize();
182
183#ifdef __WXMAC__
184 auto drawBackground =
185 [&]( wxRect aRect )
186 {
187 // wxWidgets doesn't have much support for dark mode on OSX; none of the
188 // system colours return the right values, nor does wxRendererNative draw
189 // the borders correctly. So we add some empirically chosen hacks here.
190
191 // NOTE: KEEP THESE HACKS IN SYNC WITH SPLIT_BUTTON
192
193 wxColor fg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT );
194 wxColor bg = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
195
197 {
198 bg = bg.ChangeLightness( m_bIsEnable ? 130 : 120 );
199 dc.SetBrush( bg );
200 dc.SetPen( bg );
201 }
202 else
203 {
204 bg = bg.ChangeLightness( m_bIsEnable ? 200 : 160 );
205 dc.SetBrush( bg );
206 fg = fg.ChangeLightness( 180 );
207 dc.SetPen( fg );
208 }
209
210 dc.DrawRoundedRectangle( aRect, aRect.height / 4.0 );
211 };
212#endif
213
214 wxRect r1;
215 r1.x = 0;
216 r1.y = 0;
217 r1.width = size.GetWidth();
218 r1.height = size.GetHeight();
219
220#ifdef __WXMAC__
221 // wxRendereNative doesn't handle dark mode on OSX.
222 drawBackground( r1 );
223#else
224
225#ifdef __WXMSW__
226 r1.width += 1;
227#endif
228
229 wxRendererNative::Get().DrawPushButton( this, dc, r1, m_stateButton );
230#endif
231
232 if( m_bitmap.IsOk() )
233 {
234#ifndef __WXMSW__
235 wxSize bmpSize = m_bitmap.GetDefaultSize();
236#else
237 wxSize bmpSize = m_bitmap.GetPreferredBitmapSizeFor( this );
238#endif
239
240 r1.x = ( size.GetWidth() - bmpSize.GetWidth() ) / 2;
241
242 if( r1.x < 0 )
243 r1.x = 0;
244
245 r1.y += ( size.GetHeight() - bmpSize.GetHeight() ) / 2;
246
247 wxBitmap bm = m_bitmap.GetBitmapFor( this );
248
249 if( !m_bIsEnable )
250 bm.ConvertToDisabled();
251
252 dc.DrawBitmap( bm, r1.x, r1.y, true );
253 }
254}
255
256
257bool STD_BITMAP_BUTTON::Enable( bool aEnable )
258{
259 m_bIsEnable = aEnable;
260 wxPanel::Enable( m_bIsEnable );
261
262 if( m_bIsEnable && m_stateButton == wxCONTROL_DISABLED )
263 {
264 m_stateButton = 0;
265 Refresh();
266 }
267
268 if( !m_bIsEnable && m_stateButton != wxCONTROL_DISABLED )
269 {
270 m_stateButton = wxCONTROL_DISABLED;
271 Refresh();
272 }
273
274 return aEnable;
275}
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)
const int minSize
Push and Shove router track width and via size dialog.
static const wxSize defaultSize(FRAME_T aFrameType, wxWindow *aWindow)
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition wxgtk/ui.cpp:51