Files
Phoenix/etg/richtextbuffer.py
2022-05-02 22:33:58 -04:00

474 lines
18 KiB
Python

#---------------------------------------------------------------------------
# Name: etg/richtextbuffer.py
# Author: Robin Dunn
#
# Created: 23-Mar-2013
# Copyright: (c) 2013-2020 by Total Control Software
# License: wxWindows License
#---------------------------------------------------------------------------
import etgtools
import etgtools.tweaker_tools as tools
PACKAGE = "wx"
MODULE = "_richtext"
NAME = "richtextbuffer" # 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 = [ "wxTextAttrDimension",
"wxTextAttrDimensions",
"wxTextAttrSize",
"wxTextAttrDimensionConverter",
"wxTextAttrBorder",
"wxTextAttrBorders",
"wxTextAttrShadow",
"wxTextBoxAttr",
"wxRichTextAttr",
"wxRichTextProperties",
"wxRichTextFontTable",
"wxRichTextRange",
"wxRichTextSelection",
"wxRichTextDrawingContext",
"wxRichTextObject",
"wxRichTextCompositeObject",
"wxRichTextParagraphLayoutBox",
"wxRichTextBox",
"wxRichTextField",
"wxRichTextFieldType",
"wxRichTextFieldTypeStandard",
"wxRichTextLine",
"wxRichTextParagraph",
"wxRichTextPlainText",
"wxRichTextImageBlock",
"wxRichTextImage",
"wxRichTextBuffer",
"wxRichTextCell",
"wxRichTextTable",
"wxRichTextObjectAddress",
"wxRichTextCommand",
"wxRichTextAction",
"wxRichTextFileHandler",
"wxRichTextPlainTextHandler",
"wxRichTextDrawingHandler",
"wxRichTextBufferDataObject",
"wxRichTextRenderer",
"wxRichTextStdRenderer",
]
#---------------------------------------------------------------------------
def run():
# Parse the XML file(s) building a collection of Extractor objects
module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING)
etgtools.parseDoxyXML(module, ITEMS)
#-----------------------------------------------------------------
# Tweak the parsed meta objects in the module object as needed for
# customizing the generated code and docstrings.
module.addHeaderCode('#include <wx/richtext/richtextbuffer.h>')
module.addItem(
tools.wxArrayWrapperTemplate('wxRichTextRangeArray', 'wxRichTextRange', module))
module.addItem(
tools.wxArrayWrapperTemplate('wxRichTextAttrArray', 'wxRichTextAttr', module))
module.addItem(
tools.wxArrayWrapperTemplate('wxRichTextVariantArray', 'wxVariant', module))
module.addItem(
tools.wxListWrapperTemplate('wxRichTextObjectList', 'wxRichTextObject', module))
# Can this even work? Apparently it does.
module.addItem(
tools.wxArrayPtrWrapperTemplate('wxRichTextObjectPtrArray', 'wxRichTextObject', module))
module.addItem(
tools.wxArrayWrapperTemplate('wxRichTextObjectPtrArrayArray', 'wxRichTextObjectPtrArray', module))
module.find('wxRICHTEXT_ALL').ignore()
module.find('wxRICHTEXT_NONE').ignore()
module.find('wxRICHTEXT_NO_SELECTION').ignore()
code = etgtools.PyCodeDef("""\
RICHTEXT_ALL = RichTextRange(-2, -2)
RICHTEXT_NONE = RichTextRange(-1, -1)
RICHTEXT_NO_SELECTION = RichTextRange(-2, -2)
""")
module.insertItemAfter(module.find('wxRichTextRange'), code)
module.insertItem(0, etgtools.WigCode("""\
// forward declarations
class wxRichTextFloatCollector;
"""))
#-------------------------------------------------------
c = module.find('wxTextAttrDimension')
assert isinstance(c, etgtools.ClassDef)
c.find('SetValue').findOverload('units').ignore()
c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")
c.addCppMethod('int', '__bool__', '()', "return self->IsValid();")
#-------------------------------------------------------
c = module.find('wxTextAttrDimensions')
tools.ignoreConstOverloads(c)
c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")
c.addCppMethod('int', '__bool__', '()', "return self->IsValid();")
#-------------------------------------------------------
c = module.find('wxTextAttrSize')
tools.ignoreConstOverloads(c)
c.find('SetWidth').findOverload('units').ignore()
c.find('SetHeight').findOverload('units').ignore()
c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")
c.addCppMethod('int', '__bool__', '()', "return self->IsValid();")
#-------------------------------------------------------
c = module.find('wxTextAttrBorder')
tools.ignoreConstOverloads(c)
c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")
c.addCppMethod('int', '__bool__', '()', "return self->IsValid();")
#-------------------------------------------------------
c = module.find('wxTextAttrBorders')
tools.ignoreConstOverloads(c)
c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")
c.addCppMethod('int', '__bool__', '()', "return self->IsValid();")
#-------------------------------------------------------
c = module.find('wxTextAttrShadow')
tools.ignoreConstOverloads(c)
#-------------------------------------------------------
c = module.find('wxTextBoxAttr')
tools.ignoreConstOverloads(c)
#-------------------------------------------------------
c = module.find('wxRichTextAttr')
tools.ignoreConstOverloads(c)
#-------------------------------------------------------
c = module.find('wxRichTextProperties')
tools.ignoreConstOverloads(c)
c.find('SetProperty').findOverload('bool').ignore()
c.find('operator[]').ignore()
#-------------------------------------------------------
c = module.find('wxRichTextSelection')
tools.ignoreConstOverloads(c)
c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")
c.addCppMethod('int', '__bool__', '()', "return self->IsValid();")
c.find('operator[]').ignore()
#-------------------------------------------------------
c = module.find('wxRichTextRange')
tools.addAutoProperties(c)
# wxRichTextRange typemap
c.convertFromPyObject = tools.convertTwoIntegersTemplate('wxRichTextRange')
c.addCppMethod('PyObject*', 'Get', '()', """\
wxPyThreadBlocker blocker;
return sipBuildResult(0, "(ii)", self->GetStart(), self->GetEnd());
""",
pyArgsString="() -> (start, end)",
briefDoc="Return the start and end properties as a tuple.")
tools.addGetIMMethodTemplate(module, c, ['Start', 'End'])
# Add sequence protocol methods and other goodies
c.addPyMethod('__str__', '(self)', 'return str(self.Get())')
c.addPyMethod('__repr__', '(self)', 'return "RichTextRange"+str(self.Get())')
c.addPyMethod('__len__', '(self)', 'return len(self.Get())')
c.addPyMethod('__nonzero__', '(self)', 'return self.Get() != (0,0)')
c.addPyMethod('__bool__', '(self)', 'return self.Get() != (0,0)')
c.addPyMethod('__reduce__', '(self)', 'return (RichTextRange, self.Get())')
c.addPyMethod('__getitem__', '(self, idx)', 'return self.Get()[idx]')
c.addPyMethod('__setitem__', '(self, idx, val)',
"""\
if idx == 0: self.Start = val
elif idx == 1: self.End = val
else: raise IndexError
""")
c.addPyCode('RichTextRange.__safe_for_unpickling__ = True')
#-------------------------------------------------------
def _fixDrawObject(c, addMissingVirtuals=True):
assert isinstance(c, etgtools.ClassDef)
if c.findItem('HitTest'):
c.find('HitTest.textPosition').out = True
c.find('HitTest.obj').out = True
c.find('HitTest.contextObj').out = True
if c.findItem('FindPosition'):
c.find('FindPosition.pt').out = True
c.find('FindPosition.height').out = True
if c.findItem('GetBoxRects'):
c.find('GetBoxRects.marginRect').out = True
c.find('GetBoxRects.borderRect').out = True
c.find('GetBoxRects.contentRect').out = True
c.find('GetBoxRects.paddingRect').out = True
c.find('GetBoxRects.outlineRect').out = True
if c.findItem('GetTotalMargin'):
c.find('GetTotalMargin.leftMargin').out = True
c.find('GetTotalMargin.rightMargin').out = True
c.find('GetTotalMargin.topMargin').out = True
c.find('GetTotalMargin.bottomMargin').out = True
if c.findItem('CalculateRange'):
c.find('CalculateRange.end').out = True # TODO: should it be an inOut?
if c.findItem('Clone'):
c.find('Clone').factory = True
else:
c.addItem(etgtools.WigCode("""\
virtual wxRichTextObject* Clone() const /Factory/;
"""))
# These are the pure virtuals in the base class. SIP needs to see that
# all the derived classes have an implementation, otherwise it will
# consider them to be ABCs.
if not c.findItem('Draw') and addMissingVirtuals:
c.addItem(etgtools.WigCode("""\
virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context,
const wxRichTextRange& range,
const wxRichTextSelection& selection,
const wxRect& rect, int descent, int style);"""))
if not c.findItem('Layout') and addMissingVirtuals:
c.addItem(etgtools.WigCode("""\
virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context,
const wxRect& rect, const wxRect& parentRect,
int style);"""))
# TODO: Some of these args are output parameters. How should they be dealt with?
if not c.findItem('GetRangeSize') and addMissingVirtuals:
c.addItem(etgtools.WigCode("""\
virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size,
int& descent,
wxDC& dc, wxRichTextDrawingContext& context, int flags,
const wxPoint& position = wxPoint(0,0),
const wxSize& parentSize = wxDefaultSize,
wxArrayInt* partialExtents = NULL) const;"""))
#-------------------------------------------------------
c = module.find('wxRichTextObject')
#c.find('ImportFromXML').ignore()
tools.ignoreConstOverloads(c)
_fixDrawObject(c)
#-------------------------------------------------------
c = module.find('wxRichTextCompositeObject')
tools.ignoreConstOverloads(c)
_fixDrawObject(c, addMissingVirtuals=False)
#-------------------------------------------------------
c = module.find('wxRichTextParagraphLayoutBox')
tools.ignoreConstOverloads(c)
_fixDrawObject(c)
c.find('MoveAnchoredObjectToParagraph.from').name = 'from_'
c.find('MoveAnchoredObjectToParagraph.to').name = 'to_'
c.find('DoNumberList.def').name = 'styleDef'
c.find('SetListStyle.def').name = 'styleDef'
#-------------------------------------------------------
c = module.find('wxRichTextBox')
_fixDrawObject(c)
#-------------------------------------------------------
c = module.find('wxRichTextCell')
_fixDrawObject(c)
#-------------------------------------------------------
c = module.find('wxRichTextField')
_fixDrawObject(c)
#-------------------------------------------------------
c = module.find('wxRichTextLine')
tools.ignoreConstOverloads(c)
c.find('SetRange.from').name = 'from_'
c.find('SetRange.to').name = 'to_'
c.find('Clone').factory = True
#-------------------------------------------------------
c = module.find('wxRichTextParagraph')
_fixDrawObject(c)
# These methods use an untyped wxList, but since we know what is in it
# we'll make a fake typed list for wxPython so we can know what kinds of
# values to get from it.
module.addItem(
tools.wxListWrapperTemplate('wxList', 'wxRichTextObject', module,
fakeListClassName='wxRichTextObjectList_'))
c.find('MoveToList.list').type = 'wxRichTextObjectList_&'
c.find('MoveFromList.list').type = 'wxRichTextObjectList_&'
# TODO: figure out why wxvector.sip doesn't work for this
c.find('GetLines').type = 'PyObject*'
c.find('GetLines').setCppCode("""\
wxPyThreadBlocker blocker;
PyObject* result = PyList_New(0);
const wxRichTextLineVector& vector = self->GetLines();
for (size_t idx=0; idx < vector.size(); idx++) {{
PyObject* obj;
wxRichTextLine* item = new wxRichTextLine(*vector.at(idx));
obj = wxPyConstructObject((void*)item, "wxRichTextLine", true);
PyList_Append(result, obj);
Py_DECREF(obj);
}}
return result;
""")
#-------------------------------------------------------
c = module.find('wxRichTextPlainText')
_fixDrawObject(c)
#-------------------------------------------------------
c = module.find('wxRichTextImage')
_fixDrawObject(c)
c.find('LoadAndScaleImageCache.changed').inOut = True
#-------------------------------------------------------
c = module.find('wxRichTextBuffer')
tools.ignoreConstOverloads(c)
_fixDrawObject(c)
# More untyped wxLists
module.addItem(
tools.wxListWrapperTemplate('wxList', 'wxRichTextFileHandler', module,
fakeListClassName='wxRichTextFileHandlerList'))
c.find('GetHandlers').type = 'wxRichTextFileHandlerList&'
c.find('GetHandlers').noCopy = True
module.addItem(
tools.wxListWrapperTemplate('wxList', 'wxRichTextDrawingHandler', module,
fakeListClassName='wxRichTextDrawingHandlerList'))
c.find('GetDrawingHandlers').type = 'wxRichTextDrawingHandlerList&'
c.find('GetDrawingHandlers').noCopy = True
# TODO: Need a template to wrap STRING_HASH_MAP
c.find('GetFieldTypes').ignore()
c.find('AddHandler.handler').transfer = True
c.find('InsertHandler.handler').transfer = True
c.find('AddDrawingHandler.handler').transfer = True
c.find('InsertDrawingHandler.handler').transfer = True
c.find('AddFieldType.fieldType').transfer = True
# TODO: Transfer ownership with AddEventHandler? TransferBack with Remove?
c.find('FindHandler').renameOverload('name', 'FindHandlerByName')
c.find('FindHandler').renameOverload('extension', 'FindHandlerByExtension')
c.find('FindHandler').pyName = 'FindHandlerByType'
c.find('FindHandlerFilenameOrType').pyName = 'FindHandlerByFilename'
c.find('GetExtWildcard').ignore()
c.addCppMethod('PyObject*', 'GetExtWildcard', '(bool combine=false, bool save=false)',
doc="""\
Gets a wildcard string for the file dialog based on all the currently
loaded richtext file handlers, and a list that can be used to map
those filter types to the file handler type.""",
body="""\
wxString wildcards;
wxArrayInt types;
wildcards = wxRichTextBuffer::GetExtWildcard(combine, save, &types);
wxPyThreadBlocker blocker;
PyObject* list = PyList_New(0);
for (size_t i=0; i < types.GetCount(); i++) {
PyObject* number = wxPyInt_FromLong(types[i]);
PyList_Append(list, number);
Py_DECREF(number);
}
PyObject* tup = PyTuple_New(2);
PyTuple_SET_ITEM(tup, 0, wx2PyString(wildcards));
PyTuple_SET_ITEM(tup, 1, list);
return tup;
""",
isStatic=True)
#-------------------------------------------------------
c = module.find('wxRichTextTable')
tools.ignoreConstOverloads(c)
_fixDrawObject(c)
#-------------------------------------------------------
c = module.find('wxRichTextObjectAddress')
tools.ignoreConstOverloads(c)
#-------------------------------------------------------
c = module.find('wxRichTextCommand')
module.addItem(
tools.wxListWrapperTemplate('wxList', 'wxRichTextAction', module,
fakeListClassName='wxRichTextActionList'))
c.find('GetActions').type = 'wxRichTextActionList&'
c.find('GetActions').noCopy = True
c.find('AddAction.action').transfer = True
#-------------------------------------------------------
c = module.find('wxRichTextAction')
tools.ignoreConstOverloads(c)
#-------------------------------------------------------
c = module.find('wxRichTextFileHandler')
c.find('DoLoadFile').ignore(False)
c.find('DoSaveFile').ignore(False)
c = module.find('wxRichTextPlainTextHandler')
c.find('DoLoadFile').ignore(False)
c.find('DoSaveFile').ignore(False)
#-------------------------------------------------------
# Ignore all Dump() methods since we don't wrap wxTextOutputStream.
# TODO: try switching the parameter type to wxOutputStream and then in
# the wrapper code create a wxTextOutputStream from that to pass on to
# Dump.
for m in module.findAll('Dump'):
if m.findItem('stream'):
m.ignore()
# Correct the type for this define as it is a float
module.find('wxSCRIPT_MUL_FACTOR').type = 'float'
#-----------------------------------------------------------------
tools.doCommonTweaks(module)
tools.runGenerators(module)
#---------------------------------------------------------------------------
if __name__ == '__main__':
run()