2024-02-12 19:24:09 +01:00
|
|
|
use iced::widget::scrollable::Properties;
|
2022-07-27 06:49:20 +02:00
|
|
|
use iced::widget::{
|
2022-11-19 10:29:37 -08:00
|
|
|
button, column, container, horizontal_space, progress_bar, radio, row,
|
2024-02-24 19:46:44 +01:00
|
|
|
scrollable, slider, text, vertical_space, Scrollable,
|
2020-10-22 16:10:10 -05:00
|
|
|
};
|
2024-03-16 05:33:47 +01:00
|
|
|
use iced::{Alignment, Border, Color, Command, Element, Length, Theme};
|
2023-06-27 22:30:54 +02:00
|
|
|
|
2022-12-24 21:27:44 -08:00
|
|
|
use once_cell::sync::Lazy;
|
2022-11-19 10:29:37 -08:00
|
|
|
|
2022-12-24 21:27:44 -08:00
|
|
|
static SCROLLABLE_ID: Lazy<scrollable::Id> = Lazy::new(scrollable::Id::unique);
|
2020-10-22 16:10:10 -05:00
|
|
|
|
|
|
|
|
pub fn main() -> iced::Result {
|
2024-03-17 14:16:38 +01:00
|
|
|
iced::program(
|
2024-03-16 15:53:03 +01:00
|
|
|
"Scrollable - Iced",
|
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 {
|
2022-11-19 10:29:37 -08:00
|
|
|
scrollable_direction: Direction,
|
|
|
|
|
scrollbar_width: u16,
|
|
|
|
|
scrollbar_margin: u16,
|
|
|
|
|
scroller_width: u16,
|
2023-01-08 20:07:11 +01:00
|
|
|
current_scroll_offset: scrollable::RelativeOffset,
|
2023-06-12 21:04:43 -07:00
|
|
|
alignment: scrollable::Alignment,
|
2020-10-22 16:10:10 -05:00
|
|
|
}
|
|
|
|
|
|
2022-11-19 10:29:37 -08: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 {
|
2022-11-19 10:29:37 -08:00
|
|
|
SwitchDirection(Direction),
|
2023-06-12 21:04:43 -07:00
|
|
|
AlignmentChanged(scrollable::Alignment),
|
2022-11-19 10:29:37 -08:00
|
|
|
ScrollbarWidthChanged(u16),
|
|
|
|
|
ScrollbarMarginChanged(u16),
|
|
|
|
|
ScrollerWidthChanged(u16),
|
2022-12-24 21:27:44 -08:00
|
|
|
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 {
|
2024-03-16 15:53:03 +01:00
|
|
|
fn new() -> Self {
|
|
|
|
|
ScrollableDemo {
|
|
|
|
|
scrollable_direction: Direction::Vertical,
|
|
|
|
|
scrollbar_width: 10,
|
|
|
|
|
scrollbar_margin: 0,
|
|
|
|
|
scroller_width: 10,
|
|
|
|
|
current_scroll_offset: scrollable::RelativeOffset::START,
|
|
|
|
|
alignment: scrollable::Alignment::Start,
|
|
|
|
|
}
|
2020-10-22 16:10:10 -05:00
|
|
|
}
|
|
|
|
|
|
2022-08-04 03:55:41 +02:00
|
|
|
fn update(&mut self, message: Message) -> Command<Message> {
|
2020-10-22 16:10:10 -05:00
|
|
|
match message {
|
2022-11-19 10:29:37 -08:00
|
|
|
Message::SwitchDirection(direction) => {
|
2023-01-08 20:07:11 +01:00
|
|
|
self.current_scroll_offset = scrollable::RelativeOffset::START;
|
2022-11-19 10:29:37 -08:00
|
|
|
self.scrollable_direction = direction;
|
2022-08-04 03:55:41 +02:00
|
|
|
|
2022-12-24 21:27:44 -08:00
|
|
|
scrollable::snap_to(
|
|
|
|
|
SCROLLABLE_ID.clone(),
|
|
|
|
|
self.current_scroll_offset,
|
|
|
|
|
)
|
2022-08-04 03:55:41 +02:00
|
|
|
}
|
2023-06-12 21:04:43 -07:00
|
|
|
Message::AlignmentChanged(alignment) => {
|
|
|
|
|
self.current_scroll_offset = scrollable::RelativeOffset::START;
|
|
|
|
|
self.alignment = alignment;
|
|
|
|
|
|
|
|
|
|
scrollable::snap_to(
|
|
|
|
|
SCROLLABLE_ID.clone(),
|
|
|
|
|
self.current_scroll_offset,
|
|
|
|
|
)
|
|
|
|
|
}
|
2022-11-19 10:29:37 -08:00
|
|
|
Message::ScrollbarWidthChanged(width) => {
|
|
|
|
|
self.scrollbar_width = width;
|
2022-08-04 03:55:41 +02:00
|
|
|
|
2022-11-19 10:29:37 -08:00
|
|
|
Command::none()
|
|
|
|
|
}
|
|
|
|
|
Message::ScrollbarMarginChanged(margin) => {
|
|
|
|
|
self.scrollbar_margin = margin;
|
|
|
|
|
|
|
|
|
|
Command::none()
|
2021-06-04 20:15:06 +07:00
|
|
|
}
|
2022-11-19 10:29:37 -08:00
|
|
|
Message::ScrollerWidthChanged(width) => {
|
|
|
|
|
self.scroller_width = width;
|
2022-08-04 03:55:41 +02:00
|
|
|
|
2022-11-19 10:29:37 -08:00
|
|
|
Command::none()
|
|
|
|
|
}
|
2022-12-24 21:27:44 -08:00
|
|
|
Message::ScrollToBeginning => {
|
2023-01-08 20:07:11 +01:00
|
|
|
self.current_scroll_offset = scrollable::RelativeOffset::START;
|
2022-11-19 10:29:37 -08:00
|
|
|
|
|
|
|
|
scrollable::snap_to(
|
|
|
|
|
SCROLLABLE_ID.clone(),
|
2022-12-24 21:27:44 -08:00
|
|
|
self.current_scroll_offset,
|
2022-11-19 10:29:37 -08:00
|
|
|
)
|
2021-06-04 20:46:47 +07:00
|
|
|
}
|
2022-12-24 21:27:44 -08:00
|
|
|
Message::ScrollToEnd => {
|
2023-01-08 20:07:11 +01:00
|
|
|
self.current_scroll_offset = scrollable::RelativeOffset::END;
|
2022-08-04 03:55:41 +02:00
|
|
|
|
2022-11-19 10:29:37 -08:00
|
|
|
scrollable::snap_to(
|
|
|
|
|
SCROLLABLE_ID.clone(),
|
2022-12-24 21:27:44 -08:00
|
|
|
self.current_scroll_offset,
|
2022-11-19 10:29:37 -08:00
|
|
|
)
|
|
|
|
|
}
|
2023-04-17 13:55:40 -07:00
|
|
|
Message::Scrolled(viewport) => {
|
|
|
|
|
self.current_scroll_offset = viewport.relative_offset();
|
2022-11-19 10:29:37 -08:00
|
|
|
|
2022-08-04 03:55:41 +02:00
|
|
|
Command::none()
|
2021-06-04 20:15:06 +07:00
|
|
|
}
|
2020-10-22 16:10:10 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-27 06:49:20 +02:00
|
|
|
fn view(&self) -> Element<Message> {
|
2022-11-19 10:29:37 -08:00
|
|
|
let scrollbar_width_slider = slider(
|
|
|
|
|
0..=15,
|
|
|
|
|
self.scrollbar_width,
|
|
|
|
|
Message::ScrollbarWidthChanged,
|
2020-10-22 16:10:10 -05:00
|
|
|
);
|
2022-11-19 10:29:37 -08: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
|
|
|
|
2022-11-19 10:29:37 -08:00
|
|
|
let scroll_slider_controls = column![
|
|
|
|
|
text("Scrollbar width:"),
|
|
|
|
|
scrollbar_width_slider,
|
|
|
|
|
text("Scrollbar margin:"),
|
|
|
|
|
scrollbar_margin_slider,
|
|
|
|
|
text("Scroller width:"),
|
|
|
|
|
scroller_width_slider,
|
|
|
|
|
]
|
2023-03-16 20:23:25 +01:00
|
|
|
.spacing(10);
|
2020-10-24 10:00:49 +02:00
|
|
|
|
2023-03-16 20:23:25 +01:00
|
|
|
let scroll_orientation_controls = column![
|
|
|
|
|
text("Scrollbar direction:"),
|
2022-11-19 10:29:37 -08:00
|
|
|
radio(
|
|
|
|
|
"Vertical",
|
|
|
|
|
Direction::Vertical,
|
|
|
|
|
Some(self.scrollable_direction),
|
|
|
|
|
Message::SwitchDirection,
|
2023-03-16 20:23:25 +01:00
|
|
|
),
|
2022-11-19 10:29:37 -08:00
|
|
|
radio(
|
|
|
|
|
"Horizontal",
|
|
|
|
|
Direction::Horizontal,
|
|
|
|
|
Some(self.scrollable_direction),
|
|
|
|
|
Message::SwitchDirection,
|
2023-03-16 20:23:25 +01:00
|
|
|
),
|
2022-11-19 10:29:37 -08:00
|
|
|
radio(
|
|
|
|
|
"Both!",
|
|
|
|
|
Direction::Multi,
|
|
|
|
|
Some(self.scrollable_direction),
|
|
|
|
|
Message::SwitchDirection,
|
2023-03-16 20:23:25 +01:00
|
|
|
),
|
|
|
|
|
]
|
|
|
|
|
.spacing(10);
|
2020-10-22 16:10:10 -05:00
|
|
|
|
2024-01-05 17:24:43 +01:00
|
|
|
let scroll_alignment_controls = column![
|
|
|
|
|
text("Scrollable alignment:"),
|
2023-06-12 21:04:43 -07:00
|
|
|
radio(
|
|
|
|
|
"Start",
|
|
|
|
|
scrollable::Alignment::Start,
|
|
|
|
|
Some(self.alignment),
|
|
|
|
|
Message::AlignmentChanged,
|
2024-01-05 17:24:43 +01:00
|
|
|
),
|
2023-06-12 21:04:43 -07:00
|
|
|
radio(
|
|
|
|
|
"End",
|
|
|
|
|
scrollable::Alignment::End,
|
|
|
|
|
Some(self.alignment),
|
|
|
|
|
Message::AlignmentChanged,
|
|
|
|
|
)
|
2024-01-05 17:24:43 +01:00
|
|
|
]
|
2023-03-16 20:23:25 +01:00
|
|
|
.spacing(10);
|
2023-06-12 21:04:43 -07:00
|
|
|
|
|
|
|
|
let scroll_controls = row![
|
|
|
|
|
scroll_slider_controls,
|
|
|
|
|
scroll_orientation_controls,
|
|
|
|
|
scroll_alignment_controls
|
|
|
|
|
]
|
2023-03-16 20:23:25 +01:00
|
|
|
.spacing(20);
|
2022-07-27 06:49:20 +02:00
|
|
|
|
2022-12-24 21:27:44 -08:00
|
|
|
let scroll_to_end_button = || {
|
2022-11-19 10:29:37 -08:00
|
|
|
button("Scroll to end")
|
|
|
|
|
.padding(10)
|
2022-12-24 21:27:44 -08:00
|
|
|
.on_press(Message::ScrollToEnd)
|
2022-11-19 10:29:37 -08:00
|
|
|
};
|
2022-07-27 06:49:20 +02:00
|
|
|
|
2022-12-24 21:27:44 -08:00
|
|
|
let scroll_to_beginning_button = || {
|
2022-11-19 10:29:37 -08:00
|
|
|
button("Scroll to beginning")
|
|
|
|
|
.padding(10)
|
2022-12-24 21:27:44 -08:00
|
|
|
.on_press(Message::ScrollToBeginning)
|
2022-11-19 10:29:37 -08:00
|
|
|
};
|
2022-07-27 06:49:20 +02:00
|
|
|
|
2022-11-19 10:29:37 -08:00
|
|
|
let scrollable_content: Element<Message> =
|
|
|
|
|
Element::from(match self.scrollable_direction {
|
2024-02-24 19:46:44 +01:00
|
|
|
Direction::Vertical => Scrollable::with_direction(
|
2022-07-27 06:49:20 +02:00
|
|
|
column![
|
2022-12-24 21:27:44 -08:00
|
|
|
scroll_to_end_button(),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("Beginning!"),
|
2024-02-15 02:08:22 +01:00
|
|
|
vertical_space().height(1200),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("Middle!"),
|
2024-02-15 02:08:22 +01:00
|
|
|
vertical_space().height(1200),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("End!"),
|
2022-12-24 21:27:44 -08:00
|
|
|
scroll_to_beginning_button(),
|
2022-07-27 06:49:20 +02:00
|
|
|
]
|
2022-11-19 10:29:37 -08:00
|
|
|
.align_items(Alignment::Center)
|
|
|
|
|
.padding([40, 0, 40, 0])
|
|
|
|
|
.spacing(40),
|
2024-02-24 19:46:44 +01:00
|
|
|
scrollable::Direction::Vertical(
|
|
|
|
|
Properties::new()
|
|
|
|
|
.width(self.scrollbar_width)
|
|
|
|
|
.margin(self.scrollbar_margin)
|
|
|
|
|
.scroller_width(self.scroller_width)
|
|
|
|
|
.alignment(self.alignment),
|
|
|
|
|
),
|
2022-11-19 10:29:37 -08:00
|
|
|
)
|
2024-01-05 17:24:43 +01:00
|
|
|
.width(Length::Fill)
|
2022-11-19 10:29:37 -08:00
|
|
|
.height(Length::Fill)
|
|
|
|
|
.id(SCROLLABLE_ID.clone())
|
|
|
|
|
.on_scroll(Message::Scrolled),
|
2024-02-24 19:46:44 +01:00
|
|
|
Direction::Horizontal => Scrollable::with_direction(
|
2022-11-19 10:29:37 -08:00
|
|
|
row![
|
2022-12-24 21:27:44 -08:00
|
|
|
scroll_to_end_button(),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("Beginning!"),
|
2024-02-15 02:08:22 +01:00
|
|
|
horizontal_space().width(1200),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("Middle!"),
|
2024-02-15 02:08:22 +01:00
|
|
|
horizontal_space().width(1200),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("End!"),
|
2022-12-24 21:27:44 -08:00
|
|
|
scroll_to_beginning_button(),
|
2022-11-19 10:29:37 -08:00
|
|
|
]
|
2023-02-04 12:24:13 +01:00
|
|
|
.height(450)
|
2022-11-19 10:29:37 -08:00
|
|
|
.align_items(Alignment::Center)
|
|
|
|
|
.padding([0, 40, 0, 40])
|
|
|
|
|
.spacing(40),
|
2024-02-24 19:46:44 +01:00
|
|
|
scrollable::Direction::Horizontal(
|
|
|
|
|
Properties::new()
|
|
|
|
|
.width(self.scrollbar_width)
|
|
|
|
|
.margin(self.scrollbar_margin)
|
|
|
|
|
.scroller_width(self.scroller_width)
|
|
|
|
|
.alignment(self.alignment),
|
|
|
|
|
),
|
2022-11-19 10:29:37 -08:00
|
|
|
)
|
2024-01-05 17:24:43 +01:00
|
|
|
.width(Length::Fill)
|
2022-11-19 10:29:37 -08:00
|
|
|
.height(Length::Fill)
|
|
|
|
|
.id(SCROLLABLE_ID.clone())
|
|
|
|
|
.on_scroll(Message::Scrolled),
|
2024-02-24 19:46:44 +01:00
|
|
|
Direction::Multi => Scrollable::with_direction(
|
2022-11-19 10:29:37 -08:00
|
|
|
//horizontal content
|
|
|
|
|
row![
|
|
|
|
|
column![
|
|
|
|
|
text("Let's do some scrolling!"),
|
2024-02-15 02:08:22 +01:00
|
|
|
vertical_space().height(2400)
|
2022-11-19 10:29:37 -08:00
|
|
|
],
|
2022-12-24 21:27:44 -08:00
|
|
|
scroll_to_end_button(),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("Horizontal - Beginning!"),
|
2024-02-15 02:08:22 +01:00
|
|
|
horizontal_space().width(1200),
|
2022-11-19 10:29:37 -08:00
|
|
|
//vertical content
|
|
|
|
|
column![
|
|
|
|
|
text("Horizontal - Middle!"),
|
2022-12-24 21:27:44 -08:00
|
|
|
scroll_to_end_button(),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("Vertical - Beginning!"),
|
2024-02-15 02:08:22 +01:00
|
|
|
vertical_space().height(1200),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("Vertical - Middle!"),
|
2024-02-15 02:08:22 +01:00
|
|
|
vertical_space().height(1200),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("Vertical - End!"),
|
2022-12-24 21:27:44 -08:00
|
|
|
scroll_to_beginning_button(),
|
2024-02-15 02:08:22 +01:00
|
|
|
vertical_space().height(40),
|
2022-11-19 10:29:37 -08:00
|
|
|
]
|
|
|
|
|
.spacing(40),
|
2024-02-15 02:08:22 +01:00
|
|
|
horizontal_space().width(1200),
|
2022-11-19 10:29:37 -08:00
|
|
|
text("Horizontal - End!"),
|
2022-12-24 21:27:44 -08:00
|
|
|
scroll_to_beginning_button(),
|
2022-11-19 10:29:37 -08:00
|
|
|
]
|
|
|
|
|
.align_items(Alignment::Center)
|
|
|
|
|
.padding([0, 40, 0, 40])
|
|
|
|
|
.spacing(40),
|
2024-02-24 19:46:44 +01:00
|
|
|
{
|
|
|
|
|
let properties = Properties::new()
|
|
|
|
|
.width(self.scrollbar_width)
|
|
|
|
|
.margin(self.scrollbar_margin)
|
|
|
|
|
.scroller_width(self.scroller_width)
|
|
|
|
|
.alignment(self.alignment);
|
|
|
|
|
|
|
|
|
|
scrollable::Direction::Both {
|
|
|
|
|
horizontal: properties,
|
|
|
|
|
vertical: properties,
|
|
|
|
|
}
|
|
|
|
|
},
|
2022-11-19 10:29:37 -08:00
|
|
|
)
|
2024-01-05 17:24:43 +01:00
|
|
|
.width(Length::Fill)
|
2022-11-19 10:29:37 -08:00
|
|
|
.height(Length::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)
|
2022-07-27 06:49:20 +02:00
|
|
|
.into()
|
2022-11-19 10:29:37 -08:00
|
|
|
}
|
|
|
|
|
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)
|
2022-11-19 10:29:37 -08:00
|
|
|
]
|
|
|
|
|
.spacing(10)
|
|
|
|
|
.into(),
|
|
|
|
|
};
|
2020-10-22 16:10:10 -05:00
|
|
|
|
2022-11-19 10:29:37 -08:00
|
|
|
let content: Element<Message> =
|
|
|
|
|
column![scroll_controls, scrollable_content, progress_bars]
|
|
|
|
|
.align_items(Alignment::Center)
|
|
|
|
|
.spacing(10)
|
|
|
|
|
.into();
|
|
|
|
|
|
2024-01-09 02:12:29 +01:00
|
|
|
container(content).padding(20).center_x().center_y().into()
|
2020-10-22 16:10:10 -05:00
|
|
|
}
|
2022-06-07 03:26:48 +02:00
|
|
|
|
2024-03-16 05:33:47 +01:00
|
|
|
fn theme(&self) -> Theme {
|
2022-11-19 10:29:37 -08:00
|
|
|
Theme::Dark
|
2022-06-07 03:26:48 +02:00
|
|
|
}
|
2020-10-22 16:10:10 -05:00
|
|
|
}
|
|
|
|
|
|
2024-03-16 15:53:03 +01:00
|
|
|
impl Default for ScrollableDemo {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self::new()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-23 19:42:01 +02:00
|
|
|
fn progress_bar_custom_style(theme: &Theme) -> progress_bar::Appearance {
|
|
|
|
|
progress_bar::Appearance {
|
|
|
|
|
background: theme.extended_palette().background.strong.color.into(),
|
|
|
|
|
bar: Color::from_rgb8(250, 85, 134).into(),
|
2024-03-05 22:13:36 +01:00
|
|
|
border: Border::default(),
|
2022-08-04 03:55:41 +02:00
|
|
|
}
|
2020-10-22 16:10:10 -05:00
|
|
|
}
|