mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2025-07-21 12:41:10 +02:00
474 lines
18 KiB
Python
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()
|
|
|