diff options
author | Jeff Zhao <jeff.no.zhao@gmail.com> | 2021-06-22 22:34:42 -0400 |
---|---|---|
committer | Jeff Zhao <jeff.no.zhao@gmail.com> | 2021-06-22 22:34:42 -0400 |
commit | a11ed197df4fc3830387931c684346975333baf3 (patch) | |
tree | c11b81c58ff0ac52415684e1e383ebac92b94696 /src/ui | |
parent | 72aaf0c5d10db0004d48e27c58d18d8f2c568f8f (diff) |
rudimentary file preview support
- this currently has only been tested with text files
- no line formatting is done yet
- only prints the preview as a single line
- folder previews can now be pushed onto a separate thread if needed
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/tui_backend.rs | 52 | ||||
-rw-r--r-- | src/ui/views/tui_folder_view.rs | 44 | ||||
-rw-r--r-- | src/ui/widgets/mod.rs | 2 | ||||
-rw-r--r-- | src/ui/widgets/tui_file_preview.rs | 35 |
4 files changed, 119 insertions, 14 deletions
diff --git a/src/ui/tui_backend.rs b/src/ui/tui_backend.rs index f04450d..cf32c01 100644 --- a/src/ui/tui_backend.rs +++ b/src/ui/tui_backend.rs @@ -4,11 +4,14 @@ use std::io::Write; use termion::raw::{IntoRawMode, RawTerminal}; use termion::screen::AlternateScreen; use tui::backend::TermionBackend; -use tui::widgets::Widget; +use tui::layout::{Constraint, Direction, Layout, Rect}; +use tui::widgets::{Block, Borders, Widget}; #[cfg(feature = "mouse")] use termion::input::MouseTerminal; +use crate::util::display::DisplayOption; + trait New { fn new() -> std::io::Result<Self> where @@ -81,3 +84,50 @@ impl TuiBackend { Ok(()) } } + +pub fn build_layout( + area: Rect, + constraints: &[Constraint; 3], + display_options: &DisplayOption, +) -> Vec<Rect> { + let layout_rect = if display_options.show_borders() { + let area = Rect { + y: area.top() + 1, + height: area.height - 2, + ..area + }; + + let block = Block::default().borders(Borders::ALL); + let inner = block.inner(area); + + let layout_rect = Layout::default() + .direction(Direction::Horizontal) + .constraints(constraints.as_ref()) + .split(inner); + + let block = Block::default().borders(Borders::RIGHT); + let inner1 = block.inner(layout_rect[0]); + + let block = Block::default().borders(Borders::LEFT); + let inner3 = block.inner(layout_rect[2]); + + vec![inner1, layout_rect[1], inner3] + } else { + let mut layout_rect = Layout::default() + .direction(Direction::Horizontal) + .vertical_margin(1) + .constraints(constraints.as_ref()) + .split(area); + + layout_rect[0] = Rect { + width: layout_rect[0].width - 1, + ..layout_rect[0] + }; + layout_rect[1] = Rect { + width: layout_rect[1].width - 1, + ..layout_rect[1] + }; + layout_rect + }; + layout_rect +} diff --git a/src/ui/views/tui_folder_view.rs b/src/ui/views/tui_folder_view.rs index be3909a..e391473 100644 --- a/src/ui/views/tui_folder_view.rs +++ b/src/ui/views/tui_folder_view.rs @@ -6,7 +6,10 @@ use tui::text::Span; use tui::widgets::{Block, Borders, Paragraph, Widget, Wrap}; use crate::context::AppContext; -use crate::ui::widgets::{TuiDirList, TuiDirListDetailed, TuiFooter, TuiTabBar, TuiTopBar}; +use crate::ui; +use crate::ui::widgets::{ + TuiDirList, TuiDirListDetailed, TuiFilePreview, TuiFooter, TuiTabBar, TuiTopBar, +}; const TAB_VIEW_WIDTH: u16 = 15; @@ -26,22 +29,33 @@ impl<'a> TuiFolderView<'a> { impl<'a> Widget for TuiFolderView<'a> { fn render(self, area: Rect, buf: &mut Buffer) { + let preview_context = self.context.preview_context_ref(); let curr_tab = self.context.tab_context_ref().curr_tab_ref(); let curr_list = curr_tab.curr_list_ref(); let parent_list = curr_tab.parent_list_ref(); let child_list = curr_tab.child_list_ref(); + let curr_entry = curr_list.and_then(|c| c.curr_entry_ref()); + let config = self.context.config_ref(); + let display_options = config.display_options_ref(); - let constraints: &[Constraint; 3] = if !config.display_options_ref().collapse_preview() { - &config.display_options_ref().default_layout - } else { - match child_list { - Some(_) => &config.display_options_ref().default_layout, - None => &config.display_options_ref().no_preview_layout, - } - }; + let (default_layout, constraints): (bool, &[Constraint; 3]) = + if !display_options.collapse_preview() { + (true, &display_options.default_layout) + } else { + match child_list { + Some(_) => (true, &display_options.default_layout), + None => match curr_entry { + None => (false, &display_options.no_preview_layout), + Some(e) => match preview_context.get_preview(e.file_path()) { + Some(_) => (true, &display_options.default_layout), + None => (false, &display_options.no_preview_layout), + }, + }, + } + }; let layout_rect = if config.display_options_ref().show_borders() { let area = Rect { @@ -73,7 +87,7 @@ impl<'a> Widget for TuiFolderView<'a> { }; intersections.render_left(buf); - if child_list.as_ref().is_some() { + if default_layout { intersections.render_right(buf); } } @@ -108,7 +122,7 @@ impl<'a> Widget for TuiFolderView<'a> { // render parent view if let Some(list) = parent_list.as_ref() { TuiDirList::new(&list).render(layout_rect[0], buf); - }; + } // render current view if let Some(list) = curr_list.as_ref() { @@ -137,12 +151,16 @@ impl<'a> Widget for TuiFolderView<'a> { TuiFooter::new(list).render(rect, buf); } } - }; + } // render preview if let Some(list) = child_list.as_ref() { TuiDirList::new(&list).render(layout_rect[2], buf); - }; + } else if let Some(entry) = curr_entry { + if let Some(preview) = preview_context.get_preview(entry.file_path()) { + TuiFilePreview::new(entry, preview).render(layout_rect[2], buf); + } + } let topbar_width = area.width; let rect = Rect { diff --git a/src/ui/widgets/mod.rs b/src/ui/widgets/mod.rs index 451ccdb..6319d91 100644 --- a/src/ui/widgets/mod.rs +++ b/src/ui/widgets/mod.rs @@ -1,5 +1,6 @@ mod tui_dirlist; mod tui_dirlist_detailed; +mod tui_file_preview; mod tui_footer; mod tui_menu; mod tui_prompt; @@ -10,6 +11,7 @@ mod tui_worker; pub use self::tui_dirlist::TuiDirList; pub use self::tui_dirlist_detailed::{trim_file_label, TuiDirListDetailed}; +pub use self::tui_file_preview::TuiFilePreview; pub use self::tui_footer::TuiFooter; pub use self::tui_menu::TuiMenu; pub use self::tui_prompt::TuiPrompt; diff --git a/src/ui/widgets/tui_file_preview.rs b/src/ui/widgets/tui_file_preview.rs new file mode 100644 index 0000000..f731a0e --- /dev/null +++ b/src/ui/widgets/tui_file_preview.rs @@ -0,0 +1,35 @@ +use std::process; + +use tui::buffer::Buffer; +use tui::layout::Rect; +use tui::style::{Color, Modifier, Style}; +use tui::widgets::Widget; + +use crate::fs::JoshutoDirEntry; +use crate::preview::preview_file::FilePreview; +use crate::util::format; +use crate::util::string::UnicodeTruncate; +use crate::util::style; +use unicode_width::UnicodeWidthStr; + +const MIN_LEFT_LABEL_WIDTH: i32 = 15; + +const ELLIPSIS: &str = "…"; + +pub struct TuiFilePreview<'a> { + entry: &'a JoshutoDirEntry, + preview: &'a FilePreview, +} + +impl<'a> TuiFilePreview<'a> { + pub fn new(entry: &'a JoshutoDirEntry, preview: &'a FilePreview) -> Self { + Self { entry, preview } + } +} + +impl<'a> Widget for TuiFilePreview<'a> { + fn render(self, area: Rect, buf: &mut Buffer) { + let style = Style::default(); + buf.set_string(area.x, area.y, self.preview.output.as_str(), style); + } +} |