Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ coverage.xml
.pytest_cache/
cover/

tests/output/*.drawio

# Translations
*.mo
*.pot
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ item_from_lib = drawpyo.diagram.object_from_library(
)
```

## Import external shape libraries

You can import and use external Draw.io XML shape libraries (e.g., Azure, AWS, Google Cloud icons):

```python
# Register an external library
drawpyo.register_mxlibrary(
"developer",
"https://raw.githubusercontent.com/jgraph/drawio-libs/refs/heads/main/libs/integration/developer.xml"
)

# Use shapes from the registered library
icon = drawpyo.diagram.object_from_library(
page=page,
library="developer",
obj_name="App Developing",
position=(100, 100)
)
```

## Style an object from a string

```python
Expand Down
9 changes: 9 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ I love Draw.io! Compared to expensive and heavy commercial options like Visio an

So when I had a need to generate hierarchical tree diagrams of requirement structures I looked to Draw.io but I was surprised to find there wasn't even a single existing Python library for working with these files. I took the project home and spent a weekend building the initial functionality. I've been adding functionality, robustness, and documentation intermittently since.

## Key Features

- **Create diagrams programmatically** - Generate Draw.io diagrams using Python code
- **Built-in shape libraries** - Access Draw.io's standard shape collections (General, Flowchart, etc.)
- **Import external libraries** - Load third-party icon sets from XML files (Azure, AWS, Google Cloud, etc.)
- **Automatic diagram types** - Generate trees, charts, and structured diagrams automatically
- **Full styling control** - Customize colors, fonts, borders, and effects
- **Load and modify** - Import existing Draw.io files and modify them programmatically

# The Future of Drawpyo

We’re constantly working to add new functionality, address issues and feature requests. If you find Drawpyo useful and would like to contribute, we’d greatly appreciate your help! You can reach out directly at [xander@merriman.industries](mailto:xander@merriman.industries) or join the conversation through GitHub issues.
229 changes: 227 additions & 2 deletions docs/usage/shape_libs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

The Draw.io app has a lot of built-in shape libraries available. The basic library contains shapes and building blocks but there are increasingly more specific libraries such as flowcharts, wiring diagrams, and org charts. You can also export and import shape libraries into Draw.io.

To replicate this feature for drawpyo, I created a library format based on TOML. Draw.io's libraries are XML which isn't as human readable or writable and is more specification than necessary.
To replicate this feature for drawpyo, we provide two options for shape libraries:

> Supporting Draw.io's XML based library is a planned feature.
1. **TOML format** - A custom human-readable library format we created for drawpyo, which is simpler and more accessible than XML for defining custom shapes.
2. **Draw.io's native XML format (mxlibrary)** - Direct support for Draw.io's XML shape libraries, which is useful for using third-party icon libraries like Azure, AWS, or Google Cloud icons.

## Built-In Shape Libraries

Expand Down Expand Up @@ -79,3 +80,227 @@ new_obj = drawpyo.diagram.object_from_library(
page=page,
)
```

## XML Shape Libraries (mxlibrary)

Drawpyo can import and use Draw.io's native XML shape library format (`.xml` files with `<mxlibrary>` tags). This is particularly useful for using third-party icon libraries like Azure icons, AWS icons, Google Cloud icons, and other custom shape collections available online.

### What is an mxlibrary?

An mxlibrary is Draw.io's XML-based format for storing collections of shapes. These files typically contain shapes with embedded SVG images and are commonly used for icon libraries. The format looks like:

```xml
<mxlibrary>[
{
"h": 50,
"w": 50,
"title": "Icon-Name",
"xml": "...encoded shape data..."
}
]</mxlibrary>
```

### Loading an mxlibrary

You can load an mxlibrary from either a local file or a URL:

```python
import drawpyo

# Load from a URL
shapes = drawpyo.load_mxlibrary(
"https://example.com/azure-icons.xml"
)

# Load from a local file
shapes = drawpyo.load_mxlibrary(
"/path/to/local/library.xml"
)
```

The `load_mxlibrary()` function returns a dictionary of shapes that can be used directly with `object_from_library()`.

### Registering an mxlibrary

For easier reuse, you can register an mxlibrary with a name, making it available just like the built-in libraries:

```python
import drawpyo

# Register the Azure icons library
drawpyo.register_mxlibrary(
"azure",
"https://raw.githubusercontent.com/dwarfered/azure-architecture-icons-for-drawio/main/azure-public-service-icons/004%20azure%20ecosystem.xml"
)

# Now use it like a built-in library
file = drawpyo.File()
page = drawpyo.Page(file=file)

vm_icon = drawpyo.diagram.object_from_library(
library="azure",
obj_name="01038-icon-service-Collaborative-Service",
page=page,
position=(100, 100)
)

file.write()
```

### Using mxlibrary Shapes

Once loaded or registered, you can use shapes from an mxlibrary in three ways:

#### 1. Register and use by name (recommended)

```python
import drawpyo

# Register once
drawpyo.register_mxlibrary(
"custom",
"https://example.com/custom-icons.xml"
)

# Use multiple times
file = drawpyo.File()
page = drawpyo.Page(file=file)

icon1 = drawpyo.diagram.object_from_library(
library="custom",
obj_name="Shape-Name-1",
page=page,
position=(50, 50)
)

icon2 = drawpyo.diagram.object_from_library(
library="custom",
obj_name="Shape-Name-2",
page=page,
position=(150, 50)
)
```

#### 2. Load and pass the dictionary directly

```python
import drawpyo

# Load the library
shapes = drawpyo.load_mxlibrary("https://example.com/icons.xml")

file = drawpyo.File()
page = drawpyo.Page(file=file)

# Pass the dictionary directly
icon = drawpyo.diagram.object_from_library(
library=shapes, # Pass the dict
obj_name="Icon-Name",
page=page,
position=(100, 100)
)
```

#### 3. Use with other object parameters

Like other shapes, you can override properties when creating objects from mxlibraries:

```python
icon = drawpyo.diagram.object_from_library(
library="azure",
obj_name="Virtual-Machine",
page=page,
position=(100, 100),
width=80, # Override default width
height=80, # Override default height
)
```

### Finding Shape Names

To find the available shape names in an mxlibrary:

```python
import drawpyo

shapes = drawpyo.load_mxlibrary("https://example.com/icons.xml")

# List all available shape names
print("Available shapes:")
for shape_name in shapes.keys():
print(f" - {shape_name}")
```

### Error Handling

The mxlibrary functions include comprehensive error handling:

```python
import drawpyo

try:
drawpyo.register_mxlibrary(
"mylib",
"https://example.com/library.xml"
)
except FileNotFoundError:
print("Library file not found")
except ValueError as e:
print(f"Error loading library: {e}")
```

### Example: Complete Workflow with Azure Icons

```python
import drawpyo

# Register the Azure icons library
drawpyo.register_mxlibrary(
"azure",
"https://raw.githubusercontent.com/dwarfered/azure-architecture-icons-for-drawio/main/azure-public-service-icons/004%20azure%20ecosystem.xml"
)

# Create a diagram
file = drawpyo.File()
file.file_name = "azure_architecture"
file.file_path = "./output"

page = drawpyo.Page(file=file)
page.name = "Azure Architecture"

# Add Azure service icons
vm = drawpyo.diagram.object_from_library(
library="azure",
obj_name="01038-icon-service-Collaborative-Service",
page=page,
position=(100, 100)
)

storage = drawpyo.diagram.object_from_library(
library="azure",
obj_name="01039-icon-service-Storage-Account",
page=page,
position=(300, 100)
)

# Connect them with an edge
edge = drawpyo.diagram.Edge(
page=page,
source=vm,
target=storage
)

# Save the diagram
file.write()
```

### Where to Find mxlibrary Files

Many organizations and communities provide mxlibrary files for Draw.io:

- **Azure Icons**: [GitHub - dwarfered/azure-architecture-icons-for-drawio](https://github.com/dwarfered/azure-architecture-icons-for-drawio)
- **AWS Icons**: Available from AWS Architecture Icons
- **Google Cloud Icons**: Available from Google Cloud Architecture Diagramming Tool
- **Custom Libraries**: Export your own from Draw.io via File → Export → Library

You can also create your own mxlibrary files using the Draw.io application by selecting shapes and exporting them as a library.
76 changes: 76 additions & 0 deletions etc/development scripts/create_azure_diagram.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import drawpyo

# Register Azure icons
azure_url = "https://raw.githubusercontent.com/dwarfered/azure-architecture-icons-for-drawio/refs/heads/main/azure-public-service-icons/004%20azure%20ecosystem.xml"
drawpyo.register_mxlibrary("azure", azure_url)

# Get available shapes
from drawpyo.diagram.objects import base_libraries

azure_shapes = base_libraries["azure"]
shape_names = list(azure_shapes.keys())

# Create diagram
file = drawpyo.File()
file.file_name = "azure_architecture.drawio"
file.file_path = "./etc/reference drawio charts"

page = drawpyo.Page(file=file)
page.name = "Azure Architecture Diagram"

# Add a title
title = drawpyo.diagram.Object(
page=page,
value="Azure Cloud Services",
position=(200, 50),
width=300,
height=40,
)
title.text_format.size = 20
title.text_format.bold = True
title.text_format.align = "center"
title.fillColor = "#0078D4"
title.fontColor = "#FFFFFF"
title.rounded = True

# Create shapes in a row
icons = []
y_position = 150
spacing = 150

for i, shape_name in enumerate(shape_names[:3]):
x_position = 100 + (i * spacing)

icon = drawpyo.diagram.object_from_library(
library="azure",
obj_name=shape_name,
page=page,
position=(x_position, y_position),
)

label = drawpyo.diagram.Object(
page=page,
value=shape_name.replace("-", " "),
position=(x_position - 25, y_position + 80),
width=100,
height=30,
)
label.text_format.size = 10
label.text_format.align = "center"
label.fillColor = "none"
label.strokeColor = "none"

icons.append(icon)

# Connect the icons with arrows
if len(icons) > 1:
for i in range(len(icons) - 1):
edge = drawpyo.diagram.Edge(page=page, source=icons[i], target=icons[i + 1])
edge.strokeColor = "#0078D4"
edge.strokeWidth = 2

# Save
file.write()
print(
"Azure diagram created successfully! You can now open the file in Draw.io to see the Azure icons!"
)
Loading