summaryrefslogtreecommitdiffstats
path: root/src/ui/widgets
diff options
context:
space:
mode:
authorJiayi Zhao <jeff.no.zhao@gmail.com>2020-12-11 21:07:13 -0500
committerJiayi Zhao <jeff.no.zhao@gmail.com>2020-12-11 21:07:13 -0500
commit916d72c42cfc7bcb8fc560e17cb3bd75c00757da (patch)
treea8024fc9bd9a48065cd6b65375109482ac9b7983 /src/ui/widgets
parentbf9c102a4cfb85a9fd910195e6372dcd1d062c16 (diff)
add a view for showing worker progress
Diffstat (limited to 'src/ui/widgets')
-rw-r--r--src/ui/widgets/mod.rs8
-rw-r--r--src/ui/widgets/tui_dirlist_detailed.rs2
-rw-r--r--src/ui/widgets/tui_folder_view.rs133
-rw-r--r--src/ui/widgets/tui_menu.rs4
-rw-r--r--src/ui/widgets/tui_progress_view.rs130
-rw-r--r--src/ui/widgets/tui_prompt.rs5
-rw-r--r--src/ui/widgets/tui_textfield.rs19
-rw-r--r--src/ui/widgets/tui_view.rs28
-rw-r--r--src/ui/widgets/tui_worker.rs94
-rw-r--r--src/ui/widgets/tui_worker_view.rs79
10 files changed, 114 insertions, 388 deletions
diff --git a/src/ui/widgets/mod.rs b/src/ui/widgets/mod.rs
index fe756a3..b09b4df 100644
--- a/src/ui/widgets/mod.rs
+++ b/src/ui/widgets/mod.rs
@@ -1,23 +1,19 @@
mod tui_dirlist;
mod tui_dirlist_detailed;
-mod tui_folder_view;
mod tui_footer;
mod tui_menu;
mod tui_prompt;
mod tui_tab;
mod tui_textfield;
mod tui_topbar;
-mod tui_view;
-mod tui_worker_view;
+mod tui_worker;
pub use self::tui_dirlist::TuiDirList;
pub use self::tui_dirlist_detailed::TuiDirListDetailed;
-pub use self::tui_folder_view::TuiFolderView;
pub use self::tui_footer::TuiFooter;
pub use self::tui_menu::{TuiCommandMenu, TuiMenu};
pub use self::tui_prompt::TuiPrompt;
pub use self::tui_tab::TuiTabBar;
pub use self::tui_textfield::TuiTextField;
pub use self::tui_topbar::TuiTopBar;
-pub use self::tui_view::TuiView;
-pub use self::tui_worker_view::TuiWorkerView;
+pub use self::tui_worker::TuiWorker;
diff --git a/src/ui/widgets/tui_dirlist_detailed.rs b/src/ui/widgets/tui_dirlist_detailed.rs
index c76e198..70330c9 100644
--- a/src/ui/widgets/tui_dirlist_detailed.rs
+++ b/src/ui/widgets/tui_dirlist_detailed.rs
@@ -66,7 +66,7 @@ impl<'a> Widget for TuiDirListDetailed<'a> {
buf.set_string(x + area_width as u16 - 1, y + i as u16, "…", style);
}
}
- FileType::Symlink(p) => {
+ FileType::Symlink(_) => {
if name_width < area_width - 4 {
buf.set_string(x, y + i as u16, name, style);
buf.set_string(x + area_width as u16 - 4, y + i as u16, "->", style);
diff --git a/src/ui/widgets/tui_folder_view.rs b/src/ui/widgets/tui_folder_view.rs
deleted file mode 100644
index 01dcf2b..0000000
--- a/src/ui/widgets/tui_folder_view.rs
+++ /dev/null
@@ -1,133 +0,0 @@
-use tui::buffer::Buffer;
-use tui::layout::{Direction, Layout, Rect};
-use tui::style::{Color, Style};
-use tui::text::Span;
-use tui::widgets::{Paragraph, Widget, Wrap};
-
-use super::{TuiDirList, TuiDirListDetailed, TuiFooter, TuiTabBar, TuiTopBar};
-use crate::context::JoshutoContext;
-
-const TAB_VIEW_WIDTH: u16 = 15;
-
-pub struct TuiFolderView<'a> {
- pub context: &'a JoshutoContext,
- pub show_bottom_status: bool,
-}
-
-use super::super::{DEFAULT_LAYOUT, NO_PREVIEW_LAYOUT};
-
-impl<'a> TuiFolderView<'a> {
- pub fn new(context: &'a JoshutoContext) -> Self {
- Self {
- context,
- show_bottom_status: true,
- }
- }
-}
-
-impl<'a> Widget for TuiFolderView<'a> {
- fn render(self, area: Rect, buf: &mut Buffer) {
- let f_size = area;
-
- 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 constraints = match child_list {
- Some(_) => DEFAULT_LAYOUT,
- None => NO_PREVIEW_LAYOUT,
- };
- let layout_rect = Layout::default()
- .direction(Direction::Horizontal)
- .margin(1)
- .constraints(constraints.as_ref())
- .split(f_size);
-
- // render tabs
- if self.context.tab_context_ref().len() > 1 {
- let topbar_width = if f_size.width > TAB_VIEW_WIDTH {
- f_size.width - TAB_VIEW_WIDTH
- } else {
- 0
- };
-
- let rect = Rect {
- x: 0,
- y: 0,
- width: topbar_width,
- height: 1,
- };
- TuiTopBar::new(curr_tab.pwd()).render(rect, buf);
-
- let rect = Rect {
- x: topbar_width,
- y: 0,
- width: TAB_VIEW_WIDTH,
- height: 1,
- };
- let name = if let Some(ostr) = curr_tab.pwd().file_name() {
- ostr.to_str().unwrap_or("")
- } else {
- ""
- };
- TuiTabBar::new(
- name,
- self.context.tab_context_ref().get_index(),
- self.context.tab_context_ref().len(),
- )
- .render(rect, buf);
- } else {
- let topbar_width = f_size.width;
-
- let rect = Rect {
- x: 0,
- y: 0,
- width: topbar_width,
- height: 1,
- };
- TuiTopBar::new(curr_tab.pwd()).render(rect, buf);
- }
-
- // 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() {
- TuiDirListDetailed::new(&list).render(layout_rect[1], buf);
- let rect = Rect {
- x: 0,
- y: f_size.height - 1,
- width: f_size.width,
- height: 1,
- };
-
- let message_style = Style::default().fg(Color::Yellow);
-
- if self.show_bottom_status {
- /* draw the bottom status bar */
- if let Some(msg) = self.context.worker_msg() {
- let text = Span::styled(msg, message_style);
- Paragraph::new(text)
- .wrap(Wrap { trim: true })
- .render(rect, buf);
- } else if !self.context.message_queue_ref().is_empty() {
- let text = Span::styled(&self.context.message_queue_ref()[0], message_style);
- Paragraph::new(text)
- .wrap(Wrap { trim: true })
- .render(rect, buf);
- } else {
- TuiFooter::new(list).render(rect, buf);
- }
- }
- };
-
- // render preview
- if let Some(list) = child_list.as_ref() {
- TuiDirList::new(&list).render(layout_rect[2], buf);
- };
- }
-}
diff --git a/src/ui/widgets/tui_menu.rs b/src/ui/widgets/tui_menu.rs
index 80a3d3a..f7c9080 100644
--- a/src/ui/widgets/tui_menu.rs
+++ b/src/ui/widgets/tui_menu.rs
@@ -6,10 +6,10 @@ use tui::layout::Rect;
use tui::style::{Color, Style};
use tui::widgets::{Block, Borders, Clear, Widget};
-use super::TuiView;
use crate::commands::{CommandKeybind, KeyCommand};
use crate::config::JoshutoCommandMapping;
use crate::context::JoshutoContext;
+use crate::ui::views::TuiView;
use crate::ui::TuiBackend;
use crate::util::event::Event;
use crate::util::worker;
@@ -63,7 +63,7 @@ impl TuiCommandMenu {
context.flush_event();
loop {
- terminal.draw(|frame| {
+ let _ = terminal.draw(|frame| {
let f_size: Rect = frame.size();
{
diff --git a/src/ui/widgets/tui_progress_view.rs b/src/ui/widgets/tui_progress_view.rs
deleted file mode 100644
index 9dad78f..0000000
--- a/src/ui/widgets/tui_progress_view.rs
+++ /dev/null
@@ -1,130 +0,0 @@
-use tui::buffer::Buffer;
-use tui::layout::{Direction, Layout, Rect};
-use tui::style::{Color, Style};
-use tui::widgets::{Paragraph, Text, Widget};
-
-use super::{TuiDirList, TuiDirListDetailed, TuiFooter, TuiTabBar, TuiTopBar};
-use crate::context::JoshutoContext;
-
-const TAB_VIEW_WIDTH: u16 = 15;
-
-pub struct TuiProgressView<'a> {
- pub context: &'a JoshutoContext,
-}
-
-impl<'a> TuiProgressView<'a> {
- pub fn new(context: &'a JoshutoContext) -> Self {
- Self {
- context,
- show_bottom_status: true,
- }
- }
-}
-
-impl<'a> Widget for TuiProgressView<'a> {
- fn render(self, area: Rect, buf: &mut Buffer) {
- let f_size = area;
-
- let layout_rect = Layout::default()
- .direction(Direction::Horizontal)
- .margin(1)
- .split(f_size);
-
- let terminal = backend.terminal_mut();
-
- loop {
- terminal
- .draw(|mut frame| {
- })
- .unwrap();
-
- if let Ok(event) = context.events.next() {
- match event {
- Event::IOWorkerProgress(_) => {
-
- }
- Event::Input(key) => {
- match key {
- Key::Backspace => {
- if line_buffer.backspace(1) {
- completion_tracker.take();
- }
- }
- Key::Left => {
- if line_buffer.move_backward(1) {
- completion_tracker.take();
- }
- }
- Key::Right => {
- if line_buffer.move_forward(1) {
- completion_tracker.take();
- }
- }
- Key::Delete => {
- if line_buffer.delete(1).is_some() {
- completion_tracker.take();
- }
- }
- Key::Home => {
- line_buffer.move_home();
- completion_tracker.take();
- }
- Key::End => {
- line_buffer.move_end();
- completion_tracker.take();
- }
- Key::Up => {}
- Key::Down => {}
- Key::Esc => {
- return None;
- }
- Key::Char('\t') => {
- if completion_tracker.is_none() {
- let res = completer
- .complete_path(line_buffer.as_str(), line_buffer.pos());
- if let Ok((pos, mut candidates)) = res {
- candidates.sort_by(|x, y| {
- x.display()
- .partial_cmp(y.display())
- .unwrap_or(std::cmp::Ordering::Less)
- });
- let ct = CompletionTracker::new(
- pos,
- candidates,
- String::from(line_buffer.as_str()),
- );
- completion_tracker = Some(ct);
- }
- }
-
- if let Some(ref mut s) = completion_tracker {
- if s.index < s.candidates.len() {
- let candidate = &s.candidates[s.index];
- completer.update(
- &mut line_buffer,
- s.pos,
- candidate.display(),
- );
- s.index += 1;
- }
- }
- }
- Key::Char('\n') => {
- break;
- }
- Key::Char(c) => {
- if line_buffer.insert(c, 1).is_some() {
- completion_tracker.take();
- }
- }
- _ => {}
- }
- context.events.flush();
- }
- _ => {}
- };
- }
- }
-
- }
-}
diff --git a/src/ui/widgets/tui_prompt.rs b/src/ui/widgets/tui_prompt.rs
index ea6aa49..f520de9 100644
--- a/src/ui/widgets/tui_prompt.rs
+++ b/src/ui/widgets/tui_prompt.rs
@@ -5,12 +5,11 @@ use tui::text::Span;
use tui::widgets::{Clear, Paragraph, Wrap};
use crate::context::JoshutoContext;
+use crate::ui::views::TuiView;
use crate::ui::TuiBackend;
use crate::util::event::Event;
use crate::util::worker;
-use super::TuiView;
-
pub struct TuiPrompt<'a> {
prompt: &'a str,
}
@@ -25,7 +24,7 @@ impl<'a> TuiPrompt<'a> {
context.flush_event();
loop {
- terminal.draw(|frame| {
+ let _ = terminal.draw(|frame| {
let f_size: Rect = frame.size();
if f_size.height == 0 {
return;
diff --git a/src/ui/widgets/tui_textfield.rs b/src/ui/widgets/tui_textfield.rs
index 0e413fc..07f38b8 100644
--- a/src/ui/widgets/tui_textfield.rs
+++ b/src/ui/widgets/tui_textfield.rs
@@ -8,12 +8,12 @@ use tui::text::{Span, Spans};
use tui::widgets::{Clear, Paragraph, Wrap};
use crate::context::JoshutoContext;
+use crate::ui::views::TuiView;
+use crate::ui::widgets::TuiMenu;
use crate::ui::TuiBackend;
use crate::util::event::Event;
use crate::util::worker;
-use super::{TuiMenu, TuiView};
-
struct CompletionTracker {
pub index: usize,
pub pos: usize,
@@ -40,6 +40,15 @@ pub struct TuiTextField<'a> {
}
impl<'a> TuiTextField<'a> {
+ pub fn new() -> Self {
+ Self {
+ _prompt: "",
+ _prefix: "",
+ _suffix: "",
+ _menu_items: None,
+ }
+ }
+
pub fn menu_items<I>(&mut self, items: I) -> &mut Self
where
I: Iterator<Item = &'a str>,
@@ -90,7 +99,6 @@ impl<'a> TuiTextField<'a> {
if f_size.height == 0 {
return;
}
-
{
let mut view = TuiView::new(&context);
view.show_bottom_status = false;
@@ -98,7 +106,8 @@ impl<'a> TuiTextField<'a> {
}
if let Some(items) = self._menu_items.as_ref() {
- let menu_len = items.len();
+ let menu_widget = TuiMenu::new(items);
+ let menu_len = menu_widget.len();
let menu_y = if menu_len + 2 > f_size.height as usize {
0
} else {
@@ -111,13 +120,11 @@ impl<'a> TuiTextField<'a> {
width: f_size.width,
height: menu_len as u16 + 1,
};
- let menu_widget = TuiMenu::new(items);
frame.render_widget(Clear, menu_rect);
frame.render_widget(menu_widget, menu_rect);
}
let cursor_xpos = line_buffer.pos();
-
let prefix = &line_buffer.as_str()[..cursor_xpos];
let curr = line_buffer.as_str()[cursor_xpos..].chars().next();
diff --git a/src/ui/widgets/tui_view.rs b/src/ui/widgets/tui_view.rs
deleted file mode 100644
index f86eaec..0000000
--- a/src/ui/widgets/tui_view.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-use tui::buffer::Buffer;
-use tui::layout::Rect;
-use tui::widgets::Widget;
-
-use super::TuiFolderView;
-use crate::context::JoshutoContext;
-
-const TAB_VIEW_WIDTH: u16 = 15;
-
-pub struct TuiView<'a> {
- pub context: &'a JoshutoContext,
- pub show_bottom_status: bool,
-}
-
-impl<'a> TuiView<'a> {
- pub fn new(context: &'a JoshutoContext) -> Self {
- Self {
- context,
- show_bottom_status: true,
- }
- }
-}
-
-impl<'a> Widget for TuiView<'a> {
- fn render(self, area: Rect, buf: &mut Buffer) {
- TuiFolderView::new(self.context).render(area, buf);
- }
-}
diff --git a/src/ui/widgets/tui_worker.rs b/src/ui/widgets/tui_worker.rs
new file mode 100644
index 0000000..8707e5d
--- /dev/null
+++ b/src/ui/widgets/tui_worker.rs
@@ -0,0 +1,94 @@
+use tui::buffer::Buffer;
+use tui::layout::Rect;
+use tui::style::{Color, Modifier, Style};
+use tui::text::Span;
+use tui::widgets::{Paragraph, Widget, Wrap};
+
+use crate::context::JoshutoContext;
+use crate::io::FileOp;
+use crate::ui::widgets::TuiTopBar;
+
+pub struct TuiWorker<'a> {
+ pub context: &'a JoshutoContext,
+}
+
+impl<'a> TuiWorker<'a> {
+ pub fn new(context: &'a JoshutoContext) -> Self {
+ Self { context }
+ }
+}
+
+impl<'a> Widget for TuiWorker<'a> {
+ fn render(self, area: Rect, buf: &mut Buffer) {
+ let f_size = area;
+
+ let topbar_width = f_size.width;
+
+ let curr_tab = self.context.tab_context_ref().curr_tab_ref();
+ let rect = Rect {
+ x: 0,
+ y: 0,
+ width: topbar_width,
+ height: 1,
+ };
+ TuiTopBar::new(curr_tab.pwd()).render(rect, buf);
+
+ match self.context.worker_ref() {
+ Some(io_obs) => match io_obs.progress.as_ref() {
+ Some(progress) => {
+ let msg = match progress.kind() {
+ FileOp::Copy => format!(
+ "Copying ({}/{}) {:?} -> {:?}",
+ progress.index() + 1,
+ progress.len(),
+ io_obs.src_path(),
+ io_obs.dest_path()
+ ),
+ FileOp::Cut => format!(
+ "Moving ({}/{}) {:?} -> {:?}",
+ progress.index() + 1,
+ progress.len(),
+ io_obs.src_path(),
+ io_obs.dest_path()
+ ),
+ };
+ let style = Style::default();
+ buf.set_stringn(0, 2, msg, area.width as usize, style);
+ let style = Style::default()
+ .fg(Color::Yellow)
+ .add_modifier(Modifier::BOLD);
+ buf.set_stringn(0, 4, "Queue:", area.width as usize, style);
+ let style = Style::default();
+ for (i, worker) in self.context.worker_iter().enumerate() {
+ let msg = match worker.kind() {
+ FileOp::Copy => format!(
+ "{:02} Copy {} items {:?} -> {:?}",
+ i + 1,
+ worker.paths.len(),
+ worker.paths[0].parent().unwrap(),
+ worker.dest
+ ),
+ FileOp::Cut => format!(
+ "{:02} Moving {} items {:?} -> {:?}",
+ i + 1,
+ worker.paths.len(),
+ worker.paths[0].parent().unwrap(),
+ worker.dest
+ ),
+ };
+ buf.set_stringn(0, (4 + i + 2) as u16, msg, area.width as usize, style);
+ }
+ }
+ _ => {}
+ },
+ _ => {
+ let style = Style::default();
+ buf.set_stringn(0, 2, "No operations running", area.width as usize, style);
+ let style = Style::default()
+ .fg(Color::Yellow)
+ .add_modifier(Modifier::BOLD);
+ buf.set_stringn(0, 4, "Queue:", area.width as usize, style);
+ }
+ }
+ }
+}
diff --git a/src/ui/widgets/tui_worker_view.rs b/src/ui/widgets/tui_worker_view.rs
deleted file mode 100644
index d17f7c2..0000000
--- a/src/ui/widgets/tui_worker_view.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-use tui::buffer::Buffer;
-use tui::layout::{Direction, Layout, Rect};
-use tui::style::{Color, Style};
-use tui::text::Span;
-use tui::widgets::{Paragraph, Widget, Wrap};
-
-use super::{TuiDirList, TuiDirListDetailed, TuiFooter, TuiTabBar, TuiTopBar};
-use crate::context::JoshutoContext;
-
-const TAB_VIEW_WIDTH: u16 = 15;
-
-pub struct TuiWorkerView<'a> {
- pub context: &'a JoshutoContext,
- pub show_bottom_status: bool,
-}
-
-use super::super::{DEFAULT_LAYOUT, NO_PREVIEW_LAYOUT};
-
-impl<'a> TuiWorkerView<'a> {
- pub fn new(context: &'a JoshutoContext) -> Self {
- Self {
- context,
- show_bottom_status: true,
- }
- }
-}
-
-impl<'a> Widget for TuiWorkerView<'a> {
- fn render(self, area: Rect, buf: &mut Buffer) {
- let f_size = area;
-
- let curr_tab = self.context.tab_context_ref().curr_tab_ref();
- let layout_rect = Layout::default().direction(Direction::Horizontal).margin(1);
-
- if self.context.tab_context_ref().len() > 1 {
- let topbar_width = if f_size.width > TAB_VIEW_WIDTH {
- f_size.width - TAB_VIEW_WIDTH
- } else {
- 0
- };
-
- let rect = Rect {
- x: 0,
- y: 0,
- width: topbar_width,
- height: 1,
- };
- TuiTopBar::new(curr_tab.pwd()).render(rect, buf);
-
- let rect = Rect {
- x: topbar_width,
- y: 0,
- width: TAB_VIEW_WIDTH,
- height: 1,
- };
- let name = if let Some(ostr) = curr_tab.pwd().file_name() {
- ostr.to_str().unwrap_or("")
- } else {
- ""
- };
- TuiTabBar::new(
- name,
- self.context.tab_context_ref().get_index(),
- self.context.tab_context_ref().len(),
- )
- .render(rect, buf);
- } else {
- let topbar_width = f_size.width;
-
- let rect = Rect {
- x: 0,
- y: 0,
- width: topbar_width,
- height: 1,
- };
- TuiTopBar::new(curr_tab.pwd()).render(rect, buf);
- }
- }
-}