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 The 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
46 EVT_SYS_COLOUR_CHANGED( WX_INFOBAR::onThemeChange )
49END_EVENT_TABLE()
50
51
52WX_INFOBAR::WX_INFOBAR( wxWindow* aParent, wxAuiManager* aMgr, wxWindowID aWinid )
53 : wxInfoBarGeneric( aParent, aWinid ),
54 m_showTime( 0 ),
55 m_updateLock( false ),
56 m_showTimer( nullptr ),
57 m_auiManager( aMgr ),
58 m_type( MESSAGE_TYPE::GENERIC )
59{
60 m_showTimer = new wxTimer( this, ID_CLOSE_INFOBAR );
61
62 wxColour fg, bg;
64 SetBackgroundColour( bg );
65 SetForegroundColour( fg );
66
67#ifdef __WXMAC__
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 // The infobar seems to start too small, so increase its height
77 int sx, sy;
78 GetSize( &sx, &sy );
79 sy = 1.5 * sy;
80
81 // The bitmap gets cutoff sometimes with the default size, so force it to be the same
82 // height as the infobar.
83 wxSizer* sizer = GetSizer();
84 wxSize iconSize = wxArtProvider::GetSizeHint( wxART_BUTTON );
85
86#ifdef __WXMSW__
87 DPI_SCALING_COMMON dpi( nullptr, aParent );
88 iconSize.x *= dpi.GetContentScaleFactor();
89 sx *= dpi.GetContentScaleFactor();
90 sy *= dpi.GetContentScaleFactor();
91#endif
92
93 SetSize( sx, sy );
94
95 sizer->SetItemMinSize( (size_t) 0, iconSize.x, sy );
96
97 // Forcefully remove all existing buttons added by the wx constructors.
98 // The default close button doesn't work with the AUI manager update scheme, so this
99 // ensures any close button displayed is ours.
100 RemoveAllButtons();
101
102 Layout();
103
104 m_parent->Bind( wxEVT_SIZE, &WX_INFOBAR::onSize, this );
105}
106
107
109{
110 delete m_showTimer;
111}
112
113
114void WX_INFOBAR::SetShowTime( int aTime )
115{
116 m_showTime = aTime;
117}
118
119
120void WX_INFOBAR::QueueShowMessage( const wxString& aMessage, int aFlags )
121{
122 wxCommandEvent* evt = new wxCommandEvent( KIEVT_SHOW_INFOBAR );
123
124 evt->SetString( aMessage.c_str() );
125 evt->SetInt( aFlags );
126
127 GetEventHandler()->QueueEvent( evt );
128}
129
130
132{
133 wxCommandEvent* evt = new wxCommandEvent( KIEVT_DISMISS_INFOBAR );
134
135 GetEventHandler()->QueueEvent( evt );
136}
137
138
139void WX_INFOBAR::ShowMessageFor( const wxString& aMessage, int aTime, int aFlags,
140 MESSAGE_TYPE aType )
141{
142 // Don't do anything if we requested the UI update
143 if( m_updateLock )
144 return;
145
146 m_showTime = aTime;
147 ShowMessage( aMessage, aFlags );
148
149 m_type = aType;
150}
151
152
153void WX_INFOBAR::ShowMessage( const wxString& aMessage, int aFlags )
154{
155 // Don't do anything if we requested the UI update
156 if( m_updateLock )
157 return;
158
159 m_updateLock = true;
160
161 wxString msg = aMessage;
162 msg.Trim();
163
164 wxInfoBarGeneric::ShowMessage( msg, aFlags );
165
166 if( m_auiManager )
167 updateAuiLayout( true );
168
169 if( m_showTime > 0 )
170 m_showTimer->StartOnce( m_showTime );
171
173 m_updateLock = false;
174}
175
176
177void WX_INFOBAR::ShowMessage( const wxString& aMessage, int aFlags, MESSAGE_TYPE aType )
178{
179 // Don't do anything if we requested the UI update
180 if( m_updateLock )
181 return;
182
183 ShowMessage( aMessage, aFlags );
184
185 m_type = aType;
186}
187
188
190{
191 if( !IsShownOnScreen() )
192 return;
193
194 // Don't do anything if we requested the UI update
195 if( m_updateLock )
196 return;
197
198 m_updateLock = true;
199
200 wxInfoBarGeneric::Dismiss();
201
202 if( m_auiManager )
203 updateAuiLayout( false );
204
205 if( m_callback )
206 (*m_callback)();
207
208 m_updateLock = false;
209}
210
211
212void WX_INFOBAR::onThemeChange( wxSysColourChangedEvent& aEvent )
213{
214 wxColour fg, bg;
216 SetBackgroundColour( bg );
217 SetForegroundColour( fg );
218
219 if( wxBitmapButton* btn = GetCloseButton() )
220 {
221 wxString tooltip = btn->GetToolTipText();
223 AddCloseButton( tooltip );
224 }
225}
226
227
228void WX_INFOBAR::onSize( wxSizeEvent& aEvent )
229{
230 int barWidth = GetSize().GetWidth();
231
232 // Calculate the horizontal size: because the infobar is shown on top of the draw canvas
233 // it is adjusted to the canvas width.
234 // On Mac, the canvas is the parent
235 // On other OS the parent is EDA_BASE_FRAME that contains the canvas
236 int parentWidth = m_parent->GetClientSize().GetWidth();
237 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_parent );
238
239 if( frame && frame->GetToolCanvas() )
240 parentWidth = frame->GetToolCanvas()->GetSize().GetWidth();
241
242
243 if( barWidth != parentWidth )
244 SetSize( parentWidth, GetSize().GetHeight() );
245
246 aEvent.Skip();
247}
248
249
251{
252 wxASSERT( m_auiManager );
253
254 wxAuiPaneInfo& pane = m_auiManager->GetPane( this );
255
256 // If the infobar is in a pane, then show/hide the pane
257 if( pane.IsOk() )
258 {
259 if( aShow )
260 pane.Show();
261 else
262 pane.Hide();
263 }
264
265 // Update the AUI manager regardless
266 m_auiManager->Update();
267}
268
269
270void WX_INFOBAR::AddButton( wxWindowID aId, const wxString& aLabel )
271{
272 wxButton* button = new wxButton( this, aId, aLabel );
273
274 AddButton( button );
275}
276
277
278void WX_INFOBAR::AddButton( wxButton* aButton )
279{
280 wxSizer* sizer = GetSizer();
281
282 wxASSERT( aButton );
283
284#ifdef __WXMAC__
285 // Based on the code in the original class:
286 // smaller buttons look better in the (narrow) info bar under OS X
287 aButton->SetWindowVariant( wxWINDOW_VARIANT_SMALL );
288#endif // __WXMAC__
289
290 sizer->Add( aButton, wxSizerFlags().Centre().Border( wxRIGHT ) );
291
292 if( IsShownOnScreen() )
293 sizer->Layout();
294}
295
296
297void WX_INFOBAR::AddButton( wxHyperlinkCtrl* aHypertextButton )
298{
299 wxSizer* sizer = GetSizer();
300
301 wxASSERT( aHypertextButton );
302
303 sizer->Add( aHypertextButton, wxSizerFlags().Centre().Border( wxRIGHT ) );
304
305 if( IsShownOnScreen() )
306 sizer->Layout();
307}
308
309
310void WX_INFOBAR::AddCloseButton( const wxString& aTooltip )
311{
312 wxBitmapButton* button = wxBitmapButton::NewCloseButton( this, ID_CLOSE_INFOBAR );
313
314 button->SetToolTip( aTooltip );
315
316 AddButton( button );
317}
318
319
321{
322 wxSizer* sizer = GetSizer();
323
324 if( sizer->GetItemCount() == 0 )
325 return;
326
327 // The last item is already the spacer
328 if( sizer->GetItem( sizer->GetItemCount() - 1 )->IsSpacer() )
329 return;
330
331 for( int i = sizer->GetItemCount() - 1; i >= 0; i-- )
332 {
333 wxSizerItem* sItem = sizer->GetItem( i );
334
335 // The spacer is the end of the custom buttons
336 if( sItem->IsSpacer() )
337 break;
338
339 delete sItem->GetWindow();
340 }
341}
342
343
345{
346 return GetCloseButton();
347}
348
349
350wxBitmapButton* WX_INFOBAR::GetCloseButton() const
351{
352 wxSizer* sizer = GetSizer();
353
354 if( sizer->GetItemCount() == 0 )
355 return nullptr;
356
357 if( sizer->GetItem( sizer->GetItemCount() - 1 )->IsSpacer() )
358 return nullptr;
359
360 wxSizerItem* item = sizer->GetItem( sizer->GetItemCount() - 1 );
361
362 if( item->GetWindow()->GetId() == ID_CLOSE_INFOBAR )
363 return static_cast<wxBitmapButton*>( item->GetWindow() );
364
365 return nullptr;
366}
367
368
369void WX_INFOBAR::onShowInfoBar( wxCommandEvent& aEvent )
370{
373 ShowMessage( aEvent.GetString(), aEvent.GetInt() );
374}
375
376
377void WX_INFOBAR::onDismissInfoBar( wxCommandEvent& aEvent )
378{
379 Dismiss();
380}
381
382
383void WX_INFOBAR::onCloseButton( wxCommandEvent& aEvent )
384{
385 Dismiss();
386}
387
388
389void WX_INFOBAR::onTimer( wxTimerEvent& aEvent )
390{
391 // Reset and clear the timer
392 m_showTimer->Stop();
393 m_showTime = 0;
394
395 Dismiss();
396}
397
398
399EDA_INFOBAR_PANEL::EDA_INFOBAR_PANEL( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos,
400 const wxSize& aSize, long aStyle, const wxString& aName )
401 : wxPanel( aParent, aId, aPos, aSize, aStyle, aName )
402{
403 m_mainSizer = new wxFlexGridSizer( 1, 0, 0 );
404
405 m_mainSizer->SetFlexibleDirection( wxBOTH );
406 m_mainSizer->AddGrowableCol( 0, 1 );
407
408 SetSizer( m_mainSizer );
409}
410
411
413{
414 wxASSERT( aInfoBar );
415
416 aInfoBar->Reparent( this );
417 m_mainSizer->Add( aInfoBar, 1, wxEXPAND, 0 );
418 m_mainSizer->Layout();
419}
420
421
422void EDA_INFOBAR_PANEL::AddOtherItem( wxWindow* aOtherItem )
423{
424 wxASSERT( aOtherItem );
425
426 aOtherItem->Reparent( this );
427 m_mainSizer->Add( aOtherItem, 1, wxEXPAND, 0 );
428
429 m_mainSizer->AddGrowableRow( 1, 1 );
430 m_mainSizer->Layout();
431}
432
433
434REPORTER& INFOBAR_REPORTER::Report( const wxString& aText, SEVERITY aSeverity )
435{
436 m_message.reset( new wxString( aText ) );
437 m_severity = aSeverity;
438 m_messageSet = true;
439
440 return *this;
441}
442
443
445{
446 return m_message && !m_message->IsEmpty();
447}
448
449
451{
452 // Don't do anything if no message was ever given
453 if( !m_infoBar || !m_messageSet )
454 return;
455
456 // Short circuit if the message is empty and it is already hidden
457 if( !HasMessage() && !m_infoBar->IsShownOnScreen() )
458 return;
459
460 int icon = wxICON_NONE;
461
462 switch( m_severity )
463 {
464 case RPT_SEVERITY_UNDEFINED: icon = wxICON_INFORMATION; break;
465 case RPT_SEVERITY_INFO: icon = wxICON_INFORMATION; break;
466 case RPT_SEVERITY_EXCLUSION: icon = wxICON_WARNING; break;
467 case RPT_SEVERITY_ACTION: icon = wxICON_WARNING; break;
468 case RPT_SEVERITY_WARNING: icon = wxICON_WARNING; break;
469 case RPT_SEVERITY_ERROR: icon = wxICON_ERROR; break;
470 case RPT_SEVERITY_IGNORE: icon = wxICON_INFORMATION; break;
471 case RPT_SEVERITY_DEBUG: icon = wxICON_INFORMATION; break;
472 }
473
474 if( m_message->EndsWith( wxS( "\n" ) ) )
475 *m_message = m_message->Left( m_message->Length() - 1 );
476
477 if( HasMessage() )
479 else
481}
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:399
wxFlexGridSizer * m_mainSizer
Definition: wx_infobar.h:312
void AddInfoBar(WX_INFOBAR *aInfoBar)
Add the given infobar object to the panel.
Definition: wx_infobar.cpp:412
void AddOtherItem(wxWindow *aOtherItem)
Add the other item to the panel.
Definition: wx_infobar.cpp:422
WX_INFOBAR * m_infoBar
Definition: wx_infobar.h:347
void Finalize()
Update the infobar with the reported text.
Definition: wx_infobar.cpp:450
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
Definition: wx_infobar.cpp:434
SEVERITY m_severity
Definition: wx_infobar.h:349
std::unique_ptr< wxString > m_message
Definition: wx_infobar.h:348
bool HasMessage() const override
Returns true if the reporter client is non-empty.
Definition: wx_infobar.cpp:444
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:72
virtual wxWindow * GetToolCanvas() const =0
Canvas access.
A modified version of the wxInfoBar class that allows us to:
Definition: wx_infobar.h:76
void SetShowTime(int aTime)
Set the time period to show the infobar.
Definition: wx_infobar.cpp:114
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:320
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:139
bool HasCloseButton() const
Definition: wx_infobar.cpp:344
MESSAGE_TYPE m_type
The type of message being displayed.
Definition: wx_infobar.h:264
void updateAuiLayout(bool aShow)
Update the AUI pane to show or hide this infobar.
Definition: wx_infobar.cpp:250
std::optional< std::function< void(void)> > m_callback
Optional callback made when closing infobar.
Definition: wx_infobar.h:266
int m_showTime
The time to show the infobar. 0 = don't auto hide.
Definition: wx_infobar.h:260
bool m_updateLock
True if this infobar requested the UI update.
Definition: wx_infobar.h:261
void onShowInfoBar(wxCommandEvent &aEvent)
Event handler for showing the infobar using a wxCommandEvent of the type KIEVT_SHOW_INFOBAR.
Definition: wx_infobar.cpp:369
void onDismissInfoBar(wxCommandEvent &aEvent)
Event handler for dismissing the infobar using a wxCommandEvent of the type KIEVT_DISMISS_INFOBAR.
Definition: wx_infobar.cpp:377
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: wx_infobar.cpp:278
MESSAGE_TYPE
Sets the type of message for special handling if needed.
Definition: wx_infobar.h:94
@ 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:120
void onCloseButton(wxCommandEvent &aEvent)
Event handler for the close button.
Definition: wx_infobar.cpp:383
wxBitmapButton * GetCloseButton() const
Definition: wx_infobar.cpp:350
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:189
void onThemeChange(wxSysColourChangedEvent &aEvent)
Event handler for the color theme change event.
Definition: wx_infobar.cpp:212
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: wx_infobar.cpp:310
wxTimer * m_showTimer
The timer counting the autoclose period.
Definition: wx_infobar.h:262
void onTimer(wxTimerEvent &aEvent)
Event handler for the automatic closing timer.
Definition: wx_infobar.cpp:389
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:153
wxAuiManager * m_auiManager
The AUI manager that contains this infobar.
Definition: wx_infobar.h:263
void onSize(wxSizeEvent &aEvent)
Definition: wx_infobar.cpp:228
void QueueDismiss()
Send the infobar an event telling it to hide itself.
Definition: wx_infobar.cpp:131
Base window classes and related definitions.
Common command IDs shared by more than one of the KiCad applications.
void GetInfoBarColours(wxColour &aFGColour, wxColour &aBGColour)
Return the background and foreground colors for info bars in the current scheme.
Definition: wxgtk/ui.cpp:67
SEVERITY
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_UNDEFINED
@ RPT_SEVERITY_EXCLUSION
@ RPT_SEVERITY_IGNORE
@ RPT_SEVERITY_DEBUG
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
wxDEFINE_EVENT(KIEVT_SHOW_INFOBAR, wxCommandEvent)
@ ID_CLOSE_INFOBAR
ID for the close button on the frame's infobar.
Definition: wx_infobar.h:41