summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-02-21 21:41:52 +0100
committerrabite <rabite@posteo.de>2019-02-22 00:46:41 +0100
commit3b38143f9bc758b10d76ebae39bca5a15350622b (patch)
tree687dfb1df38bb46d775623579e90ef00f46076ed
parentfe542047c231cff6c1959fe05cb51e177ddfbcc6 (diff)
added on_ready support
-rw-r--r--src/fail.rs48
-rw-r--r--src/file_browser.rs228
-rw-r--r--src/main.rs1
-rw-r--r--src/miller_columns.rs46
-rw-r--r--src/preview.rs133
-rw-r--r--src/window.rs64
6 files changed, 364 insertions, 156 deletions
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<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
+ }
+}
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<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 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<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 cwd(&self) -> File {
- self.columns.get_main_widget().content.directory.clone()
+ 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 selected_file(&self) -> &File {
- self.main_column().selected_file()
+ pub fn main_widget(&self) -> HResult<Arc<Mutex<Option<ListView<Files>>>>> {
+ let widget = self.columns.get_main_widget()?.widget()?;
+ Ok(widget)
}
- pub fn main_column(&self) -> &ListView<Files> {
- self.columns.get_main_widget()
+ pub fn left_widget(&self) -> HResult<Arc<Mutex<Option<ListView<Files>>>>> {
+ 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<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);
}
}
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<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();
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<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,