use tui::Terminal;
use tui::backend::CrosstermBackend;
use tui::widgets::{Widget, Block, Borders, Paragraph, Text};
use tui::layout::{Layout, Constraint, Direction};
use tui::style::{Style, Modifier, Color};
use crossterm::KeyEvent;
use crate::windows::{Window, EventResult};
#[derive(Debug, Clone)]
struct HelpEntry {
pub key: String,
pub text: String
}
impl HelpEntry {
pub fn new(key: String, text: String) -> HelpEntry {
HelpEntry {
key,
text
}
}
pub fn get_entry(&self, length: usize) -> [Text; 3] {
[
Text::raw(std::iter::repeat(" ").take(length - self.key.len()).collect::<String>()),
Text::styled(self.key.clone(), Style::default().bg(Color::Cyan)),
Text::raw(format!(" - {}\n\n", self.text))
]
}
}
pub struct HelpWindow {
help_entries: Vec<HelpEntry>,
should_close: bool
}
impl HelpWindow {
pub fn new() -> Box<HelpWindow> {
let mut help_entries= vec!();
HelpWindow::add_hot_key(&mut help_entries, "F1", "Show help window");
HelpWindow::add_hot_key(&mut help_entries, "F2", "Change input format");
HelpWindow::add_hot_key(&mut help_entries, "F3", "Change output format");
HelpWindow::add_hot_key(&mut help_entries, "F4", "Clear output text");
HelpWindow::add_hot_key(&mut help_entries, "F5", "Change appended newline on send");
HelpWindow::add_hot_key(&mut help_entries, "F10", "Close application");
HelpWindow::add_hot_key(&mut help_entries, "Enter", "Send input to serial");
HelpWindow::add_hot_key(&mut help_entries, "Up", "Go up in input history entries");
HelpWindow::add_hot_key(&mut help_entries, "Down", "Go down in input history entries");
HelpWindow::add_hot_key(&mut help_entries, "Ctrl + C", "Close application");
Box::new(HelpWindow {
help_entries,
should_close: false
})
}
fn get_help_text_entries(help_entries: &Vec<HelpEntry>) -> Vec<Text> {
let mut length = 0;
for entry in help_entries {
if entry.key.len() > length {
length = entry.key.len();
}
}
let title_text = format!("Key{}Action\n\n", std::iter::repeat(" ").take(length).collect::<String>());
let mut help_text = vec!(Text::styled(title_text, Style::default().modifier(Modifier::BOLD)));
for entry in help_entries {
help_text.extend_from_slice(&entry.get_entry(length));
}
help_text
}
fn add_hot_key(entries: &mut Vec<HelpEntry>, hot_key: &str, description: &str) {
entries.push(HelpEntry::new(hot_key.to_string(), description.to_string()));
}
}
impl Window for HelpWindow {
fn render(&mut self, terminal: &mut Terminal<CrosstermBackend>) -> Result<(), std::io::Error> {
let help_text = HelpWindow::get_help_text_entries(&self.help_entries);
terminal.draw(|mut f| {
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Min(0),
Constraint::Length(2)
].as_ref())
.split(f.size());
let exit_text = [Text::styled("Press ESC to exit help", Style::default().modifier(Modifier::ITALIC))];
Paragraph::new(help_text.iter())
.block(Block::default()
.title("Help")
.title_style(Style::default().modifier(Modifier::BOLD))
.borders(Borders::ALL))
.render(&mut f, chunks[0]);
Paragraph::new(exit_text.iter())
.block(Block::default())
.wrap(true)
.render(&mut f, chunks[1]);
})
}
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
match event {
KeyEvent::Esc => {
self.should_close = true;
},
_ => {}
};
EventResult::new()
}
fn should_close(&self) -> bool {
self.should_close
}
}