diff --git a/CHANGELOG.md b/CHANGELOG.md index c3f7d0bc..c5c102cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ NOTE: [`eframe`](eframe/CHANGELOG.md), [`egui_web`](egui_web/CHANGELOG.md), [`eg * `Painter`/`Fonts`: text layout now expect a color when creating a `Galley`. You may override that color with `Painter::galley_with_color`. * MSRV (Minimum Supported Rust Version) is now `1.54.0`. * By default, `DragValue`:s no longer show a tooltip when hovered. Change with `Style::explanation_tooltips`. +* Smaller and nicer color picker. ### Fixed 🐛 * Fix wrongly sized multiline `TextEdit` in justified layouts. diff --git a/egui/src/widgets/color_picker.rs b/egui/src/widgets/color_picker.rs index 3e1d24ad..658d3e43 100644 --- a/egui/src/widgets/color_picker.rs +++ b/egui/src/widgets/color_picker.rs @@ -95,10 +95,7 @@ fn color_button(ui: &mut Ui, color: Color32, open: bool) -> Response { fn color_slider_1d(ui: &mut Ui, value: &mut f32, color_at: impl Fn(f32) -> Color32) -> Response { #![allow(clippy::identity_op)] - let desired_size = vec2( - ui.spacing().slider_width, - ui.spacing().interact_size.y * 2.0, - ); + let desired_size = vec2(ui.spacing().slider_width, ui.spacing().interact_size.y); let (rect, response) = ui.allocate_at_least(desired_size, Sense::click_and_drag()); if let Some(mpos) = response.interact_pointer_pos() { @@ -211,23 +208,34 @@ pub enum Alpha { BlendOrAdditive, } -fn color_text_ui(ui: &mut Ui, color: impl Into) { +fn color_text_ui(ui: &mut Ui, color: impl Into, alpha: Alpha) { let color = color.into(); ui.horizontal(|ui| { let [r, g, b, a] = color.to_array(); - ui.label(format!( - "RGBA (premultiplied): rgba({}, {}, {}, {})", - r, g, b, a - )); if ui.button("📋").on_hover_text("Click to copy").clicked() { - ui.output().copied_text = format!("{}, {}, {}, {}", r, g, b, a); + if alpha == Alpha::Opaque { + ui.output().copied_text = format!("{}, {}, {}", r, g, b); + } else { + ui.output().copied_text = format!("{}, {}, {}, {}", r, g, b, a); + } + } + + if alpha == Alpha::Opaque { + ui.label(format!("rgb({}, {}, {})", r, g, b)) + .on_hover_text("Red Green Blue"); + } else { + ui.label(format!("rgba({}, {}, {}, {})", r, g, b, a)) + .on_hover_text("Red Green Blue with premultiplied Alpha"); } }); } fn color_picker_hsvag_2d(ui: &mut Ui, hsva: &mut HsvaGamma, alpha: Alpha) { - color_text_ui(ui, *hsva); + let current_color_size = vec2(ui.spacing().slider_width, ui.spacing().interact_size.y); + show_color(ui, *hsva, current_color_size).on_hover_text("Selected color"); + + color_text_ui(ui, *hsva, alpha); if alpha == Alpha::BlendOrAdditive { // We signal additive blending by storing a negative alpha (a bit ironic). @@ -249,82 +257,53 @@ fn color_picker_hsvag_2d(ui: &mut Ui, hsva: &mut HsvaGamma, alpha: Alpha) { } 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" + let opaque = HsvaGamma { a: 1.0, ..*hsva }; + + if alpha == Alpha::Opaque { + hsva.a = 1.0; } else { - "hsva_color_picker_normal" - }; + let a = &mut hsva.a; - crate::Grid::new(grid_id).show(ui, |ui| { - let current_color_size = vec2( - ui.spacing().slider_width, - ui.spacing().interact_size.y * 2.0, - ); - - let opaque = HsvaGamma { a: 1.0, ..*hsva }; - - if alpha == Alpha::Opaque { - hsva.a = 1.0; - } else { - let a = &mut hsva.a; - - if alpha == Alpha::OnlyBlend { - if *a < 0.0 { - *a = 0.5; // was additive, but isn't allowed to be - } - 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(); + if alpha == Alpha::OnlyBlend { + if *a < 0.0 { + *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 if !additive { + color_slider_1d(ui, a, |a| HsvaGamma { a, ..opaque }.into()).on_hover_text("Alpha"); } + } - show_color(ui, *hsva, current_color_size); - ui.label("Selected color"); - ui.end_row(); + let HsvaGamma { h, s, v, a: _ } = hsva; - ui.separator(); // TODO: fix ever-expansion - ui.end_row(); + color_slider_1d(ui, h, |h| { + HsvaGamma { + h, + s: 1.0, + v: 1.0, + a: 1.0, + } + .into() + }) + .on_hover_text("Hue"); - let HsvaGamma { h, s, v, a: _ } = hsva; + if false { + color_slider_1d(ui, s, |s| HsvaGamma { s, ..opaque }.into()).on_hover_text("Saturation"); + } - color_slider_1d(ui, h, |h| { - HsvaGamma { - h, - s: 1.0, - v: 1.0, - a: 1.0, - } - .into() - }); - ui.label("Hue"); - ui.end_row(); + if false { + color_slider_1d(ui, v, |v| HsvaGamma { v, ..opaque }.into()).on_hover_text("Value"); + } - 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(); - - color_slider_2d(ui, v, s, |v, s| HsvaGamma { s, v, ..opaque }.into()); - ui.label("Value / Saturation"); - ui.end_row(); - }); + color_slider_2d(ui, v, s, |v, s| HsvaGamma { s, v, ..opaque }.into()); } -/// return true on change +/// Returns `true` on change. fn color_picker_hsva_2d(ui: &mut Ui, hsva: &mut Hsva, alpha: Alpha) -> bool { let mut hsvag = HsvaGamma::from(*hsva); - color_picker_hsvag_2d(ui, &mut hsvag, alpha); + ui.vertical(|ui| { + color_picker_hsvag_2d(ui, &mut hsvag, alpha); + }); let new_hasva = Hsva::from(hsvag); if *hsva == new_hasva { false @@ -334,6 +313,33 @@ fn color_picker_hsva_2d(ui: &mut Ui, hsva: &mut Hsva, alpha: Alpha) -> bool { } } +/// Returns `true` on change. +pub fn color_picker_color32(ui: &mut Ui, srgba: &mut Color32, alpha: Alpha) -> bool { + // To ensure we keep hue slider when `srgba` is gray we store the + // full `Hsva` in a cache: + + let mut hsva = ui + .ctx() + .memory() + .data_temp + .get_or_default::>() + .get(srgba) + .cloned() + .unwrap_or_else(|| Hsva::from(*srgba)); + + let response = color_picker_hsva_2d(ui, &mut hsva, alpha); + + *srgba = Color32::from(hsva); + + ui.ctx() + .memory() + .data_temp + .get_mut_or_default::>() + .set(*srgba, hsva); + + response +} + pub fn color_edit_button_hsva(ui: &mut Ui, hsva: &mut Hsva, alpha: Alpha) -> Response { let pupup_id = ui.auto_id_with("popup"); let open = ui.memory().is_popup_open(pupup_id); @@ -351,7 +357,7 @@ pub fn color_edit_button_hsva(ui: &mut Ui, hsva: &mut Hsva, alpha: Alpha) -> Res .order(Order::Foreground) .default_pos(button_response.rect.max) .show(ui.ctx(), |ui| { - ui.spacing_mut().slider_width = 256.0; + ui.spacing_mut().slider_width = 210.0; Frame::popup(ui.style()).show(ui, |ui| { if color_picker_hsva_2d(ui, hsva, alpha) { button_response.mark_changed();