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
21 changes: 21 additions & 0 deletions etc/development scripts/import_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from pathlib import Path

import drawpyo
from drawpyo import load_diagram

# Load Draw.io diagram
relative_path = Path("..") / "reference drawio charts" / "object.drawio"
file_path = (Path(__file__).parent / relative_path).resolve()

diagram = load_diagram(file_path)

# Create file & page
file = drawpyo.File()
file.file_path = str(Path.home() / "Test Drawpyo Charts")
file.file_name = "Test_object.drawio"

page = drawpyo.Page(file=file)

diagram.add_to(page)
# Write the file
file.write()
47 changes: 47 additions & 0 deletions etc/reference drawio charts/object.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<mxfile host="Drawpyo">
<diagram name="Page-1" id="hyHWzmBswkbCvm2kR1NW">
<mxGraphModel dx="2037" dy="830" grid="1">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<object label="" test="test" id="2xg5nJA0Zl71o69cM8dW-4">
<mxCell
edge="1"
parent="1"
source="2xg5nJA0Zl71o69cM8dW-1"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;"
target="2xg5nJA0Zl71o69cM8dW-2"
>
<mxGeometry relative="1" as="geometry" />
</mxCell>
</object>
<object label="" test="test" id="2xg5nJA0Zl71o69cM8dW-1">
<mxCell parent="1" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1">
<mxGeometry height="60" width="120" x="350" y="370" as="geometry" />
</mxCell>
</object>
<mxCell
id="2xg5nJA0Zl71o69cM8dW-5"
edge="1"
parent="1"
source="2xg5nJA0Zl71o69cM8dW-2"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;"
target="2xg5nJA0Zl71o69cM8dW-1"
>
<mxGeometry relative="1" as="geometry" />
</mxCell>
<UserObject
label="%name%"
name="Name"
placeholders="1"
link="data:page/id,hyHWzmBswkbCvm2kR1NW"
id="2xg5nJA0Zl71o69cM8dW-2"
>
<mxCell parent="1" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1">
<mxGeometry height="60" width="120" x="150" y="280" as="geometry" />
</mxCell>
</UserObject>
</root>
</mxGraphModel>
</diagram>
</mxfile>
44 changes: 42 additions & 2 deletions src/drawpyo/diagram/edges.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.xml_class: str = "mxCell"

self.object_attributes: Dict[str, str] = dict(
kwargs.get("object_attributes", {})
)
self.user_object_attributes: Dict[str, str] = dict(
kwargs.get("user_object_attributes", {})
)

# Style
self.color_scheme: Optional[ColorScheme] = kwargs.get("color_scheme", None)
self.text_format: Optional[TextFormat] = kwargs.get("text_format", TextFormat())
Expand Down Expand Up @@ -210,15 +217,20 @@ def attributes(self) -> Dict[str, Any]:
Returns:
dict: Dictionary of object attributes and their values
"""
id_value = self.id
if self.object_attributes or self.user_object_attributes:
id_value = None
base_attr_dict: Dict[str, Any] = {
"id": self.id,
"id": id_value,
"style": self.style,
"edge": self.edge,
"parent": self.xml_parent_id,
"source": self.source_id,
"target": self.target_id,
}
if self.value is not None:
if self.value is not None and not (
self.object_attributes or self.user_object_attributes
):
base_attr_dict["value"] = self.value
return base_attr_dict

Expand Down Expand Up @@ -591,8 +603,36 @@ def xml(self) -> str:
tag: str = (
self.xml_open_tag + "\n " + self.geometry.xml + "\n" + self.xml_close_tag
)
wrapper_tag = None
wrapper_attrs = None
if self.user_object_attributes:
wrapper_tag = "UserObject"
wrapper_attrs = self.user_object_attributes
elif self.object_attributes:
wrapper_tag = "object"
wrapper_attrs = self.object_attributes
if wrapper_tag and wrapper_attrs is not None:
return (
self._wrapper_open_tag(wrapper_tag, wrapper_attrs)
+ "\n "
+ tag.replace("\n", "\n ")
+ f"\n</{wrapper_tag}>"
)
return tag

def _wrapper_open_tag(self, tag: str, attrs: Dict[str, str]) -> str:
attrs = {k: v for k, v in attrs.items() if v is not None}
if "label" not in attrs and self.value is not None:
attrs["label"] = self.value
if "id" not in attrs:
attrs["id"] = self.id

open_tag = f"<{tag}"
for att, value in attrs.items():
xml_parameter = self.xml_ify(str(value))
open_tag = open_tag + " " + att + '="' + xml_parameter + '"'
return open_tag + ">"


class BasicEdge(Edge):
pass
Expand Down
55 changes: 49 additions & 6 deletions src/drawpyo/diagram/objects.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from os import path
from typing import Optional, Dict, Any, List, Union, Tuple
from ..utils.logger import logger
from typing import Any, Dict, List, Optional, Tuple, Union

from ..utils.color_scheme import ColorScheme
from ..utils.logger import logger
from ..utils.standard_colors import StandardColor
from .base_diagram import (
DiagramBase,
Geometry,
import_shape_database,
)
from .text_format import TextFormat
from ..utils.color_scheme import ColorScheme
from ..utils.standard_colors import StandardColor

__all__ = ["Object", "BasicObject", "Group", "object_from_library"]

Expand Down Expand Up @@ -143,6 +143,12 @@ def __init__(
self.autosize_to_children: bool = kwargs.get("autosize_to_children", False)
self.autocontract: bool = kwargs.get("autocontract", False)
self.autosize_margin: int = kwargs.get("autosize_margin", 20)
self.object_attributes: Dict[str, str] = dict(
kwargs.get("object_attributes", {})
)
self.user_object_attributes: Dict[str, str] = dict(
kwargs.get("user_object_attributes", {})
)

# Geometry
self.position: Optional[tuple] = position
Expand Down Expand Up @@ -352,9 +358,16 @@ def format_as_library_object(

@property
def attributes(self) -> Dict[str, Any]:
id_value = self.id
value_value = self.value
if not (self.tag or self.tooltip) and (
self.object_attributes or self.user_object_attributes
):
id_value = None
value_value = None
return {
"id": self.id,
"value": self.value,
"id": id_value,
"value": value_value,
"style": self.style,
"vertex": self.vertex,
"parent": self.xml_parent_id,
Expand Down Expand Up @@ -704,8 +717,38 @@ def xml(self) -> str:
tag: str = (
self.xml_open_tag + "\n " + self.geometry.xml + "\n" + self.xml_close_tag
)
if self.tag or self.tooltip:
return tag
wrapper_tag = None
wrapper_attrs = None
if self.user_object_attributes:
wrapper_tag = "UserObject"
wrapper_attrs = self.user_object_attributes
elif self.object_attributes:
wrapper_tag = "object"
wrapper_attrs = self.object_attributes
if wrapper_tag and wrapper_attrs is not None:
return (
self._wrapper_open_tag(wrapper_tag, wrapper_attrs)
+ "\n "
+ tag.replace("\n", "\n ")
+ f"\n</{wrapper_tag}>"
)
return tag

def _wrapper_open_tag(self, tag: str, attrs: Dict[str, str]) -> str:
attrs = {k: v for k, v in attrs.items() if v is not None}
if "label" not in attrs and self.value is not None:
attrs["label"] = self.value
if "id" not in attrs:
attrs["id"] = self.id

open_tag = f"<{tag}"
for att, value in attrs.items():
xml_parameter = self.xml_ify(str(value))
open_tag = open_tag + " " + att + '="' + xml_parameter + '"'
return open_tag + ">"


class BasicObject(Object):
pass
Expand Down
Loading
Loading