Use Grid to add labels to the color picker sliders

Also improve the color preview in the color picker
This commit is contained in:
Emil Ernerfeldt 2021-01-13 23:00:56 +01:00
parent 63d3e9e70b
commit 73d16eb771
3 changed files with 104 additions and 53 deletions

View file

@ -19,6 +19,8 @@ fn contrast_color(color: impl Into<Rgba>) -> Color32 {
const N: u32 = 6 * 6; const N: u32 = 6 * 6;
fn background_checkers(painter: &Painter, rect: Rect) { fn background_checkers(painter: &Painter, rect: Rect) {
let rect = rect.shrink(0.5); // Small hack to avoid the checkers from peeking through the sides
let mut top_color = Color32::from_gray(128); let mut top_color = Color32::from_gray(128);
let mut bottom_color = Color32::from_gray(32); let mut bottom_color = Color32::from_gray(32);
let checker_size = Vec2::splat(rect.height() / 2.0); let checker_size = Vec2::splat(rect.height() / 2.0);
@ -40,19 +42,26 @@ fn background_checkers(painter: &Painter, rect: Rect) {
painter.add(Shape::triangles(triangles)); painter.add(Shape::triangles(triangles));
} }
pub fn show_color(ui: &mut Ui, color: impl Into<Color32>, desired_size: Vec2) -> Response { pub fn show_color(ui: &mut Ui, color: impl Into<Hsva>, desired_size: Vec2) -> Response {
show_srgba(ui, color.into(), desired_size) show_hsva(ui, color.into(), desired_size)
} }
fn show_srgba(ui: &mut Ui, srgba: Color32, desired_size: Vec2) -> Response { fn show_hsva(ui: &mut Ui, color: Hsva, desired_size: Vec2) -> Response {
let (rect, response) = ui.allocate_at_least(desired_size, Sense::hover()); let (rect, response) = ui.allocate_at_least(desired_size, Sense::hover());
background_checkers(ui.painter(), rect); background_checkers(ui.painter(), rect);
ui.painter().add(Shape::Rect { if true {
rect, let left = Rect::from_min_max(rect.left_top(), rect.center_bottom());
corner_radius: 2.0, let right = Rect::from_min_max(rect.center_top(), rect.right_bottom());
fill: srgba, ui.painter().rect_filled(left, 0.0, color);
stroke: Stroke::new(3.0, srgba.to_opaque()), ui.painter().rect_filled(right, 0.0, color.to_opaque());
}); } else {
ui.painter().add(Shape::Rect {
rect,
corner_radius: 2.0,
fill: color.into(),
stroke: Stroke::new(3.0, color.to_opaque()),
});
}
response response
} }
@ -62,12 +71,22 @@ fn color_button(ui: &mut Ui, color: Color32) -> Response {
let visuals = ui.style().interact(&response); let visuals = ui.style().interact(&response);
let rect = rect.expand(visuals.expansion); let rect = rect.expand(visuals.expansion);
background_checkers(ui.painter(), rect); background_checkers(ui.painter(), rect);
ui.painter().add(Shape::Rect { let corner_radius = visuals.corner_radius.at_most(2.0);
rect, if true {
corner_radius: visuals.corner_radius.at_most(2.0), let left = Rect::from_min_max(rect.left_top(), rect.center_bottom());
fill: color, let right = Rect::from_min_max(rect.center_top(), rect.right_bottom());
stroke: visuals.fg_stroke, ui.painter().rect_filled(left, 0.0, color);
}); ui.painter().rect_filled(right, 0.0, color.to_opaque());
ui.painter()
.rect_stroke(rect, corner_radius, visuals.fg_stroke);
} else {
ui.painter().add(Shape::Rect {
rect,
corner_radius,
fill: color,
stroke: visuals.fg_stroke,
});
}
response response
} }
@ -195,7 +214,37 @@ pub enum Alpha {
} }
fn color_picker_hsvag_2d(ui: &mut Ui, hsva: &mut HsvaGamma, alpha: Alpha) { fn color_picker_hsvag_2d(ui: &mut Ui, hsva: &mut HsvaGamma, alpha: Alpha) {
ui.vertical(|ui| { if alpha == Alpha::BlendOrAdditive {
// We signal additive blending by storing a negative alpha (a bit ironic).
let a = &mut hsva.a;
let mut additive = *a < 0.0;
ui.horizontal(|ui| {
ui.label("Blending:");
ui.radio_value(&mut additive, false, "Normal");
ui.radio_value(&mut additive, true, "Additive");
if additive {
*a = -a.abs();
}
if !additive {
*a = a.abs();
}
});
}
let additive = hsva.a < 0.0;
// Using different grid ids avoid some flickering when switching between
// (the grid remembers the sizes of its contents).
let grid_id = if alpha == Alpha::Opaque {
"hsva_color_picker_opaque"
} else if additive {
"hsva_color_picker_additive"
} else {
"hsva_color_picker_normal"
};
crate::Grid::new(grid_id).show(ui, |ui| {
let current_color_size = vec2( let current_color_size = vec2(
ui.style().spacing.slider_width, ui.style().spacing.slider_width,
ui.style().spacing.interact_size.y * 2.0, ui.style().spacing.interact_size.y * 2.0,
@ -205,53 +254,51 @@ fn color_picker_hsvag_2d(ui: &mut Ui, hsva: &mut HsvaGamma, alpha: Alpha) {
if alpha == Alpha::Opaque { if alpha == Alpha::Opaque {
hsva.a = 1.0; hsva.a = 1.0;
show_color(ui, *hsva, current_color_size).on_hover_text("Current color"); show_color(ui, *hsva, current_color_size);
ui.label("Current color");
ui.end_row();
} else { } else {
let a = &mut hsva.a; let a = &mut hsva.a;
// We signal additive blending by storing a negative alpha (a bit ironic).
let mut additive = *a < 0.0;
if alpha == Alpha::OnlyBlend { if alpha == Alpha::OnlyBlend {
if additive { if *a < 0.0 {
*a = 0.5; *a = 0.5; // was additive, but isn't allowed to be
}
color_slider_1d(ui, a, |a| HsvaGamma { a, ..opaque }.into()).on_hover_text("Alpha");
} else {
ui.horizontal(|ui| {
ui.label("Blending:");
ui.radio_value(&mut additive, false, "Normal");
ui.radio_value(&mut additive, true, "Additive");
if additive {
*a = -a.abs();
}
if !additive {
*a = a.abs();
}
});
if !additive {
color_slider_1d(ui, a, |a| HsvaGamma { a, ..opaque }.into())
.on_hover_text("Alpha");
} }
color_slider_1d(ui, a, |a| HsvaGamma { a, ..opaque }.into());
ui.label("Alpha");
ui.end_row();
} else if !additive {
color_slider_1d(ui, a, |a| HsvaGamma { a, ..opaque }.into());
ui.label("Alpha");
ui.end_row();
} }
show_color(ui, *hsva, current_color_size).on_hover_text("Current color"); show_color(ui, *hsva, current_color_size);
show_color(ui, opaque, current_color_size).on_hover_text("Current color (opaque)"); ui.label("Current color");
ui.end_row();
} }
let HsvaGamma { h, s, v, a: _ } = hsva; let HsvaGamma { h, s, v, a: _ } = hsva;
color_slider_2d(ui, h, s, |h, s| HsvaGamma::new(h, s, 1.0, 1.0).into()) color_slider_2d(ui, h, s, |h, s| HsvaGamma::new(h, s, 1.0, 1.0).into());
.on_hover_text("Hue - Saturation"); ui.label("Hue / Saturation");
color_slider_2d(ui, v, s, |v, s| HsvaGamma { v, s, ..opaque }.into()) ui.end_row();
.on_hover_text("Value - Saturation");
color_slider_1d(ui, h, |h| HsvaGamma { h, ..opaque }.into()).on_hover_text("Hue"); color_slider_2d(ui, v, s, |v, s| HsvaGamma { v, s, ..opaque }.into());
color_slider_1d(ui, s, |s| HsvaGamma { s, ..opaque }.into()).on_hover_text("Saturation"); ui.label("Value / Saturation");
color_slider_1d(ui, v, |v| HsvaGamma { v, ..opaque }.into()).on_hover_text("Value"); ui.end_row();
color_slider_1d(ui, h, |h| HsvaGamma { h, ..opaque }.into());
ui.label("Hue");
ui.end_row();
color_slider_1d(ui, s, |s| HsvaGamma { s, ..opaque }.into());
ui.label("Saturation");
ui.end_row();
color_slider_1d(ui, v, |v| HsvaGamma { v, ..opaque }.into());
ui.label("Value");
ui.end_row();
}); });
} }

View file

@ -22,7 +22,7 @@ impl Default for WidgetGallery {
radio: Enum::First, radio: Enum::First,
scalar: 42.0, scalar: 42.0,
string: "Hello World!".to_owned(), string: "Hello World!".to_owned(),
color: egui::Color32::LIGHT_BLUE, color: (egui::Rgba::from(egui::Color32::LIGHT_BLUE) * 0.5).into(),
} }
} }
} }

View file

@ -436,6 +436,10 @@ impl Hsva {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
pub fn to_opaque(self) -> Self {
Self { a: 1.0, ..self }
}
pub fn to_rgb(&self) -> [f32; 3] { pub fn to_rgb(&self) -> [f32; 3] {
rgb_from_hsv((self.h, self.s, self.v)) rgb_from_hsv((self.h, self.s, self.v))
} }