use crate::navigation::navigation::Action; use crate::navigation::navigation::Navigable; use crate::navigation::navigation::NewState; use crate::navigation::outputs::Outputs; use crate::peripherals::Peripherals; use crate::views::view::View; use alloc::boxed::Box; use alloc::string::String; use alloc::string::ToString; use core::error; use embedded_graphics::{ Drawable, mono_font::{MonoTextStyle, ascii::FONT_10X20}, pixelcolor::Rgb565, prelude::*, primitives::Rectangle, text::Text, }; use embedded_text::{ TextBox, alignment::HorizontalAlignment, style::{HeightMode, TextBoxStyleBuilder}, }; #[derive(Debug, Clone)] pub struct ErrorView { pub error: String, } impl Navigable for ErrorView { fn display( &self, outputs: &mut Outputs, _: &Peripherals, ) -> impl core::future::Future>> + Send { async move { outputs .primary_display .clear(Rgb565::BLACK) .unwrap_or_else(|error| { panic!( "Error: {error:?}\nDraw error while rendering ErrorView: {}", self.error ) }); let style = MonoTextStyle::new(&FONT_10X20, Rgb565::RED); let display_area = outputs.primary_display.bounding_box(); Text::new( "Error", Point::new((display_area.size.width / 2 - 25) as i32, 30), style, ) .draw(&mut outputs.primary_display) .unwrap_or_else(|error| { panic!( "Error: {error:?}\nDraw error while rendering ErrorView: {}", self.error ) }); let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); let textbox_style = TextBoxStyleBuilder::new() .height_mode(HeightMode::FitToText) .alignment(HorizontalAlignment::Center) .build(); let bounds = Rectangle::new(Point::new(0, 50), display_area.size); TextBox::with_textbox_style(&self.error.to_string(), bounds, style, textbox_style) .draw(&mut outputs.primary_display) .unwrap_or_else(|error| { panic!( "Error: {error:?}\nDraw error while rendering ErrorView: {}", self.error ) }); Ok(()) } } fn handle_input(&self, input: Action) -> impl core::future::Future + Send { async move { let new_menu = View::Error(self.clone()); match input { Action::Button(_) => NewState { replace_view: matches!(new_menu, View::FlashInfo(_)), view: new_menu, redraw: true, }, Action::Timer => { // Skip timer inputs NewState { view: new_menu, replace_view: true, redraw: false, } } } } } }