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:
parent
b2794028de
commit
9ad2fe62d1
@ -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.
|
||||
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "../sample.xpm"
|
||||
|
||||
#include "wx/apptrait.h"
|
||||
#include "wx/datetime.h"
|
||||
#include "wx/image.h"
|
||||
#include "wx/bookctrl.h"
|
||||
@ -83,10 +84,7 @@
|
||||
#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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
wxArrayString messages;
|
||||
wxArrayInt severities;
|
||||
wxArrayLong times;
|
||||
|
||||
if ( repeatCount > 0 )
|
||||
{
|
||||
m_aMessages[nMsgCount - 1]
|
||||
<< " (" << m_aMessages[nMsgCount - 2] << ")";
|
||||
}
|
||||
messages.swap(m_aMessages);
|
||||
severities.swap(m_aSeverity);
|
||||
times.swap(m_aTimes);
|
||||
|
||||
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();
|
||||
|
||||
(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
|
||||
|
Loading…
Reference in New Issue
Block a user