Python sequence wrappers for wxLists
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@46280 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -1,6 +1,28 @@
|
||||
Recent Changes for wxPython
|
||||
=====================================================================
|
||||
|
||||
2.8.4.1
|
||||
-------
|
||||
*
|
||||
|
||||
Added some SWIG magic that allows wx C++ lists to be exposed to
|
||||
wxPython as sqequence-like wrappers around the real list, instead of
|
||||
making a Python list that is a copy of the real list as was done
|
||||
before. These sequence-like objects support indexing, iteration and
|
||||
containment tests ("obj in seq") but not anything that would modify the
|
||||
sequence. If you need to have a real list object like before you can
|
||||
pass the sequence to Python's list() function to convert it. Current
|
||||
functions that are affected by this are wx.Window.GetChildren,
|
||||
wx.GetTopLevelWindows, wx.Sizer.GetChildren, and
|
||||
wx.Menu.GetMenuItems. Care should be taken to be sure that you don't
|
||||
try to use the sequence after the C++ object the list belongs to has
|
||||
been destroyed.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2.8.4.0
|
||||
-------
|
||||
* 14-May-2007
|
||||
|
@@ -408,6 +408,19 @@ typedef unsigned long wxUIntPtr;
|
||||
%enddef
|
||||
#endif
|
||||
|
||||
#ifdef _DO_FULL_DOCS
|
||||
%define %RenameDocStr(newname, docstr, details, type, decl)
|
||||
%feature("docstring") decl docstr;
|
||||
%rename(newname) decl;
|
||||
type decl
|
||||
%enddef
|
||||
#else
|
||||
%define %RenameDocStr(newname, docstr, details, type, decl)
|
||||
%feature("docstring") decl docstr details;
|
||||
%rename(newname) decl;
|
||||
type decl
|
||||
%enddef
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Generates a base_On* method that just wraps a call to the On*, and mark it
|
||||
@@ -459,6 +472,204 @@ FORWARD_DECLARE(wxIcon, Icon);
|
||||
FORWARD_DECLARE(wxStaticBox, StaticBox);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// This macro makes a class to wrap a type specific class derived from wxList,
|
||||
// and make it look like a Python sequence, including with iterator support
|
||||
|
||||
%define wxLIST_WRAPPER(ListClass, ItemClass)
|
||||
// first a bit of C++ code...
|
||||
%{
|
||||
class ListClass##_iterator
|
||||
{
|
||||
public:
|
||||
ListClass##_iterator(ListClass::compatibility_iterator start)
|
||||
: m_node(start) {}
|
||||
|
||||
ItemClass* next() {
|
||||
ItemClass* obj = NULL;
|
||||
if (m_node) {
|
||||
obj = m_node->GetData();
|
||||
m_node = m_node->GetNext();
|
||||
}
|
||||
else PyErr_SetString(PyExc_StopIteration, "");
|
||||
return obj;
|
||||
}
|
||||
private:
|
||||
ListClass::compatibility_iterator m_node;
|
||||
};
|
||||
%}
|
||||
|
||||
// Now declare the classes for SWIG
|
||||
|
||||
DocStr(ListClass##_iterator,
|
||||
"This class serves as an iterator for a ListClass object.", "");
|
||||
|
||||
class ListClass##_iterator
|
||||
{
|
||||
public:
|
||||
//ListClass##_iterator();
|
||||
~ListClass_iterator();
|
||||
KeepGIL(next);
|
||||
ItemClass* next();
|
||||
};
|
||||
|
||||
|
||||
DocStr(ListClass,
|
||||
"This class wraps a wxList-based class and gives it a Python
|
||||
sequence-like interface. Sequence operations supported are length,
|
||||
index access and iteration.", "");
|
||||
|
||||
class ListClass
|
||||
{
|
||||
public:
|
||||
//ListClass(); This will always be created by some C++ function
|
||||
~ListClass();
|
||||
|
||||
%extend {
|
||||
KeepGIL(__len__);
|
||||
size_t __len__() {
|
||||
return self->size();
|
||||
}
|
||||
|
||||
KeepGIL(__getitem__);
|
||||
ItemClass* __getitem__(size_t index) {
|
||||
if (index < self->size()) {
|
||||
ListClass::compatibility_iterator node = self->Item(index);
|
||||
if (node) return node->GetData();
|
||||
}
|
||||
PyErr_SetString(PyExc_IndexError, "Invalid list index");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
KeepGIL(__contains__);
|
||||
bool __contains__(const ItemClass* obj) {
|
||||
return self->Find(obj) != NULL;
|
||||
}
|
||||
|
||||
KeepGIL(__iter__);
|
||||
%newobject __iter__;
|
||||
ListClass##_iterator* __iter__() {
|
||||
return new ListClass##_iterator(self->GetFirst());
|
||||
}
|
||||
}
|
||||
%pythoncode {
|
||||
def __repr__(self):
|
||||
return "ListClass: " + repr(list(self))
|
||||
}
|
||||
};
|
||||
%enddef
|
||||
|
||||
|
||||
|
||||
// This macro is similar to the above, but it is to be used when there isn't a
|
||||
// type-specific C++ list class to use. In other words the C++ code is using
|
||||
// a plain wxList and typecasting the node values, so we'll do the same.
|
||||
%define wxUNTYPED_LIST_WRAPPER(ListClass, ItemClass)
|
||||
// first a bit of C++ code...
|
||||
%{
|
||||
class ListClass
|
||||
{
|
||||
public:
|
||||
ListClass(wxList* theList)
|
||||
: m_list(theList) {}
|
||||
~ListClass() {}
|
||||
public:
|
||||
wxList* m_list;
|
||||
};
|
||||
|
||||
class ListClass##_iterator
|
||||
{
|
||||
public:
|
||||
ListClass##_iterator(wxList::compatibility_iterator start)
|
||||
: m_node(start) {}
|
||||
|
||||
ItemClass* next() {
|
||||
ItemClass* obj = NULL;
|
||||
if (m_node) {
|
||||
obj = (ItemClass*)m_node->GetData();
|
||||
m_node = m_node->GetNext();
|
||||
}
|
||||
else PyErr_SetString(PyExc_StopIteration, "");
|
||||
return obj;
|
||||
}
|
||||
private:
|
||||
wxList::compatibility_iterator m_node;
|
||||
};
|
||||
%}
|
||||
|
||||
// Now declare the classes for SWIG
|
||||
|
||||
DocStr(ListClass##_iterator,
|
||||
"This class serves as an iterator for a ListClass object.", "");
|
||||
|
||||
class ListClass##_iterator
|
||||
{
|
||||
public:
|
||||
//ListClass##_iterator();
|
||||
~ListClass_iterator();
|
||||
KeepGIL(next);
|
||||
ItemClass* next();
|
||||
};
|
||||
|
||||
|
||||
DocStr(ListClass,
|
||||
"This class wraps a wxList-based class and gives it a Python
|
||||
sequence-like interface. Sequence operations supported are length,
|
||||
index access and iteration.", "");
|
||||
class ListClass
|
||||
{
|
||||
public:
|
||||
//ListClass(); This will always be created by some C++ function
|
||||
~ListClass();
|
||||
|
||||
%extend {
|
||||
KeepGIL(__len__);
|
||||
size_t __len__() {
|
||||
return self->m_list->size();
|
||||
}
|
||||
|
||||
KeepGIL(__getitem__);
|
||||
ItemClass* __getitem__(size_t index) {
|
||||
if (index < self->m_list->size()) {
|
||||
wxList::compatibility_iterator node = self->m_list->Item(index);
|
||||
if (node) return (ItemClass*)node->GetData();
|
||||
}
|
||||
PyErr_SetString(PyExc_IndexError, "Invalid list index");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
KeepGIL(__contains__);
|
||||
bool __contains__(const ItemClass* obj) {
|
||||
return self->m_list->Find(obj) != NULL;
|
||||
}
|
||||
|
||||
KeepGIL(__iter__);
|
||||
%newobject __iter__;
|
||||
ListClass##_iterator* __iter__() {
|
||||
return new ListClass##_iterator(self->m_list->GetFirst());
|
||||
}
|
||||
}
|
||||
%pythoncode {
|
||||
def __repr__(self):
|
||||
return "ListClass: " + repr(list(self))
|
||||
}
|
||||
};
|
||||
|
||||
// A typemap to handle converting a wxList& return value to this new list
|
||||
// type. To use this just change the return value type in the class
|
||||
// definition to this typedef instead of wxList, then SWIG will use the
|
||||
// typemap.
|
||||
%{
|
||||
typedef wxList ListClass##_t;
|
||||
%}
|
||||
%typemap(out) ListClass##_t& {
|
||||
ListClass* mylist = new ListClass($1);
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr(mylist), SWIGTYPE_p_##ListClass, SWIG_POINTER_OWN );
|
||||
}
|
||||
%enddef
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
%{
|
||||
|
@@ -16,6 +16,9 @@
|
||||
//---------------------------------------------------------------------------
|
||||
%newgroup
|
||||
|
||||
wxLIST_WRAPPER(wxMenuItemList, wxMenuItem);
|
||||
|
||||
|
||||
|
||||
MustHaveApp(wxMenu);
|
||||
|
||||
@@ -169,12 +172,7 @@ public:
|
||||
|
||||
// get the items
|
||||
size_t GetMenuItemCount() const;
|
||||
%extend {
|
||||
PyObject* GetMenuItems() {
|
||||
wxMenuItemList& list = self->GetMenuItems();
|
||||
return wxPy_ConvertList(&list);
|
||||
}
|
||||
}
|
||||
wxMenuItemList& GetMenuItems();
|
||||
|
||||
// search
|
||||
int FindItem(const wxString& item) const;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: _window.i
|
||||
// Name: _panel.i
|
||||
// Purpose: SWIG interface for wxPanel and wxScrolledWindow
|
||||
//
|
||||
// Author: Robin Dunn
|
||||
|
@@ -169,6 +169,11 @@ border size.", "");
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
%newgroup
|
||||
|
||||
wxLIST_WRAPPER( wxSizerItemList, wxSizerItem );
|
||||
|
||||
|
||||
|
||||
DocStr(wxSizerItem,
|
||||
"The wx.SizerItem class is used to track the position, size and other
|
||||
@@ -1223,21 +1228,12 @@ as well.", "");
|
||||
|
||||
|
||||
|
||||
// wxList& GetChildren();
|
||||
%extend {
|
||||
DocAStr(GetChildren,
|
||||
"GetChildren(self) -> list",
|
||||
"Returns a list of all the `wx.SizerItem` objects managed by the sizer.", "");
|
||||
PyObject* GetChildren() {
|
||||
wxSizerItemList& list = self->GetChildren();
|
||||
return wxPy_ConvertList(&list);
|
||||
}
|
||||
}
|
||||
DocStr(GetChildren,
|
||||
"Returns all of the `wx.SizerItem` objects managed by the sizer in a
|
||||
list-like object.", "");
|
||||
wxSizerItemList& GetChildren();
|
||||
|
||||
|
||||
// Manage whether individual windows or subsizers are considered
|
||||
// in the layout calculations or not.
|
||||
|
||||
%extend {
|
||||
DocAStr(Show,
|
||||
"Show(self, item, bool show=True, bool recursive=false) -> bool",
|
||||
|
@@ -24,6 +24,9 @@ MAKE_CONST_WXSTRING(PanelNameStr);
|
||||
%newgroup
|
||||
|
||||
|
||||
wxLIST_WRAPPER(wxWindowList, wxWindow);
|
||||
|
||||
|
||||
DocStr(wxVisualAttributes,
|
||||
"struct containing all the visual attributes of a control", "");
|
||||
|
||||
@@ -956,26 +959,16 @@ before win instead of putting it right after it.", "");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// parent/children relations
|
||||
// -------------------------
|
||||
|
||||
|
||||
//wxWindowList& GetChildren(); // TODO: Do a typemap or a wrapper for wxWindowList
|
||||
%extend {
|
||||
DocStr(GetChildren,
|
||||
"Returns a list of the window's children. NOTE: Currently this is a
|
||||
copy of the child window list maintained by the window, so the return
|
||||
value of this function is only valid as long as the window's children
|
||||
do not change.", "");
|
||||
PyObject* GetChildren() {
|
||||
wxWindowList& list = self->GetChildren();
|
||||
return wxPy_ConvertList(&list);
|
||||
}
|
||||
}
|
||||
"Returns an object containing a list of the window's children. The
|
||||
object provides a Python sequence-like interface over the internal
|
||||
list maintained by the window..", "");
|
||||
wxWindowList& GetChildren();
|
||||
|
||||
|
||||
DocDeclStr(
|
||||
wxWindow *, GetParent() const,
|
||||
@@ -2284,14 +2277,11 @@ MustHaveApp(wxWindow_FromHWND);
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
DocStr(GetTopLevelWindows,
|
||||
"Returns a list of the the application's top-level windows, (frames,
|
||||
dialogs, etc.) NOTE: Currently this is a copy of the list maintained
|
||||
by wxWidgets, and so it is only valid as long as no top-level windows
|
||||
are closed or new top-level windows are created.
|
||||
", "");
|
||||
"Returns a list-like object of the the application's top-level windows, (frames,
|
||||
dialogs, etc.)", "");
|
||||
%inline %{
|
||||
PyObject* GetTopLevelWindows() {
|
||||
return wxPy_ConvertList(&wxTopLevelWindows);
|
||||
wxWindowList& GetTopLevelWindows() {
|
||||
return wxTopLevelWindows;
|
||||
}
|
||||
%}
|
||||
|
||||
|
Reference in New Issue
Block a user