Skip to main content

cranpose_foundation/modifier/
scroll_axis_range.rs

1use crate::BringIntoViewSpec;
2
3/// How far a container has scrolled along one axis and how far it can go.
4///
5/// This is Compose's `ScrollAxisRange` (`verticalScrollAxisRange`,
6/// `horizontalScrollAxisRange`). A lazy list has no whole extent to give, so
7/// it reports the first visible item as the value and one more than that as
8/// the end while it can still scroll; a reader only needs to know whether it
9/// can page on.
10///
11/// `content_padding_start` and `content_padding_end` are the container's
12/// content padding at its top and bottom (or left and right) edges, in layout
13/// pixels. Content scrolls under that padding, where a bar may cover it, so a
14/// control a reader or the keyboard moves to is brought in past it.
15/// `bring_into_view_spec` says where in the space between the paddings that
16/// control comes to rest.
17#[derive(Clone, Copy, Debug, PartialEq)]
18pub struct ScrollAxisRange {
19    /// The current scroll position, in layout pixels. A lazy list reports the index of its first
20    /// visible item.
21    pub value: f32,
22    /// The largest value that `value` reaches, in the same unit.
23    pub max_value: f32,
24    /// Whether the container scrolls in reverse, so content starts at the far end. Compose's
25    /// `reverseScrolling`.
26    pub reverse: bool,
27    /// The content padding at the start edge of the container, in layout pixels.
28    pub content_padding_start: f32,
29    /// The content padding at the end edge of the container, in layout pixels.
30    pub content_padding_end: f32,
31    /// Where the container puts a child that takes focus or that a reader
32    /// moves to.
33    pub bring_into_view_spec: BringIntoViewSpec,
34}
35
36impl ScrollAxisRange {
37    /// Creates a range for a container at scroll offset `value` that reaches at most `max_value`,
38    /// with no content padding and the default [`BringIntoViewSpec`].
39    pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
40        Self {
41            value,
42            max_value,
43            reverse,
44            content_padding_start: 0.0,
45            content_padding_end: 0.0,
46            bring_into_view_spec: BringIntoViewSpec::Default,
47        }
48    }
49
50    /// The same range with the container's content padding at its start and
51    /// end edges, in layout pixels.
52    pub fn with_content_padding(self, start: f32, end: f32) -> Self {
53        Self {
54            content_padding_start: start,
55            content_padding_end: end,
56            ..self
57        }
58    }
59
60    /// The same range with the container's [`BringIntoViewSpec`].
61    pub fn with_bring_into_view_spec(self, bring_into_view_spec: BringIntoViewSpec) -> Self {
62        Self {
63            bring_into_view_spec,
64            ..self
65        }
66    }
67
68    /// Whether the container can scroll further in the forward direction.
69    pub fn can_scroll_forward(&self) -> bool {
70        self.value < self.max_value
71    }
72
73    /// Whether the container can scroll further in the backward direction.
74    pub fn can_scroll_backward(&self) -> bool {
75        self.value > 0.0
76    }
77}