diff --git a/buildtools/build_wxwidgets.py b/buildtools/build_wxwidgets.py index 62e1e476..7da3bd02 100644 --- a/buildtools/build_wxwidgets.py +++ b/buildtools/build_wxwidgets.py @@ -405,6 +405,7 @@ def main(wxDir, args): flags["wxUSE_AFM_FOR_POSTSCRIPT"] = "0" flags["wxUSE_DATEPICKCTRL_GENERIC"] = "1" flags["wxUSE_IFF"] = "1" + flags["wxUSE_ACCESSIBILITY"] = "1" # Remove this when Windows XP finally dies, or when there is a # solution for ticket #13116... diff --git a/docs/sphinx/itemToModuleMap.json b/docs/sphinx/itemToModuleMap.json index c1ade90d..ab01f861 100644 --- a/docs/sphinx/itemToModuleMap.json +++ b/docs/sphinx/itemToModuleMap.json @@ -5,6 +5,86 @@ "ACCEL_NORMAL":"wx.", "ACCEL_RAW_CTRL":"wx.", "ACCEL_SHIFT":"wx.", +"ACC_EVENT_OBJECT_ACCELERATORCHANGE":"wx.", +"ACC_EVENT_OBJECT_CREATE":"wx.", +"ACC_EVENT_OBJECT_DEFACTIONCHANGE":"wx.", +"ACC_EVENT_OBJECT_DESCRIPTIONCHANGE":"wx.", +"ACC_EVENT_OBJECT_DESTROY":"wx.", +"ACC_EVENT_OBJECT_FOCUS":"wx.", +"ACC_EVENT_OBJECT_HELPCHANGE":"wx.", +"ACC_EVENT_OBJECT_HIDE":"wx.", +"ACC_EVENT_OBJECT_LOCATIONCHANGE":"wx.", +"ACC_EVENT_OBJECT_NAMECHANGE":"wx.", +"ACC_EVENT_OBJECT_PARENTCHANGE":"wx.", +"ACC_EVENT_OBJECT_REORDER":"wx.", +"ACC_EVENT_OBJECT_SELECTION":"wx.", +"ACC_EVENT_OBJECT_SELECTIONADD":"wx.", +"ACC_EVENT_OBJECT_SELECTIONREMOVE":"wx.", +"ACC_EVENT_OBJECT_SELECTIONWITHIN":"wx.", +"ACC_EVENT_OBJECT_SHOW":"wx.", +"ACC_EVENT_OBJECT_STATECHANGE":"wx.", +"ACC_EVENT_OBJECT_VALUECHANGE":"wx.", +"ACC_EVENT_SYSTEM_ALERT":"wx.", +"ACC_EVENT_SYSTEM_CAPTUREEND":"wx.", +"ACC_EVENT_SYSTEM_CAPTURESTART":"wx.", +"ACC_EVENT_SYSTEM_CONTEXTHELPEND":"wx.", +"ACC_EVENT_SYSTEM_CONTEXTHELPSTART":"wx.", +"ACC_EVENT_SYSTEM_DIALOGEND":"wx.", +"ACC_EVENT_SYSTEM_DIALOGSTART":"wx.", +"ACC_EVENT_SYSTEM_DRAGDROPEND":"wx.", +"ACC_EVENT_SYSTEM_DRAGDROPSTART":"wx.", +"ACC_EVENT_SYSTEM_FOREGROUND":"wx.", +"ACC_EVENT_SYSTEM_MENUEND":"wx.", +"ACC_EVENT_SYSTEM_MENUPOPUPEND":"wx.", +"ACC_EVENT_SYSTEM_MENUPOPUPSTART":"wx.", +"ACC_EVENT_SYSTEM_MENUSTART":"wx.", +"ACC_EVENT_SYSTEM_MINIMIZEEND":"wx.", +"ACC_EVENT_SYSTEM_MINIMIZESTART":"wx.", +"ACC_EVENT_SYSTEM_MOVESIZEEND":"wx.", +"ACC_EVENT_SYSTEM_MOVESIZESTART":"wx.", +"ACC_EVENT_SYSTEM_SCROLLINGEND":"wx.", +"ACC_EVENT_SYSTEM_SCROLLINGSTART":"wx.", +"ACC_EVENT_SYSTEM_SOUND":"wx.", +"ACC_EVENT_SYSTEM_SWITCHEND":"wx.", +"ACC_EVENT_SYSTEM_SWITCHSTART":"wx.", +"ACC_FAIL":"wx.", +"ACC_FALSE":"wx.", +"ACC_NOT_IMPLEMENTED":"wx.", +"ACC_NOT_SUPPORTED":"wx.", +"ACC_OK":"wx.", +"ACC_SELF":"wx.", +"ACC_SEL_ADDSELECTION":"wx.", +"ACC_SEL_EXTENDSELECTION":"wx.", +"ACC_SEL_NONE":"wx.", +"ACC_SEL_REMOVESELECTION":"wx.", +"ACC_SEL_TAKEFOCUS":"wx.", +"ACC_SEL_TAKESELECTION":"wx.", +"ACC_STATE_SYSTEM_ALERT_HIGH":"wx.", +"ACC_STATE_SYSTEM_ALERT_LOW":"wx.", +"ACC_STATE_SYSTEM_ALERT_MEDIUM":"wx.", +"ACC_STATE_SYSTEM_ANIMATED":"wx.", +"ACC_STATE_SYSTEM_BUSY":"wx.", +"ACC_STATE_SYSTEM_CHECKED":"wx.", +"ACC_STATE_SYSTEM_COLLAPSED":"wx.", +"ACC_STATE_SYSTEM_DEFAULT":"wx.", +"ACC_STATE_SYSTEM_EXPANDED":"wx.", +"ACC_STATE_SYSTEM_EXTSELECTABLE":"wx.", +"ACC_STATE_SYSTEM_FLOATING":"wx.", +"ACC_STATE_SYSTEM_FOCUSABLE":"wx.", +"ACC_STATE_SYSTEM_FOCUSED":"wx.", +"ACC_STATE_SYSTEM_HOTTRACKED":"wx.", +"ACC_STATE_SYSTEM_INVISIBLE":"wx.", +"ACC_STATE_SYSTEM_MARQUEED":"wx.", +"ACC_STATE_SYSTEM_MIXED":"wx.", +"ACC_STATE_SYSTEM_MULTISELECTABLE":"wx.", +"ACC_STATE_SYSTEM_OFFSCREEN":"wx.", +"ACC_STATE_SYSTEM_PRESSED":"wx.", +"ACC_STATE_SYSTEM_PROTECTED":"wx.", +"ACC_STATE_SYSTEM_READONLY":"wx.", +"ACC_STATE_SYSTEM_SELECTABLE":"wx.", +"ACC_STATE_SYSTEM_SELECTED":"wx.", +"ACC_STATE_SYSTEM_SELFVOICING":"wx.", +"ACC_STATE_SYSTEM_UNAVAILABLE":"wx.", "AC_DEFAULT_STYLE":"wx.adv.", "AC_NO_AUTORESIZE":"wx.adv.", "ADJUST_MINSIZE":"wx.", @@ -203,9 +283,14 @@ "AboutDialogInfo":"wx.adv.", "Above":"wx.", "Absolute":"wx.", +"AccObject":"wx.", +"AccRole":"wx.", +"AccSelectionFlags":"wx.", +"AccStatus":"wx.", "AcceleratorEntry":"wx.", "AcceleratorEntryFlags":"wx.", "AcceleratorTable":"wx.", +"Accessible":"wx.", "ActivateEvent":"wx.", "AffineMatrix2D":"wx.", "AffineMatrix2DBase":"wx.", @@ -816,7 +901,7 @@ "DirProperty":"wx.propgrid.", "DirSelector":"wx.", "DirSelectorPromptStr":"wx.", -"Direction":"wx.DataObject.", +"Direction":"wx.", "DisableAsserts":"wx.", "Display":"wx.", "DisplayChangedEvent":"wx.", @@ -2346,6 +2431,14 @@ "MultiChoiceDialog":"wx.", "MultiChoiceProperty":"wx.propgrid.", "NAND":"wx.", +"NAVDIR_DOWN":"wx.", +"NAVDIR_FIRSTCHILD":"wx.", +"NAVDIR_LASTCHILD":"wx.", +"NAVDIR_LEFT":"wx.", +"NAVDIR_NEXT":"wx.", +"NAVDIR_PREVIOUS":"wx.", +"NAVDIR_RIGHT":"wx.", +"NAVDIR_UP":"wx.", "NB_BOTTOM":"wx.", "NB_DEFAULT":"wx.", "NB_FIXEDWIDTH":"wx.", @@ -2374,6 +2467,7 @@ "NativeFontInfo":"wx.", "NativePixelData":"wx.", "NativePixelData_Accessor":"wx.", +"NavDir":"wx.", "NavigationKeyEvent":"wx.", "NavigationKeyEventFlags":"wx.NavigationKeyEvent.", "NewEventType":"wx.", @@ -2407,6 +2501,18 @@ "NumberEntryDialog":"wx.", "NumericPropertyValidator":"wx.propgrid.", "NumericType":"wx.propgrid.NumericPropertyValidator.", +"OBJID_ALERT":"wx.", +"OBJID_CARET":"wx.", +"OBJID_CLIENT":"wx.", +"OBJID_CURSOR":"wx.", +"OBJID_HSCROLL":"wx.", +"OBJID_MENU":"wx.", +"OBJID_SIZEGRIP":"wx.", +"OBJID_SOUND":"wx.", +"OBJID_SYSMENU":"wx.", +"OBJID_TITLEBAR":"wx.", +"OBJID_VSCROLL":"wx.", +"OBJID_WINDOW":"wx.", "ODCB_DCLICK_CYCLES":"wx.adv.", "ODCB_PAINTING_CONTROL":"wx.adv.", "ODCB_PAINTING_SELECTED":"wx.adv.", @@ -3231,6 +3337,68 @@ "RICHTEXT_VARIABLE_HEIGHT":"wx.richtext.", "RICHTEXT_VARIABLE_WIDTH":"wx.richtext.", "RIGHT":"wx.", +"ROLE_NONE":"wx.", +"ROLE_SYSTEM_ALERT":"wx.", +"ROLE_SYSTEM_ANIMATION":"wx.", +"ROLE_SYSTEM_APPLICATION":"wx.", +"ROLE_SYSTEM_BORDER":"wx.", +"ROLE_SYSTEM_BUTTONDROPDOWN":"wx.", +"ROLE_SYSTEM_BUTTONDROPDOWNGRID":"wx.", +"ROLE_SYSTEM_BUTTONMENU":"wx.", +"ROLE_SYSTEM_CARET":"wx.", +"ROLE_SYSTEM_CELL":"wx.", +"ROLE_SYSTEM_CHARACTER":"wx.", +"ROLE_SYSTEM_CHART":"wx.", +"ROLE_SYSTEM_CHECKBUTTON":"wx.", +"ROLE_SYSTEM_CLIENT":"wx.", +"ROLE_SYSTEM_CLOCK":"wx.", +"ROLE_SYSTEM_COLUMN":"wx.", +"ROLE_SYSTEM_COLUMNHEADER":"wx.", +"ROLE_SYSTEM_COMBOBOX":"wx.", +"ROLE_SYSTEM_CURSOR":"wx.", +"ROLE_SYSTEM_DIAGRAM":"wx.", +"ROLE_SYSTEM_DIAL":"wx.", +"ROLE_SYSTEM_DIALOG":"wx.", +"ROLE_SYSTEM_DOCUMENT":"wx.", +"ROLE_SYSTEM_DROPLIST":"wx.", +"ROLE_SYSTEM_EQUATION":"wx.", +"ROLE_SYSTEM_GRAPHIC":"wx.", +"ROLE_SYSTEM_GRIP":"wx.", +"ROLE_SYSTEM_GROUPING":"wx.", +"ROLE_SYSTEM_HELPBALLOON":"wx.", +"ROLE_SYSTEM_HOTKEYFIELD":"wx.", +"ROLE_SYSTEM_INDICATOR":"wx.", +"ROLE_SYSTEM_LINK":"wx.", +"ROLE_SYSTEM_LIST":"wx.", +"ROLE_SYSTEM_LISTITEM":"wx.", +"ROLE_SYSTEM_MENUBAR":"wx.", +"ROLE_SYSTEM_MENUITEM":"wx.", +"ROLE_SYSTEM_MENUPOPUP":"wx.", +"ROLE_SYSTEM_OUTLINE":"wx.", +"ROLE_SYSTEM_OUTLINEITEM":"wx.", +"ROLE_SYSTEM_PAGETAB":"wx.", +"ROLE_SYSTEM_PAGETABLIST":"wx.", +"ROLE_SYSTEM_PANE":"wx.", +"ROLE_SYSTEM_PROGRESSBAR":"wx.", +"ROLE_SYSTEM_PROPERTYPAGE":"wx.", +"ROLE_SYSTEM_PUSHBUTTON":"wx.", +"ROLE_SYSTEM_RADIOBUTTON":"wx.", +"ROLE_SYSTEM_ROW":"wx.", +"ROLE_SYSTEM_ROWHEADER":"wx.", +"ROLE_SYSTEM_SCROLLBAR":"wx.", +"ROLE_SYSTEM_SEPARATOR":"wx.", +"ROLE_SYSTEM_SLIDER":"wx.", +"ROLE_SYSTEM_SOUND":"wx.", +"ROLE_SYSTEM_SPINBUTTON":"wx.", +"ROLE_SYSTEM_STATICTEXT":"wx.", +"ROLE_SYSTEM_STATUSBAR":"wx.", +"ROLE_SYSTEM_TABLE":"wx.", +"ROLE_SYSTEM_TEXT":"wx.", +"ROLE_SYSTEM_TITLEBAR":"wx.", +"ROLE_SYSTEM_TOOLBAR":"wx.", +"ROLE_SYSTEM_TOOLTIP":"wx.", +"ROLE_SYSTEM_WHITESPACE":"wx.", +"ROLE_SYSTEM_WINDOW":"wx.", "RadioBox":"wx.", "RadioBoxNameStr":"wx.", "RadioButton":"wx.", @@ -6337,6 +6505,10 @@ "URLDataObject":"wx.", "USER_ATTENTION_ERROR":"wx.", "USER_ATTENTION_INFO":"wx.", +"USE_ACCESSIBILITY":"wx.", +"USE_GLCANVAS":"wx.glcanvas.", +"USE_MEDIACTRL":"wx.media.", +"USE_WEBVIEW":"wx.html2.", "Uint16":"wx.", "Uint32":"wx.", "Uint64":"wx.", diff --git a/etg/_core.py b/etg/_core.py index 40dacc32..c339dd19 100644 --- a/etg/_core.py +++ b/etg/_core.py @@ -69,7 +69,8 @@ INCLUDES = [ # base and core stuff 'position', 'colour', - 'stream', 'filesys', + 'stream', + 'filesys', # GDI and graphics 'image', @@ -101,6 +102,7 @@ INCLUDES = [ # base and core stuff 'rawbmp', # more core + 'access', 'accel', 'log', 'dataobj', diff --git a/etg/_glcanvas.py b/etg/_glcanvas.py index 82594d09..79fb483e 100644 --- a/etg/_glcanvas.py +++ b/etg/_glcanvas.py @@ -62,7 +62,7 @@ def run(): #----------------------------------------------------------------- module.addHeaderCode('#include ') - + tools.generateStubs('wxUSE_GLCANVAS', module) c = module.find('wxGLContext') assert isinstance(c, etgtools.ClassDef) @@ -82,12 +82,12 @@ def run(): c.find('wxGLCanvas').findOverload('const int *attribList').ignore() m = c.addCppCtor_sip( argsString="""( - wxWindow* parent /TransferThis/, - wxWindowID id=wxID_ANY, + wxWindow* parent /TransferThis/, + wxWindowID id=wxID_ANY, wxArrayInt* attribList=NULL, - const wxPoint& pos=wxDefaultPosition, + const wxPoint& pos=wxDefaultPosition, const wxSize& size=wxDefaultSize, - long style=0, + long style=0, const wxString& name="GLCanvas", const wxPalette& palette=wxNullPalette) """, diff --git a/etg/_msw.py b/etg/_msw.py index 2eb84845..16217812 100644 --- a/etg/_msw.py +++ b/etg/_msw.py @@ -29,7 +29,7 @@ ITEMS = [] # remove it from this list of Includes, and change the MODULE value in the # promoted script to be the same as its NAME. -INCLUDES = [#'metafile', +INCLUDES = [ 'axbase', ] @@ -60,7 +60,7 @@ def run(): module.addPyCode("""\ Metafile = wx.deprecated(wx.Metafile, 'Metafile has moved to the core wx module.') - MetafileDC = wx.deprecated(wx.MetafileDC, 'MetafileDC has moved to the core wx module.') + MetafileDC = wx.deprecated(wx.MetafileDC, 'MetafileDC has moved to the core wx module.') """) # ----------------------------------------------------------------- diff --git a/etg/access.py b/etg/access.py new file mode 100644 index 00000000..4147ad66 --- /dev/null +++ b/etg/access.py @@ -0,0 +1,68 @@ +#--------------------------------------------------------------------------- +# Name: etg/access.py +# Author: Robin Dunn +# +# Created: 08-Oct-2018 +# Copyright: (c) 2018 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "access" # Base name of the file to generate to for this script +DOCSTRING = "" + +# The classes and/or the basename of the Doxygen XML files to be processed by +# this script. +ITEMS = [ 'wxAccessible', + ] + +#--------------------------------------------------------------------------- + +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 ') + + tools.generateStubs('wxUSE_ACCESSIBILITY', module, + typeValMap={'wxAccStatus':'wxACC_NOT_IMPLEMENTED'}) + + c = module.find('wxAccessible') + assert isinstance(c, etgtools.ClassDef) + c.addPrivateCopyCtor() + + c.find('GetChild.child').out = True + c.find('GetChildCount.childCount').out = True + c.find('GetDefaultAction.actionName').out = True + c.find('GetDescription.description').out = True + c.find('GetFocus.child').out = True + c.find('GetHelpText.helpText').out = True + c.find('GetKeyboardShortcut.shortcut').out = True + c.find('GetName.name').out = True + c.find('GetParent.parent').out = True + c.find('GetRole.role').out = True + c.find('GetSelections.selections').out = True + c.find('GetState.state').out = True + c.find('GetValue.strValue').out = True + + #TODO: double-check this one + c.find('GetLocation.rect').out = True + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/mediactrl.py b/etg/mediactrl.py index 59b94c8e..b5653dfe 100644 --- a/etg/mediactrl.py +++ b/etg/mediactrl.py @@ -29,12 +29,16 @@ 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. + module.addHeaderCode('#include ') + module.addHeaderCode('#include ') + tools.generateStubs('wxUSE_MEDIACTRL', module, + typeValMap={'wxMediaState': 'wxMEDIASTATE_STOPPED'}) + c = module.find('wxMediaCtrl') c.addPrivateCopyCtor() diff --git a/etg/webview.py b/etg/webview.py index 226c6176..0b9e82cd 100644 --- a/etg/webview.py +++ b/etg/webview.py @@ -43,19 +43,24 @@ def run(): #include #endif """) + module.addHeaderCode('#include ') - module.addGlobalStr('wxWebViewBackendDefault') - module.addGlobalStr('wxWebViewBackendIE') - module.addGlobalStr('wxWebViewBackendWebKit') + module.addGlobalStr('wxWebViewBackendDefault', 0) + module.addGlobalStr('wxWebViewBackendIE', 0) + module.addGlobalStr('wxWebViewBackendWebKit', 0) + module.addGlobalStr('wxWebViewNameStr', 0) + module.addGlobalStr('wxWebViewDefaultURLStr', 0) + + # This tweak is needed only for the stub code + module.find('wxWebViewHandler.wxWebViewHandler').argsString = '(const wxString& scheme="")' + + tools.generateStubs('wxUSE_WEBVIEW', module) c = module.find('wxWebView') assert isinstance(c, etgtools.ClassDef) tools.fixWindowClass(c) c.abstract = True - module.addGlobalStr('wxWebViewNameStr', c) - module.addGlobalStr('wxWebViewDefaultURLStr', c) - for m in c.find('New').all(): m.factory = True c.find('New.id').default = 'wxID_ANY' diff --git a/etg/window.py b/etg/window.py index be481ae6..a6b85e5e 100644 --- a/etg/window.py +++ b/etg/window.py @@ -210,9 +210,24 @@ def run(): """) - # MSW only. Do we want them wrapped? - c.find('GetAccessible').ignore() - c.find('SetAccessible').ignore() + # wxAccessbile is MSW only. Provide a NotImplemented fallback for the + # other platforms. + c.find('GetAccessible').setCppCode("""\ + #if wxUSE_ACCESSIBILITY + return self->GetAccessible(); + #else + wxPyRaiseNotImplemented(); + return NULL; + #endif + """) + c.find('SetAccessible.accessible').transfer = True + c.find('SetAccessible').setCppCode("""\ + #if wxUSE_ACCESSIBILITY + self->SetAccessible(accessible); + #else + wxPyRaiseNotImplemented(); + #endif + """) # Make some of the protected methods visible and overridable from Python c.find('SendDestroyEvent').ignore(False) diff --git a/etgtools/extractors.py b/etgtools/extractors.py index 86627bd7..1302697c 100644 --- a/etgtools/extractors.py +++ b/etgtools/extractors.py @@ -1581,6 +1581,8 @@ class ModuleDef(BaseDef): gv = GlobalVarDef(type='const char*', name=name) if before is None: self.addItem(gv) + elif isinstance(before, int): + self.insertItem(before, gv) else: self.insertItemBefore(before, gv) return gv diff --git a/etgtools/tweaker_tools.py b/etgtools/tweaker_tools.py index a70f3ab8..c8a9e17a 100644 --- a/etgtools/tweaker_tools.py +++ b/etgtools/tweaker_tools.py @@ -1266,3 +1266,174 @@ def guessTypeStr(v): return False #--------------------------------------------------------------------------- +# Tweakers to generate C++ stubs for cases where a feature is optional. By +# generating stubs then we can still provide the wrapper classes but simply +# have them raise NotImplemented errors or whatnot. + +def generateStubs(cppFlag, module, excludes=[], typeValMap={}): + """ + Generate C++ stubs for all items in the module, except those that are + in the optional excludes list. + """ + # First add a define for the cppFlag (like wxUSE_SOME_FEATURE) so the user + # code has a way to check if an optional classis available before using it + # and getting an exception. + assert isinstance(module, extractors.ModuleDef) + if not module.findItem(cppFlag): + module.addItem(extractors.DefineDef(name=cppFlag, value='0')) + excludes.append(cppFlag) + + # Copy incoming typeValMap so it can be updated with some stock types + import copy + typeValMap = copy.copy(typeValMap) + typeValMap.update({ + 'int': '0', + 'bool': 'false', + 'double': '0.0', + 'wxString': 'wxEmptyString', + 'const wxString &': 'wxEmptyString', + 'wxString &': 'wxEmptyString', + 'wxSize': 'wxDefaultSize', + 'wxPoint': 'wxDefaultPosition', + 'wxFileOffset': '0', + }) + + code = _StubCodeHolder(cppFlag) + + # Next add forward declarations of all classes in case they refer to + # each other. + for item in module: + if isinstance(item, extractors.ClassDef): + code.hdr.append('class {};'.format(item.name)) + + # Now write code for all the items in the module. + for item in module: + if item.name in excludes: + continue + + dispatchMap = { + extractors.DefineDef : _generateDefineStub, + extractors.GlobalVarDef : _generateGlobalStub, + extractors.EnumDef : _generateEnumStub, + extractors.ClassDef : _generateClassStub, + extractors.PyCodeDef : _ignore, + } + func = dispatchMap.get(type(item), None) + if func is None: + print('WARNING: Unable to generate stub for {}, type {}'.format( + item.name, type(item))) + else: + func(code, item, typeValMap) + + # Add the code to the module header + module.addHeaderCode(code.renderHdr()) + if code.cpp: + # and possibly the module's C++ file + module.addCppCode(code.renderCpp()) + + +# A simple class for holding lists of code snippets for the header and +# possibily the C++ file. +class _StubCodeHolder: + def __init__(self, flag): + self.flag = flag + self.hdr = [] + self.cpp = [] + + def renderHdr(self): + return self.doRender(self.hdr) + + def renderCpp(self): + return self.doRender(self.cpp) + + def doRender(self, lst): + if not lst: + return '' + code = ('#if !{}\n'.format(self.flag) + + '\n'.join(lst) + + '\n#endif //!{}\n'.format(self.flag)) + return code + + + +def _ignore(*args): + pass + + +def _generateDefineStub(code, define, typeValMap): + code.hdr.append('#define {} {}'.format(define.name, define.value)) + + +def _generateGlobalStub(code, glob, typeValMap): + code.hdr.append('extern {} {};'.format(glob.type, glob.name)) + code.cpp.append('{} {};'.format(glob.type, glob.name)) + + +def _generateEnumStub(code, enum, typeValMap): + name = '' if enum.name.startswith('@') else enum.name + code.hdr.append('\nenum {} {{'.format(name)) + for item in enum: + code.hdr.append(' {},'.format(item.name)) + code.hdr.append('};') + + +def _generateClassStub(code, klass, typeValMap): + if not klass.bases: + code.hdr.append('\nclass {} {{'.format(klass.name)) + else: + code.hdr.append('\nclass {} : {} {{'.format(klass.name, + ', '.join(['public ' + base for base in klass.bases]))) + code.hdr.append('public:') + + for item in klass: + dispatchMap = { + extractors.MethodDef : _generateMethodStub, + } + func = dispatchMap.get(type(item), None) + if func is None: + print('WARNING: Unable to generate stub for {}.{}, type {}'.format( + klass.name, item.name, type(item))) + else: + func(code, item, typeValMap) + + code.hdr.append('};') + + +def _generateMethodStub(code, method, typeValMap): + assert isinstance(method, extractors.MethodDef) + decl = ' ' + if method.isVirtual: + decl += 'virtual ' + if method.isStatic: + decl += 'static ' + if method.isCtor or method.isDtor: + decl += '{}'.format(method.name) + else: + decl += '{} {}'.format(method.type, method.name) + decl += method.argsString + if method.isPureVirtual: + decl += ';' + code.hdr.append(decl) + + if not method.isPureVirtual: + impl = ' { ' + if method.isCtor or method.isStatic: + impl += 'wxPyRaiseNotImplemented(); ' + + if not (method.isCtor or method.isDtor): + if not method.type == 'void': + rval = typeValMap.get(method.type, None) + if rval is None and '*' in method.type: + rval = 'NULL' + if rval is None: + print("WARNING: I don't know how to return a '{}' value.".format(method.type)) + rval = '0' + impl += 'return {}; '.format(rval) + + impl += '}\n' + code.hdr.append(impl) + + for overload in method.overloads: + _generateMethodStub(code, overload, typeValMap) + +#--------------------------------------------------------------------------- diff --git a/unittests/test_access.py b/unittests/test_access.py new file mode 100644 index 00000000..716bacce --- /dev/null +++ b/unittests/test_access.py @@ -0,0 +1,16 @@ +import unittest +from unittests import wtc +import wx + +#--------------------------------------------------------------------------- + +class access_Tests(wtc.WidgetTestCase): + + # TODO: Remove this test and add real ones. + def test_access1(self): + self.fail("Unit tests for access not implemented yet.") + +#--------------------------------------------------------------------------- + +if __name__ == '__main__': + unittest.main()