use core::fmt::Write; use embedded_graphics::{ mono_font::{ascii::FONT_10X20, MonoTextStyleBuilder}, pixelcolor::Rgb565, prelude::{Point, RgbColor, WebColors}, text::{Baseline, Text}, Drawable, }; use heapless::String; use super::{ scroll_tracker::{ScrollAction, ScrollTracker}, textbox::{self, TextBox}, Element, }; use crate::contact::{Contact, MAX_CONTACT_CALLSIGN_LENGTH, MAX_CONTACT_NAME_LENGTH}; const LABEL_X: i32 = 20; const TEXT_X: i32 = 100; pub struct ContactView { contact: Contact, editable: bool, name: TextBox, callsign: TextBox, ssid: TextBox, tracker: ScrollTracker, selected: usize, } impl ContactView { pub fn new(contact: Contact, editable: bool) -> Self { let mut name = TextBox::new( TEXT_X, (40 - textbox::BORDER_WIDTH).try_into().unwrap(), MAX_CONTACT_NAME_LENGTH.try_into().unwrap(), 1, ); name.set_text(&contact.name).unwrap(); name.selected = false; let mut callsign = TextBox::new( TEXT_X, (80 - textbox::BORDER_WIDTH).try_into().unwrap(), MAX_CONTACT_CALLSIGN_LENGTH.try_into().unwrap(), 1, ); callsign.set_text(&contact.callsign).unwrap(); callsign.selected = false; let mut ssid = TextBox::new( TEXT_X, (120 - textbox::BORDER_WIDTH).try_into().unwrap(), 3, 1, ); let mut ssid_buf: String<3> = String::new(); write!(ssid_buf, "{}", contact.ssid).unwrap(); ssid.set_text(&ssid_buf).unwrap(); ssid.selected = false; Self { contact, editable, name, callsign, ssid, tracker: ScrollTracker::new(), selected: 0, } } pub fn contact(&self) -> Contact { if self.editable { Contact { callsign: self .callsign .get_text() .try_into() .unwrap_or_else(|_| self.contact.callsign.clone()), ssid: self.ssid.get_text().parse().unwrap_or(self.contact.ssid), name: self .name .get_text() .try_into() .unwrap_or_else(|_| self.contact.name.clone()), } } else { self.contact.clone() } } } impl Element for ContactView { fn render< E, DT: embedded_graphics::prelude::DrawTarget< Color = embedded_graphics::pixelcolor::Rgb565, Error = E, >, >( &mut self, dt: &mut DT, ) -> Result<(), E> { let label_style = MonoTextStyleBuilder::new() .font(&FONT_10X20) .background_color(Rgb565::CSS_LIME) .text_color(Rgb565::BLACK) .build(); let text_style = MonoTextStyleBuilder::new() .font(&FONT_10X20) .text_color(Rgb565::BLACK) .build(); Text::with_baseline("Name:", Point::new(LABEL_X, 40), label_style, Baseline::Top) .draw(dt)?; Text::with_baseline("Call:", Point::new(LABEL_X, 80), label_style, Baseline::Top) .draw(dt)?; Text::with_baseline( "SSID:", Point::new(LABEL_X, 120), label_style, Baseline::Top, ) .draw(dt)?; if self.editable { self.name.selected = self.selected == 0; self.name.render(dt)?; self.callsign.selected = self.selected == 1; self.callsign.render(dt)?; self.ssid.selected = self.selected == 2; self.ssid.render(dt)? } else { Text::with_baseline( &self.contact.name, Point::new(TEXT_X, 40), text_style, Baseline::Top, ) .draw(dt)?; Text::with_baseline( &self.contact.callsign, Point::new(TEXT_X, 80), text_style, Baseline::Top, ) .draw(dt)?; let mut ssid_text = String::<3>::new(); write!(&mut ssid_text, "{}", self.contact.ssid).unwrap(); Text::with_baseline( &ssid_text, Point::new(TEXT_X, 120), text_style, Baseline::Top, ) .draw(dt)?; } Ok(()) } fn key_push(&mut self, k: crate::keyboard::KeyCode) { if !self.editable { return; } match self.selected { 0 => self.name.key_push(k), 1 => self.callsign.key_push(k), 2 => self.ssid.key_push(k), _ => unreachable!(), } } fn touchpad_scroll(&mut self, _x: i8, y: i8) { match self.tracker.scroll(y) { ScrollAction::Previous => { if self.selected > 0 { self.selected -= 1; } } ScrollAction::Next => { if self.selected < 2 { self.selected += 1; } } ScrollAction::None => {} } } }