use iced::widget::{ button, column, container, horizontal_rule, progress_bar, radio, scrollable, text, vertical_space, Row, }; use iced::{Element, Length, Sandbox, Settings, Theme}; pub fn main() -> iced::Result { ScrollableDemo::run(Settings::default()) } struct ScrollableDemo { theme: Theme, variants: Vec, } #[derive(Debug, Clone)] enum Message { ThemeChanged(Theme), ScrollToTop(usize), ScrollToBottom(usize), Scrolled(usize, f32), } impl Sandbox for ScrollableDemo { type Message = Message; fn new() -> Self { ScrollableDemo { theme: Default::default(), variants: Variant::all(), } } fn title(&self) -> String { String::from("Scrollable - Iced") } fn update(&mut self, message: Message) { match message { Message::ThemeChanged(theme) => self.theme = theme, Message::ScrollToTop(i) => { if let Some(variant) = self.variants.get_mut(i) { // TODO // variant.scrollable.snap_to(0.0); variant.latest_offset = 0.0; } } Message::ScrollToBottom(i) => { if let Some(variant) = self.variants.get_mut(i) { // TODO // variant.scrollable.snap_to(1.0); variant.latest_offset = 1.0; } } Message::Scrolled(i, offset) => { if let Some(variant) = self.variants.get_mut(i) { variant.latest_offset = offset; } } } } fn view(&self) -> Element { let ScrollableDemo { theme, variants, .. } = self; let choose_theme = [Theme::Light, Theme::Dark].iter().fold( column!["Choose a theme:"].spacing(10), |column, option| { column.push(radio( format!("{:?}", option), *option, Some(*theme), Message::ThemeChanged, )) }, ); let scrollable_row = Row::with_children( variants .iter() .enumerate() .map(|(i, variant)| { let mut contents = column![ variant.title.as_ref(), button("Scroll to bottom",) .width(Length::Fill) .padding(10) .on_press(Message::ScrollToBottom(i)), ] .padding(10) .spacing(10) .width(Length::Fill); if let Some(scrollbar_width) = variant.scrollbar_width { contents = contents.push(text(format!( "scrollbar_width: {:?}", scrollbar_width ))); } if let Some(scrollbar_margin) = variant.scrollbar_margin { contents = contents.push(text(format!( "scrollbar_margin: {:?}", scrollbar_margin ))); } if let Some(scroller_width) = variant.scroller_width { contents = contents.push(text(format!( "scroller_width: {:?}", scroller_width ))); } contents = contents .push(vertical_space(Length::Units(100))) .push( "Some content that should wrap within the \ scrollable. Let's output a lot of short words, so \ that we'll make sure to see how wrapping works \ with these scrollbars.", ) .push(vertical_space(Length::Units(1200))) .push("Middle") .push(vertical_space(Length::Units(1200))) .push("The End.") .push( button("Scroll to top") .width(Length::Fill) .padding(10) .on_press(Message::ScrollToTop(i)), ); let mut scrollable = scrollable(contents) .height(Length::Fill) .on_scroll(move |offset| Message::Scrolled(i, offset)); if let Some(scrollbar_width) = variant.scrollbar_width { scrollable = scrollable.scrollbar_width(scrollbar_width); } if let Some(scrollbar_margin) = variant.scrollbar_margin { scrollable = scrollable.scrollbar_margin(scrollbar_margin); } if let Some(scroller_width) = variant.scroller_width { scrollable = scrollable.scroller_width(scroller_width); } column![ scrollable, progress_bar(0.0..=1.0, variant.latest_offset,) ] .width(Length::Fill) .height(Length::Fill) .spacing(10) .into() }) .collect(), ) .spacing(20) .width(Length::Fill) .height(Length::Fill); let content = column![choose_theme, horizontal_rule(20), scrollable_row] .spacing(20) .padding(20); container(content) .width(Length::Fill) .height(Length::Fill) .center_x() .center_y() .into() } fn theme(&self) -> Theme { self.theme } } /// A version of a scrollable struct Variant { title: &'static str, scrollbar_width: Option, scrollbar_margin: Option, scroller_width: Option, latest_offset: f32, } impl Variant { pub fn all() -> Vec { vec![ Self { title: "Default Scrollbar", scrollbar_width: None, scrollbar_margin: None, scroller_width: None, latest_offset: 0.0, }, Self { title: "Slimmed & Margin", scrollbar_width: Some(4), scrollbar_margin: Some(3), scroller_width: Some(4), latest_offset: 0.0, }, Self { title: "Wide Scroller", scrollbar_width: Some(4), scrollbar_margin: None, scroller_width: Some(10), latest_offset: 0.0, }, Self { title: "Narrow Scroller", scrollbar_width: Some(10), scrollbar_margin: None, scroller_width: Some(4), latest_offset: 0.0, }, ] } }