map: refactor

This commit is contained in:
lunar-mining
2022-01-08 14:03:00 +01:00
parent ffd9c8e185
commit 22034e1c40
5 changed files with 250 additions and 63 deletions

39
bin/map/src/app.rs Normal file
View File

@@ -0,0 +1,39 @@
use crate::list::StatefulList;
pub struct App<'a> {
pub items: StatefulList<(&'a str, usize)>,
}
impl<'a> App<'a> {
pub fn new() -> App<'a> {
App {
items: StatefulList::with_items(vec![
("node0", 1),
("node1", 2),
("node2", 1),
("node3", 3),
("node4", 1),
("node5", 4),
("node6", 1),
("node7", 3),
("node8", 1),
("node9", 6),
("node10", 1),
("node11", 3),
("node12", 1),
("node13", 2),
("node14", 1),
("node15", 1),
("node16", 4),
("node17", 1),
("node18", 5),
("node19", 4),
("node20", 1),
("node21", 2),
("node22", 1),
("node23", 3),
("node24", 1),
]),
}
}
}

44
bin/map/src/list.rs Normal file
View File

@@ -0,0 +1,44 @@
use tui::widgets::ListState;
pub struct StatefulList<T> {
pub state: ListState,
pub items: Vec<T>,
}
impl<T> StatefulList<T> {
pub fn with_items(items: Vec<T>) -> StatefulList<T> {
StatefulList { state: ListState::default(), items }
}
pub fn next(&mut self) {
let i = match self.state.selected() {
Some(i) => {
if i >= self.items.len() - 1 {
0
} else {
i + 1
}
}
None => 0,
};
self.state.select(Some(i));
}
pub fn previous(&mut self) {
let i = match self.state.selected() {
Some(i) => {
if i == 0 {
self.items.len() - 1
} else {
i - 1
}
}
None => 0,
};
self.state.select(Some(i));
}
pub fn unselect(&mut self) {
self.state.select(None);
}
}

View File

@@ -1,87 +1,138 @@
// make async task that updates info
// this display that
//use drk::Result;
use std::{io, io::Read};
use std::{
error::Error,
io,
io::Read,
time::{Duration, Instant},
};
use termion::{async_stdin, event::Key, input::TermRead, raw::IntoRawMode};
use tui::{
backend::TermionBackend,
backend::{Backend, TermionBackend},
layout::{Constraint, Direction, Layout},
style::{Color, Modifier, Style},
text::{Span, Spans, Text},
widgets::{ListState, Block, Borders, List, ListItem, Paragraph, Wrap},
widgets::{Block, Borders, List, ListItem, ListState, Paragraph, Wrap},
Terminal,
};
pub mod app;
pub mod list;
pub mod ui;
use crate::app::App;
fn main() -> Result<(), io::Error> {
// Set up terminal output
let stdout = io::stdout().into_raw_mode()?;
let backend = TermionBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
// create app and run it
let tick_rate = Duration::from_millis(250);
let app = App::new();
let res = run_app(&mut terminal, app, tick_rate);
terminal.clear()?;
if let Err(err) = res {
println!("{:?}", err)
}
Ok(())
// Create a separate thread to poll stdin.
// This provides non-blocking input support.
//let mut asi = async_stdin();
//// Clear the terminal before first draw.
//terminal.clear()?;
//loop {
// // Lock the terminal and start a drawing session.
// terminal.draw(|frame| {
// // Create a layout into which to place our blocks.
// let chunks = Layout::default()
// .direction(Direction::Vertical)
// .constraints([Constraint::Percentage(6), Constraint::Percentage(94)].as_ref())
// .split(frame.size());
// //let size = frame.size();
// // The text lines for our text box.
// let txt = vec![Spans::from("\n Press q to quit.\n")];
// // Create a paragraph with the above text...
// let graph = Paragraph::new(txt)
// // In a block with borders and the given title...
// .block(Block::default().title("").borders(Borders::ALL))
// // With white foreground and black background...
// .style(Style::default().fg(Color::White).bg(Color::Black));
// // Render into the layout.
// frame.render_widget(graph, chunks[0]);
// // create a list
// //let mut items: Vec<ListItem> = Vec::new();
// //for num in 1..100 {
// // let new_item = ListItem::new(format!("Node {}", num));
// // items.push(new_item);
// //}
// //let list = List::new(items)
// // .block(Block::default().title("Nodes").borders(Borders::ALL))
// // .style(Style::default().fg(Color::White))
// // .highlight_style(Style::default().add_modifier(Modifier::ITALIC))
// // .highlight_symbol(">>");
// //// draw a list
// //frame.render_widget(list, chunks[1]);
// // make a paragraph
// let mut text1 = String::new();
// for num in 1..10000 {
// let text2 = format!("\n Node {}\n", num);
// text1.push_str(&text2);
// }
// let text = Spans::from(vec![Span::raw(String::from(text1))]);
// let graph = Paragraph::new(text)
// .block(Block::default().title("").borders(Borders::ALL))
// .style(Style::default().fg(Color::White).bg(Color::Black))
// .scroll((0, 10000))
// .wrap(Wrap { trim: true });
// frame.render_widget(graph, chunks[1]);
// })?;
// // Iterate over all the keys that have been pressed since the
// // last time we checked.
// for k in asi.by_ref().keys() {
// match k.unwrap() {
// // If any of them is q, quit
// Key::Char('q') => {
// // Clear the terminal before exit so as not to leave
// // a mess.
// terminal.clear()?;
// return Ok(())
// }
// Key::Char('j') => {}
// // Otherwise, throw them away.
// _ => (),
// }
// }
//}
}
fn run_app<B: Backend>(
terminal: &mut Terminal<B>,
mut app: App,
tick_rate: Duration,
) -> io::Result<()> {
let mut asi = async_stdin();
// Clear the terminal before first draw.
terminal.clear()?;
let mut last_tick = Instant::now();
loop {
// Lock the terminal and start a drawing session.
terminal.draw(|frame| {
// Create a layout into which to place our blocks.
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Percentage(6), Constraint::Percentage(94)].as_ref())
.split(frame.size());
terminal.draw(|f| ui::ui(f, &mut app))?;
//let size = frame.size();
// The text lines for our text box.
let txt = vec![Spans::from("\n Press q to quit.\n")];
// Create a paragraph with the above text...
let graph = Paragraph::new(txt)
// In a block with borders and the given title...
.block(Block::default().title("").borders(Borders::ALL))
// With white foreground and black background...
.style(Style::default().fg(Color::White).bg(Color::Black));
// Render into the layout.
frame.render_widget(graph, chunks[0]);
// create a list
//let mut items: Vec<ListItem> = Vec::new();
//for num in 1..100 {
// let new_item = ListItem::new(format!("Node {}", num));
// items.push(new_item);
//}
//let list = List::new(items)
// .block(Block::default().title("Nodes").borders(Borders::ALL))
// .style(Style::default().fg(Color::White))
// .highlight_style(Style::default().add_modifier(Modifier::ITALIC))
// .highlight_symbol(">>");
//// draw a list
//frame.render_widget(list, chunks[1]);
// make a paragraph
let mut text1 = String::new();
for num in 1..10000 {
let text2 = format!("\n Node {}\n", num);
text1.push_str(&text2);
}
let text = Spans::from(vec![Span::raw(String::from(text1))]);
let graph = Paragraph::new(text)
.block(Block::default().title("").borders(Borders::ALL))
.style(Style::default().fg(Color::White).bg(Color::Black))
.scroll((0, 10000))
.wrap(Wrap { trim: true });
frame.render_widget(graph, chunks[1]);
})?;
// Iterate over all the keys that have been pressed since the
// last time we checked.
for k in asi.by_ref().keys() {
match k.unwrap() {
// If any of them is q, quit
@@ -91,11 +142,15 @@ fn main() -> Result<(), io::Error> {
terminal.clear()?;
return Ok(())
}
Key::Char('j') => {
}
Key::Char('j') => app.items.next(),
Key::Char('k') => app.items.previous(),
// Otherwise, throw them away.
_ => (),
}
}
if last_tick.elapsed() >= tick_rate {
last_tick = Instant::now();
}
}
}

7
bin/map/src/mod.rs Normal file
View File

@@ -0,0 +1,7 @@
pub mod list;
pub mod app;
pub mod ui;
pub use list::StatefulList;
pub use app::App;
pub use ui::ui;

42
bin/map/src/ui.rs Normal file
View File

@@ -0,0 +1,42 @@
use crate::app::App;
use tui::{
backend::Backend,
layout::{Constraint, Direction, Layout},
style::{Color, Modifier, Style},
text::{Span, Spans},
widgets::{Block, Borders, List, ListItem},
Frame,
};
pub fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Percentage(6), Constraint::Percentage(94)].as_ref())
.split(f.size());
// Iterate through all elements in the `items` app and append some debug text to it.
let items: Vec<ListItem> = app
.items
.items
.iter()
.map(|i| {
let mut lines = vec![Spans::from(i.0)];
for _ in 0..i.1 {
lines.push(Spans::from(Span::styled(
"Just some random garbage",
Style::default().add_modifier(Modifier::ITALIC),
)));
}
ListItem::new(lines).style(Style::default())
})
.collect();
// Create a List from all list items and highlight the currently selected one
let items = List::new(items)
.block(Block::default().borders(Borders::ALL).title("List"))
.highlight_style(Style::default().bg(Color::LightGreen).add_modifier(Modifier::BOLD))
.highlight_symbol(">> ");
// Render the item list
f.render_stateful_widget(items, chunks[0], &mut app.items.state);
}