virtualizer_adapter/
controller.rs1use crate::{
2 Easing, ScrollAnchor, Tween, VirtualizerKey, apply_anchor, capture_first_visible_anchor,
3};
4
5#[derive(Clone, Debug)]
21pub struct Controller<K> {
22 v: virtualizer::Virtualizer<K>,
23 tween: Option<Tween>,
24}
25
26impl<K: VirtualizerKey> Controller<K> {
27 pub fn new(options: virtualizer::VirtualizerOptions<K>) -> Self {
28 Self {
29 v: virtualizer::Virtualizer::new(options),
30 tween: None,
31 }
32 }
33
34 pub fn from_virtualizer(v: virtualizer::Virtualizer<K>) -> Self {
35 Self { v, tween: None }
36 }
37
38 pub fn virtualizer(&self) -> &virtualizer::Virtualizer<K> {
39 &self.v
40 }
41
42 pub fn virtualizer_mut(&mut self) -> &mut virtualizer::Virtualizer<K> {
43 &mut self.v
44 }
45
46 pub fn into_virtualizer(self) -> virtualizer::Virtualizer<K> {
47 self.v
48 }
49
50 pub fn is_animating(&self) -> bool {
51 self.tween.is_some()
52 }
53
54 pub fn cancel_animation(&mut self) {
55 self.tween = None;
56 }
57
58 pub fn on_viewport_size(&mut self, viewport_main: u32) {
59 self.v.set_viewport_size(viewport_main);
60 }
61
62 pub fn on_scroll(&mut self, scroll_offset: u64, now_ms: u64) {
66 self.cancel_animation();
67 self.v.apply_scroll_offset_event(scroll_offset, now_ms);
68 }
69
70 pub fn tick(&mut self, now_ms: u64) -> Option<u64> {
75 let Some(tween) = self.tween else {
76 self.v.update_scrolling(now_ms);
77 return None;
78 };
79
80 let off = tween.sample(now_ms);
81 self.v.apply_scroll_offset_event_clamped(off, now_ms);
82
83 if tween.is_done(now_ms) {
84 self.tween = None;
85 self.v.set_is_scrolling(false);
86 }
87
88 Some(self.v.scroll_offset())
89 }
90
91 pub fn scroll_to_index(&mut self, index: usize, align: virtualizer::Align, now_ms: u64) -> u64 {
95 let off = self.v.scroll_to_index_offset(index, align);
96 self.v.apply_scroll_offset_event_clamped(off, now_ms);
97 self.v.scroll_offset()
98 }
99
100 pub fn scroll_to_offset(&mut self, offset: u64, now_ms: u64) -> u64 {
104 self.v.apply_scroll_offset_event_clamped(offset, now_ms);
105 self.v.scroll_offset()
106 }
107
108 pub fn start_tween_to_index(
112 &mut self,
113 index: usize,
114 align: virtualizer::Align,
115 now_ms: u64,
116 duration_ms: u64,
117 easing: Easing,
118 ) -> u64 {
119 let to = self.v.scroll_to_index_offset(index, align);
120 self.start_tween_to_offset(to, now_ms, duration_ms, easing)
121 }
122
123 pub fn start_tween_to_offset(
127 &mut self,
128 offset: u64,
129 now_ms: u64,
130 duration_ms: u64,
131 easing: Easing,
132 ) -> u64 {
133 let to = self.v.clamp_scroll_offset(offset);
134 let from = self.v.scroll_offset();
135 self.tween = Some(Tween::new(from, to, now_ms, duration_ms, easing));
136 to
137 }
138
139 pub fn capture_first_visible_anchor(&self) -> Option<ScrollAnchor<K>> {
140 capture_first_visible_anchor(&self.v)
141 }
142
143 pub fn capture_anchor_at_offset_in_viewport(
147 &self,
148 offset_in_viewport: u64,
149 ) -> Option<ScrollAnchor<K>> {
150 let abs = self.v.scroll_offset().saturating_add(offset_in_viewport);
151 let item = self.v.virtual_item_keyed_for_offset(abs)?;
152 let offset_in_viewport = self.v.scroll_offset().saturating_sub(item.start);
153 Some(ScrollAnchor {
154 key: item.key,
155 offset_in_viewport,
156 })
157 }
158
159 pub fn apply_anchor(
163 &mut self,
164 anchor: &ScrollAnchor<K>,
165 key_to_index: impl FnMut(&K) -> Option<usize>,
166 ) -> bool {
167 self.cancel_animation();
168 apply_anchor(&mut self.v, anchor, key_to_index)
169 }
170}