Skip to content
Feeding a clanker? Grab this page as raw .md

GridDraw API#

Bases: AnyWidget

Drawable square grid widget for dots and orthogonal line segments.

rows and cols count cells. Intersections are addressed as [row, col] coordinates from [0, 0] through [rows, cols].

Examples:

import marimo as mo
from wigglystuff import GridDraw

grid = mo.ui.anywidget(GridDraw(rows=8, cols=8, line_width=[1, 2, 4]))
grid

Create a GridDraw widget.

Parameters:

Name Type Description Default
rows int

Number of grid cells vertically.

8
cols int

Number of grid cells horizontally.

8
line_width int | Sequence[int]

Positive int for fixed width, or non-empty list of positive ints to show a width picker. The first list item is the default width.

2
dot_radius int

Drawn dot radius in pixels.

6
theme str | None

None follows the notebook; "light" or "dark" force the widget theme.

None
width int

Widget pixel width.

440
height int

Widget pixel height.

440
dots Iterable[Sequence[int]] | None

Optional initial dot coordinates.

None
lines Iterable[dict[str, Any]] | None

Optional initial line dictionaries.

None
**kwargs Any

Forwarded to anywidget.AnyWidget.

{}
Source code in wigglystuff/grid_draw.py
def __init__(
    self,
    rows: int = 8,
    cols: int = 8,
    line_width: int | Sequence[int] = 2,
    dot_radius: int = 6,
    theme: str | None = None,
    width: int = 440,
    height: int = 440,
    dots: Iterable[Sequence[int]] | None = None,
    lines: Iterable[dict[str, Any]] | None = None,
    **kwargs: Any,
) -> None:
    """Create a GridDraw widget.

    Args:
        rows: Number of grid cells vertically.
        cols: Number of grid cells horizontally.
        line_width: Positive int for fixed width, or non-empty list of
            positive ints to show a width picker. The first list item is
            the default width.
        dot_radius: Drawn dot radius in pixels.
        theme: ``None`` follows the notebook; ``"light"`` or ``"dark"``
            force the widget theme.
        width: Widget pixel width.
        height: Widget pixel height.
        dots: Optional initial dot coordinates.
        lines: Optional initial line dictionaries.
        **kwargs: Forwarded to ``anywidget.AnyWidget``.
    """
    rows = _ensure_positive_int("rows", rows)
    cols = _ensure_positive_int("cols", cols)
    line_width = _normalize_line_width(line_width)
    dot_radius = _ensure_positive_int("dot_radius", dot_radius)
    width = _ensure_positive_int("width", width)
    height = _ensure_positive_int("height", height)
    self._validate_theme_value(theme)

    super().__init__(
        rows=rows,
        cols=cols,
        line_width=line_width,
        dot_radius=dot_radius,
        theme=theme,
        width=width,
        height=height,
        dots=[],
        lines=[],
        **kwargs,
    )
    for dot in dots or []:
        row, col = _normalize_point(dot)
        self.add_dot(row, col)
    for line in lines or []:
        self.add_line(line["from"], line["to"], width=line.get("width"))

add_dot #

add_dot(row: int, col: int) -> None

Add a dot at an intersection.

Adding an existing dot is a no-op.

Source code in wigglystuff/grid_draw.py
def add_dot(self, row: int, col: int) -> None:
    """Add a dot at an intersection.

    Adding an existing dot is a no-op.
    """
    point = list(self._validate_intersection((row, col)))
    if point not in self.dots:
        self.dots = [*self.dots, point]

add_line #

add_line(a: Sequence[int], b: Sequence[int], width: int | None = None) -> None

Add a unit line segment between orthogonally adjacent intersections.

Source code in wigglystuff/grid_draw.py
def add_line(
    self,
    a: Sequence[int],
    b: Sequence[int],
    width: int | None = None,
) -> None:
    """Add a unit line segment between orthogonally adjacent intersections."""
    point_a, point_b = self._validate_segment(a, b)
    if width is None:
        width = self._default_line_width()
    width = _ensure_positive_int("width", width)
    start = list(point_a)
    end = list(point_b)
    if any(line.get("from") == start and line.get("to") == end for line in self.lines):
        return
    self.lines = [*self.lines, {"from": start, "to": end, "width": width}]

clear #

clear() -> None

Remove all dots and lines.

Source code in wigglystuff/grid_draw.py
def clear(self) -> None:
    """Remove all dots and lines."""
    self.dots = []
    self.lines = []

Synced traitlets#

Traitlet Type Notes
dots list Drawn intersections as [[row, col], ...].
lines list Drawn unit segments as {"from": [r, c], "to": [r, c], "width": int} dictionaries.
rows int Number of grid cells vertically; row intersections are 0..rows.
cols int Number of grid cells horizontally; column intersections are 0..cols.
line_width int \| list[int] Fixed line width, or picker options when a list is supplied.
dot_radius int Drawn dot radius in pixels.
theme str \| None None follows the notebook; "light" or "dark" forces the widget theme.
width int Widget width in pixels.
height int Widget height in pixels.