refactor: Revert tui upgrade to 0.10

Reverts tui upgrade, there are some bugs and issues - namely, issues with rendering text.
We can revert this commit when those bugs are dealt with (should be fine after 0.10.1, tested building from the repo).
This commit is contained in:
Clement Tsang 2020-08-16 01:25:59 -07:00 committed by GitHub
parent 9068108d0f
commit 08e49b63c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 546 additions and 424 deletions

6
Cargo.lock generated
View File

@ -1345,13 +1345,15 @@ checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
[[package]] [[package]]
name = "tui" name = "tui"
version = "0.10.0" version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a977b0bb2e2033a6fef950f218f13622c3c34e59754b704ce3492dedab1dfe95" checksum = "9533d39bef0ae8f510e8a99d78702e68d1bbf0b98a78ec9740509d287010ae1e"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cassowary", "cassowary",
"crossterm", "crossterm",
"either",
"itertools",
"unicode-segmentation", "unicode-segmentation",
"unicode-width", "unicode-width",
] ]

View File

@ -39,7 +39,7 @@ serde = {version = "1.0", features = ["derive"] }
unicode-segmentation = "1.6.0" unicode-segmentation = "1.6.0"
unicode-width = "0.1.7" unicode-width = "0.1.7"
# tui = {version = "0.10.0", features = ["crossterm"], default-features = false, git = "https://github.com/fdehau/tui-rs.git"} # tui = {version = "0.10.0", features = ["crossterm"], default-features = false, git = "https://github.com/fdehau/tui-rs.git"}
tui = {version = "0.10.0", features = ["crossterm"], default-features = false } tui = {version = "0.9.5", features = ["crossterm"], default-features = false }
# For debugging only... # For debugging only...
fern = "0.6.0" fern = "0.6.0"

View File

@ -4,7 +4,7 @@ use std::collections::HashMap;
use tui::{ use tui::{
backend::Backend, backend::Backend,
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
text::{Span, Spans}, widgets::Text,
Frame, Terminal, Frame, Terminal,
}; };
@ -55,7 +55,7 @@ pub struct Painter {
pub colours: CanvasColours, pub colours: CanvasColours,
height: u16, height: u16,
width: u16, width: u16,
styled_help_text: Vec<Spans<'static>>, styled_help_text: Vec<Text<'static>>,
is_mac_os: bool, is_mac_os: bool,
row_constraints: Vec<Constraint>, row_constraints: Vec<Constraint>,
col_constraints: Vec<Vec<Constraint>>, col_constraints: Vec<Vec<Constraint>>,
@ -163,27 +163,28 @@ impl Painter {
styled_help_spans.extend( styled_help_spans.extend(
section section
.iter() .iter()
.map(|&text| Span::styled(text, self.colours.text_style)) .map(|&text| Text::styled(text, self.colours.text_style))
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
); );
} else { } else {
// Not required check but it runs only a few times... so whatever ig, prevents me from // Not required check but it runs only a few times... so whatever ig, prevents me from
// being dumb and leaving a help text section only one line long. // being dumb and leaving a help text section only one line long.
if section.len() > 1 { if section.len() > 1 {
styled_help_spans.push(Span::from("")); styled_help_spans.push(Text::raw("\n\n"));
styled_help_spans styled_help_spans
.push(Span::styled(section[0], self.colours.table_header_style)); .push(Text::styled(section[0], self.colours.table_header_style));
styled_help_spans.extend( styled_help_spans.extend(
section[1..] section[1..]
.iter() .iter()
.map(|&text| Span::styled(text, self.colours.text_style)) .map(|&text| Text::styled(text, self.colours.text_style))
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
); );
} }
} }
}); });
self.styled_help_text = styled_help_spans.into_iter().map(Spans::from).collect(); // self.styled_help_text = styled_help_spans.into_iter().map(Spans::from).collect();
self.styled_help_text = styled_help_spans;
} }
pub fn draw_data<B: Backend>( pub fn draw_data<B: Backend>(
@ -251,36 +252,44 @@ impl Painter {
let dd_text = self.get_dd_spans(app_state); let dd_text = self.get_dd_spans(app_state);
let (text_width, text_height) = if let Some(dd_text) = &dd_text { let (text_width, text_height) = (
let width = if f.size().width < 100 { if f.size().width < 100 {
f.size().width * 90 / 100 f.size().width * 90 / 100
} else { } else {
let min_possible_width = (f.size().width * 50 / 100) as usize; f.size().width * 50 / 100
let mut width = dd_text.width(); },
7,
);
// let (text_width, text_height) = if let Some(dd_text) = &dd_text {
// let width = if f.size().width < 100 {
// f.size().width * 90 / 100
// } else {
// let min_possible_width = (f.size().width * 50 / 100) as usize;
// let mut width = dd_text.width();
// This should theoretically never allow width to be 0... we can be safe and do an extra check though. // // This should theoretically never allow width to be 0... we can be safe and do an extra check though.
while width > (f.size().width as usize) && width / 2 > min_possible_width { // while width > (f.size().width as usize) && width / 2 > min_possible_width {
width /= 2; // width /= 2;
} // }
std::cmp::max(width, min_possible_width) as u16 // std::cmp::max(width, min_possible_width) as u16
}; // };
( // (
width, // width,
(dd_text.height() + 2 + (dd_text.width() / width as usize)) as u16, // (dd_text.height() + 2 + (dd_text.width() / width as usize)) as u16,
) // )
} else { // } else {
// AFAIK this shouldn't happen, unless something went wrong... // // AFAIK this shouldn't happen, unless something went wrong...
( // (
if f.size().width < 100 { // if f.size().width < 100 {
f.size().width * 90 / 100 // f.size().width * 90 / 100
} else { // } else {
f.size().width * 50 / 100 // f.size().width * 50 / 100
}, // },
7, // 7,
) // )
}; // };
let vertical_bordering = f.size().height.saturating_sub(text_height) / 2; let vertical_bordering = f.size().height.saturating_sub(text_height) / 2;
let vertical_dialog_chunk = Layout::default() let vertical_dialog_chunk = Layout::default()

View File

@ -85,7 +85,7 @@ impl CanvasColours {
} }
pub fn set_table_header_colour(&mut self, colour: &str) -> error::Result<()> { pub fn set_table_header_colour(&mut self, colour: &str) -> error::Result<()> {
self.table_header_style = get_style_from_config(colour)?.add_modifier(Modifier::BOLD); self.table_header_style = get_style_from_config(colour)?.modifier(Modifier::BOLD);
Ok(()) Ok(())
} }

View File

@ -2,8 +2,7 @@ use tui::{
backend::Backend, backend::Backend,
layout::{Alignment, Rect}, layout::{Alignment, Rect},
terminal::Frame, terminal::Frame,
text::{Span, Spans, Text}, widgets::{Block, Borders, Paragraph, Text},
widgets::{Block, Borders, Paragraph, Wrap},
}; };
use crate::{app::App, canvas::Painter}; use crate::{app::App, canvas::Painter};
@ -12,61 +11,58 @@ const DD_BASE: &str = " Confirm Kill Process ── Esc to close ";
const DD_ERROR_BASE: &str = " Error ── Esc to close "; const DD_ERROR_BASE: &str = " Error ── Esc to close ";
pub trait KillDialog { pub trait KillDialog {
fn get_dd_spans(&self, app_state: &App) -> Option<Text<'_>>; fn get_dd_spans(&self, app_state: &App) -> Option<Vec<Text<'_>>>;
fn draw_dd_dialog<B: Backend>( fn draw_dd_dialog<B: Backend>(
&self, f: &mut Frame<'_, B>, dd_text: Option<Text<'_>>, app_state: &App, draw_loc: Rect, &self, f: &mut Frame<'_, B>, dd_text: Option<Vec<Text<'_>>>, app_state: &App,
draw_loc: Rect,
) -> bool; ) -> bool;
} }
impl KillDialog for Painter { impl KillDialog for Painter {
fn get_dd_spans(&self, app_state: &App) -> Option<Text<'_>> { fn get_dd_spans(&self, app_state: &App) -> Option<Vec<Text<'_>>> {
if let Some(dd_err) = &app_state.dd_err { if let Some(dd_err) = &app_state.dd_err {
return Some(Text::from(Spans::from(format!( return Some(vec![
"Failure to properly kill the process - {}", Text::raw("\n"),
dd_err Text::raw(format!("Failure to properly kill the process - {}", dd_err)),
)))); ]);
} else if let Some(to_kill_processes) = app_state.get_to_delete_processes() { } else if let Some(to_kill_processes) = app_state.get_to_delete_processes() {
if let Some(first_pid) = to_kill_processes.1.first() { if let Some(first_pid) = to_kill_processes.1.first() {
return Some(Text::from(vec![ return Some(vec![
Spans::from(vec![]), Text::raw("\n"),
Spans::from(vec![ if app_state.is_grouped(app_state.current_widget.widget_id) {
if app_state.is_grouped(app_state.current_widget.widget_id) { if to_kill_processes.1.len() != 1 {
if to_kill_processes.1.len() != 1 { Text::raw(format!(
Span::from(format!( "Kill {} processes with the name \"{}\"?",
"Kill {} processes with the name \"{}\"?", to_kill_processes.1.len(),
to_kill_processes.1.len(), to_kill_processes.0
to_kill_processes.0
))
} else {
Span::from(format!(
"Kill 1 process with the name \"{}\"?",
to_kill_processes.0
))
}
} else {
Span::from(format!(
"Kill process \"{}\" with PID {}?",
to_kill_processes.0, first_pid
)) ))
},
]),
Spans::from(vec![]),
Spans::from(vec![
if app_state.delete_dialog_state.is_on_yes {
Span::styled("Yes", self.colours.currently_selected_text_style)
} else { } else {
Span::from("Yes") Text::raw(format!(
}, "Kill 1 process with the name \"{}\"?",
Span::from(" "), to_kill_processes.0
if app_state.delete_dialog_state.is_on_yes { ))
Span::from("No") }
} else { } else {
Span::styled("No", self.colours.currently_selected_text_style) Text::raw(format!(
}, "Kill process \"{}\" with PID {}?",
]), to_kill_processes.0, first_pid
Spans::from(vec![]), ))
])); },
Text::raw("\n\n"),
if app_state.delete_dialog_state.is_on_yes {
Text::styled("Yes", self.colours.currently_selected_text_style)
} else {
Text::raw("Yes")
},
Text::raw(" "),
if app_state.delete_dialog_state.is_on_yes {
Text::raw("No")
} else {
Text::styled("No", self.colours.currently_selected_text_style)
},
Text::raw("\n"),
]);
} }
} }
@ -74,44 +70,63 @@ impl KillDialog for Painter {
} }
fn draw_dd_dialog<B: Backend>( fn draw_dd_dialog<B: Backend>(
&self, f: &mut Frame<'_, B>, dd_text: Option<Text<'_>>, app_state: &App, draw_loc: Rect, &self, f: &mut Frame<'_, B>, dd_text: Option<Vec<Text<'_>>>, app_state: &App,
draw_loc: Rect,
) -> bool { ) -> bool {
if let Some(dd_text) = dd_text { if let Some(dd_text) = dd_text {
// let dd_title = if app_state.dd_err.is_some() {
// Text::styled(
// format!(
// " Error ─{}─ Esc to close ",
// "─".repeat(
// usize::from(draw_loc.width)
// .saturating_sub(DD_ERROR_BASE.chars().count() + 2)
// )
// ),
// self.colours.border_style,
// )
// } else {
// Text::styled(
// format!(
// " Confirm Kill Process ─{}─ Esc to close ",
// "─".repeat(
// usize::from(draw_loc.width).saturating_sub(DD_BASE.chars().count() + 2)
// )
// ),
// self.colours.border_style,
// )
// };
let dd_title = if app_state.dd_err.is_some() { let dd_title = if app_state.dd_err.is_some() {
Span::styled( format!(
format!( " Error ─{}─ Esc to close ",
" Error ─{}─ Esc to close ", "".repeat(
"".repeat( usize::from(draw_loc.width)
usize::from(draw_loc.width) .saturating_sub(DD_ERROR_BASE.chars().count() + 2)
.saturating_sub(DD_ERROR_BASE.chars().count() + 2) )
)
),
self.colours.border_style,
) )
} else { } else {
Span::styled( format!(
format!( " Confirm Kill Process ─{}─ Esc to close ",
" Confirm Kill Process ─{}─ Esc to close ", "".repeat(
"".repeat( usize::from(draw_loc.width).saturating_sub(DD_BASE.chars().count() + 2)
usize::from(draw_loc.width).saturating_sub(DD_BASE.chars().count() + 2) )
)
),
self.colours.border_style,
) )
}; };
f.render_widget( f.render_widget(
Paragraph::new(dd_text) Paragraph::new(dd_text.iter())
.block( .block(
Block::default() Block::default()
.title(dd_title) .title(&dd_title)
.title_style(self.colours.border_style)
.style(self.colours.border_style) .style(self.colours.border_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(self.colours.border_style), .border_style(self.colours.border_style),
) )
.style(self.colours.text_style) .style(self.colours.text_style)
.alignment(Alignment::Center) .alignment(Alignment::Center)
.wrap(Wrap { trim: true }), .wrap(true),
draw_loc, draw_loc,
); );

View File

@ -4,8 +4,7 @@ use tui::{
backend::Backend, backend::Backend,
layout::{Alignment, Rect}, layout::{Alignment, Rect},
terminal::Frame, terminal::Frame,
text::Span, widgets::{Block, Borders, Paragraph},
widgets::{Block, Borders, Paragraph, Wrap},
}; };
use crate::{app::App, canvas::Painter, constants}; use crate::{app::App, canvas::Painter, constants};
@ -22,14 +21,19 @@ impl HelpDialog for Painter {
fn draw_help_dialog<B: Backend>( fn draw_help_dialog<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect,
) { ) {
let help_title = Span::styled( // let help_title = Text::styled(
format!( // format!(
" Help ─{}─ Esc to close ", // " Help ─{}─ Esc to close ",
"".repeat( // "─".repeat(
usize::from(draw_loc.width).saturating_sub(HELP_BASE.chars().count() + 2) // usize::from(draw_loc.width).saturating_sub(HELP_BASE.chars().count() + 2)
) // )
), // ),
self.colours.border_style, // self.colours.border_style,
// );
let help_title = format!(
" Help ─{}─ Esc to close ",
"".repeat(usize::from(draw_loc.width).saturating_sub(HELP_BASE.chars().count() + 2))
); );
if app_state.is_force_redraw { if app_state.is_force_redraw {
@ -95,24 +99,24 @@ impl HelpDialog for Painter {
} }
f.render_widget( f.render_widget(
Paragraph::new(self.styled_help_text.clone()) Paragraph::new(self.styled_help_text.iter())
.block( .block(
Block::default() Block::default()
.title(help_title) .title(&help_title)
.title_style(self.colours.border_style)
.style(self.colours.border_style) .style(self.colours.border_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(self.colours.border_style), .border_style(self.colours.border_style),
) )
.style(self.colours.text_style) .style(self.colours.text_style)
.alignment(Alignment::Left) .alignment(Alignment::Left)
.wrap(Wrap { trim: true }) .wrap(true)
.scroll(( .scroll(
app_state app_state
.help_dialog_state .help_dialog_state
.scroll_state .scroll_state
.current_scroll_index, .current_scroll_index,
0, ),
)),
draw_loc, draw_loc,
); );
} }

View File

@ -10,8 +10,7 @@ use tui::{
backend::Backend, backend::Backend,
layout::{Constraint, Layout, Rect}, layout::{Constraint, Layout, Rect},
terminal::Frame, terminal::Frame,
text::{Span, Spans}, widgets::{Block, Paragraph, Text},
widgets::{Block, Paragraph},
}; };
pub trait BasicTableArrows { pub trait BasicTableArrows {
@ -98,12 +97,10 @@ impl BasicTableArrows for Painter {
usize::from(draw_loc.width).saturating_sub(6 + left_name.len() + right_name.len()); usize::from(draw_loc.width).saturating_sub(6 + left_name.len() + right_name.len());
let arrow_text = vec![ let arrow_text = vec![
Spans::from(Span::from(String::default())), Text::raw("\n"),
Spans::from(vec![ Text::styled(format!("{}", left_name), self.colours.text_style),
Span::styled(format!("{}", left_name), self.colours.text_style), Text::raw(" ".repeat(num_spaces)),
Span::from(" ".repeat(num_spaces)), Text::styled(format!("{}", right_name), self.colours.text_style),
Span::styled(format!("{}", right_name), self.colours.text_style),
]),
]; ];
let margined_draw_loc = Layout::default() let margined_draw_loc = Layout::default()
@ -112,7 +109,7 @@ impl BasicTableArrows for Painter {
.split(draw_loc); .split(draw_loc);
f.render_widget( f.render_widget(
Paragraph::new(arrow_text).block(Block::default()), Paragraph::new(arrow_text.iter()).block(Block::default()),
margined_draw_loc[0], margined_draw_loc[0],
); );
} }

View File

@ -8,8 +8,7 @@ use tui::{
backend::Backend, backend::Backend,
layout::{Constraint, Rect}, layout::{Constraint, Rect},
terminal::Frame, terminal::Frame,
text::{Span, Spans}, widgets::{Block, Borders, Paragraph, Row, Table, Tabs, Text},
widgets::{Block, Borders, Paragraph, Row, Table, Tabs},
}; };
pub trait BatteryDisplayWidget { pub trait BatteryDisplayWidget {
@ -34,25 +33,45 @@ impl BatteryDisplayWidget for Painter {
self.colours.border_style self.colours.border_style
}; };
// let title = if app_state.is_expanded {
// const TITLE_BASE: &str = " Battery ── Esc to go back ";
// Span::styled(
// format!(
// " Battery ─{}─ Esc to go back ",
// "─".repeat(
// usize::from(draw_loc.width)
// .saturating_sub(TITLE_BASE.chars().count() + 2)
// )
// ),
// border_and_title_style,
// )
// } else {
// Span::styled(" Battery ".to_string(), self.colours.widget_title_style)
// };
let title = if app_state.is_expanded { let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Battery ── Esc to go back "; const TITLE_BASE: &str = " Battery ── Esc to go back ";
Span::styled(
format!( format!(
" Battery ─{}─ Esc to go back ", " Battery ─{}─ Esc to go back ",
"".repeat( "".repeat(
usize::from(draw_loc.width) usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
.saturating_sub(TITLE_BASE.chars().count() + 2) )
)
),
border_and_title_style,
) )
} else { } else {
Span::styled(" Battery ".to_string(), self.colours.widget_title_style) " Battery ".to_string()
};
let title_style = if app_state.is_expanded {
border_and_title_style
} else {
self.colours.widget_title_style
}; };
let battery_block = if draw_border { let battery_block = if draw_border {
Block::default() Block::default()
.title(title) .title(&title)
.title_style(title_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(border_and_title_style) .border_style(border_and_title_style)
} else if is_on_widget { } else if is_on_widget {
@ -63,22 +82,32 @@ impl BatteryDisplayWidget for Painter {
Block::default().borders(Borders::NONE) Block::default().borders(Borders::NONE)
}; };
f.render_widget( // f.render_widget(
Tabs::new( // // Tabs::new(
(app_state // // (app_state
.canvas_data // // .canvas_data
.battery_data // // .battery_data
.iter() // // .iter()
.map(|battery| Spans::from(battery.battery_name.clone()))) // // .map(|battery| Spans::from(battery.battery_name.clone())))
.collect::<Vec<_>>(), // // .collect::<Vec<_>>(),
) // // )
.block(battery_block.clone()) // Tabs::default()
.divider(tui::symbols::line::VERTICAL) // .titles(
.style(self.colours.text_style) // app_state
.highlight_style(self.colours.currently_selected_text_style) // .canvas_data
.select(battery_widget_state.currently_selected_battery_index), // .battery_data
draw_loc, // .iter()
); // .map(|battery| &battery.battery_name)
// .collect::<Vec<_>>()
// .as_ref(),
// )
// .block(battery_block)
// .divider(tui::symbols::line::VERTICAL)
// .style(self.colours.text_style)
// .highlight_style(self.colours.currently_selected_text_style)
// .select(battery_widget_state.currently_selected_battery_index),
// draw_loc,
// );
if let Some(battery_details) = app_state if let Some(battery_details) = app_state
.canvas_data .canvas_data
@ -134,21 +163,52 @@ impl BatteryDisplayWidget for Painter {
// Draw // Draw
f.render_widget( f.render_widget(
Table::new([""].iter(), battery_rows) Table::new([""].iter(), battery_rows)
.block(battery_block.clone()) .block(battery_block)
.header_style(self.colours.table_header_style) .header_style(self.colours.table_header_style)
.widths([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()), .widths([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()),
draw_loc, draw_loc,
); );
} else { } else {
f.render_widget( f.render_widget(
Paragraph::new(Spans::from(Span::styled( Paragraph::new(
"No data found for this battery", [Text::styled(
self.colours.text_style, "No data found for this battery",
))) self.colours.text_style,
)]
.iter(),
)
.block(battery_block), .block(battery_block),
draw_loc, draw_loc,
); );
} }
// Has to be placed AFTER for tui 0.9, place BEFORE for 0.10.
f.render_widget(
// Tabs::new(
// (app_state
// .canvas_data
// .battery_data
// .iter()
// .map(|battery| Spans::from(battery.battery_name.clone())))
// .collect::<Vec<_>>(),
// )
Tabs::default()
.titles(
app_state
.canvas_data
.battery_data
.iter()
.map(|battery| &battery.battery_name)
.collect::<Vec<_>>()
.as_ref(),
)
.block(battery_block)
.divider(tui::symbols::line::VERTICAL)
.style(self.colours.text_style)
.highlight_style(self.colours.currently_selected_text_style)
.select(battery_widget_state.currently_selected_battery_index),
draw_loc,
);
} }
} }
} }

View File

@ -11,8 +11,7 @@ use tui::{
backend::Backend, backend::Backend,
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
terminal::Frame, terminal::Frame,
text::{Span, Spans}, widgets::{Block, Paragraph, Text},
widgets::{Block, Paragraph},
}; };
pub trait CpuBasicWidget { pub trait CpuBasicWidget {
@ -77,10 +76,10 @@ impl CpuBasicWidget for Painter {
let num_bars = calculate_basic_use_bars(use_percentage, bar_length); let num_bars = calculate_basic_use_bars(use_percentage, bar_length);
format!( format!(
"{:3}[{}{}{:3.0}%]", "{:3}[{}{}{:3.0}%]\n",
if app_state.app_config_fields.show_average_cpu { if app_state.app_config_fields.show_average_cpu {
if cpu_index == 0 { if cpu_index == 0 {
" AVG".to_string() "AVG".to_string()
} else { } else {
(cpu_index - 1).to_string() (cpu_index - 1).to_string()
} }
@ -109,11 +108,16 @@ impl CpuBasicWidget for Painter {
let end_index = min(start_index + how_many_cpus, num_cpus); let end_index = min(start_index + how_many_cpus, num_cpus);
let cpu_column = (start_index..end_index) let cpu_column = (start_index..end_index)
.map(|cpu_index| { .map(|cpu_index| {
Spans::from(Span { // Spans::from(Span {
content: (&cpu_bars[cpu_index]).into(), // content: (&cpu_bars[cpu_index]).into(),
style: self.colours.cpu_colour_styles // style: self.colours.cpu_colour_styles
// [cpu_index % self.colours.cpu_colour_styles.len()],
// })
Text::styled(
&cpu_bars[cpu_index],
self.colours.cpu_colour_styles
[cpu_index % self.colours.cpu_colour_styles.len()], [cpu_index % self.colours.cpu_colour_styles.len()],
}) )
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -126,7 +130,7 @@ impl CpuBasicWidget for Painter {
.split(*chunk); .split(*chunk);
f.render_widget( f.render_widget(
Paragraph::new(cpu_column).block(Block::default()), Paragraph::new(cpu_column.iter()).block(Block::default()),
margined_loc[0], margined_loc[0],
); );
} }

View File

@ -17,7 +17,6 @@ use tui::{
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
symbols::Marker, symbols::Marker,
terminal::Frame, terminal::Frame,
text::Span,
widgets::{Axis, Block, Borders, Chart, Dataset, Row, Table}, widgets::{Axis, Block, Borders, Chart, Dataset, Row, Table},
}; };
@ -104,12 +103,17 @@ impl CpuGraphWidget for Painter {
if let Some(cpu_widget_state) = app_state.cpu_state.widget_states.get_mut(&widget_id) { if let Some(cpu_widget_state) = app_state.cpu_state.widget_states.get_mut(&widget_id) {
let cpu_data: &mut [ConvertedCpuData] = &mut app_state.canvas_data.cpu_data; let cpu_data: &mut [ConvertedCpuData] = &mut app_state.canvas_data.cpu_data;
let display_time_labels = vec![ // let display_time_labels = vec![
Span::styled( // Text::styled(
format!("{}s", cpu_widget_state.current_display_time / 1000), // format!("{}s", cpu_widget_state.current_display_time / 1000),
self.colours.graph_style, // self.colours.graph_style,
), // ),
Span::styled("0s".to_string(), self.colours.graph_style), // Text::styled("0s".to_string(), self.colours.graph_style),
// ];
let display_time_labels = [
format!("{}s", cpu_widget_state.current_display_time / 1000),
"0s".to_string(),
]; ];
let x_axis = if app_state.app_config_fields.hide_time let x_axis = if app_state.app_config_fields.hide_time
@ -124,7 +128,8 @@ impl CpuGraphWidget for Painter {
Axis::default() Axis::default()
.bounds([-(cpu_widget_state.current_display_time as f64), 0.0]) .bounds([-(cpu_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style) .style(self.colours.graph_style)
.labels(display_time_labels) .labels(&display_time_labels)
.labels_style(self.colours.graph_style)
} else { } else {
cpu_widget_state.autohide_timer = None; cpu_widget_state.autohide_timer = None;
Axis::default().bounds([-(cpu_widget_state.current_display_time as f64), 0.0]) Axis::default().bounds([-(cpu_widget_state.current_display_time as f64), 0.0])
@ -135,17 +140,16 @@ impl CpuGraphWidget for Painter {
Axis::default() Axis::default()
.bounds([-(cpu_widget_state.current_display_time as f64), 0.0]) .bounds([-(cpu_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style) .style(self.colours.graph_style)
.labels(display_time_labels) .labels(&display_time_labels)
.labels_style(self.colours.graph_style)
}; };
// Note this is offset as otherwise the 0 value is not drawn! // Note this is offset as otherwise the 0 value is not drawn!
let y_axis = Axis::default() let y_axis = Axis::default()
.style(self.colours.graph_style) .style(self.colours.graph_style)
.bounds([-0.5, 100.5]) .bounds([-0.5, 100.5])
.labels(vec![ .labels_style(self.colours.graph_style)
Span::styled("0%", self.colours.graph_style), .labels(&["0%", "100%"]);
Span::styled("100%", self.colours.graph_style),
]);
let use_dot = app_state.app_config_fields.use_dot; let use_dot = app_state.app_config_fields.use_dot;
let show_avg_cpu = app_state.app_config_fields.show_average_cpu; let show_avg_cpu = app_state.app_config_fields.show_average_cpu;
@ -199,17 +203,26 @@ impl CpuGraphWidget for Painter {
self.colours.border_style self.colours.border_style
}; };
let title = if app_state.is_expanded { // let title = if app_state.is_expanded {
Span::styled(" CPU ".to_string(), border_style) // Span::styled(" CPU ".to_string(), border_style)
// } else {
// Span::styled(" CPU ".to_string(), self.colours.widget_title_style)
// };
let title = " CPU ";
let title_style = if app_state.is_expanded {
border_style
} else { } else {
Span::styled(" CPU ".to_string(), self.colours.widget_title_style) self.colours.widget_title_style
}; };
f.render_widget( f.render_widget(
Chart::new(dataset_vector) // Chart::new(dataset_vector)
Chart::default()
.datasets(&dataset_vector)
.block( .block(
Block::default() Block::default()
.title(title) .title(title)
.title_style(title_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(border_style), .border_style(border_style),
) )

View File

@ -4,7 +4,6 @@ use tui::{
backend::Backend, backend::Backend,
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
terminal::Frame, terminal::Frame,
text::Span,
widgets::{Block, Borders, Row, Table}, widgets::{Block, Borders, Row, Table},
}; };
@ -77,27 +76,48 @@ impl DiskTableWidget for Painter {
(self.colours.border_style, self.colours.text_style) (self.colours.border_style, self.colours.text_style)
}; };
// let title = if app_state.is_expanded {
// const TITLE_BASE: &str = " Disk ── Esc to go back ";
// Span::styled(
// format!(
// " Disk ─{}─ Esc to go back ",
// "─".repeat(
// usize::from(draw_loc.width)
// .saturating_sub(TITLE_BASE.chars().count() + 2)
// )
// ),
// border_and_title_style,
// )
// } else if app_state.app_config_fields.use_basic_mode {
// Span::from(String::new())
// } else {
// Span::styled(" Disk ".to_string(), self.colours.widget_title_style)
// };
let title = if app_state.is_expanded { let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Disk ── Esc to go back "; const TITLE_BASE: &str = " Disk ── Esc to go back ";
Span::styled( format!(
format!( " Disk ─{}─ Esc to go back ",
" Disk ─{}─ Esc to go back ", "".repeat(
"".repeat( usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
usize::from(draw_loc.width) )
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
),
border_and_title_style,
) )
} else if app_state.app_config_fields.use_basic_mode { } else if app_state.app_config_fields.use_basic_mode {
Span::from(String::new()) String::new()
} else { } else {
Span::styled(" Disk ".to_string(), self.colours.widget_title_style) " Disk ".to_string()
};
let title_style = if app_state.is_expanded {
border_and_title_style
} else {
self.colours.widget_title_style
}; };
let disk_block = if draw_border { let disk_block = if draw_border {
Block::default() Block::default()
.title(title) .title(&title)
.title_style(title_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(border_and_title_style) .border_style(border_and_title_style)
} else if is_on_widget { } else if is_on_widget {

View File

@ -8,8 +8,7 @@ use tui::{
backend::Backend, backend::Backend,
layout::{Constraint, Layout, Rect}, layout::{Constraint, Layout, Rect},
terminal::Frame, terminal::Frame,
text::{Span, Spans}, widgets::{Block, Paragraph, Text},
widgets::{Block, Paragraph},
}; };
pub trait MemBasicWidget { pub trait MemBasicWidget {
@ -54,7 +53,7 @@ impl MemBasicWidget for Painter {
let num_bars_ram = calculate_basic_use_bars(ram_use_percentage, bar_length); let num_bars_ram = calculate_basic_use_bars(ram_use_percentage, bar_length);
let num_bars_swap = calculate_basic_use_bars(swap_use_percentage, bar_length); let num_bars_swap = calculate_basic_use_bars(swap_use_percentage, bar_length);
let mem_label = format!( let mem_label = format!(
"RAM[{}{}{:3.0}%]", "RAM[{}{}{:3.0}%]\n",
"|".repeat(num_bars_ram), "|".repeat(num_bars_ram),
" ".repeat(bar_length - num_bars_ram), " ".repeat(bar_length - num_bars_ram),
ram_use_percentage.round(), ram_use_percentage.round(),
@ -66,13 +65,13 @@ impl MemBasicWidget for Painter {
swap_use_percentage.round(), swap_use_percentage.round(),
); );
let mem_text = vec![ let mem_text = [
Spans::from(Span::styled(mem_label, self.colours.ram_style)), Text::styled(mem_label, self.colours.ram_style),
Spans::from(Span::styled(swap_label, self.colours.swap_style)), Text::styled(swap_label, self.colours.swap_style),
]; ];
f.render_widget( f.render_widget(
Paragraph::new(mem_text).block(Block::default()), Paragraph::new(mem_text.iter()).block(Block::default()),
margined_loc[0], margined_loc[0],
); );
} }

View File

@ -5,7 +5,6 @@ use tui::{
layout::{Constraint, Rect}, layout::{Constraint, Rect},
symbols::Marker, symbols::Marker,
terminal::Frame, terminal::Frame,
text::Span,
widgets::{Axis, Block, Borders, Chart, Dataset}, widgets::{Axis, Block, Borders, Chart, Dataset},
}; };
@ -23,12 +22,9 @@ impl MemGraphWidget for Painter {
let mem_data: &[(f64, f64)] = &app_state.canvas_data.mem_data; let mem_data: &[(f64, f64)] = &app_state.canvas_data.mem_data;
let swap_data: &[(f64, f64)] = &app_state.canvas_data.swap_data; let swap_data: &[(f64, f64)] = &app_state.canvas_data.swap_data;
let display_time_labels = vec![ let display_time_labels = [
Span::styled( format!("{}s", mem_widget_state.current_display_time / 1000),
format!("{}s", mem_widget_state.current_display_time / 1000), "0s".to_string(),
self.colours.graph_style,
),
Span::styled("0s".to_string(), self.colours.graph_style),
]; ];
let x_axis = if app_state.app_config_fields.hide_time let x_axis = if app_state.app_config_fields.hide_time
|| (app_state.app_config_fields.autohide_time || (app_state.app_config_fields.autohide_time
@ -42,7 +38,8 @@ impl MemGraphWidget for Painter {
Axis::default() Axis::default()
.bounds([-(mem_widget_state.current_display_time as f64), 0.0]) .bounds([-(mem_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style) .style(self.colours.graph_style)
.labels(display_time_labels) .labels(&display_time_labels)
.labels_style(self.colours.graph_style)
} else { } else {
mem_widget_state.autohide_timer = None; mem_widget_state.autohide_timer = None;
Axis::default().bounds([-(mem_widget_state.current_display_time as f64), 0.0]) Axis::default().bounds([-(mem_widget_state.current_display_time as f64), 0.0])
@ -53,17 +50,16 @@ impl MemGraphWidget for Painter {
Axis::default() Axis::default()
.bounds([-(mem_widget_state.current_display_time as f64), 0.0]) .bounds([-(mem_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style) .style(self.colours.graph_style)
.labels(display_time_labels) .labels(&display_time_labels)
.labels_style(self.colours.graph_style)
}; };
// Offset as the zero value isn't drawn otherwise... // Offset as the zero value isn't drawn otherwise...
let y_axis = Axis::default() let y_axis = Axis::default()
.style(self.colours.graph_style) .style(self.colours.graph_style)
.bounds([-0.5, 100.5]) .bounds([-0.5, 100.5])
.labels(vec![ .labels(&["0%", "100%"])
Span::styled("0%", self.colours.graph_style), .labels_style(self.colours.graph_style);
Span::styled("100%", self.colours.graph_style),
]);
let mut mem_canvas_vec: Vec<Dataset<'_>> = vec![]; let mut mem_canvas_vec: Vec<Dataset<'_>> = vec![];
@ -95,25 +91,29 @@ impl MemGraphWidget for Painter {
let title = if app_state.is_expanded { let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Memory ── Esc to go back "; const TITLE_BASE: &str = " Memory ── Esc to go back ";
Span::styled( format!(
format!( " Memory ─{}─ Esc to go back ",
" Memory ─{}─ Esc to go back ", "".repeat(
"".repeat( usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
usize::from(draw_loc.width) )
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
),
self.colours.highlighted_border_style,
) )
} else { } else {
Span::styled(" Memory ".to_string(), self.colours.widget_title_style) " Memory ".to_string()
};
let title_style = if app_state.is_expanded {
self.colours.highlighted_border_style
} else {
self.colours.widget_title_style
}; };
f.render_widget( f.render_widget(
Chart::new(mem_canvas_vec) // Chart::new(mem_canvas_vec)
Chart::default()
.datasets(&mem_canvas_vec)
.block( .block(
Block::default() Block::default()
.title(title) .title(&title)
.title_style(title_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(if app_state.current_widget.widget_id == widget_id { .border_style(if app_state.current_widget.widget_id == widget_id {
self.colours.highlighted_border_style self.colours.highlighted_border_style

View File

@ -4,8 +4,7 @@ use tui::{
backend::Backend, backend::Backend,
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
terminal::Frame, terminal::Frame,
text::{Span, Spans}, widgets::{Block, Paragraph, Text},
widgets::{Block, Paragraph},
}; };
pub trait NetworkBasicWidget { pub trait NetworkBasicWidget {
@ -44,25 +43,28 @@ impl NetworkBasicWidget for Painter {
); );
} }
let rx_label = format!("RX: {}", &app_state.canvas_data.rx_display); let rx_label = format!("RX: {}\n", &app_state.canvas_data.rx_display);
let tx_label = format!("TX: {}", &app_state.canvas_data.tx_display); let tx_label = format!("TX: {}", &app_state.canvas_data.tx_display);
let total_rx_label = format!("Total RX: {}", &app_state.canvas_data.total_rx_display); let total_rx_label = format!("Total RX: {}\n", &app_state.canvas_data.total_rx_display);
let total_tx_label = format!("Total TX: {}", &app_state.canvas_data.total_tx_display); let total_tx_label = format!("Total TX: {}", &app_state.canvas_data.total_tx_display);
let net_text = vec![ let net_text = [
Spans::from(Span::styled(rx_label, self.colours.rx_style)), Text::styled(rx_label, self.colours.rx_style),
Spans::from(Span::styled(tx_label, self.colours.tx_style)), Text::styled(tx_label, self.colours.tx_style),
]; ];
let total_net_text = vec![ let total_net_text = [
Spans::from(Span::styled(total_rx_label, self.colours.total_rx_style)), Text::styled(total_rx_label, self.colours.total_rx_style),
Spans::from(Span::styled(total_tx_label, self.colours.total_tx_style)), Text::styled(total_tx_label, self.colours.total_tx_style),
]; ];
f.render_widget(Paragraph::new(net_text).block(Block::default()), net_loc[0]);
f.render_widget( f.render_widget(
Paragraph::new(total_net_text).block(Block::default()), Paragraph::new(net_text.iter()).block(Block::default()),
net_loc[0],
);
f.render_widget(
Paragraph::new(total_net_text.iter()).block(Block::default()),
total_loc[0], total_loc[0],
); );
} }

View File

@ -12,7 +12,6 @@ use tui::{
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
symbols::Marker, symbols::Marker,
terminal::Frame, terminal::Frame,
text::Span,
widgets::{Axis, Block, Borders, Chart, Dataset, Row, Table}, widgets::{Axis, Block, Borders, Chart, Dataset, Row, Table},
}; };
@ -72,12 +71,9 @@ impl NetworkGraphWidget for Painter {
let network_data_rx: &[(f64, f64)] = &app_state.canvas_data.network_data_rx; let network_data_rx: &[(f64, f64)] = &app_state.canvas_data.network_data_rx;
let network_data_tx: &[(f64, f64)] = &app_state.canvas_data.network_data_tx; let network_data_tx: &[(f64, f64)] = &app_state.canvas_data.network_data_tx;
let display_time_labels = vec![ let display_time_labels = [
Span::styled( format!("{}s", network_widget_state.current_display_time / 1000),
format!("{}s", network_widget_state.current_display_time / 1000), "0s".to_string(),
self.colours.graph_style,
),
Span::styled("0s".to_string(), self.colours.graph_style),
]; ];
let x_axis = if app_state.app_config_fields.hide_time let x_axis = if app_state.app_config_fields.hide_time
|| (app_state.app_config_fields.autohide_time || (app_state.app_config_fields.autohide_time
@ -91,7 +87,8 @@ impl NetworkGraphWidget for Painter {
Axis::default() Axis::default()
.bounds([-(network_widget_state.current_display_time as f64), 0.0]) .bounds([-(network_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style) .style(self.colours.graph_style)
.labels(display_time_labels) .labels(&display_time_labels)
.labels_style(self.colours.graph_style)
} else { } else {
network_widget_state.autohide_timer = None; network_widget_state.autohide_timer = None;
Axis::default() Axis::default()
@ -103,35 +100,33 @@ impl NetworkGraphWidget for Painter {
Axis::default() Axis::default()
.bounds([-(network_widget_state.current_display_time as f64), 0.0]) .bounds([-(network_widget_state.current_display_time as f64), 0.0])
.style(self.colours.graph_style) .style(self.colours.graph_style)
.labels(display_time_labels) .labels(&display_time_labels)
.labels_style(self.colours.graph_style)
}; };
// 0 is offset. // 0 is offset.
let y_axis_labels = vec![ let y_axis_labels = ["0B", "1KiB", "1MiB", "1GiB"];
Span::styled("0B", self.colours.graph_style),
Span::styled("1KiB", self.colours.graph_style),
Span::styled("1MiB", self.colours.graph_style),
Span::styled("1GiB", self.colours.graph_style),
];
let y_axis = Axis::default() let y_axis = Axis::default()
.style(self.colours.graph_style) .style(self.colours.graph_style)
.bounds([-0.5, 30_f64]) .bounds([-0.5, 30_f64])
.labels(y_axis_labels); .labels(&y_axis_labels)
.labels_style(self.colours.graph_style);
let title = if app_state.is_expanded { let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Network ── Esc to go back "; const TITLE_BASE: &str = " Network ── Esc to go back ";
Span::styled( format!(
format!( " Network ─{}─ Esc to go back ",
" Network ─{}─ Esc to go back ", "".repeat(
"".repeat( usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
usize::from(draw_loc.width) )
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
),
self.colours.highlighted_border_style,
) )
} else { } else {
Span::styled(" Network ".to_string(), self.colours.widget_title_style) " Network ".to_string()
};
let title_style = if app_state.is_expanded {
self.colours.highlighted_border_style
} else {
self.colours.widget_title_style
}; };
let legend_constraints = if hide_legend { let legend_constraints = if hide_legend {
@ -142,7 +137,6 @@ impl NetworkGraphWidget for Painter {
let dataset = if app_state.app_config_fields.use_old_network_legend && !hide_legend { let dataset = if app_state.app_config_fields.use_old_network_legend && !hide_legend {
let mut ret_val = vec![]; let mut ret_val = vec![];
ret_val.push( ret_val.push(
Dataset::default() Dataset::default()
.name(format!("RX: {:7}", app_state.canvas_data.rx_display)) .name(format!("RX: {:7}", app_state.canvas_data.rx_display))
@ -220,10 +214,13 @@ impl NetworkGraphWidget for Painter {
}; };
f.render_widget( f.render_widget(
Chart::new(dataset) // Chart::new(dataset)
Chart::default()
.datasets(&dataset)
.block( .block(
Block::default() Block::default()
.title(title) .title(&title)
.title_style(title_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(if app_state.current_widget.widget_id == widget_id { .border_style(if app_state.current_widget.widget_id == widget_id {
self.colours.highlighted_border_style self.colours.highlighted_border_style

View File

@ -13,8 +13,7 @@ use tui::{
backend::Backend, backend::Backend,
layout::{Alignment, Constraint, Direction, Layout, Rect}, layout::{Alignment, Constraint, Direction, Layout, Rect},
terminal::Frame, terminal::Frame,
text::{Span, Spans}, widgets::{Block, Borders, Paragraph, Row, Table, Text},
widgets::{Block, Borders, Paragraph, Row, Table},
}; };
use unicode_segmentation::{GraphemeIndices, UnicodeSegmentation}; use unicode_segmentation::{GraphemeIndices, UnicodeSegmentation};
@ -225,26 +224,30 @@ impl ProcessTableWidget for Painter {
&& !proc_widget_state.is_sort_open && !proc_widget_state.is_sort_open
{ {
const TITLE_BASE: &str = " Processes ── Esc to go back "; const TITLE_BASE: &str = " Processes ── Esc to go back ";
Span::styled( format!(
format!( " Processes ─{}─ Esc to go back ",
" Processes ─{}─ Esc to go back ", "".repeat(
"".repeat( usize::from(draw_loc.width)
usize::from(draw_loc.width) .saturating_sub(TITLE_BASE.chars().count() + 2)
.saturating_sub(TITLE_BASE.chars().count() + 2) )
)
),
border_and_title_style,
) )
} else { } else {
Span::styled(" Processes ".to_string(), self.colours.widget_title_style) " Processes ".to_string()
} }
} else { } else {
Span::from(String::default()) String::default()
};
let title_style = if app_state.is_expanded {
border_and_title_style
} else {
self.colours.widget_title_style
}; };
let process_block = if draw_border { let process_block = if draw_border {
Block::default() Block::default()
.title(title) .title(&title)
.title_style(title_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(border_and_title_style) .border_style(border_and_title_style)
} else if is_on_widget { } else if is_on_widget {
@ -291,7 +294,7 @@ impl ProcessTableWidget for Painter {
is_on_widget: bool, grapheme_indices: GraphemeIndices<'a>, start_position: usize, is_on_widget: bool, grapheme_indices: GraphemeIndices<'a>, start_position: usize,
cursor_position: usize, query: &str, currently_selected_text_style: tui::style::Style, cursor_position: usize, query: &str, currently_selected_text_style: tui::style::Style,
text_style: tui::style::Style, text_style: tui::style::Style,
) -> Vec<Span<'a>> { ) -> Vec<Text<'a>> {
let mut current_grapheme_posn = 0; let mut current_grapheme_posn = 0;
if is_on_widget { if is_on_widget {
@ -303,9 +306,9 @@ impl ProcessTableWidget for Painter {
None None
} else { } else {
let styled = if grapheme.0 == cursor_position { let styled = if grapheme.0 == cursor_position {
Span::styled(grapheme.1, currently_selected_text_style) Text::styled(grapheme.1, currently_selected_text_style)
} else { } else {
Span::styled(grapheme.1, text_style) Text::styled(grapheme.1, text_style)
}; };
Some(styled) Some(styled)
} }
@ -313,7 +316,7 @@ impl ProcessTableWidget for Painter {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if cursor_position >= query.len() { if cursor_position >= query.len() {
res.push(Span::styled(" ", currently_selected_text_style)) res.push(Text::styled(" ", currently_selected_text_style))
} }
res res
@ -327,7 +330,7 @@ impl ProcessTableWidget for Painter {
if current_grapheme_posn <= start_position { if current_grapheme_posn <= start_position {
None None
} else { } else {
let styled = Span::styled(grapheme.1, text_style); let styled = Text::styled(grapheme.1, text_style);
Some(styled) Some(styled)
} }
}) })
@ -373,8 +376,8 @@ impl ProcessTableWidget for Painter {
self.colours.text_style, self.colours.text_style,
); );
let mut search_text = vec![Spans::from({ let mut search_text = {
let mut search_vec = vec![Span::styled( let mut search_vec = vec![Text::styled(
search_title, search_title,
if is_on_widget { if is_on_widget {
self.colours.table_header_style self.colours.table_header_style
@ -384,7 +387,7 @@ impl ProcessTableWidget for Painter {
)]; )];
search_vec.extend(query_with_cursor); search_vec.extend(query_with_cursor);
search_vec search_vec
})]; };
// Text options shamelessly stolen from VS Code. // Text options shamelessly stolen from VS Code.
let case_style = if !proc_widget_state.process_search_state.is_ignoring_case { let case_style = if !proc_widget_state.process_search_state.is_ignoring_case {
@ -411,24 +414,25 @@ impl ProcessTableWidget for Painter {
self.colours.text_style self.colours.text_style
}; };
let option_text = Spans::from(vec![ let option_text = vec![
Span::styled( Text::raw("\n"),
Text::styled(
format!("Case({})", if self.is_mac_os { "F1" } else { "Alt+C" }), format!("Case({})", if self.is_mac_os { "F1" } else { "Alt+C" }),
case_style, case_style,
), ),
Span::from(" "), Text::raw(" "),
Span::styled( Text::styled(
format!("Whole({})", if self.is_mac_os { "F2" } else { "Alt+W" }), format!("Whole({})", if self.is_mac_os { "F2" } else { "Alt+W" }),
whole_word_style, whole_word_style,
), ),
Span::from(" "), Text::raw(" "),
Span::styled( Text::styled(
format!("Regex({})", if self.is_mac_os { "F3" } else { "Alt+R" }), format!("Regex({})", if self.is_mac_os { "F3" } else { "Alt+R" }),
regex_style, regex_style,
), ),
]); ];
search_text.push(Spans::from(Span::styled( search_text.push(Text::styled(
if let Some(err) = &proc_widget_state if let Some(err) = &proc_widget_state
.process_search_state .process_search_state
.search_state .search_state
@ -439,8 +443,8 @@ impl ProcessTableWidget for Painter {
"" ""
}, },
self.colours.invalid_query_style, self.colours.invalid_query_style,
))); ));
search_text.push(option_text); search_text.extend(option_text);
let current_border_style = if proc_widget_state let current_border_style = if proc_widget_state
.process_search_state .process_search_state
@ -459,17 +463,15 @@ impl ProcessTableWidget for Painter {
let repeat_num = let repeat_num =
usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2); usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2);
Span::styled( format!("{} Esc to close ", "".repeat(repeat_num))
format!("{} Esc to close ", "".repeat(repeat_num)),
current_border_style,
)
} else { } else {
Span::from(String::new()) String::new()
}; };
let process_search_block = if draw_border { let process_search_block = if draw_border {
Block::default() Block::default()
.title(title) .title(&title)
.title_style(current_border_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(current_border_style) .border_style(current_border_style)
} else if is_on_widget { } else if is_on_widget {
@ -487,7 +489,7 @@ impl ProcessTableWidget for Painter {
.split(draw_loc); .split(draw_loc);
f.render_widget( f.render_widget(
Paragraph::new(search_text) Paragraph::new(search_text.iter())
.block(process_search_block) .block(process_search_block)
.style(self.colours.text_style) .style(self.colours.text_style)
.alignment(Alignment::Left), .alignment(Alignment::Left),

View File

@ -5,7 +5,6 @@ use tui::{
backend::Backend, backend::Backend,
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
terminal::Frame, terminal::Frame,
text::Span,
widgets::{Block, Borders, Row, Table}, widgets::{Block, Borders, Row, Table},
}; };
@ -79,28 +78,27 @@ impl TempTableWidget for Painter {
let title = if app_state.is_expanded { let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Temperatures ── Esc to go back "; const TITLE_BASE: &str = " Temperatures ── Esc to go back ";
Span::styled( format!(
format!( " Temperatures ─{}─ Esc to go back ",
" Temperatures ─{}─ Esc to go back ", "".repeat(
"".repeat( usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
usize::from(draw_loc.width) )
.saturating_sub(TITLE_BASE.chars().count() + 2)
)
),
border_and_title_style,
) )
} else if app_state.app_config_fields.use_basic_mode { } else if app_state.app_config_fields.use_basic_mode {
Span::from(String::new()) String::new()
} else { } else {
Span::styled( " Temperatures ".to_string()
" Temperatures ".to_string(), };
self.colours.widget_title_style, let title_style = if app_state.is_expanded {
) border_and_title_style
} else {
self.colours.widget_title_style
}; };
let temp_block = if draw_border { let temp_block = if draw_border {
Block::default() Block::default()
.title(title) .title(&title)
.title_style(title_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(border_and_title_style) .border_style(border_and_title_style)
} else if is_on_widget { } else if is_on_widget {

View File

@ -43,126 +43,126 @@ lazy_static! {
// Help text // Help text
pub const HELP_CONTENTS_TEXT: [&str; 7] = [ pub const HELP_CONTENTS_TEXT: [&str; 7] = [
"Press the corresponding numbers to jump to the section, or scroll:", "Press the corresponding numbers to jump to the section, or scroll:\n",
"1 - General", "1 - General\n",
"2 - CPU widget", "2 - CPU widget\n",
"3 - Process widget", "3 - Process widget\n",
"4 - Process search widget", "4 - Process search widget\n",
"5 - Process sort widget", "5 - Process sort widget\n",
"6 - Battery widget", "6 - Battery widget",
]; ];
pub const GENERAL_HELP_TEXT: [&str; 29] = [ pub const GENERAL_HELP_TEXT: [&str; 29] = [
"1 - General", "1 - General\n",
"q, Ctrl-c Quit", "q, Ctrl-c Quit\n",
"Esc Close dialog windows, search, widgets, or exit expanded mode", "Esc Close dialog windows, search, widgets, or exit expanded mode\n",
"Ctrl-r Reset display and any collected data", "Ctrl-r Reset display and any collected data\n",
"f Freeze/unfreeze updating with new data", "f Freeze/unfreeze updating with new data\n",
"Ctrl-Left, ", "Ctrl-Left, \n",
"Shift-Left, Move widget selection left", "Shift-Left, Move widget selection left\n",
"H, A ", "H, A \n",
"Ctrl-Right, ", "Ctrl-Right, \n",
"Shift-Right, Move widget selection right", "Shift-Right, Move widget selection right\n",
"L, D ", "L, D \n",
"Ctrl-Up, ", "Ctrl-Up, \n",
"Shift-Up, Move widget selection up", "Shift-Up, Move widget selection up\n",
"K, W ", "K, W \n",
"Ctrl-Down, ", "Ctrl-Down, \n",
"Shift-Down, Move widget selection down", "Shift-Down, Move widget selection down\n",
"J, S ", "J, S \n",
"Left, h Move left within widget", "Left, h Move left within widget\n",
"Down, j Move down within widget", "Down, j Move down within widget\n",
"Up, k Move up within widget", "Up, k Move up within widget\n",
"Right, l Move right within widget", "Right, l Move right within widget\n",
"? Open help menu", "? Open help menu\n",
"gg Jump to the first entry", "gg Jump to the first entry\n",
"G Jump to the last entry", "G Jump to the last entry\n",
"e Expand the currently selected widget", "e Expand the currently selected widget\n",
"+ Zoom in on chart (decrease time range)", "+ Zoom in on chart (decrease time range)\n",
"- Zoom out on chart (increase time range)", "- Zoom out on chart (increase time range)\n",
"= Reset zoom", "= Reset zoom\n",
"Mouse scroll Scroll through the tables or zoom in/out of charts by scrolling up/down", "Mouse scroll Scroll through the tables or zoom in/out of charts by scrolling up/down",
]; ];
pub const CPU_HELP_TEXT: [&str; 2] = [ pub const CPU_HELP_TEXT: [&str; 2] = [
"2 - CPU widget", "2 - CPU widget\n",
"Mouse scroll Scrolling over an CPU core/average shows only that entry on the chart", "Mouse scroll Scrolling over an CPU core/average shows only that entry on the chart",
]; ];
// TODO [Help]: Search in help? // TODO [Help]: Search in help?
// TODO [Help]: Move to using tables for easier formatting? // TODO [Help]: Move to using tables for easier formatting?
pub const PROCESS_HELP_TEXT: [&str; 11] = [ pub const PROCESS_HELP_TEXT: [&str; 11] = [
"3 - Process widget", "3 - Process widget\n",
"dd Kill the selected process", "dd Kill the selected process\n",
"c Sort by CPU usage, press again to reverse sorting order", "c Sort by CPU usage, press again to reverse sorting order\n",
"m Sort by memory usage, press again to reverse sorting order", "m Sort by memory usage, press again to reverse sorting order\n",
"p Sort by PID name, press again to reverse sorting order", "p Sort by PID name, press again to reverse sorting order\n",
"n Sort by process name, press again to reverse sorting order", "n Sort by process name, press again to reverse sorting order\n",
"Tab Group/un-group processes with the same name", "Tab Group/un-group processes with the same name\n",
"Ctrl-f, / Open process search widget", "Ctrl-f, / Open process search widget\n",
"P Toggle between showing the full path or just the process name", "P Toggle between showing the full path or just the process name\n",
"s, F6 Open process sort widget", "s, F6 Open process sort widget\n",
"I Invert current sort", "I Invert current sort",
]; ];
pub const SEARCH_HELP_TEXT: [&str; 43] = [ pub const SEARCH_HELP_TEXT: [&str; 43] = [
"4 - Process search widget", "4 - Process search widget\n",
"Tab Toggle between searching for PID and name", "Tab Toggle between searching for PID and name\n",
"Esc Close the search widget (retains the filter)", "Esc Close the search widget (retains the filter)\n",
"Ctrl-a Skip to the start of the search query", "Ctrl-a Skip to the start of the search query\n",
"Ctrl-e Skip to the end of the search query", "Ctrl-e Skip to the end of the search query\n",
"Ctrl-u Clear the current search query", "Ctrl-u Clear the current search query\n",
"Backspace Delete the character behind the cursor", "Backspace Delete the character behind the cursor\n",
"Delete Delete the character at the cursor", "Delete Delete the character at the cursor\n",
"Alt-c/F1 Toggle matching case", "Alt-c/F1 Toggle matching case\n",
"Alt-w/F2 Toggle matching the entire word", "Alt-w/F2 Toggle matching the entire word\n",
"Alt-r/F3 Toggle using regex", "Alt-r/F3 Toggle using regex\n",
"Left, Alt-h Move cursor left", "Left, Alt-h Move cursor left\n",
"Right, Alt-l Move cursor right", "Right, Alt-l Move cursor right\n",
"", "\n",
"Search keywords:", "Search keywords:\n",
"pid ex: pid 825", "pid ex: pid 825\n",
"cpu ex: cpu > 4.2", "cpu ex: cpu > 4.2\n",
"mem ex: mem < 4.2", "mem ex: mem < 4.2\n",
"read ex: read >= 1 b", "read ex: read >= 1 b\n",
"write ex: write <= 1 tb", "write ex: write <= 1 tb\n",
"tread ex: tread = 1", "tread ex: tread = 1\n",
"twrite ex: twrite = 1", "twrite ex: twrite = 1\n",
"", "\n",
"Comparison operators:", "Comparison operators:\n",
"= ex: cpu = 1", "= ex: cpu = 1\n",
"> ex: cpu > 1", "> ex: cpu > 1\n",
"< ex: cpu < 1", "< ex: cpu < 1\n",
">= ex: cpu >= 1", ">= ex: cpu >= 1\n",
"<= ex: cpu <= 1", "<= ex: cpu <= 1\n",
"", "\n",
"Logical operators:", "Logical operators:\n",
"and/&&/<Space> ex: btm and cpu > 1 and mem > 1", "and/&&/<Space> ex: btm and cpu > 1 and mem > 1\n",
"or/|| ex: btm or firefox", "or/|| ex: btm or firefox\n",
"", "\n",
"Supported units:", "Supported units:\n",
"B ex: read > 1 b", "B ex: read > 1 b\n",
"KB ex: read > 1 kb", "KB ex: read > 1 kb\n",
"MB ex: read > 1 mb", "MB ex: read > 1 mb\n",
"TB ex: read > 1 tb", "TB ex: read > 1 tb\n",
"KiB ex: read > 1 kib", "KiB ex: read > 1 kib\n",
"MiB ex: read > 1 mib", "MiB ex: read > 1 mib\n",
"GiB ex: read > 1 gib", "GiB ex: read > 1 gib\n",
"TiB ex: read > 1 tib", "TiB ex: read > 1 tib",
]; ];
pub const SORT_HELP_TEXT: [&str; 6] = [ pub const SORT_HELP_TEXT: [&str; 6] = [
"5 - Sort widget", "5 - Sort widget\n",
"Down, 'j' Scroll down in list", "Down, 'j' Scroll down in list\n",
"Up, 'k' Scroll up in list", "Up, 'k' Scroll up in list\n",
"Mouse scroll Scroll through sort widget", "Mouse scroll Scroll through sort widget\n",
"Esc Close the sort widget", "Esc Close the sort widget\n",
"Enter Sort by current selected column", "Enter Sort by current selected column",
]; ];
pub const BATTERY_HELP_TEXT: [&str; 3] = [ pub const BATTERY_HELP_TEXT: [&str; 3] = [
"6 - Battery widget", "6 - Battery widget\n",
"Left Go to previous battery", "Left Go to previous battery\n",
"Right Go to next battery", "Right Go to next battery",
]; ];