use crate::color::{ApproxBrightness, BasicColor, Color};
use std::ops::Not;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Color2 {
pub foreground: Color,
pub background: Color,
}
impl Color2 {
pub fn new<F, B>(foreground: F, background: B) -> Self
where
F: Into<Color>,
B: Into<Color>,
{
Self { foreground: foreground.into(), background: background.into() }
}
}
impl Default for Color2 {
fn default() -> Self {
Self::new(BasicColor::White, BasicColor::Black)
}
}
impl Not for Color2 {
type Output = Color2;
fn not(self) -> Self::Output {
Color2 { foreground: !self.foreground, background: !self.background }
}
}
pub trait Updater {
fn update(&self, pair: Color2) -> Color2;
}
impl Updater for Color2 {
fn update(&self, _pair: Color2) -> Color2 {
*self
}
}
impl<'this, T> Updater for &'this T
where
T: Updater,
{
fn update(&self, pair: Color2) -> Color2 {
(**self).update(pair)
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UpdateFg(pub Color);
impl Updater for UpdateFg {
fn update(&self, pair: Color2) -> Color2 {
Color2 { foreground: self.0, background: pair.background }
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UpdateBg(pub Color);
impl Updater for UpdateBg {
fn update(&self, pair: Color2) -> Color2 {
Color2 { foreground: pair.foreground, background: self.0 }
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AdaptFgToBg;
impl Updater for AdaptFgToBg {
fn update(&self, pair: Color2) -> Color2 {
Color2 {
background: pair.background,
foreground: pair
.foreground
.with_approx_brightness(pair.background.approx_brightness()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AdaptBgToFg;
impl Updater for AdaptBgToFg {
fn update(&self, pair: Color2) -> Color2 {
Color2 {
foreground: pair.foreground,
background: pair
.background
.with_approx_brightness(pair.foreground.approx_brightness()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ContrastFgWithBg;
impl Updater for ContrastFgWithBg {
fn update(&self, pair: Color2) -> Color2 {
Color2 {
background: pair.background,
foreground: pair
.foreground
.with_approx_brightness(!pair.background.approx_brightness()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ContrastBgWithFg;
impl Updater for ContrastBgWithFg {
fn update(&self, pair: Color2) -> Color2 {
Color2 {
foreground: pair.foreground,
background: pair
.background
.with_approx_brightness(!pair.foreground.approx_brightness()),
}
}
}
macro_rules! impl_tuple {
{} => {};
{ $name:ident $(, $names:ident)* } => {
impl<$name $(, $names)*> Updater for ($name, $($names),*)
where
$name: Updater,
$($names: Updater),*
{
fn update(&self, pair: Color2) -> Color2 {
#[allow(non_snake_case)]
let ($name, $($names),*) = self;
let result = $name.update(pair);
$(let result = $names.update(result);)*
result
}
}
impl_tuple! { $($names),* }
};
}
impl_tuple! {
A0, A1, A2, A3, A4, A5, A6, A7,
B0, B1, B2, B3, B4, B5, B6, B7,
C0, C1, C2, C3, C4, C5, C6, C7,
D0, D1, D2, D3, D4, D5, D6, D7
}