fix: color picker

This commit is contained in:
Ashley Wulber 2024-11-01 20:51:07 -04:00 committed by Ashley Wulber
parent 0dfaa4d158
commit 36b3cfa13a

View file

@ -4,6 +4,7 @@
//! Widgets for selecting colors with a color picker. //! Widgets for selecting colors with a color picker.
use std::borrow::Cow; use std::borrow::Cow;
use std::iter;
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@ -23,7 +24,7 @@ use iced_core::{
Rectangle, Renderer, Shadow, Shell, Size, Vector, Widget, Rectangle, Renderer, Shadow, Shell, Size, Vector, Widget,
}; };
use iced_widget::slider::{HandleShape, RailBackground}; use iced_widget::slider::HandleShape;
use iced_widget::{canvas, column, horizontal_space, row, scrollable, vertical_space, Row}; use iced_widget::{canvas, column, horizontal_space, row, scrollable, vertical_space, Row};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use palette::{FromColor, RgbHue}; use palette::{FromColor, RgbHue};
@ -38,15 +39,14 @@ pub use ColorPickerModel as Model;
// TODO is this going to look correct enough? // TODO is this going to look correct enough?
lazy_static! { lazy_static! {
pub static ref HSV_RAINBOW: Vec<ColorStop> = (0u16..8) pub static ref HSV_RAINBOW: Vec<iced::Color> = (0u16..8)
.map(|h| ColorStop { .map(
color: iced::Color::from(palette::Srgba::from_color(palette::Hsv::new_srgb_const( |h| iced::Color::from(palette::Srgba::from_color(palette::Hsv::new_srgb_const(
RgbHue::new(f32::from(h) * 360.0 / 7.0), RgbHue::new(f32::from(h) * 360.0 / 7.0),
1.0, 1.0,
1.0 1.0
))), )))
offset: f32::from(h) / 7.0 )
})
.collect(); .collect();
} }
@ -287,7 +287,8 @@ where
) -> ColorPicker<'a, Message> { ) -> ColorPicker<'a, Message> {
let on_update = self.on_update; let on_update = self.on_update;
let spacing = THEME.lock().unwrap().cosmic().spacing; let spacing = THEME.lock().unwrap().cosmic().spacing;
let mut inner = column![ let mut inner =
column![
// segmented buttons // segmented buttons
segmented_control::horizontal(self.model) segmented_control::horizontal(self.model)
.on_activate(Box::new(move |e| on_update( .on_activate(Box::new(move |e| on_update(
@ -309,18 +310,102 @@ where
on_update(ColorPickerUpdate::ActiveColor(new)) on_update(ColorPickerUpdate::ActiveColor(new))
} }
) )
.on_release(on_update(ColorPickerUpdate::ActionFinished))
.class(Slider::Custom { .class(Slider::Custom {
active: Rc::new(|t| { active: Rc::new(move |t| {
let cosmic = t.cosmic(); let cosmic = t.cosmic();
let mut a = let mut a =
slider::Catalog::style(t, &Slider::default(), slider::Status::Active); slider::Catalog::style(t, &Slider::default(), slider::Status::Active);
// a.rail.colors = RailBackground::Gradient {
// gradient: Linear::new(Radians(0.0)).add_stops(HSV_RAINBOW.clone()), let hue = self.active_color.hue.into_positive_degrees();
// auto_angle: true, let pivot = hue * 7.0 / 360.;
// };
let low_end = pivot.floor() as usize;
let high_start = pivot.ceil() as usize;
let pivot_color = palette::Hsv::new_srgb(RgbHue::new(hue), 1.0, 1.0);
let low_range = HSV_RAINBOW[0..=low_end]
.iter()
.enumerate()
.map(|(i, color)| ColorStop {
color: *color,
offset: i as f32 / pivot.max(0.0001),
})
.chain(iter::once(ColorStop {
color: iced::Color::from(palette::Srgba::from_color(pivot_color)),
offset: 1.,
}))
.collect::<Vec<_>>();
let high_range =
iter::once(ColorStop {
color: iced::Color::from(palette::Srgba::from_color(pivot_color)),
offset: 0.,
})
.chain(HSV_RAINBOW[high_start..].iter().enumerate().map(
|(i, color)| ColorStop {
color: *color,
offset: (i as f32 + (1. - pivot.fract()))
/ (7. - pivot).max(0.0001),
},
))
.collect::<Vec<_>>();
a.rail.backgrounds = ( a.rail.backgrounds = (
Background::Color(Color::TRANSPARENT), Background::Gradient(iced::Gradient::Linear(
Background::Color(Color::TRANSPARENT), Linear::new(Radians(90.0)).add_stops(low_range),
)),
Background::Gradient(iced::Gradient::Linear(
Linear::new(Radians(90.0)).add_stops(high_range),
)),
);
a.rail.width = 8.0;
a.handle.background = Color::TRANSPARENT.into();
a.handle.shape = HandleShape::Circle { radius: 8.0 };
a.handle.border_color = cosmic.palette.neutral_10.into();
a.handle.border_width = 4.0;
a
}),
hovered: Rc::new(move |t| {
let cosmic = t.cosmic();
let mut a =
slider::Catalog::style(t, &Slider::default(), slider::Status::Active);
let hue = self.active_color.hue.into_positive_degrees();
let pivot = hue * 7.0 / 360.;
let low_end = pivot.floor() as usize;
let high_start = pivot.ceil() as usize;
let pivot_color = palette::Hsv::new_srgb(RgbHue::new(hue), 1.0, 1.0);
let low_range = HSV_RAINBOW[0..=low_end]
.iter()
.enumerate()
.map(|(i, color)| ColorStop {
color: *color,
offset: i as f32 / pivot.max(0.0001),
})
.chain(iter::once(ColorStop {
color: iced::Color::from(palette::Srgba::from_color(pivot_color)),
offset: 1.,
}))
.collect::<Vec<_>>();
let high_range =
iter::once(ColorStop {
color: iced::Color::from(palette::Srgba::from_color(pivot_color)),
offset: 0.,
})
.chain(HSV_RAINBOW[high_start..].iter().enumerate().map(
|(i, color)| ColorStop {
color: *color,
offset: (i as f32 + (1. - pivot.fract()))
/ (7. - pivot).max(0.0001),
},
))
.collect::<Vec<_>>();
a.rail.backgrounds = (
Background::Gradient(iced::Gradient::Linear(
Linear::new(Radians(90.0)).add_stops(low_range),
)),
Background::Gradient(iced::Gradient::Linear(
Linear::new(Radians(90.0)).add_stops(high_range),
)),
); );
a.rail.width = 8.0; a.rail.width = 8.0;
a.handle.background = Color::TRANSPARENT.into(); a.handle.background = Color::TRANSPARENT.into();
@ -329,38 +414,49 @@ where
a.handle.border_width = 4.0; a.handle.border_width = 4.0;
a a
}), }),
hovered: Rc::new(|t| { dragging: Rc::new(move |t| {
let cosmic = t.cosmic(); let cosmic = t.cosmic();
let mut a = let mut a =
slider::Catalog::style(t, &Slider::default(), slider::Status::Active); slider::Catalog::style(t, &Slider::default(), slider::Status::Active);
// a.rail.colors = RailBackground::Gradient { let hue = self.active_color.hue.into_positive_degrees();
// gradient: Linear::new(Radians(0.0)).add_stops(HSV_RAINBOW.clone()), let pivot = hue * 7.0 / 360.;
// auto_angle: true,
// }; let low_end = pivot.floor() as usize;
a.rail.backgrounds = (Color::TRANSPARENT.into(), Color::TRANSPARENT.into()); let high_start = pivot.ceil() as usize;
a.rail.width = 8.0; let pivot_color = palette::Hsv::new_srgb(RgbHue::new(hue), 1.0, 1.0);
a.handle.background = Color::TRANSPARENT.into(); let low_range = HSV_RAINBOW[0..=low_end]
a.handle.shape = HandleShape::Circle { radius: 8.0 }; .iter()
a.handle.border_color = cosmic.palette.neutral_10.into(); .enumerate()
a.handle.border_width = 4.0; .map(|(i, color)| ColorStop {
a color: *color,
}), offset: i as f32 / pivot.max(0.0001),
dragging: Rc::new(|t| { })
let cosmic = t.cosmic(); .chain(iter::once(ColorStop {
let mut a = color: iced::Color::from(palette::Srgba::from_color(pivot_color)),
slider::Catalog::style(t, &Slider::default(), slider::Status::Active); offset: 1.,
// a.rail.backgrounds = ( }))
// RailBackground::Gradient(Gradient { .collect::<Vec<_>>();
// gradient: Linear::new(Radians(0.0)).add_stops(HSV_RAINBOW.clone()), let high_range =
// auto_angle: true, iter::once(ColorStop {
// }), color: iced::Color::from(palette::Srgba::from_color(pivot_color)),
// RailBackground::Gradient { offset: 0.,
// gradient: Linear::new(Radians(0.0)).add_stops(HSV_RAINBOW.clone()), })
// auto_angle: true, .chain(HSV_RAINBOW[high_start..].iter().enumerate().map(
// }, |(i, color)| ColorStop {
// ); color: *color,
a.rail.backgrounds = offset: (i as f32 + (1. - pivot.fract()))
(iced::Color::TRANSPARENT.into(), Color::TRANSPARENT.into()); / (7. - pivot).max(0.0001),
},
))
.collect::<Vec<_>>();
a.rail.backgrounds = (
Background::Gradient(iced::Gradient::Linear(
Linear::new(Radians(90.0)).add_stops(low_range),
)),
Background::Gradient(iced::Gradient::Linear(
Linear::new(Radians(90.0)).add_stops(high_range),
)),
);
a.rail.width = 8.0; a.rail.width = 8.0;
a.handle.background = Color::TRANSPARENT.into(); a.handle.background = Color::TRANSPARENT.into();
a.handle.shape = HandleShape::Circle { radius: 8.0 }; a.handle.shape = HandleShape::Circle { radius: 8.0 };
@ -391,7 +487,9 @@ where
.class(Button::Text); .class(Button::Text);
match self.copied_at.take() { match self.copied_at.take() {
Some(t) if Instant::now().duration_since(t) > Duration::from_secs(2) => { Some(t)
if Instant::now().duration_since(t) > Duration::from_secs(2) =>
{
button.into() button.into()
} }
Some(_) => tooltip( Some(_) => tooltip(