From 3b38143f9bc758b10d76ebae39bca5a15350622b Mon Sep 17 00:00:00 2001 From: rabite Date: Thu, 21 Feb 2019 21:41:52 +0100 Subject: added on_ready support --- src/fail.rs | 48 ++++++++++- src/file_browser.rs | 228 +++++++++++++++++++++++++++++++------------------- src/main.rs | 1 + src/miller_columns.rs | 46 ++++++---- src/preview.rs | 133 ++++++++++++++++++----------- src/window.rs | 64 ++++++++++++-- 6 files changed, 364 insertions(+), 156 deletions(-) (limited to 'src') diff --git a/src/fail.rs b/src/fail.rs index 791435b..0b9b0b3 100644 --- a/src/fail.rs +++ b/src/fail.rs @@ -1,4 +1,6 @@ use failure; +use failure::Error; +use failure::{Fail, ResultExt}; pub type HResult = Result; @@ -8,36 +10,80 @@ pub enum HError { IoError{#[cause] error: std::io::Error}, #[fail(display = "Mutex failed")] MutexError, + #[fail(display = "Can't lock!")] + TryLockError, #[fail(display = "Channel failed: {}", error)] ChannelTryRecvError{#[cause] error: std::sync::mpsc::TryRecvError}, + #[fail(display = "Channel failed: {}", error)] + ChannelRecvError{#[cause] error: std::sync::mpsc::RecvError}, + #[fail(display = "Channel failed")] + ChannelSendError, #[fail(display = "Previewer failed on file: {}", file)] PreviewFailed{file: String}, #[fail(display = "StalePreviewer for file: {}", file)] StalePreviewError{file: String}, #[fail(display = "Failed: {}", error)] - Error{#[cause] error: failure::Error } + Error{#[cause] error: failure::Error }, + #[fail(display = "Was None!")] + NoneError, + #[fail(display = "Not ready yet!")] + WillBeNotReady, + #[fail(display = "No widget found")] + NoWidgetError } impl From for HError { fn from(error: std::io::Error) -> Self { + dbg!(&error); HError::IoError { error: error } } } impl From for HError { fn from(error: failure::Error) -> Self { + dbg!(&error); HError::Error { error: error } } } impl From for HError { fn from(error: std::sync::mpsc::TryRecvError) -> Self { + dbg!(&error); HError::ChannelTryRecvError { error: error } } } +impl From for HError { + fn from(error: std::sync::mpsc::RecvError) -> Self { + dbg!(&error); + HError::ChannelRecvError { error: error } + } +} + +impl From> for HError { + fn from(error: std::sync::mpsc::SendError) -> Self { + dbg!(&error); + HError::ChannelSendError + } +} + impl From> for HError { fn from(_: std::sync::PoisonError) -> Self { + dbg!("Poisoned Mutex"); HError::MutexError } } + +impl From> for HError { + fn from(error: std::sync::TryLockError) -> Self { + dbg!(&error); + HError::TryLockError + } +} + +impl From for HError { + fn from(error: std::option::NoneError) -> Self { + dbg!(&error); + HError::NoneError + } +} diff --git a/src/file_browser.rs b/src/file_browser.rs index 322137c..e27a517 100644 --- a/src/file_browser.rs +++ b/src/file_browser.rs @@ -2,6 +2,7 @@ use termion::event::Key; use std::error::Error; use std::io::Write; +use std::sync::{Arc, Mutex}; use crate::coordinates::{Coordinates}; use crate::files::{File, Files}; @@ -9,10 +10,13 @@ use crate::listview::ListView; use crate::miller_columns::MillerColumns; use crate::widget::Widget; use crate::tabview::{TabView, Tabbable}; +use crate::preview::WillBeWidget; +use crate::fail::{HError, HResult}; #[derive(PartialEq)] pub struct FileBrowser { - pub columns: MillerColumns>, + pub columns: MillerColumns>>, + pub cwd: File } impl Tabbable for TabView { @@ -55,37 +59,70 @@ impl FileBrowser { miller.set_coordinates(&coords); - let lists: Result>, Box> = cwd - .ancestors() - .map(|path| Ok(ListView::new(Files::new_from_path(path)?))) - .take(2) - .collect(); - let mut lists = lists?; - lists.reverse(); + // let lists: Result>, Box> = cwd + // .ancestors() + // .map(|path| Ok(ListView::new(Files::new_from_path(path)?))) + // .take(2) + // .collect(); + // let mut lists = lists?; + // lists.reverse(); + let (left_coords, main_coords, _) = miller.calculate_coordinates(); - for widget in lists { - miller.push_widget(widget); - } + let main_path: std::path::PathBuf = cwd.ancestors().take(1).map(|path| std::path::PathBuf::from(path)).collect(); + let main_widget = WillBeWidget::new(Box::new(move |_| { + let mut list = ListView::new(Files::new_from_path(&main_path).unwrap()); + list.set_coordinates(&main_coords); + list.animate_slide_up(); + Ok(list) + })); + + let left_path: std::path::PathBuf = cwd.ancestors().skip(1).take(1).map(|path| std::path::PathBuf::from(path)).collect(); + let left_widget = WillBeWidget::new(Box::new(move |_| { + let mut list = ListView::new(Files::new_from_path(&left_path).unwrap()); + list.set_coordinates(&left_coords); + list.animate_slide_up(); + Ok(list) + })); + + + + + miller.push_widget(left_widget); + miller.push_widget(main_widget); + + // for widget in lists { + // miller.push_widget(widget); + // } + + let cwd = File::new_from_path(&cwd).unwrap(); - let mut file_browser = FileBrowser { columns: miller }; + let mut file_browser = FileBrowser { columns: miller, + cwd: cwd }; - file_browser.fix_selection(); - file_browser.animate_columns(); - file_browser.update_preview(); + + //file_browser.fix_selection(); + //file_browser.animate_columns(); + //file_browser.update_preview(); Ok(file_browser) } - pub fn enter_dir(&mut self) { - let file = self.selected_file(); + pub fn enter_dir(&mut self) -> HResult<()> { + let file = self.selected_file()?; + let (_, coords, _) = self.columns.calculate_coordinates(); match file.read_dir() { Ok(files) => { std::env::set_current_dir(&file.path).unwrap(); - let view = ListView::new(files); + let view = WillBeWidget::new(Box::new(move |_| { + let files = files.clone(); + let mut list = ListView::new(files); + list.set_coordinates(&coords); + list.animate_slide_up(); + Ok(list) + })); self.columns.push_widget(view); - self.update_preview(); }, _ => { let status = std::process::Command::new("rifle") @@ -103,102 +140,121 @@ impl FileBrowser { } } } + Ok(()) } - pub fn go_back(&mut self) { - if self.columns.get_left_widget().is_none() { - return; - } - let fileview = self.columns.get_main_widget(); - let path = fileview.selected_file().grand_parent().unwrap(); - std::env::set_current_dir(path).unwrap(); + pub fn go_back(&mut self) -> HResult<()> { + // if self.left_widget().is_err() { + // return None; + // } + // if self.columns.get_main_widget().is_none() { + // return None; + // } + let fileview = self.main_widget()?; + let path = self.selected_file()?.grand_parent()?; + std::env::set_current_dir(path)?; self.columns.pop_widget(); // Make sure there's a directory on the left unless it's / - if self.columns.get_left_widget().is_none() { - let file = self.columns.get_main_widget().clone_selected_file(); + if self.left_widget().is_err() { + let file = self.selected_file()?.clone(); if let Some(grand_parent) = file.grand_parent() { - let mut left_view = ListView::new(Files::new_from_path(&grand_parent).unwrap()); - left_view.select_file(&file); + let mut left_view = WillBeWidget::new(Box::new(move |_| { + let mut view + = ListView::new(Files::new_from_path(&grand_parent)?); + Ok(view) + })); self.columns.prepend_widget(left_view); } } - self.fix_selection(); self.columns.refresh(); + Ok(()) } - pub fn update_preview(&mut self) { - if self.columns.get_main_widget().content.len() == 0 { return } - let file = self.columns.get_main_widget().selected_file().clone(); + pub fn update_preview(&mut self) -> HResult<()> { + let file = self.selected_file()?.clone(); let preview = &mut self.columns.preview; preview.set_file(&file); + Ok(()) + } + + pub fn fix_selection(&mut self) -> HResult<()> { + let cwd = self.cwd()?; + (*self.left_widget()?.lock()?).as_mut()?.select_file(&cwd); + Ok(()) } - pub fn fix_selection(&mut self) { - let cwd = self.cwd(); - self.columns.get_left_widget_mut() - .map(|w| - w.select_file(&cwd)); + pub fn cwd(&self) -> HResult { + //(self.columns.get_main_widget()?.widget()?.content.directory.clone()) + let widget = self.columns.get_main_widget()?.widget()?; + let cwd = (*widget.lock()?).as_ref()?.content.directory.clone(); + Ok(cwd) } - pub fn cwd(&self) -> File { - self.columns.get_main_widget().content.directory.clone() + pub fn selected_file(&self) -> HResult { + let widget = self.main_widget()?; + let file = widget.lock()?.as_ref()?.selected_file().clone(); + Ok(file) } - pub fn selected_file(&self) -> &File { - self.main_column().selected_file() + pub fn main_widget(&self) -> HResult>>>> { + let widget = self.columns.get_main_widget()?.widget()?; + Ok(widget) } - pub fn main_column(&self) -> &ListView { - self.columns.get_main_widget() + pub fn left_widget(&self) -> HResult>>>> { + let widget = self.columns.get_left_widget()?.widget()?; + Ok(widget) } - pub fn quit_with_dir(&self) { - let cwd = self.cwd().path; - let selected_file = self.selected_file().path.to_string_lossy(); + pub fn quit_with_dir(&self) -> HResult<()> { + let cwd = self.cwd()?.path; + let selected_file = self.selected_file()?; + let selected_file = selected_file.path.to_string_lossy(); - let mut filepath = dirs_2::home_dir().unwrap(); + let mut filepath = dirs_2::home_dir()?; filepath.push(".hunter_cwd"); let output = format!("HUNTER_CWD=\"{}\"\nF=\"{}\"", - cwd.to_str().unwrap(), + cwd.to_str()?, selected_file); - let mut file = std::fs::File::create(filepath).unwrap(); - file.write(output.as_bytes()).unwrap(); + let mut file = std::fs::File::create(filepath)?; + file.write(output.as_bytes())?; panic!("Quitting!"); + Ok(()) } pub fn animate_columns(&mut self) { self.columns.get_left_widget_mut().map(|w| w.animate_slide_up()); - self.columns.get_main_widget_mut().animate_slide_up(); + self.columns.get_main_widget_mut().unwrap().animate_slide_up(); } pub fn turbo_cd(&mut self) { let dir = self.minibuffer("cd: "); - match dir { - Some(dir) => { - Files::new_from_path(&std::path::PathBuf::from(&dir)).and_then(|files| { - let cwd = files.directory.clone(); - self.columns.widgets.widgets.clear(); - self.columns.push_widget(ListView::new(files)); - - std::env::set_current_dir(&cwd.path).unwrap(); - - if let Some(grand_parent) = cwd.path.parent() { - let left_view = - ListView::new(Files::new_from_path(&grand_parent).unwrap()); - self.columns.prepend_widget(left_view); - } - self.fix_selection(); - self.update_preview(); - self.refresh(); - self.columns.refresh(); - Ok(()) - }).ok(); - } None => {} - } + // match dir { + // Some(dir) => { + // Files::new_from_path(&std::path::PathBuf::from(&dir)).and_then(|files| { + // let cwd = files.directory.clone(); + // self.columns.widgets.widgets.clear(); + // self.columns.push_widget(ListView::new(files)); + + // std::env::set_current_dir(&cwd.path).unwrap(); + + // if let Some(grand_parent) = cwd.path.parent() { + // let left_view = + // ListView::new(Files::new_from_path(&grand_parent).unwrap()); + // self.columns.prepend_widget(left_view); + // } + // self.fix_selection(); + // self.update_preview(); + // self.refresh(); + // self.columns.refresh(); + // Ok(()) + // }).ok(); + // } None => {} + // } } } @@ -211,8 +267,9 @@ impl Widget for FileBrowser { self.refresh(); } fn render_header(&self) -> String { + if self.main_widget().is_err() { return "".to_string() } let xsize = self.get_coordinates().xsize(); - let file = self.selected_file(); + let file = self.selected_file().unwrap(); let name = &file.name; let color = if file.is_dir() || file.color.is_none() { @@ -226,9 +283,10 @@ impl Widget for FileBrowser { sized_path } fn render_footer(&self) -> String { + if self.main_widget().is_err() { return "".to_string() } let xsize = self.get_coordinates().xsize(); let ypos = self.get_coordinates().position().y(); - let file = self.selected_file(); + let file = self.selected_file().unwrap(); let permissions = file.pretty_print_permissions().unwrap_or("NOPERMS".into()); let user = file.pretty_user().unwrap_or("NOUSER".into()); @@ -236,8 +294,8 @@ impl Widget for FileBrowser { let mtime = file.pretty_mtime().unwrap_or("NOMTIME".into()); - let selection = self.main_column().get_selection(); - let file_count = self.main_column().content.len(); + let selection = (*self.main_widget().as_ref().unwrap().lock().unwrap()).as_ref().unwrap().get_selection(); + let file_count = (*self.main_widget().unwrap().lock().unwrap()).as_ref().unwrap().content.len(); let file_count = format!("{}", file_count); let digits = file_count.len(); let file_count = format!("{:digits$}/{:digits$}", @@ -251,11 +309,13 @@ impl Widget for FileBrowser { crate::term::goto_xy(count_xpos, count_ypos), file_count) } fn refresh(&mut self) { + self.update_preview(); + self.fix_selection(); self.columns.refresh(); } fn get_drawlist(&self) -> String { - if self.columns.get_left_widget().is_none() { + if self.columns.get_left_widget().is_err() { self.columns.get_clearlist() + &self.columns.get_drawlist() } else { self.columns.get_drawlist() @@ -265,10 +325,10 @@ impl Widget for FileBrowser { fn on_key(&mut self, key: Key) { match key { Key::Char('/') => self.turbo_cd(), - Key::Char('Q') => self.quit_with_dir(), - Key::Right | Key::Char('f') => self.enter_dir(), - Key::Left | Key::Char('b') => self.go_back(), - _ => self.columns.get_main_widget_mut().on_key(key), + Key::Char('Q') => { self.quit_with_dir(); }, + Key::Right | Key::Char('f') => { self.enter_dir(); }, + Key::Left | Key::Char('b') => { self.go_back(); }, + _ => self.columns.get_main_widget_mut().unwrap().on_key(key), } self.update_preview(); } diff --git a/src/main.rs b/src/main.rs index 0add6c9..3fd895c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ #![feature(vec_remove_item)] #![feature(trivial_bounds)] +#![feature(try_trait)] extern crate termion; extern crate unicode_width; diff --git a/src/miller_columns.rs b/src/miller_columns.rs index 6351e8d..3c9bc8b 100644 --- a/src/miller_columns.rs +++ b/src/miller_columns.rs @@ -1,9 +1,12 @@ use termion::event::Key; +use std::sync::{Arc, Mutex}; + use crate::coordinates::{Coordinates, Position, Size}; use crate::preview::Previewer; use crate::widget::Widget; use crate::hbox::HBox; +use crate::fail::{HError, HResult}; #[derive(PartialEq)] pub struct MillerColumns where T: Widget { @@ -80,25 +83,27 @@ where (left_coords, main_coords, preview_coords) } - pub fn get_left_widget(&self) -> Option<&T> { + pub fn get_left_widget(&self) -> HResult<&T> { let len = self.widgets.widgets.len(); if len < 2 { - return None; + return Err(HError::NoWidgetError); } - self.widgets.widgets.get(len - 2) + Ok(self.widgets.widgets.get(len - 2)?) } - pub fn get_left_widget_mut(&mut self) -> Option<&mut T> { + pub fn get_left_widget_mut(&mut self) -> HResult<&mut T> { let len = self.widgets.widgets.len(); if len < 2 { - return None; + return Err(HError::NoWidgetError); } - self.widgets.widgets.get_mut(len - 2) + Ok(self.widgets.widgets.get_mut(len - 2)?) } - pub fn get_main_widget(&self) -> &T { - self.widgets.widgets.last().unwrap() + pub fn get_main_widget(&self) -> HResult<&T> { + let widget = self.widgets.widgets.last()?; + Ok(widget) } - pub fn get_main_widget_mut(&mut self) -> &mut T { - self.widgets.widgets.last_mut().unwrap() + pub fn get_main_widget_mut(&mut self) -> HResult<&mut T> { + let widget = self.widgets.widgets.last_mut()?; + Ok(widget) } } @@ -123,11 +128,11 @@ where fn refresh(&mut self) { let (left_coords, main_coords, preview_coords) = self.calculate_coordinates(); - if let Some(left_widget) = self.get_left_widget_mut() { + if let Ok(left_widget) = self.get_left_widget_mut() { left_widget.set_coordinates(&left_coords); } - if let Some(main_widget) = self.widgets.widgets.last_mut() { + if let Ok(main_widget) = self.get_main_widget_mut() { main_widget.set_coordinates(&main_coords); } @@ -137,15 +142,20 @@ where fn get_drawlist(&self) -> String { let left_widget = match self.get_left_widget() { - Some(widget) => widget.get_drawlist(), - None => "".into(), + Ok(widget) => widget.get_drawlist(), + Err(_) => "".into(), }; - let main_widget = self.get_main_widget().get_drawlist(); - let preview = self.preview.get_drawlist(); - format!("{}{}{}", main_widget, left_widget, preview) + let main_widget = self.get_main_widget(); + match main_widget { + Ok(main_widget) => { + let preview = self.preview.get_drawlist(); + format!("{}{}{}", main_widget.get_drawlist(), left_widget, preview) + } + Err(_) => "".to_string() + } } fn on_key(&mut self, key: Key) { - self.get_main_widget_mut().on_key(key); + self.get_main_widget_mut().unwrap().on_key(key); } } diff --git a/src/preview.rs b/src/preview.rs index dd78c78..dda2e68 100644 --- a/src/preview.rs +++ b/src/preview.rs @@ -29,19 +29,21 @@ fn kill_proc() -> HResult<()> { } pub fn is_stale(stale: &Arc>) -> HResult { - Ok(*(stale.lock()?)) + let stale = *(stale.try_lock().unwrap()); + Ok(stale) } -enum State { - Is(T), +enum State { + Is, Becoming, - Taken, Fail } struct WillBe { - pub state: State, - rx: std::sync::mpsc::Receiver, + pub state: Arc>, + pub thing: Arc>>, + on_ready: Arc>>) -> HResult<()> + Send>>>>, + rx: Option>, stale: Arc> } @@ -49,42 +51,58 @@ impl WillBe where { pub fn new_become(closure: HClosure) -> WillBe { let (tx,rx) = std::sync::mpsc::channel(); - let mut willbe = WillBe { state: State::Becoming, - rx: rx, + let mut willbe = WillBe { state: Arc::new(Mutex::new(State::Becoming)), + thing: Arc::new(Mutex::new(None)), + on_ready: Arc::new(Mutex::new(None)), + rx: Some(rx), stale: Arc::new(Mutex::new(false)) }; willbe.run(closure, tx); willbe } fn run(&mut self, closure: HClosure, tx: std::sync::mpsc::Sender) { + let state = self.state.clone(); let stale = self.stale.clone(); + let thing = self.thing.clone(); + let on_ready_fn = self.on_ready.clone(); std::thread::spawn(move|| { - let thing = closure(stale); - match thing { - Ok(thing) => { tx.send(thing).ok(); }, + let got_thing = closure(stale); + match got_thing { + Ok(got_thing) => { + *thing.try_lock().unwrap() = Some(got_thing); + *state.try_lock().unwrap() = State::Is; + match *on_ready_fn.lock().unwrap() { + Some(ref on_ready) => { on_ready(thing.clone()); }, + None => {} + } + }, Err(err) => { dbg!(err); } } }); } pub fn set_stale(&mut self) -> HResult<()> { - *self.stale.lock()? = true; + *self.stale.try_lock()? = true; Ok(()) } - pub fn check(&mut self) -> Result<(), Error> { - match self.state { - State::Is(_) => Ok(()), - _ => { - let thing = self.rx.try_recv()?; - self.state = State::Is(thing); - Ok(()) - } + pub fn check(&self) -> HResult<()> { + match *self.state.try_lock()? { + State::Is => Ok(()), + _ => Err(HError::WillBeNotReady) } } - pub fn wait(self) -> Result { - self.rx.recv() + pub fn on_ready(&mut self, + fun: Box>>) -> HResult<()> + Send>) + -> HResult<()> { + if self.check().is_ok() { + fun(self.thing.clone()); + //*self.on_ready.try_lock()? = None; + } else { + *self.on_ready.try_lock()? = Some(fun); + } + Ok(()) } } @@ -98,21 +116,30 @@ impl PartialEq for WillBeWidget { } } -struct WillBeWidget { +pub struct WillBeWidget { willbe: WillBe, coordinates: Coordinates } impl WillBeWidget { - fn new(closure: HClosure) -> WillBeWidget { + pub fn new(closure: HClosure) -> WillBeWidget { + let mut willbe = WillBe::new_become(Box::new(move |stale| closure(stale))); + willbe.on_ready(Box::new(|_| { + crate::window::send_event(crate::window::Events::WidgetReady); + Ok(()) })); + WillBeWidget { - willbe: WillBe::new_become(Box::new(move |stale| closure(stale))), + willbe: willbe, coordinates: Coordinates::new() } } pub fn set_stale(&mut self) -> HResult<()> { self.willbe.set_stale() } + pub fn widget(&self) -> HResult>>> { + self.willbe.check()?; + Ok(self.willbe.thing.clone()) + } } // impl WillBeWidget { @@ -126,41 +153,46 @@ impl WillBeWidget { // } //} -impl Widget for WillBeWidget { +impl Widget for WillBeWidget { fn get_coordinates(&self) -> &Coordinates { &self.coordinates } fn set_coordinates(&mut self, coordinates: &Coordinates) { - if self.coordinates == *coordinates { - return; - } self.coordinates = coordinates.clone(); - match &mut self.willbe.state { - State::Is(widget) => { - widget.set_coordinates(&coordinates.clone()); - self.refresh(); - } - _ => {} + + { + if self.willbe.check().is_err() { return } + let widget = self.widget().unwrap(); + let mut widget = widget.try_lock().unwrap(); + let widget = widget.as_mut().unwrap(); + widget.set_coordinates(&coordinates.clone()); } + + self.refresh(); } fn render_header(&self) -> String { "".to_string() } fn refresh(&mut self) { - match &mut self.willbe.state { - State::Is(widget) => { - widget.refresh(); - } - _ => {} - } + if self.willbe.check().is_err() { return } + let widget = self.widget().unwrap(); + let mut widget = widget.try_lock().unwrap(); + let widget = widget.as_mut().unwrap(); + widget.refresh(); } fn get_drawlist(&self) -> String { - match &self.willbe.state { - State::Is(widget) => { - widget.get_drawlist() - }, - _ => { "".to_string() } - } + if self.willbe.check().is_err() { return "".to_string() } + let widget = self.widget().unwrap(); + let widget = widget.try_lock().unwrap(); + let widget = widget.as_ref().unwrap(); + widget.get_drawlist() + } + fn on_key(&mut self, key: termion::event::Key) { + if self.willbe.check().is_err() { return } + let widget = self.widget().unwrap(); + let mut widget = widget.try_lock().unwrap(); + let widget = widget.as_mut().unwrap(); + widget.on_key(key); } } @@ -177,6 +209,7 @@ impl PartialEq for Previewer { pub struct Previewer { widget: WillBeWidget>, + file: Option } @@ -186,7 +219,8 @@ impl Previewer { Ok(Box::new(crate::textview::TextView::new_blank()) as Box) })); - Previewer { widget: willbe } + Previewer { widget: willbe, + file: None} } fn become_preview(&mut self, @@ -197,6 +231,9 @@ impl Previewer { } pub fn set_file(&mut self, file: &File) { + if Some(file) == self.file.as_ref() { return } + self.file = Some(file.clone()); + let coordinates = self.get_coordinates().clone(); let file = file.clone(); diff --git a/src/window.rs b/src/window.rs index 7535dbf..b31058d 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,5 +1,6 @@ use std::io::{stdin, stdout, Stdout, Write}; use std::sync::{Arc, Mutex}; +use std::sync::mpsc::{Sender, Receiver, channel}; use termion::event::{Event, Key}; use termion::input::TermRead; @@ -10,6 +11,18 @@ use crate::term::ScreenExt; use crate::coordinates::{Coordinates, Position, Size}; use crate::widget::Widget; +use crate::fail::HResult; + +lazy_static! { + static ref TX_EVENT: Arc>>> = { Arc::new(Mutex::new(None)) }; +} + + +#[derive(Debug)] +pub enum Events { + InputEvent(Event), + WidgetReady +} pub struct Window where @@ -69,17 +82,58 @@ where // Self::show_status(""); // } + pub fn handle_input(&mut self) { - for event in stdin().events() { + let (tx_event_internal, rx_event_internal) = channel(); + let (tx_event, rx_event) = channel(); + *TX_EVENT.try_lock().unwrap() = Some(tx_event); + + event_thread(rx_event, tx_event_internal.clone()); + input_thread(tx_event_internal); + + for event in rx_event_internal.iter() { //Self::clear_status(); - let event = event.unwrap(); - self.widget.on_event(event); - self.screen.cursor_hide(); - self.draw(); + //let event = event.unwrap(); + dbg!(&event); + match event { + Events::InputEvent(event) => { + self.widget.on_event(event); + self.screen.cursor_hide(); + self.draw(); + } + _ => { + self.widget.refresh(); + self.draw(); + }, + } } } } +fn event_thread(rx: Receiver, tx: Sender) { + std::thread::spawn(move || { + for event in rx.iter() { + dbg!(&event); + tx.send(event).unwrap(); + } + }); +} + +fn input_thread(tx: Sender) { + std::thread::spawn(move || { + for input in stdin().events() { + let input = input.unwrap(); + tx.send(Events::InputEvent(input)).unwrap(); + } + }); +} + +pub fn send_event(event: Events) -> HResult<()> { + let tx = TX_EVENT.lock()?.clone()?.clone(); + tx.send(event)?; + Ok(()) +} + impl Drop for Window where T: Widget, -- cgit v1.2.3