KiCad PCB EDA Suite
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 <ian.s.mcinerney@ieee.org>
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 <widgets/infobar.h>
23 #include "wx/artprov.h"
24 #include <wx/aui/framemanager.h>
25 #include <wx/debug.h>
26 #include <wx/infobar.h>
27 #include <wx/sizer.h>
28 #include <wx/timer.h>
29 #include <wx/hyperlink.h>
30 
31 
32 wxDEFINE_EVENT( KIEVT_SHOW_INFOBAR, wxCommandEvent );
33 wxDEFINE_EVENT( KIEVT_DISMISS_INFOBAR, wxCommandEvent );
34 
35 BEGIN_EVENT_TABLE( WX_INFOBAR, wxInfoBarGeneric )
36  EVT_COMMAND( wxID_ANY, KIEVT_SHOW_INFOBAR, WX_INFOBAR::OnShowInfoBar )
37  EVT_COMMAND( wxID_ANY, KIEVT_DISMISS_INFOBAR, WX_INFOBAR::OnDismissInfoBar )
38 
41 END_EVENT_TABLE()
42 
43 
44 WX_INFOBAR::WX_INFOBAR( wxWindow* aParent, wxAuiManager* aMgr, wxWindowID aWinid )
45  : wxInfoBarGeneric( aParent, aWinid ),
46  m_showTime( 0 ),
47  m_updateLock( false ),
48  m_showTimer( nullptr ),
49  m_auiManager( aMgr )
50 {
51  m_showTimer = new wxTimer( this, ID_CLOSE_INFOBAR );
52 
53  // Don't use any effects since they leave the sizer area visible under the infobar
54  SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE );
55 
56  // The infobar seems to start too small, so increase its height
57  int sx, sy;
58  GetSize( &sx, &sy );
59  sy = 1.5 * sy;
60  SetSize( sx, sy );
61 
62  // The bitmap gets cutoff sometimes with the default size, so force it to be the same
63  // height as the infobar.
64  wxSizer* sizer = GetSizer();
65  wxSize iconSize = wxArtProvider::GetSizeHint( wxART_BUTTON );
66 
67  sizer->SetItemMinSize( (size_t) 0, iconSize.x, sy );
68 
69  // Forcefully remove all existing buttons added by the wx constructors.
70  // The default close button doesn't work with the AUI manager update scheme, so this
71  // ensures any close button displayed is ours.
72  RemoveAllButtons();
73 
74  Layout();
75 }
76 
77 
79 {
80  delete m_showTimer;
81 }
82 
83 
84 void WX_INFOBAR::SetShowTime( int aTime )
85 {
86  m_showTime = aTime;
87 }
88 
89 
90 void WX_INFOBAR::QueueShowMessage( const wxString& aMessage, int aFlags )
91 {
92  wxCommandEvent* evt = new wxCommandEvent( KIEVT_SHOW_INFOBAR );
93 
94  evt->SetString( aMessage.c_str() );
95  evt->SetInt( aFlags );
96 
97  GetEventHandler()->QueueEvent( evt );
98 }
99 
100 
102 {
103  wxCommandEvent* evt = new wxCommandEvent( KIEVT_DISMISS_INFOBAR );
104 
105  GetEventHandler()->QueueEvent( evt );
106 }
107 
108 
109 void WX_INFOBAR::ShowMessageFor( const wxString& aMessage, int aTime, int aFlags )
110 {
111  // Don't do anything if we requested the UI update
112  if( m_updateLock )
113  return;
114 
115  m_showTime = aTime;
116  ShowMessage( aMessage, aFlags );
117 }
118 
119 
120 void WX_INFOBAR::ShowMessage( const wxString& aMessage, int aFlags )
121 {
122  // Don't do anything if we requested the UI update
123  if( m_updateLock )
124  return;
125 
126  m_updateLock = true;
127 
128  wxInfoBarGeneric::ShowMessage( aMessage, aFlags );
129 
130  if( m_auiManager )
131  UpdateAuiLayout( true );
132 
133  if( m_showTime > 0 )
134  m_showTimer->StartOnce( m_showTime );
135 
136  m_updateLock = false;
137 }
138 
139 
141 {
142  // Don't do anything if we requested the UI update
143  if( m_updateLock )
144  return;
145 
146  m_updateLock = true;
147 
148  wxInfoBarGeneric::Dismiss();
149 
150  if( m_auiManager )
151  UpdateAuiLayout( false );
152 
153  m_updateLock = false;
154 }
155 
156 
157 void WX_INFOBAR::UpdateAuiLayout( bool aShow )
158 {
159  wxASSERT( m_auiManager );
160 
161  wxAuiPaneInfo& pane = m_auiManager->GetPane( this );
162 
163  // If the infobar is in a pane, then show/hide the pane
164  if( pane.IsOk() )
165  {
166  if( aShow )
167  pane.Show();
168  else
169  pane.Hide();
170  }
171 
172  // Update the AUI manager regardless
173  m_auiManager->Update();
174 }
175 
176 
177 void WX_INFOBAR::AddButton( wxWindowID aId, const wxString& aLabel )
178 {
179  wxButton* button = new wxButton( this, aId, aLabel );
180 
181  AddButton( button );
182 }
183 
184 
185 void WX_INFOBAR::AddButton( wxButton* aButton )
186 {
187  wxSizer* sizer = GetSizer();
188 
189  wxASSERT( aButton );
190 
191 #ifdef __WXMAC__
192  // Based on the code in the original class:
193  // smaller buttons look better in the (narrow) info bar under OS X
194  aButton->SetWindowVariant( wxWINDOW_VARIANT_SMALL );
195 #endif // __WXMAC__
196  sizer->Add( aButton, wxSizerFlags().Centre().Border( wxRIGHT ) );
197 
198  if( IsShown() )
199  sizer->Layout();
200 }
201 
202 
203 void WX_INFOBAR::AddButton( wxHyperlinkCtrl* aHypertextButton )
204 {
205  wxSizer* sizer = GetSizer();
206 
207  wxASSERT( aHypertextButton );
208 
209  sizer->Add( aHypertextButton, wxSizerFlags().Centre().Border( wxRIGHT ) );
210 
211  if( IsShown() )
212  sizer->Layout();
213 }
214 
215 
216 void WX_INFOBAR::AddCloseButton( const wxString& aTooltip )
217 {
218  wxBitmapButton* button = wxBitmapButton::NewCloseButton( this, ID_CLOSE_INFOBAR );
219 
220  button->SetToolTip( aTooltip );
221 
222  AddButton( button );
223 }
224 
225 
227 {
228  wxSizer* sizer = GetSizer();
229 
230  if( sizer->GetItemCount() == 0 )
231  return;
232 
233  // The last item is already the spacer
234  if( sizer->GetItem( sizer->GetItemCount() - 1 )->IsSpacer() )
235  return;
236 
237  for( int i = sizer->GetItemCount() - 1; i >= 0; i-- )
238  {
239  wxSizerItem* sItem = sizer->GetItem( i );
240 
241  // The spacer is the end of the custom buttons
242  if( sItem->IsSpacer() )
243  break;
244 
245  delete sItem->GetWindow();
246  }
247 }
248 
249 
250 void WX_INFOBAR::OnShowInfoBar( wxCommandEvent& aEvent )
251 {
253  AddCloseButton();
254  ShowMessage( aEvent.GetString(), aEvent.GetInt() );
255 }
256 
257 
258 void WX_INFOBAR::OnDismissInfoBar( wxCommandEvent& aEvent )
259 {
260  Dismiss();
261 }
262 
263 
264 void WX_INFOBAR::OnCloseButton( wxCommandEvent& aEvent )
265 {
266  Dismiss();
267 }
268 
269 
270 void WX_INFOBAR::OnTimer( wxTimerEvent& aEvent )
271 {
272  // Reset and clear the timer
273  m_showTimer->Stop();
274  m_showTime = 0;
275 
276  Dismiss();
277 }
278 
279 
280 EDA_INFOBAR_PANEL::EDA_INFOBAR_PANEL( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos,
281  const wxSize& aSize, long aStyle, const wxString& aName )
282  : wxPanel( aParent, aId, aPos, aSize, aStyle, aName )
283 {
284  m_mainSizer = new wxFlexGridSizer( 1, 0, 0 );
285 
286  m_mainSizer->SetFlexibleDirection( wxBOTH );
287  m_mainSizer->AddGrowableCol( 0, 1 );
288 
289  SetSizer( m_mainSizer );
290 }
291 
292 
294 {
295  wxASSERT( aInfoBar );
296 
297  aInfoBar->Reparent( this );
298  m_mainSizer->Add( aInfoBar, 1, wxEXPAND, 0 );
299  m_mainSizer->Layout();
300 }
301 
302 
303 void EDA_INFOBAR_PANEL::AddOtherItem( wxWindow* aOtherItem )
304 {
305  wxASSERT( aOtherItem );
306 
307  aOtherItem->Reparent( this );
308  m_mainSizer->Add( aOtherItem, 1, wxEXPAND, 0 );
309 
310  m_mainSizer->AddGrowableRow( 1, 1 );
311  m_mainSizer->Layout();
312 }
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION)
Show the infobar with the provided message and icon for a specific period of time.
Definition: infobar.cpp:109
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: infobar.cpp:120
void AddButton(wxButton *aButton)
Add an already created button to the infobar.
Definition: infobar.cpp:185
wxTimer * m_showTimer
The timer counting the autoclose period.
Definition: infobar.h:211
void OnDismissInfoBar(wxCommandEvent &aEvent)
Event handler for dismissing the infobar using a wxCommandEvent of the type KIEVT_DISMISS_INFOBAR.
Definition: infobar.cpp:258
~WX_INFOBAR()
Definition: infobar.cpp:78
wxDEFINE_EVENT(KIEVT_SHOW_INFOBAR, wxCommandEvent)
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: infobar.cpp:140
void AddOtherItem(wxWindow *aOtherItem)
Add the other item to the panel.
Definition: infobar.cpp:303
ID for the close button on the frame's infobar.
Definition: infobar.h:36
void OnShowInfoBar(wxCommandEvent &aEvent)
Event handler for showing the infobar using a wxCommandEvent of the type KIEVT_SHOW_INFOBAR.
Definition: infobar.cpp:250
void OnTimer(wxTimerEvent &aEvent)
Event handler for the automatic closing timer.
Definition: infobar.cpp:270
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: infobar.cpp:226
void QueueShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION)
Send the infobar an event telling it to show a message.
Definition: infobar.cpp:90
A modified version of the wxInfoBar class that allows us to:
Definition: infobar.h:70
void SetShowTime(int aTime)
Set the time period to show the infobar.
Definition: infobar.cpp:84
void QueueDismiss()
Send the infobar an event telling it to hide itself.
Definition: infobar.cpp:101
void OnCloseButton(wxCommandEvent &aEvent)
Event handler for the close button.
Definition: infobar.cpp:264
wxFlexGridSizer * m_mainSizer
Definition: infobar.h:258
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: infobar.cpp:280
wxAuiManager * m_auiManager
The AUI manager that contains this infobar.
Definition: infobar.h:212
bool m_updateLock
True if this infobar requested the UI update.
Definition: infobar.h:210
void AddInfoBar(WX_INFOBAR *aInfoBar)
Add the given infobar object to the panel.
Definition: infobar.cpp:293
void UpdateAuiLayout(bool aShow)
Update the AUI pane to show or hide this infobar.
Definition: infobar.cpp:157
int m_showTime
The time to show the infobar. 0 = don't auto hide.
Definition: infobar.h:209
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: infobar.cpp:216