use crate::iohandler::scanner;
use crossterm::{
event::{poll, read, Event, KeyCode},
terminal,
};
use log::debug;
use std::{io, process, time::Duration};
use tui::{
backend::CrosstermBackend,
layout::{Alignment, Constraint, Direction, Layout},
style::{Color, Modifier, Style},
widgets::{Block, Borders, Paragraph, SelectableList, Text, Widget},
Terminal,
};
pub struct DrawState<'a> {
list_items: Vec<&'a str>,
selected_item: usize,
}
pub fn run() -> Result<(), crossterm::ErrorKind> {
terminal::enable_raw_mode()?;
let backend = CrosstermBackend::new(io::stdout());
let mut term = Terminal::new(backend).unwrap();
term.clear()?;
let mut draw_state = DrawState {
list_items: vec!["Init", "Add", "Remove", "Switch"],
selected_item: 0,
};
draw(&mut term, &draw_state).unwrap();
loop {
check_update(&mut term, &mut draw_state)?;
}
}
fn up_pressed(state: &mut DrawState) {
if state.selected_item != 0 {
state.selected_item -= 1;
}
}
fn down_pressed(state: &mut DrawState) {
if state.selected_item + 1 != state.list_items.len() {
state.selected_item += 1;
}
}
fn enter_pressed(_state: &mut DrawState) {
}
fn exit_routine(
term: &mut Terminal<CrosstermBackend<io::Stdout>>,
_state: &mut DrawState,
) -> Result<(), crossterm::ErrorKind> {
term.clear()?;
term.show_cursor()?;
terminal::disable_raw_mode()?;
debug!("Nice chirping... Bye!");
process::exit(1);
}
pub fn check_update(
mut term: &mut Terminal<CrosstermBackend<io::Stdout>>,
mut draw_state: &mut DrawState,
) -> Result<(), crossterm::ErrorKind> {
if poll(Duration::from_millis(100))? {
match read()? {
Event::Key(event) => {
match event.code {
KeyCode::Up => up_pressed(&mut draw_state),
KeyCode::Down => down_pressed(&mut draw_state),
KeyCode::Enter => enter_pressed(&mut draw_state),
KeyCode::Esc => exit_routine(&mut term, &mut draw_state)?,
_ => (),
}
draw(&mut term, &mut draw_state)?;
}
Event::Mouse(event) => debug!("{:?}", event),
Event::Resize(width, _) => {
debug!("{:?}", width);
draw(&mut term, &mut draw_state)?;
}
}
}
Ok(())
}
pub fn draw(
term: &mut Terminal<CrosstermBackend<io::Stdout>>,
state: &DrawState,
) -> Result<(), crossterm::ErrorKind> {
term.hide_cursor()?;
term.draw(|mut f| {
let size = f.size();
Block::default().borders(Borders::ALL).render(&mut f, size);
let chunks = Layout::default()
.direction(Direction::Vertical)
.margin(1)
.constraints([Constraint::Percentage(80), Constraint::Percentage(20)].as_ref())
.split(f.size());
let art_para =
scanner::parse_art("assets/ansi/art.ans", f.size().width as usize).unwrap_or_default();
Paragraph::new(
art_para
.into_iter()
.map(|line| Text::raw(line))
.collect::<Vec<Text>>()
.iter(),
)
.style(Style::default().fg(Color::White).bg(Color::Black))
.alignment(Alignment::Center)
.wrap(true)
.render(&mut f, chunks[0]);
SelectableList::default()
.block(Block::default().title("Operation").borders(Borders::ALL))
.items(&state.list_items)
.select(Some(state.selected_item))
.style(Style::default().fg(Color::White))
.highlight_style(Style::default().modifier(Modifier::ITALIC))
.highlight_symbol(">>")
.render(&mut f, chunks[1]);
})?;
Ok(())
}