diff --git a/candid_cli/src/main.rs b/candid_cli/src/main.rs index 1a5551c..dbc5d2d 100644 --- a/candid_cli/src/main.rs +++ b/candid_cli/src/main.rs @@ -27,16 +27,8 @@ fn main() { let client = CandidConnection::new(addr).expect("Couldn't connect to server"); - for i in 1..10 { - let data = random::().to_ne_bytes(); - println!("Sending {}, {:?}", i, data); - client.write_frame(i + 0x123, data); - } - - /* for line in client.lines() { let line = line.unwrap(); println!("Received: \"{}\"", line); } - */ } -- 2.51.2 From a9424e04d2f3d9e6f664cb7a41a9ed89881658b7 Mon Sep 17 00:00:00 2001 From: Alex van de Sandt Date: Thu, 11 Apr 2019 19:43:42 -0400 Subject: [PATCH 2/9] Remove unneeded dependencies --- candid_cli/Cargo.toml | 1 - candid_cli/src/main.rs | 7 ------- 2 files changed, 8 deletions(-) diff --git a/candid_cli/Cargo.toml b/candid_cli/Cargo.toml index 3ee685e..647d693 100644 --- a/candid_cli/Cargo.toml +++ b/candid_cli/Cargo.toml @@ -13,4 +13,3 @@ keywords = ["CAN", "SocketCAN"] [dependencies] candid_client = "^0.1" clap = "^2.32" -rand = "*" diff --git a/candid_cli/src/main.rs b/candid_cli/src/main.rs index dbc5d2d..33909b1 100644 --- a/candid_cli/src/main.rs +++ b/candid_cli/src/main.rs @@ -1,14 +1,7 @@ -extern crate rand; - -use rand::prelude::*; - use candid_client::*; use clap::{App, Arg}; -use std::io::Write; -use std::net::TcpStream; - fn main() { let matches = App::new("CANdid Client") .version("0.1.0") -- 2.51.2 From 255aa7768571e8c91ee8213c2abad3ee49b4ef1c Mon Sep 17 00:00:00 2001 From: Alex van de Sandt Date: Thu, 11 Apr 2019 19:47:12 -0400 Subject: [PATCH 3/9] Rename crate to `candid_tui` --- Cargo.toml | 2 +- {candid_cli => candid_tui}/Cargo.toml | 3 ++- {candid_cli => candid_tui}/src/main.rs | 0 3 files changed, 3 insertions(+), 2 deletions(-) rename {candid_cli => candid_tui}/Cargo.toml (90%) rename {candid_cli => candid_tui}/src/main.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 7d4e4e5..0c4d542 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,5 +2,5 @@ members = [ "candid_server", "candid_client", - "candid_cli", + "candid_tui", ] diff --git a/candid_cli/Cargo.toml b/candid_tui/Cargo.toml similarity index 90% rename from candid_cli/Cargo.toml rename to candid_tui/Cargo.toml index 647d693..bd035af 100644 --- a/candid_cli/Cargo.toml +++ b/candid_tui/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "candid_cli" +name = "candid_tui" version = "0.1.0" authors = ["Alex van de Sandt "] edition = "2018" @@ -9,6 +9,7 @@ readme = "README" documentation = "https://docs.rs/crate/candid_client/" repository = "https://gitlab.com/avandesa/candid-rs" keywords = ["CAN", "SocketCAN"] +publish = false [dependencies] candid_client = "^0.1" diff --git a/candid_cli/src/main.rs b/candid_tui/src/main.rs similarity index 100% rename from candid_cli/src/main.rs rename to candid_tui/src/main.rs -- 2.51.2 From f7122c239e8004f666ee4fc88a4256a42ac6ee4e Mon Sep 17 00:00:00 2001 From: Alex van de Sandt Date: Thu, 11 Apr 2019 21:18:23 -0400 Subject: [PATCH 4/9] Start implementing tui with app state --- candid_tui/Cargo.toml | 2 ++ candid_tui/src/app.rs | 21 +++++++++++++++++++++ candid_tui/src/main.rs | 36 +++++++++++++++++++++++++++++++----- candid_tui/src/ui.rs | 22 ++++++++++++++++++++++ candid_tui/src/util.rs | 26 ++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 candid_tui/src/app.rs create mode 100644 candid_tui/src/ui.rs create mode 100644 candid_tui/src/util.rs diff --git a/candid_tui/Cargo.toml b/candid_tui/Cargo.toml index bd035af..4728e42 100644 --- a/candid_tui/Cargo.toml +++ b/candid_tui/Cargo.toml @@ -14,3 +14,5 @@ publish = false [dependencies] candid_client = "^0.1" clap = "^2.32" +tui = "^0.5" +termion = "^1.5" diff --git a/candid_tui/src/app.rs b/candid_tui/src/app.rs new file mode 100644 index 0000000..8f5304d --- /dev/null +++ b/candid_tui/src/app.rs @@ -0,0 +1,21 @@ +use crate::util::ListState; + +use candid_client::*; + +pub struct AppState<'a> { + pub title: &'a str, + pub should_quit: bool, + pub server: CandidConnection, + pub frame_history: ListState<&'a str>, +} + +impl<'a> AppState<'a> { + pub fn new(title: &'a str, server: CandidConnection) -> AppState<'a> { + AppState { + title, + should_quit: false, + server, + frame_history: ListState::new(Vec::new()), + } + } +} diff --git a/candid_tui/src/main.rs b/candid_tui/src/main.rs index 33909b1..99ea1dc 100644 --- a/candid_tui/src/main.rs +++ b/candid_tui/src/main.rs @@ -1,7 +1,21 @@ +mod app; +mod ui; +mod util; + use candid_client::*; +use crate::app::AppState; + +use std::io; + use clap::{App, Arg}; +use termion::raw::IntoRawMode; +use termion::screen::AlternateScreen; + +use tui::backend::TermionBackend; +use tui::Terminal; + fn main() { let matches = App::new("CANdid Client") .version("0.1.0") @@ -18,10 +32,22 @@ fn main() { let addr = matches.value_of("addr").unwrap(); - let client = CandidConnection::new(addr).expect("Couldn't connect to server"); + let server = CandidConnection::new(addr).expect("Couldn't connect to server"); + + // Initialize tui + let stdout = io::stdout().into_raw_mode().unwrap(); + let stdout = AlternateScreen::from(stdout); + let backend = TermionBackend::new(stdout); + let mut terminal = Terminal::new(backend).unwrap(); + terminal.hide_cursor().unwrap(); - for line in client.lines() { - let line = line.unwrap(); - println!("Received: \"{}\"", line); - } + // Initialize the app state + let mut app = AppState::new("CANdid TUI", server); + app.frame_history.push("frame 1"); + app.frame_history.push("frame 2"); + app.frame_history.push("frame 3"); + app.frame_history.push("frame 4"); + app.frame_history.push("frame 5"); + ui::draw(&mut terminal, &app).unwrap(); + std::thread::sleep(std::time::Duration::from_millis(1000)); } diff --git a/candid_tui/src/ui.rs b/candid_tui/src/ui.rs new file mode 100644 index 0000000..b5e1e17 --- /dev/null +++ b/candid_tui/src/ui.rs @@ -0,0 +1,22 @@ +use crate::app::AppState; + +use std::io; + +use tui::backend::Backend; +use tui::style::{Color, Modifier, Style}; +use tui::widgets::{Block, Borders, SelectableList, Widget}; +use tui::Terminal; + +pub fn draw(terminal: &mut Terminal, app: &AppState) -> Result<(), io::Error> { + terminal.draw(|mut f| { + let size = f.size(); + // Box, size of the terminal, all borders, title from app state + SelectableList::default() + .block(Block::default().borders(Borders::ALL).title(app.title)) + .items(&app.frame_history.items) + .select(Some(app.frame_history.selected)) + //.highlight_style(Style::default().fg(Color::Yellow).modifier(Modifier::BOLD)) + .highlight_symbol(">") + .render(&mut f, size) + }) +} diff --git a/candid_tui/src/util.rs b/candid_tui/src/util.rs new file mode 100644 index 0000000..dfb1db4 --- /dev/null +++ b/candid_tui/src/util.rs @@ -0,0 +1,26 @@ +pub struct ListState { + pub items: Vec, + pub selected: usize, +} + +impl ListState { + pub fn new(items: Vec) -> ListState { + ListState { items, selected: 0 } + } + + pub fn push(&mut self, item: I) { + self.items.push(item); + } + + pub fn previous(&mut self) { + if self.selected > 0 { + self.selected -= 1; + } + } + + pub fn next(&mut self) { + if self.selected < self.items.len() - 1 { + self.selected += 1 + } + } +} -- 2.51.2 From d620d3b1d291cded88e4ce1cfae46d7d01e63529 Mon Sep 17 00:00:00 2001 From: Alex van de Sandt Date: Thu, 11 Apr 2019 23:09:19 -0400 Subject: [PATCH 5/9] Implement event aggregator and main loop --- candid_tui/src/app.rs | 27 ++++++++++++++- candid_tui/src/event.rs | 73 +++++++++++++++++++++++++++++++++++++++++ candid_tui/src/main.rs | 29 ++++++++++++++-- candid_tui/src/ui.rs | 4 +-- candid_tui/src/util.rs | 12 +++++-- 5 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 candid_tui/src/event.rs diff --git a/candid_tui/src/app.rs b/candid_tui/src/app.rs index 8f5304d..9c12ade 100644 --- a/candid_tui/src/app.rs +++ b/candid_tui/src/app.rs @@ -1,21 +1,46 @@ +//! Module for maintaining app state + use crate::util::ListState; use candid_client::*; +/// Container for everything related to application state pub struct AppState<'a> { + /// The title to be displayed in the top left pub title: &'a str, + + /// Whether or not the app should terminate pub should_quit: bool, + + /// The connection to the CANdid server, from which frames are read pub server: CandidConnection, + + /// The frames that have been received from the server to this point pub frame_history: ListState<&'a str>, } impl<'a> AppState<'a> { + /// Initialize a new app pub fn new(title: &'a str, server: CandidConnection) -> AppState<'a> { AppState { title, should_quit: false, server, - frame_history: ListState::new(Vec::new()), + frame_history: ListState::new(), + } + } + + pub fn on_key(&mut self, c: char) { + match c { + 'q' => self.should_quit = true, + _ => {} } } + + pub fn on_up(&mut self) { + self.frame_history.previous(); + } + pub fn on_down(&mut self) { + self.frame_history.next(); + } } diff --git a/candid_tui/src/event.rs b/candid_tui/src/event.rs new file mode 100644 index 0000000..c50b35e --- /dev/null +++ b/candid_tui/src/event.rs @@ -0,0 +1,73 @@ +//! A module for configuring and executing event loops. An `Events` instance will listen to `stdin +//! for user input and read frames from the server, aggregating these events to be sent back to the +//! app itself. +//! +//! All code in this module is *heavily* inspired by [`tui-rs`'s demo +//! code](https://github.com/fdehau/tui-rs/blob/master/examples/util/event.rs) + +use std::sync::mpsc; +use std::{io, thread}; + +use termion::event::Key; +use termion::input::TermRead; + +pub enum Event { + Input(I), +} + +/// An event handler that wraps termion input and tick events. +/// Each event thype is handled in its own thread and returned to a common `Receiver` +pub struct Events { + rx: mpsc::Receiver>, + input_handle: thread::JoinHandle<()>, + // TODO: Add thread for reading from server +} + +impl Events { + pub fn new() -> Events { + Events::with_config(Config::default()) + } + + pub fn with_config(config: Config) -> Events { + let (tx, rx) = mpsc::channel(); + + let input_handle = { + let tx = tx.clone(); + thread::spawn(move || { + let stdin = io::stdin(); + for evt in stdin.keys() { + match evt { + Ok(key) => { + if let Err(_) = tx.send(Event::Input(key)) { + return; + } + if key == config.exit_key { + return; + } + } + Err(_) => {} + } + } + }) + }; + + Events { rx, input_handle } + } + + pub fn next(&self) -> Result, mpsc::RecvError> { + self.rx.recv() + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Config { + pub exit_key: Key, +} + +impl Default for Config { + fn default() -> Config { + Config { + exit_key: Key::Char('q'), + } + } +} diff --git a/candid_tui/src/main.rs b/candid_tui/src/main.rs index 99ea1dc..ab9fabd 100644 --- a/candid_tui/src/main.rs +++ b/candid_tui/src/main.rs @@ -1,15 +1,18 @@ mod app; +mod event; mod ui; mod util; use candid_client::*; use crate::app::AppState; +use crate::event::{Event, Events}; use std::io; use clap::{App, Arg}; +use termion::event::Key; use termion::raw::IntoRawMode; use termion::screen::AlternateScreen; @@ -43,11 +46,33 @@ fn main() { // Initialize the app state let mut app = AppState::new("CANdid TUI", server); - app.frame_history.push("frame 1"); + app.frame_history.push("frame 1"); // Placeholder frames for now app.frame_history.push("frame 2"); app.frame_history.push("frame 3"); app.frame_history.push("frame 4"); app.frame_history.push("frame 5"); - ui::draw(&mut terminal, &app).unwrap(); + + // Initialize the event aggregator + let events = Events::new(); + + loop { + // Refresh the ui + ui::draw(&mut terminal, &app).unwrap(); + + // Handle an incoming event + match events.next().unwrap() { + Event::Input(key) => match key { + Key::Char(c) => app.on_key(c), + Key::Up => app.on_up(), + Key::Down => app.on_down(), + _ => {} + }, + } + + // Exit if necessary, set in app.on_key(q) + if app.should_quit { + break; + } + } std::thread::sleep(std::time::Duration::from_millis(1000)); } diff --git a/candid_tui/src/ui.rs b/candid_tui/src/ui.rs index b5e1e17..8b2be02 100644 --- a/candid_tui/src/ui.rs +++ b/candid_tui/src/ui.rs @@ -10,12 +10,12 @@ use tui::Terminal; pub fn draw(terminal: &mut Terminal, app: &AppState) -> Result<(), io::Error> { terminal.draw(|mut f| { let size = f.size(); - // Box, size of the terminal, all borders, title from app state + // List all the frames received to this point SelectableList::default() .block(Block::default().borders(Borders::ALL).title(app.title)) .items(&app.frame_history.items) .select(Some(app.frame_history.selected)) - //.highlight_style(Style::default().fg(Color::Yellow).modifier(Modifier::BOLD)) + .highlight_style(Style::default().fg(Color::Yellow).modifier(Modifier::BOLD)) .highlight_symbol(">") .render(&mut f, size) }) diff --git a/candid_tui/src/util.rs b/candid_tui/src/util.rs index dfb1db4..481e934 100644 --- a/candid_tui/src/util.rs +++ b/candid_tui/src/util.rs @@ -1,23 +1,31 @@ +/// Keeps track of the position in a list, ued for SelectableLists pub struct ListState { pub items: Vec, pub selected: usize, } impl ListState { - pub fn new(items: Vec) -> ListState { - ListState { items, selected: 0 } + /// Initialize a new ListState with no items + pub fn new() -> ListState { + ListState { + items: Vec::new(), + selected: 0, + } } + /// Add an item to the end of the list pub fn push(&mut self, item: I) { self.items.push(item); } + /// Select the previous item in the list pub fn previous(&mut self) { if self.selected > 0 { self.selected -= 1; } } + /// Select the next item in the list pub fn next(&mut self) { if self.selected < self.items.len() - 1 { self.selected += 1 -- 2.51.2 From 4c62879e9da2656ddd7f48a58ee434a08a396b82 Mon Sep 17 00:00:00 2001 From: Alex van de Sandt Date: Fri, 12 Apr 2019 14:46:13 -0400 Subject: [PATCH 6/9] Create a dummy loop for frames, extract to lib --- candid_tui/src/event.rs | 30 ++++++++++++++++++++++++++---- candid_tui/src/frame.rs | 3 +++ candid_tui/src/lib.rs | 9 +++++++++ candid_tui/src/main.rs | 18 +++++++++--------- 4 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 candid_tui/src/frame.rs create mode 100644 candid_tui/src/lib.rs diff --git a/candid_tui/src/event.rs b/candid_tui/src/event.rs index c50b35e..d69792e 100644 --- a/candid_tui/src/event.rs +++ b/candid_tui/src/event.rs @@ -5,6 +5,8 @@ //! All code in this module is *heavily* inspired by [`tui-rs`'s demo //! code](https://github.com/fdehau/tui-rs/blob/master/examples/util/event.rs) +use crate::frame::Frame; + use std::sync::mpsc; use std::{io, thread}; @@ -13,25 +15,33 @@ use termion::input::TermRead; pub enum Event { Input(I), + Frame(Frame), } /// An event handler that wraps termion input and tick events. /// Each event thype is handled in its own thread and returned to a common `Receiver` pub struct Events { + /// The receiver that aggregates all other events rx: mpsc::Receiver>, - input_handle: thread::JoinHandle<()>, - // TODO: Add thread for reading from server + + /// Thread that reads input from the user + _input_handle: thread::JoinHandle<()>, + + /// Thread that reads frames from the remote CANdid server + _frame_handle: thread::JoinHandle<()>, } impl Events { + /// Creates a new event with default configuration ('quit' key is `q`) pub fn new() -> Events { Events::with_config(Config::default()) } + /// Creates a new event with custom configuration pub fn with_config(config: Config) -> Events { let (tx, rx) = mpsc::channel(); - let input_handle = { + let _input_handle = { let tx = tx.clone(); thread::spawn(move || { let stdin = io::stdin(); @@ -51,7 +61,19 @@ impl Events { }) }; - Events { rx, input_handle } + let _frame_handle = { + let tx = tx.clone(); + thread::spawn(move || loop { + tx.send(Event::Frame(Frame { msg: "A frame" })).unwrap(); + thread::sleep(std::time::Duration::from_millis(1000)); + }) + }; + + Events { + rx, + _input_handle, + _frame_handle, + } } pub fn next(&self) -> Result, mpsc::RecvError> { diff --git a/candid_tui/src/frame.rs b/candid_tui/src/frame.rs new file mode 100644 index 0000000..e518b20 --- /dev/null +++ b/candid_tui/src/frame.rs @@ -0,0 +1,3 @@ +pub struct Frame { + pub msg: &'static str, +} diff --git a/candid_tui/src/lib.rs b/candid_tui/src/lib.rs new file mode 100644 index 0000000..6a0e163 --- /dev/null +++ b/candid_tui/src/lib.rs @@ -0,0 +1,9 @@ +pub mod app; +pub mod event; +pub mod frame; +pub mod ui; +pub mod util; + +pub use app::AppState; +pub use event::{Event, Events}; +pub use ui::draw; diff --git a/candid_tui/src/main.rs b/candid_tui/src/main.rs index ab9fabd..9e17b60 100644 --- a/candid_tui/src/main.rs +++ b/candid_tui/src/main.rs @@ -1,12 +1,12 @@ -mod app; -mod event; -mod ui; -mod util; +/* +use candid_tui::app::AppState; +use candid_tui::event::{Event, Events}; +use candid_tui::ui; +*/ -use candid_client::*; +use candid_tui::*; -use crate::app::AppState; -use crate::event::{Event, Events}; +use candid_client::*; use std::io; @@ -57,7 +57,7 @@ fn main() { loop { // Refresh the ui - ui::draw(&mut terminal, &app).unwrap(); + candid_tui::draw(&mut terminal, &app).unwrap(); // Handle an incoming event match events.next().unwrap() { @@ -67,6 +67,7 @@ fn main() { Key::Down => app.on_down(), _ => {} }, + Event::Frame(frame) => app.frame_history.push(frame.msg), } // Exit if necessary, set in app.on_key(q) @@ -74,5 +75,4 @@ fn main() { break; } } - std::thread::sleep(std::time::Duration::from_millis(1000)); } -- 2.51.2 From 1511a57ad3fe7118e52992845eb1a30f9faadbdc Mon Sep 17 00:00:00 2001 From: Alex van de Sandt Date: Sat, 13 Apr 2019 09:28:59 -0400 Subject: [PATCH 7/9] Update ui to use new client version --- candid_tui/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/candid_tui/Cargo.toml b/candid_tui/Cargo.toml index 4728e42..2f3d323 100644 --- a/candid_tui/Cargo.toml +++ b/candid_tui/Cargo.toml @@ -12,7 +12,7 @@ keywords = ["CAN", "SocketCAN"] publish = false [dependencies] -candid_client = "^0.1" +candid_client = "0.3" clap = "^2.32" -tui = "^0.5" +tui = "0.5" termion = "^1.5" -- 2.51.2 From cb5f29321d5d6566d6a4df6ec6d0d9f000cad172 Mon Sep 17 00:00:00 2001 From: Alex van de Sandt Date: Sat, 13 Apr 2019 10:51:16 -0400 Subject: [PATCH 8/9] Use Frames from candid_tui --- candid_tui/Cargo.toml | 2 +- candid_tui/src/app.rs | 4 ++-- candid_tui/src/event.rs | 11 ++++++++--- candid_tui/src/frame.rs | 3 --- candid_tui/src/lib.rs | 1 - candid_tui/src/main.rs | 13 +------------ candid_tui/src/util.rs | 12 ++++++++++++ 7 files changed, 24 insertions(+), 22 deletions(-) delete mode 100644 candid_tui/src/frame.rs diff --git a/candid_tui/Cargo.toml b/candid_tui/Cargo.toml index 2f3d323..cd0ba2b 100644 --- a/candid_tui/Cargo.toml +++ b/candid_tui/Cargo.toml @@ -12,7 +12,7 @@ keywords = ["CAN", "SocketCAN"] publish = false [dependencies] -candid_client = "0.3" +candid_client = "0.3.2" clap = "^2.32" tui = "0.5" termion = "^1.5" diff --git a/candid_tui/src/app.rs b/candid_tui/src/app.rs index 9c12ade..b9881fa 100644 --- a/candid_tui/src/app.rs +++ b/candid_tui/src/app.rs @@ -1,6 +1,6 @@ //! Module for maintaining app state -use crate::util::ListState; +use crate::util::{FrameInfo, ListState}; use candid_client::*; @@ -16,7 +16,7 @@ pub struct AppState<'a> { pub server: CandidConnection, /// The frames that have been received from the server to this point - pub frame_history: ListState<&'a str>, + pub frame_history: ListState, } impl<'a> AppState<'a> { diff --git a/candid_tui/src/event.rs b/candid_tui/src/event.rs index d69792e..340ee1c 100644 --- a/candid_tui/src/event.rs +++ b/candid_tui/src/event.rs @@ -5,17 +5,19 @@ //! All code in this module is *heavily* inspired by [`tui-rs`'s demo //! code](https://github.com/fdehau/tui-rs/blob/master/examples/util/event.rs) -use crate::frame::Frame; +use crate::util::FrameInfo; use std::sync::mpsc; use std::{io, thread}; +use candid_client::Frame; + use termion::event::Key; use termion::input::TermRead; pub enum Event { Input(I), - Frame(Frame), + Frame(FrameInfo), } /// An event handler that wraps termion input and tick events. @@ -64,7 +66,10 @@ impl Events { let _frame_handle = { let tx = tx.clone(); thread::spawn(move || loop { - tx.send(Event::Frame(Frame { msg: "A frame" })).unwrap(); + let frame = Frame::new(0, [0 as u8; 8]); + let frame = FrameInfo(frame, format!("{:?}", frame).to_string()); + + tx.send(Event::Frame(frame)).unwrap(); thread::sleep(std::time::Duration::from_millis(1000)); }) }; diff --git a/candid_tui/src/frame.rs b/candid_tui/src/frame.rs deleted file mode 100644 index e518b20..0000000 --- a/candid_tui/src/frame.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub struct Frame { - pub msg: &'static str, -} diff --git a/candid_tui/src/lib.rs b/candid_tui/src/lib.rs index 6a0e163..a188e6b 100644 --- a/candid_tui/src/lib.rs +++ b/candid_tui/src/lib.rs @@ -1,6 +1,5 @@ pub mod app; pub mod event; -pub mod frame; pub mod ui; pub mod util; diff --git a/candid_tui/src/main.rs b/candid_tui/src/main.rs index 9e17b60..fa13344 100644 --- a/candid_tui/src/main.rs +++ b/candid_tui/src/main.rs @@ -1,9 +1,3 @@ -/* -use candid_tui::app::AppState; -use candid_tui::event::{Event, Events}; -use candid_tui::ui; -*/ - use candid_tui::*; use candid_client::*; @@ -46,11 +40,6 @@ fn main() { // Initialize the app state let mut app = AppState::new("CANdid TUI", server); - app.frame_history.push("frame 1"); // Placeholder frames for now - app.frame_history.push("frame 2"); - app.frame_history.push("frame 3"); - app.frame_history.push("frame 4"); - app.frame_history.push("frame 5"); // Initialize the event aggregator let events = Events::new(); @@ -67,7 +56,7 @@ fn main() { Key::Down => app.on_down(), _ => {} }, - Event::Frame(frame) => app.frame_history.push(frame.msg), + Event::Frame(frame) => app.frame_history.push(frame), } // Exit if necessary, set in app.on_key(q) diff --git a/candid_tui/src/util.rs b/candid_tui/src/util.rs index 481e934..d549f16 100644 --- a/candid_tui/src/util.rs +++ b/candid_tui/src/util.rs @@ -1,3 +1,5 @@ +use candid_client::Frame; + /// Keeps track of the position in a list, ued for SelectableLists pub struct ListState { pub items: Vec, @@ -32,3 +34,13 @@ impl ListState { } } } + +/// Holds the Frame and its string representation +pub struct FrameInfo(pub Frame, pub String); + +impl AsRef for FrameInfo { + /// Allows the FrameInfo to be used in a SelectableList + fn as_ref(&self) -> &str { + &self.1 + } +} -- 2.51.2 From f912012f1da4c4357a3437fc70d565dfba0f7148 Mon Sep 17 00:00:00 2001 From: Alex van de Sandt Date: Sat, 13 Apr 2019 11:13:44 -0400 Subject: [PATCH 9/9] Display real frames from the server --- candid_tui/src/app.rs | 6 +----- candid_tui/src/event.rs | 29 +++++------------------------ candid_tui/src/main.rs | 4 ++-- 3 files changed, 8 insertions(+), 31 deletions(-) diff --git a/candid_tui/src/app.rs b/candid_tui/src/app.rs index b9881fa..17b8208 100644 --- a/candid_tui/src/app.rs +++ b/candid_tui/src/app.rs @@ -12,20 +12,16 @@ pub struct AppState<'a> { /// Whether or not the app should terminate pub should_quit: bool, - /// The connection to the CANdid server, from which frames are read - pub server: CandidConnection, - /// The frames that have been received from the server to this point pub frame_history: ListState, } impl<'a> AppState<'a> { /// Initialize a new app - pub fn new(title: &'a str, server: CandidConnection) -> AppState<'a> { + pub fn new(title: &'a str) -> AppState<'a> { AppState { title, should_quit: false, - server, frame_history: ListState::new(), } } diff --git a/candid_tui/src/event.rs b/candid_tui/src/event.rs index 340ee1c..4b5cb0a 100644 --- a/candid_tui/src/event.rs +++ b/candid_tui/src/event.rs @@ -10,7 +10,7 @@ use crate::util::FrameInfo; use std::sync::mpsc; use std::{io, thread}; -use candid_client::Frame; +use candid_client::*; use termion::event::Key; use termion::input::TermRead; @@ -34,13 +34,8 @@ pub struct Events { } impl Events { - /// Creates a new event with default configuration ('quit' key is `q`) - pub fn new() -> Events { - Events::with_config(Config::default()) - } - - /// Creates a new event with custom configuration - pub fn with_config(config: Config) -> Events { + /// Creates a new event handle + pub fn new(mut server: CandidConnection) -> Events { let (tx, rx) = mpsc::channel(); let _input_handle = { @@ -53,7 +48,7 @@ impl Events { if let Err(_) = tx.send(Event::Input(key)) { return; } - if key == config.exit_key { + if key == Key::Char('q') { return; } } @@ -66,11 +61,10 @@ impl Events { let _frame_handle = { let tx = tx.clone(); thread::spawn(move || loop { - let frame = Frame::new(0, [0 as u8; 8]); + let frame = server.read_frame().unwrap(); let frame = FrameInfo(frame, format!("{:?}", frame).to_string()); tx.send(Event::Frame(frame)).unwrap(); - thread::sleep(std::time::Duration::from_millis(1000)); }) }; @@ -85,16 +79,3 @@ impl Events { self.rx.recv() } } - -#[derive(Debug, Clone, Copy)] -pub struct Config { - pub exit_key: Key, -} - -impl Default for Config { - fn default() -> Config { - Config { - exit_key: Key::Char('q'), - } - } -} diff --git a/candid_tui/src/main.rs b/candid_tui/src/main.rs index fa13344..d9a8430 100644 --- a/candid_tui/src/main.rs +++ b/candid_tui/src/main.rs @@ -39,10 +39,10 @@ fn main() { terminal.hide_cursor().unwrap(); // Initialize the app state - let mut app = AppState::new("CANdid TUI", server); + let mut app = AppState::new("CANdid TUI"); // Initialize the event aggregator - let events = Events::new(); + let events = Events::new(server); loop { // Refresh the ui