From d735209fc32238185ea0f27f1f4d1d0044b90e06 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 5 Mar 2024 21:23:14 +0100 Subject: Move style types of `slider` to `iced_widget` --- widget/src/helpers.rs | 7 ++- widget/src/slider.rs | 140 +++++++++++++++++++++++++++++++++++++----- widget/src/vertical_slider.rs | 18 +++--- 3 files changed, 136 insertions(+), 29 deletions(-) (limited to 'widget') diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 8f0dcd5c..c63a9706 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -20,7 +20,8 @@ use crate::text_editor::{self, TextEditor}; use crate::text_input::{self, TextInput}; use crate::toggler::{self, Toggler}; use crate::tooltip::{self, Tooltip}; -use crate::{Column, MouseArea, Row, Space, Themer, VerticalSlider}; +use crate::vertical_slider::{self, VerticalSlider}; +use crate::{Column, MouseArea, Row, Space, Themer}; use std::borrow::Borrow; use std::ops::RangeInclusive; @@ -240,7 +241,7 @@ pub fn slider<'a, T, Message, Theme>( where T: Copy + From + std::cmp::PartialOrd, Message: Clone, - Theme: slider::StyleSheet, + Theme: slider::Style, { Slider::new(range, value, on_change) } @@ -256,7 +257,7 @@ pub fn vertical_slider<'a, T, Message, Theme>( where T: Copy + From + std::cmp::PartialOrd, Message: Clone, - Theme: slider::StyleSheet, + Theme: vertical_slider::Style, { VerticalSlider::new(range, value, on_change) } diff --git a/widget/src/slider.rs b/widget/src/slider.rs index ce02a0a6..e4dc809e 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -1,6 +1,7 @@ //! Display an interactive selector of a single value from a range of values. //! //! A [`Slider`] has some local [`State`]. +use crate::core::border; use crate::core::event::{self, Event}; use crate::core::keyboard; use crate::core::keyboard::key::{self, Key}; @@ -10,16 +11,13 @@ use crate::core::renderer; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Border, Clipboard, Element, Layout, Length, Pixels, Point, Rectangle, - Shell, Size, Widget, + Border, Clipboard, Color, Element, Layout, Length, Pixels, Point, + Rectangle, Shell, Size, Widget, }; +use crate::style::Theme; use std::ops::RangeInclusive; -pub use iced_style::slider::{ - Appearance, Handle, HandleShape, Rail, Status, StyleSheet, -}; - /// An horizontal bar and a handle that selects a single value from a range of /// values. /// @@ -45,10 +43,7 @@ pub use iced_style::slider::{ /// /// ![Slider drawn by Coffee's renderer](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/slider.png?raw=true) #[allow(missing_debug_implementations)] -pub struct Slider<'a, T, Message, Theme = crate::Theme> -where - Theme: StyleSheet, -{ +pub struct Slider<'a, T, Message, Theme = crate::Theme> { range: RangeInclusive, step: T, shift_step: Option, @@ -65,7 +60,6 @@ impl<'a, T, Message, Theme> Slider<'a, T, Message, Theme> where T: Copy + From + PartialOrd, Message: Clone, - Theme: StyleSheet, { /// The default height of a [`Slider`]. pub const DEFAULT_HEIGHT: f32 = 22.0; @@ -80,6 +74,7 @@ where /// `Message`. pub fn new(range: RangeInclusive, value: T, on_change: F) -> Self where + Theme: Style, F: 'a + Fn(T) -> Message, { let value = if value >= *range.start() { @@ -104,7 +99,7 @@ where on_release: None, width: Length::Fill, height: Self::DEFAULT_HEIGHT, - style: Theme::default(), + style: Theme::style(), } } @@ -165,7 +160,6 @@ impl<'a, T, Message, Theme, Renderer> Widget where T: Copy + Into + num_traits::FromPrimitive, Message: Clone, - Theme: StyleSheet, Renderer: crate::core::Renderer, { fn tag(&self) -> tree::Tag { @@ -359,7 +353,7 @@ where let style = (self.style)( theme, if state.is_dragging { - Status::Dragging + Status::Dragged } else if is_mouse_over { Status::Hovered } else { @@ -468,7 +462,7 @@ impl<'a, T, Message, Theme, Renderer> From> where T: Copy + Into + num_traits::FromPrimitive + 'a, Message: Clone + 'a, - Theme: StyleSheet + 'a, + Theme: 'a, Renderer: crate::core::Renderer + 'a, { fn from( @@ -483,3 +477,119 @@ struct State { is_dragging: bool, keyboard_modifiers: keyboard::Modifiers, } + +/// The possible status of a [`Slider`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Status { + /// The [`Slider`] can be interacted with. + Active, + /// The [`Slider`] is being hovered. + Hovered, + /// The [`Slider`] is being dragged. + Dragged, +} + +/// The appearance of a slider. +#[derive(Debug, Clone, Copy)] +pub struct Appearance { + /// The colors of the rail of the slider. + pub rail: Rail, + /// The appearance of the [`Handle`] of the slider. + pub handle: Handle, +} + +impl Appearance { + /// Changes the [`HandleShape`] of the [`Appearance`] to a circle + /// with the given radius. + pub fn with_circular_handle(mut self, radius: impl Into) -> Self { + self.handle.shape = HandleShape::Circle { + radius: radius.into().0, + }; + self + } +} + +/// The appearance of a slider rail +#[derive(Debug, Clone, Copy)] +pub struct Rail { + /// The colors of the rail of the slider. + pub colors: (Color, Color), + /// The width of the stroke of a slider rail. + pub width: f32, + /// The border radius of the corners of the rail. + pub border_radius: border::Radius, +} + +/// The appearance of the handle of a slider. +#[derive(Debug, Clone, Copy)] +pub struct Handle { + /// The shape of the handle. + pub shape: HandleShape, + /// The [`Color`] of the handle. + pub color: Color, + /// The border width of the handle. + pub border_width: f32, + /// The border [`Color`] of the handle. + pub border_color: Color, +} + +/// The shape of the handle of a slider. +#[derive(Debug, Clone, Copy)] +pub enum HandleShape { + /// A circular handle. + Circle { + /// The radius of the circle. + radius: f32, + }, + /// A rectangular shape. + Rectangle { + /// The width of the rectangle. + width: u16, + /// The border radius of the corners of the rectangle. + border_radius: border::Radius, + }, +} + +/// The definiton of the default style of a [`TextInput`]. +pub trait Style { + /// Returns the default style of a [`TextInput`]. + fn style() -> fn(&Self, Status) -> Appearance; +} + +impl Style for Theme { + fn style() -> fn(&Self, Status) -> Appearance { + default + } +} + +/// The default style of a [`Slider`]. +pub fn default(theme: &Theme, status: Status) -> Appearance { + let palette = theme.extended_palette(); + + let handle = Handle { + shape: HandleShape::Rectangle { + width: 8, + border_radius: 4.0.into(), + }, + color: Color::WHITE, + border_color: Color::WHITE, + border_width: 1.0, + }; + + Appearance { + rail: Rail { + colors: (palette.primary.base.color, palette.secondary.base.color), + width: 4.0, + border_radius: 2.0.into(), + }, + handle: Handle { + color: match status { + Status::Active => palette.background.base.color, + Status::Hovered => palette.primary.weak.color, + Status::Dragged => palette.primary.base.color, + }, + border_color: palette.primary.base.color, + ..handle + }, + } +} diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index b6903001..b51aa2bf 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -3,8 +3,8 @@ //! A [`VerticalSlider`] has some local [`State`]. use std::ops::RangeInclusive; -pub use crate::style::slider::{ - Appearance, Handle, HandleShape, Status, StyleSheet, +pub use crate::slider::{ + default, Appearance, Handle, HandleShape, Status, Style, }; use crate::core; @@ -44,10 +44,7 @@ use crate::core::{ /// VerticalSlider::new(0.0..=100.0, value, Message::SliderChanged); /// ``` #[allow(missing_debug_implementations)] -pub struct VerticalSlider<'a, T, Message, Theme = crate::Theme> -where - Theme: StyleSheet, -{ +pub struct VerticalSlider<'a, T, Message, Theme = crate::Theme> { range: RangeInclusive, step: T, shift_step: Option, @@ -64,7 +61,6 @@ impl<'a, T, Message, Theme> VerticalSlider<'a, T, Message, Theme> where T: Copy + From + std::cmp::PartialOrd, Message: Clone, - Theme: StyleSheet, { /// The default width of a [`VerticalSlider`]. pub const DEFAULT_WIDTH: f32 = 22.0; @@ -79,6 +75,7 @@ where /// `Message`. pub fn new(range: RangeInclusive, value: T, on_change: F) -> Self where + Theme: Style, F: 'a + Fn(T) -> Message, { let value = if value >= *range.start() { @@ -103,7 +100,7 @@ where on_release: None, width: Self::DEFAULT_WIDTH, height: Length::Fill, - style: Theme::default(), + style: Theme::style(), } } @@ -167,7 +164,6 @@ impl<'a, T, Message, Theme, Renderer> Widget where T: Copy + Into + num_traits::FromPrimitive, Message: Clone, - Theme: StyleSheet, Renderer: core::Renderer, { fn tag(&self) -> tree::Tag { @@ -364,7 +360,7 @@ where let style = (self.style)( theme, if state.is_dragging { - Status::Dragging + Status::Dragged } else if is_mouse_over { Status::Hovered } else { @@ -474,7 +470,7 @@ impl<'a, T, Message, Theme, Renderer> where T: Copy + Into + num_traits::FromPrimitive + 'a, Message: Clone + 'a, - Theme: StyleSheet + 'a, + Theme: 'a, Renderer: core::Renderer + 'a, { fn from( -- cgit