Selkie--Tree
NAME
Selkie::Tree - Tree-walking helpers used by widgets that need to reach beyond their own subtree
SYNOPSIS
use Selkie::Tree;
# Mark every widget whose plane intersects this absolute screen rect
# as dirty ā used by Image.destroy-blit-plane to repaint cells under
# the removed sprixel.
mark-widgets-in-rect-dirty(
abs-y => 5, abs-x => 10,
rows => 4, cols => 16,
);
# The active modal (or Nil), used by widgets that need to skip
# rendering when occluded.
my $modal = current-active-modal;DESCRIPTION
A small set of free subs that bridge between a widget and the wider tree it lives in, without requiring the widget to walk up to the Selkie::App instance manually. Selkie::App at init populates two class-level provider closures ā one returning the live list of tree roots (active screen + modal stack + toast), the other returning the active modal ā and the helpers here read through them.
This pattern keeps widgets like Selkie::Widget::Image from needing a circular import on Selkie::App while still letting them participate in app-level coordination (cell cleanup after sprixel destroy, modal occlusion checks, etc.).
sub set-tree-roots-provider
sub set-tree-roots-provider(
&p
) returns NilSet the tree-roots provider ā a closure returning an iterable of widget roots. Selkie::App calls this during init so tree-walking helpers can find the live trees without each helper needing a direct reference to the app.
sub current-tree-roots
sub current-tree-roots() returns ListThe current list of widget tree roots. Used internally by helpers in this module; apps don't typically call this directly.
sub set-modal-provider
sub set-modal-provider(
&p
) returns NilSet the active-modal provider ā a closure returning the topmost open modal widget or Nil. Selkie::App calls this on init.
sub current-active-modal
sub current-active-modal() returns MuThe topmost open modal widget, or Nil if no modal is open.
sub widget-occluded-by-active-modal
sub widget-occluded-by-active-modal(
Mu $widget
) returns BoolTrue when $widget is outside the active modal tree and therefore should suppress out-of-band painting such as sprixels. Widgets inside the active modal, including descendants of its content tree, are not occluded.
sub mark-widgets-in-rect-dirty
sub mark-widgets-in-rect-dirty(
Int :$abs-y!,
Int :$abs-x!,
Int :$rows! where { ... },
Int :$cols! where { ... }
) returns NilWalk every tree root and mark dirty any widget whose absolute screen bounds intersect the given rectangle. Used by sprixel-bearing widgets after they destroy a blit-plane: the cells under the removed sprixel may belong to a widget that has nothing else changing this frame, so without an explicit dirty mark the widget won't repaint and the cells will continue to show whatever was cached pre-sprixel-removal. Cheap walk; called once per blit teardown.