Skip to main content

Cx

Struct Cx 

Source
pub struct Cx<'s, 'u> {
    pub store: &'s Store,
    /* private fields */
}
Expand description

The context passed to components and hooks.

's is the lifetime of the Store and of every hook handle taken from it; it is independent of the &mut Cx borrow, so a hook can return a guard that outlives the borrow of the Cx it was taken from.

Fields§

§store: &'s Store

The hook store. Copy, so it can be re-borrowed into nested closures.

Implementations§

Source§

impl<'s, 'u> Cx<'s, 'u>

Source

pub fn new(store: &'s Store, ui: &'u mut Ui, scope: Id) -> Self

Build a Cx for ui under the scope id scope.

This is what an egui container closure (ui.vertical(|ui| ..)) uses to re-enter the tree with the inner Ui. The layout id starts at scope; an element that re-enters inside a reused list slot puts the slot’s layout id back with Cx::with_layout_id.

Source

pub fn ui(&mut self) -> &mut Ui

The egui Ui currently being drawn into.

In taffy mode this is the tree’s own Ui, so anything drawn through it is not laid out by taffy. Elements use Cx::leaf and Cx::container instead; this is the escape hatch for user code that wants to call egui directly, and it is what a docked <Panel> carves its space out of.

“The tree’s own Ui” is exact: a container is a rect, not a Ui, so however many <View>s sit between the tree root and the caller, this is the Ui the tree was started in. That is what makes four sibling <Panel>s dock along the window’s four edges instead of each carving up its own little node.

Source

pub fn in_taffy(&self) -> bool

Whether this Cx is inside a <View>.

True on both layout paths: what an element reads it for is whether its size is the layout’s decision, and that is the same either way.

Source

pub fn is_hidden(&self) -> bool

Is this Cx inside a display="none" subtree?

True inside a hidden <View> on either layout path, and inside anything a leaf of one opens (a <ScrollArea>’s children, a tree of their own).

Source

pub fn scope_id(&self) -> Id

The id of the current component scope; the base of every hook id.

Source

pub fn layout_id(&self) -> Id

The id the next taffy tree or node is keyed by.

The same as Cx::scope_id unless a list element replaced it (see Cx::with_layout_id). <View> passes this to Cx::container.

Source

pub fn with_layout_id<R>( &mut self, id: Id, f: impl FnOnce(&mut Cx<'s, '_>) -> R, ) -> R

Run f with id as the layout id, leaving hooks and the egui id stack alone.

This is an internal for list elements, not something a component body needs. <VirtualList> uses it to key each row’s taffy tree by the slot the row occupies rather than by the row’s index: a slot is drawn on every frame, so its nodes are reused instead of created, measured in an invisible pass and thrown away when the row scrolls out.

The ids handed to this must be unique among the nodes drawn in one frame; two of them under one taffy tree would collide.

Source

pub fn with_root_size<R>( &mut self, size: Vec2, f: impl FnOnce(&mut Cx<'s, '_>) -> R, ) -> R

Run f with the size the trees it opens are laid out into.

This is an internal for list elements, like Cx::with_layout_id, not something a component body needs.

A <View> over a plain Ui normally takes the width that is left, measures its own height and reserves that much room. Neither is what a <VirtualList> row wants. Inside egui::ScrollArea::show_rows the space that is left runs from the row to the bottom of the band of visible rows, so the root rect moves with the scroll offset; and the room reserved is whatever the row drew, which is not the row_h the visible range was worked out from, so the rows drift out of step with it.

With a size given, the tree’s root rect is that size at the cursor, both axes are definite, and exactly that much room is reserved afterwards. So the rows sit at one pitch, and the root size is the same on every frame: a scrolled frame lays a row out again only when something in the row really changed.

The size wins over what the tree measured. A tree that draws taller than this overlaps whatever comes after it; <VirtualList> says the same thing about its rows, and it is the same rule.

The hint is not consumed by the first tree: every tree f opens over a plain Ui gets it, at any depth of components, until a tree is entered — inside a tree the hint is dropped, so a tree opened by a leaf of this one is unaffected. Consuming it would mean shared mutable state, because a Cx is copied into each child scope rather than borrowed, and it would buy nothing: the caller’s contract is that everything drawn here is one row of a fixed height, so a second root tree in the same row is already a mistake either way.

Source

pub fn ctx(&self) -> &Context

The egui context.

Source

pub fn scope<R>( &mut self, source: impl Hash + Debug, f: impl FnOnce(&mut Cx<'s, '_>) -> R, ) -> R

Enter a component scope: deepen the hook scope, the layout id and the egui id.

source needs Debug as well as Hash because egui 0.36’s Ui::push_id takes impl AsIdSalt, which is Hash + Debug.

Source

pub fn hook_scope<R>( &mut self, location: &'static Location<'static>, f: impl FnOnce(&mut Cx<'s, '_>) -> R, ) -> R

Enter a custom hook scope: deepen the hook scope only.

Unlike Cx::scope this does not touch the egui id stack, because a custom hook is not a widget boundary.

Source

pub fn scope_sharing_ui<R>( &mut self, source: impl Hash + Debug, f: impl FnOnce(&mut Cx<'s, '_>) -> R, ) -> R

Enter a component scope that draws into this Ui.

Same hook scoping as Cx::scope, but without Ui::push_id, so the component shares the surface with its parent. #[component(shares_ui)] elements go through here: a docked panel has to carve space out of the parent’s Ui, and Ui::end_row only reaches the grid it was called on.

Source

pub fn leaf<R>(&mut self, style: &ItemStyle, f: impl FnOnce(&mut Ui) -> R) -> R

Draw one egui widget, as a taffy leaf when inside a container.

Outside a container style is ignored: a plain Ui has nothing to apply flex item properties to, and nothing to paint a background on either — the engine paints a node’s box from the rect the layout gave it, and here the rect is only known after the widget has drawn. That is what <Frame> is for.

Source

pub fn text( &mut self, style: &ItemStyle, text: WidgetText, wrap: bool, selectable: Option<bool>, ) -> Response

Draw static text, as a taffy node when inside a container.

Outside a container this is ui.add(egui::Label::new(text)) and nothing else. Inside one it skips the Label and the Ui it would need: the galley is laid out by the layout engine, which is where its size is wanted anyway, and painted straight onto the tree’s own Ui. What the engine keeps of Label is the widget rect, the WidgetInfo and the text selection, so the text is still hoverable, still in the accessibility tree, still found by egui_kittest’s label queries and still selectable with the mouse.

wrap picks between TextWrapMode::Wrap and TextWrapMode::Extend, as <Text>’s own prop does. selectable is Label::selectable: None follows the style’s interaction.selectable_labels. A <Text> created this frame is not selectable for that one frame, because its place on screen is only known once the layout is computed.

Source

pub fn leaf_fill<R>( &mut self, style: &ItemStyle, f: impl FnOnce(&mut Ui) -> R, ) -> R

Like Cx::leaf, but the leaf takes whatever space taffy gives it.

A plain leaf is measured by its content: taffy sizes it to what it drew and never larger. That is wrong for egui widgets that themselves fill the space they are given (ScrollArea): the widget fills its node, then reports that as its content size, and the node is pinned at whatever size the first frame happened to have. This variant reports no content size at all, so the node is sized purely by taffy: w / h, grow, or the remaining space in the container.

Source

pub fn container<R>( &mut self, id: Id, container: &ContainerStyle, item: &ItemStyle, f: impl FnOnce(&mut Cx<'s, '_>) -> R, ) -> R

Open a container and draw f inside it.

Outside a container this starts a new layout tree in the current Ui; inside one it adds a child node. Either way f receives a Cx that is inside a container, so its direct children become layout nodes.

The two styles are passed as they are rather than merged into a [taffy::Style], because a <VirtualList> row is laid out by the lite path (crate::engine::lite), which reads them directly and never builds a taffy style at all. The taffy path merges them itself.

Source

pub fn root_container<R>( &mut self, id: Id, style: Style, f: impl FnOnce(&mut Cx<'s, '_>) -> R, ) -> R

Cx::container for the root of an app: reserve all available space.

The runner uses this so that the outermost <View> fills the window; nested containers only reserve the available width, so that a column of them stacks instead of each one claiming the whole height.

Takes a [taffy::Style], unlike Cx::container: an app root is never a <VirtualList> row, so it never takes the lite path, and the runner’s root_style() is a taffy style users can reach for. A taffy style says nothing about paint, so the root node paints nothing; a <View> inside it does.

Source

pub fn defer(&self, f: impl FnOnce() + 'static)

Queue f to run at the end of the pass, after every guard is gone.

The closure is 'static because it outlives the component body, so captured values need move. It cannot touch the store, so it does not request a repaint on its own; use State::update_later for that.

Auto Trait Implementations§

§

impl<'s, 'u> Freeze for Cx<'s, 'u>

§

impl<'s, 'u> !RefUnwindSafe for Cx<'s, 'u>

§

impl<'s, 'u> !Send for Cx<'s, 'u>

§

impl<'s, 'u> !Sync for Cx<'s, 'u>

§

impl<'s, 'u> Unpin for Cx<'s, 'u>

§

impl<'s, 'u> UnsafeUnpin for Cx<'s, 'u>

§

impl<'s, 'u> !UnwindSafe for Cx<'s, 'u>

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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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
§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

§

fn simd_from(_simd: S, value: T) -> T

§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

§

fn simd_into(self, simd: S) -> T

Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,