You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
7.1 KiB

  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. #include <id.h>
  21. #include <widgets/infobar.h>
  22. #include "wx/artprov.h"
  23. #include <wx/aui/framemanager.h>
  24. #include <wx/debug.h>
  25. #include <wx/infobar.h>
  26. #include <wx/sizer.h>
  27. #include <wx/timer.h>
  28. wxDEFINE_EVENT( KIEVT_SHOW_INFOBAR, wxCommandEvent );
  29. wxDEFINE_EVENT( KIEVT_DISMISS_INFOBAR, wxCommandEvent );
  30. BEGIN_EVENT_TABLE( WX_INFOBAR, wxInfoBarGeneric )
  31. EVT_COMMAND( wxID_ANY, KIEVT_SHOW_INFOBAR, WX_INFOBAR::OnShowInfoBar )
  32. EVT_COMMAND( wxID_ANY, KIEVT_DISMISS_INFOBAR, WX_INFOBAR::OnDismissInfoBar )
  33. EVT_BUTTON( ID_CLOSE_INFOBAR, WX_INFOBAR::OnCloseButton )
  34. EVT_TIMER( ID_CLOSE_INFOBAR, WX_INFOBAR::OnTimer )
  35. END_EVENT_TABLE()
  36. WX_INFOBAR::WX_INFOBAR( wxWindow* aParent, wxAuiManager* aMgr, wxWindowID aWinid )
  37. : wxInfoBarGeneric( aParent, aWinid ),
  38. m_showTime( 0 ),
  39. m_updateLock( false ),
  40. m_showTimer( nullptr ),
  41. m_auiManager( aMgr )
  42. {
  43. m_showTimer = new wxTimer( this, ID_CLOSE_INFOBAR );
  44. // Don't use any effects since they leave the sizer area visible under the infobar
  45. SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE );
  46. // The infobar seems to start too small, so increase its height
  47. int sx, sy;
  48. GetSize( &sx, &sy );
  49. sy = 1.5 * sy;
  50. SetSize( sx, sy );
  51. // The bitmap gets cutoff sometimes with the default size, so force it to be the same
  52. // height as the infobar.
  53. wxSizer* sizer = GetSizer();
  54. wxSize iconSize = wxArtProvider::GetSizeHint( wxART_BUTTON );
  55. sizer->SetItemMinSize( (size_t) 0, iconSize.x, sy );
  56. // Forcefully remove all existing buttons added by the wx constructors.
  57. // The default close button doesn't work with the AUI manager update scheme, so this
  58. // ensures any close button displayed is ours.
  59. RemoveAllButtons();
  60. Layout();
  61. }
  62. WX_INFOBAR::~WX_INFOBAR()
  63. {
  64. delete m_showTimer;
  65. }
  66. void WX_INFOBAR::SetShowTime( int aTime )
  67. {
  68. m_showTime = aTime;
  69. }
  70. void WX_INFOBAR::QueueShowMessage( const wxString& aMessage, int aFlags )
  71. {
  72. wxCommandEvent* evt = new wxCommandEvent( KIEVT_SHOW_INFOBAR );
  73. evt->SetString( aMessage.c_str() );
  74. evt->SetInt( aFlags );
  75. GetEventHandler()->QueueEvent( evt );
  76. }
  77. void WX_INFOBAR::QueueDismiss()
  78. {
  79. wxCommandEvent* evt = new wxCommandEvent( KIEVT_DISMISS_INFOBAR );
  80. GetEventHandler()->QueueEvent( evt );
  81. }
  82. void WX_INFOBAR::ShowMessageFor( const wxString& aMessage, int aTime, int aFlags )
  83. {
  84. // Don't do anything if we requested the UI update
  85. if( m_updateLock )
  86. return;
  87. m_showTime = aTime;
  88. ShowMessage( aMessage, aFlags );
  89. }
  90. void WX_INFOBAR::ShowMessage( const wxString& aMessage, int aFlags )
  91. {
  92. // Don't do anything if we requested the UI update
  93. if( m_updateLock )
  94. return;
  95. m_updateLock = true;
  96. wxInfoBarGeneric::ShowMessage( aMessage, aFlags );
  97. if( m_auiManager )
  98. UpdateAuiLayout( true );
  99. if( m_showTime > 0 )
  100. m_showTimer->StartOnce( m_showTime );
  101. m_updateLock = false;
  102. }
  103. void WX_INFOBAR::Dismiss()
  104. {
  105. // Don't do anything if we requested the UI update
  106. if( m_updateLock )
  107. return;
  108. m_updateLock = true;
  109. wxInfoBarGeneric::Dismiss();
  110. if( m_auiManager )
  111. UpdateAuiLayout( false );
  112. m_updateLock = false;
  113. }
  114. void WX_INFOBAR::UpdateAuiLayout( bool aShow )
  115. {
  116. wxASSERT( m_auiManager );
  117. wxAuiPaneInfo& pane = m_auiManager->GetPane( this );
  118. // If the infobar is in a pane, then show/hide the pane
  119. if( pane.IsOk() )
  120. {
  121. if( aShow )
  122. pane.Show();
  123. else
  124. pane.Hide();
  125. }
  126. // Update the AUI manager regardless
  127. m_auiManager->Update();
  128. }
  129. void WX_INFOBAR::AddButton( wxWindowID aId, const wxString& aLabel )
  130. {
  131. wxButton* button = new wxButton( this, aId, aLabel );
  132. AddButton( button );
  133. }
  134. void WX_INFOBAR::AddButton( wxButton* aButton )
  135. {
  136. wxSizer* sizer = GetSizer();
  137. wxASSERT( aButton );
  138. #ifdef __WXMAC__
  139. // Based on the code in the original class:
  140. // smaller buttons look better in the (narrow) info bar under OS X
  141. aButton->SetWindowVariant( wxWINDOW_VARIANT_SMALL );
  142. #endif // __WXMAC__
  143. sizer->Add( aButton, wxSizerFlags().Centre().Border( wxRIGHT ) );
  144. if( IsShown() )
  145. sizer->Layout();
  146. }
  147. void WX_INFOBAR::AddCloseButton( const wxString& aTooltip )
  148. {
  149. wxBitmapButton* button = wxBitmapButton::NewCloseButton( this, ID_CLOSE_INFOBAR );
  150. button->SetToolTip( aTooltip );
  151. AddButton( button );
  152. }
  153. void WX_INFOBAR::RemoveAllButtons()
  154. {
  155. wxSizer* sizer = GetSizer();
  156. if( sizer->GetItemCount() == 0 )
  157. return;
  158. // The last item is already the spacer
  159. if( sizer->GetItem( sizer->GetItemCount() - 1 )->IsSpacer() )
  160. return;
  161. for( int i = sizer->GetItemCount() - 1; i >= 0; i-- )
  162. {
  163. wxSizerItem* sItem = sizer->GetItem( i );
  164. // The spacer is the end of the custom buttons
  165. if( sItem->IsSpacer() )
  166. break;
  167. delete sItem->GetWindow();
  168. }
  169. }
  170. void WX_INFOBAR::OnShowInfoBar( wxCommandEvent& aEvent )
  171. {
  172. RemoveAllButtons();
  173. AddCloseButton();
  174. ShowMessage( aEvent.GetString(), aEvent.GetInt() );
  175. }
  176. void WX_INFOBAR::OnDismissInfoBar( wxCommandEvent& aEvent )
  177. {
  178. Dismiss();
  179. }
  180. void WX_INFOBAR::OnCloseButton( wxCommandEvent& aEvent )
  181. {
  182. Dismiss();
  183. }
  184. void WX_INFOBAR::OnTimer( wxTimerEvent& aEvent )
  185. {
  186. // Reset and clear the timer
  187. m_showTimer->Stop();
  188. m_showTime = 0;
  189. Dismiss();
  190. }
  191. EDA_INFOBAR_PANEL::EDA_INFOBAR_PANEL( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos,
  192. const wxSize& aSize, long aStyle, const wxString& aName )
  193. : wxPanel( aParent, aId, aPos, aSize, aStyle, aName )
  194. {
  195. m_mainSizer = new wxFlexGridSizer( 1, 0, 0 );
  196. m_mainSizer->SetFlexibleDirection( wxBOTH );
  197. m_mainSizer->AddGrowableCol( 0, 1 );
  198. SetSizer( m_mainSizer );
  199. }
  200. void EDA_INFOBAR_PANEL::AddInfoBar( WX_INFOBAR* aInfoBar )
  201. {
  202. wxASSERT( aInfoBar );
  203. aInfoBar->Reparent( this );
  204. m_mainSizer->Add( aInfoBar, 1, wxEXPAND, 0 );
  205. m_mainSizer->Layout();
  206. }
  207. void EDA_INFOBAR_PANEL::AddOtherItem( wxWindow* aOtherItem )
  208. {
  209. wxASSERT( aOtherItem );
  210. aOtherItem->Reparent( this );
  211. m_mainSizer->Add( aOtherItem, 1, wxEXPAND, 0 );
  212. m_mainSizer->AddGrowableRow( 1, 1 );
  213. m_mainSizer->Layout();
  214. }