use embedded_graphics::{
draw_target::DrawTarget,
mono_font::MonoTextStyle,
pixelcolor::Rgb565,
prelude::*,
primitives::Rectangle,
text::{Text, TextStyle},
};
use crate::{Button, ButtonKind, ButtonSpec, Localized, NavHeaderAction, StackNav, lerp_i32};
use super::stack::HeaderTransition;
const BACK_BUTTON_WIDTH: u32 = 112;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(super) struct HeaderTitle<'a> {
pub title: Localized<'a>,
pub center: Point,
}
pub(super) fn show_back_button<K: Copy, const N: usize>(nav: &StackNav<K, N>) -> bool {
nav.depth() > 1 || matches!(nav.header_transition(), Some(HeaderTransition::Pop { .. }))
}
pub(super) fn header_titles<'a, K: Copy, F, const N: usize>(
nav: &StackNav<K, N>,
header: Rectangle,
title_for: &F,
back_button: Option<&Button<'a, NavHeaderAction>>,
) -> (
Option<Localized<'a>>,
HeaderTitle<'a>,
Option<HeaderTitle<'a>>,
)
where
F: Fn(K) -> Localized<'a>,
{
let center = header.center();
let right = Point::new(center.x + header.size.width as i32, center.y);
let back = back_title_center(back_button);
match nav.header_transition() {
Some(HeaderTransition::Push { from, to, progress }) => (
None,
HeaderTitle {
title: title_for(from),
center: Point::new(lerp_i32(center.x, back.x, progress), center.y),
},
Some(HeaderTitle {
title: title_for(to),
center: Point::new(lerp_i32(right.x, center.x, progress), center.y),
}),
),
Some(HeaderTransition::Pop { from, to, progress }) => (
None,
HeaderTitle {
title: title_for(to),
center: Point::new(lerp_i32(back.x, center.x, progress), center.y),
},
Some(HeaderTitle {
title: title_for(from),
center: Point::new(lerp_i32(center.x, right.x, progress), center.y),
}),
),
None => (
nav.previous().map(title_for),
HeaderTitle {
title: title_for(nav.top()),
center,
},
None,
),
}
}
pub(super) fn draw_title<D>(
display: &mut D,
title: &str,
center: Point,
style: MonoTextStyle<'_, Rgb565>,
text_style: TextStyle,
) where
D: DrawTarget<Color = Rgb565>,
{
Text::with_text_style(title, center, style, text_style)
.draw(display)
.ok();
}
pub(super) fn back_title_center(button: Option<&Button<'_, NavHeaderAction>>) -> Point {
if let Some(button) = button {
Point::new(
button.frame.top_left.x + 68,
button.frame.top_left.y + (button.frame.size.height / 2) as i32,
)
} else {
Point::zero()
}
}
pub(super) fn back_button<'a>(header: Rectangle) -> Button<'a, NavHeaderAction> {
Button::new(
Rectangle::new(
header.top_left + Point::new(16, 12),
Size::new(BACK_BUTTON_WIDTH, header.size.height.saturating_sub(24)),
),
ButtonSpec {
key: NavHeaderAction::Back,
icon: None,
label: Localized::new("", ""),
kind: ButtonKind::Ghost,
},
)
}