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. #------------------------------------------------------- c = module.find('wxTreeItemId') assert isinstance(c, etgtools.ClassDef) # add the void* ctor missing from the interface ctor = MethodDef(name='wxTreeItemId', isCtor=True, items=[ParamDef(name='pItem', type='void*')]) # add it as an overload to the existing ctor c.find('wxTreeItemId').overloads.append(ctor) c.addCppMethod('int', '__nonzero__', '()', "return self->IsOk();") c.addCppMethod('int', '__bool__', '()', "return self->IsOk();") c.addCppMethod('bool', '__eq__', '(const wxTreeItemId& other)', """\ return *self == *other; """) c.addCppMethod('bool', '__ne__', '(const wxTreeItemId& other)', """\ return *self != *other; """) c.addPyMethod('__hash__', '(self)', """\ return hash(int(self.GetID())) """) module.find('operator==').ignore() module.find('operator!=').ignore() td = etgtools.TypedefDef(name='wxTreeItemIdValue', type='void*') module.insertItemBefore(c, td) #------------------------------------------------------- module.addPyCode("""\ def TreeItemData(data): return data TreeItemData = deprecated(TreeItemData, "The TreeItemData class no longer exists, just pass your object directly to the tree instead.") """) #------------------------------------------------------- c = module.find('wxTreeCtrl') tools.fixWindowClass(c) module.addGlobalStr('wxTreeCtrlNameStr', before=c) tools.addEnableSystemTheme(c, 'wx.TreeCtrl') # Set all wxTreeItemData parameters to transfer ownership. Is this still needed with MappedTypes? for item in c.allItems(): if hasattr(item, 'type') and item.type == 'wxTreeItemData *' and \ isinstance(item, etgtools.ParamDef): item.transfer = True c.addPyCode("""\ TreeCtrl.GetItemPyData = wx.deprecated(TreeCtrl.GetItemData, 'Use GetItemData instead.') TreeCtrl.SetItemPyData = wx.deprecated(TreeCtrl.SetItemData, 'Use SetItemData instead.') TreeCtrl.GetPyData = wx.deprecated(TreeCtrl.GetItemData, 'Use GetItemData instead.') TreeCtrl.SetPyData = wx.deprecated(TreeCtrl.SetItemData, 'Use SetItemData instead.') """) # We can't use wxClassInfo c.find('EditLabel.textCtrlClass').ignore() # Replace GetSelections with a method that returns a Python list # size_t GetSelections(wxArrayTreeItemIds& selection) const; c.find('GetSelections').ignore() c.addCppMethod( 'PyObject*', 'GetSelections', '()', doc= 'Returns a list of currently selected items in the tree. This function ' 'can be called only if the control has the wx.TR_MULTIPLE style.', body="""\ wxPyThreadBlocker blocker; PyObject* rval = PyList_New(0); wxArrayTreeItemIds array; size_t num, x; num = self->GetSelections(array); for (x=0; x < num; x++) { wxTreeItemId *tii = new wxTreeItemId(array.Item(x)); PyObject* item = wxPyConstructObject((void*)tii, wxT("wxTreeItemId"), true); PyList_Append(rval, item); Py_DECREF(item); } return rval; """) # Change GetBoundingRect to return the rectangle instead of modifying the parameter. #bool GetBoundingRect(const wxTreeItemId& item, wxRect& rect, bool textOnly = false) const; c.find('GetBoundingRect').ignore() c.addCppMethod('PyObject*', 'GetBoundingRect', '(const wxTreeItemId& item, bool textOnly=false)', doc="""\ Returns the rectangle bounding the item. If textOnly is true, only the rectangle around the item's label will be returned, otherwise the item's image is also taken into account. The return value may be None if the rectangle was not successfully retrieved, such as if the item is currently not visible. """, isFactory=True, body="""\ wxRect rect; if (self->GetBoundingRect(*item, rect, textOnly)) { wxPyThreadBlocker blocker; wxRect* r = new wxRect(rect); PyObject* val = wxPyConstructObject((void*)r, wxT("wxRect"), true); return val; } else RETURN_NONE(); """) # switch the virtualness back on for those methods that need to have it. c.find('OnCompareItems').isVirtual = True # transfer imagelist ownership c.find('AssignStateImageList.imageList').transfer = True c.find('AssignButtonsImageList.imageList').transfer = True # Make the cookie values be returned, instead of setting it through the parameter c.find('GetFirstChild.cookie').out = True c.find('GetNextChild.cookie').inOut = True # TODO: These don't exist on MSW, Are they important enough that we # should provide them for the other platforms anyway? c.find('AssignButtonsImageList').ignore() c.find('GetButtonsImageList').ignore() c.find('SetButtonsImageList').ignore() #------------------------------------------------------- c = module.find('wxTreeEvent') tools.fixEventClass(c) module.addPyCode("""\ EVT_TREE_BEGIN_DRAG = PyEventBinder(wxEVT_TREE_BEGIN_DRAG , 1) EVT_TREE_BEGIN_RDRAG = PyEventBinder(wxEVT_TREE_BEGIN_RDRAG , 1) EVT_TREE_BEGIN_LABEL_EDIT = PyEventBinder(wxEVT_TREE_BEGIN_LABEL_EDIT , 1) EVT_TREE_END_LABEL_EDIT = PyEventBinder(wxEVT_TREE_END_LABEL_EDIT , 1) EVT_TREE_DELETE_ITEM = PyEventBinder(wxEVT_TREE_DELETE_ITEM , 1) EVT_TREE_GET_INFO = PyEventBinder(wxEVT_TREE_GET_INFO , 1) EVT_TREE_SET_INFO = PyEventBinder(wxEVT_TREE_SET_INFO , 1) EVT_TREE_ITEM_EXPANDED = PyEventBinder(wxEVT_TREE_ITEM_EXPANDED , 1) EVT_TREE_ITEM_EXPANDING = PyEventBinder(wxEVT_TREE_ITEM_EXPANDING , 1) EVT_TREE_ITEM_COLLAPSED = PyEventBinder(wxEVT_TREE_ITEM_COLLAPSED , 1) EVT_TREE_ITEM_COLLAPSING = PyEventBinder(wxEVT_TREE_ITEM_COLLAPSING , 1) EVT_TREE_SEL_CHANGED = PyEventBinder(wxEVT_TREE_SEL_CHANGED , 1) EVT_TREE_SEL_CHANGING = PyEventBinder(wxEVT_TREE_SEL_CHANGING , 1) EVT_TREE_KEY_DOWN = PyEventBinder(wxEVT_TREE_KEY_DOWN , 1) EVT_TREE_ITEM_ACTIVATED = PyEventBinder(wxEVT_TREE_ITEM_ACTIVATED , 1) EVT_TREE_ITEM_RIGHT_CLICK = PyEventBinder(wxEVT_TREE_ITEM_RIGHT_CLICK , 1) EVT_TREE_ITEM_MIDDLE_CLICK = PyEventBinder(wxEVT_TREE_ITEM_MIDDLE_CLICK, 1) EVT_TREE_END_DRAG = PyEventBinder(wxEVT_TREE_END_DRAG , 1) EVT_TREE_STATE_IMAGE_CLICK = PyEventBinder(wxEVT_TREE_STATE_IMAGE_CLICK, 1) EVT_TREE_ITEM_GETTOOLTIP = PyEventBinder(wxEVT_TREE_ITEM_GETTOOLTIP, 1) EVT_TREE_ITEM_MENU = PyEventBinder(wxEVT_TREE_ITEM_MENU, 1) # deprecated wxEVT aliases wxEVT_COMMAND_TREE_BEGIN_DRAG = wxEVT_TREE_BEGIN_DRAG wxEVT_COMMAND_TREE_BEGIN_RDRAG = wxEVT_TREE_BEGIN_RDRAG wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT = wxEVT_TREE_BEGIN_LABEL_EDIT wxEVT_COMMAND_TREE_END_LABEL_EDIT = wxEVT_TREE_END_LABEL_EDIT wxEVT_COMMAND_TREE_DELETE_ITEM = wxEVT_TREE_DELETE_ITEM wxEVT_COMMAND_TREE_GET_INFO = wxEVT_TREE_GET_INFO wxEVT_COMMAND_TREE_SET_INFO = wxEVT_TREE_SET_INFO wxEVT_COMMAND_TREE_ITEM_EXPANDED = wxEVT_TREE_ITEM_EXPANDED wxEVT_COMMAND_TREE_ITEM_EXPANDING = wxEVT_TREE_ITEM_EXPANDING wxEVT_COMMAND_TREE_ITEM_COLLAPSED = wxEVT_TREE_ITEM_COLLAPSED wxEVT_COMMAND_TREE_ITEM_COLLAPSING = wxEVT_TREE_ITEM_COLLAPSING wxEVT_COMMAND_TREE_SEL_CHANGED = wxEVT_TREE_SEL_CHANGED wxEVT_COMMAND_TREE_SEL_CHANGING = wxEVT_TREE_SEL_CHANGING wxEVT_COMMAND_TREE_KEY_DOWN = wxEVT_TREE_KEY_DOWN wxEVT_COMMAND_TREE_ITEM_ACTIVATED = wxEVT_TREE_ITEM_ACTIVATED wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK = wxEVT_TREE_ITEM_RIGHT_CLICK wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK = wxEVT_TREE_ITEM_MIDDLE_CLICK wxEVT_COMMAND_TREE_END_DRAG = wxEVT_TREE_END_DRAG wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK = wxEVT_TREE_STATE_IMAGE_CLICK wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP = wxEVT_TREE_ITEM_GETTOOLTIP wxEVT_COMMAND_TREE_ITEM_MENU = wxEVT_TREE_ITEM_MENU """) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
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. module.addHeaderCode("#include <wx/dataview.h>") for item in module.allItems(): if hasattr(item, 'type') and 'wxVariant' in item.type: item.type = item.type.replace('wxVariant', 'wxDVCVariant') #----------------------------------------------------------------- c = module.find('wxDataViewItem') assert isinstance(c, etgtools.ClassDef) c.addCppMethod('int', '__nonzero__', '()', "return self->IsOk();") c.addCppMethod('int', '__bool__', '()', "return self->IsOk();") c.addCppMethod('long', '__hash__', '()', "return (long)(intptr_t)self->GetID();") c.addCppMethod( 'bool', '__eq__', '(wxDataViewItem* other)', "return other ? (self->GetID() == other->GetID()) : false;") c.addCppMethod('bool', '__ne__', '(wxDataViewItem* other)', "return other ? (self->GetID() != other->GetID()) : true;") c.addAutoProperties() module.addItem( tools.wxArrayWrapperTemplate('wxDataViewItemArray', 'wxDataViewItem', module)) module.addPyCode("NullDataViewItem = DataViewItem()") #----------------------------------------------------------------- c = module.find('wxDataViewModel') c.addAutoProperties() tools.fixRefCountedClass(c) c.find('~wxDataViewModel').ignore(False) c.find('AddNotifier.notifier').transfer = True c.find('RemoveNotifier.notifier').transferBack = True # Change the GetValue method to return the value instead of passing it # through a parameter for modification. c.find('GetValue.variant').out = True c.find( 'GetValue' ).cppSignature = 'void (wxVariant& variant, const wxDataViewItem& item, unsigned int col)' # The DataViewItemObjectMapper class helps map from data items to Python # objects, and is used as a base class of PyDataViewModel as a # convenience. module.addPyClass( 'DataViewItemObjectMapper', ['object'], doc="""\ This class provides a mechanism for mapping between Python objects and the :class:`DataViewItem` objects used by the :class:`DataViewModel` for tracking the items in the view. The ID used for the item is the id() of the Python object. Use :meth:`ObjectToItem` to create a :class:`DataViewItem` using a Python object as its ID, and use :meth:`ItemToObject` to fetch that Python object again later for a given :class:`DataViewItem`. By default a regular dictionary is used to implement the ID to object mapping. Optionally a WeakValueDictionary can be useful when there will be a high turnover of objects and maintaining an extra reference to the objects would be unwise. If weak references are used then the objects associated with data items must be weak-referenceable. (Things like stock lists and dictionaries are not.) See :meth:`UseWeakRefs`. This class is used in :class:`PyDataViewModel` as a mixin for convenience. """, items=[ PyFunctionDef('__init__', '(self)', body="""\ self.mapper = dict() self.usingWeakRefs = False """), PyFunctionDef( 'ObjectToItem', '(self, obj)', doc= "Create a :class:`DataViewItem` for the object, and remember the ID-->obj mapping.", body="""\ import sys oid = id(obj) while oid > sys.maxsize: # risk of conflict here... May need some more thought. oid -= sys.maxsize self.mapper[oid] = obj return DataViewItem(oid) """), PyFunctionDef( 'ItemToObject', '(self, item)', doc="Retrieve the object that was used to create an item.", body="""\ oid = int(item.GetID()) return self.mapper[oid] """), PyFunctionDef('UseWeakRefs', '(self, flag)', doc="""\ Switch to or from using a weak value dictionary for keeping the ID to object map.""", body="""\ if flag == self.usingWeakRefs: return if flag: import weakref newmap = weakref.WeakValueDictionary() else: newmap = dict() newmap.update(self.mapper) self.mapper = newmap self.usingWeakRefs = flag """), ]) module.addPyClass( 'PyDataViewModel', ['DataViewModel', 'DataViewItemObjectMapper'], doc= "A convenience class that is a :class:`DataViewModel` combined with an object mapper.", items=[ PyFunctionDef('__init__', '(self)', body="""\ DataViewModel.__init__(self) DataViewItemObjectMapper.__init__(self) """) ]) #----------------------------------------------------------------- c = module.find('wxDataViewListModel') c.addAutoProperties() tools.fixRefCountedClass(c) # Change the GetValueByRow method to return the value instead of passing # it through a parameter for modification. c.find('GetValueByRow.variant').out = True c.find( 'GetValueByRow' ).cppSignature = 'void (wxVariant& variant, unsigned int row, unsigned int col)' # declare implementations for base class virtuals c.addItem( etgtools.WigCode("""\ virtual wxDataViewItem GetParent( const wxDataViewItem &item ) const; virtual bool IsContainer( const wxDataViewItem &item ) const; virtual void GetValue( wxDVCVariant &variant /Out/, const wxDataViewItem &item, unsigned int col ) const [void ( wxDVCVariant &variant, const wxDataViewItem &item, unsigned int col )]; virtual bool SetValue( const wxDVCVariant &variant, const wxDataViewItem &item, unsigned int col ); virtual bool GetAttr(const wxDataViewItem &item, unsigned int col, wxDataViewItemAttr &attr) const; virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const; virtual bool IsListModel() const; """)) # Add some of the pure virtuals since there are undocumented # implementations of them in these classes. The others will need to be # implemented in Python classes derived from these. for name in ['wxDataViewIndexListModel', 'wxDataViewVirtualListModel']: c = module.find(name) c.addItem( etgtools.WigCode("""\ virtual unsigned int GetRow(const wxDataViewItem& item) const; virtual unsigned int GetCount() const; virtual unsigned int GetChildren( const wxDataViewItem &item, wxDataViewItemArray &children ) const; """)) # compatibility aliases module.addPyCode("""\ PyDataViewIndexListModel = wx.deprecated(DataViewIndexListModel) PyDataViewVirtualListModel = wx.deprecated(DataViewVirtualListModel) """) #----------------------------------------------------------------- def _fixupBoolGetters(method, sig): method.type = 'void' method.find('value').out = True method.find('value').type = 'wxDVCVariant&' method.cppSignature = sig def _fixupTypeParam(klass): param = klass.findItem('{}.varianttype'.format(klass.name)) if param and param.default == 'GetDefaultType()': param.default = '{}::GetDefaultType()'.format(klass.name) c = module.find('wxDataViewRenderer') c.addPrivateCopyCtor() c.abstract = True c.find('GetView').ignore(False) # TODO: This is only available when wxUSE_ACCESSIBILITY is set to 1 c.find('GetAccessibleDescription').ignore() c.addAutoProperties() # Change variant getters to return the value for name, sig in [ ('GetValue', 'bool (wxVariant& value)'), ('GetValueFromEditorCtrl', 'bool (wxWindow * editor, wxVariant& value)'), ]: _fixupBoolGetters(c.find(name), sig) m = c.find('SetValue') m.find('value').type = 'const wxDVCVariant&' m.cppSignature = 'bool (const wxVariant& value)' m = c.find('CreateEditorCtrl') m.cppSignature = 'wxWindow* (wxWindow * parent, wxRect labelRect, const wxVariant& value)' c.find('GetView').ignore(False) c = module.find('wxDataViewCustomRenderer') _fixupTypeParam(c) m = c.find('GetValueFromEditorCtrl') _fixupBoolGetters(m, 'bool (wxWindow * editor, wxVariant& value)') # Change the virtual method handler code to follow the same pattern as the # tweaked public API, namely that the value is the return value instead of # an out parameter. m.virtualCatcherCode = """\ PyObject *sipResObj = sipCallMethod(&sipIsErr, sipMethod, "D", editor, sipType_wxWindow, NULL); if (sipResObj == NULL) { if (PyErr_Occurred()) PyErr_Print(); sipRes = false; } else if (sipResObj == Py_None) { sipRes = false; } else { sipRes = true; sipParseResult(&sipIsErr, sipMethod, sipResObj, "H5", sipType_wxDVCVariant, &value); } """ c.find('GetTextExtent').ignore(False) m = c.find('CreateEditorCtrl') m.cppSignature = 'wxWindow* (wxWindow * parent, wxRect labelRect, const wxVariant& value)' module.addPyCode("""\ PyDataViewCustomRenderer = wx.deprecated(DataViewCustomRenderer, "Use DataViewCustomRenderer instead")""" ) # Add the pure virtuals since there are undocumented implementations of # them in all these classes for name in [ 'wxDataViewTextRenderer', 'wxDataViewIconTextRenderer', 'wxDataViewProgressRenderer', 'wxDataViewSpinRenderer', 'wxDataViewToggleRenderer', 'wxDataViewChoiceRenderer', #'wxDataViewChoiceByIndexRenderer', 'wxDataViewDateRenderer', 'wxDataViewBitmapRenderer', ]: c = module.find(name) c.addAutoProperties() _fixupTypeParam(c) c.addItem( etgtools.WigCode("""\ virtual bool SetValue( const wxDVCVariant &value ) [bool (const wxVariant& value)]; virtual void GetValue( wxDVCVariant &value /Out/ ) const [bool (wxVariant& value)]; %Property(name=Value, get=GetValue, set=SetValue) """, protection='public')) # The SpinRenderer has a few additional pure virtuals that need to be declared # since it derives from DataViewCustomRenderer c = module.find('wxDataViewSpinRenderer') c.addItem( etgtools.WigCode("""\ virtual wxSize GetSize() const; virtual bool Render(wxRect cell, wxDC* dc, int state); """, protection='public')) #----------------------------------------------------------------- c = module.find('wxDataViewColumn') for m in c.find('wxDataViewColumn').all(): m.find('renderer').transfer = True # declare the virtuals from wxSettableHeaderColumn c.addItem( etgtools.WigCode("""\ virtual void SetTitle(const wxString& title); virtual wxString GetTitle() const; virtual void SetBitmap(const wxBitmap& bitmap); virtual wxBitmap GetBitmap() const; virtual void SetWidth(int width); virtual int GetWidth() const; virtual void SetMinWidth(int minWidth); virtual int GetMinWidth() const; virtual void SetAlignment(wxAlignment align); virtual wxAlignment GetAlignment() const; virtual void SetFlags(int flags); virtual int GetFlags() const; virtual bool IsSortKey() const; virtual void SetSortOrder(bool ascending); virtual bool IsSortOrderAscending() const; virtual void SetResizeable(bool resizable); virtual void SetSortable(bool sortable); virtual void SetReorderable(bool reorderable); virtual void SetHidden(bool hidden); """)) c.addAutoProperties() c.addProperty('Title', 'GetTitle', 'SetTitle') c.addProperty('Bitmap', 'GetBitmap', 'SetBitmap') c.addProperty('Width', 'GetWidth', 'SetWidth') c.addProperty('MinWidth', 'GetMinWidth', 'SetMinWidth') c.addProperty('Alignment', 'GetAlignment', 'SetAlignment') c.addProperty('Flags', 'GetFlags', 'SetFlags') c.addProperty('SortOrder', 'IsSortOrderAscending', 'SetSortOrder') #----------------------------------------------------------------- c = module.find('wxDataViewCtrl') tools.fixWindowClass(c) module.addGlobalStr('wxDataViewCtrlNameStr', c) tools.addEnableSystemTheme(c, 'wx.dataview.DataViewCtrl') c.find('AssociateModel.model').transfer = True c.find('AssociateModel').pyName = '_AssociateModel' c.addPyMethod('AssociateModel', '(self, model)', doc="""\ Associates a :class:`DataViewModel` with the control. Ownership of the model object is passed to C++, however it is reference counted so it can be shared with other views. """, body="""\ import wx.siplib wasPyOwned = wx.siplib.ispyowned(model) self._AssociateModel(model) # Ownership of the python object has just been transferred to # C++, so DecRef the C++ instance associated with this python # reference. if wasPyOwned: model.DecRef() """) c.find('PrependColumn.col').transfer = True c.find('InsertColumn.col').transfer = True c.find('AppendColumn.col').transfer = True c.addPyMethod( 'GetColumns', '(self)', doc="Returns a list of column objects.", body="return [self.GetColumn(i) for i in range(self.GetColumnCount())]" ) c.find('GetSelections').ignore() c.addCppMethod('wxDataViewItemArray*', 'GetSelections', '()', isConst=True, factory=True, doc="Returns a list of the currently selected items.", body="""\ wxDataViewItemArray* selections = new wxDataViewItemArray; self->GetSelections(*selections); return selections; """) # Pythonize HitTest c.find('HitTest').ignore() c.addCppMethod('PyObject*', 'HitTest', '(const wxPoint& point)', isConst=True, doc="""\ HitTest(point) -> (item, col)\n Returns the item and column located at point, as a 2 element tuple. """, body="""\ wxDataViewItem* item = new wxDataViewItem();; wxDataViewColumn* col = NULL; self->HitTest(*point, *item, col); wxPyThreadBlocker blocker; PyObject* value = PyTuple_New(2); PyObject* item_obj = wxPyConstructObject((void*)item, wxT("wxDataViewItem"), 1); // owned PyObject* col_obj; if (col) { col_obj = wxPyConstructObject((void*)col, wxT("wxDataViewColumn"), 0); // not owned } else { col_obj = Py_None; Py_INCREF(Py_None); } PyTuple_SET_ITEM(value, 0, item_obj); PyTuple_SET_ITEM(value, 1, col_obj); // PyTuple steals a reference, so we don't need to decref the items here return value; """) # TODO: add support for wxVector templates c.find('GetSortingColumns').ignore() #----------------------------------------------------------------- c = module.find('wxDataViewEvent') tools.fixEventClass(c) c.find('SetCache.from').name = 'from_' c.find('SetCache.to').name = 'to_' c.find('GetDataBuffer').ignore() c.addCppMethod('PyObject*', 'GetDataBuffer', '()', isConst=True, doc="Gets the data buffer for a drop data transfer", body="""\ wxPyThreadBlocker blocker; return wxPyMakeBuffer(self->GetDataBuffer(), self->GetDataSize(), true); """) # TODO: SetDataBuffer c.find('SetDataObject.obj').transfer = True module.addPyCode("""\ EVT_DATAVIEW_SELECTION_CHANGED = wx.PyEventBinder( wxEVT_DATAVIEW_SELECTION_CHANGED, 1) EVT_DATAVIEW_ITEM_ACTIVATED = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_ACTIVATED, 1) EVT_DATAVIEW_ITEM_COLLAPSED = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_COLLAPSED, 1) EVT_DATAVIEW_ITEM_EXPANDED = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_EXPANDED, 1) EVT_DATAVIEW_ITEM_COLLAPSING = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_COLLAPSING, 1) EVT_DATAVIEW_ITEM_EXPANDING = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_EXPANDING, 1) EVT_DATAVIEW_ITEM_START_EDITING = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_START_EDITING, 1) EVT_DATAVIEW_ITEM_EDITING_STARTED = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_EDITING_STARTED, 1) EVT_DATAVIEW_ITEM_EDITING_DONE = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_EDITING_DONE, 1) EVT_DATAVIEW_ITEM_VALUE_CHANGED = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, 1) EVT_DATAVIEW_ITEM_CONTEXT_MENU = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, 1) EVT_DATAVIEW_COLUMN_HEADER_CLICK = wx.PyEventBinder( wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, 1) EVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK = wx.PyEventBinder( wxEVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, 1) EVT_DATAVIEW_COLUMN_SORTED = wx.PyEventBinder( wxEVT_DATAVIEW_COLUMN_SORTED, 1) EVT_DATAVIEW_COLUMN_REORDERED = wx.PyEventBinder( wxEVT_DATAVIEW_COLUMN_REORDERED, 1) EVT_DATAVIEW_ITEM_BEGIN_DRAG = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, 1) EVT_DATAVIEW_ITEM_DROP_POSSIBLE = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, 1) EVT_DATAVIEW_ITEM_DROP = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_DROP, 1) EVT_DATAVIEW_CACHE_HINT = wx.PyEventBinder( wxEVT_DATAVIEW_CACHE_HINT, 1 ) # deprecated wxEVT aliases wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED = wxEVT_DATAVIEW_SELECTION_CHANGED wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED = wxEVT_DATAVIEW_ITEM_ACTIVATED wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED = wxEVT_DATAVIEW_ITEM_COLLAPSED wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED = wxEVT_DATAVIEW_ITEM_EXPANDED wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING = wxEVT_DATAVIEW_ITEM_COLLAPSING wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING = wxEVT_DATAVIEW_ITEM_EXPANDING wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING = wxEVT_DATAVIEW_ITEM_START_EDITING wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED = wxEVT_DATAVIEW_ITEM_EDITING_STARTED wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE = wxEVT_DATAVIEW_ITEM_EDITING_DONE wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED = wxEVT_DATAVIEW_ITEM_VALUE_CHANGED wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU = wxEVT_DATAVIEW_ITEM_CONTEXT_MENU wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK = wxEVT_DATAVIEW_COLUMN_HEADER_CLICK wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK = wxEVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED = wxEVT_DATAVIEW_COLUMN_SORTED wxEVT_COMMAND_DATAVIEW_COLUMN_REORDERED = wxEVT_DATAVIEW_COLUMN_REORDERED wxEVT_COMMAND_DATAVIEW_CACHE_HINT = wxEVT_DATAVIEW_CACHE_HINT wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG = wxEVT_DATAVIEW_ITEM_BEGIN_DRAG wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE = wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE wxEVT_COMMAND_DATAVIEW_ITEM_DROP = wxEVT_DATAVIEW_ITEM_DROP """) #----------------------------------------------------------------- c = module.find('wxDataViewListCtrl') tools.fixWindowClass(c) c.find('GetStore').overloads = [] c.find('AppendItem.values').type = 'const wxVariantVector&' c.find('PrependItem.values').type = 'const wxVariantVector&' c.find('InsertItem.values').type = 'const wxVariantVector&' c.find('GetValue.value').out = True for name in 'AppendColumn InsertColumn PrependColumn'.split(): for m in c.find(name).all(): m.find('column').transfer = True c = module.find('wxDataViewListStore') c.find('AppendItem.values').type = 'const wxVariantVector&' c.find('PrependItem.values').type = 'const wxVariantVector&' c.find('InsertItem.values').type = 'const wxVariantVector&' c.find('GetValueByRow.value').out = True c.find( 'GetValueByRow' ).cppSignature = 'void (wxVariant& value, unsigned int row, unsigned int col)' c.addAutoProperties() #----------------------------------------------------------------- def _setClientDataTrasfer(klass): for item in klass.allItems(): if isinstance(item, ParamDef) and item.type == 'wxClientData *': item.transfer = True c = module.find('wxDataViewTreeCtrl') tools.fixWindowClass(c) _setClientDataTrasfer(c) c.find('GetStore').overloads = [] c = module.find('wxDataViewTreeStore') c.addAutoProperties() tools.fixRefCountedClass(c) _setClientDataTrasfer(c) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
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 = PyEval_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="HitTestSubItem(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; """) # 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): from six import text_type pos = self.InsertItem(self.GetItemCount(), text_type(entry[0])) for i in range(1, len(entry)): self.SetItem(pos, i, text_type(entry[i])) return pos """) c.addCppMethod('wxWindow*', 'GetMainWindow', '()', body="""\ #if defined(__WXMSW__) || defined(__WXMAC__) return self; #else return (wxWindow*)self->m_mainWin; #endif """) #------------------------------------------------------- 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)