Skip to main content

ScreenLayout

Struct ScreenLayout 

Source
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

Source

pub fn new() -> Self

Source

pub fn push(&mut self, surface: Surface)

Source

pub fn surfaces(&self) -> &[Surface]

The pushed surfaces, in z-order.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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. Float in particular already has its own, finer-grained focus story — crate::ModalStack::top_focusable — rather than participating in Tab/Shift+Tab cycling.
  • Structural chrome (Split, Scrollbar, SplitTree) — containers/controls with no independent focusable identity of their own.
  • Image, Spinner and Canvas — purely decorative, never focusable, regardless of the “carries a rect plus an owning WidgetId” 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.
  • Progress unless ProgressBar::cancellable is set — a bare progress readout has nothing to activate, but a cancellable one has a real affordance ([ProgressBarHit::Cancel]) worth reaching by keyboard. Minimap stays 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§

Source§

impl Default for ScreenLayout

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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>

Convert 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)

Convert &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)

Convert &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
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> NoneValue for T
where T: Default,

Source§

type NoneType = T

Source§

fn null_value() -> T

The none-equivalent value.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more