Skip to content
Snippets Groups Projects
contact_view.rs 5.25 KiB
Newer Older
Stephen D's avatar
Stephen D committed
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;

Stephen D's avatar
Stephen D committed
use super::{
    scroll_tracker::{ScrollAction, ScrollTracker},
    textbox::{self, TextBox},
    Element,
};
use crate::contact::{Contact, MAX_CONTACT_CALLSIGN_LENGTH, MAX_CONTACT_NAME_LENGTH};
Stephen D's avatar
Stephen D committed

Stephen D's avatar
Stephen D committed
const LABEL_X: i32 = 20;
const TEXT_X: i32 = 100;
Stephen D's avatar
Stephen D committed

pub struct ContactView {
    contact: Contact,
Stephen D's avatar
Stephen D committed
    editable: bool,
    name: TextBox,
    callsign: TextBox,
    ssid: TextBox,
    tracker: ScrollTracker,
    selected: usize,
Stephen D's avatar
Stephen D committed
}

impl ContactView {
Stephen D's avatar
Stephen D committed
    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,
        }
Stephen D's avatar
Stephen D committed
    }
Stephen D's avatar
Stephen D committed

    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()
        }
    }
Stephen D's avatar
Stephen D committed
}

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();

Stephen D's avatar
Stephen D committed
        Text::with_baseline("Name:", Point::new(LABEL_X, 40), label_style, Baseline::Top)
            .draw(dt)?;
Stephen D's avatar
Stephen D committed

Stephen D's avatar
Stephen D committed
        Text::with_baseline("Call:", Point::new(LABEL_X, 80), label_style, Baseline::Top)
Stephen D's avatar
Stephen D committed
            .draw(dt)?;
Stephen D's avatar
Stephen D committed

Stephen D's avatar
Stephen D committed
        Text::with_baseline(
Stephen D's avatar
Stephen D committed
            "SSID:",
            Point::new(LABEL_X, 120),
            label_style,
Stephen D's avatar
Stephen D committed
            Baseline::Top,
        )
        .draw(dt)?;

Stephen D's avatar
Stephen D committed
        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,
            )
Stephen D's avatar
Stephen D committed
            .draw(dt)?;

Stephen D's avatar
Stephen D committed
            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)?;
        }

Stephen D's avatar
Stephen D committed
        Ok(())
    }

Stephen D's avatar
Stephen D committed
    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!(),
        }
    }
Stephen D's avatar
Stephen D committed

Stephen D's avatar
Stephen D committed
    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 => {}
        }
    }
Stephen D's avatar
Stephen D committed
}