]> 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.
 
+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:
-    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;
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:
-    wxPyClientData(PyObject* obj) {
+    wxPyClientData(PyObject* obj, bool incref=true) {
         m_obj = obj;
-        Py_INCREF(m_obj);
+        m_incRef = incref;
+        if (incref)
+            Py_INCREF(m_obj);
     }
-
     ~wxPyClientData() {
+
 #ifdef wxPyUSE_EXPORTED_API
         wxPyGetCoreAPIPtr()->p_wxPyClientData_dtor(this);
 #else
@@ -480,6 +482,7 @@ public:
 #endif
     }
     PyObject* m_obj;
+    bool      m_incRef;
 };
 
 
@@ -487,10 +490,10 @@ 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() {
+
 #ifdef wxPyUSE_EXPORTED_API
         wxPyGetCoreAPIPtr()->p_wxPyOORClientData_dtor(this);
 #else
index 5cbe3734c961b6cf15c4c909b88ead803e563cbc..d54c5aa1eb71c90fa49c13022224b007aa94b4a0 100644 (file)
@@ -73,9 +73,9 @@ public:
     }
 
     %extend {
-        void _setOORInfo(PyObject* _self) {
+        void _setOORInfo(PyObject* _self, bool incref=true) {
             if (_self && _self != Py_None) {
-                self->SetClientObject(new wxPyOORClientData(_self));
+                self->SetClientObject(new wxPyOORClientData(_self, incref));
             }
             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);
-    
+
+wxPyTimer::wxPyTimer(wxEvtHandler *owner, int id)
+    : wxTimer(owner, id)
+{
+    if (owner == NULL) SetOwner(this);
+}
+
+
 void wxPyTimer::Notify() {
     bool found;
     bool blocked = wxPyBeginBlockThreads();
@@ -58,7 +65,11 @@ MustHaveApp(wxPyTimer);
 %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
@@ -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);
+
+    // Destructor.  
     virtual ~wxPyTimer();
 
     void _setCallbackInfo(PyObject* self, PyObject* _class, int incref=1);
@@ -101,6 +114,11 @@ public:
     // 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;
@@ -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;
-        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
@@ -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!?!?!"));