22#include <wx/statusbr.h>
24#include <wx/stattext.h>
25#include <wx/statbmp.h>
26#include <wx/scrolwin.h>
27#include <wx/textctrl.h>
30#include <wx/artprov.h>
31#include <wx/tokenzr.h>
32#include <fmt/format.h>
49#include <wx/dcclient.h>
56 wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxBORDER_NONE )
60 SetBackgroundColour( bg );
61 SetForegroundColour( fg );
63 wxBoxSizer* outerSizer =
new wxBoxSizer( wxHORIZONTAL );
65 wxArtID artId = wxART_WARNING;
75 wxStaticBitmap* icon =
new wxStaticBitmap(
76 this, wxID_ANY, wxArtProvider::GetBitmapBundle( artId, wxART_OTHER, FromDIP( wxSize( 16, 16 ) ) ) );
77 icon->SetBackgroundColour( bg );
78 outerSizer->Add( icon, 0, wxALL, 4 );
80 wxBoxSizer* textSizer =
new wxBoxSizer( wxVERTICAL );
84 wxStaticText* title =
new wxStaticText(
this, wxID_ANY, aError.
GetTitle() );
88 title->Wrap( aWrapWidth );
90 textSizer->Add( title, 0, wxALL | wxEXPAND, 1 );
95 wxStaticText* desc =
new wxStaticText(
this, wxID_ANY, aError.
GetDescription() );
98 desc->Wrap( aWrapWidth );
100 textSizer->Add( desc, 0, wxALL | wxEXPAND, 1 );
108 textSizer->Add( pane, 0, wxEXPAND | wxALL, 1 );
110 wxWindow* paneWin = pane->
GetPane();
111 paneWin->SetBackgroundColour( bg );
113 int paneHeight = GetCharHeight() * ( 2 +
text.Freq(
'\n' ) );
115 wxTextCtrl* debugText =
new wxTextCtrl( paneWin, wxID_ANY,
text, wxDefaultPosition,
116 FromDIP( wxSize( -1, paneHeight ) ),
117 wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP );
119 wxFont monoFont = debugText->GetFont();
120 monoFont.SetFamily( wxFONTFAMILY_TELETYPE );
121 debugText->SetFont( monoFont );
123 wxBoxSizer* paneSizer =
new wxBoxSizer( wxVERTICAL );
124 paneSizer->Add( debugText, 1, wxEXPAND | wxALL, 2 );
125 paneWin->SetSizer( paneSizer );
129 [
this]( wxCommandEvent& aEvt )
133 wxWindow* scrolled = GetParent();
134 wxWindow* frame = scrolled->GetParent();
138 if( wxSizer* sizer = scrolled->GetSizer() )
139 sizer->Fit( scrolled );
146 outerSizer->Add( textSizer, 1, wxEXPAND | wxTOP, 3 );
148 SetSizer( outerSizer );
161 wxFrame( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
162 wxFRAME_NO_TASKBAR | wxBORDER_STATIC ),
167 const wxSize panelSize = FromDIP( wxSize( 600, 200 ) );
169 SetSize( panelSize );
170 SetSizeHints( panelSize, wxDefaultSize );
174 SetBackgroundColour( bg );
176 wxBoxSizer* mainSizer =
new wxBoxSizer( wxVERTICAL );
179 new wxScrolledWindow(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL | wxBORDER_SIMPLE );
190 wxBoxSizer* btnSizer =
new wxBoxSizer( wxHORIZONTAL );
191 btnSizer->AddStretchSpacer( 1 );
192 wxButton* clearButton =
new wxButton(
this, wxID_CLEAR,
_(
"Clear Warnings" ) );
194 btnSizer->Add( clearButton, 0, wxALL, 5 );
195 mainSizer->Add( btnSizer, 0, wxEXPAND | wxTOP | wxRIGHT | wxLEFT | wxBOTTOM, 5 );
197 SetSizer( mainSizer );
224 if( wrapWidth < 100 )
225 wrapWidth = FromDIP( 580 );
227 wrapWidth -= FromDIP( 40 );
231 for(
const auto& msgs : messages | std::views::values )
250 if( !IsDescendant( aEvent.GetWindow() ) )
262 if( aEvent.GetKeyCode() == WXK_ESCAPE )
297 wxStatusBar( parent, id, wxSTB_SIZEGRIP | wxSTB_ELLIPSIZE_MIDDLE | wxSTB_SHOW_TIPS | wxFULL_REPAINT_ON_RESIZE ),
324 if( showNotification )
327 m_backgroundTxt =
new wxStaticText(
this, wxID_ANY, wxT(
"" ), wxDefaultPosition,
328 wxDefaultSize, wxALIGN_RIGHT | wxST_NO_AUTORESIZE );
331 wxGA_HORIZONTAL | wxGA_SMOOTH );
335 m_backgroundStopButton =
new wxButton(
this, wxID_ANY,
"X", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
338 if( showNotification )
341 wxDefaultSize, wxBU_EXACTFIT );
354 wxDefaultSize, wxBU_EXACTFIT );
376 std::vector<int> styles( aNumberFields + extraFields, wxSB_FLAT );
377 SetStatusStyles( styles.size(), styles.data() );
409 if( std::optional<int> idx =
fieldIndex( FIELD::NOTIFICATION ) )
412 pos.x += r.GetWidth();
424 if( std::optional<int> idx =
fieldIndex( FIELD::BGJOB_GAUGE ) )
427 pos.x += r.GetWidth();
442 constexpr int padding = 5;
447 if( sbField >= 0 && sbField < GetFieldsCount() )
454 if( r.GetHeight() > textHeight )
455 y += ( r.GetHeight() - textHeight ) / 2;
464 if( sbField >= 0 && sbField < GetFieldsCount() )
469 int w = r.GetWidth();
470 int h = r.GetHeight();
471 wxSize buttonSize( 0, 0 );
478 buttonSize.x += padding;
488 if( sbField >= 0 && sbField < GetFieldsCount() )
505 if( sbField >= 0 && sbField < GetFieldsCount() )
510 int h = r.GetHeight();
545 if( aAmount > range )
570 wxString currentText = GetStatusText( adjacentField );
574 if( !currentText.empty() )
577 SetStatusText( wxEmptyString, adjacentField );
599 if( std::optional<int> idx =
fieldIndex( FIELD::BGJOB_LABEL ) )
602 if( std::optional<int> idx =
fieldIndex( FIELD::BGJOB_GAUGE ) )
605 if( std::optional<int> idx =
fieldIndex( FIELD::BGJOB_CANCEL ) )
613 if( std::optional<int> idx =
fieldIndex( FIELD::WARNING ) )
621 if( std::optional<int> idx =
fieldIndex( FIELD::NOTIFICATION ) )
644 if( !
text.empty() && r.GetWidth() > 4 )
646 wxClientDC dc(
this );
648 text = wxControl::Ellipsize(
text, dc, wxELLIPSIZE_END, std::max( 0, r.GetWidth() - margin ) );
661 cnt = fmt::format(
"{}", aCount );
675 wxStringTokenizer tokenizer( aMessages, wxS(
"\n" ), wxTOKEN_STRTOK );
677 while( tokenizer.HasMoreTokens() )
680 msg.
SetTitle( tokenizer.GetNextToken() );
692 wxLogTrace(
traceLibraries,
"KISTATUSBAR::AddWarningMessages: this=%p, count=%zu",
693 this, aMessages.size() );
695 if( aMessages.empty() )
698 size_t totalMessageCount = 0;
705 totalMessageCount += messages.size();
708 wxLogTrace(
traceLibraries,
" -> total messages now=%zu", totalMessageCount );
711 wxLogTrace(
traceLibraries,
" -> calling CallAfter for updateWarningUI" );
723 count += messages.size();
741 wxLogTrace(
traceLibraries,
"KISTATUSBAR::updateWarningUI: this=%p, m_warningButton=%p",
746 wxLogTrace(
traceLibraries,
" -> no warning button, returning early" );
756 for(
const std::vector<KI_ERROR>& messages :
m_warningMessages | std::views::values )
757 messageCount += messages.size();
760 wxLogTrace(
traceLibraries,
" -> message count=%zu, showing button=%s",
761 messageCount, messageCount > 0 ?
"true" :
"false" );
767 if( messageCount > 0 )
769 m_warningButton->SetToolTip( wxString::Format(
_(
"View %zu message(s)" ), messageCount ) );
772 wxString badgeText = messageCount > 99
774 : wxString::Format( wxS(
"%zu" ), messageCount );
787 if( messageCount > 0 )
803 if( aSource.IsEmpty() )
855 pos.x = iconRect.GetRight() + 1 - windowSize.GetWidth();
856 pos.y = iconRect.GetTop() - windowSize.GetHeight();
878 case FIELD::BGJOB_LABEL:
return 0;
879 case FIELD::BGJOB_GAUGE:
return 1;
880 case FIELD::BGJOB_CANCEL:
901 case FIELD::NOTIFICATION:
926 wxStatusBar::SetStatusWidths( aSize, aWidths );
928 for(
int i = 0; ( i < aSize ) && ( i < static_cast<int>(
m_fieldWidths.size() ) ); i++ )
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
void ShowList(wxWindow *aParent, wxPoint aPos)
Shows the background job list.
ERROR_CARD(wxWindow *aParent, const KI_ERROR &aError, int aWrapWidth)
KISTATUSBAR is a wxStatusBar suitable for Kicad manager.
BITMAP_BUTTON * m_notificationsButton
void AddWarningMessages(const wxString &aSource, const wxString &aMessages)
Add warning/error messages (not thread-safe, use the std::vector<KI_ERROR> variant from other threads...
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.
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()
std::unordered_map< wxString, std::vector< KI_ERROR > > m_warningMessages
void onSize(wxSizeEvent &aEvent)
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 CloseWarningList()
Close the warning message overlay panel, if it is shown.
void updateWarningUI()
Update warning button visibility and badge (main thread only)
virtual void SetStatusWidths(int aSize, const int *aWidths) override
std::map< wxString, std::vector< KI_ERROR > > GetWarningMessages() const
Get a copy of all stored warning/error messages, grouped by source and sorted by source name for stab...
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.
void PositionWarningPanel()
Position the warning message overlay panel above the warning icon.
wxStaticText * m_backgroundTxt
void ShowBackgroundProgressBar(bool aCancellable=false)
Show the background progress bar.
STATUSBAR_WARNING_LIST * m_warningList
Overlay panel listing the warning messages.
void SetNotificationCount(int aCount)
Set the notification count on the notifications button.
Holds a structured error message.
const wxString & GetTitle() const
SEVERITY GetSeverity() const
const wxString & GetDescription() const
bool HasDescription() const
KI_ERROR & SetSeverity(SEVERITY aSeverity)
KI_ERROR & SetTitle(const wxString &aTitle)
bool HasDebugText() const
const wxString & GetDebugText() const
void ShowList(wxWindow *aParent, wxPoint aPos)
Show the notification list.
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
virtual NOTIFICATIONS_MANAGER & GetNotificationsManager() const
void onClose(wxCloseEvent &aEvent)
STATUSBAR_WARNING_LIST(KISTATUSBAR *aStatusBar, wxWindow *aParent)
wxScrolledWindow * m_scrolledWindow
void onClearButtonClick(wxCommandEvent &aEvent)
wxBoxSizer * m_contentSizer
void onCharHook(wxKeyEvent &aEvent)
~STATUSBAR_WARNING_LIST() override
void onFocusLoss(wxFocusEvent &aEvent)
KISTATUSBAR * m_statusBar
A better wxCollapsiblePane that.
void Collapse(bool aCollapse=true)
bool SetBackgroundColour(const wxColour &aColor) override
const wxChar *const traceLibraries
Flag to enable library table and library manager tracing.
static long long g_warning_list_closed_timer
KICOMMON_API wxFont GetControlFont(wxWindow *aWindow)
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...
PGM_BASE & Pgm()
The global program "get" accessor.
wxLogTrace helper definitions.
Functions to provide common constants and other functions to assist in making a consistent UI.
const KICOMMON_API wxEventTypeTag< wxCommandEvent > WX_COLLAPSIBLE_PANE_CHANGED