summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-01-06 21:01:09 +0100
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-01-06 21:01:09 +0100
commitd0dc7cebf9c352f4d14827fe47489788f59e61a1 (patch)
tree17699c2225001ecf23e6730b3a3d3cbcca92ca10
parentf7dfd6537429f94af63d75617c27bc998d72d9c8 (diff)
downloadiced-d0dc7cebf9c352f4d14827fe47489788f59e61a1.tar.gz
iced-d0dc7cebf9c352f4d14827fe47489788f59e61a1.tar.bz2
iced-d0dc7cebf9c352f4d14827fe47489788f59e61a1.zip
Implement styling for `Scrollable`
-rw-r--r--examples/styling.rs63
-rw-r--r--native/src/renderer/null.rs3
-rw-r--r--native/src/widget/scrollable.rs24
-rw-r--r--src/native.rs14
-rw-r--r--style/src/lib.rs1
-rw-r--r--style/src/scrollable.rs76
-rw-r--r--wgpu/src/renderer/widget/scrollable.rs33
-rw-r--r--wgpu/src/widget.rs1
-rw-r--r--wgpu/src/widget/scrollable.rs13
9 files changed, 191 insertions, 37 deletions
diff --git a/examples/styling.rs b/examples/styling.rs
index c368ea07..61c8bcba 100644
--- a/examples/styling.rs
+++ b/examples/styling.rs
@@ -1,6 +1,6 @@
use iced::{
- button, text_input, Button, Column, Container, Element, Length, Radio, Row,
- Sandbox, Settings, Text, TextInput,
+ button, scrollable, text_input, Button, Column, Container, Element, Length,
+ Radio, Row, Sandbox, Scrollable, Settings, Text, TextInput,
};
pub fn main() {
@@ -10,6 +10,7 @@ pub fn main() {
#[derive(Default)]
struct Styling {
theme: style::Theme,
+ scroll: scrollable::State,
input: text_input::State,
input_value: String,
button: button::State,
@@ -76,10 +77,13 @@ impl Sandbox for Styling {
.push(choose_theme)
.push(Row::new().spacing(10).push(text_input).push(button));
- Container::new(content)
+ let scrollable = Scrollable::new(&mut self.scroll)
+ .style(self.theme)
+ .push(Container::new(content).width(Length::Fill).center_x());
+
+ Container::new(scrollable)
.width(Length::Fill)
.height(Length::Fill)
- .center_x()
.center_y()
.style(self.theme)
.into()
@@ -87,7 +91,7 @@ impl Sandbox for Styling {
}
mod style {
- use iced::{button, container, text_input};
+ use iced::{button, container, scrollable, text_input};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Theme {
@@ -132,6 +136,15 @@ mod style {
}
}
+ impl From<Theme> for Box<dyn scrollable::StyleSheet> {
+ fn from(theme: Theme) -> Self {
+ match theme {
+ Theme::Light => Default::default(),
+ Theme::Dark => dark::Scrollable.into(),
+ }
+ }
+ }
+
mod light {
use iced::{button, Background, Color, Vector};
@@ -161,7 +174,9 @@ mod style {
}
mod dark {
- use iced::{button, container, text_input, Background, Color};
+ use iced::{
+ button, container, scrollable, text_input, Background, Color,
+ };
pub struct Container;
@@ -239,6 +254,42 @@ mod style {
..self.active()
}
}
+
+ fn pressed(&self) -> button::Style {
+ button::Style {
+ border_width: 1,
+ border_color: Color::WHITE,
+ ..self.hovered()
+ }
+ }
+ }
+
+ pub struct Scrollable;
+
+ impl scrollable::StyleSheet for Scrollable {
+ fn active(&self) -> scrollable::Scrollbar {
+ scrollable::Scrollbar {
+ background: None,
+ border_radius: 2,
+ border_width: 0,
+ border_color: Color::TRANSPARENT,
+ scroller: scrollable::Scroller {
+ color: [1.0, 1.0, 1.0, 0.7].into(),
+ border_radius: 2,
+ border_width: 1,
+ border_color: Color::WHITE,
+ },
+ }
+ }
+
+ fn hovered(&self) -> scrollable::Scrollbar {
+ scrollable::Scrollbar {
+ background: Some(Background::Color(
+ [1.0, 1.0, 1.0, 0.3].into(),
+ )),
+ ..self.active()
+ }
+ }
}
}
}
diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs
index 96aa132c..0184ac00 100644
--- a/native/src/renderer/null.rs
+++ b/native/src/renderer/null.rs
@@ -73,6 +73,8 @@ impl text::Renderer for Null {
}
impl scrollable::Renderer for Null {
+ type Style = ();
+
fn scrollbar(
&self,
_bounds: Rectangle,
@@ -91,6 +93,7 @@ impl scrollable::Renderer for Null {
_is_mouse_over_scrollbar: bool,
_scrollbar: Option<scrollable::Scrollbar>,
_offset: u32,
+ _style: &Self::Style,
_content: Self::Output,
) {
}
diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs
index 9df09b14..a062abd0 100644
--- a/native/src/widget/scrollable.rs
+++ b/native/src/widget/scrollable.rs
@@ -11,14 +11,15 @@ use std::{f32, hash::Hash, u32};
/// A widget that can vertically display an infinite amount of content with a
/// scrollbar.
#[allow(missing_debug_implementations)]
-pub struct Scrollable<'a, Message, Renderer> {
+pub struct Scrollable<'a, Message, Renderer: self::Renderer> {
state: &'a mut State,
height: Length,
max_height: u32,
content: Column<'a, Message, Renderer>,
+ style: Renderer::Style,
}
-impl<'a, Message, Renderer> Scrollable<'a, Message, Renderer> {
+impl<'a, Message, Renderer: self::Renderer> Scrollable<'a, Message, Renderer> {
/// Creates a new [`Scrollable`] with the given [`State`].
///
/// [`Scrollable`]: struct.Scrollable.html
@@ -29,6 +30,7 @@ impl<'a, Message, Renderer> Scrollable<'a, Message, Renderer> {
height: Length::Shrink,
max_height: u32::MAX,
content: Column::new(),
+ style: Renderer::Style::default(),
}
}
@@ -90,6 +92,14 @@ impl<'a, Message, Renderer> Scrollable<'a, Message, Renderer> {
self
}
+ /// Sets the style of the [`Scrollable`] .
+ ///
+ /// [`Scrollable`]: struct.Scrollable.html
+ pub fn style(mut self, style: impl Into<Renderer::Style>) -> Self {
+ self.style = style.into();
+ self
+ }
+
/// Adds an element to the [`Scrollable`].
///
/// [`Scrollable`]: struct.Scrollable.html
@@ -105,7 +115,7 @@ impl<'a, Message, Renderer> Scrollable<'a, Message, Renderer> {
impl<'a, Message, Renderer> Widget<Message, Renderer>
for Scrollable<'a, Message, Renderer>
where
- Renderer: self::Renderer + column::Renderer,
+ Renderer: 'static + self::Renderer + column::Renderer,
{
fn width(&self) -> Length {
Length::Fill
@@ -295,12 +305,13 @@ where
is_mouse_over_scrollbar,
scrollbar,
offset,
+ &self.style,
content,
)
}
fn hash_layout(&self, state: &mut Hasher) {
- std::any::TypeId::of::<Scrollable<'static, (), ()>>().hash(state);
+ std::any::TypeId::of::<Scrollable<'static, (), Renderer>>().hash(state);
self.height.hash(state);
self.max_height.hash(state);
@@ -447,6 +458,8 @@ pub struct Scroller {
/// [`Scrollable`]: struct.Scrollable.html
/// [renderer]: ../../renderer/index.html
pub trait Renderer: crate::Renderer + Sized {
+ type Style: Default;
+
/// Returns the [`Scrollbar`] given the bounds and content bounds of a
/// [`Scrollable`].
///
@@ -483,6 +496,7 @@ pub trait Renderer: crate::Renderer + Sized {
is_mouse_over_scrollbar: bool,
scrollbar: Option<Scrollbar>,
offset: u32,
+ style: &Self::Style,
content: Self::Output,
) -> Self::Output;
}
@@ -490,7 +504,7 @@ pub trait Renderer: crate::Renderer + Sized {
impl<'a, Message, Renderer> From<Scrollable<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
- Renderer: 'a + self::Renderer + column::Renderer,
+ Renderer: 'static + self::Renderer + column::Renderer,
Message: 'static,
{
fn from(
diff --git a/src/native.rs b/src/native.rs
index 67f85c20..1061a730 100644
--- a/src/native.rs
+++ b/src/native.rs
@@ -24,20 +24,6 @@ pub mod widget {
//! [`text_input::State`]: text_input/struct.State.html
pub use iced_wgpu::widget::*;
- pub mod scrollable {
- //! Navigate an endless amount of content with a scrollbar.
-
- /// A widget that can vertically display an infinite amount of content
- /// with a scrollbar.
- ///
- /// This is an alias of an `iced_native` scrollable with a default
- /// `Renderer`.
- pub type Scrollable<'a, Message> =
- iced_winit::Scrollable<'a, Message, iced_wgpu::Renderer>;
-
- pub use iced_winit::scrollable::State;
- }
-
pub mod slider {
//! Display an interactive selector of a single value from a range of
//! values.
diff --git a/style/src/lib.rs b/style/src/lib.rs
index 1d7e57c4..fb90b2b5 100644
--- a/style/src/lib.rs
+++ b/style/src/lib.rs
@@ -1,3 +1,4 @@
pub mod button;
pub mod container;
+pub mod scrollable;
pub mod text_input;
diff --git a/style/src/scrollable.rs b/style/src/scrollable.rs
new file mode 100644
index 00000000..690c14a2
--- /dev/null
+++ b/style/src/scrollable.rs
@@ -0,0 +1,76 @@
+//! Navigate an endless amount of content with a scrollbar.
+use iced_core::{Background, Color};
+
+/// The appearance of a scrollable.
+#[derive(Debug, Clone, Copy)]
+pub struct Scrollbar {
+ pub background: Option<Background>,
+ pub border_radius: u16,
+ pub border_width: u16,
+ pub border_color: Color,
+ pub scroller: Scroller,
+}
+
+/// The appearance of the scroller of a scrollable.
+#[derive(Debug, Clone, Copy)]
+pub struct Scroller {
+ pub color: Color,
+ pub border_radius: u16,
+ pub border_width: u16,
+ pub border_color: Color,
+}
+
+/// A set of rules that dictate the style of a scrollable.
+pub trait StyleSheet {
+ /// Produces the style of an active scrollbar.
+ fn active(&self) -> Scrollbar;
+
+ /// Produces the style of an hovered scrollbar.
+ fn hovered(&self) -> Scrollbar;
+
+ /// Produces the style of a scrollbar that is being dragged.
+ fn dragging(&self) -> Scrollbar {
+ self.hovered()
+ }
+}
+
+struct Default;
+
+impl StyleSheet for Default {
+ fn active(&self) -> Scrollbar {
+ Scrollbar {
+ background: None,
+ border_radius: 5,
+ border_width: 0,
+ border_color: Color::TRANSPARENT,
+ scroller: Scroller {
+ color: [0.0, 0.0, 0.0, 0.7].into(),
+ border_radius: 5,
+ border_width: 0,
+ border_color: Color::TRANSPARENT,
+ },
+ }
+ }
+
+ fn hovered(&self) -> Scrollbar {
+ Scrollbar {
+ background: Some(Background::Color([0.0, 0.0, 0.0, 0.3].into())),
+ ..self.active()
+ }
+ }
+}
+
+impl std::default::Default for Box<dyn StyleSheet> {
+ fn default() -> Self {
+ Box::new(Default)
+ }
+}
+
+impl<T> From<T> for Box<dyn StyleSheet>
+where
+ T: 'static + StyleSheet,
+{
+ fn from(style: T) -> Self {
+ Box::new(style)
+ }
+}
diff --git a/wgpu/src/renderer/widget/scrollable.rs b/wgpu/src/renderer/widget/scrollable.rs
index 42a4a743..30d7f337 100644
--- a/wgpu/src/renderer/widget/scrollable.rs
+++ b/wgpu/src/renderer/widget/scrollable.rs
@@ -7,6 +7,8 @@ const SCROLLBAR_WIDTH: u16 = 10;
const SCROLLBAR_MARGIN: u16 = 2;
impl scrollable::Renderer for Renderer {
+ type Style = Box<dyn iced_style::scrollable::StyleSheet>;
+
fn scrollbar(
&self,
bounds: Rectangle,
@@ -53,6 +55,7 @@ impl scrollable::Renderer for Renderer {
is_mouse_over_scrollbar: bool,
scrollbar: Option<scrollable::Scrollbar>,
offset: u32,
+ style_sheet: &Self::Style,
(content, mouse_cursor): Self::Output,
) -> Self::Output {
let clip = Primitive::Clip {
@@ -64,17 +67,23 @@ impl scrollable::Renderer for Renderer {
(
if let Some(scrollbar) = scrollbar {
if is_mouse_over || state.is_scroller_grabbed() {
+ let style = if state.is_scroller_grabbed() {
+ style_sheet.dragging()
+ } else if is_mouse_over_scrollbar {
+ style_sheet.hovered()
+ } else {
+ style_sheet.active()
+ };
+
let scroller = Primitive::Quad {
bounds: scrollbar.scroller.bounds,
- background: Background::Color(
- [0.0, 0.0, 0.0, 0.7].into(),
- ),
- border_radius: 5,
- border_width: 0,
- border_color: Color::TRANSPARENT,
+ background: Background::Color(style.scroller.color),
+ border_radius: style.scroller.border_radius,
+ border_width: style.scroller.border_width,
+ border_color: style.scroller.border_color,
};
- if is_mouse_over_scrollbar || state.is_scroller_grabbed() {
+ if style.background.is_some() || style.border_width > 0 {
let scrollbar = Primitive::Quad {
bounds: Rectangle {
x: scrollbar.bounds.x
@@ -83,12 +92,12 @@ impl scrollable::Renderer for Renderer {
- f32::from(2 * SCROLLBAR_MARGIN),
..scrollbar.bounds
},
- background: Background::Color(
- [0.0, 0.0, 0.0, 0.3].into(),
+ background: style.background.unwrap_or(
+ Background::Color(Color::TRANSPARENT),
),
- border_radius: 5,
- border_width: 0,
- border_color: Color::TRANSPARENT,
+ border_radius: style.border_radius,
+ border_width: style.border_width,
+ border_color: style.border_color,
};
Primitive::Group {
diff --git a/wgpu/src/widget.rs b/wgpu/src/widget.rs
index 1d7e57c4..fb90b2b5 100644
--- a/wgpu/src/widget.rs
+++ b/wgpu/src/widget.rs
@@ -1,3 +1,4 @@
pub mod button;
pub mod container;
+pub mod scrollable;
pub mod text_input;
diff --git a/wgpu/src/widget/scrollable.rs b/wgpu/src/widget/scrollable.rs
new file mode 100644
index 00000000..1d236105
--- /dev/null
+++ b/wgpu/src/widget/scrollable.rs
@@ -0,0 +1,13 @@
+//! Navigate an endless amount of content with a scrollbar.
+use crate::Renderer;
+
+pub use iced_native::scrollable::State;
+pub use iced_style::scrollable::{Scrollbar, Scroller, StyleSheet};
+
+/// A widget that can vertically display an infinite amount of content
+/// with a scrollbar.
+///
+/// This is an alias of an `iced_native` scrollable with a default
+/// `Renderer`.
+pub type Scrollable<'a, Message> =
+ iced_native::Scrollable<'a, Message, Renderer>;