Source code for svgen.attribute.viewbox
"""
svgen - A module for the 'viewBox' attribute.
"""
# built-in
from typing import NamedTuple, Union
# third-party
from vcorelib.dict import GenericStrDict
# internal
from svgen.attribute import Attribute
from svgen.cartesian import Dimensions
from svgen.cartesian.mutate import Translation
from svgen.cartesian.plane import Plane
from svgen.cartesian.point import Point
from svgen.cartesian.rectangle import Rectangle
from svgen.cartesian.rectangle.grid import RectangleGrid
[docs]
class ViewBoxData(NamedTuple):
"""Primitive data for a viewBox attribute."""
min_x: int
min_y: int
width: int
height: int
[docs]
def translate(self, dx: int, dy: int) -> "ViewBoxData":
"""Translate this viewBox."""
return ViewBoxData(
self.min_x + dx, self.min_y + dy, self.width, self.height
)
@property
def origin(self) -> Point:
"""Get the origin for this viewBox."""
return Point(float(self.min_x), float(self.min_y))
@property
def center(self) -> Point:
"""Get the center point for this viewBox."""
return Point(
self.min_x + (float(self.width) / 2.0),
self.min_y + (float(self.height) / 2.0),
True,
)
[docs]
@staticmethod
def from_dict(data: GenericStrDict) -> "ViewBoxData":
"""Create viewBox data from a dictionary."""
return ViewBoxData(
data.get("min_x", 0),
data.get("min_y", 0),
data["width"],
data["height"],
)
[docs]
class ViewBox(Attribute):
"""An interface for viewBox attributes."""
def __init__(
self, min_x: int, min_y: int, width: int, height: int
) -> None:
"""Construct a new viewBox."""
self.data = ViewBoxData(min_x, min_y, width, height)
self.plane = Plane(self.data.origin)
self.box = Rectangle(self.dimensions, self.origin)
self.grid = RectangleGrid(self.box, width, height)
@property
def width(self) -> int:
"""Get the width of this viewbox."""
return self.data.width
@property
def height(self) -> int:
"""Get the height of this viewbox."""
return self.data.height
[docs]
def new_grid(
self, rect: Rectangle = None, columns: int = None, rows: int = None
) -> RectangleGrid:
"""Create a grid from this viewBox."""
return self.grid.adjust(columns, rows, rect)
[docs]
def translate(
self, dx: Union[Translation, float], *args, **kwargs
) -> None:
"""Apply a translation to this viewBox."""
move = Translation.normalize(dx, *args, **kwargs)
# Update instance attributes.
self.data = self.data.translate(int(move.dx), int(move.dy))
self.box = self.box.translate(move)
self.plane.translate(move)
self.grid = self.grid.translate(move)
@property
def dimensions(self) -> Dimensions:
"""Get this viewBox's dimensions."""
return Dimensions(float(self.data.width), float(self.data.height))
@property
def origin(self) -> Point:
"""Get this viewBox's origin."""
return self.plane.origin
@property
def key(self) -> str:
"""Get the string key for this attribute."""
return "viewBox"
@property
def value(self) -> str:
"""Get the string value for this attribute."""
return (
f"{self.data.min_x} {self.data.min_y} "
f"{self.data.width} {self.data.height}"
)
@property
def center(self) -> Point:
"""Get the center point for this viewBox."""
return self.data.center
[docs]
@classmethod
def decode(cls: type["ViewBox"], key: str, value: str) -> "ViewBox":
"""Create this attribute from a string."""
assert key == "viewBox"
args = [int(x) for x in value.split()]
assert len(args) == 4
return cls(*args)
[docs]
@staticmethod
def from_dict(data: GenericStrDict) -> "ViewBox":
"""Create a viewBox from dictionary data."""
return ViewBox(*ViewBoxData.from_dict(data))