From 2aab8f16ac7200349b41af957396029c176a9b9d Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Sun, 21 Oct 2001 03:56:07 +0000 Subject: [PATCH] Added wxClientDataContainer to wxSizer, so sizers can now do OOR in wxPython too. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@12130 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/clntdata.h | 8 +++--- include/wx/sizer.h | 10 ++++---- src/common/clntdata.cpp | 4 +-- wxPython/demo/OOR.py | 11 ++++++++ wxPython/src/_extras.py | 3 ++- wxPython/src/helpers.cpp | 51 ++++++++++--------------------------- wxPython/src/msw/sizers.cpp | 36 ++++++++++++++++++++++++++ wxPython/src/msw/sizers.py | 9 +++++++ wxPython/src/msw/wx.py | 3 ++- wxPython/src/sizers.i | 14 ++++++++-- 10 files changed, 98 insertions(+), 51 deletions(-) diff --git a/include/wx/clntdata.h b/include/wx/clntdata.h index 8f2d44ded5..a632635ad8 100644 --- a/include/wx/clntdata.h +++ b/include/wx/clntdata.h @@ -50,12 +50,14 @@ private: -#if 0 // This class is a mixin that provides storage and management of "client // data." The client data stored can either be a pointer to a wxClientData // object in which case it is managed by the container (i.e. it will delete // the data when it's destroyed) or an untyped pointer which won't be deleted -// by the window - but not both of them +// by the container - but not both of them +// +// NOTE: This functionality is currently duplicated in wxEvtHandler in order +// to avoid having more than one vtable in that class heirachy. class WXDLLEXPORT wxClientDataContainer { @@ -92,7 +94,7 @@ protected: wxClientDataType m_clientDataType; }; -#endif + // ---------------------------------------------------------------------------- #endif diff --git a/include/wx/sizer.h b/include/wx/sizer.h index bcdeb0339c..ccfb67985b 100644 --- a/include/wx/sizer.h +++ b/include/wx/sizer.h @@ -61,15 +61,15 @@ public: { m_ratio = (width && height) ? ((float) width / (float) height) : 1; } void SetRatio( wxSize size ) { m_ratio = (size.x && size.y) ? ((float) size.x / (float) size.y) : 1; } - void SetRatio( float ratio ) + void SetRatio( float ratio ) { m_ratio = ratio; } - float GetRatio() const + float GetRatio() const { return m_ratio; } bool IsWindow(); bool IsSizer(); bool IsSpacer(); - + void SetInitSize( int x, int y ) { m_minSize.x = x; m_minSize.y = y; } void SetOption( int option ) @@ -112,7 +112,7 @@ protected: // is shrinked. it is safer to preserve initial value. float m_ratio; wxObject *m_userData; - + private: DECLARE_CLASS(wxSizerItem); }; @@ -121,7 +121,7 @@ private: // wxSizer //--------------------------------------------------------------------------- -class WXDLLEXPORT wxSizer: public wxObject +class WXDLLEXPORT wxSizer: public wxObject, public wxClientDataContainer { public: wxSizer(); diff --git a/src/common/clntdata.cpp b/src/common/clntdata.cpp index d7a984d672..782f518465 100644 --- a/src/common/clntdata.cpp +++ b/src/common/clntdata.cpp @@ -24,7 +24,7 @@ // ---------------------------------------------------------------------------- -#if 0 + wxClientDataContainer::wxClientDataContainer() { @@ -81,7 +81,7 @@ void *wxClientDataContainer::DoGetClientData() const return m_clientData; } -#endif + // ---------------------------------------------------------------------------- diff --git a/wxPython/demo/OOR.py b/wxPython/demo/OOR.py index 7306ed9efd..9b4088fb8d 100644 --- a/wxPython/demo/OOR.py +++ b/wxPython/demo/OOR.py @@ -32,6 +32,8 @@ class TestPanel(wxPanel): self.SetSizer(sizer) self.SetAutoLayout(true) + self.sizer = sizer # save it for testing later + EVT_BUTTON(self, BTN1, self.OnFindButton1) EVT_BUTTON(self, BTN2, self.OnFindButton2) @@ -68,6 +70,15 @@ class TestPanel(wxPanel): else: self.log.write("The objects are NOT the same! \n") + sizer = self.GetSizer() + if sizer is None: + self.log.write("***** OOPS! None returned...\n") + return + if sizer is self.sizer: + self.log.write("The objects are the same! \n") + else: + self.log.write("The objects are NOT the same! \n") + #---------------------------------------------------------------------- diff --git a/wxPython/src/_extras.py b/wxPython/src/_extras.py index cc7b8ce623..0e8da6d20e 100644 --- a/wxPython/src/_extras.py +++ b/wxPython/src/_extras.py @@ -637,7 +637,8 @@ def wxPyTypeCast(obj, typeStr): theClass = globals()[typeStr+"Ptr"] typeStr = __wxPyPtrTypeMap.get(typeStr, typeStr) if hasattr(obj, "this"): - if obj.__class__ is theClass: # if already the right type then just return it + # if already the right type then just return it + if isinstance(obj, theClass) or obj.__class__ is theClass: return obj newPtr = ptrcast(obj.this, typeStr+"_p") else: diff --git a/wxPython/src/helpers.cpp b/wxPython/src/helpers.cpp index e4c6354b20..95c921d17b 100644 --- a/wxPython/src/helpers.cpp +++ b/wxPython/src/helpers.cpp @@ -294,6 +294,8 @@ PyObject* wxPyMake_wxObject(wxObject* source) { bool isEvtHandler = FALSE; if (source) { + // If it's derived from wxEvtHandler then there may + // already be a pointer to a Python objec that we can use. if (wxIsKindOf(source, wxEvtHandler)) { wxEvtHandler* eh = (wxEvtHandler*)source; wxPyClientData* data = (wxPyClientData*)eh->GetClientObject(); @@ -302,8 +304,19 @@ PyObject* wxPyMake_wxObject(wxObject* source) { Py_INCREF(target); } } + else if (wxIsKindOf(source, wxSizer)) { + // wxSizers also track the original object + wxSizer* sz = (wxSizer*)source; + wxPyClientData* data = (wxPyClientData*)sz->GetClientObject(); + if (data) { + target = data->m_obj; + Py_INCREF(target); + } + } if (! target) { + // Otherwise make it the old fashioned way by making a + // new shadow object and putting this pointer in it. wxClassInfo* info = source->GetClassInfo(); wxChar* name = (wxChar*)info->GetClassName(); PyObject* klass = wxPyClassExists(name); @@ -391,42 +404,6 @@ PyObject* wxPyConstructObject(void* ptr, //--------------------------------------------------------------------------- -// static PyThreadState* myPyThreadState_Get() { -// PyThreadState* current; -// current = PyThreadState_Swap(NULL); -// PyThreadState_Swap(current); -// return current; -// } - - -// bool wxPyRestoreThread() { -// // NOTE: The Python API docs state that if a thread already has the -// // interpreter lock and calls PyEval_RestoreThread again a deadlock -// // occurs, so I put in this code as a guard condition since there are -// // many possibilites for nested events and callbacks in wxPython. If -// // The current thread is our thread, then we can assume that we -// // already have the lock. (I hope!) -// // -// #ifdef WXP_WITH_THREAD -// if (wxPyEventThreadState != myPyThreadState_Get()) { -// PyEval_AcquireThread(wxPyEventThreadState); -// return TRUE; -// } -// else -// #endif -// return FALSE; -// } - - -// void wxPySaveThread(bool doSave) { -// #ifdef WXP_WITH_THREAD -// if (doSave) { -// PyEval_ReleaseThread(wxPyEventThreadState); -// } -// #endif -// } - - wxPyTState* wxPyBeginBlockThreads() { wxPyTState* state = NULL; @@ -619,7 +596,7 @@ void wxPyCBH_delete(wxPyCallbackHelper* cbh) { //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -// These classes can be derived from in Python and passed through the event +// These event classes can be derived from in Python and passed through the event // system without losing anything. They do this by keeping a reference to // themselves and some special case handling in wxPyCallback::EventThunker. diff --git a/wxPython/src/msw/sizers.cpp b/wxPython/src/msw/sizers.cpp index 1460f4f14c..5690d72d71 100644 --- a/wxPython/src/msw/sizers.cpp +++ b/wxPython/src/msw/sizers.cpp @@ -837,6 +837,41 @@ static void *SwigwxSizerTowxObject(void *ptr) { return (void *) dest; } +static void wxSizer__setOORInfo(wxSizer *self,PyObject * _self) { + self->SetClientObject(new wxPyClientData(_self)); + } +static PyObject *_wrap_wxSizer__setOORInfo(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject * _resultobj; + wxSizer * _arg0; + PyObject * _arg1; + PyObject * _argo0 = 0; + PyObject * _obj1 = 0; + char *_kwnames[] = { "self","_self", NULL }; + + self = self; + if(!PyArg_ParseTupleAndKeywords(args,kwargs,"OO:wxSizer__setOORInfo",_kwnames,&_argo0,&_obj1)) + return NULL; + if (_argo0) { + if (_argo0 == Py_None) { _arg0 = NULL; } + else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxSizer_p")) { + PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxSizer__setOORInfo. Expected _wxSizer_p."); + return NULL; + } + } +{ + _arg1 = _obj1; +} +{ + wxPy_BEGIN_ALLOW_THREADS; + wxSizer__setOORInfo(_arg0,_arg1); + + wxPy_END_ALLOW_THREADS; + if (PyErr_Occurred()) return NULL; +} Py_INCREF(Py_None); + _resultobj = Py_None; + return _resultobj; +} + static void wxSizer_Destroy(wxSizer *self) { delete self; } static PyObject *_wrap_wxSizer_Destroy(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject * _resultobj; @@ -2912,6 +2947,7 @@ static PyMethodDef sizerscMethods[] = { { "wxSizer_AddSizer", (PyCFunction) _wrap_wxSizer_AddSizer, METH_VARARGS | METH_KEYWORDS }, { "wxSizer_AddWindow", (PyCFunction) _wrap_wxSizer_AddWindow, METH_VARARGS | METH_KEYWORDS }, { "wxSizer_Destroy", (PyCFunction) _wrap_wxSizer_Destroy, METH_VARARGS | METH_KEYWORDS }, + { "wxSizer__setOORInfo", (PyCFunction) _wrap_wxSizer__setOORInfo, METH_VARARGS | METH_KEYWORDS }, { "wxSizerItem_GetUserData", (PyCFunction) _wrap_wxSizerItem_GetUserData, METH_VARARGS | METH_KEYWORDS }, { "wxSizerItem_SetBorder", (PyCFunction) _wrap_wxSizerItem_SetBorder, METH_VARARGS | METH_KEYWORDS }, { "wxSizerItem_SetFlag", (PyCFunction) _wrap_wxSizerItem_SetFlag, METH_VARARGS | METH_KEYWORDS }, diff --git a/wxPython/src/msw/sizers.py b/wxPython/src/msw/sizers.py index e0105a3495..2eaac713ff 100644 --- a/wxPython/src/msw/sizers.py +++ b/wxPython/src/msw/sizers.py @@ -103,6 +103,9 @@ class wxSizerPtr(wxObjectPtr): def __init__(self,this): self.this = this self.thisown = 0 + def _setOORInfo(self, *_args, **_kwargs): + val = apply(sizersc.wxSizer__setOORInfo,(self,) + _args, _kwargs) + return val def Destroy(self, *_args, **_kwargs): val = apply(sizersc.wxSizer_Destroy,(self,) + _args, _kwargs) return val @@ -252,6 +255,7 @@ class wxPySizer(wxPySizerPtr): self.this = apply(sizersc.new_wxPySizer,_args,_kwargs) self.thisown = 1 self._setCallbackInfo(self, wxPySizer) + self._setOORInfo(self) @@ -276,6 +280,7 @@ class wxBoxSizer(wxBoxSizerPtr): def __init__(self,*_args,**_kwargs): self.this = apply(sizersc.new_wxBoxSizer,_args,_kwargs) self.thisown = 1 + self._setOORInfo(self) @@ -300,6 +305,7 @@ class wxStaticBoxSizer(wxStaticBoxSizerPtr): def __init__(self,*_args,**_kwargs): self.this = apply(sizersc.new_wxStaticBoxSizer,_args,_kwargs) self.thisown = 1 + self._setOORInfo(self) @@ -324,6 +330,7 @@ class wxNotebookSizer(wxNotebookSizerPtr): def __init__(self,*_args,**_kwargs): self.this = apply(sizersc.new_wxNotebookSizer,_args,_kwargs) self.thisown = 1 + self._setOORInfo(self) @@ -369,6 +376,7 @@ class wxGridSizer(wxGridSizerPtr): def __init__(self,*_args,**_kwargs): self.this = apply(sizersc.new_wxGridSizer,_args,_kwargs) self.thisown = 1 + self._setOORInfo(self) @@ -402,6 +410,7 @@ class wxFlexGridSizer(wxFlexGridSizerPtr): def __init__(self,*_args,**_kwargs): self.this = apply(sizersc.new_wxFlexGridSizer,_args,_kwargs) self.thisown = 1 + self._setOORInfo(self) diff --git a/wxPython/src/msw/wx.py b/wxPython/src/msw/wx.py index e5f773b490..59779e933e 100644 --- a/wxPython/src/msw/wx.py +++ b/wxPython/src/msw/wx.py @@ -1499,7 +1499,8 @@ def wxPyTypeCast(obj, typeStr): theClass = globals()[typeStr+"Ptr"] typeStr = __wxPyPtrTypeMap.get(typeStr, typeStr) if hasattr(obj, "this"): - if obj.__class__ is theClass: # if already the right type then just return it + # if already the right type then just return it + if isinstance(obj, theClass) or obj.__class__ is theClass: return obj newPtr = ptrcast(obj.this, typeStr+"_p") else: diff --git a/wxPython/src/sizers.i b/wxPython/src/sizers.i index c1a6c05373..0a6f3f15cc 100644 --- a/wxPython/src/sizers.i +++ b/wxPython/src/sizers.i @@ -93,6 +93,12 @@ public: // wxSizer(); **** abstract, can't instantiate // ~wxSizer(); + %addmethods { + void _setOORInfo(PyObject* _self) { + self->SetClientObject(new wxPyClientData(_self)); + } + } + %addmethods { void Destroy() { delete self; } @@ -268,6 +274,7 @@ public: wxPySizer(); void _setCallbackInfo(PyObject* self, PyObject* _class); %pragma(python) addtomethod = "__init__:self._setCallbackInfo(self, wxPySizer)" + %pragma(python) addtomethod = "__init__:self._setOORInfo(self)" }; @@ -276,6 +283,7 @@ public: class wxBoxSizer : public wxSizer { public: wxBoxSizer(int orient = wxHORIZONTAL); + %pragma(python) addtomethod = "__init__:self._setOORInfo(self)" int GetOrientation(); void RecalcSizes(); wxSize CalcMin(); @@ -286,6 +294,7 @@ public: class wxStaticBoxSizer : public wxBoxSizer { public: wxStaticBoxSizer(wxStaticBox *box, int orient = wxHORIZONTAL); + %pragma(python) addtomethod = "__init__:self._setOORInfo(self)" wxStaticBox *GetStaticBox(); void RecalcSizes(); wxSize CalcMin(); @@ -296,10 +305,9 @@ public: class wxNotebookSizer: public wxSizer { public: wxNotebookSizer( wxNotebook *nb ); - + %pragma(python) addtomethod = "__init__:self._setOORInfo(self)" void RecalcSizes(); wxSize CalcMin(); - wxNotebook *GetNotebook(); }; @@ -309,6 +317,7 @@ class wxGridSizer: public wxSizer { public: wxGridSizer( int rows=1, int cols=0, int vgap=0, int hgap=0 ); + %pragma(python) addtomethod = "__init__:self._setOORInfo(self)" void RecalcSizes(); wxSize CalcMin(); @@ -329,6 +338,7 @@ class wxFlexGridSizer: public wxGridSizer { public: wxFlexGridSizer( int rows=1, int cols=0, int vgap=0, int hgap=0 ); + %pragma(python) addtomethod = "__init__:self._setOORInfo(self)" void RecalcSizes(); wxSize CalcMin(); -- 2.45.2