use crate::dynamic_color::DynamicColor;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TonePolarity {
Darker,
Lighter,
Nearer,
Farther,
RelativeDarker,
RelativeLighter,
}
impl std::fmt::Display for TonePolarity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TonePolarity::Darker => write!(f, "darker"),
TonePolarity::Lighter => write!(f, "lighter"),
TonePolarity::Nearer => write!(f, "nearer"),
TonePolarity::Farther => write!(f, "farther"),
TonePolarity::RelativeDarker => write!(f, "relative_darker"),
TonePolarity::RelativeLighter => write!(f, "relative_lighter"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum DeltaConstraint {
#[default]
Exact,
Nearer,
Farther,
}
impl std::fmt::Display for DeltaConstraint {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DeltaConstraint::Exact => write!(f, "exact"),
DeltaConstraint::Nearer => write!(f, "nearer"),
DeltaConstraint::Farther => write!(f, "farther"),
}
}
}
#[derive(Clone)]
pub struct ToneDeltaPair {
pub role_a: DynamicColor,
pub role_b: DynamicColor,
pub delta: f64,
pub polarity: TonePolarity,
pub stay_together: bool,
pub constraint: DeltaConstraint,
}
impl ToneDeltaPair {
pub fn new(
role_a: DynamicColor,
role_b: DynamicColor,
delta: f64,
polarity: TonePolarity,
stay_together: bool,
constraint: DeltaConstraint,
) -> Self {
ToneDeltaPair {
role_a,
role_b,
delta,
polarity,
stay_together,
constraint,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::dynamic_scheme::DynamicScheme;
use mcu_palettes::TonalPalette;
fn make_test_color(name: &str) -> DynamicColor {
DynamicColor::from_palette(
name,
|_scheme: &DynamicScheme| TonalPalette::from_hue_and_chroma(0.0, 0.0),
Some(|_scheme: &DynamicScheme| 50.0),
false,
None::<fn(&DynamicScheme) -> f64>,
None::<fn(&DynamicScheme) -> Option<DynamicColor>>,
None::<fn(&DynamicScheme) -> Option<DynamicColor>>,
None::<fn(&DynamicScheme) -> Option<crate::ContrastCurve>>,
None::<fn(&DynamicScheme) -> Option<ToneDeltaPair>>,
)
}
#[test]
fn test_tone_polarity_variants() {
assert_eq!(TonePolarity::Darker, TonePolarity::Darker);
assert_eq!(TonePolarity::Lighter, TonePolarity::Lighter);
assert_eq!(TonePolarity::Nearer, TonePolarity::Nearer);
assert_eq!(TonePolarity::Farther, TonePolarity::Farther);
assert_eq!(TonePolarity::RelativeDarker, TonePolarity::RelativeDarker);
assert_eq!(TonePolarity::RelativeLighter, TonePolarity::RelativeLighter);
}
#[test]
fn test_tone_polarity_display() {
assert_eq!(TonePolarity::Darker.to_string(), "darker");
assert_eq!(TonePolarity::Lighter.to_string(), "lighter");
assert_eq!(TonePolarity::Nearer.to_string(), "nearer");
assert_eq!(TonePolarity::Farther.to_string(), "farther");
assert_eq!(TonePolarity::RelativeDarker.to_string(), "relative_darker");
assert_eq!(
TonePolarity::RelativeLighter.to_string(),
"relative_lighter"
);
}
#[test]
fn test_tone_polarity_clone_copy() {
let polarity = TonePolarity::Darker;
let polarity_copy = polarity;
assert_eq!(polarity, polarity_copy);
}
#[test]
fn test_delta_constraint_variants() {
assert_eq!(DeltaConstraint::Exact, DeltaConstraint::Exact);
assert_eq!(DeltaConstraint::Nearer, DeltaConstraint::Nearer);
assert_eq!(DeltaConstraint::Farther, DeltaConstraint::Farther);
}
#[test]
fn test_delta_constraint_display() {
assert_eq!(DeltaConstraint::Exact.to_string(), "exact");
assert_eq!(DeltaConstraint::Nearer.to_string(), "nearer");
assert_eq!(DeltaConstraint::Farther.to_string(), "farther");
}
#[test]
fn test_delta_constraint_default() {
let constraint: DeltaConstraint = Default::default();
assert_eq!(constraint, DeltaConstraint::Exact);
}
#[test]
fn test_delta_constraint_clone_copy() {
let constraint = DeltaConstraint::Exact;
let constraint_copy = constraint;
assert_eq!(constraint, constraint_copy);
}
#[test]
fn test_tone_delta_pair_new() {
let role_a = make_test_color("primary");
let role_b = make_test_color("secondary");
let pair = ToneDeltaPair::new(
role_a,
role_b,
15.0,
TonePolarity::Darker,
true,
DeltaConstraint::Exact,
);
assert_eq!(pair.role_a.name, "primary");
assert_eq!(pair.role_b.name, "secondary");
assert_eq!(pair.delta, 15.0);
assert_eq!(pair.polarity, TonePolarity::Darker);
assert!(pair.stay_together);
assert_eq!(pair.constraint, DeltaConstraint::Exact);
}
#[test]
fn test_tone_delta_pair_with_constraint() {
let role_a = make_test_color("surface");
let role_b = make_test_color("outline");
let pair = ToneDeltaPair::new(
role_a,
role_b,
10.0,
TonePolarity::RelativeLighter,
false,
DeltaConstraint::Farther,
);
assert_eq!(pair.role_a.name, "surface");
assert_eq!(pair.role_b.name, "outline");
assert_eq!(pair.delta, 10.0);
assert_eq!(pair.polarity, TonePolarity::RelativeLighter);
assert!(!pair.stay_together);
assert_eq!(pair.constraint, DeltaConstraint::Farther);
}
#[test]
fn test_tone_delta_pair_clone() {
let role_a = make_test_color("primary");
let role_b = make_test_color("secondary");
let pair = ToneDeltaPair::new(
role_a,
role_b,
15.0,
TonePolarity::Darker,
true,
DeltaConstraint::Nearer,
);
let pair_clone = pair.clone();
assert_eq!(pair.role_a.name, pair_clone.role_a.name);
assert_eq!(pair.role_b.name, pair_clone.role_b.name);
assert_eq!(pair.delta, pair_clone.delta);
assert_eq!(pair.polarity, pair_clone.polarity);
assert_eq!(pair.stay_together, pair_clone.stay_together);
assert_eq!(pair.constraint, pair_clone.constraint);
}
#[test]
fn test_tone_polarity_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(TonePolarity::Darker);
set.insert(TonePolarity::Lighter);
set.insert(TonePolarity::Darker);
assert_eq!(set.len(), 2);
}
#[test]
fn test_delta_constraint_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(DeltaConstraint::Exact);
set.insert(DeltaConstraint::Nearer);
set.insert(DeltaConstraint::Exact);
assert_eq!(set.len(), 2);
}
#[test]
fn test_tone_delta_pair_all_polarities() {
let polarities = vec![
TonePolarity::Darker,
TonePolarity::Lighter,
TonePolarity::Nearer,
TonePolarity::Farther,
TonePolarity::RelativeDarker,
TonePolarity::RelativeLighter,
];
for polarity in polarities {
let role_a = make_test_color("role_a");
let role_b = make_test_color("role_b");
let pair =
ToneDeltaPair::new(role_a, role_b, 10.0, polarity, true, DeltaConstraint::Exact);
assert_eq!(pair.polarity, polarity);
}
}
#[test]
fn test_tone_delta_pair_all_constraints() {
let constraints = vec![
DeltaConstraint::Exact,
DeltaConstraint::Nearer,
DeltaConstraint::Farther,
];
for constraint in constraints {
let role_a = make_test_color("role_a");
let role_b = make_test_color("role_b");
let pair =
ToneDeltaPair::new(role_a, role_b, 10.0, TonePolarity::Darker, true, constraint);
assert_eq!(pair.constraint, constraint);
}
}
}