KiCad PCB EDA Suite
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
35wxDEFINE_EVENT( KIEVT_SHOW_INFOBAR, wxCommandEvent );
36wxDEFINE_EVENT( KIEVT_DISMISS_INFOBAR, wxCommandEvent );
37
38BEGIN_EVENT_TABLE( WX_INFOBAR, wxInfoBarGeneric )
39 EVT_COMMAND( wxID_ANY, KIEVT_SHOW_INFOBAR, WX_INFOBAR::onShowInfoBar )
40 EVT_COMMAND( wxID_ANY, KIEVT_DISMISS_INFOBAR, WX_INFOBAR::onDismissInfoBar )
41
44END_EVENT_TABLE()
45
46
47WX_INFOBAR::WX_INFOBAR( wxWindow* aParent, wxAuiManager* aMgr, wxWindowID aWinid )
48 : wxInfoBarGeneric( aParent, aWinid ),
49 m_showTime( 0 ),
50 m_updateLock( false ),
51 m_showTimer( nullptr ),
52 m_auiManager( aMgr ),
53 m_type( MESSAGE_TYPE::GENERIC )
54{
55 m_showTimer = new wxTimer( this, ID_CLOSE_INFOBAR );
56
57#ifdef __WXMAC__
58 // wxWidgets hard-codes wxSYS_COLOUR_INFOBK to { 0xFF, 0xFF, 0xD3 } on Mac.
60 SetBackgroundColour( wxColour( 28, 27, 20 ) );
61 else
62 SetBackgroundColour( wxColour( 255, 249, 189 ) );
63
64 // Infobar is broken on Mac without the effects
65 SetShowHideEffects( wxSHOW_EFFECT_ROLL_TO_BOTTOM, wxSHOW_EFFECT_ROLL_TO_TOP );
66 SetEffectDuration( 300 );
67#else
68 // Infobar freezes canvas on Windows with the effect, and GTK looks bad with it
69 SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE );
70#endif
71
72
73 // The infobar seems to start too small, so increase its height
74 int sx, sy;
75 GetSize( &sx, &sy );
76 sy = 1.5 * sy;
77 SetSize( sx, sy );
78
79 // The bitmap gets cutoff sometimes with the default size, so force it to be the same
80 // height as the infobar.
81 wxSizer* sizer = GetSizer();
82 wxSize iconSize = wxArtProvider::GetSizeHint( wxART_BUTTON );
83
84 sizer->SetItemMinSize( (size_t) 0, iconSize.x, sy );
85
86 // Forcefully remove all existing buttons added by the wx constructors.
87 // The default close button doesn't work with the AUI manager update scheme, so this
88 // ensures any close button displayed is ours.
89 RemoveAllButtons();
90
91 Layout();
92
93 m_parent->Bind( wxEVT_SIZE, &WX_INFOBAR::onSize, this );
94}
95
96
98{
99 delete m_showTimer;
100}
101
102
103void WX_INFOBAR::SetShowTime( int aTime )
104{
105 m_showTime = aTime;
106}
107
108
109void WX_INFOBAR::QueueShowMessage( const wxString& aMessage, int aFlags )
110{
111 wxCommandEvent* evt = new wxCommandEvent( KIEVT_SHOW_INFOBAR );
112
113 evt->SetString( aMessage.c_str() );
114 evt->SetInt( aFlags );
115
116 GetEventHandler()->QueueEvent( evt );
117}
118
119
121{
122 wxCommandEvent* evt = new wxCommandEvent( KIEVT_DISMISS_INFOBAR );
123
124 GetEventHandler()->QueueEvent( evt );
125}
126
127
128void WX_INFOBAR::ShowMessageFor( const wxString& aMessage, int aTime, int aFlags,
129 MESSAGE_TYPE aType )
130{
131 // Don't do anything if we requested the UI update
132 if( m_updateLock )
133 return;
134
135 m_showTime = aTime;
136 ShowMessage( aMessage, aFlags );
137
138 m_type = aType;
139}
140
141
142void WX_INFOBAR::ShowMessage( const wxString& aMessage, int aFlags )
143{
144 // Don't do anything if we requested the UI update
145 if( m_updateLock )
146 return;
147
148 m_updateLock = true;
149
150 wxInfoBarGeneric::ShowMessage( aMessage, aFlags );
151
152 if( m_auiManager )
153 updateAuiLayout( true );
154
155 if( m_showTime > 0 )
156 m_showTimer->StartOnce( m_showTime );
157
159 m_updateLock = false;
160}
161
162
163void WX_INFOBAR::ShowMessage( const wxString& aMessage, int aFlags, MESSAGE_TYPE aType )
164{
165 // Don't do anything if we requested the UI update
166 if( m_updateLock )
167 return;
168
169 ShowMessage( aMessage, aFlags );
170
171 m_type = aType;
172}
173
174
176{
177 if( !IsShown() )
178 return;
179
180 // Don't do anything if we requested the UI update
181 if( m_updateLock )
182 return;
183
184 m_updateLock = true;
185
186 wxInfoBarGeneric::Dismiss();
187
188 if( m_auiManager )
189 updateAuiLayout( false );
190
191 if( m_callback )
192 (*m_callback)();
193
194 m_updateLock = false;
195}
196
197
198void WX_INFOBAR::onSize( wxSizeEvent& aEvent )
199{
200 int barWidth = GetSize().GetWidth();
201
202 // Calculate the horizontal size: because the infobar is shown on top of the draw canvas
203 // it is adjusted to the canvas width.
204 // On Mac, the canvas is the parent
205 // On other OS the parent is EDA_BASE_FRAME that contains the canvas
206 int parentWidth = m_parent->GetClientSize().GetWidth();
207 EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( m_parent );
208
209 if( frame && frame->GetToolCanvas() )
210 parentWidth = frame->GetToolCanvas()->GetSize().GetWidth();
211
212
213 if( barWidth != parentWidth )
214 SetSize( parentWidth, GetSize().GetHeight() );
215
216 aEvent.Skip();
217}
218
219
221{
222 wxASSERT( m_auiManager );
223
224 wxAuiPaneInfo& pane = m_auiManager->GetPane( this );
225
226 // If the infobar is in a pane, then show/hide the pane
227 if( pane.IsOk() )
228 {
229 if( aShow )
230 pane.Show();
231 else
232 pane.Hide();
233 }
234
235 // Update the AUI manager regardless
236 m_auiManager->Update();
237}
238
239
240void WX_INFOBAR::AddButton( wxWindowID aId, const wxString& aLabel )
241{
242 wxButton* button = new wxButton( this, aId, aLabel );
243
244 AddButton( button );
245}
246
247
248void WX_INFOBAR::AddButton( wxButton* aButton )
249{
250 wxSizer* sizer = GetSizer();
251
252 wxASSERT( aButton );
253
254#ifdef __WXMAC__
255 // Based on the code in the original class:
256 // smaller buttons look better in the (narrow) info bar under OS X
257 aButton->SetWindowVariant( wxWINDOW_VARIANT_SMALL );
258#endif // __WXMAC__
259 sizer->Add( aButton, wxSizerFlags().Centre().Border( wxRIGHT ) );
260
261 if( IsShown() )
262 sizer->Layout();
263}
264
265
266void WX_INFOBAR::AddButton( wxHyperlinkCtrl* aHypertextButton )
267{
268 wxSizer* sizer = GetSizer();
269
270 wxASSERT( aHypertextButton );
271
272 sizer->Add( aHypertextButton, wxSizerFlags().Centre().Border( wxRIGHT ) );
273
274 if( IsShown() )
275 sizer->Layout();
276}
277
278
279void WX_INFOBAR::AddCloseButton( const wxString& aTooltip )
280{
281 wxBitmapButton* button = wxBitmapButton::NewCloseButton( this, ID_CLOSE_INFOBAR );
282
283 button->SetToolTip( aTooltip );
284
285 AddButton( button );
286}
287
288
290{
291 wxSizer* sizer = GetSizer();
292
293 if( sizer->GetItemCount() == 0 )
294 return;
295
296 // The last item is already the spacer
297 if( sizer->GetItem( sizer->GetItemCount() - 1 )->IsSpacer() )
298 return;
299
300 for( int i = sizer->GetItemCount() - 1; i >= 0; i-- )
301 {
302 wxSizerItem* sItem = sizer->GetItem( i );
303
304 // The spacer is the end of the custom buttons
305 if( sItem->IsSpacer() )
306 break;
307
308 delete sItem->GetWindow();
309 }
310}
311
312
314{
315 wxSizer* sizer = GetSizer();
316
317 if( sizer->GetItemCount() == 0 )
318 return false;
319
320 if( sizer->GetItem( sizer->GetItemCount() - 1 )->IsSpacer() )
321 return false;
322
323 wxSizerItem* item = sizer->GetItem( sizer->GetItemCount() - 1 );
324
325 return ( item->GetWindow()->GetId() == ID_CLOSE_INFOBAR );
326}
327
328
329void WX_INFOBAR::onShowInfoBar( wxCommandEvent& aEvent )
330{
333 ShowMessage( aEvent.GetString(), aEvent.GetInt() );
334}
335
336
337void WX_INFOBAR::onDismissInfoBar( wxCommandEvent& aEvent )
338{
339 Dismiss();
340}
341
342
343void WX_INFOBAR::onCloseButton( wxCommandEvent& aEvent )
344{
345 Dismiss();
346}
347
348
349void WX_INFOBAR::onTimer( wxTimerEvent& aEvent )
350{
351 // Reset and clear the timer
352 m_showTimer->Stop();
353 m_showTime = 0;
354
355 Dismiss();
356}
357
358
359EDA_INFOBAR_PANEL::EDA_INFOBAR_PANEL( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos,
360 const wxSize& aSize, long aStyle, const wxString& aName )
361 : wxPanel( aParent, aId, aPos, aSize, aStyle, aName )
362{
363 m_mainSizer = new wxFlexGridSizer( 1, 0, 0 );
364
365 m_mainSizer->SetFlexibleDirection( wxBOTH );
366 m_mainSizer->AddGrowableCol( 0, 1 );
367
368 SetSizer( m_mainSizer );
369}
370
371
373{
374 wxASSERT( aInfoBar );
375
376 aInfoBar->Reparent( this );
377 m_mainSizer->Add( aInfoBar, 1, wxEXPAND, 0 );
378 m_mainSizer->Layout();
379}
380
381
382void EDA_INFOBAR_PANEL::AddOtherItem( wxWindow* aOtherItem )
383{
384 wxASSERT( aOtherItem );
385
386 aOtherItem->Reparent( this );
387 m_mainSizer->Add( aOtherItem, 1, wxEXPAND, 0 );
388
389 m_mainSizer->AddGrowableRow( 1, 1 );
390 m_mainSizer->Layout();
391}
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:359
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:372
void AddOtherItem(wxWindow *aOtherItem)
Add the other item to the panel.
Definition: wx_infobar.cpp:382
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:103
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:289
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:128
bool HasCloseButton() const
Definition: wx_infobar.cpp:313
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:220
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:329
void onDismissInfoBar(wxCommandEvent &aEvent)
Event handler for dismissing the infobar using a wxCommandEvent of the type KIEVT_DISMISS_INFOBAR.
Definition: wx_infobar.cpp:337
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: wx_infobar.cpp:248
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:109
void onCloseButton(wxCommandEvent &aEvent)
Event handler for the close button.
Definition: wx_infobar.cpp:343
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:175
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: wx_infobar.cpp:279
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:349
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:142
wxAuiManager * m_auiManager
The AUI manager that contains this infobar.
Definition: wx_infobar.h:255
void onSize(wxSizeEvent &aEvent)
Definition: wx_infobar.cpp:198
void QueueDismiss()
Send the infobar an event telling it to hide itself.
Definition: wx_infobar.cpp:120
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:31
wxDEFINE_EVENT(KIEVT_SHOW_INFOBAR, wxCommandEvent)
@ ID_CLOSE_INFOBAR
ID for the close button on the frame's infobar.
Definition: wx_infobar.h:40