diff --git a/tui/src/tui_color.rs b/tui/src/tui_color.rs index 9c274abe..e8ef4979 100644 --- a/tui/src/tui_color.rs +++ b/tui/src/tui_color.rs @@ -1,10 +1,14 @@ use crate::*; use rand::{thread_rng, distributions::uniform::UniformSampler}; -impl Theme for Tui {} -pub trait Theme { - const HOTKEY_FG: Color = Color::Rgb(255, 255, 0); - fn null () -> Color { Color::Reset } - fn g (g: u8) -> Color { Color::Rgb(g, g, g) } +impl Tui { + pub const fn null () -> Color { Color::Reset } + pub const fn g (g: u8) -> Color { Color::Rgb(g, g, g) } + pub const fn red () -> Color { Color::Rgb(255,0, 0) } + pub const fn orange () -> Color { Color::Rgb(255,128,0) } + pub const fn yellow () -> Color { Color::Rgb(255,255,0) } + pub const fn brown () -> Color { Color::Rgb(128,255,0) } + pub const fn green () -> Color { Color::Rgb(0,255,0) } + pub const fn electric () -> Color { Color::Rgb(0,255,128) } //fn bg0 () -> Color { Color::Rgb(20, 20, 20) } //fn bg () -> Color { Color::Rgb(28, 35, 25) } //fn border_bg () -> Color { Color::Rgb(40, 50, 30) } @@ -18,12 +22,6 @@ pub trait Theme { //fn bo2 () -> Color { Color::Rgb(70, 80, 50) } //fn ti1 () -> Color { Color::Rgb(150, 160, 90) } //fn ti2 () -> Color { Color::Rgb(120, 130, 100) } - fn red () -> Color { Color::Rgb(255,0, 0) } - fn orange () -> Color { Color::Rgb(255,128,0) } - fn yellow () -> Color { Color::Rgb(255,255,0) } - fn brown () -> Color { Color::Rgb(128,255,0) } - fn green () -> Color { Color::Rgb(0, 255,0) } - fn electric () -> Color { Color::Rgb(0, 255,128) } } pub trait HasColor { fn color (&self) -> ItemColor; } #[macro_export] macro_rules! has_color { @@ -39,9 +37,26 @@ pub trait HasColor { fn color (&self) -> ItemColor; } pub rgb: Color, } from!(|okhsl: Okhsl|ItemColor = Self { okhsl, rgb: okhsl_to_rgb(okhsl) }); +pub fn okhsl_to_rgb (color: Okhsl) -> Color { + let Srgb { red, green, blue, .. }: Srgb = Srgb::from_color_unclamped(color); + Color::Rgb((red * 255.0) as u8, (green * 255.0) as u8, (blue * 255.0) as u8,) +} from!(|rgb: Color|ItemColor = Self { rgb, okhsl: rgb_to_okhsl(rgb) }); +pub fn rgb_to_okhsl (color: Color) -> Okhsl { + if let Color::Rgb(r, g, b) = color { + Okhsl::from_color(Srgb::new(r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0)) + } else { + unreachable!("only Color::Rgb is supported") + } +} // A single color within item theme parameters, in OKHSL and RGB representations. impl ItemColor { + pub const fn from_rgb (rgb: Color) -> Self { + Self { rgb, okhsl: Okhsl::new_const(OklabHue::new(0.0), 0.0, 0.0) } + } + pub const fn from_okhsl (okhsl: Okhsl) -> Self { + Self { rgb: Color::Rgb(0, 0, 0), okhsl } + } pub fn random () -> Self { let mut rng = thread_rng(); let lo = Okhsl::new(-180.0, 0.01, 0.25); @@ -74,12 +89,27 @@ impl ItemColor { } impl ItemPalette { pub const G: [Self;256] = { - let mut builder = konst::ArrayBuilder::new(); + let mut builder = konst::array::ArrayBuilder::new(); let mut index = 0; while !builder.is_full() { - builder.push(ItemPalette::G[index]); - index++; + let light = (index as f64 * 1.3) as u8; + let lighter = (index as f64 * 1.6) as u8; + let lightest = (index as f64 * 1.9) as u8; + let dark = (index as f64 * 0.9) as u8; + let darker = (index as f64 * 0.6) as u8; + let darkest = (index as f64 * 0.3) as u8; + builder.push(ItemPalette { + base: ItemColor::from_rgb(Color::Rgb(index, index, index )), + light: ItemColor::from_rgb(Color::Rgb(light, light, light, )), + lighter: ItemColor::from_rgb(Color::Rgb(lighter, lighter, lighter, )), + lightest: ItemColor::from_rgb(Color::Rgb(lightest, lightest, lightest, )), + dark: ItemColor::from_rgb(Color::Rgb(dark, dark, dark, )), + darker: ItemColor::from_rgb(Color::Rgb(darker, darker, darker, )), + darkest: ItemColor::from_rgb(Color::Rgb(darkest, darkest, darkest, )), + }); + index += 1; } + builder.build() }; pub fn random () -> Self { ItemColor::random().into() } pub fn random_near (color: Self, distance: f32) -> Self { @@ -100,42 +130,35 @@ impl ItemPalette { darkest: color, } }; -} -from!(|base: Color|ItemPalette = Self::from(ItemColor::from(base))); -from!(|base: ItemColor|ItemPalette = { - let mut light = base.okhsl; - light.lightness = (light.lightness * 1.3).min(Okhsl::::max_lightness()); - let mut lighter = light; - lighter.lightness = (lighter.lightness * 1.3).min(Okhsl::::max_lightness()); - let mut lightest = base.okhsl; - lightest.lightness = 0.95; - let mut dark = base.okhsl; - dark.lightness = (dark.lightness * 0.75).max(Okhsl::::min_lightness()); - dark.saturation = (dark.saturation * 0.75).max(Okhsl::::min_saturation()); - let mut darker = dark; - darker.lightness = (darker.lightness * 0.66).max(Okhsl::::min_lightness()); - darker.saturation = (darker.saturation * 0.66).max(Okhsl::::min_saturation()); - let mut darkest = darker; - darkest.lightness = 0.1; - darkest.saturation = (darkest.saturation * 0.50).max(Okhsl::::min_saturation()); - Self { - base, - light: light.into(), - lighter: lighter.into(), - lightest: lightest.into(), - dark: dark.into(), - darker: darker.into(), - darkest: darkest.into(), + pub fn from_tui_color (base: Color) -> Self { + Self::from_item_color(ItemColor::from_rgb(base)) } -}); -pub fn okhsl_to_rgb (color: Okhsl) -> Color { - let Srgb { red, green, blue, .. }: Srgb = Srgb::from_color_unclamped(color); - Color::Rgb((red * 255.0) as u8, (green * 255.0) as u8, (blue * 255.0) as u8,) -} -pub fn rgb_to_okhsl (color: Color) -> Okhsl { - if let Color::Rgb(r, g, b) = color { - Okhsl::from_color(Srgb::new(r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0)) - } else { - unreachable!("only Color::Rgb is supported") + pub fn from_item_color (base: ItemColor) -> Self { + let mut light = base.okhsl; + light.lightness = (light.lightness * 1.3).min(1.0); + let mut lighter = light; + lighter.lightness = (lighter.lightness * 1.3).min(1.0); + let mut lightest = base.okhsl; + lightest.lightness = 0.95; + let mut dark = base.okhsl; + dark.lightness = (dark.lightness * 0.75).max(0.0); + dark.saturation = (dark.saturation * 0.75).max(0.0); + let mut darker = dark; + darker.lightness = (darker.lightness * 0.66).max(0.0); + darker.saturation = (darker.saturation * 0.66).max(0.0); + let mut darkest = darker; + darkest.lightness = 0.1; + darkest.saturation = (darkest.saturation * 0.50).max(0.0); + Self { + base, + light: light.into(), + lighter: lighter.into(), + lightest: lightest.into(), + dark: dark.into(), + darker: darker.into(), + darkest: darkest.into(), + } } } +from!(|base: Color| ItemPalette = Self::from_tui_color(base)); +from!(|base: ItemColor|ItemPalette = Self::from_item_color(base));