Skip to main content

ListState

Struct ListState 

Source
pub struct ListState(/* private fields */);
Expand description

The state of a list. Store it on your view and pass a clone to list each frame.

The state records each row’s height, the scroll position and the follow mode. Call its methods when the rows change, such as Self::splice or Self::remeasure_items. Clones share the same state.

Implementations§

Source§

impl ListState

Source

pub fn new( item_count: usize, alignment: ListAlignment, overdraw: Pixels, ) -> Self

Creates the state for a list of item_count rows, to store on your view.

alignment sets where the list starts: ListAlignment::Top at the first row, or ListAlignment::Bottom at the last row, as a chat log does.

overdraw is extra space above and below the viewport. Rows in that space are rendered and measured, but not painted, so rows that scroll into view are already measured.

Rows start unmeasured. An unmeasured row counts as zero pixels tall until it is rendered, unless it has a height hint from Self::with_uniform_item_height.

§Examples
let state = ListState::new(3, ListAlignment::Top, px(100.));
assert_eq!(state.item_count(), 3);
Source

pub fn measure_all(self) -> Self

Measures every row on the next layout, instead of only the rows that are rendered.

The scrollbar then reflects the full content height from the first frame. The cost is one render and measure per row, which is slow for a large list. For rows of similar height, Self::with_uniform_item_height gives a close estimate without measuring. Measuring runs again after the width changes, and after Self::reset, Self::remeasure or Self::remeasure_items.

Source

pub fn with_uniform_item_height(self, height: Pixels) -> Self

Gives every unmeasured row a height estimate of height, so the scrollbar is the right size before the rows are rendered.

Each row’s real height replaces the estimate when the row is rendered. This costs less than Self::measure_all, and suits lists whose rows are close to one height, such as table rows.

§Examples
let state = ListState::new(1_000, ListAlignment::Top, px(0.)).with_uniform_item_height(px(50.));
assert_eq!(state.max_offset_for_scrollbar().y, px(50_000.));
Source

pub fn reset(&self, element_count: usize)

Replaces every row with element_count new, unmeasured rows, and returns the scroll position to the start.

The position goes to the first row for ListAlignment::Top and to the last row for ListAlignment::Bottom. Scroll events are dropped until the next paint. To keep the scroll position, use Self::splice.

§Examples
let state = ListState::new(3, ListAlignment::Top, px(0.));
state.reset(10);
assert_eq!(state.item_count(), 10);
assert_eq!(state.logical_scroll_top().item_ix, 0);
Source

pub fn reset_with_uniform_height(&self, element_count: usize, height: Pixels)

Like Self::reset, and gives every new row the height estimate height.

See Self::with_uniform_item_height.

Source

pub fn remeasure(&self)

Marks every row unmeasured, so each is measured again when next rendered.

Use this when all rows change height together, such as when the font size changes. The scroll position keeps the same fraction of the row at the top of the viewport. For one row whose content changed, use Self::remeasure_items.

Source

pub fn remeasure_items(&self, range: Range<usize>)

Marks the rows in range unmeasured, so they are measured again when next rendered.

Use this when a row’s content changed height but the row is still at the same index, such as streaming text. The scroll position is kept. If the row at the top of the viewport is in range, the same pixel offset into that row is kept. Unlike Self::splice, the row count doesn’t change.

Source

pub fn item_count(&self) -> usize

Returns the number of rows in this list.

§Examples
let state = ListState::new(3, ListAlignment::Top, px(0.));
assert_eq!(state.item_count(), 3);
Source

pub fn is_scrolled_to_end(&self) -> Option<bool>

Returns whether the list is scrolled to its end.

Returns None when the list isn’t scrollable, when it hasn’t been painted yet, or when a row has no height yet, because the end isn’t known until then. A row has a height once it is rendered, or once it has a height hint from Self::with_uniform_item_height.

§Examples
let state = ListState::new(3, ListAlignment::Top, px(0.));
assert_eq!(state.is_scrolled_to_end(), None);
Source

pub fn splice(&self, old_range: Range<usize>, count: usize)

Replaces the rows in old_range with count new, unmeasured rows.

Call this after you add, remove or move rows. Rows after old_range keep their measurements and shift by the change in count. New rows count as zero pixels tall until they are rendered. If the row at the top of the viewport is in old_range, the list scrolls to the start of the new rows. Use Self::splice_focusable to keep a focused row rendered.

splice(old_count..old_count, 1) appends one row, and splice(0..0, 1) inserts one at the top.

§Examples
let state = ListState::new(3, ListAlignment::Top, px(0.));
state.splice(1..2, 4); // replace the middle row with four new rows
assert_eq!(state.item_count(), 6);
Source

pub fn splice_focusable( &self, old_range: Range<usize>, focus_handles: impl IntoIterator<Item = Option<FocusHandle>>, )

Replaces the rows in old_range like Self::splice, and gives each new row an optional focus handle.

Pass None for rows that can’t take focus. If a row with a focus handle holds focus when it scrolls out of view, the list keeps rendering it after the visible rows, so keyboard input still reaches it, until focus moves elsewhere.

Source

pub fn set_scroll_handler( &self, handler: impl FnMut(&ListScrollEvent, &mut Window, &mut App) + 'static, )

Sets a callback that runs after each wheel or trackpad scroll of the list.

The callback runs on every wheel event the list handles, including events that don’t move it. It does not run for Self::scroll_to, Self::scroll_by, Self::scroll_to_reveal_item or scrollbar drags.

The callback runs while the list’s state is borrowed. Use the ListScrollEvent it receives, and don’t call methods on the ListState from inside it.

§Examples
let scrolls = Rc::new(Cell::new(0));
let counted = scrolls.clone();
window.update(|feed, _, _| {
    feed.state.set_scroll_handler(move |event, _window, _cx| {
        assert_eq!(event.count, 10);
        counted.set(counted.get() + 1);
    });
});
window.draw();
// Scroll down 100px, which is row 2 of 50px rows.
window.simulate_scroll(point(px(20.), px(20.)), point(px(0.), px(-100.)));
assert_eq!(scrolls.get(), 1);
window.read(|feed, _| assert_eq!(feed.state.logical_scroll_top().item_ix, 2));
Source

pub fn logical_scroll_top(&self) -> ListOffset

Returns the first visible row, and the pixel offset into that row.

Before the list is scrolled, this is row 0 for ListAlignment::Top. For ListAlignment::Bottom it is the end of the list, the item count, with an offset of zero. Pass a value you saved to Self::scroll_to to restore a position.

Source

pub fn scroll_by(&self, distance: Pixels)

Scrolls the list by distance pixels: toward the end when positive, and toward the start when negative.

The start is clamped at zero. Past the end, the next paint clamps the position. A scroll toward the start stops following the tail. This doesn’t call the scroll handler, and it doesn’t redraw, so call cx.notify() to show the new position.

§Examples
window.draw();
window.update(|feed, _, cx| {
    feed.state.scroll_by(px(120.));
    cx.notify();
});
window.draw();
// 120px down is row 2, 20px into it.
window.read(|feed, _| {
    let top = feed.state.logical_scroll_top();
    assert_eq!((top.item_ix, top.offset_in_item), (2, px(20.)));
});
Source

pub fn scroll_to_end(&self)

Scrolls past the last row, so the bottom of the list stays in view while the last row grows.

Unlike Self::scroll_to_reveal_item, this anchors to the end of the list, not to a row. The next paint walks back from the end and shows the bottom of the last row, even while that row is still growing, as when text streams in. The scroll takes effect on the next paint.

Source

pub fn set_follow_mode(&self, mode: FollowMode)

Sets whether the list keeps the end in view as rows are added.

FollowMode::Tail scrolls to the end now, and keeps it there on each paint while Self::is_following_tail is true. A user scroll toward the start stops following, and the list starts following again when the user scrolls back to the end. FollowMode::Normal stops following and leaves the position where it is.

§Examples
let state = ListState::new(5, ListAlignment::Top, px(0.));
state.set_follow_mode(FollowMode::Tail);
assert!(state.is_following_tail());
state.set_follow_mode(FollowMode::Normal);
assert!(!state.is_following_tail());
Source

pub fn pause_following_tail(&self)

Stops following the tail and keeps the current position, until the user scrolls back to the end.

Unlike Self::set_follow_mode with FollowMode::Normal, the list stays in FollowMode::Tail, so it resumes following when the view returns to the end. Does nothing if the list isn’t following.

Use this when something other than the user changes a row’s height, such as zooming a diagram, and the position should not jump to the end.

§Examples
let state = ListState::new(5, ListAlignment::Top, px(0.));
state.set_follow_mode(FollowMode::Tail);
state.pause_following_tail();
assert!(!state.is_following_tail());
Source

pub fn is_following_tail(&self) -> bool

Returns whether the list is following the tail right now.

This is true after Self::set_follow_mode with FollowMode::Tail, until the user scrolls toward the start or Self::pause_following_tail is called. It is false in FollowMode::Normal.

Source

pub fn scroll_to(&self, scroll_top: ListOffset)

Scrolls the list so that scroll_top is at the top of the viewport.

If scroll_top is past the last row, the list scrolls to the end. A position before the end stops following the tail.

§Examples
let state = ListState::new(5, ListAlignment::Top, px(0.));
state.scroll_to(ListOffset { item_ix: 2, offset_in_item: px(10.) });
assert_eq!(state.logical_scroll_top().item_ix, 2);
assert_eq!(state.logical_scroll_top().offset_in_item, px(10.));
Source

pub fn scroll_to_reveal_item(&self, ix: usize)

Scrolls the least amount that shows row ix fully.

A row above the current top is moved to the top of the viewport. A row below it is moved so its bottom edge sits at the bottom of the viewport. The position takes effect on the next paint.

§Examples
window.draw();
window.update(|feed, _, _| feed.state.scroll_to_reveal_item(9));
window.draw();
window.read(|feed, _| {
    assert_eq!(feed.state.item_is_above_viewport(9), Some(false));
    assert_eq!(feed.state.item_is_below_viewport(9), Some(false));
});
Source

pub fn bounds_for_item(&self, ix: usize) -> Option<Bounds<Pixels>>

Returns the bounds of row ix in window coordinates, or None if the row is above the scroll position or has not been measured.

A measured row below the viewport still has bounds, so compare them with Self::viewport_bounds. Self::item_is_above_viewport and Self::item_is_below_viewport answer that directly.

Source

pub fn scrollbar_drag_started(&self)

Tells the list that the user started dragging its scrollbar.

Until Self::scrollbar_drag_ended, the scrollbar uses the content height from this moment, so the thumb doesn’t move while rows in the overdraw are measured.

Source

pub fn scrollbar_drag_ended(&self)

Tells the list that the scrollbar drag has ended, so the scrollbar uses the live content height again. See Self::scrollbar_drag_started.

Source

pub fn is_scrollbar_dragging(&self) -> bool

Returns whether the scrollbar is being dragged.

This is true between Self::scrollbar_drag_started and Self::scrollbar_drag_ended. Use it to tell a scrollbar drag from a wheel or trackpad scroll, for example to stop auto-scrolling during a manual drag.

Source

pub fn set_offset_from_scrollbar(&self, point: Point<Pixels>)

Scrolls the list to the position that a scrollbar reports.

point.y is a negative scroll offset, as Self::scroll_px_offset_for_scrollbar returns it. It is clamped to the content. A drag to the end while the list is in FollowMode::Tail resumes following the tail, and any other position stops it. Does nothing before the first paint.

Source

pub fn max_offset_for_scrollbar(&self) -> Point<Pixels>

Returns the largest scroll distance, as a positive y.

This is the content height minus the viewport height, using the heights measured so far and any height hints. During a scrollbar drag it keeps the value from when the drag started.

Source

pub fn scroll_px_offset_for_scrollbar(&self) -> Point<Pixels>

Returns the current scroll position for the scrollbar, as a negative y.

The value is the negation of how far the content has moved, so it is the negative of Self::max_offset_for_scrollbar for a bottom-aligned list that is pinned to the end.

Source

pub fn viewport_bounds(&self) -> Bounds<Pixels>

Returns the viewport’s bounds in window coordinates, from the last prepaint.

Before the first prepaint this returns empty bounds at the origin.

Source

pub fn item_is_above_viewport(&self, ix: usize) -> Option<bool>

Returns whether row ix is entirely above the viewport, or None before the first layout.

Rows before the scroll position are above the viewport (Some(true)) even when they were never measured. Any other row needs bounds, so it returns None if it hasn’t been measured. A zero-height viewport still gives an answer, so the result doesn’t flicker while sibling UI resizes the list.

Source

pub fn item_is_below_viewport(&self, ix: usize) -> Option<bool>

Returns whether row ix is entirely below the viewport, or None when the answer isn’t known yet.

Rows before the scroll position return Some(false). Other rows follow the rules of Self::item_is_above_viewport.

Trait Implementations§

Source§

impl Clone for ListState

Source§

fn clone(&self) -> Self

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 Debug for ListState

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for S
where T: Real + Zero + Arithmetics + Clone, Swp: WhitePoint<T>, Dwp: WhitePoint<T>, D: AdaptFrom<S, Swp, Dwp, T>,

Source§

fn adapt_into_using<M>(self, method: M) -> D
where M: TransformMatrix<T>,

👎Deprecated since 0.7.7:

replaced by palette::chromatic_adaptation::AdaptIntoUnclamped

Convert the source color to the destination color using the specified method.
Source§

fn adapt_into(self) -> D

👎Deprecated since 0.7.7:

replaced by palette::chromatic_adaptation::AdaptIntoUnclamped

Convert the source color to the destination color using the bradford method by default.
Source§

impl<T, C> AdaptIntoUnclamped<T> for C
where T: AdaptFromUnclamped<C>,

Source§

type Scalar = <T as AdaptFromUnclamped<C>>::Scalar

The number type that’s used as the color’s components.
Source§

fn adapt_into_unclamped_with<M>(self) -> T

Adapt a color of type Self into a color of type T, using the custom matrix M. Read more
Source§

fn adapt_into_unclamped(self) -> T
where Bradford: LmsToXyz<Self::Scalar> + XyzToLms<Self::Scalar>,

Adapt a color of type Self into a color of type T, using the Bradford matrix. Read more
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, C> ArraysFrom<C> for T
where C: IntoArrays<T>,

Source§

fn arrays_from(colors: C) -> T

Cast a collection of colors into a collection of arrays.
Source§

impl<T, C> ArraysInto<C> for T
where C: FromArrays<T>,

Source§

fn arrays_into(self) -> C

Cast this collection of arrays into a collection of colors.
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<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for U
where T: FromCam16Unclamped<WpParam, U>,

Source§

type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

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

Source§

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

impl<T, C> ComponentsFrom<C> for T
where C: IntoComponents<T>,

Source§

fn components_from(colors: C) -> T

Cast a collection of colors into a collection of color components.
Source§

impl<T, C> ComponentsInto<C> for T

Source§

fn components_into(self) -> C

Cast this collection of color components into a collection of colors. Read more
Source§

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

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromAngle<T> for T

Source§

fn from_angle(angle: T) -> T

Performs a conversion from angle.
Source§

impl<T, U> FromStimulus<U> for T
where U: IntoStimulus<T>,

Source§

fn from_stimulus(other: U) -> T

Converts other into Self, while performing the appropriate scaling, rounding and clamping.
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, U> IntoAngle<U> for T
where U: FromAngle<T>,

Source§

fn into_angle(self) -> U

Performs a conversion into T.
Source§

impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for U
where T: Cam16FromUnclamped<WpParam, U>,

Source§

type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T, U> IntoColor<U> for T
where U: FromColor<T>,

Source§

fn into_color(self) -> U

Convert into T with values clamped to the color defined bounds Read more
Source§

impl<T, U> IntoColorUnclamped<U> for T
where U: FromColorUnclamped<T>,

Source§

fn into_color_unclamped(self) -> U

Convert into T. The resulting color might be invalid in its color space Read more
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> IntoStimulus<T> for T

Source§

fn into_stimulus(self) -> T

Converts self into T, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

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

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, C> TryComponentsInto<C> for T
where C: TryFromComponents<T>,

Source§

type Error = <C as TryFromComponents<T>>::Error

The error for when try_into_colors fails to cast.
Source§

fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>

Try to cast this collection of color components into a collection of colors. Read more
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, U> TryIntoColor<U> for T
where U: TryFromColor<T>,

Source§

fn try_into_color(self) -> Result<U, OutOfBounds<U>>

Convert into T, returning ok if the color is inside of its defined range, otherwise an OutOfBounds error is returned which contains the unclamped color. Read more
Source§

impl<C, U> UintsFrom<C> for U
where C: IntoUints<U>,

Source§

fn uints_from(colors: C) -> U

Cast a collection of colors into a collection of unsigned integers.
Source§

impl<C, U> UintsInto<C> for U
where C: FromUints<U>,

Source§

fn uints_into(self) -> C

Cast this collection of unsigned integers into a collection of colors.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

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