#[allow(dead_code)] mod util; use std::io; use itui::{ backend::TermionBackend, layout::{Constraint, Layout}, style::{Color, Modifier, Style}, widgets::{Block, Borders, Row, Table, Widget}, Terminal, }; use termion::{event::Key, input::MouseTerminal, raw::IntoRawMode, screen::AlternateScreen}; use crate::util::event::{Event, Events}; struct App<'a> { items: Vec>, selected: usize, } impl<'a> App<'a> { fn new() -> App<'a> { App { items: vec![ vec!["Row12", "Row12", "Row13"], vec!["Row21", "Row22", "Row23"], vec!["Row31", "Row32", "Row33"], vec!["Row41", "Row42", "Row43"], vec!["Row51", "Row52", "Row53"], vec!["Row61", "Row62", "Row63"], ], selected: 0, } } } fn main() -> Result<(), failure::Error> { // Terminal initialization let stdout = io::stdout().into_raw_mode()?; let stdout = MouseTerminal::from(stdout); let stdout = AlternateScreen::from(stdout); let backend = TermionBackend::new(stdout); let mut terminal = Terminal::new(backend)?; terminal.hide_cursor()?; let events = Events::new(); // App let mut app = App::new(); // Input loop { terminal.draw(|mut f| { let selected_style = Style::default().fg(Color::Yellow).modifier(Modifier::BOLD); let normal_style = Style::default().fg(Color::White); let header = ["Header1", "Header2", "Header3"]; let rows = app.items.iter().enumerate().map(|(i, item)| { if i == app.selected { Row::StyledData(item.into_iter(), selected_style) } else { Row::StyledData(item.into_iter(), normal_style) } }); let rects = Layout::default() .constraints([Constraint::Percentage(100)].as_ref()) .margin(5) .split(f.size()); Table::new(header.into_iter(), rows) .block( Block::default() .borders(Borders::ALL) .title("Table") .area(rects[0]), ) .widths(&[10, 10, 10]) .render(&mut f); })?; match events.next()? { Event::Input(key) => match key { Key::Char('q') => { break; } Key::Down => { app.selected += 1; if app.selected > app.items.len() - 1 { app.selected = 0; } } Key::Up => { if app.selected > 0 { app.selected -= 1; } else { app.selected = app.items.len() - 1; } } _ => {} }, _ => {} }; } Ok(()) }