Skip to content

visualdynamics.gui.drawer_tab

drawer_tab

The handle a collapsible drawer wears on its edge.

Drawn to the design Brandon had made in Claude Design (2026-09-03, icons/drawer-tab-shape.svg is the reference): a flat tab with rounded shoulders and feet that flare out into the edge it sits on, the word in the middle and a chevron either side of it pointing where a click will move the edge. The reference is one fixed width, so the shape is drawn here from its radii at whatever width the label needs, and the colours come from the palette so light and dark both work.

Painted by hand rather than styled: a stylesheet gives a box, and the flared feet are what make it read as a handle on an edge rather than a button floating near one.

Classes:

Name Description
DrawerTab

A checkable handle for a drawer on the bottom edge: checked is

Classes

DrawerTab

DrawerTab(text: str, parent: QWidget | None = None)

Bases: QAbstractButton

A checkable handle for a drawer on the bottom edge: checked is open. The edge is fixed for now; a drawer on another edge would turn the shape and the text, and the glyph already knows how.

Methods:

Name Description
outline

The tab's edge at its current size, open along the base so

Source code in src/visualdynamics/gui/drawer_tab.py
def __init__(self, text: str, parent: QWidget | None = None) -> None:
    super().__init__(parent)
    self.setCheckable(True)
    self.setText(text)
    self.setAttribute(Qt.WidgetAttribute.WA_Hover)
    # The tab floats over the 3-D view, and the VTK widget takes a
    # native window (`winId()`), which makes every sibling up the
    # tree native too — this one included, and it has to be, or it
    # could never draw over the view. A native child has a surface
    # of its own, and it needs an alpha channel or everything
    # outside the flared outline shows as a grey box on the black
    # scene (Brandon, 2026-09-04). Declared translucent here, before
    # the surface exists, so it is made with one. Not enough on its
    # own — see `paintEvent` for the rest of that story.
    self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
Methods:
outline
outline() -> QPainterPath

The tab's edge at its current size, open along the base so no line is drawn across the edge it sits on.

Source code in src/visualdynamics/gui/drawer_tab.py
def outline(self) -> QPainterPath:
    """The tab's edge at its current size, open along the base so
    no line is drawn across the edge it sits on."""
    w, h = self.width(), self.height()
    top, base = self.TOP, h - 0.5
    foot, shoulder = self.FOOT, self.SHOULDER
    path = QPainterPath(QPointF(0, base))
    # a concave foot: a quarter circle centred on the edge, from
    # straight below its centre round to its right
    path.arcTo(QRectF(-foot, base - 2 * foot, 2 * foot, 2 * foot),
               270, 90)
    path.lineTo(foot, top + shoulder)
    path.arcTo(QRectF(foot, top, 2 * shoulder, 2 * shoulder), 180, -90)
    path.lineTo(w - foot - shoulder, top)
    path.arcTo(QRectF(w - foot - 2 * shoulder, top,
                      2 * shoulder, 2 * shoulder), 90, -90)
    path.lineTo(w - foot, base - foot)
    path.arcTo(QRectF(w - foot, base - 2 * foot, 2 * foot, 2 * foot),
               180, 90)
    return path

Functions: