Skip to main content

mcu_dynamiccolor/
variant.rs

1// <FILE>crates/mcu-dynamiccolor/src/variant.rs</FILE> - <DESC>Dynamic color variant enumeration</DESC>
2// <VERS>VERSION: 1.1.0</VERS>
3// <WCTX>Complete implementation of Material Design 3 dynamic color variants</WCTX>
4// <CLOG>Add all 9 variants with documentation, derive standard traits, add comprehensive unit tests</CLOG>
5
6/// Enumeration of dynamic color scheme variants for Material Design 3.
7///
8/// Each variant represents a different approach to generating color schemes
9/// from a source color, balancing different aesthetic and functional properties.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub enum Variant {
12    /// Monochrome variant using only lightness and saturation variations.
13    ///
14    /// Creates a scheme using a single hue, varying only the tone (lightness).
15    /// Useful for minimalist, accessibility-focused designs.
16    Monochrome,
17
18    /// Neutral variant with subtle color shifts.
19    ///
20    /// Generates a scheme that is mostly neutral with very subtle chromatic content.
21    /// Best for conservative, professional designs.
22    Neutral,
23
24    /// Tonal spot variant emphasizing the source color with tonal adjustments.
25    ///
26    /// Uses the source color as an accent with complementary tones.
27    /// This is the most commonly used variant and the default.
28    TonalSpot,
29
30    /// Vibrant variant with saturated, bold colors.
31    ///
32    /// Generates a scheme with maximum saturation while maintaining readability.
33    /// Ideal for energetic, modern designs.
34    Vibrant,
35
36    /// Expressive variant with creative color manipulation.
37    ///
38    /// Uses complex color transformations to create unexpected but harmonious combinations.
39    /// Best for distinctive, artistic designs.
40    Expressive,
41
42    /// Fidelity variant that closely follows the source color's hue and chroma.
43    ///
44    /// Prioritizes accuracy in reproducing the source color's visual characteristics.
45    /// Useful when precise color representation is critical.
46    Fidelity,
47
48    /// Content variant that extracts dominant colors from images.
49    ///
50    /// Designed to work with extracted colors from images or artwork.
51    /// Adapts to the dominant colors in visual content.
52    Content,
53
54    /// Rainbow variant creating a spectrum-inspired color scheme.
55    ///
56    /// Generates colors distributed across the full hue range.
57    /// Best for playful, colorful designs.
58    Rainbow,
59
60    /// Fruit salad variant with warm, saturated colors.
61    ///
62    /// Creates a scheme with warm hues and high saturation, inspired by fruit colors.
63    /// Ideal for fun, appetizing designs.
64    FruitSalad,
65}
66
67impl Default for Variant {
68    /// The default variant is TonalSpot, the most commonly used variant.
69    fn default() -> Self {
70        Variant::TonalSpot
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn test_variant_monochrome() {
80        let variant = Variant::Monochrome;
81        assert_eq!(variant, Variant::Monochrome);
82    }
83
84    #[test]
85    fn test_variant_neutral() {
86        let variant = Variant::Neutral;
87        assert_eq!(variant, Variant::Neutral);
88    }
89
90    #[test]
91    fn test_variant_tonal_spot() {
92        let variant = Variant::TonalSpot;
93        assert_eq!(variant, Variant::TonalSpot);
94    }
95
96    #[test]
97    fn test_variant_vibrant() {
98        let variant = Variant::Vibrant;
99        assert_eq!(variant, Variant::Vibrant);
100    }
101
102    #[test]
103    fn test_variant_expressive() {
104        let variant = Variant::Expressive;
105        assert_eq!(variant, Variant::Expressive);
106    }
107
108    #[test]
109    fn test_variant_fidelity() {
110        let variant = Variant::Fidelity;
111        assert_eq!(variant, Variant::Fidelity);
112    }
113
114    #[test]
115    fn test_variant_content() {
116        let variant = Variant::Content;
117        assert_eq!(variant, Variant::Content);
118    }
119
120    #[test]
121    fn test_variant_rainbow() {
122        let variant = Variant::Rainbow;
123        assert_eq!(variant, Variant::Rainbow);
124    }
125
126    #[test]
127    fn test_variant_fruit_salad() {
128        let variant = Variant::FruitSalad;
129        assert_eq!(variant, Variant::FruitSalad);
130    }
131
132    #[test]
133    fn test_variant_default_is_tonal_spot() {
134        assert_eq!(Variant::default(), Variant::TonalSpot);
135    }
136
137    #[test]
138    fn test_variant_clone() {
139        let variant = Variant::Vibrant;
140        let cloned = variant; // Copy trait, clone is implicit
141        assert_eq!(variant, cloned);
142    }
143
144    #[test]
145    fn test_variant_copy() {
146        let variant = Variant::Expressive;
147        let copied = variant;
148        assert_eq!(variant, copied);
149    }
150
151    #[test]
152    fn test_variant_debug() {
153        let variant = Variant::FruitSalad;
154        let debug_str = format!("{:?}", variant);
155        assert_eq!(debug_str, "FruitSalad");
156    }
157
158    #[test]
159    fn test_all_variants_are_distinct() {
160        let variants = [
161            Variant::Monochrome,
162            Variant::Neutral,
163            Variant::TonalSpot,
164            Variant::Vibrant,
165            Variant::Expressive,
166            Variant::Fidelity,
167            Variant::Content,
168            Variant::Rainbow,
169            Variant::FruitSalad,
170        ];
171
172        for (i, &variant_a) in variants.iter().enumerate() {
173            for &variant_b in variants.iter().skip(i + 1) {
174                assert_ne!(variant_a, variant_b, "Variants should be distinct");
175            }
176        }
177    }
178
179    #[test]
180    fn test_variant_hash_consistency() {
181        use std::collections::hash_map::DefaultHasher;
182        use std::hash::{Hash, Hasher};
183
184        let variant1 = Variant::TonalSpot;
185        let variant2 = Variant::TonalSpot;
186
187        let mut hasher1 = DefaultHasher::new();
188        variant1.hash(&mut hasher1);
189        let hash1 = hasher1.finish();
190
191        let mut hasher2 = DefaultHasher::new();
192        variant2.hash(&mut hasher2);
193        let hash2 = hasher2.finish();
194
195        assert_eq!(hash1, hash2, "Equal variants should have equal hashes");
196    }
197
198    #[test]
199    fn test_variant_in_collection() {
200        use std::collections::HashSet;
201
202        let mut set = HashSet::new();
203        set.insert(Variant::TonalSpot);
204        set.insert(Variant::Vibrant);
205        set.insert(Variant::TonalSpot); // Duplicate
206
207        assert_eq!(set.len(), 2);
208        assert!(set.contains(&Variant::TonalSpot));
209        assert!(set.contains(&Variant::Vibrant));
210        assert!(!set.contains(&Variant::Rainbow));
211    }
212}
213
214// <FILE>crates/mcu-dynamiccolor/src/variant.rs</FILE> - <DESC>Dynamic color variant enumeration</DESC>
215// <VERS>END OF VERSION: 1.1.0</VERS>