use std::ops::Index;
pub struct Palette {
pub name: &'static str,
colors: Vec<String>,
}
impl Palette {
pub fn custom(name: &'static str, colors: Vec<String>) -> Self {
Self { name, colors }
}
pub fn len(&self) -> usize {
self.colors.len()
}
pub fn is_empty(&self) -> bool {
self.colors.is_empty()
}
pub fn colors(&self) -> &[String] {
&self.colors
}
pub fn iter(&self) -> PaletteCycleIter<'_> {
PaletteCycleIter { palette: self, index: 0 }
}
pub fn wong() -> Self {
Self {
name: "wong",
colors: vec![
"#E69F00", "#56B4E9", "#009E73", "#F0E442",
"#0072B2", "#D55E00", "#CC79A7", "#000000",
].into_iter().map(Into::into).collect(),
}
}
pub fn okabe_ito() -> Self {
let mut p = Self::wong();
p.name = "okabe_ito";
p
}
pub fn tol_bright() -> Self {
Self {
name: "tol_bright",
colors: vec![
"#4477AA", "#EE6677", "#228833", "#CCBB44",
"#66CCEE", "#AA3377", "#BBBBBB",
].into_iter().map(Into::into).collect(),
}
}
pub fn tol_muted() -> Self {
Self {
name: "tol_muted",
colors: vec![
"#CC6677", "#332288", "#DDCC77", "#117733",
"#88CCEE", "#882255", "#44AA99", "#999933",
"#AA4499", "#DDDDDD",
].into_iter().map(Into::into).collect(),
}
}
pub fn tol_light() -> Self {
Self {
name: "tol_light",
colors: vec![
"#77AADD", "#EE8866", "#EEDD88", "#FFAABB",
"#99DDFF", "#44BB99", "#BBCC33", "#AAAA00",
"#DDDDDD",
].into_iter().map(Into::into).collect(),
}
}
pub fn ibm() -> Self {
Self {
name: "ibm",
colors: vec![
"#648FFF", "#785EF0", "#DC267F", "#FE6100", "#FFB000",
].into_iter().map(Into::into).collect(),
}
}
pub fn deuteranopia() -> Self {
let mut p = Self::wong();
p.name = "deuteranopia";
p
}
pub fn protanopia() -> Self {
let mut p = Self::wong();
p.name = "protanopia";
p
}
pub fn tritanopia() -> Self {
let mut p = Self::tol_bright();
p.name = "tritanopia";
p
}
pub fn category10() -> Self {
Self {
name: "category10",
colors: vec![
"#1f77b4", "#ff7f0e", "#2ca02c", "#d62728",
"#9467bd", "#8c564b", "#e377c2", "#7f7f7f",
"#bcbd22", "#17becf",
].into_iter().map(Into::into).collect(),
}
}
pub fn pastel() -> Self {
Self {
name: "pastel",
colors: vec![
"#aec7e8", "#ffbb78", "#98df8a", "#ff9896",
"#c5b0d5", "#c49c94", "#f7b6d2", "#c7c7c7",
"#dbdb8d", "#9edae5",
].into_iter().map(Into::into).collect(),
}
}
pub fn bold() -> Self {
Self {
name: "bold",
colors: vec![
"#e41a1c", "#377eb8", "#4daf4a", "#984ea3",
"#ff7f00", "#a65628", "#f781bf", "#999999",
"#66c2a5", "#fc8d62",
].into_iter().map(Into::into).collect(),
}
}
}
impl Default for Palette {
fn default() -> Self {
Self::category10()
}
}
impl Index<usize> for Palette {
type Output = str;
fn index(&self, index: usize) -> &str {
&self.colors[index % self.colors.len()]
}
}
pub struct PaletteCycleIter<'a> {
palette: &'a Palette,
index: usize,
}
impl<'a> Iterator for PaletteCycleIter<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<Self::Item> {
let color = &self.palette[self.index];
self.index += 1;
Some(color)
}
}