summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-03-09 11:06:13 +0100
committerrabite <rabite@posteo.de>2019-03-09 11:06:13 +0100
commit5d456539015876c1891bf0ac05b8f7dd3fbe8d57 (patch)
tree39e2e42cd28773eb9ac785d0430b51f72e6876d6
parent6e02ef6486b6660b69136e19c7086e8b2b3eb7ee (diff)
use enum to allow multiple widget types in hbox
-rw-r--r--src/fail.rs16
-rw-r--r--src/file_browser.rs340
-rw-r--r--src/files.rs21
-rw-r--r--src/hbox.rs91
-rw-r--r--src/miller_columns.rs86
-rw-r--r--src/minibuffer.rs2
-rw-r--r--src/preview.rs72
-rw-r--r--src/proclist.rs154
-rw-r--r--src/tabview.rs3
-rw-r--r--src/widget.rs21
10 files changed, 504 insertions, 302 deletions
diff --git a/src/fail.rs b/src/fail.rs
index a6f8abe..2c01885 100644
--- a/src/fail.rs
+++ b/src/fail.rs
@@ -45,13 +45,27 @@ pub enum HError {
#[fail(display = "No header for widget")]
NoHeaderError,
#[fail(display = "You wanted this!")]
- Quit
+ Quit,
+ #[fail(display = "HBox ratio mismatch: {} widgets, ratio is {:?}", wnum, ratio)]
+ HBoxWrongRatioError{ wnum: usize, ratio: Vec<usize> },
+ #[fail(display = "Got wrong widget: {}! Wanted: {}", got, wanted)]
+ WrongWidgetError{got: String, wanted: String},
}
impl HError {
pub fn quit() -> HResult<()> {
Err(HError::Quit)
}
+ pub fn wrong_ratio<T>(wnum: usize, ratio: Vec<usize>) -> HResult<T> {
+ Err(HError::HBoxWrongRatioError{ wnum: wnum, ratio: ratio })
+ }
+ pub fn no_widget<T>() -> HResult<T> {
+ Err(HError::NoWidgetError(Backtrace::new()))
+ }
+ pub fn wrong_widget<T>(got: &str, wanted: &str) -> HResult<T> {
+ Err(HError::WrongWidgetError{ got: got.to_string(),
+ wanted: wanted.to_string()})
+ }
}
pub trait ErrorLog where Self: Sized {
diff --git a/src/file_browser.rs b/src/file_browser.rs
index 37a836c..fb8fea2 100644
--- a/src/file_browser.rs
+++ b/src/file_browser.rs
@@ -6,22 +6,55 @@ use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::time::Duration;
use std::path::PathBuf;
+use std::collections::HashMap;
use crate::files::{File, Files};
use crate::listview::ListView;
use crate::miller_columns::MillerColumns;
use crate::widget::Widget;
use crate::tabview::{TabView, Tabbable};
-use crate::preview::WillBeWidget;
+use crate::preview::{Previewer, WillBeWidget};
use crate::fail::{HResult, HError, ErrorLog};
use crate::widget::{Events, WidgetCore};
use crate::proclist::ProcView;
+#[derive(PartialEq)]
+pub enum FileBrowserWidgets {
+ FileList(WillBeWidget<ListView<Files>>),
+ Previewer(Previewer),
+}
+impl Widget for FileBrowserWidgets {
+ fn get_core(&self) -> HResult<&WidgetCore> {
+ match self {
+ FileBrowserWidgets::FileList(widget) => widget.get_core(),
+ FileBrowserWidgets::Previewer(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()
+ }
+ }
+ fn refresh(&mut self) -> HResult<()> {
+ match self {
+ FileBrowserWidgets::FileList(widget) => widget.refresh(),
+ FileBrowserWidgets::Previewer(widget) => widget.refresh()
+ }
+ }
+ fn get_drawlist(&self) -> HResult<String> {
+ match self {
+ FileBrowserWidgets::FileList(widget) => widget.get_drawlist(),
+ FileBrowserWidgets::Previewer(widget) => widget.get_drawlist()
+ }
+ }
+}
pub struct FileBrowser {
- pub columns: MillerColumns<WillBeWidget<ListView<Files>>>,
+ pub columns: MillerColumns<FileBrowserWidgets>,
pub cwd: File,
+ selections: HashMap<File, File>,
core: WidgetCore,
watcher: INotifyWatcher,
watches: Vec<PathBuf>,
@@ -105,15 +138,17 @@ fn watch_dir(rx: Receiver<DebouncedEvent>,
impl FileBrowser {
pub fn new_cored(core: &WidgetCore) -> HResult<FileBrowser> {
let cwd = std::env::current_dir().unwrap();
- let coords = core.coordinates.clone();
- let core_m = core.clone();
- let core_l = core.clone();
+ let mut core_m = core.clone();
+ let mut core_l = core.clone();
+ let mut core_p = core.clone();
let mut miller = MillerColumns::new(core);
- miller.set_coordinates(&coords)?;
-
+ miller.set_ratios(vec![20,30,49]);
+ let list_coords = miller.calculate_coordinates()?;
- let (left_coords, main_coords, _) = miller.calculate_coordinates();
+ core_l.coordinates = list_coords[0].clone();
+ core_m.coordinates = list_coords[1].clone();
+ core_p.coordinates = list_coords[2].clone();
let main_path = cwd.ancestors()
.take(1)
@@ -125,7 +160,6 @@ impl FileBrowser {
let main_widget = WillBeWidget::new(&core, Box::new(move |_| {
let mut list = ListView::new(&core_m,
Files::new_from_path(&main_path)?);
- list.set_coordinates(&main_coords).log();
list.animate_slide_up().log();
Ok(list)
}));
@@ -134,14 +168,18 @@ impl FileBrowser {
let left_widget = WillBeWidget::new(&core, Box::new(move |_| {
let mut list = ListView::new(&core_l,
Files::new_from_path(&left_path)?);
- list.set_coordinates(&left_coords).log();
list.animate_slide_up().log();
Ok(list)
}));
+ let left_widget = FileBrowserWidgets::FileList(left_widget);
miller.push_widget(left_widget);
}
- miller.push_widget(main_widget);
+ let previewer = Previewer::new(&core_p);
+
+ miller.push_widget(FileBrowserWidgets::FileList(main_widget));
+ miller.push_widget(FileBrowserWidgets::Previewer(previewer));
+ miller.refresh().log();
let cwd = File::new_from_path(&cwd).unwrap();
@@ -151,11 +189,13 @@ impl FileBrowser {
let watcher = INotifyWatcher::new(tx_watch, Duration::from_secs(2)).unwrap();
watch_dir(rx_watch, dir_events.clone(), core.get_sender());
- let mut proc_view = ProcView::new(core);
- proc_view.set_coordinates(&coords).log();
+ let proc_view = ProcView::new(core);
+
+
Ok(FileBrowser { columns: miller,
cwd: cwd,
+ selections: HashMap::new(),
core: core.clone(),
watcher: watcher,
watches: vec![],
@@ -165,112 +205,138 @@ impl FileBrowser {
pub fn enter_dir(&mut self) -> HResult<()> {
let file = self.selected_file()?;
- let (_, coords, _) = self.columns.calculate_coordinates();
- let core = self.core.clone();
-
- match file.read_dir() {
- Ok(files) => {
- std::env::set_current_dir(&file.path).unwrap();
- self.cwd = file.clone();
- let view = WillBeWidget::new(&core.clone(), Box::new(move |_| {
- let files = files.clone();
- let mut list = ListView::new(&core, files);
- list.set_coordinates(&coords).log();
- list.animate_slide_up().log();
- Ok(list)
- }));
- self.columns.push_widget(view);
- },
- _ => {
- let status = std::process::Command::new("rifle")
- .args(file.path.file_name())
- .status();
-
- match status {
- Ok(status) =>
- self.show_status(&format!("\"{}\" exited with {}",
- "rifle", status)).log(),
- Err(err) =>
- self.show_status(&format!("Can't run this \"{}\": {}",
- "rifle", err)).log()
-
- };
+
+ if file.is_dir() {
+ self.main_widget_goto(&file).log();
+ } else {
+ let status = std::process::Command::new("rifle")
+ .args(file.path.file_name())
+ .status();
+
+ match status {
+ Ok(status) =>
+ self.show_status(&format!("\"{}\" exited with {}",
+ "rifle", status)).log(),
+ Err(err) =>
+ self.show_status(&format!("Can't run this \"{}\": {}",
+ "rifle", err)).log()
}
}
Ok(())
}
- pub fn go_back(&mut self) -> HResult<()> {
- self.columns.pop_widget();
+ pub fn main_widget_goto(&mut self, dir: &File) -> HResult<()> {
+ self.cwd = dir.clone();
+ let dir = dir.clone();
+ let selected_file = self.get_selection(&dir).ok().cloned();
+
+ let main_widget = self.main_widget_mut()?;
+ main_widget.change_to(Box::new(move |stale, core| {
+ let path = dir.path();
+ let files = Files::new_from_path_cancellable(&path, stale)?;
+
+ let mut list = ListView::new(&core, files);
+
+ if let Some(file) = &selected_file {
+ list.select_file(file);
+ }
+ Ok(list)
+ })).log();
+
+ if let Ok(grand_parent) = self.cwd()?.parent_as_file() {
+ self.left_widget_goto(&grand_parent).log();
+ } else {
+ self.left_widget_mut()?.set_stale().log();
+ }
+
+ Ok(())
+ }
+
+ pub fn left_widget_goto(&mut self, dir: &File) -> HResult<()> {
+ let dir = dir.clone();
+
+ let left_widget = self.left_widget_mut()?;
+ left_widget.change_to(Box::new(move |stale, core| {
+ let path = dir.path();
+ let files = Files::new_from_path_cancellable(&path, stale)?;
+ let list = ListView::new(&core, files);
+ Ok(list)
+ }))?;
+ Ok(())
+ }
- if let Ok(new_cwd) = self.cwd.grand_parent_as_file() {
- self.cwd = new_cwd;
+ pub fn go_back(&mut self) -> HResult<()> {
+ if let Ok(new_cwd) = self.cwd.parent_as_file() {
+ self.main_widget_goto(&new_cwd).log();
}
self.refresh()
}
pub fn update_preview(&mut self) -> HResult<()> {
+ if !self.main_widget()?.ready() { return Ok(()) }
let file = self.selected_file()?.clone();
- let preview = &mut self.columns.preview;
- preview.set_file(&file);
+ let selection = self.get_selection(&file).ok().cloned();
+ let preview = self.preview_widget_mut()?;
+ preview.set_file(&file, selection);
Ok(())
}
- pub fn fix_selection(&mut self) -> HResult<()> {
- let cwd = self.cwd()?;
- (*self.left_widget()?.lock()?).as_mut()?.select_file(&cwd);
+ pub fn set_left_selection(&mut self) -> HResult<()> {
+ if !self.left_widget()?.ready() { return Ok(()) }
+
+ let parent = self.cwd()?.parent_as_file();
+
+ let left_selection = self.get_selection(&parent?)?;
+ self.left_widget()?.widget()?.lock()?.as_mut()?.select_file(&left_selection);
+
Ok(())
}
- pub fn fix_left(&mut self) -> HResult<()> {
- if self.left_widget().is_err() {
- let cwd = self.selected_file()?.clone();
- if let Ok(grand_parent) = cwd.grand_parent_as_file() {
- let (coords, _, _) = self.columns.calculate_coordinates();
- let core = self.core.clone();
- let left_view = WillBeWidget::new(&self.core, Box::new(move |_| {
- let mut view
- = ListView::new(&core,
- Files::new_from_path(&grand_parent.path)?);
- view.set_coordinates(&coords).log();
- Ok(view)
- }));
- self.columns.prepend_widget(left_view);
- }
+ pub fn get_selection(&self, dir: &File) -> HResult<&File> {
+ Ok(self.selections.get(dir)?)
+ }
+
+ pub fn save_selection(&mut self) -> HResult<()> {
+ let cwd = self.cwd()?.clone();
+ if let Ok(main_selection) = self.selected_file() {
+ self.selections.insert(cwd.clone(), main_selection);
+ }
+ if let Ok(left_dir) = self.cwd()?.parent_as_file() {
+ self.selections.insert(left_dir, cwd);
}
Ok(())
}
- pub fn cwd(&self) -> HResult<File> {
- let widget = self.columns.get_main_widget()?.widget()?;
- let cwd = (*widget.lock()?).as_ref()?.content.directory.clone();
- Ok(cwd)
+ pub fn cwd(&self) -> HResult<&File> {
+ Ok(&self.cwd)
}
pub fn set_cwd(&mut self) -> HResult<()> {
let cwd = self.cwd()?;
std::env::set_current_dir(&cwd.path)?;
- self.cwd = cwd;
Ok(())
}
pub fn left_dir(&self) -> HResult<File> {
- let widget = self.columns.get_left_widget()?.widget()?;
- let dir = (*widget.lock()?).as_ref()?.content.directory.clone();
+ let widget = self.left_widget()?.widget()?;
+ let dir = widget.lock()?.as_ref()?.content.directory.clone();
Ok(dir)
}
fn update_watches(&mut self) -> HResult<()> {
+ if !self.left_widget()?.ready() || !self.main_widget()?.ready() {
+ return Ok(())
+ }
let watched_dirs = self.watches.clone();
- let cwd = self.cwd()?;
+ let cwd = self.cwd()?.clone();
let left_dir = self.left_dir()?;
let preview_dir = self.selected_file().ok().map(|f| f.path);
for watched_dir in watched_dirs.iter() {
if watched_dir != &cwd.path && watched_dir != &left_dir.path &&
Some(watched_dir.clone()) != preview_dir {
- self.watcher.unwatch(&watched_dir).unwrap();
+ self.watcher.unwatch(&watched_dir).ok();
self.watches.remove_item(&watched_dir);
}
}
@@ -292,51 +358,85 @@ impl FileBrowser {
}
fn handle_dir_events(&mut self) -> HResult<()> {
- let mut dir_events = self.dir_events.lock()?;
- for event in dir_events.iter() {
- let main_widget = self.columns.get_main_widget()?.widget()?;
- let main_files = &mut (*main_widget.lock()?);
- let main_files = &mut main_files.as_mut()?.content;
- let main_result = main_files.handle_event(event);
-
- let left_widget = self.columns.get_left_widget()?.widget()?;
- let left_files = &mut (*left_widget.lock()?);
- let left_files = &mut left_files.as_mut()?.content;
- let left_result = left_files.handle_event(event);
+ let dir_events = self.dir_events.clone();
+ for event in dir_events.lock()?.iter() {
+ let main_widget = self.main_widget()?.widget()?;
+ let mut main_widget = main_widget.lock()?;
+ let main_result = main_widget.as_mut()?.content.handle_event(event);
+
+ let left_widget = self.left_widget()?.widget()?;
+ let mut left_files = left_widget.lock()?;
+ let left_result = left_files.as_mut()?.content.handle_event(event);
match main_result {
Err(HError::WrongDirectoryError { .. }) => {
match left_result {
Err(HError::WrongDirectoryError { .. }) => {
- let preview = &mut self.columns.preview;
+ let preview = self.preview_widget_mut()?;
preview.reload();
}, _ => {}
}
}, _ => {}
}
}
- dir_events.clear();
+ dir_events.lock()?.clear();
Ok(())
}
pub fn selected_file(&self) -> HResult<File> {
- let widget = self.main_widget()?;
+ let widget = self.main_widget()?.widget()?;
let file = widget.lock()?.as_ref()?.selected_file().clone();
Ok(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_widget(&self) -> HResult<&WillBeWidget<ListView<Files>>> {
+ let widget = match self.columns.get_main_widget()? {
+ FileBrowserWidgets::FileList(filelist) => Ok(filelist),
+ _ => { return HError::wrong_widget("previewer", "filelist"); }
+ };
+ widget
+ }
+
+ pub fn main_widget_mut(&mut self) -> HResult<&mut WillBeWidget<ListView<Files>>> {
+ let widget = match self.columns.get_main_widget_mut()? {
+ FileBrowserWidgets::FileList(filelist) => Ok(filelist),
+ _ => { return HError::wrong_widget("previewer", "filelist"); }
+ };
+ widget
+ }
+
+ pub fn left_widget(&self) -> HResult<&WillBeWidget<ListView<Files>>> {
+ let widget = match self.columns.get_left_widget()? {
+ FileBrowserWidgets::FileList(filelist) => Ok(filelist),
+ _ => { return HError::wrong_widget("previewer", "filelist"); }
+ };
+ widget
+ }
+
+ pub fn left_widget_mut(&mut self) -> HResult<&mut WillBeWidget<ListView<Files>>> {
+ let widget = match self.columns.get_left_widget_mut()? {
+ FileBrowserWidgets::FileList(filelist) => Ok(filelist),
+ _ => { return HError::wrong_widget("previewer", "filelist"); }
+ };
+ widget
+ }
+
+ pub fn preview_widget(&self) -> HResult<&Previewer> {
+ match self.columns.get_right_widget()? {
+ FileBrowserWidgets::Previewer(previewer) => Ok(previewer),
+ _ => { return HError::wrong_widget("filelist", "previewer"); }
+ }
}
- pub fn left_widget(&self) -> HResult<Arc<Mutex<Option<ListView<Files>>>>> {
- let widget = self.columns.get_left_widget()?.widget()?;
- Ok(widget)
+ pub fn preview_widget_mut(&mut self) -> HResult<&mut Previewer> {
+ match self.columns.get_right_widget_mut()? {
+ FileBrowserWidgets::Previewer(previewer) => Ok(previewer),
+ _ => { return HError::wrong_widget("filelist", "previewer"); }
+ }
}
pub fn quit_with_dir(&self) -> HResult<()> {
- let cwd = self.cwd()?.path;
+ let cwd = self.cwd()?.clone().path;
let selected_file = self.selected_file()?;
let selected_file = selected_file.path.to_string_lossy();
@@ -362,22 +462,22 @@ impl FileBrowser {
self.cwd = cwd;
let dir = std::path::PathBuf::from(&dir);
let left_dir = std::path::PathBuf::from(&dir);
- let (left_coords, main_coords, _) = self.columns.calculate_coordinates();
- let mcore = self.core.clone();
- let lcore = self.core.clone();
+ let mcore = self.main_widget()?.get_core()?.clone();
+ let lcore = self.left_widget()?.get_core()?.clone();;
let middle = WillBeWidget::new(&self.core, Box::new(move |_| {
let files = Files::new_from_path(&dir.clone())?;
- let mut listview = ListView::new(&mcore, files);
- listview.set_coordinates(&main_coords).log();
+ let listview = ListView::new(&mcore, files);
Ok(listview)
}));
+ let middle = FileBrowserWidgets::FileList(middle);
+
let left = WillBeWidget::new(&self.core, Box::new(move |_| {
let files = Files::new_from_path(&left_dir.parent()?)?;
- let mut listview = ListView::new(&lcore, files);
- listview.set_coordinates(&left_coords).log();
+ let listview = ListView::new(&lcore, files);
Ok(listview)
}));
+ let left = FileBrowserWidgets::FileList(left);
self.columns.push_widget(left);
self.columns.push_widget(middle);
},
@@ -388,9 +488,9 @@ impl FileBrowser {
fn exec_cmd(&mut self, tab_dirs: Vec<File>) -> HResult<()> {
let filename = self.selected_file()?.name.clone();
- let widget = self.main_widget()?;
+ let widget = self.main_widget()?.widget()?;
let widget = widget.lock()?;
- let selected_files = (*widget).as_ref()?.content.get_selected();
+ let selected_files = widget.as_ref()?.content.get_selected();
let file_names
= selected_files.iter().map(|f| f.name.clone()).collect::<Vec<String>>();
@@ -424,6 +524,9 @@ impl Widget for FileBrowser {
fn get_core(&self) -> HResult<&WidgetCore> {
Ok(&self.core)
}
+ fn get_core_mut(&mut self) -> HResult<&mut WidgetCore> {
+ Ok(&mut self.core)
+ }
fn render_header(&self) -> HResult<String> {
let xsize = self.get_coordinates()?.xsize();
let file = self.selected_file()?;
@@ -449,9 +552,9 @@ impl Widget for FileBrowser {
let group = file.pretty_group().unwrap_or("NOGROUP".into());
let mtime = file.pretty_mtime().unwrap_or("NOMTIME".into());
-
- let selection = (*self.main_widget().as_ref().unwrap().lock()?).as_ref()?.get_selection();
- let file_count = (*self.main_widget()?.lock()?).as_ref()?.content.len();
+ let main_widget = self.main_widget()?.widget()?;
+ let selection = main_widget.lock()?.as_ref().unwrap().get_selection();
+ let file_count = main_widget.lock()?.as_ref().unwrap().content.len();
let file_count = format!("{}", file_count);
let digits = file_count.len();
let file_count = format!("{:digits$}/{:digits$}",
@@ -466,22 +569,23 @@ impl Widget for FileBrowser {
}
fn refresh(&mut self) -> HResult<()> {
//self.proc_view.lock()?.set_coordinates(self.get_coordinates()?);
- self.handle_dir_events()?;
+ self.handle_dir_events().ok();
self.columns.refresh().ok();
- self.fix_left().ok();
- self.fix_selection().ok();
+ self.set_left_selection().log();
+ self.save_selection().log();
self.set_cwd().ok();
self.update_watches().ok();
self.update_preview().ok();
+ self.columns.refresh().ok();
Ok(())
}
fn get_drawlist(&self) -> HResult<String> {
- if self.columns.get_left_widget().is_err() {
- Ok(self.columns.get_clearlist()? + &self.columns.get_drawlist()?)
- } else {
- Ok(self.columns.get_drawlist()?)
- }
+ let left = self.left_widget()?.get_drawlist()?;
+ let main = self.main_widget()?.get_drawlist()?;
+ let prev = self.preview_widget()?.get_drawlist()?;
+
+ Ok(left + &main + &prev)
}
fn on_key(&mut self, key: Key) -> HResult<()> {
@@ -494,7 +598,7 @@ impl Widget for FileBrowser {
self.proc_view.lock()?.popup()?;
}
,
- _ => { self.columns.get_main_widget_mut()?.on_key(key)?; },
+ _ => { self.main_widget_mut()?.on_key(key)?; },
}
self.update_preview()?;
Ok(())
diff --git a/src/files.rs b/src/files.rs
index fe0dc8b..daabb9e 100644
--- a/src/files.rs
+++ b/src/files.rs
@@ -3,6 +3,7 @@ use std::ops::Index;
use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
+use std::hash::{Hash, Hasher};
use lscolors::LsColors;
use mime_detective;
@@ -294,6 +295,16 @@ impl PartialEq for File {
}
}
+impl Hash for File {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.name.hash(state);
+ self.path.hash(state);
+ self.selected.hash(state);
+ }
+}
+
+impl Eq for File {}
+
#[derive(Debug, Clone)]
pub struct File {
pub name: String,
@@ -403,6 +414,16 @@ impl File {
Some(mime.type_().as_str().to_string())
}
+
+ pub fn parent(&self) -> Option<PathBuf> {
+ Some(self.path.parent()?.to_path_buf())
+ }
+
+ pub fn parent_as_file(&self) -> HResult<File> {
+ let pathbuf = self.parent()?;
+ File::new_from_path(&pathbuf)
+ }
+
pub fn grand_parent(&self) -> Option<PathBuf> {
Some(self.path.parent()?.parent()?.to_path_buf())
}
diff --git a/src/hbox.rs b/src/hbox.rs
index 6a2aa8e..7982333 100644
--- a/src/hbox.rs
+++ b/src/hbox.rs
@@ -2,12 +2,13 @@ use termion::event::{Event};
use crate::widget::{Widget, WidgetCore};
use crate::coordinates::{Coordinates, Size, Position};
-use crate::fail::{HResult, ErrorLog};
+use crate::fail::{HResult, HError, ErrorLog};
#[derive(PartialEq)]
pub struct HBox<T: Widget> {
pub core: WidgetCore,
pub widgets: Vec<T>,
+ pub ratios: Option<Vec<usize>>,
pub active: Option<usize>,
}
@@ -16,59 +17,89 @@ impl<T> HBox<T> where T: Widget + PartialEq {
pub fn new(core: &WidgetCore) -> HBox<T> {
HBox { core: core.clone(),
widgets: vec![],
+ ratios: None,
active: None
}
}
- pub fn resize_children(&mut self) {
- let coords: Vec<Coordinates>
- = self.widgets.iter().map(
- |w|
- self.calculate_coordinates(w)).collect();
+ pub fn resize_children(&mut self) -> HResult<()> {
+ let len = self.widgets.len();
+ if len == 0 { return Ok(()) }
+
+ let coords: Vec<Coordinates> = self.calculate_coordinates()?;
+
+
for (widget, coord) in self.widgets.iter_mut().zip(coords.iter()) {
widget.set_coordinates(coord).log();
}
+
+ Ok(())
}
- pub fn push_widget(&mut self, widget: T) where T: PartialEq {
+ pub fn push_widget(&mut self, widget: T) {
self.widgets.push(widget);
- self.resize_children();
- self.refresh().log();
}
pub fn pop_widget(&mut self) -> Option<T> {
let widget = self.widgets.pop();
- self.resize_children();
- self.refresh().log();
widget
}
pub fn prepend_widget(&mut self, widget: T) {
self.widgets.insert(0, widget);
- self.resize_children();
- self.refresh().log();
}
- pub fn calculate_coordinates(&self, widget: &T)
- -> Coordinates where T: PartialEq {
- let coordinates = self.get_coordinates().unwrap();
- let xsize = coordinates.xsize();
- let ysize = coordinates.ysize();
- let top = coordinates.top().y();
+ pub fn set_ratios(&mut self, ratios: Vec<usize>) {
+ self.ratios = Some(ratios);
+ }
- let pos = self.widgets.iter().position(|w | w == widget).unwrap();
- let num = self.widgets.len();
+ pub fn calculate_equal_ratios(&self) -> HResult<Vec<usize>> {
+ let len = self.widgets.len();
+ if len == 0 { return HError::no_widget(); }
- let widget_xsize = (xsize / num as u16) + 1;
- let widget_xpos = widget_xsize * pos as u16;
+ let ratios = (0..len).map(|_| 100 / len).collect();
+ Ok(ratios)
+ }
- Coordinates {
- size: Size((widget_xsize,
- ysize)),
- position: Position((widget_xpos,
- top))
- }
+ pub fn calculate_coordinates(&self)
+ -> HResult<Vec<Coordinates>> {
+ let box_coords = self.get_coordinates()?;
+ let box_xsize = box_coords.xsize();
+ let box_ysize = box_coords.ysize();
+ let box_top = box_coords.top().y();
+
+ let ratios = match &self.ratios {
+ Some(ratios) => ratios.clone(),
+ None => self.calculate_equal_ratios()?
+ };
+
+ let coords = ratios.iter().fold(Vec::<Coordinates>::new(), |mut coords, ratio| {
+ let ratio = *ratio as u16;
+ let len = coords.len();
+ let gap = if len == 0 { 0 } else { 1 };
+
+ let widget_xsize = box_xsize * ratio / 100;
+ let widget_xpos = if len == 0 {
+ box_coords.top().x()
+ } else {
+ let prev_coords = coords.last().unwrap();
+ let prev_xsize = prev_coords.xsize();
+ let prev_xpos = prev_coords.position().x();
+
+ prev_xsize + prev_xpos + gap
+ };
+
+ coords.push(Coordinates {
+ size: Size((widget_xsize,
+ box_ysize)),
+ position: Position((widget_xpos,
+ box_top))
+ });
+ coords
+ });
+
+ Ok(coords)
}
pub fn active_widget(&self) -> &T {
@@ -92,7 +123,7 @@ impl<T> Widget for HBox<T> where T: Widget + PartialEq {
}
fn refresh(&mut self) -> HResult<()> {
- self.resize_children();
+ self.resize_children().log();
for child in &mut self.widgets {
child.refresh()?
}
diff --git a/src/miller_columns.rs b/src/miller_columns.rs
index 3a240cb..ca621e4 100644
--- a/src/miller_columns.rs
+++ b/src/miller_columns.rs
@@ -1,8 +1,7 @@
use termion::event::Key;
use failure::Backtrace;
-use crate::coordinates::{Coordinates, Position, Size};
-use crate::preview::Previewer;
+use crate::coordinates::{Coordinates};
use crate::widget::{Widget, WidgetCore};
use crate::hbox::HBox;
use crate::fail::{HError, HResult, ErrorLog};
@@ -11,11 +10,6 @@ use crate::fail::{HError, HResult, ErrorLog};
pub struct MillerColumns<T> where T: Widget {
pub widgets: HBox<T>,
pub core: WidgetCore,
- // pub left: Option<T>,
- // pub main: Option<T>,
- //pub preview: AsyncPreviewer,
- pub preview: Previewer,
- pub ratio: (u16, u16, u16),
}
impl<T> MillerColumns<T>
@@ -26,8 +20,6 @@ where
MillerColumns {
widgets: HBox::new(core),
core: core.clone(),
- ratio: (20, 30, 50),
- preview: Previewer::new(core)
}
}
@@ -46,64 +38,45 @@ where
self.widgets.prepend_widget(widget);
}
- pub fn calculate_coordinates(&self) -> (Coordinates, Coordinates, Coordinates) {
- let coordinates = self.get_coordinates().unwrap();
- let xsize = coordinates.xsize();
- let ysize = coordinates.ysize();
- let top = coordinates.top().y();
- let ratio = self.ratio;
-
- let left_xsize = xsize * ratio.0 / 100;
- let left_size = Size((left_xsize, ysize));
- let left_pos = coordinates.top();
-
- let main_xsize = xsize * ratio.1 / 100;
- let main_size = Size((main_xsize, ysize));
- let main_pos = Position((left_xsize + 2, top));
-
- let preview_xsize = xsize * ratio.2 / 100;
- let preview_size = Size((preview_xsize - 1, ysize));
- let preview_pos = Position((left_xsize + main_xsize + 3, top));
-
- let left_coords = Coordinates {
- size: left_size,
- position: left_pos,
- };
-
- let main_coords = Coordinates {
- size: main_size,
- position: main_pos,
- };
-
- let preview_coords = Coordinates {
- size: preview_size,
- position: preview_pos,
- };
+ pub fn set_ratios(&mut self, ratios: Vec<usize>) {
+ self.widgets.set_ratios(ratios);
+ }
- (left_coords, main_coords, preview_coords)
+ pub fn calculate_coordinates(&self) -> HResult<Vec<Coordinates>> {
+ self.widgets.calculate_coordinates()
}
pub fn get_left_widget(&self) -> HResult<&T> {
let len = self.widgets.widgets.len();
- if len < 2 {
+ if len < 3 {
return Err(HError::NoWidgetError(Backtrace::new()));
}
- let widget = self.widgets.widgets.get(len - 2)?;
+ let widget = self.widgets.widgets.get(len - 3)?;
Ok(widget)
}
pub fn get_left_widget_mut(&mut self) -> HResult<&mut T> {
let len = self.widgets.widgets.len();
- if len < 2 {
+ if len < 3 {
return Err(HError::NoWidgetError(Backtrace::new()));
}
- let widget = self.widgets.widgets.get_mut(len - 2)?;
+ let widget = self.widgets.widgets.get_mut(len - 3)?;
Ok(widget)
}
pub fn get_main_widget(&self) -> HResult<&T> {
- let widget = self.widgets.widgets.last()?;
+ let len = self.widgets.widgets.len();
+ let widget = self.widgets.widgets.get(len-2)?;
Ok(widget)
}
pub fn get_main_widget_mut(&mut self) -> HResult<&mut T> {
+ let len = self.widgets.widgets.len();
+ let widget = self.widgets.widgets.get_mut(len-2)?;
+ Ok(widget)
+ }
+ pub fn get_right_widget(&self) -> HResult<&T> {
+ let widget = self.widgets.widgets.last()?;
+ Ok(widget)
+ }
+ pub fn get_right_widget_mut(&mut self) -> HResult<&mut T> {
let widget = self.widgets.widgets.last_mut()?;
Ok(widget)
}
@@ -121,29 +94,18 @@ where
Ok(&mut self.core)
}
fn refresh(&mut self) -> HResult<()> {
- let (left_coords, main_coords, preview_coords) = self.calculate_coordinates();
-
- if let Ok(left_widget) = self.get_left_widget_mut() {
- left_widget.set_coordinates(&left_coords).log();
- }
-
- if let Ok(main_widget) = self.get_main_widget_mut() {
- main_widget.set_coordinates(&main_coords).log();
- }
-
- let preview_widget = &mut self.preview;
- preview_widget.set_coordinates(&preview_coords)?;
+ self.widgets.refresh().log();
Ok(())
}
fn get_drawlist(&self) -> HResult<String> {
let left_widget = self.get_left_widget()?;
let main_widget = self.get_main_widget()?;