X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1e6feb95a79834836e88143b15d9f424ebe79621..b00786ec12dfb0141d7deb6a4e2235a95a9c26f7:/src/common/appcmn.cpp diff --git a/src/common/appcmn.cpp b/src/common/appcmn.cpp index 761c50b9ff..78ede412b9 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 @@ -30,125 +30,284 @@ #ifndef WX_PRECOMP #include "wx/app.h" + #include "wx/intl.h" #include "wx/list.h" + #include "wx/log.h" + #include "wx/msgdlg.h" #endif +#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" -#ifdef __WXUNIVERSAL__ - #include "wx/univ/theme.h" -#endif // __WXUNIVERSAL__ +// ============================================================================ +// wxAppBase implementation +// ============================================================================ -// =========================================================================== -// implementation -// =========================================================================== +// ---------------------------------------------------------------------------- +// initialization +// ---------------------------------------------------------------------------- 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; +} + +bool wxAppBase::Initialize(int& argc, wxChar **argv) +{ + if ( !wxAppConsole::Initialize(argc, argv) ) + return false; + +#if wxUSE_THREADS + wxPendingEventsLocker = new wxCriticalSection; +#endif + + wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING); + wxTheColourDatabase->Initialize(); + + wxInitializeStockLists(); + wxInitializeStockObjects(); + + wxBitmap::InitStandardHandlers(); + + return true; +} + +// ---------------------------------------------------------------------------- +// cleanup +// ---------------------------------------------------------------------------- + +wxAppBase::~wxAppBase() +{ + // this destructor is required for Darwin +} + +void wxAppBase::CleanUp() +{ + // one last chance for pending objects to be cleaned up + DeletePendingObjects(); + + wxBitmap::CleanUpHandlers(); + + wxDeleteStockObjects(); + + wxDeleteStockLists(); + + delete wxTheColourDatabase; + wxTheColourDatabase = NULL; + +#if wxUSE_THREADS + delete wxPendingEvents; + wxPendingEvents = NULL; + + delete wxPendingEventsLocker; + wxPendingEventsLocker = NULL; + +#if wxUSE_VALIDATORS + // If we don't do the following, we get an apparent memory leak. + ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker(); +#endif // wxUSE_VALIDATORS +#endif // wxUSE_THREADS } // ---------------------------------------------------------------------------- -// initialization and termination +// OnXXX() hooks // ---------------------------------------------------------------------------- -#if wxUSE_GUI bool wxAppBase::OnInitGui() { #ifdef __WXUNIVERSAL__ - if ( !wxTheme::CreateDefault() ) + if ( !wxTheme::Get() && !wxTheme::CreateDefault() ) return FALSE; #endif // __WXUNIVERSAL__ 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 + // see the comment in ctor: if the initial value hasn't been changed, use + // the default Yes from now on + if ( m_exitOnFrameDelete == Later ) + { + m_exitOnFrameDelete = Yes; + } + //else: it has been changed, assume the user knows what he is doing -#ifdef __WXUNIVERSAL__ - delete wxTheme::Set(NULL); -#endif // __WXUNIVERSAL__ + return MainLoop(); +} - return 0; +void wxAppBase::Exit() +{ + ExitMainLoop(); } -// --------------------------------------------------------------------------- -// wxAppBase +wxAppTraits *wxAppBase::CreateTraits() +{ + return wxAppTraits::CreateGUI(); +} + +// ---------------------------------------------------------------------------- +// misc // ---------------------------------------------------------------------------- -void wxAppBase::ProcessPendingEvents() +void wxAppBase::SetActive(bool active, wxWindow * WXUNUSED(lastFocus)) { - // ensure that we're the only thread to modify the pending events list - wxENTER_CRIT_SECT( *wxPendingEventsLocker ); - - if ( !wxPendingEvents ) - { - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); + if ( active == m_isActive ) return; - } - // iterate until the list becomes empty - wxNode *node = wxPendingEvents->First(); + m_isActive = active; + + wxActivateEvent event(wxEVT_ACTIVATE_APP, active); + event.SetEventObject(this); + + (void)ProcessEvent(event); +} + +void wxAppBase::DeletePendingObjects() +{ + wxNode *node = wxPendingDelete.GetFirst(); while (node) { - wxEvtHandler *handler = (wxEvtHandler *)node->Data(); - delete node; + wxObject *obj = node->GetData(); - // 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 ); + delete obj; - node = wxPendingEvents->First(); - } + if (wxPendingDelete.Member(obj)) + delete node; - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); + // Deleting one object may have deleted other pending + // objects, so start from beginning of list again. + node = wxPendingDelete.GetFirst(); + } } // ---------------------------------------------------------------------------- -// misc +// wxGUIAppTraitsBase // ---------------------------------------------------------------------------- -#if wxUSE_GUI +#if wxUSE_LOG -void wxAppBase::SetActive(bool active, wxWindow *lastFocus) +wxLog *wxGUIAppTraitsBase::CreateLogTarget() { - static wxWindow *s_lastFocus = (wxWindow *)NULL; + return new wxLogGui; +} - m_isActive = active; +#endif // wxUSE_LOG - // if we're being deactivated remember the last focused window - if ( !active ) - { - s_lastFocus = lastFocus; - } +wxMessageOutput *wxGUIAppTraitsBase::CreateMessageOutput() +{ + // 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_FONTMAP + +wxFontMapper *wxGUIAppTraitsBase::CreateFontMapper() +{ + return new wxFontMapper; +} + +#endif // wxUSE_FONTMAP - if ( s_lastFocus ) +#ifdef __WXDEBUG__ + +bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg) +{ + // 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 ) ) { - // give the focused window the chance to refresh itself if its - // appearance depends on the app activation state - wxActivateEvent event(wxEVT_ACTIVATE, active); - s_lastFocus->GetEventHandler()->ProcessEvent(event); + case wxYES: + wxTrap(); + break; + + case wxCANCEL: + // no more asserts + return true; + + //case wxNO: nothing to do } + + return false; +#endif // !wxUSE_MSGDLG/wxUSE_MSGDLG +} + +#endif // __WXDEBUG__ + +bool wxGUIAppTraitsBase::HasStderr() +{ + // 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 + return false; +#endif +} + +void wxGUIAppTraitsBase::ScheduleForDestroy(wxObject *object) +{ + if ( !wxPendingDelete.Member(object) ) + wxPendingDelete.Append(object); +} + +void wxGUIAppTraitsBase::RemoveFromPendingDelete(wxObject *object) +{ + wxPendingDelete.DeleteObject(object); +} + +// ---------------------------------------------------------------------------- +// wxAppTraits +// ---------------------------------------------------------------------------- + +wxAppTraits *wxAppTraitsBase::CreateGUI() +{ + return new wxGUIAppTraits; } -#endif // wxUSE_GUI