From ca6859b8313eb3174516fd4ec2804dd55d3773f0 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Fri, 31 Dec 2010 18:31:29 +0000 Subject: [PATCH] Add a tool that generates a wrapper around a wxList derived class, such as wxWindowList. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@66507 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- etg/defs.py | 1 - etg/window.py | 13 +++++- etgtools/tweaker_tools.py | 94 +++++++++++++++++++++++++++++++++++++++ sip/gen/defs.sip | 1 - sip/gen/window.sip | 78 ++++++++++++++++++++++++++++++++ 5 files changed, 183 insertions(+), 4 deletions(-) diff --git a/etg/defs.py b/etg/defs.py index 3600d3df..e08d1b34 100644 --- a/etg/defs.py +++ b/etg/defs.py @@ -64,7 +64,6 @@ def run(): class wxMenu; class wxCursor; class wxBitmap; - class wxWindowList; class wxSizer; class wxPalette; class wxAcceleratorTable; diff --git a/etg/window.py b/etg/window.py index b86feece..4194d213 100644 --- a/etg/window.py +++ b/etg/window.py @@ -220,14 +220,15 @@ def run(): ##c.addProperty('GtkWidget GetGtkWidget') - # We probably won't ever need most of the wxWindow virtuals to be # overridable in Python, so we'll clear all the virtual flags here and add # back those that we want to keep in the next step. tools.removeVirtuals(c) tools.addWindowVirtuals(c) - + + #----------------------------------------------------------------------- + # Other stuff module.addPyCode('''\ class FrozenWindow(object): @@ -245,11 +246,19 @@ def run(): self._win.Thaw() ''') + + # Add a wrapper for wxWindowList and a new iterator class for it that + # makes wxWindowList quack like a read-only Python sequence. + module.addItem(tools.wxListWrapperTemplate('wxWindowList', 'wxWindow')) + + + #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module) + #--------------------------------------------------------------------------- if __name__ == '__main__': run() diff --git a/etgtools/tweaker_tools.py b/etgtools/tweaker_tools.py index ec7953d5..42643e20 100644 --- a/etgtools/tweaker_tools.py +++ b/etgtools/tweaker_tools.py @@ -416,3 +416,97 @@ def convertFourDoublesTemplate(CLASS): +#--------------------------------------------------------------------------- +# Templates for creating wrappers for type-specific wxList and wxArray classes + + +def wxListWrapperTemplate(ListClass, ItemClass, RealItemClass=None): + if RealItemClass is None: + RealItemClass = ItemClass + + # *** TODO: This can probably be done in a way that is not SIP-specfic. Try + # creating extractor objects from scratch and attach cppMethods to them. + + return extractors.WigCode('''\ +class {ListClass}_iterator /Abstract/ +{{ + // the C++ implementation of this class + %TypeHeaderCode + class {ListClass}_iterator {{ + public: + {ListClass}_iterator({ListClass}::compatibility_iterator start) + : m_node(start) {{}} + + {ItemClass}* next() {{ + {RealItemClass}* obj = NULL; + if (m_node) {{ + obj = m_node->GetData(); + m_node = m_node->GetNext(); + }} + else PyErr_SetString(PyExc_StopIteration, ""); + return ({ItemClass}*)obj; + }} + private: + {ListClass}::compatibility_iterator m_node; + }}; + %End +public: + {ItemClass}* next(); +}}; + +class {ListClass} +{{ +public: + int __len__(); + %MethodCode + sipRes = sipCpp->size(); + %End + + {ItemClass}* __getitem__(size_t index); + %MethodCode + if (index < sipCpp->size()) {{ + {ListClass}::compatibility_iterator node = sipCpp->Item(index); + if (node) + sipRes = ({ItemClass}*)node->GetData(); + }} + PyErr_SetString(PyExc_IndexError, "sequence index out of range"); + sipError = sipErrorFail; + %End + + int __contains__(const {ItemClass}* obj); + %MethodCode + {ListClass}::compatibility_iterator node; + node = sipCpp->Find(({RealItemClass}*)obj); + sipRes = node != NULL; + %End + + {ListClass}_iterator* __iter__() /Factory/; + %MethodCode + sipRes = new {ListClass}_iterator(sipCpp->GetFirst()); + %End + + // TODO: add support for index(value, [start, [stop]]) + int index({ItemClass}* obj); + %MethodCode + int idx = sipCpp->IndexOf(({RealItemClass}*)obj); + if (idx == wxNOT_FOUND) {{ + sipError = sipErrorFail; + PyErr_SetString(PyExc_ValueError, + "sequence.index(x): x not in sequence"); + }} + sipRes = idx; + %End +}}; + +%Extract(id=pycode) +def _{ListClass}___repr__(self): + return "{ListClass}: " + repr(list(self)) +{ListClass}.__repr__ = _{ListClass}___repr__ +del _{ListClass}___repr__ +%End +'''.format(**locals())) + + + + +#--------------------------------------------------------------------------- diff --git a/sip/gen/defs.sip b/sip/gen/defs.sip index 4671805b..1b8f7bb0 100644 --- a/sip/gen/defs.sip +++ b/sip/gen/defs.sip @@ -24,7 +24,6 @@ class wxMenu; class wxCursor; class wxBitmap; - class wxWindowList; class wxSizer; class wxPalette; class wxAcceleratorTable; diff --git a/sip/gen/window.sip b/sip/gen/window.sip index 7043d68c..17e967e3 100644 --- a/sip/gen/window.sip +++ b/sip/gen/window.sip @@ -1156,6 +1156,84 @@ class FrozenWindow(object): %End +class wxWindowList_iterator /Abstract/ +{ + // the C++ implementation of this class + %TypeHeaderCode + class wxWindowList_iterator { + public: + wxWindowList_iterator(wxWindowList::compatibility_iterator start) + : m_node(start) {} + + wxWindow* next() { + wxWindow* obj = NULL; + if (m_node) { + obj = m_node->GetData(); + m_node = m_node->GetNext(); + } + else PyErr_SetString(PyExc_StopIteration, ""); + return (wxWindow*)obj; + } + private: + wxWindowList::compatibility_iterator m_node; + }; + %End +public: + wxWindow* next(); +}; + +class wxWindowList +{ +public: + int __len__(); + %MethodCode + sipRes = sipCpp->size(); + %End + + wxWindow* __getitem__(size_t index); + %MethodCode + if (index < sipCpp->size()) { + wxWindowList::compatibility_iterator node = sipCpp->Item(index); + if (node) + sipRes = (wxWindow*)node->GetData(); + } + PyErr_SetString(PyExc_IndexError, "sequence index out of range"); + sipError = sipErrorFail; + %End + + int __contains__(const wxWindow* obj); + %MethodCode + wxWindowList::compatibility_iterator node; + node = sipCpp->Find((wxWindow*)obj); + sipRes = node != NULL; + %End + + wxWindowList_iterator* __iter__() /Factory/; + %MethodCode + sipRes = new wxWindowList_iterator(sipCpp->GetFirst()); + %End + + // TODO: add support for index(value, [start, [stop]]) + int index(wxWindow* obj); + %MethodCode + int idx = sipCpp->IndexOf((wxWindow*)obj); + if (idx == wxNOT_FOUND) { + sipError = sipErrorFail; + PyErr_SetString(PyExc_ValueError, + "sequence.index(x): x not in sequence"); + } + sipRes = idx; + %End +}; + +%Extract(id=pycode) +def _wxWindowList___repr__(self): + return "wxWindowList: " + repr(list(self)) +wxWindowList.__repr__ = _wxWindowList___repr__ +del _wxWindowList___repr__ +%End + + //---------------------------------------------------------------------------