pub struct ScreenLayout { /* private fields */ }Expand description
Declarative frame description. Push surfaces in back-to-front
z-order, then call Self::draw to render and get a hit map.
Implementations§
Source§impl ScreenLayout
impl ScreenLayout
pub fn new() -> Self
pub fn push(&mut self, surface: Surface)
Sourcepub fn surfaces_mut(&mut self) -> &mut [Surface]
pub fn surfaces_mut(&mut self) -> &mut [Surface]
The pushed surfaces, mutably — for a caller that keeps a layout
across frames and edits a surface in place instead of rebuilding
the whole screen. Surfaces can be replaced, not added or
removed, so each surface’s index (and therefore the idx its
FrameZone carries) is stable.
Sourcepub fn tree_frame(&mut self) -> Vec<(Handle<TreeView>, Rect)>
pub fn tree_frame(&mut self) -> Vec<(Handle<TreeView>, Rect)>
Geometry for every pushed Surface::Tree as (Handle, Rect)
pairs instead of cloning each tree’s rows into the returned
Vec.
Each tree is kept in an internal DescriptorStore keyed by its
WidgetId. A tree whose id was already seen — e.g. the same
logical tree replaced in place via Self::surfaces_mut on a
retained ScreenLayout — reuses its existing Handle and
store slot rather than being removed and re-inserted. An id that
stops being pushed (the surface was replaced with a different
id, or dropped) has its handle and store slot evicted by this
same call, so a retained layout’s store stays bounded by the
number of tree ids pushed this frame, not by how many have
ever been pushed.
This only pays off for a ScreenLayout an app keeps across
frames and mutates via Self::surfaces_mut; a fresh
ScreenLayout::new() built every frame (every in-repo example
and the templates/app scaffold do this today) still inserts —
and clones — every tree from an empty store each call. And even
on a retained layout, this still compares the whole tree
(PartialEq over every row) to decide whether to skip the
clone, so a changed tree costs a full compare-then-clone rather
than the zero-diff in-place DescriptorStore::update the
store is designed around — a caller that wants that property
has to mutate through the returned Handle itself instead of
calling this on a freshly diffed Surface::Tree.
Pushing two Surface::Tree entries with the same
WidgetId is not rejected, but only the last one survives in
the store: both resolve to the same Handle, so the earlier
tree’s content is overwritten by the later one before either is
returned.
This leaves Self::draw, Self::hit_map and
Self::tab_stops untouched; they still paint and hit-test
directly off Self::surfaces. No in-crate caller consumes
this yet — draw/hit_map/tab_stops/OwnedFrame still
read Self::surfaces directly — so treat this as an early,
additive building block rather than a finished migration.
Sourcepub fn draw(&self, backend: &mut dyn Backend) -> FrameHitMap
pub fn draw(&self, backend: &mut dyn Backend) -> FrameHitMap
Render all surfaces via backend in z-order and return a
FrameHitMap for unified click dispatch. Each surface’s
bounding rect is registered as a hit zone; apps then use
per-surface hit_test() methods for fine-grained resolution.
If you’re accumulating surfaces that are painted elsewhere
(e.g. at their natural call sites across an existing paint
pass) purely to recover a hit map, use Self::hit_map
instead — it skips every backend.draw_*() call.
Sourcepub fn hit_map(&self) -> FrameHitMap
pub fn hit_map(&self) -> FrameHitMap
Return the FrameHitMap that Self::draw would produce,
without invoking any backend.draw_*() call. For apps that
already painted these same surfaces elsewhere in the frame and
only need the hit-test result — pushing surfaces here re-invokes
no rendering, so it’s safe to build this after (or interleaved
with) the app’s real paint sequencing.
Sourcepub fn tab_stops(&self) -> Vec<(WidgetId, Rect)>
pub fn tab_stops(&self) -> Vec<(WidgetId, Rect)>
Tab order for this frame, as (WidgetId, Rect) pairs in reading
order (top-to-bottom, then left-to-right by rect origin) — the
shared source of truth crate::focus::FocusManager::sync_tab_order
cycles through. An app that builds its screen via
ScreenLayout hands this straight to
crate::runner::AppLogic::tab_stops; see that method’s doc for
the opt-in contract.
Only surfaces that carry both a plain rect and an owning
WidgetId participate. Excluded, deliberately:
- Transient overlays (
Tooltip,ContextMenu,Dialog,Float,Completions,RichTextPopup,FindReplace,Toast,DropOverlay) — these already own their own internal focus/dismiss handling while open, and being modal, nothing behind them should be Tab-reachable anyway.Floatin particular already has its own, finer-grained focus story —crate::ModalStack::top_focusable— rather than participating inTab/Shift+Tabcycling. - Structural chrome (
Split,Scrollbar,SplitTree) — containers/controls with no independent focusable identity of their own. Image,SpinnerandCanvas— purely decorative, never focusable, regardless of the “carries arectplus an owningWidgetId” rule: a consumer that adopts them would otherwise get dead stops in its Tab order.Canvas’s own hit-test (crate::primitives::canvas::CanvasHit) only ever answers “inside”/“outside” of its bounds — it has no activation affordance to reach by keyboard.ProgressunlessProgressBar::cancellableis set — a bare progress readout has nothing to activate, but a cancellable one has a real affordance ([ProgressBarHit::Cancel]) worth reaching by keyboard.Minimapstays included even though it is also mostly visual, because it is click-to-scroll and so has a real interaction to land on.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for ScreenLayout
impl RefUnwindSafe for ScreenLayout
impl Send for ScreenLayout
impl Sync for ScreenLayout
impl Unpin for ScreenLayout
impl UnsafeUnpin for ScreenLayout
impl UnwindSafe for ScreenLayout
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more