Ejemplo n.º 1
0
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('wxPGPropArgCls')
    assert isinstance(c, etgtools.ClassDef)
    c.find('GetPtr').overloads[0].ignore()


    c = module.find('wxPropertyGridInterface')
    c.abstract = True
    for m in c.findAll('GetIterator'):
        if m.type == 'wxPropertyGridConstIterator':
            m.ignore()

    c.find('SetPropertyValue').findOverload('int value').ignore()
    c.find('SetPropertyValue').findOverload('bool value').ignore()
    c.find('SetPropertyValue').findOverload('wxLongLong_t value').ignore()
    c.find('SetPropertyValue').findOverload('wxULongLong_t value').ignore()
    c.find('SetPropertyValue').findOverload('wxObject *value').ignore()

    module.addItem(
        tools.wxArrayPtrWrapperTemplate('wxArrayPGProperty', 'wxPGProperty', module))


    # wxPGPropArg is a typedef for "const wxPGPropArgCls&" so having the
    # wrappers treat it as a normal type can be problematic. ("new cannot be
    # applied to a reference type", etc.) Let's just ignore it an replace it
    # everywhere for the real type.
    module.find('wxPGPropArg').ignore()
    for item in module.allItems():
        if hasattr(item, 'type') and item.type == 'wxPGPropArg':
            item.type = 'const wxPGPropArgCls &'


    #-----------------------------------------------------------------
    tools.doCommonTweaks(module)
    tools.runGenerators(module)
Ejemplo n.º 2
0
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('wxPGPropArgCls')
    assert isinstance(c, etgtools.ClassDef)
    c.find('GetPtr').overloads[0].ignore()

    c = module.find('wxPropertyGridInterface')
    c.abstract = True
    for m in c.findAll('GetIterator'):
        if m.type == 'wxPropertyGridConstIterator':
            m.ignore()

    c.find('SetPropertyValue').findOverload('int value').ignore()
    c.find('SetPropertyValue').findOverload('bool value').ignore()
    c.find('SetPropertyValue').findOverload('wxLongLong_t value').ignore()
    c.find('SetPropertyValue').findOverload('wxULongLong_t value').ignore()
    c.find('SetPropertyValue').findOverload('wxObject *value').ignore()

    module.addItem(
        tools.wxArrayPtrWrapperTemplate('wxArrayPGProperty', 'wxPGProperty',
                                        module))

    # wxPGPropArg is a typedef for "const wxPGPropArgCls&" so having the
    # wrappers treat it as a normal type can be problematic. ("new cannot be
    # applied to a reference type", etc.) Let's just ignore it an replace it
    # everywhere for the real type.
    module.find('wxPGPropArg').ignore()
    for item in module.allItems():
        if hasattr(item, 'type') and item.type == 'wxPGPropArg':
            item.type = 'const wxPGPropArgCls &'

    #-----------------------------------------------------------------
    tools.doCommonTweaks(module)
    tools.runGenerators(module)
Ejemplo n.º 3
0
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))
    module.addItem(
        tools.wxListWrapperTemplate('wxRichTextLineList', 'wxRichTextLine', 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 = module.find('wxTextAttrDimensions')
    tools.ignoreConstOverloads(c)
    c.addCppMethod('int', '__nonzero__', '()', "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 = module.find('wxTextAttrBorder')
    tools.ignoreConstOverloads(c)
    c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")


    #-------------------------------------------------------
    c = module.find('wxTextAttrBorders')
    tools.ignoreConstOverloads(c)
    c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")


    #-------------------------------------------------------
    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.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('__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_&'


    #-------------------------------------------------------
    c = module.find('wxRichTextPlainText')
    _fixDrawObject(c)

    #-------------------------------------------------------
    c = module.find('wxRichTextImage')
    _fixDrawObject(c)

    #-------------------------------------------------------
    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 swithcing 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)
Ejemplo n.º 4
0
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('wxPGPropArgCls')
    assert isinstance(c, etgtools.ClassDef)
    c.find('wxPGPropArgCls').findOverload('wxString &').ignore()
    c.find('wxPGPropArgCls').findOverload('char *').ignore()
    c.find('wxPGPropArgCls').findOverload('wchar_t *').ignore()
    c.find('wxPGPropArgCls').findOverload('int').ignore()
    c.find('wxPGPropArgCls').findOverload('deallocPtr').ignore()

    # Make a string ctor that uses the wxPython-specific version of
    # the C++ class' ctor
    newCtor = c.addCppCtor('(const wxString& str)',
        doc="Creates a PGPropArgCls from a string.",
        body="""\
            wxString* name = new wxString(*str);
            return new wxPGPropArgCls(name, true);
        """
        )

    # Make it be the first overload instead of the last
    ctor = c.find('wxPGPropArgCls')
    overloads = list(ctor.overloads)
    del overloads[overloads.index(newCtor)]
    overloads.insert(0, newCtor)
    ctor.overloads = overloads


    c.find('GetPtr').overloads[0].ignore()

    c.convertFromPyObject = """\
        // Code to test a PyObject for compatibility with wxPGPropArgCls
        if (!sipIsErr) {
            if (sipCanConvertToType(sipPy, sipType_wxPGPropArgCls, SIP_NO_CONVERTORS))
                return TRUE;
            if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))
                return TRUE;
            if (sipPy == Py_None)
                return TRUE;
            if (sipCanConvertToType(sipPy, sipType_wxPGProperty, SIP_NO_CONVERTORS))
                return TRUE;
            return FALSE;
        }

        // Code to convert a compatible PyObject to a wxPGPropArgCls
        if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy)) {
            wxString* name = new wxString(Py2wxString(sipPy));
            *sipCppPtr = new wxPGPropArgCls(name, true);
            return sipGetState(sipTransferObj);
        }
        else if (sipCanConvertToType(sipPy, sipType_wxPGProperty, SIP_NO_CONVERTORS)) {
            int state = 0;
            wxPGProperty* prop = reinterpret_cast<wxPGProperty*>(
                sipConvertToType(sipPy, sipType_wxPGProperty, sipTransferObj, SIP_NO_CONVERTORS, &state, sipIsErr));
            *sipCppPtr = new wxPGPropArgCls(prop);
            sipReleaseType(prop, sipType_wxPGProperty, state);
            return sipGetState(sipTransferObj);
        }
        else if (sipPy == Py_None) {
            *sipCppPtr = new wxPGPropArgCls(reinterpret_cast< wxPGProperty * >(NULL));
            return sipGetState(sipTransferObj);
        }
        else {
            // It's already a wxPGPropArgCls, just fetch the pointer and return
            *sipCppPtr = reinterpret_cast<wxPGPropArgCls*>(sipConvertToType(
                sipPy, sipType_wxPGPropArgCls, sipTransferObj,
                SIP_NO_CONVERTORS, 0, sipIsErr));
            return 0; // not a new instance
        }
        """


    #----------------------------------------------------------

    c = module.find('wxPropertyGridInterface')
    c.abstract = True
    for m in c.findAll('GetIterator'):
        if m.type == 'wxPropertyGridConstIterator':
            m.ignore()

    spv = c.find('SetPropertyValue')
    spv.findOverload('int value').ignore()
    spv.findOverload('wxLongLong_t value').ignore()
    spv.findOverload('wxULongLong_t value').ignore()
    spv.findOverload('wxObject *value').ignore()

    # Reorder SetPropertyValue overloads so the one taking a long int is not
    # first. Mark others that could be auto-converted from int as
    # "constrained" so they will only be used for that specific type. This
    # should result in SetPropertyValue(id, double) only used for floats and
    # not ints, or other things that can convert to int.
    spv.findOverload('bool value').find('value').constrained = True
    spv.findOverload('double value').find('value').constrained = True
    spv_long = spv.findOverload('long value')
    spv_long.ignore()
    spv.reorderOverloads() # Ensures an ignored item is not first,
    spv_long.ignore(False) # and then we can unignore it.


    c.find('Append.property').transfer = True
    c.find('AppendIn.newProperty').transfer = True
    for m in c.find('Insert').all():
        m.find('newProperty').transfer = True



    # Tons of Python method implementations ported from Classic...

    module.addPyCode("""\
        _type2property = None
        _vt2getter = None
        """)

    c.addPyMethod('MapType', '(self, class_, factory)',
        doc="""\
            Registers Python type/class to property mapping.

            :param `factory`: Property builder function/class.
            """,
        body="""\
            global _type2property
            if _type2property is None:
                raise AssertionError("call only after a propertygrid or "
                                     "manager instance constructed")
            _type2property[class_] = factory
            """)


    c.addPyMethod('DoDefaultTypeMappings', '(self)',
        doc="Add built-in properties to the map.",
        body="""\
            import sys
            global _type2property
            if _type2property is not None:
                return
            _type2property = dict()

            _type2property[str] = StringProperty
            if sys.version_info.major < 2:
                _type2property[unicode] = StringProperty
            _type2property[int] = IntProperty
            _type2property[float] = FloatProperty
            _type2property[bool] = BoolProperty
            _type2property[list] = ArrayStringProperty
            _type2property[tuple] = ArrayStringProperty
            _type2property[wx.Font] = FontProperty
            _type2property[wx.Colour] = ColourProperty
            #_type2property[wx.Size] = SizeProperty
            #_type2property[wx.Point] = PointProperty
            #_type2property[wx.FontData] = FontDataProperty
            """)


    # TODO: is this still needed?
    c.addPyMethod('DoDefaultValueTypeMappings', '(self)',
        doc="Map pg value type ids to getter methods.",
        body="""\
            global _vt2getter
            if _vt2getter is not None:
                return
            _vt2getter = dict()
        """)


    c.find('GetPropertyValues').ignore()
    c.addPyMethod('GetPropertyValues',
        '(self, dict_=None, as_strings=False, inc_attributes=False)',
        doc="""\
            Returns all property values in the grid.\n
            :param `dict_`: A to fill with the property values. If not given,
                then a new one is created. The dict_ can be an object as well,
                in which case it's __dict__ is used.
            :param `as_strings`: if True, then string representations of values
                are fetched instead of native types. Useful for config and such.
            :param `inc_attributes`: if True, then property attributes are added
                in the form of "@<propname>@<attr>".
            :returns: A dictionary with values. It is always a dictionary,
                so if dict_ was and object with __dict__ attribute, then that
                attribute is returned.
            """,
        body="""\
            if dict_ is None:
                dict_ = {}
            elif hasattr(dict_,'__dict__'):
                dict_ = dict_.__dict__

            getter = self.GetPropertyValue if not as_strings else self.GetPropertyValueAsString

            it = self.GetVIterator(PG_ITERATE_PROPERTIES)
            while not it.AtEnd():
                p = it.GetProperty()
                name = p.GetName()
                dict_[name] = getter(p)

                if inc_attributes:
                    attrs = p.GetAttributes()
                    if attrs and len(attrs):
                        dict_['@%s@attr'%name] = attrs

                it.Next()

            return dict_
            """)


    for m in c.find('SetPropertyValues').all():
        m.ignore()
    c.addPyMethod('SetPropertyValues', '(self, dict_, autofill=False)',
        doc="""\
            Sets property values from a dictionary.\n
            :param `dict_`: the source of the property values to set, which can be
                either a dictionary or an object with a __dict__ attribute.
            :param `autofill`: If true, keys with not relevant properties are
                auto-created. For more info, see :method:`AutoFill`.

            :note:
              * Keys starting with underscore are ignored.
              * Attributes can be set with entries named like "@<propname>@<attr>".
            """,
        body="""\
            if dict_ is None:
                dict_ = {}
            elif hasattr(dict_,'__dict__'):
                dict_ = dict_.__dict__
            attr_dicts = []

            def set_sub_obj(k0, dict_):
                for k,v in dict_.items():
                    if k[0] != '_':
                        if k.endswith('@attr'):
                            attr_dicts.append((k[1:-5],v))
                        else:
                            try:
                                self.SetPropertyValue(k,v)
                            except:
                                try:
                                    if autofill:
                                        self._AutoFillOne(k0,k,v)
                                        continue
                                except:
                                    if isinstance(v,dict):
                                        set_sub_obj(k,v)
                                    elif hasattr(v,'__dict__'):
                                        set_sub_obj(k,v.__dict__)

                for k,v in attr_dicts:
                    p = self.GetPropertyByName(k)
                    if not p:
                        raise AssertionError("No such property: '%s'"%k)
                    for an,av in v.items():
                        p.SetAttribute(an, av)


            cur_page = False
            is_manager = isinstance(self, PropertyGridManager)

            try:
                set_sub_obj(self.GetGrid().GetRoot(), dict_)
            except:
                import traceback
                traceback.print_exc()

            self.Refresh()
            """)

    # TODO: should these be marked as deprecated?
    module.addPyCode("""\
        PropertyGridInterface.GetValues = PropertyGridInterface.GetPropertyValues
        PropertyGridInterface.SetValues = PropertyGridInterface.SetPropertyValues
        """)


    c.addPyMethod('_AutoFillMany', '(self,cat,dict_)',
        body="""\
            for k,v in dict_.items():
                self._AutoFillOne(cat,k,v)
            """)

    c.addPyMethod('_AutoFillOne', '(self,cat,k,v)',
        body="""\
            global _type2property
            factory = _type2property.get(v.__class__,None)
            if factory:
                self.AppendIn(cat, factory(k,k,v))
            elif hasattr(v,'__dict__'):
                cat2 = self.AppendIn(cat, PropertyCategory(k))
                self._AutoFillMany(cat2, v.__dict__)
            elif isinstance(v, dict):
                cat2 = self.AppendIn(cat, PropertyCategory(k))
                self._AutoFillMany(cat2, v)
            elif not k.startswith('_'):
                raise AssertionError("member '%s' is of unregistered type/"
                                     "class '%s'"%(k,v.__class__))
            """)

    c.addPyMethod('AutoFill', '(self, obj, parent=None)',
        doc="""\
            "Clears properties and re-fills to match members and values of
            the given object or dictionary obj.
            """,
        body="""\
            self.edited_objects[parent] = obj

            cur_page = False
            is_manager = isinstance(self, PropertyGridManager)

            if not parent:
                if is_manager:
                    page = self.GetCurrentPage()
                    page.Clear()
                    parent = page.GetRoot()
                else:
                    self.Clear()
                    parent = self.GetGrid().GetRoot()
            else:
                it = self.GetIterator(PG_ITERATE_PROPERTIES, parent)
                it.Next()  # Skip the parent
                while not it.AtEnd():
                    p = it.GetProperty()
                    if not p.IsSomeParent(parent):
                        break

                    self.DeleteProperty(p)

                    name = p.GetName()
                    it.Next()

            if not is_manager or page == self.GetCurrentPage():
                self.Freeze()
                cur_page = True

            try:
                self._AutoFillMany(parent,obj.__dict__)
            except:
                import traceback
                traceback.print_exc()

            if cur_page:
                self.Thaw()
            """)


    c.addPyMethod('RegisterEditor', '(self, editor, editorName=None)',
        doc="Register a new editor, either an instance or a class.",
        body="""\
            if not isinstance(editor, PGEditor):
                editor = editor()
            if not editorName:
                editorName = editor.__class__.__name__
            try:
                self._editor_instances.append(editor)
            except:
                self._editor_instances = [editor]
            return PropertyGrid.DoRegisterEditorClass(editor, editorName)
            """
        )


    c.find('GetPropertyClientData').ignore()
    c.addPyMethod('GetPropertyClientData', '(self, p)',
        body="""\
            if isinstance(p, str):
                p = self.GetPropertyByName(p)
            return p.GetClientData()
            """)

    c.find('SetPropertyClientData').ignore()
    c.addPyMethod('SetPropertyClientData', '(self, p, data)',
        body="""\
            if isinstance(p, str):
                p = self.GetPropertyByName(p)
            return p.SetClientData(data)
            """)



    c.addPyMethod('GetPyIterator', '(self, flags=PG_ITERATE_DEFAULT, firstProperty=None)',
        doc="""\
            Returns a pythonic property iterator for a single :ref:`PropertyGrid`
            or page in :ref:`PropertyGridManager`. Arguments are same as for
            :ref:`GetIterator`.

            The following example demonstrates iterating absolutely all items in
            a single grid::

                iterator = propGrid.GetPyIterator(wx.propgrid.PG_ITERATE_ALL)
                for prop in iterator:
                    print(prop)

            :see: `wx.propgrid.PropertyGridInterface.Properties`
                  `wx.propgrid.PropertyGridInterface.Items`
            """,
        body="""\
            it = self.GetIterator(flags, firstProperty)
            while not it.AtEnd():
                yield it.GetProperty()
                it.Next()
            """)


    c.addPyMethod('GetPyVIterator', '(self, flags=PG_ITERATE_DEFAULT)',
        doc="""\
            Similar to :ref:`GetVIterator` but returns a pythonic iterator.
            """,
        body="""\
            it = self.GetVIterator(flags)
            while not it.AtEnd():
                yield it.GetProperty()
                it.Next()
            """)


    c.addPyMethod('_Properties', '(self)',
        doc="""\
            This attribute is a pythonic iterator over all properties in
            this `PropertyGrid` property container. It will only skip
            categories and private child properties. Usage is simple::

                for prop in propGrid.Properties:
                    print(prop)

            :see: `wx.propgrid.PropertyGridInterface.Items`
                  `wx.propgrid.PropertyGridInterface.GetPyIterator`
            """,
        body="""\
            it = self.GetIterator(PG_ITERATE_NORMAL)
            while not it.AtEnd():
                yield it.GetProperty()
                it.Next()
            """)
    c.addPyProperty('Properties', '_Properties')


    c.addPyMethod('_Items', '(self)',
        doc="""\
            This attribute is a pythonic iterator over all items in this
            `PropertyGrid` property container, excluding only private child
            properties. Usage is simple::

                for prop in propGrid.Items:
                    print(prop)

            :see: `wx.propgrid.PropertyGridInterface.Properties`
                  `wx.propgrid.PropertyGridInterface.GetPyVIterator`
            """,
        body="""\
            it = self.GetVIterator(PG_ITERATE_NORMAL | PG_ITERATE_CATEGORIES)
            while not it.AtEnd():
                yield it.GetProperty()
                it.Next()
            """)
    c.addPyProperty('Items', '_Items')


    #----------------------------------------------------------

    module.addItem(
        tools.wxArrayPtrWrapperTemplate('wxArrayPGProperty', 'wxPGProperty', module))



    # wxPGPropArg is a typedef for "const wxPGPropArgCls&" so having the
    # wrappers treat it as a normal type can be problematic. ("new cannot be
    # applied to a reference type", etc.) Let's just ignore it and replace it
    # everywhere for the real type.
    module.find('wxPGPropArg').ignore()
    for item in module.allItems():
        if hasattr(item, 'type') and item.type == 'wxPGPropArg':
            item.type = 'const wxPGPropArgCls &'


    # Switch all wxVariant types to wxPGVariant, so the propgrid-specific
    # version of the MappedType will be used for converting to/from Python
    # objects.
    for item in module.allItems():
        if hasattr(item, 'type') and 'wxVariant' in item.type:
            item.type = item.type.replace('wxVariant', 'wxPGVariant')


    #-----------------------------------------------------------------
    tools.doCommonTweaks(module)
    tools.runGenerators(module)
Ejemplo n.º 5
0
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))
    module.addItem(
        tools.wxListWrapperTemplate('wxRichTextLineList', 'wxRichTextLine', 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 = module.find('wxTextAttrDimensions')
    tools.ignoreConstOverloads(c)
    c.addCppMethod('int', '__nonzero__', '()', "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 = module.find('wxTextAttrBorder')
    tools.ignoreConstOverloads(c)
    c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")


    #-------------------------------------------------------
    c = module.find('wxTextAttrBorders')
    tools.ignoreConstOverloads(c)
    c.addCppMethod('int', '__nonzero__', '()', "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.find('operator[]').ignore()


    #-------------------------------------------------------
    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?
    
    
        # This are the pure virtuals in the base class. SIP needs to see that
        # all the drived 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('wxRichTextField')
    _fixDrawObject(c)


    #-------------------------------------------------------
    c = module.find('wxRichTextLine')
    tools.ignoreConstOverloads(c)
    c.find('SetRange.from').name = 'from_'
    c.find('SetRange.to').name = 'to_'


    #-------------------------------------------------------
    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_&'
    
    
    #-------------------------------------------------------
    c = module.find('wxRichTextPlainText')
    _fixDrawObject(c)
    
    #-------------------------------------------------------
    c = module.find('wxRichTextImage')
    tools.ignoreConstOverloads(c)
    _fixDrawObject(c)
    
    
    #-------------------------------------------------------
    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 = 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 swithcing 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()
    

    
    #-----------------------------------------------------------------
    tools.doCommonTweaks(module)
    tools.runGenerators(module)
Ejemplo n.º 6
0
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.

    # These are duplicates, ignore the ones in this module
    module.find('wxPG_PROPERTYVALUES_FLAGS').ignore()
    module.find('wxPG_LABEL').ignore()
    module.find('wxPG_LABEL_STRING').ignore()
    module.find('wxPG_COLOUR_BLACK').ignore()
    module.find('wxPG_COLOUR').ignore()
    module.find('wxPG_DEFAULT_IMAGE_SIZE').ignore()


    #----------------------------------------------------------
    c = module.find('wxPGPropArgCls')
    assert isinstance(c, etgtools.ClassDef)
    c.find('wxPGPropArgCls').findOverload('wxString &').ignore()
    c.find('wxPGPropArgCls').findOverload('char *').ignore()
    c.find('wxPGPropArgCls').findOverload('wchar_t *').ignore()
    c.find('wxPGPropArgCls').findOverload('int').ignore()
    c.find('wxPGPropArgCls').findOverload('deallocPtr').ignore()

    # Make a string ctor that uses the wxPython-specific version of
    # the C++ class' ctor
    newCtor = c.addCppCtor('(const wxString& str)',
        doc="Creates a PGPropArgCls from a string.",
        body="""\
            wxString* name = new wxString(*str);
            return new wxPGPropArgCls(name, true);
        """
        )

    # Make it be the first overload instead of the last
    ctor = c.find('wxPGPropArgCls')
    overloads = list(ctor.overloads)
    del overloads[overloads.index(newCtor)]
    overloads.insert(0, newCtor)
    ctor.overloads = overloads


    c.find('GetPtr').overloads[0].ignore()

    c.convertFromPyObject = """\
        // Code to test a PyObject for compatibility with wxPGPropArgCls
        if (!sipIsErr) {
            if (sipCanConvertToType(sipPy, sipType_wxPGPropArgCls, SIP_NO_CONVERTORS))
                return TRUE;
            if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy))
                return TRUE;
            if (sipPy == Py_None)
                return TRUE;
            if (sipCanConvertToType(sipPy, sipType_wxPGProperty, SIP_NO_CONVERTORS))
                return TRUE;
            return FALSE;
        }

        // Code to convert a compatible PyObject to a wxPGPropArgCls
        if (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy)) {
            wxString* name = new wxString(Py2wxString(sipPy));
            *sipCppPtr = new wxPGPropArgCls(name, true);
            return sipGetState(sipTransferObj);
        }
        else if (sipCanConvertToType(sipPy, sipType_wxPGProperty, SIP_NO_CONVERTORS)) {
            int state = 0;
            wxPGProperty* prop = reinterpret_cast<wxPGProperty*>(
                sipConvertToType(sipPy, sipType_wxPGProperty, sipTransferObj, SIP_NO_CONVERTORS, &state, sipIsErr));
            *sipCppPtr = new wxPGPropArgCls(prop);
            sipReleaseType(prop, sipType_wxPGProperty, state);
            return sipGetState(sipTransferObj);
        }
        else if (sipPy == Py_None) {
            *sipCppPtr = new wxPGPropArgCls(reinterpret_cast< wxPGProperty * >(NULL));
            return sipGetState(sipTransferObj);
        }
        else {
            // It's already a wxPGPropArgCls, just fetch the pointer and return
            *sipCppPtr = reinterpret_cast<wxPGPropArgCls*>(sipConvertToType(
                sipPy, sipType_wxPGPropArgCls, sipTransferObj,
                SIP_NO_CONVERTORS, 0, sipIsErr));
            return 0; // not a new instance
        }
        """


    #----------------------------------------------------------
    c = module.find('wxPropertyGridInterface')
    c.abstract = True
    for m in c.findAll('GetIterator'):
        if m.type == 'wxPropertyGridConstIterator':
            m.ignore()

    tools.ignoreConstOverloads(c)

    spv = c.find('SetPropertyValue')
    spv.findOverload('int value').ignore()
    spv.findOverload('wxLongLong_t value').ignore()
    spv.findOverload('wxULongLong_t value').ignore()
    spv.findOverload('wxObject *value').ignore()

    # Reorder SetPropertyValue overloads so the one taking a long int is not
    # first. Mark others that could be auto-converted from int as
    # "constrained" so they will only be used for that specific type. This
    # should result in SetPropertyValue(id, double) only used for floats and
    # not ints, or other things that can convert to int.
    spv.findOverload('bool value').find('value').constrained = True
    spv.findOverload('double value').find('value').constrained = True
    spv_long = spv.findOverload('long value')
    spv_long.ignore()
    spv.reorderOverloads() # Ensures an ignored item is not first,
    spv_long.ignore(False) # and then we can unignore it.


    c.find('Append.property').transfer = True
    c.find('AppendIn.newProperty').transfer = True
    for m in c.find('Insert').all():
        m.find('newProperty').transfer = True

    # Fix some syntax that sip doesn't like
    p = c.find('GetPropertiesWithFlag.iterFlags')
    if p.default.startswith('('):
        p.default = p.default[1:-1]


    # Tons of Python method implementations ported from Classic...

    module.addPyCode("""\
        _type2property = None
        _vt2getter = None
        """)

    c.addPyMethod('MapType', '(self, class_, factory)',
        doc="""\
            Registers Python type/class to property mapping.

            :param `factory`: Property builder function/class.
            """,
        body="""\
            global _type2property
            if _type2property is None:
                raise AssertionError("call only after a propertygrid or "
                                     "manager instance constructed")
            _type2property[class_] = factory
            """)


    c.addPyMethod('DoDefaultTypeMappings', '(self)',
        doc="Add built-in properties to the map.",
        body="""\
            import sys
            global _type2property
            if _type2property is not None:
                return
            _type2property = dict()

            _type2property[str] = StringProperty
            if sys.version_info.major < 2:
                _type2property[unicode] = StringProperty
            _type2property[int] = IntProperty
            _type2property[float] = FloatProperty
            _type2property[bool] = BoolProperty
            _type2property[list] = ArrayStringProperty
            _type2property[tuple] = ArrayStringProperty
            _type2property[wx.Font] = FontProperty
            _type2property[wx.Colour] = ColourProperty
            #_type2property[wx.Size] = SizeProperty
            #_type2property[wx.Point] = PointProperty
            #_type2property[wx.FontData] = FontDataProperty
            """)


    # TODO: is this still needed?
    c.addPyMethod('DoDefaultValueTypeMappings', '(self)',
        doc="Map pg value type ids to getter methods.",
        body="""\
            global _vt2getter
            if _vt2getter is not None:
                return
            _vt2getter = dict()
        """)


    c.find('GetPropertyValues').ignore()
    c.addPyMethod('GetPropertyValues',
        '(self, dict_=None, as_strings=False, inc_attributes=False)',
        doc="""\
            Returns all property values in the grid.\n
            :param `dict_`: A to fill with the property values. If not given,
                then a new one is created. The dict_ can be an object as well,
                in which case it's __dict__ is used.
            :param `as_strings`: if True, then string representations of values
                are fetched instead of native types. Useful for config and such.
            :param `inc_attributes`: if True, then property attributes are added
                in the form of "@<propname>@<attr>".
            :returns: A dictionary with values. It is always a dictionary,
                so if dict_ was and object with __dict__ attribute, then that
                attribute is returned.
            """,
        body="""\
            if dict_ is None:
                dict_ = {}
            elif hasattr(dict_,'__dict__'):
                dict_ = dict_.__dict__

            getter = self.GetPropertyValue if not as_strings else self.GetPropertyValueAsString

            it = self.GetVIterator(PG_ITERATE_PROPERTIES)
            while not it.AtEnd():
                p = it.GetProperty()
                name = p.GetName()
                dict_[name] = getter(p)

                if inc_attributes:
                    attrs = p.GetAttributes()
                    if attrs and len(attrs):
                        dict_['@%s@attr'%name] = attrs

                it.Next()

            return dict_
            """)


    for m in c.find('SetPropertyValues').all():
        m.ignore()
    c.addPyMethod('SetPropertyValues', '(self, dict_, autofill=False)',
        doc="""\
            Sets property values from a dictionary.\n
            :param `dict_`: the source of the property values to set, which can be
                either a dictionary or an object with a __dict__ attribute.
            :param `autofill`: If true, keys with not relevant properties are
                auto-created. For more info, see :method:`AutoFill`.

            :note:
              * Keys starting with underscore are ignored.
              * Attributes can be set with entries named like "@<propname>@<attr>".
            """,
        body="""\
            if dict_ is None:
                dict_ = {}
            elif hasattr(dict_,'__dict__'):
                dict_ = dict_.__dict__
            attr_dicts = []

            def set_sub_obj(k0, dict_):
                for k,v in dict_.items():
                    if k[0] != '_':
                        if k.endswith('@attr'):
                            attr_dicts.append((k[1:-5],v))
                        else:
                            try:
                                self.SetPropertyValue(k,v)
                            except:
                                try:
                                    if autofill:
                                        self._AutoFillOne(k0,k,v)
                                        continue
                                except:
                                    if isinstance(v,dict):
                                        set_sub_obj(k,v)
                                    elif hasattr(v,'__dict__'):
                                        set_sub_obj(k,v.__dict__)

                for k,v in attr_dicts:
                    p = self.GetPropertyByName(k)
                    if not p:
                        raise AssertionError("No such property: '%s'"%k)
                    for an,av in v.items():
                        p.SetAttribute(an, av)


            cur_page = False
            is_manager = isinstance(self, PropertyGridManager)

            try:
                set_sub_obj(self.GetGrid().GetRoot(), dict_)
            except:
                import traceback
                traceback.print_exc()

            self.Refresh()
            """)

    # TODO: should these be marked as deprecated?
    module.addPyCode("""\
        PropertyGridInterface.GetValues = PropertyGridInterface.GetPropertyValues
        PropertyGridInterface.SetValues = PropertyGridInterface.SetPropertyValues
        """)


    c.addPyMethod('_AutoFillMany', '(self,cat,dict_)',
        body="""\
            for k,v in dict_.items():
                self._AutoFillOne(cat,k,v)
            """)

    c.addPyMethod('_AutoFillOne', '(self,cat,k,v)',
        body="""\
            global _type2property
            factory = _type2property.get(v.__class__,None)
            if factory:
                self.AppendIn(cat, factory(k,k,v))
            elif hasattr(v,'__dict__'):
                cat2 = self.AppendIn(cat, PropertyCategory(k))
                self._AutoFillMany(cat2, v.__dict__)
            elif isinstance(v, dict):
                cat2 = self.AppendIn(cat, PropertyCategory(k))
                self._AutoFillMany(cat2, v)
            elif not k.startswith('_'):
                raise AssertionError("member '%s' is of unregistered type/"
                                     "class '%s'"%(k,v.__class__))
            """)

    c.addPyMethod('AutoFill', '(self, obj, parent=None)',
        doc="""\
            "Clears properties and re-fills to match members and values of
            the given object or dictionary obj.
            """,
        body="""\
            self.edited_objects[parent] = obj

            cur_page = False
            is_manager = isinstance(self, PropertyGridManager)

            if not parent:
                if is_manager:
                    page = self.GetCurrentPage()
                    page.Clear()
                    parent = page.GetRoot()
                else:
                    self.Clear()
                    parent = self.GetGrid().GetRoot()
            else:
                it = self.GetIterator(PG_ITERATE_PROPERTIES, parent)
                it.Next()  # Skip the parent
                while not it.AtEnd():
                    p = it.GetProperty()
                    if not p.IsSomeParent(parent):
                        break

                    self.DeleteProperty(p)

                    name = p.GetName()
                    it.Next()

            if not is_manager or page == self.GetCurrentPage():
                self.Freeze()
                cur_page = True

            try:
                self._AutoFillMany(parent,obj.__dict__)
            except:
                import traceback
                traceback.print_exc()

            if cur_page:
                self.Thaw()
            """)


    c.addPyMethod('RegisterEditor', '(self, editor, editorName=None)',
        doc="Register a new editor, either an instance or a class.",
        body="""\
            if not isinstance(editor, PGEditor):
                editor = editor()
            if not editorName:
                editorName = editor.__class__.__name__
            try:
                self._editor_instances.append(editor)
            except:
                self._editor_instances = [editor]
            return PropertyGrid.DoRegisterEditorClass(editor, editorName)
            """
        )


    c.find('GetPropertyClientData').ignore()
    c.addPyMethod('GetPropertyClientData', '(self, p)',
        body="""\
            if isinstance(p, str):
                p = self.GetPropertyByName(p)
            return p.GetClientData()
            """)

    c.find('SetPropertyClientData').ignore()
    c.addPyMethod('SetPropertyClientData', '(self, p, data)',
        body="""\
            if isinstance(p, str):
                p = self.GetPropertyByName(p)
            return p.SetClientData(data)
            """)



    c.addPyMethod('GetPyIterator', '(self, flags=PG_ITERATE_DEFAULT, firstProperty=None)',
        doc="""\
            Returns a pythonic property iterator for a single :ref:`PropertyGrid`
            or page in :ref:`PropertyGridManager`. Arguments are same as for
            :ref:`GetIterator`.

            The following example demonstrates iterating absolutely all items in
            a single grid::

                iterator = propGrid.GetPyIterator(wx.propgrid.PG_ITERATE_ALL)
                for prop in iterator:
                    print(prop)

            :see: `wx.propgrid.PropertyGridInterface.Properties`
                  `wx.propgrid.PropertyGridInterface.Items`
            """,
        body="""\
            it = self.GetIterator(flags, firstProperty)
            while not it.AtEnd():
                yield it.GetProperty()
                it.Next()
            """)


    c.addPyMethod('GetPyVIterator', '(self, flags=PG_ITERATE_DEFAULT)',
        doc="""\
            Similar to :ref:`GetVIterator` but returns a pythonic iterator.
            """,
        body="""\
            it = self.GetVIterator(flags)
            while not it.AtEnd():
                yield it.GetProperty()
                it.Next()
            """)


    c.addPyMethod('_Properties', '(self)',
        doc="""\
            This attribute is a pythonic iterator over all properties in
            this `PropertyGrid` property container. It will only skip
            categories and private child properties. Usage is simple::

                for prop in propGrid.Properties:
                    print(prop)

            :see: `wx.propgrid.PropertyGridInterface.Items`
                  `wx.propgrid.PropertyGridInterface.GetPyIterator`
            """,
        body="""\
            it = self.GetIterator(PG_ITERATE_NORMAL)
            while not it.AtEnd():
                yield it.GetProperty()
                it.Next()
            """)
    c.addPyProperty('Properties', '_Properties')


    c.addPyMethod('_Items', '(self)',
        doc="""\
            This attribute is a pythonic iterator over all items in this
            `PropertyGrid` property container, excluding only private child
            properties. Usage is simple::

                for prop in propGrid.Items:
                    print(prop)

            :see: `wx.propgrid.PropertyGridInterface.Properties`
                  `wx.propgrid.PropertyGridInterface.GetPyVIterator`
            """,
        body="""\
            it = self.GetVIterator(PG_ITERATE_NORMAL | PG_ITERATE_CATEGORIES)
            while not it.AtEnd():
                yield it.GetProperty()
                it.Next()
            """)
    c.addPyProperty('Items', '_Items')


    #----------------------------------------------------------

    module.addItem(
        tools.wxArrayPtrWrapperTemplate('wxArrayPGProperty', 'wxPGProperty', module))



    # wxPGPropArg is a typedef for "const wxPGPropArgCls&" so having the
    # wrappers treat it as a normal type can be problematic. ("new cannot be
    # applied to a reference type", etc.) Let's just ignore it and replace it
    # everywhere for the real type.
    module.find('wxPGPropArg').ignore()
    for item in module.allItems():
        if hasattr(item, 'type') and item.type == 'wxPGPropArg':
            item.type = 'const wxPGPropArgCls &'


    # Switch all wxVariant types to wxPGVariant, so the propgrid-specific
    # version of the MappedType will be used for converting to/from Python
    # objects.
    for item in module.allItems():
        if hasattr(item, 'type') and 'wxVariant' in item.type:
            item.type = item.type.replace('wxVariant', 'wxPGVariant')


    #-----------------------------------------------------------------
    tools.doCommonTweaks(module)
    tools.runGenerators(module)
Ejemplo n.º 7
0
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))
    module.addItem(
        tools.wxListWrapperTemplate('wxRichTextLineList', 'wxRichTextLine',
                                    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 = module.find('wxTextAttrDimensions')
    tools.ignoreConstOverloads(c)
    c.addCppMethod('int', '__nonzero__', '()', "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 = module.find('wxTextAttrBorder')
    tools.ignoreConstOverloads(c)
    c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")

    #-------------------------------------------------------
    c = module.find('wxTextAttrBorders')
    tools.ignoreConstOverloads(c)
    c.addCppMethod('int', '__nonzero__', '()', "return self->IsValid();")

    #-------------------------------------------------------
    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.find('operator[]').ignore()

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

        # This are the pure virtuals in the base class. SIP needs to see that
        # all the drived 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('wxRichTextField')
    _fixDrawObject(c)

    #-------------------------------------------------------
    c = module.find('wxRichTextLine')
    tools.ignoreConstOverloads(c)
    c.find('SetRange.from').name = 'from_'
    c.find('SetRange.to').name = 'to_'

    #-------------------------------------------------------
    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_&'

    #-------------------------------------------------------
    c = module.find('wxRichTextPlainText')
    _fixDrawObject(c)

    #-------------------------------------------------------
    c = module.find('wxRichTextImage')
    _fixDrawObject(c)

    #-------------------------------------------------------
    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 = 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 swithcing 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()

    #-----------------------------------------------------------------
    tools.doCommonTweaks(module)
    tools.runGenerators(module)