def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) module.addHeaderCode('#include "wx/mediactrl.h"') #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxMediaCtrl') c.addPrivateCopyCtor() c.find('wxMediaCtrl.id').default = '-1' c.find('Create.id').default = '-1' # the C++ class has three overloaded Load(...) methods # for now we ignore all than the first one for loading a filename for item in c.findAll("Load"): if not "fileName" in item.argsString: # ignore e.g. the Load with args '(const wxURI &uri)' # keep e.g. '(const wxString &fileName)' item.ignore() # Transplant the docstrings from the ignored Load methods into the # appropriate compatibility method if 'proxy' in item.argsString: m = c.find('LoadURIWithProxy') else: m = c.find('LoadURI') m.briefDoc = item.briefDoc m.detailedDoc = item.detailedDoc c = module.find('wxMediaEvent') tools.fixEventClass(c) module.addPyCode("""\ EVT_MEDIA_LOADED = wx.PyEventBinder( wxEVT_MEDIA_LOADED ) EVT_MEDIA_STOP = wx.PyEventBinder( wxEVT_MEDIA_STOP ) EVT_MEDIA_FINISHED = wx.PyEventBinder( wxEVT_MEDIA_FINISHED ) EVT_MEDIA_STATECHANGED = wx.PyEventBinder( wxEVT_MEDIA_STATECHANGED ) EVT_MEDIA_PLAY = wx.PyEventBinder( wxEVT_MEDIA_PLAY ) EVT_MEDIA_PAUSE = wx.PyEventBinder( wxEVT_MEDIA_PAUSE ) """) # See mediactrl.h: module.addPyCode("""\ MEDIABACKEND_DIRECTSHOW = "wxAMMediaBackend" MEDIABACKEND_MCI = "wxMCIMediaBackend" MEDIABACKEND_QUICKTIME = "wxQTMediaBackend" MEDIABACKEND_GSTREAMER = "wxGStreamerMediaBackend" MEDIABACKEND_REALPLAYER = "wxRealPlayerMediaBackend" MEDIABACKEND_WMP10 = "wxWMP10MediaBackend" """) #----------------------------------------------------------------- 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. c = module.find('wxHtmlDCRenderer') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() tools.fixHtmlSetFonts(c) c.find('Render.from').name = 'from_' c.find('Render.to').name = 'to_' c = module.find('wxHtmlEasyPrinting') c.addPrivateCopyCtor() c = module.find('wxHtmlPrintout') c.addPrivateCopyCtor() #----------------------------------------------------------------- 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. c = module.find('wxRichTextHeaderFooterData') assert isinstance(c, etgtools.ClassDef) tools.ignoreAllOperators(c) c = module.find('wxRichTextPrintout') assert isinstance(c, etgtools.ClassDef) c.find('GetPageInfo.minPage').out = True c.find('GetPageInfo.maxPage').out = True c.find('GetPageInfo.selPageFrom').out = True c.find('GetPageInfo.selPageTo').out = True c = module.find('wxRichTextPrinting') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() #----------------------------------------------------------------- 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/textdlg.h>") module.find('wxGetTextFromUserPromptStr').ignore() module.find('wxGetPasswordFromUserPromptStr').ignore() c = module.find('wxTextEntryDialog') assert isinstance(c, etgtools.ClassDef) tools.fixTopLevelWindowClass(c) # We don't wrap wxTextValidator for m in c.find('SetTextValidator').all(): m.ignore() module.addGlobalStr('wxGetTextFromUserPromptStr', c) module.addGlobalStr('wxGetPasswordFromUserPromptStr', c) c = module.find('wxPasswordEntryDialog') tools.fixTopLevelWindowClass(c) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxPopupWindow') assert isinstance(c, etgtools.ClassDef) tools.fixWindowClass(c) c.find('Position').isVirtual = True c = module.find('wxPopupTransientWindow') tools.fixWindowClass(c) c.find('Dismiss').isVirtual = True c.find('ProcessLeftDown').isVirtual = True c.find('OnDismiss').ignore(False) c.find('OnDismiss').isVirtual = 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. c = module.find('wxCheckBox') assert isinstance(c, etgtools.ClassDef) c.find('wxCheckBox.label').default = 'wxEmptyString' c.find('Create.label').default = 'wxEmptyString' module.addGlobalStr('wxCheckBoxNameStr', c) # Workaround warning for the property name starting with a digit c.find('Get3StateValue').ignore() c.addAutoProperties() c.find('Get3StateValue').ignore(False) c.addProperty('ThreeStateValue Get3StateValue Set3StateValue') tools.fixWindowClass(c) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxMDIClientWindow') assert isinstance(c, etgtools.ClassDef) tools.fixWindowClass(c) c.find('CreateClient').isVirtual = True c = module.find('wxMDIParentFrame') tools.fixTopLevelWindowClass(c) c.find('OnCreateClient').isVirtual = True m = c.find('GetClientWindow') assert isinstance(m, etgtools.MethodDef) m.type = 'wxMDIClientWindow *' m.setCppCode("return static_cast<wxMDIClientWindow*>(self->GetClientWindow());") c = module.find('wxMDIChildFrame') tools.fixTopLevelWindowClass(c) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. module.addHeaderCode("#include <wx/datectrl.h>") dpc = module.find('wxDatePickerCtrl') assert isinstance(dpc, etgtools.ClassDef) # Make a copy and call it wxDatePickerCtrlGeneric so we can generate # wrappers for both classes gdpc = tools.copyClassDef(dpc, 'wxDatePickerCtrlGeneric') assert isinstance(gdpc, etgtools.ClassDef) module.insertItemAfter(dpc, gdpc) # and give it a new Python name to match Classic gdpc.pyName = 'GenericDatePickerCtrl' # now back to our regular tweaking for c in [dpc, gdpc]: tools.fixWindowClass(c) c.find('GetRange.dt1').out = True c.find('GetRange.dt2').out = True gdpc.addHeaderCode("#include <wx/generic/datectrl.h>") #----------------------------------------------------------------- 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. c = module.find('wxHtmlHelpController') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() c.find('CreateHelpDialog').ignore(False) c.find('CreateHelpFrame').ignore(False) c.addItem(etgtools.WigCode("""\ // Add implementations for the pure virtuals in the base class virtual bool DisplayBlock(long blockNo); virtual bool DisplaySection(int sectionNo); virtual bool LoadFile(const wxString& file = wxEmptyString); virtual bool Quit(); """)) #----------------------------------------------------------------- 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/timectrl.h>') c = module.find('wxTimePickerCtrl') assert isinstance(c, etgtools.ClassDef) tools.fixWindowClass(c) # ignore the return value and set the parameters to be outputs c.find('GetTime').type = 'void' c.find('GetTime.hour').out = True c.find('GetTime.min').out = True c.find('GetTime.sec').out = 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.addHeaderCode("#include <wx/dcbuffer.h>") c = module.find('wxBufferedDC') c.addPrivateCopyCtor() for m in c.find('wxBufferedDC').all() + c.find('Init').all(): if m.findItem('dc'): m.findItem('dc').keepReference = True if m.findItem('buffer'): m.findItem('buffer').keepReference = True c = module.find('wxBufferedPaintDC') c.addPrivateCopyCtor() c.find('wxBufferedPaintDC').findOverload('wxBitmap').find('buffer').keepReference = True c = module.find('wxAutoBufferedPaintDC') c.addPrivateCopyCtor() module.find('wxAutoBufferedPaintDCFactory').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.addHeaderCode('#include <wx/ribbon/control.h>') # Not sure why these are showing up in this module as they are in core, so # let's just turn them off here... module.find('wxEllipsizeFlags').ignore() module.find('wxEllipsizeMode').ignore() c = module.find('wxRibbonControl') assert isinstance(c, etgtools.ClassDef) c.find('DoGetNextSmallerSize').ignore(False) c.find('DoGetNextLargerSize').ignore(False) tools.fixWindowClass(c) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxNativeFontInfo') assert isinstance(c, etgtools.ClassDef) c.addCppMethod('wxString*', '__str__', '()', """\ return new wxString(self->ToString()); """) # linker errors on all but MSW... c.find('GetPixelSize').ignore() c.find('SetPixelSize').ignore() c.addAutoProperties() #----------------------------------------------------------------- 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. c = module.find('wxTimer') assert isinstance(c, etgtools.ClassDef) c = module.find('wxTimerRunner') c.addPrivateCopyCtor() module.addPyCode('EVT_TIMER = wx.PyEventBinder( wxEVT_TIMER )') module.addPyCode("""\ class PyTimer(Timer): '''This timer class is passed the callable object to be called when the timer expires.''' def __init__(self, notify): Timer.__init__(self) self.notify = notify def Notify(self): if self.notify: self.notify() """) #----------------------------------------------------------------- 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. c = module.find('wxFindDialogEvent') assert isinstance(c, etgtools.ClassDef) tools.fixEventClass(c) module.addPyCode("""\ EVT_FIND = wx.PyEventBinder( wxEVT_FIND, 1 ) EVT_FIND_NEXT = wx.PyEventBinder( wxEVT_FIND_NEXT, 1 ) EVT_FIND_REPLACE = wx.PyEventBinder( wxEVT_FIND_REPLACE, 1 ) EVT_FIND_REPLACE_ALL = wx.PyEventBinder( wxEVT_FIND_REPLACE_ALL, 1 ) EVT_FIND_CLOSE = wx.PyEventBinder( wxEVT_FIND_CLOSE, 1 ) # deprecated wxEVT aliases wxEVT_COMMAND_FIND = wxEVT_FIND wxEVT_COMMAND_FIND_NEXT = wxEVT_FIND_NEXT wxEVT_COMMAND_FIND_REPLACE = wxEVT_FIND_REPLACE wxEVT_COMMAND_FIND_REPLACE_ALL = wxEVT_FIND_REPLACE_ALL wxEVT_COMMAND_FIND_CLOSE = wxEVT_FIND_CLOSE """) c = module.find('wxFindReplaceDialog') tools.fixTopLevelWindowClass(c) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. module.addHeaderCode("#include <wx/rawbmp.h>") addPixelDataBaseClass(module) addPixelDataClass(module, 'wxNativePixelData', 'wxBitmap', bpp=24, doc="""\ A class providing direct access to a :class:`wx.Bitmap`'s internal data without alpha channel (RGB). """) addPixelDataClass(module, 'wxAlphaPixelData', 'wxBitmap', bpp=32, doc="""\ A class providing direct access to a :class:`wx.Bitmap`'s internal data including the alpha channel (RGBA). """) #addPixelDataClass(module, 'wxImagePixelData', 'wxImage', bpp=32, # doc="""\ # ImagePixelData: A class providing direct access to a wx.Image's # internal data usign the same api as the other PixelData classes. # """) #----------------------------------------------------------------- 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. c = module.find('wxWizardPage') assert isinstance(c, etgtools.ClassDef) tools.fixWindowClass(c, False) module.addPyCode("PyWizardPage = wx.deprecated(WizardPage, 'Use WizardPage instead.')") c = module.find('wxWizardPageSimple') tools.fixWindowClass(c, False) c.addItem(etgtools.WigCode("""\ virtual wxWizardPage* GetNext() const; virtual wxWizardPage* GetPrev() const; """)) c = module.find('wxWizard') tools.fixWindowClass(c, False) # ShowPage is undocumented and labeled "implementation only" but it seems # too useful to ignore, so add a MethodDef for it here. m = MethodDef(name='ShowPage', type='bool', isVirtual=True, briefDoc="Show the given wizard page.", detailedDoc=["""\ Calls TransferDataFromWindow on the current page first, and returns false without changing the page if it returned false. Returns True/False to indicate if the page was actually changed."""], items=[ParamDef(name='page', type='wxWizardPage*'), ParamDef(name='goingForward', type='bool', default='true')]) c.addItem(m) # Same for IsRunning m = MethodDef(name='IsRunning', type='bool', isConst=True) c.addItem(m) c = module.find('wxWizardEvent') tools.fixEventClass(c) module.addPyCode("""\ EVT_WIZARD_BEFORE_PAGE_CHANGED = wx.PyEventBinder( wxEVT_WIZARD_BEFORE_PAGE_CHANGED, 1) EVT_WIZARD_PAGE_CHANGED = wx.PyEventBinder( wxEVT_WIZARD_PAGE_CHANGED, 1) EVT_WIZARD_PAGE_CHANGING = wx.PyEventBinder( wxEVT_WIZARD_PAGE_CHANGING, 1) EVT_WIZARD_CANCEL = wx.PyEventBinder( wxEVT_WIZARD_CANCEL, 1) EVT_WIZARD_HELP = wx.PyEventBinder( wxEVT_WIZARD_HELP, 1) EVT_WIZARD_FINISHED = wx.PyEventBinder( wxEVT_WIZARD_FINISHED, 1) EVT_WIZARD_PAGE_SHOWN = wx.PyEventBinder( wxEVT_WIZARD_PAGE_SHOWN, 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. c = module.find('wxNotificationMessage') assert isinstance(c, etgtools.ClassDef) # take care of some methods only available on MSW c.find('UseTaskBarIcon').setCppCode("""\ #ifdef __WXMSW__ return wxNotificationMessage::UseTaskBarIcon(icon); #else wxPyRaiseNotImplemented(); return NULL; #endif """) c.find('MSWUseToasts').setCppCode("""\ #ifdef __WXMSW__ return wxNotificationMessage::MSWUseToasts(*shortcutPath, *appId); #else wxPyRaiseNotImplemented(); return false; #endif """) #----------------------------------------------------------------- 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. c = module.find('wxAuiMDIParentFrame') assert isinstance(c, etgtools.ClassDef) tools.fixTopLevelWindowClass(c) c.find('SetMenuBar.menuBar').transfer = True c.find('SetArtProvider.provider').transfer = True c = module.find('wxAuiMDIChildFrame') tools.fixTopLevelWindowClass(c) tools.fixSetStatusWidths(c.find('SetStatusWidths')) c.find('SetMenuBar.menuBar').transfer = True c.find('Show').isVirtual = True c = module.find('wxAuiMDIClientWindow') tools.fixWindowClass(c) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxMessageDialog') assert isinstance(c, etgtools.ClassDef) module.addGlobalStr('wxMessageBoxCaptionStr', c) # Several of the wxMessageDIalog methods take a # wxMessageDialog::ButtonLabel parameter, which enables either a string or # a Stock ID to be passed. To facilitate this same ability for Python the # SIP types are changed to a custom type which is a MappedType which # handles converting from the two types for us. See msgdlg_btnlabel.sip c.find('ButtonLabel').ignore() for item in c.allItems(): if isinstance(item, ParamDef) and item.type == 'const ButtonLabel &': item.type = 'const wxMessageDialogButtonLabel &' tools.fixTopLevelWindowClass(c) # Make a copy of wxMessageDialog so we can generate code for # wxGenericMessageDialog too. gmd = copy.deepcopy(c) assert isinstance(gmd, etgtools.ClassDef) gmd.name = 'wxGenericMessageDialog' gmd.find('wxMessageDialog').name = 'wxGenericMessageDialog' # the ctor m = gmd.addItem(etgtools.MethodDef( protection='protected', type='void', name='AddMessageDialogCheckBox', briefDoc="Can be overridden to provide more contents for the dialog", className=gmd.name)) m.addItem(etgtools.ParamDef(type='wxSizer*', name='sizer')) m = gmd.addItem(etgtools.MethodDef( protection='protected', type='void', name='AddMessageDialogDetails', briefDoc="Can be overridden to provide more contents for the dialog", className=gmd.name)) m.addItem(etgtools.ParamDef(type='wxSizer*', name='sizer')) module.addItem(gmd) module.find('wxMessageBox').releaseGIL() c = module.find('wxMessageBox') 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. c = module.find('wxAppTraits') assert isinstance(c, etgtools.ClassDef) c.abstract = True # TODO: Enable these as etg scripts for their return types are added for name in [ 'CreateFontMapper', 'CreateMessageOutput', 'CreateRenderer', ]: c.find(name).ignore() for name in [ 'CreateConfig', 'CreateEventLoop', 'CreateLogTarget', #'GetStandardPaths', ]: c.find(name).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.addHeaderCode("#include <wx/dateevt.h>") c = module.find('wxDateEvent') assert isinstance(c, etgtools.ClassDef) tools.fixEventClass(c) c.addPyCode("""\ EVT_DATE_CHANGED = wx.PyEventBinder( wxEVT_DATE_CHANGED, 1 ) EVT_TIME_CHANGED = wx.PyEventBinder( wxEVT_TIME_CHANGED, 1 ) """) c.addPyCode("""\ DateEvent.PyGetDate = wx.deprecated(DateEvent.GetDate, 'Use GetDate instead.') DateEvent.PySetDate = wx.deprecated(DateEvent.SetDate, 'Use SetDate instead.') """) #----------------------------------------------------------------- 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/laywin.h>') c = module.find('wxSashLayoutWindow') assert isinstance(c, etgtools.ClassDef) tools.fixWindowClass(c) c = module.find('wxQueryLayoutInfoEvent') tools.fixEventClass(c) c = module.find('wxCalculateLayoutEvent') tools.fixEventClass(c) module.addPyCode("""\ EVT_QUERY_LAYOUT_INFO = wx.PyEventBinder( wxEVT_QUERY_LAYOUT_INFO ) EVT_CALCULATE_LAYOUT = wx.PyEventBinder( wxEVT_CALCULATE_LAYOUT ) """) #----------------------------------------------------------------- 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/unichar.h>') c = module.find('wxUniChar') assert isinstance(c, etgtools.ClassDef) m = c.find('wxUniChar').findOverload('long int') m.find('c').type = 'long' m = c.find('wxUniChar').findOverload('unsigned long int') m.find('c').type = 'unsigned long' for m in c.find('wxUniChar').all(): p = m.find('c') if 'long' not in p.type: m.ignore() tools.ignoreAllOperators(c) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING, check4unittest=False # wxEventLoop is well tested in # myYield used by other tests... ) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxEventLoopBase') assert isinstance(c, etgtools.ClassDef) c.abstract = True c.find('Yield').releaseGIL() c.find('YieldFor').releaseGIL() c.find('OnExit').ignore(False) c = module.find('wxEventLoopActivator') c.addPrivateAssignOp() c.addPrivateCopyCtor() # context manager methods c.addPyMethod('__enter__', '(self)', 'return self') c.addPyMethod('__exit__', '(self, exc_type, exc_val, exc_tb)', 'return False') c = module.find('wxGUIEventLoop') c.addPrivateCopyCtor() # Add declaration of the base class pure virtuals so sip knows they have # implementations here c.addItem(etgtools.WigCode("""\ public: virtual int Run(); virtual void Exit(int rc = 0); virtual bool Pending() const; virtual bool Dispatch(); virtual int DispatchTimeout(unsigned long timeout); virtual void WakeUp(); virtual bool ProcessIdle(); """)) module.addPyCode("""\ @wx.deprecatedMsg('Use GUIEventLoop instead.') class EventLoop(GUIEventLoop): '''Class using the old name for compatibility.''' def __init__(self): GUIEventLoop.__init__(self) """) #----------------------------------------------------------------- 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) module.check4unittest = False #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. module.addHeaderCode('#include <wxpy_api.h>') module.addImport('_core') module.addPyCode("import wx", order=10) module.addInclude(INCLUDES) module.addCppCode("""\ #include <wx/html/htmlwin.h> #include <wx/html/htmprint.h> #include <wx/html/helpctrl.h> #include <wx/html/helpwnd.h> #include <wx/html/helpfrm.h> #include <wx/html/helpdlg.h> """) #----------------------------------------------------------------- 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, check4unittest = False) 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 <wxPython/wxpy_api.h>') module.addImport('_core') module.addPyCode("import wx", order=10) module.addImport('_xml') module.addImport('_html') module.addImport('_adv') module.addInclude(INCLUDES) # Redo the initialization of wxModules in the case where this extension # module is not imported until *after* the wx.App has been created. module.addInitializerCode("""\ wxPyReinitializeModules(); """) #----------------------------------------------------------------- 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. c = module.find('wxPlatformInfo') assert isinstance(c, etgtools.ClassDef) # to avoid conflicts with wxPython's wx.PlatformInfo c.renameClass('PlatformInformation') c.find('GetEndianness').findOverload('end').ignore() c.find('GetArchName').findOverload('arch').ignore() c.find('GetOperatingSystemId').findOverload('name').ignore() c.find('GetPortId').findOverload('portname').ignore() c.find('GetEndiannessName').findOverload('end').ignore() c.find('GetOperatingSystemIdName').findOverload('os').ignore() c.find('GetOperatingSystemFamilyName').findOverload('os').ignore() c.find('GetPortIdName').findOverload('port').ignore() c.find('GetPortIdShortName').findOverload('port').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.find('wxPG_LABEL').ignore() module.find('wxPG_LABEL_STRING').ignore() module.find('wxPG_NULL_BITMAP').ignore() module.find('wxPG_COLOUR_BLACK').ignore() module.find('wxPG_COLOUR').ignore() module.find('wxPG_DEFAULT_IMAGE_SIZE').ignore() module.find('wxPGSortCallback').ignore() module.addPyCode( code="""\ PG_LABEL = "@!" PG_LABEL_STRING = PG_LABEL PG_NULL_BITMAP = wx.NullBitmap PG_COLOUR_BLACK = wx.BLACK PG_DEFAULT_IMAGE_SIZE = wx.Size(-1, -1) """, order=15) #----------------------------------------------------------------- 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.addItem( tools.wxArrayWrapperTemplate('wxHtmlBookRecArray', 'wxHtmlBookRecord', module)) module.addItem( tools.wxArrayWrapperTemplate('wxHtmlHelpDataItems', 'wxHtmlHelpDataItem', module)) c = module.find('wxHtmlHelpData') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. # Compatibility alias module.addPyCode("""\ ListItemAttr = wx.deprecated(ItemAttr, 'Use ItemAttr instead') """) #------------------------------------------------------- c = module.find('wxListItem') assert isinstance(c, etgtools.ClassDef) c.find('SetData').findOverload('void *').ignore() c.find('GetData').type = 'long' #------------------------------------------------------- c = module.find('wxListCtrl') tools.fixWindowClass(c) module.addGlobalStr('wxListCtrlNameStr', before=c) # Unignore some protected virtual methods that we want to allow to be # overridden in derived classes for name in [ 'OnGetItemAttr', #'OnGetItemColumnAttr', # MSW only? 'OnGetItemColumnImage', 'OnGetItemImage', 'OnGetItemText', 'OnGetItemIsChecked', ]: c.find(name).ignore(False) c.find(name).isVirtual = True tools.addEnableSystemTheme(c, 'wx.ListCtrl') # Tweaks to allow passing and using a Python callable object for the sort # compare function. First provide a sort callback function that can call the # Python function. c.addCppCode("""\ static int wxCALLBACK wxPyListCtrl_SortItems(wxIntPtr item1, wxIntPtr item2, wxIntPtr funcPtr) { int retval = 0; PyObject* func = (PyObject*)funcPtr; wxPyThreadBlocker blocker; #if SIZEOF_LONG >= SIZEOF_VOID_P PyObject* args = Py_BuildValue("(ll)", item1, item2); #else PyObject* args = Py_BuildValue("(LL)", item1, item2); #endif PyObject* result = PyEval_CallObject(func, args); Py_DECREF(args); if (result) { retval = wxPyInt_AsLong(result); Py_DECREF(result); } return retval; } """) # Next, provide an alternate implementation of SortItems that will use that callback. sim = c.find('SortItems') assert isinstance(sim, etgtools.MethodDef) sim.find('fnSortCallBack').type = 'PyObject*' sim.find('data').ignore( ) # we will be using it to pass the python callback function sim.argsString = sim.argsString.replace('wxListCtrlCompare', 'PyObject*') sim.setCppCode("""\ if (!PyCallable_Check(fnSortCallBack)) return false; return self->SortItems((wxListCtrlCompare)wxPyListCtrl_SortItems, (wxIntPtr)fnSortCallBack); """) # SetItemData takes a long, so lets return that type from GetItemData too, # instead of a wxUIntPtr. c.find('GetItemData').type = 'long' c.find('SetItemPtrData').ignore() # Change the semantics of GetColumn to return the item as the return # value instead of through a parameter. # bool GetColumn(int col, wxListItem& item) const; c.find('GetColumn').ignore() c.addCppMethod( 'wxListItem*', 'GetColumn', '(int col)', doc= 'Gets information about this column. See SetItem() for more information.', factory=True, body="""\ wxListItem item; item.SetMask( wxLIST_MASK_STATE | wxLIST_MASK_TEXT | wxLIST_MASK_IMAGE | wxLIST_MASK_DATA | wxLIST_SET_ITEM | wxLIST_MASK_WIDTH | wxLIST_MASK_FORMAT ); if (self->GetColumn(col, item)) return new wxListItem(item); else return NULL; """) # Do the same for GetItem # bool GetItem(wxListItem& info) const; c.find('GetItem').ignore() c.addCppMethod( 'wxListItem*', 'GetItem', '(int itemIdx, int col=0)', doc= 'Gets information about the item. See SetItem() for more information.', factory=True, body="""\ wxListItem* info = new wxListItem; info->m_itemId = itemIdx; info->m_col = col; info->m_mask = 0xFFFF; info->m_stateMask = 0xFFFF; self->GetItem(*info); return info; """) # bool GetItemPosition(long item, wxPoint& pos) const; c.find('GetItemPosition').ignore() c.addCppMethod( 'wxPoint*', 'GetItemPosition', '(long item)', doc='Returns the position of the item, in icon or small icon view.', factory=True, body="""\ wxPoint* pos = new wxPoint; self->GetItemPosition(item, *pos); return pos; """) # bool GetItemRect(long item, wxRect& rect, int code = wxLIST_RECT_BOUNDS) const; c.find('GetItemRect').ignore() c.addCppMethod('wxRect*', 'GetItemRect', '(long item, int code = wxLIST_RECT_BOUNDS)', doc="""\ Returns the rectangle representing the item's size and position, in physical coordinates. code is one of wx.LIST_RECT_BOUNDS, wx.LIST_RECT_ICON, wx.LIST_RECT_LABEL.""", factory=True, body="""\ wxRect* rect = new wxRect; self->GetItemRect(item, *rect, code); return rect; """) c.find('EditLabel.textControlClass').ignore() c.find('EndEditLabel').ignore() c.find('AssignImageList.imageList').transfer = True c.find('HitTest.flags').out = True c.find('HitTest.ptrSubItem').ignore() c.addCppMethod( 'PyObject*', 'HitTestSubItem', '(const wxPoint& point)', pyArgsString="HitTestSubItem(point) -> (item, flags, subitem)", doc= "Determines which item (if any) is at the specified point, giving details in flags.", body="""\ long item, subitem; int flags; item = self->HitTest(*point, flags, &subitem); wxPyThreadBlocker blocker; PyObject* rv = PyTuple_New(3); PyTuple_SetItem(rv, 0, wxPyInt_FromLong(item)); PyTuple_SetItem(rv, 1, wxPyInt_FromLong(flags)); PyTuple_SetItem(rv, 2, wxPyInt_FromLong(subitem)); return rv; """) # Some deprecated aliases for Classic renames c.addPyCode( 'ListCtrl.FindItemData = wx.deprecated(ListCtrl.FindItem, "Use FindItem instead.")' ) c.addPyCode( 'ListCtrl.FindItemAtPos = wx.deprecated(ListCtrl.FindItem, "Use FindItem instead.")' ) c.addPyCode( 'ListCtrl.InsertStringItem = wx.deprecated(ListCtrl.InsertItem, "Use InsertItem instead.")' ) c.addPyCode( 'ListCtrl.InsertImageItem = wx.deprecated(ListCtrl.InsertItem, "Use InsertItem instead.")' ) c.addPyCode( 'ListCtrl.InsertImageStringItem = wx.deprecated(ListCtrl.InsertItem, "Use InsertItem instead.")' ) c.addPyCode( 'ListCtrl.SetStringItem = wx.deprecated(ListCtrl.SetItem, "Use SetItem instead.")' ) # Provide a way to determine if column ordering is possible c.addCppMethod( 'bool', 'HasColumnOrderSupport', '()', """\ #ifdef wxHAS_LISTCTRL_COLUMN_ORDER return true; #else return false; #endif """) # And provide implementation of those methods that will work whether or # not wx has column ordering support c.find('GetColumnOrder').setCppCode("""\ #ifdef wxHAS_LISTCTRL_COLUMN_ORDER return self->GetColumnOrder(col); #else wxPyRaiseNotImplemented(); return 0; #endif """) c.find('GetColumnIndexFromOrder').setCppCode("""\ #ifdef wxHAS_LISTCTRL_COLUMN_ORDER return self->GetColumnIndexFromOrder(pos); #else wxPyRaiseNotImplemented(); return 0; #endif """) c.find('GetColumnsOrder').type = 'wxArrayInt*' c.find('GetColumnsOrder').factory = True c.find('GetColumnsOrder').setCppCode("""\ #ifdef wxHAS_LISTCTRL_COLUMN_ORDER return new wxArrayInt(self->GetColumnsOrder()); #else wxPyRaiseNotImplemented(); return new wxArrayInt(); #endif """) c.find('SetColumnsOrder').setCppCode("""\ #ifdef wxHAS_LISTCTRL_COLUMN_ORDER return self->SetColumnsOrder(*orders); #else wxPyRaiseNotImplemented(); return false; #endif """) # Add some Python helper methods c.addPyMethod('Select', '(self, idx, on=1)', doc='Selects/deselects an item.', body="""\ if on: state = wx.LIST_STATE_SELECTED else: state = 0 self.SetItemState(idx, state, wx.LIST_STATE_SELECTED) """) c.addPyMethod('Focus', '(self, idx)', doc='Focus and show the given item.', body="""\ self.SetItemState(idx, wx.LIST_STATE_FOCUSED, wx.LIST_STATE_FOCUSED) self.EnsureVisible(idx) """) c.addPyMethod( 'GetFocusedItem', '(self)', doc='Gets the currently focused item or -1 if none is focused.', body= 'return self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_FOCUSED)') c.addPyMethod( 'GetFirstSelected', '(self, *args)', doc='Returns the first selected item, or -1 when none is selected.', body="return self.GetNextSelected(-1)") c.addPyMethod( 'GetNextSelected', '(self, item)', doc= 'Returns subsequent selected items, or -1 when no more are selected.', body= "return self.GetNextItem(item, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)" ) c.addPyMethod( 'IsSelected', '(self, idx)', doc='Returns ``True`` if the item is selected.', body= "return (self.GetItemState(idx, wx.LIST_STATE_SELECTED) & wx.LIST_STATE_SELECTED) != 0" ) c.addPyMethod('SetColumnImage', '(self, col, image)', body="""\ item = self.GetColumn(col) # preserve all other attributes too item.SetMask( wx.LIST_MASK_STATE | wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_DATA | wx.LIST_SET_ITEM | wx.LIST_MASK_WIDTH | wx.LIST_MASK_FORMAT ) item.SetImage(image) self.SetColumn(col, item) """) c.addPyMethod('ClearColumnImage', '(self, col)', body="self.SetColumnImage(col, -1)") c.addPyMethod('Append', '(self, entry)', doc='''\ Append an item to the list control. The `entry` parameter should be a sequence with an item for each column''', body="""\ if len(entry): from six import text_type pos = self.InsertItem(self.GetItemCount(), text_type(entry[0])) for i in range(1, len(entry)): self.SetItem(pos, i, text_type(entry[i])) return pos """) c.addCppMethod('wxWindow*', 'GetMainWindow', '()', body="""\ #if defined(__WXMSW__) || defined(__WXMAC__) return self; #else return (wxWindow*)self->m_mainWin; #endif """) #------------------------------------------------------- c = module.find('wxListView') tools.fixWindowClass(c) #------------------------------------------------------- c = module.find('wxListEvent') tools.fixEventClass(c) module.addPyCode("""\ EVT_LIST_BEGIN_DRAG = PyEventBinder(wxEVT_LIST_BEGIN_DRAG , 1) EVT_LIST_BEGIN_RDRAG = PyEventBinder(wxEVT_LIST_BEGIN_RDRAG , 1) EVT_LIST_BEGIN_LABEL_EDIT = PyEventBinder(wxEVT_LIST_BEGIN_LABEL_EDIT , 1) EVT_LIST_END_LABEL_EDIT = PyEventBinder(wxEVT_LIST_END_LABEL_EDIT , 1) EVT_LIST_DELETE_ITEM = PyEventBinder(wxEVT_LIST_DELETE_ITEM , 1) EVT_LIST_DELETE_ALL_ITEMS = PyEventBinder(wxEVT_LIST_DELETE_ALL_ITEMS , 1) EVT_LIST_ITEM_SELECTED = PyEventBinder(wxEVT_LIST_ITEM_SELECTED , 1) EVT_LIST_ITEM_DESELECTED = PyEventBinder(wxEVT_LIST_ITEM_DESELECTED , 1) EVT_LIST_KEY_DOWN = PyEventBinder(wxEVT_LIST_KEY_DOWN , 1) EVT_LIST_INSERT_ITEM = PyEventBinder(wxEVT_LIST_INSERT_ITEM , 1) EVT_LIST_COL_CLICK = PyEventBinder(wxEVT_LIST_COL_CLICK , 1) EVT_LIST_ITEM_RIGHT_CLICK = PyEventBinder(wxEVT_LIST_ITEM_RIGHT_CLICK , 1) EVT_LIST_ITEM_MIDDLE_CLICK = PyEventBinder(wxEVT_LIST_ITEM_MIDDLE_CLICK, 1) EVT_LIST_ITEM_ACTIVATED = PyEventBinder(wxEVT_LIST_ITEM_ACTIVATED , 1) EVT_LIST_CACHE_HINT = PyEventBinder(wxEVT_LIST_CACHE_HINT , 1) EVT_LIST_COL_RIGHT_CLICK = PyEventBinder(wxEVT_LIST_COL_RIGHT_CLICK , 1) EVT_LIST_COL_BEGIN_DRAG = PyEventBinder(wxEVT_LIST_COL_BEGIN_DRAG , 1) EVT_LIST_COL_DRAGGING = PyEventBinder(wxEVT_LIST_COL_DRAGGING , 1) EVT_LIST_COL_END_DRAG = PyEventBinder(wxEVT_LIST_COL_END_DRAG , 1) EVT_LIST_ITEM_FOCUSED = PyEventBinder(wxEVT_LIST_ITEM_FOCUSED , 1) EVT_LIST_ITEM_CHECKED = PyEventBinder(wxEVT_LIST_ITEM_CHECKED , 1) EVT_LIST_ITEM_UNCHECKED = PyEventBinder(wxEVT_LIST_ITEM_UNCHECKED , 1) # deprecated wxEVT aliases wxEVT_COMMAND_LIST_BEGIN_DRAG = wxEVT_LIST_BEGIN_DRAG wxEVT_COMMAND_LIST_BEGIN_RDRAG = wxEVT_LIST_BEGIN_RDRAG wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT = wxEVT_LIST_BEGIN_LABEL_EDIT wxEVT_COMMAND_LIST_END_LABEL_EDIT = wxEVT_LIST_END_LABEL_EDIT wxEVT_COMMAND_LIST_DELETE_ITEM = wxEVT_LIST_DELETE_ITEM wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS = wxEVT_LIST_DELETE_ALL_ITEMS wxEVT_COMMAND_LIST_ITEM_SELECTED = wxEVT_LIST_ITEM_SELECTED wxEVT_COMMAND_LIST_ITEM_DESELECTED = wxEVT_LIST_ITEM_DESELECTED wxEVT_COMMAND_LIST_KEY_DOWN = wxEVT_LIST_KEY_DOWN wxEVT_COMMAND_LIST_INSERT_ITEM = wxEVT_LIST_INSERT_ITEM wxEVT_COMMAND_LIST_COL_CLICK = wxEVT_LIST_COL_CLICK wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK = wxEVT_LIST_ITEM_RIGHT_CLICK wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK = wxEVT_LIST_ITEM_MIDDLE_CLICK wxEVT_COMMAND_LIST_ITEM_ACTIVATED = wxEVT_LIST_ITEM_ACTIVATED wxEVT_COMMAND_LIST_CACHE_HINT = wxEVT_LIST_CACHE_HINT wxEVT_COMMAND_LIST_COL_RIGHT_CLICK = wxEVT_LIST_COL_RIGHT_CLICK wxEVT_COMMAND_LIST_COL_BEGIN_DRAG = wxEVT_LIST_COL_BEGIN_DRAG wxEVT_COMMAND_LIST_COL_DRAGGING = wxEVT_LIST_COL_DRAGGING wxEVT_COMMAND_LIST_COL_END_DRAG = wxEVT_LIST_COL_END_DRAG wxEVT_COMMAND_LIST_ITEM_FOCUSED = wxEVT_LIST_ITEM_FOCUSED """) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxRegion') assert isinstance(c, etgtools.ClassDef) tools.removeVirtuals(c) c.mustHaveApp() # Replace one of the constructors with one having a more python-friendly API c.find('wxRegion').findOverload('points').ignore() c.addCppCode( tools.ObjArrayHelperTemplate( 'wxPoint', 'sipType_wxPoint', "Expected a sequence of length-2 sequences or wx.Point objects.")) c.addCppCtor_sip( '(PyObject* points, wxPolygonFillMode fillStyle = wxODDEVEN_RULE)', doc="""\ Constructs a region corresponding to the polygon made from the points in the provided sequence.""", body="""\ size_t count; wxPoint* array = wxPoint_array_helper(points, &count); if ( array != NULL ) { sipCpp = new wxRegion(count, array, fillStyle); delete [] array; } if (PyErr_Occurred()) sipIsErr = 1; """) c.find('GetBox').findOverload('wxCoord').ignore() # Iterator stuff c.addPyMethod( '__iter__', '(self)', 'return PyRegionIterator(self)', """\ Returns a rectangle interator conforming to the Python iterator protocol.""") c.addPyCode("""\ class PyRegionIterator(object): "A Python iterator for wx.Region objects" def __init__(self, region): self._region = region self._iterator = wx.RegionIterator(region) def next(self): if not self._iterator: raise StopIteration rect = self._iterator.GetRect() if self._iterator.HaveRects(): self._iterator.Next() return rect __next__ = next # for Python 3 """) c = module.find('wxRegionIterator') c.mustHaveApp() c.find('operator++').ignore() c.find('operator bool').ignore() c.addCppMethod( 'int', '__nonzero__', '()', 'return (int)self->operator bool();', 'Returns true while there are still rectangles available in the iteration.' ) c.addCppMethod( 'int', '__bool__', '()', 'return (int)self->operator bool();', 'Returns true while there are still rectangles available in the iteration.' ) c.addCppMethod('void', 'Next', '()', 'self->operator++();', 'Move the iterator to the next rectangle in the region.') # This is defined in the docs, but not in any of the real headers! module.find('wxNullRegion').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. scrolled = module.find('wxScrolled') assert isinstance(scrolled, etgtools.ClassDef) scrolled.find('GetViewStart').findOverload('()').ignore() scrolled.find('GetViewStart.x').out = True scrolled.find('GetViewStart.y').out = True m = scrolled.find('CalcScrolledPosition').findOverload('xx') m.find('xx').out = True m.find('yy').out = True m = scrolled.find('CalcUnscrolledPosition').findOverload('xx') m.find('xx').out = True m.find('yy').out = True scrolled.find('GetScrollPixelsPerUnit.xUnit').out = True scrolled.find('GetScrollPixelsPerUnit.yUnit').out = True # Just ignore this one and let the already tweaked versions be inherited from wx.Window. scrolled.find('GetVirtualSize').ignore() scrolled.addPrivateCopyCtor() scrolled.addPrivateAssignOp() tools.fixWindowClass(scrolled) # Add back some virtuals that were removed in fixWindowClass scrolled.find('OnDraw').isVirtual = True scrolled.find('GetSizeAvailableForScrollTarget').isVirtual = True scrolled.find('GetSizeAvailableForScrollTarget').ignore(False) scrolled.find('SendAutoScrollEvents').isVirtual = True # The wxScrolledCanvas typedef will be output normally and SIP will treat # it like a class that has a wxScrolled mix-in as one of the base classes. # Let's add some more info to them for the doc generators. docBase = """\ The :ref:`{name}` class is a combination of the :ref:`{base}` and :ref:`Scrolled` classes, and manages scrolling for its client area, transforming the coordinates according to the scrollbar positions, and setting the scroll positions, thumb sizes and ranges according to the area in view. """ item = module.find('wxScrolledCanvas') item.docAsClass = True item.bases = ['wxWindow', 'wxScrolled'] item.briefDoc = docBase.format(name='ScrolledCanvas', base='Window') item.detailedDoc[0] = "This scrolled window is not intended to have children "\ "so it doesn't have special handling for TAB traversal "\ "or focus management." # move it ahead of wxScrolledWindow sw = module.find('wxScrolledWindow') module.items.remove(item) module.insertItemBefore(sw, item) # wxScrolledWindow is documented as a typedef but it's actually a class. # So we need to implement it that way here too in order to keep # static_casts and such happy. assert isinstance(sw, TypedefDef) # First, let's add a typedef to serve as the base class of # wxScrolledWindow, since SIP doesn't yet understand using template # instantiations as base classes. Setting noTypeName tells SIP to not use # the typedef name in the actual generated code, but the typedef's type # instead. td = TypedefDef(name='_ScrolledWindowBase', type='wxScrolled<wxPanel>', noTypeName=True, piIgnored=True) module.insertItemAfter(sw, td) module.addHeaderCode('typedef wxScrolled<wxPanel> _ScrolledWindowBase;') sw.ignore() # Now implement the class definition klass = ClassDef( name='wxScrolledWindow', bases=['_ScrolledWindowBase'], piBases=['Window', 'Scrolled'], briefDoc=sw.briefDoc, detailedDoc=sw.detailedDoc, items=[ MethodDef(name='wxScrolledWindow', isCtor=True, items=[], overloads=[ MethodDef(name='wxScrolledWindow', isCtor=True, items=[ ParamDef(name='parent', type='wxWindow*'), ParamDef(name='id', type='wxWindowID', default='wxID_ANY'), ParamDef(name='pos', type='const wxPoint&', default='wxDefaultPosition'), ParamDef(name='size', type='const wxSize&', default='wxDefaultSize'), ParamDef( name='style', type='long', default='wxScrolledWindowStyle'), ParamDef(name='name', type='const wxString&', default='wxPanelNameStr'), ]), ]), MethodDef(name='SetFocusIgnoringChildren', type='void', items=[], briefDoc="""\ In contrast to SetFocus() this will set the focus to the panel even if there are child windows in the panel. This is only rarely needed.""" ), ], ) tools.fixWindowClass(klass) module.insertItemAfter(td, klass) module.addPyCode( "PyScrolledWindow = wx.deprecated(ScrolledWindow, 'Use ScrolledWindow instead.')" ) #----------------------------------------------------------------- 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)) #----------------------------------------------------------------- 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.GridSelectCells = Grid.SelectCells Grid.GridSelectRows = Grid.SelectRows Grid.GridSelectColumns = Grid.SelectColumns Grid.GridSelectRowsOrColumns = 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 run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxFileSystem') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() c.find('AddHandler.handler').transfer = True c.find('RemoveHandler').transferBack = True c = module.find('wxFileSystemHandler') c.find('GetAnchor').ignore(False) c.find('GetLeftLocation').ignore(False) c.find('GetProtocol').ignore(False) c.find('GetRightLocation').ignore(False) def _fixHandlerClass(klass): klass.addItem( etgtools.WigCode("""\ virtual bool CanOpen(const wxString& location); virtual wxFSFile* OpenFile(wxFileSystem& fs, const wxString& location); virtual wxString FindFirst(const wxString& spec, int flags = 0); virtual wxString FindNext(); """)) c = module.find('wxArchiveFSHandler') _fixHandlerClass(c) c.addPrivateCopyCtor() module.addPyCode( 'ZipFSHandler = wx.deprecated(ArchiveFSHandler, "Use ArchiveFSHandler instead.")' ) c = module.find('wxFSFile') c.addPrivateCopyCtor() c.find('wxFSFile.stream').transfer = True c.find('DetachStream').transferBack = True c = module.find('wxFilterFSHandler') _fixHandlerClass(c) c.addPrivateCopyCtor() c = module.find('wxInternetFSHandler') _fixHandlerClass(c) c.addPrivateCopyCtor() c = module.find('wxMemoryFSHandler') _fixHandlerClass(c) c.addPrivateCopyCtor() # Make some more python-friendly versions of the AddFile methods accepting raw data c.find('AddFile').findOverload('binarydata').ignore() c.find('AddFileWithMimeType').findOverload('binarydata').ignore() c.addCppMethod( 'void', 'AddFile', '(const wxString& filename, wxPyBuffer* binarydata)', isStatic=True, doc="Add a file from raw data in a python buffer compatible object.", body="""\ wxMemoryFSHandler::AddFile(*filename, binarydata->m_ptr, binarydata->m_len); """) c.addCppMethod( 'void', 'AddFileWithMimeType', '(const wxString& filename, wxPyBuffer* binarydata, const wxString& mimetype)', isStatic=True, doc="Add a file from raw data in a python buffer compatible object.", body="""\ wxMemoryFSHandler::AddFileWithMimeType( *filename, binarydata->m_ptr, binarydata->m_len, *mimetype); """) #----------------------------------------------------------------- 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. c = module.find('wxImage') assert isinstance(c, etgtools.ClassDef) c.find('wxImage').findOverload('(const char *const *xpmData)').ignore() c.find('GetHandlers').ignore() # TODO c.find('wxImage').findOverload('wxBitmap').mustHaveApp() # Ignore the ctors taking raw data buffers, so we can add in our own # versions that are a little smarter (accept any buffer object, check # the data length, etc.) c.find('wxImage').findOverload( 'int width, int height, unsigned char *data, bool static_data').ignore( ) c.find('wxImage').findOverload( 'const wxSize &sz, unsigned char *data, bool static_data').ignore() c.find('wxImage').findOverload( 'int width, int height, unsigned char *data, unsigned char *alpha, bool static_data' ).ignore() c.find('wxImage').findOverload( 'const wxSize &sz, unsigned char *data, unsigned char *alpha, bool static_data' ).ignore() c.addCppCtor_sip('(int width, int height, wxPyBuffer* data)', doc="Creates an image from RGB data in memory.", body="""\ if (! data->checkSize(width*height*3)) return NULL; void* copy = data->copy(); if (! copy) return NULL; sipCpp = new sipwxImage; sipCpp->Create(width, height, (byte*)copy); """) c.addCppCtor_sip( '(int width, int height, wxPyBuffer* data, wxPyBuffer* alpha)', doc="Creates an image from RGB data in memory, plus an alpha channel", body="""\ void* dcopy; void* acopy; if (!data->checkSize(width*height*3) || !alpha->checkSize(width*height)) return NULL; if ((dcopy = data->copy()) == NULL || (acopy = alpha->copy()) == NULL) return NULL; sipCpp = new sipwxImage; sipCpp->Create(width, height, (byte*)dcopy, (byte*)acopy, false); """) c.addCppCtor_sip('(const wxSize& size, wxPyBuffer* data)', doc="Creates an image from RGB data in memory.", body="""\ if (! data->checkSize(size->x*size->y*3)) return NULL; void* copy = data->copy(); if (! copy) return NULL; sipCpp = new sipwxImage; sipCpp->Create(size->x, size->y, (byte*)copy, false); """) c.addCppCtor_sip( '(const wxSize& size, wxPyBuffer* data, wxPyBuffer* alpha)', doc="Creates an image from RGB data in memory, plus an alpha channel", body="""\ void* dcopy; void* acopy; if (!data->checkSize(size->x*size->y*3) || !alpha->checkSize(size->x*size->y)) return NULL; if ((dcopy = data->copy()) == NULL || (acopy = alpha->copy()) == NULL) return NULL; sipCpp = new sipwxImage; sipCpp->Create(size->x, size->y, (byte*)dcopy, (byte*)acopy, false); """) # Do the same for the Create method overloads that need to deal with data buffers c.find('Create').findOverload( 'int width, int height, unsigned char *data, bool static_data').ignore( ) c.find('Create').findOverload( 'const wxSize &sz, unsigned char *data, bool static_data').ignore() c.find('Create').findOverload( 'int width, int height, unsigned char *data, unsigned char *alpha, bool static_data' ).ignore() c.find('Create').findOverload( 'const wxSize &sz, unsigned char *data, unsigned char *alpha, bool static_data' ).ignore() c.addCppMethod( 'bool', 'Create', '(int width, int height, wxPyBuffer* data)', doc="Create a new image initialized with the given RGB data.", body="""\ if (! data->checkSize(width*height*3)) return false; void* copy = data->copy(); if (! copy) return false; return self->Create(width, height, (byte*)copy); """) c.addCppMethod( 'bool', 'Create', '(int width, int height, wxPyBuffer* data, wxPyBuffer* alpha)', doc= "Create a new image initialized with the given RGB data and Alpha data.", body="""\ void* dcopy; void* acopy; if (!data->checkSize(width*height*3) || !alpha->checkSize(width*height)) return false; if ((dcopy = data->copy()) == NULL || (acopy = alpha->copy()) == NULL) return false; return self->Create(width, height, (byte*)dcopy, (byte*)acopy); """) c.addCppMethod( 'bool', 'Create', '(const wxSize& size, wxPyBuffer* data)', doc="Create a new image initialized with the given RGB data.", body="""\ if (! data->checkSize(size->x*size->y*3)) return false; void* copy = data->copy(); if (! copy) return false; return self->Create(size->x, size->y, (byte*)copy); """) c.addCppMethod( 'bool', 'Create', '(const wxSize& size, wxPyBuffer* data, wxPyBuffer* alpha)', doc= "Create a new image initialized with the given RGB data and Alpha data.", body="""\ void* dcopy; void* acopy; if (!data->checkSize(size->x*size->y*3) || !alpha->checkSize(size->x*size->y)) return false; if ((dcopy = data->copy()) == NULL || (acopy = alpha->copy()) == NULL) return false; return self->Create(size->x, size->y, (byte*)dcopy, (byte*)acopy); """) # And also do similar for SetData and SetAlpha m = c.find('SetData').findOverload('unsigned char *data') bd, dd = m.briefDoc, m.detailedDoc m.ignore() c.addCppMethod('void', 'SetData', '(wxPyBuffer* data)', briefDoc=bd, detailedDoc=dd, body="""\ if (!data->checkSize(self->GetWidth()*self->GetHeight()*3)) return; void* copy = data->copy(); if (!copy) return; self->SetData((byte*)copy, false); """) c.find('SetData').findOverload('int new_width').ignore() c.addCppMethod('void', 'SetData', '(wxPyBuffer* data, int new_width, int new_height)', body="""\ if (!data->checkSize(new_width*new_height*3)) return; void* copy = data->copy(); if (!copy) return; self->SetData((byte*)copy, new_width, new_height, false); """) m = c.find('SetAlpha').findOverload('unsigned char *alpha') bd, dd = m.briefDoc, m.detailedDoc m.ignore() c.addCppMethod('void', 'SetAlpha', '(wxPyBuffer* alpha)', briefDoc=bd, detailedDoc=dd, body="""\ if (!alpha->checkSize(self->GetWidth()*self->GetHeight())) return; void* copy = alpha->copy(); if (!copy) return; self->SetAlpha((byte*)copy, false); """) # GetData() and GetAlpha() return a copy of the image data/alpha bytes as # a bytearray object. c.find('GetData').ignore() c.addCppMethod('PyObject*', 'GetData', '()', doc="Returns a copy of the RGB bytes of the image.", body="""\ byte* data = self->GetData(); Py_ssize_t len = self->GetWidth() * self->GetHeight() * 3; PyObject* rv = NULL; wxPyBLOCK_THREADS( rv = PyByteArray_FromStringAndSize((const char*)data, len)); return rv; """) c.find('GetAlpha').findOverload('()').ignore() c.addCppMethod('PyObject*', 'GetAlpha', '()', doc="Returns a copy of the Alpha bytes of the image.", body="""\ byte* data = self->GetAlpha(); Py_ssize_t len = self->GetWidth() * self->GetHeight(); PyObject* rv = NULL; wxPyBLOCK_THREADS( rv = PyByteArray_FromStringAndSize((const char*)data, len)); return rv; """) # GetDataBuffer, GetAlphaBuffer provide direct access to the image's # internal buffers as a writable buffer object. We'll use memoryview # objects. c.addCppMethod('PyObject*', 'GetDataBuffer', '()', doc="""\ Returns a writable Python buffer object that is pointing at the RGB image data buffer inside the :class:`Image`. You need to ensure that you do not use this buffer object after the image has been destroyed.""", body="""\ byte* data = self->GetData(); Py_ssize_t len = self->GetWidth() * self->GetHeight() * 3; PyObject* rv; wxPyThreadBlocker blocker; rv = wxPyMakeBuffer(data, len); return rv; """) c.addCppMethod('PyObject*', 'GetAlphaBuffer', '()', doc="""\ Returns a writable Python buffer object that is pointing at the Alpha data buffer inside the :class:`Image`. You need to ensure that you do not use this buffer object after the image has been destroyed.""", body="""\ byte* data = self->GetAlpha(); Py_ssize_t len = self->GetWidth() * self->GetHeight(); PyObject* rv; wxPyThreadBlocker blocker; rv = wxPyMakeBuffer(data, len); return rv; """) # SetDataBuffer, SetAlphaBuffer tell the image to use some other memory # buffer pointed to by a Python buffer object. c.addCppMethod('void', 'SetDataBuffer', '(wxPyBuffer* data)', doc="""\ Sets the internal image data pointer to point at a Python buffer object. This can save making an extra copy of the data but you must ensure that the buffer object lives lives at least as long as the :class:`Image` does.""", body="""\ if (!data->checkSize(self->GetWidth() * self->GetHeight() * 3)) return; // True means don't free() the pointer self->SetData((byte*)data->m_ptr, true); """) c.addCppMethod('void', 'SetDataBuffer', '(wxPyBuffer* data, int new_width, int new_height)', doc="""\ Sets the internal image data pointer to point at a Python buffer object. This can save making an extra copy of the data but you must ensure that the buffer object lives lives at least as long as the :class:`Image` does.""", body="""\ if (!data->checkSize(new_width * new_height * 3)) return; // True means don't free() the pointer self->SetData((byte*)data->m_ptr, new_width, new_height, true); """) c.addCppMethod('void', 'SetAlphaBuffer', '(wxPyBuffer* alpha)', doc="""\ Sets the internal image alpha pointer to point at a Python buffer object. This can save making an extra copy of the data but you must ensure that the buffer object lives lives at least as long as the :class:`Image` does.""", body="""\ if (!alpha->checkSize(self->GetWidth() * self->GetHeight())) return; // True means don't free() the pointer self->SetAlpha((byte*)alpha->m_ptr, true); """) def setParamsPyInt(name): """Set the pyInt flag on 'unsigned char' params""" method = c.find(name) for m in [method] + method.overloads: for p in m.items: if p.type == 'unsigned char': p.pyInt = True setParamsPyInt('Replace') setParamsPyInt('ConvertAlphaToMask') setParamsPyInt('ConvertToMono') setParamsPyInt('ConvertToDisabled') setParamsPyInt('IsTransparent') setParamsPyInt('SetAlpha') setParamsPyInt('SetMaskColour') setParamsPyInt('SetMaskFromImage') setParamsPyInt('SetRGB') c.find('FindFirstUnusedColour').type = 'void' c.find('FindFirstUnusedColour.r').pyInt = True c.find('FindFirstUnusedColour.g').pyInt = True c.find('FindFirstUnusedColour.b').pyInt = True c.find('FindFirstUnusedColour.startR').pyInt = True c.find('FindFirstUnusedColour.startG').pyInt = True c.find('FindFirstUnusedColour.startB').pyInt = True c.find('FindFirstUnusedColour.r').out = True c.find('FindFirstUnusedColour.g').out = True c.find('FindFirstUnusedColour.b').out = True c.find('GetAlpha').findOverload('int x, int y').pyInt = True c.find('GetRed').pyInt = True c.find('GetGreen').pyInt = True c.find('GetBlue').pyInt = True c.find('GetMaskRed').pyInt = True c.find('GetMaskGreen').pyInt = True c.find('GetMaskBlue').pyInt = True c.find('GetOrFindMaskColour').type = 'void' c.find('GetOrFindMaskColour.r').pyInt = True c.find('GetOrFindMaskColour.g').pyInt = True c.find('GetOrFindMaskColour.b').pyInt = True c.find('GetOrFindMaskColour.r').out = True c.find('GetOrFindMaskColour.g').out = True c.find('GetOrFindMaskColour.b').out = True c.find('RGBValue.red').pyInt = True c.find('RGBValue.green').pyInt = True c.find('RGBValue.blue').pyInt = True c.find('RGBValue.RGBValue.r').pyInt = True c.find('RGBValue.RGBValue.g').pyInt = True c.find('RGBValue.RGBValue.b').pyInt = True c.addCppMethod('int', '__nonzero__', '()', 'return self->IsOk();') c.addPyMethod('ConvertToBitmap', '(self, depth=-1)', doc="""\ ConvertToBitmap(depth=-1) -> Bitmap\n Convert the image to a :class:`wx.Bitmap`.""", body="""\ bmp = wx.Bitmap(self, depth) return bmp """) c.addPyMethod('ConvertToMonoBitmap', '(self, red, green, blue)', doc="""\ ConvertToMonoBitmap(red, green, blue) -> Bitmap\n Creates a monochrome version of the image and returns it as a :class:`wx.Bitmap`.""", body="""\ mono = self.ConvertToMono( red, green, blue ) bmp = wx.Bitmap( mono, 1 ) return bmp """) c.addCppMethod( 'wxImage*', 'AdjustChannels', '(double factor_red, double factor_green, double factor_blue, double factor_alpha=1.0)', doc="""\ This function muliplies all 4 channels (red, green, blue, alpha) with a factor (around 1.0). Useful for gamma correction, colour correction and to add a certain amount of transparency to a image (fade in fade out effects). If factor_alpha is given but the original image has no alpha channel then a alpha channel will be added. """, body="""\ wxCHECK_MSG( self->Ok(), NULL, wxT("invalid image") ); wxImage* dest = new wxImage( self->GetWidth(), self->GetHeight(), false ); wxCHECK_MSG( dest && dest->IsOk(), NULL, wxT("unable to create image") ); unsigned rgblen = 3 * self->GetWidth() * self->GetHeight(); unsigned alphalen = self->GetWidth() * self->GetHeight(); byte* src_data = self->GetData(); byte* src_alpha = self->GetAlpha(); byte* dst_data = dest->GetData(); byte* dst_alpha = NULL; // adjust rgb if ( factor_red == 1.0 && factor_green == 1.0 && factor_blue == 1.0) { // nothing to do for RGB memcpy(dst_data, src_data, rgblen); } else { // rgb pixel for pixel for ( unsigned i = 0; i < rgblen; i= i + 3 ) { dst_data[i] = (byte) wxMin( 255, (int) (factor_red * src_data[i]) ); dst_data[i + 1] = (byte) wxMin( 255, (int) (factor_green * src_data[i + 1]) ); dst_data[i + 2] = (byte) wxMin( 255, (int) (factor_blue * src_data[i + 2]) ); } } // adjust the mask colour if ( self->HasMask() ) { dest->SetMaskColour((byte) wxMin( 255, (int) (factor_red * self->GetMaskRed() ) ), (byte) wxMin( 255, (int) (factor_green * self->GetMaskGreen() ) ), (byte) wxMin( 255, (int) (factor_blue * self->GetMaskBlue() ) ) ); } // adjust the alpha channel if ( src_alpha ) { // source image already has alpha information dest->SetAlpha(); // create an empty alpha channel (not initialized) dst_alpha = dest->GetAlpha(); wxCHECK_MSG( dst_alpha, NULL, wxT("unable to create alpha data") ); if ( factor_alpha == 1.0) { // no need to adjust memcpy(dst_alpha, src_alpha, alphalen); } else { // alpha value for alpha value for ( unsigned i = 0; i < alphalen; ++i ) { dst_alpha[i] = (byte) wxMin( 255, (int) (factor_alpha * src_alpha[i]) ); } } } else if ( factor_alpha != 1.0 ) { // no alpha yet but we want to adjust -> create dest->SetAlpha(); // create an empty alpha channel (not initialized) dst_alpha = dest->GetAlpha(); wxCHECK_MSG( dst_alpha, NULL, wxT("unable to create alpha data") ); for ( unsigned i = 0; i < alphalen; ++i ) { dst_alpha[i] = (byte) wxMin( 255, (int) (factor_alpha * 255) ); } } // do we have an alpha channel and a mask in the new image? if ( dst_alpha && dest->HasMask() ) { // make the mask transparent honoring the alpha channel const byte mr = dest->GetMaskRed(); const byte mg = dest->GetMaskGreen(); const byte mb = dest->GetMaskBlue(); for ( unsigned i = 0; i < alphalen; ++i ) { int n = i * 3; dst_alpha[i] = ( dst_data[n] == mr && dst_data[n + 1] == mg && dst_data[n + 2] == mb ) ? wxIMAGE_ALPHA_TRANSPARENT : dst_alpha[i]; } // remove the mask now dest->SetMask(false); } return dest;""", factory=True) c.addProperty('Width GetWidth') c.addProperty('Height GetHeight') c.addProperty('MaskBlue GetMaskBlue') c.addProperty('MaskGreen GetMaskGreen') c.addProperty('MaskRed GetMaskRed') c.addProperty('Type GetType SetType') # For compatibility: module.addPyFunction( 'EmptyImage', '(width=0, height=0, clear=True)', deprecated="Use :class:`Image` instead.", doc= 'A compatibility wrapper for the wx.Image(width, height) constructor', body='return Image(width, height, clear)') module.addPyFunction( 'ImageFromBitmap', '(bitmap)', deprecated="Use bitmap.ConvertToImage instead.", doc='Create a :class:`Image` from a :class:`wx.Bitmap`', body='return bitmap.ConvertToImage()') module.addPyFunction('ImageFromStream', '(stream, type=BITMAP_TYPE_ANY, index=-1)', deprecated="Use :class:`Image` instead.", doc='Load an image from a stream (file-like object)', body='return wx.Image(stream, type, index)') module.addPyFunction( 'ImageFromData', '(width, height, data)', deprecated="Use :class:`Image` instead.", doc='Compatibility wrapper for creating an image from RGB data', body='return Image(width, height, data)') module.addPyFunction( 'ImageFromDataWithAlpha', '(width, height, data, alpha)', deprecated="Use :class:`Image` instead.", doc= 'Compatibility wrapper for creating an image from RGB and Alpha data', body='return Image(width, height, data, alpha)') module.addPyFunction('ImageFromBuffer', '(width, height, dataBuffer, alphaBuffer=None)', doc="""\ Creates a :class:`Image` from the data in `dataBuffer`. The `dataBuffer` parameter must be a Python object that implements the buffer interface, such as a string, array, etc. The `dataBuffer` object is expected to contain a series of RGB bytes and be width*height*3 bytes long. A buffer object can optionally be supplied for the image's alpha channel data, and it is expected to be width*height bytes long. The :class:`Image` will be created with its data and alpha pointers initialized to the memory address pointed to by the buffer objects, thus saving the time needed to copy the image data from the buffer object to the :class:`Image`. While this has advantages, it also has the shoot-yourself-in-the-foot risks associated with sharing a C pointer between two objects. To help alleviate the risk a reference to the data and alpha buffer objects are kept with the :class:`Image`, so that they won't get deleted until after the wx.Image is deleted. However please be aware that it is not guaranteed that an object won't move its memory buffer to a new location when it needs to resize its contents. If that happens then the :class:`Image` will end up referring to an invalid memory location and could cause the application to crash. Therefore care should be taken to not manipulate the objects used for the data and alpha buffers in a way that would cause them to change size. """, body="""\ img = Image(width, height) img.SetDataBuffer(dataBuffer) if alphaBuffer: img.SetAlphaBuffer(alphaBuffer) img._buffer = dataBuffer img._alpha = alphaBuffer return img """) #------------------------------------------------------- c = module.find('wxImageHistogram') c.bases = [] # wxImageHistogramBase doesn't actually exist setParamsPyInt('MakeKey') c.find('FindFirstUnusedColour').type = 'void' c.find('FindFirstUnusedColour.r').pyInt = True c.find('FindFirstUnusedColour.g').pyInt = True c.find('FindFirstUnusedColour.b').pyInt = True c.find('FindFirstUnusedColour.startR').pyInt = True c.find('FindFirstUnusedColour.startG').pyInt = True c.find('FindFirstUnusedColour.startB').pyInt = True c.find('FindFirstUnusedColour.r').out = True c.find('FindFirstUnusedColour.g').out = True c.find('FindFirstUnusedColour.b').out = True #------------------------------------------------------- c = module.find('wxImageHandler') c.addPrivateCopyCtor() c.find('GetLibraryVersionInfo').ignore() c.find('DoGetImageCount').ignore(False) c.find('DoCanRead').ignore(False) #------------------------------------------------------- module.find('wxIMAGE_ALPHA_TRANSPARENT').pyInt = True module.find('wxIMAGE_ALPHA_OPAQUE').pyInt = True module.find('wxIMAGE_ALPHA_THRESHOLD').pyInt = True # These are defines for string objects, not integers, so we can't # generate code for them the same way as integer values. Since they are # #defines we can't just tell SIP that they are global wxString objects # because it will then end up taking the address of temporary values when # it makes the getters for them. So instead we'll just make some python # code to insert into the .py module and hope that the interface file # always has the correct values of these options. pycode = "" for item in module: if 'IMAGE_OPTION' in item.name and isinstance(item, etgtools.DefineDef): item.ignore() name = tools.removeWxPrefix(item.name) value = item.value for txt in ['wxString(', 'wxT(', ')']: value = value.replace(txt, '') pycode += '%s = %s\n' % (name, value) module.addPyCode(pycode) #----------------------------------------------------------------- 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. # These are duplicates, ignore the ones in this module module.find('wxPG_PROPERTYVALUES_FLAGS').ignore() module.find('wxPG_LABEL').ignore() module.find('wxPG_LABEL_STRING').ignore() module.find('wxPG_COLOUR_BLACK').ignore() module.find('wxPG_COLOUR').ignore() module.find('wxPG_DEFAULT_IMAGE_SIZE').ignore() #---------------------------------------------------------- c = module.find('wxPGPropArgCls') assert isinstance(c, etgtools.ClassDef) c.find('wxPGPropArgCls').findOverload('wxString &').ignore() c.find('wxPGPropArgCls').findOverload('char *').ignore() c.find('wxPGPropArgCls').findOverload('wchar_t *').ignore() c.find('wxPGPropArgCls').findOverload('int').ignore() c.find('wxPGPropArgCls').findOverload('deallocPtr').ignore() # Make a string ctor that uses the wxPython-specific version of # the C++ class' ctor newCtor = c.addCppCtor('(const wxString& str)', doc="Creates a PGPropArgCls from a string.", body="""\ wxString* name = new wxString(*str); return new wxPGPropArgCls(name, true); """) # Make it be the first overload instead of the last ctor = c.find('wxPGPropArgCls') overloads = list(ctor.overloads) del overloads[overloads.index(newCtor)] overloads.insert(0, newCtor) ctor.overloads = overloads c.find('GetPtr').overloads[0].ignore() c.convertFromPyObject = """\ // Code to test a PyObject for compatibility with wxPGPropArgCls if (!sipIsErr) { if (sipCanConvertToType(sipPy, sipType_wxPGPropArgCls, SIP_NO_CONVERTORS)) return TRUE; if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy)) return TRUE; if (sipPy == Py_None) return TRUE; if (sipCanConvertToType(sipPy, sipType_wxPGProperty, SIP_NO_CONVERTORS)) return TRUE; return FALSE; } // Code to convert a compatible PyObject to a wxPGPropArgCls if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy)) { wxString* name = new wxString(Py2wxString(sipPy)); *sipCppPtr = new wxPGPropArgCls(name, true); return sipGetState(sipTransferObj); } else if (sipCanConvertToType(sipPy, sipType_wxPGProperty, SIP_NO_CONVERTORS)) { int state = 0; wxPGProperty* prop = reinterpret_cast<wxPGProperty*>( sipConvertToType(sipPy, sipType_wxPGProperty, sipTransferObj, SIP_NO_CONVERTORS, &state, sipIsErr)); *sipCppPtr = new wxPGPropArgCls(prop); sipReleaseType(prop, sipType_wxPGProperty, state); return sipGetState(sipTransferObj); } else if (sipPy == Py_None) { *sipCppPtr = new wxPGPropArgCls(static_cast< wxPGProperty * >(NULL)); return sipGetState(sipTransferObj); } else { // It's already a wxPGPropArgCls, just fetch the pointer and return *sipCppPtr = reinterpret_cast<wxPGPropArgCls*>(sipConvertToType( sipPy, sipType_wxPGPropArgCls, sipTransferObj, SIP_NO_CONVERTORS, 0, sipIsErr)); return 0; // not a new instance } """ #---------------------------------------------------------- c = module.find('wxPropertyGridInterface') c.abstract = True for m in c.findAll('GetIterator'): if m.type == 'wxPropertyGridConstIterator': m.ignore() tools.ignoreConstOverloads(c) spv = c.find('SetPropertyValue') spv.findOverload('int value').ignore() spv.findOverload('wxLongLong value').ignore() spv.findOverload('wxLongLong_t value').ignore() spv.findOverload('wxULongLong value').ignore() spv.findOverload('wxULongLong_t value').ignore() spv.findOverload('wxObject *value').ignore() spv.findOverload('wchar_t *value').ignore() spv.findOverload('char *value').ignore() # Reorder SetPropertyValue overloads so the one taking a long int is not # first. Mark others that could be auto-converted from int as # "constrained" so they will only be used for that specific type. This # should result in SetPropertyValue(id, double) only used for floats and # not ints, or other things that can convert to int. spv.findOverload('bool value').find('value').constrained = True spv.findOverload('double value').find('value').constrained = True spv_long = spv.findOverload('long value') spv_long.ignore() spv.reorderOverloads() # Ensures an ignored item is not first, spv_long.ignore(False) # and then we can unignore it. c.find('Append.property').transfer = True c.find('AppendIn.newProperty').transfer = True for m in c.find('Insert').all(): m.find('newProperty').transfer = True # Fix some syntax that sip doesn't like p = c.find('GetPropertiesWithFlag.iterFlags') if p.default.startswith('('): p.default = p.default[1:-1] # Tons of Python method implementations ported from Classic... module.addPyCode("""\ _type2property = None _vt2getter = None """) c.addPyMethod('MapType', '(self, class_, factory)', doc="""\ Registers Python type/class to property mapping. :param `factory`: Property builder function/class. """, body="""\ global _type2property if _type2property is None: raise AssertionError("call only after a propertygrid or " "manager instance constructed") _type2property[class_] = factory """) c.addPyMethod('DoDefaultTypeMappings', '(self)', doc="Add built-in properties to the map.", body="""\ import sys global _type2property if _type2property is not None: return _type2property = dict() _type2property[str] = StringProperty if sys.version_info.major < 2: _type2property[unicode] = StringProperty _type2property[int] = IntProperty _type2property[float] = FloatProperty _type2property[bool] = BoolProperty _type2property[list] = ArrayStringProperty _type2property[tuple] = ArrayStringProperty _type2property[wx.Font] = FontProperty _type2property[wx.Colour] = ColourProperty #_type2property[wx.Size] = SizeProperty #_type2property[wx.Point] = PointProperty #_type2property[wx.FontData] = FontDataProperty """) # TODO: is this still needed? c.addPyMethod('DoDefaultValueTypeMappings', '(self)', doc="Map pg value type ids to getter methods.", body="""\ global _vt2getter if _vt2getter is not None: return _vt2getter = dict() """) c.find('GetPropertyValues').ignore() c.addPyMethod('GetPropertyValues', '(self, dict_=None, as_strings=False, inc_attributes=False)', doc="""\ Returns all property values in the grid.\n :param `dict_`: A to fill with the property values. If not given, then a new one is created. The dict_ can be an object as well, in which case it's __dict__ is used. :param `as_strings`: if True, then string representations of values are fetched instead of native types. Useful for config and such. :param `inc_attributes`: if True, then property attributes are added in the form of "@<propname>@<attr>". :returns: A dictionary with values. It is always a dictionary, so if dict_ was and object with __dict__ attribute, then that attribute is returned. """, body="""\ if dict_ is None: dict_ = {} elif hasattr(dict_,'__dict__'): dict_ = dict_.__dict__ getter = self.GetPropertyValue if not as_strings else self.GetPropertyValueAsString it = self.GetVIterator(PG_ITERATE_PROPERTIES) while not it.AtEnd(): p = it.GetProperty() name = p.GetName() dict_[name] = getter(p) if inc_attributes: attrs = p.GetAttributes() if attrs and len(attrs): dict_['@%s@attr'%name] = attrs it.Next() return dict_ """) for m in c.find('SetPropertyValues').all(): m.ignore() c.addPyMethod('SetPropertyValues', '(self, dict_, autofill=False)', doc="""\ Sets property values from a dictionary.\n :param `dict_`: the source of the property values to set, which can be either a dictionary or an object with a __dict__ attribute. :param `autofill`: If true, keys with not relevant properties are auto-created. For more info, see :method:`AutoFill`. :note: * Keys starting with underscore are ignored. * Attributes can be set with entries named like "@<propname>@<attr>". """, body="""\ if dict_ is None: dict_ = {} elif hasattr(dict_,'__dict__'): dict_ = dict_.__dict__ attr_dicts = [] def set_sub_obj(k0, dict_): for k,v in dict_.items(): if k[0] != '_': if k.endswith('@attr'): attr_dicts.append((k[1:-5],v)) else: try: self.SetPropertyValue(k,v) except: try: if autofill: self._AutoFillOne(k0,k,v) continue except: if isinstance(v,dict): set_sub_obj(k,v) elif hasattr(v,'__dict__'): set_sub_obj(k,v.__dict__) for k,v in attr_dicts: p = self.GetPropertyByName(k) if not p: raise AssertionError("No such property: '%s'"%k) for an,av in v.items(): p.SetAttribute(an, av) cur_page = False is_manager = isinstance(self, PropertyGridManager) try: set_sub_obj(self.GetGrid().GetRoot(), dict_) except: import traceback traceback.print_exc() self.Refresh() """) # TODO: should these be marked as deprecated? module.addPyCode("""\ PropertyGridInterface.GetValues = PropertyGridInterface.GetPropertyValues PropertyGridInterface.SetValues = PropertyGridInterface.SetPropertyValues """) c.addPyMethod('_AutoFillMany', '(self,cat,dict_)', body="""\ for k,v in dict_.items(): self._AutoFillOne(cat,k,v) """) c.addPyMethod('_AutoFillOne', '(self,cat,k,v)', body="""\ global _type2property factory = _type2property.get(v.__class__,None) if factory: self.AppendIn(cat, factory(k,k,v)) elif hasattr(v,'__dict__'): cat2 = self.AppendIn(cat, PropertyCategory(k)) self._AutoFillMany(cat2, v.__dict__) elif isinstance(v, dict): cat2 = self.AppendIn(cat, PropertyCategory(k)) self._AutoFillMany(cat2, v) elif not k.startswith('_'): raise AssertionError("member '%s' is of unregistered type/" "class '%s'"%(k,v.__class__)) """) c.addPyMethod('AutoFill', '(self, obj, parent=None)', doc="""\ "Clears properties and re-fills to match members and values of the given object or dictionary obj. """, body="""\ self.edited_objects[parent] = obj cur_page = False is_manager = isinstance(self, PropertyGridManager) if not parent: if is_manager: page = self.GetCurrentPage() page.Clear() parent = page.GetRoot() else: self.Clear() parent = self.GetGrid().GetRoot() else: it = self.GetIterator(PG_ITERATE_PROPERTIES, parent) it.Next() # Skip the parent while not it.AtEnd(): p = it.GetProperty() if not p.IsSomeParent(parent): break self.DeleteProperty(p) name = p.GetName() it.Next() if not is_manager or page == self.GetCurrentPage(): self.Freeze() cur_page = True try: self._AutoFillMany(parent,obj.__dict__) except: import traceback traceback.print_exc() if cur_page: self.Thaw() """) c.addPyMethod('RegisterEditor', '(self, editor, editorName=None)', doc="Register a new editor, either an instance or a class.", body="""\ if not isinstance(editor, PGEditor): editor = editor() if not editorName: editorName = editor.__class__.__name__ try: self._editor_instances.append(editor) except: self._editor_instances = [editor] return PropertyGrid.DoRegisterEditorClass(editor, editorName) """) c.find('GetPropertyClientData').ignore() c.addPyMethod('GetPropertyClientData', '(self, p)', body="""\ if isinstance(p, str): p = self.GetPropertyByName(p) return p.GetClientData() """) c.find('SetPropertyClientData').ignore() c.addPyMethod('SetPropertyClientData', '(self, p, data)', body="""\ if isinstance(p, str): p = self.GetPropertyByName(p) return p.SetClientData(data) """) c.addPyMethod('GetPyIterator', '(self, flags=PG_ITERATE_DEFAULT, firstProperty=None)', doc="""\ Returns a pythonic property iterator for a single :ref:`PropertyGrid` or page in :ref:`PropertyGridManager`. Arguments are same as for :ref:`GetIterator`. The following example demonstrates iterating absolutely all items in a single grid:: iterator = propGrid.GetPyIterator(wx.propgrid.PG_ITERATE_ALL) for prop in iterator: print(prop) :see: `wx.propgrid.PropertyGridInterface.Properties` `wx.propgrid.PropertyGridInterface.Items` """, body="""\ it = self.GetIterator(flags, firstProperty) while not it.AtEnd(): yield it.GetProperty() it.Next() """) c.addPyMethod('GetPyVIterator', '(self, flags=PG_ITERATE_DEFAULT)', doc="""\ Similar to :ref:`GetVIterator` but returns a pythonic iterator. """, body="""\ it = self.GetVIterator(flags) while not it.AtEnd(): yield it.GetProperty() it.Next() """) c.addPyMethod('_Properties', '(self)', doc="""\ This attribute is a pythonic iterator over all properties in this `PropertyGrid` property container. It will only skip categories and private child properties. Usage is simple:: for prop in propGrid.Properties: print(prop) :see: `wx.propgrid.PropertyGridInterface.Items` `wx.propgrid.PropertyGridInterface.GetPyIterator` """, body="""\ it = self.GetIterator(PG_ITERATE_NORMAL) while not it.AtEnd(): yield it.GetProperty() it.Next() """) c.addPyProperty('Properties', '_Properties') c.addPyMethod('_Items', '(self)', doc="""\ This attribute is a pythonic iterator over all items in this `PropertyGrid` property container, excluding only private child properties. Usage is simple:: for prop in propGrid.Items: print(prop) :see: `wx.propgrid.PropertyGridInterface.Properties` `wx.propgrid.PropertyGridInterface.GetPyVIterator` """, body="""\ it = self.GetVIterator(PG_ITERATE_NORMAL | PG_ITERATE_CATEGORIES) while not it.AtEnd(): yield it.GetProperty() it.Next() """) c.addPyProperty('Items', '_Items') #---------------------------------------------------------- module.addItem( tools.wxArrayPtrWrapperTemplate('wxArrayPGProperty', 'wxPGProperty', module)) # wxPGPropArg is a typedef for "const wxPGPropArgCls&" so having the # wrappers treat it as a normal type can be problematic. ("new cannot be # applied to a reference type", etc.) Let's just ignore it and replace it # everywhere for the real type. module.find('wxPGPropArg').ignore() for item in module.allItems(): if hasattr(item, 'type') and item.type == 'wxPGPropArg': item.type = 'const wxPGPropArgCls &' # Switch all wxVariant types to wxPGVariant, so the propgrid-specific # version of the MappedType will be used for converting to/from Python # objects. for item in module.allItems(): if hasattr(item, 'type') and 'wxVariant' in item.type: item.type = item.type.replace('wxVariant', 'wxPGVariant') #----------------------------------------------------------------- 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. c = module.find('wxPickerBase') assert isinstance(c, etgtools.ClassDef) c.find('CreateBase.id').default = 'wxID_ANY' c.find('GetTextCtrlStyle').ignore(False) c.find('GetPickerStyle').ignore(False) c.find('PostCreation').ignore(False) #----------------------------------------------------------------- module.addHeaderCode('#include <wx/clrpicker.h>') c = module.find('wxColourPickerCtrl') tools.fixWindowClass(c) module.addGlobalStr('wxColourPickerWidgetNameStr', c) module.addGlobalStr('wxColourPickerCtrlNameStr', c) c.addItem( etgtools.WigCode("""\ virtual void UpdatePickerFromTextCtrl(); virtual void UpdateTextCtrlFromPicker(); """)) c = module.find('wxColourPickerEvent') tools.fixEventClass(c) c.addPyCode("""\ EVT_COLOURPICKER_CHANGED = wx.PyEventBinder( wxEVT_COLOURPICKER_CHANGED, 1 ) # deprecated wxEVT alias wxEVT_COMMAND_COLOURPICKER_CHANGED = wxEVT_COLOURPICKER_CHANGED """) #----------------------------------------------------------------- module.addHeaderCode('#include <wx/filepicker.h>') c = module.find('wxFilePickerCtrl') tools.fixWindowClass(c) module.addGlobalStr('wxFilePickerWidgetLabel', c) module.addGlobalStr('wxFilePickerWidgetNameStr', c) module.addGlobalStr('wxFilePickerCtrlNameStr', c) module.addGlobalStr('wxFileSelectorPromptStr', c) module.addGlobalStr('wxFileSelectorDefaultWildcardStr', c) c.addItem( etgtools.WigCode("""\ virtual void UpdatePickerFromTextCtrl(); virtual void UpdateTextCtrlFromPicker(); """)) # we'll use the [G|S]etPath methods instead so we don't have to mess with wxFileName c.find('GetFileName').ignore() c.find('SetFileName').ignore() c = module.find('wxDirPickerCtrl') tools.fixWindowClass(c) module.addGlobalStr('wxDirPickerWidgetLabel', c) module.addGlobalStr('wxDirPickerWidgetNameStr', c) module.addGlobalStr('wxDirPickerCtrlNameStr', c) module.addGlobalStr('wxDirSelectorPromptStr', c) c.addItem( etgtools.WigCode("""\ virtual void UpdatePickerFromTextCtrl(); virtual void UpdateTextCtrlFromPicker(); """)) # we'll use the [G|S]etPath methods instead so we don't have to mess with wxFileName c.find('GetDirName').ignore() c.find('SetDirName').ignore() c = module.find('wxFileDirPickerEvent') tools.fixEventClass(c) c.addPyCode("""\ EVT_FILEPICKER_CHANGED = wx.PyEventBinder( wxEVT_FILEPICKER_CHANGED, 1 ) EVT_DIRPICKER_CHANGED = wx.PyEventBinder( wxEVT_DIRPICKER_CHANGED, 1 ) # deprecated wxEVT aliases wxEVT_COMMAND_FILEPICKER_CHANGED = wxEVT_FILEPICKER_CHANGED wxEVT_COMMAND_DIRPICKER_CHANGED = wxEVT_DIRPICKER_CHANGED """) #----------------------------------------------------------------- module.addHeaderCode('#include <wx/fontpicker.h>') c = module.find('wxFontPickerCtrl') tools.fixWindowClass(c) module.addGlobalStr('wxFontPickerWidgetNameStr', c) module.addGlobalStr('wxFontPickerCtrlNameStr', c) c.addItem( etgtools.WigCode("""\ virtual void UpdatePickerFromTextCtrl(); virtual void UpdateTextCtrlFromPicker(); """)) c = module.find('wxFontPickerEvent') tools.fixEventClass(c) c.addPyCode("""\ EVT_FONTPICKER_CHANGED = wx.PyEventBinder( wxEVT_FONTPICKER_CHANGED, 1 ) # deprecated wxEVT alias wxEVT_COMMAND_FONTPICKER_CHANGED = wxEVT_FONTPICKER_CHANGED """) #----------------------------------------------------------------- # The C++ wxColourPickerCtrl uses a wx.Button for the implementation, # but that looks and works very badly on Mac because the native # button can't change color. So for the Mac we'll implement our own # picker using a wx.BitmapButton instead. module.addPyCode("""\ if 'wxMac' in wx.PlatformInfo: class ColourPickerCtrl(PickerBase): ''' This control allows the user to select a colour. The implementation varies by platform but is usually a button which brings up a `wx.ColourDialog` when clicked. Window Styles ------------- ====================== ============================================ wx.CLRP_DEFAULT Default style. wx.CLRP_USE_TEXTCTRL Creates a text control to the left of the picker button which is completely managed by the `wx.ColourPickerCtrl` and which can be used by the user to specify a colour. The text control is automatically synchronized with the button's value. Use functions defined in `wx.PickerBase` to modify the text control. wx.CLRP_SHOW_LABEL Shows the colour in HTML form (AABBCC) as the colour button label (instead of no label at all). ====================== ============================================ Events ------ ======================== ========================================== EVT_COLOURPICKER_CHANGED The user changed the colour selected in the control either using the button or using the text control (see wx.CLRP_USE_TEXTCTRL; note that in this case the event is fired only if the user's input is valid, i.e. recognizable). ======================== ========================================== ''' # ColourData object to be shared by all colour pickers, so they can # share the custom colours _colourData = None #-------------------------------------------------- class ColourPickerButton(BitmapButton): def __init__(self, parent, id=-1, colour=wx.BLACK, pos=wx.DefaultPosition, size=wx.DefaultSize, style = CLRP_DEFAULT_STYLE, validator = wx.DefaultValidator, name = "colourpickerwidget"): wx.BitmapButton.__init__(self, parent, id, wx.Bitmap(1,1), pos, size, style, validator, name) self.SetColour(colour) self.InvalidateBestSize() self.SetInitialSize(size) self.Bind(wx.EVT_BUTTON, self.OnButtonClick) if ColourPickerCtrl._colourData is None: ColourPickerCtrl._colourData = wx.ColourData() ColourPickerCtrl._colourData.SetChooseFull(True) grey = 0 for i in range(16): c = wx.Colour(grey, grey, grey) ColourPickerCtrl._colourData.SetCustomColour(i, c) grey += 16 def SetColour(self, colour): # force a copy, in case the _colorData is shared self.colour = wx.Colour(colour) bmp = self._makeBitmap() self.SetBitmapLabel(bmp) def GetColour(self): return self.colour def OnButtonClick(self, evt): ColourPickerCtrl._colourData.SetColour(self.colour) dlg = wx.ColourDialog(self, ColourPickerCtrl._colourData) if dlg.ShowModal() == wx.ID_OK: ColourPickerCtrl._colourData = dlg.GetColourData() self.SetColour(ColourPickerCtrl._colourData.GetColour()) evt = wx.ColourPickerEvent(self, self.GetId(), self.GetColour()) self.GetEventHandler().ProcessEvent(evt) def _makeBitmap(self): width = height = 24 bg = self.GetColour() if self.HasFlag(CLRP_SHOW_LABEL): w, h = self.GetTextExtent(bg.GetAsString(wx.C2S_HTML_SYNTAX)) width += w bmp = wx.Bitmap(width, height) dc = wx.MemoryDC(bmp) dc.SetBackground(wx.Brush(self.colour)) dc.Clear() if self.HasFlag(CLRP_SHOW_LABEL): from wx.lib.colourutils import BestLabelColour fg = BestLabelColour(bg) dc.SetTextForeground(fg) dc.DrawText(bg.GetAsString(wx.C2S_HTML_SYNTAX), (width - w)/2, (height - h)/2) return bmp #-------------------------------------------------- def __init__(self, parent, id=-1, colour=wx.BLACK, pos=wx.DefaultPosition, size=wx.DefaultSize, style = CLRP_DEFAULT_STYLE, validator = wx.DefaultValidator, name = "colourpicker"): if type(colour) != wx.Colour: colour = wx.Colour(colour) wx.PickerBase.__init__(self) self.CreateBase(parent, id, colour.GetAsString(), pos, size, style, validator, name) widget = ColourPickerCtrl.ColourPickerButton( self, -1, colour, style=self.GetPickerStyle(style)) self.SetPickerCtrl(widget) widget.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnColourChange) self.PostCreation() def GetColour(self): '''Set the displayed colour.''' return self.GetPickerCtrl().GetColour() def SetColour(self, colour): '''Returns the currently selected colour.''' self.GetPickerCtrl().SetColour(colour) self.UpdateTextCtrlFromPicker() Colour = property(GetColour, SetColour) def UpdatePickerFromTextCtrl(self): col = wx.Colour(self.GetTextCtrl().GetValue()) if not col.IsOk(): return if self.GetColour() != col: self.GetPickerCtrl().SetColour(col) evt = wx.ColourPickerEvent(self, self.GetId(), self.GetColour()) self.GetEventHandler().ProcessEvent(evt) def UpdateTextCtrlFromPicker(self): if not self.GetTextCtrl(): return self.GetTextCtrl().SetValue(self.GetColour().GetAsString()) def GetPickerStyle(self, style): return style & CLRP_SHOW_LABEL def OnColourChange(self, evt): self.UpdateTextCtrlFromPicker() evt = wx.ColourPickerEvent(self, self.GetId(), self.GetColour()) self.GetEventHandler().ProcessEvent(evt) """) #----------------------------------------------------------------- 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. c = module.find('wxComboBox') assert isinstance(c, etgtools.ClassDef) tools.fixWindowClass(c) tools.fixTextClipboardMethods(c) c.find('wxComboBox').findOverload('wxString choices').ignore() c.find('wxComboBox').findOverload('wxArrayString').find( 'choices').default = 'wxArrayString()' c.find('wxComboBox').findOverload('wxArrayString').find( 'value').default = 'wxEmptyString' c.find('Create').findOverload('wxString choices').ignore() c.find('Create').findOverload('wxArrayString').find( 'choices').default = 'wxArrayString()' c.find('Create').findOverload('wxArrayString').find( 'value').default = 'wxEmptyString' # When the from,to are set as output parameters the overloaded methods # will be ambiguous, so let's give this one a new name. m = c.find('GetSelection').renameOverload('long *from, long *to', 'GetTextSelection') m.find('from').out = True m.find('to').out = True # For SetSelection we want to keep the existing method since it is # inherited from base classes and has no ambiguities, so just add a new # method for SetTextSelection instead of renaming. orig = c.find('SetSelection').findOverload('from') orig.find('from').name = 'from_' orig.find('to').name = 'to_' m = etgtools.CppMethodDef.FromMethod(orig) m.overloads = [] m.name = 'SetTextSelection' m.argsString = '(long from_, long to_)' m.body = "self->SetSelection(from_, to_);" c.insertItemAfter(c.find('SetSelection'), m) # The docs say to not use this one. c.find('IsEmpty').ignore() c.addPyCode( "ComboBox.SetMark = wx.deprecated(ComboBox.SetTextSelection, 'Use SetTextSelection instead.')" ) c.addPyCode( "ComboBox.GetMark = wx.deprecated(ComboBox.GetTextSelection, 'Use GetTextSelection instead.')" ) module.addGlobalStr('wxComboBoxNameStr', c) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxHtmlWinTagHandler') assert isinstance(c, etgtools.ClassDef) c.addCppMethod('wxHtmlWinParser*', 'GetParser', '()', body="return (wxHtmlWinParser*)self->GetParser();") c.addPrivateCopyCtor() c = module.find('wxHtmlWinParser') c.find('GetEncodingConverter').ignore() c.find('GetInputEncoding').ignore() c.find('GetOutputEncoding').ignore() c.find('SetInputEncoding').ignore() tools.fixHtmlSetFonts(c) c.find('AddModule').ignore() c.addItem(etgtools.WigCode("""\ virtual wxObject* GetProduct(); """)) module.addCppCode("""\ class wxPyHtmlTagsModule : public wxHtmlTagsModule { public: wxPyHtmlTagsModule(PyObject* thc) : wxHtmlTagsModule() { m_tagHandlerClass = thc; wxPyThreadBlocker blocker; Py_INCREF(m_tagHandlerClass); RegisterModule(this); wxHtmlWinParser::AddModule(this); } void OnExit() { wxPyThreadBlocker blocker; Py_DECREF(m_tagHandlerClass); m_tagHandlerClass = NULL; for (size_t x=0; x < m_objArray.GetCount(); x++) { PyObject* obj = (PyObject*)m_objArray.Item(x); Py_DECREF(obj); } } void FillHandlersTable(wxHtmlWinParser *parser) { wxPyThreadBlocker blocker; wxHtmlWinTagHandler* thPtr = 0; // First, make a new instance of the tag handler PyObject* arg = PyTuple_New(0); PyObject* obj = PyObject_CallObject(m_tagHandlerClass, arg); Py_DECREF(arg); // Make sure it succeeded if (!obj) { PyErr_Print(); return; } // now figure out where it's C++ object is... if (! wxPyConvertWrappedPtr(obj, (void **)&thPtr, wxT("wxHtmlWinTagHandler"))) { return; } // add it, parser->AddTagHandler(thPtr); // and track it. m_objArray.Add(obj); } private: PyObject* m_tagHandlerClass; wxArrayPtrVoid m_objArray; }; """) module.addCppFunction('void', 'HtmlWinParser_AddTagHandler', '(PyObject* tagHandlerClass)', body="""\ // Dynamically create a new wxModule. Refcounts tagHandlerClass // and adds itself to the wxModules list and to the wxHtmlWinParser. new wxPyHtmlTagsModule(tagHandlerClass); wxModule::InitializeModules(); """) #----------------------------------------------------------------- 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/treelist.h>') module.find('wxTreeListEventHandler').ignore() module.find('wxTreeListItems').ignore() #----------------------------------------------------------------- c = module.find('wxTreeListItem') assert isinstance(c, etgtools.ClassDef) c.addCppMethod('int', '__nonzero__', '()', """\ return self->IsOk(); """) #----------------------------------------------------------------- c = module.find('wxTreeListItemComparator') c.addPrivateCopyCtor() #----------------------------------------------------------------- c = module.find('wxTreeListCtrl') tools.fixWindowClass(c) module.addGlobalStr('wxTreeListCtrlNameStr', c) # Change NO_IMAGE default arg values to just -1, as the pi code has # problems when using the class name before the class is fully defined. for item in c.allItems(): if isinstance(item, etgtools.ParamDef) and item.default == 'NO_IMAGE': item.default = '-1' # transfer ownership of some parameters c.find('AssignImageList.imageList').transfer = True c.find('SetItemData.data').transfer = True c.find('AppendItem.data').transfer = True c.find('InsertItem.data').transfer = True c.find('PrependItem.data').transfer = True # Replace GetSelections with an implementation that returns a Python list c.find('GetSelections').ignore() c.addCppMethod('PyObject*', 'GetSelections', '()', doc="""\ Returns a list of all selected items. This method can be used in both single and multi-selection case.""", body="""\ unsigned count; wxTreeListItems items; count = self->GetSelections(items); wxPyThreadBlocker blocker; PyObject* list = PyList_New(count); for (size_t i=0; i<count; i++) { wxTreeListItem* item = new wxTreeListItem(items[i]); PyObject* obj = wxPyConstructObject((void*)item, wxT("wxTreeListItem"), true); PyList_SET_ITEM(list, i, obj); // PyList_SET_ITEM steals a reference } return list; """) # Set output parameter flags c.find('GetSortColumn.col').out = True c.find('GetSortColumn.ascendingOrder').out = True # Replace NO_IMAGE with wxTreeListCtrl::NO_IMAGE in parameter default values for item in c.allItems(): if isinstance(item, etgtools.ParamDef) and item.default == 'NO_IMAGE': item.default = 'wxTreeListCtrl::NO_IMAGE' #----------------------------------------------------------------- c = module.find('wxTreeListEvent') tools.fixEventClass(c) c.addPyCode("""\ EVT_TREELIST_SELECTION_CHANGED = wx.PyEventBinder( wxEVT_TREELIST_SELECTION_CHANGED ) EVT_TREELIST_ITEM_EXPANDING = wx.PyEventBinder( wxEVT_TREELIST_ITEM_EXPANDING ) EVT_TREELIST_ITEM_EXPANDED = wx.PyEventBinder( wxEVT_TREELIST_ITEM_EXPANDED ) EVT_TREELIST_ITEM_CHECKED = wx.PyEventBinder( wxEVT_TREELIST_ITEM_CHECKED ) EVT_TREELIST_ITEM_ACTIVATED = wx.PyEventBinder( wxEVT_TREELIST_ITEM_ACTIVATED ) EVT_TREELIST_ITEM_CONTEXT_MENU = wx.PyEventBinder( wxEVT_TREELIST_ITEM_CONTEXT_MENU ) EVT_TREELIST_COLUMN_SORTED = wx.PyEventBinder( wxEVT_TREELIST_COLUMN_SORTED ) # deprecated wxEVT aliases wxEVT_COMMAND_TREELIST_SELECTION_CHANGED = wxEVT_TREELIST_SELECTION_CHANGED wxEVT_COMMAND_TREELIST_ITEM_EXPANDING = wxEVT_TREELIST_ITEM_EXPANDING wxEVT_COMMAND_TREELIST_ITEM_EXPANDED = wxEVT_TREELIST_ITEM_EXPANDED wxEVT_COMMAND_TREELIST_ITEM_CHECKED = wxEVT_TREELIST_ITEM_CHECKED wxEVT_COMMAND_TREELIST_ITEM_ACTIVATED = wxEVT_TREELIST_ITEM_ACTIVATED wxEVT_COMMAND_TREELIST_ITEM_CONTEXT_MENU = wxEVT_TREELIST_ITEM_CONTEXT_MENU wxEVT_COMMAND_TREELIST_COLUMN_SORTED = wxEVT_TREELIST_COLUMN_SORTED """) #----------------------------------------------------------------- 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. # Add a ctor/factory for the Mac that can use the theme brush module.addCppCode("""\ #ifdef __WXMAC__ #include <wx/osx/private.h> #endif """) module.addCppFunction('wxColour*', 'MacThemeColour', '(int themeBrushID)', """\ #ifdef __WXMAC__ return new wxColour(wxMacCreateCGColorFromHITheme(themeBrushID)); #else wxPyRaiseNotImplemented(); return NULL; #endif """, factory=True) # Change this macro into a value so we wont have problems when SIP takes its # address module.addCppCode("""\ #undef wxTransparentColour wxColour wxTransparentColour(0, 0, 0, wxALPHA_TRANSPARENT); """) module.find('wxFromString').ignore() module.find('wxToString').ignore() module.find('wxALPHA_TRANSPARENT').type = 'const int' module.find('wxALPHA_OPAQUE').type = 'const int' c = module.find('wxColour') assert isinstance(c, etgtools.ClassDef) tools.removeVirtuals(c) # Just set mustHaveApp for the copy ctor as it may need to use the colour # database to look up color names. c.find('wxColour').findOverload('const wxColour &').mustHaveApp() # Hide the string ctor so our typemap will be invoked for the copy ctor instead. c.find('wxColour').findOverload('wxString').ignore() c.addProperty('Pixel GetPixel') c.addProperty('RGB GetRGB SetRGB') c.addProperty('RGBA GetRGBA SetRGBA') c.addProperty('red Red') c.addProperty('green Green') c.addProperty('blue Blue') c.addProperty('alpha Alpha') c.find('GetPixel').ignore() # We need to add a typcast c.addCppMethod( 'wxIntPtr*', 'GetPixel', '()', """\ #ifdef __WXGTK3__ return new wxIntPtr(0); #else return new wxIntPtr((wxIntPtr)self->GetPixel()); #endif """) # Set a flag on the return value and parameter types that are 'unsigned char' # such that they will be treated as an integer instead of a string. for item in c.allItems(): if hasattr(item, 'type') and item.type == 'unsigned char': item.pyInt = True c.find('ChangeLightness.r').inOut = True c.find('ChangeLightness.g').inOut = True c.find('ChangeLightness.b').inOut = True c.find('MakeDisabled.r').inOut = True c.find('MakeDisabled.g').inOut = True c.find('MakeDisabled.b').inOut = True c.find('MakeGrey.r').inOut = True c.find('MakeGrey.g').inOut = True c.find('MakeGrey.b').inOut = True c.find('MakeGrey').findOverload('double').find('r').inOut = True c.find('MakeGrey').findOverload('double').find('g').inOut = True c.find('MakeGrey').findOverload('double').find('b').inOut = True c.find('MakeMono.r').out = True c.find('MakeMono.g').out = True c.find('MakeMono.b').out = True # The stock Colour items are documented as simple pointers, but in # reality they are macros that evaluate to a function call that returns a # Colour pointer, and that is only valid *after* the wx.App object has # been created. That messes up the code that SIP generates for them. So # instead we will just create uninitialized colours in a block of Python # code, that will then be initialized later when the wx.App is created. c.addCppMethod('void', '_copyFrom', '(const wxColour* other)', "*self = *other;", briefDoc="For internal use only.") # ?? pycode = '# These stock colours will be initialized when the wx.App object is created.\n' for name in [ 'wxBLACK', 'wxBLUE', 'wxCYAN', 'wxGREEN', 'wxYELLOW', 'wxLIGHT_GREY', 'wxRED', 'wxWHITE', ]: item = module.find(name) item.ignore() pycode += '%s = Colour()\n' % tools.removeWxPrefix(item.name) module.addPyCode(pycode) c.addCppMethod('PyObject*', 'Get', '(bool includeAlpha=true)', """\ int red = -1; int green = -1; int blue = -1; int alpha = wxALPHA_OPAQUE; if (self->IsOk()) { red = self->Red(); green = self->Green(); blue = self->Blue(); alpha = self->Alpha(); } if (includeAlpha) return sipBuildResult(0, "(iiii)", red, green, blue, alpha); else return sipBuildResult(0, "(iii)", red, green, blue); """, pyArgsString="(includeAlpha=True) -> (r,g,b) or (r,g,b,a)", briefDoc="""\ Returns the RGB intensity values as a tuple, optionally the alpha value as well.""" ) tools.addGetIMMethodTemplate(module, c, ['red', 'green', 'blue', 'alpha']) # Add sequence protocol methods and other goodies c.addPyMethod('__str__', '(self)', 'return str(self.Get())') c.addPyMethod('__repr__', '(self)', 'return "wx.Colour"+str(self.Get())') c.addPyMethod('__len__', '(self)', 'return len(self.Get())') c.addPyMethod('__nonzero__', '(self)', 'return self.IsOk()') c.addPyMethod('__reduce__', '(self)', 'return (Colour, self.Get())') c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]') c.addPyMethod( '__setitem__', '(self, idx, val)', """\ if idx == 0: self.red = val elif idx == 1: self.green = val elif idx == 2: self.blue = val elif idx == 3: self.alpha = val else: raise IndexError """) c.addPyCode('Colour.__safe_for_unpickling__ = True') # Types that can be converted to wx.Colour: # wxColour (duh) # Sequence with 3 or 4 integers # String with color name or #RRGGBB or #RRGGBBAA format # None (converts to wxNullColour) c.allowNone = True c.convertFromPyObject = """\ // is it just a typecheck? if (!sipIsErr) { if (sipPy == Py_None) return 1; if (sipCanConvertToType(sipPy, sipType_wxColour, SIP_NO_CONVERTORS)) return 1; if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy)) return 1; if (wxPyNumberSequenceCheck(sipPy, 4) || wxPyNumberSequenceCheck(sipPy, 3)) { return 1; } return 0; } // otherwise do the conversion // is it None? if (sipPy == Py_None) { *sipCppPtr = new wxColour(wxNullColour); return sipGetState(sipTransferObj); } // Is it a string? else if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy)) { wxString spec = Py2wxString(sipPy); if (!spec.empty() && spec.GetChar(0) == '#' && (spec.length() == 7 || spec.length() == 9)) { // It's #RRGGBB[AA] long red, green, blue; red = green = blue = 0; spec.Mid(1,2).ToLong(&red, 16); spec.Mid(3,2).ToLong(&green, 16); spec.Mid(5,2).ToLong(&blue, 16); if (spec.length() == 7) // no alpha *sipCppPtr = new wxColour(red, green, blue); else { // yes alpha long alpha; spec.Mid(7,2).ToLong(&alpha, 16); *sipCppPtr = new wxColour(red, green, blue, alpha); } return sipGetState(sipTransferObj); } else { // assume it's a colour name // check if alpha is there too int pos; if (((pos = spec.Find(':', true)) != wxNOT_FOUND) && (pos == spec.length()-3)) { long alpha; spec.Right(2).ToLong(&alpha, 16); wxColour c = wxColour(spec.Left(spec.length()-3)); *sipCppPtr = new wxColour(c.Red(), c.Green(), c.Blue(), alpha); } else *sipCppPtr = new wxColour(spec); return sipGetState(sipTransferObj); } } // Is it a sequence? (if so then length was checked above) else if (wxPyNumberSequenceCheck(sipPy)) { size_t len = PySequence_Size(sipPy); PyObject* o1 = PySequence_ITEM(sipPy, 0); PyObject* o2 = PySequence_ITEM(sipPy, 1); PyObject* o3 = PySequence_ITEM(sipPy, 2); if (len == 3) *sipCppPtr = new wxColour(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2), wxPyInt_AsLong(o3)); else { PyObject* o4 = PySequence_ITEM(sipPy, 3); *sipCppPtr = new wxColour(wxPyInt_AsLong(o1), wxPyInt_AsLong(o2), wxPyInt_AsLong(o3), wxPyInt_AsLong(o4)); Py_DECREF(o4); } Py_DECREF(o1); Py_DECREF(o2); Py_DECREF(o3); return sipGetState(sipTransferObj); } // if we get this far then it must already be a wxColour instance *sipCppPtr = reinterpret_cast<wxColour*>(sipConvertToType( sipPy, sipType_wxColour, sipTransferObj, SIP_NO_CONVERTORS, 0, sipIsErr)); return 0; // not a new instance """ module.addPyCode( 'NamedColour = wx.deprecated(Colour, "Use Colour instead.")') # Just for TESTING, remove it later module.addCppCode("""\ wxColour testColourTypeMap(const wxColour& c) { return c; } """) module.addItem( etgtools.WigCode("""\ wxColour testColourTypeMap(const wxColour& c); """)) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. # These enums are declared in files that we will not be using because # wxPython does not need the classes that are in those files. So just # inject the enums here instead. from etgtools import EnumDef, EnumValueDef e = EnumDef(name='wxStreamError') e.items.extend([ EnumValueDef(name='wxSTREAM_NO_ERROR'), EnumValueDef(name='wxSTREAM_EOF'), EnumValueDef(name='wxSTREAM_WRITE_ERROR'), EnumValueDef(name='wxSTREAM_READ_ERROR'), ]) module.insertItem(0, e) e = EnumDef(name='wxSeekMode') e.items.extend([ EnumValueDef(name='wxFromStart'), EnumValueDef(name='wxFromCurrent'), EnumValueDef(name='wxFromEnd'), ]) module.insertItem(1, e) #----------------------------------------------------------------- c = module.find('wxStreamBase') assert isinstance(c, etgtools.ClassDef) c.abstract = True tools.removeVirtuals(c) c.find('operator!').ignore() #----------------------------------------------------------------- c = module.find('wxInputStream') c.abstract = True tools.removeVirtuals(c) # Include a C++ class that can wrap a Python file-like object so it can # be used as a wxInputStream c.includeCppCode('src/stream_input.cpp') # Use that class for the convert code c.convertFromPyObject = """\ // is it just a typecheck? if (!sipIsErr) { if (wxPyInputStream::Check(sipPy)) return 1; return 0; } // otherwise do the conversion *sipCppPtr = new wxPyInputStream(sipPy); return sipGetState(sipTransferObj); """ # Add Python file-like methods so a wx.InputStream can be used as if it # was any other Python file object. c.addCppMethod( 'void', 'seek', '(wxFileOffset offset, int whence=0)', """\ self->SeekI(offset, (wxSeekMode)whence); """) c.addCppMethod('wxFileOffset', 'tell', '()', """\ return self->TellI(); """) c.addCppMethod('void', 'close', '()', """\ // ignored for now """) c.addCppMethod('void', 'flush', '()', """\ // ignored for now """) c.addCppMethod('bool', 'eof', '()', """\ return self->Eof(); """) c.addCppCode("""\ // helper used by the read and readline methods to make a PyObject static PyObject* _makeReadBufObj(wxInputStream* self, wxMemoryBuffer& buf) { PyObject* obj = NULL; wxPyThreadBlocker blocker; wxStreamError err = self->GetLastError(); // error check if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) { PyErr_SetString(PyExc_IOError,"IOError in wxInputStream"); } else { // Return the data as a string object. TODO: Py3 obj = PyBytes_FromStringAndSize(buf, buf.GetDataLen()); } return obj; } """) c.addCppMethod( 'PyObject*', 'read', '()', """\ wxMemoryBuffer buf; const ulong BUFSIZE = 1024; // read while bytes are available on the stream while ( self->CanRead() ) { self->Read(buf.GetAppendBuf(BUFSIZE), BUFSIZE); buf.UngetAppendBuf(self->LastRead()); } return _makeReadBufObj(self, buf); """) c.addCppMethod( 'PyObject*', 'read', '(ulong size)', """\ wxMemoryBuffer buf; // Read only size number of characters self->Read(buf.GetWriteBuf(size), size); buf.UngetWriteBuf(self->LastRead()); return _makeReadBufObj(self, buf); """) c.addCppMethod( 'PyObject*', 'readline', '()', """\ wxMemoryBuffer buf; char ch = 0; // read until \\n while ((ch != '\\n') && (self->CanRead())) { ch = self->GetC(); buf.AppendByte(ch); } return _makeReadBufObj(self, buf); """) c.addCppMethod( 'PyObject*', 'readline', '(ulong size)', """\ wxMemoryBuffer buf; int i; char ch; // read until \\n or byte limit reached for (i=ch=0; (ch != '\\n') && (self->CanRead()) && (i < size); i++) { ch = self->GetC(); buf.AppendByte(ch); } return _makeReadBufObj(self, buf); """) c.addCppCode("""\ PyObject* _wxInputStream_readline(wxInputStream* self); // This does the real work of the readlines methods static PyObject* _readlinesHelper(wxInputStream* self, bool useSizeHint=false, ulong sizehint=0) { PyObject* pylist; // init list { wxPyThreadBlocker blocker; pylist = PyList_New(0); if (!pylist) { PyErr_NoMemory(); return NULL; } } // read sizehint bytes or until EOF ulong i; for (i=0; (self->CanRead()) && (useSizeHint || (i < sizehint));) { PyObject* s = _wxInputStream_readline(self); if (s == NULL) { wxPyThreadBlocker blocker; Py_DECREF(pylist); return NULL; } wxPyThreadBlocker blocker; PyList_Append(pylist, s); i += PyBytes_Size(s); } // error check wxStreamError err = self->GetLastError(); if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) { wxPyThreadBlocker blocker; Py_DECREF(pylist); PyErr_SetString(PyExc_IOError,"IOError in wxInputStream"); return NULL; } return pylist; } """) c.addCppMethod('PyObject*', 'readlines', '()', """\ return _readlinesHelper(self); """) c.addCppMethod( 'PyObject*', 'readlines', '(ulong sizehint)', """\ return _readlinesHelper(self, true, sizehint); """) #----------------------------------------------------------------- c = module.find('wxOutputStream') c.abstract = True tools.removeVirtuals(c) # Include a C++ class that can wrap a Python file-like object so it can # be used as a wxOutputStream c.includeCppCode('src/stream_output.cpp') # Use that class for the convert code c.convertFromPyObject = """\ // is it just a typecheck? if (!sipIsErr) { if (wxPyOutputStream::Check(sipPy)) return 1; return 0; } // otherwise do the conversion *sipCppPtr = new wxPyOutputStream(sipPy); return sipGetState(sipTransferObj); """ # Add Python file-like methods so a wx.OutputStream can be used as if it # was any other Python file object. c.addCppMethod( 'void', 'seek', '(wxFileOffset offset, int whence=0)', """\ self->SeekO(offset, (wxSeekMode)whence); """) c.addCppMethod('wxFileOffset', 'tell', '()', """\ return self->TellO(); """) c.addCppMethod('void', 'close', '()', """\ self->Close(); """) c.addCppMethod('void', 'flush', '()', """\ self->Sync(); """) c.addCppMethod('bool', 'eof', '()', """\ return false; //self->Eof(); """) c.addCppMethod( 'PyObject*', 'write', '(PyObject* data)', """\ // We use only bytes objects (strings in 2.7) for the streams, never unicode wxPyThreadBlocker blocker; if (!PyBytes_Check(data)) { PyErr_SetString(PyExc_TypeError, "Bytes object expected"); return NULL; } self->Write(PyBytes_AS_STRING(data), PyBytes_GET_SIZE(data)); RETURN_NONE(); """) # TODO: Add a writelines(sequence) method #----------------------------------------------------------------- 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. c = module.find('wxWizardPage') assert isinstance(c, etgtools.ClassDef) tools.fixWindowClass(c, False) module.addPyCode( "PyWizardPage = wx.deprecated(WizardPage, 'Use WizardPage instead.')") c = module.find('wxWizardPageSimple') tools.fixWindowClass(c, False) c.addItem( etgtools.WigCode("""\ virtual wxWizardPage* GetNext() const; virtual wxWizardPage* GetPrev() const; """)) c = module.find('wxWizard') tools.fixWindowClass(c, False) # ShowPage is undocumented and labeled "implementation only" but it seems # too useful to ignore, so add a MethodDef for it here. m = MethodDef(name='ShowPage', type='bool', isVirtual=True, briefDoc="Show the given wizard page.", detailedDoc=[ """\ Calls TransferDataFromWindow on the current page first, and returns false without changing the page if it returned false. Returns True/False to indicate if the page was actually changed.""" ], items=[ ParamDef(name='page', type='wxWizardPage*'), ParamDef(name='goingForward', type='bool', default='true') ]) c.addItem(m) # Same for IsRunning m = MethodDef(name='IsRunning', type='bool', isConst=True) c.addItem(m) c = module.find('wxWizardEvent') tools.fixEventClass(c) module.addPyCode("""\ EVT_WIZARD_BEFORE_PAGE_CHANGED = wx.PyEventBinder( wxEVT_WIZARD_BEFORE_PAGE_CHANGED, 1) EVT_WIZARD_PAGE_CHANGED = wx.PyEventBinder( wxEVT_WIZARD_PAGE_CHANGED, 1) EVT_WIZARD_PAGE_CHANGING = wx.PyEventBinder( wxEVT_WIZARD_PAGE_CHANGING, 1) EVT_WIZARD_CANCEL = wx.PyEventBinder( wxEVT_WIZARD_CANCEL, 1) EVT_WIZARD_HELP = wx.PyEventBinder( wxEVT_WIZARD_HELP, 1) EVT_WIZARD_FINISHED = wx.PyEventBinder( wxEVT_WIZARD_FINISHED, 1) EVT_WIZARD_PAGE_SHOWN = wx.PyEventBinder( wxEVT_WIZARD_PAGE_SHOWN, 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) module.check4unittest = False #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. module.addHeaderCode('#include <wxpy_api.h>') module.addImport('_core') module.addPyCode('import wx', order=10) module.addInclude(INCLUDES) #----------------------------------------------------------------- module.addHeaderCode('#include <wx/glcanvas.h>') c = module.find('wxGLContext') assert isinstance(c, etgtools.ClassDef) c.mustHaveApp() c.addPrivateCopyCtor() c = module.find('wxGLCanvas') tools.fixWindowClass(c) # We already have a MappedType for wxArrayInt, so just tweak the # interfaces to use that instead of a const int pointer. c.find('wxGLCanvas').ignore() m = c.addCppCtor_sip( argsString="""( wxWindow* parent, wxWindowID id=wxID_ANY, wxArrayInt* attribList=NULL, const wxPoint& pos=wxDefaultPosition, const wxSize& size=wxDefaultSize, long style=0, const wxString& name="GLCanvas", const wxPalette& palette=wxNullPalette)""", cppSignature="""( wxWindow* parent, wxWindowID id=wxID_ANY, const int* attribList=NULL, const wxPoint& pos=wxDefaultPosition, const wxSize& size=wxDefaultSize, long style=0, const wxString& name="GLCanvas", const wxPalette& palette=wxNullPalette)""", pyArgsString= "(parent, id=wx.ID_ANY, attribList=None, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, name='GLCanvas', palette=wx.NullPalette)", body="""\ const int* attribPtr = NULL; if (attribList) { attribList->push_back(0); // ensure it is zero-terminated attribPtr = &attribList->front(); } sipCpp = new sipwxGLCanvas(parent, id, attribPtr, *pos, *size, style, *name, *palette); """, noDerivedCtor=False, ) m = c.find('IsDisplaySupported') m.find('attribList').type = 'wxArrayInt*' m.setCppCode_sip("""\ const int* attribPtr = NULL; if (attribList) { attribList->push_back(0); // ensure it is zero-terminated attribPtr = &attribList->front(); } sipRes = wxGLCanvas::IsDisplaySupported(attribPtr); """) #----------------------------------------------------------------- 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) module.check4unittest = False #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. module.addHeaderCode('#include <wxpy_api.h>') module.addImport('_core') module.addPyCode('''\ import wx ID_ANY = wx.ID_ANY # Needed for some parameter defaults in this module ''', order=10) module.addInclude(INCLUDES) #----------------------------------------------------------------- module.addHeaderCode('#include <wx/stc/stc.h>') module.addHeaderCode('#include "wxpybuffer.h"') c = module.find('wxStyledTextCtrl') assert isinstance(c, etgtools.ClassDef) c.bases = ['wxControl'] # wxTextCtrlIface is also a base... c.piBases = ['wx.Control', 'wx.TextEntry'] tools.fixWindowClass(c, False) module.addGlobalStr('wxSTCNameStr', c) c.find('GetCurLine.linePos').out = True c.find('GetCurLineRaw.linePos').out = True for name in ['Remove', 'Replace', 'SetSelection', 'GetSelection']: m = c.find(name) m.find('from').name = 'from_' m.find('to').name = 'to_' c.find('GetSelection.from_').out = True c.find('GetSelection.to_').out = True c.find('PositionToXY.x').out = True c.find('PositionToXY.y').out = True # Split the HitTest overloads into separately named methods since once # the output parameters are applied they will have the same function # signature. ht1 = c.find('HitTest') ht2 = ht1.overloads[0] ht1.overloads = [] c.insertItemAfter(ht1, ht2) ht1.pyName = 'HitTestPos' ht1.find('pos').out = True ht2.find('row').out = True ht2.find('col').out = True # Replace the *Pointer methods with ones that return a memoryview object instead. c.find('GetCharacterPointer').ignore() c.addCppMethod('PyObject*', 'GetCharacterPointer', '()', doc="""\ Compact the document buffer and return a read-only memoryview object of the characters in the document.""", body=""" const char* ptr = self->GetCharacterPointer(); Py_ssize_t len = self->GetLength(); PyObject* rv; wxPyBLOCK_THREADS( rv = wxPyMakeBuffer((void*)ptr, len, true) ); return rv; """) c.find('GetRangePointer').ignore() c.addCppMethod('PyObject*', 'GetRangePointer', '(int position, int rangeLength)', doc="""\ Return a read-only pointer to a range of characters in the document. May move the gap so that the range is contiguous, but will only move up to rangeLength bytes.""", body=""" const char* ptr = self->GetRangePointer(position, rangeLength); Py_ssize_t len = rangeLength; PyObject* rv; wxPyBLOCK_THREADS( rv = wxPyMakeBuffer((void*)ptr, len, true) ); return rv; """) # Generate the code for this differently because it needs to be # forcibly mashed into an int in the C code module.find('wxSTC_MASK_FOLDERS').forcedInt = True # Make sure that all the methods from wxTextEntry and wxTextCtrl are # included. This is needed because we are pretending that this class only # derives from wxControl but the real C++ class also derives from # wxTextCtrlIface which derives from wxTextEntryBase. import textentry mod = textentry.parseAndTweakModule() klass = mod.find('wxTextEntry') items = [ item for item in klass.items if isinstance(item, etgtools.MethodDef) and not item.isCtor and not item.isDtor and not c.findItem(item.name) ] c.items.extend(items) import textctrl mod = textctrl.parseAndTweakModule() klass = mod.find('wxTextCtrl') items = [ item for item in klass.items if isinstance(item, etgtools.MethodDef) and not item.isCtor and not item.isDtor and not c.findItem(item.name) ] c.items.extend(items) c.find('EmulateKeyPress').ignore() c.find('IsMultiLine').ignore() c.find('IsSingleLine').ignore() c.find('MacCheckSpelling').ignore() c.find('ShowNativeCaret').ignore() c.find('HideNativeCaret').ignore() # Change the *RGBAImage methods to accept any buffer object c.find('MarkerDefineRGBAImage').ignore() c.addCppMethod('void', 'MarkerDefineRGBAImage', '(int markerNumber, wxPyBuffer* pixels)', doc="""\ Define a marker from RGBA data.\n It has the width and height from RGBAImageSetWidth/Height. You must ensure that the buffer is at least width*height*4 bytes long. """, body="""\ self->MarkerDefineRGBAImage(markerNumber, (unsigned char*)pixels->m_ptr); """) c.find('RegisterRGBAImage').ignore() c.addCppMethod('void', 'RegisterRGBAImage', '(int type, wxPyBuffer* pixels)', doc="""\ Register an RGBA image for use in autocompletion lists.\n It has the width and height from RGBAImageSetWidth/Height. You must ensure that the buffer is at least width*height*4 bytes long. """, body="""\ self->RegisterRGBAImage(type, (unsigned char*)pixels->m_ptr); """) # TODO: Add the UTF8 PyMethods from classic (see _stc_utf8_methods.py) #----------------------------------------------------------------- c = module.find('wxStyledTextEvent') tools.fixEventClass(c) module.addPyCode("""\ EVT_STC_CHANGE = wx.PyEventBinder( wxEVT_STC_CHANGE, 1 ) EVT_STC_STYLENEEDED = wx.PyEventBinder( wxEVT_STC_STYLENEEDED, 1 ) EVT_STC_CHARADDED = wx.PyEventBinder( wxEVT_STC_CHARADDED, 1 ) EVT_STC_SAVEPOINTREACHED = wx.PyEventBinder( wxEVT_STC_SAVEPOINTREACHED, 1 ) EVT_STC_SAVEPOINTLEFT = wx.PyEventBinder( wxEVT_STC_SAVEPOINTLEFT, 1 ) EVT_STC_ROMODIFYATTEMPT = wx.PyEventBinder( wxEVT_STC_ROMODIFYATTEMPT, 1 ) EVT_STC_KEY = wx.PyEventBinder( wxEVT_STC_KEY, 1 ) EVT_STC_DOUBLECLICK = wx.PyEventBinder( wxEVT_STC_DOUBLECLICK, 1 ) EVT_STC_UPDATEUI = wx.PyEventBinder( wxEVT_STC_UPDATEUI, 1 ) EVT_STC_MODIFIED = wx.PyEventBinder( wxEVT_STC_MODIFIED, 1 ) EVT_STC_MACRORECORD = wx.PyEventBinder( wxEVT_STC_MACRORECORD, 1 ) EVT_STC_MARGINCLICK = wx.PyEventBinder( wxEVT_STC_MARGINCLICK, 1 ) EVT_STC_NEEDSHOWN = wx.PyEventBinder( wxEVT_STC_NEEDSHOWN, 1 ) EVT_STC_PAINTED = wx.PyEventBinder( wxEVT_STC_PAINTED, 1 ) EVT_STC_USERLISTSELECTION = wx.PyEventBinder( wxEVT_STC_USERLISTSELECTION, 1 ) EVT_STC_URIDROPPED = wx.PyEventBinder( wxEVT_STC_URIDROPPED, 1 ) EVT_STC_DWELLSTART = wx.PyEventBinder( wxEVT_STC_DWELLSTART, 1 ) EVT_STC_DWELLEND = wx.PyEventBinder( wxEVT_STC_DWELLEND, 1 ) EVT_STC_START_DRAG = wx.PyEventBinder( wxEVT_STC_START_DRAG, 1 ) EVT_STC_DRAG_OVER = wx.PyEventBinder( wxEVT_STC_DRAG_OVER, 1 ) EVT_STC_DO_DROP = wx.PyEventBinder( wxEVT_STC_DO_DROP, 1 ) EVT_STC_ZOOM = wx.PyEventBinder( wxEVT_STC_ZOOM, 1 ) EVT_STC_HOTSPOT_CLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_CLICK, 1 ) EVT_STC_HOTSPOT_DCLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_DCLICK, 1 ) EVT_STC_HOTSPOT_RELEASE_CLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_RELEASE_CLICK, 1 ) EVT_STC_CALLTIP_CLICK = wx.PyEventBinder( wxEVT_STC_CALLTIP_CLICK, 1 ) EVT_STC_AUTOCOMP_SELECTION = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_SELECTION, 1 ) EVT_STC_INDICATOR_CLICK = wx.PyEventBinder( wxEVT_STC_INDICATOR_CLICK, 1 ) EVT_STC_INDICATOR_RELEASE = wx.PyEventBinder( wxEVT_STC_INDICATOR_RELEASE, 1 ) EVT_STC_AUTOCOMP_CANCELLED = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_CANCELLED, 1 ) EVT_STC_AUTOCOMP_CHAR_DELETED = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_CHAR_DELETED, 1 ) EVT_STC_CLIPBOARD_COPY = wx.PyEventBinder( wxEVT_STC_CLIPBOARD_COPY, 1) EVT_STC_CLIPBOARD_PASTE = wx.PyEventBinder( wxEVT_STC_CLIPBOARD_PASTE, 1) EVT_STC_AUTOCOMP_COMPLETED = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_COMPLETED, 1) EVT_STC_MARGIN_RIGHT_CLICK = wx.PyEventBinder( wxEVT_STC_MARGIN_RIGHT_CLICK, 1) """) #----------------------------------------------------------------- # Keep some of the old names module.addPyCode("""\ # compatibility aliases STC_SCMOD_NORM = STC_KEYMOD_NORM STC_SCMOD_SHIFT = STC_KEYMOD_SHIFT STC_SCMOD_CTRL = STC_KEYMOD_CTRL STC_SCMOD_ALT = STC_KEYMOD_ALT STC_SCMOD_SUPER = STC_KEYMOD_SUPER STC_SCMOD_META = STC_KEYMOD_META """) #----------------------------------------------------------------- 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, check4unittest=False) # all classes abstract, no unitests needed etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxItemContainerImmutable') c.abstract = True c = module.find('wxItemContainer') assert isinstance(c, etgtools.ClassDef) c.abstract = True # Ignore the Append and Insert method overloads that we don't want to # support. This will keep the ones that take a wxString or an # wxArrayString, and wxClientData. def pickOverloads(m): assert isinstance(m, etgtools.MethodDef) if 'void *' in m.argsString or \ 'wxClientData **' in m.argsString or \ 'wxString *' in m.argsString or \ 'std::vector' in m.argsString: m.ignore() for m in c.findAll('Append'): pickOverloads(m) for m in c.findAll('Insert'): pickOverloads(m) for m in c.findAll('Set'): pickOverloads(m) # The [G|S]etClientData methods deal with untyped void* values, which we # don't support. The [G|S]etClientObject methods use wxClientData instaces # which we have a MappedType for, so make the ClientData methods just be # aliases for ClientObjects. From the Python programmer's perspective they # would be virtually the same anyway. c.find('SetClientObject.data').transfer = True c.find('GetClientData').ignore() c.find('SetClientData').ignore() c.find('GetClientObject').pyName = 'GetClientData' c.find('SetClientObject').pyName = 'SetClientData' c.addPyMethod('GetClientObject', '(self, n)', doc="Alias for :meth:`GetClientData`", body="return self.GetClientData(n)") c.addPyMethod('SetClientObject', '(self, n, data)', doc="Alias for :meth:`SetClientData`", body="self.SetClientData(n, data)") # Deal with transfering ownership of wxClientData objects c.find('DetachClientObject').transfer = True c.find('SetClientObject.data').transfer = True c.find('Append').findOverload('clientData').find( 'clientData').transfer = True c.find('Insert').findOverload('clientData').find( 'clientData').transfer = True # for compatibility, should they be deprecated? c.addPyMethod('AppendItems', '(self, items)', 'self.Append(items)') c.addPyMethod('GetItems', '(self)', 'return self.GetStrings()') c.addPyMethod('SetItems', '(self, items)', 'self.Set(items)') c = module.find('wxControlWithItems') c.abstract = 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. #------------------------------------------------------- c = module.find('wxTreeItemId') assert isinstance(c, etgtools.ClassDef) c.addCppMethod('int', '__nonzero__', '()', """\ return self->IsOk(); """) td = etgtools.TypedefDef(name='wxTreeItemIdValue', type='void*') module.insertItemBefore(c, td) #------------------------------------------------------- module.addPyCode("""\ def TreeItemData(data): return data TreeItemData = deprecated(TreeItemData, "The TreeItemData class no longer exists, just pass your object directly to the tree instead.") """) #------------------------------------------------------- c = module.find('wxTreeCtrl') tools.fixWindowClass(c) module.addGlobalStr('wxTreeCtrlNameStr', before=c) # Set all wxTreeItemData parameters to transfer ownership. Is this still needed with MappedTypes? for item in c.allItems(): if hasattr(item, 'type') and item.type == 'wxTreeItemData *' and \ isinstance(item, etgtools.ParamDef): item.transfer = True c.addPyCode("""\ TreeCtrl.GetItemPyData = wx.deprecated(TreeCtrl.GetItemData, 'Use GetItemData instead.') TreeCtrl.SetItemPyData = wx.deprecated(TreeCtrl.SetItemData, 'Use SetItemData instead.') TreeCtrl.GetPyData = wx.deprecated(TreeCtrl.GetItemData, 'Use GetItemData instead.') TreeCtrl.SetPyData = wx.deprecated(TreeCtrl.SetItemData, 'Use SetItemData instead.') """) # We can't use wxClassInfo c.find('EditLabel.textCtrlClass').ignore() # Replace GetSelections with a method that returns a Python list # size_t GetSelections(wxArrayTreeItemIds& selection) const; c.find('GetSelections').ignore() c.addCppMethod( 'PyObject*', 'GetSelections', '()', doc= 'Returns a list of currently selected items in the tree. This function ' 'can be called only if the control has the wx.TR_MULTIPLE style.', body="""\ wxPyThreadBlocker blocker; PyObject* rval = PyList_New(0); wxArrayTreeItemIds array; size_t num, x; num = self->GetSelections(array); for (x=0; x < num; x++) { wxTreeItemId *tii = new wxTreeItemId(array.Item(x)); PyObject* item = wxPyConstructObject((void*)tii, wxT("wxTreeItemId"), true); PyList_Append(rval, item); Py_DECREF(item); } return rval; """) # Change GetBoundingRect to return the rectangle instead of modifying the parameter. #bool GetBoundingRect(const wxTreeItemId& item, wxRect& rect, bool textOnly = false) const; c.find('GetBoundingRect').ignore() c.addCppMethod('PyObject*', 'GetBoundingRect', '(const wxTreeItemId& item, bool textOnly=false)', doc="""\ Returns the rectangle bounding the item. If textOnly is true, only the rectangle around the item's label will be returned, otherwise the item's image is also taken into account. The return value may be None if the rectangle was not successfully retrieved, such as if the item is currently not visible. """, isFactory=True, body="""\ wxRect rect; if (self->GetBoundingRect(*item, rect, textOnly)) { wxPyThreadBlocker blocker; wxRect* r = new wxRect(rect); PyObject* val = wxPyConstructObject((void*)r, wxT("wxRect"), true); return val; } else RETURN_NONE(); """) # switch the virtualness back on for those methods that need to have it. c.find('OnCompareItems').isVirtual = True # transfer imagelist ownership c.find('AssignImageList.imageList').transfer = True c.find('AssignStateImageList.imageList').transfer = True c.find('AssignButtonsImageList.imageList').transfer = True # Make the cookie values be returned, instead of setting it through the parameter c.find('GetFirstChild.cookie').out = True c.find('GetNextChild.cookie').inOut = True # TODO: These don't exist on MSW, Are they important enough that we # should provide them for the other platforms anyway? c.find('AssignButtonsImageList').ignore() c.find('GetButtonsImageList').ignore() c.find('SetButtonsImageList').ignore() #------------------------------------------------------- c = module.find('wxTreeEvent') tools.fixEventClass(c) c.addPyCode("""\ EVT_TREE_BEGIN_DRAG = PyEventBinder(wxEVT_TREE_BEGIN_DRAG , 1) EVT_TREE_BEGIN_RDRAG = PyEventBinder(wxEVT_TREE_BEGIN_RDRAG , 1) EVT_TREE_BEGIN_LABEL_EDIT = PyEventBinder(wxEVT_TREE_BEGIN_LABEL_EDIT , 1) EVT_TREE_END_LABEL_EDIT = PyEventBinder(wxEVT_TREE_END_LABEL_EDIT , 1) EVT_TREE_DELETE_ITEM = PyEventBinder(wxEVT_TREE_DELETE_ITEM , 1) EVT_TREE_GET_INFO = PyEventBinder(wxEVT_TREE_GET_INFO , 1) EVT_TREE_SET_INFO = PyEventBinder(wxEVT_TREE_SET_INFO , 1) EVT_TREE_ITEM_EXPANDED = PyEventBinder(wxEVT_TREE_ITEM_EXPANDED , 1) EVT_TREE_ITEM_EXPANDING = PyEventBinder(wxEVT_TREE_ITEM_EXPANDING , 1) EVT_TREE_ITEM_COLLAPSED = PyEventBinder(wxEVT_TREE_ITEM_COLLAPSED , 1) EVT_TREE_ITEM_COLLAPSING = PyEventBinder(wxEVT_TREE_ITEM_COLLAPSING , 1) EVT_TREE_SEL_CHANGED = PyEventBinder(wxEVT_TREE_SEL_CHANGED , 1) EVT_TREE_SEL_CHANGING = PyEventBinder(wxEVT_TREE_SEL_CHANGING , 1) EVT_TREE_KEY_DOWN = PyEventBinder(wxEVT_TREE_KEY_DOWN , 1) EVT_TREE_ITEM_ACTIVATED = PyEventBinder(wxEVT_TREE_ITEM_ACTIVATED , 1) EVT_TREE_ITEM_RIGHT_CLICK = PyEventBinder(wxEVT_TREE_ITEM_RIGHT_CLICK , 1) EVT_TREE_ITEM_MIDDLE_CLICK = PyEventBinder(wxEVT_TREE_ITEM_MIDDLE_CLICK, 1) EVT_TREE_END_DRAG = PyEventBinder(wxEVT_TREE_END_DRAG , 1) EVT_TREE_STATE_IMAGE_CLICK = PyEventBinder(wxEVT_TREE_STATE_IMAGE_CLICK, 1) EVT_TREE_ITEM_GETTOOLTIP = PyEventBinder(wxEVT_TREE_ITEM_GETTOOLTIP, 1) EVT_TREE_ITEM_MENU = PyEventBinder(wxEVT_TREE_ITEM_MENU, 1) # deprecated wxEVT aliases wxEVT_COMMAND_TREE_BEGIN_DRAG = wxEVT_TREE_BEGIN_DRAG wxEVT_COMMAND_TREE_BEGIN_RDRAG = wxEVT_TREE_BEGIN_RDRAG wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT = wxEVT_TREE_BEGIN_LABEL_EDIT wxEVT_COMMAND_TREE_END_LABEL_EDIT = wxEVT_TREE_END_LABEL_EDIT wxEVT_COMMAND_TREE_DELETE_ITEM = wxEVT_TREE_DELETE_ITEM wxEVT_COMMAND_TREE_GET_INFO = wxEVT_TREE_GET_INFO wxEVT_COMMAND_TREE_SET_INFO = wxEVT_TREE_SET_INFO wxEVT_COMMAND_TREE_ITEM_EXPANDED = wxEVT_TREE_ITEM_EXPANDED wxEVT_COMMAND_TREE_ITEM_EXPANDING = wxEVT_TREE_ITEM_EXPANDING wxEVT_COMMAND_TREE_ITEM_COLLAPSED = wxEVT_TREE_ITEM_COLLAPSED wxEVT_COMMAND_TREE_ITEM_COLLAPSING = wxEVT_TREE_ITEM_COLLAPSING wxEVT_COMMAND_TREE_SEL_CHANGED = wxEVT_TREE_SEL_CHANGED wxEVT_COMMAND_TREE_SEL_CHANGING = wxEVT_TREE_SEL_CHANGING wxEVT_COMMAND_TREE_KEY_DOWN = wxEVT_TREE_KEY_DOWN wxEVT_COMMAND_TREE_ITEM_ACTIVATED = wxEVT_TREE_ITEM_ACTIVATED wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK = wxEVT_TREE_ITEM_RIGHT_CLICK wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK = wxEVT_TREE_ITEM_MIDDLE_CLICK wxEVT_COMMAND_TREE_END_DRAG = wxEVT_TREE_END_DRAG wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK = wxEVT_TREE_STATE_IMAGE_CLICK wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP = wxEVT_TREE_ITEM_GETTOOLTIP wxEVT_COMMAND_TREE_ITEM_MENU = wxEVT_TREE_ITEM_MENU """) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. c = module.find('wxSizerItem') assert isinstance(c, etgtools.ClassDef) tools.removeVirtuals(c) # ctors taking a sizer transfer ownership for m in c.find('wxSizerItem').all(): if m.findItem('sizer'): m.find('sizer').transfer = True c.find('AssignSizer.sizer').transfer = True # userData args transfer ownership too, and we'll use wxPyUserData # instead of any wxObject for m in c.allItems(): if isinstance(m, etgtools.MethodDef) and m.findItem('userData'): m.find('userData').transfer = True m.find('userData').type = 'wxPyUserData*' gud = c.find('GetUserData') gud.type = 'wxPyUserData*' gud.setCppCode('return dynamic_cast<wxPyUserData*>(self->GetUserData());') # these have been deprecated for a while so go ahead and get rid of them c.find('SetWindow').ignore() c.find('SetSizer').ignore() c.find('SetSpacer').ignore() c.addPrivateCopyCtor() #--------------------------------------------- c = module.find('wxSizer') assert isinstance(c, etgtools.ClassDef) tools.fixSizerClass(c) c.addPrivateCopyCtor() c.addPrivateAssignOp() for func in c.findAll('Add') + c.findAll('Insert') + c.findAll('Prepend'): if func.findItem('sizer'): func.find('sizer').transfer = True if func.findItem('userData'): func.find('userData').transfer = True func.find('userData').type = 'wxPyUserData*' if func.findItem('item'): func.find('item').transfer = True c.find('GetChildren').overloads = [] c.find('GetChildren').noCopy = True # Needs wxWin 2.6 compatibility c.find('Remove').findOverload('(wxWindow *window)').ignore() # deprecated and removed c.find('SetVirtualSizeHints').ignore() c.addPyMethod('AddMany', '(self, items)', doc="""\ :meth:`AddMany` is a convenience method for adding several items to a sizer at one time. Simply pass it a list of tuples, where each tuple consists of the parameters that you would normally pass to the :meth:`Add` method. """, body="""\ for item in items: if not isinstance(item, (tuple, list)): item = (item, ) self.Add(*item) """) c.addCppMethod( 'wxSizerItem*', 'Add', '(const wxSize& size, int proportion=0, int flag=0, ' 'int border=0, wxPyUserData* userData /Transfer/ = NULL)', doc="Add a spacer using a :class:`Size` object.", body= "return self->Add(size->x, size->y, proportion, flag, border, userData);" ) c.addCppMethod( 'wxSizerItem*', 'Prepend', '(const wxSize& size, int proportion=0, int flag=0, ' 'int border=0, wxPyUserData* userData /Transfer/ = NULL)', doc="Prepend a spacer using a :class:`Size` object.", body= "return self->Prepend(size->x, size->y, proportion, flag, border, userData);" ) c.addCppMethod( 'wxSizerItem*', 'Insert', '(ulong index, const wxSize& size, int proportion=0, int flag=0, ' 'int border=0, wxPyUserData* userData /Transfer/ = NULL)', doc="Insert a spacer using a :class:`Size` object.", body= "return self->Insert(index, size->x, size->y, proportion, flag, border, userData);" ) c.addCppMethod('wxSizerItem*', 'Add', '(const wxSize& size, const wxSizerFlags& flags)', doc="Add a spacer using a :class:`Size` object.", body="return self->Add(size->x, size->y, *flags);") c.addCppMethod('wxSizerItem*', 'Prepend', '(const wxSize& size, const wxSizerFlags& flags)', doc="Prepend a spacer using a :class:`Size` object.", body="return self->Prepend(size->x, size->y, *flags);") c.addCppMethod( 'wxSizerItem*', 'Insert', '(ulong index, const wxSize& size, const wxSizerFlags& flags)', doc="Insert a spacer using a :class:`Size` object.", body="return self->Insert(index, size->x, size->y, *flags);") c.addPyMethod( '__nonzero__', '(self)', doc= "Can be used to test if the C++ part of the sizer still exists, with \n" "code like this::\n\n" " if theSizer:\n" " doSomething()", body="""\ import wx.siplib return not wx.siplib.isdeleted(self) """) c.addPyMethod( '__iter__', '(self)', doc= "A Py convenience method that allows Sizers to act as iterables that will yield their wx.SizerItems.", body="for item in self.GetChildren(): yield item") c.addPyCode('Sizer.__bool__ = Sizer.__nonzero__') # For Python 3 #--------------------------------------------- c = module.find('wxBoxSizer') tools.fixSizerClass(c) c.find('wxBoxSizer.orient').default = 'wxHORIZONTAL' #--------------------------------------------- c = module.find('wxStaticBoxSizer') tools.fixSizerClass(c) c.find('wxStaticBoxSizer.orient').default = 'wxHORIZONTAL' #--------------------------------------------- c = module.find('wxGridSizer') tools.fixSizerClass(c) c.addPyMethod('CalcRowsCols', '(self)', doc="""\ CalcRowsCols() -> (rows, cols) Calculates how many rows and columns will be in the sizer based on the current number of items and also the rows, cols specified in the constructor. """, body="""\ nitems = len(self.GetChildren()) rows = self.GetRows() cols = self.GetCols() assert rows != 0 or cols != 0, "Grid sizer must have either rows or columns fixed" if cols != 0: rows = (nitems + cols - 1) / cols elif rows != 0: cols = (nitems + rows - 1) / rows return (rows, cols) """) #--------------------------------------------- c = module.find('wxFlexGridSizer') tools.fixSizerClass(c) #--------------------------------------------- c = module.find('wxStdDialogButtonSizer') tools.fixSizerClass(c) module.addPyCode("PySizer = wx.deprecated(Sizer, 'Use Sizer instead.')") module.addItem( tools.wxListWrapperTemplate('wxSizerItemList', 'wxSizerItem', module)) #----------------------------------------------------------------- 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. c = module.find('wxPalette') tools.removeVirtuals(c) # Add a helper function for use with the Create method and the Ctor # accepting RGB data. c.addCppCode("""\ // a helper function to be used in the Create method and one of the Ctors bool _paletteCreateHelper(wxPalette* self, PyObject* red, PyObject* green, PyObject* blue) { bool rval = false; wxPyThreadBlocker blocker; char* errMsg = "Expected a sequence of integer objects"; if (!PySequence_Check(red) || !PySequence_Check(green) || !PySequence_Check(blue)) { PyErr_SetString(PyExc_TypeError, errMsg); return rval; } Py_ssize_t count = PySequence_Size(red); if (PySequence_Size(green) != count || PySequence_Size(blue) != count) { PyErr_SetString(PyExc_ValueError, "Sequence lengths must be equal"); return rval; } unsigned char* redArray = new unsigned char[count]; unsigned char* greenArray = new unsigned char[count]; unsigned char* blueArray = new unsigned char[count]; for (Py_ssize_t i = 0; i < count; i++) { PyObject* redItem = PySequence_ITEM(red, i); PyObject* greenItem = PySequence_ITEM(green, i); PyObject* blueItem = PySequence_ITEM(blue, i); if (!wxPyInt_Check(redItem) || !wxPyInt_Check(greenItem) || !wxPyInt_Check(blueItem)) { PyErr_SetString(PyExc_TypeError, errMsg); goto pch_exit; } long redLong = wxPyInt_AsLong(redItem); long greenLong = wxPyInt_AsLong(greenItem); long blueLong = wxPyInt_AsLong(blueItem); Py_DECREF(redItem); Py_DECREF(greenItem); Py_DECREF(blueItem); if (redLong < 0 || redLong > 255 || greenLong < 0 || greenLong > 255 || blueLong < 0 || blueLong > 255) { PyErr_SetString(PyExc_ValueError, "Sequence values must be in the 0..255 range"); goto pch_exit; } redArray[i] = redLong; greenArray[i] = greenLong; blueArray[i] = blueLong; } rval = self->Create(count, redArray, greenArray, blueArray); pch_exit: delete[] redArray; delete[] greenArray; delete[] blueArray; return rval; } """) #----------------------------------------------------------------- # Replace the constructor accepting the arrays of RGB values with one that # understands any Python sequence. c.find('wxPalette').findOverload('red').ignore() c.addCppCtor('(PyObject* red, PyObject* green, PyObject* blue)', doc=dedent("""\ Creates a palette from a set of sequences of integers, one for each red, green and blue color components. :param red: A sequence of integer values in the range 0..255 inclusive. :param green: A sequence of integer values in the range 0..255 inclusive. :param blue: A sequence of integer values in the range 0..255 inclusive. .. note:: All sequences must be the same length. """), body="""\ wxPalette* pal = new wxPalette; _paletteCreateHelper(pal, red, green, blue); if (PyErr_Occurred()) { delete pal; return NULL; } return pal; """) c.find('GetPixel.red').pyInt = True c.find('GetPixel.green').pyInt = True c.find('GetPixel.blue').pyInt = True c.find('GetRGB').ignore() c.addCppMethod('PyObject*', 'GetRGB', '(int pixel)', pyArgsString="(pixel) -> (red, green, blue)", doc="Returns RGB values for a given palette index.", body="""\ unsigned char red; unsigned char green; unsigned char blue; wxPyThreadBlocker blocker; if (!self->GetRGB(pixel, &red, &green, &blue)) { PyErr_SetString(PyExc_IndexError, "Pixel out of range"); return NULL; } PyObject* rv = PyTuple_New(3); PyTuple_SetItem(rv, 0, wxPyInt_FromLong(red)); PyTuple_SetItem(rv, 1, wxPyInt_FromLong(green)); PyTuple_SetItem(rv, 2, wxPyInt_FromLong(blue)); return rv; """) # Replace the Create method with one that understands any kind of Python sequence c.find('Create').ignore() c.addCppMethod('PyObject*', 'Create', '(PyObject* red, PyObject* green, PyObject* blue)', pyArgsString="(red, green, blue) -> bool", doc=dedent("""\ Creates a palette from 3 sequences of integers, one for each red, blue or green component. :param red: A sequence of integer values in the range 0..255 inclusive. :param green: A sequence of integer values in the range 0..255 inclusive. :param blue: A sequence of integer values in the range 0..255 inclusive. .. note:: All sequences must be the same length. """), body="""\ bool rval = _paletteCreateHelper(self, red, green, blue); wxPyThreadBlocker blocker; if (PyErr_Occurred()) return NULL; if (rval) Py_RETURN_TRUE; else Py_RETURN_FALSE; """) #----------------------------------------------------------------- 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. c = module.find('wxBrush') assert isinstance(c, etgtools.ClassDef) tools.removeVirtuals(c) # Set mustHaveApp on all ctors except the default ctor for ctor in c.find('wxBrush').all(): if ctor.isCtor and ctor.argsString != '()': ctor.mustHaveApp() c.addCppMethod('int', '__nonzero__', '()', "return self->IsOk();") c.addCppMethod('int', '__bool__', '()', "return self->IsOk();") c.addCppCode("""\ #ifdef __WXMAC__ #include <wx/osx/private.h> #endif """) c.addCppMethod( 'void', 'MacSetTheme', '(int macThemeBrushID)', """\ #ifdef __WXMAC__ self->SetColour(wxColour(wxMacCreateCGColorFromHITheme(macThemeBrushID))); #else wxPyRaiseNotImplemented(); #endif """) c.addAutoProperties() # The stock Brush items are documented as simple pointers, but in reality # they are macros that evaluate to a function call that returns a brush # pointer, and that is only valid *after* the wx.App object has been # created. That messes up the code that SIP generates for them, so we need # to come up with another solution. So instead we will just create # uninitialized brush in a block of Python code, that will then be # initialized later when the wx.App is created. c.addCppMethod('void', '_copyFrom', '(const wxBrush* other)', "*self = *other;", briefDoc="For internal use only.") # ?? pycode = '# These stock brushes will be initialized when the wx.App object is created.\n' for item in module: if '_BRUSH' in item.name: item.ignore() pycode += '%s = Brush()\n' % tools.removeWxPrefix(item.name) module.addPyCode(pycode) # it is delay-initialized, see stockgdi.sip module.find('wxTheBrushList').ignore() # Some aliases that should be phased out eventually, (sooner rather than # later.) They are already gone (or wrapped by an #if) in the C++ code, # and so are not found in the documentation... module.addPyCode("""\ wx.STIPPLE_MASK_OPAQUE = int(wx.BRUSHSTYLE_STIPPLE_MASK_OPAQUE) wx.STIPPLE_MASK = int(wx.BRUSHSTYLE_STIPPLE_MASK) wx.STIPPLE = int(wx.BRUSHSTYLE_STIPPLE) wx.BDIAGONAL_HATCH = int(wx.BRUSHSTYLE_BDIAGONAL_HATCH) wx.CROSSDIAG_HATCH = int(wx.BRUSHSTYLE_CROSSDIAG_HATCH) wx.FDIAGONAL_HATCH = int(wx.BRUSHSTYLE_FDIAGONAL_HATCH) wx.CROSS_HATCH = int(wx.BRUSHSTYLE_CROSS_HATCH) wx.HORIZONTAL_HATCH = int(wx.BRUSHSTYLE_HORIZONTAL_HATCH) wx.VERTICAL_HATCH = int(wx.BRUSHSTYLE_VERTICAL_HATCH) """) #----------------------------------------------------------------- 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/wx.h>') #--------------------------------------- # wxPoint2D and wxRect2D tweaks c = module.find('wxPoint2DDouble') c.renameClass('Point2D') c.find('wxPoint2DDouble').findOverload('wxPoint2DInt').ignore() c.find('m_x').pyName = 'x' c.find('m_y').pyName = 'y' c.find('GetFloor.x').out = True c.find('GetFloor.y').out = True c.find('GetRounded.x').out = True c.find('GetRounded.y').out = True # these have link errors c.find('operator/=').findOverload('wxDouble').ignore() c.find('operator*=').findOverload('wxDouble').ignore() c.convertFromPyObject = tools.convertTwoDoublesTemplate('wxPoint2DDouble') c.addCppMethod('PyObject*', 'Get', '()', """\ wxPyThreadBlocker blocker; return sipBuildResult(0, "(dd)", self->m_x, self->m_y); """, briefDoc="""\ Get() -> (x,y)\n 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.Point2D"+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 (Point2D, 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('Point2D.__safe_for_unpickling__ = True') # ignore these operator methods, since we are not wrapping the Int version c.find('operator*=').findOverload('wxInt32').ignore() c.find('operator/=').findOverload('wxInt32').ignore() # ignore all the global operators too, there is no equivallent in Python for item in module: if isinstance( item, etgtools.FunctionDef) and item.name.startswith('operator'): for f in item.all(): f.ignore() c = module.find('wxRect2DDouble') c.renameClass('Rect2D') c.find('m_x').pyName = 'x' c.find('m_y').pyName = 'y' c.find('m_width').pyName = 'width' c.find('m_height').pyName = 'height' c.convertFromPyObject = tools.convertFourDoublesTemplate('wxRect2DDouble') c.addCppMethod('PyObject*', 'Get', '()', """\ wxPyThreadBlocker blocker; return sipBuildResult(0, "(dddd)", self->m_x, self->m_y, self->m_width, self->m_height); """, briefDoc="""\ Get() -> (x, y, width, height)\n 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.Rect2D"+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 (Rect2D, 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('Rect2D.__safe_for_unpickling__ = 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. c = module.find('wxDC') assert isinstance(c, etgtools.ClassDef) c.mustHaveApp() c.addPrivateCopyCtor() c.addPublic() tools.removeVirtuals(c) # Keep only the wxSize overloads of these c.find('GetSize').findOverload('wxCoord').ignore() c.find('GetSizeMM').findOverload('wxCoord').ignore() # TODO: needs wxAffineMatrix2D support. #c.find('GetTransformMatrix').ignore() #c.find('SetTransformMatrix').ignore() # remove wxPoint* overloads, we use the wxPointList ones c.find('DrawLines').findOverload('wxPoint points').ignore() c.find('DrawPolygon').findOverload('wxPoint points').ignore() c.find('DrawSpline').findOverload('wxPoint points').ignore() # TODO: we'll need a custom method implementation for this since there # are multiple array parameters involved... c.find('DrawPolyPolygon').ignore() # Add output param annotations so the generated docstrings will be correct c.find('GetUserScale.x').out = True c.find('GetUserScale.y').out = True c.find('GetLogicalScale.x').out = True c.find('GetLogicalScale.y').out = True c.find('GetLogicalOrigin').overloads = [] c.find('GetLogicalOrigin.x').out = True c.find('GetLogicalOrigin.y').out = True c.find('GetClippingBox.x').out = True c.find('GetClippingBox.y').out = True c.find('GetClippingBox.width').out = True c.find('GetClippingBox.height').out = True c.addPyMethod( 'GetClippingRect', '(self)', doc="Gets the rectangle surrounding the current clipping region", body="return wx.Rect(*self.GetClippingBox())") # Deal with the text-extent methods. In Classic we renamed one overloaded # method with a "Full" name, and the simpler one was left with the # original name. I think a simpler approach here will be to remove the # simple version, rename the Full version as before, and then add a # CppMethod to reimplement the simple version. for name in ['GetTextExtent', 'GetMultiLineTextExtent']: m = c.find(name) # if these fail then double-check order of parsed methods, etc. assert len(m.overloads) == 1 assert 'wxCoord' not in m.overloads[0].argsString m.overloads = [] c.find('GetTextExtent').pyName = 'GetFullTextExtent' c.find('GetMultiLineTextExtent').pyName = 'GetFullMultiLineTextExtent' # Set output parameters c.find('GetTextExtent.w').out = True c.find('GetTextExtent.h').out = True c.find('GetTextExtent.descent').out = True c.find('GetTextExtent.externalLeading').out = True c.find('GetMultiLineTextExtent.w').out = True c.find('GetMultiLineTextExtent.h').out = True c.find('GetMultiLineTextExtent.heightLine').out = True # Update the docs to remove references to overloading, pointer values, etc. m = c.find('GetTextExtent') m.briefDoc = "Gets the dimensions of the string as it would be drawn." m.detailedDoc = [ dedent("""\ The ``string`` parameter is the string to measure. The return value is a tuple of integer values consisting of ``widget``, ``height``, ``decent`` and ``externalLeading``. The ``descent`` is the dimension from the baseline of the font to the bottom of the descender, and ``externalLeading`` is any extra vertical space added to the font by the font designer (usually is zero). If the optional parameter ``font`` is specified and valid, then it is used for the text extent calculation. Otherwise the currently selected font is. .. seealso:: :class:`wx.Font`, :meth:`~wx.DC.SetFont`, :meth:`~wx.DC.GetPartialTextExtents, :meth:`~wx.DC.GetMultiLineTextExtent` """) ] m = c.find('GetMultiLineTextExtent') m.briefDoc = "Gets the dimensions of the string as it would be drawn." m.detailedDoc = [ dedent("""\ The ``string`` parameter is the string to measure. The return value is a tuple of integer values consisting of ``widget``, ``height`` and ``heightLine``. The ``heightLine`` is the the height of a single line. If the optional parameter ``font`` is specified and valid, then it is used for the text extent calculation. Otherwise the currently selected font is. .. note:: This function works with both single-line and multi-line strings. .. seealso:: :class:`wx.Font`, :meth:`~wx.DC.SetFont`, :meth:`~wx.DC.GetPartialTextExtents, :meth:`~wx.DC.GetTextExtent` """) ] # Now add the simpler versions of the extent methods c.addCppMethod('wxSize*', 'GetTextExtent', '(const wxString& st)', isConst=True, doc=dedent("""\ Return the dimensions of the given string's text extent using the currently selected font. :param st: The string to be measured .. seealso:: :meth:`~wx.DC.GetFullTextExtent` """), body="""\ return new wxSize(self->GetTextExtent(*st)); """, overloadOkay=False, factory=True) c.addCppMethod('wxSize*', 'GetMultiLineTextExtent', '(const wxString& st)', isConst=True, doc=dedent("""\ Return the dimensions of the given string's text extent using the currently selected font, taking into account multiple lines if present in the string. :param st: The string to be measured .. seealso:: :meth:`~wx.DC.GetFullMultiLineTextExtent` """), body="""\ return new wxSize(self->GetMultiLineTextExtent(*st)); """, overloadOkay=False, factory=True) # Add some alternate implementations for other DC methods, in order to # avoid using parameters as return values, etc. as well as Classic # compatibility. c.find('GetPixel').ignore() c.addCppMethod('wxColour*', 'GetPixel', '(wxCoord x, wxCoord y)', doc="Gets the colour at the specified location on the DC.", body="""\ wxColour* col = new wxColour; self->GetPixel(x, y, col); return col; """, factory=True) # Return the rect instead of using an output parameter m = c.find('DrawLabel').findOverload('rectBounding') m.type = 'wxRect*' m.find('rectBounding').ignore() m.factory = True # a new instance of wxRect is being created m.setCppCode("""\ wxRect rv; self->DrawLabel(*text, *bitmap, *rect, alignment, indexAccel, &rv); return new wxRect(rv); """) c.addPyCode( 'DC.DrawImageLabel = wx.deprecated(DC.DrawLabel, "Use DrawLabel instead.")' ) # Return the array instead of using an output parameter m = c.find('GetPartialTextExtents') m.type = 'wxArrayInt*' m.find('widths').ignore() m.factory = True # a new instance is being created m.setCppCode("""\ wxArrayInt rval; self->GetPartialTextExtents(*text, rval); return new wxArrayInt(rval); """) c.addCppMethod('int', '__nonzero__', '()', """\ return self->IsOk(); """) c.addPyMethod( 'GetBoundingBox', '(self)', doc="""\ GetBoundingBox() -> (x1,y1, x2,y2)\n Returns the min and max points used in drawing commands so far.""", body="return (self.MinX(), self.MinY(), self.MaxX(), self.MaxY())") c.addCppMethod( 'long', 'GetHDC', '()', """\ #ifdef __WXMSW__ return (long)self->GetHandle(); #else wxPyRaiseNotImplemented(); return 0; #endif""") c.addCppMethod( 'void*', 'GetCGContext', '()', """\ #ifdef __WXMAC__ return self->GetHandle(); #else wxPyRaiseNotImplemented(); return NULL; #endif""") c.addCppMethod( 'void*', 'GetGdkDrawable', '()', """\ #ifdef __WXGTK__ return self->GetHandle(); #else wxPyRaiseNotImplemented(); return NULL; #endif""") c.addPyCode( 'DC.GetHDC = wx.deprecated(DC.GetHDC, "Use GetHandle instead.")') c.addPyCode( 'DC.GetCGContext = wx.deprecated(DC.GetCGContext, "Use GetHandle instead.")' ) c.addPyCode( 'DC.GetGdkDrawable = wx.deprecated(DC.GetGdkDrawable, "Use GetHandle instead.")' ) # This file contains implementations of functions for quickly drawing # lists of items on the DC. They are called from the CppMethods defined # below, which in turn are called from the PyMethods below that. c.includeCppCode('src/dc_ex.cpp') c.addCppMethod( 'PyObject*', '_DrawPointList', '(PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes)', body= "return wxPyDrawXXXList(*self, wxPyDrawXXXPoint, pyCoords, pyPens, pyBrushes);" ) c.addCppMethod( 'PyObject*', '_DrawLineList', '(PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes)', body= "return wxPyDrawXXXList(*self, wxPyDrawXXXLine, pyCoords, pyPens, pyBrushes);" ) c.addCppMethod( 'PyObject*', '_DrawRectangleList', '(PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes)', body= "return wxPyDrawXXXList(*self, wxPyDrawXXXRectangle, pyCoords, pyPens, pyBrushes);" ) c.addCppMethod( 'PyObject*', '_DrawEllipseList', '(PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes)', body= "return wxPyDrawXXXList(*self, wxPyDrawXXXEllipse, pyCoords, pyPens, pyBrushes);" ) c.addCppMethod( 'PyObject*', '_DrawPolygonList', '(PyObject* pyCoords, PyObject* pyPens, PyObject* pyBrushes)', body= "return wxPyDrawXXXList(*self, wxPyDrawXXXPolygon, pyCoords, pyPens, pyBrushes);" ) c.addCppMethod( 'PyObject*', '_DrawTextList', '(PyObject* textList, PyObject* pyPoints, PyObject* foregroundList, PyObject* backgroundList)', body= "return wxPyDrawTextList(*self, textList, pyPoints, foregroundList, backgroundList);" ) c.addPyMethod('DrawPointList', '(self, points, pens=None)', doc="""\ Draw a list of points as quickly as possible. :param points: A sequence of 2-element sequences representing each point to draw, (x,y). :param pens: If None, then the current pen is used. If a single pen then it will be used for all points. If a list of pens then there should be one for each point in points. """, body="""\ if pens is None: pens = [] elif isinstance(pens, wx.Pen): pens = [pens] elif len(pens) != len(points): raise ValueError('points and pens must have same length') return self._DrawPointList(points, pens, []) """) c.addPyMethod('DrawLineList', '(self, lines, pens=None)', doc="""\ Draw a list of lines as quickly as possible. :param lines: A sequence of 4-element sequences representing each line to draw, (x1,y1, x2,y2). :param pens: If None, then the current pen is used. If a single pen then it will be used for all lines. If a list of pens then there should be one for each line in lines. """, body="""\ if pens is None: pens = [] elif isinstance(pens, wx.Pen): pens = [pens] elif len(pens) != len(lines): raise ValueError('lines and pens must have same length') return self._DrawLineList(lines, pens, []) """) c.addPyMethod('DrawRectangleList', '(self, rectangles, pens=None, brushes=None)', doc="""\ Draw a list of rectangles as quickly as possible. :param rectangles: A sequence of 4-element sequences representing each rectangle to draw, (x,y, w,h). :param pens: If None, then the current pen is used. If a single pen then it will be used for all rectangles. If a list of pens then there should be one for each rectangle in rectangles. :param brushes: A brush or brushes to be used to fill the rectagles, with similar semantics as the pens parameter. """, body="""\ if pens is None: pens = [] elif isinstance(pens, wx.Pen): pens = [pens] elif len(pens) != len(rectangles): raise ValueError('rectangles and pens must have same length') if brushes is None: brushes = [] elif isinstance(brushes, wx.Brush): brushes = [brushes] elif len(brushes) != len(rectangles): raise ValueError('rectangles and brushes must have same length') return self._DrawRectangleList(rectangles, pens, brushes) """) c.addPyMethod('DrawEllipseList', '(self, ellipses, pens=None, brushes=None)', doc="""\ Draw a list of ellipses as quickly as possible. :param ellipses: A sequence of 4-element sequences representing each ellipse to draw, (x,y, w,h). :param pens: If None, then the current pen is used. If a single pen then it will be used for all ellipses. If a list of pens then there should be one for each ellipse in ellipses. :param brushes: A brush or brushes to be used to fill the ellipses, with similar semantics as the pens parameter. """, body="""\ if pens is None: pens = [] elif isinstance(pens, wx.Pen): pens = [pens] elif len(pens) != len(ellipses): raise ValueError('ellipses and pens must have same length') if brushes is None: brushes = [] elif isinstance(brushes, wx.Brush): brushes = [brushes] elif len(brushes) != len(ellipses): raise ValueError('ellipses and brushes must have same length') return self._DrawEllipseList(ellipses, pens, brushes) """) c.addPyMethod('DrawPolygonList', '(self, polygons, pens=None, brushes=None)', doc="""\ Draw a list of polygons, each of which is a list of points. :param polygons: A sequence of sequences of sequences. [[(x1,y1),(x2,y2),(x3,y3)...], [(x1,y1),(x2,y2),(x3,y3)...]] :param pens: If None, then the current pen is used. If a single pen then it will be used for all polygons. If a list of pens then there should be one for each polygon. :param brushes: A brush or brushes to be used to fill the polygons, with similar semantics as the pens parameter. """, body="""\ if pens is None: pens = [] elif isinstance(pens, wx.Pen): pens = [pens] elif len(pens) != len(polygons): raise ValueError('polygons and pens must have same length') if brushes is None: brushes = [] elif isinstance(brushes, wx.Brush): brushes = [brushes] elif len(brushes) != len(polygons): raise ValueError('polygons and brushes must have same length') return self._DrawPolygonList(polygons, pens, brushes) """) c.addPyMethod( 'DrawTextList', '(self, textList, coords, foregrounds=None, backgrounds=None)', doc="""\ Draw a list of strings using a list of coordinants for positioning each string. :param textList: A list of strings :param coords: A list of (x,y) positions :param foregrounds: A list of `wx.Colour` objects to use for the foregrounds of the strings. :param backgrounds: A list of `wx.Colour` objects to use for the backgrounds of the strings. NOTE: Make sure you set background mode to wx.Solid (DC.SetBackgroundMode) If you want backgrounds to do anything. """, body="""\ if type(textList) == type(''): textList = [textList] elif len(textList) != len(coords): raise ValueError('textlist and coords must have same length') if foregrounds is None: foregrounds = [] elif isinstance(foregrounds, wx.Colour): foregrounds = [foregrounds] elif len(foregrounds) != len(coords): raise ValueError('foregrounds and coords must have same length') if backgrounds is None: backgrounds = [] elif isinstance(backgrounds, wx.Colour): backgrounds = [backgrounds] elif len(backgrounds) != len(coords): raise ValueError('backgrounds and coords must have same length') return self._DrawTextList(textList, coords, foregrounds, backgrounds) """) #----------------------------------------------------------------- c = module.find('wxDCClipper') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() # context manager methods c.addPyMethod('__enter__', '(self)', 'return self') c.addPyMethod('__exit__', '(self, exc_type, exc_val, exc_tb)', 'return False') #----------------------------------------------------------------- c = module.find('wxDCBrushChanger') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() # context manager methods c.addPyMethod('__enter__', '(self)', 'return self') c.addPyMethod('__exit__', '(self, exc_type, exc_val, exc_tb)', 'return False') #----------------------------------------------------------------- c = module.find('wxDCPenChanger') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() # context manager methods c.addPyMethod('__enter__', '(self)', 'return self') c.addPyMethod('__exit__', '(self, exc_type, exc_val, exc_tb)', 'return False') #----------------------------------------------------------------- c = module.find('wxDCTextColourChanger') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() # context manager methods c.addPyMethod('__enter__', '(self)', 'return self') c.addPyMethod('__exit__', '(self, exc_type, exc_val, exc_tb)', 'return False') #----------------------------------------------------------------- c = module.find('wxDCFontChanger') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() # context manager methods c.addPyMethod('__enter__', '(self)', 'return self') c.addPyMethod('__exit__', '(self, exc_type, exc_val, exc_tb)', 'return False') #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. module.addHeaderCode("#include <wx/dataview.h>") for item in module.allItems(): if hasattr(item, 'type') and 'wxVariant' in item.type: item.type = item.type.replace('wxVariant', 'wxDVCVariant') #----------------------------------------------------------------- c = module.find('wxDataViewItem') assert isinstance(c, etgtools.ClassDef) c.addCppMethod('int', '__nonzero__', '()', """\ return self->IsOk(); """) c.addCppMethod('long', '__hash__', '()', """\ return (long)self->GetID(); """) c.addCppMethod('bool', '__eq__', '(wxDataViewItem* other)', "return (self->GetID() == other->GetID());") c.addCppMethod('bool', '__ne__', '(wxDataViewItem* other)', "return (self->GetID() != other->GetID());") c.addAutoProperties() module.addItem( tools.wxArrayWrapperTemplate('wxDataViewItemArray', 'wxDataViewItem', module)) module.addPyCode("NullDataViewItem = DataViewItem()") #----------------------------------------------------------------- c = module.find('wxDataViewModel') c.addAutoProperties() tools.fixRefCountedClass(c) c.find('~wxDataViewModel').ignore(False) c.find('AddNotifier.notifier').transfer = True c.find('RemoveNotifier.notifier').transferBack = True # Change the GetValue method to return the value instead of passing it # through a parameter for modification. c.find('GetValue.variant').out = True # The DataViewItemObjectMapper class helps map from data items to Python # objects, and is used as a base class of PyDataViewModel as a # convenience. module.addPyClass( 'DataViewItemObjectMapper', ['object'], doc="""\ This class provides a mechanism for mapping between Python objects and the :class:`DataViewItem` objects used by the :class:`DataViewModel` for tracking the items in the view. The ID used for the item is the id() of the Python object. Use :meth:`ObjectToItem` to create a :class:`DataViewItem` using a Python object as its ID, and use :meth:`ItemToObject` to fetch that Python object again later for a given :class:`DataViewItem`. By default a regular dictionary is used to implement the ID to object mapping. Optionally a WeakValueDictionary can be useful when there will be a high turnover of objects and mantaining an extra reference to the objects would be unwise. If weak references are used then the objects associated with data items must be weak-referenceable. (Things like stock lists and dictionaries are not.) See :meth:`UseWeakRefs`. This class is used in :class:`PyDataViewModel` as a mixin for convenience. """, items=[ PyFunctionDef('__init__', '(self)', body="""\ self.mapper = dict() self.usingWeakRefs = False """), PyFunctionDef( 'ObjectToItem', '(self, obj)', doc= "Create a :class:`DataViewItem` for the object, and remember the ID-->obj mapping.", body="""\ import sys oid = id(obj) while oid > sys.maxsize: # risk of conflict here... May need some more thought. oid -= sys.maxsize self.mapper[oid] = obj return DataViewItem(oid) """), PyFunctionDef( 'ItemToObject', '(self, item)', doc="Retrieve the object that was used to create an item.", body="""\ oid = int(item.GetID()) return self.mapper[oid] """), PyFunctionDef('UseWeakRefs', '(self, flag)', doc="""\ Switch to or from using a weak value dictionary for keeping the ID to object map.""", body="""\ if flag == self.usingWeakRefs: return if flag: import weakref newmap = weakref.WeakValueDictionary() else: newmap = dict() newmap.update(self.mapper) self.mapper = newmap self.usingWeakRefs = flag """), ]) module.addPyClass( 'PyDataViewModel', ['DataViewModel', 'DataViewItemObjectMapper'], doc= "A convenience class that is a :class:`DataViewModel` combined with an object mapper.", items=[ PyFunctionDef('__init__', '(self)', body="""\ DataViewModel.__init__(self) DataViewItemObjectMapper.__init__(self) """) ]) #----------------------------------------------------------------- c = module.find('wxDataViewListModel') c.addAutoProperties() tools.fixRefCountedClass(c) # Change the GetValueByRow method to return the value instead of passing # it through a parameter for modification. c.find('GetValueByRow.variant').out = True # declare implementations for base class virtuals c.addItem( etgtools.WigCode("""\ virtual wxDataViewItem GetParent( const wxDataViewItem &item ) const; virtual bool IsContainer( const wxDataViewItem &item ) const; virtual void GetValue( wxDVCVariant &variant /Out/, const wxDataViewItem &item, unsigned int col ) const [void ( wxDVCVariant &variant, const wxDataViewItem &item, unsigned int col )]; virtual bool SetValue( const wxDVCVariant &variant, const wxDataViewItem &item, unsigned int col ); virtual bool GetAttr(const wxDataViewItem &item, unsigned int col, wxDataViewItemAttr &attr) const; virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const; virtual bool IsListModel() const; """)) # Add some of the pure virtuals since there are undocumented # implementations of them in these classes. The others will need to be # implemented in Python classes derived from these. for name in ['wxDataViewIndexListModel', 'wxDataViewVirtualListModel']: c = module.find(name) c.addItem( etgtools.WigCode("""\ virtual unsigned int GetRow(const wxDataViewItem& item) const; virtual unsigned int GetCount() const; virtual unsigned int GetChildren( const wxDataViewItem &item, wxDataViewItemArray &children ) const; """)) # compatibility aliases module.addPyCode("""\ PyDataViewIndexListModel = wx.deprecated(DataViewIndexListModel) PyDataViewVirtualListModel = wx.deprecated(DataViewVirtualListModel) """) #----------------------------------------------------------------- def _fixupBoolGetters(method, sig): method.type = 'void' method.find('value').out = True method.find('value').type = 'wxDVCVariant&' method.cppSignature = sig c = module.find('wxDataViewRenderer') c.addPrivateCopyCtor() c.abstract = True c.addAutoProperties() c.find('GetView').ignore(False) # Change variant getters to return the value for name, sig in [ ('GetValue', 'bool (wxVariant& value)'), ('GetValueFromEditorCtrl', 'bool (wxWindow * editor, wxVariant& value)'), ]: _fixupBoolGetters(c.find(name), sig) m = c.find('SetValue') m.find('value').type = 'wxDVCVariant&' m.cppSignature = 'bool (const wxVariant& value)' c = module.find('wxDataViewCustomRenderer') m = c.find('GetValueFromEditorCtrl') _fixupBoolGetters(m, 'bool (wxWindow * editor, wxVariant& value)') # Change the virtual method handler code to follow the same pattern as the # tweaked public API, namely that the value is the return value instead of # an out parameter. m.virtualCatcherCode = """\ PyObject *sipResObj = sipCallMethod(&sipIsErr, sipMethod, "D", editor, sipType_wxWindow, NULL); if (sipResObj == Py_None) { sipRes = false; } else { sipRes = true; sipParseResult(&sipIsErr, sipMethod, sipResObj, "H5", sipType_wxDVCVariant, &value); } """ c.find('GetTextExtent').ignore(False) module.addPyCode("""\ PyDataViewCustomRenderer = wx.deprecated(DataViewCustomRenderer, "Use DataViewCustomRenderer instead")""" ) # Add the pure virtuals since there are undocumented implementations of # them in all these classes for name in [ 'wxDataViewTextRenderer', 'wxDataViewIconTextRenderer', 'wxDataViewProgressRenderer', 'wxDataViewSpinRenderer', 'wxDataViewToggleRenderer', 'wxDataViewChoiceRenderer', #'wxDataViewChoiceByIndexRenderer', 'wxDataViewDateRenderer', 'wxDataViewBitmapRenderer', ]: c = module.find(name) c.addAutoProperties() c.addItem( etgtools.WigCode("""\ virtual bool SetValue( const wxDVCVariant &value ) [bool (const wxVariant& value)]; virtual void GetValue( wxDVCVariant &value /Out/ ) const [bool (wxVariant& value)]; %Property(name=Value, get=GetValue, set=SetValue) """, protection='public')) # The SpinRenderer has a few additional pure virtuals that need to be declared # since it derives from DataViewCustomRenderer c = module.find('wxDataViewSpinRenderer') c.addItem( etgtools.WigCode("""\ virtual wxSize GetSize() const; virtual bool Render(wxRect cell, wxDC* dc, int state); """, protection='public')) #----------------------------------------------------------------- c = module.find('wxDataViewColumn') for m in c.find('wxDataViewColumn').all(): m.find('renderer').transfer = True # declare the virtuals from wxSettableHeaderColumn c.addItem( etgtools.WigCode("""\ virtual void SetTitle(const wxString& title); virtual wxString GetTitle() const; virtual void SetBitmap(const wxBitmap& bitmap); virtual wxBitmap GetBitmap() const; virtual void SetWidth(int width); virtual int GetWidth() const; virtual void SetMinWidth(int minWidth); virtual int GetMinWidth() const; virtual void SetAlignment(wxAlignment align); virtual wxAlignment GetAlignment() const; virtual void SetFlags(int flags); virtual int GetFlags() const; virtual bool IsSortKey() const; virtual void SetSortOrder(bool ascending); virtual bool IsSortOrderAscending() const; virtual void SetResizeable(bool resizable); virtual void SetSortable(bool sortable); virtual void SetReorderable(bool reorderable); virtual void SetHidden(bool hidden); """)) c.addAutoProperties() c.addProperty('Title', 'GetTitle', 'SetTitle') c.addProperty('Bitmap', 'GetBitmap', 'SetBitmap') c.addProperty('Width', 'GetWidth', 'SetWidth') c.addProperty('MinWidth', 'GetMinWidth', 'SetMinWidth') c.addProperty('Alignment', 'GetAlignment', 'SetAlignment') c.addProperty('Flags', 'GetFlags', 'SetFlags') c.addProperty('SortOrder', 'IsSortOrderAscending', 'SetSortOrder') #----------------------------------------------------------------- c = module.find('wxDataViewCtrl') tools.fixWindowClass(c) module.addGlobalStr('wxDataViewCtrlNameStr', c) c.find('AssociateModel.model').transfer = True c.find('AssociateModel').pyName = '_AssociateModel' c.addPyMethod('AssociateModel', '(self, model)', doc="""\ Associates a :class:`DataViewModel` with the control. Ownership of the model object is passed to C++, however it is reference counted so it can be shared with other views. """, body="""\ import wx.siplib wasPyOwned = wx.siplib.ispyowned(model) self._AssociateModel(model) # Ownership of the python object has just been transferred to # C++, so DecRef the C++ instance associated with this python # reference. if wasPyOwned: model.DecRef() """) c.find('PrependColumn.col').transfer = True c.find('InsertColumn.col').transfer = True c.find('AppendColumn.col').transfer = True c.addPyMethod( 'GetColumns', '(self)', doc="Returns a list of column objects.", body="return [self.GetColumn(i) for i in range(self.GetColumnCount())]" ) c.find('GetSelections').ignore() c.addCppMethod('wxDataViewItemArray*', 'GetSelections', '()', isConst=True, factory=True, doc="Returns a list of the currently selected items.", body="""\ wxDataViewItemArray* selections = new wxDataViewItemArray; self->GetSelections(*selections); return selections; """) # Pythonize HitTest c.find('HitTest').ignore() c.addCppMethod('PyObject*', 'HitTest', '(const wxPoint& point)', isConst=True, doc="""\ HitTest(point) -> (item, col)\n Returns the item and column located at point, as a 2 element tuple. """, body="""\ wxDataViewItem* item = new wxDataViewItem();; wxDataViewColumn* col = NULL; self->HitTest(*point, *item, col); wxPyThreadBlocker blocker; PyObject* value = PyTuple_New(2); PyObject* item_obj = wxPyConstructObject((void*)item, wxT("wxDataViewItem"), 1); // owned PyObject* col_obj; if (col) { col_obj = wxPyConstructObject((void*)col, wxT("wxDataViewColumn"), 0); // not owned } else { col_obj = Py_None; Py_INCREF(Py_None); } PyTuple_SET_ITEM(value, 0, item_obj); PyTuple_SET_ITEM(value, 1, col_obj); // PyTuple steals a reference, so we don't need to decref the items here return value; """) #----------------------------------------------------------------- c = module.find('wxDataViewEvent') tools.fixEventClass(c) c.addProperty('EditCancelled', 'IsEditCancelled', 'SetEditCanceled') c.find('SetCache.from').name = 'from_' c.find('SetCache.to').name = 'to_' c.find('GetDataBuffer').ignore() c.addCppMethod('PyObject*', 'GetDataBuffer', '()', isConst=True, doc="Gets the data buffer for a drop data transfer", body="""\ wxPyThreadBlocker blocker; return wxPyMakeBuffer(self->GetDataBuffer(), self->GetDataSize(), true); """) # TODO: SetDataBuffer c.find('SetDataObject.obj').transfer = True module.addPyCode("""\ EVT_DATAVIEW_SELECTION_CHANGED = wx.PyEventBinder( wxEVT_DATAVIEW_SELECTION_CHANGED, 1) EVT_DATAVIEW_ITEM_ACTIVATED = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_ACTIVATED, 1) EVT_DATAVIEW_ITEM_COLLAPSED = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_COLLAPSED, 1) EVT_DATAVIEW_ITEM_EXPANDED = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_EXPANDED, 1) EVT_DATAVIEW_ITEM_COLLAPSING = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_COLLAPSING, 1) EVT_DATAVIEW_ITEM_EXPANDING = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_EXPANDING, 1) EVT_DATAVIEW_ITEM_START_EDITING = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_START_EDITING, 1) EVT_DATAVIEW_ITEM_EDITING_STARTED = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_EDITING_STARTED, 1) EVT_DATAVIEW_ITEM_EDITING_DONE = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_EDITING_DONE, 1) EVT_DATAVIEW_ITEM_VALUE_CHANGED = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, 1) EVT_DATAVIEW_ITEM_CONTEXT_MENU = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, 1) EVT_DATAVIEW_COLUMN_HEADER_CLICK = wx.PyEventBinder( wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, 1) EVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK = wx.PyEventBinder( wxEVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, 1) EVT_DATAVIEW_COLUMN_SORTED = wx.PyEventBinder( wxEVT_DATAVIEW_COLUMN_SORTED, 1) EVT_DATAVIEW_COLUMN_REORDERED = wx.PyEventBinder( wxEVT_DATAVIEW_COLUMN_REORDERED, 1) EVT_DATAVIEW_ITEM_BEGIN_DRAG = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, 1) EVT_DATAVIEW_ITEM_DROP_POSSIBLE = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, 1) EVT_DATAVIEW_ITEM_DROP = wx.PyEventBinder( wxEVT_DATAVIEW_ITEM_DROP, 1) EVT_DATAVIEW_CACHE_HINT = wx.PyEventBinder( wxEVT_DATAVIEW_CACHE_HINT, 1 ) # deprecated wxEVT aliases wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED = wxEVT_DATAVIEW_SELECTION_CHANGED wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED = wxEVT_DATAVIEW_ITEM_ACTIVATED wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED = wxEVT_DATAVIEW_ITEM_COLLAPSED wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED = wxEVT_DATAVIEW_ITEM_EXPANDED wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING = wxEVT_DATAVIEW_ITEM_COLLAPSING wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING = wxEVT_DATAVIEW_ITEM_EXPANDING wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING = wxEVT_DATAVIEW_ITEM_START_EDITING wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED = wxEVT_DATAVIEW_ITEM_EDITING_STARTED wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE = wxEVT_DATAVIEW_ITEM_EDITING_DONE wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED = wxEVT_DATAVIEW_ITEM_VALUE_CHANGED wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU = wxEVT_DATAVIEW_ITEM_CONTEXT_MENU wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK = wxEVT_DATAVIEW_COLUMN_HEADER_CLICK wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK = wxEVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED = wxEVT_DATAVIEW_COLUMN_SORTED wxEVT_COMMAND_DATAVIEW_COLUMN_REORDERED = wxEVT_DATAVIEW_COLUMN_REORDERED wxEVT_COMMAND_DATAVIEW_CACHE_HINT = wxEVT_DATAVIEW_CACHE_HINT wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG = wxEVT_DATAVIEW_ITEM_BEGIN_DRAG wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE = wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE wxEVT_COMMAND_DATAVIEW_ITEM_DROP = wxEVT_DATAVIEW_ITEM_DROP """) #----------------------------------------------------------------- c = module.find('wxDataViewListCtrl') tools.fixWindowClass(c) c.find('GetStore').overloads = [] c.find('AppendItem.values').type = 'const wxVariantVector&' c.find('PrependItem.values').type = 'const wxVariantVector&' c.find('InsertItem.values').type = 'const wxVariantVector&' c.find('GetValue.value').out = True for name in 'AppendColumn InsertColumn PrependColumn'.split(): for m in c.find(name).all(): m.find('column').transfer = True c = module.find('wxDataViewListStore') c.find('AppendItem.values').type = 'const wxVariantVector&' c.find('PrependItem.values').type = 'const wxVariantVector&' c.find('InsertItem.values').type = 'const wxVariantVector&' c.find('GetValueByRow.value').out = True c.addAutoProperties() #----------------------------------------------------------------- c = module.find('wxDataViewTreeCtrl') tools.fixWindowClass(c) c.find('GetStore').overloads = [] c = module.find('wxDataViewTreeStore') c.addAutoProperties() tools.fixRefCountedClass(c) #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)
def run(): # Parse the XML file(s) building a collection of Extractor objects module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING) etgtools.parseDoxyXML(module, ITEMS) module.check4unittest = False #----------------------------------------------------------------- # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. module.addHeaderCode('#include <wxpy_api.h>') module.addImport('_core') module.addImport('_xml') module.addPyCode('''\ import wx ID_NONE = wx.ID_NONE # Needed for some parameter defaults in this module ''', order=10) module.addInclude(INCLUDES) module.addInitializerCode("""\ wxXmlInitResourceModule(); wxXmlResource::Get()->InitAllHandlers(); """) module.addHeaderCode('#include <wx/xrc/xmlres.h>') module.addHeaderCode('#include <wx/fs_mem.h>') module.addHeaderCode('#include "wxpybuffer.h"') module.insertItem( 0, etgtools.WigCode("""\ // forward declarations class wxAnimation; """)) #----------------------------------------------------------------- c = module.find('wxXmlResource') assert isinstance(c, etgtools.ClassDef) c.addPrivateCopyCtor() # Add a bit of code to the ctors to call InitAllHandlers(), for # compatibility with Classic for ctor in c.find('wxXmlResource').all(): template = """\ Py_BEGIN_ALLOW_THREADS sipCpp = new sipwxXmlResource({args}); sipCpp->InitAllHandlers(); Py_END_ALLOW_THREADS """ if 'filemask' in ctor.argsString: args = '*filemask,flags,*domain' else: args = 'flags,*domain' ctor.setCppCode_sip(template.format(args=args)) c.addPublic() c.addCppMethod( 'bool', 'LoadFromBuffer', '(wxPyBuffer* data)', doc= "Load the resource from a bytes string or other data buffer compatible object.", #protection='public', body="""\ static int s_memFileIdx = 0; // Check for memory FS. If not present, load the handler: wxMemoryFSHandler::AddFile(wxT("XRC_resource/dummy_file"), wxT("dummy data")); wxFileSystem fsys; wxFSFile *f = fsys.OpenFile(wxT("memory:XRC_resource/dummy_file")); wxMemoryFSHandler::RemoveFile(wxT("XRC_resource/dummy_file")); if (f) delete f; else wxFileSystem::AddHandler(new wxMemoryFSHandler); // Now put the resource data into the memory FS wxString filename(wxT("XRC_resource/data_string_")); filename << s_memFileIdx; s_memFileIdx += 1; wxMemoryFSHandler::AddFile(filename, data->m_ptr, data->m_len); // Load the "file" into the resource object bool retval = self->Load(wxT("memory:") + filename ); return retval; """) c.addPyCode( "XmlResource.LoadFromString = wx.deprecated(XmlResource.LoadFromBuffer, 'Use LoadFromBuffer instead')" ) c.find('AddHandler.handler').transfer = True c.find('InsertHandler.handler').transfer = True c.find('Set.res').transfer = True c.find('Set').transferBack = True c.find('AddSubclassFactory.factory').transfer = True #----------------------------------------------------------------- c = module.find('wxXmlResourceHandler') # un-ignore all the protected methods for item in c.allItems(): if isinstance(item, etgtools.MethodDef): item.ignore(False) c.find('DoCreateResource').factory = True #----------------------------------------------------------------- module.addPyFunction( 'EmptyXmlResource', '(flags=XRC_USE_LOCALE, domain="")', deprecated="Use :class:`xrc.XmlResource` instead", doc= 'A compatibility wrapper for the XmlResource(flags, domain) constructor', body='return XmlResource(flags, domain)') module.addPyFunction( 'XRCID', '(str_id, value_if_not_found=wx.ID_NONE)', doc= 'Returns a numeric ID that is equivalent to the string ID used in an XML resource.', body='return XmlResource.GetXRCID(str_id, value_if_not_found)') module.addPyFunction( 'XRCCTRL', '(window, str_id, *ignoreargs)', doc= 'Returns the child window associated with the string ID in an XML resource.', body='return window.FindWindow(XRCID(str_id))') cls = ClassDef(name='wxXmlSubclassFactory', briefDoc="", items=[ MethodDef(name='wxXmlSubclassFactory', isCtor=True), MethodDef(name='~wxXmlSubclassFactory', isDtor=True), MethodDef(name='Create', type='wxObject*', isVirtual=True, isPureVirtual=True, factory=True, items=[ ParamDef(type='const wxString&', name='className') ]) ]) module.addItem(cls) module.addPyCode("""\ # Create a factory for handling the subclass property of XRC's # object tag. This factory will search for the specified # package.module.class and will try to instantiate it for XRC's # use. The class must support instantiation with no parameters and # delayed creation of the UI widget (aka 2-phase create). def _my_import(name): try: mod = __import__(name) except ImportError: import traceback print(traceback.format_exc()) raise components = name.split('.') for comp in components[1:]: mod = getattr(mod, comp) return mod class XmlSubclassFactory_Python(XmlSubclassFactory): def __init__(self): XmlSubclassFactory.__init__(self) def Create(self, className): assert className.find('.') != -1, "Module name must be specified!" mname = className[:className.rfind('.')] cname = className[className.rfind('.')+1:] module = _my_import(mname) klass = getattr(module, cname) inst = klass() return inst XmlResource.AddSubclassFactory(XmlSubclassFactory_Python()) """) #----------------------------------------------------------------- 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. # Lots of the uses of wxDateTime_t have been changed to "unsigned short" # in the interface file, so lets go ahead and translate the rest of them # too so there will not be any "wxDateTime_t" in Phoenix confusingly # mixed with "unsigned short"s. # # Also add the class scope specifier to nested enum types for parameters # and return values. for item in module.allItems(): if isinstance( item, (etgtools.FunctionDef, etgtools.ParamDef, etgtools.VariableDef)): typesMap = { 'wxDateTime_t': 'unsigned short', 'Month': 'wxDateTime::Month', 'WeekDay': 'wxDateTime::WeekDay', 'TZ': 'wxDateTime::TZ', 'TimeZone': 'wxDateTime::TimeZone', 'Tm': 'wxDateTime::Tm', } if item.type in typesMap: item.type = typesMap[item.type] # ignore the #define and add it as a Python alias instead module.find('wxInvalidDateTime').ignore() module.addPyCode('InvalidDateTime = DefaultDateTime') gs = module.addGlobalStr('wxDefaultDateTimeFormat', module.find('wxInvalidDateTime')) module.addGlobalStr('wxDefaultTimeSpanFormat', gs) #--------------------------------------------- # Tweaks for the wxDateTime class c = module.find('wxDateTime') assert isinstance(c, etgtools.ClassDef) c.allowAutoProperties = False tools.ignoreAllOperators(c) # Ignore ctors with unknown types or that have overload conflicts that # can't be distingished in Python ctor = c.find('wxDateTime') ctor.findOverload('time_t').ignore() ctor.findOverload('struct tm').ignore() ctor.findOverload('double jdn').ignore() ctor.findOverload('_SYSTEMTIME').ignore() ctor.findOverload('hour').ignore( ) # careful, the one we want to keep has an 'hour' param too # Add static factories for some of the ctors we ignored c.addCppMethod( 'wxDateTime*', 'FromTimeT', '(time_t timet)', factory=True, isStatic=True, doc= "Construct a :class:`DateTime` from a C ``time_t`` value, the number of seconds since the epoch.", body="return new wxDateTime(timet);") c.addCppMethod( 'wxDateTime*', 'FromJDN', '(double jdn)', factory=True, isStatic=True, doc="Construct a :class:`DateTime` from a Julian Day Number.\n\n" "By definition, the Julian Day Number, usually abbreviated as JDN, of a particular instant is the fractional number of days since 12 hours Universal Coordinated Time (Greenwich mean noon) on January 1 of the year -4712 in the Julian proleptic calendar.", body="return new wxDateTime(jdn);") c.addCppMethod( 'wxDateTime*', 'FromHMS', """(unsigned short hour, unsigned short minute=0, unsigned short second=0, unsigned short millisecond=0)""", factory=True, isStatic=True, doc= "Construct a :class:`DateTime` equal to :meth:`Today` () with the time set to the supplied parameters.", body="return new wxDateTime(hour, minute, second, millisecond);") c.addCppMethod( 'wxDateTime*', 'FromDMY', """(unsigned short day, wxDateTime::Month month, int year = Inv_Year, unsigned short hour=0, unsigned short minute=0, unsigned short second=0, unsigned short millisecond=0)""", factory=True, isStatic=True, doc="Construct a :class:`DateTime` using the supplied parameters.", body= "return new wxDateTime(day, month, year, hour, minute, second, millisecond);" ) # and give them some simple wrappers for Classic compatibility module.addPyFunction( 'DateTimeFromTimeT', '(timet)', doc="Compatibility wrapper for :meth:`DateTime.FromTimeT`", body="return DateTime.FromTimeT(timet)", deprecated='Use :meth:`DateTime.FromTimeT` instead.') module.addPyFunction( 'DateTimeFromJDN', '(jdn)', doc="Compatibility wrapper for :meth:`DateTime.FromJDN`", body="return DateTime.FromJDN(jdn)", deprecated='Use :meth:`DateTime.FromJDN` instead.') module.addPyFunction( 'DateTimeFromHMS', '(hour, minute=0, second=0, millisecond=0)', doc="Compatibility wrapper for :meth:`DateTime.FromHMS`", body="return DateTime.FromHMS(hour, minute, second, millisecond)", deprecated='Use :meth:`DateTime.FromHMS` instead.') module.addPyFunction( 'DateTimeFromDMY', '(day, month, year=DateTime.Inv_Year, hour=0, minute=0, second=0, millisecond=0)', doc="Compatibility wrapper for :meth:`DateTime.FromDMY`", body= "return DateTime.FromDMY(day, month, year, hour, minute, second, millisecond)", deprecated='Use :meth:`DateTime.FromDMY` instead.') # Fixup similar conflicts in the Set method overloads c.find('Set').findOverload('struct tm').ignore() c.find('Set').renameOverload('Tm', 'SetTm') c.find('Set').renameOverload('time_t', 'SetTimeT') c.find('Set').renameOverload('double jdn', 'SetJDN') c.find('Set').renameOverload('hour', 'SetHMS') # Unknown parameter and return types c.find('SetFromMSWSysTime').ignore() c.find('GetAsMSWSysTime').ignore() # this overload is static, the other isn't. Rename it? c.find('GetCentury').findOverload('year').ignore() c.find('GetNumberOfDays').ignore() c.find('GetTmNow').ignore() c.find('GetTmNow').ignore() # output the am/pm parameter values c.find('GetAmPmStrings.am').out = True c.find('GetAmPmStrings.pm').out = True # remove the const version of the overloaded Add's and Subtract's c.find('Add').findOverload('wxDateSpan', isConst=True).ignore() c.find('Add').findOverload('wxTimeSpan', isConst=True).ignore() c.find('Subtract').findOverload('wxDateSpan', isConst=True).ignore() c.find('Subtract').findOverload('wxTimeSpan', isConst=True).ignore() # Ignore the end parameter for the Parse*() methods, and provide # replacement implementations that don't need them. Change them to be # like they were in Classic, returning a -1 on failure, or the number of # characters parsed otherwise. def fixParseMethod(m, code): assert isinstance(m, etgtools.MethodDef) m.find('end').ignore() m.type = 'int' m.setCppCode(code) return m fixParseMethod( c.find('ParseDate'), """\ wxString::const_iterator begin = date->begin(); wxString::const_iterator end; if (! self->ParseDate(*date, &end)) return -1; return end - begin; """) fixParseMethod( c.find('ParseDateTime'), """\ wxString::const_iterator begin = datetime->begin(); wxString::const_iterator end; if (! self->ParseDateTime(*datetime, &end)) return -1; return end - begin; """) fixParseMethod( c.find('ParseTime'), """\ wxString::const_iterator begin = time->begin(); wxString::const_iterator end; if (! self->ParseTime(*time, &end)) return -1; return end - begin; """) fixParseMethod( c.find('ParseRfc822Date'), """\ wxString::const_iterator begin = date->begin(); wxString::const_iterator end; if (! self->ParseRfc822Date(*date, &end)) return -1; return end - begin; """) pf = c.find('ParseFormat') pf1 = fixParseMethod( pf.findOverload( 'const wxString &date, const wxString &format, const wxDateTime &dateDef, wxString::' ), """\ wxString::const_iterator begin = date->begin(); wxString::const_iterator end; if (! self->ParseFormat(*date, *format, *dateDef, &end)) return -1; return end - begin; """) pf2 = fixParseMethod( pf.findOverload( 'const wxString &date, const wxString &format, wxString::'), """\ wxString::const_iterator begin = date->begin(); wxString::const_iterator end; if (! self->ParseFormat(*date, *format, &end)) return -1; return end - begin; """) pf3 = fixParseMethod( pf.findOverload('const wxString &date, wxString::'), """\ wxString::const_iterator begin = date->begin(); wxString::const_iterator end; if (! self->ParseFormat(*date, &end)) return -1; return end - begin; """) # Fiddle with the docstrings for ParseFormat to make them reflect the new # reality. The other Parse*() docs refer the reader to this one, so we # don't have to change all of them. # find the <simplesect kind="return"> node in the last paragraph para = pf1.detailedDoc[-1] elem = para.find("simplesect[@kind='return']") # it has a child paragraph containing the text we need to replace elem[ 0].text = '-1 if the parse failed, the number of characters parsed otherwise.' pf2.briefDoc = "This version of the :meth:`ParseFormat` method works the same, but with missing values filled in from :meth:`Today`." pf3.briefDoc = "This version uses \"%c\" as the format code, which is the same default used by :meth:`Format`." c.addPyMethod( '__repr__', '(self)', """\ from six import PY2 if self.IsValid(): f = self.Format() if PY2: f = f.encode('utf-8') return '<wx.DateTime: "%s">' % f else: return '<wx.DateTime: \"INVALID\">' """) c.addPyMethod( '__str__', '(self)', """\ from six import PY2 if self.IsValid(): f = self.Format() if PY2: f = f.encode('utf-8') return f else: return "INVALID DateTime" """) # use lowercase to avoid conflicts c.addProperty("day GetDay SetDay") c.addProperty("month GetMonth SetMonth") c.addProperty("year GetYear SetYear") c.addProperty("hour GetHour SetHour") c.addProperty("minute GetMinute SetMinute") c.addProperty("second GetSecond SetSecond") c.addProperty("millisecond GetMillisecond SetMillisecond") c.addProperty("JDN GetJDN SetJDN") c.addProperty("DayOfYear GetDayOfYear") c.addProperty("JulianDayNumber GetJulianDayNumber") c.addProperty("LastMonthDay GetLastMonthDay") c.addProperty("MJD GetMJD") c.addProperty("ModifiedJulianDayNumber GetModifiedJulianDayNumber") c.addProperty("RataDie GetRataDie") c.addProperty("Ticks GetTicks") c.addProperty("WeekOfMonth GetWeekOfMonth") c.addProperty("WeekOfYear GetWeekOfYear") c.addItem( etgtools.WigCode("""\ bool operator<(const wxDateTime& dt) const; bool operator<=(const wxDateTime& dt) const; bool operator>(const wxDateTime& dt) const; bool operator>=(const wxDateTime& dt) const; bool operator==(const wxDateTime& dt) const; bool operator!=(const wxDateTime& dt) const; wxDateTime& operator+=(const wxTimeSpan& diff); wxDateTime operator+(const wxTimeSpan& ts) const; wxDateTime& operator-=(const wxTimeSpan& diff); wxDateTime operator-(const wxTimeSpan& ts) const; wxDateTime& operator+=(const wxDateSpan& diff); wxDateTime operator+(const wxDateSpan& ds) const; wxDateTime& operator-=(const wxDateSpan& diff); wxDateTime operator-(const wxDateSpan& ds) const; wxTimeSpan operator-(const wxDateTime& dt2) const; """)) # Add some code to automatically convert from a Python datetime.date or a # datetime.datetime object c.convertFromPyObject = """\ // Code to test a PyObject for compatibility with wxDateTime if (!sipIsErr) { if (sipCanConvertToType(sipPy, sipType_wxDateTime, SIP_NO_CONVERTORS)) return TRUE; if (wxPyDateTime_Check(sipPy) || wxPyDate_Check(sipPy)) return TRUE; return FALSE; } // Code to convert a compatible PyObject to a wxDateTime if (wxPyDateTime_Check(sipPy)) { *sipCppPtr = wxPyDateTime_ToWxDateTime(sipPy); return sipGetState(sipTransferObj); } if (wxPyDate_Check(sipPy)) { *sipCppPtr = wxPyDate_ToWxDateTime(sipPy); return sipGetState(sipTransferObj); } // if we get this far then it must already be a wxDateTime instance *sipCppPtr = reinterpret_cast<wxDateTime*>(sipConvertToType( sipPy, sipType_wxDateTime, sipTransferObj, SIP_NO_CONVERTORS, 0, sipIsErr)); return 0; // Not a new instance """ #--------------------------------------------- # Tweaks for the wxDateSpan class c = module.find('wxDateSpan') c.allowAutoProperties = False tools.ignoreAllOperators(c) c.find('Add').findOverload('', isConst=True).ignore() c.find('Multiply').findOverload('', isConst=True).ignore() c.find('Subtract').findOverload('', isConst=True).ignore() c.addItem( etgtools.WigCode("""\ wxDateSpan& operator+=(const wxDateSpan& other); wxDateSpan operator+(const wxDateSpan& ds) const; wxDateSpan& operator-=(const wxDateSpan& other); wxDateSpan operator-(const wxDateSpan& ds) const; wxDateSpan& operator-(); wxDateSpan& operator*=(int factor); wxDateSpan operator*(int n) const; bool operator==(const wxDateSpan& ds) const; bool operator!=(const wxDateSpan& ds) const; """)) #--------------------------------------------- # Tweaks for the wxTimeSpan class c = module.find('wxTimeSpan') c.allowAutoProperties = False tools.ignoreAllOperators(c) c.find('Add').findOverload('', isConst=True).ignore() c.find('Multiply').findOverload('', isConst=True).ignore() c.find('Subtract').findOverload('', isConst=True).ignore() c.addItem( etgtools.WigCode("""\ wxTimeSpan& operator+=(const wxTimeSpan& diff); wxTimeSpan operator+(const wxTimeSpan& ts) const; wxTimeSpan& operator-=(const wxTimeSpan& diff); wxTimeSpan operator-(const wxTimeSpan& ts); wxTimeSpan& operator*=(int n); wxTimeSpan operator*(int n) const; wxTimeSpan& operator-(); bool operator<(const wxTimeSpan &ts) const; bool operator<=(const wxTimeSpan &ts) const; bool operator>(const wxTimeSpan &ts) const; bool operator>=(const wxTimeSpan &ts) const; bool operator==(const wxTimeSpan &ts) const; bool operator!=(const wxTimeSpan &ts) const; """)) #--------------------------------------------- # Convert to/from Python date objects module.addPyFunction( 'pydate2wxdate', '(date)', doc='Convert a Python date or datetime to a :class:`DateTime` object', body="""\ import datetime assert isinstance(date, (datetime.datetime, datetime.date)) return DateTime(date) # the built-in typemap will convert it for us """) module.addPyFunction( 'wxdate2pydate', '(date)', doc='Convert a :class:`DateTime` object to a Python datetime.', body="""\ import datetime assert isinstance(date, DateTime) if date.IsValid(): return datetime.datetime(date.year, date.month+1, date.day, date.hour, date.minute, date.second, date.millisecond*1000) else: return None """) #----------------------------------------------------------------- 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/gdicmn.h>') def markCreateFactories(klass): """Mark all Create methods as factories""" for func in klass.allItems(): if isinstance(func, etgtools.FunctionDef) \ and func.name.startswith('Create') \ and '*' in func.type: func.factory = True #--------------------------------------------- c = module.find('wxGraphicsObject') assert isinstance(c, etgtools.ClassDef) c.mustHaveApp() c.addCppMethod('bool', 'IsOk', '()', 'return !self->IsNull();') c.addCppMethod('int', '__nonzero__', '()', "return !self->IsNull();") c.addCppMethod('int', '__bool__', '()', "return !self->IsNull();") #--------------------------------------------- c = module.find('wxGraphicsContext') assert isinstance(c, etgtools.ClassDef) tools.removeVirtuals(c) c.abstract = True c.mustHaveApp() c.addCppMethod('wxGraphicsContext*', 'Create', '(wxAutoBufferedPaintDC* autoPaintDC /KeepReference/)', pyArgsString='(autoPaintDC) -> GraphicsContext', isStatic=True, body="""\ return wxGraphicsContext::Create(*autoPaintDC); """) m = c.find('Create').findOverload('wxEnhMetaFileDC') m.find('metaFileDC').type = 'const wxMetafileDC&' m.argsString = '(const wxMetafileDC& metaFileDC)' m.setCppCode("""\ #ifdef __WXMSW__ #if wxUSE_ENH_METAFILE return wxGraphicsContext::Create(*metaFileDC); #endif #endif wxPyRaiseNotImplemented(); return NULL; """) markCreateFactories(c) # Ensure that the target DC or image passed to Create lives as long as the # GC does. NOTE: Since the Creates are static methods there is no self to # associate the extra reference with, but since they are factories then # that extra reference will be held by the return value of the factory # instead. for m in c.find('Create').all(): for p in m.items: if 'DC' in p.name or p.name == 'image': p.keepReference = True c.find('GetSize.width').out = True c.find('GetSize.height').out = True c.find('GetDPI.dpiX').out = True c.find('GetDPI.dpiY').out = True m = c.find('GetPartialTextExtents') m.find('widths').ignore() m.type = 'wxArrayDouble*' m.factory = True # a new instance is being created m.setCppCode("""\ wxArrayDouble rval; self->GetPartialTextExtents(*text, rval); return new wxArrayDouble(rval); """) m = c.find('GetTextExtent') m.pyName = 'GetFullTextExtent' m.find('width').out = True m.find('height').out = True m.find('descent').out = True m.find('externalLeading').out = True c.addCppMethod( 'PyObject*', 'GetTextExtent', '(const wxString& text)', pyArgsString="(text) -> (width, height)", doc= "Gets the dimensions of the string using the currently selected font.", body="""\ wxDouble width = 0.0, height = 0.0; self->GetTextExtent(*text, &width, &height, NULL, NULL); wxPyThreadBlocker blocker; return sipBuildResult(0, "(dd)", width, height); """) c.addPyCode( "GraphicsContext.DrawRotatedText = wx.deprecated(GraphicsContext.DrawText, 'Use DrawText instead.')" ) c.addCppCode( tools.ObjArrayHelperTemplate( 'wxPoint2D', 'sipType_wxPoint2DDouble', "Expected a sequence of length-2 sequences or wx.Point2D objects.") ) # we'll reimplement this overload as StrokeLineSegments c.find('StrokeLines').findOverload('beginPoints').ignore() c.addCppMethod('void', 'StrokeLineSegments', '(PyObject* beginPoints, PyObject* endPoints)', pyArgsString="(beginPoint2Ds, endPoint2Ds)", doc="Stroke disconnected lines from begin to end points.", body="""\ size_t c1, c2, count; wxPoint2D* beginP = wxPoint2D_array_helper(beginPoints, &c1); wxPoint2D* endP = wxPoint2D_array_helper(endPoints, &c2); if ( beginP != NULL && endP != NULL ) { count = wxMin(c1, c2); self->StrokeLines(count, beginP, endP); } delete [] beginP; delete [] endP; """) # Also reimplement the main StrokeLines method to reuse the same helper # function as StrokeLineSegments m = c.find('StrokeLines').findOverload('points').ignore() c.addCppMethod('void', 'StrokeLines', '(PyObject* points)', pyArgsString="(point2Ds)", doc="Stroke lines connecting all the points.", body="""\ size_t count; wxPoint2D* ptsArray = wxPoint2D_array_helper(points, &count); if ( ptsArray != NULL ) { self->StrokeLines(count, ptsArray); delete [] ptsArray; } """) # and once more for DrawLines m = c.find('DrawLines').ignore() c.addCppMethod( 'void', 'DrawLines', '(PyObject* points, wxPolygonFillMode fillStyle = wxODDEVEN_RULE)', pyArgsString="(point2Ds, fillStyle=ODDEVEN_RULE)", doc="Draws a polygon.", body="""\ size_t count; wxPoint2D* ptsArray = wxPoint2D_array_helper(points, &count); if ( ptsArray != NULL ) { self->DrawLines(count, ptsArray, fillStyle); delete [] ptsArray; } """) # TODO: support this? c.find('CreateFromNativeHDC').ignore() #--------------------------------------------- c = module.find('wxGraphicsPath') tools.removeVirtuals(c) c.find('GetBox').findOverload('wxDouble *x, wxDouble *y').ignore() c.find('GetCurrentPoint').findOverload('wxDouble *x, wxDouble *y').ignore() c.mustHaveApp() c.find('GetNativePath').setCppCode("""\ if (self->IsNull()) return (void*)0; return self->GetNativePath(); """) #--------------------------------------------- c = module.find('wxGraphicsRenderer') tools.removeVirtuals(c) markCreateFactories(c) c.abstract = True # The KeepReference annotation doesn't work for us in this case, as it will # hold the reference in the renderer object, but it is better to hold the # reference in the returned context object instead. Otherwise there is still # some possibility that the held DC will be destroyed before the context. c.addPyCode("""\ def _ctx_hold_ref(f): from functools import wraps @wraps(f) def wrapper(self, obj): ctx = f(self, obj) if ctx is not None: ctx._obj = obj return ctx return wrapper GraphicsRenderer.CreateContext = _ctx_hold_ref(GraphicsRenderer.CreateContext) GraphicsRenderer.CreateContextFromImage = _ctx_hold_ref(GraphicsRenderer.CreateContextFromImage) GraphicsRenderer.CreateContextFromUnknownDC = _ctx_hold_ref(GraphicsRenderer.CreateContextFromUnknownDC) """) # TODO: support this? c.find('CreateContext').findOverload('wxEnhMetaFileDC').ignore() # TODO: support this? c.find('CreateContextFromNativeHDC').ignore() c.addPyMethod('GetType', '(self)', doc="Returns the name of the GraphicsRenderer class.", body="return self.GetClassInfo().GetClassName()") c.find('GetGDIPlusRenderer').ignore() c.addCppMethod('wxGraphicsRenderer*', 'GetGDIPlusRenderer', '()', isStatic=True, doc="Returns GDI+ renderer (MSW only).", body="""\ #ifdef __WXMSW__ return wxGraphicsRenderer::GetGDIPlusRenderer(); #else return NULL; #endif """) c.find('GetDirect2DRenderer').ignore() c.addCppMethod('wxGraphicsRenderer*', 'GetDirect2DRenderer', '()', isStatic=True, doc="Returns Direct2D renderer (MSW and Python3 only).", body="""\ #if wxUSE_GRAPHICS_DIRECT2D return wxGraphicsRenderer::GetDirect2DRenderer(); #else return NULL; #endif """) #--------------------------------------------- c = module.find('wxGraphicsMatrix') tools.removeVirtuals(c) c.mustHaveApp() c.find('Concat').overloads = [] c.find('IsEqual').overloads = [] c.find('Get.a').out = True c.find('Get.b').out = True c.find('Get.c').out = True c.find('Get.d').out = True c.find('Get.tx').out = True c.find('Get.ty').out = True c.find('TransformDistance.dx').inOut = True c.find('TransformDistance.dy').inOut = True c.find('TransformPoint.x').inOut = True c.find('TransformPoint.y').inOut = True c.find('GetNativeMatrix').setCppCode("""\ if (self->IsNull()) return (void*)0; return self->GetNativeMatrix(); """) #--------------------------------------------- c = module.find('wxGraphicsGradientStops') c.addCppMethod('SIP_SSIZE_T', '__len__', '()', body="return (SIP_SSIZE_T)self->GetCount();") c.addCppMethod('wxGraphicsGradientStop*', '__getitem__', '(ulong n)', pyArgsString='(n)', body="return new wxGraphicsGradientStop(self->Item(n));", factory=True) #--------------------------------------------- c = module.find('wxGraphicsBitmap') c.find('GetNativeBitmap').setCppCode("""\ if (self->IsNull()) return (void*)0; return self->GetNativeBitmap(); """) #--------------------------------------------- c = module.find('wxGraphicsPenInfo') # Ignore Dashes for now # TODO: we need to do something like wx.Pen.SetDashes, but since # GraphicsPenInfo is transitory we can't save the reference in it to the # holder, and the pen will not have been created yet... c.find('Dashes').ignore() c.find('GetDashes').ignore() c.find('GetDashCount').ignore() c.find('GetDash').ignore() #--------------------------------------------- # Use the pyNames we set for these classes in geometry.py so the old # names do not show up in the docstrings, etc. tools.changeTypeNames(module, 'wxPoint2DDouble', 'wxPoint2D') tools.changeTypeNames(module, 'wxRect2DDouble', 'wxRect2D') #----------------------------------------------------------------- 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. # do not use the va_list forms of the functions for func in module.allItems(): if 'wxVLog' in func.name: func.ignore() for f in module.find('wxLogTrace').all(): # deprecated in 2.8 f.ignore() # Switch the parameters to wxStrings to capitalize on the conversion code # we already have for them. String formatting can be done in Python if # needed. Drop the '...' too. for name in ['wxLogMessage', 'wxLogVerbose', 'wxLogWarning', 'wxLogFatalError', 'wxLogError', 'wxLogDebug', 'wxLogStatus', 'wxLogSysError', 'wxLogGeneric']: for f in module.find(name).all(): p = f.find('formatString') p.type = 'const wxString&' p.name = 'message' f.items = f.items[:-1] module.find('wxSysErrorMsg').type = 'wxString' c = module.find('wxLogRecordInfo') c.find('threadId').ignore() c = module.find('wxLog') assert isinstance(c, etgtools.ClassDef) c.find('SetActiveTarget').transferBack = True c.find('SetActiveTarget.logtarget').transfer = True c.find('SetThreadActiveTarget').transferBack = True c.find('SetThreadActiveTarget.logger').transfer = True # we need to un-ignore these protected methods as they need to be overridable c.find('DoLogRecord').ignore(False) c.find('DoLogTextAtLevel').ignore(False) c.find('DoLogText').ignore(False) c = module.find('wxLogStderr') c.find('wxLogStderr.fp').ignore() c.addPrivateCopyCtor() c.addPrivateAssignOp() c = module.find('wxLogBuffer') c.addPrivateCopyCtor() c.addPrivateAssignOp() c = module.find('wxLogChain') c.addPrivateCopyCtor() c.addPrivateAssignOp() c = module.find('wxLogGui') c.addPrivateCopyCtor() c.addPrivateAssignOp() c = module.find('wxLogTextCtrl') c.addPrivateCopyCtor() c.addPrivateAssignOp() c = module.find('wxLogFormatter') c.find('FormatTime').ignore(False) #----------------------------------------------------------------- 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. # Use wxPyUserData for the clientData values instead of a plain wxObject def _fixClientData(c): for item in c.allItems(): if isinstance(item, etgtools.ParamDef) and item.name == 'clientData': item.type = 'wxPyUserData*' item.transfer = True #--------------------------------------------- c = module.find('wxToolBarToolBase') assert isinstance(c, etgtools.ClassDef) c.abstract = True tools.removeVirtuals(c) _fixClientData(c) # Switch all wxToolBarBase to wxToolBar for item in c.allItems(): if isinstance(item, etgtools.ParamDef) and item.name == 'tbar': item.type = 'wxToolBar*' c.find('GetToolBar').ignore() c.addCppMethod('wxToolBar*', 'GetToolBar', '()', doc="Return the toolbar this tool is a member of.", body="""\ return (wxToolBar*)self->GetToolBar(); """) gcd = c.find('GetClientData') gcd.type = 'wxPyUserData*' gcd.setCppCode( 'return dynamic_cast<wxPyUserData*>(self->GetClientData());') #--------------------------------------------- c = module.find('wxToolBar') tools.fixWindowClass(c) _fixClientData(c) c.find('SetBitmapResource').ignore() module.addGlobalStr('wxToolBarNameStr', c) gcd = c.find('GetToolClientData') gcd.type = 'wxPyUserData*' gcd.setCppCode( 'return dynamic_cast<wxPyUserData*>(self->GetToolClientData(toolId));') c.find('AddTool.tool').transfer = True c.find('InsertTool.tool').transfer = True c.find('OnLeftClick').ignore() c.find('OnMouseEnter').ignore() c.find('OnRightClick').ignore() c.find('OnLeftClick').ignore() # Add some deprecated methods to aid with Classic compatibility. # TODO: Which others are commonly enough used that they should be here too? c.addPyMethod( 'AddSimpleTool', '(self, toolId, bitmap, shortHelpString="", longHelpString="", isToggle=0)', doc='Old style method to add a tool to the toolbar.', deprecated='Use :meth:`AddTool` instead.', body="""\ kind = wx.ITEM_NORMAL if isToggle: kind = wx.ITEM_CHECK return self.AddTool(toolId, '', bitmap, wx.NullBitmap, kind, shortHelpString, longHelpString) """) c.addPyMethod( 'AddLabelTool', '(self, id, label, bitmap, bmpDisabled=wx.NullBitmap, kind=wx.ITEM_NORMAL,' ' shortHelp="", longHelp="", clientData=None)', doc='Old style method to add a tool in the toolbar.', deprecated='Use :meth:`AddTool` instead.', body="""\ return self.AddTool(id, label, bitmap, bmpDisabled, kind, shortHelp, longHelp, clientData) """) c.addPyMethod( 'InsertSimpleTool', '(self, pos, toolId, bitmap, shortHelpString="", longHelpString="", isToggle=0)', doc='Old style method to insert a tool in the toolbar.', deprecated='Use :meth:`InsertTool` instead.', body="""\ kind = wx.ITEM_NORMAL if isToggle: kind = wx.ITEM_CHECK return self.InsertTool(pos, toolId, '', bitmap, wx.NullBitmap, kind, shortHelpString, longHelpString) """) c.addPyMethod( 'InsertLabelTool', '(self, pos, id, label, bitmap, bmpDisabled=wx.NullBitmap, kind=wx.ITEM_NORMAL,' ' shortHelp="", longHelp="", clientData=None)', doc='Old style method to insert a tool in the toolbar.', deprecated='Use :meth:`InsertTool` instead.', body="""\ return self.InsertTool(pos, id, label, bitmap, bmpDisabled, kind, shortHelp, longHelp, clientData) """) #----------------------------------------------------------------- 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. c = module.find('wxMask') c.mustHaveApp() for m in c.find('Create').all(): m.ignore() c = module.find('wxBitmap') assert isinstance(c, etgtools.ClassDef) c.mustHaveApp() tools.removeVirtuals(c) # TODO: The wxCursor version of the ctor is not implemented on OSX... c.find('wxBitmap').findOverload('wxCursor').ignore() c.find('wxBitmap.bits').type = 'const char*' c.find('wxBitmap.type').default = 'wxBITMAP_TYPE_ANY' c.find('LoadFile.type').default = 'wxBITMAP_TYPE_ANY' c.find('wxBitmap').findOverload('(const char *const *bits)').ignore() c.addCppCtor('(PyObject* listOfBytes)', doc="Construct a Bitmap from a list of strings formatted as XPM data.", body="""\ wxPyThreadBlocker blocker; char** cArray = NULL; int count; char errMsg[] = "Expected a list of bytes objects."; if (!PyList_Check(listOfBytes)) { PyErr_SetString(PyExc_TypeError, errMsg); return NULL; } count = PyList_Size(listOfBytes); cArray = new char*[count]; for(int x=0; x<count; x++) { PyObject* item = PyList_GET_ITEM(listOfBytes, x); if (!PyBytes_Check(item)) { PyErr_SetString(PyExc_TypeError, errMsg); delete [] cArray; return NULL; } cArray[x] = PyBytes_AsString(item); } wxBitmap* bmp = new wxBitmap(cArray); delete [] cArray; return bmp; """) c.find('SetMask.mask').transfer = True c.addCppMethod('void', 'SetMaskColour', '(const wxColour& colour)', doc="Create a mask for this bitmap based on the pixels with the given colour.", body="""\ wxMask* mask = new wxMask(*self, *colour); self->SetMask(mask); """) c.addCppMethod('int', '__nonzero__', '()', "return self->IsOk();") c.addCppMethod('int', '__bool__', '()', "return self->IsOk();") c.addCppMethod('long', 'GetHandle', '()', doc='MSW-only method to fetch the windows handle for the bitmap.', body="""\ #ifdef __WXMSW__ return (long)self->GetHandle(); #else return 0; #endif """) c.addCppMethod('void', 'SetHandle', '(long handle)', doc='MSW-only method to set the windows handle for the bitmap.', body="""\ #ifdef __WXMSW__ self->SetHandle((WXHANDLE)handle); #endif """) c.addCppMethod('void', 'SetSize', '(const wxSize& size)', doc='Set the bitmap size (does not alter the existing native bitmap data or image size).', body="""\ self->SetWidth(size->x); self->SetHeight(size->y); """) # On MSW the bitmap handler classes are different than what is # documented, and this causes compile errors. Nobody has needed them from # Python thus far, so just ignore them all for now. for m in c.find('FindHandler').all(): m.ignore() c.find('AddHandler').ignore() c.find('CleanUpHandlers').ignore() c.find('GetHandlers').ignore() c.find('InsertHandler').ignore() c.find('RemoveHandler').ignore() # This one is called from the wx startup code, it's not needed in Python # so nuke it too since we're nuking all the others. c.find('InitStandardHandlers').ignore() module.find('wxBitmapHandler').ignore() #module.addItem(tools.wxListWrapperTemplate('wxList', 'wxBitmapHandler', module)) #----------------------------------------------------------------------- # Declarations, helpers and methods for converting to/from buffer objects # with raw bitmap access. from etgtools import EnumDef, EnumValueDef e = EnumDef(name='wxBitmapBufferFormat') e.items.extend([ EnumValueDef(name='wxBitmapBufferFormat_RGB'), EnumValueDef(name='wxBitmapBufferFormat_RGBA'), EnumValueDef(name='wxBitmapBufferFormat_RGB32'), EnumValueDef(name='wxBitmapBufferFormat_ARGB32'), ]) module.insertItem(0, e) c.includeCppCode('src/bitmap_ex.cpp') module.addHeaderCode('#include "bitmap_ex.h"') c.addCppMethod('void', 'CopyFromBuffer', '(wxPyBuffer* data, wxBitmapBufferFormat format=wxBitmapBufferFormat_RGB, int stride=-1)', doc="""\ Copy data from a buffer object to replace the bitmap pixel data. Default format is plain RGB, but other formats are now supported as well. The following symbols are used to specify the format of the bytes in the buffer: ============================= ================================ wx.BitmapBufferFormat_RGB A simple sequence of RGB bytes wx.BitmapBufferFormat_RGBA A simple sequence of RGBA bytes wx.BitmapBufferFormat_ARGB32 A sequence of 32-bit values in native endian order, with alpha in the upper 8 bits, followed by red, green, and blue. wx.BitmapBufferFormat_RGB32 Same as above but the alpha byte is ignored. ============================= ================================""", body="""\ wxPyCopyBitmapFromBuffer(self, (byte*)data->m_ptr, data->m_len, format, stride); """) c.addCppMethod('void', 'CopyToBuffer', '(wxPyBuffer* data, wxBitmapBufferFormat format=wxBitmapBufferFormat_RGB, int stride=-1)', doc="""\ Copy pixel data to a buffer object. See :meth:`CopyFromBuffer` for buffer format details.""", body="""\ wxPyCopyBitmapToBuffer(self, (byte*)data->m_ptr, data->m_len, format, stride); """) # Some bitmap factories added as static methods c.addCppMethod('wxBitmap*', 'FromBufferAndAlpha', '(int width, int height, wxPyBuffer* data, wxPyBuffer* alpha)', isStatic=True, factory=True, doc="""\ Creates a :class:`wx.Bitmap` from in-memory data. The data and alpha parameters must be a Python object that implements the buffer interface, such as a string, bytearray, etc. The data object is expected to contain a series of RGB bytes and be at least (width * height * 3) bytes long, while the alpha object is expected to be width*height bytes long and represents the image's alpha channel. On Windows and Mac the RGB values will be 'premultiplied' by the alpha values. (The other platforms do the multiplication themselves.) Unlike :func:`wx.ImageFromBuffer` the bitmap created with this function does not share the memory block with the buffer object. This is because the native pixel buffer format varies on different platforms, and so instead an efficient as possible copy of the data is made from the buffer object to the bitmap's native pixel buffer. """, body="""\ if (!data->checkSize(width*height*3) || !alpha->checkSize(width*height)) return NULL; byte* ddata = (byte*)data->m_ptr; byte* adata = (byte*)alpha->m_ptr; wxBitmap* bmp = new wxBitmap(width, height, 32); wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height)); if (! pixData) { wxPyErr_SetString(PyExc_RuntimeError, "Failed to gain raw access to bitmap data."); return NULL; } wxAlphaPixelData::Iterator p(pixData); for (int y=0; y<height; y++) { wxAlphaPixelData::Iterator rowStart = p; for (int x=0; x<width; x++) { byte a = *(adata++); p.Red() = wxPy_premultiply(*(ddata++), a); p.Green() = wxPy_premultiply(*(ddata++), a); p.Blue() = wxPy_premultiply(*(ddata++), a); p.Alpha() = a; ++p; } p = rowStart; p.OffsetY(pixData, 1); } return bmp; """) c.addCppMethod('wxBitmap*', 'FromBuffer', '(int width, int height, wxPyBuffer* data)', isStatic=True, factory=True, doc="""\ Creates a :class:`wx.Bitmap` from in-memory data. The data parameter must be a Python object that implements the buffer interface, such as a string, bytearray, etc. The data object is expected to contain a series of RGB bytes and be at least (width * height * 3) bytes long. Unlike :func:`wx.ImageFromBuffer` the bitmap created with this function does not share the memory block with the buffer object. This is because the native pixel buffer format varies on different platforms, and so instead an efficient as possible copy of the data is made from the buffer object to the bitmap's native pixel buffer. """, body="""\ wxBitmap* bmp = new wxBitmap(width, height, 24); wxPyCopyBitmapFromBuffer(bmp, (byte*)data->m_ptr, data->m_len, wxBitmapBufferFormat_RGB); wxPyThreadBlocker blocker; if (PyErr_Occurred()) { delete bmp; bmp = NULL; } return bmp; """) module.addPyFunction('BitmapFromBuffer', '(width, height, dataBuffer, alphaBuffer=None)', deprecated="Use :meth:`wx.Bitmap.FromBuffer` or :meth:`wx.Bitmap.FromBufferAndAlpha` instead.", doc='A compatibility wrapper for :meth:`wx.Bitmap.FromBuffer` and :meth:`wx.Bitmap.FromBufferAndAlpha`', body="""\ if alphaBuffer is not None: return Bitmap.FromBufferAndAlpha(width, height, dataBuffer, alphaBuffer) else: return Bitmap.FromBuffer(width, height, dataBuffer) """) c.addCppMethod('wxBitmap*', 'FromBufferRGBA', '(int width, int height, wxPyBuffer* data)', isStatic=True, factory=True, doc="""\ Creates a :class:`wx.Bitmap` from in-memory data. The data parameter must be a Python object that implements the buffer interface, such as a string, bytearray, etc. The data object is expected to contain a series of RGBA bytes and be at least (width * height * 4) bytes long. On Windows and Mac the RGB values will be 'premultiplied' by the alpha values. (The other platforms do the multiplication themselves.) Unlike :func:`wx.ImageFromBuffer` the bitmap created with this function does not share the memory block with the buffer object. This is because the native pixel buffer format varies on different platforms, and so instead an efficient as possible copy of the data is made from the buffer object to the bitmap's native pixel buffer. """, body="""\ wxBitmap* bmp = new wxBitmap(width, height, 32); wxPyCopyBitmapFromBuffer(bmp, (byte*)data->m_ptr, data->m_len, wxBitmapBufferFormat_RGBA); wxPyThreadBlocker blocker; if (PyErr_Occurred()) { delete bmp; bmp = NULL; } return bmp; """) module.addPyFunction('BitmapFromBufferRGBA', '(width, height, dataBuffer)', deprecated="Use :meth:`wx.Bitmap.FromBufferRGBA` instead.", doc='A compatibility wrapper for :meth:`wx.Bitmap.FromBufferRGBA`', body='return Bitmap.FromBufferRGBA(width, height, dataBuffer)') c.addCppMethod('wxBitmap*', 'FromRGBA', '(int width, int height, byte red=0, byte green=0, byte blue=0, byte alpha=0)', isStatic=True, factory=True, doc="""\ Creates a new empty 32-bit :class:`wx.Bitmap` where every pixel has been initialized with the given RGBA values. """, body="""\ if ( !(width > 0 && height > 0) ) { wxPyErr_SetString(PyExc_ValueError, "Width and height must be greater than zero"); return NULL; } wxBitmap* bmp = new wxBitmap(width, height, 32); wxAlphaPixelData pixData(*bmp, wxPoint(0,0), wxSize(width,height)); if (! pixData) { wxPyErr_SetString(PyExc_RuntimeError, "Failed to gain raw access to bitmap data."); return NULL; } wxAlphaPixelData::Iterator p(pixData); for (int y=0; y<height; y++) { wxAlphaPixelData::Iterator rowStart = p; for (int x=0; x<width; x++) { p.Red() = wxPy_premultiply(red, alpha); p.Green() = wxPy_premultiply(green, alpha); p.Blue() = wxPy_premultiply(blue, alpha); p.Alpha() = alpha; ++p; } p = rowStart; p.OffsetY(pixData, 1); } return bmp; """) module.addPyFunction('EmptyBitmapRGBA', '(width, height, red=0, green=0, blue=0, alpha=0)', deprecated="Use :meth:`wx.Bitmap.FromRGBA` instead.", doc='A compatibility wrapper for :meth:`wx.Bitmap.FromRGBA`', body='return Bitmap.FromRGBA(width, height, red, green, blue, alpha)') #----------------------------------------------------------------------- # For compatibility: module.addPyFunction('EmptyBitmap', '(width, height, depth=BITMAP_SCREEN_DEPTH)', deprecated="Use :class:`wx.Bitmap` instead", doc='A compatibility wrapper for the wx.Bitmap(width, height, depth) constructor', body='return Bitmap(width, height, depth)') module.addPyFunction('BitmapFromImage', '(image)', deprecated="Use :class:`wx.Bitmap` instead", doc='A compatibility wrapper for the wx.Bitmap(wx.Image) constructor', body='return Bitmap(image)') #----------------------------------------------------------------- tools.doCommonTweaks(module) tools.runGenerators(module)