pub struct StyledContainer { /* private fields */ }Implementations§
Source§impl StyledContainer
impl StyledContainer
pub fn new( layout_style: LayoutStyle, style: impl Fn(Rect) -> RectStyle + 'static, children: Vec<Box<dyn LayoutItem>>, ) -> Result<Self, LayoutError>
Sourcepub fn from_slots(
layout_style: LayoutStyle,
style: impl Fn(Rect) -> RectStyle + 'static,
slots: Vec<ChildSlot>,
) -> Result<Self, LayoutError>
pub fn from_slots( layout_style: LayoutStyle, style: impl Fn(Rect) -> RectStyle + 'static, slots: Vec<ChildSlot>, ) -> Result<Self, LayoutError>
A styled box whose children are a mix of static widgets and reactive fragments (ChildSlots),
reconciled into this box’s own node so they inherit its flex direction/gap — the transparent
box-with-a-for path (see Container::from_slots).
pub fn with_opacity(self, opacity: impl Fn() -> f32 + 'static) -> Self
Sourcepub fn with_transform(
self,
transform: impl Fn(Rect) -> Option<[f32; 6]> + 'static,
) -> Self
pub fn with_transform( self, transform: impl Fn(Rect) -> Option<[f32; 6]> + 'static, ) -> Self
Apply an affine transform (rotate/scale/translate) to the whole box each view(). The closure
takes the laid-out rect and returns the 2×3 matrix, or None for identity.
Sourcepub fn hover_style(self, f: impl Fn(Rect) -> RectStyle + 'static) -> Self
pub fn hover_style(self, f: impl Fn(Rect) -> RectStyle + 'static) -> Self
Paint the box with f while the mouse hovers it (a declarative style swap, like Button).
Hover is mouse-only; touch never sets it, so a tap leaves no stuck hover state.
Sourcepub fn active_style(self, f: impl Fn(Rect) -> RectStyle + 'static) -> Self
pub fn active_style(self, f: impl Fn(Rect) -> RectStyle + 'static) -> Self
Paint the box with f while a primary pointer is held down inside it — the pressed / CSS :active
state, which takes precedence over hover_style. Unlike hover it tracks touch as well as mouse,
and it clears on release, on leaving the box, or once the press drags off, so it never sticks.
Sourcepub fn disabled(self, f: impl Fn() -> bool + 'static) -> Self
pub fn disabled(self, f: impl Fn() -> bool + 'static) -> Self
Marks the box unusable while f reads true: it stops taking the pointer, stops tracking hover and
the pressed state, stops showing its cursor, and paints its
disabled_style ahead of every other state.
Closed here rather than left to each widget because the web never asks anyone to write it: disabled
is platform semantics that a selector and the hit-tester read for free, and a catalogue that made every
component re-implement it would get a different subset right in each one. The failure it prevents is
small and immediate — a control the application has already disabled still lighting up under the
pointer and still showing a hand cursor, which says “press me” about something that will do nothing.
Sourcepub fn disabled_style(self, f: impl Fn(Rect) -> RectStyle + 'static) -> Self
pub fn disabled_style(self, f: impl Fn(Rect) -> RectStyle + 'static) -> Self
The paint for the disabled state, which wins over the pressed and hover ones.
Sourcepub fn control(self, role: Role) -> Self
pub fn control(self, role: Role) -> Self
The focus ring: drawn over whichever state won, while the box holds focus and should show it.
Composed rather than swapped, unlike the other three, and the difference is the point. Hover, pressed
and disabled are answers to “what is this box doing”, so one of them replaces the rest. A ring answers
a different question — where the keyboard is going — and a hovered box that lost its ring would hide
that answer at the exact moment the user reached for the mouse. Which is why CSS gives focus its own
property (outline) rather than another background.
Only the properties the ring names are applied; radius always comes from the box, since a ring sits
on a shape it does not get to reshape. Shown on focus::is_focus_visible, so a tap
takes focus without drawing one.
Declares this box a control, and is the way to build one.
One call because the three halves are one fact, and each alone is a control that does not work: a box that takes a tap but never a key, a ring on something Tab cannot reach, a thing announced to a screen reader that cannot say what it is. Splitting them across three optional builders is how nine catalogue components shipped answering the mouse and nothing else — every one of them compiled, and looked right.
It joins the tab order at this node, answers Enter and Space the way it answers a tap, draws the
theme’s focus ring while the keyboard is what reached it (see
focus::is_focus_visible), and reports role outwards. A caller
that wants a ring of its own still says so with focus_style; this only
supplies one when nothing else has.
Deliberately not implied by on_press: a scrim, a click-away backdrop and a drag
surface all take presses and none of them is a place the keyboard should stop.
Sourcepub fn toggled(self, state: impl Fn() -> bool + 'static) -> Self
pub fn toggled(self, state: impl Fn() -> bool + 'static) -> Self
Declares that this control carries a checked state, and how to read it.
Only meaningful after control, and only for the roles that have one. Without it a
reader announces “checkbox” and stops — and a default of “unticked” would be worse, since it would be
confidently wrong for half of them.
Sourcepub fn valued(self, read: impl Fn() -> NumericValue + 'static) -> Self
pub fn valued(self, read: impl Fn() -> NumericValue + 'static) -> Self
Declares the number this box carries, so a reader says where a slider stands and not only that it is
one. The counterpart of toggled for a control whose state is a value.
pub fn focus_style(self, f: impl Fn(Rect) -> RectStyle + 'static) -> Self
Sourcepub fn cursor(self, cursor: Cursor) -> Self
pub fn cursor(self, cursor: Cursor) -> Self
Shows cursor while the pointer is over this box, and restores the default when it leaves.
The shape is the app’s statement of what the next press will do — orbit, resize a panel, place a point — so it belongs to the widget that would handle that press, not to a mode the app tracks.
Sourcepub fn click_through(self, through: bool) -> Self
pub fn click_through(self, through: bool) -> Self
Declares that this box does not stand between the pointer and whatever it is drawn over — CSS’s
pointer-events: none, and the second consumer of the hook [Overlay] opened.
A box covers what is behind it: since the hit-test walks in paint order, the topmost child under the pointer takes the event whether or not it wants it. That is right for a panel and wrong for a label — a readout floating over a canvas, a badge over a photo, a drag ghost — which is drawn on top precisely so it can be read, and whose whole contract is that the thing underneath still works. A modeller’s transform readout sits across the top of the viewport it reports on; without this, moving the pointer under it stops the operation it is describing.
It is a property of this box only. Children still hit-test normally, so a click-through bar can
hold a real button — the same split CSS makes with pointer-events: auto on a child.
Sourcepub fn keeping(self, subscription: Effect) -> Self
pub fn keeping(self, subscription: Effect) -> Self
Give this widget ownership of an Effect, so it runs for exactly as long as the widget exists.
The reactive runtime scopes an effect to the surface it was registered on, which is the right span for a shell-wide subscription and far too coarse for one row of a list: the row goes, the effect stays, and it keeps firing at a node that is gone. Dropping the handle instead is the opposite failure — the effect deregisters, runs once, and stops, with nothing to say so. This is the third answer, and the one an effect that belongs to a widget wants.
Chainable, so several effects can be kept without nesting anything.
Sourcepub fn styled_by(self, style: impl Fn() -> LayoutStyle + 'static) -> Self
pub fn styled_by(self, style: impl Fn() -> LayoutStyle + 'static) -> Self
Keeps the box’s layout style in step with the reactive state it was built from — the theme’s metric
tokens, today. style runs now, and again whenever a signal it read changes; the node is restyled in
place, so a live theme switch re-spaces the box as well as re-colouring it.
Paint needs nothing like this: a rect or text style is a closure the renderer re-runs every frame, so a token read inside one is already live. A layout style is a value, handed to the layout tree once when the node is made — which is why the reactive read has to be arranged here rather than coming for free.
Give new the same builder, so the node starts at the style it will settle on:
StyledContainer::new(shell(), paint, kids)?.styled_by(shell).
Sourcepub fn on_press(self, f: impl Fn() + 'static) -> Self
pub fn on_press(self, f: impl Fn() + 'static) -> Self
Make the box itself pressable. The callback fires on a tap (release, not press) inside the box; a child widget that handles the press wins, and a scroll gesture started on the box does not fire it.
Sourcepub fn maybe_on_press(self, f: Option<impl Fn() + 'static>) -> Self
pub fn maybe_on_press(self, f: Option<impl Fn() + 'static>) -> Self
on_press for a handler the caller may not have supplied.
What a wrapper component needs to forward an optional callback. A box whose press handler is a no-op
still reports the tap Handled, so “no handler” would become “swallows the click” — a display-only chip
eating a press instead of letting it through. None leaves the box exactly as it was; the maybe_*
pairs below say the same for every other event whose absence the box can observe.
Sourcepub fn on_alt_press(self, f: impl Fn(PointerButton) + 'static) -> Self
pub fn on_alt_press(self, f: impl Fn(PointerButton) + 'static) -> Self
Fire f(button) on a tap with a non-primary button — Secondary (right) or Auxiliary (middle).
Same tap-on-release semantics as Self::on_press: a child that handles the press wins, and travel
past the tap slop cancels it.
Opt-in per box rather than folded into on_press, because a non-primary press otherwise falls through
to whatever is behind it — silently swallowing right-clicks on every pressable box would break that.
Sourcepub fn maybe_on_alt_press(
self,
f: Option<impl Fn(PointerButton) + 'static>,
) -> Self
pub fn maybe_on_alt_press( self, f: Option<impl Fn(PointerButton) + 'static>, ) -> Self
on_alt_press for a handler the caller may not have supplied.
Sourcepub fn on_long_press(self, f: impl Fn() + 'static) -> Self
pub fn on_long_press(self, f: impl Fn() + 'static) -> Self
Fires once a press inside the box is held past ~500ms without moving past the tap slop, instead of
on_press’s tap-on-release. There is no dedicated timer in the gesture pipeline, so the threshold is
only checked on the next pointer event after the press (a move or the release) — it fires slightly
late, never at exactly 500ms, and a release before that next check-in is a normal tap.
Sourcepub fn maybe_on_long_press(self, f: Option<impl Fn() + 'static>) -> Self
pub fn maybe_on_long_press(self, f: Option<impl Fn() + 'static>) -> Self
on_long_press for a handler the caller may not have supplied.
Sourcepub fn on_drag_end(self, f: impl Fn(f32, f32) + 'static) -> Self
pub fn on_drag_end(self, f: impl Fn(f32, f32) + 'static) -> Self
Make the box draggable. The callback fires with the pointer position (layout space) on a press
inside the box and on every move until release — even after the pointer leaves the box. Map the
coordinate to a value (slider) or an offset (reorder/resize).
Fires once when a drag started on this box ends, with the position it finished at (layout space, local
to the box, same as on_drag).
This is what makes a threshold gesture expressible: on_drag alone reports where the pointer is but
never that it let go, so a swipe-to-dismiss or a drag-to-open can be tracked and never decided. A drag
also ends when the pointer leaves the window or a child consumes the release; those carry no position,
so the last one the drag reached is reported instead — the gesture always ends exactly once.
Sourcepub fn maybe_on_drag_end(self, f: Option<impl Fn(f32, f32) + 'static>) -> Self
pub fn maybe_on_drag_end(self, f: Option<impl Fn(f32, f32) + 'static>) -> Self
on_drag_end for a handler the caller may not have supplied.
pub fn on_drag(self, f: impl Fn(f32, f32) + 'static) -> Self
Sourcepub fn maybe_on_drag(self, f: Option<impl Fn(f32, f32) + 'static>) -> Self
pub fn maybe_on_drag(self, f: Option<impl Fn(f32, f32) + 'static>) -> Self
on_drag for a handler the caller may not have supplied.
Let button start the drag too, on top of the primary one that always does.
A slider or a splitter wants exactly one button and gets it by default. A surface with more than one
thing to drag needs the others: a modeller orbits with the primary button and pans with the secondary,
which is what the OS and every 3D application call those gestures. The handler is the same one — read
crate::pointer_buttons inside it to tell which button is doing the dragging.
Sourcepub fn drag_threshold(self, px: f32) -> Self
pub fn drag_threshold(self, px: f32) -> Self
How far the pointer must travel before this box counts as being dragged.
Without it a press is a drag from its first instant, which is right for a slider — pressing the track is how you set the value — and wrong for anything where a click and a drag mean different things on the same button. A viewport is the case: a click picks what is under it, a drag orbits, and telling them apart is the difference between selecting something and nudging the camera by a pixel.
Set it and the two stop overlapping: a stroke that never travels this far fires only
on_press, one that does fires only the drag handlers, and neither fires both.
Sourcepub fn on_hover(self, f: impl Fn(bool) + 'static) -> Self
pub fn on_hover(self, f: impl Fn(bool) + 'static) -> Self
Fire f(true) when the mouse enters the box and f(false) when it leaves (mouse only). Independent
of hover_style: a box can observe hover without swapping its paint.
Registers the box as a pointer target, like on_scroll does for the same reason: a
surface that carves its input region from its content (a click-through overlay) never receives a move
event over a box it left out of that region, so a hover it did not register is a hover it can’t observe.
Sourcepub fn maybe_on_hover(self, f: Option<impl Fn(bool) + 'static>) -> Self
pub fn maybe_on_hover(self, f: Option<impl Fn(bool) + 'static>) -> Self
on_hover for a handler the caller may not have supplied.
Sourcepub fn on_pointer_move(self, f: impl Fn(f32, f32) + 'static) -> Self
pub fn on_pointer_move(self, f: impl Fn(f32, f32) + 'static) -> Self
Fire f(x, y) with the pointer position — local to the box, as on_drag reports it —
on every move over it.
The continuous half of on_hover, which reports only the crossings. It is what a
surface that answers to where the pointer is needs: highlighting the face under the cursor, previewing
a snap, stretching a dimension line. Fires for touch as well as mouse, since a drag on a touchscreen
asks the same question.
Sourcepub fn maybe_on_pointer_move(
self,
f: Option<impl Fn(f32, f32) + 'static>,
) -> Self
pub fn maybe_on_pointer_move( self, f: Option<impl Fn(f32, f32) + 'static>, ) -> Self
on_pointer_move for a handler the caller may not have supplied.
Sourcepub fn on_scroll(self, f: impl Fn(f32, f32) + 'static) -> Self
pub fn on_scroll(self, f: impl Fn(f32, f32) + 'static) -> Self
Fire f(dx, dy) with the wheel delta while the pointer is over the box — scroll-to-adjust on a control
(a volume or brightness chip, a stepper), or zoom on a viewport. Deltas are normalised to pixels,
matching ScrollArea: a line delta counts as 20px, so one wheel notch is roughly
±60.
Targeted by hit-testing the wheel’s own position, so it answers a wheel that arrives before the pointer has moved at all. A scrollable child (a scroll area inside the box) gets first refusal and keeps it.
Sourcepub fn maybe_on_scroll(self, f: Option<impl Fn(f32, f32) + 'static>) -> Self
pub fn maybe_on_scroll(self, f: Option<impl Fn(f32, f32) + 'static>) -> Self
on_scroll for a handler the caller may not have supplied.
Sourcepub fn on_key(self, f: impl Fn(&Key) + 'static) -> Self
pub fn on_key(self, f: impl Fn(&Key) + 'static) -> Self
Fire f(&key) on every key press. This is a GLOBAL handler (key events reach every widget; there is
no per-widget focus), so it suits app-level shortcuts, not focused text entry.
It stands aside while a text entry holds focus and the press is text it would take
(focus::text_entry_takes_key) — so a shortcut on 3 does not also fire when the user types 3
into a field, while ⌘S still reaches it. Read the modifiers with crate::modifiers: key events
carry them, but pointer events do not, so the state registry is the one answer that works everywhere.
Sourcepub fn maybe_on_key(self, f: Option<impl Fn(&Key) + 'static>) -> Self
pub fn maybe_on_key(self, f: Option<impl Fn(&Key) + 'static>) -> Self
on_key for a handler the caller may not have supplied.
Sourcepub fn on_focus(self, f: impl Fn(bool) + 'static) -> Self
pub fn on_focus(self, f: impl Fn(bool) + 'static) -> Self
Make the box focusable and fire f(true)/f(false) when it gains/loses keyboard focus. It joins
the tab order (Tab/Shift-Tab reach it) and takes focus on tap. Use it to drive a focus ring or to
build a custom focusable widget on top of a box.