use concinnity_core::ecs::World;
use super::list_panel::{self, ListIds, Row};
use super::registry::PanelKey;
use crate::editor::hud_ids::{hud_ids, panel_base};
use crate::editor::widget::{self, point_in};
pub(crate) const fn count() -> usize {
concinnity_cook::authoring::template::TEMPLATES.len()
}
fn title(i: usize) -> &'static str {
concinnity_cook::authoring::template::TEMPLATES[i].title
}
hud_ids! {
base: panel_base(PanelKey::Templates);
sprites: [pub(crate) PANEL_BG, CLOSE_BG, pub(crate) row_bg[count()]];
labels: [TITLE_LABEL, CLOSE_LABEL, row_label[count()]];
}
const LIST: ListIds = ListIds {
panel_bg: PANEL_BG,
title: TITLE_LABEL,
close_bg: CLOSE_BG,
close_label: CLOSE_LABEL,
row_bg,
row_label,
check_box: None,
value_label: None,
};
const TEMPLATES_W: f32 = 220.0;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum TemplatesAction {
Pick(usize),
Consume,
}
pub(crate) fn default_origin(vw: f32) -> [f32; 2] {
[vw * 0.5 - TEMPLATES_W * 0.5, crate::editor::hud::body_top()]
}
pub(crate) fn size() -> [f32; 2] {
list_panel::size(TEMPLATES_W, count())
}
pub(crate) fn hit_test(mx: f32, my: f32, o: [f32; 2], s: [f32; 2]) -> Option<TemplatesAction> {
if let Some(i) = list_panel::hit_row(mx, my, o, s[0], count()) {
return Some(TemplatesAction::Pick(i));
}
point_in(mx, my, widget::outer_rect(o, s)).then_some(TemplatesAction::Consume)
}
pub(crate) fn place(
world: &mut World,
o: [f32; 2],
s: [f32; 2],
selected: Option<usize>,
mouse: [f32; 2],
) {
let rows: Vec<Row> = (0..count())
.map(|i| Row::label(title(i)).select(selected == Some(i)))
.collect();
list_panel::place(world, &LIST, o, s, "Templates", &rows, mouse);
}
#[cfg(test)]
mod tests {
use super::*;
use concinnity_core::components::{Sprite, TextLabel};
fn injected_world() -> World {
ids().test_world()
}
#[test]
fn hit_test_picks_a_row_or_swallows() {
let o = default_origin(1280.0);
let s = size();
let r0 = list_panel::row_rect(o, TEMPLATES_W, 0);
assert_eq!(
hit_test(r0[0] + 10.0, r0[1] + 10.0, o, s),
Some(TemplatesAction::Pick(0))
);
let t = widget::title_rect(o, TEMPLATES_W);
assert_eq!(
hit_test(t[0] + 5.0, t[1] + 5.0, o, s),
Some(TemplatesAction::Consume)
);
assert_eq!(hit_test(2000.0, 2000.0, o, s), None);
}
#[test]
fn place_labels_rows_from_the_templates_crate() {
let mut world = injected_world();
place(&mut world, default_origin(1280.0), size(), None, [0.0, 0.0]);
let title = world.get_by_id::<TextLabel>(TITLE_LABEL).unwrap();
assert!(title.visible && title.content == "Templates");
for i in 0..count() {
let l = world.get_by_id::<TextLabel>(row_label(i)).unwrap();
assert_eq!(
l.content,
concinnity_cook::authoring::template::TEMPLATES[i].title
);
}
}
#[test]
fn selected_row_is_highlighted() {
let mut world = injected_world();
let o = default_origin(1280.0);
place(&mut world, o, size(), None, [0.0, 0.0]);
let idle = world.get_by_id::<Sprite>(row_bg(0)).cloned().unwrap().tint;
place(&mut world, o, size(), Some(0), [0.0, 0.0]);
let selected = world.get_by_id::<Sprite>(row_bg(0)).unwrap().tint;
assert_ne!(idle, selected);
}
}