Implement theme styling for Scrollable
This commit is contained in:
parent
ce53d3933c
commit
de21a651c0
11 changed files with 127 additions and 267 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
mod style;
|
use iced::button;
|
||||||
|
use iced::scrollable;
|
||||||
use iced::{
|
use iced::{
|
||||||
button, scrollable, Button, Column, Container, Element, Length,
|
Button, Column, Container, Element, Length, ProgressBar, Radio, Row, Rule,
|
||||||
ProgressBar, Radio, Row, Rule, Sandbox, Scrollable, Settings, Space, Text,
|
Sandbox, Scrollable, Settings, Space, Text, Theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
|
|
@ -10,13 +10,13 @@ pub fn main() -> iced::Result {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScrollableDemo {
|
struct ScrollableDemo {
|
||||||
theme: style::Theme,
|
theme: Theme,
|
||||||
variants: Vec<Variant>,
|
variants: Vec<Variant>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum Message {
|
enum Message {
|
||||||
ThemeChanged(style::Theme),
|
ThemeChanged(Theme),
|
||||||
ScrollToTop(usize),
|
ScrollToTop(usize),
|
||||||
ScrollToBottom(usize),
|
ScrollToBottom(usize),
|
||||||
Scrolled(usize, f32),
|
Scrolled(usize, f32),
|
||||||
|
|
@ -66,7 +66,7 @@ impl Sandbox for ScrollableDemo {
|
||||||
theme, variants, ..
|
theme, variants, ..
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let choose_theme = style::Theme::ALL.iter().fold(
|
let choose_theme = [Theme::Light, Theme::Dark].iter().fold(
|
||||||
Column::new().spacing(10).push(Text::new("Choose a theme:")),
|
Column::new().spacing(10).push(Text::new("Choose a theme:")),
|
||||||
|column, option| {
|
|column, option| {
|
||||||
column.push(Radio::new(
|
column.push(Radio::new(
|
||||||
|
|
@ -92,7 +92,6 @@ impl Sandbox for ScrollableDemo {
|
||||||
.on_scroll(move |offset| {
|
.on_scroll(move |offset| {
|
||||||
Message::Scrolled(i, offset)
|
Message::Scrolled(i, offset)
|
||||||
})
|
})
|
||||||
.style(*theme)
|
|
||||||
.push(Text::new(variant.title))
|
.push(Text::new(variant.title))
|
||||||
.push(
|
.push(
|
||||||
Button::new(
|
Button::new(
|
||||||
|
|
@ -157,12 +156,7 @@ impl Sandbox for ScrollableDemo {
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.spacing(10)
|
.spacing(10)
|
||||||
.push(
|
.push(scrollable)
|
||||||
Container::new(scrollable)
|
|
||||||
.width(Length::Fill)
|
|
||||||
.height(Length::Fill)
|
|
||||||
.style(*theme),
|
|
||||||
)
|
|
||||||
.push(ProgressBar::new(
|
.push(ProgressBar::new(
|
||||||
0.0..=1.0,
|
0.0..=1.0,
|
||||||
variant.latest_offset,
|
variant.latest_offset,
|
||||||
|
|
@ -187,9 +181,12 @@ impl Sandbox for ScrollableDemo {
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.center_x()
|
.center_x()
|
||||||
.center_y()
|
.center_y()
|
||||||
.style(self.theme)
|
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn theme(&self) -> Theme {
|
||||||
|
self.theme
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A version of a scrollable
|
/// A version of a scrollable
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use iced::{container, scrollable};
|
use iced::container;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Theme {
|
pub enum Theme {
|
||||||
|
|
@ -25,17 +25,8 @@ impl<'a> From<Theme> for Box<dyn container::StyleSheet + 'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<Theme> for Box<dyn scrollable::StyleSheet + 'a> {
|
|
||||||
fn from(theme: Theme) -> Self {
|
|
||||||
match theme {
|
|
||||||
Theme::Light => Default::default(),
|
|
||||||
Theme::Dark => dark::Scrollable.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod dark {
|
mod dark {
|
||||||
use iced::{container, scrollable, Color};
|
use iced::{container, Color};
|
||||||
|
|
||||||
const BACKGROUND: Color = Color::from_rgb(
|
const BACKGROUND: Color = Color::from_rgb(
|
||||||
0x36 as f32 / 255.0,
|
0x36 as f32 / 255.0,
|
||||||
|
|
@ -43,24 +34,6 @@ mod dark {
|
||||||
0x3F as f32 / 255.0,
|
0x3F as f32 / 255.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
const ACCENT: Color = Color::from_rgb(
|
|
||||||
0x6F as f32 / 255.0,
|
|
||||||
0xFF as f32 / 255.0,
|
|
||||||
0xE9 as f32 / 255.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
const SCROLLBAR: Color = Color::from_rgb(
|
|
||||||
0x2E as f32 / 255.0,
|
|
||||||
0x33 as f32 / 255.0,
|
|
||||||
0x38 as f32 / 255.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
const SCROLLER: Color = Color::from_rgb(
|
|
||||||
0x20 as f32 / 255.0,
|
|
||||||
0x22 as f32 / 255.0,
|
|
||||||
0x25 as f32 / 255.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
pub struct Container;
|
pub struct Container;
|
||||||
|
|
||||||
impl container::StyleSheet for Container {
|
impl container::StyleSheet for Container {
|
||||||
|
|
@ -76,52 +49,4 @@ mod dark {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Scrollable;
|
|
||||||
|
|
||||||
impl scrollable::StyleSheet for Scrollable {
|
|
||||||
fn active(&self) -> scrollable::Scrollbar {
|
|
||||||
scrollable::Scrollbar {
|
|
||||||
background: Color {
|
|
||||||
a: 0.8,
|
|
||||||
..SCROLLBAR
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
border_radius: 2.0,
|
|
||||||
border_width: 0.0,
|
|
||||||
border_color: Color::TRANSPARENT,
|
|
||||||
scroller: scrollable::Scroller {
|
|
||||||
color: Color { a: 0.7, ..SCROLLER },
|
|
||||||
border_radius: 2.0,
|
|
||||||
border_width: 0.0,
|
|
||||||
border_color: Color::TRANSPARENT,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hovered(&self) -> scrollable::Scrollbar {
|
|
||||||
let active = self.active();
|
|
||||||
|
|
||||||
scrollable::Scrollbar {
|
|
||||||
background: SCROLLBAR.into(),
|
|
||||||
scroller: scrollable::Scroller {
|
|
||||||
color: SCROLLER,
|
|
||||||
..active.scroller
|
|
||||||
},
|
|
||||||
..active
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dragging(&self) -> scrollable::Scrollbar {
|
|
||||||
let hovered = self.hovered();
|
|
||||||
|
|
||||||
scrollable::Scrollbar {
|
|
||||||
scroller: scrollable::Scroller {
|
|
||||||
color: ACCENT,
|
|
||||||
..hovered.scroller
|
|
||||||
},
|
|
||||||
..hovered
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ pub fn main() -> iced::Result {
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Styling {
|
struct Styling {
|
||||||
theme: style::Theme,
|
theme: Theme,
|
||||||
scroll: scrollable::State,
|
scroll: scrollable::State,
|
||||||
input: text_input::State,
|
input: text_input::State,
|
||||||
input_value: String,
|
input_value: String,
|
||||||
|
|
@ -27,7 +27,7 @@ struct Styling {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum Message {
|
enum Message {
|
||||||
ThemeChanged(style::Theme),
|
ThemeChanged(Theme),
|
||||||
InputChanged(String),
|
InputChanged(String),
|
||||||
ButtonPressed,
|
ButtonPressed,
|
||||||
SliderChanged(f32),
|
SliderChanged(f32),
|
||||||
|
|
@ -58,7 +58,7 @@ impl Sandbox for Styling {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&mut self) -> Element<Message> {
|
fn view(&mut self) -> Element<Message> {
|
||||||
let choose_theme = style::Theme::ALL.iter().fold(
|
let choose_theme = [Theme::Light, Theme::Dark].iter().fold(
|
||||||
Column::new().spacing(10).push(Text::new("Choose a theme:")),
|
Column::new().spacing(10).push(Text::new("Choose a theme:")),
|
||||||
|column, theme| {
|
|column, theme| {
|
||||||
column.push(Radio::new(
|
column.push(Radio::new(
|
||||||
|
|
@ -95,7 +95,6 @@ impl Sandbox for Styling {
|
||||||
let scrollable = Scrollable::new(&mut self.scroll)
|
let scrollable = Scrollable::new(&mut self.scroll)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Units(100))
|
.height(Length::Units(100))
|
||||||
.style(self.theme)
|
|
||||||
.push(Text::new("Scroll me!"))
|
.push(Text::new("Scroll me!"))
|
||||||
.push(Space::with_height(Length::Units(800)))
|
.push(Space::with_height(Length::Units(800)))
|
||||||
.push(Text::new("You did it!"));
|
.push(Text::new("You did it!"));
|
||||||
|
|
@ -148,104 +147,6 @@ impl Sandbox for Styling {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Theme {
|
fn theme(&self) -> Theme {
|
||||||
match self.theme {
|
self.theme
|
||||||
style::Theme::Light => Theme::Light,
|
|
||||||
style::Theme::Dark => Theme::Dark,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod style {
|
|
||||||
use iced::scrollable;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum Theme {
|
|
||||||
Light,
|
|
||||||
Dark,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Theme {
|
|
||||||
pub const ALL: [Theme; 2] = [Theme::Light, Theme::Dark];
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Theme {
|
|
||||||
fn default() -> Theme {
|
|
||||||
Theme::Light
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<Theme> for Box<dyn scrollable::StyleSheet + 'a> {
|
|
||||||
fn from(theme: Theme) -> Self {
|
|
||||||
match theme {
|
|
||||||
Theme::Light => Default::default(),
|
|
||||||
Theme::Dark => dark::Scrollable.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod dark {
|
|
||||||
use iced::{scrollable, Color};
|
|
||||||
|
|
||||||
const SURFACE: Color = Color::from_rgb(
|
|
||||||
0x40 as f32 / 255.0,
|
|
||||||
0x44 as f32 / 255.0,
|
|
||||||
0x4B as f32 / 255.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
const ACTIVE: Color = Color::from_rgb(
|
|
||||||
0x72 as f32 / 255.0,
|
|
||||||
0x89 as f32 / 255.0,
|
|
||||||
0xDA as f32 / 255.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
const HOVERED: Color = Color::from_rgb(
|
|
||||||
0x67 as f32 / 255.0,
|
|
||||||
0x7B as f32 / 255.0,
|
|
||||||
0xC4 as f32 / 255.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
pub struct Scrollable;
|
|
||||||
|
|
||||||
impl scrollable::StyleSheet for Scrollable {
|
|
||||||
fn active(&self) -> scrollable::Scrollbar {
|
|
||||||
scrollable::Scrollbar {
|
|
||||||
background: SURFACE.into(),
|
|
||||||
border_radius: 2.0,
|
|
||||||
border_width: 0.0,
|
|
||||||
border_color: Color::TRANSPARENT,
|
|
||||||
scroller: scrollable::Scroller {
|
|
||||||
color: ACTIVE,
|
|
||||||
border_radius: 2.0,
|
|
||||||
border_width: 0.0,
|
|
||||||
border_color: Color::TRANSPARENT,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hovered(&self) -> scrollable::Scrollbar {
|
|
||||||
let active = self.active();
|
|
||||||
|
|
||||||
scrollable::Scrollbar {
|
|
||||||
background: Color { a: 0.5, ..SURFACE }.into(),
|
|
||||||
scroller: scrollable::Scroller {
|
|
||||||
color: HOVERED,
|
|
||||||
..active.scroller
|
|
||||||
},
|
|
||||||
..active
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dragging(&self) -> scrollable::Scrollbar {
|
|
||||||
let hovered = self.hovered();
|
|
||||||
|
|
||||||
scrollable::Scrollbar {
|
|
||||||
scroller: scrollable::Scroller {
|
|
||||||
color: Color::from_rgb(0.85, 0.85, 0.85),
|
|
||||||
..hovered.scroller
|
|
||||||
},
|
|
||||||
..hovered
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ impl<'a, T, Renderer> Menu<'a, T, Renderer>
|
||||||
where
|
where
|
||||||
T: ToString + Clone,
|
T: ToString + Clone,
|
||||||
Renderer: text::Renderer + 'a,
|
Renderer: text::Renderer + 'a,
|
||||||
|
Renderer::Theme: scrollable::StyleSheet,
|
||||||
{
|
{
|
||||||
/// Creates a new [`Menu`] with the given [`State`], a list of options, and
|
/// Creates a new [`Menu`] with the given [`State`], a list of options, and
|
||||||
/// the message to produced when an option is selected.
|
/// the message to produced when an option is selected.
|
||||||
|
|
@ -117,17 +118,19 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Overlay<'a, Message, Renderer: text::Renderer> {
|
struct Overlay<'a, Message, Renderer> {
|
||||||
container: Container<'a, Message, Renderer>,
|
container: Container<'a, Message, Renderer>,
|
||||||
width: u16,
|
width: u16,
|
||||||
target_height: f32,
|
target_height: f32,
|
||||||
style: Style,
|
style: Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message, Renderer: text::Renderer> Overlay<'a, Message, Renderer>
|
impl<'a, Message, Renderer> Overlay<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
Message: 'a,
|
Message: 'a,
|
||||||
Renderer: 'a,
|
Renderer: 'a,
|
||||||
|
Renderer: text::Renderer,
|
||||||
|
Renderer::Theme: scrollable::StyleSheet,
|
||||||
{
|
{
|
||||||
pub fn new<T>(menu: Menu<'a, T, Renderer>, target_height: f32) -> Self
|
pub fn new<T>(menu: Menu<'a, T, Renderer>, target_height: f32) -> Self
|
||||||
where
|
where
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use crate::overlay::menu::{self, Menu};
|
||||||
use crate::renderer;
|
use crate::renderer;
|
||||||
use crate::text::{self, Text};
|
use crate::text::{self, Text};
|
||||||
use crate::touch;
|
use crate::touch;
|
||||||
|
use crate::widget::scrollable;
|
||||||
use crate::{
|
use crate::{
|
||||||
Clipboard, Element, Layout, Length, Padding, Point, Rectangle, Shell, Size,
|
Clipboard, Element, Layout, Length, Padding, Point, Rectangle, Shell, Size,
|
||||||
Widget,
|
Widget,
|
||||||
|
|
@ -322,6 +323,7 @@ pub fn overlay<'a, T, Message, Renderer>(
|
||||||
where
|
where
|
||||||
Message: 'a,
|
Message: 'a,
|
||||||
Renderer: text::Renderer + 'a,
|
Renderer: text::Renderer + 'a,
|
||||||
|
Renderer::Theme: scrollable::StyleSheet,
|
||||||
T: Clone + ToString,
|
T: Clone + ToString,
|
||||||
{
|
{
|
||||||
if state.is_open {
|
if state.is_open {
|
||||||
|
|
@ -430,6 +432,7 @@ where
|
||||||
[T]: ToOwned<Owned = Vec<T>>,
|
[T]: ToOwned<Owned = Vec<T>>,
|
||||||
Message: 'static,
|
Message: 'static,
|
||||||
Renderer: text::Renderer + 'a,
|
Renderer: text::Renderer + 'a,
|
||||||
|
Renderer::Theme: scrollable::StyleSheet,
|
||||||
{
|
{
|
||||||
fn width(&self) -> Length {
|
fn width(&self) -> Length {
|
||||||
self.width
|
self.width
|
||||||
|
|
@ -490,7 +493,7 @@ where
|
||||||
fn draw(
|
fn draw(
|
||||||
&self,
|
&self,
|
||||||
renderer: &mut Renderer,
|
renderer: &mut Renderer,
|
||||||
theme: &Renderer::Theme,
|
_theme: &Renderer::Theme,
|
||||||
_style: &renderer::Style,
|
_style: &renderer::Style,
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
|
|
@ -531,8 +534,9 @@ impl<'a, T: 'a, Message, Renderer> Into<Element<'a, Message, Renderer>>
|
||||||
where
|
where
|
||||||
T: Clone + ToString + Eq,
|
T: Clone + ToString + Eq,
|
||||||
[T]: ToOwned<Owned = Vec<T>>,
|
[T]: ToOwned<Owned = Vec<T>>,
|
||||||
Renderer: text::Renderer + 'a,
|
|
||||||
Message: 'static,
|
Message: 'static,
|
||||||
|
Renderer: text::Renderer + 'a,
|
||||||
|
Renderer::Theme: scrollable::StyleSheet,
|
||||||
{
|
{
|
||||||
fn into(self) -> Element<'a, Message, Renderer> {
|
fn into(self) -> Element<'a, Message, Renderer> {
|
||||||
Element::new(self)
|
Element::new(self)
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,11 @@ pub mod style {
|
||||||
/// A widget that can vertically display an infinite amount of content with a
|
/// A widget that can vertically display an infinite amount of content with a
|
||||||
/// scrollbar.
|
/// scrollbar.
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Scrollable<'a, Message, Renderer> {
|
pub struct Scrollable<'a, Message, Renderer>
|
||||||
|
where
|
||||||
|
Renderer: crate::Renderer,
|
||||||
|
Renderer::Theme: StyleSheet,
|
||||||
|
{
|
||||||
state: &'a mut State,
|
state: &'a mut State,
|
||||||
height: Length,
|
height: Length,
|
||||||
max_height: u32,
|
max_height: u32,
|
||||||
|
|
@ -34,10 +38,14 @@ pub struct Scrollable<'a, Message, Renderer> {
|
||||||
scroller_width: u16,
|
scroller_width: u16,
|
||||||
content: Column<'a, Message, Renderer>,
|
content: Column<'a, Message, Renderer>,
|
||||||
on_scroll: Option<Box<dyn Fn(f32) -> Message + 'a>>,
|
on_scroll: Option<Box<dyn Fn(f32) -> Message + 'a>>,
|
||||||
style_sheet: Box<dyn StyleSheet + 'a>,
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> {
|
impl<'a, Message, Renderer> Scrollable<'a, Message, Renderer>
|
||||||
|
where
|
||||||
|
Renderer: crate::Renderer,
|
||||||
|
Renderer::Theme: StyleSheet,
|
||||||
|
{
|
||||||
/// Creates a new [`Scrollable`] with the given [`State`].
|
/// Creates a new [`Scrollable`] with the given [`State`].
|
||||||
pub fn new(state: &'a mut State) -> Self {
|
pub fn new(state: &'a mut State) -> Self {
|
||||||
Scrollable {
|
Scrollable {
|
||||||
|
|
@ -49,7 +57,7 @@ impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> {
|
||||||
scroller_width: 10,
|
scroller_width: 10,
|
||||||
content: Column::new(),
|
content: Column::new(),
|
||||||
on_scroll: None,
|
on_scroll: None,
|
||||||
style_sheet: Default::default(),
|
style: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,9 +140,9 @@ impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> {
|
||||||
/// Sets the style of the [`Scrollable`] .
|
/// Sets the style of the [`Scrollable`] .
|
||||||
pub fn style(
|
pub fn style(
|
||||||
mut self,
|
mut self,
|
||||||
style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
|
style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.style_sheet = style_sheet.into();
|
self.style = style.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -428,15 +436,17 @@ pub fn mouse_interaction(
|
||||||
pub fn draw<Renderer>(
|
pub fn draw<Renderer>(
|
||||||
state: &State,
|
state: &State,
|
||||||
renderer: &mut Renderer,
|
renderer: &mut Renderer,
|
||||||
|
theme: &Renderer::Theme,
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
scrollbar_width: u16,
|
scrollbar_width: u16,
|
||||||
scrollbar_margin: u16,
|
scrollbar_margin: u16,
|
||||||
scroller_width: u16,
|
scroller_width: u16,
|
||||||
style_sheet: &dyn StyleSheet,
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
draw_content: impl FnOnce(&mut Renderer, Layout<'_>, Point, &Rectangle),
|
draw_content: impl FnOnce(&mut Renderer, Layout<'_>, Point, &Rectangle),
|
||||||
) where
|
) where
|
||||||
Renderer: crate::Renderer,
|
Renderer: crate::Renderer,
|
||||||
|
Renderer::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
let bounds = layout.bounds();
|
let bounds = layout.bounds();
|
||||||
let content_layout = layout.children().next().unwrap();
|
let content_layout = layout.children().next().unwrap();
|
||||||
|
|
@ -482,11 +492,11 @@ pub fn draw<Renderer>(
|
||||||
});
|
});
|
||||||
|
|
||||||
let style = if state.is_scroller_grabbed() {
|
let style = if state.is_scroller_grabbed() {
|
||||||
style_sheet.dragging()
|
theme.dragging(style)
|
||||||
} else if is_mouse_over_scrollbar {
|
} else if is_mouse_over_scrollbar {
|
||||||
style_sheet.hovered()
|
theme.hovered(style)
|
||||||
} else {
|
} else {
|
||||||
style_sheet.active()
|
theme.active(style)
|
||||||
};
|
};
|
||||||
|
|
||||||
let is_scrollbar_visible =
|
let is_scrollbar_visible =
|
||||||
|
|
@ -618,6 +628,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
|
||||||
for Scrollable<'a, Message, Renderer>
|
for Scrollable<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: crate::Renderer,
|
Renderer: crate::Renderer,
|
||||||
|
Renderer::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
fn width(&self) -> Length {
|
fn width(&self) -> Length {
|
||||||
Widget::<Message, Renderer>::width(&self.content)
|
Widget::<Message, Renderer>::width(&self.content)
|
||||||
|
|
@ -711,12 +722,13 @@ where
|
||||||
draw(
|
draw(
|
||||||
&self.state,
|
&self.state,
|
||||||
renderer,
|
renderer,
|
||||||
|
theme,
|
||||||
layout,
|
layout,
|
||||||
cursor_position,
|
cursor_position,
|
||||||
self.scrollbar_width,
|
self.scrollbar_width,
|
||||||
self.scrollbar_margin,
|
self.scrollbar_margin,
|
||||||
self.scroller_width,
|
self.scroller_width,
|
||||||
self.style_sheet.as_ref(),
|
self.style,
|
||||||
|renderer, layout, cursor_position, viewport| {
|
|renderer, layout, cursor_position, viewport| {
|
||||||
self.content.draw(
|
self.content.draw(
|
||||||
renderer,
|
renderer,
|
||||||
|
|
@ -916,8 +928,9 @@ struct Scroller {
|
||||||
impl<'a, Message, Renderer> From<Scrollable<'a, Message, Renderer>>
|
impl<'a, Message, Renderer> From<Scrollable<'a, Message, Renderer>>
|
||||||
for Element<'a, Message, Renderer>
|
for Element<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: 'a + crate::Renderer,
|
|
||||||
Message: 'a,
|
Message: 'a,
|
||||||
|
Renderer: 'a + crate::Renderer,
|
||||||
|
Renderer::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
fn from(
|
fn from(
|
||||||
scrollable: Scrollable<'a, Message, Renderer>,
|
scrollable: Scrollable<'a, Message, Renderer>,
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ pub fn scrollable<'a, Message, Renderer>(
|
||||||
) -> widget::Scrollable<'a, Message, Renderer>
|
) -> widget::Scrollable<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: iced_native::Renderer,
|
Renderer: iced_native::Renderer,
|
||||||
|
Renderer::Theme: widget::scrollable::StyleSheet,
|
||||||
{
|
{
|
||||||
widget::Scrollable::new(content)
|
widget::Scrollable::new(content)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
//! Display a dropdown list of selectable values.
|
//! Display a dropdown list of selectable values.
|
||||||
|
use crate::widget::scrollable;
|
||||||
use crate::widget::tree::{self, Tree};
|
use crate::widget::tree::{self, Tree};
|
||||||
use crate::{Element, Widget};
|
use crate::{Element, Widget};
|
||||||
|
|
||||||
|
|
@ -110,6 +111,7 @@ where
|
||||||
[T]: ToOwned<Owned = Vec<T>>,
|
[T]: ToOwned<Owned = Vec<T>>,
|
||||||
Message: 'a,
|
Message: 'a,
|
||||||
Renderer: text::Renderer + 'a,
|
Renderer: text::Renderer + 'a,
|
||||||
|
Renderer::Theme: scrollable::StyleSheet,
|
||||||
{
|
{
|
||||||
fn tag(&self) -> tree::Tag {
|
fn tag(&self) -> tree::Tag {
|
||||||
tree::Tag::of::<pick_list::State<T>>()
|
tree::Tag::of::<pick_list::State<T>>()
|
||||||
|
|
@ -225,8 +227,9 @@ impl<'a, T: 'a, Message, Renderer> Into<Element<'a, Message, Renderer>>
|
||||||
where
|
where
|
||||||
T: Clone + ToString + Eq + 'static,
|
T: Clone + ToString + Eq + 'static,
|
||||||
[T]: ToOwned<Owned = Vec<T>>,
|
[T]: ToOwned<Owned = Vec<T>>,
|
||||||
Renderer: text::Renderer + 'a,
|
|
||||||
Message: 'a,
|
Message: 'a,
|
||||||
|
Renderer: text::Renderer + 'a,
|
||||||
|
Renderer::Theme: scrollable::StyleSheet,
|
||||||
{
|
{
|
||||||
fn into(self) -> Element<'a, Message, Renderer> {
|
fn into(self) -> Element<'a, Message, Renderer> {
|
||||||
Element::new(self)
|
Element::new(self)
|
||||||
|
|
|
||||||
|
|
@ -15,18 +15,24 @@ pub use iced_style::scrollable::{Scrollbar, Scroller, StyleSheet};
|
||||||
/// A widget that can vertically display an infinite amount of content with a
|
/// A widget that can vertically display an infinite amount of content with a
|
||||||
/// scrollbar.
|
/// scrollbar.
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Scrollable<'a, Message, Renderer> {
|
pub struct Scrollable<'a, Message, Renderer>
|
||||||
|
where
|
||||||
|
Renderer: iced_native::Renderer,
|
||||||
|
Renderer::Theme: StyleSheet,
|
||||||
|
{
|
||||||
height: Length,
|
height: Length,
|
||||||
scrollbar_width: u16,
|
scrollbar_width: u16,
|
||||||
scrollbar_margin: u16,
|
scrollbar_margin: u16,
|
||||||
scroller_width: u16,
|
scroller_width: u16,
|
||||||
on_scroll: Option<Box<dyn Fn(f32) -> Message + 'a>>,
|
|
||||||
style_sheet: Box<dyn StyleSheet + 'a>,
|
|
||||||
content: Element<'a, Message, Renderer>,
|
content: Element<'a, Message, Renderer>,
|
||||||
|
on_scroll: Option<Box<dyn Fn(f32) -> Message + 'a>>,
|
||||||
|
style: <Renderer::Theme as StyleSheet>::Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message, Renderer: iced_native::Renderer>
|
impl<'a, Message, Renderer> Scrollable<'a, Message, Renderer>
|
||||||
Scrollable<'a, Message, Renderer>
|
where
|
||||||
|
Renderer: iced_native::Renderer,
|
||||||
|
Renderer::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
/// Creates a new [`Scrollable`].
|
/// Creates a new [`Scrollable`].
|
||||||
pub fn new(content: impl Into<Element<'a, Message, Renderer>>) -> Self {
|
pub fn new(content: impl Into<Element<'a, Message, Renderer>>) -> Self {
|
||||||
|
|
@ -35,9 +41,9 @@ impl<'a, Message, Renderer: iced_native::Renderer>
|
||||||
scrollbar_width: 10,
|
scrollbar_width: 10,
|
||||||
scrollbar_margin: 0,
|
scrollbar_margin: 0,
|
||||||
scroller_width: 10,
|
scroller_width: 10,
|
||||||
on_scroll: None,
|
|
||||||
style_sheet: Default::default(),
|
|
||||||
content: content.into(),
|
content: content.into(),
|
||||||
|
on_scroll: None,
|
||||||
|
style: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,9 +86,9 @@ impl<'a, Message, Renderer: iced_native::Renderer>
|
||||||
/// Sets the style of the [`Scrollable`] .
|
/// Sets the style of the [`Scrollable`] .
|
||||||
pub fn style(
|
pub fn style(
|
||||||
mut self,
|
mut self,
|
||||||
style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
|
style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.style_sheet = style_sheet.into();
|
self.style = style.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -91,6 +97,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
|
||||||
for Scrollable<'a, Message, Renderer>
|
for Scrollable<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: iced_native::Renderer,
|
Renderer: iced_native::Renderer,
|
||||||
|
Renderer::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
fn tag(&self) -> tree::Tag {
|
fn tag(&self) -> tree::Tag {
|
||||||
tree::Tag::of::<scrollable::State>()
|
tree::Tag::of::<scrollable::State>()
|
||||||
|
|
@ -180,12 +187,13 @@ where
|
||||||
scrollable::draw(
|
scrollable::draw(
|
||||||
tree.state.downcast_ref::<scrollable::State>(),
|
tree.state.downcast_ref::<scrollable::State>(),
|
||||||
renderer,
|
renderer,
|
||||||
|
theme,
|
||||||
layout,
|
layout,
|
||||||
cursor_position,
|
cursor_position,
|
||||||
self.scrollbar_width,
|
self.scrollbar_width,
|
||||||
self.scrollbar_margin,
|
self.scrollbar_margin,
|
||||||
self.scroller_width,
|
self.scroller_width,
|
||||||
self.style_sheet.as_ref(),
|
self.style,
|
||||||
|renderer, layout, cursor_position, viewport| {
|
|renderer, layout, cursor_position, viewport| {
|
||||||
self.content.as_widget().draw(
|
self.content.as_widget().draw(
|
||||||
&tree.children[0],
|
&tree.children[0],
|
||||||
|
|
@ -259,6 +267,7 @@ impl<'a, Message, Renderer> From<Scrollable<'a, Message, Renderer>>
|
||||||
where
|
where
|
||||||
Message: 'a + Clone,
|
Message: 'a + Clone,
|
||||||
Renderer: 'a + iced_native::Renderer,
|
Renderer: 'a + iced_native::Renderer,
|
||||||
|
Renderer::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
fn from(
|
fn from(
|
||||||
text_input: Scrollable<'a, Message, Renderer>,
|
text_input: Scrollable<'a, Message, Renderer>,
|
||||||
|
|
|
||||||
|
|
@ -22,55 +22,16 @@ pub struct Scroller {
|
||||||
|
|
||||||
/// A set of rules that dictate the style of a scrollable.
|
/// A set of rules that dictate the style of a scrollable.
|
||||||
pub trait StyleSheet {
|
pub trait StyleSheet {
|
||||||
|
type Style: Default + Copy;
|
||||||
|
|
||||||
/// Produces the style of an active scrollbar.
|
/// Produces the style of an active scrollbar.
|
||||||
fn active(&self) -> Scrollbar;
|
fn active(&self, style: Self::Style) -> Scrollbar;
|
||||||
|
|
||||||
/// Produces the style of an hovered scrollbar.
|
/// Produces the style of an hovered scrollbar.
|
||||||
fn hovered(&self) -> Scrollbar;
|
fn hovered(&self, style: Self::Style) -> Scrollbar;
|
||||||
|
|
||||||
/// Produces the style of a scrollbar that is being dragged.
|
/// Produces the style of a scrollbar that is being dragged.
|
||||||
fn dragging(&self) -> Scrollbar {
|
fn dragging(&self, style: Self::Style) -> Scrollbar {
|
||||||
self.hovered()
|
self.hovered(style)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Default;
|
|
||||||
|
|
||||||
impl StyleSheet for Default {
|
|
||||||
fn active(&self) -> Scrollbar {
|
|
||||||
Scrollbar {
|
|
||||||
background: None,
|
|
||||||
border_radius: 5.0,
|
|
||||||
border_width: 0.0,
|
|
||||||
border_color: Color::TRANSPARENT,
|
|
||||||
scroller: Scroller {
|
|
||||||
color: [0.0, 0.0, 0.0, 0.7].into(),
|
|
||||||
border_radius: 5.0,
|
|
||||||
border_width: 0.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<'a> std::default::Default for Box<dyn StyleSheet + 'a> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Box::new(Default)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> From<T> for Box<dyn StyleSheet + 'a>
|
|
||||||
where
|
|
||||||
T: StyleSheet + 'a,
|
|
||||||
{
|
|
||||||
fn from(style_sheet: T) -> Self {
|
|
||||||
Box::new(style_sheet)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use crate::pane_grid;
|
||||||
use crate::progress_bar;
|
use crate::progress_bar;
|
||||||
use crate::radio;
|
use crate::radio;
|
||||||
use crate::rule;
|
use crate::rule;
|
||||||
|
use crate::scrollable;
|
||||||
use crate::slider;
|
use crate::slider;
|
||||||
use crate::text_input;
|
use crate::text_input;
|
||||||
use crate::toggler;
|
use crate::toggler;
|
||||||
|
|
@ -458,6 +459,48 @@ impl rule::StyleSheet for Theme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scrollable
|
||||||
|
*/
|
||||||
|
|
||||||
|
impl scrollable::StyleSheet for Theme {
|
||||||
|
type Style = ();
|
||||||
|
|
||||||
|
fn active(&self, _style: Self::Style) -> scrollable::Scrollbar {
|
||||||
|
let palette = self.extended_palette();
|
||||||
|
|
||||||
|
scrollable::Scrollbar {
|
||||||
|
background: palette.background.weak.color.into(),
|
||||||
|
border_radius: 2.0,
|
||||||
|
border_width: 0.0,
|
||||||
|
border_color: Color::TRANSPARENT,
|
||||||
|
scroller: scrollable::Scroller {
|
||||||
|
color: palette.background.strong.color.into(),
|
||||||
|
border_radius: 2.0,
|
||||||
|
border_width: 0.0,
|
||||||
|
border_color: Color::TRANSPARENT,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hovered(&self, _style: Self::Style) -> scrollable::Scrollbar {
|
||||||
|
let palette = self.extended_palette();
|
||||||
|
|
||||||
|
scrollable::Scrollbar {
|
||||||
|
background: palette.background.weak.color.into(),
|
||||||
|
border_radius: 2.0,
|
||||||
|
border_width: 0.0,
|
||||||
|
border_color: Color::TRANSPARENT,
|
||||||
|
scroller: scrollable::Scroller {
|
||||||
|
color: palette.primary.strong.color.into(),
|
||||||
|
border_radius: 2.0,
|
||||||
|
border_width: 0.0,
|
||||||
|
border_color: Color::TRANSPARENT,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Text Input
|
* Text Input
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue