lunar-mining 4 лет назад
Родитель
Сommit
22034e1c40
5 измененных файлов с 250 добавлено и 63 удалено
  1. 39 0
      bin/map/src/app.rs
  2. 44 0
      bin/map/src/list.rs
  3. 118 63
      bin/map/src/main.rs
  4. 7 0
      bin/map/src/mod.rs
  5. 42 0
      bin/map/src/ui.rs

+ 39 - 0
bin/map/src/app.rs

@@ -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 - 0
bin/map/src/list.rs

@@ -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);
+    }
+}

+ 118 - 63
bin/map/src/main.rs

@@ -1,87 +1,138 @@
 // make async task that updates info
 // make async task that updates info
 // this display that
 // this display that
 //use drk::Result;
 //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 termion::{async_stdin, event::Key, input::TermRead, raw::IntoRawMode};
 use tui::{
 use tui::{
-    backend::TermionBackend,
+    backend::{Backend, TermionBackend},
     layout::{Constraint, Direction, Layout},
     layout::{Constraint, Direction, Layout},
     style::{Color, Modifier, Style},
     style::{Color, Modifier, Style},
     text::{Span, Spans, Text},
     text::{Span, Spans, Text},
-    widgets::{ListState, Block, Borders, List, ListItem, Paragraph, Wrap},
+    widgets::{Block, Borders, List, ListItem, ListState, Paragraph, Wrap},
     Terminal,
     Terminal,
 };
 };
 
 
+pub mod app;
+pub mod list;
+pub mod ui;
+
+use crate::app::App;
+
 fn main() -> Result<(), io::Error> {
 fn main() -> Result<(), io::Error> {
     // Set up terminal output
     // Set up terminal output
     let stdout = io::stdout().into_raw_mode()?;
     let stdout = io::stdout().into_raw_mode()?;
     let backend = TermionBackend::new(stdout);
     let backend = TermionBackend::new(stdout);
     let mut terminal = Terminal::new(backend)?;
     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.
     // Create a separate thread to poll stdin.
     // This provides non-blocking input support.
     // This provides non-blocking input support.
-    let mut asi = async_stdin();
+    //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);
-            }
+    //// 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]);
 
 
-            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 });
+    //        // 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);
+    //        //}
 
 
-            frame.render_widget(graph, chunks[1]);
-        })?;
+    //        //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();
+
+    let mut last_tick = Instant::now();
+    loop {
+        terminal.draw(|f| ui::ui(f, &mut app))?;
 
 
-        // Iterate over all the keys that have been pressed since the
-        // last time we checked.
         for k in asi.by_ref().keys() {
         for k in asi.by_ref().keys() {
             match k.unwrap() {
             match k.unwrap() {
                 // If any of them is q, quit
                 // If any of them is q, quit
@@ -91,11 +142,15 @@ fn main() -> Result<(), io::Error> {
                     terminal.clear()?;
                     terminal.clear()?;
                     return Ok(())
                     return Ok(())
                 }
                 }
-                Key::Char('j') => {
-                }
+                Key::Char('j') => app.items.next(),
+                Key::Char('k') => app.items.previous(),
                 // Otherwise, throw them away.
                 // Otherwise, throw them away.
                 _ => (),
                 _ => (),
             }
             }
         }
         }
+
+        if last_tick.elapsed() >= tick_rate {
+            last_tick = Instant::now();
+        }
     }
     }
 }
 }

+ 7 - 0
bin/map/src/mod.rs

@@ -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 - 0
bin/map/src/ui.rs

@@ -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);
+}