Skip to content
Snippets Groups Projects
contact_view.rs 5.51 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 crate::storage::{Contact, MAX_CONTACT_CALLSIGN_LENGTH, MAX_CONTACT_NAME_LENGTH};

Stephen D's avatar
Stephen D committed
use super::{
Stephen D's avatar
Stephen D committed
    button::Button,
Stephen D's avatar
Stephen D committed
    scroll_tracker::{ScrollAction, ScrollTracker},
    textbox::{self, TextBox},
    Element,
};
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,
Stephen D's avatar
Stephen D committed
    delete: Button,
Stephen D's avatar
Stephen D committed
    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;

Stephen D's avatar
Stephen D committed
        let mut delete = Button::new(LABEL_X, 160, "Delete");
        delete.selected = false;

Stephen D's avatar
Stephen D committed
        Self {
            contact,
            editable,
            name,
            callsign,
            ssid,
Stephen D's avatar
Stephen D committed
            delete,
Stephen D's avatar
Stephen D committed
            tracker: ScrollTracker::new(),
            selected: 0,
        }
Stephen D's avatar
Stephen D committed
    }
Stephen D's avatar
Stephen D committed

Stephen D's avatar
Stephen D committed
    pub fn contact(&mut self) -> Contact {
Stephen D's avatar
Stephen D committed
        if self.editable {
Stephen D's avatar
Stephen D committed
            if let Ok(callsign) = self.callsign.get_text().try_into() {
                self.contact.callsign = callsign;
            }

            if let Ok(ssid) = self.ssid.get_text().parse() {
                self.contact.ssid = ssid;
            }

            if let Ok(name) = self.name.get_text().try_into() {
                self.contact.name = name;
Stephen D's avatar
Stephen D committed
            }
        }
Stephen D's avatar
Stephen D committed

        self.contact.clone()
Stephen D's avatar
Stephen D committed
    }
Stephen D's avatar
Stephen D committed
}

impl Element for ContactView {
Stephen D's avatar
Stephen D committed
    type KeyPushReturn = bool;
Stephen D's avatar
Stephen D committed

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

            self.delete.selected = self.selected == 3;
            self.delete.render(dt)?;
Stephen D's avatar
Stephen D committed
        } 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
    // Returns true if contact should be deleted
    fn key_push(&mut self, k: crate::keyboard::KeyCode) -> bool {
Stephen D's avatar
Stephen D committed
        if !self.editable {
Stephen D's avatar
Stephen D committed
            return false;
Stephen D's avatar
Stephen D committed
        }

        match self.selected {
            0 => self.name.key_push(k),
            1 => self.callsign.key_push(k),
            2 => self.ssid.key_push(k),
Stephen D's avatar
Stephen D committed
            3 => return self.delete.key_push(k),
Stephen D's avatar
Stephen D committed
            _ => unreachable!(),
        }
Stephen D's avatar
Stephen D committed

        false
Stephen D's avatar
Stephen D committed
    }
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 => {
Stephen D's avatar
Stephen D committed
                if self.selected < 3 {
Stephen D's avatar
Stephen D committed
                    self.selected += 1;
                }
            }
            ScrollAction::None => {}
        }
    }
Stephen D's avatar
Stephen D committed
}