"""GUI document data stored inside the core document metadata field.""" from __future__ import annotations from collections.abc import Mapping from dataclasses import dataclass, field from enum import Enum from typing import Any from bedit_core.models import ComponentID, ID, PortID class ShapeID(ID): pass @dataclass class Shape: layer: int type: str | None = None pos: tuple[int, int] = (0, 0) @classmethod def from_data(cls, data: Mapping[str, Any]) -> Shape: if cls is Shape and data.get("type") == "rectangle": return Rectangle.from_data(data) pos = data.get("pos", [0, 0]) return cls(layer=int(data.get("layer", 0)), type=data.get("type"), pos=(int(pos[0]), int(pos[1]))) def to_data(self) -> dict[str, Any]: return {"layer": self.layer, "type": self.type, "pos": list(self.pos)} class LineType(Enum): NONE = "none" SOLID = "solid" DASHED = "dashed" DOTTED = "dotted" DASH_DOT = "dash_dot" @dataclass class Rectangle(Shape): type: str = field(init=False, default="rectangle") width: float = 32.0 height: float = 32.0 line_type: LineType = LineType.SOLID line_thickness: float = 1.0 corner_radius: float = 0.0 line_color: str = "#000000ff" fill_color: str = "#ffffff00" @classmethod def from_data(cls, data: Mapping[str, Any]) -> Rectangle: pos = data.get("pos", [0, 0]) return cls(layer=int(data.get("layer", 0)), pos=(int(pos[0]), int(pos[1])), width=float(data.get("width", 100.0)), height=float(data.get("height", 100.0)), line_type=LineType(data.get("line_type", "solid")), line_thickness=float(data.get("line_thickness", 1.0)), corner_radius=float(data.get("corner_radius", 0.0)), line_color=str(data.get("line_color", "#000000ff")), fill_color=str(data.get("fill_color", "#ffffff00"))) def to_data(self) -> dict[str, Any]: return {**super().to_data(), "width": self.width, "height": self.height, "line_type": self.line_type.value, "line_thickness": self.line_thickness, "corner_radius": self.corner_radius, "line_color": self.line_color, "fill_color": self.fill_color} @dataclass class Text(Shape): type: str = field(init=False, default="text") width: float = 100.0 height: float = 100.0 color: str = "#000000ff" bold: bool = False italic: bool = False size: float = 16.0 text: str = "" @dataclass class Icon: shapes: dict[ShapeID, Shape] = field(default_factory=dict) port_positions: dict[PortID, tuple[int, int]] = field(default_factory=dict) @classmethod def from_data(cls, data: Mapping[str, Any]) -> Icon: shapes = {ShapeID(key): Shape.from_data(value) for key, value in data.get("shapes", {}).items()} port_positions = {PortID(key): (int(value[0]), int(value[1])) for key, value in data.get("port_positions", {}).items()} return cls(shapes=shapes, port_positions=port_positions) def to_data(self) -> dict[str, Any]: return {"shapes": {str(key): shape.to_data() for key, shape in self.shapes.items()}, "port_positions": {str(key): list(position) for key, position in self.port_positions.items()}} @dataclass class IconDatabase: format_version: int = 1 icons: dict[ComponentID, Icon] = field(default_factory=dict) @classmethod def from_data(cls, data: Mapping[str, Any]) -> IconDatabase: icons = {ComponentID(key): Icon.from_data(value) for key, value in data.get("icons", {}).items()} return cls(format_version=int(data.get("format_version", 1)), icons=icons) def to_data(self) -> dict[str, Any]: return {"format_version": self.format_version, "icons": {str(key): icon.to_data() for key, icon in self.icons.items()}}