X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/159b66c02a8f1c724d1af3c768ad5d90f4c8a0e2..c15d9c859c64f28c56d1e61b7d031a74e6018583:/src/common/appcmn.cpp diff --git a/src/common/appcmn.cpp b/src/common/appcmn.cpp index 86a63a1090..b179284223 100644 --- a/src/common/appcmn.cpp +++ b/src/common/appcmn.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // Name: common/appcmn.cpp -// Purpose: wxAppBase methods common to all platforms +// Purpose: wxAppConsole and wxAppBase methods common to all platforms // Author: Vadim Zeitlin // Modified by: // Created: 18.10.99 @@ -32,26 +32,21 @@ #include "wx/app.h" #include "wx/intl.h" #include "wx/list.h" - #if wxUSE_GUI - #include "wx/msgdlg.h" - #endif // wxUSE_GUI + #include "wx/log.h" + #include "wx/msgdlg.h" #endif -#include "wx/cmdline.h" +#include "wx/apptrait.h" +#if wxUSE_FONTMAP + #include "wx/fontmap.h" +#endif // wxUSE_FONTMAP +#include "wx/msgout.h" #include "wx/thread.h" -#include "wx/confbase.h" +#include "wx/utils.h" -#if !defined(__WXMSW__) || defined(__WXMICROWIN__) - #include // for SIGTRAP used by wxTrap() -#endif //Win/Unix - -#if defined(__WXMSW__) - #include "wx/msw/private.h" // includes windows.h for MessageBox() -#endif - -// =========================================================================== -// implementation -// =========================================================================== +// ============================================================================ +// wxAppBase implementation +// ============================================================================ // ---------------------------------------------------------------------------- // initialization and termination @@ -59,20 +54,30 @@ wxAppBase::wxAppBase() { - wxTheApp = (wxApp *)this; - - // VZ: what's this? is it obsolete? - m_wantDebugOutput = FALSE; - -#if wxUSE_GUI m_topWindow = (wxWindow *)NULL; m_useBestVisual = FALSE; - m_exitOnFrameDelete = TRUE; m_isActive = TRUE; -#endif // wxUSE_GUI + + // We don't want to exit the app if the user code shows a dialog from its + // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete + // to Yes initially as this dialog would be the last top level window. + // OTOH, if we set it to No initially we'll have to overwrite it with Yes + // when we enter our OnRun() because we do want the default behaviour from + // then on. But this would be a problem if the user code calls + // SetExitOnFrameDelete(FALSE) from OnInit(). + // + // So we use the special "Later" value which is such that + // GetExitOnFrameDelete() returns FALSE for it but which we know we can + // safely (i.e. without losing the effect of the users SetExitOnFrameDelete + // call) overwrite in OnRun() + m_exitOnFrameDelete = Later; +} + +wxAppBase::~wxAppBase() +{ + // this destructor is required for Darwin } -#if wxUSE_GUI bool wxAppBase::OnInitGui() { #ifdef __WXUNIVERSAL__ @@ -82,339 +87,153 @@ bool wxAppBase::OnInitGui() return TRUE; } -#endif // wxUSE_GUI -int wxAppBase::OnExit() +int wxAppBase::OnRun() { -#if wxUSE_CONFIG - // delete the config object if any (don't use Get() here, but Set() - // because Get() could create a new config object) - delete wxConfigBase::Set((wxConfigBase *) NULL); -#endif // wxUSE_CONFIG - -#ifdef __WXUNIVERSAL__ - delete wxTheme::Set(NULL); -#endif // __WXUNIVERSAL__ - - return 0; -} - -// --------------------------------------------------------------------------- -// wxAppBase -// ---------------------------------------------------------------------------- - -void wxAppBase::ProcessPendingEvents() -{ - // ensure that we're the only thread to modify the pending events list - wxENTER_CRIT_SECT( *wxPendingEventsLocker ); - - if ( !wxPendingEvents ) + // see the comment in ctor: if the initial value hasn't been changed, use + // the default Yes from now on + if ( m_exitOnFrameDelete == Later ) { - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); - return; + m_exitOnFrameDelete = Yes; } + //else: it has been changed, assume the user knows what he is doing - // iterate until the list becomes empty - wxNode *node = wxPendingEvents->First(); - while (node) - { - wxEvtHandler *handler = (wxEvtHandler *)node->Data(); - delete node; - - // In ProcessPendingEvents(), new handlers might be add - // and we can safely leave the critical section here. - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); - handler->ProcessPendingEvents(); - wxENTER_CRIT_SECT( *wxPendingEventsLocker ); + return MainLoop(); +} - node = wxPendingEvents->First(); - } +void wxAppBase::Exit() +{ + ExitMainLoop(); +} - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); +wxAppTraits *wxAppBase::CreateTraits() +{ + return wxAppTraits::CreateGUI(); } // ---------------------------------------------------------------------------- // misc // ---------------------------------------------------------------------------- -#if wxUSE_GUI - void wxAppBase::SetActive(bool active, wxWindow * WXUNUSED(lastFocus)) { + if ( active == m_isActive ) + return; + m_isActive = active; -} -#endif // wxUSE_GUI + wxActivateEvent event(wxEVT_ACTIVATE_APP, active); + event.SetEventObject(this); + + (void)ProcessEvent(event); +} // ---------------------------------------------------------------------------- -// cmd line parsing +// wxGUIAppTraitsBase // ---------------------------------------------------------------------------- -bool wxAppBase::OnInit() -{ -#if wxUSE_CMDLINE_PARSER - wxCmdLineParser parser(argc, argv); - - OnInitCmdLine(parser); - - bool cont; - switch ( parser.Parse() ) - { - case -1: - cont = OnCmdLineHelp(parser); - break; - - case 0: - cont = OnCmdLineParsed(parser); - break; - - default: - cont = OnCmdLineError(parser); - break; - } - - if ( !cont ) - return FALSE; -#endif // wxUSE_CMDLINE_PARSER +#if wxUSE_LOG - return TRUE; +wxLog *wxGUIAppTraitsBase::CreateLogTarget() +{ + return new wxLogGui; } -#if wxUSE_CMDLINE_PARSER - -#define OPTION_VERBOSE _T("verbose") -#define OPTION_THEME _T("theme") +#endif // wxUSE_LOG -void wxAppBase::OnInitCmdLine(wxCmdLineParser& parser) +wxMessageOutput *wxGUIAppTraitsBase::CreateMessageOutput() { - // the standard command line options - static const wxCmdLineEntryDesc cmdLineDesc[] = - { - { - wxCMD_LINE_SWITCH, - _T("h"), - _T("help"), - gettext_noop("show this help message"), - wxCMD_LINE_VAL_NONE, - wxCMD_LINE_OPTION_HELP - }, + // The standard way of printing help on command line arguments (app --help) + // is (according to common practice): + // - console apps: to stderr (on any platform) + // - GUI apps: stderr on Unix platforms (!) + // message box under Windows and others +#ifdef __UNIX__ + return new wxMessageOutputStderr; +#else // !__UNIX__ + // wxMessageOutputMessageBox doesn't work under Motif + #ifdef __WXMOTIF__ + return new wxMessageOutputLog; + #else + return new wxMessageOutputMessageBox; + #endif +#endif // __UNIX__/!__UNIX__ +} -#if wxUSE_LOG - { - wxCMD_LINE_SWITCH, - _T(""), - OPTION_VERBOSE, - gettext_noop("generate verbose log messages") - }, -#endif // wxUSE_LOG +#if wxUSE_FONTMAP -#ifdef __WXUNIVERSAL__ - { - wxCMD_LINE_OPTION, - _T(""), - OPTION_THEME, - gettext_noop("specify the theme to use"), - wxCMD_LINE_VAL_STRING - }, -#endif // __WXUNIVERSAL__ +wxFontMapper *wxGUIAppTraitsBase::CreateFontMapper() +{ + return new wxFontMapper; +} - // terminator - { wxCMD_LINE_NONE } - }; +#endif // wxUSE_FONTMAP - parser.SetDesc(cmdLineDesc); -} +#ifdef __WXDEBUG__ -bool wxAppBase::OnCmdLineParsed(wxCmdLineParser& parser) +bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg) { -#if wxUSE_LOG - if ( parser.Found(OPTION_VERBOSE) ) - { - wxLog::SetVerbose(TRUE); - } -#endif // wxUSE_LOG - -#ifdef __WXUNIVERSAL__ - wxString themeName; - if ( parser.Found(OPTION_THEME, &themeName) ) + // under MSW we prefer to use the base class version using ::MessageBox() + // even if wxMessageBox() is available because it has less chances to + // double fault our app than our wxMessageBox() +#if defined(__WXMSW__) || !wxUSE_MSGDLG + return wxAppTraitsBase::ShowAssertDialog(msg); +#else // wxUSE_MSGDLG + // this message is intentionally not translated -- it is for + // developpers only + wxString msgDlg(msg); + msgDlg += wxT("\nDo you want to stop the program?\n") + wxT("You can also choose [Cancel] to suppress ") + wxT("further warnings."); + + switch ( wxMessageBox(msgDlg, wxT("wxWindows Debug Alert"), + wxYES_NO | wxCANCEL | wxICON_STOP ) ) { - wxTheme *theme = wxTheme::Create(themeName); - if ( !theme ) - { - wxLogError(_("Unsupported theme '%s'."), themeName.c_str()); + case wxYES: + wxTrap(); + break; - return FALSE; - } + case wxCANCEL: + // no more asserts + return true; - wxTheme::Set(theme); + //case wxNO: nothing to do } -#endif // __WXUNIVERSAL__ - - return TRUE; -} - -bool wxAppBase::OnCmdLineHelp(wxCmdLineParser& parser) -{ - parser.Usage(); - - return FALSE; -} - -bool wxAppBase::OnCmdLineError(wxCmdLineParser& parser) -{ - parser.Usage(); - return FALSE; + return false; +#endif // !wxUSE_MSGDLG/wxUSE_MSGDLG } -#endif // wxUSE_CMDLINE_PARSER - -// ---------------------------------------------------------------------------- -// debugging support -// ---------------------------------------------------------------------------- - -#ifdef __WXDEBUG__ - -// wxASSERT() helper -bool wxAssertIsEqual(int x, int y) -{ - return x == y; -} +#endif // __WXDEBUG__ -// break into the debugger -void wxTrap() +bool wxGUIAppTraitsBase::HasStderr() { -#if defined(__WXMSW__) && !defined(__WXMICROWIN__) - DebugBreak(); -#elif defined(__WXMAC__) -#if __powerc - Debugger(); + // we consider that under Unix stderr always goes somewhere, even if the + // user doesn't always see it under GUI desktops +#ifdef __UNIX__ + return true; #else - SysBreak(); + return false; #endif -#elif defined(__UNIX__) - raise(SIGTRAP); -#else - // TODO -#endif // Win/Unix } -// show the assert modal dialog -static -void ShowAssertDialog(const wxChar *szFile, int nLine, const wxChar *szMsg) +void wxGUIAppTraitsBase::ScheduleForDestroy(wxObject *object) { - // this variable can be set to true to suppress "assert failure" messages - static bool s_bNoAsserts = FALSE; - static bool s_bInAssert = FALSE; // FIXME MT-unsafe - - if ( s_bInAssert ) - { - // He-e-e-e-elp!! we're trapped in endless loop - wxTrap(); - - s_bInAssert = FALSE; - - return; - } - - s_bInAssert = TRUE; - - wxChar szBuf[4096]; - - // make life easier for people using VC++ IDE: clicking on the message - // will take us immediately to the place of the failed assert - wxSnprintf(szBuf, WXSIZEOF(szBuf), -#ifdef __VISUALC__ - wxT("%s(%d): assert failed"), -#else // !VC++ - // make the error message more clear for all the others - wxT("Assert failed in file %s at line %d"), -#endif // VC/!VC - szFile, nLine); - - if ( szMsg != NULL ) - { - wxStrcat(szBuf, wxT(": ")); - wxStrcat(szBuf, szMsg); - } - else // no message given - { - wxStrcat(szBuf, wxT(".")); - } - - if ( !s_bNoAsserts ) - { - // send it to the normal log destination - wxLogDebug(szBuf); - -#if (wxUSE_GUI && wxUSE_MSGDLG) || defined(__WXMSW__) - // this message is intentionally not translated - it is for - // developpers only - wxStrcat(szBuf, wxT("\nDo you want to stop the program?\nYou can also choose [Cancel] to suppress further warnings.")); - - // use the native message box if available: this is more robust than - // using our own -#if defined(__WXMSW__) && !defined(__WXMICROWIN__) - switch ( ::MessageBox(NULL, szBuf, _T("Debug"), - MB_YESNOCANCEL | MB_ICONSTOP ) ) - { - case IDYES: - wxTrap(); - break; - - case IDCANCEL: - s_bNoAsserts = TRUE; - break; - - //case IDNO: nothing to do - } -#else // !MSW - switch ( wxMessageBox(szBuf, wxT("Debug"), - wxYES_NO | wxCANCEL | wxICON_STOP ) ) - { - case wxYES: - wxTrap(); - break; - - case wxCANCEL: - s_bNoAsserts = TRUE; - break; - - //case wxNO: nothing to do - } -#endif // GUI or MSW - -#else // !GUI - wxTrap(); -#endif // GUI/!GUI - } - - s_bInAssert = FALSE; + if ( !wxPendingDelete.Member(object) ) + wxPendingDelete.Append(object); } -// this function is called when an assert fails -void wxOnAssert(const wxChar *szFile, int nLine, const wxChar *szMsg) +void wxGUIAppTraitsBase::RemoveFromPendingDelete(wxObject *object) { - wxMessageBox( "ttest", "test", wxOK ); - return; - - if ( !wxTheApp ) - { - // by default, show the assert dialog box - we can't customize this - // behaviour - ShowAssertDialog(szFile, nLine, szMsg); - } - else - { - // let the app process it as it wants - wxTheApp->OnAssert(szFile, nLine, szMsg); - } + wxPendingDelete.DeleteObject(object); } -void wxAppBase::OnAssert(const wxChar *file, int line, const wxChar *msg) +// ---------------------------------------------------------------------------- +// wxAppTraits +// ---------------------------------------------------------------------------- + +wxAppTraits *wxAppTraitsBase::CreateGUI() { - ShowAssertDialog(file, line, msg); + return new wxGUIAppTraits; } -#endif //WXDEBUG -