Event handling~

This commit is contained in:
Gregor Reitzenstein 2020-11-03 13:33:37 +01:00
parent 97bc38e74a
commit 02c310aa67
4 changed files with 56 additions and 51 deletions

View File

@ -1,10 +1,14 @@
use std::mem;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll, Waker};
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use futures::prelude::*; use futures::prelude::*;
use futures::ready;
use futures_signals::signal::{Mutable, Signal, MutableSignalCloned, MutableLockMut}; use futures_signals::signal::{Mutable, Signal, MutableSignalCloned, MutableLockMut};
use termion::event::Key;
use crate::input::Inputs; use crate::input::Inputs;
use crate::schema::API; use crate::schema::API;
@ -32,7 +36,6 @@ pub struct Sute<'a, S> {
// change the state. // change the state.
state: SuteState<'a>, state: SuteState<'a>,
modified: bool,
signal: S, signal: S,
inputs: Inputs, inputs: Inputs,
@ -47,7 +50,6 @@ impl<'a, S: Unpin> Sute<'a, S> {
Self { Self {
state: state, state: state,
modified: false,
signal: s, signal: s,
inputs: inputs, inputs: inputs,
@ -66,31 +68,51 @@ impl<'a, S: Unpin> Sute<'a, S> {
fn handle_resize(&mut self, new_size: (u16,u16)) { fn handle_resize(&mut self, new_size: (u16,u16)) {
self.state.size = new_size; self.state.size = new_size;
self.modified = true
} }
pub fn get_state(&self) -> SuteState<'a> { pub fn get_state(&self) -> SuteState<'a> {
self.state.clone() self.state.clone()
} }
pub fn handle_key(&mut self, key: Key) {
match key {
Key::Char('\n') => {
let cmd = mem::replace(&mut self.state.cmd_line, String::new());
self.run_cmd(cmd);
},
Key::Char(c) => {
self.state.cmd_line.push(c);
},
Key::Backspace => {
self.state.cmd_line.pop();
},
_ => {}
}
}
} }
impl<'a, S: Signal<Item=(u16,u16)> + Unpin> Signal for Sute<'a, S> { impl<'a, S: Signal<Item=(u16,u16)> + Unpin> Signal for Sute<'a, S> {
type Item = SuteState<'a>; type Item = SuteState<'a>;
fn poll_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> { fn poll_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
match Pin::new(&mut self.inputs).poll_next(cx) { let mut dirty = false;
Poll::Ready(Some(line)) => self.run_cmd(line),
if let Poll::Ready(Some(size)) = Pin::new(&mut self.signal).poll_change(cx) {
dirty = true;
self.handle_resize(size);
}
match ready!(Pin::new(&mut self.inputs).poll_next(cx)) {
Some(key) => {
dirty = true;
self.handle_key(key);
},
// If the input closes stop the program // If the input closes stop the program
Poll::Ready(None) => { None => {
self.state.running = false; self.state.running = false;
return Poll::Ready(None); return Poll::Ready(None);
}, },
Poll::Pending => { },
}
if let Poll::Ready(Some(size)) = Pin::new(&mut self.signal).poll_change(cx) {
self.handle_resize(size);
} }
if self.modified { if dirty {
Poll::Ready(Some(self.get_state())) Poll::Ready(Some(self.get_state()))
} else { } else {
Poll::Pending Poll::Pending
@ -125,6 +147,7 @@ pub struct SuteState<'a> {
pub server: Option<&'a str>, pub server: Option<&'a str>,
pub log: Arc<LogDrain<'a>>, pub log: Arc<LogDrain<'a>>,
pub cmd_line: String, pub cmd_line: String,
pub tick_c: char,
} }
impl<'a> SuteState<'a> { impl<'a> SuteState<'a> {
@ -137,6 +160,7 @@ impl<'a> SuteState<'a> {
server: None, server: None,
log: log, log: log,
cmd_line: String::new(), cmd_line: String::new(),
tick_c: '|',
} }
} }
} }

View File

@ -13,7 +13,6 @@ use futures::SinkExt;
pub struct Inputs { pub struct Inputs {
rx: mpsc::Receiver<Key>, rx: mpsc::Receiver<Key>,
hndl: thread::JoinHandle<()>, hndl: thread::JoinHandle<()>,
cmd_line: String,
} }
impl Inputs { impl Inputs {
@ -32,42 +31,14 @@ impl Inputs {
Self { Self {
rx: rx, rx: rx,
hndl: hndl, hndl: hndl,
cmd_line: String::new(),
}
}
pub fn get_line(&self) -> &str {
self.cmd_line.as_ref()
}
pub fn handle_key(&mut self, key: Key) -> Option<String> {
match key {
Key::Char('\n') => Some(mem::replace(&mut self.cmd_line, String::new())),
Key::Char(c) => {
self.cmd_line.push(c);
None
},
Key::Backspace => {
self.cmd_line.pop();
None
},
_ => None
} }
} }
} }
impl Stream for Inputs { impl Stream for Inputs {
type Item = String; type Item = Key;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> { fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
if let Some(key) = ready!(Pin::new(&mut self.rx).poll_next(cx)) { Pin::new(&mut self.rx).poll_next(cx)
if let Some(line) = self.handle_key(key) {
Poll::Ready(Some(line))
} else {
Poll::Pending
}
} else {
Poll::Pending
}
} }
} }

View File

@ -79,6 +79,8 @@ fn main() -> Result<(), io::Error> {
let mut terminal = Terminal::new(backend)?; let mut terminal = Terminal::new(backend)?;
terminal.hide_cursor()?; terminal.hide_cursor()?;
let mut tick_c = '|';
// Refresh the screen once by resizing the terminal // Refresh the screen once by resizing the terminal
if let Ok((x,y)) = termion::terminal_size() { if let Ok((x,y)) = termion::terminal_size() {
terminal.resize(tui::layout::Rect::new(0, 0, x,y)).unwrap(); terminal.resize(tui::layout::Rect::new(0, 0, x,y)).unwrap();
@ -90,6 +92,14 @@ fn main() -> Result<(), io::Error> {
break; break;
} }
tick_c = match tick_c {
'\\' => '|',
'|' => '/',
'/' => '-',
'-' => '\\',
_ => '|',
};
state.tick_c = tick_c;
terminal.draw(|f| ui::draw_ui(f, &mut state))?; terminal.draw(|f| ui::draw_ui(f, &mut state))?;
} else { } else {
break; break;

View File

@ -31,14 +31,12 @@ fn draw_header<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk:
} }
fn draw_main<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) { fn draw_main<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
let chunk = Layout::default() // let chunk = Layout::default()
.direction(Direction::Horizontal) // .direction(Direction::Horizontal)
.constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref()) // .constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref())
.split(layout_chunk); // .split(layout_chunk);
f.render_widget(Paragraph::new(app.server.unwrap_or("Not connected")), chunk[0]); draw_logs(f, app, layout_chunk)
draw_logs(f, app, chunk[1])
} }
fn draw_logs<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) { fn draw_logs<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
// TODO: Just use a signal. // TODO: Just use a signal.
@ -53,5 +51,7 @@ fn draw_command_line<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_c
let inner_rect = block.inner(layout_chunk); let inner_rect = block.inner(layout_chunk);
f.render_widget(block, layout_chunk); f.render_widget(block, layout_chunk);
f.render_widget(Paragraph::new(app.cmd_line.as_ref()), inner_rect);
let cmdline = format!("{} > {}", app.tick_c, app.cmd_line);
f.render_widget(Paragraph::new(&cmdline[..]), inner_rect);
} }