iced-yoda/examples/scrollable/src/main.rs

351 lines
11 KiB
Rust
Raw Normal View History

use iced::widget::{
button, column, container, horizontal_space, progress_bar, radio, row,
scrollable, slider, text, vertical_space,
2020-10-22 16:10:10 -05:00
};
use iced::{Border, Center, Color, Element, Fill, Task, Theme};
2025-01-06 23:00:21 +01:00
use std::sync::LazyLock;
2024-10-03 22:27:25 -05:00
static SCROLLABLE_ID: LazyLock<scrollable::Id> =
LazyLock::new(scrollable::Id::unique);
2020-10-22 16:10:10 -05:00
pub fn main() -> iced::Result {
iced::application(
ScrollableDemo::default,
2024-03-16 05:33:47 +01:00
ScrollableDemo::update,
ScrollableDemo::view,
)
.theme(ScrollableDemo::theme)
.run()
2020-10-22 16:10:10 -05:00
}
struct ScrollableDemo {
scrollable_direction: Direction,
scrollbar_width: u32,
scrollbar_margin: u32,
scroller_width: u32,
current_scroll_offset: scrollable::RelativeOffset,
anchor: scrollable::Anchor,
2020-10-22 16:10:10 -05:00
}
#[derive(Debug, Clone, Eq, PartialEq, Copy)]
enum Direction {
Vertical,
Horizontal,
Multi,
2022-09-08 17:36:59 -04:00
}
2020-10-22 16:10:10 -05:00
#[derive(Debug, Clone)]
enum Message {
SwitchDirection(Direction),
AlignmentChanged(scrollable::Anchor),
ScrollbarWidthChanged(u32),
ScrollbarMarginChanged(u32),
ScrollerWidthChanged(u32),
ScrollToBeginning,
ScrollToEnd,
2023-04-17 13:55:40 -07:00
Scrolled(scrollable::Viewport),
2020-10-22 16:10:10 -05:00
}
2024-03-16 05:33:47 +01:00
impl ScrollableDemo {
fn new() -> Self {
ScrollableDemo {
scrollable_direction: Direction::Vertical,
scrollbar_width: 10,
scrollbar_margin: 0,
scroller_width: 10,
current_scroll_offset: scrollable::RelativeOffset::START,
anchor: scrollable::Anchor::Start,
}
2020-10-22 16:10:10 -05:00
}
fn update(&mut self, message: Message) -> Task<Message> {
2020-10-22 16:10:10 -05:00
match message {
Message::SwitchDirection(direction) => {
self.current_scroll_offset = scrollable::RelativeOffset::START;
self.scrollable_direction = direction;
scrollable::snap_to(
SCROLLABLE_ID.clone(),
self.current_scroll_offset,
)
}
2023-06-12 21:04:43 -07:00
Message::AlignmentChanged(alignment) => {
self.current_scroll_offset = scrollable::RelativeOffset::START;
self.anchor = alignment;
2023-06-12 21:04:43 -07:00
scrollable::snap_to(
SCROLLABLE_ID.clone(),
self.current_scroll_offset,
)
}
Message::ScrollbarWidthChanged(width) => {
self.scrollbar_width = width;
Task::none()
}
Message::ScrollbarMarginChanged(margin) => {
self.scrollbar_margin = margin;
Task::none()
}
Message::ScrollerWidthChanged(width) => {
self.scroller_width = width;
Task::none()
}
Message::ScrollToBeginning => {
self.current_scroll_offset = scrollable::RelativeOffset::START;
scrollable::snap_to(
SCROLLABLE_ID.clone(),
self.current_scroll_offset,
)
}
Message::ScrollToEnd => {
self.current_scroll_offset = scrollable::RelativeOffset::END;
scrollable::snap_to(
SCROLLABLE_ID.clone(),
self.current_scroll_offset,
)
}
2023-04-17 13:55:40 -07:00
Message::Scrolled(viewport) => {
self.current_scroll_offset = viewport.relative_offset();
Task::none()
}
2020-10-22 16:10:10 -05:00
}
}
fn view(&self) -> Element<'_, Message> {
let scrollbar_width_slider = slider(
0..=15,
self.scrollbar_width,
Message::ScrollbarWidthChanged,
2020-10-22 16:10:10 -05:00
);
let scrollbar_margin_slider = slider(
0..=15,
self.scrollbar_margin,
Message::ScrollbarMarginChanged,
);
let scroller_width_slider =
slider(0..=15, self.scroller_width, Message::ScrollerWidthChanged);
2020-10-22 16:10:10 -05:00
let scroll_slider_controls = column![
text("Scrollbar width:"),
scrollbar_width_slider,
text("Scrollbar margin:"),
scrollbar_margin_slider,
text("Scroller width:"),
scroller_width_slider,
]
.spacing(10);
let scroll_orientation_controls = column![
text("Scrollbar direction:"),
radio(
"Vertical",
Direction::Vertical,
Some(self.scrollable_direction),
Message::SwitchDirection,
),
radio(
"Horizontal",
Direction::Horizontal,
Some(self.scrollable_direction),
Message::SwitchDirection,
),
radio(
"Both!",
Direction::Multi,
Some(self.scrollable_direction),
Message::SwitchDirection,
),
]
.spacing(10);
2020-10-22 16:10:10 -05:00
let scroll_alignment_controls = column![
text("Scrollable alignment:"),
2023-06-12 21:04:43 -07:00
radio(
"Start",
scrollable::Anchor::Start,
Some(self.anchor),
2023-06-12 21:04:43 -07:00
Message::AlignmentChanged,
),
2023-06-12 21:04:43 -07:00
radio(
"End",
scrollable::Anchor::End,
Some(self.anchor),
2023-06-12 21:04:43 -07:00
Message::AlignmentChanged,
)
]
.spacing(10);
2023-06-12 21:04:43 -07:00
let scroll_controls = row![
scroll_slider_controls,
scroll_orientation_controls,
scroll_alignment_controls
]
.spacing(20);
let scroll_to_end_button = || {
button("Scroll to end")
.padding(10)
.on_press(Message::ScrollToEnd)
};
let scroll_to_beginning_button = || {
button("Scroll to beginning")
.padding(10)
.on_press(Message::ScrollToBeginning)
};
let scrollable_content: Element<Message> =
Element::from(match self.scrollable_direction {
Direction::Vertical => scrollable(
column![
scroll_to_end_button(),
text("Beginning!"),
vertical_space().height(1200),
text("Middle!"),
vertical_space().height(1200),
text("End!"),
scroll_to_beginning_button(),
]
.align_x(Center)
.padding([40, 0])
.spacing(40),
)
.direction(scrollable::Direction::Vertical(
scrollable::Scrollbar::new()
.width(self.scrollbar_width)
.margin(self.scrollbar_margin)
.scroller_width(self.scroller_width)
.anchor(self.anchor),
))
.width(Fill)
.height(Fill)
.id(SCROLLABLE_ID.clone())
.on_scroll(Message::Scrolled),
Direction::Horizontal => scrollable(
row![
scroll_to_end_button(),
text("Beginning!"),
horizontal_space().width(1200),
text("Middle!"),
horizontal_space().width(1200),
text("End!"),
scroll_to_beginning_button(),
]
.height(450)
.align_y(Center)
.padding([0, 40])
.spacing(40),
)
.direction(scrollable::Direction::Horizontal(
scrollable::Scrollbar::new()
.width(self.scrollbar_width)
.margin(self.scrollbar_margin)
.scroller_width(self.scroller_width)
.anchor(self.anchor),
))
.width(Fill)
.height(Fill)
.id(SCROLLABLE_ID.clone())
.on_scroll(Message::Scrolled),
Direction::Multi => scrollable(
//horizontal content
row![
column![
text("Let's do some scrolling!"),
vertical_space().height(2400)
],
scroll_to_end_button(),
text("Horizontal - Beginning!"),
horizontal_space().width(1200),
//vertical content
column![
text("Horizontal - Middle!"),
scroll_to_end_button(),
text("Vertical - Beginning!"),
vertical_space().height(1200),
text("Vertical - Middle!"),
vertical_space().height(1200),
text("Vertical - End!"),
scroll_to_beginning_button(),
vertical_space().height(40),
]
.spacing(40),
horizontal_space().width(1200),
text("Horizontal - End!"),
scroll_to_beginning_button(),
]
.align_y(Center)
.padding([0, 40])
.spacing(40),
)
.direction({
let scrollbar = scrollable::Scrollbar::new()
.width(self.scrollbar_width)
.margin(self.scrollbar_margin)
.scroller_width(self.scroller_width)
.anchor(self.anchor);
scrollable::Direction::Both {
horizontal: scrollbar,
vertical: scrollbar,
}
})
.width(Fill)
.height(Fill)
.id(SCROLLABLE_ID.clone())
.on_scroll(Message::Scrolled),
});
let progress_bars: Element<Message> = match self.scrollable_direction {
Direction::Vertical => {
progress_bar(0.0..=1.0, self.current_scroll_offset.y).into()
}
Direction::Horizontal => {
progress_bar(0.0..=1.0, self.current_scroll_offset.x)
2023-05-23 19:42:01 +02:00
.style(progress_bar_custom_style)
.into()
}
Direction::Multi => column![
progress_bar(0.0..=1.0, self.current_scroll_offset.y),
2023-05-23 19:42:01 +02:00
progress_bar(0.0..=1.0, self.current_scroll_offset.x)
.style(progress_bar_custom_style)
]
.spacing(10)
.into(),
};
2020-10-22 16:10:10 -05:00
let content: Element<Message> =
column![scroll_controls, scrollable_content, progress_bars]
.align_x(Center)
.spacing(10)
.into();
container(content).padding(20).into()
2020-10-22 16:10:10 -05:00
}
2024-03-16 05:33:47 +01:00
fn theme(&self) -> Theme {
Theme::Dark
}
2020-10-22 16:10:10 -05:00
}
impl Default for ScrollableDemo {
fn default() -> Self {
Self::new()
}
}
2024-03-24 05:03:09 +01:00
fn progress_bar_custom_style(theme: &Theme) -> progress_bar::Style {
progress_bar::Style {
2023-05-23 19:42:01 +02:00
background: theme.extended_palette().background.strong.color.into(),
bar: Color::from_rgb8(250, 85, 134).into(),
border: Border::default(),
}
2020-10-22 16:10:10 -05:00
}