From 35b36cfe5e2053a53656d3e1b4ba54a10d1a1618 Mon Sep 17 00:00:00 2001 From: Jeff Zhao Date: Mon, 5 Sep 2022 17:00:01 -0400 Subject: move border rendering out of folder view --- src/context/app_context.rs | 9 +- src/context/mod.rs | 2 + src/context/ui_context.rs | 6 ++ src/ui/views/tui_folder_view.rs | 200 +++++++++++++++++++++++----------------- 4 files changed, 125 insertions(+), 92 deletions(-) create mode 100644 src/context/ui_context.rs (limited to 'src') diff --git a/src/context/app_context.rs b/src/context/app_context.rs index 66ffbc6..4f605ce 100644 --- a/src/context/app_context.rs +++ b/src/context/app_context.rs @@ -2,12 +2,12 @@ use std::collections::HashSet; use std::process; use std::sync::mpsc; use std::thread; -use tui::layout::Rect; use crate::commands::quit::QuitAction; use crate::config; use crate::context::{ - CommandLineContext, LocalStateContext, MessageQueue, PreviewContext, TabContext, WorkerContext, + CommandLineContext, LocalStateContext, MessageQueue, PreviewContext, TabContext, UiContext, + WorkerContext, }; use crate::event::{AppEvent, Events}; use crate::ui::views; @@ -17,11 +17,6 @@ use crate::Args; use notify::{RecursiveMode, Watcher}; use std::path; -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct UiContext { - pub layout: Vec, -} - pub struct AppContext { pub quit: QuitAction, // event loop querying diff --git a/src/context/mod.rs b/src/context/mod.rs index 884c492..ac6c445 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -4,6 +4,7 @@ mod local_state; mod message_queue; mod preview_context; mod tab_context; +mod ui_context; mod worker_context; pub use self::app_context::*; @@ -12,4 +13,5 @@ pub use self::local_state::*; pub use self::message_queue::*; pub use self::preview_context::*; pub use self::tab_context::*; +pub use self::ui_context::*; pub use self::worker_context::*; diff --git a/src/context/ui_context.rs b/src/context/ui_context.rs new file mode 100644 index 0000000..c5a8006 --- /dev/null +++ b/src/context/ui_context.rs @@ -0,0 +1,6 @@ +use tui::layout::Rect; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct UiContext { + pub layout: Vec, +} diff --git a/src/ui/views/tui_folder_view.rs b/src/ui/views/tui_folder_view.rs index 10f16c7..260c8fa 100644 --- a/src/ui/views/tui_folder_view.rs +++ b/src/ui/views/tui_folder_view.rs @@ -15,6 +15,62 @@ use crate::ui::widgets::{ }; use crate::ui::PreviewArea; +struct TuiFolderViewBorders<'a> { + pub constraints: &'a [Constraint; 3], +} + +impl<'a> TuiFolderViewBorders<'a> { + pub fn new(constraints: &'a [Constraint; 3]) -> Self { + Self { constraints } + } +} + +impl<'a> Widget for TuiFolderViewBorders<'a> { + fn render(self, area: Rect, buf: &mut Buffer) { + let block = Block::default().borders(Borders::ALL); + let inner = block.inner(area); + block.render(area, buf); + + let layout_rect = Layout::default() + .direction(Direction::Horizontal) + .constraints(self.constraints.as_ref()) + .split(inner); + + // Won't render intersections if parent view is turned off + match self.constraints[0] { + Constraint::Ratio(0, _) => {} + _ => { + let block = Block::default().borders(Borders::RIGHT); + block.render(layout_rect[0], buf); + } + } + let block = Block::default().borders(Borders::LEFT); + block.render(layout_rect[2], buf); + + let top = area.top(); + let bottom = area.bottom() - 1; + let left = layout_rect[1].left() - 1; + let right = layout_rect[2].left(); + let intersections = Intersections { + top, + bottom, + left, + right, + }; + + // Won't render intersections if parent view is turned off + match self.constraints[0] { + Constraint::Ratio(0, _) => (), + _ => intersections.render_left(buf), + } + // Won't render intersections if child preview is unavailable + match self.constraints[2] { + Constraint::Ratio(0, _) => (), + _ => intersections.render_right(buf), + } + } +} + pub struct TuiFolderView<'a> { pub context: &'a AppContext, pub show_bottom_status: bool, @@ -27,10 +83,57 @@ impl<'a> TuiFolderView<'a> { show_bottom_status: true, } } + + pub fn folder_area(area: &Rect) -> Rect { + Rect { + y: area.top() + 1, + height: area.bottom() - 2, + ..area.clone() + } + } + + pub fn header_area(area: &Rect) -> Rect { + Rect { + x: area.left(), + y: area.top(), + width: area.width, + height: 1, + } + } + + pub fn footer_area(area: &Rect) -> Rect { + Rect { + x: area.x, + y: area.bottom() - 1, + width: area.width, + height: 1, + } + } + + pub fn tab_area(&self, area: &Rect, num_tabs: usize) -> Rect { + // render tabs + let tab_width = (num_tabs * 5) as u16; + let tab_width = if tab_width > area.width { + area.width + } else { + tab_width + }; + let topbar_x = area.width.saturating_sub(tab_width); + + Rect { + x: topbar_x, + y: area.top(), + width: tab_width, + height: 1, + } + } } impl<'a> Widget for TuiFolderView<'a> { fn render(self, area: Rect, buf: &mut Buffer) { + let config = self.context.config_ref(); + let display_options = config.display_options_ref(); + let preview_context = self.context.preview_context_ref(); let curr_tab = self.context.tab_context_ref().curr_tab_ref(); let curr_tab_cwd = curr_tab.cwd(); @@ -40,71 +143,22 @@ impl<'a> Widget for TuiFolderView<'a> { 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 = get_constraints(self.context); - let is_default_layout = constraints == &display_options.default_layout; let layout_rect = if display_options.show_borders() { - let area = Rect { - y: area.top() + 1, - height: area.height - 2, - ..area - }; + let area = Self::folder_area(&area); + TuiFolderViewBorders::new(constraints).render(area, buf); let layout = calculate_layout_with_borders(area, constraints); - - let block = Block::default().borders(Borders::ALL); - let inner = block.inner(area); - block.render(area, buf); - - let layout_rect = Layout::default() - .direction(Direction::Horizontal) - .constraints(constraints.as_ref()) - .split(inner); - - let block = Block::default().borders(Borders::RIGHT); - block.render(layout_rect[0], buf); - - let block = Block::default().borders(Borders::LEFT); - block.render(layout_rect[2], buf); - - // Render inner borders properly. - { - let top = area.top(); - let bottom = area.bottom() - 1; - let left = layout_rect[1].left() - 1; - let right = layout_rect[2].left(); - let intersections = Intersections { - top, - bottom, - left, - right, - }; - - // Won't render intersections if parent view is turned off - match constraints[0] { - Constraint::Ratio(0, _) => (), - _ => intersections.render_left(buf), - } - if is_default_layout { - intersections.render_right(buf); - } - } layout } else { - let area = Rect { - y: area.top() + 1, - height: area.height - 2, - ..area - }; + let area = Self::folder_area(&area); calculate_layout(area, constraints) }; // render parent view match constraints[0] { - Constraint::Ratio(0, _) => (), + Constraint::Ratio(0, _) => {} _ => { if let Some(list) = curr_tab.parent_list_ref().as_ref() { TuiDirList::new(list, true).render(layout_rect[0], buf); @@ -115,13 +169,8 @@ impl<'a> Widget for TuiFolderView<'a> { // render current view if let Some(list) = curr_list.as_ref() { TuiDirListDetailed::new(list, display_options, true).render(layout_rect[1], buf); - let rect = Rect { - x: 0, - y: area.height - 1, - width: area.width, - height: 1, - }; + let footer_area = Self::footer_area(&area); if self.show_bottom_status { /* draw the bottom status bar */ if let Some(msg) = self.context.worker_context_ref().get_msg() { @@ -129,14 +178,14 @@ impl<'a> Widget for TuiFolderView<'a> { let text = Span::styled(msg, message_style); Paragraph::new(text) .wrap(Wrap { trim: true }) - .render(rect, buf); + .render(footer_area, buf); } else if let Some(msg) = self.context.message_queue_ref().current_message() { let text = Span::styled(msg.content.as_str(), msg.style); Paragraph::new(text) .wrap(Wrap { trim: true }) - .render(rect, buf); + .render(footer_area, buf); } else { - TuiFooter::new(list).render(rect, buf); + TuiFooter::new(list).render(footer_area, buf); } } } else { @@ -186,35 +235,16 @@ impl<'a> Widget for TuiFolderView<'a> { .render(layout_rect[2], buf); } - let topbar_width = area.width; - let rect = Rect { - x: 0, - y: 0, - width: topbar_width, - height: 1, - }; - TuiTopBar::new(self.context, curr_tab_cwd).render(rect, buf); + let topbar_area = Self::header_area(&area); + TuiTopBar::new(self.context, curr_tab_cwd).render(topbar_area, buf); // render tabs - let topbar_width = (self.context.tab_context_ref().len() * 5) as u16; - let topbar_width = if topbar_width > area.width { - area.width - } else { - topbar_width - }; - let topbar_x = area.width.saturating_sub(topbar_width); - - let rect = Rect { - x: topbar_x, - y: 0, - width: topbar_width, - height: 1, - }; + let tab_area = self.tab_area(&area, self.context.tab_context_ref().len()); TuiTabBar::new( self.context.tab_context_ref().tab_order.as_slice(), self.context.tab_context_ref().index, ) - .render(rect, buf); + .render(tab_area, buf); } } -- cgit v1.2.3