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 #ifndef INFOBAR_H_ 22 #define INFOBAR_H_ 23 24 #include <core/optional.h> 25 #include <wx/event.h> 26 #include <wx/infobar.h> 27 #include <wx/timer.h> 28 #include <wx/panel.h> 29 #include <wx/sizer.h> 30 31 32 class wxAuiManager; 33 class wxHyperlinkCtrl; 34 35 36 enum 37 { 38 /// ID for the close button on the frame's infobar 39 ID_CLOSE_INFOBAR = 2000, 40 }; 41 42 43 wxDECLARE_EVENT( KIEVT_SHOW_INFOBAR, wxCommandEvent ); 44 wxDECLARE_EVENT( KIEVT_DISMISS_INFOBAR, wxCommandEvent ); 45 46 /** 47 * A modified version of the wxInfoBar class that allows us to: 48 * * Show the close button along with the other buttons 49 * * Remove all user-provided buttons at once 50 * * Allow automatically hiding the infobar after a time period 51 * * Show/hide using events 52 * * Place it inside an AUI manager 53 * 54 * This inherits from the generic infobar because the native infobar 55 * on GTK doesn't include the icon on the left and it looks worse. 56 * 57 * There are 2 events associated with the infobar: 58 * 59 * KIEVT_SHOW_INFOBAR: 60 * An event that tells the infobar to show a message. 61 * 62 * The message text is contained inside the string component, 63 * and the message flag is contained inside the int component. 64 * 65 * Sample event creation code: 66 * wxCommandEvent* evt = new wxCommandEvent( KIEVT_SHOW_INFOBAR ); 67 * evt->SetString( "A message to show" ); 68 * evt->SetInt( wxICON_WARNING ); 69 * 70 * KIEVT_DISMISS_INFOBAR: 71 * An event that tells the infobar to hide itself. 72 */ 73 class WX_INFOBAR : public wxInfoBarGeneric 74 { 75 public: 76 /** 77 * Construct an infobar that can exist inside an AUI managed frame. 78 * 79 * @param aParent is the parent 80 * @param aMgr is the AUI manager that this infobar is added to 81 * @param aWinId is the ID for this infobar object 82 */ 83 WX_INFOBAR( wxWindow* aParent, wxAuiManager* aMgr = nullptr, wxWindowID aWinid = wxID_ANY ); 84 85 ~WX_INFOBAR(); 86 87 88 /** 89 * Sets the type of message for special handling if needed 90 */ 91 enum class MESSAGE_TYPE 92 { 93 GENERIC, /**< GENERIC Are messages that do not have special handling */ 94 OUTDATED_SAVE, /**< OUTDATED_SAVE Messages that should be cleared on save */ 95 DRC_RULES_ERROR, 96 DRC_VIOLATION 97 }; 98 GetMessageType()99 MESSAGE_TYPE GetMessageType() const { return m_type; } 100 101 /** 102 * Set the time period to show the infobar. 103 * 104 * This only applies for the next showing of the infobar, 105 * so it must be reset every time. A value of 0 disables 106 * the automatic hiding (this is the default). 107 * 108 * @param aTime is the time in milliseconds to show the infobar 109 */ 110 void SetShowTime( int aTime ); 111 112 /** 113 * Add the default close button to the infobar on the right side. 114 * 115 * @param aTooltip is the tooltip to give the close button 116 */ 117 void AddCloseButton( const wxString& aTooltip = _( "Hide this message." ) ); 118 119 /** 120 * Add an already created button to the infobar. 121 * New buttons are added in the right-most position. 122 * 123 * @param aButton is the button to add 124 */ 125 void AddButton( wxButton* aButton ); 126 127 /** 128 * Add an already created hypertext link to the infobar. 129 * New buttons are added in the right-most position. 130 * 131 * @param aHypertextButton is the button to add 132 */ 133 void AddButton( wxHyperlinkCtrl* aHypertextButton ); 134 135 /** 136 * Add a button with the provided ID and text. 137 * The new button is created on the right-most position. 138 * 139 * @param aId is the ID to assign to the button 140 * @param aLabel is the text for the button 141 */ 142 void AddButton( wxWindowID aId, const wxString& aLabel = wxEmptyString ) override; 143 144 /** 145 * Remove all the buttons that have been added by the user. 146 */ 147 void RemoveAllButtons(); 148 149 bool HasCloseButton() const; 150 151 /** 152 * Provide a callback to be called when the infobar is dismissed (either by user action 153 * or timer). 154 * @param aCallback 155 */ SetCallback(std::function<void (void)> aCallback)156 void SetCallback( std::function<void(void)> aCallback ) 157 { 158 m_callback = aCallback; 159 } 160 161 /** 162 * Show the infobar with the provided message and icon for a specific period 163 * of time. 164 * 165 * @param aMessage is the message to display 166 * @param aTime is the amount of time in milliseconds to show the infobar 167 * @param aFlags is the flag containing the icon to display on the left side of the infobar 168 */ 169 void ShowMessageFor( const wxString& aMessage, int aTime, int aFlags = wxICON_INFORMATION, 170 MESSAGE_TYPE aType = WX_INFOBAR::MESSAGE_TYPE::GENERIC ); 171 172 /** 173 * Show the info bar with the provided message and icon. 174 * 175 * @param aMessage is the message to display 176 * @param aFlags is the flag containing the icon to display on the left side of the infobar 177 */ 178 void ShowMessage( const wxString& aMessage, int aFlags = wxICON_INFORMATION ) override; 179 180 /** 181 * Show the info bar with the provided message and icon, setting the type 182 * 183 * @param aMessage is the message to display 184 * @param aFlags is the flag containing the icon to display on the left side of the infobar 185 * @param aType is the type of message being displayed 186 */ 187 void ShowMessage( const wxString& aMessage, int aFlags, MESSAGE_TYPE aType ); 188 189 /** 190 * Dismisses the infobar and updates the containing layout and AUI manager 191 * (if one is provided). 192 */ 193 void Dismiss() override; 194 195 /** 196 * Send the infobar an event telling it to show a message. 197 * 198 * @param aMessage is the message to display 199 * @param aFlags is the flag containing the icon to display on the left side of the infobar 200 */ 201 void QueueShowMessage( const wxString& aMessage, int aFlags = wxICON_INFORMATION ); 202 203 /** 204 * Send the infobar an event telling it to hide itself. 205 */ 206 void QueueDismiss(); 207 208 /** 209 * Returns true if the infobar is being updated. 210 */ IsLocked()211 bool IsLocked() 212 { 213 return m_updateLock; 214 } 215 216 protected: 217 /** 218 * Event handler for showing the infobar using a wxCommandEvent of the type 219 * KIEVT_SHOW_INFOBAR. The message is stored inside the string field, and the 220 * icon flag is stored inside the int field. 221 */ 222 void onShowInfoBar( wxCommandEvent& aEvent ); 223 224 /** 225 * Event handler for dismissing the infobar using a wxCommandEvent of the type 226 * KIEVT_DISMISS_INFOBAR. 227 */ 228 void onDismissInfoBar( wxCommandEvent& aEvent ); 229 230 /** 231 * Event handler for the close button. 232 * This is bound to ID_CLOSE_INFOBAR on the infobar. 233 */ 234 void onCloseButton( wxCommandEvent& aEvent ); 235 236 /** 237 * Event handler for the automatic closing timer. 238 */ 239 void onTimer( wxTimerEvent& aEvent ); 240 241 void onSize( wxSizeEvent& aEvent ); 242 243 /** 244 * Update the AUI pane to show or hide this infobar. 245 * 246 * @param aShow is true to show the pane 247 */ 248 void updateAuiLayout( bool aShow ); 249 250 protected: 251 int m_showTime; ///< The time to show the infobar. 0 = don't auto hide 252 bool m_updateLock; ///< True if this infobar requested the UI update 253 wxTimer* m_showTimer; ///< The timer counting the autoclose period 254 wxAuiManager* m_auiManager; ///< The AUI manager that contains this infobar 255 MESSAGE_TYPE m_type; ///< The type of message being displayed 256 257 OPT<std::function<void(void)>> m_callback; ///< Optional callback made when closing infobar 258 259 DECLARE_EVENT_TABLE() 260 }; 261 262 263 /** 264 * A wxPanel derived class that hold an infobar and another control. 265 * The infobar is located at the top of the panel, and the other control 266 * is located below it. 267 * 268 * This allows the infobar to be controlled nicely by an AUI manager, 269 * since adding the infobar on its own to the AUI manager produces 270 * artifacts when showing/hiding it due to the AUI pane layout. 271 * 272 * Note that this implementation currently has issues on Windows with 273 * event processing inside the GAL canvas, see: 274 * https://gitlab.com/kicad/code/kicad/-/issues/4501 275 * 276 */ 277 class EDA_INFOBAR_PANEL : public wxPanel 278 { 279 public: 280 EDA_INFOBAR_PANEL( wxWindow* aParent, wxWindowID aId = wxID_ANY, 281 const wxPoint& aPos = wxDefaultPosition, 282 const wxSize& aSize = wxSize( -1,-1 ), 283 long aStyle = wxTAB_TRAVERSAL, 284 const wxString& aName = wxEmptyString ); 285 286 /** 287 * Add the given infobar object to the panel 288 * 289 * @param aInfoBar is the infobar to add 290 */ 291 void AddInfoBar( WX_INFOBAR* aInfoBar ); 292 293 /** 294 * Add the other item to the panel. 295 * This item will expand to fill up the vertical space left. 296 * 297 * @param aOtherItem is the item to add 298 */ 299 void AddOtherItem( wxWindow* aOtherItem ); 300 301 protected: 302 // The sizer containing the infobar and the other object 303 wxFlexGridSizer* m_mainSizer; 304 }; 305 306 #endif // INFOBAR_H_ 307