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}