diff options
Diffstat (limited to '')
-rw-r--r-- | core/src/widget.rs | 4 | ||||
-rw-r--r-- | core/src/widget/scrollable.rs | 151 |
2 files changed, 155 insertions, 0 deletions
diff --git a/core/src/widget.rs b/core/src/widget.rs index f9d4bf2a..3ee8e347 100644 --- a/core/src/widget.rs +++ b/core/src/widget.rs @@ -14,6 +14,7 @@ mod radio; mod row; pub mod button; +pub mod scrollable; pub mod slider; pub mod text; @@ -26,6 +27,9 @@ pub use slider::Slider; #[doc(no_inline)] pub use text::Text; +#[doc(no_inline)] +pub use scrollable::Scrollable; + pub use checkbox::Checkbox; pub use column::Column; pub use image::Image; diff --git a/core/src/widget/scrollable.rs b/core/src/widget/scrollable.rs new file mode 100644 index 00000000..31a5abed --- /dev/null +++ b/core/src/widget/scrollable.rs @@ -0,0 +1,151 @@ +use crate::{Align, Column, Length, Point, Rectangle}; + +#[derive(Debug)] +pub struct Scrollable<'a, Element> { + pub state: &'a mut State, + pub height: Length, + pub max_height: Length, + pub align_self: Option<Align>, + pub content: Column<Element>, +} + +impl<'a, Element> Scrollable<'a, Element> { + pub fn new(state: &'a mut State) -> Self { + Scrollable { + state, + height: Length::Shrink, + max_height: Length::Shrink, + align_self: None, + content: Column::new(), + } + } + + /// Sets the vertical spacing _between_ elements. + /// + /// Custom margins per element do not exist in Iced. You should use this + /// method instead! While less flexible, it helps you keep spacing between + /// elements consistent. + pub fn spacing(mut self, units: u16) -> Self { + self.content = self.content.spacing(units); + self + } + + /// Sets the padding of the [`Scrollable`]. + /// + /// [`Scrollable`]: struct.Scrollable.html + pub fn padding(mut self, units: u16) -> Self { + self.content = self.content.padding(units); + self + } + + /// Sets the width of the [`Scrollable`]. + /// + /// [`Scrollable`]: struct.Scrollable.html + pub fn width(mut self, width: Length) -> Self { + self.content = self.content.width(width); + self + } + + /// Sets the height of the [`Scrollable`]. + /// + /// [`Scrollable`]: struct.Scrollable.html + pub fn height(mut self, height: Length) -> Self { + self.height = height; + self + } + + /// Sets the maximum width of the [`Scrollable`]. + /// + /// [`Scrollable`]: struct.Scrollable.html + pub fn max_width(mut self, max_width: Length) -> Self { + self.content = self.content.max_width(max_width); + self + } + + /// Sets the maximum height of the [`Scrollable`] in pixels. + /// + /// [`Scrollable`]: struct.Scrollable.html + pub fn max_height(mut self, max_height: Length) -> Self { + self.max_height = max_height; + self + } + + /// Sets the alignment of the [`Scrollable`] itself. + /// + /// This is useful if you want to override the default alignment given by + /// the parent container. + /// + /// [`Scrollable`]: struct.Scrollable.html + pub fn align_self(mut self, align: Align) -> Self { + self.align_self = Some(align); + self + } + + /// Sets the horizontal alignment of the contents of the [`Scrollable`] . + /// + /// [`Scrollable`]: struct.Scrollable.html + pub fn align_items(mut self, align_items: Align) -> Self { + self.content = self.content.align_items(align_items); + self + } + + /// Adds an element to the [`Scrollable`]. + /// + /// [`Scrollable`]: struct.Scrollable.html + pub fn push<E>(mut self, child: E) -> Scrollable<'a, Element> + where + E: Into<Element>, + { + self.content = self.content.push(child); + self + } +} + +#[derive(Debug, Clone, Copy, Default)] +pub struct State { + pub scrollbar_grabbed_at: Option<Point>, + offset: u32, +} + +impl State { + pub fn new() -> Self { + State::default() + } + + pub fn scroll( + &mut self, + delta_y: f32, + bounds: Rectangle, + content_bounds: Rectangle, + ) { + if bounds.height >= content_bounds.height { + return; + } + + self.offset = (self.offset as i32 - delta_y.round() as i32) + .max(0) + .min((content_bounds.height - bounds.height) as i32) + as u32; + } + + pub fn scroll_to( + &mut self, + percentage: f32, + bounds: Rectangle, + content_bounds: Rectangle, + ) { + self.offset = ((content_bounds.height - bounds.height) * percentage) + .max(0.0) as u32; + } + + pub fn offset(&self, bounds: Rectangle, content_bounds: Rectangle) -> u32 { + let hidden_content = + (content_bounds.height - bounds.height).round() as u32; + + self.offset.min(hidden_content).max(0) + } + + pub fn is_scrollbar_grabbed(&self) -> bool { + self.scrollbar_grabbed_at.is_some() + } +} |