1use std::io::Write;
34
35use xml::writer::{EventWriter, XmlEvent};
36
37use crate::chart::tag_percent::TagPercent;
38use crate::chart::ColorIter;
39#[cfg(doc)]
40use crate::chart::PieChart;
41use crate::emit_xml;
42
43pub struct Legend<'a> {
45 font_size: f32,
47 colors: ColorIter<'a>
49}
50
51impl<'a> Legend<'a> {
52 pub fn new(font_size: f32, colors: ColorIter<'a>) -> Self { Self { font_size, colors } }
54
55 pub fn font_size(&self) -> f32 { self.font_size }
57
58 fn color<W: Write>(&self, w: &mut EventWriter<W>, clr: &str) -> crate::Result<()> {
64 let size = format!("{}", self.font_size());
65 emit_xml!(w, svg, height: &size, width: &size => {
66 emit_xml!(w, rect, height: &size, width: &size, fill: clr)
67 })
68 }
69
70 fn write_line<W: Write>(
76 &self, w: &mut EventWriter<W>, clr: &str, label: &str
77 ) -> crate::Result<()> {
78 emit_xml!(w, tr => {
79 emit_xml!(w, td => {
80 self.color(w, clr)?;
81 emit_xml!(w, span; label)
82 })
83 })
84 }
85
86 pub fn write<'b, W, Iter>(&self, w: &mut EventWriter<W>, percents: Iter) -> crate::Result<()>
92 where
93 Iter: Iterator<Item = &'b TagPercent>,
94 W: Write
95 {
96 emit_xml!(w, table, class: "legend", style: &format!("font-size: {}px", self.font_size()) => {
97 for (p, clr) in percents.zip(self.colors.clone()) {
98 self.write_line(w, clr, &p.display_label())?;
99 }
100 Ok(())
101 })
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use spectral::prelude::*;
108 use xml::writer::EmitterConfig;
109
110 use super::*;
111
112 #[test]
113 fn test_new() {
114 let legend = Legend::new(12.0, ColorIter::default());
115 assert_that!(legend.font_size()).is_equal_to(&12.0);
116 }
117
118 #[test]
119 fn test_fmt_line() {
120 let colors = ["blue", "green"];
121 let legend = Legend::new(14.0, ColorIter::new(&colors));
122 let tags = [
123 TagPercent::new("Foo", 30.0).unwrap(),
124 TagPercent::new("Bar", 70.0).unwrap()
125 ];
126
127 let mut actual: Vec<u8> = Vec::new();
128 let mut w = EmitterConfig::new()
129 .perform_indent(true)
130 .write_document_declaration(false)
131 .create_writer(&mut actual);
132
133 let expected = r#"<table class="legend" style="font-size: 14px">
134 <tr>
135 <td>
136 <svg height="14" width="14">
137 <rect height="14" width="14" fill="blue" />
138 </svg>
139 <span>30% - Foo</span>
140 </td>
141 </tr>
142 <tr>
143 <td>
144 <svg height="14" width="14">
145 <rect height="14" width="14" fill="green" />
146 </svg>
147 <span>70% - Bar</span>
148 </td>
149 </tr>
150</table>"#;
151 assert_that!(legend.write(&mut w, tags.iter())).is_ok();
152 assert_that!(String::from_utf8(actual).unwrap()).is_equal_to(expected.to_string())
153 }
154}