pub const TABLE_COLS: usize = 13;
pub const TABLE_ROWS: usize = 16;
pub const PANEL_ROW: u16 = 9;
pub const PANEL_COL: u16 = 7;
pub const PLOT_LEFT: u16 = 3;
pub const PLOT_RIGHT: u16 = 11;
pub const PLOT_TOP: u16 = 5;
pub const PLOT_BOTTOM: u16 = 13;
const PLOT_COL_SPAN: u16 = PLOT_RIGHT - PLOT_LEFT + 1;
pub const MARGIN_TOP_ROW: u16 = 1;
pub const MARGIN_BOTTOM_ROW: u16 = TABLE_ROWS as u16;
pub const MARGIN_LEFT_COL: u16 = 1;
pub const MARGIN_RIGHT_COL: u16 = TABLE_COLS as u16;
pub const PADDING_TOP_ROW: u16 = 2;
pub const PADDING_BOTTOM_ROW: u16 = TABLE_ROWS as u16 - 1;
pub const PADDING_LEFT_COL: u16 = 2;
pub const PADDING_RIGHT_COL: u16 = TABLE_COLS as u16 - 1;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Slot {
Panel,
Background,
AxisTop,
AxisTopTitle,
StripTop,
LegendTop,
AxisBottom,
AxisBottomTitle,
StripBottom,
LegendBottom,
AxisLeft,
AxisLeftTitle,
StripLeft,
LegendLeft,
AxisRight,
AxisRightTitle,
StripRight,
LegendRight,
Title,
Subtitle,
Caption,
}
impl Slot {
pub const fn name(self) -> &'static str {
match self {
Slot::Panel => "panel",
Slot::Background => "background",
Slot::AxisTop => "axis_top",
Slot::AxisTopTitle => "axis_top_title",
Slot::StripTop => "strip_top",
Slot::LegendTop => "legend_top",
Slot::AxisBottom => "axis_bottom",
Slot::AxisBottomTitle => "axis_bottom_title",
Slot::StripBottom => "strip_bottom",
Slot::LegendBottom => "legend_bottom",
Slot::AxisLeft => "axis_left",
Slot::AxisLeftTitle => "axis_left_title",
Slot::StripLeft => "strip_left",
Slot::LegendLeft => "legend_left",
Slot::AxisRight => "axis_right",
Slot::AxisRightTitle => "axis_right_title",
Slot::StripRight => "strip_right",
Slot::LegendRight => "legend_right",
Slot::Title => "title",
Slot::Subtitle => "subtitle",
Slot::Caption => "caption",
}
}
pub const fn placement(self) -> (u16, u16, u16, u16) {
match self {
Slot::Panel => (PANEL_ROW, PANEL_COL, 1, 1),
Slot::Background => (
PADDING_TOP_ROW,
PADDING_LEFT_COL,
TABLE_ROWS as u16 - 2,
TABLE_COLS as u16 - 2,
),
Slot::AxisTop => (8, PANEL_COL, 1, 1),
Slot::AxisTopTitle => (7, PANEL_COL, 1, 1),
Slot::StripTop => (6, PANEL_COL, 1, 1),
Slot::LegendTop => (PLOT_TOP, PANEL_COL, 1, 1),
Slot::AxisBottom => (10, PANEL_COL, 1, 1),
Slot::AxisBottomTitle => (11, PANEL_COL, 1, 1),
Slot::StripBottom => (12, PANEL_COL, 1, 1),
Slot::LegendBottom => (PLOT_BOTTOM, PANEL_COL, 1, 1),
Slot::AxisLeft => (PANEL_ROW, 6, 1, 1),
Slot::AxisLeftTitle => (PANEL_ROW, 5, 1, 1),
Slot::StripLeft => (PANEL_ROW, 4, 1, 1),
Slot::LegendLeft => (PANEL_ROW, PLOT_LEFT, 1, 1),
Slot::AxisRight => (PANEL_ROW, 8, 1, 1),
Slot::AxisRightTitle => (PANEL_ROW, 9, 1, 1),
Slot::StripRight => (PANEL_ROW, 10, 1, 1),
Slot::LegendRight => (PANEL_ROW, PLOT_RIGHT, 1, 1),
Slot::Title => (3, PLOT_LEFT, 1, PLOT_COL_SPAN),
Slot::Subtitle => (4, PLOT_LEFT, 1, PLOT_COL_SPAN),
Slot::Caption => (14, PLOT_LEFT, 1, PLOT_COL_SPAN),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
const ALL_SLOTS: &[Slot] = &[
Slot::Panel,
Slot::Background,
Slot::AxisTop,
Slot::AxisTopTitle,
Slot::StripTop,
Slot::LegendTop,
Slot::AxisBottom,
Slot::AxisBottomTitle,
Slot::StripBottom,
Slot::LegendBottom,
Slot::AxisLeft,
Slot::AxisLeftTitle,
Slot::StripLeft,
Slot::LegendLeft,
Slot::AxisRight,
Slot::AxisRightTitle,
Slot::StripRight,
Slot::LegendRight,
Slot::Title,
Slot::Subtitle,
Slot::Caption,
];
#[test]
fn names_are_unique() {
let mut names: Vec<&str> = ALL_SLOTS.iter().map(|s| s.name()).collect();
let count = names.len();
names.sort_unstable();
names.dedup();
assert_eq!(names.len(), count, "slot names collide");
}
#[test]
fn placements_stay_within_grid() {
for s in ALL_SLOTS {
let (r, c, rs, cs) = s.placement();
assert!(
r >= 1 && c >= 1,
"{} starts at ({r}, {c}) — must be 1-indexed",
s.name()
);
assert!(
r + rs - 1 <= TABLE_ROWS as u16,
"{} extends past TABLE_ROWS",
s.name()
);
assert!(
c + cs - 1 <= TABLE_COLS as u16,
"{} extends past TABLE_COLS",
s.name()
);
}
}
#[test]
fn background_excludes_margin_tracks() {
let (r, c, rs, cs) = Slot::Background.placement();
assert_eq!(r, PADDING_TOP_ROW);
assert_eq!(c, PADDING_LEFT_COL);
assert_eq!(r + rs - 1, PADDING_BOTTOM_ROW);
assert_eq!(c + cs - 1, PADDING_RIGHT_COL);
}
}