use std::ops::{Add, AddAssign};
use crate::Computed;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CssGroup {
CssStatic { value: &'static str },
CssDynamic { value: String },
CssMedia { query: String, rules: Vec<String> },
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Css {
pub groups: Vec<CssGroup>,
}
impl Css {
pub fn str(value: &'static str) -> Self {
Self {
groups: vec![CssGroup::CssStatic { value }],
}
}
pub fn string(value: String) -> Self {
Self {
groups: vec![CssGroup::CssDynamic { value }],
}
}
#[must_use]
pub fn push_str(mut self, value: &'static str) -> Self {
self.groups.push(CssGroup::CssStatic { value });
self
}
pub fn push_string(&mut self, value: String) {
self.groups.push(CssGroup::CssDynamic { value })
}
#[must_use]
pub fn extend(mut self, new_css: Self) -> Self {
for item in new_css.groups {
self.groups.push(item);
}
self
}
pub fn extend_inplace(&mut self, new_css: Self) {
for item in new_css.groups {
self.groups.push(item);
}
}
}
impl Add for Css {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
self.extend(rhs)
}
}
impl Add for &Css {
type Output = Css;
fn add(self, rhs: Self) -> Self::Output {
self.clone().extend(rhs.clone())
}
}
impl Add<&Self> for Css {
type Output = Self;
fn add(self, rhs: &Self) -> Self::Output {
self.extend(rhs.clone())
}
}
impl Add<Css> for &Css {
type Output = Css;
fn add(self, rhs: Css) -> Self::Output {
self.clone().extend(rhs)
}
}
impl AddAssign for Css {
fn add_assign(&mut self, other: Self) {
self.extend_inplace(other);
}
}
impl AddAssign<&Self> for Css {
fn add_assign(&mut self, other: &Self) {
self.extend_inplace(other.clone());
}
}
impl AddAssign<&Css> for &mut Css {
fn add_assign(&mut self, other: &Css) {
self.extend_inplace(other.clone());
}
}
impl Add<Css> for Computed<Css> {
type Output = Computed<Css>;
fn add(self, rhs: Css) -> Self::Output {
self.map(move |left| left.extend(rhs.clone()))
}
}
impl Add<Computed<Css>> for Computed<Css> {
type Output = Computed<Css>;
fn add(self, rhs: Computed<Css>) -> Self::Output {
Computed::from({
let left = self.clone();
let right = rhs.clone();
move |ctx| left.get(ctx) + right.get(ctx)
})
}
}
#[cfg(test)]
mod tests {
use super::{Css, CssGroup};
use crate::{Computed, Value, transaction};
#[test]
fn computed_css_add_css() {
let base = Css::str("color: red;");
let extra = Css::str("background: blue;");
let value = Value::new(base.clone());
let comp: Computed<Css> = value.to_computed();
let result = comp + extra.clone();
transaction(|ctx| {
let css = result.get(ctx);
assert_eq!(
css.groups,
vec![
CssGroup::CssStatic {
value: "color: red;"
},
CssGroup::CssStatic {
value: "background: blue;"
}
]
);
});
}
#[test]
fn computed_css_add_computed_css() {
let base = Css::str("color: red;");
let extra = Css::str("background: blue;");
let value1 = Value::new(base.clone());
let value2 = Value::new(extra.clone());
let comp1: Computed<Css> = value1.to_computed();
let comp2: Computed<Css> = value2.to_computed();
let result = comp1 + comp2;
transaction(|ctx| {
let css = result.get(ctx);
assert_eq!(
css.groups,
vec![
CssGroup::CssStatic {
value: "color: red;"
},
CssGroup::CssStatic {
value: "background: blue;"
}
]
);
});
}
}