From 4219e024402f517c34d89dba1468d44061e10af4 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Sat, 3 Sep 2011 01:42:42 +0000 Subject: [PATCH] * move wxPen to etg/pen.py * move wxBrush to etg/brush.py * move wxBookCtrlBase and wxBookCtrlEvent to etg/bookctrl.py * move wxBitmapButton to etg/bmpbuttn.py * move wxArrayString MappedType and add wxArrayInt plus some unittests * add checking for default values for pos and size parameters in fixWindowClass * set out parameter flags for wxImageHistogram.FindFirstUnusedColour * Restore layout constraints classes and related methods * Create a MappedType for wxClientData * update used of wxClientData in wx.CommandEvent * Move wxControlWithItems, wxItemContainer and wxControlWithItems to etg/ctrlsub.py * enable some Append, Insert and Set overloads in wxControlWithItems * addGetterSetterProps: don't make setter-only properties * addGetterSetterProps: ensure that the getter can be called with zero args * addGetterSetterProps: ensure that the setter can be called with just 1 arg * restore version checking code * moved DC classes to other etg files to match interface file names. * allow both overloads for wx.DC.GetTextExtent and GetMultiLineTextExtent by renaming 1 * add wx.DC.GetPartialTextExtents * and some other stuff git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@68975 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- TODO.txt | 114 +++++++++++++++++++++ buildtools/distutils_hacks.py | 2 +- etg/_core.py | 37 +++++-- etg/bitmap.py | 4 + etg/bmpbuttn.py | 50 +++++++++ etg/bookctrl.py | 48 +++++++++ etg/brush.py | 62 +++++++++++ etg/button.py | 14 +-- etg/choice.py | 4 - etg/collpane.py | 4 +- etg/control.py | 27 ++--- etg/ctrlsub.py | 88 ++++++++++++++++ etg/dc.py | 59 ++++------- etg/dcbuffer.py | 56 ++++++++++ etg/dcclient.py | 55 ++++++++++ etg/dcgraph.py | 46 +++++++++ etg/dcmemory.py | 46 +++++++++ etg/dcmirror.py | 46 +++++++++ etg/dcprint.py | 46 +++++++++ etg/dcps.py | 46 +++++++++ etg/dcscreen.py | 46 +++++++++ etg/dcsvg.py | 46 +++++++++ etg/event.py | 31 ++---- etg/gdicmn.py | 41 +------- etg/image.py | 5 + etg/notebook.py | 13 +-- etg/panel.py | 4 +- etg/pen.py | 80 +++++++++++++++ etg/template.py | 2 +- etg/window.py | 12 +-- etgtools/extractors.py | 103 +++++++++++-------- etgtools/tweaker_tools.py | 16 ++- sip/cpp/README.txt | 3 + sip/gen/README.txt | 2 + src/arrays.sip | 187 ++++++++++++++++++++++++++++++++++ src/clntdata.sip | 38 ++++++- src/core_ex.py | 20 ++-- src/event_ex.py | 1 - src/string.sip | 56 +--------- unittests/runtests.py | 1 + unittests/test_app.py | 3 + unittests/test_arrayint.py | 27 +++++ unittests/test_arraystring.py | 31 ++++++ unittests/test_gdicmn.py | 8 +- 44 files changed, 1349 insertions(+), 281 deletions(-) create mode 100644 TODO.txt create mode 100644 etg/bmpbuttn.py create mode 100644 etg/bookctrl.py create mode 100644 etg/brush.py create mode 100644 etg/ctrlsub.py create mode 100644 etg/dcbuffer.py create mode 100644 etg/dcclient.py create mode 100644 etg/dcgraph.py create mode 100644 etg/dcmemory.py create mode 100644 etg/dcmirror.py create mode 100644 etg/dcprint.py create mode 100644 etg/dcps.py create mode 100644 etg/dcscreen.py create mode 100644 etg/dcsvg.py create mode 100644 etg/pen.py create mode 100644 src/arrays.sip create mode 100644 unittests/test_arrayint.py create mode 100644 unittests/test_arraystring.py diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 00000000..3883c9b8 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,114 @@ +Phoenix TODO List +================= + +This is just a place for me to jot down things as I think of them. +The items are in no particular order, and the fact that something is +on this list does not mean that it will ever actually be done. +Additionally, no meaning should be attached to items being removed +from this file, it could mean that items have been done or just that +I've decided that they will not be done or no longer apply. + + + +For all new etg files +--------------------- + * Use a filename that matches the wxWidgets/interface/wx file name + that the classes and other stuff is being loaded from. This + means that there will be lots of very small files in etg, but it + will help to find the interface header source to compare what is + being declared there with what is being generated and to better + understand what may need tweaked in the etg script file. + * Check for extras added to the class in Classic wxPython and + evaluate whether the same extras should be added to the Phoenix + verison. + * Check for backwards compatibility issues with Classic wxPython + and document in the MigrationGuide. (This file is still in the + Classic wxPython source tree.) + * For window classes check if there are other virtual methods + besides those added in addWindowVirtuals() that should also be + added back. + * UNITTESTS! At least check that every class can be constructed. + + +Handling the GIL +---------------- +Currenlty nothing is set for how to deal with the GIL, so there is no +release and reaquire happening yet, meaning that threads will be +blocked while control is in the C++ code. There are some +possibilities to be considered. + + * Classic wxPython would wrap **every** call to a C++ function in + GIL release/reaquire code. Later on I added the ability to not + do that for specific classes or methods (those known to not + block, take a "long" time, or that could result in a callback.) + This likely missed many places that could have benefitted from + not dealing with the GIL. Should the same approach be taken + with Phoenix? Or should the default be to not release/aquire + the GIL and we'll have to turn it on for classes or functions + that need it? If so we could automatically turn it on for + Window classes and that would probably take care of most of the + places that must have it. + + * Take a look at what SIP does when it makes callbacks for virtual + methods. We'll need to do the same thing in the EventThunker + and anywhere else that we're doing callbacks ourselves. NOTE: + Currently there is some Classic code alread in use there. I + need to at least verify that it is doing the right thing... + + * Can we reuse the GIL handling functions from Classic wxPython or + do they need to be rewritten? + + +Exceptions +---------- + * Can we convert C++ exceptions to Python exceptions? + * Can we propagate Python exceptions over C++ blocks? + * Should we? (Classic doesn't.) + + +build.py +-------- + * Get Kevin's wscript? + * Change from using a --waf option to being a "waf" command like + the other build.py commands, and assume that any other items on + the command line after the waf command are to be passed on the + waf command line when it is run. If there are not any other + items on the command line then use a default set of waf + commands. + + +etg/gdicmn.py +------------- + * I've never liked the x,y properties on a wxSize... + + +wx interface files +------------------- + * commit my layout.h on the trunk + * also Kevin's interface files patch + + +etg/window.py +------------- + * Do we really want to keep the SetDimensions alias when we have a + working overload of SetSize? + * Keep the PyWindow alias? Just deprecate it? Discuss on + wxPython-dev. Do the same for PyPanel, PySizer, PyControl, etc. + + +etg/pen.py +---------- + * Add new implementations of Get|SetDashes that use wxArrayInt. + SetDashes will likely need some black magic like what was done in + Classic wxPython. + + +etg/menu.py +------------ + * Move wxMenuItem to its own etg file + * We should be able to support GetMenuItems + * wxMenuBar::FindItem as well. + * Figure out what to do about the MSW-only methods in wxMenuItem + + + diff --git a/buildtools/distutils_hacks.py b/buildtools/distutils_hacks.py index c3909385..d44ff58a 100644 --- a/buildtools/distutils_hacks.py +++ b/buildtools/distutils_hacks.py @@ -177,7 +177,7 @@ def _darwin_compiler_fixup(compiler_so, cc_args): stripArch = stripSysroot = True else: stripArch = '-arch' in cc_args - stripSysroot = '-isysroot' in cc_args or stripArch + stripSysroot = '-isysroot' in cc_args or stripArch or ccHasSysroot if stripArch: while 1: diff --git a/etg/_core.py b/etg/_core.py index 8f6d73ac..bd628f57 100644 --- a/etg/_core.py +++ b/etg/_core.py @@ -31,6 +31,7 @@ ITEMS = [ ] INCLUDES = [ 'defs', 'wxpy_utils', 'string', + 'arrays', 'clntdata', 'windowid', 'platinfo', @@ -38,21 +39,34 @@ INCLUDES = [ 'defs', 'vidmode', 'intl', - 'gdiobj', - 'bitmap', - 'font', - 'image', - 'region', - + 'object', 'gdicmn', 'geometry', - 'object', + 'image', + 'gdiobj', + 'bitmap', + 'font', + 'pen', + 'brush', + 'region', + 'dc', + 'dcclient', + 'dcmemory', + 'dcbuffer', + 'dcscreen', + #'dcgraph', # TODO: needs wxGaphicsContext + 'dcmirror', + #'dcprint', # TODO: needs wxPrintData + #'dcps', # TODO: needs wxPrintData + 'dcsvg', + 'colour', 'tracker', 'kbdstate', 'mousestate', 'tooltip', + 'layout', 'event', 'pyevent', 'process', @@ -73,15 +87,18 @@ INCLUDES = [ 'defs', 'statbmp', 'stattext', 'control', + 'ctrlsub', 'choice', - 'dc', 'button', + 'bmpbuttn', + 'bookctrl', 'notebook', 'imagelist', 'splitter', 'collpane', 'statline', - 'stdpaths', + 'stdpaths', + ] @@ -257,6 +274,8 @@ void wxPyCoreModuleInject(PyObject* moduleDict) #else _AddInfoString("wx-assertions-off"); #endif + _AddInfoString("phoenix"); + #undef _AddInfoString PyObject* PortInfoTuple = PyList_AsTuple(PortInfo); diff --git a/etg/bitmap.py b/etg/bitmap.py index 8f667b72..b6023280 100644 --- a/etg/bitmap.py +++ b/etg/bitmap.py @@ -31,6 +31,10 @@ def run(): # customizing the generated code and docstrings. c = module.find('wxBitmap') + assert isinstance(c, etgtools.ClassDef) + + tools.removeVirtuals(c) + c.find('wxBitmap').findOverload('(const char *const *bits)').ignore() c.find('wxBitmap.type').default = 'wxBITMAP_TYPE_ANY' c.find('GetHandlers').ignore() diff --git a/etg/bmpbuttn.py b/etg/bmpbuttn.py new file mode 100644 index 00000000..5dfab422 --- /dev/null +++ b/etg/bmpbuttn.py @@ -0,0 +1,50 @@ +#--------------------------------------------------------------------------- +# Name: etg/bmpbuttn.py +# Author: Robin Dunn +# +# Created: 31-Aug-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "bmpbuttn" # 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 = [ 'wxBitmapButton' ] + +#--------------------------------------------------------------------------- + +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('wxBitmapButton') + c.find('wxBitmapButton.bitmap').default = 'wxNullBitmap' + c.find('Create.bitmap').default = 'wxNullBitmap' + + tools.fixWindowClass(c) + tools.removeVirtuals(c) + tools.addWindowVirtuals(c) + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/bookctrl.py b/etg/bookctrl.py new file mode 100644 index 00000000..531abed5 --- /dev/null +++ b/etg/bookctrl.py @@ -0,0 +1,48 @@ +#--------------------------------------------------------------------------- +# Name: etg/bookctrl.py +# Author: Robin Dunn +# +# Created: 31-Aug-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "bookctrl" # 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 = [ 'wxBookCtrlBase', + 'wxBookCtrlEvent', + ] + +#--------------------------------------------------------------------------- + +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('wxBookCtrlBase') + assert isinstance(c, etgtools.ClassDef) + c.abstract = True + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/brush.py b/etg/brush.py new file mode 100644 index 00000000..5eaa4f03 --- /dev/null +++ b/etg/brush.py @@ -0,0 +1,62 @@ +#--------------------------------------------------------------------------- +# Name: etg/brush.py +# Author: Robin Dunn +# +# Created: +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "brush" # 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 = [ 'wxBrush' ] + +#--------------------------------------------------------------------------- + +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) + + # TODO: Fix these. I'm not sure why exactly, but in the CPP code + # they end up with the wrong signature. + module.find('wxBLUE_BRUSH').ignore() + module.find('wxGREEN_BRUSH').ignore() + module.find('wxYELLOW_BRUSH').ignore() + module.find('wxWHITE_BRUSH').ignore() + module.find('wxBLACK_BRUSH').ignore() + module.find('wxGREY_BRUSH').ignore() + module.find('wxMEDIUM_GREY_BRUSH').ignore() + module.find('wxLIGHT_GREY_BRUSH').ignore() + module.find('wxTRANSPARENT_BRUSH').ignore() + module.find('wxCYAN_BRUSH').ignore() + module.find('wxRED_BRUSH').ignore() + + module.find('wxTheBrushList').ignore() + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/button.py b/etg/button.py index f9b08f99..ae14cc79 100644 --- a/etg/button.py +++ b/etg/button.py @@ -17,10 +17,7 @@ DOCSTRING = "" # The classes and/or the basename of the Doxygen XML files to be processed by # this script. -ITEMS = [ - 'wxBitmapButton', - 'wxButton' - ] +ITEMS = [ 'wxButton' ] #--------------------------------------------------------------------------- @@ -33,17 +30,8 @@ def run(): # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. - c = module.find('wxBitmapButton') - c.find('wxBitmapButton.bitmap').default = 'wxNullBitmap' - c.find('Create.bitmap').default = 'wxNullBitmap' - tools.fixWindowClass(c) - - tools.removeVirtuals(c) - tools.addWindowVirtuals(c) - c = module.find('wxButton') tools.fixWindowClass(c) - tools.removeVirtuals(c) tools.addWindowVirtuals(c) diff --git a/etg/choice.py b/etg/choice.py index 9b5a8e8f..e94cf929 100644 --- a/etg/choice.py +++ b/etg/choice.py @@ -33,13 +33,9 @@ def run(): c = module.find('wxChoice') c.abstract = False c.find('wxChoice').findOverload('wxString choices').ignore() - c.find('wxChoice').findOverload('wxArrayString').find('size').default = 'wxDefaultSize' - c.find('wxChoice').findOverload('wxArrayString').find('pos').default = 'wxDefaultPosition' c.find('wxChoice').findOverload('wxArrayString').find('choices').default = 'wxArrayString()' c.find('Create').findOverload('wxString choices').ignore() - c.find('Create').findOverload('wxArrayString').find('size').default = 'wxDefaultSize' - c.find('Create').findOverload('wxArrayString').find('pos').default = 'wxDefaultPosition' c.find('Create').findOverload('wxArrayString').find('choices').default = 'wxArrayString()' tools.fixWindowClass(c) diff --git a/etg/collpane.py b/etg/collpane.py index faa542a1..f789ee5a 100644 --- a/etg/collpane.py +++ b/etg/collpane.py @@ -1,5 +1,5 @@ #--------------------------------------------------------------------------- -# Name: etg/notebook.py +# Name: etg/collpane.py # Author: Kevin Ollivier # # Created: 27-Aug-2011 @@ -34,6 +34,8 @@ def run(): # customizing the generated code and docstrings. module.addHeaderCode("#include ") + module.addPyCode( + "EVT_COLLAPSIBLEPANE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_COLLPANE_CHANGED )") c = module.find('wxCollapsiblePane') c.find('wxCollapsiblePane.label').default = 'wxEmptyString' diff --git a/etg/control.py b/etg/control.py index a53356bc..23f9db8c 100644 --- a/etg/control.py +++ b/etg/control.py @@ -1,5 +1,5 @@ #--------------------------------------------------------------------------- -# Name: etg/statbmp.py +# Name: etg/control.py # Author: Kevin Ollivier # # Created: 26-Aug-2011 @@ -17,7 +17,7 @@ DOCSTRING = "" # The classes and/or the basename of the Doxygen XML files to be processed by # this script. -ITEMS = [ 'wxControl', 'wxControlWithItems', 'wxItemContainer', 'wxItemContainerImmutable', ] +ITEMS = [ 'wxControl', ] #--------------------------------------------------------------------------- @@ -30,22 +30,13 @@ def run(): # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. - c = module.find('wxControlWithItems') - c.abstract = True - - c = module.find('wxItemContainer') - c.abstract = True - c.find('Append').overloads = [] - c.find('Insert').overloads = [] - c.find('Set').overloads = [] - - c.find('DetachClientObject').ignore() - c.find('GetClientObject').ignore() - c.find('SetClientObject').ignore() - - c = module.find('wxItemContainerImmutable') - c.abstract = True - + c = module.find('wxControl') + assert isinstance(c, etgtools.ClassDef) + + tools.fixWindowClass(c) + tools.removeVirtuals(c) + tools.addWindowVirtuals(c) + module.addPyCode("PyControl = Control") #----------------------------------------------------------------- diff --git a/etg/ctrlsub.py b/etg/ctrlsub.py new file mode 100644 index 00000000..c9429d81 --- /dev/null +++ b/etg/ctrlsub.py @@ -0,0 +1,88 @@ +#--------------------------------------------------------------------------- +# Name: etg/strlsub.py +# Author: Robin Dunn +# +# Created: 2-Sept-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "ctrlsub" # 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 = [ 'wxItemContainerImmutable', 'wxItemContainer', 'wxControlWithItems', ] + +#--------------------------------------------------------------------------- + +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('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: + 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 + # woiuld be virtually the same anyway. + c.find('GetClientData').ignore() + c.find('SetClientData').ignore() + c.addPyCode("""\ + ItemContainer.GetClientData = ItemContainer.GetClientObject + ItemContainer.SetClientData = ItemContainer.SetClientObject""") + + # 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 + + c = module.find('wxControlWithItems') + c.abstract = True + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/dc.py b/etg/dc.py index 2d643709..f68f45c8 100644 --- a/etg/dc.py +++ b/etg/dc.py @@ -17,16 +17,7 @@ DOCSTRING = "" # The classes and/or the basename of the Doxygen XML files to be processed by # this script. -ITEMS = [ 'wxAutoBufferedPaintDC', - 'wxBufferedDC', - 'wxBufferedPaintDC', - 'wxDC', - 'wxClientDC', - 'wxMemoryDC', - 'wxPaintDC', - 'wxScreenDC', - 'wxWindowDC', - ] +ITEMS = [ 'wxDC' ] #--------------------------------------------------------------------------- @@ -39,45 +30,39 @@ def run(): # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. - c = module.find('wxAutoBufferedPaintDC') - c.addPrivateCopyCtor() - - c = module.find('wxBufferedDC') - c.addPrivateCopyCtor() - - c = module.find('wxBufferedPaintDC') - c.addPrivateCopyCtor() - - + c = module.find('wxDC') + assert isinstance(c, etgtools.ClassDef) + c.addPrivateCopyCtor() - c.find('GetMultiLineTextExtent').overloads = [] - c.find('GetTextExtent').overloads = [] - c.find('GetSize').overloads = [] - c.find('GetSizeMM').overloads = [] + tools.removeVirtuals(c) + + # rename the more complex overload for these two, like in classic wxPython + c.find('GetTextExtent').findOverload('wxCoord *').pyName = 'GetFullTextExtent' + c.find('GetMultiLineTextExtent').findOverload('wxCoord *').pyName = 'GetFullMultiLineTextExtent' + + # Switch this one to return the array instead of passing it through an arg + c.find('GetPartialTextExtents').ignore() + c.addCppMethod('wxArrayInt', 'GetPartialTextExtents', '(const wxString& text)', """\ + wxArrayInt rval; + self->GetPartialTextExtents(*text, rval); + return rval;""") + + + # Keep the wxSize overloads of these + c.find('GetSize').findOverload('wxCoord').ignore() + c.find('GetSizeMM').findOverload('wxCoord').ignore() # needs wxAffineMatrix2D support. c.find('GetTransformMatrix').ignore() c.find('SetTransformMatrix').ignore() - - # TODO: restore this once we add wxArrayInt type map - c.find('GetPartialTextExtents').ignore() - - # TODO: add wxFloodFillStyle type map - c.find('FloodFill').ignore() - c.find('FloodFill').findOverload('int style').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('DrawPolyPolygon').findOverload('wxPoint points').ignore() c.find('DrawSpline').findOverload('wxPoint points').ignore() - c = module.find('wxClientDC') - c.addPrivateCopyCtor() - - c = module.find('wxWindowDC') - c.addPrivateCopyCtor() #----------------------------------------------------------------- tools.doCommonTweaks(module) diff --git a/etg/dcbuffer.py b/etg/dcbuffer.py new file mode 100644 index 00000000..0b1ca78d --- /dev/null +++ b/etg/dcbuffer.py @@ -0,0 +1,56 @@ +#--------------------------------------------------------------------------- +# Name: etg/dcbuffer.h +# Author: Robin Dunn +# +# Created: 2-Sept-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "dcbuffer" # 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 = [ 'wxBufferedDC', + 'wxAutoBufferedPaintDC', + 'wxBufferedPaintDC', + ] + +#--------------------------------------------------------------------------- + +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('wxBufferedDC') + c.addPrivateCopyCtor() + + c = module.find('wxAutoBufferedPaintDC') + c.addPrivateCopyCtor() + + c = module.find('wxBufferedPaintDC') + c.addPrivateCopyCtor() + + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/dcclient.py b/etg/dcclient.py new file mode 100644 index 00000000..8e955dc2 --- /dev/null +++ b/etg/dcclient.py @@ -0,0 +1,55 @@ +#--------------------------------------------------------------------------- +# Name: etg/dcclient.py +# Author: Robin Dunn +# +# Created: 2-Sept-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "dcclient" # 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 = [ 'wxPaintDC', + 'wxClientDC', + 'wxWindowDC', + ] + +#--------------------------------------------------------------------------- + +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('wxPaintDC') + c.addPrivateCopyCtor() + + c = module.find('wxClientDC') + c.addPrivateCopyCtor() + + c = module.find('wxWindowDC') + c.addPrivateCopyCtor() + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/dcgraph.py b/etg/dcgraph.py new file mode 100644 index 00000000..85c50327 --- /dev/null +++ b/etg/dcgraph.py @@ -0,0 +1,46 @@ +#--------------------------------------------------------------------------- +# Name: etg/dcgraph.py +# Author: Robin Dunn +# +# Created: 2-Sept-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "dcgraph" # 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 = [ 'wxGCDC' ] + +#--------------------------------------------------------------------------- + +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('wxGCDC') + c.addPrivateCopyCtor() + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/dcmemory.py b/etg/dcmemory.py new file mode 100644 index 00000000..43c9f74a --- /dev/null +++ b/etg/dcmemory.py @@ -0,0 +1,46 @@ +#--------------------------------------------------------------------------- +# Name: etg/dcmemory.py +# Author: Robin Dunn +# +# Created: 2-Sept-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "dcmemory" # 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 = [ 'wxMemoryDC' ] + +#--------------------------------------------------------------------------- + +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('wxMemoryDC') + c.addPrivateCopyCtor() + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/dcmirror.py b/etg/dcmirror.py new file mode 100644 index 00000000..c91f6bc3 --- /dev/null +++ b/etg/dcmirror.py @@ -0,0 +1,46 @@ +#--------------------------------------------------------------------------- +# Name: etg/dcmirror.py +# Author: Robin Dunn +# +# Created: 2-Sept-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "dcmirror" # 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 = [ 'wxMirrorDC' ] + +#--------------------------------------------------------------------------- + +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('wxMirrorDC') + c.addPrivateCopyCtor() + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/dcprint.py b/etg/dcprint.py new file mode 100644 index 00000000..6b4b2f6a --- /dev/null +++ b/etg/dcprint.py @@ -0,0 +1,46 @@ +#--------------------------------------------------------------------------- +# Name: etg/dcprint.py +# Author: Robin Dunn +# +# Created: 2-Sept-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "dcprint" # 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 = [ 'wxPrinterDC' ] + +#--------------------------------------------------------------------------- + +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('wxPrinterDC') + c.addPrivateCopyCtor() + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/dcps.py b/etg/dcps.py new file mode 100644 index 00000000..8f6a317f --- /dev/null +++ b/etg/dcps.py @@ -0,0 +1,46 @@ +#--------------------------------------------------------------------------- +# Name: etg/dcps.py +# Author: Robin Dunn +# +# Created: 2-Sept-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "dcps" # 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 = [ 'wxPostScriptDC' ] + +#--------------------------------------------------------------------------- + +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('wxPostScriptDC') + c.addPrivateCopyCtor() + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/dcscreen.py b/etg/dcscreen.py new file mode 100644 index 00000000..fdd9bed7 --- /dev/null +++ b/etg/dcscreen.py @@ -0,0 +1,46 @@ +#--------------------------------------------------------------------------- +# Name: etg/dcscreen.py +# Author: Robin Dunn +# +# Created: 2-Sept-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "dcscreen" # 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 = [ 'wxScreenDC' ] + +#--------------------------------------------------------------------------- + +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('wxScreenDC') + c.addPrivateCopyCtor() + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/dcsvg.py b/etg/dcsvg.py new file mode 100644 index 00000000..a12b98a0 --- /dev/null +++ b/etg/dcsvg.py @@ -0,0 +1,46 @@ +#--------------------------------------------------------------------------- +# Name: etg/dcsvg.py +# Author: Robin Dunn +# +# Created: 2-Sept-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "dcsvg" # 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 = [ 'wxSVGFileDC' ] + +#--------------------------------------------------------------------------- + +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('wxSVGFileDC') + c.addPrivateCopyCtor() + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/event.py b/etg/event.py index 4c3db20d..284a0829 100644 --- a/etg/event.py +++ b/etg/event.py @@ -25,7 +25,6 @@ ITEMS = [ 'wxCommandEvent', 'wxActivateEvent', - 'wxBookCtrlEvent', 'wxChildFocusEvent', 'wxClipboardTextEvent', 'wxCloseEvent', @@ -86,8 +85,6 @@ def run(): #endif """) - module.addHeaderCode("#include ") - # Macros module.find('wx__DECLARE_EVT0').ignore() module.find('wx__DECLARE_EVT1').ignore() @@ -213,29 +210,15 @@ def run(): # wxCommandEvent c = module.find('wxCommandEvent') - c.find('GetClientObject').ignore() - c.find('SetClientObject').ignore() c.find('GetClientData').ignore() c.find('SetClientData').ignore() - - c.addCppMethod('PyObject*', 'GetClientData', '()', """\ - wxPyClientData* data = (wxPyClientData*)self->GetClientObject(); - if (data) { - Py_INCREF(data->m_obj); - return data->m_obj; - } else { - Py_INCREF(Py_None); - return Py_None; - } - """) - - c.addCppMethod('void', 'SetClientData', '(PyObject* clientData)', """\ - wxPyClientData* data = new wxPyClientData(clientData); - self->SetClientObject(data); - """) - - - c.addProperty('ClientData GetClientData SetClientData') + + c.addPyCode("""\ + CommandEvent.GetClientData = CommandEvent.GetClientObject + CommandEvent.SetClientData = CommandEvent.SetClientObject""") + + c.addProperty('ClientObject GetClientObject SetClientObject') + c.addPyCode('CommandEvent.ClientData = CommandEvent.ClientObject') c.addProperty('ExtraLong GetExtraLong SetExtraLong') c.addProperty('Int GetInt SetInt') c.addProperty('Selection GetSelection') diff --git a/etg/gdicmn.py b/etg/gdicmn.py index d2a3be5c..4a746104 100644 --- a/etg/gdicmn.py +++ b/etg/gdicmn.py @@ -17,10 +17,7 @@ DOCSTRING = "" # The classes and/or the basename of the Doxygen XML files to be processed by # this script. -ITEMS = [ - 'wxBrush', - 'wxPen', - 'wxPoint', +ITEMS = [ 'wxPoint', 'wxSize', 'wxRect', 'wxRealPoint', @@ -304,42 +301,6 @@ def run(): """) c.addPyCode('RealPoint.__safe_for_unpickling__ = True') - c = module.find('wxPen') - # TODO: Add back when we add a wxDash typedef - c.find('GetDashes').ignore() - c.find('SetDashes').ignore() - - # TODO: Fix these. I'm not sure why exactly, but in the CPP code - # they end up with the wrong signature. - module.find('wxRED_PEN').ignore() - module.find('wxBLUE_PEN').ignore() - module.find('wxCYAN_PEN').ignore() - module.find('wxGREEN_PEN').ignore() - module.find('wxYELLOW_PEN').ignore() - module.find('wxBLACK_PEN').ignore() - module.find('wxWHITE_PEN').ignore() - module.find('wxTRANSPARENT_PEN').ignore() - module.find('wxBLACK_DASHED_PEN').ignore() - module.find('wxGREY_PEN').ignore() - module.find('wxMEDIUM_GREY_PEN').ignore() - module.find('wxLIGHT_GREY_PEN').ignore() - - module.find('wxBLUE_BRUSH').ignore() - module.find('wxGREEN_BRUSH').ignore() - module.find('wxYELLOW_BRUSH').ignore() - module.find('wxWHITE_BRUSH').ignore() - module.find('wxBLACK_BRUSH').ignore() - module.find('wxGREY_BRUSH').ignore() - module.find('wxMEDIUM_GREY_BRUSH').ignore() - module.find('wxLIGHT_GREY_BRUSH').ignore() - module.find('wxTRANSPARENT_BRUSH').ignore() - module.find('wxCYAN_BRUSH').ignore() - module.find('wxRED_BRUSH').ignore() - - module.find('wxTheBrushList').ignore() - module.find('wxThePenList').ignore() - #module.addItem(tools.wxListWrapperTemplate('wxBrushList', 'wxBrush')) - #module.addItem(tools.wxListWrapperTemplate('wxPenList', 'wxPen')) module.addItem(tools.wxListWrapperTemplate('wxPointList', 'wxPoint')) #----------------------------------------------------------------- diff --git a/etg/image.py b/etg/image.py index 6d341a14..41475a2b 100644 --- a/etg/image.py +++ b/etg/image.py @@ -38,6 +38,11 @@ def run(): c.find('RGBtoHSV').ignore() c.find('HSVtoRGB').ignore() + f = module.find('wxImageHistogram.FindFirstUnusedColour') + f.find('r').out = True + f.find('g').out = True + f.find('b').out = True + #----------------------------------------------------------------- tools.doCommonTweaks(module) diff --git a/etg/notebook.py b/etg/notebook.py index 4b481f5d..76839c46 100644 --- a/etg/notebook.py +++ b/etg/notebook.py @@ -17,10 +17,7 @@ DOCSTRING = "" # The classes and/or the basename of the Doxygen XML files to be processed by # this script. -ITEMS = [ - 'wxBookCtrlBase', - 'wxNotebook', - ] +ITEMS = [ 'wxNotebook' ] #--------------------------------------------------------------------------- @@ -33,12 +30,12 @@ def run(): # Tweak the parsed meta objects in the module object as needed for # customizing the generated code and docstrings. - c = module.find('wxBookCtrlBase') - c.abstract = True - c = module.find('wxNotebook') - tools.fixWindowClass(c) + c.find('OnSelChange').ignore() + #c.addGetterSetterProps() + + tools.fixWindowClass(c) tools.removeVirtuals(c) tools.addWindowVirtuals(c) diff --git a/etg/panel.py b/etg/panel.py index 7a3b04c7..6611a7d5 100644 --- a/etg/panel.py +++ b/etg/panel.py @@ -32,8 +32,10 @@ def run(): c = module.find('wxPanel') assert isinstance(c, etgtools.ClassDef) - tools.fixWindowClass(c) + + c.find('OnSysColourChanged').ignore() + tools.fixWindowClass(c) tools.removeVirtuals(c) tools.addWindowVirtuals(c) diff --git a/etg/pen.py b/etg/pen.py new file mode 100644 index 00000000..37e1610d --- /dev/null +++ b/etg/pen.py @@ -0,0 +1,80 @@ +#--------------------------------------------------------------------------- +# Name: etg/pen.py +# Author: Robin Dunn +# +# Created: 31-Aug-2011 +# Copyright: (c) 2011 by Total Control Software +# License: wxWindows License +#--------------------------------------------------------------------------- + +import etgtools +import etgtools.tweaker_tools as tools + +PACKAGE = "wx" +MODULE = "_core" +NAME = "pen" # 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 = [ 'wxPen' ] + +#--------------------------------------------------------------------------- + +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('wxPen') + assert isinstance(c, etgtools.ClassDef) + tools.removeVirtuals(c) + + c.find('GetDashes').ignore() + c.find('SetDashes').ignore() + c.addCppMethod('wxArrayInt*', 'GetDashes', '()', """\ + wxArrayInt* arr = new wxArrayInt; + wxDash* dashes; + int num = self->GetDashes(&dashes); + for (int i=0; iAdd(dashes[i]); + return arr;""") + + # TODO: SetDashes needs to keep the wxDash array alive as long as the pen + # is alive, but the pen does not take ownership of the array... Classic + # wxPython did some black magic here, is that still the best way? + + # TODO: Fix these. I'm not sure why exactly, but in the CPP code + # they end up with the wrong signature. + module.find('wxRED_PEN').ignore() + module.find('wxBLUE_PEN').ignore() + module.find('wxCYAN_PEN').ignore() + module.find('wxGREEN_PEN').ignore() + module.find('wxYELLOW_PEN').ignore() + module.find('wxBLACK_PEN').ignore() + module.find('wxWHITE_PEN').ignore() + module.find('wxTRANSPARENT_PEN').ignore() + module.find('wxBLACK_DASHED_PEN').ignore() + module.find('wxGREY_PEN').ignore() + module.find('wxMEDIUM_GREY_PEN').ignore() + module.find('wxLIGHT_GREY_PEN').ignore() + + module.find('wxThePenList').ignore() + #module.addItem(tools.wxListWrapperTemplate('wxBrushList', 'wxBrush')) + #module.addItem(tools.wxListWrapperTemplate('wxPenList', 'wxPen')) + + + + #----------------------------------------------------------------- + tools.doCommonTweaks(module) + tools.runGenerators(module) + + +#--------------------------------------------------------------------------- +if __name__ == '__main__': + run() + diff --git a/etg/template.py b/etg/template.py index cd2c980c..d26653bc 100644 --- a/etg/template.py +++ b/etg/template.py @@ -3,7 +3,7 @@ # Author: Robin Dunn # # Created: -# Copyright: (c) 2010 by Total Control Software +# Copyright: (c) 2011 by Total Control Software # License: wxWindows License #--------------------------------------------------------------------------- diff --git a/etg/window.py b/etg/window.py index 47404b63..76f6f124 100644 --- a/etg/window.py +++ b/etg/window.py @@ -115,14 +115,14 @@ def run(): # Make the Register/UnregisterHotKey functions be available on Windows, # and empty stubs otherwise c.find('RegisterHotKey').setCppCode("""\ - #ifdef __WXMSW__ + #if wxUSE_HOTKEY sipRes = sipCpp->RegisterHotKey(hotkeyId, modifiers, virtualKeyCode); #else sipRes = false; #endif """) c.find('UnregisterHotKey').setCppCode("""\ - #ifdef __WXMSW__ + #if wxUSE_HOTKEY sipRes = sipCpp->UnregisterHotKey(hotkeyId); #else sipRes = false; @@ -147,10 +147,6 @@ def run(): c.find('GetAccessible').ignore() c.find('SetAccessible').ignore() - # now undocumented - c.find('GetConstraints').ignore() - c.find('SetConstraints').ignore() - # Make some of the protected methods visible and overridable from Python c.find('SendDestroyEvent').ignore(False) @@ -161,7 +157,7 @@ def run(): c.find('SetCaret.caret').transfer = True c.find('SetToolTip.tip').transfer = True c.find('SetDropTarget.target').transfer = True - #c.find('SetConstraints.constraints').transfer = True + c.find('SetConstraints.constraints').transfer = True c.find('SetSizer.sizer').transfer = True c.find('SetSizerAndFit.sizer').transfer = True @@ -181,7 +177,7 @@ def run(): c.addProperty('ClientAreaOrigin GetClientAreaOrigin') c.addProperty('ClientRect GetClientRect SetClientRect') c.addProperty('ClientSize GetClientSize SetClientSize') - #c.addProperty('Constraints GetConstraints SetConstraints') + c.addProperty('Constraints GetConstraints SetConstraints') c.addProperty('ContainingSizer GetContainingSizer SetContainingSizer') c.addProperty('Cursor GetCursor SetCursor') c.addProperty('DefaultAttributes GetDefaultAttributes') diff --git a/etgtools/extractors.py b/etgtools/extractors.py index e8cee88e..6dbcfa70 100644 --- a/etgtools/extractors.py +++ b/etgtools/extractors.py @@ -78,7 +78,7 @@ class BaseDef(object): except ValueError: head, tail = name, None for item in self._findItems(): - if item.name == head or item.pyName == head: + if item.name == head or item.pyName == head: # TODO: exclude ignored items? if not tail: return item else: @@ -285,7 +285,7 @@ class FunctionDef(BaseDef): Search for an overloaded method that has matchText in its C++ argsString. """ for o in self.all(): - if matchText in o.argsString: + if matchText in o.argsString and not o.ignored: return o return None @@ -445,38 +445,51 @@ class ClassDef(BaseDef): self.addCppCode(file(filename).read()) def addGetterSetterProps(self): - props = {} # format: { propName: [getter, setter] } - getters = [] - setters = [] + def countNonDefaultArgs(m): + count = 0 + for p in m.items: + if not p.default: + count += 1 + return count + + props = dict() for item in self.items: if item.ignored: continue - if isinstance(item, MethodDef): - if not item.name == 'Get' and item.name.find('Get') != -1: - getters.append(item.name) - elif not item.name == 'Set' and item.name.find('Set') != -1: - setters.append(item.name) - - for getter in getters: - props[getter.replace('Get', '')] = [getter] - - for setter in setters: - propName = setter.replace('Set', '') - if not propName in props: - props[propName] = [setter] - else: - props[propName].append(setter) + if isinstance(item, MethodDef) and item.name not in ['Get', 'Set'] \ + and (item.name.startswith('Get') or item.name.startswith('Set')): + prefix = item.name[:3] + name = item.name[3:] + prop = props.get(name, PropertyDef(name)) + if prefix == 'Get': + prop.getter = item.name + # Getters must be able to be called with no args, ensure + # that item has exactly zero args without a default value + if countNonDefaultArgs(item) != 0: + # TODO: check overloads too + continue + elif prefix == 'Set': + prop.setter = item.name + # Setters must be able to be called with 1 arg, ensure + # that item has at least 1 arg and not more than 1 without + # a default value. + if len(item.items) == 0 or countNonDefaultArgs(item) > 1: + # TODO: check overloads too + continue + props[name] = prop - for prop in props: + if props: + self.addPublic() + for name, prop in sorted(props.items()): # only create the prop if a method with that name does not exist - if not self.findItem(prop): - propString = "%s %s" % (prop, props[prop][0]) - if len(props[prop]) > 1: - propString += " %s" % props[prop][1] - self.addProperty(propString.strip()) + if not self.findItem(name): + # properties must have at least a getter + if prop.getter: + self.items.append(prop) else: - print "WARNING: Method %s::%s already exists in C++ class API" % (self.name, prop) + print "WARNING: Method %s::%s already exists in C++ class API, can not create a property." % (self.name, name) + def addProperty(self, *args, **kw): """ Add a property to a class, with a name, getter function and optionally @@ -661,6 +674,19 @@ class EnumValueDef(BaseDef): self.__dict__.update(kw) +#--------------------------------------------------------------------------- + +class DefineDef(BaseDef): + """ + Represents a #define with a name and a value. + """ + def __init__(self, element, **kw): + super(DefineDef, self).__init__() + self.name = element.find('name').text + self.value = element.find('initializer').text + self.__dict__.update(kw) + + #--------------------------------------------------------------------------- class PropertyDef(BaseDef): @@ -670,7 +696,7 @@ class PropertyDef(BaseDef): NOTE: This one is not automatically extracted, but can be added to classes in the tweaker stage """ - def __init__(self, name, getter, setter=None, doc=None, **kw): + def __init__(self, name, getter=None, setter=None, doc=None, **kw): super(PropertyDef, self).__init__() self.name = name self.getter = getter @@ -679,19 +705,6 @@ class PropertyDef(BaseDef): self.protection = 'public' self.__dict__.update(kw) -class DefineDef(BaseDef): - """ - Use the C++ methods of a class to make a Python property. - - NOTE: This one is not automatically extracted, but can be added to - classes in the tweaker stage - """ - def __init__(self, element, **kw): - super(DefineDef, self).__init__() - self.name = element.find('name').text - self.value = element.find('initializer').text - self.__dict__.update(kw) - #--------------------------------------------------------------------------- class CppMethodDef(MethodDef): @@ -721,7 +734,7 @@ class CppMethodDef(MethodDef): class CppMethodDef_sip(CppMethodDef): """ Just like the above, but instead of generating a new function from the - privided code, the code is used inline inside SIP's %MethodCode directive. + provided code, the code is used inline inside SIP's %MethodCode directive. This makes it possible to use additional SIP magic for things that are beyond the general scope of the other C++ Method implementation. """ @@ -732,8 +745,10 @@ class CppMethodDef_sip(CppMethodDef): class WigCode(BaseDef): """ - This class allows code defined by the triggers to be injected into the - generated Wrapper Interface Generator file. + This class allows code defined by the extractors to be injected into the + generated Wrapper Interface Generator file. In other words, this is extra + code meant to be consumed by the back-end code generator, and it will be + injected at the point in the file generation that this object is seen. """ def __init__(self, code, **kw): super(WigCode, self).__init__() diff --git a/etgtools/tweaker_tools.py b/etgtools/tweaker_tools.py index 7906a92c..58cc7fbf 100644 --- a/etgtools/tweaker_tools.py +++ b/etgtools/tweaker_tools.py @@ -60,13 +60,15 @@ def ignoreAllOperators(node): if isinstance(item, extractors.MethodDef) and item.name.startswith('operator'): item.ignore() + def addGetterSetterProps(node): """ - Set the ignored flag for all class methods that are any kind of operator + Call klass.addGetterSetterProps for all classes in node. """ for item in node.allItems(): if isinstance(item, extractors.ClassDef): item.addGetterSetterProps() + def createPyArgsStrings(node): """ @@ -100,12 +102,20 @@ def fixWindowClass(klass): Do common tweaks for a window class. """ # The ctor and Create method transfer ownership of the this pointer - for func in klass.findAll('%s' % klass.name) + klass.findAll('Create'): + for func in klass.findAll(klass.name) + klass.findAll('Create'): if isinstance(func, extractors.MethodDef): func.find('parent').transferThis = True # give the id param a default value func.find('id').default = 'wxID_ANY' - + + # if there is a pos or size parameter without a default then give it one. + p = func.findItem('pos') + if p and not p.default: + p.default = 'wxDefaultPosition' + p = func.findItem('size') + if p and not p.default: + p.default = 'wxDefaultSize' + def fixTopLevelWindowClass(klass): """ diff --git a/sip/cpp/README.txt b/sip/cpp/README.txt index 9404aeb2..770fd84d 100644 --- a/sip/cpp/README.txt +++ b/sip/cpp/README.txt @@ -1,3 +1,6 @@ This folder is where the ouput of SIP is placed. These will be the C++ source and header files, as well as a file for each module that specifies what files were generated for that module (which is used by the build scripts.) + +Currently these files are not committed to the SVN repository, but +they should be included in any source tarballs that are distributed. diff --git a/sip/gen/README.txt b/sip/gen/README.txt index c496472e..dfea26d6 100644 --- a/sip/gen/README.txt +++ b/sip/gen/README.txt @@ -3,3 +3,5 @@ wrapper generator files which describe the wxWidgets APIs that wxPython wraps. These files will be fed to SIP to procude the C++ code for the extension modules. +Currently these files are not committed to the SVN repository, but +they should be included in any source tarballs that are distributed. diff --git a/src/arrays.sip b/src/arrays.sip new file mode 100644 index 00000000..430beb2a --- /dev/null +++ b/src/arrays.sip @@ -0,0 +1,187 @@ +//-------------------------------------------------------------------------- +// Name: src/arrays.sip +// Purpose: Implements a %MappedType for wxArrayString and wxArrayInt +// +// Author: Robin Dunn +// +// Created: 2-Sept-2011 +// Copyright: (c) 2011 by Total Control Software +// Licence: wxWindows license +//-------------------------------------------------------------------------- + + +// Some SIP MappedTypes that automatically convert Python lists of +// strings/ints to and from wxArrayString/wxArrayInt. + +//-------------------------------------------------------------------------- + +%MappedType wxArrayString +{ + %ConvertToTypeCode + // Code to test a PyObject for compatibility + if (!sipIsErr) { + int success = TRUE; + // ensure that it is a sequence + if (! PySequence_Check(sipPy)) + success = FALSE; + // Ensure it is not a string or unicode object (they are sequences) + else if (PyString_Check(sipPy) || PyUnicode_Check(sipPy)) + success = FALSE; + // ensure each item is a string/unicode object + else { + Py_ssize_t i, len = PySequence_Length(sipPy); + for (i=0; iAdd(string); + Py_DECREF(item); + } + *sipCppPtr = array; + return sipGetState(sipTransferObj); + %End + + + %ConvertFromTypeCode + // Code to convert a wxArrayString to a Python list of strings. + PyObject* list = PyList_New(0); + for (size_t i=0; i < sipCpp->GetCount(); i++) { + PyObject* str = PyUnicode_FromWideChar(sipCpp->Item(i).c_str(), sipCpp->Item(i).Len()); + PyList_Append(list, str); + Py_DECREF(str); + } + return list; + %End + +}; + + +// Used just for unittesting the MappedType code, it can be removed later +%ModuleCode +wxArrayString testArrayStringTypemap(const wxArrayString& arr) +{ + wxArrayString local = arr; // force a copy + return local; +} +%End +wxArrayString testArrayStringTypemap(const wxArrayString& arr); + + +//-------------------------------------------------------------------------- + +%MappedType wxArrayInt +{ + %ConvertToTypeCode + // Code to test a PyObject for compatibility + if (!sipIsErr) { + int success = TRUE; + // ensure that it is a sequence + if (! PySequence_Check(sipPy)) + success = FALSE; + // ensure each item is a number object + else { + Py_ssize_t i, len = PySequence_Length(sipPy); + for (i=0; iAdd(PyInt_AS_LONG(number)); + Py_DECREF(item); + Py_DECREF(number); + } + *sipCppPtr = array; + return sipGetState(sipTransferObj); + %End + + + %ConvertFromTypeCode + // Code to convert a wxArrayInt to a Python list of integers. + PyObject* list = PyList_New(0); + for (size_t i=0; i < sipCpp->GetCount(); i++) { + PyObject* number = PyInt_FromLong(sipCpp->Item(i)); + PyList_Append(list, number); + Py_DECREF(number); + } + return list; + %End + +}; + + +// Used just for unittesting the MappedType code, it can be removed later +%ModuleCode +wxArrayInt testArrayIntTypemap(const wxArrayInt& arr) +{ + wxArrayInt local = arr; // force a copy + return local; +} +%End +wxArrayInt testArrayIntTypemap(const wxArrayInt& arr); + + +//-------------------------------------------------------------------------- + + diff --git a/src/clntdata.sip b/src/clntdata.sip index eee0cbc2..e6a324a9 100644 --- a/src/clntdata.sip +++ b/src/clntdata.sip @@ -11,7 +11,6 @@ %ModuleHeaderCode - // A wxClientData that holds a reference to a Python object class wxPyClientData : public wxClientData { @@ -26,7 +25,7 @@ ~wxPyClientData() { if (m_incRef) { - //wxPyBlock_t blocked = wxPyBeginBlockThreads(); + // TODO: wxPyBlock_t blocked = wxPyBeginBlockThreads(); Py_DECREF(m_obj); //wxPyEndBlockThreads(blocked); } @@ -39,5 +38,36 @@ %End -// TODO: Can we just use a MappedType for wxClientData instead of writing -// CppMethods where it needs to be used? +// We'll use the wxPyClientData defined above wherever a wxClientData parameter or +// return value is specified in the API. This MappedType code will convert to/from a +// PyObject so it will be totally transparent to the programmer and from their +// perspective any python object is being stored as the client data. +%MappedType wxClientData +{ + %ConvertToTypeCode + // Code to test a PyObject for compatibility + if (!sipIsErr) { + return TRUE; // any python object is valid + } + + // Code to create a new wxClientData from the PyObject + wxClientData* data = new wxPyClientData(sipPy); + *sipCppPtr = data; + return sipGetState(sipTransferObj); + %End + + + %ConvertFromTypeCode + // Code to convert a wxClientData back to the PyObject. + PyObject* obj; + if (sipCpp == NULL) { + obj = Py_None; + } else { + wxPyClientData* data = static_cast(sipCpp); // TODO: verify poitner type? + obj = data->m_obj; + } + Py_INCREF(obj); + return obj; + %End + +}; diff --git a/src/core_ex.py b/src/core_ex.py index 6a5066f7..d91352c4 100644 --- a/src/core_ex.py +++ b/src/core_ex.py @@ -8,12 +8,14 @@ wx = _sys.modules[__name__] # Load version numbers from __version__... Ensure that major and minor # versions are the same for both wxPython and wxWidgets. from __version__ import * +import _core __version__ = VERSION_STRING -assert MAJOR_VERSION == MAJOR_VERSION, "wxPython/wxWidgets version mismatch" -assert MINOR_VERSION == MINOR_VERSION, "wxPython/wxWidgets version mismatch" -if RELEASE_NUMBER != RELEASE_NUMBER: +assert MAJOR_VERSION == _core.MAJOR_VERSION, "wxPython/wxWidgets version mismatch" +assert MINOR_VERSION == _core.MINOR_VERSION, "wxPython/wxWidgets version mismatch" +if RELEASE_NUMBER != _core.RELEASE_NUMBER: import warnings warnings.warn("wxPython/wxWidgets release number mismatch") +del _core def version(): @@ -31,7 +33,7 @@ def version(): port = 'gtk2' else: port = '???' - return "%s %s" % (wx.VERSION_STRING, port) + return "%s %s (phoenix)" % (wx.VERSION_STRING, port) def deprecated(func): @@ -108,7 +110,7 @@ def deprecated(func): #---------------------------------------------------------------------------- -def CallAfter(callable, *args, **kw): +def CallAfter(callableObj, *args, **kw): """ Call the specified function after the current and pending event handlers have been completed. This is also good for making GUI @@ -117,6 +119,7 @@ def CallAfter(callable, *args, **kw): :see: `wx.CallLater` """ + assert callable(callableObj), "callableObj is not callable" app = wx.GetApp() assert app is not None, 'No wx.App created yet' @@ -126,7 +129,7 @@ def CallAfter(callable, *args, **kw): lambda event: event.callable(*event.args, **event.kw) ) evt = wx.PyEvent() evt.SetEventType(app._CallAfterId) - evt.callable = callable + evt.callable = callableObj evt.args = args evt.kw = kw wx.PostEvent(app, evt) @@ -150,9 +153,10 @@ def CallAfter(callable, *args, **kw): ## :see: `wx.CallAfter` ## """ -## def __init__(self, millis, callable, *args, **kwargs): +## def __init__(self, millis, callableObj, *args, **kwargs): +## assert callable(callableObj), "callableObj is not callable" ## self.millis = millis -## self.callable = callable +## self.callable = callableObj ## self.SetArgs(*args, **kwargs) ## self.runCount = 0 ## self.running = False diff --git a/src/event_ex.py b/src/event_ex.py index f198b814..7b548345 100644 --- a/src/event_ex.py +++ b/src/event_ex.py @@ -287,5 +287,4 @@ EVT_TEXT_PASTE = wx.PyEventBinder( wxEVT_COMMAND_TEXT_PASTE ) EVT_THREAD = wx.PyEventBinder( wxEVT_THREAD ) -EVT_COLLAPSIBLEPANE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_COLLPANE_CHANGED ) diff --git a/src/string.sip b/src/string.sip index a4825a39..7c5af17d 100644 --- a/src/string.sip +++ b/src/string.sip @@ -14,7 +14,7 @@ // at all, so it will be mapped to and from Python Unicode objects using the // code snippets below. -// NOTE: Currently we assume that string objects are encoding in utf-8. +// NOTE: Currently we assume that string objects are encoded in utf-8. %MappedType wxString { @@ -55,60 +55,6 @@ }; -%MappedType wxArrayString -{ - %ConvertToTypeCode - if (!sipIsErr) { - if (! PySequence_Check(sipPy)) { - PyErr_SetString(PyExc_TypeError, "Sequence of strings expected."); - return FALSE; - } else - return TRUE; - } - - wxArrayString *array = new wxArrayString; - int i, len=PySequence_Length(sipPy); - for (i=0; iAdd(*string); - delete string; - Py_DECREF(item); - } - *sipCppPtr = array; - return sipGetState(sipTransferObj); - %End - - - %ConvertFromTypeCode - PyObject* list = PyList_New(0); - for (size_t i=0; i < sipCpp->GetCount(); i++) { - PyObject* str = PyUnicode_FromWideChar(sipCpp->Item(i).c_str(), sipCpp->Item(i).Len()); - PyList_Append(list, str); - Py_DECREF(str); - } - return list; - %End - -}; // Used just for testing the MappedType code, it can be removed later diff --git a/unittests/runtests.py b/unittests/runtests.py index 6afaefe3..96de7b7d 100755 --- a/unittests/runtests.py +++ b/unittests/runtests.py @@ -21,6 +21,7 @@ if sys.version_info < (2,7): # The unittest2 package has back-ported most of the new features of the # unittest module in Python 2.7, you can get it at PyPI. import unittest2 + unittest = unittest2 else: import unittest sys.modules['unittest2'] = unittest diff --git a/unittests/test_app.py b/unittests/test_app.py index 65dd11dd..bb6d73d6 100644 --- a/unittests/test_app.py +++ b/unittests/test_app.py @@ -39,6 +39,9 @@ class App(unittest2.TestCase): def test_version(self): v = wx.version() + wx.VERSION + wx.VERSION_STRING + wx.__version__ def test_PySimpleApp(self): # wx.PySimpleApp is supposed to be deprecated, make sure it is. diff --git a/unittests/test_arrayint.py b/unittests/test_arrayint.py new file mode 100644 index 00000000..e2f5944c --- /dev/null +++ b/unittests/test_arrayint.py @@ -0,0 +1,27 @@ +import unittest2 +import wxPhoenix as wx + + +#--------------------------------------------------------------------------- + +class ArrayInt(unittest2.TestCase): + + if hasattr(wx, 'testArrayIntTypemap'): + def test_ArrayStringTypemaps(self): + # basic conversion of list or tuples of numbers + seqList = [1,2,3,4.5,6.7] + self.assertEqual(wx.testArrayIntTypemap(seqList), [1,2,3,4,6]) #floats are truncated to int + seqTuple = (1,2,3,4.5,6.7) + self.assertEqual(wx.testArrayIntTypemap(seqTuple), [1,2,3,4,6]) + + def test_ArrayIntTypemapErrors(self): + # test error conditions + with self.assertRaises(TypeError): + wx.testArrayIntTypemap([1,2,3, "baditem", ["listitem"]]) + + +#--------------------------------------------------------------------------- + + +if __name__ == '__main__': + unittest2.main() diff --git a/unittests/test_arraystring.py b/unittests/test_arraystring.py new file mode 100644 index 00000000..2da2b5f5 --- /dev/null +++ b/unittests/test_arraystring.py @@ -0,0 +1,31 @@ +import unittest2 +import wxPhoenix as wx + + +#--------------------------------------------------------------------------- + +class ArrayString(unittest2.TestCase): + + if hasattr(wx, 'testArrayStringTypemap'): + def test_ArrayStringTypemaps(self): + # basic conversion of list or tuples of strings + seqList = ['a', u'b', 'hello world'] + self.assertEqual(wx.testArrayStringTypemap(seqList), seqList) + seqTuple = ('a', u'b', 'hello world') + self.assertEqual(wx.testArrayStringTypemap(seqTuple), list(seqTuple)) + + def test_ArrayStringTypemapErrors(self): + # test error conditions + with self.assertRaises(TypeError): + wx.testArrayStringTypemap("STRING sequence") + with self.assertRaises(TypeError): + wx.testArrayStringTypemap(u"UNICODE sequence") + with self.assertRaises(TypeError): + wx.testArrayStringTypemap(["list", "with", "non-string", "items", 123]) + + +#--------------------------------------------------------------------------- + + +if __name__ == '__main__': + unittest2.main() diff --git a/unittests/test_gdicmn.py b/unittests/test_gdicmn.py index 807b5e85..93d1e418 100644 --- a/unittests/test_gdicmn.py +++ b/unittests/test_gdicmn.py @@ -235,6 +235,12 @@ class Rect(unittest2.TestCase): def test_xywh_ctor(self): r = wx.Rect(1, 2, 3, 4) + + def test_kwargs_ctor(self): + r1 = wx.Rect(x=1, y=2, width=3, height=4) + r2 = wx.Rect(width=3, height=4, x=1, y=2) + self.assertTrue(r1 == r2) + self.assertTrue(r2 == (1,2,3,4)) def test_possize_ctor(self): r = wx.Rect(wx.Point(10,10), wx.Size(100,100)) @@ -266,4 +272,4 @@ class Rect(unittest2.TestCase): if __name__ == '__main__': - unittest2.main() \ No newline at end of file + unittest2.main()