]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/appbase.cpp
Use stock id instead of duplicating its string label in CheckFit().
[wxWidgets.git] / src / common / appbase.cpp
index 888c6828f70f499d5bb179f5fd41a1a66581e850..4851b5ac8041109aa62f1e34b4c322ac67d03e80 100644 (file)
@@ -115,6 +115,8 @@ wxAppInitializerFunction wxAppConsoleBase::ms_appInitFn = NULL;
 
 wxSocketManager *wxAppTraitsBase::ms_manager = NULL;
 
+WXDLLIMPEXP_DATA_BASE(wxList) wxPendingDelete;
+
 // ----------------------------------------------------------------------------
 // wxEventLoopPtr
 // ----------------------------------------------------------------------------
@@ -264,7 +266,7 @@ wxAppTraits *wxAppConsoleBase::GetTraits()
     {
         m_traits = CreateTraits();
 
-        wxASSERT_MSG( m_traits, _T("wxApp::CreateTraits() failed?") );
+        wxASSERT_MSG( m_traits, wxT("wxApp::CreateTraits() failed?") );
     }
 
     return m_traits;
@@ -341,6 +343,13 @@ bool wxAppConsoleBase::ProcessIdle()
     return event.MoreRequested();
 }
 
+bool wxAppConsoleBase::UsesEventLoop() const
+{
+    // in console applications we don't know whether we're going to have an
+    // event loop so assume we won't -- unless we already have one running
+    return wxEventLoopBase::GetActive() != NULL;
+}
+
 // ----------------------------------------------------------------------------
 // events
 // ----------------------------------------------------------------------------
@@ -433,43 +442,46 @@ void wxAppConsoleBase::ResumeProcessingOfPendingEvents()
 
 void wxAppConsoleBase::ProcessPendingEvents()
 {
-    if (!m_bDoPendingEventProcessing)
-        return;
+    if ( m_bDoPendingEventProcessing )
+    {
+        wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
 
-    wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
+        wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
+                     "this helper list should be empty" );
 
-    wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
-                 "this helper list should be empty" );
+        // iterate until the list becomes empty: the handlers remove themselves
+        // from it when they don't have any more pending events
+        while (!m_handlersWithPendingEvents.IsEmpty())
+        {
+            // In ProcessPendingEvents(), new handlers might be added
+            // and we can safely leave the critical section here.
+            wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
 
-    // iterate until the list becomes empty: the handlers remove themselves
-    // from it when they don't have any more pending events
-    while (!m_handlersWithPendingEvents.IsEmpty())
-    {
-        // In ProcessPendingEvents(), new handlers might be added
-        // and we can safely leave the critical section here.
-        wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
+            // NOTE: we always call ProcessPendingEvents() on the first event handler
+            //       with pending events because handlers auto-remove themselves
+            //       from this list (see RemovePendingEventHandler) if they have no
+            //       more pending events.
+            m_handlersWithPendingEvents[0]->ProcessPendingEvents();
 
-        // NOTE: we always call ProcessPendingEvents() on the first event handler
-        //       with pending events because handlers auto-remove themselves
-        //       from this list (see RemovePendingEventHandler) if they have no
-        //       more pending events.
-        m_handlersWithPendingEvents[0]->ProcessPendingEvents();
+            wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
+        }
 
-        wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
-    }
+        // now the wxHandlersWithPendingEvents is surely empty; however some event
+        // handlers may have moved themselves into wxHandlersWithPendingDelayedEvents
+        // because of a selective wxYield call in progress.
+        // Now we need to move them back to wxHandlersWithPendingEvents so the next
+        // call to this function has the chance of processing them:
+        if (!m_handlersWithPendingDelayedEvents.IsEmpty())
+        {
+            WX_APPEND_ARRAY(m_handlersWithPendingEvents, m_handlersWithPendingDelayedEvents);
+            m_handlersWithPendingDelayedEvents.Clear();
+        }
 
-    // now the wxHandlersWithPendingEvents is surely empty; however some event
-    // handlers may have moved themselves into wxHandlersWithPendingDelayedEvents
-    // because of a selective wxYield call in progress.
-    // Now we need to move them back to wxHandlersWithPendingEvents so the next
-    // call to this function has the chance of processing them:
-    if (!m_handlersWithPendingDelayedEvents.IsEmpty())
-    {
-        WX_APPEND_ARRAY(m_handlersWithPendingEvents, m_handlersWithPendingDelayedEvents);
-        m_handlersWithPendingDelayedEvents.Clear();
+        wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
     }
 
-    wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
+    // Garbage collect all objects previously scheduled for destruction.
+    DeletePendingObjects();
 }
 
 void wxAppConsoleBase::DeletePendingEvents()
@@ -487,6 +499,50 @@ void wxAppConsoleBase::DeletePendingEvents()
     wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
 }
 
+// ----------------------------------------------------------------------------
+// delayed objects destruction
+// ----------------------------------------------------------------------------
+
+bool wxAppConsoleBase::IsScheduledForDestruction(wxObject *object) const
+{
+    return wxPendingDelete.Member(object);
+}
+
+void wxAppConsoleBase::ScheduleForDestruction(wxObject *object)
+{
+    if ( !UsesEventLoop() )
+    {
+        // we won't be able to delete it later so do it right now
+        delete object;
+        return;
+    }
+    //else: we either already have or will soon start an event loop
+
+    if ( !wxPendingDelete.Member(object) )
+        wxPendingDelete.Append(object);
+}
+
+void wxAppConsoleBase::DeletePendingObjects()
+{
+    wxList::compatibility_iterator node = wxPendingDelete.GetFirst();
+    while (node)
+    {
+        wxObject *obj = node->GetData();
+
+        // remove it from the list first so that if we get back here somehow
+        // during the object deletion (e.g. wxYield called from its dtor) we
+        // wouldn't try to delete it the second time
+        if ( wxPendingDelete.Member(obj) )
+            wxPendingDelete.Erase(node);
+
+        delete obj;
+
+        // Deleting one object may have deleted other pending
+        // objects, so start from beginning of list again.
+        node = wxPendingDelete.GetFirst();
+    }
+}
+
 // ----------------------------------------------------------------------------
 // exception handling
 // ----------------------------------------------------------------------------
@@ -650,7 +706,7 @@ bool wxAppConsoleBase::CheckBuildOptions(const char *optionsSignature,
         wxString progName = wxString::FromAscii(componentName);
         wxString msg;
 
-        msg.Printf(_T("Mismatch between the program and library build versions detected.\nThe library used %s,\nand %s used %s."),
+        msg.Printf(wxT("Mismatch between the program and library build versions detected.\nThe library used %s,\nand %s used %s."),
                    lib.c_str(), progName.c_str(), prog.c_str());
 
         wxLogFatalError(msg.c_str());
@@ -738,16 +794,6 @@ bool wxConsoleAppTraitsBase::HasStderr()
     return true;
 }
 
-void wxConsoleAppTraitsBase::ScheduleForDestroy(wxObject *object)
-{
-    delete object;
-}
-
-void wxConsoleAppTraitsBase::RemoveFromPendingDelete(wxObject * WXUNUSED(object))
-{
-    // nothing to do
-}
-
 // ----------------------------------------------------------------------------
 // wxAppTraits
 // ----------------------------------------------------------------------------
@@ -804,7 +850,7 @@ bool wxAppTraitsBase::ShowAssertDialog(const wxString& msgOriginal)
 
     const wxString stackTrace = GetAssertStackTrace();
     if ( !stackTrace.empty() )
-        msg << _T("\n\nCall stack:\n") << stackTrace;
+        msg << wxT("\n\nCall stack:\n") << stackTrace;
 #endif // wxUSE_STACKWALKER
 
     return DoShowAssertDialog(msg);
@@ -833,29 +879,29 @@ wxString wxAppTraitsBase::GetAssertStackTrace()
         {
             m_stackTrace << wxString::Format
                             (
-                              _T("[%02d] "),
+                              wxT("[%02d] "),
                               wx_truncate_cast(int, frame.GetLevel())
                             );
 
             wxString name = frame.GetName();
             if ( !name.empty() )
             {
-                m_stackTrace << wxString::Format(_T("%-40s"), name.c_str());
+                m_stackTrace << wxString::Format(wxT("%-40s"), name.c_str());
             }
             else
             {
-                m_stackTrace << wxString::Format(_T("%p"), frame.GetAddress());
+                m_stackTrace << wxString::Format(wxT("%p"), frame.GetAddress());
             }
 
             if ( frame.HasSourceLocation() )
             {
-                m_stackTrace << _T('\t')
+                m_stackTrace << wxT('\t')
                              << frame.GetFileName()
-                             << _T(':')
+                             << wxT(':')
                              << frame.GetLine();
             }
 
-            m_stackTrace << _T('\n');
+            m_stackTrace << wxT('\n');
         }
 
     private:
@@ -1087,7 +1133,7 @@ bool DoShowAssertDialog(const wxString& msg)
               wxT("You can also choose [Cancel] to suppress ")
               wxT("further warnings.");
 
-    switch ( ::MessageBox(NULL, msgDlg.wx_str(), _T("wxWidgets Debug Alert"),
+    switch ( ::MessageBox(NULL, msgDlg.wx_str(), wxT("wxWidgets Debug Alert"),
                           MB_YESNOCANCEL | MB_ICONSTOP ) )
     {
         case IDYES:
@@ -1134,16 +1180,16 @@ void ShowAssertDialog(const wxString& file,
 
     // add the function name, if any
     if ( !func.empty() )
-        msg << _T(" in ") << func << _T("()");
+        msg << wxT(" in ") << func << wxT("()");
 
     // and the message itself
     if ( !msgUser.empty() )
     {
-        msg << _T(": ") << msgUser;
+        msg << wxT(": ") << msgUser;
     }
     else // no message given
     {
-        msg << _T('.');
+        msg << wxT('.');
     }
 
 #if wxUSE_THREADS
@@ -1170,7 +1216,7 @@ void ShowAssertDialog(const wxString& file,
     if ( !s_bNoAsserts )
     {
         // send it to the normal log destination
-        wxLogDebug(_T("%s"), msg.c_str());
+        wxLogDebug(wxT("%s"), msg.c_str());
 
         if ( traits )
         {