def fixRendererClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.addAutoProperties(klass) methods = [ ('Clone', "virtual wxGridCellRenderer* Clone() const /Factory/;"), ('Draw', "virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, " " const wxRect& rect, int row, int col, bool isSelected);"), ('GetBestSize', "virtual wxSize GetBestSize(wxGrid& grid, wxGridCellAttr& attr, " " wxDC& dc, int row, int col);"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code))
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. # ignore some of these enum values e = module.find('wxBitmapType') for i in e: if i.name.endswith('_RESOURCE'): i.ignore() module.addCppCode("""\ #if !defined(__WXMAC__) #define wxCURSOR_COPY_ARROW wxCURSOR_ARROW #endif """) # these are X11 only e = module.find('wxStockCursor') e.find('wxCURSOR_BASED_ARROW_DOWN').ignore() e.find('wxCURSOR_BASED_ARROW_UP').ignore() e.find('wxCURSOR_CROSS_REVERSE').ignore() e.find('wxCURSOR_DOUBLE_ARROW').ignore() module.find('wxClientDisplayRect.x').out = True module.find('wxClientDisplayRect.y').out = True module.find('wxClientDisplayRect.width').out = True module.find('wxClientDisplayRect.height').out = True module.find('wxDisplaySize.width').out = True module.find('wxDisplaySize.height').out = True module.find('wxDisplaySizeMM.width').out = True module.find('wxDisplaySizeMM.height').out = True #--------------------------------------- # wxPoint tweaks c = module.find('wxPoint') tools.addAutoProperties(c) # Some operators are documented within the class that shouldn't be, so just # ignore them all. tools.ignoreAllOperators(c) # Undo a few of those ignores for legitimate items that were # documented correctly for f in c.find('operator+=').all() + c.find('operator-=').all(): f.ignore(False) # Add some method declarations for operators that really do exist. Note # that these actually use C++ global operator functions, but we treat # them as methods to help disambiguate implementations due to how # multiple classes can be converted automatically to/from 2-element # sequences. c.addCppMethod('bool', '__eq__', '(const wxPoint& other)', body="return *self == *other;") c.addCppMethod('bool', '__ne__', '(const wxPoint& other)', body="return *self != *other;") c.addItem( etgtools.WigCode("""\ wxPoint operator+(const wxPoint& other); wxPoint operator+(const wxSize& other); wxPoint operator-(); wxPoint operator-(const wxPoint& other); wxPoint operator-(const wxSize& other); wxPoint operator*(int i); wxPoint operator/(int i); """)) # wxPoint typemap c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxPoint') c.addCppMethod('PyObject*', 'Get', '()', """\ wxPyThreadBlocker blocker; return sipBuildResult(0, "(ii)", self->x, self->y); """, pyArgsString="() -> (x,y)", briefDoc="Return the x and y properties as a tuple.") tools.addGetIMMethodTemplate(module, c, ['x', 'y']) # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "wx.Point"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (Point, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod( '__setitem__', '(self, idx, val)', """\ if idx == 0: self.x = val elif idx == 1: self.y = val else: raise IndexError """) c.addPyCode('Point.__safe_for_unpickling__ = True') module.addItem( tools.wxListWrapperTemplate('wxPointList', 'wxPoint', module, includeConvertToType=True)) #--------------------------------------- # wxSize tweaks c = module.find('wxSize') tools.addAutoProperties(c) # Used for testing releasing or holding the GIL in giltest.py #c.find('wxSize').findOverload('int width, int height').releaseGIL() #c.find('DecBy').findOverload('int dx, int dy').releaseGIL() #c.find('IncBy').findOverload('int dx, int dy').releaseGIL() c.addProperty("width GetWidth SetWidth") c.addProperty("height GetHeight SetHeight") # TODO: How prevalent is the use of x,y properties on a size object? Can we deprecate them? c.addProperty("x GetWidth SetWidth") c.addProperty("y GetHeight SetHeight") # Take care of the same issues as wxPoint tools.ignoreAllOperators(c) for f in c.find('operator+=').all() + \ c.find('operator-=').all() + \ c.find('operator*=').all() + \ c.find('operator/=').all(): f.ignore(False) c.addCppMethod('bool', '__eq__', '(const wxSize& other)', body="return *self == *other;") c.addCppMethod('bool', '__ne__', '(const wxSize& other)', body="return *self != *other;") c.addItem( etgtools.WigCode("""\ wxSize operator+(const wxSize& other); wxSize operator-(const wxSize& other); wxSize operator*(int i); wxSize operator/(int i); wxPoint operator+(const wxPoint& other); wxPoint operator-(const wxPoint& other); wxRealPoint operator+(const wxRealPoint& other); wxRealPoint operator-(const wxRealPoint& other); """)) # wxSize typemap c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxSize') c.addCppMethod( 'PyObject*', 'Get', '()', """\ wxPyThreadBlocker blocker; return sipBuildResult(0, "(ii)", self->GetWidth(), self->GetHeight()); """, pyArgsString="() -> (width, height)", briefDoc="Return the width and height properties as a tuple.") tools.addGetIMMethodTemplate(module, c, ['width', 'height']) # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "wx.Size"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (Size, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod( '__setitem__', '(self, idx, val)', """\ if idx == 0: self.width = val elif idx == 1: self.height = val else: raise IndexError """) c.addPyCode('Size.__safe_for_unpickling__ = True') #--------------------------------------- # wxRect tweaks c = module.find('wxRect') assert isinstance(c, etgtools.ClassDef) tools.addAutoProperties(c) c.addProperty("left GetLeft SetLeft") c.addProperty("top GetTop SetTop") c.addProperty("right GetRight SetRight") c.addProperty("bottom GetBottom SetBottom") c.addProperty("bottomLeft GetBottomLeft SetBottomLeft") c.addProperty("bottomRight GetBottomRight SetBottomRight") c.addProperty("topLeft GetTopLeft SetTopLeft") c.addProperty("topRight GetTopRight SetTopRight") # take care of the same issues as wxPoint tools.ignoreAllOperators(c) for f in c.find('operator+=').all() + \ c.find('operator*=').all(): f.ignore(False) c.addCppMethod('bool', '__eq__', '(const wxRect& other)', body="return *self == *other;") c.addCppMethod('bool', '__ne__', '(const wxRect& other)', body="return *self != *other;") c.addItem( etgtools.WigCode("""\ wxRect operator+(const wxRect& other); wxRect operator*(const wxRect& other); """)) # Because of our add-ons that make wx.Point and wx.Size act like 2-element # sequences, and also the typecheck code that allows 2-element sequences, then # we end up with a bit of confusion about the (Point,Point) and the # (Point,Size) overloads of the wx.Rect constructor. The confusion can be # dealt with by using keyword args, but I think that the (Point,Size) version # will be used more, so reorder the overloads so it is found first. m = module.find('wxRect.wxRect') mo = m.findOverload('topLeft') del m.overloads[m.overloads.index(mo)] m.overloads.append(mo) # These methods have some overloads that will end up with the same signature # in Python, so we have to remove one. module.find('wxRect.Deflate').findOverload(') const').ignore() module.find('wxRect.Inflate').findOverload(') const').ignore() module.find('wxRect.Union').findOverload(') const').ignore() module.find('wxRect.Intersect').findOverload(') const').ignore() # wxRect typemap c.convertFromPyObject = tools.convertFourIntegersTemplate('wxRect') c.addCppMethod('PyObject*', 'Get', '()', """\ wxPyThreadBlocker blocker; return sipBuildResult(0, "(iiii)", self->x, self->y, self->width, self->height); """, pyArgsString="() -> (x, y, width, height)", briefDoc="Return the rectangle's properties as a tuple.") tools.addGetIMMethodTemplate(module, c, ['x', 'y', 'width', 'height']) # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "wx.Rect"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0,0,0)') c.addPyMethod('__reduce__', '(self)', 'return (Rect, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod( '__setitem__', '(self, idx, val)', """\ if idx == 0: self.x = val elif idx == 1: self.y = val elif idx == 2: self.width = val elif idx == 3: self.height = val else: raise IndexError """) c.addPyCode('Rect.__safe_for_unpickling__ = True') #--------------------------------------- # wxRealPoint tweaks c = module.find('wxRealPoint') tools.addAutoProperties(c) # take care of the same issues as wxPoint tools.ignoreAllOperators(c) for f in c.find('operator+=').all() + \ c.find('operator-=').all(): f.ignore(False) c.addCppMethod('bool', '__eq__', '(const wxRealPoint& other)', body="return *self == *other;") c.addCppMethod('bool', '__ne__', '(const wxRealPoint& other)', body="return *self != *other;") c.addItem( etgtools.WigCode("""\ wxRealPoint operator+(const wxRealPoint& other); wxRealPoint operator-(const wxRealPoint& other); wxRealPoint operator*(int i); wxRealPoint operator/(int i); """)) # wxRealPoint typemap c.convertFromPyObject = tools.convertTwoDoublesTemplate('wxRealPoint') c.addCppMethod('PyObject*', 'Get', '()', """\ wxPyThreadBlocker blocker; return sipBuildResult(0, "(dd)", self->x, self->y); """, pyArgsString="() -> (x, y)", briefDoc="Return the point's properties as a tuple.") tools.addGetIMMethodTemplate(module, c, ['x', 'y']) # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "wx.RealPoint"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (Rect, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod( '__setitem__', '(self, idx, val)', """\ if idx == 0: self.x = val elif idx == 1: self.y = val else: raise IndexError """) c.addPyCode('RealPoint.__safe_for_unpickling__ = True') c = module.find('wxColourDatabase') c.mustHaveApp() c.addPyMethod('FindColour', '(self, colour)', 'return self.Find(colour)') module.find('wxTheColourDatabase').ignore() #----------------------------------------------------------------- module.addCppFunction('PyObject*', 'IntersectRect', '(wxRect* r1, wxRect* r2)', doc="""\ Calculate and return the intersection of r1 and r2. Returns None if there is no intersection.""", body="""\ wxRegion reg1(*r1); wxRegion reg2(*r2); wxRect dest(0,0,0,0); PyObject* obj; reg1.Intersect(reg2); dest = reg1.GetBox(); wxPyThreadBlocker blocker; if (dest != wxRect(0,0,0,0)) { wxRect* newRect = new wxRect(dest); obj = wxPyConstructObject((void*)newRect, wxT("wxRect"), true); return obj; } Py_INCREF(Py_None); return Py_None; """) for funcname in [ 'wxColourDisplay', 'wxDisplayDepth', 'wxDisplaySize', 'wxGetDisplaySize', 'wxDisplaySizeMM', 'wxGetDisplaySizeMM', 'wxGetDisplayPPI', 'wxClientDisplayRect', 'wxGetClientDisplayRect', 'wxSetCursor', #'wxGetXDisplay', ]: c = module.find(funcname) c.mustHaveApp() #----------------------------------------------------------------- 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/webview.h> #if wxUSE_WEBVIEW_IE && defined(__WXMSW__) #include <wx/msw/webview_ie.h> #endif """) module.addGlobalStr('wxWebViewBackendDefault') module.addGlobalStr('wxWebViewBackendIE') module.addGlobalStr('wxWebViewBackendWebKit') c = module.find('wxWebView') assert isinstance(c, etgtools.ClassDef) tools.fixWindowClass(c) c.abstract = True module.addGlobalStr('wxWebViewNameStr', c) module.addGlobalStr('wxWebViewDefaultURLStr', c) for m in c.find('New').all(): m.factory = True c.find('New.id').default = 'wxID_ANY' c.find('New.parent').transferThis = True c.find('RegisterHandler.handler').type = 'wxWebViewHandler*' c.find('RegisterHandler.handler').transfer = True c.find('RegisterHandler').setCppCode_sip( "sipCpp->RegisterHandler(wxSharedPtr<wxWebViewHandler>(handler));") c.find('RegisterFactory.factory').type = 'wxWebViewFactory*' c.find('RegisterFactory.factory').transfer = True c.find('RegisterFactory').setCppCode_sip( "wxWebView::RegisterFactory(*backend, wxSharedPtr<wxWebViewFactory>(factory));") c.find('RunScript.output').out = True # Custom code to deal with the # wxVector<wxSharedPtr<wxWebViewHistoryItem>> return type of these two # methods. We'll just convert them to a Python list of history items. code = """\ wxPyThreadBlocker blocker; PyObject* result = PyList_New(0); wxVector<wxSharedPtr<wxWebViewHistoryItem> > vector = self->{method}(); for (size_t idx=0; idx < vector.size(); idx++) {{ PyObject* obj; wxWebViewHistoryItem* item = new wxWebViewHistoryItem(*vector[idx].get()); obj = wxPyConstructObject((void*)item, "wxWebViewHistoryItem", true); PyList_Append(result, obj); Py_DECREF(obj); }} return result; """ c.find('GetBackwardHistory').type = 'PyObject*' c.find('GetBackwardHistory').setCppCode(code.format(method='GetBackwardHistory')) c.find('GetForwardHistory').type = 'PyObject*' c.find('GetForwardHistory').setCppCode(code.format(method='GetForwardHistory')) # Since LoadHistoryItem expects to get an actual item in the history # list, and since we make copies of the items in the cppCode above, then # this won't be possible to do from the Python wrappers. However, it's # just as easy to use LoadURL to reload a history item so it's not a # great loss. c.find('LoadHistoryItem').ignore() ##c.find('LoadHistoryItem.item').type = 'wxWebViewHistoryItem*' ##c.find('LoadHistoryItem.item').transfer = True ##c.find('LoadHistoryItem').setCppCode_sip( ## "sipCpp->LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem>(item));") c.find('MSWSetModernEmulationLevel').setCppCode("""\ #if wxUSE_WEBVIEW_IE && defined(__WXMSW__) return wxWebViewIE::MSWSetModernEmulationLevel(modernLevel); #else return false; #endif """) c = module.find('wxWebViewEvent') tools.fixEventClass(c) module.addPyCode("""\ EVT_WEBVIEW_NAVIGATING = wx.PyEventBinder( wxEVT_WEBVIEW_NAVIGATING, 1 ) EVT_WEBVIEW_NAVIGATED = wx.PyEventBinder( wxEVT_WEBVIEW_NAVIGATED, 1 ) EVT_WEBVIEW_LOADED = wx.PyEventBinder( wxEVT_WEBVIEW_LOADED, 1 ) EVT_WEBVIEW_ERROR = wx.PyEventBinder( wxEVT_WEBVIEW_ERROR, 1 ) EVT_WEBVIEW_NEWWINDOW = wx.PyEventBinder( wxEVT_WEBVIEW_NEWWINDOW, 1 ) EVT_WEBVIEW_TITLE_CHANGED = wx.PyEventBinder( wxEVT_WEBVIEW_TITLE_CHANGED, 1 ) # deprecated wxEVT aliases wxEVT_COMMAND_WEBVIEW_NAVIGATING = wxEVT_WEBVIEW_NAVIGATING wxEVT_COMMAND_WEBVIEW_NAVIGATED = wxEVT_WEBVIEW_NAVIGATED wxEVT_COMMAND_WEBVIEW_LOADED = wxEVT_WEBVIEW_LOADED wxEVT_COMMAND_WEBVIEW_ERROR = wxEVT_WEBVIEW_ERROR wxEVT_COMMAND_WEBVIEW_NEWWINDOW = wxEVT_WEBVIEW_NEWWINDOW wxEVT_COMMAND_WEBVIEW_TITLE_CHANGED = wxEVT_WEBVIEW_TITLE_CHANGED """) c = module.find('wxWebViewHistoryItem') tools.addAutoProperties(c) for name in [ 'wxWebViewHandler', 'wxWebViewArchiveHandler', 'wxWebViewFSHandler' ]: c = module.find(name) c.find('GetFile').factory = True #----------------------------------------------------------------- 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.addGlobalStr('wxGridNameStr', module.items[0]) module.addPyCode("""\ GRID_VALUE_STRING = "string" GRID_VALUE_BOOL = "bool" GRID_VALUE_NUMBER = "long" GRID_VALUE_FLOAT = "double" GRID_VALUE_CHOICE = "choice" GRID_VALUE_DATE = "date" GRID_VALUE_TEXT = "string" GRID_VALUE_LONG = "long" GRID_VALUE_CHOICEINT = "choiceint" GRID_VALUE_DATETIME = "datetime" """) # Add compatibility constants for these since they've been removed from wxWidgets # TODO: Remove these in a future release. module.addPyCode("""\ GRIDTABLE_REQUEST_VIEW_GET_VALUES = 2000 GRIDTABLE_REQUEST_VIEW_SEND_VALUES = 2001 """) module.insertItem( 0, etgtools.TypedefDef(type='wxWindow', name='wxGridWindow')) #----------------------------------------------------------------- c = module.find('wxGridCellCoords') assert isinstance(c, etgtools.ClassDef) tools.addAutoProperties(c) c.find('operator!').ignore() c.find('operator=').ignore() # Add a typemap for 2 element sequences c.convertFromPyObject = tools.convertTwoIntegersTemplate( 'wxGridCellCoords') c.addCppMethod('PyObject*', 'Get', '()', """\ wxPyThreadBlocker blocker; return sipBuildResult(0, "(ii)", self->GetRow(), self->GetCol()); """, pyArgsString="() -> (row,col)", briefDoc="Return the row and col properties as a tuple.") tools.addGetIMMethodTemplate(module, c, ['Row', 'Col']) # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "GridCellCoords"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__bool__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (GridCellCoords, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod( '__setitem__', '(self, idx, val)', """\ if idx == 0: self.Row = val elif idx == 1: self.Col = val else: raise IndexError """) c.addPyCode('GridCellCoords.__safe_for_unpickling__ = True') module.addItem( tools.wxArrayWrapperTemplate('wxGridCellCoordsArray', 'wxGridCellCoords', module, getItemCopy=True)) #----------------------------------------------------------------- c = module.find('wxGridBlockCoords') tools.addAutoProperties(c) c.find('operator!').ignore() c.addCppMethod('int', '__bool__', '()', "return self->operator!();") c.addCppMethod('PyObject*', 'Get', '()', """\ wxPyThreadBlocker blocker; return sipBuildResult(0, "(iiii)", self->GetTopRow(), self->GetLeftCol(), self->GetBottomRow(), self->GetRightCol()); """, pyArgsString="() -> (topRow, leftCol, bottomRow, rightCol)", briefDoc="Return the block coordinants as a tuple.") c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "GridBlockCoords"+str(self.Get())') #----------------------------------------------------------------- c = module.find('wxGridBlockDiffResult') c.find('m_parts').ignore() c.addCppMethod( 'PyObject*', '_getParts', '()', """\ wxPyThreadBlocker blocker; PyObject* ret = PyTuple_New(4); if (ret) { PyTuple_SET_ITEM(ret, 0, wxPyConstructObject(&self->m_parts[0], "wxGridBlockCoords", false)); PyTuple_SET_ITEM(ret, 1, wxPyConstructObject(&self->m_parts[1], "wxGridBlockCoords", false)); PyTuple_SET_ITEM(ret, 2, wxPyConstructObject(&self->m_parts[2], "wxGridBlockCoords", false)); PyTuple_SET_ITEM(ret, 3, wxPyConstructObject(&self->m_parts[3], "wxGridBlockCoords", false)); } return ret; """) c.addProperty('m_parts', '_getParts') #----------------------------------------------------------------- c = module.find('wxGridBlocks') c.addPrivateDefaultCtor() c.addPrivateAssignOp() c.addPyMethod( '__iter__', '(self)', 'return PyGridBlocksIterator(self)', "Returns a Python iterator for accessing the collection of grid blocks." ) # This class is the Python iterator that knows how to fetch blocks from the # wxGridBlocks object c.addPyCode("""\ class PyGridBlocksIterator(object): "A Python iterator for GridBlocks objects" def __init__(self, blocks): self._blocks = blocks self._iterator = self._blocks.begin() def __next__(self): if self._iterator == self._blocks.end(): raise StopIteration obj = self._iterator._get() self._iterator = self._iterator._next() return obj """) # c.find('iterator').addCppMethod('wxGridBlocks::iterator', '_next', '()', # "return self->operator++();") # c.find('iterator').addCppMethod('const wxGridBlockCoords&', '_get', '()', # "return self->operator*();") # TODO: Doing these the normal way (above) breaks because it tries to use just # "iterator" for the self param type, instead of wxGridBlocks::iterator. # That should be fixable, but until then just add these methods the manual # sip way. c.find('iterator').addItem( etgtools.WigCode("""\ iterator& _next(); %MethodCode PyErr_Clear(); Py_BEGIN_ALLOW_THREADS sipRes = &sipCpp->operator++(); Py_END_ALLOW_THREADS if (PyErr_Occurred()) return 0; %End const wxGridBlockCoords& _get() const; %MethodCode PyErr_Clear(); Py_BEGIN_ALLOW_THREADS sipRes = new ::wxGridBlockCoords(sipCpp->operator*()); Py_END_ALLOW_THREADS if (PyErr_Occurred()) return 0; %End bool __eq__(const iterator& it) const; bool __ne__(const iterator& it) const; """)) #----------------------------------------------------------------- c = module.find('wxGridSizesInfo') c.find('m_customSizes').ignore( ) # TODO: Add support for wxUnsignedToIntHashMap?? #----------------------------------------------------------------- def fixRendererClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.fixRefCountedClass(klass) tools.addAutoProperties(klass) methods = [ ('Clone', "virtual wxGridCellRenderer* Clone() const /Factory/;"), ('Draw', "virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, " " const wxRect& rect, int row, int col, bool isSelected);"), ('GetBestSize', "virtual wxSize GetBestSize(wxGrid& grid, wxGridCellAttr& attr, " " wxDC& dc, int row, int col);"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code)) c = module.find('wxGridCellRenderer') c.addPrivateCopyCtor() c.find('~wxGridCellRenderer').ignore(False) c.find('Clone').factory = True tools.fixRefCountedClass(c) for name in ITEMS: if 'Cell' in name and 'Renderer' in name: fixRendererClass(name) module.addPyCode( "PyGridCellRenderer = wx.deprecated(GridCellRenderer, 'Use GridCellRenderer instead.')" ) #----------------------------------------------------------------- c = module.find('wxGridActivationResult') c.ignore() # FIXME c.addPrivateAssignOp() c.instanceCode = 'sipCpp = new wxGridActivationResult::DoNothing();' c = module.find('wxGridActivationSource') c.ignore() # FIXME c.noDefCtor = True c.addPrivateAssignOp() #----------------------------------------------------------------- def fixEditorClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.fixRefCountedClass(klass) tools.addAutoProperties(klass) methods = [ ('BeginEdit', "virtual void BeginEdit(int row, int col, wxGrid* grid);"), ('Clone', "virtual wxGridCellEditor* Clone() const /Factory/;"), ('Create', "virtual void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler);" ), #('EndEdit', "virtual bool EndEdit(int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval);"), ('ApplyEdit', "virtual void ApplyEdit(int row, int col, wxGrid* grid);"), ('Reset', "virtual void Reset();"), ('GetValue', "virtual wxString GetValue() const;"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code)) # Fix up EndEdit so it returns newval on success or None on failure pureVirtual = False if klass.findItem('EndEdit'): klass.find('EndEdit').ignore() pureVirtual = True # The Python version of EndEdit has a different signature than the # C++ version, so we need to take care of mapping between them so the # C++ compiler still recognizes this as a match for the virtual # method in the base class. klass.addCppMethod( 'PyObject*', 'EndEdit', '(int row, int col, const wxGrid* grid, const wxString& oldval)', cppSignature= 'bool (int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval)', pyArgsString='(row, col, grid, oldval)', isVirtual=True, isPureVirtual=pureVirtual, doc="""\ End editing the cell. This function must check if the current value of the editing cell is valid and different from the original value in its string form. If not then simply return None. If it has changed then this method should save the new value so that ApplyEdit can apply it later and the string representation of the new value should be returned. Notice that this method shoiuld not modify the grid as the change could still be vetoed. """, # Code for Python --> C++ calls. Make it return newval or None. body="""\ bool rv; wxString newval; rv = self->EndEdit(row, col, grid, *oldval, &newval); if (rv) { return wx2PyString(newval); } else { Py_INCREF(Py_None); return Py_None; } """, # Code for C++ --> Python calls. This is used when a C++ method # call needs to be reflected to a call to the overridden Python # method, so we need to translate between the real C++ signature # and the Python signature. virtualCatcherCode="""\ // VirtualCatcherCode for wx.grid.GridCellEditor.EndEdit PyObject *result; result = sipCallMethod(0, sipMethod, "iiDN", row, col, const_cast<wxGrid *>(grid),sipType_wxGrid,NULL, new wxString(oldval),sipType_wxString,NULL); if (result == NULL) { if (PyErr_Occurred()) PyErr_Print(); sipRes = false; } else if (result == Py_None) { sipRes = false; } else { sipRes = true; *newval = Py2wxString(result); } Py_XDECREF(result); """ if pureVirtual else "", # only used with the base class ) c = module.find('wxGridCellEditor') c.addPrivateCopyCtor() c.find('~wxGridCellEditor').ignore(False) c.find('Clone').factory = True tools.fixRefCountedClass(c) c.find('TryActivate').ignore( ) # FIXME: remove this when the compilation issues with wxGridActivationResult is fixed c = module.find('wxGridCellActivatableEditor') c.ignore() # FIXME: see above c = module.find('wxGridCellChoiceEditor') c.find('wxGridCellChoiceEditor').findOverload('count').ignore() for name in ITEMS: if 'Cell' in name and 'Editor' in name and name != 'wxGridCellActivatableEditor': fixEditorClass(name) module.addPyCode( "PyGridCellEditor = wx.deprecated(GridCellEditor, 'Use GridCellEditor instead.')" ) #----------------------------------------------------------------- c = module.find('wxGridCellAttr') c.addPrivateCopyCtor() c.find('~wxGridCellAttr').ignore(False) c.find('Clone').factory = True tools.fixRefCountedClass(c) c.find('GetAlignment.hAlign').out = True c.find('GetAlignment.vAlign').out = True c.find('GetNonDefaultAlignment.hAlign').out = True c.find('GetNonDefaultAlignment.vAlign').out = True c.find('GetSize.num_rows').out = True c.find('GetSize.num_cols').out = True c.find('SetEditor.editor' ).transfer = True # these are probably redundant now... c.find('SetRenderer.renderer').transfer = True #----------------------------------------------------------------- module.find('wxGridCellRendererPtr').piIgnored = True module.find('wxGridCellEditorPtr').piIgnored = True module.find('wxGridCellAttrPtr').piIgnored = True #----------------------------------------------------------------- # The instanceCode attribute is code that is used to make a default # instance of the class. We can't create them using the same class in # this case because they are abstract. c = module.find('wxGridCornerHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridCornerHeaderRendererDefault;' c = module.find('wxGridRowHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridRowHeaderRendererDefault;' c = module.find('wxGridColumnHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridColumnHeaderRendererDefault;' #----------------------------------------------------------------- c = module.find('wxGridCellAttrProvider') c.addPrivateCopyCtor() c.find('SetAttr.attr').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True module.addPyCode( "PyGridCellAttrProvider = wx.deprecated(GridCellAttrProvider, 'Use GridCellAttrProvider instead.')" ) #----------------------------------------------------------------- c = module.find('wxGridTableBase') c.addPrivateCopyCtor() c.find('SetAttr.attr').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True module.addPyCode( "PyGridTableBase = wx.deprecated(GridTableBase, 'Use GridTableBase instead.')" ) # Make the GetValue methods easier to use from Python. For example, # instead of needing to always return a string, the GetValue in the derived # class can return any type (as long as the renderer and editor knows how # to deal with it, and the value can be converted to a string for display). m = c.find('GetValue') m.type = 'PyObject*' m.cppSignature = 'wxString (int row, int col)' m.setCppCode("return wx2PyString(self->GetValue(row, col));") m.virtualCatcherCode = """\ // virtualCatcherCode for GridTableBase.GetValue PyObject *result = sipCallMethod(&sipIsErr, sipMethod, "ii", row, col); if (result == NULL) { if (PyErr_Occurred()) PyErr_Print(); sipRes = ""; } else if (result == Py_None) { sipRes = ""; } else { if (!PyBytes_Check(result) && !PyUnicode_Check(result)) { PyObject* old = result; result = PyObject_Str(result); Py_DECREF(old); } sipRes = Py2wxString(result); } Py_XDECREF(result); """ # SetValue is okay as-is... # Replace these virtuals in the base class with Python methods, they just # need to call GetValue or SetValue directly since they must already be # implemented in the derived Python class because they are pure virtual. c.addPyMethod('GetValueAsLong', '(self, row, col)', body="""\ val = self.GetValue(row, col) try: return int(val) except ValueError: return 0 """, docsIgnored=True) c.addPyMethod('GetValueAsDouble', '(self, row, col)', body="""\ val = self.GetValue(row, col) try: return float(val) except ValueError: return 0.0 """, docsIgnored=True) c.addPyMethod('GetValueAsBool', '(self, row, col)', body="""\ val = self.GetValue(row, col) try: return bool(val) except ValueError: return False """, docsIgnored=True) c.addPyMethod('SetValueAsLong', '(self, row, col, value)', body="self.SetValue(row, col, int(value))", docsIgnored=True) c.addPyMethod('SetValueAsDouble', '(self, row, col, value)', body="self.SetValue(row, col, float(value))", docsIgnored=True) c.addPyMethod('SetValueAsBool', '(self, row, col, value)', body="self.SetValue(row, col, bool(value))", docsIgnored=True) # Should we add support for using generic PyObjects in the *AsCustom # methods? I don't think it is necessary due to the GetValue # modifications above, so for now, at least, let.s just ignore them. c.find('GetValueAsCustom').ignore() c.find('SetValueAsCustom').ignore() #----------------------------------------------------------------- c = module.find('wxGridStringTable') c.addPrivateCopyCtor() #----------------------------------------------------------------- c = module.find('wxGridTableMessage') c.addPrivateCopyCtor() #----------------------------------------------------------------- c = module.find('wxGrid') tools.fixWindowClass(c, ignoreProtected=False) c.bases = ['wxScrolledCanvas'] c.find('GetColLabelAlignment.horiz').out = True c.find('GetColLabelAlignment.vert').out = True c.find('GetRowLabelAlignment.horiz').out = True c.find('GetRowLabelAlignment.vert').out = True c.find('GetCellAlignment.horiz').out = True c.find('GetCellAlignment.vert').out = True c.find('GetDefaultCellAlignment.horiz').out = True c.find('GetDefaultCellAlignment.vert').out = True c.find('RegisterDataType.renderer').transfer = True c.find('RegisterDataType.editor').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True c.find('SetCellEditor.editor').transfer = True c.find('SetCellRenderer.renderer').transfer = True # This overload is deprecated, so don't generate code for it. c.find('SetCellValue').findOverload('wxString &val').ignore() c.find('SetDefaultEditor.editor').transfer = True c.find('SetDefaultRenderer.renderer').transfer = True for n in [ 'GetColGridLinePen', 'GetDefaultGridLinePen', 'GetRowGridLinePen' ]: c.find(n).isVirtual = True # The SetTable method can optionally pass ownership of the table # object to the grid, so we need to optionally update the # ownership of the Python proxy object to match. c.find('SetTable').pyName = '_SetTable' c.addPyMethod( 'SetTable', '(self, table, takeOwnership=False, selmode=Grid.GridSelectCells)', piArgsString= '(self, table, takeOwnership=False, selmode=GridSelectCells)', doc="Set the Grid Table to be used by this grid.", body="""\ val = self._SetTable(table, takeOwnership, selmode) if takeOwnership: import wx.siplib wx.siplib.transferto(table, self) return val """) # SIP will normally try to add support for overriding this method since # it is inherited from super classes, but in this case we want it to be # ignored (because IRL it is private in one of the intermediate classes) # so we'll tell SIP that it is private here instead. c.addItem( etgtools.WigCode("""\ wxSize GetSizeAvailableForScrollTarget(const wxSize& size); """, protection='private')) # Add a simpler set of names for the wxGridSelectionModes enum c.addPyCode("""\ Grid.SelectCells = Grid.GridSelectCells Grid.SelectRows = Grid.GridSelectRows Grid.SelectColumns = Grid.GridSelectColumns Grid.SelectRowsOrColumns = Grid.GridSelectRowsOrColumns """) c.find('SetCellAlignment').findOverload('align').ignore() c.find('SetCellTextColour').overloads = [] c.find('GetGridWindowOffset').findOverload('int &x').ignore() # Custom code to deal with the wxGridBlockCoordsVector return type of these # methods. It's a wxVector, which we'll just convert to a list. # TODO: There are a few of these now to we ought to either wrap wxVector, or add # something in tweaker_tools to make adding code like this easier and more # automated. code = """\ wxPyThreadBlocker blocker; PyObject* result = PyList_New(0); wxGridBlockCoordsVector vector = self->{method}(); for (size_t idx=0; idx < vector.size(); idx++) {{ PyObject* obj; wxGridBlockCoords* item = new wxGridBlockCoords(vector[idx]); obj = wxPyConstructObject((void*)item, "wxGridBlockCoords", true); PyList_Append(result, obj); Py_DECREF(obj); }} return result; """ c.find('GetSelectedRowBlocks').type = 'PyObject*' c.find('GetSelectedRowBlocks').setCppCode( code.format(method='GetSelectedRowBlocks')) c.find('GetSelectedColBlocks').type = 'PyObject*' c.find('GetSelectedColBlocks').setCppCode( code.format(method='GetSelectedColBlocks')) #----------------------------------------------------------------- c = module.find('wxGridUpdateLocker') c.addPrivateCopyCtor() # context manager methods c.addPyMethod('__enter__', '(self)', 'return self') c.addPyMethod('__exit__', '(self, exc_type, exc_val, exc_tb)', 'return False') #----------------------------------------------------------------- for name in [ 'wxGridSizeEvent', 'wxGridRangeSelectEvent', 'wxGridEditorCreatedEvent', 'wxGridEvent' ]: c = module.find(name) tools.fixEventClass(c) module.addPyCode("""\ EVT_GRID_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK ) EVT_GRID_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK ) EVT_GRID_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK ) EVT_GRID_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK ) EVT_GRID_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK ) EVT_GRID_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK ) EVT_GRID_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK ) EVT_GRID_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK ) EVT_GRID_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE ) EVT_GRID_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE ) EVT_GRID_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT ) EVT_GRID_CELL_CHANGING = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGING ) EVT_GRID_CELL_CHANGED = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGED ) EVT_GRID_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL ) EVT_GRID_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN ) EVT_GRID_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN ) EVT_GRID_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED ) EVT_GRID_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG ) EVT_GRID_COL_MOVE = wx.PyEventBinder( wxEVT_GRID_COL_MOVE ) EVT_GRID_COL_SORT = wx.PyEventBinder( wxEVT_GRID_COL_SORT ) EVT_GRID_TABBING = wx.PyEventBinder( wxEVT_GRID_TABBING ) # The same as above but with the ability to specify an identifier EVT_GRID_CMD_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK, 1 ) EVT_GRID_CMD_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK, 1 ) EVT_GRID_CMD_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK, 1 ) EVT_GRID_CMD_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK, 1 ) EVT_GRID_CMD_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK, 1 ) EVT_GRID_CMD_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK, 1 ) EVT_GRID_CMD_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK, 1 ) EVT_GRID_CMD_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK, 1 ) EVT_GRID_CMD_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE, 1 ) EVT_GRID_CMD_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE, 1 ) EVT_GRID_CMD_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT, 1 ) EVT_GRID_CMD_CELL_CHANGING = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGING, 1 ) EVT_GRID_CMD_CELL_CHANGED = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGED, 1 ) EVT_GRID_CMD_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL, 1 ) EVT_GRID_CMD_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN, 1 ) EVT_GRID_CMD_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN, 1 ) EVT_GRID_CMD_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED, 1 ) EVT_GRID_CMD_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG, 1 ) EVT_GRID_CMD_COL_MOVE = wx.PyEventBinder( wxEVT_GRID_COL_MOVE, 1 ) EVT_GRID_CMD_COL_SORT = wx.PyEventBinder( wxEVT_GRID_COL_SORT, 1 ) EVT_GRID_CMD_TABBING = wx.PyEventBinder( wxEVT_GRID_TABBING, 1 ) """) #----------------------------------------------------------------- #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def fixEditorClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.fixRefCountedClass(klass) tools.addAutoProperties(klass) methods = [ ('BeginEdit', "virtual void BeginEdit(int row, int col, wxGrid* grid);"), ('Clone', "virtual wxGridCellEditor* Clone() const /Factory/;"), ('Create', "virtual void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler);" ), #('EndEdit', "virtual bool EndEdit(int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval);"), ('ApplyEdit', "virtual void ApplyEdit(int row, int col, wxGrid* grid);"), ('Reset', "virtual void Reset();"), ('GetValue', "virtual wxString GetValue() const;"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code)) # Fix up EndEdit so it returns newval on success or None on failure pureVirtual = False if klass.findItem('EndEdit'): klass.find('EndEdit').ignore() pureVirtual = True # The Python version of EndEdit has a different signature than the # C++ version, so we need to take care of mapping between them so the # C++ compiler still recognizes this as a match for the virtual # method in the base class. klass.addCppMethod( 'PyObject*', 'EndEdit', '(int row, int col, const wxGrid* grid, const wxString& oldval)', cppSignature= 'bool (int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval)', pyArgsString='(row, col, grid, oldval)', isVirtual=True, isPureVirtual=pureVirtual, doc="""\ End editing the cell. This function must check if the current value of the editing cell is valid and different from the original value in its string form. If not then simply return None. If it has changed then this method should save the new value so that ApplyEdit can apply it later and the string representation of the new value should be returned. Notice that this method shoiuld not modify the grid as the change could still be vetoed. """, # Code for Python --> C++ calls. Make it return newval or None. body="""\ bool rv; wxString newval; rv = self->EndEdit(row, col, grid, *oldval, &newval); if (rv) { return wx2PyString(newval); } else { Py_INCREF(Py_None); return Py_None; } """, # Code for C++ --> Python calls. This is used when a C++ method # call needs to be reflected to a call to the overridden Python # method, so we need to translate between the real C++ signature # and the Python signature. virtualCatcherCode="""\ // VirtualCatcherCode for wx.grid.GridCellEditor.EndEdit PyObject *result; result = sipCallMethod(0, sipMethod, "iiDN", row, col, const_cast<wxGrid *>(grid),sipType_wxGrid,NULL, new wxString(oldval),sipType_wxString,NULL); if (result == NULL) { if (PyErr_Occurred()) PyErr_Print(); sipRes = false; } else if (result == Py_None) { sipRes = false; } else { sipRes = true; *newval = Py2wxString(result); } Py_XDECREF(result); """ if pureVirtual else "", # only used with the base class )
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/webview.h> #if wxUSE_WEBVIEW_IE && defined(__WXMSW__) #include <wx/msw/webview_ie.h> #include <wx/msw/webview_edge.h> #endif """) module.addHeaderCode('#include <wx/filesys.h>') module.addGlobalStr('wxWebViewBackendDefault', 0) module.addGlobalStr('wxWebViewBackendIE', 0) module.addGlobalStr('wxWebViewBackendEdge', 0) module.addGlobalStr('wxWebViewBackendWebKit', 0) module.addGlobalStr('wxWebViewNameStr', 0) module.addGlobalStr('wxWebViewDefaultURLStr', 0) module.addHeaderCode("""\ #if wxUSE_WEBVIEW && !defined(wxWebViewIE_H) enum wxWebViewIE_EmulationLevel { wxWEBVIEWIE_EMU_DEFAULT = 0, wxWEBVIEWIE_EMU_IE7 = 7000, wxWEBVIEWIE_EMU_IE8 = 8000, wxWEBVIEWIE_EMU_IE8_FORCE = 8888, wxWEBVIEWIE_EMU_IE9 = 9000, wxWEBVIEWIE_EMU_IE9_FORCE = 9999, wxWEBVIEWIE_EMU_IE10 = 10000, wxWEBVIEWIE_EMU_IE10_FORCE = 10001, wxWEBVIEWIE_EMU_IE11 = 11000, wxWEBVIEWIE_EMU_IE11_FORCE = 11001 }; #endif """) module.addPyCode(order=15, code="""\ # On Windows we need to ensure that the wx package folder is on on the # PATH, so the MS Edge Loader DLLs can be found when they are dynamically # loaded. import os if os.name == 'nt': _path = os.environ.get('PATH') _pkg_path = os.path.abspath(os.path.dirname(wx.__file__)) if _pkg_path.lower() not in _path.lower(): os.environ['PATH'] = _path + os.pathsep + _pkg_path """) # Pull out the obj for wxWebViewIE so we can use it later, but not include it in the stubs wvie = module.find('wxWebViewIE') module.items.remove(wvie) # This tweak is needed only for the stub code module.find('wxWebViewHandler.wxWebViewHandler').argsString = '(const wxString& scheme="")' tools.generateStubs('wxUSE_WEBVIEW', module, typeValMap={ 'wxWebViewNavigationActionFlags': 'wxWEBVIEW_NAV_ACTION_NONE', 'wxWebViewZoom': 'wxWEBVIEW_ZOOM_MEDIUM', 'wxVersionInfo': 'wxVersionInfo()', }) c = module.find('wxWebView') assert isinstance(c, etgtools.ClassDef) tools.fixWindowClass(c) c.abstract = True for m in c.find('New').all(): m.factory = True c.find('New.id').default = 'wxID_ANY' c.find('New.parent').transferThis = True c.find('RegisterHandler.handler').type = 'wxWebViewHandler*' c.find('RegisterHandler.handler').transfer = True c.find('RegisterHandler').setCppCode_sip( "sipCpp->RegisterHandler(wxSharedPtr<wxWebViewHandler>(handler));") c.find('RegisterFactory.factory').type = 'wxWebViewFactory*' c.find('RegisterFactory.factory').transfer = True c.find('RegisterFactory').setCppCode_sip( "wxWebView::RegisterFactory(*backend, wxSharedPtr<wxWebViewFactory>(factory));") c.find('RunScript.output').out = True # Custom code to deal with the # wxVector<wxSharedPtr<wxWebViewHistoryItem>> return type of these two # methods. We'll just convert them to a Python list of history items. code = """\ wxPyThreadBlocker blocker; PyObject* result = PyList_New(0); wxVector<wxSharedPtr<wxWebViewHistoryItem> > vector = self->{method}(); for (size_t idx=0; idx < vector.size(); idx++) {{ PyObject* obj; wxWebViewHistoryItem* item = new wxWebViewHistoryItem(*vector[idx].get()); obj = wxPyConstructObject((void*)item, "wxWebViewHistoryItem", true); PyList_Append(result, obj); Py_DECREF(obj); }} return result; """ c.find('GetBackwardHistory').type = 'PyObject*' c.find('GetBackwardHistory').setCppCode(code.format(method='GetBackwardHistory')) c.find('GetForwardHistory').type = 'PyObject*' c.find('GetForwardHistory').setCppCode(code.format(method='GetForwardHistory')) # Since LoadHistoryItem expects to get an actual item in the history # list, and since we make copies of the items in the cppCode above, then # this won't be possible to do from the Python wrappers. However, it's # just as easy to use LoadURL to reload a history item so it's not a # great loss. c.find('LoadHistoryItem').ignore() ##c.find('LoadHistoryItem.item').type = 'wxWebViewHistoryItem*' ##c.find('LoadHistoryItem.item').transfer = True ##c.find('LoadHistoryItem').setCppCode_sip( ## "sipCpp->LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem>(item));") # Add the MSW methods in wxWebViewIE into the main WebView class like they were before. c.addItem(wvie.find('MSWSetEmulationLevel')) c.addItem(wvie.find('MSWSetModernEmulationLevel')) # Give them an implementation that doesn't matter which class they are actually located in. c.find('MSWSetEmulationLevel').setCppCode("""\ #if wxUSE_WEBVIEW_IE && defined(__WXMSW__) return _do_MSWSetEmulationLevel(level); #else return false; #endif """) c.find('MSWSetModernEmulationLevel').setCppCode("""\ #if wxUSE_WEBVIEW_IE && defined(__WXMSW__) return _do_MSWSetEmulationLevel(modernLevel ? wxWEBVIEWIE_EMU_IE8 : wxWEBVIEWIE_EMU_DEFAULT); #else return false; #endif """) # The emulation level is set as a per-application value in the Windows # Registry. The way this is implemented in the C++ code we end up with the # name of the _core extransion module in the Reistry instead of the .exe # name, which is what is really needed. # # So instead of doing simple wrappers with #if checks like normal, replace # these methods with a new implementation that does the RightThing using # sys.executable. c.addCppCode(r""" #if wxUSE_WEBVIEW_IE && defined(__WXMSW__) #include <wx/msw/webview_ie.h> #include <wx/msw/registry.h> bool _do_MSWSetEmulationLevel(wxWebViewIE_EmulationLevel level) { wxString programName; wxPyBLOCK_THREADS( programName = Py2wxString(PySys_GetObject("executable"))); programName = programName.AfterLast('\\'); // Registry key where emulation level for programs are set static const wxChar* IE_EMULATION_KEY = wxT("SOFTWARE\\Microsoft\\Internet Explorer\\Main") wxT("\\FeatureControl\\FEATURE_BROWSER_EMULATION"); wxRegKey key(wxRegKey::HKCU, IE_EMULATION_KEY); if ( !key.Exists() ) { wxLogWarning(_("Failed to find web view emulation level in the registry")); return false; } if ( level != wxWEBVIEWIE_EMU_DEFAULT ) { if ( !key.SetValue(programName, level) ) { wxLogWarning(_("Failed to set web view to modern emulation level")); return false; } } else { if ( !key.DeleteValue(programName) ) { wxLogWarning(_("Failed to reset web view to standard emulation level")); return false; } } return true; } #endif """) c = module.find('wxWebViewEvent') tools.fixEventClass(c) module.addPyCode("""\ EVT_WEBVIEW_NAVIGATING = wx.PyEventBinder( wxEVT_WEBVIEW_NAVIGATING, 1 ) EVT_WEBVIEW_NAVIGATED = wx.PyEventBinder( wxEVT_WEBVIEW_NAVIGATED, 1 ) EVT_WEBVIEW_LOADED = wx.PyEventBinder( wxEVT_WEBVIEW_LOADED, 1 ) EVT_WEBVIEW_ERROR = wx.PyEventBinder( wxEVT_WEBVIEW_ERROR, 1 ) EVT_WEBVIEW_NEWWINDOW = wx.PyEventBinder( wxEVT_WEBVIEW_NEWWINDOW, 1 ) EVT_WEBVIEW_TITLE_CHANGED = wx.PyEventBinder( wxEVT_WEBVIEW_TITLE_CHANGED, 1 ) EVT_WEBVIEW_FULLSCREEN_CHANGED = wx.PyEventBinder( wxEVT_WEBVIEW_FULLSCREEN_CHANGED, 1) EVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED = wx.PyEventBinder( wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, 1) # deprecated wxEVT aliases wxEVT_COMMAND_WEBVIEW_NAVIGATING = wxEVT_WEBVIEW_NAVIGATING wxEVT_COMMAND_WEBVIEW_NAVIGATED = wxEVT_WEBVIEW_NAVIGATED wxEVT_COMMAND_WEBVIEW_LOADED = wxEVT_WEBVIEW_LOADED wxEVT_COMMAND_WEBVIEW_ERROR = wxEVT_WEBVIEW_ERROR wxEVT_COMMAND_WEBVIEW_NEWWINDOW = wxEVT_WEBVIEW_NEWWINDOW wxEVT_COMMAND_WEBVIEW_TITLE_CHANGED = wxEVT_WEBVIEW_TITLE_CHANGED """) c = module.find('wxWebViewHistoryItem') tools.addAutoProperties(c) for name in [ 'wxWebViewHandler', 'wxWebViewArchiveHandler', 'wxWebViewFSHandler' ]: c = module.find(name) c.find('GetFile').factory = True #----------------------------------------------------------------- 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.addGlobalStr('wxGridNameStr', module.items[0]) module.addPyCode("""\ GRID_VALUE_STRING = "string" GRID_VALUE_BOOL = "bool" GRID_VALUE_NUMBER = "long" GRID_VALUE_FLOAT = "double" GRID_VALUE_CHOICE = "choice" GRID_VALUE_TEXT = "string" GRID_VALUE_LONG = "long" GRID_VALUE_CHOICEINT = "choiceint" GRID_VALUE_DATETIME = "datetime" """) #----------------------------------------------------------------- c = module.find('wxGridCellCoords') assert isinstance(c, etgtools.ClassDef) tools.addAutoProperties(c) c.find('operator!').ignore() c.find('operator=').ignore() # Add a typemap for 2 element sequences c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxGridCellCoords') c.addCppMethod('PyObject*', 'Get', '()', """\ wxPyThreadBlocker blocker; return sipBuildResult(0, "(ii)", self->GetRow(), self->GetCol()); """, pyArgsString="() -> (row,col)", briefDoc="Return the row and col properties as a tuple.") tools.addGetIMMethodTemplate(module, c, ['Row', 'Col']) # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "GridCellCoords"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (GridCellCoords, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod('__setitem__', '(self, idx, val)', """\ if idx == 0: self.Row = val elif idx == 1: self.Col = val else: raise IndexError """) c.addPyCode('GridCellCoords.__safe_for_unpickling__ = True') module.addItem( tools.wxArrayWrapperTemplate('wxGridCellCoordsArray', 'wxGridCellCoords', module, getItemCopy=True)) #----------------------------------------------------------------- c = module.find('wxGridSizesInfo') c.find('m_customSizes').ignore() # TODO: Add support for wxUnsignedToIntHashMap?? #----------------------------------------------------------------- def fixRendererClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.fixRefCountedClass(klass) tools.addAutoProperties(klass) methods = [ ('Clone', "virtual wxGridCellRenderer* Clone() const /Factory/;"), ('Draw', "virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, " " const wxRect& rect, int row, int col, bool isSelected);"), ('GetBestSize', "virtual wxSize GetBestSize(wxGrid& grid, wxGridCellAttr& attr, " " wxDC& dc, int row, int col);"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code)) c = module.find('wxGridCellRenderer') c.addPrivateCopyCtor() c.find('~wxGridCellRenderer').ignore(False) c.find('Clone').factory = True tools.fixRefCountedClass(c) for name in ITEMS: if 'Cell' in name and 'Renderer' in name: fixRendererClass(name) module.addPyCode("PyGridCellRenderer = wx.deprecated(GridCellRenderer, 'Use GridCellRenderer instead.')") #----------------------------------------------------------------- def fixEditorClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.fixRefCountedClass(klass) tools.addAutoProperties(klass) methods = [ ('BeginEdit', "virtual void BeginEdit(int row, int col, wxGrid* grid);"), ('Clone', "virtual wxGridCellEditor* Clone() const /Factory/;"), ('Create', "virtual void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler);"), #('EndEdit', "virtual bool EndEdit(int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval);"), ('ApplyEdit', "virtual void ApplyEdit(int row, int col, wxGrid* grid);"), ('Reset', "virtual void Reset();"), ('GetValue', "virtual wxString GetValue() const;"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code)) # Fix up EndEdit so it returns newval on success or None on failure pureVirtual = False if klass.findItem('EndEdit'): klass.find('EndEdit').ignore() pureVirtual = True # The Python version of EndEdit has a different signature than the # C++ version, so we need to take care of mapping between them so the # C++ compiler still recognizes this as a match for the virtual # method in the base class. klass.addCppMethod('PyObject*', 'EndEdit', '(int row, int col, const wxGrid* grid, const wxString& oldval)', cppSignature='bool (int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval)', pyArgsString='(row, col, grid, oldval)', isVirtual=True, isPureVirtual=pureVirtual, doc="""\ End editing the cell. This function must check if the current value of the editing cell is valid and different from the original value in its string form. If not then simply return None. If it has changed then this method should save the new value so that ApplyEdit can apply it later and the string representation of the new value should be returned. Notice that this method shoiuld not modify the grid as the change could still be vetoed. """, # Code for Python --> C++ calls. Make it return newval or None. body="""\ bool rv; wxString newval; rv = self->EndEdit(row, col, grid, *oldval, &newval); if (rv) { return wx2PyString(newval); } else { Py_INCREF(Py_None); return Py_None; } """, # Code for C++ --> Python calls. This is used when a C++ method # call needs to be reflected to a call to the overridden Python # method, so we need to translate between the real C++ signature # and the Python signature. virtualCatcherCode="""\ // VirtualCatcherCode for wx.grid.GridCellEditor.EndEdit PyObject *result; result = sipCallMethod(0, sipMethod, "iiDN", row, col, const_cast<wxGrid *>(grid),sipType_wxGrid,NULL, new wxString(oldval),sipType_wxString,NULL); if (result == Py_None) { sipRes = false; } else { sipRes = true; *newval = Py2wxString(result); } Py_DECREF(result); """ if pureVirtual else "", # only used with the base class ) c = module.find('wxGridCellEditor') c.addPrivateCopyCtor() c.find('~wxGridCellEditor').ignore(False) c.find('Clone').factory = True tools.fixRefCountedClass(c) c = module.find('wxGridCellChoiceEditor') c.find('wxGridCellChoiceEditor').findOverload('count').ignore() for name in ITEMS: if 'Cell' in name and 'Editor' in name: fixEditorClass(name) module.addPyCode("PyGridCellEditor = wx.deprecated(GridCellEditor, 'Use GridCellEditor instead.')") #----------------------------------------------------------------- c = module.find('wxGridCellAttr') c.addPrivateCopyCtor() c.find('~wxGridCellAttr').ignore(False) c.find('Clone').factory = True tools.fixRefCountedClass(c) c.find('GetAlignment.hAlign').out = True c.find('GetAlignment.vAlign').out = True c.find('GetNonDefaultAlignment.hAlign').out = True c.find('GetNonDefaultAlignment.vAlign').out = True c.find('GetSize.num_rows').out = True c.find('GetSize.num_cols').out = True c.find('SetEditor.editor').transfer = True # these are probably redundant now... c.find('SetRenderer.renderer').transfer = True #----------------------------------------------------------------- # The instanceCode attribute is code that is used to make a default # instance of the class. We can't create them using the same class in # this case because they are abstract. c = module.find('wxGridCornerHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridCornerHeaderRendererDefault;' c = module.find('wxGridRowHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridRowHeaderRendererDefault;' c = module.find('wxGridColumnHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridColumnHeaderRendererDefault;' #----------------------------------------------------------------- c = module.find('wxGridCellAttrProvider') c.addPrivateCopyCtor() c.find('SetAttr.attr').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True module.addPyCode("PyGridCellAttrProvider = wx.deprecated(GridCellAttrProvider, 'Use GridCellAttrProvider instead.')") #----------------------------------------------------------------- c = module.find('wxGridTableBase') c.addPrivateCopyCtor() c.find('SetAttr.attr').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True module.addPyCode("PyGridTableBase = wx.deprecated(GridTableBase, 'Use GridTableBase instead.')") # Make the GetValue methods easier to use from Python. For example, # instead of needing to always return a string, the GetValue in the derived # class can return any type (as long as the renderer and editor knows how # to deal with it, and the value can be converted to a string for display). m = c.find('GetValue') m.type = 'PyObject*' m.cppSignature = 'wxString (int row, int col)' m.setCppCode("return wx2PyString(self->GetValue(row, col));") m.virtualCatcherCode = """\ // virtualCatcherCode for GridTableBase.GetValue PyObject *result = sipCallMethod(&sipIsErr, sipMethod, "ii", row, col); if (result == Py_None) { sipRes = ""; } else { if (!PyBytes_Check(result) && !PyUnicode_Check(result)) { PyObject* old = result; result = PyObject_Str(result); Py_DECREF(old); } sipRes = Py2wxString(result); } Py_XDECREF(result); """ # SetValue is okay as-is... # Replace these virtuals in the base class with Python methods, they just # need to call GetValue or SetValue directly since they must already be # implemented in the derived Python class because they are pure virtual. c.addPyMethod('GetValueAsLong', '(self, row, col)', body="""\ val = self.GetValue(row, col) try: return int(val) except ValueError: return 0 """, docsIgnored=True) c.addPyMethod('GetValueAsDouble', '(self, row, col)', body="""\ val = self.GetValue(row, col) try: return float(val) except ValueError: return 0.0 """, docsIgnored=True) c.addPyMethod('GetValueAsBool', '(self, row, col)', body="""\ val = self.GetValue(row, col) try: return bool(val) except ValueError: return False """, docsIgnored=True) c.addPyMethod('SetValueAsLong', '(self, row, col, value)', body="self.SetValue(row, col, int(value))", docsIgnored=True) c.addPyMethod('SetValueAsDouble', '(self, row, col, value)', body="self.SetValue(row, col, float(value))", docsIgnored=True) c.addPyMethod('SetValueAsBool', '(self, row, col, value)', body="self.SetValue(row, col, bool(value))", docsIgnored=True) # Should we add support for using generic PyObjects in the *AsCustom # methods? I don't think it is necessary due to the GetValue # modifications above, so for now, at least, let.s just ignore them. c.find('GetValueAsCustom').ignore() c.find('SetValueAsCustom').ignore() #----------------------------------------------------------------- c = module.find('wxGridTableMessage') c.addPrivateCopyCtor() #----------------------------------------------------------------- c = module.find('wxGrid') tools.fixWindowClass(c, ignoreProtected=False) c.bases = ['wxScrolledWindow'] c.find('GetColLabelAlignment.horiz').out = True c.find('GetColLabelAlignment.vert').out = True c.find('GetRowLabelAlignment.horiz').out = True c.find('GetRowLabelAlignment.vert').out = True c.find('GetCellAlignment.horiz').out = True c.find('GetCellAlignment.vert').out = True c.find('GetDefaultCellAlignment.horiz').out = True c.find('GetDefaultCellAlignment.vert').out = True c.find('RegisterDataType.renderer').transfer = True c.find('RegisterDataType.editor').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True c.find('SetCellEditor.editor').transfer = True c.find('SetCellRenderer.renderer').transfer = True # This overload is deprecated, so don't generate code for it. c.find('SetCellValue').findOverload('wxString &val').ignore() c.find('SetDefaultEditor.editor').transfer = True c.find('SetDefaultRenderer.renderer').transfer = True for n in ['GetColGridLinePen', 'GetDefaultGridLinePen', 'GetRowGridLinePen']: c.find(n).isVirtual = True # The SetTable method can optionally pass ownership of the table # object to the grid, so we need to optionally update the # ownership of the Python proxy object to match. c.find('SetTable').pyName = '_SetTable' c.addPyMethod('SetTable', '(self, table, takeOwnership=False, selmode=Grid.SelectCells)', piArgsString='(self, table, takeOwnership=False, selmode=SelectCells)', doc="Set the Grid Table to be used by this grid.", body="""\ val = self._SetTable(table, takeOwnership, selmode) if takeOwnership: import wx.siplib wx.siplib.transferto(table, self) return val """) # SIP will normally try to add support for overriding this method since # it is inherited from super classes, but in this case we want it to be # ignored (because IRL it is private in one of the intermediate classes) # so we'll tell SIP that it is private here instead. c.addItem(etgtools.WigCode("""\ wxSize GetSizeAvailableForScrollTarget(const wxSize& size); """, protection='private')) # Rename some nested enum values c.find('wxGridSelectionModes.wxGridSelectCells').pyName = 'SelectCells' c.find('wxGridSelectionModes.wxGridSelectRows').pyName = 'SelectRows' c.find('wxGridSelectionModes.wxGridSelectColumns').pyName = 'SelectColumns' c.find('wxGridSelectionModes.wxGridSelectRowsOrColumns').pyName = 'SelectRowsOrColumns' # But also keep aliases for the old names, just in case c.addPyCode("""\ Grid.wxGridSelectCells = Grid.SelectCells Grid.wxGridSelectRows = Grid.SelectRows Grid.wxGridSelectColumns = Grid.SelectColumns Grid.wxGridSelectRowsOrColumns = Grid.SelectRowsOrColumns """) #----------------------------------------------------------------- c = module.find('wxGridUpdateLocker') c.addPrivateCopyCtor() # context manager methods c.addPyMethod('__enter__', '(self)', 'return self') c.addPyMethod('__exit__', '(self, exc_type, exc_val, exc_tb)', 'return False') #----------------------------------------------------------------- for name in ['wxGridSizeEvent', 'wxGridRangeSelectEvent', 'wxGridEditorCreatedEvent', 'wxGridEvent' ]: c = module.find(name) tools.fixEventClass(c) c.addPyCode("""\ EVT_GRID_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK ) EVT_GRID_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK ) EVT_GRID_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK ) EVT_GRID_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK ) EVT_GRID_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK ) EVT_GRID_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK ) EVT_GRID_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK ) EVT_GRID_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK ) EVT_GRID_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE ) EVT_GRID_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE ) EVT_GRID_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT ) EVT_GRID_CELL_CHANGING = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGING ) EVT_GRID_CELL_CHANGED = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGED ) EVT_GRID_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL ) EVT_GRID_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN ) EVT_GRID_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN ) EVT_GRID_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED ) EVT_GRID_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG ) EVT_GRID_COL_MOVE = wx.PyEventBinder( wxEVT_GRID_COL_MOVE ) EVT_GRID_COL_SORT = wx.PyEventBinder( wxEVT_GRID_COL_SORT ) EVT_GRID_TABBING = wx.PyEventBinder( wxEVT_GRID_TABBING ) # The same as above but with the ability to specify an identifier EVT_GRID_CMD_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK, 1 ) EVT_GRID_CMD_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK, 1 ) EVT_GRID_CMD_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK, 1 ) EVT_GRID_CMD_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK, 1 ) EVT_GRID_CMD_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK, 1 ) EVT_GRID_CMD_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK, 1 ) EVT_GRID_CMD_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK, 1 ) EVT_GRID_CMD_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK, 1 ) EVT_GRID_CMD_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE, 1 ) EVT_GRID_CMD_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE, 1 ) EVT_GRID_CMD_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT, 1 ) EVT_GRID_CMD_CELL_CHANGING = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGING, 1 ) EVT_GRID_CMD_CELL_CHANGED = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGED, 1 ) EVT_GRID_CMD_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL, 1 ) EVT_GRID_CMD_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN, 1 ) EVT_GRID_CMD_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN, 1 ) EVT_GRID_CMD_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED, 1 ) EVT_GRID_CMD_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG, 1 ) EVT_GRID_CMD_COL_MOVE = wx.PyEventBinder( wxEVT_GRID_COL_MOVE, 1 ) EVT_GRID_CMD_COL_SORT = wx.PyEventBinder( wxEVT_GRID_COL_SORT, 1 ) EVT_GRID_CMD_TABBING = wx.PyEventBinder( wxEVT_GRID_TABBING, 1 ) """) #----------------------------------------------------------------- #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def fixEditorClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.fixRefCountedClass(klass) tools.addAutoProperties(klass) methods = [ ('BeginEdit', "virtual void BeginEdit(int row, int col, wxGrid* grid);"), ('Clone', "virtual wxGridCellEditor* Clone() const /Factory/;"), ('Create', "virtual void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler);"), #('EndEdit', "virtual bool EndEdit(int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval);"), ('ApplyEdit', "virtual void ApplyEdit(int row, int col, wxGrid* grid);"), ('Reset', "virtual void Reset();"), ('GetValue', "virtual wxString GetValue() const;"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code)) # Fix up EndEdit so it returns newval on success or None on failure pureVirtual = False if klass.findItem('EndEdit'): klass.find('EndEdit').ignore() pureVirtual = True # The Python version of EndEdit has a different signature than the # C++ version, so we need to take care of mapping between them so the # C++ compiler still recognizes this as a match for the virtual # method in the base class. klass.addCppMethod('PyObject*', 'EndEdit', '(int row, int col, const wxGrid* grid, const wxString& oldval)', cppSignature='bool (int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval)', pyArgsString='(row, col, grid, oldval)', isVirtual=True, isPureVirtual=pureVirtual, doc="""\ End editing the cell. This function must check if the current value of the editing cell is valid and different from the original value in its string form. If not then simply return None. If it has changed then this method should save the new value so that ApplyEdit can apply it later and the string representation of the new value should be returned. Notice that this method shoiuld not modify the grid as the change could still be vetoed. """, # Code for Python --> C++ calls. Make it return newval or None. body="""\ bool rv; wxString newval; rv = self->EndEdit(row, col, grid, *oldval, &newval); if (rv) { return wx2PyString(newval); } else { Py_INCREF(Py_None); return Py_None; } """, # Code for C++ --> Python calls. This is used when a C++ method # call needs to be reflected to a call to the overridden Python # method, so we need to translate between the real C++ signature # and the Python signature. virtualCatcherCode="""\ // VirtualCatcherCode for wx.grid.GridCellEditor.EndEdit PyObject *result; result = sipCallMethod(0, sipMethod, "iiDN", row, col, const_cast<wxGrid *>(grid),sipType_wxGrid,NULL, new wxString(oldval),sipType_wxString,NULL); if (result == Py_None) { sipRes = false; } else { sipRes = true; *newval = Py2wxString(result); } Py_DECREF(result); """ if pureVirtual else "", # only used with the base class )
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/richtext/richtextbuffer.h>') module.addItem( tools.wxArrayWrapperTemplate('wxRichTextRangeArray', 'wxRichTextRange', module)) module.addItem( tools.wxArrayWrapperTemplate('wxRichTextAttrArray', 'wxRichTextAttr', module)) module.addItem( tools.wxArrayWrapperTemplate('wxRichTextVariantArray', 'wxVariant', module)) module.addItem( tools.wxListWrapperTemplate('wxRichTextObjectList', 'wxRichTextObject', module)) module.addItem( tools.wxListWrapperTemplate('wxRichTextLineList', 'wxRichTextLine', module)) # Can this even work? Apparently it does. module.addItem( tools.wxArrayPtrWrapperTemplate('wxRichTextObjectPtrArray', 'wxRichTextObject', module)) module.addItem( tools.wxArrayWrapperTemplate('wxRichTextObjectPtrArrayArray', 'wxRichTextObjectPtrArray', module)) module.find('wxRICHTEXT_ALL').ignore() module.find('wxRICHTEXT_NONE').ignore() module.find('wxRICHTEXT_NO_SELECTION').ignore() code = etgtools.PyCodeDef("""\ RICHTEXT_ALL = RichTextRange(-2, -2) RICHTEXT_NONE = RichTextRange(-1, -1) RICHTEXT_NO_SELECTION = RichTextRange(-2, -2) """) module.insertItemAfter(module.find('wxRichTextRange'), code) module.insertItem(0, etgtools.WigCode("""\ // forward declarations class wxRichTextFloatCollector; """)) #------------------------------------------------------- c = module.find('wxTextAttrDimension') assert isinstance(c, etgtools.ClassDef) c.find('SetValue').findOverload('units').ignore() c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();") #------------------------------------------------------- c = module.find('wxTextAttrDimensions') tools.ignoreConstOverloads(c) c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();") #------------------------------------------------------- c = module.find('wxTextAttrSize') tools.ignoreConstOverloads(c) c.find('SetWidth').findOverload('units').ignore() c.find('SetHeight').findOverload('units').ignore() c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();") #------------------------------------------------------- c = module.find('wxTextAttrBorder') tools.ignoreConstOverloads(c) c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();") #------------------------------------------------------- c = module.find('wxTextAttrBorders') tools.ignoreConstOverloads(c) c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();") #------------------------------------------------------- c = module.find('wxTextBoxAttr') tools.ignoreConstOverloads(c) #------------------------------------------------------- c = module.find('wxRichTextAttr') tools.ignoreConstOverloads(c) #------------------------------------------------------- c = module.find('wxRichTextProperties') tools.ignoreConstOverloads(c) c.find('SetProperty').findOverload('bool').ignore() c.find('operator[]').ignore() #------------------------------------------------------- c = module.find('wxRichTextSelection') tools.ignoreConstOverloads(c) c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();") c.find('operator[]').ignore() #------------------------------------------------------- c = module.find('wxRichTextRange') tools.addAutoProperties(c) # wxRichTextRange typemap c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxRichTextRange') c.addCppMethod('PyObject*', 'Get', '()', """\ wxPyThreadBlocker blocker; return sipBuildResult(0, "(ii)", self->GetStart(), self->GetEnd()); """, pyArgsString="() -> (start, end)", briefDoc="Return the start and end properties as a tuple.") tools.addGetIMMethodTemplate(module, c, ['Start', 'End']) # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "RichTextRange"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (RichTextRange, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod('__setitem__', '(self, idx, val)', """\ if idx == 0: self.Start = val elif idx == 1: self.End = val else: raise IndexError """) c.addPyCode('RichTextRange.__safe_for_unpickling__ = True') #------------------------------------------------------- def _fixDrawObject(c, addMissingVirtuals=True): assert isinstance(c, etgtools.ClassDef) if c.findItem('HitTest'): c.find('HitTest.textPosition').out = True c.find('HitTest.obj').out = True c.find('HitTest.contextObj').out = True if c.findItem('FindPosition'): c.find('FindPosition.pt').out = True c.find('FindPosition.height').out = True if c.findItem('GetBoxRects'): c.find('GetBoxRects.marginRect').out = True c.find('GetBoxRects.borderRect').out = True c.find('GetBoxRects.contentRect').out = True c.find('GetBoxRects.paddingRect').out = True c.find('GetBoxRects.outlineRect').out = True if c.findItem('GetTotalMargin'): c.find('GetTotalMargin.leftMargin').out = True c.find('GetTotalMargin.rightMargin').out = True c.find('GetTotalMargin.topMargin').out = True c.find('GetTotalMargin.bottomMargin').out = True if c.findItem('CalculateRange'): c.find('CalculateRange.end').out = True # TODO: should it be an inOut? if c.findItem('Clone'): c.find('Clone').factory = True else: c.addItem(etgtools.WigCode("""\ virtual wxRichTextObject* Clone() const /Factory/; """)) # These are the pure virtuals in the base class. SIP needs to see that # all the derived classes have an implementation, otherwise it will # consider them to be ABCs. if not c.findItem('Draw') and addMissingVirtuals: c.addItem(etgtools.WigCode("""\ virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style);""")) if not c.findItem('Layout') and addMissingVirtuals: c.addItem(etgtools.WigCode("""\ virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style);""")) # TODO: Some of these args are output parameters. How should they be dealt with? if not c.findItem('GetRangeSize') and addMissingVirtuals: c.addItem(etgtools.WigCode("""\ virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, const wxPoint& position = wxPoint(0,0), const wxSize& parentSize = wxDefaultSize, wxArrayInt* partialExtents = NULL) const;""")) #------------------------------------------------------- c = module.find('wxRichTextObject') #c.find('ImportFromXML').ignore() tools.ignoreConstOverloads(c) _fixDrawObject(c) #------------------------------------------------------- c = module.find('wxRichTextCompositeObject') tools.ignoreConstOverloads(c) _fixDrawObject(c, addMissingVirtuals=False) #------------------------------------------------------- c = module.find('wxRichTextParagraphLayoutBox') tools.ignoreConstOverloads(c) _fixDrawObject(c) c.find('MoveAnchoredObjectToParagraph.from').name = 'from_' c.find('MoveAnchoredObjectToParagraph.to').name = 'to_' c.find('DoNumberList.def').name = 'styleDef' c.find('SetListStyle.def').name = 'styleDef' #------------------------------------------------------- c = module.find('wxRichTextBox') _fixDrawObject(c) #------------------------------------------------------- c = module.find('wxRichTextCell') _fixDrawObject(c) #------------------------------------------------------- c = module.find('wxRichTextField') _fixDrawObject(c) #------------------------------------------------------- c = module.find('wxRichTextLine') tools.ignoreConstOverloads(c) c.find('SetRange.from').name = 'from_' c.find('SetRange.to').name = 'to_' c.find('Clone').factory = True #------------------------------------------------------- c = module.find('wxRichTextParagraph') _fixDrawObject(c) # These methods use an untyped wxList, but since we know what is in it # we'll make a fake typed list for wxPython so we can know what kinds of # values to get from it. module.addItem( tools.wxListWrapperTemplate('wxList', 'wxRichTextObject', module, fakeListClassName='wxRichTextObjectList_')) c.find('MoveToList.list').type = 'wxRichTextObjectList_&' c.find('MoveFromList.list').type = 'wxRichTextObjectList_&' #------------------------------------------------------- c = module.find('wxRichTextPlainText') _fixDrawObject(c) #------------------------------------------------------- c = module.find('wxRichTextImage') _fixDrawObject(c) #------------------------------------------------------- c = module.find('wxRichTextBuffer') tools.ignoreConstOverloads(c) _fixDrawObject(c) # More untyped wxLists module.addItem( tools.wxListWrapperTemplate('wxList', 'wxRichTextFileHandler', module, fakeListClassName='wxRichTextFileHandlerList')) c.find('GetHandlers').type = 'wxRichTextFileHandlerList&' c.find('GetHandlers').noCopy = True module.addItem( tools.wxListWrapperTemplate('wxList', 'wxRichTextDrawingHandler', module, fakeListClassName='wxRichTextDrawingHandlerList')) c.find('GetDrawingHandlers').type = 'wxRichTextDrawingHandlerList&' c.find('GetDrawingHandlers').noCopy = True # TODO: Need a template to wrap STRING_HASH_MAP c.find('GetFieldTypes').ignore() c.find('AddHandler.handler').transfer = True c.find('InsertHandler.handler').transfer = True c.find('AddDrawingHandler.handler').transfer = True c.find('InsertDrawingHandler.handler').transfer = True c.find('AddFieldType.fieldType').transfer = True # TODO: Transfer ownership with AddEventHandler? TransferBack with Remove? c.find('FindHandler').renameOverload('name', 'FindHandlerByName') c.find('FindHandler').renameOverload('extension', 'FindHandlerByExtension') c.find('FindHandler').pyName = 'FindHandlerByType' c.find('FindHandlerFilenameOrType').pyName = 'FindHandlerByFilename' c.find('GetExtWildcard').ignore() c.addCppMethod('PyObject*', 'GetExtWildcard', '(bool combine=false, bool save=false)', doc="""\ Gets a wildcard string for the file dialog based on all the currently loaded richtext file handlers, and a list that can be used to map those filter types to the file handler type.""", body="""\ wxString wildcards; wxArrayInt types; wildcards = wxRichTextBuffer::GetExtWildcard(combine, save, &types); wxPyThreadBlocker blocker; PyObject* list = PyList_New(0); for (size_t i=0; i < types.GetCount(); i++) { PyObject* number = wxPyInt_FromLong(types[i]); PyList_Append(list, number); Py_DECREF(number); } PyObject* tup = PyTuple_New(2); PyTuple_SET_ITEM(tup, 0, wx2PyString(wildcards)); PyTuple_SET_ITEM(tup, 1, list); return tup; """, isStatic=True) #------------------------------------------------------- c = module.find('wxRichTextTable') tools.ignoreConstOverloads(c) _fixDrawObject(c) #------------------------------------------------------- c = module.find('wxRichTextObjectAddress') tools.ignoreConstOverloads(c) #------------------------------------------------------- c = module.find('wxRichTextCommand') module.addItem( tools.wxListWrapperTemplate('wxList', 'wxRichTextAction', module, fakeListClassName='wxRichTextActionList')) c.find('GetActions').type = 'wxRichTextActionList&' c.find('GetActions').noCopy = True c.find('AddAction.action').transfer = True #------------------------------------------------------- c = module.find('wxRichTextAction') tools.ignoreConstOverloads(c) #------------------------------------------------------- c = module.find('wxRichTextFileHandler') c.find('DoLoadFile').ignore(False) c.find('DoSaveFile').ignore(False) c = module.find('wxRichTextPlainTextHandler') c.find('DoLoadFile').ignore(False) c.find('DoSaveFile').ignore(False) #------------------------------------------------------- # Ignore all Dump() methods since we don't wrap wxTextOutputStream. # TODO: try swithcing the parameter type to wxOutputStream and then in # the wrapper code create a wxTextOutputStream from that to pass on to # Dump. for m in module.findAll('Dump'): if m.findItem('stream'): m.ignore() # Correct the type for this define as it is a float module.find('wxSCRIPT_MUL_FACTOR').type = 'float' #----------------------------------------------------------------- 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. # ignore some of these enum values e = module.find('wxBitmapType') for i in e: if i.name.endswith('_RESOURCE'): i.ignore() module.addCppCode("""\ #if !defined(__WXMAC__) #define wxCURSOR_COPY_ARROW wxCURSOR_ARROW #endif """) # these are X11 only e = module.find('wxStockCursor') e.find('wxCURSOR_BASED_ARROW_DOWN').ignore() e.find('wxCURSOR_BASED_ARROW_UP').ignore() e.find('wxCURSOR_CROSS_REVERSE').ignore() e.find('wxCURSOR_DOUBLE_ARROW').ignore() module.find('wxClientDisplayRect.x').out = True module.find('wxClientDisplayRect.y').out = True module.find('wxClientDisplayRect.width').out = True module.find('wxClientDisplayRect.height').out = True module.find('wxDisplaySize.width').out = True module.find('wxDisplaySize.height').out = True module.find('wxDisplaySizeMM.width').out = True module.find('wxDisplaySizeMM.height').out = True #--------------------------------------- # wxPoint tweaks c = module.find('wxPoint') tools.addAutoProperties(c) # Some operators are documented within the class that shouldn't be, so just # ignore them all. tools.ignoreAllOperators(c) # Undo a few of those ignores for legitimate items that were # documented correctly for f in c.find('operator+=').all() + c.find('operator-=').all(): f.ignore(False) # Add some method declarations for operators that really do exist. Note # that these actually use C++ global operator functions, but we treat # them as methods to help disambiguate implementations due to how # multiple classes can be converted automatically to/from 2-element # sequences. c.addCppMethod('bool', '__eq__', '(const wxPoint& other)', body="return *self == *other;") c.addCppMethod('bool', '__neq__', '(const wxPoint& other)', body="return *self != *other;") c.addItem(etgtools.WigCode("""\ wxPoint operator+(const wxPoint& other); wxPoint operator-(); wxPoint operator-(const wxPoint& other); wxPoint operator*(int i); wxPoint operator/(int i); """)) # wxPoint typemap c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxPoint') c.addCppMethod('PyObject*', 'Get', '()', """\ return sipBuildResult(0, "(ii)", self->x, self->y); """, pyArgsString="() -> (x,y)", briefDoc="Return the x and y properties as a tuple.") # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "wx.Point"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (Point, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod('__setitem__', '(self, idx, val)', """\ if idx == 0: self.x = val elif idx == 1: self.y = val else: raise IndexError """) c.addPyCode('Point.__safe_for_unpickling__ = True') module.addItem( tools.wxListWrapperTemplate('wxPointList', 'wxPoint', module, includeConvertToType=True)) #--------------------------------------- # wxSize tweaks c = module.find('wxSize') tools.addAutoProperties(c) # Used for testing releasing or holding the GIL in giltest.py #c.find('wxSize').findOverload('int width, int height').releaseGIL() #c.find('DecBy').findOverload('int dx, int dy').releaseGIL() #c.find('IncBy').findOverload('int dx, int dy').releaseGIL() c.addProperty("width GetWidth SetWidth") c.addProperty("height GetHeight SetHeight") # TODO: How prevalent is the use of x,y properties on a size object? Can we deprecate them? c.addProperty("x GetWidth SetWidth") c.addProperty("y GetHeight SetHeight") # Take care of the same issues as wxPoint tools.ignoreAllOperators(c) for f in c.find('operator+=').all() + \ c.find('operator-=').all() + \ c.find('operator*=').all() + \ c.find('operator/=').all(): f.ignore(False) c.addCppMethod('bool', '__eq__', '(const wxSize& other)', body="return *self == *other;") c.addCppMethod('bool', '__neq__', '(const wxSize& other)', body="return *self != *other;") c.addItem(etgtools.WigCode("""\ wxSize operator+(const wxSize& other); wxSize operator-(const wxSize& other); wxSize operator*(int i); wxSize operator/(int i); wxPoint operator+(const wxPoint& other); wxPoint operator-(const wxPoint& other); wxRealPoint operator+(const wxRealPoint& other); wxRealPoint operator-(const wxRealPoint& other); """)) # wxSize typemap c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxSize') c.addCppMethod('PyObject*', 'Get', '()', """\ return sipBuildResult(0, "(ii)", self->GetWidth(), self->GetHeight()); """, pyArgsString="() -> (width, height)", briefDoc="Return the width and height properties as a tuple.") # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "wx.Size"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (Size, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod('__setitem__', '(self, idx, val)', """\ if idx == 0: self.width = val elif idx == 1: self.height = val else: raise IndexError """) c.addPyCode('Size.__safe_for_unpickling__ = True') #--------------------------------------- # wxRect tweaks c = module.find('wxRect') assert isinstance(c, etgtools.ClassDef) tools.addAutoProperties(c) c.addProperty("left GetLeft SetLeft") c.addProperty("top GetTop SetTop") c.addProperty("right GetRight SetRight") c.addProperty("bottom GetBottom SetBottom") c.addProperty("bottomLeft GetBottomLeft SetBottomLeft") c.addProperty("bottomRight GetBottomRight SetBottomRight") c.addProperty("topLeft GetTopLeft SetTopLeft") c.addProperty("topRight GetTopRight SetTopRight") # take care of the same issues as wxPoint tools.ignoreAllOperators(c) for f in c.find('operator+=').all() + \ c.find('operator*=').all(): f.ignore(False) c.addCppMethod('bool', '__eq__', '(const wxRect& other)', body="return *self == *other;") c.addCppMethod('bool', '__neq__', '(const wxRect& other)', body="return *self != *other;") c.addItem(etgtools.WigCode("""\ wxRect operator+(const wxRect& other); wxRect operator*(const wxRect& other); """)) # Because of our add-ons that make wx.Point and wx.Size act like 2-element # sequences, and also the typecheck code that allows 2-element sequences, then # we end up with a bit of confusion about the (Point,Point) and the # (Point,Size) overloads of the wx.Rect constructor. The confusion can be # dealt with by using keyword args, but I think that the (Point,Size) version # will be used more, so reorder the overloads so it is found first. m = module.find('wxRect.wxRect') mo = m.findOverload('topLeft') del m.overloads[m.overloads.index(mo)] m.overloads.append(mo) # These methods have some overloads that will end up with the same signature # in Python, so we have to remove one. module.find('wxRect.Deflate').findOverload(') const').ignore() module.find('wxRect.Inflate').findOverload(') const').ignore() module.find('wxRect.Union').findOverload(') const').ignore() module.find('wxRect.Intersect').findOverload(') const').ignore() # wxRect typemap c.convertFromPyObject = tools.convertFourIntegersTemplate('wxRect') c.addCppMethod('PyObject*', 'Get', '()', """\ return sipBuildResult(0, "(iiii)", self->x, self->y, self->width, self->height); """, pyArgsString="() -> (x, y, width, height)", briefDoc="Return the rectangle's properties as a tuple.") # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "wx.Rect"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0,0,0)') c.addPyMethod('__reduce__', '(self)', 'return (Rect, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod('__setitem__', '(self, idx, val)', """\ if idx == 0: self.x = val elif idx == 1: self.y = val elif idx == 2: self.width = val elif idx == 3: self.height = val else: raise IndexError """) c.addPyCode('Rect.__safe_for_unpickling__ = True') #--------------------------------------- # wxRealPoint tweaks c = module.find('wxRealPoint') tools.addAutoProperties(c) # take care of the same issues as wxPoint tools.ignoreAllOperators(c) for f in c.find('operator+=').all() + \ c.find('operator-=').all(): f.ignore(False) c.addCppMethod('bool', '__eq__', '(const wxRealPoint& other)', body="return *self == *other;") c.addCppMethod('bool', '__neq__', '(const wxRealPoint& other)', body="return *self != *other;") c.addItem(etgtools.WigCode("""\ wxRealPoint operator+(const wxRealPoint& other); wxRealPoint operator-(const wxRealPoint& other); wxRealPoint operator*(int i); wxRealPoint operator/(int i); """)) # wxRealPoint typemap c.convertFromPyObject = tools.convertTwoDoublesTemplate('wxRealPoint') c.addCppMethod('PyObject*', 'Get', '()', """\ return sipBuildResult(0, "(dd)", self->x, self->y); """, pyArgsString="() -> (x, y)", briefDoc="Return the point's properties as a tuple.") # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "wx.RealPoint"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (Rect, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod('__setitem__', '(self, idx, val)', """\ if idx == 0: self.x = val elif idx == 1: self.y = val else: raise IndexError """) c.addPyCode('RealPoint.__safe_for_unpickling__ = True') c = module.find('wxColourDatabase') c.addPyMethod('FindColour', '(self, colour)', 'return self.Find(colour)') module.find('wxTheColourDatabase').ignore() #----------------------------------------------------------------- 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.addGlobalStr('wxGridNameStr', module.items[0]) module.addPyCode("""\ GRID_VALUE_STRING = "string" GRID_VALUE_BOOL = "bool" GRID_VALUE_NUMBER = "long" GRID_VALUE_FLOAT = "double" GRID_VALUE_CHOICE = "choice" GRID_VALUE_TEXT = "string" GRID_VALUE_LONG = "long" GRID_VALUE_CHOICEINT = "choiceint" GRID_VALUE_DATETIME = "datetime" """) #----------------------------------------------------------------- c = module.find('wxGridCellCoords') assert isinstance(c, etgtools.ClassDef) tools.addAutoProperties(c) c.find('operator!').ignore() c.find('operator=').ignore() # Add a typemap for 2 element sequences c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxGridCellCoords') c.addCppMethod('PyObject*', 'Get', '()', """\ return sipBuildResult(0, "(ii)", self->GetRow(), self->GetCol()); """, pyArgsString="() -> (row,col)", briefDoc="Return the row and col properties as a tuple.") tools.addGetIMMethodTemplate(module, c, ['Row', 'Col']) # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "GridCellCoords"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (GridCellCoords, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod('__setitem__', '(self, idx, val)', """\ if idx == 0: self.Row = val elif idx == 1: self.Col = val else: raise IndexError """) c.addPyCode('GridCellCoords.__safe_for_unpickling__ = True') module.addItem( tools.wxArrayWrapperTemplate('wxGridCellCoordsArray', 'wxGridCellCoords', module)) #----------------------------------------------------------------- c = module.find('wxGridSizesInfo') c.find('m_customSizes').ignore() # TODO: Add support for wxUnsignedToIntHashMap?? #----------------------------------------------------------------- def fixRendererClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.addAutoProperties(klass) methods = [ ('Clone', "virtual wxGridCellRenderer* Clone() const /Factory/;"), ('Draw', "virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, " " const wxRect& rect, int row, int col, bool isSelected);"), ('GetBestSize', "virtual wxSize GetBestSize(wxGrid& grid, wxGridCellAttr& attr, " " wxDC& dc, int row, int col);"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code)) c = module.find('wxGridCellRenderer') c.addPrivateCopyCtor() c.find('~wxGridCellRenderer').ignore(False) c.find('Clone').factory = True for name in ITEMS: if 'Cell' in name and 'Renderer' in name: fixRendererClass(name) module.addPyCode("PyGridCellRenderer = wx.deprecated(GridCellRenderer, 'Use GridCellRenderer instead.')") #----------------------------------------------------------------- def fixEditorClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.addAutoProperties(klass) methods = [ ('BeginEdit', "virtual void BeginEdit(int row, int col, wxGrid* grid);"), ('Clone', "virtual wxGridCellEditor* Clone() const /Factory/;"), ('Create', "virtual void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler);"), #('EndEdit', "virtual bool EndEdit(int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval);"), ('ApplyEdit', "virtual void ApplyEdit(int row, int col, wxGrid* grid);"), ('Reset', "virtual void Reset();"), ('GetValue', "virtual wxString GetValue() const;"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code)) # Fix up EndEdit so it returns newval on success or None on failure pureVirtual = False if klass.findItem('EndEdit'): klass.find('EndEdit').ignore() pureVirtual = True # The Python version of EndEdit has a different signature than the # C++ version, so we need to take care of mapping between them so the # C++ compiler still recognizes this as a match for the virtual # method in the base class. klass.addCppMethod('PyObject*', 'EndEdit', '(int row, int col, const wxGrid* grid, const wxString& oldval)', cppSignature='bool (int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval)', pyArgsString='(row, col, grid, oldval)', isVirtual=True, isPureVirtual=pureVirtual, doc="""\ End editing the cell. This function must check if the current value of the editing cell is valid and different from the original value in its string form. If not then simply return None. If it has changed then this method should save the new value so that ApplyEdit can apply it later and the string representation of the new value should be returned. Notice that this method shoiuld not modify the grid as the change could still be vetoed. """, # Code for Python --> C++ calls. Make it return newval or None. body="""\ bool rv; wxString newval; rv = self->EndEdit(row, col, grid, *oldval, &newval); if (rv) { return wx2PyString(newval); } else { Py_INCREF(Py_None); return Py_None; } """, # Code for C++ --> Python calls. This is used when a C++ method # call needs to be reflected to a call to the overridden Python # method, so we need to translate between the real C++ siganture # and the Python signature. virtualCatcherCode="""\ // VirtualCatcherCode for wx.grid.GridCellEditor.EndEdit PyObject *result; result = sipCallMethod(0, sipMethod, "iiDN", row, col, const_cast<wxGrid *>(grid),sipType_wxGrid,NULL, new wxString(oldval),sipType_wxString,NULL); if (result == Py_None) { sipRes = false; } else { sipRes = true; *newval = Py2wxString(result); } Py_DECREF(result); """ if pureVirtual else "", # only used with the base class ) c = module.find('wxGridCellEditor') c.addPrivateCopyCtor() c.find('~wxGridCellEditor').ignore(False) c.find('Clone').factory = True c = module.find('wxGridCellChoiceEditor') c.find('wxGridCellChoiceEditor').findOverload('count').ignore() for name in ITEMS: if 'Cell' in name and 'Editor' in name: fixEditorClass(name) module.addPyCode("PyGridCellEditor = wx.deprecated(GridCellEditor, 'Use GridCellEditor instead.')") #----------------------------------------------------------------- c = module.find('wxGridCellAttr') c.addPrivateCopyCtor() c.find('~wxGridCellAttr').ignore(False) c.find('Clone').factory = True c.find('GetAlignment.hAlign').out = True c.find('GetAlignment.vAlign').out = True c.find('GetNonDefaultAlignment.hAlign').out = True c.find('GetNonDefaultAlignment.vAlign').out = True c.find('GetSize.num_rows').out = True c.find('GetSize.num_cols').out = True c.find('SetEditor.editor').transfer = True c.find('SetRenderer.renderer').transfer = True #----------------------------------------------------------------- # The instanceCode attribute is code that is used to make a default # instance of the class. We can't create them using the same class in # this case because they are abstract. c = module.find('wxGridCornerHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridCornerHeaderRendererDefault;' c = module.find('wxGridRowHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridRowHeaderRendererDefault;' c = module.find('wxGridColumnHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridColumnHeaderRendererDefault;' #----------------------------------------------------------------- c = module.find('wxGridCellAttrProvider') c.addPrivateCopyCtor() c.find('SetAttr.attr').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True module.addPyCode("PyGridCellAttrProvider = wx.deprecated(GridCellAttrProvider, 'Use GridCellAttrProvider instead.')") #----------------------------------------------------------------- c = module.find('wxGridTableBase') c.addPrivateCopyCtor() c.find('SetAttr.attr').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True module.addPyCode("PyGridTableBase = wx.deprecated(GridTableBase, 'Use GridTableBase instead.')") #----------------------------------------------------------------- c = module.find('wxGridTableMessage') c.addPrivateCopyCtor() #----------------------------------------------------------------- c = module.find('wxGrid') tools.fixWindowClass(c, ignoreProtected=False) c.bases = ['wxScrolledWindow'] c.find('GetColLabelAlignment.horiz').out = True c.find('GetColLabelAlignment.vert').out = True c.find('GetRowLabelAlignment.horiz').out = True c.find('GetRowLabelAlignment.vert').out = True c.find('GetCellAlignment.horiz').out = True c.find('GetCellAlignment.vert').out = True c.find('GetDefaultCellAlignment.horiz').out = True c.find('GetDefaultCellAlignment.vert').out = True c.find('RegisterDataType.renderer').transfer = True c.find('RegisterDataType.editor').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True c.find('SetCellEditor.editor').transfer = True c.find('SetCellRenderer.renderer').transfer = True # This overload is deprecated, so don't generate code for it. c.find('SetCellValue').findOverload('wxString &val').ignore() c.find('SetDefaultEditor.editor').transfer = True c.find('SetDefaultRenderer.renderer').transfer = True for n in ['GetColGridLinePen', 'GetDefaultGridLinePen', 'GetRowGridLinePen']: c.find(n).isVirtual = True # The SetTable method can optionally pass ownership of the table # object to the grid, so we need to optionally update the # ownership of the Python proxy object to match. c.find('SetTable').pyName = '_SetTable' c.addPyMethod('SetTable', '(self, table, takeOwnership=False, selmode=Grid.GridSelectCells)', piArgsString='(self, table, takeOwnership=False, selmode=GridSelectCells)', doc="Set the Grid Table to be used by this grid.", body="""\ val = self._SetTable(table, takeOwnership, selmode) if takeOwnership: import wx.siplib wx.siplib.transferto(table, self) return val """) # SIP will normally try to add support for overriding this method since # it is inherited from super classes, but in this case we want it to be # ignored (because IRL it is private in one of the intermediate classes) # so we'll tell SIP that it is private here instead. c.addItem(etgtools.WigCode("""\ wxSize GetSizeAvailableForScrollTarget(const wxSize& size); """, protection='private')) #----------------------------------------------------------------- c = module.find('wxGridUpdateLocker') c.addPrivateCopyCtor() # context manager methods c.addPyMethod('__enter__', '(self)', 'return self') c.addPyMethod('__exit__', '(self, exc_type, exc_val, exc_tb)', 'return False') #----------------------------------------------------------------- for name in ['wxGridSizeEvent', 'wxGridRangeSelectEvent', 'wxGridEditorCreatedEvent', 'wxGridEvent' ]: c = module.find(name) tools.fixEventClass(c) c.addPyCode("""\ EVT_GRID_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK ) EVT_GRID_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK ) EVT_GRID_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK ) EVT_GRID_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK ) EVT_GRID_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK ) EVT_GRID_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK ) EVT_GRID_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK ) EVT_GRID_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK ) EVT_GRID_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE ) EVT_GRID_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE ) EVT_GRID_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT ) EVT_GRID_CELL_CHANGING = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGING ) EVT_GRID_CELL_CHANGED = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGED ) EVT_GRID_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL ) EVT_GRID_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN ) EVT_GRID_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN ) EVT_GRID_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED ) EVT_GRID_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG ) EVT_GRID_COL_MOVE = wx.PyEventBinder( wxEVT_GRID_COL_MOVE ) EVT_GRID_COL_SORT = wx.PyEventBinder( wxEVT_GRID_COL_SORT ) EVT_GRID_TABBING = wx.PyEventBinder( wxEVT_GRID_TABBING ) # The same as above but with the ability to specify an identifier EVT_GRID_CMD_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK, 1 ) EVT_GRID_CMD_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK, 1 ) EVT_GRID_CMD_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK, 1 ) EVT_GRID_CMD_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK, 1 ) EVT_GRID_CMD_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK, 1 ) EVT_GRID_CMD_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK, 1 ) EVT_GRID_CMD_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK, 1 ) EVT_GRID_CMD_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK, 1 ) EVT_GRID_CMD_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE, 1 ) EVT_GRID_CMD_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE, 1 ) EVT_GRID_CMD_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT, 1 ) EVT_GRID_CMD_CELL_CHANGING = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGING, 1 ) EVT_GRID_CMD_CELL_CHANGED = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGED, 1 ) EVT_GRID_CMD_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL, 1 ) EVT_GRID_CMD_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN, 1 ) EVT_GRID_CMD_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN, 1 ) EVT_GRID_CMD_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED, 1 ) EVT_GRID_CMD_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG, 1 ) EVT_GRID_CMD_COL_MOVE = wx.PyEventBinder( wxEVT_GRID_COL_MOVE, 1 ) EVT_GRID_CMD_COL_SORT = wx.PyEventBinder( wxEVT_GRID_COL_SORT, 1 ) EVT_GRID_CMD_TABBING = wx.PyEventBinder( wxEVT_GRID_TABBING, 1 ) """) #----------------------------------------------------------------- #----------------------------------------------------------------- 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.addGlobalStr('wxGridNameStr', module.items[0]) module.addPyCode("""\ GRID_VALUE_STRING = "string" GRID_VALUE_BOOL = "bool" GRID_VALUE_NUMBER = "long" GRID_VALUE_FLOAT = "double" GRID_VALUE_CHOICE = "choice" GRID_VALUE_TEXT = "string" GRID_VALUE_LONG = "long" GRID_VALUE_CHOICEINT = "choiceint" GRID_VALUE_DATETIME = "datetime" """) #----------------------------------------------------------------- c = module.find('wxGridCellCoords') assert isinstance(c, etgtools.ClassDef) tools.addAutoProperties(c) c.find('operator!').ignore() c.find('operator=').ignore() # Add a typemap for 2 element sequences c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxGridCellCoords') c.addCppMethod('PyObject*', 'Get', '()', """\ return sipBuildResult(0, "(ii)", self->GetRow(), self->GetCol()); """, pyArgsString="() -> (row,col)", briefDoc="Return the row and col properties as a tuple.") # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "GridCellCoords"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)') c.addPyMethod('__reduce__', '(self)', 'return (GridCellCoords, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod('__setitem__', '(self, idx, val)', """\ if idx == 0: self.Row = val elif idx == 1: self.Col = val else: raise IndexError """) c.addPyCode('GridCellCoords.__safe_for_unpickling__ = True') module.addItem( tools.wxArrayWrapperTemplate('wxGridCellCoordsArray', 'wxGridCellCoords', module)) #----------------------------------------------------------------- c = module.find('wxGridSizesInfo') c.find('m_customSizes').ignore() # TODO: Add support for wxUnsignedToIntHashMap?? #----------------------------------------------------------------- def fixRendererClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.addAutoProperties(klass) methods = [ ('Clone', "virtual wxGridCellRenderer* Clone() const;"), ('Draw', "virtual void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, " " const wxRect& rect, int row, int col, bool isSelected);"), ('GetBestSize', "virtual wxSize GetBestSize(wxGrid& grid, wxGridCellAttr& attr, " " wxDC& dc, int row, int col);"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code)) c = module.find('wxGridCellRenderer') c.addPrivateCopyCtor() c.find('~wxGridCellRenderer').ignore(False) for name in ITEMS: if 'Cell' in name and 'Renderer' in name: fixRendererClass(name) module.addPyCode("PyGridCellRenderer = wx.deprecated(GridCellRenderer, 'Use GridCellRenderer instead.')") #----------------------------------------------------------------- def fixEditorClass(name): klass = module.find(name) assert isinstance(klass, etgtools.ClassDef) tools.addAutoProperties(klass) methods = [ ('BeginEdit', "virtual void BeginEdit(int row, int col, wxGrid* grid);"), ('Clone', "virtual wxGridCellEditor* Clone() const;"), ('Create', "virtual void Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler);"), #('EndEdit', "virtual bool EndEdit(int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval);"), ('ApplyEdit', "virtual void ApplyEdit(int row, int col, wxGrid* grid);"), ('Reset', "virtual void Reset();"), ('GetValue', "virtual wxString GetValue() const;"), ] for method, code in methods: if not klass.findItem(method): klass.addItem(etgtools.WigCode(code)) # Fix up EndEdit so it returns newval on success or None on failure pureVirtual = False if klass.findItem('EndEdit'): klass.find('EndEdit').ignore() pureVirtual = True klass.addCppMethod('PyObject*', 'EndEdit', '(int row, int col, const wxGrid* grid, const wxString& oldval)', cppSignature='bool (int row, int col, const wxGrid* grid, const wxString& oldval, wxString* newval)', pyArgsString='(row, col, grid, oldval)', isVirtual=True, isPureVirtual=pureVirtual, doc="""\ End editing the cell. This function must check if the current value of the editing cell is valid and different from the original value in its string form. If not then simply return None. If it has changed then this method should save the new value so that ApplyEdit can apply it later and the string representation of the new value should be returned. Notice that this method shoiuld not modify the grid as the change could still be vetoed. """, # Code for Python --> C++ calls. Make it return newval or None. body="""\ bool rv; wxString newval; rv = self->EndEdit(row, col, grid, *oldval, &newval); if (rv) { return wx2PyString(newval); } else { Py_INCREF(Py_None); return Py_None; } """, # Code for C++ --> Python calls. This is used when a C++ method # call needs to be reflected to a call to the overridden Python # method, so we need to translate between the real C++ siganture # and the Python signature. virtualCatcherCode="""\ // VirtualCatcherCode for wx.grid.GridCellEditor.EndEdit PyObject *result; result = sipCallMethod(0, sipMethod, "iiDN", row, col, const_cast<wxGrid *>(grid),sipType_wxGrid,NULL); if (result == Py_None) { sipRes = false; } else { sipRes = true; *newval = Py2wxString(result); } Py_DECREF(result); """ if pureVirtual else "", # only used with the base class ) c = module.find('wxGridCellEditor') c.addPrivateCopyCtor() c.find('~wxGridCellEditor').ignore(False) c = module.find('wxGridCellChoiceEditor') c.find('wxGridCellChoiceEditor').findOverload('count').ignore() for name in ITEMS: if 'Cell' in name and 'Editor' in name: fixEditorClass(name) module.addPyCode("PyGridCellEditor = wx.deprecated(GridCellEditor, 'Use GridCellEditor instead.')") #----------------------------------------------------------------- c = module.find('wxGridCellAttr') c.addPrivateCopyCtor() c.find('~wxGridCellAttr').ignore(False) c.find('GetAlignment.hAlign').out = True c.find('GetAlignment.vAlign').out = True c.find('GetNonDefaultAlignment.hAlign').out = True c.find('GetNonDefaultAlignment.vAlign').out = True #----------------------------------------------------------------- # The insanceCode attribute is code that is used to make a default # instance of the class. We can't create them using the same class in # this case because they are abstract. c = module.find('wxGridCornerHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridCornerHeaderRendererDefault;' c = module.find('wxGridRowHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridRowHeaderRendererDefault;' c = module.find('wxGridColumnHeaderRenderer') c.instanceCode = 'sipCpp = new wxGridColumnHeaderRendererDefault;' #----------------------------------------------------------------- c = module.find('wxGridCellAttrProvider') c.addPrivateCopyCtor() c.find('SetAttr.attr').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True module.addPyCode("PyGridCellAttrProvider = wx.deprecated(GridCellAttrProvider, 'Use GridCellAttrProvider instead.')") #----------------------------------------------------------------- c = module.find('wxGridTableBase') c.addPrivateCopyCtor() c.find('SetAttr.attr').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True module.addPyCode("PyGridTableBase = wx.deprecated(GridTableBase, 'Use GridTableBase instead.')") #----------------------------------------------------------------- c = module.find('wxGridTableMessage') c.addPrivateCopyCtor() #----------------------------------------------------------------- c = module.find('wxGrid') tools.fixWindowClass(c, ignoreProtected=False) c.bases = ['wxScrolledWindow'] c.find('GetColLabelAlignment.horiz').out = True c.find('GetColLabelAlignment.vert').out = True c.find('GetRowLabelAlignment.horiz').out = True c.find('GetRowLabelAlignment.vert').out = True c.find('GetCellAlignment.horiz').out = True c.find('GetCellAlignment.vert').out = True c.find('GetDefaultCellAlignment.horiz').out = True c.find('GetDefaultCellAlignment.vert').out = True c.find('RegisterDataType.renderer').transfer = True c.find('RegisterDataType.editor').transfer = True c.find('SetRowAttr.attr').transfer = True c.find('SetColAttr.attr').transfer = True c.find('SetCellEditor.editor').transfer = True c.find('SetCellRenderer.renderer').transfer = True # This overload is deprecated, so don't generate code for it. c.find('SetCellValue').findOverload('wxString &val').ignore() c.find('SetDefaultEditor.editor').transfer = True c.find('SetDefaultRenderer.renderer').transfer = True for n in ['GetColGridLinePen', 'GetDefaultGridLinePen', 'GetRowGridLinePen']: c.find(n).isVirtual = True #----------------------------------------------------------------- c = module.find('wxGridUpdateLocker') c.addPrivateCopyCtor() # context manager methods c.addPyMethod('__enter__', '(self)', 'return self') c.addPyMethod('__exit__', '(self, exc_type, exc_val, exc_tb)', 'return False') #----------------------------------------------------------------- for name in ['wxGridSizeEvent', 'wxGridRangeSelectEvent', 'wxGridEditorCreatedEvent', 'wxGridEvent' ]: c = module.find(name) tools.fixEventClass(c) c.addPyCode("""\ EVT_GRID_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK ) EVT_GRID_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK ) EVT_GRID_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK ) EVT_GRID_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK ) EVT_GRID_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK ) EVT_GRID_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK ) EVT_GRID_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK ) EVT_GRID_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK ) EVT_GRID_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE ) EVT_GRID_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE ) EVT_GRID_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT ) EVT_GRID_CELL_CHANGING = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGING ) EVT_GRID_CELL_CHANGED = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGED ) EVT_GRID_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL ) EVT_GRID_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN ) EVT_GRID_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN ) EVT_GRID_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED ) EVT_GRID_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG ) EVT_GRID_COL_MOVE = wx.PyEventBinder( wxEVT_GRID_COL_MOVE ) EVT_GRID_COL_SORT = wx.PyEventBinder( wxEVT_GRID_COL_SORT ) EVT_GRID_TABBING = wx.PyEventBinder( wxEVT_GRID_TABBING ) # The same as above but with the ability to specify an identifier EVT_GRID_CMD_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK, 1 ) EVT_GRID_CMD_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK, 1 ) EVT_GRID_CMD_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK, 1 ) EVT_GRID_CMD_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK, 1 ) EVT_GRID_CMD_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK, 1 ) EVT_GRID_CMD_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK, 1 ) EVT_GRID_CMD_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK, 1 ) EVT_GRID_CMD_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK, 1 ) EVT_GRID_CMD_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE, 1 ) EVT_GRID_CMD_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE, 1 ) EVT_GRID_CMD_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT, 1 ) EVT_GRID_CMD_CELL_CHANGING = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGING, 1 ) EVT_GRID_CMD_CELL_CHANGED = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGED, 1 ) EVT_GRID_CMD_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL, 1 ) EVT_GRID_CMD_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN, 1 ) EVT_GRID_CMD_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN, 1 ) EVT_GRID_CMD_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED, 1 ) EVT_GRID_CMD_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG, 1 ) EVT_GRID_CMD_COL_MOVE = wx.PyEventBinder( wxEVT_GRID_COL_MOVE, 1 ) EVT_GRID_CMD_COL_SORT = wx.PyEventBinder( wxEVT_GRID_COL_SORT, 1 ) EVT_GRID_CMD_TABBING = wx.PyEventBinder( wxEVT_GRID_TABBING, 1 ) """) #----------------------------------------------------------------- #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)