]> git.saurik.com Git - wxWidgets.git/commitdiff
made wxLogGui more flexible and documented it and added example of customizing it...
authorVadim Zeitlin <vadim@wxwidgets.org>
Thu, 11 Sep 2008 13:58:54 +0000 (13:58 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Thu, 11 Sep 2008 13:58:54 +0000 (13:58 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55552 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/doxygen/overviews/log.h
include/wx/generic/logg.h
samples/dialogs/dialogs.cpp
samples/dialogs/dialogs.h
src/generic/logg.cpp

index c7c4a69caa6679935659bc01c4327b9cff7bbb4b..048f291d39101713d8d36cee04612a21d814cd10 100644 (file)
@@ -24,6 +24,13 @@ Classes:
 @li wxLogInterposerTemp
 @li wxStreamToTextRedirector
 
+@li @ref overview_log_introduction
+@li @ref overview_log_targets
+@li @ref overview_log_customize
+
+
+@section overview_log_introduction Introduction
+
 This is a general overview of logging classes provided by wxWidgets. The word
 logging here has a broad sense, including all of the program output, not only
 non-interactive messages. The logging facilities included in wxWidgets provide
@@ -108,6 +115,9 @@ classes are. Some of advantages in using wxWidgets log functions are:
     error message) will be given to the user together with "high level" message
     about data file writing error.
 
+
+@section overview_log_targets Log Targets
+
 After having enumerated all the functions which are normally used to log the
 messages, and why would you want to use them we now describe how all this
 works.
@@ -170,5 +180,27 @@ messages somewhere else (for example, to a log file) but also process them as
 normally. For this the wxLogChain, wxLogInterposer, and wxLogInterposerTemp can
 be used.
 
+
+@section overview_log_customize Logging Customization
+
+To completely change the logging behaviour you may define a custom log target.
+For example, you could define a class inheriting from wxLog which shows all the
+log messages in some part of your main application window reserved for the
+message output without interrupting the user work flow with modal message
+boxes.
+
+To use your custom log target you may either call wxLog::SetActiveTarget() with
+your custom log object or create a wxAppTraits-derived class and override
+CreateLogTarget() virtual method in it and also override wxApp::CreateTraits()
+to return an instance of your custom traits object. Notice that in the latter
+case you should be prepared for logging messages early during the program
+startup and also during program shutdown so you shouldn't rely on existence of
+the main application window, for example. You can however safely assume that
+GUI is (already/still) available when your log target as used as wxWidgets
+automatically switches to using wxLogStderr if it isn't.
+
+The dialog sample illustrates this approach by defining a custom log target
+customizing the dialog used by wxLogGui for the single messages.
+
 */
 
index 02273173231aba0ec4b1a135e608dde33a9a9d51..269c65921ad9d8a75994e45ef77f7a03975e6461 100644 (file)
@@ -63,9 +63,18 @@ protected:
 
     wxSUPPRESS_DOLOG_HIDE_WARNING()
 
+    // return the title to be used for the log dialog, depending on m_bErrors
+    // and m_bWarnings values
+    wxString GetTitle() const;
+
+    // return the icon (one of wxICON_XXX constants) to be used for the dialog
+    // depending on m_bErrors/m_bWarnings
+    int GetSeverityIcon() const;
+
     // empty everything
     void Clear();
 
+
     wxArrayString m_aMessages;      // the log message texts
     wxArrayInt    m_aSeverity;      // one of wxLOG_XXX values
     wxArrayLong   m_aTimes;         // the time of each message
@@ -73,6 +82,19 @@ protected:
                   m_bWarnings,      // any warnings?
                   m_bHasMessages;   // any messages at all?
 
+private:
+    // this method is called to show a single log message, it uses
+    // wxMessageBox() by default
+    virtual void DoShowSingleLogMessage(const wxString& message,
+                                        const wxString& title,
+                                        int style);
+
+    // this method is called to show multiple log messages, it uses wxLogDialog
+    virtual void DoShowMultipleLogMessages(const wxArrayString& messages,
+                                           const wxArrayInt& severities,
+                                           const wxArrayLong& times,
+                                           const wxString& title,
+                                           int style);
 };
 
 #endif // wxUSE_LOGGUI
index 754945495698005dcb8730922d3558a3e0df30a7..d0e24dea0976b85a63b3e0b2f8dd0ff343086101 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "../sample.xpm"
 
+#include "wx/apptrait.h"
 #include "wx/datetime.h"
 #include "wx/image.h"
 #include "wx/bookctrl.h"
     #include "wx/fdrepdlg.h"
 #endif // wxUSE_FINDREPLDLG
 
-#if wxUSE_SPINCTRL
 #include "wx/spinctrl.h"
-#endif
-
 #include "wx/propdlg.h"
 
 #include "dialogs.h"
@@ -2327,3 +2325,29 @@ void TestMessageBoxDialog::OnClose(wxCommandEvent& WXUNUSED(event))
 }
 
 #endif // USE_SETTINGS_DIALOG
+
+#if wxUSE_LOG
+
+// ----------------------------------------------------------------------------
+// custom log target
+// ----------------------------------------------------------------------------
+
+class MyLogGui : public wxLogGui
+{
+private:
+    virtual void DoShowSingleLogMessage(const wxString& message,
+                                        const wxString& title,
+                                        int style)
+    {
+        wxMessageDialog dlg(NULL, message, title, wxOK | style);
+        dlg.SetExtendedMessage("Note that this is a custom log dialog.");
+        dlg.ShowModal();
+    }
+};
+
+wxLog *MyAppTraits::CreateLogTarget()
+{
+    return new MyLogGui;
+}
+
+#endif // wxUSE_LOG
index 7be46aaf50ef19d800741ae5a9847c03e7995d74..ad8956acfb7041c8e5f0a6cc9411e146194790fa 100644 (file)
@@ -98,15 +98,31 @@ of MSW, MAC and OS2
     #define USE_SETTINGS_DIALOG 0
 #endif
 
+#if wxUSE_LOG
+
+// Custom application traits class which we use to override the default log
+// target creation
+class MyAppTraits : public wxGUIAppTraits
+{
+public:
+    virtual wxLog *CreateLogTarget();
+};
+
+#endif // wxUSE_LOG
 
 // Define a new application type
 class MyApp: public wxApp
 {
 public:
-    bool OnInit();
+    virtual bool OnInit();
 
     wxFont       m_canvasFont;
     wxColour     m_canvasTextColour;
+
+protected:
+#if wxUSE_LOG
+    virtual wxAppTraits *CreateTraits() { return new MyAppTraits; }
+#endif // wxUSE_LOG
 };
 
 #if USE_MODAL_PRESENTATION
index f0c18bb999c7d6324906bdd78617a1e3e5a612a6..80aab72d473abe71b372c27b542c38a55524dbdb 100644 (file)
@@ -281,6 +281,74 @@ void wxLogGui::Clear()
     m_aTimes.Empty();
 }
 
+int wxLogGui::GetSeverityIcon() const
+{
+    return m_bErrors ? wxICON_STOP
+                     : m_bWarnings ? wxICON_EXCLAMATION
+                                   : wxICON_INFORMATION;
+}
+
+wxString wxLogGui::GetTitle() const
+{
+    wxString titleFormat;
+    switch ( GetSeverityIcon() )
+    {
+        case wxICON_STOP:
+            titleFormat = _("%s Error");
+            break;
+
+        case wxICON_EXCLAMATION:
+            titleFormat = _("%s Warning");
+            break;
+
+        default:
+            wxFAIL_MSG( "unexpected icon severity" );
+            // fall through
+
+        case wxICON_INFORMATION:
+            titleFormat = _("%s Information");
+    }
+
+    return wxString::Format(titleFormat, wxTheApp->GetAppDisplayName());
+}
+
+void
+wxLogGui::DoShowSingleLogMessage(const wxString& message,
+                                 const wxString& title,
+                                 int style)
+{
+    wxMessageBox(message, title, wxOK | style);
+}
+
+void
+wxLogGui::DoShowMultipleLogMessages(const wxArrayString& messages,
+                                    const wxArrayInt& severities,
+                                    const wxArrayLong& times,
+                                    const wxString& title,
+                                    int style)
+{
+#if wxUSE_LOG_DIALOG
+    wxLogDialog dlg(NULL,
+                    messages, severities, times,
+                    title, style);
+
+    // clear the message list before showing the dialog because while it's
+    // shown some new messages may appear
+    Clear();
+
+    (void)dlg.ShowModal();
+#else // !wxUSE_LOG_DIALOG
+    // start from the most recent message
+    wxString message;
+    str.reserve(nMsgCount*100);
+    for ( size_t n = nMsgCount; n > 0; n-- ) {
+        message << m_aMessages[n - 1] << wxT("\n");
+    }
+
+    DoShowSingleLogMessage(message, title, style);
+#endif // wxUSE_LOG_DIALOG/!wxUSE_LOG_DIALOG
+}
+
 void wxLogGui::Flush()
 {
     if ( !m_bHasMessages )
@@ -289,85 +357,45 @@ void wxLogGui::Flush()
     // do it right now to block any new calls to Flush() while we're here
     m_bHasMessages = false;
 
+    // note that this must be done before examining m_aMessages as it may log
+    // yet another message
     const unsigned repeatCount = LogLastRepeatIfNeeded();
 
-    wxString appName = wxTheApp->GetAppDisplayName();
+    const size_t nMsgCount = m_aMessages.size();
 
-    long style;
-    wxString titleFormat;
-    if ( m_bErrors ) {
-        titleFormat = _("%s Error");
-        style = wxICON_STOP;
-    }
-    else if ( m_bWarnings ) {
-        titleFormat = _("%s Warning");
-        style = wxICON_EXCLAMATION;
-    }
-    else {
-        titleFormat = _("%s Information");
-        style = wxICON_INFORMATION;
+    if ( repeatCount > 0 )
+    {
+        m_aMessages[nMsgCount - 1] << " (" << m_aMessages[nMsgCount - 2] << ")";
     }
 
-    wxString title;
-    title.Printf(titleFormat, appName.c_str());
-
-    size_t nMsgCount = m_aMessages.GetCount();
+    const wxString title = GetTitle();
+    const int style = GetSeverityIcon();
 
     // avoid showing other log dialogs until we're done with the dialog we're
     // showing right now: nested modal dialogs make for really bad UI!
     Suspend();
 
-    wxString str;
     if ( nMsgCount == 1 )
     {
-        str = m_aMessages[0];
+        // make a copy before calling Clear()
+        const wxString message(m_aMessages[0]);
+        Clear();
+
+        DoShowSingleLogMessage(message, title, style);
     }
     else // more than one message
     {
-#if wxUSE_LOG_DIALOG
-
-        if ( repeatCount > 0 )
-        {
-            m_aMessages[nMsgCount - 1]
-                << " (" << m_aMessages[nMsgCount - 2] << ")";
-        }
+        wxArrayString messages;
+        wxArrayInt severities;
+        wxArrayLong times;
 
-        wxLogDialog dlg(NULL,
-                        m_aMessages, m_aSeverity, m_aTimes,
-                        title, style);
+        messages.swap(m_aMessages);
+        severities.swap(m_aSeverity);
+        times.swap(m_aTimes);
 
-        // clear the message list before showing the dialog because while it's
-        // shown some new messages may appear
         Clear();
 
-        (void)dlg.ShowModal();
-#else // !wxUSE_LOG_DIALOG
-        // concatenate all strings (but not too many to not overfill the msg box)
-        size_t nLines = 0;
-
-        // start from the most recent message
-        for ( size_t n = nMsgCount; n > 0; n-- ) {
-            // for Windows strings longer than this value are wrapped (NT 4.0)
-            const size_t nMsgLineWidth = 156;
-
-            nLines += (m_aMessages[n - 1].Len() + nMsgLineWidth - 1) / nMsgLineWidth;
-
-            if ( nLines > 25 )  // don't put too many lines in message box
-                break;
-
-            str << m_aMessages[n - 1] << wxT("\n");
-        }
-#endif // wxUSE_LOG_DIALOG/!wxUSE_LOG_DIALOG
-    }
-
-    // this catches both cases of 1 message with wxUSE_LOG_DIALOG and any
-    // situation without it
-    if ( !str.empty() )
-    {
-        wxMessageBox(str, title, wxOK | style);
-
-        // no undisplayed messages whatsoever
-        Clear();
+        DoShowMultipleLogMessages(messages, severities, times, title, style);
     }
 
     // allow flushing the logs again