dbg!(AxisFacets::new(&faceting[Axis2::Y]));
let ny_facets = y_facets.len();
- let mut x_headings = FacetHeadings::new(
- Side::Bottom,
- &faceting[Axis2::X],
- rect.0[Axis2::X].length(),
- graph.x_dimension(),
- &mut font_metrics,
- );
- let mut y_headings = FacetHeadings::new(
- Side::Top,
- &faceting[Axis2::Y],
- rect.0[Axis2::Y].length() - x_headings.total_height(),
- graph.y_dimension(),
- &mut font_metrics,
- );
- for _ in 0..5 {
- println!(
- "{:.0} x {:.0}",
- x_headings.total_height(),
- y_headings.total_height()
- );
- x_headings = FacetHeadings::new(
- Side::Bottom,
- &faceting[Axis2::X],
- rect.0[Axis2::X].length() - y_headings.total_height(),
- graph.x_dimension(),
- &mut font_metrics,
- );
- y_headings = FacetHeadings::new(
- Side::Top,
- &faceting[Axis2::Y],
- rect.0[Axis2::Y].length() - x_headings.total_height(),
- graph.y_dimension(),
- &mut font_metrics,
- );
- }
+ let mut heading_heights = EnumMap::from_fn(|_| 0.0);
+ let mut iteration = 0..5;
+ let headings = loop {
+ let headings = EnumMap::from_fn(|axis| {
+ let heading = FacetHeadings::new(
+ Side::default_for_axis(axis),
+ &faceting[axis],
+ rect.0[axis].length() - heading_heights[!axis],
+ graph.axis_dimension(axis),
+ &mut font_metrics,
+ );
+ heading_heights[axis] = heading.total_height();
+ heading
+ });
+ if iteration.next().is_none() {
+ break headings;
+ }
+ };
let inner = rect.inset(
[
- y_headings.height(Side::Top),
- y_headings.height(Side::Bottom),
+ headings[Axis2::Y].height(Side::Top),
+ headings[Axis2::Y].height(Side::Bottom),
],
[
- x_headings.height(Side::Top),
- x_headings.height(Side::Bottom),
+ headings[Axis2::X].height(Side::Top),
+ headings[Axis2::X].height(Side::Bottom),
],
);
- let top = x_headings
+ let top = headings[Axis2::X]
.render(Side::Top)
.set("c:description", "X axis facets above graph")
.set(
"transform",
format!("translate({} {})", inner.0[Axis2::X].0, rect.0[Axis2::Y].0),
);
- let bottom = x_headings
+ let bottom = headings[Axis2::X]
.render(Side::Bottom)
.set("c:description", "X axis facets below graph")
.set(
format!("translate({} {})", inner.0[Axis2::X].0, inner.0[Axis2::Y].1,),
);
- let left = y_headings
+ let left = headings[Axis2::Y]
.render(Side::Top)
.set("c:description", "Y axis facets on left side of graph")
.set("transform", {
let y = inner.0[Axis2::Y].1;
format!("rotate(-90 {x} {y}) translate({x} {y})")
});
- let right = y_headings
+ let right = headings[Axis2::Y]
.render(Side::Bottom)
.set("c:description", "Y axis facets on right side of graph")
.set("transform", {
self.coordinates().next()?.dimensions().skip(1).next()
}
+ fn axis_dimension(&self, axis: Axis2) -> Option<&Dimension> {
+ match axis {
+ Axis2::X => self.x_dimension(),
+ Axis2::Y => self.y_dimension(),
+ }
+ }
+
fn elements(&self) -> impl Iterator<Item = (&RawElement, Graphic)> {
self.children.iter().filter_map(|child| child.element())
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
struct Axis {
- /// For an X-axis, false means that the axis appears below the graph, true
- /// means that it appears above the graph.
+ /// Controls where the axis labels and tick marks appear:
+ ///
+ /// - X-axis: false means below the graph, true means above the graph.
///
- /// For a Y-axis, false means that the axis appears to the left of the
- /// graph, true means that it appears to the right of the graph.
+ /// - Y-axis: false means to the left of the graph, true to the right of the
+ /// graph.
#[serde(rename = "@opposite", default)]
opposite: bool,
Bottom,
}
+impl Side {
+ fn default_for_axis(axis: Axis2) -> Self {
+ match axis {
+ Axis2::X => Side::Bottom,
+ Axis2::Y => Side::Top,
+ }
+ }
+}
+
impl Not for Side {
type Output = Side;