use crate::{
Offset,
style::{default_colors, text_marks, tick_marks},
};
use iced_core::{Color, Rectangle, image::Handle};
#[derive(Debug, Clone)]
pub enum Appearance {
Texture(TextureAppearance),
Classic(ClassicAppearance),
Rect(RectAppearance),
RectBipolar(RectBipolarAppearance),
}
#[derive(Debug, Clone)]
pub struct ClassicRail {
pub rail_colors: (Color, Color),
pub rail_widths: (f32, f32),
pub rail_padding: f32,
}
#[derive(Debug, Clone)]
pub struct TextureAppearance {
pub rail: ClassicRail,
pub image_handle: Handle,
pub handle_width: u16,
pub image_bounds: Rectangle,
}
#[derive(Debug, Clone)]
pub struct ClassicAppearance {
pub rail: ClassicRail,
pub handle: ClassicHandle,
}
impl Default for ClassicAppearance {
fn default() -> Self {
ClassicAppearance {
rail: ClassicRail {
rail_colors: default_colors::SLIDER_RAIL,
rail_widths: (1.0, 1.0),
rail_padding: 12.0,
},
handle: ClassicHandle::default(),
}
}
}
#[derive(Debug, Clone)]
pub struct ClassicHandle {
pub color: Color,
pub width: u16,
pub notch_width: f32,
pub notch_color: Color,
pub border_radius: f32,
pub border_width: f32,
pub border_color: Color,
}
impl Default for ClassicHandle {
fn default() -> Self {
ClassicHandle {
color: default_colors::LIGHT_BACK,
width: 34,
notch_width: 4.0,
notch_color: default_colors::BORDER,
border_radius: 2.0,
border_color: default_colors::BORDER,
border_width: 1.0,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct RectAppearance {
pub back_color: Color,
pub back_border_width: f32,
pub back_border_radius: f32,
pub back_border_color: Color,
pub filled_color: Color,
pub handle_color: Color,
pub handle_width: u16,
pub handle_filled_gap: f32,
}
#[derive(Debug, Clone, Copy)]
pub struct RectBipolarAppearance {
pub back_color: Color,
pub back_border_width: f32,
pub back_border_radius: f32,
pub back_border_color: Color,
pub left_filled_color: Color,
pub right_filled_color: Color,
pub handle_left_color: Color,
pub handle_right_color: Color,
pub handle_center_color: Color,
pub handle_width: u16,
pub handle_filled_gap: f32,
}
#[derive(Debug, Clone)]
pub enum ModRangePlacement {
Center {
height: f32,
offset: f32,
},
CenterFilled {
edge_padding: f32,
},
Top {
height: f32,
offset: f32,
},
Bottom {
height: f32,
offset: f32,
},
}
#[derive(Debug, Clone)]
pub struct ModRangeAppearance {
pub placement: ModRangePlacement,
pub back_border_width: f32,
pub back_border_radius: f32,
pub back_border_color: Color,
pub back_color: Option<Color>,
pub filled_color: Color,
pub filled_inverse_color: Color,
}
#[derive(Debug, Clone)]
pub struct TickMarksAppearance {
pub style: tick_marks::Appearance,
pub placement: tick_marks::Placement,
}
#[derive(Debug, Clone)]
pub struct TextMarksAppearance {
pub style: text_marks::Appearance,
pub placement: text_marks::Placement,
}
pub trait StyleSheet {
type Style;
fn idle(&self, style: &Self::Style) -> Appearance;
fn hovered(&self, style: &Self::Style) -> Appearance {
self.idle(style)
}
fn gesturing(&self, style: &Self::Style) -> Appearance {
self.hovered(style)
}
fn disabled(&self, style: &Self::Style) -> Appearance {
self.idle(style)
}
fn tick_marks_appearance(&self, _style: &Self::Style) -> Option<TickMarksAppearance> {
None
}
fn mod_range_appearance(&self, _style: &Self::Style) -> Option<ModRangeAppearance> {
None
}
fn mod_range_appearance_2(&self, _style: &Self::Style) -> Option<ModRangeAppearance> {
None
}
fn text_marks_appearance(&self, _style: &Self::Style) -> Option<TextMarksAppearance> {
None
}
}
#[derive(Default)]
pub enum HSlider {
#[default]
Default,
Custom(Box<dyn StyleSheet<Style = iced_core::Theme>>),
}
impl<S> From<S> for HSlider
where
S: 'static + StyleSheet<Style = iced_core::Theme>,
{
fn from(val: S) -> Self {
HSlider::Custom(Box::new(val))
}
}
impl StyleSheet for iced_core::Theme {
type Style = HSlider;
fn idle(&self, style: &Self::Style) -> Appearance {
match style {
HSlider::Default => Appearance::Classic(Default::default()),
HSlider::Custom(custom) => custom.idle(self),
}
}
fn hovered(&self, style: &Self::Style) -> Appearance {
match style {
HSlider::Default => Appearance::Classic(ClassicAppearance {
handle: ClassicHandle {
color: default_colors::LIGHT_BACK_HOVER,
..Default::default()
},
..Default::default()
}),
HSlider::Custom(custom) => custom.hovered(self),
}
}
fn gesturing(&self, style: &Self::Style) -> Appearance {
match style {
HSlider::Default => Appearance::Classic(ClassicAppearance {
handle: ClassicHandle {
color: default_colors::LIGHT_BACK_DRAG,
..Default::default()
},
..Default::default()
}),
HSlider::Custom(custom) => custom.gesturing(self),
}
}
fn disabled(&self, style: &Self::Style) -> Appearance {
self.idle(style)
}
fn tick_marks_appearance(&self, style: &Self::Style) -> Option<TickMarksAppearance> {
match style {
HSlider::Default => Some(TickMarksAppearance {
style: tick_marks::Appearance {
tier_1: tick_marks::Shape::Line {
length: 24.0,
width: 2.0,
color: default_colors::TICK_TIER_1,
},
tier_2: tick_marks::Shape::Line {
length: 22.0,
width: 1.0,
color: default_colors::TICK_TIER_2,
},
tier_3: tick_marks::Shape::Line {
length: 18.0,
width: 1.0,
color: default_colors::TICK_TIER_3,
},
},
placement: tick_marks::Placement::Center {
offset: Offset::ZERO,
fill_length: false,
},
}),
HSlider::Custom(custom) => custom.tick_marks_appearance(self),
}
}
fn mod_range_appearance(&self, style: &Self::Style) -> Option<ModRangeAppearance> {
match style {
HSlider::Default => None,
HSlider::Custom(custom) => custom.mod_range_appearance(self),
}
}
fn mod_range_appearance_2(&self, style: &Self::Style) -> Option<ModRangeAppearance> {
match style {
HSlider::Default => None,
HSlider::Custom(custom) => custom.mod_range_appearance_2(self),
}
}
fn text_marks_appearance(&self, style: &Self::Style) -> Option<TextMarksAppearance> {
match style {
HSlider::Default => Some(TextMarksAppearance {
style: Default::default(),
placement: text_marks::Placement::RightOrBottom {
inside: false,
offset: Offset { x: 0.0, y: 7.0 },
},
}),
HSlider::Custom(custom) => custom.text_marks_appearance(self),
}
}
}