added on_ready support

This commit is contained in:
rabite 2019-02-21 21:41:52 +01:00
parent fe542047c2
commit 3b38143f9b
6 changed files with 362 additions and 154 deletions

View File

@ -1,4 +1,6 @@
use failure;
use failure::Error;
use failure::{Fail, ResultExt};
pub type HResult<T> = Result<T, HError>;
@ -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<std::io::Error> for HError {
fn from(error: std::io::Error) -> Self {
dbg!(&error);
HError::IoError { error: error }
}
}
impl From<failure::Error> for HError {
fn from(error: failure::Error) -> Self {
dbg!(&error);
HError::Error { error: error }
}
}
impl From<std::sync::mpsc::TryRecvError> for HError {
fn from(error: std::sync::mpsc::TryRecvError) -> Self {
dbg!(&error);
HError::ChannelTryRecvError { error: error }
}
}
impl From<std::sync::mpsc::RecvError> for HError {
fn from(error: std::sync::mpsc::RecvError) -> Self {
dbg!(&error);
HError::ChannelRecvError { error: error }
}
}
impl<T> From<std::sync::mpsc::SendError<T>> for HError {
fn from(error: std::sync::mpsc::SendError<T>) -> Self {
dbg!(&error);
HError::ChannelSendError
}
}
impl<T> From<std::sync::PoisonError<T>> for HError {
fn from(_: std::sync::PoisonError<T>) -> Self {
dbg!("Poisoned Mutex");
HError::MutexError
}
}
impl<T> From<std::sync::TryLockError<T>> for HError {
fn from(error: std::sync::TryLockError<T>) -> Self {
dbg!(&error);
HError::TryLockError
}
}
impl From<std::option::NoneError> for HError {
fn from(error: std::option::NoneError) -> Self {
dbg!(&error);
HError::NoneError
}
}

View File

@ -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<ListView<Files>>,
pub columns: MillerColumns<WillBeWidget<ListView<Files>>>,
pub cwd: File
}
impl Tabbable for TabView<FileBrowser> {
@ -55,37 +59,70 @@ impl FileBrowser {
miller.set_coordinates(&coords);
let lists: Result<Vec<ListView<Files>>, Box<Error>> = cwd
.ancestors()
.map(|path| Ok(ListView::new(Files::new_from_path(path)?)))
.take(2)
.collect();
let mut lists = lists?;
lists.reverse();
// let lists: Result<Vec<ListView<Files>>, Box<Error>> = 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 mut file_browser = FileBrowser { columns: miller };
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)
}));
file_browser.fix_selection();
file_browser.animate_columns();
file_browser.update_preview();
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,
cwd: cwd };
//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) {
let cwd = self.cwd();
self.columns.get_left_widget_mut()
.map(|w|
w.select_file(&cwd));
pub fn fix_selection(&mut self) -> HResult<()> {
let cwd = self.cwd()?;
(*self.left_widget()?.lock()?).as_mut()?.select_file(&cwd);
Ok(())
}
pub fn cwd(&self) -> File {
self.columns.get_main_widget().content.directory.clone()
pub fn cwd(&self) -> HResult<File> {
//(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 selected_file(&self) -> &File {
self.main_column().selected_file()
pub fn selected_file(&self) -> HResult<File> {
let widget = self.main_widget()?;
let file = widget.lock()?.as_ref()?.selected_file().clone();
Ok(file)
}
pub fn main_column(&self) -> &ListView<Files> {
self.columns.get_main_widget()
pub fn main_widget(&self) -> HResult<Arc<Mutex<Option<ListView<Files>>>>> {
let widget = self.columns.get_main_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 left_widget(&self) -> HResult<Arc<Mutex<Option<ListView<Files>>>>> {
let widget = self.columns.get_left_widget()?.widget()?;
Ok(widget)
}
let mut filepath = dirs_2::home_dir().unwrap();
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()?;
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));
// 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();
// 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 => {}
}
// 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();
}

View File

@ -1,5 +1,6 @@
#![feature(vec_remove_item)]
#![feature(trivial_bounds)]
#![feature(try_trait)]
extern crate termion;
extern crate unicode_width;

View File

@ -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<T> 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);
}
}

View File

@ -29,19 +29,21 @@ fn kill_proc() -> HResult<()> {
}
pub fn is_stale(stale: &Arc<Mutex<bool>>) -> HResult<bool> {
Ok(*(stale.lock()?))
let stale = *(stale.try_lock().unwrap());
Ok(stale)
}
enum State<T: Send> {
Is(T),
enum State {
Is,
Becoming,
Taken,
Fail
}
struct WillBe<T: Send> {
pub state: State<T>,
rx: std::sync::mpsc::Receiver<T>,
pub state: Arc<Mutex<State>>,
pub thing: Arc<Mutex<Option<T>>>,
on_ready: Arc<Mutex<Option<Box<Fn(Arc<Mutex<Option<T>>>) -> HResult<()> + Send>>>>,
rx: Option<std::sync::mpsc::Receiver<T>>,
stale: Arc<Mutex<bool>>
}
@ -49,42 +51,58 @@ impl<T: Send + 'static> WillBe<T> where {
pub fn new_become(closure: HClosure<T>)
-> WillBe<T> {
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<T>, tx: std::sync::mpsc::Sender<T>) {
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<T, std::sync::mpsc::RecvError> {
self.rx.recv()
pub fn on_ready(&mut self,
fun: Box<Fn(Arc<Mutex<Option<T>>>) -> 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<W: Widget + Send> PartialEq for WillBeWidget<W> {
}
}
struct WillBeWidget<T: Widget + Send> {
pub struct WillBeWidget<T: Widget + Send> {
willbe: WillBe<T>,
coordinates: Coordinates
}
impl<T: Widget + Send + 'static> WillBeWidget<T> {
fn new(closure: HClosure<T>) -> WillBeWidget<T> {
pub fn new(closure: HClosure<T>) -> WillBeWidget<T> {
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<Arc<Mutex<Option<T>>>> {
self.willbe.check()?;
Ok(self.willbe.thing.clone())
}
}
// impl<T: Widget + Send> WillBeWidget<T> {
@ -126,41 +153,46 @@ impl<T: Widget + Send + 'static> WillBeWidget<T> {
// }
//}
impl<T: Widget + Send> Widget for WillBeWidget<T> {
impl<T: Widget + Send + 'static> Widget for WillBeWidget<T> {
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<Box<dyn Widget + Send>>,
file: Option<File>
}
@ -186,7 +219,8 @@ impl Previewer {
Ok(Box::new(crate::textview::TextView::new_blank())
as Box<dyn Widget + Send>)
}));
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();

View File

@ -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<Mutex<Option<Sender<Events>>>> = { Arc::new(Mutex::new(None)) };
}
#[derive(Debug)]
pub enum Events {
InputEvent(Event),
WidgetReady
}
pub struct Window<T>
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<Events>, tx: Sender<Events>) {
std::thread::spawn(move || {
for event in rx.iter() {
dbg!(&event);
tx.send(event).unwrap();
}
});
}
fn input_thread(tx: Sender<Events>) {
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<T> Drop for Window<T>
where
T: Widget,