use std::collections::HashMap;
use super::prop_validation::{self, types, CssAttributeValue, CssStyleAttribute};
use crate::unit::Unit;
#[derive(Debug, Clone)]
pub enum CssStyleProperty {
Color(CssAttributeValue<types::CssColor>),
BackgroundColor(CssAttributeValue<types::CssBackgroundColor>),
Width(CssAttributeValue<types::CssWidth>),
Height(CssAttributeValue<types::CssHeight>),
Padding(
CssAttributeValue<types::CssPadding>,
CssAttributeValue<types::CssPadding>,
CssAttributeValue<types::CssPadding>,
CssAttributeValue<types::CssPadding>,
),
Spacing(
CssAttributeValue<types::CssSpacing>,
CssAttributeValue<types::CssSpacing>,
CssAttributeValue<types::CssSpacing>,
CssAttributeValue<types::CssSpacing>,
),
FontFamily(CssAttributeValue<types::CssFontFamily>),
FontSize(CssAttributeValue<types::CssFontSize>),
LineHeight(CssAttributeValue<types::CssLineHeight>),
WordBreak(CssAttributeValue<types::CssWordBreak>),
MaxWidth(CssAttributeValue<types::CssMaxWidth>),
MaxHeight(CssAttributeValue<types::CssMaxHeight>),
JustifyContent(CssAttributeValue<types::CssJustifyContent>),
VerticalAlign(CssAttributeValue<types::CssVerticalAlign>),
OverflowX(CssAttributeValue<types::CssOverflowX>),
OverflowY(CssAttributeValue<types::CssOverflowY>),
ObjectFit(CssAttributeValue<types::CssObjectFit>),
ImageRendering(CssAttributeValue<types::CssImageRendering>),
Opacity(CssAttributeValue<types::CssOpacity>),
UnknownProperty(String, Vec<Vec<Unit>>),
}
pub type IsImportant = bool;
#[derive(Debug, Clone, Default)]
pub struct CssStyleProperties(pub Vec<(CssStyleProperty, IsImportant)>);
impl CssStyleProperty {
pub fn from_attribute_values(values: Box<[CssStyleAttribute]>) -> Self {
match &*values {
[CssStyleAttribute::Color(val)] => Self::Color(val.clone()),
[CssStyleAttribute::BackgroundColor(val)] => Self::BackgroundColor(val.clone()),
[CssStyleAttribute::Width(val)] => Self::Width(val.clone()),
[CssStyleAttribute::Height(val)] => Self::Height(val.clone()),
[CssStyleAttribute::MaxWidth(val)] => Self::MaxWidth(val.clone()),
[CssStyleAttribute::MaxHeight(val)] => Self::MaxHeight(val.clone()),
[CssStyleAttribute::LineHeight(val)] => Self::LineHeight(val.clone()),
[CssStyleAttribute::VerticalAlign(val)] => Self::VerticalAlign(val.clone()),
[CssStyleAttribute::Padding(val)] => {
Self::Padding(val.clone(), val.clone(), val.clone(), val.clone())
}
[CssStyleAttribute::Padding(val1), CssStyleAttribute::Padding(val2)] => {
Self::Padding(val1.clone(), val2.clone(), val1.clone(), val2.clone())
}
[CssStyleAttribute::Padding(val1), CssStyleAttribute::Padding(val2), CssStyleAttribute::Padding(val3)] => {
Self::Padding(val1.clone(), val2.clone(), val3.clone(), val2.clone())
}
[CssStyleAttribute::Padding(val1), CssStyleAttribute::Padding(val2), CssStyleAttribute::Padding(val3), CssStyleAttribute::Padding(val4)] => {
Self::Padding(val1.clone(), val2.clone(), val3.clone(), val4.clone())
}
[CssStyleAttribute::Spacing(val)] => {
Self::Spacing(val.clone(), val.clone(), val.clone(), val.clone())
}
[CssStyleAttribute::Spacing(val1), CssStyleAttribute::Spacing(val2)] => {
Self::Spacing(val1.clone(), val2.clone(), val1.clone(), val2.clone())
}
[CssStyleAttribute::Spacing(val1), CssStyleAttribute::Spacing(val2), CssStyleAttribute::Spacing(val3)] => {
Self::Spacing(val1.clone(), val2.clone(), val3.clone(), val2.clone())
}
[CssStyleAttribute::Spacing(val1), CssStyleAttribute::Spacing(val2), CssStyleAttribute::Spacing(val3), CssStyleAttribute::Spacing(val4)] => {
Self::Spacing(val1.clone(), val2.clone(), val3.clone(), val4.clone())
}
[CssStyleAttribute::FontFamily(val)] => Self::FontFamily(val.clone()),
[CssStyleAttribute::FontSize(val)] => Self::FontSize(val.clone()),
[CssStyleAttribute::UnknownProperty(prop_name, prop_values)] => {
Self::UnknownProperty(prop_name.clone(), prop_values.clone())
}
_ => todo!("Update structure unknown: {values:?}"),
}
}
}
impl std::ops::Deref for CssStyleProperties {
type Target = Vec<(CssStyleProperty, bool)>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for CssStyleProperties {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl std::fmt::Display for CssStyleProperties {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for (item, important) in self.iter() {
write!(f, " ");
match item {
CssStyleProperty::UnknownProperty(prop_name, prop_values) => {
let prop_string = prop_values.iter()
.map(|group| {
group.iter()
.map(|values| values.to_string())
.collect::<Vec<_>>()
.join(" ")
})
.collect::<Vec<_>>()
.join(", ")
;
write!(f, "{prop_name}: {prop_string} /* this prop is unknown and has no validation or guarantees */")
},
CssStyleProperty::Color(css_attribute_value)
=> write!(f, "color: {css_attribute_value}"),
CssStyleProperty::BackgroundColor(css_attribute_value)
=> write!(f, "background-color: {css_attribute_value}"),
CssStyleProperty::Width(css_attribute_value)
=> write!(f, "width: {css_attribute_value}"),
CssStyleProperty::Height(css_attribute_value)
=> write!(f, "height: {css_attribute_value}"),
CssStyleProperty::Padding(css_attribute_value1, css_attribute_value2, css_attribute_value3, css_attribute_value4)
=> write!(f, "padding: {css_attribute_value1} {css_attribute_value2} {css_attribute_value3} {css_attribute_value4}"),
CssStyleProperty::Spacing(css_attribute_value1, css_attribute_value2, css_attribute_value3, css_attribute_value4)
=> write!(f, "spacing: {css_attribute_value1} {css_attribute_value2} {css_attribute_value3} {css_attribute_value4}"),
CssStyleProperty::FontFamily(css_attribute_value)
=> write!(f, "font-family: {css_attribute_value}"),
CssStyleProperty::FontSize(css_attribute_value)
=> write!(f, "font-size: {css_attribute_value}"),
CssStyleProperty::LineHeight(css_attribute_value)
=> write!(f, "line-height: {css_attribute_value}"),
CssStyleProperty::WordBreak(css_attribute_value)
=> write!(f, "word-break: {css_attribute_value}"),
CssStyleProperty::MaxWidth(css_attribute_value)
=> write!(f, "max-width: {css_attribute_value}"),
CssStyleProperty::MaxHeight(css_attribute_value)
=> write!(f, "max-height: {css_attribute_value}"),
CssStyleProperty::JustifyContent(css_attribute_value)
=> write!(f, "justify-content: {css_attribute_value}"),
CssStyleProperty::VerticalAlign(css_attribute_value)
=> write!(f, "vertical-align: {css_attribute_value}"),
CssStyleProperty::OverflowX(css_attribute_value)
=> write!(f, "overflow-x: {css_attribute_value}"),
CssStyleProperty::OverflowY(css_attribute_value)
=> write!(f, "overflow-y: {css_attribute_value}"),
CssStyleProperty::ObjectFit(css_attribute_value)
=> write!(f, "object-fit: {css_attribute_value}"),
CssStyleProperty::ImageRendering(css_attribute_value)
=> write!(f, "image-rendering: {css_attribute_value}"),
CssStyleProperty::Opacity(css_attribute_value)
=> write!(f, "opacity: {css_attribute_value}"),
};
if *important {
write!(f, " !important");
}
writeln!(f, ";");
}
Ok(())
}
}