use crate::{
error::ChartWarning,
layout::{LABEL_SIZE, NumericScale, PlotArea, fit_text, format_value},
metrics::TextMetrics,
scene::{Element, Polyline, Text, TextAnchor},
spec::ChartSpec,
};
pub(crate) fn values(spec: &ChartSpec) -> impl Iterator<Item = f64> + '_ {
spec.references.iter().map(|reference| reference.value)
}
pub(crate) fn push(
spec: &ChartSpec,
scale: NumericScale,
plot: PlotArea,
under: usize,
elements: &mut Vec<Element>,
warnings: &mut Vec<ChartWarning>,
metrics: &impl TextMetrics,
) {
let right = plot.left + plot.width;
let bottom = plot.top + plot.height;
let mut lines = Vec::new();
for (index, reference) in spec.references.iter().enumerate() {
let path = format!("/references/{index}/label");
let (points, x, y, anchor, room) = if plot.vertical_bars {
let y = scale.map(reference.value, bottom, plot.top);
(
vec![(plot.left, y), (right, y)],
right - 4.0,
y - 6.0,
TextAnchor::End,
plot.width / 2.0,
)
} else {
let x = scale.map(reference.value, plot.left, right);
let (label_x, anchor) = if x > plot.left + plot.width * 0.7 {
(x - 4.0, TextAnchor::End)
} else {
(x + 4.0, TextAnchor::Start)
};
(
vec![(x, plot.top), (x, bottom)],
label_x,
plot.top - 6.0,
anchor,
plot.width * 0.4,
)
};
lines.push(Element::Polyline(Polyline {
points,
class: "chartlet-rule",
topic: None,
series_index: None,
style_index: None,
tooltip: Some(format!(
"{}: {}",
reference.label,
format_value(reference.value, spec.number_style())
)),
}));
elements.push(Element::Text(Text {
x,
y,
class: "chartlet-rule-label",
anchor,
content: fit_text(&reference.label, room, LABEL_SIZE, metrics, warnings, &path),
}));
}
elements.splice(under..under, lines);
}