Inkscape.org
Creating New Extensions symbols and custom attributes
  1. #1
    ssm2017 ssm2017 @ssm2017

    hello

    using Inkscape 1.3 (0e150ed6c4, 2023-07-21)

    i am learning how to write extensions.

    i would like to :

    - drag n drop a symbol who contains custom attributes like "foo=yes another="yes again" from the symbol panel to the document.
    - run an extension script to place text elements around the dropped symbol (my current hobby)

    problem : the attributes are not transmitted

    how to reproduce :

    - create a rectangle and add a custom attribute using the xml editor
    - click (+) in the symbols panel
    - read the code in the xml editor and see that the custom attribute is stored inside the <rect/> element who is a child of a <symbol/> element
    - drop the symbol to the document and see that there is a <use> element without the custom attribute passed

    and then :

    - using the xml editor, add a custom attribute to the <symbol/> element
    - drop the symbol to the document and see that there is a <use> element without the custom attribute passed

    questions :

    if (svg_restriction || inkscape_restriction)
    {
        say("will not be implemented because of technical impossibility (even the ai(s) could not be able to write the code)")
    }
    else {
        say("i understand your needs and the software need this powerfull option so i have just made a pr and this feature is implemented in the next release on tomorrow")
        input("coffee with or without shugar ?")
    }

    :)

  2. #2
    inklinea inklinea @inklinea⛰️

    It's more a question of what the <use> element actually is.

    https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use

    When you click the + icon in the symbol panel.

    The node for that element is moved into <defs> as a child of a new <symbol> element.

    A <use> element with a link to the above symbol is created and occupies the same position in the document that  your original element had.

    If you navigate in the xml editor to <defs> and look for the new <symbol>, you will see that the code for the original element is there, including and custom attributes you have made.

    So all the attributes on the original element will not be visible in <use>.

    If that was not the case then <use> would not serve much purpose.

    The question is - what happens if we duplicate (creating a conflict) or add new unique attributes to the <use> element ? 

    Generally x, y are additive, transforms are additive, width and height only have an effect if the element you have created has it's own viewbox - (which is a complex example)

    For other attributes it depends.

    style attributes on the <use> element will not override the style attribute in the symbol for example. style would have to be removed from the symbol to allow the <use> element to have it's own style.

    For custom attributes, if they are not attributes which are already part of the svg spec, then the attribute on the <use> element should override. 

    If you want to use custom attributes it might be better to use the svg data-* attribute, that way you know that conflicts should not occur.

    https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/data-*

    For example:

    <my_element data-waffle="A load of Waffle"/>

    However if you wanted to read an attribute which is not specified in the <use> element, then you would have to query the linked symbol.

    -------------------------

    For making a text element it's as simple as

    from inkex import TextElement

    my_text_element = TextElement()
    my_text_element.set('x', 20)
    my_text_element.set('y', 40)
    my_text_element.text = 'Inkscape Is Cool !'
    my_text_element.style = {'stroke': 'none', 'fill': 'blue', 'font-family': 'cursive'}
    self.svg.get_current_layer().append(my_text_element)

    Positioning the text around the object is another question. You can created textpaths etc - or use the bounding box of the <use> element to place the text.

  3. #3
    ssm2017 ssm2017 @ssm2017

    hello,

    thank you for you quick answer.

    maybe my post was posted at the wrong place because my issue is not really related to the extension's dev but a feature request for the symbol panel itself.

    thank you for telling me about the "data-*" attribute and i will use them now for my needs.

    as you said, i need to write a script to query and copy the custom attributes from the <symbol/> to the <use/>.

    but if i am adding data-* attributes to the <symbol/> element, maybe the inkscape's symbol panel could pass these attributes to the <use/> element and cherry on the cake, the custom data-* attributes could be displayed and edited in the object properties's panel :)

  4. #4
    ssm2017 ssm2017 @ssm2017

    here is the script i have made for that :

    symbol_attributes_extractor.inx

    <?xml version="1.0" encoding="UTF-8"?>
    <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
      <name>Symbol attributes extractor</name>
      <id>org.inkscape.ssm2017.symbol_attributes_extractor</id>
      <effect>
        <effects-menu>
          <submenu name="Symbols"/>
        </effects-menu>
      </effect>
      <script>
        <command location="inx" interpreter="python">symbol_attributes_extractor.py</command>
      </script>
    </inkscape-extension>
    

    symbol_attributes_extractor.py

    import inkex
    
    class SymbolAttributesExtracterExtension(inkex.EffectExtension):
    
        def effect(self):
    
            for node in self.svg.selection:
                # check if the node is a <use> element
                if node.tag_name == "use":
                    # get the symbol id
                    symbol_id = node.get("xlink:href")
                    # look for the symbol
                    symbol = self.svg.getElementById(symbol_id)
                    # get attributes and assign them to the <use>
                    for attrib_name, attrib_value in symbol.attrib.items():
                        if attrib_name.startswith("data-"):
                            if not node.get(attrib_name):
                                node.set(attrib_name, attrib_value)
    
    if __name__ == '__main__':
        SymbolAttributesExtracterExtension().run()

     

  5. #5
    inklinea inklinea @inklinea⛰️

    Yes that will work. 

    However be aware that <use> can reference any ID in the document, not just symbols.

    <use> is most commonly used for 'clones' that is 'xlink:href' refs to another object on canvas.

    You can in fact have a clone of a clone of a clone :)

    Or a object which refers to a symbol then a clone of a clone of that object :)

    -----------------------------

    Also if the svg file is not one you  have created yourself, (for example web generated) it may use the newer 'href' rather than 'xlink:hef'