KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kistatusbar.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) 2023 Mark Roszko <[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
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <wx/button.h>
26#include <wx/statusbr.h>
27#include <wx/gauge.h>
28#include <wx/stattext.h>
29#include <wx/tokenzr.h>
30#include <fmt/format.h>
31#include <array>
32#include <ranges>
33#include <widgets/kistatusbar.h>
36#include <widgets/ui_common.h>
37#include <pgm_base.h>
40#include <bitmaps.h>
41#include <reporter.h>
43#include <trace_helpers.h>
44#include <wx/dcclient.h>
45
46
48{
49public:
50 STATUSBAR_WARNING_REPORTER_DIALOG( wxWindow* aParent, KISTATUSBAR* aStatusBar ) :
51 DIALOG_HTML_REPORTER( aParent, wxID_ANY, _( "Messages" ) ),
52 m_statusBar( aStatusBar )
53 {
54 m_clearButton = new wxButton( this, wxID_CLEAR, _( "Clear" ) );
55 m_clearButton->Bind( wxEVT_BUTTON,
57
58 m_sdbSizer->Insert( 0, m_clearButton, 0, wxALL, 5 );
59 GetSizer()->Layout();
60 GetSizer()->Fit( this );
61 }
62
63private:
64 void onClearButtonClick( wxCommandEvent& aEvent )
65 {
66 if( m_statusBar )
67 m_statusBar->ClearWarningMessages();
68
69 EndModal( wxID_CLEAR );
70 }
71
72private:
74 wxButton* m_clearButton;
75};
76
77
78KISTATUSBAR::KISTATUSBAR( int aNumberFields, wxWindow* parent, wxWindowID id, STYLE_FLAGS aFlags ) :
79 wxStatusBar( parent, id ),
80 m_backgroundStopButton( nullptr ),
81 m_notificationsButton( nullptr ),
82 m_warningButton( nullptr ),
83 m_normalFieldsCount( aNumberFields ),
84 m_styleFlags( aFlags )
85{
86#ifdef __WXOSX__
87 // we need +1 extra field on OSX to offset from the rounded corner on the right
88 // OSX doesn't use resize grippers like the other platforms and the statusbar field
89 // includes the rounded part
90 int extraFields = 3;
91#else
92 int extraFields = 2;
93#endif
94
95 bool showNotification = ( m_styleFlags & NOTIFICATION_ICON );
96 bool showCancel = ( m_styleFlags & CANCEL_BUTTON );
97 bool showWarning = ( m_styleFlags & WARNING_ICON );
98
99 if( showCancel )
100 extraFields++;
101
102 if( showWarning )
103 extraFields++;
104
105 if( showNotification )
106 extraFields++;
107
108 SetFieldsCount( aNumberFields + extraFields );
109
110 m_fieldWidths.assign( aNumberFields + extraFields, -1 );
111
112 // Make the first pane wider.
113 if( aNumberFields )
114 m_fieldWidths[0] = -2;
115
116 int padding = KIUI::GetTextSize( wxT( "M" ), this ).x;
117
118#ifdef __WXOSX__
119 // offset from the right edge
120 m_fieldWidths[aNumberFields + extraFields - 1] = padding;
121#endif
122
123 int* styles = new int[aNumberFields + extraFields];
124
125 for( int i = 0; i < aNumberFields + extraFields; i++ )
126 styles[i] = wxSB_FLAT;
127
128 SetStatusStyles( aNumberFields + extraFields, styles );
129 delete[] styles;
130
131 m_backgroundTxt = new wxStaticText( this, wxID_ANY, wxT( "" ), wxDefaultPosition,
132 wxDefaultSize, wxALIGN_RIGHT | wxST_NO_AUTORESIZE );
133
134 m_backgroundProgressBar = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize,
135 wxGA_HORIZONTAL | wxGA_SMOOTH );
136
137 if( showCancel )
138 {
139 m_backgroundStopButton = new wxButton( this, wxID_ANY, "X", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
140 }
141
142 if( showNotification )
143 {
144 m_notificationsButton = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition,
145 wxDefaultSize, wxBU_EXACTFIT );
146
147 m_notificationsButton->SetPadding( 0 );
149 m_notificationsButton->SetShowBadge( true );
150 m_notificationsButton->SetBitmapCentered( true );
151
153 }
154
155 if( showWarning )
156 {
157 m_warningButton = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition,
158 wxDefaultSize, wxBU_EXACTFIT );
159
160 m_warningButton->SetPadding( 0 );
162 m_warningButton->SetBitmapCentered( true );
163 m_warningButton->SetToolTip( _( "View load messages" ) );
164 m_warningButton->Hide();
165
166
167 m_warningButton->Bind( wxEVT_BUTTON, &KISTATUSBAR::onLoadWarningsIconClick, this );
168 }
169
170 if( std::optional<int> idx = fieldIndex( FIELD::BGJOB_LABEL ) )
172
173 if( std::optional<int> idx = fieldIndex( FIELD::BGJOB_GAUGE ) )
174 {
176 m_fieldWidths[m_normalFieldsCount + *idx] = m_backgroundProgressBar->GetSize().x + padding;
177 else
179 }
180
181 if( std::optional<int> idx = fieldIndex( FIELD::BGJOB_CANCEL ) )
182 {
184 m_fieldWidths[m_normalFieldsCount + *idx] = m_backgroundStopButton->GetSize().x + padding;
185 else
187 }
188
189 if( std::optional<int> idx = fieldIndex( FIELD::WARNING ) )
190 {
191 if( m_warningButton )
192 m_fieldWidths[m_normalFieldsCount + *idx] = m_warningButton->GetSize().x + padding;
193 else
195 }
196
197 if( std::optional<int> idx = fieldIndex( FIELD::NOTIFICATION ) )
198 {
200 m_fieldWidths[m_normalFieldsCount + *idx] = m_notificationsButton->GetSize().x + padding;
201 else
203 }
204
205 SetStatusWidths( aNumberFields + extraFields, m_fieldWidths.data() );
206
207 Bind( wxEVT_SIZE, &KISTATUSBAR::onSize, this );
209
211 Layout();
212}
213
214
216{
218 m_notificationsButton->Unbind( wxEVT_BUTTON, &KISTATUSBAR::onNotificationsIconClick, this );
219
220 if( m_warningButton )
221 m_warningButton->Unbind( wxEVT_BUTTON, &KISTATUSBAR::onLoadWarningsIconClick, this );
222
223 Unbind( wxEVT_SIZE, &KISTATUSBAR::onSize, this );
225 this );
226}
227
228
229void KISTATUSBAR::onNotificationsIconClick( wxCommandEvent& aEvent )
230{
231 wxCHECK( m_notificationsButton, /* void */ );
232 wxPoint pos = m_notificationsButton->GetScreenPosition();
233
234 wxRect r;
235 if( std::optional<int> idx = fieldIndex( FIELD::NOTIFICATION ) )
236 {
237 GetFieldRect( m_normalFieldsCount + *idx, r );
238 pos.x += r.GetWidth();
239 }
240
241 Pgm().GetNotificationsManager().ShowList( this, pos );
242}
243
244
245void KISTATUSBAR::onBackgroundProgressClick( wxMouseEvent& aEvent )
246{
247 wxPoint pos = m_backgroundProgressBar->GetScreenPosition();
248
249 wxRect r;
250 if( std::optional<int> idx = fieldIndex( FIELD::BGJOB_GAUGE ) )
251 {
252 GetFieldRect( m_normalFieldsCount + *idx, r );
253 pos.x += r.GetWidth();
254 }
255
256 Pgm().GetBackgroundJobMonitor().ShowList( this, pos );
257}
258
259
260void KISTATUSBAR::onSize( wxSizeEvent& aEvent )
261{
263}
264
265
267{
268 constexpr int padding = 5;
269
270 wxRect r;
272
273 if( sbField >= 0 && sbField < GetFieldsCount() )
274 {
275 GetFieldRect( m_normalFieldsCount + *fieldIndex( FIELD::BGJOB_LABEL ), r );
276 int x = r.GetLeft();
277 int y = r.GetTop();
278 int textHeight = KIUI::GetTextSize( wxT( "bp" ), this ).y;
279
280 if( r.GetHeight() > textHeight )
281 y += ( r.GetHeight() - textHeight ) / 2;
282
283 m_backgroundTxt->SetPosition( { x, y } );
284 m_backgroundTxt->SetSize( r.GetWidth(), textHeight );
286 }
287
289
290 if( sbField >= 0 && sbField < GetFieldsCount() )
291 {
292 GetFieldRect( m_normalFieldsCount + *fieldIndex( FIELD::BGJOB_GAUGE ), r );
293 int x = r.GetLeft();
294 int y = r.GetTop();
295 int w = r.GetWidth();
296 int h = r.GetHeight();
297 wxSize buttonSize( 0, 0 );
298
300 {
301 buttonSize = m_backgroundStopButton->GetEffectiveMinSize();
302 m_backgroundStopButton->SetPosition( { x + w - buttonSize.GetWidth(), y } );
303 m_backgroundStopButton->SetSize( buttonSize.GetWidth(), h );
304 buttonSize.x += padding;
305 }
306
307 m_backgroundProgressBar->SetPosition( { x + padding, y } );
308 m_backgroundProgressBar->SetSize( w - buttonSize.GetWidth() - padding, h );
309
311 {
313
314 if( sbField >= 0 && sbField < GetFieldsCount() )
315 {
316 GetFieldRect( m_normalFieldsCount + *fieldIndex( FIELD::NOTIFICATION ), r );
317 x = r.GetLeft();
318 y = r.GetTop();
319 h = r.GetHeight();
320 buttonSize = m_notificationsButton->GetEffectiveMinSize();
321 m_notificationsButton->SetPosition( { x, y } );
322 m_notificationsButton->SetSize( buttonSize.GetWidth() + 6, h );
323 }
324 }
325 }
326
327 if( m_warningButton )
328 {
330
331 if( sbField >= 0 && sbField < GetFieldsCount() )
332 {
333 GetFieldRect( m_normalFieldsCount + *fieldIndex( FIELD::WARNING ), r );
334 int x = r.GetLeft();
335 int y = r.GetTop();
336 int h = r.GetHeight();
337 wxSize buttonSize = m_warningButton->GetEffectiveMinSize();
338 m_warningButton->SetPosition( { x, y } );
339 m_warningButton->SetSize( buttonSize.GetWidth() + 6, h );
340 }
341 }
342}
343
344
346{
348
350 m_backgroundStopButton->Show( aCancellable );
351
353}
354
355
365
366
368{
369 int range = m_backgroundProgressBar->GetRange();
370
371 if( aAmount > range )
372 aAmount = range;
373
374 m_backgroundProgressBar->SetValue( aAmount );
375}
376
377
379{
380 m_backgroundProgressBar->SetRange( aAmount );
381}
382
383
384void KISTATUSBAR::SetBackgroundStatusText( const wxString& aTxt )
385{
386 m_backgroundRawText = aTxt;
388
389 // When there are multiple normal fields, the last normal field (typically used for
390 // file watcher status on Windows) can visually overlap with the background job label
391 // since both have variable width. Save and clear that field when showing background
392 // text, and restore it when the background text is cleared.
393 if( m_normalFieldsCount > 1 )
394 {
395 int adjacentField = m_normalFieldsCount - 1;
396
397 if( !aTxt.empty() )
398 {
399 m_savedStatusText = GetStatusText( adjacentField );
400 SetStatusText( wxEmptyString, adjacentField );
401 }
402 else if( !m_savedStatusText.empty() )
403 {
404 SetStatusText( m_savedStatusText, adjacentField );
405 m_savedStatusText.clear();
406 }
407 }
408}
409
410
412{
413 if( m_fieldWidths.empty() )
414 return;
415
416 int padding = KIUI::GetTextSize( wxT( "M" ), this ).x;
417
418 if( std::optional<int> idx = fieldIndex( FIELD::BGJOB_LABEL ) )
420
421 if( std::optional<int> idx = fieldIndex( FIELD::BGJOB_GAUGE ) )
423
424 if( std::optional<int> idx = fieldIndex( FIELD::BGJOB_CANCEL ) )
425 {
427 m_fieldWidths[m_normalFieldsCount + *idx] = m_backgroundStopButton->GetSize().x + padding;
428 else
430 }
431
432 if( std::optional<int> idx = fieldIndex( FIELD::WARNING ) )
433 {
434 if( m_warningButton && m_warningButton->IsShown() )
435 m_fieldWidths[m_normalFieldsCount + *idx] = m_warningButton->GetSize().x + padding;
436 else
438 }
439
440 if( std::optional<int> idx = fieldIndex( FIELD::NOTIFICATION ) )
441 {
443 m_fieldWidths[m_normalFieldsCount + *idx] = m_notificationsButton->GetSize().x + padding;
444 else
446 }
447
448 SetStatusWidths( static_cast<int>( m_fieldWidths.size() ), m_fieldWidths.data() );
451}
452
453
455{
456 wxRect r;
457
458 if( !GetFieldRect( m_normalFieldsCount + *fieldIndex( FIELD::BGJOB_LABEL ), r ) )
459 return;
460
461 wxString text = m_backgroundRawText;
462
463 if( !text.empty() && r.GetWidth() > 4 )
464 {
465 wxClientDC dc( this );
466 int margin = KIUI::GetTextSize( wxT( "XX" ), this ).x;
467 text = wxControl::Ellipsize( text, dc, wxELLIPSIZE_END, std::max( 0, r.GetWidth() - margin ) );
468 }
469
470 m_backgroundTxt->SetLabel( text );
471}
472
473
475{
476 wxCHECK( m_notificationsButton, /* void */ );
477 wxString cnt = "";
478
479 if( aCount > 0 )
480 cnt = fmt::format( "{}", aCount );
481
482 m_notificationsButton->SetBadgeText( cnt );
483
484 // force a repaint or it wont until it gets activity
485 Refresh();
486}
487
488
489void KISTATUSBAR::AddWarningMessages( const wxString& aSource, const wxString& aMessages )
490{
491 {
492 std::lock_guard<std::mutex> lock( m_warningMutex );
493
494 wxStringTokenizer tokenizer( aMessages, wxS( "\n" ), wxTOKEN_STRTOK );
495
496 while( tokenizer.HasMoreTokens() )
497 {
498 LOAD_MESSAGE msg;
499 msg.message = tokenizer.GetNextToken();
500 msg.severity = RPT_SEVERITY_WARNING; // Default to warning for font substitutions
501 m_warningMessages[aSource].push_back( msg );
502 }
503 }
504
506}
507
508
509void KISTATUSBAR::AddWarningMessages( const wxString& aSource, const std::vector<LOAD_MESSAGE>& aMessages )
510{
511 wxLogTrace( traceLibraries, "KISTATUSBAR::AddWarningMessages: this=%p, count=%zu",
512 this, aMessages.size() );
513
514 if( aMessages.empty() )
515 return;
516
517 size_t totalMessageCount = 0;
518
519 {
520 std::lock_guard<std::mutex> lock( m_warningMutex );
521 m_warningMessages[aSource].insert( m_warningMessages[aSource].end(), aMessages.begin(), aMessages.end() );
522
523 for( const auto& [source, messages] : m_warningMessages )
524 totalMessageCount += messages.size();
525 }
526
527 wxLogTrace( traceLibraries, " -> total messages now=%zu", totalMessageCount );
528
529 // Update UI on main thread
530 wxLogTrace( traceLibraries, " -> calling CallAfter for updateWarningUI" );
531 CallAfter( [this]() { updateWarningUI(); } );
532}
533
534
536{
537 std::lock_guard<std::mutex> lock( m_warningMutex );
538
539 size_t count = 0;
540
541 for( const auto& [source, messages] : m_warningMessages )
542 count += messages.size();
543
544 return count;
545}
546
547
549{
550 wxLogTrace( traceLibraries, "KISTATUSBAR::updateWarningUI: this=%p, m_warningButton=%p",
551 this, m_warningButton );
552
553 if( !m_warningButton )
554 {
555 wxLogTrace( traceLibraries, " -> no warning button, returning early" );
556 return;
557 }
558
559 size_t messageCount;
560 {
561 std::lock_guard<std::mutex> lock( m_warningMutex );
562
563 messageCount = 0;
564
565 for( const std::vector<LOAD_MESSAGE>& messages : m_warningMessages | std::views::values )
566 messageCount += messages.size();
567 }
568
569 wxLogTrace( traceLibraries, " -> message count=%zu, showing button=%s",
570 messageCount, messageCount > 0 ? "true" : "false" );
571
572 m_warningButton->Show( messageCount > 0 );
573 m_warningButton->SetShowBadge( messageCount > 0 );
575
576 if( messageCount > 0 )
577 {
578 m_warningButton->SetToolTip( wxString::Format( _( "View %zu message(s)" ), messageCount ) );
579
580 // Show count badge on the warning button
581 wxString badgeText = messageCount > 99
582 ? wxString( "99+" )
583 : wxString::Format( wxS( "%zu" ), messageCount );
584 m_warningButton->SetBadgeText( badgeText );
585
586 wxLogTrace( traceLibraries, " -> badge set to '%s'", badgeText );
587 }
588 else
589 {
590 m_warningButton->SetBadgeText( wxEmptyString );
591 m_warningButton->SetToolTip( _( "View messages" ) );
592 }
593
594 Layout();
595 Refresh();
596}
597
598
599void KISTATUSBAR::ClearWarningMessages( const wxString& aSource )
600{
601 {
602 std::lock_guard<std::mutex> lock( m_warningMutex );
603
604 if( aSource.IsEmpty() )
605 m_warningMessages.clear();
606 else if( auto it = m_warningMessages.find( aSource ); it != m_warningMessages.end() )
607 m_warningMessages.erase( it );
608 }
609
611}
612
613
614void KISTATUSBAR::onLoadWarningsIconClick( wxCommandEvent& aEvent )
615{
616 // Copy messages under lock to avoid holding lock during modal dialog
617 std::unordered_map<wxString, std::vector<LOAD_MESSAGE>> messages;
618 {
619 std::lock_guard<std::mutex> lock( m_warningMutex );
620 messages = m_warningMessages;
621 }
622
623 if( messages.empty() )
624 return;
625
626 STATUSBAR_WARNING_REPORTER_DIALOG dlg( GetParent(), this );
627
628 for( const std::vector<LOAD_MESSAGE>& source : std::views::values( messages ) )
629 for( const LOAD_MESSAGE& msg : source )
630 dlg.m_Reporter->Report( msg.message, msg.severity );
631
632 dlg.m_Reporter->Flush();
633 dlg.ShowModal();
634}
635
636void KISTATUSBAR::SetEllipsedTextField( const wxString& aText, int aFieldId )
637{
638 wxRect fieldRect;
639 int width = -1;
640 wxString etext = aText;
641
642 // Only GetFieldRect() returns the current size for variable size fields
643 // Other methods return -1 for the width of these fields.
644 if( GetFieldRect( aFieldId, fieldRect ) )
645 width = fieldRect.GetWidth();
646
647 if( width > 20 )
648 {
649 wxClientDC dc( this );
650
651 // Gives a margin to the text to be sure it is not clamped at its end
652 int margin = KIUI::GetTextSize( wxT( "XX" ), this ).x;
653 etext = wxControl::Ellipsize( etext, dc, wxELLIPSIZE_MIDDLE, width - margin );
654 }
655
656 SetStatusText( etext, aFieldId );
657}
658
659
660std::optional<int> KISTATUSBAR::fieldIndex( FIELD aField ) const
661{
662 switch( aField )
663 {
664 case FIELD::BGJOB_LABEL: return 0;
665 case FIELD::BGJOB_GAUGE: return 1;
667 {
669 return 2;
670
671 break;
672 }
673 case FIELD::WARNING:
674 {
676 {
677 int offset = 2;
678
680 offset++;
681
682 return offset;
683 }
684
685 break;
686 }
688 {
690 {
691 int offset = 2;
692
694 offset++;
695
697 offset++;
698
699 return offset;
700 }
701
702 break;
703 }
704 }
705
706 return std::nullopt;
707}
708
709
710void KISTATUSBAR::SetStatusWidths( int aSize, const int* aWidths )
711{
712 wxStatusBar::SetStatusWidths( aSize, aWidths );
713
714 for( int i = 0; ( i < aSize ) && ( i < static_cast<int>( m_fieldWidths.size() ) ); i++ )
715 m_fieldWidths[i] = *( aWidths + i );
716}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
void ShowList(wxWindow *aParent, wxPoint aPos)
Shows the background job list.
A bitmap button widget that behaves like an AUI toolbar item's button when it is drawn.
wxStdDialogButtonSizer * m_sdbSizer
WX_HTML_REPORT_BOX * m_Reporter
DIALOG_HTML_REPORTER(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Report"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
int ShowModal() override
STYLE_FLAGS m_styleFlags
BITMAP_BUTTON * m_notificationsButton
void AddWarningMessages(const wxString &aSource, const wxString &aMessages)
Add warning/error messages (not thread-safe, use the std::vector<LOAD_MESSAGE> variant from other thr...
void onLoadWarningsIconClick(wxCommandEvent &aEvent)
std::optional< int > fieldIndex(FIELD aField) const
void SetBackgroundStatusText(const wxString &aTxt)
Set the status text that displays next to the progress bar.
BITMAP_BUTTON * m_warningButton
wxString m_backgroundRawText
Unellipsized background status text.
std::unordered_map< wxString, std::vector< LOAD_MESSAGE > > m_warningMessages
size_t GetLoadWarningCount() const
Get current message count (thread-safe).
void onBackgroundProgressClick(wxMouseEvent &aEvent)
KISTATUSBAR(int aNumberFields, wxWindow *parent, wxWindowID id, STYLE_FLAGS aFlags=DEFAULT_STYLE)
void updateAuxFieldWidths()
void layoutControls()
void onSize(wxSizeEvent &aEvent)
int m_normalFieldsCount
void ClearWarningMessages(const wxString &aSource=wxEmptyString)
Clears all warning messages from the given source (or all sources if aSource is empty)
wxString m_savedStatusText
Saved text from adjacent field during background jobs.
std::mutex m_warningMutex
Protects m_warningMessages.
void updateBackgroundText()
void SetBackgroundProgress(int aAmount)
Set the current progress of the progress bar.
wxGauge * m_backgroundProgressBar
wxButton * m_backgroundStopButton
void updateWarningUI()
Update warning button visibility and badge (main thread only)
void SetEllipsedTextField(const wxString &aText, int aFieldId)
Set the text in a field using wxELLIPSIZE_MIDDLE option to adjust the text size to the field size.
virtual void SetStatusWidths(int aSize, const int *aWidths) override
std::vector< int > m_fieldWidths
void HideBackgroundProgressBar()
Hide the background progress bar.
void onNotificationsIconClick(wxCommandEvent &aEvent)
void SetBackgroundProgressMax(int aAmount)
Set the max progress of the progress bar.
wxStaticText * m_backgroundTxt
void ShowBackgroundProgressBar(bool aCancellable=false)
Show the background progress bar.
void SetNotificationCount(int aCount)
Set the notification count on the notifications button.
void ShowList(wxWindow *aParent, wxPoint aPos)
Show the notification list.
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
Definition pgm_base.h:136
virtual NOTIFICATIONS_MANAGER & GetNotificationsManager() const
Definition pgm_base.h:141
void onClearButtonClick(wxCommandEvent &aEvent)
STATUSBAR_WARNING_REPORTER_DIALOG(wxWindow *aParent, KISTATUSBAR *aStatusBar)
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
void Flush()
Build the HTML messages page.
#define _(s)
const wxChar *const traceLibraries
Flag to enable library table and library manager tracing.
KICOMMON_API wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
Definition ui_common.cpp:78
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
@ RPT_SEVERITY_WARNING
KISTATUSBAR is a wxStatusBar suitable for Kicad manager.
Definition kistatusbar.h:54
wxString message
Definition kistatusbar.h:55
SEVERITY severity
Definition kistatusbar.h:56
VECTOR2I end
wxLogTrace helper definitions.
Functions to provide common constants and other functions to assist in making a consistent UI.