fix(color picker): avoid 0 in color picker slider value
This commit is contained in:
parent
f17cd2928a
commit
a929829521
1 changed files with 152 additions and 225 deletions
|
|
@ -289,237 +289,164 @@ where
|
||||||
copy_to_clipboard_label: T,
|
copy_to_clipboard_label: T,
|
||||||
copied_to_clipboard_label: T,
|
copied_to_clipboard_label: T,
|
||||||
) -> ColorPicker<'a, Message> {
|
) -> ColorPicker<'a, Message> {
|
||||||
|
fn rail_backgrounds(hue: f32) -> (Background, Background) {
|
||||||
|
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<_>>();
|
||||||
|
(
|
||||||
|
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),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
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(
|
||||||
ColorPickerUpdate::ActivateSegmented(e)
|
ColorPickerUpdate::ActivateSegmented(e)
|
||||||
)))
|
)))
|
||||||
.minimum_button_width(0)
|
.minimum_button_width(0)
|
||||||
.width(self.width),
|
.width(self.width),
|
||||||
// canvas with gradient for the current color
|
// canvas with gradient for the current color
|
||||||
// still needs the canvas and the handle to be drawn on it
|
// still needs the canvas and the handle to be drawn on it
|
||||||
container(vertical_space().height(self.height))
|
container(vertical_space().height(self.height))
|
||||||
.width(self.width)
|
.width(self.width)
|
||||||
.height(self.height),
|
.height(self.height),
|
||||||
slider(
|
slider(
|
||||||
0.0..=359.99,
|
0.001..=359.99,
|
||||||
self.active_color.hue.into_positive_degrees(),
|
self.active_color.hue.into_positive_degrees(),
|
||||||
move |v| {
|
move |v| {
|
||||||
let mut new = self.active_color;
|
let mut new = self.active_color;
|
||||||
new.hue = v.into();
|
new.hue = v.into();
|
||||||
on_update(ColorPickerUpdate::ActiveColor(new))
|
on_update(ColorPickerUpdate::ActiveColor(new))
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
.on_release(on_update(ColorPickerUpdate::ActionFinished))
|
||||||
|
.class(Slider::Custom {
|
||||||
|
active: 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();
|
||||||
|
a.rail.backgrounds = rail_backgrounds(hue);
|
||||||
|
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();
|
||||||
|
a.rail.backgrounds = rail_backgrounds(hue);
|
||||||
|
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
|
||||||
|
}),
|
||||||
|
dragging: 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();
|
||||||
|
a.rail.backgrounds = rail_backgrounds(hue);
|
||||||
|
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
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.width(self.width),
|
||||||
|
text_input("", self.input_color)
|
||||||
|
.on_input(move |s| on_update(ColorPickerUpdate::Input(s)))
|
||||||
|
.on_paste(move |s| on_update(ColorPickerUpdate::Input(s)))
|
||||||
|
.on_submit(move |_| on_update(ColorPickerUpdate::AppliedColor))
|
||||||
|
.leading_icon(
|
||||||
|
color_button(
|
||||||
|
None,
|
||||||
|
Some(Color::from(palette::Srgb::from_color(self.active_color))),
|
||||||
|
Length::FillPortion(12)
|
||||||
|
)
|
||||||
|
.into()
|
||||||
)
|
)
|
||||||
.on_release(on_update(ColorPickerUpdate::ActionFinished))
|
// TODO copy paste input contents
|
||||||
.class(Slider::Custom {
|
.trailing_icon({
|
||||||
active: Rc::new(move |t| {
|
let button = button::custom(crate::widget::icon(
|
||||||
let cosmic = t.cosmic();
|
from_name("edit-copy-symbolic").size(spacing.space_s).into(),
|
||||||
let mut a =
|
))
|
||||||
slider::Catalog::style(t, &Slider::default(), slider::Status::Active);
|
.on_press(on_update(ColorPickerUpdate::Copied(Instant::now())))
|
||||||
|
.class(Button::Text);
|
||||||
|
|
||||||
let hue = self.active_color.hue.into_positive_degrees();
|
match self.copied_at.take() {
|
||||||
let pivot = hue * 7.0 / 360.;
|
Some(t) if Instant::now().duration_since(t) > Duration::from_secs(2) => {
|
||||||
|
button.into()
|
||||||
let low_end = pivot.floor() as usize;
|
}
|
||||||
let high_start = pivot.ceil() as usize;
|
Some(_) => tooltip(
|
||||||
let pivot_color = palette::Hsv::new_srgb(RgbHue::new(hue), 1.0, 1.0);
|
button,
|
||||||
let low_range = HSV_RAINBOW[0..=low_end]
|
text(copied_to_clipboard_label),
|
||||||
.iter()
|
iced_widget::tooltip::Position::Bottom,
|
||||||
.enumerate()
|
)
|
||||||
.map(|(i, color)| ColorStop {
|
.into(),
|
||||||
color: *color,
|
None => tooltip(
|
||||||
offset: i as f32 / pivot.max(0.0001),
|
button,
|
||||||
})
|
text(copy_to_clipboard_label),
|
||||||
.chain(iter::once(ColorStop {
|
iced_widget::tooltip::Position::Bottom,
|
||||||
color: iced::Color::from(palette::Srgba::from_color(pivot_color)),
|
)
|
||||||
offset: 1.,
|
.into(),
|
||||||
}))
|
}
|
||||||
.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.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.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
|
|
||||||
}),
|
|
||||||
dragging: 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.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
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
.width(self.width),
|
.width(self.width),
|
||||||
text_input("", self.input_color)
|
]
|
||||||
.on_input(move |s| on_update(ColorPickerUpdate::Input(s)))
|
// Should we ensure the side padding is at least half the width of the handle?
|
||||||
.on_paste(move |s| on_update(ColorPickerUpdate::Input(s)))
|
.padding([
|
||||||
.on_submit(move |_| on_update(ColorPickerUpdate::AppliedColor))
|
spacing.space_none,
|
||||||
.leading_icon(
|
spacing.space_s,
|
||||||
color_button(
|
spacing.space_s,
|
||||||
None,
|
spacing.space_s,
|
||||||
Some(Color::from(palette::Srgb::from_color(self.active_color))),
|
])
|
||||||
Length::FillPortion(12)
|
.spacing(spacing.space_s);
|
||||||
)
|
|
||||||
.into()
|
|
||||||
)
|
|
||||||
// TODO copy paste input contents
|
|
||||||
.trailing_icon({
|
|
||||||
let button = button::custom(crate::widget::icon(
|
|
||||||
from_name("edit-copy-symbolic").size(spacing.space_s).into(),
|
|
||||||
))
|
|
||||||
.on_press(on_update(ColorPickerUpdate::Copied(Instant::now())))
|
|
||||||
.class(Button::Text);
|
|
||||||
|
|
||||||
match self.copied_at.take() {
|
|
||||||
Some(t)
|
|
||||||
if Instant::now().duration_since(t) > Duration::from_secs(2) =>
|
|
||||||
{
|
|
||||||
button.into()
|
|
||||||
}
|
|
||||||
Some(_) => tooltip(
|
|
||||||
button,
|
|
||||||
text(copied_to_clipboard_label),
|
|
||||||
iced_widget::tooltip::Position::Bottom,
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
None => tooltip(
|
|
||||||
button,
|
|
||||||
text(copy_to_clipboard_label),
|
|
||||||
iced_widget::tooltip::Position::Bottom,
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.width(self.width),
|
|
||||||
]
|
|
||||||
// Should we ensure the side padding is at least half the width of the handle?
|
|
||||||
.padding([
|
|
||||||
spacing.space_none,
|
|
||||||
spacing.space_s,
|
|
||||||
spacing.space_s,
|
|
||||||
spacing.space_s,
|
|
||||||
])
|
|
||||||
.spacing(spacing.space_s);
|
|
||||||
|
|
||||||
if !self.recent_colors.is_empty() {
|
if !self.recent_colors.is_empty() {
|
||||||
inner = inner.push(horizontal::light().width(self.width));
|
inner = inner.push(horizontal::light().width(self.width));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue