1 /* 2 * This program source code file is part of KiCad, a free EDA CAD application. 3 * 4 * Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com> 5 * Copyright (C) 2013-2021 KiCad Developers, see AUTHORS.txt for contributors. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, you may find one here: 19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 20 * or you may search the http://www.gnu.org website for the version 2 license, 21 * or you may write to the Free Software Foundation, Inc., 22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 23 */ 24 25 #ifndef _REPORTER_H_ 26 #define _REPORTER_H_ 27 28 #include <memory> 29 30 #include <eda_units.h> 31 #include <widgets/report_severity.h> 32 33 /** 34 * @file reporter.h 35 * @author Wayne Stambaugh 36 * @note A special thanks to Dick Hollenbeck who came up with the idea that inspired 37 * me to write this. 38 * @warning Do not add any dependencies to wxWidgets (or any other third party UI library ) 39 * to the REPORTER object. All wxWidgets objects should be defined by pointer or 40 * reference and forward declared so that using reporters in low level KiCad objects 41 * will not require pulling in wxWidgets to building them. 42 */ 43 44 class wxString; 45 class wxStatusBar; 46 class wxTextCtrl; 47 class WX_HTML_REPORT_PANEL; 48 class WX_INFOBAR; 49 50 51 /** 52 * A pure virtual class used to derive REPORTER objects from. 53 * 54 * The purpose of the REPORTER object is to offer a way for a procedural function 55 * to report multiple errors without having to: 56 * <ul> 57 * <li> know too much about the caller's UI, i.e. wx. </li> 58 * <li> stop after the first error </li> 59 * </ul> 60 * the reporter has 4 severity levels (flags) tagging the messages: 61 * - information 62 * - warning 63 * - error 64 * - action (i.e. indication of changes - add component, change footprint, etc. ) 65 * 66 * They are indicators for the message formatting and displaying code, 67 * filtering is not made here. 68 */ 69 70 class REPORTER 71 { 72 public: 73 /** 74 * Location where the message is to be reported. 75 * LOC_HEAD messages are printed before all others (typically intro messages) 76 * LOC_BODY messages are printed in the middle 77 * LOC_TAIL messages are printed after all others (typically status messages) 78 */ 79 enum LOCATION { 80 LOC_HEAD = 0, 81 LOC_BODY, 82 LOC_TAIL 83 }; 84 85 /** 86 * Report a string with a given severity. 87 * 88 * @param aText is the string to report. 89 * @param aSeverity is an indicator ( RPT_UNDEFINED, RPT_INFO, RPT_WARNING, RPT_ERROR, 90 * RPT_ACTION ) used to filter and format messages 91 */ 92 93 virtual REPORTER& Report( const wxString& aText, 94 SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) = 0; 95 96 /** 97 * Places the report at the end of the list, for objects that support report ordering 98 */ 99 virtual REPORTER& ReportTail( const wxString& aText, 100 SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) 101 { 102 return Report( aText, aSeverity ); 103 } 104 105 /** 106 * Places the report at the beginning of the list for objects that support ordering. 107 */ 108 virtual REPORTER& ReportHead( const wxString& aText, 109 SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) 110 { 111 return Report( aText, aSeverity ); 112 } 113 114 REPORTER& Report( const char* aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ); 115 116 REPORTER& operator <<( const wxString& aText ) { return Report( aText ); } 117 118 /** 119 * Returns true if the reporter client is non-empty. 120 */ 121 virtual bool HasMessage() const = 0; 122 GetUnits()123 virtual EDA_UNITS GetUnits() const 124 { 125 return EDA_UNITS::MILLIMETRES; 126 } 127 ~REPORTER()128 virtual ~REPORTER() 129 { 130 } 131 }; 132 133 134 /** 135 * A wrapper for reporting to a wxTextCtrl object. 136 */ 137 class WX_TEXT_CTRL_REPORTER : public REPORTER 138 { 139 public: WX_TEXT_CTRL_REPORTER(wxTextCtrl * aTextCtrl)140 WX_TEXT_CTRL_REPORTER( wxTextCtrl* aTextCtrl ) : 141 REPORTER(), 142 m_textCtrl( aTextCtrl ) 143 { 144 } 145 ~WX_TEXT_CTRL_REPORTER()146 virtual ~WX_TEXT_CTRL_REPORTER() 147 { 148 } 149 150 REPORTER& Report( const wxString& aText, 151 SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; 152 153 bool HasMessage() const override; 154 155 private: 156 wxTextCtrl* m_textCtrl; 157 }; 158 159 160 /** 161 * A wrapper for reporting to a wxString object. 162 */ 163 class WX_STRING_REPORTER : public REPORTER 164 { 165 public: WX_STRING_REPORTER(wxString * aString)166 WX_STRING_REPORTER( wxString* aString ) : 167 REPORTER(), 168 m_string( aString ) 169 { 170 } 171 ~WX_STRING_REPORTER()172 virtual ~WX_STRING_REPORTER() 173 { 174 } 175 176 REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; 177 178 bool HasMessage() const override; 179 180 private: 181 wxString* m_string; 182 }; 183 184 185 /** 186 * A wrapper for reporting to a wx HTML window. 187 */ 188 class WX_HTML_PANEL_REPORTER : public REPORTER 189 { 190 public: WX_HTML_PANEL_REPORTER(WX_HTML_REPORT_PANEL * aPanel)191 WX_HTML_PANEL_REPORTER( WX_HTML_REPORT_PANEL* aPanel ) : 192 REPORTER(), 193 m_panel( aPanel ) 194 { 195 } 196 ~WX_HTML_PANEL_REPORTER()197 virtual ~WX_HTML_PANEL_REPORTER() 198 { 199 } 200 201 REPORTER& Report( const wxString& aText, 202 SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; 203 204 REPORTER& ReportTail( const wxString& aText, 205 SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; 206 207 REPORTER& ReportHead( const wxString& aText, 208 SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; 209 210 bool HasMessage() const override; 211 212 private: 213 WX_HTML_REPORT_PANEL* m_panel; 214 }; 215 216 217 /** 218 * A singleton reporter that reports to nowhere. 219 * 220 * Used as to simplify code by avoiding the reportee to check for a non-NULL reporter object. 221 */ 222 class NULL_REPORTER : public REPORTER 223 { 224 public: NULL_REPORTER()225 NULL_REPORTER() 226 { 227 } 228 ~NULL_REPORTER()229 virtual ~NULL_REPORTER() 230 { 231 } 232 233 static REPORTER& GetInstance(); 234 235 REPORTER& Report( const wxString& aText, 236 SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; 237 HasMessage()238 bool HasMessage() const override { return false; } 239 }; 240 241 242 /** 243 * Debug type reporter, forwarding messages to std::cout. 244 */ 245 class STDOUT_REPORTER : public REPORTER 246 { 247 public: STDOUT_REPORTER()248 STDOUT_REPORTER() 249 { 250 } 251 ~STDOUT_REPORTER()252 virtual ~STDOUT_REPORTER() 253 { 254 } 255 256 static REPORTER& GetInstance(); 257 258 REPORTER& Report( const wxString& aMsg, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; 259 HasMessage()260 bool HasMessage() const override { return false; } 261 }; 262 263 264 class WXLOG_REPORTER : public REPORTER 265 { 266 public: WXLOG_REPORTER()267 WXLOG_REPORTER() 268 { 269 } 270 ~WXLOG_REPORTER()271 virtual ~WXLOG_REPORTER() 272 { 273 } 274 275 static REPORTER& GetInstance(); 276 277 REPORTER& Report( const wxString& aMsg, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; 278 HasMessage()279 bool HasMessage() const override { return false; } 280 }; 281 282 283 /** 284 * A wrapper for reporting to a specific text location in a statusbar. 285 */ 286 class STATUSBAR_REPORTER : public REPORTER 287 { 288 public: 289 STATUSBAR_REPORTER( wxStatusBar* aStatusBar, int aPosition = 0 ) REPORTER()290 : REPORTER(), 291 m_statusBar( aStatusBar ), 292 m_position( aPosition ) 293 { 294 } 295 296 REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; 297 298 bool HasMessage() const override; 299 300 private: 301 wxStatusBar* m_statusBar; 302 int m_position; 303 }; 304 305 306 /** 307 * A wrapper for reporting to a #WX_INFOBAR UI element. 308 * 309 * The infobar is not updated until the @c Finalize() method is called. That method will 310 * queue either a show message or a dismiss event for the infobar - so this reporter is 311 * safe to use inside a paint event without causing an infinite paint event loop. 312 * 313 * No action is taken if no message is given to the reporter. 314 */ 315 class INFOBAR_REPORTER : public REPORTER 316 { 317 public: INFOBAR_REPORTER(WX_INFOBAR * aInfoBar)318 INFOBAR_REPORTER( WX_INFOBAR* aInfoBar ) 319 : REPORTER(), 320 m_messageSet( false ), 321 m_infoBar( aInfoBar ), 322 m_severity( RPT_SEVERITY_UNDEFINED ) 323 { 324 } 325 326 virtual ~INFOBAR_REPORTER(); 327 328 REPORTER& Report( const wxString& aText, 329 SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override; 330 331 bool HasMessage() const override; 332 333 /** 334 * Update the infobar with the reported text. 335 */ 336 void Finalize(); 337 338 private: 339 bool m_messageSet; 340 WX_INFOBAR* m_infoBar; 341 std::unique_ptr<wxString> m_message; 342 SEVERITY m_severity; 343 }; 344 345 #endif // _REPORTER_H_ 346