nav-scrollabe: detect size to determine if needs scrolling, msg when ready
[?]
Jun 28, 2025, 9:47 AM
WIFVLV376GIMVTGVXBFWIPU7FR5O3SGIQ343KIJEBWB6UURTJZJQCDependencies
- [2]
6YZAVBWUInitial commit - [3]
3SYSJKYLadd app icon - [4]
23SFYK4Qbig view refactor into a new crate - [5]
SGHF5QCVcargo update - [6]
WW36JYLRadd iced_nav_scrollable widget crate - [7]
KLR5FRIBadd fs state read/write of repos - [8]
IQDCHWCPload a pijul repo - [9]
6SW7UVSHupdate iced version
Change contents
- edit in iced_nav_scrollable/src/lib.rs at line 6
use iced_futures::MaybeSend; - edit in iced_nav_scrollable/src/lib.rs at line 11
pub offsets_ready: bool,pub offsets: Vec<f32>,pub y_offset: f32, - replacement in iced_nav_scrollable/src/lib.rs at line 12
pub sections: IndexMap<container::Id, f32>,pub height: f32,pub offset: f32,pub needs_scrolling: NeedsScrolling,pub generation: usize,pub section_heights: IndexMap<container::Id, f32>,pub section_offsets: Vec<f32>,pub pending_tasks: Option<usize>, - replacement in iced_nav_scrollable/src/lib.rs at line 24
GotHeight { id: container::Id, height: f32 },GotScrollableHeight {height: f32,generation: usize,},GotSectionHeight {id: container::Id,height: f32,generation: usize,}, - edit in iced_nav_scrollable/src/lib.rs at line 36
}#[derive(Debug, Clone, Copy)]pub enum NeedsScrolling {Yes,No, - replacement in iced_nav_scrollable/src/lib.rs at line 45
let (sections, tasks): (IndexMap<_, _>, Vec<_>) = (0..contents_count)let generation = 0;let (section_heights, mut tasks): (IndexMap<_, _>, Vec<_>) = (0..contents_count) - replacement in iced_nav_scrollable/src/lib.rs at line 54
let task =height_task(id.clone()).map(move |height| Msg::GotHeight {let task = container_height_task(id.clone()).map(move |height| {Msg::GotSectionHeight { - replacement in iced_nav_scrollable/src/lib.rs at line 58
});generation,}}); - edit in iced_nav_scrollable/src/lib.rs at line 66
tasks.push(scrollable_height_task(id.clone()).map(move |height| {Msg::GotScrollableHeight { height, generation }}));// To be computed from sizes once tasks completelet section_offsets = vec![0.0; section_heights.len()];// 1 task to get the scrollable heightlet pending_tasks = Some(contents_count + 1); - edit in iced_nav_scrollable/src/lib.rs at line 76
offsets_ready: false,// To be computed from sizes once tasks completeoffsets: vec![0.0; sections.len()],y_offset: 0.0, - replacement in iced_nav_scrollable/src/lib.rs at line 77
sections,height: 0.0,offset: 0.0,needs_scrolling: NeedsScrolling::Yes,generation,section_heights,section_offsets,// 1 task to get the scrollable heightpending_tasks, - replacement in iced_nav_scrollable/src/lib.rs at line 94
pub fn update(nav: &mut NavScrollable, msg: Msg) -> Task<Msg> {pub fn update<Message, MapFn, OnReady>(nav: &mut NavScrollable,msg: Msg,map_msg: MapFn,on_ready: OnReady,) -> Task<Message>whereMessage: MaybeSend + 'static,MapFn: Fn(Msg) -> Message + MaybeSend + 'static,OnReady: Fn(NeedsScrolling) -> Message,{ - replacement in iced_nav_scrollable/src/lib.rs at line 108
Task::batch(nav.sections.keys().map(|id| {let id_clone = id.clone();height_task(id.clone()).map(move |height| Msg::GotHeight {id: id_clone.clone(),height,})}))let generation = nav.generation;// 1 task to get the scrollable heightnav.pending_tasks = Some(nav.section_heights.len() + 1);Task::batch(nav.section_heights.keys().map(|id| {let id_clone = id.clone();container_height_task(id.clone()).map(move |height| {Msg::GotSectionHeight {id: id_clone.clone(),height,generation,}})}).chain([scrollable_height_task(nav.id.clone()).map(move |height| Msg::GotScrollableHeight {height,generation,},)]),).map(map_msg)}Msg::GotScrollableHeight { height, generation } => {if generation == nav.generation {nav.height = height;if let Some(offsets) = nav.pending_tasks.as_mut() {*offsets -= 1;update_offsets_if_ready(nav);if nav.pending_tasks.is_none() {return Task::done(on_ready(nav.needs_scrolling));}}}Task::none() - replacement in iced_nav_scrollable/src/lib.rs at line 148
Msg::GotHeight { id, height } => {reset_offsets(nav);nav.sections.insert(id, height);Msg::GotSectionHeight {id,height,generation,} => {if generation == nav.generation {nav.section_heights.insert(id, height);if let Some(offsets) = nav.pending_tasks.as_mut() {*offsets -= 1;update_offsets_if_ready(nav);if nav.pending_tasks.is_none() {return Task::done(on_ready(nav.needs_scrolling));}}} - replacement in iced_nav_scrollable/src/lib.rs at line 167
nav.y_offset = viewport.absolute_offset().y;nav.offset = viewport.absolute_offset().y; - replacement in iced_nav_scrollable/src/lib.rs at line 171
update_offsets(nav);if nav.offsets_ready {if let Some(y) =nav.offsets.iter().find(|offset| *offset > &nav.y_offset)if nav.pending_tasks.is_none() {if let Some(y) = nav.section_offsets.iter().find(|offset| *offset > &nav.offset) - replacement in iced_nav_scrollable/src/lib.rs at line 186
update_offsets(nav);if nav.offsets_ready {if nav.pending_tasks.is_none() { - replacement in iced_nav_scrollable/src/lib.rs at line 188
.offsets.section_offsets - replacement in iced_nav_scrollable/src/lib.rs at line 191
.find(|offset| *offset < &nav.y_offset).find(|offset| *offset < &nav.offset) - replacement in iced_nav_scrollable/src/lib.rs at line 206
pub fn view<'a, Message, Theme, Renderer, F>(pub fn view<'a, Message, Theme, Renderer, MapFn>( - replacement in iced_nav_scrollable/src/lib.rs at line 210
map_msg: F,map_msg: MapFn, - replacement in iced_nav_scrollable/src/lib.rs at line 216
F: Fn(Msg) -> Message + 'a,MapFn: Fn(Msg) -> Message + 'a, - replacement in iced_nav_scrollable/src/lib.rs at line 218
debug_assert_eq!(nav.sections.len(), children.len(), "The `NavScrollable` was most likely initialized with a count different from the number of actual children given to the the view function. Count is {}, but got {} children", nav.sections.len(), children.len());debug_assert_eq!(nav.section_heights.len(), children.len(), "The `NavScrollable` was most likely initialized with a count different from the number of actual children given to the the view function. Count is {}, but got {} children", nav.section_heights.len(), children.len()); - replacement in iced_nav_scrollable/src/lib.rs at line 222
.zip(nav.sections.keys()).zip(nav.section_heights.keys()) - replacement in iced_nav_scrollable/src/lib.rs at line 232
nav.offsets_ready = false;nav.section_offsets.iter_mut().for_each(|offset| *offset = 0.0);nav.generation = nav.generation.wrapping_add(1); - replacement in iced_nav_scrollable/src/lib.rs at line 238
fn update_offsets(nav: &mut NavScrollable) {if !nav.offsets_ready {debug_assert_eq!(nav.sections.len(), nav.offsets.len());fn update_offsets_if_ready(nav: &mut NavScrollable) {if nav.pending_tasks == Some(0) {debug_assert_eq!(nav.section_heights.len(), nav.section_offsets.len()); - replacement in iced_nav_scrollable/src/lib.rs at line 242
nav.sections.values().enumerate().for_each(|(i, height)| {// The current offset is the value of the accnav.offsets[i] = acc;// Increment the acc with the height of this sectionacc += *height;});nav.offsets_ready = true;nav.section_heights.values().enumerate().for_each(|(i, height)| {// The current offset is the value of the accnav.section_offsets[i] = acc;// Increment the acc with the height of this sectionacc += *height;});nav.needs_scrolling = if acc > nav.height {NeedsScrolling::Yes} else {NeedsScrolling::No};nav.pending_tasks = None;}}/// Produces a [`Task`] that queries the height of the contents of [`Scrollable`] with the/// given [`Id`].fn scrollable_height_task(id: impl Into<scrollable::Id>) -> Task<f32> {let id = id.into();struct SizeOp {target: advanced::widget::Id,height: Option<f32>,}impl advanced::widget::Operation<f32> for SizeOp {fn scrollable(&mut self,id: Option<&advanced::widget::Id>,_bounds: Rectangle,content_bounds: Rectangle,_translation: iced::Vector,_state: &mut dyn advanced::widget::operation::Scrollable,) {if id == Some(&self.target) {dbg!(&_bounds, &content_bounds);self.height = Some(content_bounds.height);return;}}fn container(&mut self,_id: Option<&advanced::widget::Id>,_bounds: Rectangle,operate_on_children: &mut dyn FnMut(&mut dyn advanced::widget::Operation<f32>,),) {operate_on_children(self);}fn finish(&self) -> advanced::widget::operation::Outcome<f32> {advanced::widget::operation::Outcome::Some(self.height.expect("Must be able to determine the size. If this even panics, make the height optional and re-try the task when None"),)} - edit in iced_nav_scrollable/src/lib.rs at line 303
advanced::widget::operate(SizeOp {target: id.into(),height: None,}) - replacement in iced_nav_scrollable/src/lib.rs at line 312
fn height_task(id: impl Into<container::Id>) -> Task<f32> {fn container_height_task(id: impl Into<container::Id>) -> Task<f32> { - edit in iced_nav_scrollable/Cargo.toml at line 13
workspace = true[dependencies.iced_futures] - edit in Cargo.toml at line 42
[workspace.dependencies.iced_futures]git = "https://github.com/iced-rs/iced"rev = "c952ea8485b00e58bdff153989f708553272e131"# path = "../iced/futures" - replacement in Cargo.lock at line 446
version = "0.8.3"version = "0.8.4" - replacement in Cargo.lock at line 448
checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e"checksum = "19135c0c7a60bfee564dbe44ab5ce0557c6bf3884e5291a50be76a15640c4fbd" - replacement in Cargo.lock at line 1889
version = "0.13.1"version = "0.13.3" - replacement in Cargo.lock at line 1891
checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2"checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" - edit in Cargo.lock at line 2102
"iced_futures", - replacement in Cargo.lock at line 2438
version = "0.2.2"version = "0.2.3" - replacement in Cargo.lock at line 2440
checksum = "14d75c7014ddab93c232bc6bb9f64790d3dfd1d605199acd4b40b6d69e691e9f"checksum = "f6970fe7a5300b4b42e62c52efa0187540a5bef546c60edaf554ef595d2e6f0b" - replacement in Cargo.lock at line 2644
version = "0.3.1"version = "0.3.2" - replacement in Cargo.lock at line 2646
checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0"checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" - replacement in Cargo.lock at line 4066
version = "1.0.16"version = "1.0.17" - replacement in Cargo.lock at line 4068
checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" - replacement in Cargo.lock at line 4233
version = "0.11.12"version = "0.11.20" - replacement in Cargo.lock at line 4235
checksum = "d6a5f31fcf7500f9401fea858ea4ab5525c99f2322cfcee732c0e6c74208c0c6"checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" - replacement in Cargo.lock at line 6780
version = "0.4.17"version = "0.4.18" - replacement in Cargo.lock at line 6782
checksum = "0f6fe2e33d02a98ee64423802e16df3de99c43e5cf5ff983767e1128b394c8ac"checksum = "7384255a918371b5af158218d131530f694de9ad3815ebdd0453a940485cb0fa"