mod layout;
mod node;
mod reconcile;
pub use layout::measure_slider;
pub use node::SliderNode;
pub use reconcile::reconcile_slider;
use unicode_width::UnicodeWidthStr;
use crate::callback::Callback;
use crate::core::element::Element;
use crate::style::{Length, Padding, Style, StyleSlot};
use crate::utils::gradient::ColorGradient;
#[derive(Clone)]
pub struct Slider {
pub value: f64,
pub min: f64,
pub max: f64,
pub step: f64,
pub on_change: Option<Callback<f64>>,
pub on_click: Option<Callback<f64>>,
pub style: Style,
pub filled_track_style: Style,
pub filled_track_gradient: Option<ColorGradient>,
pub thumb_style: Style,
pub thumb_gradient: Option<ColorGradient>,
pub label: Option<String>,
pub label_style: Style,
pub show_value: bool,
pub width: Length,
pub height: Length,
pub padding: Padding,
pub focusable: bool,
pub focus_style: StyleSlot,
pub focus_thumb_style: StyleSlot,
pub hover_thumb_style: StyleSlot,
pub thumb_symbol: String,
pub track_symbol: String,
pub filled_track_symbol: String,
pub hover_thumb_symbol: Option<String>,
}
impl Slider {
pub fn new(value: f64) -> Self {
Self {
value,
min: 0.0,
max: 100.0,
step: 1.0,
on_change: None,
on_click: None,
style: Style::default(),
filled_track_style: Style::default(),
filled_track_gradient: None,
thumb_style: Style::default(),
thumb_gradient: None,
label: None,
label_style: Style::default(),
show_value: true,
width: Length::Flex(1),
height: Length::Px(1),
padding: Padding::default(),
focusable: true,
focus_style: StyleSlot::Inherit,
focus_thumb_style: StyleSlot::Inherit,
hover_thumb_style: StyleSlot::Inherit,
thumb_symbol: "●".to_string(),
track_symbol: "─".to_string(),
filled_track_symbol: "━".to_string(),
hover_thumb_symbol: None,
}
}
pub fn min(mut self, min: f64) -> Self {
self.min = min;
self
}
pub fn max(mut self, max: f64) -> Self {
self.max = max;
self
}
pub fn step(mut self, step: f64) -> Self {
self.step = step;
self
}
pub fn label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn on_change(mut self, cb: Callback<f64>) -> Self {
self.on_change = Some(cb);
self
}
pub fn on_click(mut self, cb: Callback<f64>) -> Self {
self.on_click = Some(cb);
self
}
pub fn label_style(mut self, style: Style) -> Self {
self.label_style = style;
self
}
pub fn show_value(mut self, show: bool) -> Self {
self.show_value = show;
self
}
pub fn style(mut self, style: Style) -> Self {
self.style = style;
self
}
pub fn filled_track_style(mut self, style: Style) -> Self {
self.filled_track_style = style;
self
}
pub fn filled_track_gradient(mut self, gradient: ColorGradient) -> Self {
self.filled_track_gradient = Some(gradient);
self
}
pub fn thumb_style(mut self, style: Style) -> Self {
self.thumb_style = style;
self
}
pub fn thumb_gradient(mut self, gradient: ColorGradient) -> Self {
self.thumb_gradient = Some(gradient);
self
}
pub fn width(mut self, width: Length) -> Self {
self.width = width;
self
}
pub fn height(mut self, height: Length) -> Self {
self.height = height;
self
}
pub fn focusable(mut self, focusable: bool) -> Self {
self.focusable = focusable;
self
}
pub fn focus_style(mut self, style: Style) -> Self {
self.focus_style = StyleSlot::Replace(style);
self
}
pub fn extend_focus_style(mut self, style: Style) -> Self {
self.focus_style = StyleSlot::Extend(style);
self
}
pub fn inherit_focus_style(mut self) -> Self {
self.focus_style = StyleSlot::Inherit;
self
}
pub fn focus_style_slot(mut self, slot: StyleSlot) -> Self {
self.focus_style = slot;
self
}
pub fn focus_thumb_style(mut self, style: Style) -> Self {
self.focus_thumb_style = StyleSlot::Replace(style);
self
}
pub fn extend_focus_thumb_style(mut self, style: Style) -> Self {
self.focus_thumb_style = StyleSlot::Extend(style);
self
}
pub fn inherit_focus_thumb_style(mut self) -> Self {
self.focus_thumb_style = StyleSlot::Inherit;
self
}
pub fn focus_thumb_style_slot(mut self, slot: StyleSlot) -> Self {
self.focus_thumb_style = slot;
self
}
pub fn hover_thumb_style(mut self, style: Style) -> Self {
self.hover_thumb_style = StyleSlot::Replace(style);
self
}
pub fn extend_hover_thumb_style(mut self, style: Style) -> Self {
self.hover_thumb_style = StyleSlot::Extend(style);
self
}
pub fn inherit_hover_thumb_style(mut self) -> Self {
self.hover_thumb_style = StyleSlot::Inherit;
self
}
pub fn hover_thumb_style_slot(mut self, slot: StyleSlot) -> Self {
self.hover_thumb_style = slot;
self
}
pub fn thumb_symbol(mut self, symbol: impl Into<String>) -> Self {
self.thumb_symbol = symbol.into();
self
}
pub fn track_symbol(mut self, symbol: impl Into<String>) -> Self {
self.track_symbol = symbol.into();
self
}
pub fn filled_track_symbol(mut self, symbol: impl Into<String>) -> Self {
self.filled_track_symbol = symbol.into();
self
}
pub fn hover_thumb_symbol(mut self, symbol: impl Into<String>) -> Self {
self.hover_thumb_symbol = Some(symbol.into());
self
}
}
impl From<Slider> for Element {
fn from(mut slider: Slider) -> Self {
if slider.min > slider.max {
std::mem::swap(&mut slider.min, &mut slider.max);
}
if (slider.max - slider.min).abs() < f64::EPSILON {
slider.max = slider.min + 1.0;
}
slider.value = slider.value.clamp(slider.min, slider.max);
Element::new(crate::core::element::ElementKind::Slider(slider))
}
}
pub(crate) fn value_slot_width(min: f64, max: f64) -> u16 {
let min_text = format!("{:.1}", min);
let max_text = format!("{:.1}", max);
let width = UnicodeWidthStr::width(min_text.as_str())
.max(UnicodeWidthStr::width(max_text.as_str()))
.min(u16::MAX as usize) as u16;
width.max(1)
}
impl crate::layout::hash::LayoutHash for Slider {
fn layout_hash(
&self,
hasher: &mut impl std::hash::Hasher,
_recurse: &dyn Fn(&crate::core::element::Element) -> Option<u64>,
) -> Option<()> {
use std::hash::Hash;
self.width.hash(hasher);
self.height.hash(hasher);
self.label.hash(hasher);
self.padding.hash(hasher);
Some(())
}
}