diff --git a/cursive-core/src/style/color.rs b/cursive-core/src/style/color.rs index d4589e80..bcb60fe7 100644 --- a/cursive-core/src/style/color.rs +++ b/cursive-core/src/style/color.rs @@ -95,6 +95,160 @@ impl From for BaseColor { } } +/// RGB color. +/// +/// If `T = u8` this is a 24-bit color. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct Rgb { + /// Red component. + pub r: T, + + /// Green component. + pub g: T, + + /// Blue component. + pub b: T, +} + +impl From<[T; 3]> for Rgb { + fn from(o: [T; 3]) -> Self { + let [r, g, b] = o; + Self { r, g, b } + } +} + +impl From for Rgb { + fn from(hex: u32) -> Self { + Self::from_u32(hex) + } +} + +impl From> for Rgb { + fn from(o: Rgb) -> Self { + o.as_f32() + } +} + +impl Rgb { + /// Create a new Rgb from individual r, g and b values. + pub fn new(r: T, g: T, b: T) -> Self { + Self { r, g, b } + } + + /// Run a closure on each component pair. + pub fn zip_map(a: Self, b: Rgb, mut f: impl FnMut(T, U) -> V) -> Rgb { + Self::zip(a, b).map(|(a, b)| f(a, b)) + } + + /// Zip two Rgb into a single Rgb of tuples. + pub fn zip(a: Self, b: Rgb) -> Rgb<(T, U)> { + Rgb { + r: (a.r, b.r), + g: (a.g, b.g), + b: (a.b, b.b), + } + } + + /// Apply a closure on each component. + pub fn map(self, mut f: impl FnMut(T) -> U) -> Rgb { + Rgb { + r: f(self.r), + g: f(self.g), + b: f(self.b), + } + } +} + +impl Rgb { + /// Casts each component to u8. + pub fn as_u8(self) -> Rgb { + self.map(|x| x as u8) + } + + /// Convert to a Color. + pub fn as_color(self) -> Color { + self.as_u8().as_color() + } +} + +impl Rgb<(f32, f32)> { + /// Interpolate each component individually. + pub fn interpolate(self, x: f32) -> Rgb { + self.map(|(a, b)| a * (1f32 - x) + b * x) + } +} + +impl Rgb<(u8, u8)> { + /// Cast each component to a tuple of f32. + pub fn as_f32(self) -> Rgb<(f32, f32)> { + self.map(|(x, y)| (x as f32, y as f32)) + } +} + +impl Rgb { + /// Convert to a Color. + pub fn as_color(self) -> Color { + Color::Rgb(self.r, self.g, self.b) + } + + /// Return a Rgb using the lowest 24 bits. + /// + /// This can parse hex codes like `0xFF0000`. + pub const fn from_u32(hex: u32) -> Self { + let r = ((hex & 0xFF0000) >> 16) as u8; + let g = ((hex & 0x00FF00) >> 8) as u8; + let b = (hex & 0x0000FF) as u8; + Self { r, g, b } + } + + /// Cast each component to f32. + pub fn as_f32(self) -> Rgb { + self.map(|x| x as f32) + } + + /// Returns a pure red RGB color. + pub const fn red() -> Self { + Self::from_u32(0xFF0000) + } + + /// Returns a pure green RGB color. + pub const fn green() -> Self { + Self::from_u32(0x00FF00) + } + + /// Returns a pure blue RGB color. + pub const fn blue() -> Self { + Self::from_u32(0x0000FF) + } + + /// Returns a pure yellow RGB color. + pub const fn yellow() -> Self { + Self::from_u32(0xFFFF00) + } + /// Returns a pure magenta RGB color. + pub const fn magenta() -> Self { + Self::from_u32(0xFF00FF) + } + /// Returns a pure cyan RGB color. + pub const fn cyan() -> Self { + Self::from_u32(0x00FFFF) + } + /// Returns a pure white RGB color. + pub const fn white() -> Self { + Self::from_u32(0xFFFFFF) + } + /// Returns a pure black RGB color. + pub const fn black() -> Self { + Self::from_u32(0x000000) + } +} + +impl From> for Color { + fn from(rgb: Rgb) -> Self { + rgb.as_color() + } +} + /// Represents a color used by the theme. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum Color { diff --git a/cursive-core/src/style/gradient/mod.rs b/cursive-core/src/style/gradient/mod.rs index babbde98..f8239f87 100644 --- a/cursive-core/src/style/gradient/mod.rs +++ b/cursive-core/src/style/gradient/mod.rs @@ -1,154 +1,5 @@ //! Gradients -use crate::style::Color; -use crate::{Vec2, XY}; - -/// RGB color. -/// -/// If `T = u8` this is a 24-bit color. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct Rgb { - /// Red component. - pub r: T, - - /// Green component. - pub g: T, - - /// Blue component. - pub b: T, -} - -impl From<[T; 3]> for Rgb { - fn from(o: [T; 3]) -> Self { - let [r, g, b] = o; - Self { r, g, b } - } -} - -impl From for Rgb { - fn from(hex: u32) -> Self { - Self::from_u32(hex) - } -} - -impl From> for Rgb { - fn from(o: Rgb) -> Self { - o.as_f32() - } -} - -impl Rgb { - /// Create a new Rgb from individual r, g and b values. - pub fn new(r: T, g: T, b: T) -> Self { - Self { r, g, b } - } - - /// Run a closure on each component pair. - pub fn zip_map(a: Self, b: Rgb, mut f: impl FnMut(T, U) -> V) -> Rgb { - Self::zip(a, b).map(|(a, b)| f(a, b)) - } - - /// Zip two Rgb into a single Rgb of tuples. - pub fn zip(a: Self, b: Rgb) -> Rgb<(T, U)> { - Rgb { - r: (a.r, b.r), - g: (a.g, b.g), - b: (a.b, b.b), - } - } - - /// Apply a closure on each component. - pub fn map(self, mut f: impl FnMut(T) -> U) -> Rgb { - Rgb { - r: f(self.r), - g: f(self.g), - b: f(self.b), - } - } -} - -impl Rgb { - /// Casts each component to u8. - pub fn as_u8(self) -> Rgb { - self.map(|x| x as u8) - } - - /// Convert to a Color. - pub fn as_color(self) -> Color { - self.as_u8().as_color() - } -} - -impl Rgb<(f32, f32)> { - /// Interpolate each component individually. - pub fn interpolate(self, x: f32) -> Rgb { - self.map(|(a, b)| a * (1f32 - x) + b * x) - } -} - -impl Rgb<(u8, u8)> { - /// Cast each component to a tuple of f32. - pub fn as_f32(self) -> Rgb<(f32, f32)> { - self.map(|(x, y)| (x as f32, y as f32)) - } -} - -impl Rgb { - /// Convert to a Color. - pub fn as_color(self) -> Color { - Color::Rgb(self.r, self.g, self.b) - } - - /// Return a Rgb using the lowest 24 bits. - /// - /// This can parse hex codes like `0xFF0000`. - pub const fn from_u32(hex: u32) -> Self { - let r = ((hex & 0xFF0000) >> 16) as u8; - let g = ((hex & 0x00FF00) >> 8) as u8; - let b = (hex & 0x0000FF) as u8; - Self { r, g, b } - } - - /// Cast each component to f32. - pub fn as_f32(self) -> Rgb { - self.map(|x| x as f32) - } - - /// Returns a pure red RGB color. - pub const fn red() -> Self { - Self::from_u32(0xFF0000) - } - - /// Returns a pure green RGB color. - pub const fn green() -> Self { - Self::from_u32(0x00FF00) - } - - /// Returns a pure blue RGB color. - pub const fn blue() -> Self { - Self::from_u32(0x0000FF) - } - - /// Returns a pure yellow RGB color. - pub const fn yellow() -> Self { - Self::from_u32(0xFFFF00) - } - /// Returns a pure magenta RGB color. - pub const fn magenta() -> Self { - Self::from_u32(0xFF00FF) - } - /// Returns a pure cyan RGB color. - pub const fn cyan() -> Self { - Self::from_u32(0x00FFFF) - } - /// Returns a pure white RGB color. - pub const fn white() -> Self { - Self::from_u32(0xFFFFFF) - } - /// Returns a pure black RGB color. - pub const fn black() -> Self { - Self::from_u32(0x000000) - } -} +use crate::{style::Rgb, Vec2, XY}; /// A linear gradient interpolating between 0 and 1. pub struct Linear { diff --git a/cursive-core/src/style/mod.rs b/cursive-core/src/style/mod.rs index fa6282ce..852c3660 100644 --- a/cursive-core/src/style/mod.rs +++ b/cursive-core/src/style/mod.rs @@ -134,7 +134,7 @@ mod palette; mod style; pub use self::border_style::BorderStyle; -pub use self::color::{BaseColor, Color}; +pub use self::color::{BaseColor, Color, Rgb}; pub use self::color_pair::ColorPair; pub use self::color_style::{ColorStyle, ColorType}; pub use self::effect::{ConcreteEffects, Effect, EffectStatus, Effects}; diff --git a/cursive-core/src/utils/markup/gradient.rs b/cursive-core/src/utils/markup/gradient.rs index 80df9be5..c745bc2b 100644 --- a/cursive-core/src/utils/markup/gradient.rs +++ b/cursive-core/src/utils/markup/gradient.rs @@ -1,9 +1,6 @@ //! Generate StyledString with gradients. -use crate::style::{ - gradient::{Linear, Rgb}, - ColorStyle, Style, -}; +use crate::style::{gradient::Linear, ColorStyle, Rgb, Style}; use crate::utils::markup::{StyledIndexedSpan, StyledString}; use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthStr; @@ -95,7 +92,7 @@ where #[cfg(test)] mod tests { use super::decorate_front; - use crate::style::gradient::Rgb; + use crate::style::Rgb; use crate::utils::markup::cursup; #[test] diff --git a/cursive/examples/gradient.rs b/cursive/examples/gradient.rs index f10f3ff4..ed83fbab 100644 --- a/cursive/examples/gradient.rs +++ b/cursive/examples/gradient.rs @@ -1,9 +1,12 @@ use cursive::event::EventResult; -use cursive::style::gradient::{Angled, Bilinear, Linear, Radial, Rgb}; +use cursive::style::{ + gradient::{Angled, Bilinear, Linear, Radial}, + Rgb, +}; use cursive::traits::*; use cursive::utils::markup::gradient; use cursive::views::{Dialog, GradientView, OnEventView, TextView}; -use cursive::{Cursive, XY}; +use cursive::XY; fn main() { let mut siv = cursive::default();