use denise::KeyCode;
use denise_render::icon::Icon;
use crate::icons;
use crate::LAYOUT_KEY as LAYOUT;
#[derive(Clone, Copy, Debug)]
pub struct Key {
pub code: KeyCode,
pub legend: Option<&'static str>,
pub icon: Option<&'static Icon>,
pub units: i32,
pub repeats: bool,
}
const LETTER: i32 = 2;
impl Key {
const fn new(code: KeyCode) -> Self {
Self {
code,
legend: None,
icon: None,
units: LETTER,
repeats: false,
}
}
const fn wide(code: KeyCode, legend: &'static str, units: i32) -> Self {
Self {
code,
legend: Some(legend),
icon: None,
units,
repeats: false,
}
}
const fn repeating(mut self) -> Self {
self.repeats = true;
self
}
const fn drawn(mut self, icon: &'static Icon) -> Self {
self.icon = Some(icon);
self
}
}
#[derive(Clone, Copy, Debug)]
pub struct Row {
pub keys: &'static [Key],
}
const DIGITS: [Key; 14] = [
Key::new(KeyCode::Backquote),
Key::new(KeyCode::Digit1),
Key::new(KeyCode::Digit2),
Key::new(KeyCode::Digit3),
Key::new(KeyCode::Digit4),
Key::new(KeyCode::Digit5),
Key::new(KeyCode::Digit6),
Key::new(KeyCode::Digit7),
Key::new(KeyCode::Digit8),
Key::new(KeyCode::Digit9),
Key::new(KeyCode::Digit0),
Key::new(KeyCode::Minus),
Key::new(KeyCode::Equal),
Key::wide(KeyCode::Backspace, "back", LETTER * 2)
.drawn(&icons::BACKSPACE)
.repeating(),
];
const TOP: [Key; 14] = [
Key::wide(KeyCode::Tab, "tab", LETTER * 3 / 2).drawn(&icons::TAB),
Key::new(KeyCode::Q),
Key::new(KeyCode::W),
Key::new(KeyCode::E),
Key::new(KeyCode::R),
Key::new(KeyCode::T),
Key::new(KeyCode::Y),
Key::new(KeyCode::U),
Key::new(KeyCode::I),
Key::new(KeyCode::O),
Key::new(KeyCode::P),
Key::new(KeyCode::BracketLeft),
Key::new(KeyCode::BracketRight),
Key::new(KeyCode::Backslash),
];
const HOME: [Key; 13] = [
Key::wide(KeyCode::CapsLock, "caps", LETTER * 2),
Key::new(KeyCode::A),
Key::new(KeyCode::S),
Key::new(KeyCode::D),
Key::new(KeyCode::F),
Key::new(KeyCode::G),
Key::new(KeyCode::H),
Key::new(KeyCode::J),
Key::new(KeyCode::K),
Key::new(KeyCode::L),
Key::new(KeyCode::Semicolon),
Key::new(KeyCode::Quote),
Key::wide(KeyCode::Enter, "enter", LETTER * 2).drawn(&icons::ENTER),
];
const BOTTOM: [Key; 12] = [
Key::wide(KeyCode::ShiftLeft, "shift", LETTER * 5 / 2),
Key::new(KeyCode::Z),
Key::new(KeyCode::X),
Key::new(KeyCode::C),
Key::new(KeyCode::V),
Key::new(KeyCode::B),
Key::new(KeyCode::N),
Key::new(KeyCode::M),
Key::new(KeyCode::Comma),
Key::new(KeyCode::Period),
Key::new(KeyCode::Slash),
Key::wide(KeyCode::ShiftLeft, "shift", LETTER * 5 / 2),
];
const SPACE_ROW: [Key; 7] = [
Key::wide(KeyCode::ControlLeft, "ctrl", LETTER * 3 / 2),
Key::wide(KeyCode::AltRight, "alt", LETTER * 3 / 2),
Key {
code: LAYOUT,
legend: None,
icon: Some(&icons::GLOBE),
units: LETTER * 2,
repeats: false,
},
Key::wide(KeyCode::Space, " ", LETTER * 6),
Key::wide(KeyCode::ArrowLeft, "<-", LETTER).drawn(&icons::ARROW_LEFT),
Key::wide(KeyCode::ArrowRight, "->", LETTER).drawn(&icons::ARROW_RIGHT),
Key::wide(KeyCode::Escape, "esc", LETTER * 2).drawn(&icons::DISMISS),
];
pub static ROWS: [Row; 5] = [
Row { keys: &DIGITS },
Row { keys: &TOP },
Row { keys: &HOME },
Row { keys: &BOTTOM },
Row { keys: &SPACE_ROW },
];
pub(crate) fn legend_of(code: KeyCode) -> Option<&'static str> {
entry(code).and_then(|key| key.legend)
}
pub(crate) fn icon_of(code: KeyCode) -> Option<&'static Icon> {
entry(code).and_then(|key| key.icon)
}
fn entry(code: KeyCode) -> Option<&'static Key> {
ROWS.iter()
.flat_map(|row| row.keys)
.find(|key| key.code == code)
}