1pub trait ToXml {
8 fn to_xml(&self) -> String;
10
11 fn write_xml(&self, writer: &mut String) {
13 writer.push_str(&self.to_xml());
14 }
15}
16
17pub trait XmlElement: ToXml {
19 fn tag_name(&self) -> &'static str;
21
22 fn namespace_prefix(&self) -> &'static str {
24 ""
25 }
26
27 fn qualified_name(&self) -> String {
29 let prefix = self.namespace_prefix();
30 if prefix.is_empty() {
31 self.tag_name().to_string()
32 } else {
33 format!("{}:{}", prefix, self.tag_name())
34 }
35 }
36}
37
38pub trait Positioned {
40 fn x(&self) -> u32;
42
43 fn y(&self) -> u32;
45
46 fn set_position(&mut self, x: u32, y: u32);
48}
49
50pub trait Sized {
52 fn width(&self) -> u32;
54
55 fn height(&self) -> u32;
57
58 fn set_size(&mut self, width: u32, height: u32);
60}
61
62pub trait Styled {
64 fn color(&self) -> Option<&str>;
66
67 fn set_color(&mut self, color: &str);
69}
70
71#[derive(Clone, Debug, PartialEq, Eq)]
73#[allow(dead_code)]
74pub struct RgbColor {
75 pub r: u8,
76 pub g: u8,
77 pub b: u8,
78}
79
80#[allow(dead_code)]
81impl RgbColor {
82 pub fn new(r: u8, g: u8, b: u8) -> Self {
83 Self { r, g, b }
84 }
85
86 pub fn from_hex(hex: &str) -> Option<Self> {
88 let hex = hex.trim_start_matches('#');
89 if hex.len() != 6 {
90 return None;
91 }
92 let r = u8::from_str_radix(&hex[0..2], 16).ok()?;
93 let g = u8::from_str_radix(&hex[2..4], 16).ok()?;
94 let b = u8::from_str_radix(&hex[4..6], 16).ok()?;
95 Some(Self { r, g, b })
96 }
97
98 pub fn to_hex(&self) -> String {
100 format!("{:02X}{:02X}{:02X}", self.r, self.g, self.b)
101 }
102}
103
104impl ToXml for RgbColor {
105 fn to_xml(&self) -> String {
106 format!(r#"<a:srgbClr val="{}"/>"#, self.to_hex())
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test_rgb_color_from_hex() {
116 let color = RgbColor::from_hex("FF0000").unwrap();
117 assert_eq!(color.r, 255);
118 assert_eq!(color.g, 0);
119 assert_eq!(color.b, 0);
120
121 let color = RgbColor::from_hex("#00FF00").unwrap();
122 assert_eq!(color.to_hex(), "00FF00");
123 }
124
125 #[test]
126 fn test_rgb_color_to_xml() {
127 let color = RgbColor::new(255, 0, 0);
128 assert_eq!(color.to_xml(), r#"<a:srgbClr val="FF0000"/>"#);
129 }
130}