Better drawing and added more icons

This commit is contained in:
2026-07-20 13:18:16 +02:00
parent ee859c4311
commit 4ab74f64e2
27 changed files with 4087 additions and 307 deletions

View File

@@ -51,18 +51,33 @@ class Icon:
def __post_init__(self) -> None:
if not self.elements:
self.elements = [{
"type": "ellipse" if self.shape == "ellipse" else "rectangle",
"x": 32.0, "y": 32.0, "width": 64.0, "height": 64.0,
"fill": self.fill, "stroke": self.border, "lineWidth": 1.5,
"lineStyle": "solid", "cornerRadius": 5.0,
}]
self.elements = [
{
"type": "ellipse" if self.shape == "ellipse" else "rectangle",
"x": 32.0,
"y": 32.0,
"width": 64.0,
"height": 64.0,
"fill": self.fill,
"stroke": self.border,
"lineWidth": 1.5,
"lineStyle": "solid",
"cornerRadius": 5.0,
}
]
if self.text:
self.elements.append({
"type": "text", "x": 40.0, "y": 40.0,
"width": 48.0, "height": 48.0,
"text": self.text, "color": "#202020", "fontSize": 12.0,
})
self.elements.append(
{
"type": "text",
"x": 40.0,
"y": 40.0,
"width": 48.0,
"height": 48.0,
"text": self.text,
"color": "#202020",
"fontSize": 12.0,
}
)
def to_dict(self) -> dict[str, Any]:
return {
@@ -137,15 +152,57 @@ class Connection:
)
@dataclass
class Annotation:
id: str
kind: str
x: float = 0.0
y: float = 0.0
width: float = 0.0
height: float = 0.0
text: str = ""
layer: int = -1
properties: dict[str, Any] = field(default_factory=dict)
def to_dict(self) -> dict[str, Any]:
return {
"id": self.id,
"kind": self.kind,
"position": {"x": self.x, "y": self.y},
"size": {"width": self.width, "height": self.height},
"text": self.text,
"layer": self.layer,
"properties": deepcopy(self.properties),
}
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "Annotation":
position = data.get("position", {})
size = data.get("size", {})
return cls(
id=str(data["id"]),
kind=str(data["kind"]),
x=float(position.get("x", 0)),
y=float(position.get("y", 0)),
width=float(size.get("width", 0)),
height=float(size.get("height", 0)),
text=str(data.get("text", "")),
layer=int(data.get("layer", -1)),
properties=deepcopy(data.get("properties", {})),
)
@dataclass
class Graph:
blocks: dict[str, Component] = field(default_factory=dict)
connections: dict[str, Connection] = field(default_factory=dict)
annotations: dict[str, Annotation] = field(default_factory=dict)
def to_dict(self) -> dict[str, Any]:
return {
"blocks": [block.to_dict() for block in self.blocks.values()],
"connections": [connection.to_dict() for connection in self.connections.values()],
"annotations": [item.to_dict() for item in self.annotations.values()],
}
@classmethod
@@ -153,13 +210,19 @@ class Graph:
data = data or {}
blocks = [Component.from_dict(item) for item in data.get("blocks", [])]
connections = [Connection.from_dict(item) for item in data.get("connections", [])]
annotations = [Annotation.from_dict(item) for item in data.get("annotations", [])]
if len({block.id for block in blocks}) != len(blocks):
raise ValueError("A graph contains duplicate component IDs")
if len({connection.id for connection in connections}) != len(connections):
raise ValueError("A graph contains duplicate connection IDs")
if len({item.id for item in annotations}) != len(annotations):
raise ValueError("A graph contains duplicate annotation IDs")
if any(item.kind not in {"box", "line", "text"} for item in annotations):
raise ValueError("A graph contains an unknown annotation kind")
return cls(
blocks={block.id: block for block in blocks},
connections={connection.id: connection for connection in connections},
annotations={item.id: item for item in annotations},
)
@@ -349,14 +412,35 @@ def clone_component(source: Component) -> Component:
for connection in current.graph.connections.values()
for new_id in [str(uuid4())]
},
annotations={
new_id: Annotation(
new_id,
annotation.kind,
annotation.x,
annotation.y,
annotation.width,
annotation.height,
annotation.text,
annotation.layer,
deepcopy(annotation.properties),
)
for annotation in current.graph.annotations.values()
for new_id in [str(uuid4())]
},
)
return Component(
id=str(uuid4()),
name=current.name,
x=current.x,
y=current.y,
inputs=[Port(port.id, port.name, port.x, port.y, deepcopy(port.properties), port.type) for port in current.inputs],
outputs=[Port(port.id, port.name, port.x, port.y, deepcopy(port.properties), port.type) for port in current.outputs],
inputs=[
Port(port.id, port.name, port.x, port.y, deepcopy(port.properties), port.type)
for port in current.inputs
],
outputs=[
Port(port.id, port.name, port.x, port.y, deepcopy(port.properties), port.type)
for port in current.outputs
],
icon=Icon.from_dict(current.icon.to_dict()),
properties=deepcopy(current.properties),
implementation_kind=current.implementation_kind,