From 1017850a6cc91328abc1127bdb117495f5e909d8 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Thu, 28 Apr 2022 21:25:27 +0000 Subject: [PATCH 01/13] feat: refactored centered box to diplay in any of 9 areas --- README.md | 13 +++-- src/app_error.rs | 25 +++------ src/input_handler/mod.rs | 35 ++++++++++++- src/main.rs | 2 + src/ui/draw_blocks.rs | 68 ++++++++++++++++++------- src/ui/gui_state.rs | 106 +++++++++++++++++++++++++++++++++------ src/ui/mod.rs | 10 +++- 7 files changed, 202 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index ae524e6..4610130 100644 --- a/README.md +++ b/README.md @@ -21,14 +21,21 @@

-## Download +## Download & install See releases +install +```bash +INSTALL_DIR="${HOME}/.local/bin" +tar xzvf oxker_linux_x86_64.tar.gz oxker +install -Dm 755 oxker -t "$INSTALL_DIR" +rm oxker_linux_x86_64.tar.gz oxker +``` ## Run -```./oxker``` +```oxker``` available command line arguments | argument|result| @@ -56,7 +63,7 @@ requires docker & error!("Unable to access docker daemon"), - Self::DockerInterval => error!("Docker update interval needs to be greater than 0"), - Self::InputPoll => error!("Unable to poll user input"), - Self::Terminal => error!("Unable to draw to terminal"), - Self::DockerCommand(s) => { - let error = format!("Unable to {} container", s); - error!(%error); - } - } - } -} - /// Convert errors into strings to display impl fmt::Display for AppError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -39,6 +22,10 @@ impl fmt::Display for AppError { Self::InputPoll => "Unable to poll user input".to_owned(), Self::Terminal => "Unable to draw to terminal".to_owned(), Self::DockerCommand(s) => format!("Unable to {} container", s), + Self::MouseCapture(x) => { + let reason = if *x { "en" } else { "dis" }; + format!("Unable to {}able mouse capture", reason) + } }; write!(f, "{}", disp) } diff --git a/src/input_handler/mod.rs b/src/input_handler/mod.rs index 3e14fb5..610c0f5 100644 --- a/src/input_handler/mod.rs +++ b/src/input_handler/mod.rs @@ -4,7 +4,12 @@ use std::sync::{ }; use bollard::{container::StartContainerOptions, Docker}; -use crossterm::event::{KeyCode, MouseButton, MouseEvent, MouseEventKind}; +use crossterm::{ + event::{ + DisableMouseCapture, EnableMouseCapture, KeyCode, MouseButton, MouseEvent, MouseEventKind, + }, + execute, +}; use parking_lot::Mutex; use tokio::sync::broadcast::Receiver; use tui::layout::Rect; @@ -25,6 +30,7 @@ pub struct InputHandler { gui_state: Arc>, is_running: Arc, rec: Receiver, + mouse_capture: bool, } impl InputHandler { @@ -42,6 +48,7 @@ impl InputHandler { gui_state, is_running, rec, + mouse_capture: true, }; inner.start().await; } @@ -69,6 +76,7 @@ impl InputHandler { async fn button_press(&mut self, key_code: KeyCode) { let show_error = self.app_data.lock().show_error; let show_info = self.gui_state.lock().show_help; + if show_error { match key_code { KeyCode::Char('q') => { @@ -98,6 +106,31 @@ impl InputHandler { KeyCode::Char('h') => { self.gui_state.lock().show_help = true; } + KeyCode::Char('m') => { + if self.mouse_capture { + match execute!(std::io::stdout(), DisableMouseCapture) { + Ok(_) => self + .gui_state + .lock() + .set_info_box("Mouse capture disabled".to_owned()), + Err(_) => self + .app_data + .lock() + .set_error(AppError::MouseCapture(false)), + } + } else { + match execute!(std::io::stdout(), EnableMouseCapture) { + Ok(_) => self + .gui_state + .lock() + .set_info_box("Mouse capture enabled".to_owned()), + Err(_) => self.app_data.lock().set_error(AppError::MouseCapture(true)), + } + todo!("tokio spawn for x seconds and then reset, probably need to take in an arc clone for self.gui_state") + // execute!(stdout, EnableMouseCapture).unwrap(); + }; + self.mouse_capture = !self.mouse_capture; + } KeyCode::Tab => self.gui_state.lock().next_panel(), KeyCode::BackTab => self.gui_state.lock().previous_panel(), KeyCode::Home => { diff --git a/src/main.rs b/src/main.rs index 97a3e50..112118a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![allow(unused)] + use app_data::AppData; use app_error::AppError; use bollard::Docker; diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index f3ac6c9..28830b0 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -19,6 +19,7 @@ use crate::{ app_error::AppError, }; +use super::gui_state::BoxLocation; use super::{GuiState, SelectablePanel}; const NAME_TEXT: &str = r#" @@ -497,7 +498,7 @@ pub fn draw_help_box(f: &mut Frame<'_, B>) { .border_type(BorderType::Rounded) .border_style(Style::default().fg(Color::Black)); - let area = centered_info(lines as u16, max_line_width as u16, f.size()); + let area = draw_popup(lines as u16, max_line_width as u16, f.size(), BoxLocation::MiddleCentre); let split_popup = Layout::default() .direction(Direction::Vertical) @@ -560,38 +561,67 @@ pub fn draw_error(f: &mut Frame<'_, B>, error: AppError, seconds: Op .block(block) .alignment(Alignment::Center); - let area = centered_info(lines as u16, max_line_width as u16, f.size()); + let area = draw_popup(lines as u16, max_line_width as u16, f.size(), BoxLocation::MiddleCentre); + f.render_widget(Clear, area); + f.render_widget(paragraph, area); +} + +/// Show info box in bottom right corner +pub fn draw_info(f: &mut Frame<'_, B>, text: String) { + let block = Block::default() + .title("") + .title_alignment(Alignment::Center) + .borders(Borders::NONE); + + // Add a blank line, so that the text is verticall centered + let text = format!("\n{}", text); + + let mut max_line_width = 0; + text.lines().into_iter().for_each(|line| { + let width = line.chars().count(); + if width > max_line_width { + max_line_width = width; + } + }); + + let mut lines = text.lines().count(); + + // Add some horizontal & vertical margins + max_line_width += 8; + lines += 3; + + let paragraph = Paragraph::new(text) + .style(Style::default().bg(Color::Blue).fg(Color::White)) + .block(block) + .alignment(Alignment::Center); + + let area = draw_popup(lines as u16, max_line_width as u16, f.size(), BoxLocation::BottomRight); f.render_widget(Clear, area); f.render_widget(paragraph, area); } /// draw a box in the center of the screen, based on max line width + number of lines -fn centered_info(number_lines: u16, max_line_width: u16, r: Rect) -> Rect { +fn draw_popup(text_lines: u16, text_width: u16, r: Rect, box_location:BoxLocation) -> Rect { // This can panic if number_lines or max_line_width is larger than r.height or r.width - let blank_vertical = (r.height - number_lines) / 2; - let blank_horizontal = (r.width - max_line_width) / 2; + let blank_vertical = (r.height - text_lines) / 2; + let blank_horizontal = (r.width - text_width) / 2; + + let vertical_constraints = box_location.get_vertical_constraints(blank_vertical, text_lines); + let horizontal_constraints = box_location.get_horizontal_constraints(blank_horizontal, text_width); + + let indexes = box_location.get_indexes(); let popup_layout = Layout::default() .direction(Direction::Vertical) .constraints( - [ - Constraint::Max(blank_vertical), - Constraint::Max(number_lines), - Constraint::Max(blank_vertical), - ] - .as_ref(), + vertical_constraints ) .split(r); Layout::default() .direction(Direction::Horizontal) .constraints( - [ - Constraint::Max(blank_horizontal), - Constraint::Max(max_line_width), - Constraint::Max(blank_horizontal), - ] - .as_ref(), + horizontal_constraints ) - .split(popup_layout[1])[1] -} + .split(popup_layout[indexes.0])[indexes.1] +} \ No newline at end of file diff --git a/src/ui/gui_state.rs b/src/ui/gui_state.rs index eb53924..7ee205e 100644 --- a/src/ui/gui_state.rs +++ b/src/ui/gui_state.rs @@ -1,5 +1,5 @@ use std::{collections::HashMap, fmt}; -use tui::layout::Rect; +use tui::layout::{Constraint, Rect}; #[derive(Debug, PartialEq, std::hash::Hash, std::cmp::Eq, Clone, Copy)] pub enum SelectablePanel { @@ -7,7 +7,78 @@ pub enum SelectablePanel { Commands, Logs, } -#[derive(Debug)] + +#[derive(Debug, Clone, Copy)] +pub enum BoxLocation { + TopLeft, + TopCentre, + TopRight, + MiddleLeft, + MiddleCentre, + MiddleRight, + BottomLeft, + BottomCentre, + BottomRight, +} + +impl BoxLocation { + pub fn get_indexes(&self) -> (usize, usize) { + match self { + Self::TopLeft => (0, 0), + Self::TopCentre => (0, 1), + Self::TopRight => (0, 2), + Self::MiddleLeft => (1, 0), + Self::MiddleCentre => (1, 1), + Self::MiddleRight => (1, 2), + Self::BottomLeft => (2, 0), + Self::BottomCentre => (2, 1), + Self::BottomRight => (2, 2), + } + } + + // Should combine and just return a tupple? + pub fn get_horizontal_constraints(&self, blank_vertical: u16, text_width: u16) -> [Constraint; 3] { + match self { + Self::TopLeft | Self::MiddleLeft | Self::BottomLeft => [ + Constraint::Max(text_width), + Constraint::Max(blank_vertical), + Constraint::Max(blank_vertical), + ], + Self::TopCentre | Self::MiddleCentre | Self::BottomCentre => [ + Constraint::Max(blank_vertical), + Constraint::Max(text_width), + Constraint::Max(blank_vertical), + ], + Self::TopRight | Self::MiddleRight | Self::BottomRight => [ + Constraint::Max(blank_vertical), + Constraint::Max(blank_vertical), + Constraint::Max(text_width), + ], + } + } + pub fn get_vertical_constraints(&self, blank_vertical: u16, number_lines: u16) -> [Constraint; 3] { + match self { + Self::TopLeft | Self::TopCentre | Self::TopRight => [ + Constraint::Max(number_lines), + Constraint::Max(blank_vertical), + Constraint::Max(blank_vertical), + ], + Self::MiddleLeft | Self::MiddleCentre | Self::MiddleRight => [ + Constraint::Max(blank_vertical), + Constraint::Max(number_lines), + Constraint::Max(blank_vertical), + ], + Self::BottomLeft | Self::BottomCentre | Self::BottomRight => [ + Constraint::Max(blank_vertical), + Constraint::Max(blank_vertical), + Constraint::Max(number_lines), + ], + } + } + +} + +#[derive(Debug, Clone)] pub enum Loading { One, Two, @@ -34,20 +105,9 @@ impl Loading { Self::Eight => Self::Nine, Self::Nine => Self::Ten, Self::Ten => Self::One, - // Self::Five => Self::One } } } -// "⠋", -// "⠙", -// "⠹", -// "⠸", -// "⠼", -// "⠴", -// "⠦", -// "⠧", -// "⠇", -// "⠏" impl fmt::Display for Loading { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -92,7 +152,7 @@ impl SelectablePanel { } /// Global gui_state, stored in an Arc -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct GuiState { // Think this should be a BMapTree, so can define order when iterating over potential intersects // Is an issue if two panels are in the same space, sush as a smaller panel embedded, yet infront of, a larger panel @@ -101,6 +161,8 @@ pub struct GuiState { loading: Loading, pub selected_panel: SelectablePanel, pub show_help: bool, + // show_info_panel: bool, + pub info_box_text: Option, } impl GuiState { @@ -111,6 +173,8 @@ impl GuiState { loading: Loading::One, selected_panel: SelectablePanel::Containers, show_help: false, + // show_info_panel: false, + info_box_text: None, } } @@ -158,4 +222,18 @@ impl GuiState { pub fn reset_loading(&mut self) { self.loading = Loading::One; } + + pub fn set_info_box(&mut self, text: String) { + self.info_box_text = Some(text); + // self.show_info_panel = true; + + // Should spawn and after 10 seconds close? + // Need to copy whatever we're doing with parsing logs icon + } + + pub fn reset_info_box(&mut self) { + // self.loading = Loading::One; + self.info_box_text = None; + // self.show_info_panel = false; + } } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 002175a..65f3291 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -11,6 +11,7 @@ use std::{ sync::{atomic::Ordering, Arc}, }; use tokio::sync::broadcast::Sender; +use tracing::error; use tui::{ backend::{Backend, CrosstermBackend}, layout::{Constraint, Direction, Layout}, @@ -50,7 +51,7 @@ pub async fn create_ui( terminal.show_cursor().unwrap(); if let Err(err) = res { - err.disp() + error!(%err); } Ok(()) } @@ -126,6 +127,7 @@ fn ui( let log_index = app_data.lock().get_selected_log_index(); let selected_panel = gui_state.lock().selected_panel; let show_help = gui_state.lock().show_help; + let info_text = gui_state.lock().info_box_text.clone(); let whole_layout = Layout::default() .direction(Direction::Vertical) @@ -198,11 +200,17 @@ fn ui( show_help, ); + + // only draw charts if there are containers if has_containers { draw_chart(f, lower_main[1], app_data, log_index); } + if let Some(info) = info_text { + draw_info(f, info); + } + // Check if error, and show popup if so if show_help { draw_help_box(f); From b10f927481c9e38a48c1d4b94e744ec48e8b6ba6 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 01:03:06 +0000 Subject: [PATCH 02/13] feat: show id column --- src/app_data/container_state.rs | 16 ++++---- src/input_handler/mod.rs | 21 +++++++--- src/ui/draw_blocks.rs | 71 +++++++++++++++++++++++---------- src/ui/gui_state.rs | 15 +++++-- src/ui/mod.rs | 6 +-- 5 files changed, 87 insertions(+), 42 deletions(-) diff --git a/src/app_data/container_state.rs b/src/app_data/container_state.rs index 0c0243c..3852e4c 100644 --- a/src/app_data/container_state.rs +++ b/src/app_data/container_state.rs @@ -398,12 +398,13 @@ impl ContainerItem { /// Container information panel headings + widths, for nice pretty formatting #[derive(Debug)] pub struct Columns { - pub cpu: (String, usize), - pub image: (String, usize), - pub name: (String, usize), pub state: (String, usize), pub status: (String, usize), + pub cpu: (String, usize), pub mem: (String, usize), + pub id: (String, usize), + pub name: (String, usize), + pub image: (String, usize), pub net_rx: (String, usize), pub net_tx: (String, usize), } @@ -411,13 +412,14 @@ pub struct Columns { impl Columns { pub fn new() -> Self { Self { - // 7 to allow for 100.00% - cpu: (String::from("cpu"), 7), - image: (String::from("image"), 5), - name: (String::from("name"), 4), state: (String::from("state"), 11), status: (String::from("status"), 16), + // 7 to allow for "100.00%" + cpu: (String::from("cpu"), 7), mem: (String::from("memory/limit"), 12), + id: (String::from("id"), 8), + name: (String::from("name"), 4), + image: (String::from("image"), 5), net_rx: (String::from("↓ rx"), 5), net_tx: (String::from("↑ tx"), 5), } diff --git a/src/input_handler/mod.rs b/src/input_handler/mod.rs index 610c0f5..68728b8 100644 --- a/src/input_handler/mod.rs +++ b/src/input_handler/mod.rs @@ -11,7 +11,7 @@ use crossterm::{ execute, }; use parking_lot::Mutex; -use tokio::sync::broadcast::Receiver; +use tokio::{sync::broadcast::Receiver, task::JoinHandle}; use tui::layout::Rect; mod message; @@ -31,6 +31,7 @@ pub struct InputHandler { is_running: Arc, rec: Receiver, mouse_capture: bool, + info_sleep: Option>, } impl InputHandler { @@ -49,6 +50,7 @@ impl InputHandler { is_running, rec, mouse_capture: true, + info_sleep: None, }; inner.start().await; } @@ -112,7 +114,7 @@ impl InputHandler { Ok(_) => self .gui_state .lock() - .set_info_box("Mouse capture disabled".to_owned()), + .set_info_box("✖ mouse capture disabled".to_owned()), Err(_) => self .app_data .lock() @@ -123,12 +125,21 @@ impl InputHandler { Ok(_) => self .gui_state .lock() - .set_info_box("Mouse capture enabled".to_owned()), + .set_info_box("✓ mouse capture enabled".to_owned()), Err(_) => self.app_data.lock().set_error(AppError::MouseCapture(true)), } - todo!("tokio spawn for x seconds and then reset, probably need to take in an arc clone for self.gui_state") - // execute!(stdout, EnableMouseCapture).unwrap(); }; + + let gui_state = Arc::clone(&self.gui_state); + + if self.info_sleep.is_some() { + self.info_sleep.as_ref().unwrap().abort() + } + self.info_sleep = Some(tokio::spawn(async move { + tokio::time::sleep(std::time::Duration::from_millis(4000)).await; + gui_state.lock().reset_info_box() + })); + self.mouse_capture = !self.mouse_capture; } KeyCode::Tab => self.gui_state.lock().next_panel(), diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index 28830b0..1a0b2bb 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -45,7 +45,7 @@ fn generate_block<'a>( app_data: &Arc>, selected_panel: &SelectablePanel, ) -> Block<'a> { - let mut block = Block::default().borders(Borders::ALL); + let mut block = Block::default().borders(Borders::ALL).border_type(BorderType::Rounded); if let Some(panel) = selectable_panel { let title = match panel { @@ -63,11 +63,12 @@ fn generate_block<'a>( }; block = block.title(title); if selected_panel == &panel { - let selected_style = Style::default().fg(Color::LightCyan); - let selected_border = BorderType::Plain; + // let selected_style = Style::default().fg(Color::LightCyan); + // let selected_border = BorderType::Plain; + // let selected_border = BorderType::Rounded; block = block - .border_style(selected_style) - .border_type(selected_border); + .border_style(Style::default().fg(Color::LightCyan)); + // .border_type(BorderType::Rounded); } } block @@ -170,6 +171,10 @@ pub fn draw_containers( Span::styled( format!("{}{:>width$}", MARGIN, mems, width = widths.mem.1), state_style, + ), + Span::styled( + format!("{}{:>width$}", MARGIN, i.id.chars().take(8).collect::(), width = widths.id.1), + blue, ), Span::styled( format!("{}{:>width$}", MARGIN, i.name, width = widths.name.1), @@ -331,7 +336,8 @@ fn make_chart( .add_modifier(Modifier::BOLD), )) .borders(Borders::ALL) - .border_type(BorderType::Plain), + // .border_type(BorderType::Plain), + .border_type(BorderType::Rounded), ) .x_axis( Axis::default() @@ -355,7 +361,7 @@ fn make_chart( } /// Show error popup over whole screen -pub fn draw_info_bar( +pub fn draw_heading_bar( area: Rect, columns: &Columns, f: &mut Frame<'_, B>, @@ -380,6 +386,15 @@ pub fn draw_info_bar( .push_str(format!("{}{:>width$}", MARGIN, columns.cpu.0, width = columns.cpu.1).as_str()); column_headings .push_str(format!("{}{:>width$}", MARGIN, columns.mem.0, width = columns.mem.1).as_str()); + column_headings.push_str( + format!( + "{}{:>width$}", + MARGIN, + columns.id.0, + width = columns.id.1 + ) + .as_str(), + ); column_headings.push_str( format!( "{}{:>width$}", @@ -498,7 +513,12 @@ pub fn draw_help_box(f: &mut Frame<'_, B>) { .border_type(BorderType::Rounded) .border_style(Style::default().fg(Color::Black)); - let area = draw_popup(lines as u16, max_line_width as u16, f.size(), BoxLocation::MiddleCentre); + let area = draw_popup( + lines as u16, + max_line_width as u16, + f.size(), + BoxLocation::MiddleCentre, + ); let split_popup = Layout::default() .direction(Direction::Vertical) @@ -561,7 +581,12 @@ pub fn draw_error(f: &mut Frame<'_, B>, error: AppError, seconds: Op .block(block) .alignment(Alignment::Center); - let area = draw_popup(lines as u16, max_line_width as u16, f.size(), BoxLocation::MiddleCentre); + let area = draw_popup( + lines as u16, + max_line_width as u16, + f.size(), + BoxLocation::MiddleCentre, + ); f.render_widget(Clear, area); f.render_widget(paragraph, area); } @@ -573,7 +598,7 @@ pub fn draw_info(f: &mut Frame<'_, B>, text: String) { .title_alignment(Alignment::Center) .borders(Borders::NONE); - // Add a blank line, so that the text is verticall centered + // Add a blank line, so that the text is verticall centered let text = format!("\n{}", text); let mut max_line_width = 0; @@ -595,33 +620,35 @@ pub fn draw_info(f: &mut Frame<'_, B>, text: String) { .block(block) .alignment(Alignment::Center); - let area = draw_popup(lines as u16, max_line_width as u16, f.size(), BoxLocation::BottomRight); + let area = draw_popup( + lines as u16, + max_line_width as u16, + f.size(), + BoxLocation::BottomRight, + ); f.render_widget(Clear, area); f.render_widget(paragraph, area); } /// draw a box in the center of the screen, based on max line width + number of lines -fn draw_popup(text_lines: u16, text_width: u16, r: Rect, box_location:BoxLocation) -> Rect { +fn draw_popup(text_lines: u16, text_width: u16, r: Rect, box_location: BoxLocation) -> Rect { // This can panic if number_lines or max_line_width is larger than r.height or r.width let blank_vertical = (r.height - text_lines) / 2; let blank_horizontal = (r.width - text_width) / 2; - let vertical_constraints = box_location.get_vertical_constraints(blank_vertical, text_lines); - let horizontal_constraints = box_location.get_horizontal_constraints(blank_horizontal, text_width); + let vertical_constraints = box_location.get_vertical_constraints(blank_vertical, text_lines); + let horizontal_constraints = + box_location.get_horizontal_constraints(blank_horizontal, text_width); - let indexes = box_location.get_indexes(); + let indexes = box_location.get_indexes(); let popup_layout = Layout::default() .direction(Direction::Vertical) - .constraints( - vertical_constraints - ) + .constraints(vertical_constraints) .split(r); Layout::default() .direction(Direction::Horizontal) - .constraints( - horizontal_constraints - ) + .constraints(horizontal_constraints) .split(popup_layout[indexes.0])[indexes.1] -} \ No newline at end of file +} diff --git a/src/ui/gui_state.rs b/src/ui/gui_state.rs index 7ee205e..72ef238 100644 --- a/src/ui/gui_state.rs +++ b/src/ui/gui_state.rs @@ -36,8 +36,12 @@ impl BoxLocation { } } - // Should combine and just return a tupple? - pub fn get_horizontal_constraints(&self, blank_vertical: u16, text_width: u16) -> [Constraint; 3] { + // Should combine and just return a tupple? + pub fn get_horizontal_constraints( + &self, + blank_vertical: u16, + text_width: u16, + ) -> [Constraint; 3] { match self { Self::TopLeft | Self::MiddleLeft | Self::BottomLeft => [ Constraint::Max(text_width), @@ -56,7 +60,11 @@ impl BoxLocation { ], } } - pub fn get_vertical_constraints(&self, blank_vertical: u16, number_lines: u16) -> [Constraint; 3] { + pub fn get_vertical_constraints( + &self, + blank_vertical: u16, + number_lines: u16, + ) -> [Constraint; 3] { match self { Self::TopLeft | Self::TopCentre | Self::TopRight => [ Constraint::Max(number_lines), @@ -75,7 +83,6 @@ impl BoxLocation { ], } } - } #[derive(Debug, Clone)] diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 65f3291..7027a5a 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -192,7 +192,7 @@ fn ui( &selected_panel, ); - draw_info_bar( + draw_heading_bar( whole_layout[0], &column_widths, f, @@ -200,14 +200,12 @@ fn ui( show_help, ); - - // only draw charts if there are containers if has_containers { draw_chart(f, lower_main[1], app_data, log_index); } - if let Some(info) = info_text { + if let Some(info) = info_text { draw_info(f, info); } From 421aa82ebde080ee62411675f5efa1a1857a2b32 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 01:11:20 +0000 Subject: [PATCH 03/13] feat: help box "m" explanation --- Cargo.toml | 2 +- src/ui/draw_blocks.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 59fce02..a26aed7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ parking_lot = {version= "0.12.0"} tokio = {version = "1.17.0", features=["full"]} tracing = "0.1.32" tracing-subscriber = "0.3.9" -tui = "0.17" +tui = "0.18" [dev-dependencies] diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index 1a0b2bb..3d492b2 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -476,6 +476,7 @@ pub fn draw_help_box(f: &mut Frame<'_, B>) { description_text.push_str("\n Tab or Alt+Tab to change panels, arrows to change lines, enter to send docker container commands."); description_text.push_str("\n Mouse input also available."); description_text.push_str("\n ( q ) to quit at any time."); + description_text.push_str("\n ( m ) to toggle mouse capture. When disabled, text on screen can be selected & copied, but mouse clicks get disabled"); description_text .push_str("\n\n currenty an early work in progress, all and any input appreciated"); description_text.push_str(format!("\n {}", REPO.trim()).as_str()); From 01e000169dab710ea78cc38b0c58b648f190f6b6 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 01:12:44 +0000 Subject: [PATCH 04/13] feat: help box "m" explanation --- src/ui/draw_blocks.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index 3d492b2..362735e 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -634,8 +634,20 @@ pub fn draw_info(f: &mut Frame<'_, B>, text: String) { /// draw a box in the center of the screen, based on max line width + number of lines fn draw_popup(text_lines: u16, text_width: u16, r: Rect, box_location: BoxLocation) -> Rect { // This can panic if number_lines or max_line_width is larger than r.height or r.width - let blank_vertical = (r.height - text_lines) / 2; - let blank_horizontal = (r.width - text_width) / 2; + + + + let blank_vertical = if r.height > text_lines { + (r.height - text_lines) / 2 + } else { + r.height / 2 + }; + let blank_horizontal = if r.width > text_width { + (r.width - text_width) / 2 + }else { + r.width / 2 + + }; let vertical_constraints = box_location.get_vertical_constraints(blank_vertical, text_lines); let horizontal_constraints = From 12b5cfce6ce46a9225f00121a905245759fa2244 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 01:16:26 +0000 Subject: [PATCH 05/13] fix: make sure popup blank sapce can't be negative --- src/ui/draw_blocks.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index 362735e..e55f3a0 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -633,20 +633,17 @@ pub fn draw_info(f: &mut Frame<'_, B>, text: String) { /// draw a box in the center of the screen, based on max line width + number of lines fn draw_popup(text_lines: u16, text_width: u16, r: Rect, box_location: BoxLocation) -> Rect { - // This can panic if number_lines or max_line_width is larger than r.height or r.width - - + // Make sure blank_space can't be an negative, as will crash let blank_vertical = if r.height > text_lines { (r.height - text_lines) / 2 } else { - r.height / 2 + 1 }; let blank_horizontal = if r.width > text_width { (r.width - text_width) / 2 }else { - r.width / 2 - + 1 }; let vertical_constraints = box_location.get_vertical_constraints(blank_vertical, text_lines); From 00dfacfe13ccd7562b622d15e923a831fca1fd69 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 01:30:31 +0000 Subject: [PATCH 06/13] refactor: m_button, help box text --- src/input_handler/mod.rs | 87 +++++++++++++++++++--------------------- src/ui/draw_blocks.rs | 15 ++++--- 2 files changed, 50 insertions(+), 52 deletions(-) diff --git a/src/input_handler/mod.rs b/src/input_handler/mod.rs index 68728b8..af2f63c 100644 --- a/src/input_handler/mod.rs +++ b/src/input_handler/mod.rs @@ -74,6 +74,41 @@ impl InputHandler { } } + fn m_button(&mut self) { + if self.mouse_capture { + match execute!(std::io::stdout(), DisableMouseCapture) { + Ok(_) => self + .gui_state + .lock() + .set_info_box("✖ mouse capture disabled".to_owned()), + Err(_) => self + .app_data + .lock() + .set_error(AppError::MouseCapture(false)), + } + } else { + match execute!(std::io::stdout(), EnableMouseCapture) { + Ok(_) => self + .gui_state + .lock() + .set_info_box("✓ mouse capture enabled".to_owned()), + Err(_) => self.app_data.lock().set_error(AppError::MouseCapture(true)), + } + }; + + let gui_state = Arc::clone(&self.gui_state); + + if self.info_sleep.is_some() { + self.info_sleep.as_ref().unwrap().abort() + } + self.info_sleep = Some(tokio::spawn(async move { + tokio::time::sleep(std::time::Duration::from_millis(4000)).await; + gui_state.lock().reset_info_box() + })); + + self.mouse_capture = !self.mouse_capture; + } + /// Handle any keyboard button events async fn button_press(&mut self, key_code: KeyCode) { let show_error = self.app_data.lock().show_error; @@ -92,56 +127,16 @@ impl InputHandler { } } else if show_info { match key_code { - KeyCode::Char('q') => { - self.is_running.store(false, Ordering::SeqCst); - } - KeyCode::Char('h') => { - self.gui_state.lock().show_help = false; - } + KeyCode::Char('q') => self.is_running.store(false, Ordering::SeqCst), + KeyCode::Char('h') => self.gui_state.lock().show_help = false, + KeyCode::Char('m') => self.m_button(), _ => (), } } else { match key_code { - KeyCode::Char('q') => { - self.is_running.store(false, Ordering::SeqCst); - } - KeyCode::Char('h') => { - self.gui_state.lock().show_help = true; - } - KeyCode::Char('m') => { - if self.mouse_capture { - match execute!(std::io::stdout(), DisableMouseCapture) { - Ok(_) => self - .gui_state - .lock() - .set_info_box("✖ mouse capture disabled".to_owned()), - Err(_) => self - .app_data - .lock() - .set_error(AppError::MouseCapture(false)), - } - } else { - match execute!(std::io::stdout(), EnableMouseCapture) { - Ok(_) => self - .gui_state - .lock() - .set_info_box("✓ mouse capture enabled".to_owned()), - Err(_) => self.app_data.lock().set_error(AppError::MouseCapture(true)), - } - }; - - let gui_state = Arc::clone(&self.gui_state); - - if self.info_sleep.is_some() { - self.info_sleep.as_ref().unwrap().abort() - } - self.info_sleep = Some(tokio::spawn(async move { - tokio::time::sleep(std::time::Duration::from_millis(4000)).await; - gui_state.lock().reset_info_box() - })); - - self.mouse_capture = !self.mouse_capture; - } + KeyCode::Char('q') => self.is_running.store(false, Ordering::SeqCst), + KeyCode::Char('h') => self.gui_state.lock().show_help = true, + KeyCode::Char('m') => self.m_button(), KeyCode::Tab => self.gui_state.lock().next_panel(), KeyCode::BackTab => self.gui_state.lock().previous_panel(), KeyCode::Home => { diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index e55f3a0..b6bb42d 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -471,12 +471,15 @@ pub fn draw_heading_bar( pub fn draw_help_box(f: &mut Frame<'_, B>) { let title = format!(" {} ", VERSION); - let mut description_text = - String::from("\n A basic docker container information viewer and controller."); - description_text.push_str("\n Tab or Alt+Tab to change panels, arrows to change lines, enter to send docker container commands."); - description_text.push_str("\n Mouse input also available."); - description_text.push_str("\n ( q ) to quit at any time."); - description_text.push_str("\n ( m ) to toggle mouse capture. When disabled, text on screen can be selected & copied, but mouse clicks get disabled"); + let mut description_text = String::new(); + // String::from("\n A basic docker container information viewer and controller."); + description_text.push_str("\n ( tab ) or ( alt+tab ) to change panels"); + description_text.push_str("\n ( ↑ ↓ ← → ) mto change selected line"); + description_text.push_str("\n ( enter ) to send docker container commands"); + description_text.push_str("\n ( m ) to toggle mouse capture - if disabled, text on screen can be selected & copied, but mouse clicks get disabled"); + description_text.push_str("\n ( h ) to toggle this help information"); + description_text.push_str("\n ( q ) to quit at any time"); + description_text.push_str("\n mouse scrolling & clicking also available"); description_text .push_str("\n\n currenty an early work in progress, all and any input appreciated"); description_text.push_str(format!("\n {}", REPO.trim()).as_str()); From db99e61a3718d41a2c464373550bafdd58ceaa28 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 01:36:20 +0000 Subject: [PATCH 07/13] refactor: help box text --- src/ui/draw_blocks.rs | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index b6bb42d..3e85ab7 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -471,22 +471,24 @@ pub fn draw_heading_bar( pub fn draw_help_box(f: &mut Frame<'_, B>) { let title = format!(" {} ", VERSION); - let mut description_text = String::new(); - // String::from("\n A basic docker container information viewer and controller."); - description_text.push_str("\n ( tab ) or ( alt+tab ) to change panels"); - description_text.push_str("\n ( ↑ ↓ ← → ) mto change selected line"); - description_text.push_str("\n ( enter ) to send docker container commands"); - description_text.push_str("\n ( m ) to toggle mouse capture - if disabled, text on screen can be selected & copied, but mouse clicks get disabled"); - description_text.push_str("\n ( h ) to toggle this help information"); - description_text.push_str("\n ( q ) to quit at any time"); - description_text.push_str("\n mouse scrolling & clicking also available"); - description_text + let description_text = String::from("\n A basic docker container information viewer and controller"); + + let mut help_text = String::from("\n ( tab ) or ( alt+tab ) to change panels"); + help_text.push_str("\n ( ↑ ↓ ← → ) mto change selected line"); + help_text.push_str("\n ( enter ) to send docker container commands"); + help_text.push_str("\n ( h ) to toggle this help information"); + help_text.push_str("\n ( m ) to toggle mouse capture - if disabled, text on screen can be selected & copied, but mouse clicks get disabled"); + help_text.push_str("\n ( q ) to quit at any time"); + help_text.push_str("\n mouse scrolling & clicking also available"); + help_text .push_str("\n\n currenty an early work in progress, all and any input appreciated"); - description_text.push_str(format!("\n {}", REPO.trim()).as_str()); + help_text.push_str(format!("\n {}", REPO.trim()).as_str()); let mut max_line_width = 0; - let all_text = format!("{}{}", NAME_TEXT, description_text); + + + let all_text = format!("{}{}{}", NAME_TEXT, description_text, help_text); all_text.lines().into_iter().for_each(|line| { let width = line.chars().count(); @@ -506,7 +508,13 @@ pub fn draw_help_box(f: &mut Frame<'_, B>) { .block(Block::default()) .alignment(Alignment::Center); - let description_paragraph = Paragraph::new(description_text.as_str()) + + let description_paragrpah = Paragraph::new(description_text.as_str()) + .style(Style::default().bg(Color::Magenta).fg(Color::Black)) + .block(Block::default()) + .alignment(Alignment::Center); + + let help_paragraph = Paragraph::new(help_text.as_str()) .style(Style::default().bg(Color::Magenta).fg(Color::Black)) .block(Block::default()) .alignment(Alignment::Left); @@ -529,7 +537,8 @@ pub fn draw_help_box(f: &mut Frame<'_, B>) { .constraints( [ Constraint::Max(NAME_TEXT.lines().count() as u16), - Constraint::Max(description_text.lines().count() as u16), + Constraint::Max(description_text.lines().count() as u16), + Constraint::Max(help_text.lines().count() as u16), ] .as_ref(), ) @@ -538,7 +547,8 @@ pub fn draw_help_box(f: &mut Frame<'_, B>) { // Order is important here f.render_widget(Clear, area); f.render_widget(name_paragraph, split_popup[0]); - f.render_widget(description_paragraph, split_popup[1]); + f.render_widget(description_paragrpah, split_popup[1]); + f.render_widget(help_paragraph, split_popup[2]); f.render_widget(block, area); } From 757103c54fe05afcd6e3cfeba09da2a8806e8086 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 01:39:21 +0000 Subject: [PATCH 08/13] refactor: help box description from TOML --- src/app_data/container_state.rs | 4 +- src/input_handler/mod.rs | 64 +++++++++++++-------------- src/ui/draw_blocks.rs | 77 +++++++++++++++------------------ 3 files changed, 70 insertions(+), 75 deletions(-) diff --git a/src/app_data/container_state.rs b/src/app_data/container_state.rs index 3852e4c..aca3744 100644 --- a/src/app_data/container_state.rs +++ b/src/app_data/container_state.rs @@ -402,7 +402,7 @@ pub struct Columns { pub status: (String, usize), pub cpu: (String, usize), pub mem: (String, usize), - pub id: (String, usize), + pub id: (String, usize), pub name: (String, usize), pub image: (String, usize), pub net_rx: (String, usize), @@ -417,7 +417,7 @@ impl Columns { // 7 to allow for "100.00%" cpu: (String::from("cpu"), 7), mem: (String::from("memory/limit"), 12), - id: (String::from("id"), 8), + id: (String::from("id"), 8), name: (String::from("name"), 4), image: (String::from("image"), 5), net_rx: (String::from("↓ rx"), 5), diff --git a/src/input_handler/mod.rs b/src/input_handler/mod.rs index af2f63c..9baadc7 100644 --- a/src/input_handler/mod.rs +++ b/src/input_handler/mod.rs @@ -74,40 +74,40 @@ impl InputHandler { } } - fn m_button(&mut self) { - if self.mouse_capture { - match execute!(std::io::stdout(), DisableMouseCapture) { - Ok(_) => self - .gui_state - .lock() - .set_info_box("✖ mouse capture disabled".to_owned()), - Err(_) => self - .app_data - .lock() - .set_error(AppError::MouseCapture(false)), - } - } else { - match execute!(std::io::stdout(), EnableMouseCapture) { - Ok(_) => self - .gui_state - .lock() - .set_info_box("✓ mouse capture enabled".to_owned()), - Err(_) => self.app_data.lock().set_error(AppError::MouseCapture(true)), - } - }; + fn m_button(&mut self) { + if self.mouse_capture { + match execute!(std::io::stdout(), DisableMouseCapture) { + Ok(_) => self + .gui_state + .lock() + .set_info_box("✖ mouse capture disabled".to_owned()), + Err(_) => self + .app_data + .lock() + .set_error(AppError::MouseCapture(false)), + } + } else { + match execute!(std::io::stdout(), EnableMouseCapture) { + Ok(_) => self + .gui_state + .lock() + .set_info_box("✓ mouse capture enabled".to_owned()), + Err(_) => self.app_data.lock().set_error(AppError::MouseCapture(true)), + } + }; - let gui_state = Arc::clone(&self.gui_state); + let gui_state = Arc::clone(&self.gui_state); - if self.info_sleep.is_some() { - self.info_sleep.as_ref().unwrap().abort() - } - self.info_sleep = Some(tokio::spawn(async move { - tokio::time::sleep(std::time::Duration::from_millis(4000)).await; - gui_state.lock().reset_info_box() - })); + if self.info_sleep.is_some() { + self.info_sleep.as_ref().unwrap().abort() + } + self.info_sleep = Some(tokio::spawn(async move { + tokio::time::sleep(std::time::Duration::from_millis(4000)).await; + gui_state.lock().reset_info_box() + })); - self.mouse_capture = !self.mouse_capture; - } + self.mouse_capture = !self.mouse_capture; + } /// Handle any keyboard button events async fn button_press(&mut self, key_code: KeyCode) { @@ -129,7 +129,7 @@ impl InputHandler { match key_code { KeyCode::Char('q') => self.is_running.store(false, Ordering::SeqCst), KeyCode::Char('h') => self.gui_state.lock().show_help = false, - KeyCode::Char('m') => self.m_button(), + KeyCode::Char('m') => self.m_button(), _ => (), } } else { diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index 3e85ab7..9f97085 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -35,6 +35,7 @@ a8" "8a `Y8, ,8P' 88 ,a8" a8P_____88 88P' "Y8 const NAME: &str = env!("CARGO_PKG_NAME"); const VERSION: &str = env!("CARGO_PKG_VERSION"); const REPO: &str = env!("CARGO_PKG_REPOSITORY"); +const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); const ORANGE: Color = Color::Rgb(255, 178, 36); const MARGIN: &str = " "; @@ -45,7 +46,9 @@ fn generate_block<'a>( app_data: &Arc>, selected_panel: &SelectablePanel, ) -> Block<'a> { - let mut block = Block::default().borders(Borders::ALL).border_type(BorderType::Rounded); + let mut block = Block::default() + .borders(Borders::ALL) + .border_type(BorderType::Rounded); if let Some(panel) = selectable_panel { let title = match panel { @@ -65,10 +68,9 @@ fn generate_block<'a>( if selected_panel == &panel { // let selected_style = Style::default().fg(Color::LightCyan); // let selected_border = BorderType::Plain; - // let selected_border = BorderType::Rounded; - block = block - .border_style(Style::default().fg(Color::LightCyan)); - // .border_type(BorderType::Rounded); + // let selected_border = BorderType::Rounded; + block = block.border_style(Style::default().fg(Color::LightCyan)); + // .border_type(BorderType::Rounded); } } block @@ -172,8 +174,13 @@ pub fn draw_containers( format!("{}{:>width$}", MARGIN, mems, width = widths.mem.1), state_style, ), - Span::styled( - format!("{}{:>width$}", MARGIN, i.id.chars().take(8).collect::(), width = widths.id.1), + Span::styled( + format!( + "{}{:>width$}", + MARGIN, + i.id.chars().take(8).collect::(), + width = widths.id.1 + ), blue, ), Span::styled( @@ -337,7 +344,7 @@ fn make_chart( )) .borders(Borders::ALL) // .border_type(BorderType::Plain), - .border_type(BorderType::Rounded), + .border_type(BorderType::Rounded), ) .x_axis( Axis::default() @@ -386,15 +393,8 @@ pub fn draw_heading_bar( .push_str(format!("{}{:>width$}", MARGIN, columns.cpu.0, width = columns.cpu.1).as_str()); column_headings .push_str(format!("{}{:>width$}", MARGIN, columns.mem.0, width = columns.mem.1).as_str()); - column_headings.push_str( - format!( - "{}{:>width$}", - MARGIN, - columns.id.0, - width = columns.id.1 - ) - .as_str(), - ); + column_headings + .push_str(format!("{}{:>width$}", MARGIN, columns.id.0, width = columns.id.1).as_str()); column_headings.push_str( format!( "{}{:>width$}", @@ -471,23 +471,20 @@ pub fn draw_heading_bar( pub fn draw_help_box(f: &mut Frame<'_, B>) { let title = format!(" {} ", VERSION); - let description_text = String::from("\n A basic docker container information viewer and controller"); + let description_text = format!("\n{}", DESCRIPTION); let mut help_text = String::from("\n ( tab ) or ( alt+tab ) to change panels"); - help_text.push_str("\n ( ↑ ↓ ← → ) mto change selected line"); - help_text.push_str("\n ( enter ) to send docker container commands"); + help_text.push_str("\n ( ↑ ↓ ← → ) mto change selected line"); + help_text.push_str("\n ( enter ) to send docker container commands"); help_text.push_str("\n ( h ) to toggle this help information"); - help_text.push_str("\n ( m ) to toggle mouse capture - if disabled, text on screen can be selected & copied, but mouse clicks get disabled"); - help_text.push_str("\n ( q ) to quit at any time"); + help_text.push_str("\n ( m ) to toggle mouse capture - if disabled, text on screen can be selected & copied, but mouse clicks get disabled"); + help_text.push_str("\n ( q ) to quit at any time"); help_text.push_str("\n mouse scrolling & clicking also available"); - help_text - .push_str("\n\n currenty an early work in progress, all and any input appreciated"); + help_text.push_str("\n\n currenty an early work in progress, all and any input appreciated"); help_text.push_str(format!("\n {}", REPO.trim()).as_str()); let mut max_line_width = 0; - - let all_text = format!("{}{}{}", NAME_TEXT, description_text, help_text); all_text.lines().into_iter().for_each(|line| { @@ -508,8 +505,7 @@ pub fn draw_help_box(f: &mut Frame<'_, B>) { .block(Block::default()) .alignment(Alignment::Center); - - let description_paragrpah = Paragraph::new(description_text.as_str()) + let description_paragrpah = Paragraph::new(description_text.as_str()) .style(Style::default().bg(Color::Magenta).fg(Color::Black)) .block(Block::default()) .alignment(Alignment::Center); @@ -537,7 +533,7 @@ pub fn draw_help_box(f: &mut Frame<'_, B>) { .constraints( [ Constraint::Max(NAME_TEXT.lines().count() as u16), - Constraint::Max(description_text.lines().count() as u16), + Constraint::Max(description_text.lines().count() as u16), Constraint::Max(help_text.lines().count() as u16), ] .as_ref(), @@ -547,7 +543,7 @@ pub fn draw_help_box(f: &mut Frame<'_, B>) { // Order is important here f.render_widget(Clear, area); f.render_widget(name_paragraph, split_popup[0]); - f.render_widget(description_paragrpah, split_popup[1]); + f.render_widget(description_paragrpah, split_popup[1]); f.render_widget(help_paragraph, split_popup[2]); f.render_widget(block, area); } @@ -646,18 +642,17 @@ pub fn draw_info(f: &mut Frame<'_, B>, text: String) { /// draw a box in the center of the screen, based on max line width + number of lines fn draw_popup(text_lines: u16, text_width: u16, r: Rect, box_location: BoxLocation) -> Rect { - - // Make sure blank_space can't be an negative, as will crash + // Make sure blank_space can't be an negative, as will crash let blank_vertical = if r.height > text_lines { - (r.height - text_lines) / 2 - } else { - 1 - }; - let blank_horizontal = if r.width > text_width { - (r.width - text_width) / 2 - }else { - 1 - }; + (r.height - text_lines) / 2 + } else { + 1 + }; + let blank_horizontal = if r.width > text_width { + (r.width - text_width) / 2 + } else { + 1 + }; let vertical_constraints = box_location.get_vertical_constraints(blank_vertical, text_lines); let horizontal_constraints = From 836df247c45667e61be9478fd39a9ad36c32ef58 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 02:28:58 +0000 Subject: [PATCH 09/13] fix: cli arg DOCKER > ms --- src/docker_data/mod.rs | 2 +- src/parse_args/mod.rs | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/docker_data/mod.rs b/src/docker_data/mod.rs index 0ab2a94..e6364c3 100644 --- a/src/docker_data/mod.rs +++ b/src/docker_data/mod.rs @@ -220,7 +220,7 @@ impl DockerData { docker, gui_state, initialised: false, - sleep_duration: Duration::from_millis(args.docker as u64), + sleep_duration: Duration::from_millis(args.docker_interval as u64), timestamps: args.timestamp, }; inner.initialise_container_data().await; diff --git a/src/parse_args/mod.rs b/src/parse_args/mod.rs index 351917a..6133465 100644 --- a/src/parse_args/mod.rs +++ b/src/parse_args/mod.rs @@ -8,13 +8,17 @@ use tracing::error; pub struct CliArgs { /// Docker update interval in ms, minimum 1, reccomended 500+ - #[clap(short = 'd', default_value_t = 1000)] - pub docker: u32, + #[clap(short = 'd', value_name = "ms", default_value_t = 1000)] + pub docker_interval: u32, /// Don't draw gui - for debugging - mostly pointless #[clap(short = 'g')] pub gui: bool, + /// Install to ./local/bin + #[clap(short = 'i')] + pub install: bool, + /// Remove timestamps from Docker logs #[clap(short = 't')] pub timestamp: bool, @@ -35,15 +39,16 @@ impl CliArgs { // Quit the program if the docker update argument is 0 // Should maybe change it to check if less than 100 - if args.docker == 0 { + if args.docker_interval == 0 { error!("docker args needs to be greater than 0"); process::exit(1) } Self { color: args.color, - docker: args.docker, + docker_interval: args.docker_interval, gui: !args.gui, raw: args.raw, + install: args.install, timestamp: !args.timestamp, } } From 3542f65e61543df8dbcb9bbb6ac3714ed1d5c6c7 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 03:10:41 +0000 Subject: [PATCH 10/13] refactor: dead space removed --- src/parse_args/mod.rs | 9 ++++----- src/ui/draw_blocks.rs | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/parse_args/mod.rs b/src/parse_args/mod.rs index 6133465..524da85 100644 --- a/src/parse_args/mod.rs +++ b/src/parse_args/mod.rs @@ -15,10 +15,9 @@ pub struct CliArgs { #[clap(short = 'g')] pub gui: bool, - /// Install to ./local/bin - #[clap(short = 'i')] - pub install: bool, - + // /// Install to ./local/bin + // #[clap(short = 'i')] + // pub install: bool, /// Remove timestamps from Docker logs #[clap(short = 't')] pub timestamp: bool, @@ -48,7 +47,7 @@ impl CliArgs { docker_interval: args.docker_interval, gui: !args.gui, raw: args.raw, - install: args.install, + // install: args.install, timestamp: !args.timestamp, } } diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index 9f97085..20dfc50 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -471,7 +471,7 @@ pub fn draw_heading_bar( pub fn draw_help_box(f: &mut Frame<'_, B>) { let title = format!(" {} ", VERSION); - let description_text = format!("\n{}", DESCRIPTION); + let description_text = format!("\n{}", DESCRIPTION); let mut help_text = String::from("\n ( tab ) or ( alt+tab ) to change panels"); help_text.push_str("\n ( ↑ ↓ ← → ) mto change selected line"); From 1daf1c177d90e98916865409e9b932a3d933411c Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 03:14:35 +0000 Subject: [PATCH 11/13] fix: info box lines --- src/ui/draw_blocks.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index 20dfc50..451a3ac 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -608,8 +608,6 @@ pub fn draw_info(f: &mut Frame<'_, B>, text: String) { .title_alignment(Alignment::Center) .borders(Borders::NONE); - // Add a blank line, so that the text is verticall centered - let text = format!("\n{}", text); let mut max_line_width = 0; text.lines().into_iter().for_each(|line| { @@ -623,7 +621,7 @@ pub fn draw_info(f: &mut Frame<'_, B>, text: String) { // Add some horizontal & vertical margins max_line_width += 8; - lines += 3; + lines += 2; let paragraph = Paragraph::new(text) .style(Style::default().bg(Color::Blue).fg(Color::White)) From bfd5ab87733d8c54e5edcf3ec86ef888654c5f8b Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 14:24:34 +0000 Subject: [PATCH 12/13] fix: help box typos --- src/ui/draw_blocks.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index 451a3ac..a04628f 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -474,10 +474,10 @@ pub fn draw_help_box(f: &mut Frame<'_, B>) { let description_text = format!("\n{}", DESCRIPTION); let mut help_text = String::from("\n ( tab ) or ( alt+tab ) to change panels"); - help_text.push_str("\n ( ↑ ↓ ← → ) mto change selected line"); + help_text.push_str("\n ( ↑ ↓ ← → ) to change selected line"); help_text.push_str("\n ( enter ) to send docker container commands"); help_text.push_str("\n ( h ) to toggle this help information"); - help_text.push_str("\n ( m ) to toggle mouse capture - if disabled, text on screen can be selected & copied, but mouse clicks get disabled"); + help_text.push_str("\n ( m ) to toggle mouse capture - if disabled, text on screen can be selected & copied"); help_text.push_str("\n ( q ) to quit at any time"); help_text.push_str("\n mouse scrolling & clicking also available"); help_text.push_str("\n\n currenty an early work in progress, all and any input appreciated"); From 4b46efe89d737c64f0169deaac6ac4ea1987d199 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Fri, 29 Apr 2022 14:28:29 +0000 Subject: [PATCH 13/13] fix: gui typo --- src/ui/draw_blocks.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/ui/draw_blocks.rs b/src/ui/draw_blocks.rs index a04628f..4d71af0 100644 --- a/src/ui/draw_blocks.rs +++ b/src/ui/draw_blocks.rs @@ -39,7 +39,7 @@ const DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); const ORANGE: Color = Color::Rgb(255, 178, 36); const MARGIN: &str = " "; -/// Generate block, add a bored if is the selected panel, +/// Generate block, add a border if is the selected panel, /// add custom title based on state of each panel fn generate_block<'a>( selectable_panel: Option, @@ -66,11 +66,7 @@ fn generate_block<'a>( }; block = block.title(title); if selected_panel == &panel { - // let selected_style = Style::default().fg(Color::LightCyan); - // let selected_border = BorderType::Plain; - // let selected_border = BorderType::Rounded; block = block.border_style(Style::default().fg(Color::LightCyan)); - // .border_type(BorderType::Rounded); } } block @@ -343,7 +339,6 @@ fn make_chart( .add_modifier(Modifier::BOLD), )) .borders(Borders::ALL) - // .border_type(BorderType::Plain), .border_type(BorderType::Rounded), ) .x_axis( @@ -362,7 +357,6 @@ fn make_chart( .fg(label_color), ), ]) - // add 0.01, for cases when the value is 0 .bounds([0.0, max.get_value() + 0.01]), ) }