AI-powered tool that generates publication-quality SVG charts matching PIMCO's InDesign style. Upload Excel/CSV data, write a plain-English brief, then iterate with natural language edits until the chart is exactly right. - Claude Opus 4.6 interprets briefs into structured ChartSpec JSON - Deterministic SVG renderer via drawsvg (no visual hallucinations) - Roboto/Roboto Condensed fonts base64-embedded in SVG - FastAPI + HTMX web frontend with live preview - Conversational refinement: "make lines thicker", "change title", etc. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
63 lines
1.7 KiB
Python
63 lines
1.7 KiB
Python
"""Canvas sizing and panel layout computation."""
|
|
|
|
from __future__ import annotations
|
|
from dataclasses import dataclass
|
|
from app.models.style import LAYOUT
|
|
|
|
|
|
@dataclass
|
|
class PanelBounds:
|
|
"""Pixel boundaries for a chart panel's plot area."""
|
|
left: float
|
|
right: float
|
|
top: float
|
|
bottom: float
|
|
|
|
@property
|
|
def width(self) -> float:
|
|
return self.right - self.left
|
|
|
|
@property
|
|
def height(self) -> float:
|
|
return self.bottom - self.top
|
|
|
|
|
|
def compute_layout(layout_type: str) -> tuple[int, int, list[PanelBounds]]:
|
|
"""Compute canvas dimensions and panel bounds.
|
|
|
|
Returns: (canvas_width, canvas_height, list_of_panel_bounds)
|
|
"""
|
|
margins = LAYOUT["margins"]
|
|
|
|
if layout_type == "dual_panel":
|
|
dims = LAYOUT["dual_panel"]
|
|
w, h = dims["width"], dims["height"]
|
|
gap = LAYOUT["panel_gap"]
|
|
|
|
usable_width = w - margins["left"] - margins["right"] - gap
|
|
panel_width = usable_width / 2
|
|
|
|
left_panel = PanelBounds(
|
|
left=margins["left"],
|
|
right=margins["left"] + panel_width,
|
|
top=margins["top"],
|
|
bottom=h - margins["bottom"],
|
|
)
|
|
right_panel = PanelBounds(
|
|
left=margins["left"] + panel_width + gap,
|
|
right=w - margins["right"],
|
|
top=margins["top"],
|
|
bottom=h - margins["bottom"],
|
|
)
|
|
return w, h, [left_panel, right_panel]
|
|
|
|
else: # single
|
|
dims = LAYOUT["single"]
|
|
w, h = dims["width"], dims["height"]
|
|
panel = PanelBounds(
|
|
left=margins["left"],
|
|
right=w - margins["right"],
|
|
top=margins["top"],
|
|
bottom=h - margins["bottom"],
|
|
)
|
|
return w, h, [panel]
|