made wxLogGui more flexible and documented it and added example of customizing it to the dialogs sample
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55552 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -24,6 +24,13 @@ Classes:
|
|||||||
@li wxLogInterposerTemp
|
@li wxLogInterposerTemp
|
||||||
@li wxStreamToTextRedirector
|
@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
|
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
|
logging here has a broad sense, including all of the program output, not only
|
||||||
non-interactive messages. The logging facilities included in wxWidgets provide
|
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
|
error message) will be given to the user together with "high level" message
|
||||||
about data file writing error.
|
about data file writing error.
|
||||||
|
|
||||||
|
|
||||||
|
@section overview_log_targets Log Targets
|
||||||
|
|
||||||
After having enumerated all the functions which are normally used to log the
|
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
|
messages, and why would you want to use them we now describe how all this
|
||||||
works.
|
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
|
normally. For this the wxLogChain, wxLogInterposer, and wxLogInterposerTemp can
|
||||||
be used.
|
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.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@@ -63,9 +63,18 @@ protected:
|
|||||||
|
|
||||||
wxSUPPRESS_DOLOG_HIDE_WARNING()
|
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
|
// empty everything
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
|
||||||
wxArrayString m_aMessages; // the log message texts
|
wxArrayString m_aMessages; // the log message texts
|
||||||
wxArrayInt m_aSeverity; // one of wxLOG_XXX values
|
wxArrayInt m_aSeverity; // one of wxLOG_XXX values
|
||||||
wxArrayLong m_aTimes; // the time of each message
|
wxArrayLong m_aTimes; // the time of each message
|
||||||
@@ -73,6 +82,19 @@ protected:
|
|||||||
m_bWarnings, // any warnings?
|
m_bWarnings, // any warnings?
|
||||||
m_bHasMessages; // any messages at all?
|
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
|
#endif // wxUSE_LOGGUI
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "../sample.xpm"
|
#include "../sample.xpm"
|
||||||
|
|
||||||
|
#include "wx/apptrait.h"
|
||||||
#include "wx/datetime.h"
|
#include "wx/datetime.h"
|
||||||
#include "wx/image.h"
|
#include "wx/image.h"
|
||||||
#include "wx/bookctrl.h"
|
#include "wx/bookctrl.h"
|
||||||
@@ -83,10 +84,7 @@
|
|||||||
#include "wx/fdrepdlg.h"
|
#include "wx/fdrepdlg.h"
|
||||||
#endif // wxUSE_FINDREPLDLG
|
#endif // wxUSE_FINDREPLDLG
|
||||||
|
|
||||||
#if wxUSE_SPINCTRL
|
|
||||||
#include "wx/spinctrl.h"
|
#include "wx/spinctrl.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "wx/propdlg.h"
|
#include "wx/propdlg.h"
|
||||||
|
|
||||||
#include "dialogs.h"
|
#include "dialogs.h"
|
||||||
@@ -2327,3 +2325,29 @@ void TestMessageBoxDialog::OnClose(wxCommandEvent& WXUNUSED(event))
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_SETTINGS_DIALOG
|
#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
|
||||||
|
@@ -98,15 +98,31 @@ of MSW, MAC and OS2
|
|||||||
#define USE_SETTINGS_DIALOG 0
|
#define USE_SETTINGS_DIALOG 0
|
||||||
#endif
|
#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
|
// Define a new application type
|
||||||
class MyApp: public wxApp
|
class MyApp: public wxApp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool OnInit();
|
virtual bool OnInit();
|
||||||
|
|
||||||
wxFont m_canvasFont;
|
wxFont m_canvasFont;
|
||||||
wxColour m_canvasTextColour;
|
wxColour m_canvasTextColour;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
#if wxUSE_LOG
|
||||||
|
virtual wxAppTraits *CreateTraits() { return new MyAppTraits; }
|
||||||
|
#endif // wxUSE_LOG
|
||||||
};
|
};
|
||||||
|
|
||||||
#if USE_MODAL_PRESENTATION
|
#if USE_MODAL_PRESENTATION
|
||||||
|
@@ -281,6 +281,74 @@ void wxLogGui::Clear()
|
|||||||
m_aTimes.Empty();
|
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()
|
void wxLogGui::Flush()
|
||||||
{
|
{
|
||||||
if ( !m_bHasMessages )
|
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
|
// do it right now to block any new calls to Flush() while we're here
|
||||||
m_bHasMessages = false;
|
m_bHasMessages = false;
|
||||||
|
|
||||||
|
// note that this must be done before examining m_aMessages as it may log
|
||||||
|
// yet another message
|
||||||
const unsigned repeatCount = LogLastRepeatIfNeeded();
|
const unsigned repeatCount = LogLastRepeatIfNeeded();
|
||||||
|
|
||||||
wxString appName = wxTheApp->GetAppDisplayName();
|
const size_t nMsgCount = m_aMessages.size();
|
||||||
|
|
||||||
long style;
|
if ( repeatCount > 0 )
|
||||||
wxString titleFormat;
|
{
|
||||||
if ( m_bErrors ) {
|
m_aMessages[nMsgCount - 1] << " (" << m_aMessages[nMsgCount - 2] << ")";
|
||||||
titleFormat = _("%s Error");
|
|
||||||
style = wxICON_STOP;
|
|
||||||
}
|
|
||||||
else if ( m_bWarnings ) {
|
|
||||||
titleFormat = _("%s Warning");
|
|
||||||
style = wxICON_EXCLAMATION;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
titleFormat = _("%s Information");
|
|
||||||
style = wxICON_INFORMATION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString title;
|
const wxString title = GetTitle();
|
||||||
title.Printf(titleFormat, appName.c_str());
|
const int style = GetSeverityIcon();
|
||||||
|
|
||||||
size_t nMsgCount = m_aMessages.GetCount();
|
|
||||||
|
|
||||||
// avoid showing other log dialogs until we're done with the dialog we're
|
// 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!
|
// showing right now: nested modal dialogs make for really bad UI!
|
||||||
Suspend();
|
Suspend();
|
||||||
|
|
||||||
wxString str;
|
|
||||||
if ( nMsgCount == 1 )
|
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
|
else // more than one message
|
||||||
{
|
{
|
||||||
#if wxUSE_LOG_DIALOG
|
wxArrayString messages;
|
||||||
|
wxArrayInt severities;
|
||||||
|
wxArrayLong times;
|
||||||
|
|
||||||
if ( repeatCount > 0 )
|
messages.swap(m_aMessages);
|
||||||
{
|
severities.swap(m_aSeverity);
|
||||||
m_aMessages[nMsgCount - 1]
|
times.swap(m_aTimes);
|
||||||
<< " (" << m_aMessages[nMsgCount - 2] << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
wxLogDialog dlg(NULL,
|
|
||||||
m_aMessages, m_aSeverity, m_aTimes,
|
|
||||||
title, style);
|
|
||||||
|
|
||||||
// clear the message list before showing the dialog because while it's
|
|
||||||
// shown some new messages may appear
|
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
(void)dlg.ShowModal();
|
DoShowMultipleLogMessages(messages, severities, times, title, style);
|
||||||
#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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow flushing the logs again
|
// allow flushing the logs again
|
||||||
|
Reference in New Issue
Block a user