summaryrefslogtreecommitdiffstats
path: root/core/src/widget
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector0193@gmail.com>2019-11-03 05:19:12 +0100
committerLibravatar GitHub <noreply@github.com>2019-11-03 05:19:12 +0100
commit0ea911ae36bbde8c288f7ae1ba8a0049b696d7c4 (patch)
tree929cb493b674512520f1b6a92f86d7a09e5801f6 /core/src/widget
parentde3c87b9a793c0d0799948e16ad1b14e5b4892ba (diff)
parent022dc0139b7437f167a8d3ae483bf8e83f1dab04 (diff)
downloadiced-0ea911ae36bbde8c288f7ae1ba8a0049b696d7c4.tar.gz
iced-0ea911ae36bbde8c288f7ae1ba8a0049b696d7c4.tar.bz2
iced-0ea911ae36bbde8c288f7ae1ba8a0049b696d7c4.zip
Merge pull request #35 from hecrj/feature/scrollables
Scrollable widget
Diffstat (limited to 'core/src/widget')
-rw-r--r--core/src/widget/scrollable.rs151
1 files changed, 151 insertions, 0 deletions
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()
+ }
+}