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::task::{Context, Poll};
use std::task::{Context, Poll, Waker};
use std::sync::{Arc, Mutex, MutexGuard};
use futures::prelude::*;
use futures::ready;
use futures_signals::signal::{Mutable, Signal, MutableSignalCloned, MutableLockMut};
use termion::event::Key;
use crate::input::Inputs;
use crate::schema::API;
@ -32,7 +36,6 @@ pub struct Sute<'a, S> {
// change the state.
state: SuteState<'a>,
modified: bool,
signal: S,
inputs: Inputs,
@ -47,7 +50,6 @@ impl<'a, S: Unpin> Sute<'a, S> {
Self {
state: state,
modified: false,
signal: s,
inputs: inputs,
@ -66,31 +68,51 @@ impl<'a, S: Unpin> Sute<'a, S> {
fn handle_resize(&mut self, new_size: (u16,u16)) {
self.state.size = new_size;
self.modified = true
}
pub fn get_state(&self) -> SuteState<'a> {
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> {
type Item = SuteState<'a>;
fn poll_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
match Pin::new(&mut self.inputs).poll_next(cx) {
Poll::Ready(Some(line)) => self.run_cmd(line),
let mut dirty = false;
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
Poll::Ready(None) => {
None => {
self.state.running = false;
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()))
} else {
Poll::Pending
@ -125,6 +147,7 @@ pub struct SuteState<'a> {
pub server: Option<&'a str>,
pub log: Arc<LogDrain<'a>>,
pub cmd_line: String,
pub tick_c: char,
}
impl<'a> SuteState<'a> {
@ -137,6 +160,7 @@ impl<'a> SuteState<'a> {
server: None,
log: log,
cmd_line: String::new(),
tick_c: '|',
}
}
}

View File

@ -13,7 +13,6 @@ use futures::SinkExt;
pub struct Inputs {
rx: mpsc::Receiver<Key>,
hndl: thread::JoinHandle<()>,
cmd_line: String,
}
impl Inputs {
@ -32,42 +31,14 @@ impl Inputs {
Self {
rx: rx,
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 {
type Item = String;
type Item = Key;
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)) {
if let Some(line) = self.handle_key(key) {
Poll::Ready(Some(line))
} else {
Poll::Pending
}
} else {
Poll::Pending
}
Pin::new(&mut self.rx).poll_next(cx)
}
}

View File

@ -79,6 +79,8 @@ fn main() -> Result<(), io::Error> {
let mut terminal = Terminal::new(backend)?;
terminal.hide_cursor()?;
let mut tick_c = '|';
// Refresh the screen once by resizing the terminal
if let Ok((x,y)) = termion::terminal_size() {
terminal.resize(tui::layout::Rect::new(0, 0, x,y)).unwrap();
@ -90,6 +92,14 @@ fn main() -> Result<(), io::Error> {
break;
}
tick_c = match tick_c {
'\\' => '|',
'|' => '/',
'/' => '-',
'-' => '\\',
_ => '|',
};
state.tick_c = tick_c;
terminal.draw(|f| ui::draw_ui(f, &mut state))?;
} else {
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) {
let chunk = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref())
.split(layout_chunk);
// let chunk = Layout::default()
// .direction(Direction::Horizontal)
// .constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref())
// .split(layout_chunk);
f.render_widget(Paragraph::new(app.server.unwrap_or("Not connected")), chunk[0]);
draw_logs(f, app, chunk[1])
draw_logs(f, app, layout_chunk)
}
fn draw_logs<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
// 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);
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);
}