Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-app/src/colorpicker.rs

//! **`ColorPicker` — a themed colour picker with preset swatches.** Wraps egui's
//! colour editor and adds a swatch row + a semantic, observable layer: the chosen
//! colour lives in the struct (FC-1) and is reported as hex (`state_json`).

use serde_json::{Value, json};

/// A colour picker: a swatch row + egui's colour button, over an owned RGBA value.
pub struct ColorPicker {
    rgba: [u8; 4],
    swatches: Vec<[u8; 4]>,
}

impl ColorPicker {
    pub fn new(rgba: [u8; 4]) -> Self {
        Self { rgba, swatches: Vec::new() }
    }
    /// Preset swatches shown as one-click chips.
    pub fn swatches(mut self, swatches: impl IntoIterator<Item = [u8; 4]>) -> Self {
        self.swatches = swatches.into_iter().collect();
        self
    }
    pub fn color(&self) -> [u8; 4] {
        self.rgba
    }
    pub fn set_color(&mut self, rgba: [u8; 4]) {
        self.rgba = rgba;
    }
    /// The current colour as `#RRGGBBAA`.
    pub fn hex(&self) -> String {
        let [r, g, b, a] = self.rgba;
        format!("#{r:02X}{g:02X}{b:02X}{a:02X}")
    }

    /// Draw the swatches + colour button; returns the new colour if it changed.
    pub fn show(&mut self, ui: &mut egui::Ui) -> Option<[u8; 4]> {
        let before = self.rgba;
        ui.horizontal(|ui| {
            for sw in &self.swatches {
                let c = egui::Color32::from_rgba_unmultiplied(sw[0], sw[1], sw[2], sw[3]);
                if ui.add(egui::Button::new("  ").fill(c)).clicked() {
                    self.rgba = *sw;
                }
            }
            let mut c = egui::Color32::from_rgba_unmultiplied(self.rgba[0], self.rgba[1], self.rgba[2], self.rgba[3]);
            if ui.color_edit_button_srgba(&mut c).changed() {
                self.rgba = [c.r(), c.g(), c.b(), c.a()];
            }
            ui.monospace(self.hex());
        });
        (self.rgba != before).then_some(self.rgba)
    }

    pub fn state_json(&self) -> Value {
        json!({ "rgba": self.rgba, "hex": self.hex() })
    }
}