Added wxMessageOutput as per the discussion on wx-dev.

Added wxApp::DoInit to initialize the global wxMessageOutput instance.
Changed wxCommandLineParser to use wxMessageOutput.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16267 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Mattia Barbon
2002-07-24 19:29:53 +00:00
parent 53d838be50
commit 74698d3a22
8 changed files with 287 additions and 56 deletions

View File

@@ -202,6 +202,7 @@ memory.cpp Common Base
menucmn.cpp Common menucmn.cpp Common
mimecmn.cpp Common Win32Only,Base mimecmn.cpp Common Win32Only,Base
module.cpp Common Base module.cpp Common Base
msgout.cpp Common Base
mstream.cpp Common Base mstream.cpp Common Base
nbkbase.cpp Common nbkbase.cpp Common
object.cpp Common Base object.cpp Common Base
@@ -891,6 +892,7 @@ mimetype.h WXH Base
minifram.h WXH minifram.h WXH
module.h WXH Base module.h WXH Base
msgdlg.h WXH msgdlg.h WXH
msgout.h WXH Base
mslu.cpp MSW mslu.cpp MSW
mstream.h WXH Base mstream.h WXH Base
notebook.h WXH notebook.h WXH

View File

@@ -108,6 +108,10 @@ public:
// Override: always in GUI application, rarely in console ones. // Override: always in GUI application, rarely in console ones.
virtual bool OnInit(); virtual bool OnInit();
// initializes wxMessageOutput; other responsibilities
// may be added later
virtual void DoInit();
#if wxUSE_GUI #if wxUSE_GUI
// a platform-dependent version of OnInit(): the code here is likely to // a platform-dependent version of OnInit(): the code here is likely to
// depend on the toolkit. default version does nothing. // depend on the toolkit. default version does nothing.

View File

@@ -202,6 +202,9 @@ public:
static wxArrayString ConvertStringToArgs(const wxChar *cmdline); static wxArrayString ConvertStringToArgs(const wxChar *cmdline);
private: private:
// get usage string
wxString GetUsageString();
// common part of all ctors // common part of all ctors
void Init(); void Init();

78
include/wx/msgout.h Executable file
View File

@@ -0,0 +1,78 @@
///////////////////////////////////////////////////////////////////////////////
// Name: wx/msgout.h
// Purpose: wxMessageOutput class. Shows a message to the user
// Author: Mattia Barbon
// Modified by:
// Created: 17.07.02
// RCS-ID: $Id$
// Copyright: (c) wxWindows team
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_MSGOUT_H_
#define _WX_MSGOUT_H_
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#ifdef __GNUG__
#pragma interface "msgout.h"
#endif
#include "wx/defs.h"
#include "wx/wxchar.h"
class WXDLLEXPORT wxMessageOutput
{
public:
virtual ~wxMessageOutput() {};
// show a message to the user
virtual void Printf(const wxChar* format, ...) ATTRIBUTE_PRINTF_2 = 0;
// gets the current wxMessageOutput object
static wxMessageOutput* Get();
// sets the global wxMessageOutput instance; returns the previous one
static wxMessageOutput* Set(wxMessageOutput* msgout);
private:
static wxMessageOutput* ms_msgOut;
};
// sends output to stderr
class WXDLLEXPORT wxMessageOutputStderr : public wxMessageOutput
{
public:
wxMessageOutputStderr() {};
virtual void Printf(const wxChar* format, ...) ATTRIBUTE_PRINTF_2;
};
#if wxUSE_GUI
// shows output in a message box
class WXDLLEXPORT wxMessageOutputMessageBox : public wxMessageOutput
{
public:
wxMessageOutputMessageBox() {};
virtual void Printf(const wxChar* format, ...) ATTRIBUTE_PRINTF_2;
};
#ifdef __WXMOTIF__
// use wxLog; this is only required for wxMotif, so we put this code
// inside wxUSE_GUI; it will work even without GUI
class WXDLLEXPORT wxMessageOutputLog : public wxMessageOutput
{
public:
wxMessageOutputLog() {};
virtual void Printf(const wxChar* format, ...) ATTRIBUTE_PRINTF_2;
};
#endif // __WXMOTIF__
#endif // wxUSE_GUI
#endif
// _WX_MSGOUT_H_

View File

@@ -42,6 +42,7 @@
#include "wx/confbase.h" #include "wx/confbase.h"
#include "wx/tokenzr.h" #include "wx/tokenzr.h"
#include "wx/utils.h" #include "wx/utils.h"
#include "wx/msgout.h"
#if wxUSE_GUI #if wxUSE_GUI
#include "wx/artprov.h" #include "wx/artprov.h"
@@ -188,12 +189,27 @@ int wxAppBase::FilterEvent(wxEvent& WXUNUSED(event))
return -1; return -1;
} }
void wxAppBase::DoInit()
{
if(wxMessageOutput::Get()) return;
#if wxUSE_GUI
#ifdef __WXMOTIF__
wxMessageOutput::Set(new wxMessageOutputLog);
#else
wxMessageOutput::Set(new wxMessageOutputMessageBox);
#endif
#else
wxMessageOutput::Set(new wxMessageOutputStderr);
#endif
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// cmd line parsing // cmd line parsing
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool wxAppBase::OnInit() bool wxAppBase::OnInit()
{ {
DoInit();
#if wxUSE_CMDLINE_PARSER #if wxUSE_CMDLINE_PARSER
wxCmdLineParser parser(argc, argv); wxCmdLineParser parser(argc, argv);

View File

@@ -44,6 +44,7 @@
#include <ctype.h> #include <ctype.h>
#include "wx/datetime.h" #include "wx/datetime.h"
#include "wx/msgout.h"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// private functions // private functions
@@ -513,6 +514,7 @@ int wxCmdLineParser::Parse(bool showUsage)
size_t currentParam = 0; // the index in m_paramDesc size_t currentParam = 0; // the index in m_paramDesc
size_t countParam = m_data->m_paramDesc.GetCount(); size_t countParam = m_data->m_paramDesc.GetCount();
wxString errorMsg;
Reset(); Reset();
@@ -559,7 +561,7 @@ int wxCmdLineParser::Parse(bool showUsage)
optInd = m_data->FindOptionByLongName(name); optInd = m_data->FindOptionByLongName(name);
if ( optInd == wxNOT_FOUND ) if ( optInd == wxNOT_FOUND )
{ {
wxLogError(_("Unknown long option '%s'"), name.c_str()); errorMsg << wxString::Format(_("Unknown long option '%s'"), name.c_str()) << "\n";
} }
} }
else else
@@ -568,7 +570,7 @@ int wxCmdLineParser::Parse(bool showUsage)
// Print the argument including leading "--" // Print the argument including leading "--"
name.Prepend( wxT("--") ); name.Prepend( wxT("--") );
wxLogError(_("Unknown option '%s'"), name.c_str()); errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str()) << "\n";
} }
} }
@@ -589,7 +591,7 @@ int wxCmdLineParser::Parse(bool showUsage)
{ {
// we couldn't find a valid option name in the // we couldn't find a valid option name in the
// beginning of this string // beginning of this string
wxLogError(_("Unknown option '%s'"), name.c_str()); errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str()) << "\n";
break; break;
} }
@@ -661,7 +663,7 @@ int wxCmdLineParser::Parse(bool showUsage)
if ( *p++ != _T('=') ) if ( *p++ != _T('=') )
{ {
wxLogError(_("Option '%s' requires a value, '=' expected."), name.c_str()); errorMsg << wxString::Format(_("Option '%s' requires a value, '=' expected."), name.c_str()) << "\n";
ok = FALSE; ok = FALSE;
} }
@@ -681,8 +683,8 @@ int wxCmdLineParser::Parse(bool showUsage)
if ( ++n == count ) if ( ++n == count )
{ {
// ... but there is none // ... but there is none
wxLogError(_("Option '%s' requires a value."), errorMsg << wxString::Format(_("Option '%s' requires a value."),
name.c_str()); name.c_str()) << "\n";
ok = FALSE; ok = FALSE;
} }
@@ -698,8 +700,8 @@ int wxCmdLineParser::Parse(bool showUsage)
// not depending on the option style // not depending on the option style
if ( opt.flags & wxCMD_LINE_NEEDS_SEPARATOR ) if ( opt.flags & wxCMD_LINE_NEEDS_SEPARATOR )
{ {
wxLogError(_("Separator expected after the option '%s'."), errorMsg << wxString::Format(_("Separator expected after the option '%s'."),
name.c_str()); name.c_str()) << "\n";
ok = FALSE; ok = FALSE;
} }
@@ -728,8 +730,8 @@ int wxCmdLineParser::Parse(bool showUsage)
} }
else else
{ {
wxLogError(_("'%s' is not a correct numeric value for option '%s'."), errorMsg << wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
value.c_str(), name.c_str()); value.c_str(), name.c_str()) << "\n";
ok = FALSE; ok = FALSE;
} }
@@ -742,8 +744,8 @@ int wxCmdLineParser::Parse(bool showUsage)
const wxChar *res = dt.ParseDate(value); const wxChar *res = dt.ParseDate(value);
if ( !res || *res ) if ( !res || *res )
{ {
wxLogError(_("Option '%s': '%s' cannot be converted to a date."), errorMsg << wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
name.c_str(), value.c_str()); name.c_str(), value.c_str()) << "\n";
ok = FALSE; ok = FALSE;
} }
@@ -783,7 +785,7 @@ int wxCmdLineParser::Parse(bool showUsage)
} }
else else
{ {
wxLogError(_("Unexpected parameter '%s'"), arg.c_str()); errorMsg << wxString::Format(_("Unexpected parameter '%s'"), arg.c_str()) << "\n";
ok = FALSE; ok = FALSE;
} }
@@ -811,8 +813,8 @@ int wxCmdLineParser::Parse(bool showUsage)
opt.longName.c_str()); opt.longName.c_str());
} }
wxLogError(_("The value for the option '%s' must be specified."), errorMsg << wxString::Format(_("The value for the option '%s' must be specified."),
optName.c_str()); optName.c_str()) << "\n";
ok = FALSE; ok = FALSE;
} }
@@ -832,17 +834,21 @@ int wxCmdLineParser::Parse(bool showUsage)
if ( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL) ) if ( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL) )
{ {
wxLogError(_("The required parameter '%s' was not specified."), errorMsg << wxString::Format(_("The required parameter '%s' was not specified."),
param.description.c_str()); param.description.c_str()) << "\n";
ok = FALSE; ok = FALSE;
} }
} }
} }
if ( !ok && showUsage ) if ( !ok && errorMsg.length() != 0 )
{ {
Usage(); wxString usage;
wxMessageOutput* msgOut = wxMessageOutput::Get();
if ( showUsage ) usage = GetUsageString();
if ( msgOut )
msgOut->Printf( wxT("%s%s"), usage.c_str(), errorMsg.c_str() );
} }
return ok ? 0 : helpRequested ? -1 : 1; return ok ? 0 : helpRequested ? -1 : 1;
@@ -853,11 +859,20 @@ int wxCmdLineParser::Parse(bool showUsage)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxCmdLineParser::Usage() void wxCmdLineParser::Usage()
{
wxString usage = GetUsageString();
wxMessageOutput* msgOut = wxMessageOutput::Get();
if ( msgOut )
msgOut->Printf( wxT("%s"), usage.c_str() );
}
wxString wxCmdLineParser::GetUsageString()
{ {
wxString appname = wxTheApp->GetAppName(); wxString appname = wxTheApp->GetAppName();
if ( !appname ) if ( !appname )
{ {
wxCHECK_RET( !m_data->m_arguments.IsEmpty(), _T("no program name") ); wxCHECK_MSG( !m_data->m_arguments.IsEmpty(), wxEmptyString,
_T("no program name") );
appname = wxFileNameFromPath(m_data->m_arguments[0]); appname = wxFileNameFromPath(m_data->m_arguments[0]);
wxStripExtension(appname); wxStripExtension(appname);
@@ -866,9 +881,15 @@ void wxCmdLineParser::Usage()
// we construct the brief cmd line desc on the fly, but not the detailed // we construct the brief cmd line desc on the fly, but not the detailed
// help message below because we want to align the options descriptions // help message below because we want to align the options descriptions
// and for this we must first know the longest one of them // and for this we must first know the longest one of them
wxString brief; wxString usage;
wxArrayString namesOptions, descOptions; wxArrayString namesOptions, descOptions;
brief.Printf(_("Usage: %s"), appname.c_str());
if ( !!m_data->m_logo )
{
usage << m_data->m_logo << _T('\n');
}
usage << wxString::Format(_("Usage: %s"), appname.c_str());
// the switch char is usually '-' but this can be changed with // the switch char is usually '-' but this can be changed with
// SetSwitchChars() and then the first one of possible chars is used // SetSwitchChars() and then the first one of possible chars is used
@@ -881,19 +902,19 @@ void wxCmdLineParser::Usage()
{ {
wxCmdLineOption& opt = m_data->m_options[n]; wxCmdLineOption& opt = m_data->m_options[n];
brief << _T(' '); usage << _T(' ');
if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) ) if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) )
{ {
brief << _T('['); usage << _T('[');
} }
if ( !opt.shortName.empty() ) if ( !opt.shortName.empty() )
{ {
brief << chSwitch << opt.shortName; usage << chSwitch << opt.shortName;
} }
else if ( areLongOptionsEnabled && !opt.longName.empty() ) else if ( areLongOptionsEnabled && !opt.longName.empty() )
{ {
brief << _T("--") << opt.longName; usage << _T("--") << opt.longName;
} }
else else
{ {
@@ -925,13 +946,13 @@ void wxCmdLineParser::Usage()
{ {
wxString val; wxString val;
val << _T('<') << GetTypeName(opt.type) << _T('>'); val << _T('<') << GetTypeName(opt.type) << _T('>');
brief << _T(' ') << val; usage << _T(' ') << val;
option << (!opt.longName ? _T(':') : _T('=')) << val; option << (!opt.longName ? _T(':') : _T('=')) << val;
} }
if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) ) if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) )
{ {
brief << _T(']'); usage << _T(']');
} }
namesOptions.Add(option); namesOptions.Add(option);
@@ -943,37 +964,26 @@ void wxCmdLineParser::Usage()
{ {
wxCmdLineParam& param = m_data->m_paramDesc[n]; wxCmdLineParam& param = m_data->m_paramDesc[n];
brief << _T(' '); usage << _T(' ');
if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL ) if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL )
{ {
brief << _T('['); usage << _T('[');
} }
brief << param.description; usage << param.description;
if ( param.flags & wxCMD_LINE_PARAM_MULTIPLE ) if ( param.flags & wxCMD_LINE_PARAM_MULTIPLE )
{ {
brief << _T("..."); usage << _T("...");
} }
if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL ) if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL )
{ {
brief << _T(']'); usage << _T(']');
} }
} }
if ( !!m_data->m_logo ) usage << _T('\n');
{
wxLogMessage(m_data->m_logo);
}
// in console mode we want to show the brief usage message first, then the
// detailed one but in GUI build we give the details first and then the
// summary - like this, the brief message appears in the wxLogGui dialog,
// as expected
#if !wxUSE_GUI
wxLogMessage(brief);
#endif // !wxUSE_GUI
// now construct the detailed help message // now construct the detailed help message
size_t len, lenMax = 0; size_t len, lenMax = 0;
@@ -985,22 +995,16 @@ void wxCmdLineParser::Usage()
lenMax = len; lenMax = len;
} }
wxString detailed;
for ( n = 0; n < count; n++ ) for ( n = 0; n < count; n++ )
{ {
len = namesOptions[n].length(); len = namesOptions[n].length();
detailed << namesOptions[n] usage << namesOptions[n]
<< wxString(_T(' '), lenMax - len) << _T('\t') << wxString(_T(' '), lenMax - len) << _T('\t')
<< descOptions[n] << descOptions[n]
<< _T('\n'); << _T('\n');
} }
wxLogMessage(detailed); return usage;
// do it now if not done above
#if wxUSE_GUI
wxLogMessage(brief);
#endif // wxUSE_GUI
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -109,6 +109,7 @@ bool WXDLLEXPORT wxInitialize()
return FALSE; return FALSE;
} }
wxTheApp->DoInit();
gs_nInitCount++; gs_nInitCount++;
return TRUE; return TRUE;

123
src/common/msgout.cpp Executable file
View File

@@ -0,0 +1,123 @@
/////////////////////////////////////////////////////////////////////////////
// Name: common/msgout.cpp
// Purpose: wxMessageOutput implementation
// Author: Mattia Barbon
// Modified by:
// Created: 17.07.02
// RCS-ID: $Id$
// Copyright: (c) the wxWindows team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ---------------------------------------------------------------------------
// headers
// ---------------------------------------------------------------------------
#ifdef __GNUG__
#pragma implementation "msgout.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if defined(__BORLANDC__)
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/string.h"
#include "wx/ffile.h"
#include "wx/app.h"
#if wxUSE_GUI
#include "wx/msgdlg.h"
#endif // wxUSE_GUI
#endif
#include "wx/msgout.h"
#include <stdarg.h>
#include <stdio.h>
// ===========================================================================
// implementation
// ===========================================================================
wxMessageOutput* wxMessageOutput::ms_msgOut = 0;
wxMessageOutput* wxMessageOutput::Get()
{
return ms_msgOut;
}
wxMessageOutput* wxMessageOutput::Set(wxMessageOutput* msgout)
{
wxMessageOutput* old = ms_msgOut;
ms_msgOut = msgout;
return old;
}
// ----------------------------------------------------------------------------
// wxMessageOutputStderr
// ----------------------------------------------------------------------------
void wxMessageOutputStderr::Printf(const wxChar* format, ...)
{
va_list args;
va_start(args, format);
wxString out;
out.PrintfV(format, args);
va_end(args);
fprintf(stderr, "%s", out.mb_str());
}
// ----------------------------------------------------------------------------
// wxMessageOutputMessageBox
// ----------------------------------------------------------------------------
#if wxUSE_GUI
void wxMessageOutputMessageBox::Printf(const wxChar* format, ...)
{
va_list args;
va_start(args, format);
wxString out;
out.PrintfV(format, args);
va_end(args);
#ifndef __WXMSW__
out.Replace("\t"," ");
#endif
::wxMessageBox(out);
}
#endif // wxUSE_GUI
// ----------------------------------------------------------------------------
// wxMessageOutputLog
// ----------------------------------------------------------------------------
#if wxUSE_GUI && defined(__WXMOTIF__)
void wxMessageOutputLog::Printf(const wxChar* format, ...)
{
va_list args;
va_start(args, format);
wxString out;
out.PrintfV(format, args);
va_end(args);
out.Replace("\t"," ");
// under Motif, wxMessageDialog needs a parent window, so we use
// wxLog, which is better than nothing
::wxLogMessage("%s", out.c_str());
}
#endif // wxUSE_GUI