summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorJeff Zhao <jeff.no.zhao@gmail.com>2021-06-22 22:34:42 -0400
committerJeff Zhao <jeff.no.zhao@gmail.com>2021-06-22 22:34:42 -0400
commita11ed197df4fc3830387931c684346975333baf3 (patch)
treec11b81c58ff0ac52415684e1e383ebac92b94696 /src/ui
parent72aaf0c5d10db0004d48e27c58d18d8f2c568f8f (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.rs52
-rw-r--r--src/ui/views/tui_folder_view.rs44
-rw-r--r--src/ui/widgets/mod.rs2
-rw-r--r--src/ui/widgets/tui_file_preview.rs35
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);
+ }
+}