]> git.saurik.com Git - wxWidgets.git/commitdiff
Allow the OOR reference to be saved without doing an INCREF. This
authorRobin Dunn <robin@alldunn.com>
Mon, 20 Dec 2004 22:50:29 +0000 (22:50 +0000)
committerRobin Dunn <robin@alldunn.com>
Mon, 20 Dec 2004 22:50:29 +0000 (22:50 +0000)
solves the circular reference problem with wx.Timer.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31095 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

wxPython/docs/CHANGES.txt
wxPython/include/wx/wxPython/pyclasses.h
wxPython/include/wx/wxPython/wxPython_int.h
wxPython/src/_evthandler.i
wxPython/src/_timer.i
wxPython/src/helpers.cpp

index a2da7e6d48575c4fb4262463a207201670ebc84a..62f5b951161fe18964115e6fc10107568a5640f8 100644 (file)
@@ -87,6 +87,22 @@ maintainable and hopefully less buggy.  The position of the labels has
 also been changed in order to better comply with Microsoft's examples
 of how to use the control.
 
 also been changed in order to better comply with Microsoft's examples
 of how to use the control.
 
+wxMSW:  Fix wx.TreeCtrl to end label editing if the control loses
+focus (a slightly modified patch 1084592.)
+
+Added wx.EXEC_NODISABLE flag for wx.Execute, which will prevent all
+the app's windows being disabled while a synchronous child process is
+running. 
+
+wxMSW: Much work to correct painting (or leaving transparent) of
+control backgrounds, properly using background themes on XP, etc.
+
+Fixed a circular reference problem with wx.Timer.  It will now
+completely cleanup after itself when the last reference to the timer
+is removed.  If you were previously using timer.Destroy() to cleanup
+your timers it will no longer work.  Instead you should hold a
+reference to the timer and then del the reference when you are
+finished with the timer.
 
 
 
 
 
 
index 2859590f0980421619675b505639338d2a3104bf..8ec04a4fdef3f5d337f657da9e444ab19877a76d 100644 (file)
@@ -79,11 +79,7 @@ public:
 class wxPyTimer : public wxTimer
 {
 public:
 class wxPyTimer : public wxTimer
 {
 public:
-    wxPyTimer(wxEvtHandler *owner=NULL, int id = -1)
-        : wxTimer(owner, id)
-    {
-        if (owner == NULL) SetOwner(this);
-    }
+    wxPyTimer(wxEvtHandler *owner=NULL, int id = -1);
 
     DEC_PYCALLBACK__(Notify);
     PYPRIVATE;
 
     DEC_PYCALLBACK__(Notify);
     PYPRIVATE;
index ff605d8b4b566526da550cbb5c2102d6a61de9ca..336c20c33e8bc40bb1d5555337d42496cba04404 100644 (file)
@@ -467,12 +467,14 @@ public:
 // A wxClientData that holds a refernece to a Python object
 class wxPyClientData : public wxClientData {
 public:
 // A wxClientData that holds a refernece to a Python object
 class wxPyClientData : public wxClientData {
 public:
-    wxPyClientData(PyObject* obj) {
+    wxPyClientData(PyObject* obj, bool incref=true) {
         m_obj = obj;
         m_obj = obj;
-        Py_INCREF(m_obj);
+        m_incRef = incref;
+        if (incref)
+            Py_INCREF(m_obj);
     }
     }
-
     ~wxPyClientData() {
     ~wxPyClientData() {
+
 #ifdef wxPyUSE_EXPORTED_API
         wxPyGetCoreAPIPtr()->p_wxPyClientData_dtor(this);
 #else
 #ifdef wxPyUSE_EXPORTED_API
         wxPyGetCoreAPIPtr()->p_wxPyClientData_dtor(this);
 #else
@@ -480,6 +482,7 @@ public:
 #endif
     }
     PyObject* m_obj;
 #endif
     }
     PyObject* m_obj;
+    bool      m_incRef;
 };
 
 
 };
 
 
@@ -487,10 +490,10 @@ public:
 // OOR magic on the Python Object.
 class wxPyOORClientData : public wxPyClientData {
 public:
 // OOR magic on the Python Object.
 class wxPyOORClientData : public wxPyClientData {
 public:
-    wxPyOORClientData(PyObject* obj)
-        : wxPyClientData(obj) {}
-
+    wxPyOORClientData(PyObject* obj, bool incref=true)
+        : wxPyClientData(obj, incref) {}
     ~wxPyOORClientData() {
     ~wxPyOORClientData() {
+
 #ifdef wxPyUSE_EXPORTED_API
         wxPyGetCoreAPIPtr()->p_wxPyOORClientData_dtor(this);
 #else
 #ifdef wxPyUSE_EXPORTED_API
         wxPyGetCoreAPIPtr()->p_wxPyOORClientData_dtor(this);
 #else
index 5cbe3734c961b6cf15c4c909b88ead803e563cbc..d54c5aa1eb71c90fa49c13022224b007aa94b4a0 100644 (file)
@@ -73,9 +73,9 @@ public:
     }
 
     %extend {
     }
 
     %extend {
-        void _setOORInfo(PyObject* _self) {
+        void _setOORInfo(PyObject* _self, bool incref=true) {
             if (_self && _self != Py_None) {
             if (_self && _self != Py_None) {
-                self->SetClientObject(new wxPyOORClientData(_self));
+                self->SetClientObject(new wxPyOORClientData(_self, incref));
             }
             else {
                 wxPyOORClientData* data = (wxPyOORClientData*)self->GetClientObject();
             }
             else {
                 wxPyOORClientData* data = (wxPyOORClientData*)self->GetClientObject();
index b84e0db64b13bbad2a045aee862c814b9865daee..910a3864cad50475c662ded96c665c76c7cc67ed 100644 (file)
@@ -35,7 +35,14 @@ enum {
 //IMP_PYCALLBACK__(wxPyTimer, wxTimer, Notify);
 
 IMPLEMENT_ABSTRACT_CLASS(wxPyTimer, wxTimer);
 //IMP_PYCALLBACK__(wxPyTimer, wxTimer, Notify);
 
 IMPLEMENT_ABSTRACT_CLASS(wxPyTimer, wxTimer);
-    
+
+wxPyTimer::wxPyTimer(wxEvtHandler *owner, int id)
+    : wxTimer(owner, id)
+{
+    if (owner == NULL) SetOwner(this);
+}
+
+
 void wxPyTimer::Notify() {
     bool found;
     bool blocked = wxPyBeginBlockThreads();
 void wxPyTimer::Notify() {
     bool found;
     bool blocked = wxPyBeginBlockThreads();
@@ -58,7 +65,11 @@ MustHaveApp(wxPyTimer);
 %name(Timer) class wxPyTimer : public wxEvtHandler
 {
 public:
 %name(Timer) class wxPyTimer : public wxEvtHandler
 {
 public:
-    %pythonAppend wxPyTimer         "self._setCallbackInfo(self, Timer, 0); self._setOORInfo(self)"
+    // Don't let the OOR or callback info hold references to the object so
+    // there won't be a reference cycle and it can clean itself up via normal
+    // Python refcounting
+    %pythonAppend wxPyTimer
+        "self._setCallbackInfo(self, Timer, 0); self._setOORInfo(self, 0)"
 
 
     // if you don't call SetOwner() or provide an owner in the contstructor
 
 
     // if you don't call SetOwner() or provide an owner in the contstructor
@@ -66,6 +77,8 @@ public:
     // notification.  If the owner is set then it will get the timer
     // notifications which can be handled with EVT_TIMER.
     wxPyTimer(wxEvtHandler *owner=NULL, int id = -1);
     // notification.  If the owner is set then it will get the timer
     // notifications which can be handled with EVT_TIMER.
     wxPyTimer(wxEvtHandler *owner=NULL, int id = -1);
+
+    // Destructor.  
     virtual ~wxPyTimer();
 
     void _setCallbackInfo(PyObject* self, PyObject* _class, int incref=1);
     virtual ~wxPyTimer();
 
     void _setCallbackInfo(PyObject* self, PyObject* _class, int incref=1);
@@ -101,6 +114,11 @@ public:
     // return the timer ID
     int GetId() const;
 
     // return the timer ID
     int GetId() const;
 
+    %pythoncode {
+        def Destroy():
+            """NO-OP: Timers must be destroyed by normal refrence counting"""
+            pass
+    }
 };
 
 
 };
 
 
index ef5fb35e32d9c09e9e1e3dfa56d70bcb9612edfc..d3f1aebbb8df7ea308972242060acdc7076839f9 100644 (file)
@@ -866,10 +866,8 @@ bool wxPyCheckForApp() {
 
 //---------------------------------------------------------------------------
 
 
 //---------------------------------------------------------------------------
 
-
-void wxPyClientData_dtor(wxPyClientData* self) {
-    if (! wxPyDoingCleanup) {           // Don't do it during cleanup as Python
-                                        // may have already garbage collected the object...
+void wxPyUserData_dtor(wxPyUserData* self) {
+    if (! wxPyDoingCleanup) {
         bool blocked = wxPyBeginBlockThreads();
         Py_DECREF(self->m_obj);
         self->m_obj = NULL;
         bool blocked = wxPyBeginBlockThreads();
         Py_DECREF(self->m_obj);
         self->m_obj = NULL;
@@ -877,16 +875,21 @@ void wxPyClientData_dtor(wxPyClientData* self) {
     }
 }
 
     }
 }
 
-void wxPyUserData_dtor(wxPyUserData* self) {
-    if (! wxPyDoingCleanup) {
-        bool blocked = wxPyBeginBlockThreads();
-        Py_DECREF(self->m_obj);
+
+void wxPyClientData_dtor(wxPyClientData* self) {
+    if (! wxPyDoingCleanup) {           // Don't do it during cleanup as Python
+                                        // may have already garbage collected the object...
+        if (self->m_incRef) {
+            bool blocked = wxPyBeginBlockThreads();
+            Py_DECREF(self->m_obj);
+            wxPyEndBlockThreads(blocked);
+        }
         self->m_obj = NULL;
         self->m_obj = NULL;
-        wxPyEndBlockThreads(blocked);
     }
 }
 
 
     }
 }
 
 
+
 // This is called when an OOR controled object is being destroyed.  Although
 // the C++ object is going away there is no way to force the Python object
 // (and all references to it) to die too.  This causes problems (crashes) in
 // This is called when an OOR controled object is being destroyed.  Although
 // the C++ object is going away there is no way to force the Python object
 // (and all references to it) to die too.  This causes problems (crashes) in
@@ -909,8 +912,9 @@ void wxPyOORClientData_dtor(wxPyOORClientData* self) {
     }
 
 
     }
 
 
-    // Only if there is more than one reference to the object
-    if ( !wxPyDoingCleanup && self->m_obj->ob_refcnt > 1 ) {
+    // Only if there is more than one reference to the object and we are
+    // holding the OOR reference:
+    if ( !wxPyDoingCleanup && self->m_obj->ob_refcnt > 1 && self->m_incRef) {
         // bool isInstance = wxPyInstance_Check(self->m_obj);
         // TODO same here
         //wxASSERT_MSG(isInstance, wxT("m_obj not an instance!?!?!"));
         // bool isInstance = wxPyInstance_Check(self->m_obj);
         // TODO same here
         //wxASSERT_MSG(isInstance, wxT("m_obj not an instance!?!?!"));