diff options
-rw-r--r-- | src/fail.rs | 8 | ||||
-rw-r--r-- | src/file_browser.rs | 212 | ||||
-rw-r--r-- | src/files.rs | 1 | ||||
-rw-r--r-- | src/fscache.rs | 98 | ||||
-rw-r--r-- | src/hbox.rs | 5 | ||||
-rw-r--r-- | src/preview.rs | 131 | ||||
-rw-r--r-- | src/term.rs | 11 | ||||
-rw-r--r-- | src/widget.rs | 7 |
8 files changed, 401 insertions, 72 deletions
diff --git a/src/fail.rs b/src/fail.rs index ea5a4a7..1d5736d 100644 --- a/src/fail.rs +++ b/src/fail.rs @@ -84,7 +84,9 @@ pub enum HError { #[fail(display = "{}", _0)] Log(String), #[fail(display = "Metadata already processed")] - MetadataProcessedError + MetadataProcessedError, + #[fail(display = "No files to take from widget")] + WidgetNoFilesError, } impl HError { @@ -158,6 +160,10 @@ impl HError { pub fn metadata_processed<T>() -> HResult<T> { Err(HError::MetadataProcessedError) } + + pub fn no_files<T>() -> HResult<T> { + Err(HError::WidgetNoFilesError) + } } diff --git a/src/file_browser.rs b/src/file_browser.rs index 941901c..2c94219 100644 --- a/src/file_browser.rs +++ b/src/file_browser.rs @@ -4,6 +4,7 @@ use std::io::Write; use std::sync::{Arc, Mutex}; use std::path::PathBuf; use std::ffi::OsString; +use std::collections::HashSet; use crate::files::{File, Files, PathBufExt}; use crate::fscache::FsCache; @@ -12,6 +13,7 @@ use crate::hbox::HBox; use crate::widget::Widget; use crate::tabview::{TabView, Tabbable}; use crate::preview::{Previewer, AsyncWidget}; +use crate::textview::TextView; use crate::fail::{HResult, HError, ErrorLog}; use crate::widget::{Events, WidgetCore}; use crate::proclist::ProcView; @@ -25,37 +27,43 @@ use crate::coordinates::Coordinates; pub enum FileBrowserWidgets { FileList(AsyncWidget<ListView<Files>>), Previewer(Previewer), + Blank(AsyncWidget<TextView>), } impl Widget for FileBrowserWidgets { fn get_core(&self) -> HResult<&WidgetCore> { match self { 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> { match self { 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<()> { match self { FileBrowserWidgets::FileList(widget) => widget.set_coordinates(coordinates), FileBrowserWidgets::Previewer(widget) => widget.set_coordinates(coordinates), + FileBrowserWidgets::Blank(widget) => widget.set_coordinates(coordinates), } } fn refresh(&mut self) -> HResult<()> { match self { 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> { match self { 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() } } + + 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(()) } } @@ -199,9 +223,14 @@ impl FileBrowser { let cache = fs_cache.clone(); let main_widget = AsyncWidget::new(&core, Box::new(move |_| { - let main_dir = File::new(&main_path.file_name()? - .to_string_lossy() - .to_string(), + let name = if main_path.parent().is_none() { + "root".to_string() + } else { + main_path.file_name()? + .to_string_lossy() + .to_string() + }; + let main_dir = File::new(&name, main_path.clone(), None); let files = cache.get_files_sync(&main_dir)?; @@ -225,9 +254,14 @@ impl FileBrowser { let cache = fs_cache.clone(); if let Some(left_path) = left_path { let left_widget = AsyncWidget::new(&core, Box::new(move |_| { - let left_dir = File::new(&left_path.file_name()? - .to_string_lossy() - .to_string(), + let name = if left_path.parent().is_none() { + "root".to_string() + } else { + left_path.file_name()? + .to_string_lossy() + .to_string() + }; + let left_dir = File::new(&name, left_path.clone(), None); let files = cache.get_files_sync(&left_dir)?; @@ -248,6 +282,14 @@ impl FileBrowser { })); let left_widget = FileBrowserWidgets::FileList(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()); @@ -281,7 +323,8 @@ impl FileBrowser { let file = self.selected_file()?; if file.is_dir() { - match file.is_readable() { + let dir = file; + match dir.is_readable() { Ok(true) => {}, Ok(false) => { let status = @@ -293,7 +336,38 @@ impl FileBrowser { 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 { self.core.get_sender().send(Events::InputEnabled(false))?; @@ -392,9 +466,42 @@ impl FileBrowser { pub fn go_back(&mut self) -> HResult<()> { 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() } @@ -459,8 +566,8 @@ impl FileBrowser { } 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.left_async_widget_mut()?.ready() { return Ok(()) } let selection = self.cwd()?.clone(); @@ -469,6 +576,63 @@ impl FileBrowser { 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> { Ok(&self.main_widget()?.content) } @@ -484,10 +648,12 @@ impl FileBrowser { self.main_widget_mut()?.content.meta_updated = false; - let left_selection = self.left_widget()?.clone_selected_file(); - let left_files = self.get_left_files()?; - self.fs_cache.put_files(left_files, Some(left_selection)).log(); - self.left_widget_mut()?.content.meta_updated = false; + if self.cwd.parent().is_some() { + let left_selection = self.left_widget()?.clone_selected_file(); + let left_files = self.get_left_files()?; + self.fs_cache.put_files(left_files, Some(left_selection)).log(); + self.left_widget_mut()?.content.meta_updated = false; + } Ok(()) } @@ -516,6 +682,9 @@ impl FileBrowser { if &self.cwd == dir { 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 { self.left_widget_mut()?.content.replace_file(old, new.cloned()).log(); } @@ -590,6 +759,13 @@ impl FileBrowser { 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> { match self.columns.widgets.get_mut(2)? { FileBrowserWidgets::Previewer(previewer) => Ok(previewer), diff --git a/src/files.rs b/src/files.rs index a1c5592..01620bd 100644 --- a/src/files.rs +++ b/src/files.rs @@ -464,7 +464,6 @@ impl Hash for File { fn hash<H: Hasher>(&self, state: &mut H) { self.name.hash(state); self.path.hash(state); - self.selected.hash(state); } } diff --git a/src/fscache.rs b/src/fscache.rs index 8e33d44..ba0212f 100644 --- a/src/fscache.rs +++ b/src/fscache.rs @@ -114,15 +114,17 @@ impl FsCache { } else { self.add_watch(&dir).log(); let dir = dir.clone(); + let selection = self.get_selection(&dir).ok(); let files = Async::new(Box::new(move |_| { let files = Files::new_from_path_cancellable(&dir.path, stale)?; Ok(files) })); - Ok((None, files)) + Ok((selection, 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; files.wait() } @@ -145,17 +147,17 @@ impl FsCache { 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 files.meta_updated { - let mut files = files.clone(); - files.meta_updated = false; - file_cache.insert(dir, files); - } - } else { - file_cache.insert(dir, files.clone()); - } + // if file_cache.contains_key(&files.directory) { + // if files.meta_updated { + // let mut files = files.clone(); + // files.meta_updated = false; + // file_cache.insert(dir, files); + // } + // } else { + // file_cache.insert(dir, files.clone()); + // } Ok(()) } @@ -164,8 +166,23 @@ impl FsCache { 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<()> { if !self.watched_dirs.read()?.contains(&dir) { + self.watched_dirs.write()?.insert(dir.clone()); self.watcher.write()?.watch(&dir.path, RecursiveMode::NonRecursive)? } 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>)>>>, event: DebouncedEvent) -> HResult<()> { let path = &event.get_source_path()?; - 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)); - } - } + let dirpath = path.parent() + .map(|path| path.to_path_buf()) + .unwrap_or_else(|| PathBuf::from("/")); + let dir = File::new_from_path(&dirpath, None)?; + + let old_file = File::new_from_path(&path, None)?; + let mut new_file = match event { + DebouncedEvent::Remove(_) => None, + _ => Some(File::new_from_path(&path, None)?) + }; + + new_file.as_mut().map(|file| file.meta_sync()); + + 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(()) } diff --git a/src/hbox.rs b/src/hbox.rs index 0be0408..4537961 100644 --- a/src/hbox.rs +++ b/src/hbox.rs @@ -66,6 +66,11 @@ impl<T> HBox<T> where T: Widget + PartialEq { 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<()> { self.clear().log(); self.zoom_active = !self.zoom_active; diff --git a/src/preview.rs b/src/preview.rs index 013b2d6..4607fa4 100644 --- a/src/preview.rs +++ b/src/preview.rs @@ -3,7 +3,8 @@ use std::boxed::FnBox; use rayon::ThreadPool; -use crate::files::{File, Kind}; +use crate::files::{File, Files, Kind}; +use crate::fscache::FsCache; use crate::listview::ListView; use crate::textview::TextView; use crate::widget::{Widget, WidgetCore}; @@ -131,7 +132,9 @@ impl<T: Send + 'static> Async<T> { let value_fn = async_fn.lock()?.take()?; let value = value_fn.call_box((stale.clone(),)); 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(()) } @@ -331,6 +334,10 @@ impl<W: Widget + Send + 'static> AsyncWidget<W> { self.widget.get_mut() } + pub fn take_widget(self) -> HResult<W> { + Ok(self.widget.value?) + } + pub fn ready(&self) -> bool { 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 { - widget: AsyncWidget<Box<dyn Widget + Send>>, + widget: AsyncWidget<PreviewWidget>, core: WidgetCore, file: Option<File>, pub cache: FsCache, @@ -414,7 +427,9 @@ impl Previewer { pub fn new(core: &WidgetCore, cache: FsCache) -> Previewer { let core_ = core.clone(); 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, core: core.clone(), @@ -423,7 +438,7 @@ impl Previewer { } fn become_preview(&mut self, - widget: HResult<AsyncWidget<WidgetO>>) -> HResult<()> { + widget: HResult<AsyncWidget<PreviewWidget>>) -> HResult<()> { let coordinates = self.get_coordinates()?.clone(); self.widget = widget?; self.widget.set_coordinates(&coordinates)?; @@ -438,6 +453,57 @@ impl Previewer { 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, file: &File) -> HResult<()> { 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); if preview.is_ok() { return preview; } else { - let mut blank = Box::new(TextView::new_blank(&core)); + let mut blank = TextView::new_blank(&core); blank.set_coordinates(&coordinates).log(); blank.refresh().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) } @@ -493,7 +561,7 @@ impl Previewer { cache: FsCache, core: &WidgetCore, stale: Stale) - -> Result<WidgetO, HError> { + -> HResult<PreviewWidget> { let (selection, cached_files) = cache.get_files(&file, stale.clone())?; let files = cached_files.wait()?; @@ -510,11 +578,11 @@ impl Previewer { file_list.refresh()?; if is_stale(&stale)? { return Previewer::preview_failed(&file) } 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) - -> HResult<WidgetO> { + -> HResult<PreviewWidget> { let lines = core.coordinates.ysize() as usize; let mut textview = TextView::new_from_file_limit_lines(&core, @@ -528,13 +596,13 @@ impl Previewer { if is_stale(&stale)? { return Previewer::preview_failed(&file) } textview.animate_slide_up()?; - Ok(Box::new(textview)) + Ok(PreviewWidget::TextView(textview)) } fn preview_external(file: &File, core: &WidgetCore, stale: Stale) - -> Result<Box<dyn Widget + Send>, HError> { + -> HResult<PreviewWidget> { let process = std::process::Command::new("scope.sh") .arg(&file.path) @@ -577,7 +645,7 @@ impl Previewer { textview.set_coordinates(&core.coordinates).log(); textview.refresh().log(); textview.animate_slide_up().log(); - return Ok(Box::new(textview)) + return Ok(PreviewWidget::TextView(textview)) } 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 { diff --git a/src/term.rs b/src/term.rs index 7c63066..bc99c36 100644 --- a/src/term.rs +++ b/src/term.rs @@ -54,8 +54,15 @@ impl Screen { Ok(()) } - pub fn is_resized(&self) -> HResult<(usize, usize)> { - Ok(self.size.read()?.clone()?) + pub fn is_resized(&self) -> HResult<bool> { + 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)> { diff --git a/src/widget.rs b/src/widget.rs index 4f400c6..46eb340 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -348,7 +348,9 @@ pub trait Widget { _ => {} } self.resize().log(); - self.screen()?.take_size().ok(); + if self.screen()?.is_resized()? { + self.screen()?.take_size().ok(); + } self.refresh().ok(); self.draw().ok(); } @@ -408,7 +410,8 @@ pub trait Widget { } 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(); coords.set_size_u(xsize, ysize-2); self.set_coordinates(&coords)?; |