1
0
mirror of https://github.com/bobwen-dev/hunter synced 2025-04-12 00:55:41 +02:00

move widgets/files around instead of caching

This commit is contained in:
rabite 2019-04-02 22:17:07 +02:00
parent ed32c83aca
commit e99a3d993c
8 changed files with 399 additions and 70 deletions

View File

@ -84,7 +84,9 @@ pub enum HError {
#[fail(display = "{}", _0)] #[fail(display = "{}", _0)]
Log(String), Log(String),
#[fail(display = "Metadata already processed")] #[fail(display = "Metadata already processed")]
MetadataProcessedError MetadataProcessedError,
#[fail(display = "No files to take from widget")]
WidgetNoFilesError,
} }
impl HError { impl HError {
@ -158,6 +160,10 @@ impl HError {
pub fn metadata_processed<T>() -> HResult<T> { pub fn metadata_processed<T>() -> HResult<T> {
Err(HError::MetadataProcessedError) Err(HError::MetadataProcessedError)
} }
pub fn no_files<T>() -> HResult<T> {
Err(HError::WidgetNoFilesError)
}
} }

View File

@ -4,6 +4,7 @@ use std::io::Write;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::path::PathBuf; use std::path::PathBuf;
use std::ffi::OsString; use std::ffi::OsString;
use std::collections::HashSet;
use crate::files::{File, Files, PathBufExt}; use crate::files::{File, Files, PathBufExt};
use crate::fscache::FsCache; use crate::fscache::FsCache;
@ -12,6 +13,7 @@ use crate::hbox::HBox;
use crate::widget::Widget; use crate::widget::Widget;
use crate::tabview::{TabView, Tabbable}; use crate::tabview::{TabView, Tabbable};
use crate::preview::{Previewer, AsyncWidget}; use crate::preview::{Previewer, AsyncWidget};
use crate::textview::TextView;
use crate::fail::{HResult, HError, ErrorLog}; use crate::fail::{HResult, HError, ErrorLog};
use crate::widget::{Events, WidgetCore}; use crate::widget::{Events, WidgetCore};
use crate::proclist::ProcView; use crate::proclist::ProcView;
@ -25,37 +27,43 @@ use crate::coordinates::Coordinates;
pub enum FileBrowserWidgets { pub enum FileBrowserWidgets {
FileList(AsyncWidget<ListView<Files>>), FileList(AsyncWidget<ListView<Files>>),
Previewer(Previewer), Previewer(Previewer),
Blank(AsyncWidget<TextView>),
} }
impl Widget for FileBrowserWidgets { impl Widget for FileBrowserWidgets {
fn get_core(&self) -> HResult<&WidgetCore> { fn get_core(&self) -> HResult<&WidgetCore> {
match self { match self {
FileBrowserWidgets::FileList(widget) => widget.get_core(), FileBrowserWidgets::FileList(widget) => widget.get_core(),
FileBrowserWidgets::Previewer(widget) => widget.get_core() FileBrowserWidgets::Previewer(widget) => widget.get_core(),
FileBrowserWidgets::Blank(widget) => widget.get_core(),
} }
} }
fn get_core_mut(&mut self) -> HResult<&mut WidgetCore> { fn get_core_mut(&mut self) -> HResult<&mut WidgetCore> {
match self { match self {
FileBrowserWidgets::FileList(widget) => widget.get_core_mut(), FileBrowserWidgets::FileList(widget) => widget.get_core_mut(),
FileBrowserWidgets::Previewer(widget) => widget.get_core_mut() FileBrowserWidgets::Previewer(widget) => widget.get_core_mut(),
FileBrowserWidgets::Blank(widget) => widget.get_core_mut(),
} }
} }
fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> { fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> {
match self { match self {
FileBrowserWidgets::FileList(widget) => widget.set_coordinates(coordinates), FileBrowserWidgets::FileList(widget) => widget.set_coordinates(coordinates),
FileBrowserWidgets::Previewer(widget) => widget.set_coordinates(coordinates), FileBrowserWidgets::Previewer(widget) => widget.set_coordinates(coordinates),
FileBrowserWidgets::Blank(widget) => widget.set_coordinates(coordinates),
} }
} }
fn refresh(&mut self) -> HResult<()> { fn refresh(&mut self) -> HResult<()> {
match self { match self {
FileBrowserWidgets::FileList(widget) => widget.refresh(), FileBrowserWidgets::FileList(widget) => widget.refresh(),
FileBrowserWidgets::Previewer(widget) => widget.refresh() FileBrowserWidgets::Previewer(widget) => widget.refresh(),
FileBrowserWidgets::Blank(widget) => widget.refresh(),
} }
} }
fn get_drawlist(&self) -> HResult<String> { fn get_drawlist(&self) -> HResult<String> {
match self { match self {
FileBrowserWidgets::FileList(widget) => widget.get_drawlist(), FileBrowserWidgets::FileList(widget) => widget.get_drawlist(),
FileBrowserWidgets::Previewer(widget) => widget.get_drawlist() FileBrowserWidgets::Previewer(widget) => widget.get_drawlist(),
FileBrowserWidgets::Blank(widget) => widget.get_drawlist(),
} }
} }
} }
@ -162,6 +170,22 @@ impl Tabbable for TabView<FileBrowser> {
new_file.as_ref()).log() new_file.as_ref()).log()
} }
} }
let open_dirs = self.widgets
.iter()
.fold(HashSet::new(), |mut dirs, tab| {
tab.left_dir().map(|dir| dirs.insert(dir.clone())).ok();
dirs.insert(tab.cwd.clone());
tab.preview_widget()
.map(|preview| preview.get_file().map(|file| {
if file.is_dir() {
dirs.insert(file.clone());
}
})).ok();
dirs
});
self.active_tab_mut_().fs_cache.watch_only(open_dirs).log();
Ok(()) Ok(())
} }
} }
@ -199,9 +223,14 @@ impl FileBrowser {
let cache = fs_cache.clone(); let cache = fs_cache.clone();
let main_widget = AsyncWidget::new(&core, Box::new(move |_| { let main_widget = AsyncWidget::new(&core, Box::new(move |_| {
let main_dir = File::new(&main_path.file_name()? let name = if main_path.parent().is_none() {
.to_string_lossy() "root".to_string()
.to_string(), } else {
main_path.file_name()?
.to_string_lossy()
.to_string()
};
let main_dir = File::new(&name,
main_path.clone(), main_path.clone(),
None); None);
let files = cache.get_files_sync(&main_dir)?; let files = cache.get_files_sync(&main_dir)?;
@ -225,9 +254,14 @@ impl FileBrowser {
let cache = fs_cache.clone(); let cache = fs_cache.clone();
if let Some(left_path) = left_path { if let Some(left_path) = left_path {
let left_widget = AsyncWidget::new(&core, Box::new(move |_| { let left_widget = AsyncWidget::new(&core, Box::new(move |_| {
let left_dir = File::new(&left_path.file_name()? let name = if left_path.parent().is_none() {
.to_string_lossy() "root".to_string()
.to_string(), } else {
left_path.file_name()?
.to_string_lossy()
.to_string()
};
let left_dir = File::new(&name,
left_path.clone(), left_path.clone(),
None); None);
let files = cache.get_files_sync(&left_dir)?; let files = cache.get_files_sync(&left_dir)?;
@ -248,6 +282,14 @@ impl FileBrowser {
})); }));
let left_widget = FileBrowserWidgets::FileList(left_widget); let left_widget = FileBrowserWidgets::FileList(left_widget);
columns.push_widget(left_widget); columns.push_widget(left_widget);
} else {
let left_widget = AsyncWidget::new(&core, Box::new(move |_| {
let blank = TextView::new_blank(&core_l);
Ok(blank)
}));
let left_widget = FileBrowserWidgets::Blank(left_widget);
columns.push_widget(left_widget);
} }
let previewer = Previewer::new(&core_p, fs_cache.clone()); let previewer = Previewer::new(&core_p, fs_cache.clone());
@ -281,7 +323,8 @@ impl FileBrowser {
let file = self.selected_file()?; let file = self.selected_file()?;
if file.is_dir() { if file.is_dir() {
match file.is_readable() { let dir = file;
match dir.is_readable() {
Ok(true) => {}, Ok(true) => {},
Ok(false) => { Ok(false) => {
let status = let status =
@ -293,7 +336,38 @@ impl FileBrowser {
err @ Err(_) => err.log() err @ Err(_) => err.log()
} }
self.main_widget_goto(&file).log(); let previewer_files = self.preview_widget_mut()?.take_files().ok();
self.columns.remove_widget(0);
self.prev_cwd = Some(self.cwd.clone());
self.cwd = dir.clone();
let core = self.core.clone();
let cache = self.fs_cache.clone();
let main_widget = AsyncWidget::new(&core.clone(), Box::new(move |_| {
let files = match previewer_files {
Some(files) => files,
None => cache.get_files_sync(&dir)?
};
let selection = cache.get_selection(&dir).ok();
let mut list = ListView::new(&core, files);
if let Some(file) = selection {
list.select_file(&file);
}
list.content.meta_all();
Ok(list)
}));
let main_widget = FileBrowserWidgets::FileList(main_widget);
self.columns.insert_widget(1, main_widget);
} else { } else {
self.core.get_sender().send(Events::InputEnabled(false))?; self.core.get_sender().send(Events::InputEnabled(false))?;
@ -392,9 +466,42 @@ impl FileBrowser {
pub fn go_back(&mut self) -> HResult<()> { pub fn go_back(&mut self) -> HResult<()> {
if let Ok(new_cwd) = self.cwd.parent_as_file() { if let Ok(new_cwd) = self.cwd.parent_as_file() {
self.main_widget_goto(&new_cwd).log(); let core = self.core.clone();
let preview_files = self.take_main_files();
let old_left = self.columns.remove_widget(0);
self.prev_cwd = Some(self.cwd.clone());
self.cwd = new_cwd.clone();
if let Ok(left_dir) = new_cwd.parent_as_file() {
let cache = self.fs_cache.clone();
let left_widget = AsyncWidget::new(&core.clone(), Box::new(move |_| {
let files = cache.get_files_sync(&left_dir)?;
let list = ListView::new(&core, files);
Ok(list)
}));
let left_widget = FileBrowserWidgets::FileList(left_widget);
self.columns.prepend_widget(left_widget);
} else {
let left_widget = AsyncWidget::new(&core.clone(), Box::new(move |_| {
let blank = TextView::new_blank(&core);
Ok(blank)
}));
let left_widget = FileBrowserWidgets::Blank(left_widget);
self.columns.prepend_widget(left_widget);
}
self.columns.replace_widget(1, old_left);
self.main_widget_mut()?.content.meta_all();
if let Ok(preview_files) = preview_files {
self.preview_widget_mut().map(|preview| {
preview.put_preview_files(preview_files)
}).ok();
}
} }
self.columns.resize_children();
self.refresh() self.refresh()
} }
@ -459,8 +566,8 @@ impl FileBrowser {
} }
pub fn set_left_selection(&mut self) -> HResult<()> { pub fn set_left_selection(&mut self) -> HResult<()> {
if !self.left_async_widget_mut()?.ready() { return Ok(()) }
if self.cwd.parent().is_none() { return Ok(()) } if self.cwd.parent().is_none() { return Ok(()) }
if !self.left_async_widget_mut()?.ready() { return Ok(()) }
let selection = self.cwd()?.clone(); let selection = self.cwd()?.clone();
@ -469,6 +576,63 @@ impl FileBrowser {
Ok(()) Ok(())
} }
pub fn take_main_files(&mut self) -> HResult<Files> {
let core = self.core.clone();
let blank = AsyncWidget::new(&core.clone(), Box::new(move |_| {
HError::no_files()
}));
let blank = FileBrowserWidgets::Blank(blank);
let old_widget = self.columns.replace_widget(1, blank);
if let FileBrowserWidgets::FileList(main_widget) = old_widget {
let files = main_widget.take_widget()?.content;
return Ok(files)
}
HError::no_files()
}
pub fn take_left_files(&mut self) -> HResult<Files> {
let core = self.core.clone();
let blank = AsyncWidget::new(&core.clone(), Box::new(move |_| {
HError::no_files()
}));
let blank = FileBrowserWidgets::FileList(blank);
let old_widget = self.columns.replace_widget(0, blank);
if let FileBrowserWidgets::FileList(left_widget) = old_widget {
let files = left_widget.take_widget()?.content;
return Ok(files)
}
HError::no_files()
}
// pub fn take_preview_files(&mut self) -> HResult<Files> {
// let widget = self.columns.remove_widget(2);
// if let Filxx
// }
// pub fn take_files_from_widget(&self,
// widget: FileBrowserWidgets) -> HResult<Files> {
// match widget {
// FileBrowserWidgets::FileList(file_list) => {
// match file_list.take_widget() {
// Ok(widget) => {
// let files = widget.content;
// Ok(files)
// }
// _ => HError::no_files()
// }
// }
// FileBrowserWidgets::Previewer(previewer) => {
// let files = previewer.take_files()?;
// Ok(files)
// }
// _ => HError::no_files()
// }
// }
pub fn get_files(&self) -> HResult<&Files> { pub fn get_files(&self) -> HResult<&Files> {
Ok(&self.main_widget()?.content) Ok(&self.main_widget()?.content)
} }
@ -484,10 +648,12 @@ impl FileBrowser {
self.main_widget_mut()?.content.meta_updated = false; self.main_widget_mut()?.content.meta_updated = false;
let left_selection = self.left_widget()?.clone_selected_file(); if self.cwd.parent().is_some() {
let left_files = self.get_left_files()?; let left_selection = self.left_widget()?.clone_selected_file();
self.fs_cache.put_files(left_files, Some(left_selection)).log(); let left_files = self.get_left_files()?;
self.left_widget_mut()?.content.meta_updated = false; self.fs_cache.put_files(left_files, Some(left_selection)).log();
self.left_widget_mut()?.content.meta_updated = false;
}
Ok(()) Ok(())
} }
@ -516,6 +682,9 @@ impl FileBrowser {
if &self.cwd == dir { if &self.cwd == dir {
self.main_widget_mut()?.content.replace_file(old, new.cloned()).log(); self.main_widget_mut()?.content.replace_file(old, new.cloned()).log();
} }
self.preview_widget_mut()?.replace_file(dir, old, new).ok();
if &self.left_dir()? == &dir { if &self.left_dir()? == &dir {
self.left_widget_mut()?.content.replace_file(old, new.cloned()).log(); self.left_widget_mut()?.content.replace_file(old, new.cloned()).log();
} }
@ -590,6 +759,13 @@ impl FileBrowser {
widget widget
} }
pub fn preview_widget(&self) -> HResult<&Previewer> {
match self.columns.widgets.get(2)? {
FileBrowserWidgets::Previewer(previewer) => Ok(previewer),
_ => { return HError::wrong_widget("filelist", "previewer"); }
}
}
pub fn preview_widget_mut(&mut self) -> HResult<&mut Previewer> { pub fn preview_widget_mut(&mut self) -> HResult<&mut Previewer> {
match self.columns.widgets.get_mut(2)? { match self.columns.widgets.get_mut(2)? {
FileBrowserWidgets::Previewer(previewer) => Ok(previewer), FileBrowserWidgets::Previewer(previewer) => Ok(previewer),

View File

@ -464,7 +464,6 @@ impl Hash for File {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state); self.name.hash(state);
self.path.hash(state); self.path.hash(state);
self.selected.hash(state);
} }
} }

View File

@ -114,15 +114,17 @@ impl FsCache {
} else { } else {
self.add_watch(&dir).log(); self.add_watch(&dir).log();
let dir = dir.clone(); let dir = dir.clone();
let selection = self.get_selection(&dir).ok();
let files = Async::new(Box::new(move |_| { let files = Async::new(Box::new(move |_| {
let files = Files::new_from_path_cancellable(&dir.path, stale)?; let files = Files::new_from_path_cancellable(&dir.path, stale)?;
Ok(files) Ok(files)
})); }));
Ok((None, files)) Ok((selection, files))
} }
} }
pub fn get_files_sync(&self, dir: &File) -> HResult<Files> { pub fn get_files_sync(&self, dir: &File) -> HResult<Files> {
self.add_watch(&dir).log();
let files = self.get_files(&dir, Stale::new())?.1; let files = self.get_files(&dir, Stale::new())?.1;
files.wait() files.wait()
} }
@ -145,17 +147,17 @@ impl FsCache {
self.tab_settings.write()?.insert(dir.clone(), tab_settings); self.tab_settings.write()?.insert(dir.clone(), tab_settings);
let mut file_cache = self.files.write()?; // let mut file_cache = self.files.write()?;
if file_cache.contains_key(&files.directory) { // if file_cache.contains_key(&files.directory) {
if files.meta_updated { // if files.meta_updated {
let mut files = files.clone(); // let mut files = files.clone();
files.meta_updated = false; // files.meta_updated = false;
file_cache.insert(dir, files); // file_cache.insert(dir, files);
} // }
} else { // } else {
file_cache.insert(dir, files.clone()); // file_cache.insert(dir, files.clone());
} // }
Ok(()) Ok(())
} }
@ -164,8 +166,23 @@ impl FsCache {
Ok(self.files.read()?.contains_key(dir)) Ok(self.files.read()?.contains_key(dir))
} }
pub fn watch_only(&self, open_dirs: HashSet<File>) -> HResult<()> {
let removable = self.watched_dirs
.read()?
.difference(&open_dirs)
.map(|dir| dir.clone())
.collect::<Vec<File>>();
for watch in removable {
self.remove_watch(&watch).log();
}
Ok(())
}
fn add_watch(&self, dir: &File) -> HResult<()> { fn add_watch(&self, dir: &File) -> HResult<()> {
if !self.watched_dirs.read()?.contains(&dir) { if !self.watched_dirs.read()?.contains(&dir) {
self.watched_dirs.write()?.insert(dir.clone());
self.watcher.write()?.watch(&dir.path, RecursiveMode::NonRecursive)? self.watcher.write()?.watch(&dir.path, RecursiveMode::NonRecursive)?
} }
Ok(()) Ok(())
@ -245,32 +262,49 @@ fn watch_fs(rx_fs_events: Receiver<DebouncedEvent>,
}); });
} }
fn apply_event(fs_cache: &Arc<RwLock<HashMap<File, Files>>>, fn apply_event(_fs_cache: &Arc<RwLock<HashMap<File, Files>>>,
fs_changes: &Arc<RwLock<Vec<(File, Option<File>, Option<File>)>>>, fs_changes: &Arc<RwLock<Vec<(File, Option<File>, Option<File>)>>>,
event: DebouncedEvent) event: DebouncedEvent)
-> HResult<()> { -> HResult<()> {
let path = &event.get_source_path()?; let path = &event.get_source_path()?;
for dir in fs_cache.write()?.values_mut() { let dirpath = path.parent()
if dir.path_in_here(&path).unwrap_or(false) { .map(|path| path.to_path_buf())
let old_file = dir.find_file_with_path(&path).cloned(); .unwrap_or_else(|| PathBuf::from("/"));
let dirty_meta = old_file let dir = File::new_from_path(&dirpath, None)?;
.as_ref()
.map(|f| f.dirty_meta.clone())
.unwrap_or(None);
let mut new_file = match event {
DebouncedEvent::Remove(_) => None,
_ => Some(File::new_from_path(&path, dirty_meta)?)
};
new_file.as_mut().map(|file| file.meta_sync()); let old_file = File::new_from_path(&path, None)?;
dir.replace_file(old_file.as_ref(), new_file.clone()).log(); let mut new_file = match event {
DebouncedEvent::Remove(_) => None,
_ => Some(File::new_from_path(&path, None)?)
};
fs_changes.write()?.push((dir.directory.clone(), new_file.as_mut().map(|file| file.meta_sync());
old_file,
new_file)); fs_changes.write()?.push((dir,
} Some(old_file),
} new_file));
// for dir in fs_cache.write()?.values_mut() {
// if dir.path_in_here(&path).unwrap_or(false) {
// let old_file = dir.find_file_with_path(&path).cloned();
// let dirty_meta = old_file
// .as_ref()
// .map(|f| f.dirty_meta.clone())
// .unwrap_or(None);
// let mut new_file = match event {
// DebouncedEvent::Remove(_) => None,
// _ => Some(File::new_from_path(&path, dirty_meta)?)
// };
// new_file.as_mut().map(|file| file.meta_sync());
// dir.replace_file(old_file.as_ref(), new_file.clone()).log();
// fs_changes.write()?.push((dir.directory.clone(),
// old_file,
// new_file));
// }
// }
Ok(()) Ok(())
} }

View File

@ -66,6 +66,11 @@ impl<T> HBox<T> where T: Widget + PartialEq {
self.widgets.insert(index, widget); self.widgets.insert(index, widget);
} }
pub fn replace_widget(&mut self, index: usize, mut widget: T) -> T {
std::mem::swap(&mut self.widgets[index], &mut widget);
widget
}
pub fn toggle_zoom(&mut self) -> HResult<()> { pub fn toggle_zoom(&mut self) -> HResult<()> {
self.clear().log(); self.clear().log();
self.zoom_active = !self.zoom_active; self.zoom_active = !self.zoom_active;

View File

@ -3,7 +3,8 @@ use std::boxed::FnBox;
use rayon::ThreadPool; use rayon::ThreadPool;
use crate::files::{File, Kind}; use crate::files::{File, Files, Kind};
use crate::fscache::FsCache;
use crate::listview::ListView; use crate::listview::ListView;
use crate::textview::TextView; use crate::textview::TextView;
use crate::widget::{Widget, WidgetCore}; use crate::widget::{Widget, WidgetCore};
@ -131,7 +132,9 @@ impl<T: Send + 'static> Async<T> {
let value_fn = async_fn.lock()?.take()?; let value_fn = async_fn.lock()?.take()?;
let value = value_fn.call_box((stale.clone(),)); let value = value_fn.call_box((stale.clone(),));
async_value.lock()?.replace(value); async_value.lock()?.replace(value);
on_ready_fn.lock()?.take()?.call_box(()).log(); on_ready_fn.lock()?
.take()
.map(|on_ready| on_ready.call_box(()).log());
Ok(()) Ok(())
} }
@ -331,6 +334,10 @@ impl<W: Widget + Send + 'static> AsyncWidget<W> {
self.widget.get_mut() self.widget.get_mut()
} }
pub fn take_widget(self) -> HResult<W> {
Ok(self.widget.value?)
}
pub fn ready(&self) -> bool { pub fn ready(&self) -> bool {
self.widget().is_ok() self.widget().is_ok()
} }
@ -400,10 +407,16 @@ impl PartialEq for Previewer {
} }
} }
use crate::fscache::FsCache; #[derive(PartialEq)]
enum PreviewWidget {
FileList(ListView<Files>),
TextView(TextView)
}
pub struct Previewer { pub struct Previewer {
widget: AsyncWidget<Box<dyn Widget + Send>>, widget: AsyncWidget<PreviewWidget>,
core: WidgetCore, core: WidgetCore,
file: Option<File>, file: Option<File>,
pub cache: FsCache, pub cache: FsCache,
@ -414,7 +427,9 @@ impl Previewer {
pub fn new(core: &WidgetCore, cache: FsCache) -> Previewer { pub fn new(core: &WidgetCore, cache: FsCache) -> Previewer {
let core_ = core.clone(); let core_ = core.clone();
let widget = AsyncWidget::new(&core, Box::new(move |_| { let widget = AsyncWidget::new(&core, Box::new(move |_| {
Ok(Box::new(TextView::new_blank(&core_)) as Box<dyn Widget + Send>) let blank = TextView::new_blank(&core_);
let blank = PreviewWidget::TextView(blank);
Ok(blank)
})); }));
Previewer { widget: widget, Previewer { widget: widget,
core: core.clone(), core: core.clone(),
@ -423,7 +438,7 @@ impl Previewer {
} }
fn become_preview(&mut self, fn become_preview(&mut self,
widget: HResult<AsyncWidget<WidgetO>>) -> HResult<()> { widget: HResult<AsyncWidget<PreviewWidget>>) -> HResult<()> {
let coordinates = self.get_coordinates()?.clone(); let coordinates = self.get_coordinates()?.clone();
self.widget = widget?; self.widget = widget?;
self.widget.set_coordinates(&coordinates)?; self.widget.set_coordinates(&coordinates)?;
@ -438,6 +453,57 @@ impl Previewer {
self.file.as_ref() self.file.as_ref()
} }
pub fn take_files(&mut self) -> HResult<Files> {
let core = self.core.clone();
let mut widget = AsyncWidget::new(&core.clone(), Box::new(move |_| {
let widget = TextView::new_blank(&core);
let widget = PreviewWidget::TextView(widget);
Ok(widget)
}));
std::mem::swap(&mut self.widget, &mut widget);
match widget.take_widget() {
Ok(PreviewWidget::FileList(file_list)) => {
let files = file_list.content;
Ok(files)
}
_ => HError::no_files()?
}
}
pub fn replace_file(&mut self, dir: &File,
old: Option<&File>,
new: Option<&File>) -> HResult<()> {
if self.file.as_ref() != Some(dir) { return Ok(()) }
self.widget.widget_mut().map(|widget| {
match widget {
PreviewWidget::FileList(filelist) => {
filelist.content.replace_file(old, new.cloned()).map(|_| {
filelist.refresh().ok();
}).ok();
}
_ => {}
}
})
}
pub fn put_preview_files(&mut self, files: Files) {
let core = self.core.clone();
let dir = files.directory.clone();
let cache = self.cache.clone();
self.file = Some(dir);
self.widget = AsyncWidget::new(&self.core, Box::new(move |_| {
let selected_file = cache.get_selection(&files.directory);
let mut filelist = ListView::new(&core, files);
selected_file.map(|file| filelist.select_file(&file));
Ok(PreviewWidget::FileList(filelist))
}));
}
pub fn set_file(&mut self, pub fn set_file(&mut self,
file: &File) -> HResult<()> { file: &File) -> HResult<()> {
if Some(file) == self.file.as_ref() && !self.widget.is_stale()? { return Ok(()) } if Some(file) == self.file.as_ref() && !self.widget.is_stale()? { return Ok(()) }
@ -469,11 +535,11 @@ impl Previewer {
let preview = Previewer::preview_external(&file, &core, stale); let preview = Previewer::preview_external(&file, &core, stale);
if preview.is_ok() { return preview; } if preview.is_ok() { return preview; }
else { else {
let mut blank = Box::new(TextView::new_blank(&core)); let mut blank = TextView::new_blank(&core);
blank.set_coordinates(&coordinates).log(); blank.set_coordinates(&coordinates).log();
blank.refresh().log(); blank.refresh().log();
blank.animate_slide_up().log(); blank.animate_slide_up().log();
return Ok(blank) return Ok(PreviewWidget::TextView(blank))
} }
})))) }))))
} }
@ -485,7 +551,9 @@ impl Previewer {
} }
} }
fn preview_failed(file: &File) -> HResult<WidgetO> {
fn preview_failed(file: &File) -> HResult<PreviewWidget> {
HError::preview_failed(file) HError::preview_failed(file)
} }
@ -493,7 +561,7 @@ impl Previewer {
cache: FsCache, cache: FsCache,
core: &WidgetCore, core: &WidgetCore,
stale: Stale) stale: Stale)
-> Result<WidgetO, HError> { -> HResult<PreviewWidget> {
let (selection, cached_files) = cache.get_files(&file, stale.clone())?; let (selection, cached_files) = cache.get_files(&file, stale.clone())?;
let files = cached_files.wait()?; let files = cached_files.wait()?;
@ -510,11 +578,11 @@ impl Previewer {
file_list.refresh()?; file_list.refresh()?;
if is_stale(&stale)? { return Previewer::preview_failed(&file) } if is_stale(&stale)? { return Previewer::preview_failed(&file) }
file_list.animate_slide_up()?; file_list.animate_slide_up()?;
Ok(Box::new(file_list) as Box<dyn Widget + Send>) Ok(PreviewWidget::FileList(file_list))
} }
fn preview_text(file: &File, core: &WidgetCore, stale: Stale) fn preview_text(file: &File, core: &WidgetCore, stale: Stale)
-> HResult<WidgetO> { -> HResult<PreviewWidget> {
let lines = core.coordinates.ysize() as usize; let lines = core.coordinates.ysize() as usize;
let mut textview let mut textview
= TextView::new_from_file_limit_lines(&core, = TextView::new_from_file_limit_lines(&core,
@ -528,13 +596,13 @@ impl Previewer {
if is_stale(&stale)? { return Previewer::preview_failed(&file) } if is_stale(&stale)? { return Previewer::preview_failed(&file) }
textview.animate_slide_up()?; textview.animate_slide_up()?;
Ok(Box::new(textview)) Ok(PreviewWidget::TextView(textview))
} }
fn preview_external(file: &File, fn preview_external(file: &File,
core: &WidgetCore, core: &WidgetCore,
stale: Stale) stale: Stale)
-> Result<Box<dyn Widget + Send>, HError> { -> HResult<PreviewWidget> {
let process = let process =
std::process::Command::new("scope.sh") std::process::Command::new("scope.sh")
.arg(&file.path) .arg(&file.path)
@ -577,7 +645,7 @@ impl Previewer {
textview.set_coordinates(&core.coordinates).log(); textview.set_coordinates(&core.coordinates).log();
textview.refresh().log(); textview.refresh().log();
textview.animate_slide_up().log(); textview.animate_slide_up().log();
return Ok(Box::new(textview)) return Ok(PreviewWidget::TextView(textview))
} }
HError::preview_failed(file) HError::preview_failed(file)
} }
@ -607,7 +675,38 @@ impl Widget for Previewer {
} }
} }
impl Widget for PreviewWidget {
fn get_core(&self) -> HResult<&WidgetCore> {
match self {
PreviewWidget::FileList(widget) => widget.get_core(),
PreviewWidget::TextView(widget) => widget.get_core()
}
}
fn get_core_mut(&mut self) -> HResult<&mut WidgetCore> {
match self {
PreviewWidget::FileList(widget) => widget.get_core_mut(),
PreviewWidget::TextView(widget) => widget.get_core_mut()
}
}
fn set_coordinates(&mut self, coordinates: &Coordinates) -> HResult<()> {
match self {
PreviewWidget::FileList(widget) => widget.set_coordinates(coordinates),
PreviewWidget::TextView(widget) => widget.set_coordinates(coordinates),
}
}
fn refresh(&mut self) -> HResult<()> {
match self {
PreviewWidget::FileList(widget) => widget.refresh(),
PreviewWidget::TextView(widget) => widget.refresh()
}
}
fn get_drawlist(&self) -> HResult<String> {
match self {
PreviewWidget::FileList(widget) => widget.get_drawlist(),
PreviewWidget::TextView(widget) => widget.get_drawlist()
}
}
}
impl<T> Widget for Box<T> where T: Widget + ?Sized { impl<T> Widget for Box<T> where T: Widget + ?Sized {

View File

@ -54,8 +54,15 @@ impl Screen {
Ok(()) Ok(())
} }
pub fn is_resized(&self) -> HResult<(usize, usize)> { pub fn is_resized(&self) -> HResult<bool> {
Ok(self.size.read()?.clone()?) Ok(self.size.read()?.is_some())
}
pub fn get_size(&self) -> HResult<(usize, usize)> {
match self.size.read()?.clone() {
Some((xsize, ysize)) => Ok((xsize, ysize)),
None => Ok((self.xsize()?, self.ysize()?))
}
} }
pub fn take_size(&self) -> HResult<(usize, usize)> { pub fn take_size(&self) -> HResult<(usize, usize)> {

View File

@ -348,7 +348,9 @@ pub trait Widget {
_ => {} _ => {}
} }
self.resize().log(); self.resize().log();
self.screen()?.take_size().ok(); if self.screen()?.is_resized()? {
self.screen()?.take_size().ok();
}
self.refresh().ok(); self.refresh().ok();
self.draw().ok(); self.draw().ok();
} }
@ -408,7 +410,8 @@ pub trait Widget {
} }
fn resize(&mut self) -> HResult<()> { fn resize(&mut self) -> HResult<()> {
if let Ok((xsize, ysize)) = self.screen()?.is_resized() { if let Ok(true) = self.screen()?.is_resized() {
let (xsize, ysize) = self.screen()?.get_size()?;
let mut coords = self.get_core()?.coordinates.clone(); let mut coords = self.get_core()?.coordinates.clone();
coords.set_size_u(xsize, ysize-2); coords.set_size_u(xsize, ysize-2);
self.set_coordinates(&coords)?; self.set_coordinates(&coords)?;