Container
NAME
Selkie::Container - Role for widgets that hold child widgets
SYNOPSIS
A minimal custom container that stacks its children vertically with a one-row gap between them:
use Selkie::Widget;
use Selkie::Container;
use Selkie::Sizing;
unit class My::GapBox does Selkie::Container;
method render() {
my $y = 0;
for self.children -> $child {
if $child.plane {
$child.reposition($y, 0);
$child.resize($child.sizing.value, self.cols);
} else {
$child.init-plane(
self.plane,
y => $y, x => 0,
rows => $child.sizing.value,
cols => self.cols,
);
}
$child.render;
$y += $child.sizing.value + 1; # leave a 1-row gap
}
self.clear-dirty;
}
DESCRIPTION
Selkie::Container layers on top of Selkie::Widget (also does
Selkie::Widget). Compose it for any widget that owns child widgets ā
layouts (VBox, HBox, Split), decorators (Border, Modal),
scrollers (ScrollView).
The role provides:
A
childrenlist, manipulated viaadd,remove,clearAutomatic store propagation to added children
Recursive destruction and subscription cleanup on
remove/clearA
focusable-descendantswalker soSelkie::Appcan build the Tab cycleA
!render-childrenhelper that cascades dirty flags for correct subtree redraws
Your container's job is to implement render, which positions and
sizes each child before rendering it. For typical layouts, lean on
VBox/HBox/Split instead of building your own container from
scratch.
EXAMPLES
Adding and removing children
my $vbox = Selkie::Layout::VBox.new(sizing => Sizing.flex);
my $header = Selkie::Widget::Text.new(text => 'Hi', sizing => Sizing.fixed(1));
$vbox.add($header);
# Later ā remove cleans up the widget's plane, subscriptions, and children
$vbox.remove($header);
Rebuilding from scratch
$vbox.clear; # destroys all children
$vbox.add($new-a);
$vbox.add($new-b);
Writing your own container
If the built-in layouts don't fit, compose Selkie::Container directly
and implement render. Use !render-children (inherited) to cascade
dirty flags and render each child ā this ensures subtree correctness
when the container is dirty:
method render() {
self!layout-children; # your own positioning logic
self!render-children; # handles dirty cascade + per-child render
self.clear-dirty;
}
SEE ALSO
Selkie::Widget ā the base role
Containerbuilds onSelkie::Layout::VBox, Selkie::Layout::HBox, Selkie::Layout::Split ā the built-in containers
Selkie::Widget::Border, Selkie::Widget::Modal ā decorators that also compose
Container