Skip to main content

SizePolicy

Enum SizePolicy 

Source
#[non_exhaustive]
pub enum SizePolicy { Fixed, HeightForWidth, Intrinsic, }
Expand description

How an entry’s local_bounds is decided each layout pass.

The default, Fixed, is what every scene had before this existed: the model owns both axes and nothing measures anything. The other two hand one or both axes to the widget, which is the only thing that can answer “how tall is this text at this width”.

§Heavyweight only, and why

A lightweight SceneItem has no layout_response to ask — it publishes its own AABB, and Scene::add_item_dynamic already re-reads that each build. A widget’s height is not a value it publishes; it is the answer to a question asked at a width. So the two mechanisms are not variants of each other, and this one is refused for a lightweight entry rather than silently doing nothing: Scene::set_size_policy returns false.

§What is measured, and what is not

A view measures exactly the cards it gives a non-zero size — the ones inside its viewport. Not the ones it keeps alive in the retention band, and not the one the user is interacting with if the camera has left it behind: those are laid out at Size::ZERO, so there is nothing a measurement could be for. A card the camera has never shown keeps the size add_widget_item was handed, and is corrected on the first pass that places it, in the same frame it appears. That is the contract ListView::auto_item_height already makes for rows: the number in the model is an estimate until the thing has been on screen, and every whole-scene query that reads it — scene_rect_extent, the spatial index, a marquee, a minimap — reads the estimate for a card that has never been realised. Give a plausible one; the alternative is measuring every card in the scene on every pass, which is the cost the viewport cull exists to avoid.

§The measurement must be idempotent

A measured height feeds back into the model, and the model feeds the next pass. A body whose layout_response answers differently for the same width — because it mutates state, or because its natural height depends on the height it was given — would oscillate forever. The view bounds that, and it is careful about what an oscillation is: 100 → 120 → 100 is one when the body is answering its own last answer, and is a user typing a character that wraps and then deleting it when it is not. The two are indistinguishable from the numbers, and freezing the second is the most ordinary editing action there is.

What separates them is who drove the pass. A body’s answer is a function of its content and of the width it is offered; at a fixed width its content cannot change without something dirtying the card — a Signal bound at Relayout, a rebuild, a fresh node — whereas the view’s own write dirties only the view and what is above it. So on the pass a write causes, the card reads clean, and a clean card that answers differently is reading back what was written to it. The view takes the taller of the two answers, and after a couple of such contradictions stops taking new ones for the rest of the chain — which writes nothing, and a pass that writes nothing schedules no successor. A non-idempotent body therefore costs a bounded number of passes per external event rather than an unbounded number for ever, and an edited one is never bounded at all. See [teksilo_core::widget::Widget::cacheable_layout] for the framework’s own statement of the same obligation.

§A resize does not reach an axis the content owns

HeightForWidth keeps its width, so the selection frame resizes it horizontally and the words decide the rest; the vertical half of a corner drag is neutralised in Scene::apply_transform_delta, because a height written there is one the next pass measures straight back over. Intrinsic owns neither axis, so Scene::transformable_roots offers it no resize handles at all. And a measurement taken while a gesture is previewing a transform is placed but never written: the preview is recomputed from the gesture’s frozen start frame each sample, so a previewed width that reached the model would be scaled again on the next one.

#[non_exhaustive]: this crate has out-of-tree consumers.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Fixed

The model owns both axes. Today’s behaviour, and the default, so every existing scene is bit-identical.

§

HeightForWidth

The model owns the width; the height is measured from the widget at that width on every pass that lays it out.

The right policy for text: a note’s width is authored (you drag its edge) and its height follows the words. scene_rect(id).height becomes advisory for such an entry — it reports the last measured height, not the one add_widget_item was handed.

§

Intrinsic

Both axes are measured: the entry shrink-wraps its widget.

For content that knows its own size on both axes — a pinned label, a badge, a fixed-aspect thumbnail. The rect passed to add_widget_item supplies only the position.

Trait Implementations§

Source§

impl Clone for SizePolicy

Source§

fn clone(&self) -> SizePolicy

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for SizePolicy

Source§

impl Debug for SizePolicy

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for SizePolicy

Source§

fn default() -> SizePolicy

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

impl Eq for SizePolicy

Source§

impl PartialEq for SizePolicy

Source§

fn eq(&self, other: &SizePolicy) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for SizePolicy

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
§

impl<T> AnyEq for T
where T: Any + PartialEq,

§

fn equals(&self, other: &(dyn Any + 'static)) -> bool

§

fn as_any(&self) -> &(dyn Any + 'static)

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
§

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,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

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

§

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

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

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

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

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

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

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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
§

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

§

type NoneType = T

§

fn null_value() -> T

The none-equivalent value.
§

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

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

§

impl<T> WasmNotSend for T
where T: Send,

§

impl<T> WasmNotSendSync for T
where T: WasmNotSend + WasmNotSync,

§

impl<T> WasmNotSync for T
where T: Sync,

§

impl<T> WithSubscriber for T

§

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
§

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

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