1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use cssparser::*;
use super::border::{BorderStyle, GenericBorder, BorderSideWidth};
use crate::traits::{Parse, ToCss, PropertyHandler};
use crate::values::color::CssColor;
use super::Property;
use crate::declaration::DeclarationList;
use crate::printer::Printer;

#[derive(Debug, Clone, PartialEq)]
pub enum OutlineStyle {
  Auto,
  BorderStyle(BorderStyle)
}

impl Parse for OutlineStyle {
  fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ()>> {
    if let Ok(border_style) = input.try_parse(BorderStyle::parse) {
      return Ok(OutlineStyle::BorderStyle(border_style))
    }

    input.expect_ident_matching("auto")?;
    Ok(OutlineStyle::Auto)
  }
}

impl ToCss for OutlineStyle {
  fn to_css<W>(&self, dest: &mut Printer<W>) -> std::fmt::Result where W: std::fmt::Write {
    match self {
      OutlineStyle::Auto => dest.write_str("auto"),
      OutlineStyle::BorderStyle(border_style) => border_style.to_css(dest)
    }
  }
}

impl Default for OutlineStyle {
  fn default() -> OutlineStyle {
    OutlineStyle::BorderStyle(BorderStyle::None)
  }
}

pub type Outline = GenericBorder<OutlineStyle>;

#[derive(Default, Debug)]
pub(crate) struct OutlineHandler {
  pub width: Option<BorderSideWidth>,
  pub style: Option<OutlineStyle>,
  pub color: Option<CssColor>
}

impl PropertyHandler for OutlineHandler {
  fn handle_property(&mut self, property: &Property, _: &mut DeclarationList) -> bool {
    use Property::*;

    match property {
      OutlineColor(val) => self.color = Some(val.clone()),
      OutlineStyle(val) => self.style = Some(val.clone()),
      OutlineWidth(val) => self.width = Some(val.clone()),
      Outline(val) => {
        self.color = Some(val.color.clone());
        self.style = Some(val.style.clone());
        self.width = Some(val.width.clone());
      }
      _ => return false
    }

    true
  }

  fn finalize(&mut self, decls: &mut DeclarationList) {
    let width = std::mem::take(&mut self.width);
    let style = std::mem::take(&mut self.style);
    let color = std::mem::take(&mut self.color);
    if width.is_some() && style.is_some() && color.is_some() {
      decls.push(Property::Outline(Outline {
        width: width.unwrap(),
        style: style.unwrap(),
        color: color.unwrap()
      }))
    } else {
      if let Some(color) = color {
        decls.push(Property::OutlineColor(color))
      }

      if let Some(style) = style {
        decls.push(Property::OutlineStyle(style))
      }

      if let Some(width) = width {
        decls.push(Property::OutlineWidth(width))
      }
    }
  }
}