mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2025-12-15 17:20:07 +01:00
403 lines
16 KiB
Python
403 lines
16 KiB
Python
#---------------------------------------------------------------------------
|
|
# Name: etg/listctrl.py
|
|
# Author: Robin Dunn
|
|
#
|
|
# Created: 23-Mar-2012
|
|
# Copyright: (c) 2012-2020 by Total Control Software
|
|
# License: wxWindows License
|
|
#---------------------------------------------------------------------------
|
|
|
|
import etgtools
|
|
import etgtools.tweaker_tools as tools
|
|
|
|
PACKAGE = "wx"
|
|
MODULE = "_core"
|
|
NAME = "listctrl" # 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 = [ "wxItemAttr", # TODO: technically this should be in its own etg script...
|
|
"wxListItem",
|
|
"wxListCtrl",
|
|
"wxListView",
|
|
"wxListEvent",
|
|
]
|
|
|
|
#---------------------------------------------------------------------------
|
|
|
|
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.
|
|
|
|
# Compatibility alias
|
|
module.addPyCode("""\
|
|
ListItemAttr = wx.deprecated(ItemAttr, 'Use ItemAttr instead')
|
|
""")
|
|
|
|
#-------------------------------------------------------
|
|
c = module.find('wxListItem')
|
|
assert isinstance(c, etgtools.ClassDef)
|
|
c.find('SetData').findOverload('void *').ignore()
|
|
c.find('GetData').type = 'long'
|
|
|
|
#-------------------------------------------------------
|
|
c = module.find('wxListCtrl')
|
|
tools.fixWindowClass(c)
|
|
|
|
module.addGlobalStr('wxListCtrlNameStr', before=c)
|
|
|
|
# Unignore some protected virtual methods that we want to allow to be
|
|
# overridden in derived classes
|
|
for name in [ 'OnGetItemAttr',
|
|
#'OnGetItemColumnAttr', # MSW only?
|
|
'OnGetItemColumnImage',
|
|
'OnGetItemImage',
|
|
'OnGetItemText',
|
|
'OnGetItemIsChecked',
|
|
]:
|
|
c.find(name).ignore(False)
|
|
c.find(name).isVirtual = True
|
|
|
|
tools.addEnableSystemTheme(c, 'wx.ListCtrl')
|
|
|
|
# Tweaks to allow passing and using a Python callable object for the sort
|
|
# compare function. First provide a sort callback function that can call the
|
|
# Python function.
|
|
c.addCppCode("""\
|
|
static int wxCALLBACK wxPyListCtrl_SortItems(wxIntPtr item1, wxIntPtr item2, wxIntPtr funcPtr)
|
|
{
|
|
int retval = 0;
|
|
PyObject* func = (PyObject*)funcPtr;
|
|
wxPyThreadBlocker blocker;
|
|
|
|
#if SIZEOF_LONG >= SIZEOF_VOID_P
|
|
PyObject* args = Py_BuildValue("(ll)", item1, item2);
|
|
#else
|
|
PyObject* args = Py_BuildValue("(LL)", item1, item2);
|
|
#endif
|
|
|
|
PyObject* result = PyObject_CallObject(func, args);
|
|
Py_DECREF(args);
|
|
if (result) {
|
|
retval = wxPyInt_AsLong(result);
|
|
Py_DECREF(result);
|
|
}
|
|
return retval;
|
|
}
|
|
""")
|
|
|
|
# Next, provide an alternate implementation of SortItems that will use that callback.
|
|
sim = c.find('SortItems')
|
|
assert isinstance(sim, etgtools.MethodDef)
|
|
sim.find('fnSortCallBack').type = 'PyObject*'
|
|
sim.find('data').ignore() # we will be using it to pass the python callback function
|
|
sim.argsString = sim.argsString.replace('wxListCtrlCompare', 'PyObject*')
|
|
sim.setCppCode("""\
|
|
if (!PyCallable_Check(fnSortCallBack))
|
|
return false;
|
|
return self->SortItems((wxListCtrlCompare)wxPyListCtrl_SortItems,
|
|
(wxIntPtr)fnSortCallBack);
|
|
""")
|
|
|
|
# SetItemData takes a long, so lets return that type from GetItemData too,
|
|
# instead of a wxUIntPtr.
|
|
c.find('GetItemData').type = 'long'
|
|
c.find('SetItemPtrData').ignore()
|
|
|
|
|
|
# Change the semantics of GetColumn to return the item as the return
|
|
# value instead of through a parameter.
|
|
# bool GetColumn(int col, wxListItem& item) const;
|
|
c.find('GetColumn').ignore()
|
|
c.addCppMethod('wxListItem*', 'GetColumn', '(int col)',
|
|
doc='Gets information about this column. See SetItem() for more information.',
|
|
factory=True,
|
|
body="""\
|
|
wxListItem item;
|
|
item.SetMask( wxLIST_MASK_STATE |
|
|
wxLIST_MASK_TEXT |
|
|
wxLIST_MASK_IMAGE |
|
|
wxLIST_MASK_DATA |
|
|
wxLIST_SET_ITEM |
|
|
wxLIST_MASK_WIDTH |
|
|
wxLIST_MASK_FORMAT
|
|
);
|
|
if (self->GetColumn(col, item))
|
|
return new wxListItem(item);
|
|
else
|
|
return NULL;
|
|
""")
|
|
|
|
# Do the same for GetItem
|
|
# bool GetItem(wxListItem& info) const;
|
|
c.find('GetItem').ignore()
|
|
c.addCppMethod('wxListItem*', 'GetItem', '(int itemIdx, int col=0)',
|
|
doc='Gets information about the item. See SetItem() for more information.',
|
|
factory=True,
|
|
body="""\
|
|
wxListItem* info = new wxListItem;
|
|
info->m_itemId = itemIdx;
|
|
info->m_col = col;
|
|
info->m_mask = 0xFFFF;
|
|
info->m_stateMask = 0xFFFF;
|
|
self->GetItem(*info);
|
|
return info;
|
|
""")
|
|
|
|
# bool GetItemPosition(long item, wxPoint& pos) const;
|
|
c.find('GetItemPosition').ignore()
|
|
c.addCppMethod('wxPoint*', 'GetItemPosition', '(long item)',
|
|
doc='Returns the position of the item, in icon or small icon view.',
|
|
factory=True,
|
|
body="""\
|
|
wxPoint* pos = new wxPoint;
|
|
self->GetItemPosition(item, *pos);
|
|
return pos;
|
|
""")
|
|
|
|
# bool GetItemRect(long item, wxRect& rect, int code = wxLIST_RECT_BOUNDS) const;
|
|
c.find('GetItemRect').ignore()
|
|
c.addCppMethod('wxRect*', 'GetItemRect', '(long item, int code = wxLIST_RECT_BOUNDS)',
|
|
doc="""\
|
|
Returns the rectangle representing the item's size and position, in physical coordinates.
|
|
code is one of wx.LIST_RECT_BOUNDS, wx.LIST_RECT_ICON, wx.LIST_RECT_LABEL.""",
|
|
factory=True,
|
|
body="""\
|
|
wxRect* rect = new wxRect;
|
|
self->GetItemRect(item, *rect, code);
|
|
return rect;
|
|
""")
|
|
|
|
|
|
c.find('EditLabel.textControlClass').ignore()
|
|
c.find('EndEditLabel').ignore()
|
|
c.find('AssignImageList.imageList').transfer = True
|
|
c.find('HitTest.flags').out = True
|
|
c.find('HitTest.ptrSubItem').ignore()
|
|
|
|
c.addCppMethod(
|
|
'PyObject*', 'HitTestSubItem', '(const wxPoint& point)',
|
|
pyArgsString="(point) -> (item, flags, subitem)",
|
|
doc="Determines which item (if any) is at the specified point, giving details in flags.",
|
|
body="""\
|
|
long item, subitem;
|
|
int flags;
|
|
item = self->HitTest(*point, flags, &subitem);
|
|
wxPyThreadBlocker blocker;
|
|
PyObject* rv = PyTuple_New(3);
|
|
PyTuple_SetItem(rv, 0, wxPyInt_FromLong(item));
|
|
PyTuple_SetItem(rv, 1, wxPyInt_FromLong(flags));
|
|
PyTuple_SetItem(rv, 2, wxPyInt_FromLong(subitem));
|
|
return rv;
|
|
""")
|
|
|
|
c.find('CheckItem.check').default = 'true'
|
|
|
|
|
|
# Some deprecated aliases for Classic renames
|
|
c.addPyCode('ListCtrl.FindItemData = wx.deprecated(ListCtrl.FindItem, "Use FindItem instead.")')
|
|
c.addPyCode('ListCtrl.FindItemAtPos = wx.deprecated(ListCtrl.FindItem, "Use FindItem instead.")')
|
|
c.addPyCode('ListCtrl.InsertStringItem = wx.deprecated(ListCtrl.InsertItem, "Use InsertItem instead.")')
|
|
c.addPyCode('ListCtrl.InsertImageItem = wx.deprecated(ListCtrl.InsertItem, "Use InsertItem instead.")')
|
|
c.addPyCode('ListCtrl.InsertImageStringItem = wx.deprecated(ListCtrl.InsertItem, "Use InsertItem instead.")')
|
|
c.addPyCode('ListCtrl.SetStringItem = wx.deprecated(ListCtrl.SetItem, "Use SetItem instead.")')
|
|
|
|
|
|
# Provide a way to determine if column ordering is possible
|
|
c.addCppMethod('bool', 'HasColumnOrderSupport', '()',
|
|
"""\
|
|
#ifdef wxHAS_LISTCTRL_COLUMN_ORDER
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
""")
|
|
|
|
# And provide implementation of those methods that will work whether or
|
|
# not wx has column ordering support
|
|
c.find('GetColumnOrder').setCppCode("""\
|
|
#ifdef wxHAS_LISTCTRL_COLUMN_ORDER
|
|
return self->GetColumnOrder(col);
|
|
#else
|
|
wxPyRaiseNotImplemented();
|
|
return 0;
|
|
#endif
|
|
""")
|
|
|
|
c.find('GetColumnIndexFromOrder').setCppCode("""\
|
|
#ifdef wxHAS_LISTCTRL_COLUMN_ORDER
|
|
return self->GetColumnIndexFromOrder(pos);
|
|
#else
|
|
wxPyRaiseNotImplemented();
|
|
return 0;
|
|
#endif
|
|
""")
|
|
|
|
c.find('GetColumnsOrder').type = 'wxArrayInt*'
|
|
c.find('GetColumnsOrder').factory=True
|
|
c.find('GetColumnsOrder').setCppCode("""\
|
|
#ifdef wxHAS_LISTCTRL_COLUMN_ORDER
|
|
return new wxArrayInt(self->GetColumnsOrder());
|
|
#else
|
|
wxPyRaiseNotImplemented();
|
|
return new wxArrayInt();
|
|
#endif
|
|
""")
|
|
|
|
c.find('SetColumnsOrder').setCppCode("""\
|
|
#ifdef wxHAS_LISTCTRL_COLUMN_ORDER
|
|
return self->SetColumnsOrder(*orders);
|
|
#else
|
|
wxPyRaiseNotImplemented();
|
|
return false;
|
|
#endif
|
|
""")
|
|
|
|
|
|
# Add some Python helper methods
|
|
c.addPyMethod('Select', '(self, idx, on=1)',
|
|
doc='Selects/deselects an item.',
|
|
body="""\
|
|
if on: state = wx.LIST_STATE_SELECTED
|
|
else: state = 0
|
|
self.SetItemState(idx, state, wx.LIST_STATE_SELECTED)
|
|
""")
|
|
|
|
c.addPyMethod('Focus', '(self, idx)',
|
|
doc='Focus and show the given item.',
|
|
body="""\
|
|
self.SetItemState(idx, wx.LIST_STATE_FOCUSED, wx.LIST_STATE_FOCUSED)
|
|
self.EnsureVisible(idx)
|
|
""")
|
|
|
|
c.addPyMethod('GetFocusedItem', '(self)',
|
|
doc='Gets the currently focused item or -1 if none is focused.',
|
|
body='return self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_FOCUSED)')
|
|
|
|
c.addPyMethod('GetFirstSelected', '(self, *args)',
|
|
doc='Returns the first selected item, or -1 when none is selected.',
|
|
body="return self.GetNextSelected(-1)")
|
|
|
|
c.addPyMethod('GetNextSelected', '(self, item)',
|
|
doc='Returns subsequent selected items, or -1 when no more are selected.',
|
|
body="return self.GetNextItem(item, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)")
|
|
|
|
c.addPyMethod('IsSelected', '(self, idx)',
|
|
doc='Returns ``True`` if the item is selected.',
|
|
body="return (self.GetItemState(idx, wx.LIST_STATE_SELECTED) & wx.LIST_STATE_SELECTED) != 0")
|
|
|
|
c.addPyMethod('SetColumnImage', '(self, col, image)',
|
|
body="""\
|
|
item = self.GetColumn(col)
|
|
# preserve all other attributes too
|
|
item.SetMask( wx.LIST_MASK_STATE |
|
|
wx.LIST_MASK_TEXT |
|
|
wx.LIST_MASK_IMAGE |
|
|
wx.LIST_MASK_DATA |
|
|
wx.LIST_SET_ITEM |
|
|
wx.LIST_MASK_WIDTH |
|
|
wx.LIST_MASK_FORMAT )
|
|
item.SetImage(image)
|
|
self.SetColumn(col, item)
|
|
""")
|
|
|
|
c.addPyMethod('ClearColumnImage', '(self, col)',
|
|
body="self.SetColumnImage(col, -1)")
|
|
|
|
c.addPyMethod('Append', '(self, entry)',
|
|
doc='''\
|
|
Append an item to the list control. The `entry` parameter should be a
|
|
sequence with an item for each column''',
|
|
body="""\
|
|
if len(entry):
|
|
pos = self.InsertItem(self.GetItemCount(), str(entry[0]))
|
|
for i in range(1, len(entry)):
|
|
self.SetItem(pos, i, str(entry[i]))
|
|
return pos
|
|
""")
|
|
|
|
|
|
c.addCppMethod('wxWindow*', 'GetMainWindow', '()',
|
|
body="""\
|
|
#if defined(__WXMSW__) || defined(__WXMAC__)
|
|
return self;
|
|
#else
|
|
return (wxWindow*)self->m_mainWin;
|
|
#endif
|
|
""")
|
|
|
|
# Documented wrongly in 3.1.6
|
|
c.find('RemoveSortIndicator').type = 'void'
|
|
c.find('RemoveSortIndicator').isConst = False
|
|
|
|
|
|
#-------------------------------------------------------
|
|
c = module.find('wxListView')
|
|
tools.fixWindowClass(c)
|
|
|
|
#-------------------------------------------------------
|
|
c = module.find('wxListEvent')
|
|
tools.fixEventClass(c)
|
|
|
|
module.addPyCode("""\
|
|
EVT_LIST_BEGIN_DRAG = PyEventBinder(wxEVT_LIST_BEGIN_DRAG , 1)
|
|
EVT_LIST_BEGIN_RDRAG = PyEventBinder(wxEVT_LIST_BEGIN_RDRAG , 1)
|
|
EVT_LIST_BEGIN_LABEL_EDIT = PyEventBinder(wxEVT_LIST_BEGIN_LABEL_EDIT , 1)
|
|
EVT_LIST_END_LABEL_EDIT = PyEventBinder(wxEVT_LIST_END_LABEL_EDIT , 1)
|
|
EVT_LIST_DELETE_ITEM = PyEventBinder(wxEVT_LIST_DELETE_ITEM , 1)
|
|
EVT_LIST_DELETE_ALL_ITEMS = PyEventBinder(wxEVT_LIST_DELETE_ALL_ITEMS , 1)
|
|
EVT_LIST_ITEM_SELECTED = PyEventBinder(wxEVT_LIST_ITEM_SELECTED , 1)
|
|
EVT_LIST_ITEM_DESELECTED = PyEventBinder(wxEVT_LIST_ITEM_DESELECTED , 1)
|
|
EVT_LIST_KEY_DOWN = PyEventBinder(wxEVT_LIST_KEY_DOWN , 1)
|
|
EVT_LIST_INSERT_ITEM = PyEventBinder(wxEVT_LIST_INSERT_ITEM , 1)
|
|
EVT_LIST_COL_CLICK = PyEventBinder(wxEVT_LIST_COL_CLICK , 1)
|
|
EVT_LIST_ITEM_RIGHT_CLICK = PyEventBinder(wxEVT_LIST_ITEM_RIGHT_CLICK , 1)
|
|
EVT_LIST_ITEM_MIDDLE_CLICK = PyEventBinder(wxEVT_LIST_ITEM_MIDDLE_CLICK, 1)
|
|
EVT_LIST_ITEM_ACTIVATED = PyEventBinder(wxEVT_LIST_ITEM_ACTIVATED , 1)
|
|
EVT_LIST_CACHE_HINT = PyEventBinder(wxEVT_LIST_CACHE_HINT , 1)
|
|
EVT_LIST_COL_RIGHT_CLICK = PyEventBinder(wxEVT_LIST_COL_RIGHT_CLICK , 1)
|
|
EVT_LIST_COL_BEGIN_DRAG = PyEventBinder(wxEVT_LIST_COL_BEGIN_DRAG , 1)
|
|
EVT_LIST_COL_DRAGGING = PyEventBinder(wxEVT_LIST_COL_DRAGGING , 1)
|
|
EVT_LIST_COL_END_DRAG = PyEventBinder(wxEVT_LIST_COL_END_DRAG , 1)
|
|
EVT_LIST_ITEM_FOCUSED = PyEventBinder(wxEVT_LIST_ITEM_FOCUSED , 1)
|
|
EVT_LIST_ITEM_CHECKED = PyEventBinder(wxEVT_LIST_ITEM_CHECKED , 1)
|
|
EVT_LIST_ITEM_UNCHECKED = PyEventBinder(wxEVT_LIST_ITEM_UNCHECKED , 1)
|
|
|
|
# deprecated wxEVT aliases
|
|
wxEVT_COMMAND_LIST_BEGIN_DRAG = wxEVT_LIST_BEGIN_DRAG
|
|
wxEVT_COMMAND_LIST_BEGIN_RDRAG = wxEVT_LIST_BEGIN_RDRAG
|
|
wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT = wxEVT_LIST_BEGIN_LABEL_EDIT
|
|
wxEVT_COMMAND_LIST_END_LABEL_EDIT = wxEVT_LIST_END_LABEL_EDIT
|
|
wxEVT_COMMAND_LIST_DELETE_ITEM = wxEVT_LIST_DELETE_ITEM
|
|
wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS = wxEVT_LIST_DELETE_ALL_ITEMS
|
|
wxEVT_COMMAND_LIST_ITEM_SELECTED = wxEVT_LIST_ITEM_SELECTED
|
|
wxEVT_COMMAND_LIST_ITEM_DESELECTED = wxEVT_LIST_ITEM_DESELECTED
|
|
wxEVT_COMMAND_LIST_KEY_DOWN = wxEVT_LIST_KEY_DOWN
|
|
wxEVT_COMMAND_LIST_INSERT_ITEM = wxEVT_LIST_INSERT_ITEM
|
|
wxEVT_COMMAND_LIST_COL_CLICK = wxEVT_LIST_COL_CLICK
|
|
wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK = wxEVT_LIST_ITEM_RIGHT_CLICK
|
|
wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK = wxEVT_LIST_ITEM_MIDDLE_CLICK
|
|
wxEVT_COMMAND_LIST_ITEM_ACTIVATED = wxEVT_LIST_ITEM_ACTIVATED
|
|
wxEVT_COMMAND_LIST_CACHE_HINT = wxEVT_LIST_CACHE_HINT
|
|
wxEVT_COMMAND_LIST_COL_RIGHT_CLICK = wxEVT_LIST_COL_RIGHT_CLICK
|
|
wxEVT_COMMAND_LIST_COL_BEGIN_DRAG = wxEVT_LIST_COL_BEGIN_DRAG
|
|
wxEVT_COMMAND_LIST_COL_DRAGGING = wxEVT_LIST_COL_DRAGGING
|
|
wxEVT_COMMAND_LIST_COL_END_DRAG = wxEVT_LIST_COL_END_DRAG
|
|
wxEVT_COMMAND_LIST_ITEM_FOCUSED = wxEVT_LIST_ITEM_FOCUSED
|
|
""")
|
|
|
|
#-----------------------------------------------------------------
|
|
tools.doCommonTweaks(module)
|
|
tools.runGenerators(module)
|
|
|
|
|
|
#---------------------------------------------------------------------------
|
|
if __name__ == '__main__':
|
|
run()
|