KiCad PCB EDA Suite
Loading...
Searching...
No Matches
wx_infobar.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) 2020 Ian McInerney <[email protected]>
5 * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <id.h>
22#include <kiplatform/ui.h>
23#include <widgets/wx_infobar.h>
24#include "wx/artprov.h"
25#include <wx/aui/framemanager.h>
26#include <wx/debug.h>
27#include <wx/infobar.h>
28#include <wx/sizer.h>
29#include <wx/timer.h>
30#include <wx/hyperlink.h>
31#include <wx/bmpbuttn.h>
32#include <eda_base_frame.h>
33
34#ifdef __WXMSW__
35#include <dpi_scaling_common.h>
36#endif
37
38
39wxDEFINE_EVENT( KIEVT_SHOW_INFOBAR, wxCommandEvent );
40wxDEFINE_EVENT( KIEVT_DISMISS_INFOBAR, wxCommandEvent );
41
42BEGIN_EVENT_TABLE( WX_INFOBAR, wxInfoBarGeneric )
43 EVT_COMMAND( wxID_ANY, KIEVT_SHOW_INFOBAR, WX_INFOBAR::onShowInfoBar )
44 EVT_COMMAND( wxID_ANY, KIEVT_DISMISS_INFOBAR, WX_INFOBAR::onDismissInfoBar )
45
48END_EVENT_TABLE()
49
50
51WX_INFOBAR::WX_INFOBAR( wxWindow* aParent, wxAuiManager* aMgr, wxWindowID aWinid )
52 : wxInfoBarGeneric( aParent, aWinid ),
53 m_showTime( 0 ),
54 m_updateLock( false ),
55 m_showTimer( nullptr ),
56 m_auiManager( aMgr ),
57 m_type( MESSAGE_TYPE::GENERIC )
58{
59 m_showTimer = new wxTimer( this, ID_CLOSE_INFOBAR );
60
61#ifdef __WXMAC__
62 // wxWidgets hard-codes wxSYS_COLOUR_INFOBK to { 0xFF, 0xFF, 0xD3 } on Mac.
64 SetBackgroundColour( wxColour( 28, 27, 20 ) );
65 else
66 SetBackgroundColour( wxColour( 255, 249, 189 ) );
67
68 // Infobar is broken on Mac without the effects
69 SetShowHideEffects( wxSHOW_EFFECT_ROLL_TO_BOTTOM, wxSHOW_EFFECT_ROLL_TO_TOP );
70 SetEffectDuration( 200 );
71#else
72 // Infobar freezes canvas on Windows with the effect, and GTK looks bad with it
73 SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE );
74#endif
75
76
77 // The infobar seems to start too small, so increase its height
78 int sx, sy;
79 GetSize( &sx, &sy );
80 sy = 1.5 * sy;
81
82 // The bitmap gets cutoff sometimes with the default size, so force it to be the same
83 // height as the infobar.
84 wxSizer* sizer = GetSizer();
85 wxSize iconSize = wxArtProvider::GetSizeHint( wxART_BUTTON );
86
87#ifdef __WXMSW__
88 DPI_SCALING_COMMON dpi( nullptr, aParent );
89 iconSize.x *= dpi.GetContentScaleFactor();
90 sx *= dpi.GetContentScaleFactor();
91 sy *= dpi.GetContentScaleFactor();
92#endif
93
94 SetSize( sx, sy );
95
96 sizer->SetItemMinSize( (size_t) 0, iconSize.x, sy );
97
98 // Forcefully remove all existing buttons added by the wx constructors.
99 // The default close button doesn't work with the AUI manager update scheme, so this
100 // ensures any close button displayed is ours.
101 RemoveAllButtons();
102
103 Layout();
104
105 m_parent->Bind( wxEVT_SIZE, &WX_INFOBAR::onSize, this );
106}
107
108
110{
111 delete m_showTimer;
112}
113
114
115void WX_INFOBAR::SetShowTime( int aTime )
116{
117 m_showTime = aTime;
118}
119
120
121void WX_INFOBAR::QueueShowMessage( const wxString& aMessage, int aFlags )
122{
123 wxCommandEvent* evt = new wxCommandEvent( KIEVT_SHOW_INFOBAR );
124
125 evt->SetString( aMessage.c_str() );
126 evt->SetInt( aFlags );
127
128 GetEventHandler()->QueueEvent( evt );
129}
130
131
133{
134 wxCommandEvent* evt = new wxCommandEvent( KIEVT_DISMISS_INFOBAR );
135
136 GetEventHandler()->QueueEvent( evt );
137}
138
139
140void WX_INFOBAR::ShowMessageFor( const wxString& aMessage, int aTime, int aFlags,
141 MESSAGE_TYPE aType )
142{
143 // Don't do anything if we requested the UI update
144 if( m_updateLock )
145 return;
146
147 m_showTime = aTime;
148 ShowMessage( aMessage, aFlags );
149
150 m_type = aType;
151}
152
153
154void WX_INFOBAR::ShowMessage( const wxString& aMessage, int aFlags )
155{
156 // Don't do anything if we requested the UI update
157 if( m_updateLock )
158 return;
159
160 m_updateLock = true;
161
162 wxInfoBarGeneric::ShowMessage( aMessage, aFlags );
163
164 if( m_auiManager )
165 updateAuiLayout( true );
166
167 if( m_showTime > 0 )
168 m_showTimer->StartOnce( m_showTime );
169
171 m_updateLock = false;
172}
173
174
175void WX_INFOBAR::ShowMessage( const wxString& aMessage, int aFlags, MESSAGE_TYPE aType )
176{
177 // Don't do anything if we requested the UI update
178 if( m_updateLock )
179 return;
180
181 ShowMessage( aMessage, aFlags );
182
183 m_type = aType;
184}
185
186
188{
189 if( !IsShownOnScreen() )
190 return;
191
192 // Don't do anything if we requested the UI update
193 if( m_updateLock )
194 return;
195
196 m_updateLock = true;
197
198 wxInfoBarGeneric::Dismiss();
199
200 if( m_auiManager )
201 updateAuiLayout( false );
202
203 if( m_callback )
204 (*m_callback)();
205
206 m_updateLock = false;
207}
208
209
210void WX_INFOBAR::onSize( wxSizeEvent& aEvent )
211{
212 int barWidth = GetSize().GetWidth();
213
214 // Calculate the horizontal size: because the infobar is shown on top of the draw canvas
215 // it is adjusted to the canvas width.
216 // On Mac, the canvas is the parent
217 // On other OS the parent is EDA_BASE_FRAME that contains the canvas
218 int parentWidth = m_parent->GetClientSize().GetWidth();
219 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_parent );
220
221 if( frame && frame->GetToolCanvas() )
222 parentWidth = frame->GetToolCanvas()->GetSize().GetWidth();
223
224
225 if( barWidth != parentWidth )
226 SetSize( parentWidth, GetSize().GetHeight() );
227
228 aEvent.Skip();
229}
230
231
233{
234 wxASSERT( m_auiManager );
235
236 wxAuiPaneInfo& pane = m_auiManager->GetPane( this );
237
238 // If the infobar is in a pane, then show/hide the pane
239 if( pane.IsOk() )
240 {
241 if( aShow )
242 pane.Show();
243 else
244 pane.Hide();
245 }
246
247 // Update the AUI manager regardless
248 m_auiManager->Update();
249}
250
251
252void WX_INFOBAR::AddButton( wxWindowID aId, const wxString& aLabel )
253{
254 wxButton* button = new wxButton( this, aId, aLabel );
255
256 AddButton( button );
257}
258
259
260void WX_INFOBAR::AddButton( wxButton* aButton )
261{
262 wxSizer* sizer = GetSizer();
263
264 wxASSERT( aButton );
265
266#ifdef __WXMAC__
267 // Based on the code in the original class:
268 // smaller buttons look better in the (narrow) info bar under OS X
269 aButton->SetWindowVariant( wxWINDOW_VARIANT_SMALL );
270#endif // __WXMAC__
271 sizer->Add( aButton, wxSizerFlags().Centre().Border( wxRIGHT ) );
272
273 if( IsShownOnScreen() )
274 sizer->Layout();
275}
276
277
278void WX_INFOBAR::AddButton( wxHyperlinkCtrl* aHypertextButton )
279{
280 wxSizer* sizer = GetSizer();
281
282 wxASSERT( aHypertextButton );
283
284 sizer->Add( aHypertextButton, wxSizerFlags().Centre().Border( wxRIGHT ) );
285
286 if( IsShownOnScreen() )
287 sizer->Layout();
288}
289
290
291void WX_INFOBAR::AddCloseButton( const wxString& aTooltip )
292{
293 wxBitmapButton* button = wxBitmapButton::NewCloseButton( this, ID_CLOSE_INFOBAR );
294
295 button->SetToolTip( aTooltip );
296
297 AddButton( button );
298}
299
300
302{
303 wxSizer* sizer = GetSizer();
304
305 if( sizer->GetItemCount() == 0 )
306 return;
307
308 // The last item is already the spacer
309 if( sizer->GetItem( sizer->GetItemCount() - 1 )->IsSpacer() )
310 return;
311
312 for( int i = sizer->GetItemCount() - 1; i >= 0; i-- )
313 {
314 wxSizerItem* sItem = sizer->GetItem( i );
315
316 // The spacer is the end of the custom buttons
317 if( sItem->IsSpacer() )
318 break;
319
320 delete sItem->GetWindow();
321 }
322}
323
324
326{
327 wxSizer* sizer = GetSizer();
328
329 if( sizer->GetItemCount() == 0 )
330 return false;
331
332 if( sizer->GetItem( sizer->GetItemCount() - 1 )->IsSpacer() )
333 return false;
334
335 wxSizerItem* item = sizer->GetItem( sizer->GetItemCount() - 1 );
336
337 return ( item->GetWindow()->GetId() == ID_CLOSE_INFOBAR );
338}
339
340
341void WX_INFOBAR::onShowInfoBar( wxCommandEvent& aEvent )
342{
345 ShowMessage( aEvent.GetString(), aEvent.GetInt() );
346}
347
348
349void WX_INFOBAR::onDismissInfoBar( wxCommandEvent& aEvent )
350{
351 Dismiss();
352}
353
354
355void WX_INFOBAR::onCloseButton( wxCommandEvent& aEvent )
356{
357 Dismiss();
358}
359
360
361void WX_INFOBAR::onTimer( wxTimerEvent& aEvent )
362{
363 // Reset and clear the timer
364 m_showTimer->Stop();
365 m_showTime = 0;
366
367 Dismiss();
368}
369
370
371EDA_INFOBAR_PANEL::EDA_INFOBAR_PANEL( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos,
372 const wxSize& aSize, long aStyle, const wxString& aName )
373 : wxPanel( aParent, aId, aPos, aSize, aStyle, aName )
374{
375 m_mainSizer = new wxFlexGridSizer( 1, 0, 0 );
376
377 m_mainSizer->SetFlexibleDirection( wxBOTH );
378 m_mainSizer->AddGrowableCol( 0, 1 );
379
380 SetSizer( m_mainSizer );
381}
382
383
385{
386 wxASSERT( aInfoBar );
387
388 aInfoBar->Reparent( this );
389 m_mainSizer->Add( aInfoBar, 1, wxEXPAND, 0 );
390 m_mainSizer->Layout();
391}
392
393
394void EDA_INFOBAR_PANEL::AddOtherItem( wxWindow* aOtherItem )
395{
396 wxASSERT( aOtherItem );
397
398 aOtherItem->Reparent( this );
399 m_mainSizer->Add( aOtherItem, 1, wxEXPAND, 0 );
400
401 m_mainSizer->AddGrowableRow( 1, 1 );
402 m_mainSizer->Layout();
403}
Class to handle configuration and automatic determination of the DPI scale to use for canvases.
double GetContentScaleFactor() const override
Get the content scale factor, which may be different from the scale factor on some platforms.
The base frame for deriving all KiCad main window classes.
EDA_INFOBAR_PANEL(wxWindow *aParent, wxWindowID aId=wxID_ANY, const wxPoint &aPos=wxDefaultPosition, const wxSize &aSize=wxSize(-1,-1), long aStyle=wxTAB_TRAVERSAL, const wxString &aName=wxEmptyString)
Definition: wx_infobar.cpp:371
wxFlexGridSizer * m_mainSizer
Definition: wx_infobar.h:304
void AddInfoBar(WX_INFOBAR *aInfoBar)
Add the given infobar object to the panel.
Definition: wx_infobar.cpp:384
void AddOtherItem(wxWindow *aOtherItem)
Add the other item to the panel.
Definition: wx_infobar.cpp:394
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
A modified version of the wxInfoBar class that allows us to:
Definition: wx_infobar.h:75
void SetShowTime(int aTime)
Set the time period to show the infobar.
Definition: wx_infobar.cpp:115
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:301
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION, MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the infobar with the provided message and icon for a specific period of time.
Definition: wx_infobar.cpp:140
bool HasCloseButton() const
Definition: wx_infobar.cpp:325
MESSAGE_TYPE m_type
The type of message being displayed.
Definition: wx_infobar.h:256
void updateAuiLayout(bool aShow)
Update the AUI pane to show or hide this infobar.
Definition: wx_infobar.cpp:232
std::optional< std::function< void(void)> > m_callback
Optional callback made when closing infobar.
Definition: wx_infobar.h:258
int m_showTime
The time to show the infobar. 0 = don't auto hide.
Definition: wx_infobar.h:252
bool m_updateLock
True if this infobar requested the UI update.
Definition: wx_infobar.h:253
void onShowInfoBar(wxCommandEvent &aEvent)
Event handler for showing the infobar using a wxCommandEvent of the type KIEVT_SHOW_INFOBAR.
Definition: wx_infobar.cpp:341
void onDismissInfoBar(wxCommandEvent &aEvent)
Event handler for dismissing the infobar using a wxCommandEvent of the type KIEVT_DISMISS_INFOBAR.
Definition: wx_infobar.cpp:349
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: wx_infobar.cpp:260
MESSAGE_TYPE
Sets the type of message for special handling if needed.
Definition: wx_infobar.h:93
@ GENERIC
GENERIC Are messages that do not have special handling.
void QueueShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION)
Send the infobar an event telling it to show a message.
Definition: wx_infobar.cpp:121
void onCloseButton(wxCommandEvent &aEvent)
Event handler for the close button.
Definition: wx_infobar.cpp:355
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:187
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: wx_infobar.cpp:291
wxTimer * m_showTimer
The timer counting the autoclose period.
Definition: wx_infobar.h:254
void onTimer(wxTimerEvent &aEvent)
Event handler for the automatic closing timer.
Definition: wx_infobar.cpp:361
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:154
wxAuiManager * m_auiManager
The AUI manager that contains this infobar.
Definition: wx_infobar.h:255
void onSize(wxSizeEvent &aEvent)
Definition: wx_infobar.cpp:210
void QueueDismiss()
Send the infobar an event telling it to hide itself.
Definition: wx_infobar.cpp:132
Base window classes and related definitions.
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition: gtk/ui.cpp:48
wxDEFINE_EVENT(KIEVT_SHOW_INFOBAR, wxCommandEvent)
@ ID_CLOSE_INFOBAR
ID for the close button on the frame's infobar.
Definition: wx_infobar.h:40