drawpyo Documentation

repository·main·Indexed 19 days ago

https://github.com/merrimanind/drawpyo

A Python library for programmatically generating Diagrams.net/Draw.io charts. It enables developers to create, style, and position diagram objects, write them to XML-based .drawio files, and load existing diagrams for modification. The library supports basic object placement, external shape library registration, and high-level diagram types with automated layout, including TreeDiagram, BarChart, PieChart, and BinaryTreeDiagram.

Tokens
27.9K
Snippets
107
Records
148
Agent score
64%

What's inside drawpyo

  1. Overview of drawpyo

    main
    drawpyo is a Python library designed for the programmatic generation of Draw.io charts. It allows developers to create diagram objects, place and style elements, and export the resulting diagrams to files. This is particularly useful for versioning diagrams alongside code in a repository, as Draw.io files are XML-based and plaintext-compatible.
  2. Create basic diagrams

    main

    Drawpyo's core functionality mirrors the Draw.io app. You can:

    • Create files containing one or more pages.
    • Add objects (shapes, containers, or edges) to pages.
    • Position objects within the diagram.
    • Style objects using built-in shape libraries, manual styling, or style strings.
    • Save diagrams in formats compatible with the Draw.io app.

    For detailed implementation steps, refer to the Basic Diagrams - Usage guide.

  3. Understand the color resolution hierarchy

    main

    Drawpyo resolves colors using a specific hierarchy. When an object needs a color, it checks sources in this order of priority:

    1. Object-specific colors: Colors set directly on the object (e.g., fill_color, stroke_color, or fontColor via text_format) have the highest priority and override everything else.
    2. Color Scheme: If no object-specific colors are set, Drawpyo uses the values defined in the object's assigned ColorScheme.
    3. Defaults: If neither an object-specific color nor a color scheme provides a value, Drawpyo falls back to internal defaults (e.g., Draw.io defaults).

    Hierarchy Summary: Object-specific colors > Color scheme colors > Default colors

  4. Create and manage ColorScheme objects

    main

    A ColorScheme is a reusable object that groups fill_color, stroke_color, and font_color. Each color value in a scheme can be None, a hex string (format #RRGGBB), or a StandardColor enum value. Invalid hex strings will raise a ValueError.

    from drawpyo import ColorScheme, StandardColor
    
    scheme = ColorScheme(
        fill_color=StandardColor.BLUE5,
        stroke_color="#FF0000",
    )
    
    # You can also update components after creation
    scheme.set_fill_color("#ABCDEF")
    scheme.set_stroke_color(StandardColor.GRAY7)
    scheme.set_gradient(None)
  5. Style edge labels using TextFormat

    main
    Styling for an edge's label is managed via a TextFormat object. You can access and configure these parameters through the Edge.text_format attribute. For detailed text styling options (like font, size, etc.), refer to the TextFormat documentation.
  6. How Binary Tree Diagrams work

    main

    Binary trees in drawpyo are managed using two specialized classes: BinaryTreeDiagram and BinaryNodeObject.

    • BinaryTreeDiagram: Extends TreeDiagram to provide binary-friendly layout defaults and helper methods. It manages the overall structure and layout.
    • BinaryNodeObject: A subclass of NodeObject that enforces the strict binary tree rule (at most two children). It provides dedicated left and right properties to manage child slots.

    This pairing ensures that the tree structure remains valid (no node has more than two children) and provides intuitive ways to navigate and link nodes.

    from drawpyo.diagram_types import BinaryTreeDiagram, BinaryNodeObject
    
    tree = BinaryTreeDiagram(file_path="path/to/diagram", file_name="Binary Tree.drawio")
    root = BinaryNodeObject(tree=tree, value="Root")
  7. Configure autosizing for parent containers

    main

    You can make a parent object automatically expand or contract to fit its children. This behavior is disabled by default.

    To enable it, use the following parameters:

    • autosize_to_children: Set to True to allow the parent to expand to fit its contents.
    • autosize_margin: An integer defining the margin (in pixels) to maintain around child objects. Note that this margin is inclusive of the container's title block.
    • autocontract: Set to True if you want the parent to also contract when children are removed or resized. If False, the parent will expand but never shrink.

    Manual Triggering: You can manually trigger the autofit logic at any time by calling the resize_to_children() method on the object. This method respects the configured autosize_margin and autocontract settings.

    # Example configuration
    parent_container = drawpyo.diagram.Object(
        autosize_to_children=True,
        autosize_margin=20,
        autocontract=True,
        page=page
    )
    
    # Manually trigger resize
    parent_container.resize_to_children()
  8. Rules and constraints for BinaryNodeObject

    main

    The BinaryNodeObject enforces several structural guarantees:

    • Child Slot Normalization: Nodes always maintain exactly two slots: [left, right]. If you provide only one child during creation (e.g., BinaryNodeObject(tree_children=[child])), the second slot is automatically set to None ([child, None]).
    • Strict Child Limit: Providing more than two children to tree_children (e.g., BinaryNodeObject(tree_children=[a, b, c])) will raise a ValueError.
    • Parent Safety: A node cannot have more than one parent, and it cannot occupy both the left and right slots of a parent at the same time. Assigning a node to a new parent automatically detaches it from its old one.
  9. Navigate nested objects and hierarchies

    main

    Drawpyo preserves the parent-child relationships used by Draw.io containers, swimlanes, and groups. You can navigate the hierarchy by accessing the .objects attribute of a container object, which returns its direct children. Drawpyo applies absolute positioning recursively, so child coordinates are relative to their parent.

    # Access a parent container
    parent_container = diagram.get_by_id("2292288764992")
    
    # List all child objects
    for child in parent_container.objects:
        print(f"- {child.value} at ({child.geometry.x}, {child.geometry.y})")
  10. What are Extended Objects in drawpyo

    main
    Extended objects are specialized classes that inherit from the base Object class. They provide convenience for complex Draw.io objects that are actually small groups of objects (like a container with multiple children). While they offer more functionality than a standard Object, they are not as complex as full custom diagram types. Currently, the List is the primary extended object implemented.
  11. Configure edge color, shading, and effects

    main

    You can customize the visual appearance of an edge using color, shading, and boolean effects.

    Color and Shading

    ParameterEffect
    opacityThe opacity of the edge (0-100)
    strokeColorThe color of the edge or the stroke around the edge shape ('default', 'none', or a hex color code)
    strokeWidthThe width of the edge or the stroke around the edge shape (1-999)
    fillColorThe fill color of the edge shape ('default', 'none', or a hex color code)

    Effects

    Set these boolean parameters to enable specific visual effects:

    • rounded
    • shadow
    • sketch
    • flowAnimation (animates in Draw.io)
  12. Customize Pie Chart slice labels

    main

    By default, PieChart labels slices using the format: "{label}: {percentage:.1f}%".

    You can override this behavior by providing a label_formatter callable to the PieChart constructor. The callback must accept three arguments: category (the string label), value (the numerical value), and total (the sum of all values in the dataset).

    def label_formatter(category: str, value: float, total: float) -> str:
        return f"{category}: {value/total*100:.1f}%"
    
    chart = PieChart(data, label_formatter=label_formatter)