Separate out event logic again
This commit is contained in:
parent
df59e45b80
commit
8d6446d886
45
src/main.rs
45
src/main.rs
@ -2,8 +2,9 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
mod calc;
|
mod calc;
|
||||||
mod util;
|
|
||||||
mod format;
|
mod format;
|
||||||
|
mod util;
|
||||||
|
use util::event::{Event, Events};
|
||||||
|
|
||||||
use calc::constants::{CalculatorDisplayMode, CalculatorState, RegisterState};
|
use calc::constants::{CalculatorDisplayMode, CalculatorState, RegisterState};
|
||||||
use calc::errors::CalculatorResult;
|
use calc::errors::CalculatorResult;
|
||||||
@ -19,9 +20,7 @@ use std::convert::TryFrom;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
use std::{error::Error, io};
|
use std::{error::Error, io};
|
||||||
// use termion::{event::Key, raw::IntoRawMode, screen::AlternateScreen};
|
|
||||||
use tui::{
|
use tui::{
|
||||||
backend::CrosstermBackend,
|
backend::CrosstermBackend,
|
||||||
layout::{Constraint, Direction, Layout},
|
layout::{Constraint, Direction, Layout},
|
||||||
@ -31,9 +30,6 @@ use tui::{
|
|||||||
widgets::{Block, Borders, Clear, List, ListItem, Paragraph},
|
widgets::{Block, Borders, Clear, List, ListItem, Paragraph},
|
||||||
Terminal,
|
Terminal,
|
||||||
};
|
};
|
||||||
use util::event::Event;
|
|
||||||
|
|
||||||
const TICK_RATE: Duration = Duration::from_millis(250);
|
|
||||||
|
|
||||||
struct Dimensions {
|
struct Dimensions {
|
||||||
width: u16,
|
width: u16,
|
||||||
@ -78,29 +74,9 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let backend = CrosstermBackend::new(stdout);
|
let backend = CrosstermBackend::new(stdout);
|
||||||
let mut terminal = Terminal::new(backend)?;
|
let mut terminal = Terminal::new(backend)?;
|
||||||
|
|
||||||
let (tx, rx) = mpsc::channel();
|
let events = Events::new(250);
|
||||||
let mut app = App::default();
|
let mut app = App::default();
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
let mut last_tick = Instant::now();
|
|
||||||
loop {
|
|
||||||
// poll for tick rate duration, if no events, sent tick event.
|
|
||||||
let timeout = TICK_RATE
|
|
||||||
.checked_sub(last_tick.elapsed())
|
|
||||||
.unwrap_or_else(|| Duration::from_secs(0));
|
|
||||||
if event::poll(timeout).unwrap() {
|
|
||||||
if let CEvent::Key(key) = event::read().unwrap() {
|
|
||||||
tx.send(Event::Input(key)).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if last_tick.elapsed() >= TICK_RATE {
|
|
||||||
tx.send(Event::Tick).unwrap();
|
|
||||||
last_tick = Instant::now();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
'outer: loop {
|
'outer: loop {
|
||||||
terminal.draw(|f| {
|
terminal.draw(|f| {
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
@ -304,7 +280,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Event::Input(key) = rx.recv()? {
|
if let Event::Input(key) = events.next()? {
|
||||||
app.error_msg = match handle_key(&mut app, key) {
|
app.error_msg = match handle_key(&mut app, key) {
|
||||||
// Exit the program
|
// Exit the program
|
||||||
Ok(CalculatorResponse::Quit) => break 'outer,
|
Ok(CalculatorResponse::Quit) => break 'outer,
|
||||||
@ -314,7 +290,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Slurp events without a redraw
|
// Slurp events without a redraw
|
||||||
for e in rx.try_iter() {
|
for e in events.try_iter() {
|
||||||
match e {
|
match e {
|
||||||
Event::Input(key) => {
|
Event::Input(key) => {
|
||||||
app.error_msg = match handle_key(&mut app, key) {
|
app.error_msg = match handle_key(&mut app, key) {
|
||||||
@ -366,7 +342,7 @@ fn handle_key(app: &mut App, key: KeyEvent) -> CalculatorResult<CalculatorRespon
|
|||||||
app.state = AppState::Help;
|
app.state = AppState::Help;
|
||||||
}
|
}
|
||||||
KeyEvent {
|
KeyEvent {
|
||||||
code: KeyCode::Char('\n'),
|
code: KeyCode::Enter,
|
||||||
modifiers: KeyModifiers::NONE,
|
modifiers: KeyModifiers::NONE,
|
||||||
}
|
}
|
||||||
| KeyEvent {
|
| KeyEvent {
|
||||||
@ -399,6 +375,14 @@ fn handle_key(app: &mut App, key: KeyEvent) -> CalculatorResult<CalculatorRespon
|
|||||||
} => {
|
} => {
|
||||||
app.calculator.take_input(c)?;
|
app.calculator.take_input(c)?;
|
||||||
}
|
}
|
||||||
|
KeyEvent {
|
||||||
|
code: KeyCode::Char(c),
|
||||||
|
modifiers: KeyModifiers::SHIFT,
|
||||||
|
} => {
|
||||||
|
for c in (c.to_uppercase()) {
|
||||||
|
app.calculator.take_input(c)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
(AppState::Help, _) => match key {
|
(AppState::Help, _) => match key {
|
||||||
@ -486,4 +470,3 @@ fn draw_clippy_rect<T: std::io::Write>(c: ClippyRectangle, f: &mut Frame<Crosste
|
|||||||
.block(Block::default().borders(Borders::ALL).title(c.title));
|
.block(Block::default().borders(Borders::ALL).title(c.title));
|
||||||
f.render_widget(help_message, area);
|
f.render_widget(help_message, area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,105 +1,64 @@
|
|||||||
// use std::io;
|
use std::io;
|
||||||
// use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
// use std::sync::mpsc::TryIter;
|
use std::sync::mpsc::TryIter;
|
||||||
// use std::sync::{
|
use std::sync::{
|
||||||
// atomic::{AtomicBool, Ordering},
|
atomic::{AtomicBool, Ordering},
|
||||||
// Arc,
|
Arc,
|
||||||
// };
|
};
|
||||||
// use std::thread;
|
use std::thread;
|
||||||
// use std::time::Duration;
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
// use crossterm::event::{KeyEvent, KeyCode, KeyModifiers};
|
use crossterm::event::{self, Event as CEvent, KeyCode, KeyEvent, KeyModifiers};
|
||||||
|
|
||||||
pub enum Event<I> {
|
pub enum Event<I> {
|
||||||
Input(I),
|
Input(I),
|
||||||
Tick,
|
Tick,
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// A small event handler that wrap termion input and tick events. Each event
|
pub struct Events {
|
||||||
// /// type is handled in its own thread and returned to a common `Receiver`
|
rx: mpsc::Receiver<Event<KeyEvent>>,
|
||||||
// #[allow(dead_code)]
|
tx: mpsc::Sender<Event<KeyEvent>>,
|
||||||
// pub struct Events {
|
tick_handle: thread::JoinHandle<()>,
|
||||||
// rx: mpsc::Receiver<Event<KeyEvent>>,
|
}
|
||||||
// tx: mpsc::Sender<Event<KeyEvent>>,
|
|
||||||
// input_handle: thread::JoinHandle<()>,
|
|
||||||
// ignore_exit_key: Arc<AtomicBool>,
|
|
||||||
// tick_handle: thread::JoinHandle<()>,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[derive(Debug, Clone, Copy)]
|
impl Events {
|
||||||
// pub struct Config {
|
pub fn new(tick_rate: u64) -> Events {
|
||||||
// pub exit_key: KeyEvent,
|
let (tx, rx) = mpsc::channel();
|
||||||
// pub tick_rate: Duration,
|
let tick_handle = {
|
||||||
// }
|
let tx = tx.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut last_tick = Instant::now();
|
||||||
|
let tick_rate = Duration::from_millis(tick_rate);
|
||||||
|
loop {
|
||||||
|
// poll for tick rate duration, if no events, sent tick event.
|
||||||
|
let timeout = tick_rate
|
||||||
|
.checked_sub(last_tick.elapsed())
|
||||||
|
.unwrap_or_else(|| Duration::from_secs(0));
|
||||||
|
if event::poll(timeout).unwrap() {
|
||||||
|
if let CEvent::Key(key) = event::read().unwrap() {
|
||||||
|
tx.send(Event::Input(key)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// impl Default for Config {
|
if last_tick.elapsed() >= tick_rate {
|
||||||
// fn default() -> Self {
|
tx.send(Event::Tick).unwrap();
|
||||||
// Config {
|
last_tick = Instant::now();
|
||||||
// exit_key: KeyEvent::new(KeyCode::Char('q'), KeyModifiers::NONE),
|
}
|
||||||
// tick_rate: Duration::from_millis(250),
|
}
|
||||||
// }
|
})
|
||||||
// }
|
};
|
||||||
// }
|
Events {
|
||||||
|
tx: tx,
|
||||||
|
rx: rx,
|
||||||
|
tick_handle,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// impl Events {
|
pub fn next(&self) -> Result<Event<KeyEvent>, mpsc::RecvError> {
|
||||||
// pub fn new() -> Events {
|
self.rx.recv()
|
||||||
// Events::with_config(Config::default())
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn with_config(config: Config) -> Events {
|
pub fn try_iter(&self) -> TryIter<Event<KeyEvent>> {
|
||||||
// let (tx, rx) = mpsc::channel();
|
self.rx.try_iter()
|
||||||
// let mac_tx = tx.clone();
|
}
|
||||||
// let ignore_exit_key = Arc::new(AtomicBool::new(true));
|
}
|
||||||
// let input_handle = {
|
|
||||||
// let tx = tx.clone();
|
|
||||||
// let ignore_exit_key = ignore_exit_key.clone();
|
|
||||||
// thread::spawn(move || {
|
|
||||||
// let stdin = io::stdin();
|
|
||||||
// for evt in stdin.keys() {
|
|
||||||
// if let Ok(key) = evt {
|
|
||||||
// if let Err(err) = tx.send(Event::Input(key)) {
|
|
||||||
// eprintln!("{}", err);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if !ignore_exit_key.load(Ordering::Relaxed) && key == config.exit_key {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// };
|
|
||||||
// let tick_handle = {
|
|
||||||
// thread::spawn(move || loop {
|
|
||||||
// if tx.send(Event::Tick).is_err() {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// thread::sleep(config.tick_rate);
|
|
||||||
// })
|
|
||||||
// };
|
|
||||||
// Events {
|
|
||||||
// rx,
|
|
||||||
// tx: mac_tx,
|
|
||||||
// ignore_exit_key,
|
|
||||||
// input_handle,
|
|
||||||
// tick_handle,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn next(&self) -> Result<Event<KeyEvent>, mpsc::RecvError> {
|
|
||||||
// self.rx.recv()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn try_iter(&self) -> TryIter<Event<KeyEvent>> {
|
|
||||||
// self.rx.try_iter()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[allow(dead_code)]
|
|
||||||
// pub fn disable_exit_key(&mut self) {
|
|
||||||
// self.ignore_exit_key.store(true, Ordering::Relaxed);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[allow(dead_code)]
|
|
||||||
// pub fn enable_exit_key(&mut self) {
|
|
||||||
// self.ignore_exit_key.store(false, Ordering::Relaxed);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user