diff --git a/TODO.txt b/TODO.txt index c0941ff5..8749ca75 100644 --- a/TODO.txt +++ b/TODO.txt @@ -112,10 +112,6 @@ other dev stuff created/used that should not be done before there is an application object. - * Move PyEvent and PyCommandEvent classes to an etg script and build them - using extractor objects so they will be seen by the document generator and - others. - * Locate and/or add items for the various functions and things in Classic's _functions.i module. diff --git a/etg/pyevent.py b/etg/pyevent.py new file mode 100644 index 00000000..df88dbe5 --- /dev/null +++ b/etg/pyevent.py @@ -0,0 +1,135 @@ +#--------------------------------------------------------------------------- +# Name: etg/pyevent.py +# Author: Robin Dunn +# +# Created: 02-Nov-2012 +# Copyright: (c) 2012 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools +from etgtools.extractors import ClassDef, MethodDef, ParamDef + +PACKAGE = "wx" +MODULE = "_core" +NAME = "pyevent" # Base name of the file to generate to for this script +DOCSTRING = "" + +# The classes and/or the basename of the Doxygen XML files to be processed by +# this script. +ITEMS = [ ] + +#--------------------------------------------------------------------------- + +def run(): + # Parse the XML file(s) building a collection of Extractor objects + module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) + etgtools.parseDoxyXML(module, ITEMS) + + #----------------------------------------------------------------- + # Tweak the parsed meta objects in the module object as needed for + # customizing the generated code and docstrings. + + cls = ClassDef(name='wxPyEvent', bases=['wxEvent'], + briefDoc="""\ + wx.PyEvent can be used as a base class for implementing custom + event types in Python. You should derive from this class instead + of `wx.Event` because this class is Python-aware and is able to + transport its Python bits safely through the wxWidgets event + system and have them still be there when the event handler is + invoked. Note that since wx.PyEvent is taking care of preserving + the extra attributes that have been set then you do not need to + override the Clone method in your derived classes. + + :see: `wx.PyCommandEvent`""", + items=[ + MethodDef(name='wxPyEvent', isCtor=True, items=[ + ParamDef(type='int', name='id', default='0'), + ParamDef(type='wxEventType', name='evenType', default='wxEVT_NULL'), + ]), + + MethodDef(name='__getattr__', type='PyObject*', items=[ + ParamDef(type='PyObject*', name='name'),], + cppCode=("sipRes = sipCpp->__getattr__(name);", "sip")), + + MethodDef(name='__delattr__', type='void', items=[ + ParamDef(type='PyObject*', name='name'),], + cppCode=("sipCpp->__delattr__(name);", "sip")), + + MethodDef(name='__setattr__', type='void', items=[ + ParamDef(type='PyObject*', name='name'), + ParamDef(type='PyObject*', name='value'),], + cppCode=("sipCpp->__setattr__(name, value);", "sip")), + + MethodDef(name='Clone', type='wxEvent*', isVirtual=True, isConst=True, factory=True), + MethodDef(name='_getAttrDict', type='PyObject*'), + ]) + + module.addItem(cls) + cls.addCppCode("IMPLEMENT_DYNAMIC_CLASS(wxPyEvent, wxEvent);") + cls.addHeaderCode('#include "pyevent.h"') + + + + cls = ClassDef(name='wxPyCommandEvent', bases=['wxCommandEvent'], + briefDoc="""\ + wx.PyCommandEvent can be used as a base class for implementing + custom event types in Python. You should derive from this class + instead of `wx.CommandEvent` because this class is Python-aware + and is able to transport its Python bits safely through the + wxWidgets event system and have them still be there when the + event handler is invoked. Note that since wx.PyCommandEvent is + taking care of preserving the extra attributes that have been set + then you do not need to override the Clone method in your + derived classes. + + :see: `wx.PyEvent`""", + items=[ + MethodDef(name='wxPyCommandEvent', isCtor=True, items=[ + ParamDef(type='wxEventType', name='evenType', default='wxEVT_NULL'), + ParamDef(type='int', name='id', default='0'), + ]), + + MethodDef(name='__getattr__', type='PyObject*', items=[ + ParamDef(type='PyObject*', name='name'),], + cppCode=("sipRes = sipCpp->__getattr__(name);", "sip")), + + MethodDef(name='__delattr__', type='void', items=[ + ParamDef(type='PyObject*', name='name'),], + cppCode=("sipCpp->__delattr__(name);", "sip")), + + MethodDef(name='__setattr__', type='void', items=[ + ParamDef(type='PyObject*', name='name'), + ParamDef(type='PyObject*', name='value'),], + cppCode=("sipCpp->__setattr__(name, value);", "sip")), + + MethodDef(name='Clone', type='wxEvent*', isVirtual=True, isConst=True, factory=True), + MethodDef(name='_getAttrDict', type='PyObject*'), + ]) + + module.addItem(cls) + cls.addCppCode("IMPLEMENT_DYNAMIC_CLASS(wxPyCommandEvent, wxCommandEvent);") + cls.addHeaderCode('#include "pyevent.h"') + + + + # TODO: Temporary testing code, get rid of this later + module.addCppCode("""\ + wxEvent* testCppClone(wxEvent& evt) { + return evt.Clone(); + }""") + module.addItem(etgtools.WigCode("wxEvent* testCppClone(wxEvent& evt);")) + + + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/src/pyevent.h b/src/pyevent.h new file mode 100644 index 00000000..f33c0927 --- /dev/null +++ b/src/pyevent.h @@ -0,0 +1,123 @@ +//-------------------------------------------------------------------------- +// Name: pyevent.h +// Purpose: A set of event classes that can be derived from in Python +// and that preserve their attributes when cloned. +// +// Author: Robin Dunn +// +// Created: 18-Dec-2010 +// Copyright: (c) 2012 by Total Control Software +// Licence: wxWindows license +//-------------------------------------------------------------------------- + +#ifndef PYEVENT_H +#define PYEVENT_H + +// The wxPyEvent and wxPyCommandEvent classes can be derived from in Python +// and passed through the event system without losing anything. + +// This wxPyEvtDict class holds a Python dictionary object and is used to +// store any attributes that are set from Python code for the wx.PyEvent and +// wx.PyCommandEvent classes. This dictionary is used to make it easy to +// transport those attributes over to the clone when wx needs to make a copy +// of the event instance. + +// NOTE: This class is intentionally not exposed to SIP as there is no +// need for it in Python code. Intead we just tell SIP that the __*attr__ +// methods are in the event classes. (See wxPyEvent and wxPyCommandEvent +// below.) + +class wxPyEvtDict +{ +public: + wxPyEvtDict() + { + wxPyThreadBlocker blocker; + m_dict = PyDict_New(); + } + + wxPyEvtDict(const wxPyEvtDict& other) + { + wxPyThreadBlocker blocker; + m_dict = PyDict_Copy(other.m_dict); + } + + ~wxPyEvtDict() + { + wxPyThreadBlocker blocker; + Py_DECREF(m_dict); + m_dict = NULL; + } + + PyObject* _getAttrDict() + { + wxPyThreadBlocker blocker; + Py_INCREF(m_dict); + return m_dict; + } + + PyObject* __getattr__(PyObject* name) + { + PyObject* value = NULL; + wxPyThreadBlocker blocker; + if (PyDict_Contains(m_dict, name)) { + value = PyDict_GetItem(m_dict, name); + Py_INCREF(value); + } + else { + PyErr_SetObject(PyExc_AttributeError, name); + } + return value; + } + + void __setattr__(PyObject* name, PyObject* value) + { + wxPyThreadBlocker blocker; + PyDict_SetItem(m_dict, name, value); + } + + void __delattr__(PyObject* name) + { + wxPyThreadBlocker blocker; + if (PyDict_Contains(m_dict, name)) + PyDict_DelItem(m_dict, name); + else + PyErr_SetObject(PyExc_AttributeError, name); + } + +protected: + PyObject* m_dict; +}; + + +//-------------------------------------------------------------------------- + + +class wxPyEvent : public wxEvent, public wxPyEvtDict +{ + DECLARE_DYNAMIC_CLASS(wxPyEvent) +public: + wxPyEvent(int id=0, wxEventType eventType = wxEVT_NULL) + : wxEvent(id, eventType) {} + + virtual wxEvent* Clone() const { return new wxPyEvent(*this); } +}; + + +//-------------------------------------------------------------------------- + + +class wxPyCommandEvent : public wxCommandEvent, public wxPyEvtDict +{ + DECLARE_DYNAMIC_CLASS(wxPyCommandEvent) +public: + wxPyCommandEvent(wxEventType eventType = wxEVT_NULL, int id=0) + : wxCommandEvent(eventType, id) {} + + virtual wxEvent* Clone() const { return new wxPyCommandEvent(*this); } +}; + + + +//-------------------------------------------------------------------------- +#endif diff --git a/src/pyevent.sip b/src/pyevent.sip deleted file mode 100644 index f3926f32..00000000 --- a/src/pyevent.sip +++ /dev/null @@ -1,204 +0,0 @@ -//-------------------------------------------------------------------------- -// Name: pyevent.sip -// Purpose: A set of event classes that can be derived from in Python -// and that preserve their attributes when cloned. -// -// Author: Robin Dunn -// -// Created: 18-Dec-2010 -// Copyright: (c) 2011 by Total Control Software -// Licence: wxWindows license -//-------------------------------------------------------------------------- - -// The wxPyEvent and wxPyCommandEvent classes can be derived from in Python -// and passed through the event system without losing anything. - -%ModuleHeaderCode - // This class holds a Python dictionary object and is used to store any - // attributes that are set from Python code for the wx.PyEvent and - // wx.PyCommandEvent classes. This dictionary is used to make it easy to - // transport those attributes over to the clone when wx needs to make a copy - // of the event instance. - - // NOTE: This class is intentionally not exposed to SIP as there is no - // need for it in Python code. Intead we just tell SIP that the __*attr__ - // methods are in the event classes. (See wxPyEvent and wxPyCommandEvent - // below.) - - class wxPyEvtDict - { - public: - wxPyEvtDict() - { - wxPyBLOCK_THREADS(m_dict = PyDict_New()); - } - - wxPyEvtDict(const wxPyEvtDict& other) - { - wxPyBLOCK_THREADS(m_dict = PyDict_Copy(other.m_dict)); - } - - ~wxPyEvtDict() - { - wxPyThreadBlocker blocker; - Py_DECREF(m_dict); - m_dict = NULL; - } - - PyObject* _getAttrDict() - { - wxPyBLOCK_THREADS( Py_INCREF(m_dict) ); - return m_dict; - } - - PyObject* __getattr__(PyObject* name) - { - PyObject* value = NULL; - wxPyThreadBlocker blocker; - if (PyDict_Contains(m_dict, name)) { - value = PyDict_GetItem(m_dict, name); - Py_INCREF(value); - } - else { - PyErr_SetObject(PyExc_AttributeError, name); - } - return value; - } - - void __setattr__(PyObject* name, PyObject* value) - { - wxPyThreadBlocker blocker; - PyDict_SetItem(m_dict, name, value); - } - - void __delattr__(PyObject* name) - { - wxPyThreadBlocker blocker; - if (PyDict_Contains(m_dict, name)) - PyDict_DelItem(m_dict, name); - else - PyErr_SetObject(PyExc_AttributeError, name); - } - - protected: - PyObject* m_dict; - }; -%End - - -//--------------------------------------------------------------------------- - -// TODO: Move these classes to an etg script and build using extractor -// objects so they will be seen by the document generator and others. - -class wxPyEvent : wxEvent -{ -%Docstring -wx.PyEvent can be used as a base class for implementing custom event types -in Python. You should derive from this class instead of `wx.Event` because -this class is Python-aware and is able to transport its Python bits safely -through the wxWidgets event system and have them still be there when the -event handler is invoked. Note that since wx.PyEvent is taking care of -preserving the extra attributes that have been set then you do not need to -implement the Clone method in your derived classes. - -:see: `wx.PyCommandEvent` -%End - // first declare the C++ version of the class - %TypeCode - class wxPyEvent : public wxEvent, public wxPyEvtDict - { - DECLARE_DYNAMIC_CLASS(wxPyEvent) - public: - wxPyEvent(int id=0, wxEventType eventType = wxEVT_NULL) - : wxEvent(id, eventType) {} - - virtual wxEvent* Clone() const { return new wxPyEvent(*this); } - }; - IMPLEMENT_DYNAMIC_CLASS(wxPyEvent, wxEvent); - %End - -public: - wxPyEvent(int id=0, wxEventType eventType = wxEVT_NULL ); - virtual wxEvent* Clone() const /Factory/; - PyObject* _getAttrDict(); - - PyObject* __getattr__(PyObject* name); - %MethodCode - sipRes = sipCpp->__getattr__(name); - %End - - void __setattr__(PyObject* name, PyObject* value); - %MethodCode - sipCpp->__setattr__(name, value); - %End - - void __delattr__(PyObject* name); - %MethodCode - sipCpp->__delattr__(name); - %End - -}; - - - -class wxPyCommandEvent : wxCommandEvent -{ -%Docstring -wx.PyCommandEvent can be used as a base class for implementing custom event types -in Python. You should derive from this class instead of `wx.CommandEvent` because -this class is Python-aware and is able to transport its Python bits safely -through the wxWidgets event system and have them still be there when the -event handler is invoked. Note that since wx.PyCommandEvent is taking care of -preserving the extra attributes that have been set then you do not need to -implement the Clone method in your derived classes. - -:see: `wx.PyEvent` -%End - // first declare the C++ version of the class - %TypeCode - class wxPyCommandEvent : public wxCommandEvent, public wxPyEvtDict - { - DECLARE_DYNAMIC_CLASS(wxPyCommandEvent) - public: - wxPyCommandEvent(wxEventType eventType = wxEVT_NULL, int id=0) - : wxCommandEvent(eventType, id) {} - - virtual wxEvent* Clone() const { return new wxPyCommandEvent(*this); } - }; - IMPLEMENT_DYNAMIC_CLASS(wxPyCommandEvent, wxCommandEvent); - %End - -public: - wxPyCommandEvent(wxEventType eventType = wxEVT_NULL, int id=0); - virtual wxEvent* Clone() const /Factory/; - PyObject* _getAttrDict(); - - PyObject* __getattr__(PyObject* name); - %MethodCode - sipRes = sipCpp->__getattr__(name); - %End - - void __setattr__(PyObject* name, PyObject* value); - %MethodCode - sipCpp->__setattr__(name, value); - %End - - void __delattr__(PyObject* name); - %MethodCode - sipCpp->__delattr__(name); - %End -}; - - - -// TODO: Temporary testing code, get rid of this later -%ModuleCode -wxEvent* testCppClone(wxEvent& evt) -{ - return evt.Clone(); -} -%End -wxEvent* testCppClone(wxEvent& evt); - -