diff options
-rw-r--r-- | src/coordinates.rs | 59 | ||||
-rw-r--r-- | src/file_browser.rs | 99 | ||||
-rw-r--r-- | src/hbox.rs | 28 | ||||
-rw-r--r-- | src/listview.rs | 50 | ||||
-rw-r--r-- | src/main.rs | 74 | ||||
-rw-r--r-- | src/miller_columns.rs | 195 | ||||
-rw-r--r-- | src/widget.rs | 12 | ||||
-rw-r--r-- | src/window.rs | 1 |
8 files changed, 468 insertions, 50 deletions
diff --git a/src/coordinates.rs b/src/coordinates.rs new file mode 100644 index 0000000..5506b4d --- /dev/null +++ b/src/coordinates.rs @@ -0,0 +1,59 @@ +#[derive(Debug,Clone)] +pub struct Size(pub (u16,u16)); +#[derive(Debug,Clone)] +pub struct Position(pub (u16,u16)); + + +#[derive(Debug,Clone)] +pub struct Coordinates { + pub size: Size, + pub position: Position, +} + +impl Coordinates { + pub fn size(&self) -> &Size { + &self.size + } + + pub fn xsize(&self) -> u16 { + self.size.xsize() + } + + pub fn ysize(&self) -> u16 { + self.size.ysize() + } + + pub fn position(&self) -> &Position { + &self.position + } + + pub fn top(&self) -> Position { + self.position().clone() + } + +// pub fn left(&self) -> / +} + +impl Size { + pub fn size(&self) -> (u16,u16) { + self.0 + } + pub fn xsize(&self) -> u16 { + (self.0).0 + } + pub fn ysize(&self) -> u16 { + (self.0).1 + } +} + +impl Position { + pub fn position(&self) -> (u16,u16) { + self.0 + } + pub fn x(&self) -> u16 { + (self.0).1 + } + pub fn y(&self) -> u16 { + (self.0).1 + } +} diff --git a/src/file_browser.rs b/src/file_browser.rs new file mode 100644 index 0000000..e021dd9 --- /dev/null +++ b/src/file_browser.rs @@ -0,0 +1,99 @@ +use termion::event::{Key,Event}; + + +use crate::widget::Widget; +use crate::files::Files; +//use crate::hbox::HBox; +use crate::listview::ListView; +use crate::coordinates::{Coordinates, Size,Position}; +use crate::files::File; +use crate::miller_columns::MillerColumns; + +pub struct FileBrowser { + pub columns: MillerColumns<ListView<Files>>, +} + +impl FileBrowser { + pub fn set_left_directory(&mut self) { + + } +} + + +impl Widget for FileBrowser { + fn render(&self) -> Vec<String> { + vec![] + } + fn get_size(&self) -> &Size { + &self.columns.get_size() + } + fn get_position(&self) -> &Position { + &self.columns.get_position() + } + fn set_size(&mut self, size: Size) { + self.columns.set_size(size); + } + fn set_position(&mut self, position: Position) { + self.columns.set_position(position); + } + fn render_header(&self) -> String { + "".to_string() + } + fn refresh(&mut self) { + self.columns.refresh(); + } + + fn get_drawlist(&self) -> String { + self.columns.get_drawlist() + // let view_count = self.columns.widgets.len(); + + // if view_count < 2 { + // // TODO: Special handling + // } else if view_count < 1 { + // // etc. + // } + + // self.views + // .iter() + // .skip(view_count - 2) + // .map(|view| { + // eprintln!("{}", view.get_drawlist()); + // view.get_drawlist() + // }).collect() + } + + + fn on_key(&mut self, key: Key) { + match key { + Key::Right => { + match self.columns.get_main_widget() { + Some(widget) => { + let path = widget.selected_file().path(); + let files = Files::new_from_path(&path).unwrap(); + let view = ListView::new(files); + self.columns.widgets.push(view); + self.refresh(); + }, None => { } + } + }, + Key::Left => { + if self.columns.get_left_widget().is_some() { + self.columns.widgets.pop(); + } + } + + _ => { + match self.columns.get_main_widget_mut() { + Some(widget) => { + widget.on_key(key); + self.set_left_directory(); + self.refresh(); + }, None => { self.refresh(); } + + } + //_ => { self.bad(Event::Key(key)); } + } + } + } +} + diff --git a/src/hbox.rs b/src/hbox.rs index 3cd8f53..330bb0e 100644 --- a/src/hbox.rs +++ b/src/hbox.rs @@ -1,6 +1,7 @@ use termion::event::{Event}; use crate::widget::Widget; +use crate::coordinates::{Coordinates, Size, Position}; // pub struct Child<T> { // widget: T, @@ -12,6 +13,7 @@ use crate::widget::Widget; pub struct HBox { dimensions: (u16, u16), position: (u16, u16), + coordinates: Coordinates, children: Vec<Box<Widget>>, active: usize } @@ -20,10 +22,14 @@ pub struct HBox { impl HBox { pub fn new(widgets: Vec<Box<Widget>>, dimensions: (u16, u16), + coordinates: Coordinates, position: (u16, u16), main: usize) -> HBox { let mut hbox = HBox { dimensions: dimensions, + coordinates: Coordinates { size: Size (dimensions), + position: Position (position), + parent: None }, position: position, children: widgets, active: main @@ -40,7 +46,7 @@ impl HBox { let mut current_pos = dbg!(hbox_position.1); for widget in &mut self.children { - widget.set_dimensions(dbg!((cell_size, hbox_size.1))); + widget.set_size(Size ( (cell_size, hbox_size.1)) ); widget.set_position(dbg!((current_pos, hbox_position.1))); widget.refresh(); dbg!(current_pos += cell_size); @@ -76,23 +82,23 @@ impl Widget for HBox { } } - fn get_drawlist(&mut self) -> String { - self.children.iter_mut().map(|child| { + fn get_drawlist(&self) -> String { + self.children.iter().map(|child| { child.get_drawlist() }).collect() } - fn get_dimensions(&self) -> (u16, u16) { - self.dimensions + fn get_size(&self) -> Size { + Size( self.dimensions ) } - fn get_position(&self) -> (u16, u16) { - self.position + fn get_position(&self) -> Position { + Position ( self.position ) } - fn set_dimensions(&mut self, size: (u16, u16)) { - self.dimensions = size; + fn set_size(&mut self, size: Size) { + self.dimensions = size.0; } - fn set_position(&mut self, position: (u16, u16)) { - self.position = position; + fn set_position(&mut self, position: Position) { + self.position = position.0; } diff --git a/src/listview.rs b/src/listview.rs index bd8f3a3..c6d200a 100644 --- a/src/listview.rs +++ b/src/listview.rs @@ -6,6 +6,7 @@ use std::path::{Path, PathBuf}; use crate::term; use crate::files::{File, Files}; use crate::widget::Widget; +use crate::coordinates::{Coordinates,Size,Position}; // Maybe also buffer drawlist for efficiency when it doesn't change every draw @@ -14,8 +15,9 @@ pub struct ListView<T> { selection: usize, offset: usize, buffer: Vec<String>, - dimensions: (u16, u16), - position: (u16, u16), + // dimensions: (u16, u16), + // position: (u16, u16), + coordinates: Coordinates, } impl<T: 'static> ListView<T> where ListView<T>: Widget { @@ -25,8 +27,10 @@ impl<T: 'static> ListView<T> where ListView<T>: Widget { selection: 0, offset: 0, buffer: Vec::new(), - dimensions: (1,1), - position: (1,1) + coordinates: Coordinates { size: Size ((1,1)), + position: Position((1,1)) } + // dimensions: (1,1), + // position: (1,1) }; view } @@ -48,7 +52,7 @@ impl<T: 'static> ListView<T> where ListView<T>: Widget { } fn move_down(&mut self) { let lines = self.buffer.len(); - let y_size = self.dimensions.1 as usize; + let y_size = self.coordinates.ysize() as usize; if self.selection == lines - 1 { return; @@ -63,7 +67,7 @@ impl<T: 'static> ListView<T> where ListView<T>: Widget { } fn set_selection(&mut self, position: usize) { - let ysize = self.dimensions.1 as usize; + let ysize = self.coordinates.ysize() as usize; let mut offset = 0; while position + 1 > ysize + offset { offset += 1 } @@ -76,7 +80,7 @@ impl<T: 'static> ListView<T> where ListView<T>: Widget { let name = &file.name; let (size, unit) = file.calculate_size(); - let (xsize, _) = self.get_dimensions(); + let xsize = self.get_size().xsize(); let sized_string = term::sized_string(&name, xsize); let padding = xsize - sized_string.width() as u16; let styled_string = match &file.style { @@ -105,23 +109,23 @@ impl ListView<Files> where Files: std::ops::Index<usize, Output=File>, Files: std::marker::Sized { - fn selected_file(&self) -> &File { + pub fn selected_file(&self) -> &File { let selection = self.selection; let file = &self.content[selection]; file } - fn clone_selected_file(&self) -> File { + pub fn clone_selected_file(&self) -> File { let selection = self.selection; let file = self.content[selection].clone(); file } - fn grand_parent(&self) -> Option<PathBuf> { + pub fn grand_parent(&self) -> Option<PathBuf> { self.selected_file().grand_parent() } - fn goto_grand_parent(&mut self) { + pub fn goto_grand_parent(&mut self) { match self.grand_parent() { Some(grand_parent) => self.goto_path(&grand_parent), None => self.show_status("Can't go further!") @@ -134,7 +138,7 @@ impl ListView<Files> where self.goto_path(&path); } - fn goto_path(&mut self, path: &Path) { + pub fn goto_path(&mut self, path: &Path) { match crate::files::Files::new_from_path(path){ Ok(files) => { self.content = files; @@ -198,17 +202,17 @@ impl ListView<Files> where impl Widget for ListView<Files> { - fn get_dimensions(&self) -> (u16, u16) { - self.dimensions + fn get_size(&self) -> &Size { + &self.coordinates.size } - fn get_position(&self) -> (u16, u16) { - self.position + fn get_position(&self) -> &Position { + &self.coordinates.position } - fn set_dimensions(&mut self, size: (u16, u16)) { - self.dimensions = size; + fn set_size(&mut self, size: Size) { + self.coordinates.size = size; } - fn set_position(&mut self, position: (u16, u16)) { - self.position = position; + fn set_position(&mut self, position: Position) { + self.coordinates.position = position; } fn refresh(&mut self) { self.buffer = self.render(); @@ -222,10 +226,10 @@ impl Widget for ListView<Files> { }).collect() } - fn get_drawlist(&mut self) -> String { + fn get_drawlist(&self) -> String { let mut output = term::reset(); - let (xsize, ysize) = self.dimensions; - let (xpos, ypos) = self.position; + let (xsize, ysize) = self.coordinates.size().size(); + let (xpos, ypos) = self.coordinates.position().position(); output += &term::reset(); diff --git a/src/main.rs b/src/main.rs index 4a79322..b6a2321 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,30 +19,82 @@ mod listview; mod files; mod win_main; mod widget; -mod hbox; +//mod hbox; +mod miller_columns; +mod coordinates; use listview::ListView; use window::Window; -use hbox::HBox; - +//use hbox::HBox; +use miller_columns::MillerColumns; +use widget::Widget; +use coordinates::{Coordinates,Size,Position}; +mod file_browser; +use file_browser::FileBrowser; fn main() { // Need to do this here to actually turn terminal into raw mode... let mut _screen = AlternateScreen::from(Box::new(stdout())); let mut _stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap()); - let files = files::get_files("/home/project/code").unwrap(); - let listview = ListView::new(files, (50,50), (10,10)); + let (xsize, ysize) = term::size(); + let ysize = ysize - 1; + + let coordinates = Coordinates { size: Size ((xsize, ysize - 1)) , + position: Position( (1, 2 )) }; + + + let files = files::Files::new_from_path("/home/project/").unwrap(); + let mut listview = ListView::new(files); + + let files = files::Files::new_from_path("/home/project/Downloads/").unwrap(); + let mut listview2 = ListView::new(files); + + let files = files::Files::new_from_path("/home/").unwrap(); + let mut listview3 = ListView::new(files); + + // let files = files::Files::new_from_path("/").unwrap(); + // let mut listview4 = ListView::new(files); + + // listview.set_size( Size ((20,30))); + // listview.set_position(Position((160,1))); + + // listview2.set_size( Size ((20,30))); + // listview2.set_position(Position((160,1))); + + // listview3.set_size( Size ((20,30))); + // listview3.set_position(Position((160,1))); + + // listview4.set_size( Size ((20,30))); + // listview4.set_position(Position((160,1))); + + + // listview2.set_dimensions((95,53)); + // listview2.set_position((95,1)); + + // let boxed = vec![listview.to_trait(), listview2.to_trait()]; + + // let hbox = HBox::new(boxed, (xsize, ysize-1), (1,2) , 0); + + + + let mut miller + = MillerColumns::new(vec![listview3,listview,listview2], + coordinates, + (33, 33, 33)); - let files = files::get_files("/home/project/code").unwrap(); - let listview2 = ListView::new(files, (50,50), (80,10)); + // miller.main = Some(listview2); + // miller.left = Some(listview3); + // miller.preview = Some(listview4); - let boxed = vec![listview.to_trait(), listview2.to_trait()]; + let coords = dbg!(miller.calculate_coordinates()); - let hbox = HBox::new(boxed); - let mut win = Window::new(hbox); + miller.refresh(); + let filebrowser = crate::file_browser::FileBrowser { columns: miller }; + + let mut win = Window::new(filebrowser); win.handle_input(); write!(_stdout, "{}", termion::cursor::Show).unwrap(); -} + } diff --git a/src/miller_columns.rs b/src/miller_columns.rs new file mode 100644 index 0000000..fce25ac --- /dev/null +++ b/src/miller_columns.rs @@ -0,0 +1,195 @@ +use termion::event::{Key,Event}; + + +use crate::widget::Widget; +use crate::files::Files; +//use crate::hbox::HBox; +use crate::listview::ListView; +use crate::coordinates::{Coordinates, Size,Position}; +use crate::files::File; + +pub struct MillerColumns<T> { + pub widgets: Vec<T>, + // pub left: Option<T>, + // pub main: Option<T>, + // pub preview: Option<T>, + ratio: (u16,u16,u16), + coordinates: Coordinates, +} + + + + + +impl<T> MillerColumns<T> where T: Widget { + pub fn new(widgets: Vec<T>, + coordinates: Coordinates, + ratio: (u16, u16, u16)) + -> Self { Self { widgets: widgets, + coordinates: coordinates, + ratio: ratio } } + + + pub fn push_widget(&mut self, widget: T) { + + } + + pub fn calculate_coordinates(&self) -> (Coordinates, Coordinates, Coordinates) { + let xsize = self.coordinates.xsize(); + let ysize = self.coordinates.ysize(); + let top = self.coordinates.top().x(); + let ratio = self.ratio; + + let left_xsize = xsize * ratio.0 / 100; + let left_size = Size ((left_xsize, ysize)); + let left_pos = self.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, ysize) ); + let preview_pos = Position ( (left_xsize + main_xsize + 2, 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 }; + + + (left_coords, main_coords, preview_coords) + } + + pub fn get_left_widget(&self) -> Option<&T> { + let len = self.widgets.len(); + self.widgets.get(len-2) + } + pub fn get_left_widget_mut(&mut self) -> Option<&mut T> { + let len = self.widgets.len(); + dbg!((self.widgets[len-2]).get_position()); + Some(&mut self.widgets[len-2]) + } + pub fn get_main_widget(&self) -> Option<&T> { + self.widgets.last() + } + pub fn get_main_widget_mut(&mut self) -> Option<&mut T> { + self.widgets.last_mut() + } + + +} + +impl<T> Widget for MillerColumns<T> where T: Widget { + fn render(&self) -> Vec<String> { + vec![] + } + fn get_size(&self) -> &Size { + &self.coordinates.size + } + fn get_position(&self) -> &Position { + &self.coordinates.position + } + fn set_size(&mut self, size: Size) { + self.coordinates.size = size; + } + fn set_position(&mut self, position: Position) { + self.coordinates.position = position; + } + fn render_header(&self) -> String { + "".to_string() + } + fn refresh(&mut self) { + let (left_coords, main_coords, preview_coords) = self.calculate_coordinates(); + + // self.left.as_mut().unwrap().set_size(left_coords.size); + // self.left.as_mut().unwrap().set_position(left_coords.position); + + // self.get_main_widget_mut().map(|widget| { + // widget.set_size(main_coords.size); + // widget.set_position(main_coords.position); + // }); + + + let (left_coords, main_coords, preview_coords) = self.calculate_coordinates(); + + let widget2 = self.get_left_widget_mut().unwrap(); + widget2.set_size( left_coords.size ); + widget2.set_position( left_coords.position ); + widget2.refresh(); + + + let widget = self.get_main_widget_mut().unwrap(); + widget.set_size(main_coords.size); + widget.set_position(main_coords.position); + widget.refresh(); + + + // self.main.as_mut().unwrap().set_size(main_coords.size); + // self.main.as_mut().unwrap().set_position(main_coords.position); + + // self.preview.as_mut().unwrap().set_size(preview_coords.size); + // self.preview.as_mut().unwrap().set_position(preview_coords.position); + + // self.left.as_mut().unwrap().refresh(); + // self.main.as_mut().unwrap().refresh(); + // self.preview.as_mut().unwrap().refresh() + } + + fn get_drawlist(&self) -> String { + let left_widget = self.get_left_widget().unwrap().get_drawlist(); + let main_widget = self.get_main_widget().unwrap().get_drawlist(); + format!("{}{}", main_widget, left_widget) + // let left_drawlist = &self.left.as_ref().unwrap().get_drawlist(); + // let main_drawlist = &self.main.as_ref().unwrap().get_drawlist(); + // let preview_drawlist = &self.preview.as_ref().unwrap().get_drawlist(); + + // format!("{}{}{}", left_drawlist, &main_drawlist, &preview_drawlist) + // let main_widget_drawlist = self.get_main_widget().map(|widget| { + + // widget.get_drawlist() + // }); + + + // match main_widget_drawlist { + // Some(drawlist) => { drawlist }, + // None => "Can't draw this".to_string() + // } + + } + + fn on_key(&mut self, key: Key) { + match key { + _ => { + self.refresh(); + self.get_main_widget_mut().unwrap().on_key(key); + //self.set_left_directory(); + self.refresh(); + }, + //_ => { self.bad(Event::Key(key)); } + } + } +// } + +// impl MillerColumns<ListView<Files>> +// { + // pub fn godir(&mut self) -> Result<(),Box<dyn std::error::Error>> { + // let current_dir = self.widgets.iter().last().unwrap(); + // let selected_path = ¤t_dir.selected_file().path; + // let files = Files::new_from_path(selected_path)?; + // let dir_list = ListView::new(files); + // Ok(()) + // } + // fn set_left_directory(&mut self, dir: File) { + // let parent_dir = self.main.as_ref().unwrap().grand_parent().unwrap(); + // self.left.as_mut().unwrap().goto_path(&parent_dir); + // } +} + diff --git a/src/widget.rs b/src/widget.rs index 2cbdbaf..7fc319c 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -1,12 +1,14 @@ use termion::event::{Key, MouseEvent, Event}; +use crate::coordinates::{Coordinates, Size, Position}; + pub trait Widget { fn render(&self) -> Vec<String>; - fn get_dimensions(&self) -> (u16, u16); - fn get_position(&self) -> (u16, u16); - fn set_dimensions(&mut self, size: (u16, u16)); - fn set_position(&mut self, position: (u16, u16)); + fn get_size(&self) -> &Size; + fn get_position(&self) -> &Position; + fn set_size(&mut self, size: Size); + fn set_position(&mut self, position: Position); fn render_header(&self) -> String; @@ -77,5 +79,5 @@ pub trait Widget { //fn get_buffer(&self) -> &Vec<String>; fn refresh(&mut self); - fn get_drawlist(&mut self) -> String; + fn get_drawlist(&self) -> String; } diff --git a/src/window.rs b/src/window.rs index b0a1974..8c21b7e 100644 --- a/src/window.rs +++ b/src/window.rs @@ -68,6 +68,7 @@ where self.draw(); let event = event.unwrap(); self.widget.on_event(event); + self.widget.refresh(); self.draw(); } } |