* 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
This commit is contained in:
Robin Dunn
2011-09-03 01:42:42 +00:00
parent 49fda7ada4
commit 4219e02440
44 changed files with 1349 additions and 281 deletions

114
TODO.txt Normal file
View File

@@ -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

View File

@@ -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:

View File

@@ -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',
]
@@ -257,6 +274,8 @@ void wxPyCoreModuleInject(PyObject* moduleDict)
#else
_AddInfoString("wx-assertions-off");
#endif
_AddInfoString("phoenix");
#undef _AddInfoString
PyObject* PortInfoTuple = PyList_AsTuple(PortInfo);

View File

@@ -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()

50
etg/bmpbuttn.py Normal file
View File

@@ -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()

48
etg/bookctrl.py Normal file
View File

@@ -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()

62
etg/brush.py Normal file
View File

@@ -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()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 <wx/collpane.h>")
module.addPyCode(
"EVT_COLLAPSIBLEPANE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_COLLPANE_CHANGED )")
c = module.find('wxCollapsiblePane')
c.find('wxCollapsiblePane.label').default = 'wxEmptyString'

View File

@@ -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,21 +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('wxControlWithItems')
c.abstract = True
c = module.find('wxControl')
assert isinstance(c, etgtools.ClassDef)
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
tools.fixWindowClass(c)
tools.removeVirtuals(c)
tools.addWindowVirtuals(c)
module.addPyCode("PyControl = Control")

88
etg/ctrlsub.py Normal file
View File

@@ -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()

View File

@@ -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)

56
etg/dcbuffer.py Normal file
View File

@@ -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()

55
etg/dcclient.py Normal file
View File

@@ -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()

46
etg/dcgraph.py Normal file
View File

@@ -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()

46
etg/dcmemory.py Normal file
View File

@@ -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()

46
etg/dcmirror.py Normal file
View File

@@ -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()

46
etg/dcprint.py Normal file
View File

@@ -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()

46
etg/dcps.py Normal file
View File

@@ -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()

46
etg/dcscreen.py Normal file
View File

@@ -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()

46
etg/dcsvg.py Normal file
View File

@@ -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()

View File

@@ -25,7 +25,6 @@ ITEMS = [
'wxCommandEvent',
'wxActivateEvent',
'wxBookCtrlEvent',
'wxChildFocusEvent',
'wxClipboardTextEvent',
'wxCloseEvent',
@@ -86,8 +85,6 @@ def run():
#endif
""")
module.addHeaderCode("#include <wx/collpane.h>")
# 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.addPyCode("""\
CommandEvent.GetClientData = CommandEvent.GetClientObject
CommandEvent.SetClientData = CommandEvent.SetClientObject""")
c.addCppMethod('void', 'SetClientData', '(PyObject* clientData)', """\
wxPyClientData* data = new wxPyClientData(clientData);
self->SetClientObject(data);
""")
c.addProperty('ClientData GetClientData SetClientData')
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')

View File

@@ -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'))
#-----------------------------------------------------------------

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

80
etg/pen.py Normal file
View File

@@ -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; i<num; i++)
arr->Add(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()

View File

@@ -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
#---------------------------------------------------------------------------

View File

@@ -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')

View File

@@ -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,37 +445,50 @@ 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)
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 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)
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):
"""
@@ -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__()

View File

@@ -60,14 +60,16 @@ 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):
"""
TODO: Create a pythonized version of the argsString in function and method
@@ -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):
"""

View File

@@ -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.

View File

@@ -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.

187
src/arrays.sip Normal file
View File

@@ -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; i<len; i++) {
PyObject* item = PySequence_GetItem(sipPy, i);
if (!PyString_Check(item) && !PyUnicode_Check(item)) {
Py_DECREF(item);
success = FALSE;
break;
}
Py_DECREF(item);
}
}
if (!success)
PyErr_SetString(PyExc_TypeError, "Sequence of string or unicode objects expected.");
return success;
}
// Code to create a new wxArrayString and convert a compatible PyObject
wxArrayString *array = new wxArrayString;
Py_ssize_t i, len = PySequence_Length(sipPy);
for (i=0; i<len; i++) {
PyObject* item = PySequence_GetItem(sipPy, i);
// if it's a string object convert it to unicode first, assuming utf-8
if (PyString_Check(item)) {
Py_DECREF(item);
item = PyUnicode_FromEncodedObject(item, "utf-8", "strict");
if (PyErr_Occurred()) {
*sipIsErr = 1;
delete array;
Py_DECREF(item);
return 0;
}
}
wxString string;
size_t len = PyUnicode_GET_SIZE(item);
if (len) {
PyUnicode_AsWideChar((PyUnicodeObject*)item,
wxStringBuffer(string, len), len);
}
if (PyErr_Occurred()) {
*sipIsErr = 1;
delete array;
Py_DECREF(item);
return 0;
}
array->Add(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; i<len; i++) {
PyObject* item = PySequence_GetItem(sipPy, i);
if (!PyNumber_Check(item)) {
Py_DECREF(item);
success = FALSE;
break;
}
Py_DECREF(item);
}
}
if (!success)
PyErr_SetString(PyExc_TypeError, "Sequence of numbers expected.");
return success;
}
// Code to create a new wxArrayInt and convert a compatible PyObject
wxArrayInt *array = new wxArrayInt;
Py_ssize_t i, len = PySequence_Length(sipPy);
for (i=0; i<len; i++) {
PyObject* item = PySequence_GetItem(sipPy, i);
PyObject* number = PyNumber_Int(item);
if (PyErr_Occurred()) {
*sipIsErr = 1;
delete array;
Py_DECREF(item);
return 0;
}
array->Add(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);
//--------------------------------------------------------------------------

View File

@@ -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<wxPyClientData*>(sipCpp); // TODO: verify poitner type?
obj = data->m_obj;
}
Py_INCREF(obj);
return obj;
%End
};

View File

@@ -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

View File

@@ -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 )

View File

@@ -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; i<len; i++) {
PyObject* item = PySequence_GetItem(sipPy, i);
if (PyString_Check(item)) {
// if it's a string object convert it to unicode first, assuming utf-8
item = PyUnicode_FromEncodedObject(item, "utf-8", "strict");
if (PyErr_Occurred()) {
*sipIsErr = 1;
return 0;
}
}
wxString* string = new wxString();
size_t len = PyUnicode_GET_SIZE(item);
if (len) {
PyUnicode_AsWideChar((PyUnicodeObject*)item,
wxStringBuffer(*string, len), len);
}
if (PyErr_Occurred()) {
*sipIsErr = 1;
return 0;
}
array->Add(*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

View File

@@ -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

View File

@@ -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.

View File

@@ -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()

View File

@@ -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()

View File

@@ -236,6 +236,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))
self.assertTrue(r.width == 100 and r.height == 100)