refactor: rip out trait system for drawing widgets

This rips out this weird trait system I previously used for drawing
widgets, where I implemented a trait onto the Painter struct that did
the drawing.  I have no idea what I was thinking back then.
This commit is contained in:
ClementTsang 2021-08-24 22:34:25 -04:00
parent 189be96622
commit dd7e183ec8
16 changed files with 3070 additions and 3221 deletions

View File

@ -270,6 +270,10 @@ impl AppState {
EventResult::NoRedraw EventResult::NoRedraw
} }
} }
BottomEvent::Resize {
width: _,
height: _,
} => EventResult::Redraw,
BottomEvent::Clean => { BottomEvent::Clean => {
self.data_collection self.data_collection
.clean_data(constants::STALE_MAX_MILLISECONDS); .clean_data(constants::STALE_MAX_MILLISECONDS);

View File

@ -233,6 +233,12 @@ fn main() -> Result<()> {
try_drawing(&mut terminal, &mut app, &mut painter)?; try_drawing(&mut terminal, &mut app, &mut painter)?;
} }
} }
BottomEvent::Resize {
width: _,
height: _,
} => {
try_drawing(&mut terminal, &mut app, &mut painter)?;
}
BottomEvent::Clean => { BottomEvent::Clean => {
app.data_collection app.data_collection
.clean_data(constants::STALE_MAX_MILLISECONDS); .clean_data(constants::STALE_MAX_MILLISECONDS);

View File

@ -95,8 +95,6 @@ impl FromStr for ColourScheme {
/// Handles the canvas' state. TODO: [OPT] implement this. /// Handles the canvas' state. TODO: [OPT] implement this.
pub struct Painter { pub struct Painter {
pub colours: CanvasColours, pub colours: CanvasColours,
height: u16,
width: u16,
styled_help_text: Vec<Spans<'static>>, styled_help_text: Vec<Spans<'static>>,
is_mac_os: bool, // FIXME: This feels out of place... is_mac_os: bool, // FIXME: This feels out of place...
row_constraints: Vec<Constraint>, row_constraints: Vec<Constraint>,
@ -182,8 +180,6 @@ impl Painter {
let mut painter = Painter { let mut painter = Painter {
colours: CanvasColours::default(), colours: CanvasColours::default(),
height: 0,
width: 0,
styled_help_text: Vec::default(), styled_help_text: Vec::default(),
is_mac_os: cfg!(target_os = "macos"), is_mac_os: cfg!(target_os = "macos"),
row_constraints, row_constraints,
@ -313,36 +309,6 @@ impl Painter {
let terminal_height = terminal_size.height; let terminal_height = terminal_size.height;
let terminal_width = terminal_size.width; let terminal_width = terminal_size.width;
if (self.height == 0 && self.width == 0)
|| (self.height != terminal_height || self.width != terminal_width)
{
app_state.is_force_redraw = true;
self.height = terminal_height;
self.width = terminal_width;
}
if app_state.should_get_widget_bounds() {
// If we're force drawing, reset ALL mouse boundaries.
for widget in app_state.widget_map.values_mut() {
widget.top_left_corner = None;
widget.bottom_right_corner = None;
}
// Reset dd_dialog...
app_state.delete_dialog_state.button_positions = vec![];
// Reset battery dialog...
for battery_widget in app_state.battery_state.widget_states.values_mut() {
battery_widget.tab_click_locs = None;
}
// Reset column headers for sorting in process widget...
for proc_widget in app_state.proc_state.widget_states.values_mut() {
proc_widget.columns.column_header_y_loc = None;
proc_widget.columns.column_header_x_locs = None;
}
}
if app_state.help_dialog_state.is_showing_help { if app_state.help_dialog_state.is_showing_help {
let gen_help_len = GENERAL_HELP_TEXT.len() as u16 + 3; let gen_help_len = GENERAL_HELP_TEXT.len() as u16 + 3;
let border_len = terminal_height.saturating_sub(gen_help_len) / 2; let border_len = terminal_height.saturating_sub(gen_help_len) / 2;
@ -461,39 +427,45 @@ impl Painter {
.constraints([Constraint::Percentage(100)]) .constraints([Constraint::Percentage(100)])
.split(terminal_size); .split(terminal_size);
match &app_state.current_widget.widget_type { match &app_state.current_widget.widget_type {
Cpu => self.draw_cpu( Cpu => draw_cpu(
self,
&mut f, &mut f,
app_state, app_state,
rect[0], rect[0],
app_state.current_widget.widget_id, app_state.current_widget.widget_id,
), ),
CpuLegend => self.draw_cpu( CpuLegend => draw_cpu(
self,
&mut f, &mut f,
app_state, app_state,
rect[0], rect[0],
app_state.current_widget.widget_id - 1, app_state.current_widget.widget_id - 1,
), ),
Mem | BasicMem => self.draw_memory_graph( Mem | BasicMem => draw_memory_graph(
self,
&mut f, &mut f,
app_state, app_state,
rect[0], rect[0],
app_state.current_widget.widget_id, app_state.current_widget.widget_id,
), ),
Disk => self.draw_disk_table( Disk => draw_disk_table(
self,
&mut f, &mut f,
app_state, app_state,
rect[0], rect[0],
true, true,
app_state.current_widget.widget_id, app_state.current_widget.widget_id,
), ),
Temp => self.draw_temp_table( Temp => draw_temp_table(
self,
&mut f, &mut f,
app_state, app_state,
rect[0], rect[0],
true, true,
app_state.current_widget.widget_id, app_state.current_widget.widget_id,
), ),
Net => self.draw_network_graph( Net => draw_network_graph(
self,
&mut f, &mut f,
app_state, app_state,
rect[0], rect[0],
@ -508,9 +480,10 @@ impl Painter {
_ => 0, _ => 0,
}; };
self.draw_process_features(&mut f, app_state, rect[0], true, widget_id); draw_process_features(self, &mut f, app_state, rect[0], true, widget_id);
} }
Battery => self.draw_battery_display( Battery => draw_battery_display(
self,
&mut f, &mut f,
app_state, app_state,
rect[0], rect[0],
@ -555,16 +528,17 @@ impl Painter {
.direction(Direction::Horizontal) .direction(Direction::Horizontal)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
.split(vertical_chunks[1]); .split(vertical_chunks[1]);
self.draw_basic_cpu(&mut f, app_state, vertical_chunks[0], 1); draw_basic_cpu(self, &mut f, app_state, vertical_chunks[0], 1);
self.draw_basic_memory(&mut f, app_state, middle_chunks[0], 2); draw_basic_memory(self, &mut f, app_state, middle_chunks[0], 2);
self.draw_basic_network(&mut f, app_state, middle_chunks[1], 3); draw_basic_network(self, &mut f, app_state, middle_chunks[1], 3);
let mut later_widget_id: Option<u64> = None; let mut later_widget_id: Option<u64> = None;
if let Some(basic_table_widget_state) = &app_state.basic_table_widget_state { if let Some(basic_table_widget_state) = &app_state.basic_table_widget_state {
let widget_id = basic_table_widget_state.currently_displayed_widget_id; let widget_id = basic_table_widget_state.currently_displayed_widget_id;
later_widget_id = Some(widget_id); later_widget_id = Some(widget_id);
match basic_table_widget_state.currently_displayed_widget_type { match basic_table_widget_state.currently_displayed_widget_type {
Disk => self.draw_disk_table( Disk => draw_disk_table(
self,
&mut f, &mut f,
app_state, app_state,
vertical_chunks[3], vertical_chunks[3],
@ -578,7 +552,8 @@ impl Painter {
ProcSort => 2, ProcSort => 2,
_ => 0, _ => 0,
}; };
self.draw_process_features( draw_process_features(
self,
&mut f, &mut f,
app_state, app_state,
vertical_chunks[3], vertical_chunks[3],
@ -586,14 +561,16 @@ impl Painter {
wid, wid,
); );
} }
Temp => self.draw_temp_table( Temp => draw_temp_table(
self,
&mut f, &mut f,
app_state, app_state,
vertical_chunks[3], vertical_chunks[3],
false, false,
widget_id, widget_id,
), ),
Battery => self.draw_battery_display( Battery => draw_battery_display(
self,
&mut f, &mut f,
app_state, app_state,
vertical_chunks[3], vertical_chunks[3],
@ -605,7 +582,7 @@ impl Painter {
} }
if let Some(widget_id) = later_widget_id { if let Some(widget_id) = later_widget_id {
self.draw_basic_table_arrows(&mut f, app_state, vertical_chunks[2], widget_id); draw_basic_table_arrows(self, &mut f, app_state, vertical_chunks[2], widget_id);
} }
} else { } else {
// Draws using the passed in (or default) layout. // Draws using the passed in (or default) layout.
@ -713,23 +690,25 @@ impl Painter {
for (widget, widget_draw_loc) in widgets.children.iter().zip(widget_draw_locs) { for (widget, widget_draw_loc) in widgets.children.iter().zip(widget_draw_locs) {
match &widget.widget_type { match &widget.widget_type {
Empty => {} Empty => {}
Cpu => self.draw_cpu(f, app_state, *widget_draw_loc, widget.widget_id), Cpu => draw_cpu(self, f, app_state, *widget_draw_loc, widget.widget_id),
Mem => self.draw_memory_graph(f, app_state, *widget_draw_loc, widget.widget_id), Mem => draw_memory_graph(self, f, app_state, *widget_draw_loc, widget.widget_id),
Net => self.draw_network(f, app_state, *widget_draw_loc, widget.widget_id), Net => draw_network(self, f, app_state, *widget_draw_loc, widget.widget_id),
Temp => { Temp => {
self.draw_temp_table(f, app_state, *widget_draw_loc, true, widget.widget_id) draw_temp_table(self, f, app_state, *widget_draw_loc, true, widget.widget_id)
} }
Disk => { Disk => {
self.draw_disk_table(f, app_state, *widget_draw_loc, true, widget.widget_id) draw_disk_table(self, f, app_state, *widget_draw_loc, true, widget.widget_id)
} }
Proc => self.draw_process_features( Proc => draw_process_features(
self,
f, f,
app_state, app_state,
*widget_draw_loc, *widget_draw_loc,
true, true,
widget.widget_id, widget.widget_id,
), ),
Battery => self.draw_battery_display( Battery => draw_battery_display(
self,
f, f,
app_state, app_state,
*widget_draw_loc, *widget_draw_loc,

View File

@ -10,14 +10,14 @@ pub mod network_graph;
pub mod process_table; pub mod process_table;
pub mod temp_table; pub mod temp_table;
pub use basic_table_arrows::BasicTableArrows; pub use basic_table_arrows::*;
pub use battery_display::BatteryDisplayWidget; pub use battery_display::*;
pub use cpu_basic::CpuBasicWidget; pub use cpu_basic::*;
pub use cpu_graph::CpuGraphWidget; pub use cpu_graph::*;
pub use disk_table::DiskTableWidget; pub use disk_table::*;
pub use mem_basic::MemBasicWidget; pub use mem_basic::*;
pub use mem_graph::MemGraphWidget; pub use mem_graph::*;
pub use network_basic::NetworkBasicWidget; pub use network_basic::*;
pub use network_graph::NetworkGraphWidget; pub use network_graph::*;
pub use process_table::ProcessTableWidget; pub use process_table::*;
pub use temp_table::TempTableWidget; pub use temp_table::*;

View File

@ -12,16 +12,10 @@ use tui::{
widgets::{Block, Paragraph}, widgets::{Block, Paragraph},
}; };
pub trait BasicTableArrows { pub fn draw_basic_table_arrows<B: Backend>(
fn draw_basic_table_arrows<B: Backend>( painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, widget_id: u64,
); ) {
}
impl BasicTableArrows for Painter {
fn draw_basic_table_arrows<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
) {
if let Some(current_table) = app_state.widget_map.get(&widget_id) { if let Some(current_table) = app_state.widget_map.get(&widget_id) {
let current_table = if let BottomWidgetType::ProcSort = current_table.widget_type { let current_table = if let BottomWidgetType::ProcSort = current_table.widget_type {
current_table current_table
@ -46,9 +40,7 @@ impl BasicTableArrows for Painter {
.left_neighbour .left_neighbour
.map(|left_left_widget_id| { .map(|left_left_widget_id| {
app_state.widget_map.get(&left_left_widget_id).map( app_state.widget_map.get(&left_left_widget_id).map(
|left_left_widget| { |left_left_widget| &left_left_widget.widget_type,
&left_left_widget.widget_type
},
) )
}) })
.unwrap_or(Some(&BottomWidgetType::Temp)) .unwrap_or(Some(&BottomWidgetType::Temp))
@ -73,12 +65,11 @@ impl BasicTableArrows for Painter {
right_widget right_widget
.right_neighbour .right_neighbour
.map(|right_right_widget_id| { .map(|right_right_widget_id| {
app_state app_state.widget_map.get(&right_right_widget_id).map(
.widget_map |right_right_widget| {
.get(&right_right_widget_id)
.map(|right_right_widget| {
&right_right_widget.widget_type &right_right_widget.widget_type
}) },
)
}) })
.unwrap_or(Some(&BottomWidgetType::Disk)) .unwrap_or(Some(&BottomWidgetType::Disk))
.unwrap_or(&BottomWidgetType::Disk) .unwrap_or(&BottomWidgetType::Disk)
@ -102,7 +93,7 @@ impl BasicTableArrows for Painter {
Spans::default(), Spans::default(),
Spans::from(Span::styled( Spans::from(Span::styled(
format!("{}", left_name), format!("{}", left_name),
self.colours.text_style, painter.colours.text_style,
)), )),
]; ];
@ -110,7 +101,7 @@ impl BasicTableArrows for Painter {
Spans::default(), Spans::default(),
Spans::from(Span::styled( Spans::from(Span::styled(
format!("{}", right_name), format!("{}", right_name),
self.colours.text_style, painter.colours.text_style,
)), )),
]; ];
@ -147,14 +138,12 @@ impl BasicTableArrows for Painter {
// https://github.com/ClementTsang/bottom/pull/459 for details). // https://github.com/ClementTsang/bottom/pull/459 for details).
// - So in other words, to make it simple, we keep this to a standard and overshoot by one here. // - So in other words, to make it simple, we keep this to a standard and overshoot by one here.
if let Some(basic_table) = &mut app_state.basic_table_widget_state { if let Some(basic_table) = &mut app_state.basic_table_widget_state {
basic_table.left_tlc = basic_table.left_tlc = Some((margined_draw_loc[0].x, margined_draw_loc[0].y + 1));
Some((margined_draw_loc[0].x, margined_draw_loc[0].y + 1));
basic_table.left_brc = Some(( basic_table.left_brc = Some((
margined_draw_loc[0].x + margined_draw_loc[0].width, margined_draw_loc[0].x + margined_draw_loc[0].width,
margined_draw_loc[0].y + 2, margined_draw_loc[0].y + 2,
)); ));
basic_table.right_tlc = basic_table.right_tlc = Some((margined_draw_loc[2].x, margined_draw_loc[2].y + 1));
Some((margined_draw_loc[2].x, margined_draw_loc[2].y + 1));
basic_table.right_brc = Some(( basic_table.right_brc = Some((
margined_draw_loc[2].x + margined_draw_loc[2].width, margined_draw_loc[2].x + margined_draw_loc[2].width,
margined_draw_loc[2].y + 2, margined_draw_loc[2].y + 2,
@ -162,5 +151,4 @@ impl BasicTableArrows for Painter {
} }
} }
} }
}
} }

View File

@ -13,27 +13,17 @@ use tui::{
}; };
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
pub trait BatteryDisplayWidget { pub fn draw_battery_display<B: Backend>(
fn draw_battery_display<B: Backend>( painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, draw_border: bool, draw_border: bool, widget_id: u64,
widget_id: u64, ) {
);
}
impl BatteryDisplayWidget for Painter {
fn draw_battery_display<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, draw_border: bool,
widget_id: u64,
) {
let should_get_widget_bounds = app_state.should_get_widget_bounds(); let should_get_widget_bounds = app_state.should_get_widget_bounds();
if let Some(battery_widget_state) = if let Some(battery_widget_state) = app_state.battery_state.widget_states.get_mut(&widget_id) {
app_state.battery_state.widget_states.get_mut(&widget_id)
{
let is_on_widget = widget_id == app_state.current_widget.widget_id; let is_on_widget = widget_id == app_state.current_widget.widget_id;
let border_style = if is_on_widget { let border_style = if is_on_widget {
self.colours.highlighted_border_style painter.colours.highlighted_border_style
} else { } else {
self.colours.border_style painter.colours.border_style
}; };
let table_gap = if draw_loc.height < TABLE_GAP_HEIGHT_LIMIT { let table_gap = if draw_loc.height < TABLE_GAP_HEIGHT_LIMIT {
0 0
@ -44,7 +34,7 @@ impl BatteryDisplayWidget for Painter {
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 ";
Spans::from(vec![ Spans::from(vec![
Span::styled(" Battery ".to_string(), self.colours.widget_title_style), Span::styled(" Battery ".to_string(), painter.colours.widget_title_style),
Span::styled( Span::styled(
format!( format!(
"─{}─ Esc to go back ", "─{}─ Esc to go back ",
@ -58,7 +48,7 @@ impl BatteryDisplayWidget for Painter {
} else { } else {
Spans::from(Span::styled( Spans::from(Span::styled(
" Battery ".to_string(), " Battery ".to_string(),
self.colours.widget_title_style, painter.colours.widget_title_style,
)) ))
}; };
@ -70,7 +60,7 @@ impl BatteryDisplayWidget for Painter {
} else if is_on_widget { } else if is_on_widget {
Block::default() Block::default()
.borders(*SIDE_BORDERS) .borders(*SIDE_BORDERS)
.border_style(self.colours.highlighted_border_style) .border_style(painter.colours.highlighted_border_style)
} else { } else {
Block::default().borders(Borders::NONE) Block::default().borders(Borders::NONE)
}; };
@ -100,8 +90,8 @@ impl BatteryDisplayWidget for Painter {
) )
.block(Block::default()) .block(Block::default())
.divider(tui::symbols::line::VERTICAL) .divider(tui::symbols::line::VERTICAL)
.style(self.colours.text_style) .style(painter.colours.text_style)
.highlight_style(self.colours.currently_selected_text_style) .highlight_style(painter.colours.currently_selected_text_style)
.select(battery_widget_state.currently_selected_battery_index), .select(battery_widget_state.currently_selected_battery_index),
tab_draw_loc, tab_draw_loc,
); );
@ -118,8 +108,7 @@ impl BatteryDisplayWidget for Painter {
.get(battery_widget_state.currently_selected_battery_index) .get(battery_widget_state.currently_selected_battery_index)
{ {
// Assuming a 50/50 split in width // Assuming a 50/50 split in width
let bar_length = let bar_length = usize::from((draw_loc.width.saturating_sub(2) / 2).saturating_sub(8));
usize::from((draw_loc.width.saturating_sub(2) / 2).saturating_sub(8));
let charge_percentage = battery_details.charge_percentage; let charge_percentage = battery_details.charge_percentage;
let num_bars = calculate_basic_use_bars(charge_percentage, bar_length); let num_bars = calculate_basic_use_bars(charge_percentage, bar_length);
let bars = format!( let bars = format!(
@ -131,29 +120,28 @@ impl BatteryDisplayWidget for Painter {
let battery_rows = vec![ let battery_rows = vec![
Row::new(vec![ Row::new(vec![
Cell::from("Charge %").style(self.colours.text_style), Cell::from("Charge %").style(painter.colours.text_style),
Cell::from(bars).style(if charge_percentage < 10.0 { Cell::from(bars).style(if charge_percentage < 10.0 {
self.colours.low_battery_colour painter.colours.low_battery_colour
} else if charge_percentage < 50.0 { } else if charge_percentage < 50.0 {
self.colours.medium_battery_colour painter.colours.medium_battery_colour
} else { } else {
self.colours.high_battery_colour painter.colours.high_battery_colour
}), }),
]), ]),
Row::new(vec!["Consumption", &battery_details.watt_consumption]) Row::new(vec!["Consumption", &battery_details.watt_consumption])
.style(self.colours.text_style), .style(painter.colours.text_style),
if let Some(duration_until_full) = &battery_details.duration_until_full { if let Some(duration_until_full) = &battery_details.duration_until_full {
Row::new(vec!["Time to full", duration_until_full]) Row::new(vec!["Time to full", duration_until_full])
.style(self.colours.text_style) .style(painter.colours.text_style)
} else if let Some(duration_until_empty) = &battery_details.duration_until_empty } else if let Some(duration_until_empty) = &battery_details.duration_until_empty {
{
Row::new(vec!["Time to empty", duration_until_empty]) Row::new(vec!["Time to empty", duration_until_empty])
.style(self.colours.text_style) .style(painter.colours.text_style)
} else { } else {
Row::new(vec!["Time to full/empty", "N/A"]).style(self.colours.text_style) Row::new(vec!["Time to full/empty", "N/A"]).style(painter.colours.text_style)
}, },
Row::new(vec!["Health %", &battery_details.health]) Row::new(vec!["Health %", &battery_details.health])
.style(self.colours.text_style), .style(painter.colours.text_style),
]; ];
// Draw // Draw
@ -169,7 +157,7 @@ impl BatteryDisplayWidget for Painter {
contents.push(Spans::from(Span::styled( contents.push(Spans::from(Span::styled(
"No data found for this battery", "No data found for this battery",
self.colours.text_style, painter.colours.text_style,
))); )));
f.render_widget( f.render_widget(
@ -187,8 +175,7 @@ impl BatteryDisplayWidget for Painter {
for battery in battery_names { for battery in battery_names {
// +1 because there's a space after the tab label. // +1 because there's a space after the tab label.
let width = unicode_width::UnicodeWidthStr::width(battery.as_str()) as u16; let width = unicode_width::UnicodeWidthStr::width(battery.as_str()) as u16;
tab_click_locs tab_click_locs.push(((current_x, current_y), (current_x + width, current_y)));
.push(((current_x, current_y), (current_x + width, current_y)));
// +4 because we want to go one space, then one space past to get to the '|', then 2 more // +4 because we want to go one space, then one space past to get to the '|', then 2 more
// to start at the blank space before the tab label. // to start at the blank space before the tab label.
@ -207,5 +194,4 @@ impl BatteryDisplayWidget for Painter {
} }
} }
} }
}
} }

View File

@ -15,16 +15,10 @@ use tui::{
widgets::{Block, Paragraph}, widgets::{Block, Paragraph},
}; };
pub trait CpuBasicWidget { pub fn draw_basic_cpu<B: Backend>(
fn draw_basic_cpu<B: Backend>( painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, widget_id: u64,
); ) {
}
impl CpuBasicWidget for Painter {
fn draw_basic_cpu<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
) {
// Skip the first element, it's the "all" element // Skip the first element, it's the "all" element
if app_state.canvas_data.cpu_data.len() > 1 { if app_state.canvas_data.cpu_data.len() > 1 {
let cpu_data: &[ConvertedCpuData] = &app_state.canvas_data.cpu_data[1..]; let cpu_data: &[ConvertedCpuData] = &app_state.canvas_data.cpu_data[1..];
@ -43,7 +37,7 @@ impl CpuBasicWidget for Painter {
f.render_widget( f.render_widget(
Block::default() Block::default()
.borders(*SIDE_BORDERS) .borders(*SIDE_BORDERS)
.border_style(self.colours.highlighted_border_style), .border_style(painter.colours.highlighted_border_style),
draw_loc, draw_loc,
); );
} }
@ -164,14 +158,14 @@ impl CpuBasicWidget for Painter {
content: (&cpu_bars[itx]).into(), content: (&cpu_bars[itx]).into(),
style: if show_avg_cpu { style: if show_avg_cpu {
if itx == 0 { if itx == 0 {
self.colours.avg_colour_style painter.colours.avg_colour_style
} else { } else {
self.colours.cpu_colour_styles painter.colours.cpu_colour_styles
[(itx - 1) % self.colours.cpu_colour_styles.len()] [(itx - 1) % painter.colours.cpu_colour_styles.len()]
} }
} else { } else {
self.colours.cpu_colour_styles painter.colours.cpu_colour_styles
[itx % self.colours.cpu_colour_styles.len()] [itx % painter.colours.cpu_colour_styles.len()]
}, },
}) })
}) })
@ -202,5 +196,4 @@ impl CpuBasicWidget for Painter {
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height)); Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
} }
} }
}
} }

View File

@ -32,22 +32,10 @@ static CPU_LEGEND_HEADER_LENS: Lazy<Vec<u16>> = Lazy::new(|| {
.collect::<Vec<_>>() .collect::<Vec<_>>()
}); });
pub trait CpuGraphWidget { pub fn draw_cpu<B: Backend>(
fn draw_cpu<B: Backend>( painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, widget_id: u64,
); ) {
fn draw_cpu_graph<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
);
fn draw_cpu_legend<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
);
}
impl CpuGraphWidget for Painter {
fn draw_cpu<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
) {
if draw_loc.width as f64 * 0.15 <= 6.0 { if draw_loc.width as f64 * 0.15 <= 6.0 {
// Skip drawing legend // Skip drawing legend
if app_state.current_widget.widget_id == (widget_id + 1) { if app_state.current_widget.widget_id == (widget_id + 1) {
@ -57,7 +45,7 @@ impl CpuGraphWidget for Painter {
app_state.move_widget_selection(&WidgetDirection::Left); app_state.move_widget_selection(&WidgetDirection::Left);
} }
} }
self.draw_cpu_graph(f, app_state, draw_loc, widget_id); draw_cpu_graph(painter, f, app_state, draw_loc, widget_id);
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) {
cpu_widget_state.is_legend_hidden = true; cpu_widget_state.is_legend_hidden = true;
} }
@ -71,8 +59,7 @@ impl CpuGraphWidget for Painter {
} }
} }
} else { } else {
let (graph_index, legend_index, constraints) = let (graph_index, legend_index, constraints) = if app_state.app_config_fields.left_legend {
if app_state.app_config_fields.left_legend {
( (
1, 1,
0, 0,
@ -92,8 +79,15 @@ impl CpuGraphWidget for Painter {
.constraints(constraints) .constraints(constraints)
.split(draw_loc); .split(draw_loc);
self.draw_cpu_graph(f, app_state, partitioned_draw_loc[graph_index], widget_id); draw_cpu_graph(
self.draw_cpu_legend( painter,
f,
app_state,
partitioned_draw_loc[graph_index],
widget_id,
);
draw_cpu_legend(
painter,
f, f,
app_state, app_state,
partitioned_draw_loc[legend_index], partitioned_draw_loc[legend_index],
@ -108,10 +102,8 @@ impl CpuGraphWidget for Painter {
partitioned_draw_loc[graph_index].y, partitioned_draw_loc[graph_index].y,
)); ));
cpu_widget.bottom_right_corner = Some(( cpu_widget.bottom_right_corner = Some((
partitioned_draw_loc[graph_index].x partitioned_draw_loc[graph_index].x + partitioned_draw_loc[graph_index].width,
+ partitioned_draw_loc[graph_index].width, partitioned_draw_loc[graph_index].y + partitioned_draw_loc[graph_index].height,
partitioned_draw_loc[graph_index].y
+ partitioned_draw_loc[graph_index].height,
)); ));
} }
@ -121,33 +113,33 @@ impl CpuGraphWidget for Painter {
partitioned_draw_loc[legend_index].y, partitioned_draw_loc[legend_index].y,
)); ));
legend_widget.bottom_right_corner = Some(( legend_widget.bottom_right_corner = Some((
partitioned_draw_loc[legend_index].x partitioned_draw_loc[legend_index].x + partitioned_draw_loc[legend_index].width,
+ partitioned_draw_loc[legend_index].width,
partitioned_draw_loc[legend_index].y partitioned_draw_loc[legend_index].y
+ partitioned_draw_loc[legend_index].height, + partitioned_draw_loc[legend_index].height,
)); ));
} }
} }
} }
} }
fn draw_cpu_graph<B: Backend>( fn draw_cpu_graph<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
) { widget_id: u64,
) {
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( Span::styled(
format!("{}s", cpu_widget_state.current_display_time / 1000), format!("{}s", cpu_widget_state.current_display_time / 1000),
self.colours.graph_style, painter.colours.graph_style,
), ),
Span::styled("0s".to_string(), self.colours.graph_style), Span::styled("0s".to_string(), painter.colours.graph_style),
]; ];
let y_axis_labels = vec![ let y_axis_labels = vec![
Span::styled(" 0%", self.colours.graph_style), Span::styled(" 0%", painter.colours.graph_style),
Span::styled("100%", self.colours.graph_style), Span::styled("100%", painter.colours.graph_style),
]; ];
let time_start = -(cpu_widget_state.current_display_time as f64); let time_start = -(cpu_widget_state.current_display_time as f64);
@ -163,7 +155,7 @@ impl CpuGraphWidget for Painter {
{ {
Axis::default() Axis::default()
.bounds([time_start, 0.0]) .bounds([time_start, 0.0])
.style(self.colours.graph_style) .style(painter.colours.graph_style)
.labels(display_time_labels) .labels(display_time_labels)
} else { } else {
cpu_widget_state.autohide_timer = None; cpu_widget_state.autohide_timer = None;
@ -174,12 +166,12 @@ impl CpuGraphWidget for Painter {
} else { } else {
Axis::default() Axis::default()
.bounds([time_start, 0.0]) .bounds([time_start, 0.0])
.style(self.colours.graph_style) .style(painter.colours.graph_style)
.labels(display_time_labels) .labels(display_time_labels)
}; };
let y_axis = Axis::default() let y_axis = Axis::default()
.style(self.colours.graph_style) .style(painter.colours.graph_style)
.bounds([0.0, 100.5]) .bounds([0.0, 100.5])
.labels(y_axis_labels); .labels(y_axis_labels);
@ -252,17 +244,17 @@ impl CpuGraphWidget for Painter {
Marker::Braille Marker::Braille
}) })
.style(if show_avg_cpu && itx == AVG_POSITION { .style(if show_avg_cpu && itx == AVG_POSITION {
self.colours.avg_colour_style painter.colours.avg_colour_style
} else if itx == ALL_POSITION { } else if itx == ALL_POSITION {
self.colours.all_colour_style painter.colours.all_colour_style
} else { } else {
self.colours.cpu_colour_styles[(itx - 1 // Because of the all position painter.colours.cpu_colour_styles[(itx - 1 // Because of the all position
- (if show_avg_cpu { - (if show_avg_cpu {
AVG_POSITION AVG_POSITION
} else { } else {
0 0
})) }))
% self.colours.cpu_colour_styles.len()] % painter.colours.cpu_colour_styles.len()]
}) })
.data(&cpu.cpu_data[..]) .data(&cpu.cpu_data[..])
.graph_type(tui::widgets::GraphType::Line) .graph_type(tui::widgets::GraphType::Line)
@ -276,9 +268,9 @@ impl CpuGraphWidget for Painter {
Marker::Braille Marker::Braille
}) })
.style(if show_avg_cpu && current_scroll_position == AVG_POSITION { .style(if show_avg_cpu && current_scroll_position == AVG_POSITION {
self.colours.avg_colour_style painter.colours.avg_colour_style
} else { } else {
self.colours.cpu_colour_styles[(cpu_widget_state painter.colours.cpu_colour_styles[(cpu_widget_state
.scroll_state .scroll_state
.current_scroll_position .current_scroll_position
- 1 // Because of the all position - 1 // Because of the all position
@ -287,7 +279,7 @@ impl CpuGraphWidget for Painter {
} else { } else {
0 0
})) }))
% self.colours.cpu_colour_styles.len()] % painter.colours.cpu_colour_styles.len()]
}) })
.data(&cpu.cpu_data[..]) .data(&cpu.cpu_data[..])
.graph_type(tui::widgets::GraphType::Line)] .graph_type(tui::widgets::GraphType::Line)]
@ -297,9 +289,9 @@ impl CpuGraphWidget for Painter {
let is_on_widget = widget_id == app_state.current_widget.widget_id; let is_on_widget = widget_id == app_state.current_widget.widget_id;
let border_style = if is_on_widget { let border_style = if is_on_widget {
self.colours.highlighted_border_style painter.colours.highlighted_border_style
} else { } else {
self.colours.border_style painter.colours.border_style
}; };
let title = if cfg!(target_family = "unix") { let title = if cfg!(target_family = "unix") {
@ -315,8 +307,8 @@ impl CpuGraphWidget for Painter {
const TITLE_BASE: &str = " CPU ── Esc to go back "; const TITLE_BASE: &str = " CPU ── Esc to go back ";
Spans::from(vec![ Spans::from(vec![
Span::styled(" CPU ", self.colours.widget_title_style), Span::styled(" CPU ", painter.colours.widget_title_style),
Span::styled(load_avg_str, self.colours.widget_title_style), Span::styled(load_avg_str, painter.colours.widget_title_style),
Span::styled( Span::styled(
format!( format!(
"─{}─ Esc to go back ", "─{}─ Esc to go back ",
@ -331,15 +323,15 @@ impl CpuGraphWidget for Painter {
]) ])
} else { } else {
Spans::from(vec![ Spans::from(vec![
Span::styled(" CPU ", self.colours.widget_title_style), Span::styled(" CPU ", painter.colours.widget_title_style),
Span::styled(load_avg_str, self.colours.widget_title_style), Span::styled(load_avg_str, painter.colours.widget_title_style),
]) ])
} }
} else if app_state.is_expanded { } else if app_state.is_expanded {
const TITLE_BASE: &str = " CPU ── Esc to go back "; const TITLE_BASE: &str = " CPU ── Esc to go back ";
Spans::from(vec![ Spans::from(vec![
Span::styled(" CPU ", self.colours.widget_title_style), Span::styled(" CPU ", painter.colours.widget_title_style),
Span::styled( Span::styled(
format!( format!(
"─{}─ Esc to go back ", "─{}─ Esc to go back ",
@ -351,7 +343,10 @@ impl CpuGraphWidget for Painter {
), ),
]) ])
} else { } else {
Spans::from(vec![Span::styled(" CPU ", self.colours.widget_title_style)]) Spans::from(vec![Span::styled(
" CPU ",
painter.colours.widget_title_style,
)])
}; };
f.render_widget( f.render_widget(
@ -379,14 +374,14 @@ impl CpuGraphWidget for Painter {
} }
}); });
} }
} }
fn draw_cpu_legend<B: Backend>( fn draw_cpu_legend<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
) { widget_id: u64,
) {
let recalculate_column_widths = app_state.should_get_widget_bounds(); let recalculate_column_widths = app_state.should_get_widget_bounds();
if let Some(cpu_widget_state) = app_state.cpu_state.widget_states.get_mut(&(widget_id - 1)) if let Some(cpu_widget_state) = app_state.cpu_state.widget_states.get_mut(&(widget_id - 1)) {
{
cpu_widget_state.is_legend_hidden = false; cpu_widget_state.is_legend_hidden = false;
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 cpu_table_state = &mut cpu_widget_state.scroll_state.table_state; let cpu_table_state = &mut cpu_widget_state.scroll_state.table_state;
@ -398,7 +393,7 @@ impl CpuGraphWidget for Painter {
}; };
let start_position = get_start_position( let start_position = get_start_position(
usize::from( usize::from(
(draw_loc.height + (1 - table_gap)).saturating_sub(self.table_height_offset), (draw_loc.height + (1 - table_gap)).saturating_sub(painter.table_height_offset),
), ),
&cpu_widget_state.scroll_state.scroll_direction, &cpu_widget_state.scroll_state.scroll_direction,
&mut cpu_widget_state.scroll_state.previous_scroll_position, &mut cpu_widget_state.scroll_state.previous_scroll_position,
@ -474,36 +469,34 @@ impl CpuGraphWidget for Painter {
&& itx == offset_scroll_index && itx == offset_scroll_index
&& itx + start_position == ALL_POSITION && itx + start_position == ALL_POSITION
{ {
truncated_name.patch_style(self.colours.currently_selected_text_style); truncated_name.patch_style(painter.colours.currently_selected_text_style);
Row::new(vec![truncated_name, truncated_legend]) Row::new(vec![truncated_name, truncated_legend])
} else { } else {
let cpu_string_row = vec![truncated_name, truncated_legend]; let cpu_string_row = vec![truncated_name, truncated_legend];
Row::new(cpu_string_row).style(if itx == offset_scroll_index { Row::new(cpu_string_row).style(if itx == offset_scroll_index {
self.colours.currently_selected_text_style painter.colours.currently_selected_text_style
} else if itx + start_position == ALL_POSITION { } else if itx + start_position == ALL_POSITION {
self.colours.all_colour_style painter.colours.all_colour_style
} else if show_avg_cpu { } else if show_avg_cpu {
if itx + start_position == AVG_POSITION { if itx + start_position == AVG_POSITION {
self.colours.avg_colour_style painter.colours.avg_colour_style
} else { } else {
self.colours.cpu_colour_styles[(itx + start_position painter.colours.cpu_colour_styles[(itx + start_position - AVG_POSITION - 1)
- AVG_POSITION % painter.colours.cpu_colour_styles.len()]
- 1)
% self.colours.cpu_colour_styles.len()]
} }
} else { } else {
self.colours.cpu_colour_styles[(itx + start_position - ALL_POSITION - 1) painter.colours.cpu_colour_styles[(itx + start_position - ALL_POSITION - 1)
% self.colours.cpu_colour_styles.len()] % painter.colours.cpu_colour_styles.len()]
}) })
} }
}); });
// Note we don't set highlight_style, as it should always be shown for this widget. // Note we don't set highlight_style, as it should always be shown for this widget.
let border_and_title_style = if is_on_widget { let border_and_title_style = if is_on_widget {
self.colours.highlighted_border_style painter.colours.highlighted_border_style
} else { } else {
self.colours.border_style painter.colours.border_style
}; };
// Draw // Draw
@ -516,7 +509,7 @@ impl CpuGraphWidget for Painter {
) )
.header( .header(
Row::new(CPU_LEGEND_HEADER.to_vec()) Row::new(CPU_LEGEND_HEADER.to_vec())
.style(self.colours.table_header_style) .style(painter.colours.table_header_style)
.bottom_margin(table_gap), .bottom_margin(table_gap),
) )
.widths( .widths(
@ -531,5 +524,4 @@ impl CpuGraphWidget for Painter {
cpu_table_state, cpu_table_state,
); );
} }
}
} }

View File

@ -27,18 +27,10 @@ static DISK_HEADERS_LENS: Lazy<Vec<u16>> = Lazy::new(|| {
.collect::<Vec<_>>() .collect::<Vec<_>>()
}); });
pub trait DiskTableWidget { pub fn draw_disk_table<B: Backend>(
fn draw_disk_table<B: Backend>( painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut app::AppState, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, app_state: &mut app::AppState, draw_loc: Rect,
draw_border: bool, widget_id: u64, draw_border: bool, widget_id: u64,
); ) {
}
impl DiskTableWidget for Painter {
fn draw_disk_table<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut app::AppState, draw_loc: Rect,
draw_border: bool, widget_id: u64,
) {
let recalculate_column_widths = app_state.should_get_widget_bounds(); let recalculate_column_widths = app_state.should_get_widget_bounds();
if let Some(disk_widget_state) = app_state.disk_state.widget_states.get_mut(&widget_id) { if let Some(disk_widget_state) = app_state.disk_state.widget_states.get_mut(&widget_id) {
let table_gap = if draw_loc.height < TABLE_GAP_HEIGHT_LIMIT { let table_gap = if draw_loc.height < TABLE_GAP_HEIGHT_LIMIT {
@ -48,7 +40,7 @@ impl DiskTableWidget for Painter {
}; };
let start_position = get_start_position( let start_position = get_start_position(
usize::from( usize::from(
(draw_loc.height + (1 - table_gap)).saturating_sub(self.table_height_offset), (draw_loc.height + (1 - table_gap)).saturating_sub(painter.table_height_offset),
), ),
&disk_widget_state.scroll_state.scroll_direction, &disk_widget_state.scroll_state.scroll_direction,
&mut disk_widget_state.scroll_state.previous_scroll_position, &mut disk_widget_state.scroll_state.previous_scroll_position,
@ -117,10 +109,13 @@ impl DiskTableWidget for Painter {
let dcw = &disk_widget_state.table_width_state.desired_column_widths; let dcw = &disk_widget_state.table_width_state.desired_column_widths;
let ccw = &disk_widget_state.table_width_state.calculated_column_widths; let ccw = &disk_widget_state.table_width_state.calculated_column_widths;
let disk_rows = let disk_rows = sliced_vec.iter().map(|disk_row| {
sliced_vec.iter().map(|disk_row| { let truncated_data =
let truncated_data = disk_row.iter().zip(&hard_widths).enumerate().map( disk_row
|(itx, (entry, width))| { .iter()
.zip(&hard_widths)
.enumerate()
.map(|(itx, (entry, width))| {
if width.is_none() { if width.is_none() {
if let (Some(desired_col_width), Some(calculated_col_width)) = if let (Some(desired_col_width), Some(calculated_col_width)) =
(dcw.get(itx), ccw.get(itx)) (dcw.get(itx), ccw.get(itx))
@ -146,19 +141,18 @@ impl DiskTableWidget for Painter {
} }
Text::raw(entry) Text::raw(entry)
}, });
);
Row::new(truncated_data) Row::new(truncated_data)
}); });
let (border_style, highlight_style) = if is_on_widget { let (border_style, highlight_style) = if is_on_widget {
( (
self.colours.highlighted_border_style, painter.colours.highlighted_border_style,
self.colours.currently_selected_text_style, painter.colours.currently_selected_text_style,
) )
} else { } else {
(self.colours.border_style, self.colours.text_style) (painter.colours.border_style, painter.colours.text_style)
}; };
let title_base = if app_state.app_config_fields.show_table_scroll_position { let title_base = if app_state.app_config_fields.show_table_scroll_position {
@ -197,16 +191,13 @@ impl DiskTableWidget for Painter {
}; };
Spans::from(vec![ Spans::from(vec![
Span::styled(chosen_title_base, self.colours.widget_title_style), Span::styled(chosen_title_base, painter.colours.widget_title_style),
Span::styled( Span::styled(
format!( format!(
"─{}─ Esc to go back ", "─{}─ Esc to go back ",
"".repeat( "".repeat(
usize::from(draw_loc.width).saturating_sub( usize::from(draw_loc.width).saturating_sub(
UnicodeSegmentation::graphemes( UnicodeSegmentation::graphemes(expanded_title_base.as_str(), true)
expanded_title_base.as_str(),
true
)
.count() .count()
+ 2 + 2
) )
@ -216,7 +207,7 @@ impl DiskTableWidget for Painter {
), ),
]) ])
} else { } else {
Spans::from(Span::styled(title_base, self.colours.widget_title_style)) Spans::from(Span::styled(title_base, painter.colours.widget_title_style))
}; };
let disk_block = if draw_border { let disk_block = if draw_border {
@ -227,7 +218,7 @@ impl DiskTableWidget for Painter {
} else if is_on_widget { } else if is_on_widget {
Block::default() Block::default()
.borders(*SIDE_BORDERS) .borders(*SIDE_BORDERS)
.border_style(self.colours.highlighted_border_style) .border_style(painter.colours.highlighted_border_style)
} else { } else {
Block::default().borders(Borders::NONE) Block::default().borders(Borders::NONE)
}; };
@ -244,11 +235,11 @@ impl DiskTableWidget for Painter {
.block(disk_block) .block(disk_block)
.header( .header(
Row::new(DISK_HEADERS.to_vec()) Row::new(DISK_HEADERS.to_vec())
.style(self.colours.table_header_style) .style(painter.colours.table_header_style)
.bottom_margin(table_gap), .bottom_margin(table_gap),
) )
.highlight_style(highlight_style) .highlight_style(highlight_style)
.style(self.colours.text_style) .style(painter.colours.text_style)
.widths( .widths(
&(disk_widget_state &(disk_widget_state
.table_width_state .table_width_state
@ -272,5 +263,4 @@ impl DiskTableWidget for Painter {
} }
} }
} }
}
} }

View File

@ -13,16 +13,10 @@ use tui::{
widgets::{Block, Paragraph}, widgets::{Block, Paragraph},
}; };
pub trait MemBasicWidget { pub fn draw_basic_memory<B: Backend>(
fn draw_basic_memory<B: Backend>( painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, widget_id: u64,
); ) {
}
impl MemBasicWidget for Painter {
fn draw_basic_memory<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
) {
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;
@ -35,7 +29,7 @@ impl MemBasicWidget for Painter {
f.render_widget( f.render_widget(
Block::default() Block::default()
.borders(*SIDE_BORDERS) .borders(*SIDE_BORDERS)
.border_style(self.colours.highlighted_border_style), .border_style(painter.colours.highlighted_border_style),
draw_loc, draw_loc,
); );
} }
@ -109,8 +103,8 @@ impl MemBasicWidget for Painter {
}; };
let mem_text = vec![ let mem_text = vec![
Spans::from(Span::styled(mem_label, self.colours.ram_style)), Spans::from(Span::styled(mem_label, painter.colours.ram_style)),
Spans::from(Span::styled(swap_label, self.colours.swap_style)), Spans::from(Span::styled(swap_label, painter.colours.swap_style)),
]; ];
f.render_widget( f.render_widget(
@ -126,5 +120,4 @@ impl MemBasicWidget for Painter {
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height)); Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
} }
} }
}
} }

View File

@ -15,16 +15,10 @@ use tui::{
}; };
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
pub trait MemGraphWidget { pub fn draw_memory_graph<B: Backend>(
fn draw_memory_graph<B: Backend>( painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, widget_id: u64,
); ) {
}
impl MemGraphWidget for Painter {
fn draw_memory_graph<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
) {
if let Some(mem_widget_state) = app_state.mem_state.widget_states.get_mut(&widget_id) { if let Some(mem_widget_state) = app_state.mem_state.widget_states.get_mut(&widget_id) {
let mem_data: &mut [(f64, f64)] = &mut app_state.canvas_data.mem_data; let mem_data: &mut [(f64, f64)] = &mut app_state.canvas_data.mem_data;
let swap_data: &mut [(f64, f64)] = &mut app_state.canvas_data.swap_data; let swap_data: &mut [(f64, f64)] = &mut app_state.canvas_data.swap_data;
@ -34,13 +28,13 @@ impl MemGraphWidget for Painter {
let display_time_labels = vec![ let display_time_labels = vec![
Span::styled( Span::styled(
format!("{}s", mem_widget_state.current_display_time / 1000), format!("{}s", mem_widget_state.current_display_time / 1000),
self.colours.graph_style, painter.colours.graph_style,
), ),
Span::styled("0s".to_string(), self.colours.graph_style), Span::styled("0s".to_string(), painter.colours.graph_style),
]; ];
let y_axis_label = vec![ let y_axis_label = vec![
Span::styled(" 0%", self.colours.graph_style), Span::styled(" 0%", painter.colours.graph_style),
Span::styled("100%", self.colours.graph_style), Span::styled("100%", painter.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
@ -54,7 +48,7 @@ impl MemGraphWidget for Painter {
{ {
Axis::default() Axis::default()
.bounds([time_start, 0.0]) .bounds([time_start, 0.0])
.style(self.colours.graph_style) .style(painter.colours.graph_style)
.labels(display_time_labels) .labels(display_time_labels)
} else { } else {
mem_widget_state.autohide_timer = None; mem_widget_state.autohide_timer = None;
@ -65,12 +59,12 @@ impl MemGraphWidget for Painter {
} else { } else {
Axis::default() Axis::default()
.bounds([time_start, 0.0]) .bounds([time_start, 0.0])
.style(self.colours.graph_style) .style(painter.colours.graph_style)
.labels(display_time_labels) .labels(display_time_labels)
}; };
let y_axis = Axis::default() let y_axis = Axis::default()
.style(self.colours.graph_style) .style(painter.colours.graph_style)
.bounds([0.0, 100.5]) .bounds([0.0, 100.5])
.labels(y_axis_label); .labels(y_axis_label);
@ -84,8 +78,7 @@ impl MemGraphWidget for Painter {
let outside_point = mem_data.get(start_pos); let outside_point = mem_data.get(start_pos);
let inside_point = mem_data.get(end_pos); let inside_point = mem_data.get(end_pos);
if let (Some(outside_point), Some(inside_point)) = (outside_point, inside_point) if let (Some(outside_point), Some(inside_point)) = (outside_point, inside_point) {
{
let old = *outside_point; let old = *outside_point;
let new_point = ( let new_point = (
@ -118,8 +111,7 @@ impl MemGraphWidget for Painter {
let outside_point = swap_data.get(start_pos); let outside_point = swap_data.get(start_pos);
let inside_point = swap_data.get(end_pos); let inside_point = swap_data.get(end_pos);
if let (Some(outside_point), Some(inside_point)) = (outside_point, inside_point) if let (Some(outside_point), Some(inside_point)) = (outside_point, inside_point) {
{
let old = *outside_point; let old = *outside_point;
let new_point = ( let new_point = (
@ -155,7 +147,7 @@ impl MemGraphWidget for Painter {
} else { } else {
Marker::Braille Marker::Braille
}) })
.style(self.colours.ram_style) .style(painter.colours.ram_style)
.data(mem_data) .data(mem_data)
.graph_type(tui::widgets::GraphType::Line), .graph_type(tui::widgets::GraphType::Line),
); );
@ -171,7 +163,7 @@ impl MemGraphWidget for Painter {
} else { } else {
Marker::Braille Marker::Braille
}) })
.style(self.colours.swap_style) .style(painter.colours.swap_style)
.data(swap_data) .data(swap_data)
.graph_type(tui::widgets::GraphType::Line), .graph_type(tui::widgets::GraphType::Line),
); );
@ -179,15 +171,15 @@ impl MemGraphWidget for Painter {
let is_on_widget = widget_id == app_state.current_widget.widget_id; let is_on_widget = widget_id == app_state.current_widget.widget_id;
let border_style = if is_on_widget { let border_style = if is_on_widget {
self.colours.highlighted_border_style painter.colours.highlighted_border_style
} else { } else {
self.colours.border_style painter.colours.border_style
}; };
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 ";
Spans::from(vec![ Spans::from(vec![
Span::styled(" Memory ", self.colours.widget_title_style), Span::styled(" Memory ", painter.colours.widget_title_style),
Span::styled( Span::styled(
format!( format!(
"─{}─ Esc to go back ", "─{}─ Esc to go back ",
@ -201,7 +193,7 @@ impl MemGraphWidget for Painter {
} else { } else {
Spans::from(Span::styled( Spans::from(Span::styled(
" Memory ".to_string(), " Memory ".to_string(),
self.colours.widget_title_style, painter.colours.widget_title_style,
)) ))
}; };
@ -212,9 +204,9 @@ impl MemGraphWidget for Painter {
.title(title) .title(title)
.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 painter.colours.highlighted_border_style
} else { } else {
self.colours.border_style painter.colours.border_style
}), }),
) )
.x_axis(x_axis) .x_axis(x_axis)
@ -245,5 +237,4 @@ impl MemGraphWidget for Painter {
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height)); Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
} }
} }
}
} }

View File

@ -8,16 +8,10 @@ use tui::{
widgets::{Block, Paragraph}, widgets::{Block, Paragraph},
}; };
pub trait NetworkBasicWidget { pub fn draw_basic_network<B: Backend>(
fn draw_basic_network<B: Backend>( painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, widget_id: u64,
); ) {
}
impl NetworkBasicWidget for Painter {
fn draw_basic_network<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
) {
let divided_loc = Layout::default() let divided_loc = Layout::default()
.direction(Direction::Horizontal) .direction(Direction::Horizontal)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
@ -39,7 +33,7 @@ impl NetworkBasicWidget for Painter {
f.render_widget( f.render_widget(
Block::default() Block::default()
.borders(*SIDE_BORDERS) .borders(*SIDE_BORDERS)
.border_style(self.colours.highlighted_border_style), .border_style(painter.colours.highlighted_border_style),
draw_loc, draw_loc,
); );
} }
@ -50,13 +44,13 @@ impl NetworkBasicWidget for Painter {
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 = vec![
Spans::from(Span::styled(rx_label, self.colours.rx_style)), Spans::from(Span::styled(rx_label, painter.colours.rx_style)),
Spans::from(Span::styled(tx_label, self.colours.tx_style)), Spans::from(Span::styled(tx_label, painter.colours.tx_style)),
]; ];
let total_net_text = vec![ let total_net_text = vec![
Spans::from(Span::styled(total_rx_label, self.colours.total_rx_style)), Spans::from(Span::styled(total_rx_label, painter.colours.total_rx_style)),
Spans::from(Span::styled(total_tx_label, self.colours.total_tx_style)), Spans::from(Span::styled(total_tx_label, painter.colours.total_tx_style)),
]; ];
f.render_widget(Paragraph::new(net_text).block(Block::default()), net_loc[0]); f.render_widget(Paragraph::new(net_text).block(Block::default()), net_loc[0]);
@ -74,5 +68,4 @@ impl NetworkBasicWidget for Painter {
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height)); Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
} }
} }
}
} }

View File

@ -32,25 +32,10 @@ static NETWORK_HEADERS_LENS: Lazy<Vec<u16>> = Lazy::new(|| {
.collect::<Vec<_>>() .collect::<Vec<_>>()
}); });
pub trait NetworkGraphWidget { pub fn draw_network<B: Backend>(
fn draw_network<B: Backend>( painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, widget_id: u64,
); ) {
fn draw_network_graph<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
hide_legend: bool,
);
fn draw_network_labels<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
);
}
impl NetworkGraphWidget for Painter {
fn draw_network<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64,
) {
if app_state.app_config_fields.use_old_network_legend { if app_state.app_config_fields.use_old_network_legend {
let network_chunk = Layout::default() let network_chunk = Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
@ -61,10 +46,10 @@ impl NetworkGraphWidget for Painter {
]) ])
.split(draw_loc); .split(draw_loc);
self.draw_network_graph(f, app_state, network_chunk[0], widget_id, true); draw_network_graph(painter, f, app_state, network_chunk[0], widget_id, true);
self.draw_network_labels(f, app_state, network_chunk[1], widget_id); draw_network_labels(painter, f, app_state, network_chunk[1], widget_id);
} else { } else {
self.draw_network_graph(f, app_state, draw_loc, widget_id, false); draw_network_graph(painter, f, app_state, draw_loc, widget_id, false);
} }
if app_state.should_get_widget_bounds() { if app_state.should_get_widget_bounds() {
@ -77,12 +62,12 @@ impl NetworkGraphWidget for Painter {
Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height)); Some((draw_loc.x + draw_loc.width, draw_loc.y + draw_loc.height));
} }
} }
} }
fn draw_network_graph<B: Backend>( pub fn draw_network_graph<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
hide_legend: bool, widget_id: u64, hide_legend: bool,
) { ) {
/// Point is of time, data /// Point is of time, data
type Point = (f64, f64); type Point = (f64, f64);
@ -427,9 +412,9 @@ impl NetworkGraphWidget for Painter {
let display_time_labels = vec![ let display_time_labels = vec![
Span::styled( Span::styled(
format!("{}s", network_widget_state.current_display_time / 1000), format!("{}s", network_widget_state.current_display_time / 1000),
self.colours.graph_style, painter.colours.graph_style,
), ),
Span::styled("0s".to_string(), self.colours.graph_style), Span::styled("0s".to_string(), painter.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
@ -442,7 +427,7 @@ impl NetworkGraphWidget for Painter {
{ {
Axis::default() Axis::default()
.bounds([time_start, 0.0]) .bounds([time_start, 0.0])
.style(self.colours.graph_style) .style(painter.colours.graph_style)
.labels(display_time_labels) .labels(display_time_labels)
} else { } else {
network_widget_state.autohide_timer = None; network_widget_state.autohide_timer = None;
@ -453,7 +438,7 @@ impl NetworkGraphWidget for Painter {
} else { } else {
Axis::default() Axis::default()
.bounds([time_start, 0.0]) .bounds([time_start, 0.0])
.style(self.colours.graph_style) .style(painter.colours.graph_style)
.labels(display_time_labels) .labels(display_time_labels)
}; };
@ -569,24 +554,24 @@ impl NetworkGraphWidget for Painter {
let y_axis_labels = labels let y_axis_labels = labels
.iter() .iter()
.map(|label| Span::styled(label, self.colours.graph_style)) .map(|label| Span::styled(label, painter.colours.graph_style))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let y_axis = Axis::default() let y_axis = Axis::default()
.style(self.colours.graph_style) .style(painter.colours.graph_style)
.bounds([0.0, max_range]) .bounds([0.0, max_range])
.labels(y_axis_labels); .labels(y_axis_labels);
let is_on_widget = widget_id == app_state.current_widget.widget_id; let is_on_widget = widget_id == app_state.current_widget.widget_id;
let border_style = if is_on_widget { let border_style = if is_on_widget {
self.colours.highlighted_border_style painter.colours.highlighted_border_style
} else { } else {
self.colours.border_style painter.colours.border_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 ";
Spans::from(vec![ Spans::from(vec![
Span::styled(" Network ", self.colours.widget_title_style), Span::styled(" Network ", painter.colours.widget_title_style),
Span::styled( Span::styled(
format!( format!(
"─{}─ Esc to go back ", "─{}─ Esc to go back ",
@ -598,7 +583,10 @@ impl NetworkGraphWidget for Painter {
), ),
]) ])
} else { } else {
Spans::from(Span::styled(" Network ", self.colours.widget_title_style)) Spans::from(Span::styled(
" Network ",
painter.colours.widget_title_style,
))
}; };
let legend_constraints = if hide_legend { let legend_constraints = if hide_legend {
@ -617,7 +605,7 @@ impl NetworkGraphWidget for Painter {
} else { } else {
Marker::Braille Marker::Braille
}) })
.style(self.colours.rx_style) .style(painter.colours.rx_style)
.data(network_data_rx) .data(network_data_rx)
.graph_type(tui::widgets::GraphType::Line), .graph_type(tui::widgets::GraphType::Line),
Dataset::default() Dataset::default()
@ -627,7 +615,7 @@ impl NetworkGraphWidget for Painter {
} else { } else {
Marker::Braille Marker::Braille
}) })
.style(self.colours.tx_style) .style(painter.colours.tx_style)
.data(network_data_tx) .data(network_data_tx)
.graph_type(tui::widgets::GraphType::Line), .graph_type(tui::widgets::GraphType::Line),
Dataset::default() Dataset::default()
@ -635,13 +623,13 @@ impl NetworkGraphWidget for Painter {
"Total RX: {:7}", "Total RX: {:7}",
app_state.canvas_data.total_rx_display app_state.canvas_data.total_rx_display
)) ))
.style(self.colours.total_rx_style), .style(painter.colours.total_rx_style),
Dataset::default() Dataset::default()
.name(format!( .name(format!(
"Total TX: {:7}", "Total TX: {:7}",
app_state.canvas_data.total_tx_display app_state.canvas_data.total_tx_display
)) ))
.style(self.colours.total_tx_style), .style(painter.colours.total_tx_style),
] ]
} else { } else {
vec![ vec![
@ -652,7 +640,7 @@ impl NetworkGraphWidget for Painter {
} else { } else {
Marker::Braille Marker::Braille
}) })
.style(self.colours.rx_style) .style(painter.colours.rx_style)
.data(network_data_rx) .data(network_data_rx)
.graph_type(tui::widgets::GraphType::Line), .graph_type(tui::widgets::GraphType::Line),
Dataset::default() Dataset::default()
@ -662,7 +650,7 @@ impl NetworkGraphWidget for Painter {
} else { } else {
Marker::Braille Marker::Braille
}) })
.style(self.colours.tx_style) .style(painter.colours.tx_style)
.data(network_data_tx) .data(network_data_tx)
.graph_type(tui::widgets::GraphType::Line), .graph_type(tui::widgets::GraphType::Line),
] ]
@ -675,9 +663,9 @@ impl NetworkGraphWidget for Painter {
.title(title) .title(title)
.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 painter.colours.highlighted_border_style
} else { } else {
self.colours.border_style painter.colours.border_style
}), }),
) )
.x_axis(x_axis) .x_axis(x_axis)
@ -699,11 +687,12 @@ impl NetworkGraphWidget for Painter {
} }
} }
} }
} }
fn draw_network_labels<B: Backend>( fn draw_network_labels<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, widget_id: u64, painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
) { widget_id: u64,
) {
let table_gap = if draw_loc.height < TABLE_GAP_HEIGHT_LIMIT { let table_gap = if draw_loc.height < TABLE_GAP_HEIGHT_LIMIT {
0 0
} else { } else {
@ -724,7 +713,7 @@ impl NetworkGraphWidget for Painter {
]]; ]];
let mapped_network = total_network let mapped_network = total_network
.into_iter() .into_iter()
.map(|val| Row::new(val).style(self.colours.text_style)); .map(|val| Row::new(val).style(painter.colours.text_style));
// Calculate widths // Calculate widths
let intrinsic_widths = get_column_widths( let intrinsic_widths = get_column_widths(
@ -747,17 +736,17 @@ impl NetworkGraphWidget for Painter {
Table::new(mapped_network) Table::new(mapped_network)
.header( .header(
Row::new(NETWORK_HEADERS.to_vec()) Row::new(NETWORK_HEADERS.to_vec())
.style(self.colours.table_header_style) .style(painter.colours.table_header_style)
.bottom_margin(table_gap), .bottom_margin(table_gap),
) )
.block(Block::default().borders(Borders::ALL).border_style( .block(Block::default().borders(Borders::ALL).border_style(
if app_state.current_widget.widget_id == widget_id { if app_state.current_widget.widget_id == widget_id {
self.colours.highlighted_border_style painter.colours.highlighted_border_style
} else { } else {
self.colours.border_style painter.colours.border_style
}, },
)) ))
.style(self.colours.text_style) .style(painter.colours.text_style)
.widths( .widths(
&(intrinsic_widths &(intrinsic_widths
.iter() .iter()
@ -766,5 +755,4 @@ impl NetworkGraphWidget for Painter {
), ),
draw_loc, draw_loc,
); );
}
} }

View File

@ -99,49 +99,10 @@ static PROCESS_HEADERS_SOFT_WIDTH_MAX_NO_GROUP_ELSE: Lazy<Vec<Option<f64>>> = La
] ]
}); });
pub trait ProcessTableWidget { pub fn draw_process_features<B: Backend>(
/// Draws and handles all process-related drawing. Use this. painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
/// - `widget_id` here represents the widget ID of the process widget itself! draw_border: bool, widget_id: u64,
fn draw_process_features<B: Backend>( ) {
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, draw_border: bool,
widget_id: u64,
);
/// Draws the process sort box.
/// - `widget_id` represents the widget ID of the process widget itself.
///
/// This should not be directly called.
fn draw_processes_table<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, draw_border: bool,
widget_id: u64,
);
/// Draws the process search field.
/// - `widget_id` represents the widget ID of the search box itself --- NOT the process widget
/// state that is stored.
///
/// This should not be directly called.
fn draw_search_field<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, draw_border: bool,
widget_id: u64,
);
/// Draws the process sort box.
/// - `widget_id` represents the widget ID of the sort box itself --- NOT the process widget
/// state that is stored.
///
/// This should not be directly called.
fn draw_process_sort<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, draw_border: bool,
widget_id: u64,
);
}
impl ProcessTableWidget for Painter {
fn draw_process_features<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, draw_border: bool,
widget_id: u64,
) {
if let Some(process_widget_state) = app_state.proc_state.widget_states.get(&widget_id) { if let Some(process_widget_state) = app_state.proc_state.widget_states.get(&widget_id) {
let search_height = if draw_border { 5 } else { 3 }; let search_height = if draw_border { 5 } else { 3 };
let is_sort_open = process_widget_state.is_sort_open; let is_sort_open = process_widget_state.is_sort_open;
@ -155,7 +116,8 @@ impl ProcessTableWidget for Painter {
.split(draw_loc); .split(draw_loc);
proc_draw_loc = processes_chunk[0]; proc_draw_loc = processes_chunk[0];
self.draw_search_field( draw_search_field(
painter,
f, f,
app_state, app_state,
processes_chunk[1], processes_chunk[1],
@ -171,7 +133,8 @@ impl ProcessTableWidget for Painter {
.split(proc_draw_loc); .split(proc_draw_loc);
proc_draw_loc = processes_chunk[1]; proc_draw_loc = processes_chunk[1];
self.draw_process_sort( draw_process_sort(
painter,
f, f,
app_state, app_state,
processes_chunk[0], processes_chunk[0],
@ -180,14 +143,14 @@ impl ProcessTableWidget for Painter {
); );
} }
self.draw_processes_table(f, app_state, proc_draw_loc, draw_border, widget_id); draw_processes_table(painter, f, app_state, proc_draw_loc, draw_border, widget_id);
}
} }
}
fn draw_processes_table<B: Backend>( fn draw_processes_table<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, draw_border: bool, painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
widget_id: u64, draw_border: bool, widget_id: u64,
) { ) {
let should_get_widget_bounds = app_state.should_get_widget_bounds(); let should_get_widget_bounds = app_state.should_get_widget_bounds();
if let Some(proc_widget_state) = app_state.proc_state.widget_states.get_mut(&widget_id) { if let Some(proc_widget_state) = app_state.proc_state.widget_states.get_mut(&widget_id) {
let recalculate_column_widths = let recalculate_column_widths =
@ -205,11 +168,11 @@ impl ProcessTableWidget for Painter {
let (border_style, highlight_style) = if is_on_widget { let (border_style, highlight_style) = if is_on_widget {
( (
self.colours.highlighted_border_style, painter.colours.highlighted_border_style,
self.colours.currently_selected_text_style, painter.colours.currently_selected_text_style,
) )
} else { } else {
(self.colours.border_style, self.colours.text_style) (painter.colours.border_style, painter.colours.text_style)
}; };
let title_base = if app_state.app_config_fields.show_table_scroll_position { let title_base = if app_state.app_config_fields.show_table_scroll_position {
@ -262,16 +225,13 @@ impl ProcessTableWidget for Painter {
}; };
Spans::from(vec![ Spans::from(vec![
Span::styled(chosen_title_base, self.colours.widget_title_style), Span::styled(chosen_title_base, painter.colours.widget_title_style),
Span::styled( Span::styled(
format!( format!(
"─{}─ Esc to go back ", "─{}─ Esc to go back ",
"".repeat( "".repeat(
usize::from(draw_loc.width).saturating_sub( usize::from(draw_loc.width).saturating_sub(
UnicodeSegmentation::graphemes( UnicodeSegmentation::graphemes(expanded_title_base.as_str(), true)
expanded_title_base.as_str(),
true
)
.count() .count()
+ 2 + 2
) )
@ -281,7 +241,7 @@ impl ProcessTableWidget for Painter {
), ),
]) ])
} else { } else {
Spans::from(Span::styled(title_base, self.colours.widget_title_style)) Spans::from(Span::styled(title_base, painter.colours.widget_title_style))
}; };
let process_block = if draw_border { let process_block = if draw_border {
@ -292,7 +252,7 @@ impl ProcessTableWidget for Painter {
} else if is_on_widget { } else if is_on_widget {
Block::default() Block::default()
.borders(*SIDE_BORDERS) .borders(*SIDE_BORDERS)
.border_style(self.colours.highlighted_border_style) .border_style(painter.colours.highlighted_border_style)
} else { } else {
Block::default().borders(Borders::NONE) Block::default().borders(Borders::NONE)
}; };
@ -309,8 +269,7 @@ impl ProcessTableWidget for Painter {
}; };
let position = get_start_position( let position = get_start_position(
usize::from( usize::from(
(draw_loc.height + (1 - table_gap)) (draw_loc.height + (1 - table_gap)).saturating_sub(painter.table_height_offset),
.saturating_sub(self.table_height_offset),
), ),
&proc_widget_state.scroll_state.scroll_direction, &proc_widget_state.scroll_state.scroll_direction,
&mut proc_widget_state.scroll_state.previous_scroll_position, &mut proc_widget_state.scroll_state.previous_scroll_position,
@ -416,8 +375,7 @@ impl ProcessTableWidget for Painter {
&*PROCESS_HEADERS_SOFT_WIDTH_MAX_NO_GROUP_ELSE &*PROCESS_HEADERS_SOFT_WIDTH_MAX_NO_GROUP_ELSE
}; };
proc_widget_state.table_width_state.calculated_column_widths = proc_widget_state.table_width_state.calculated_column_widths = get_column_widths(
get_column_widths(
draw_loc.width, draw_loc.width,
hard_widths, hard_widths,
&soft_widths_min, &soft_widths_min,
@ -484,7 +442,7 @@ impl ProcessTableWidget for Painter {
); );
if *disabled { if *disabled {
Row::new(truncated_data).style(self.colours.disabled_text_style) Row::new(truncated_data).style(painter.colours.disabled_text_style)
} else { } else {
Row::new(truncated_data) Row::new(truncated_data)
} }
@ -494,20 +452,18 @@ impl ProcessTableWidget for Painter {
Table::new(process_rows) Table::new(process_rows)
.header( .header(
Row::new(process_headers) Row::new(process_headers)
.style(self.colours.table_header_style) .style(painter.colours.table_header_style)
.bottom_margin(table_gap), .bottom_margin(table_gap),
) )
.block(process_block) .block(process_block)
.highlight_style(highlight_style) .highlight_style(highlight_style)
.style(self.colours.text_style) .style(painter.colours.text_style)
.widths( .widths(
&(proc_widget_state &(proc_widget_state
.table_width_state .table_width_state
.calculated_column_widths .calculated_column_widths
.iter() .iter()
.map(|calculated_width| { .map(|calculated_width| Constraint::Length(*calculated_width as u16))
Constraint::Length(*calculated_width as u16)
})
.collect::<Vec<_>>()), .collect::<Vec<_>>()),
), ),
margined_draw_loc, margined_draw_loc,
@ -564,12 +520,12 @@ impl ProcessTableWidget for Painter {
} }
} }
} }
} }
fn draw_search_field<B: Backend>( fn draw_search_field<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, draw_border: bool, painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
widget_id: u64, draw_border: bool, widget_id: u64,
) { ) {
fn build_query<'a>( fn build_query<'a>(
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,
@ -609,9 +565,7 @@ impl ProcessTableWidget for Painter {
} }
// TODO: Make the cursor scroll back if there's space! // TODO: Make the cursor scroll back if there's space!
if let Some(proc_widget_state) = if let Some(proc_widget_state) = app_state.proc_state.widget_states.get_mut(&(widget_id - 1)) {
app_state.proc_state.widget_states.get_mut(&(widget_id - 1))
{
let is_on_widget = widget_id == app_state.current_widget.widget_id; let is_on_widget = widget_id == app_state.current_widget.widget_id;
let num_columns = usize::from(draw_loc.width); let num_columns = usize::from(draw_loc.width);
let search_title = "> "; let search_title = "> ";
@ -645,17 +599,17 @@ impl ProcessTableWidget for Painter {
start_position, start_position,
cursor_position, cursor_position,
query, query,
self.colours.currently_selected_text_style, painter.colours.currently_selected_text_style,
self.colours.text_style, painter.colours.text_style,
); );
let mut search_text = vec![Spans::from({ let mut search_text = vec![Spans::from({
let mut search_vec = vec![Span::styled( let mut search_vec = vec![Span::styled(
search_title, search_title,
if is_on_widget { if is_on_widget {
self.colours.table_header_style painter.colours.table_header_style
} else { } else {
self.colours.text_style painter.colours.text_style
}, },
)]; )];
search_vec.extend(query_with_cursor); search_vec.extend(query_with_cursor);
@ -665,44 +619,44 @@ impl ProcessTableWidget for Painter {
// 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 {
self.colours.currently_selected_text_style painter.colours.currently_selected_text_style
} else { } else {
self.colours.text_style painter.colours.text_style
}; };
let whole_word_style = if proc_widget_state let whole_word_style = if proc_widget_state
.process_search_state .process_search_state
.is_searching_whole_word .is_searching_whole_word
{ {
self.colours.currently_selected_text_style painter.colours.currently_selected_text_style
} else { } else {
self.colours.text_style painter.colours.text_style
}; };
let regex_style = if proc_widget_state let regex_style = if proc_widget_state
.process_search_state .process_search_state
.is_searching_with_regex .is_searching_with_regex
{ {
self.colours.currently_selected_text_style painter.colours.currently_selected_text_style
} else { } else {
self.colours.text_style painter.colours.text_style
}; };
// FIXME: [MOUSE] Mouse support for these in search // FIXME: [MOUSE] Mouse support for these in search
// FIXME: [MOVEMENT] Movement support for these in search // FIXME: [MOVEMENT] Movement support for these in search
let option_text = Spans::from(vec![ let option_text = Spans::from(vec![
Span::styled( Span::styled(
format!("Case({})", if self.is_mac_os { "F1" } else { "Alt+C" }), format!("Case({})", if painter.is_mac_os { "F1" } else { "Alt+C" }),
case_style, case_style,
), ),
Span::raw(" "), Span::raw(" "),
Span::styled( Span::styled(
format!("Whole({})", if self.is_mac_os { "F2" } else { "Alt+W" }), format!("Whole({})", if painter.is_mac_os { "F2" } else { "Alt+W" }),
whole_word_style, whole_word_style,
), ),
Span::raw(" "), Span::raw(" "),
Span::styled( Span::styled(
format!("Regex({})", if self.is_mac_os { "F3" } else { "Alt+R" }), format!("Regex({})", if painter.is_mac_os { "F3" } else { "Alt+R" }),
regex_style, regex_style,
), ),
]); ]);
@ -717,7 +671,7 @@ impl ProcessTableWidget for Painter {
} else { } else {
"" ""
}, },
self.colours.invalid_query_style, painter.colours.invalid_query_style,
))); )));
search_text.push(option_text); search_text.push(option_text);
@ -726,11 +680,11 @@ impl ProcessTableWidget for Painter {
.search_state .search_state
.is_invalid_search .is_invalid_search
{ {
self.colours.invalid_query_style painter.colours.invalid_query_style
} else if is_on_widget { } else if is_on_widget {
self.colours.highlighted_border_style painter.colours.highlighted_border_style
} else { } else {
self.colours.border_style painter.colours.border_style
}; };
let title = Span::styled( let title = Span::styled(
@ -767,7 +721,7 @@ impl ProcessTableWidget for Painter {
f.render_widget( f.render_widget(
Paragraph::new(search_text) Paragraph::new(search_text)
.block(process_search_block) .block(process_search_block)
.style(self.colours.text_style) .style(painter.colours.text_style)
.alignment(Alignment::Left), .alignment(Alignment::Left),
margined_draw_loc, margined_draw_loc,
); );
@ -783,17 +737,15 @@ impl ProcessTableWidget for Painter {
} }
} }
} }
} }
fn draw_process_sort<B: Backend>( fn draw_process_sort<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect, draw_border: bool, painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut AppState, draw_loc: Rect,
widget_id: u64, draw_border: bool, widget_id: u64,
) { ) {
let is_on_widget = widget_id == app_state.current_widget.widget_id; let is_on_widget = widget_id == app_state.current_widget.widget_id;
if let Some(proc_widget_state) = if let Some(proc_widget_state) = app_state.proc_state.widget_states.get_mut(&(widget_id - 2)) {
app_state.proc_state.widget_states.get_mut(&(widget_id - 2))
{
let current_scroll_position = proc_widget_state.columns.current_scroll_position; let current_scroll_position = proc_widget_state.columns.current_scroll_position;
let sort_string = proc_widget_state let sort_string = proc_widget_state
.columns .columns
@ -817,7 +769,7 @@ impl ProcessTableWidget for Painter {
}; };
let position = get_start_position( let position = get_start_position(
usize::from( usize::from(
(draw_loc.height + (1 - table_gap)).saturating_sub(self.table_height_offset), (draw_loc.height + (1 - table_gap)).saturating_sub(painter.table_height_offset),
), ),
&proc_widget_state.columns.scroll_direction, &proc_widget_state.columns.scroll_direction,
&mut proc_widget_state.columns.previous_scroll_position, &mut proc_widget_state.columns.previous_scroll_position,
@ -850,11 +802,11 @@ impl ProcessTableWidget for Painter {
.search_state .search_state
.is_invalid_search .is_invalid_search
{ {
self.colours.invalid_query_style painter.colours.invalid_query_style
} else if is_on_widget { } else if is_on_widget {
self.colours.highlighted_border_style painter.colours.highlighted_border_style
} else { } else {
self.colours.border_style painter.colours.border_style
}; };
let process_sort_block = if draw_border { let process_sort_block = if draw_border {
@ -870,9 +822,9 @@ impl ProcessTableWidget for Painter {
}; };
let highlight_style = if is_on_widget { let highlight_style = if is_on_widget {
self.colours.currently_selected_text_style painter.colours.currently_selected_text_style
} else { } else {
self.colours.text_style painter.colours.text_style
}; };
let margined_draw_loc = Layout::default() let margined_draw_loc = Layout::default()
@ -885,12 +837,12 @@ impl ProcessTableWidget for Painter {
Table::new(sort_options) Table::new(sort_options)
.header( .header(
Row::new(vec!["Sort By"]) Row::new(vec!["Sort By"])
.style(self.colours.table_header_style) .style(painter.colours.table_header_style)
.bottom_margin(table_gap), .bottom_margin(table_gap),
) )
.block(process_sort_block) .block(process_sort_block)
.highlight_style(highlight_style) .highlight_style(highlight_style)
.style(self.colours.text_style) .style(painter.colours.text_style)
.widths(&[Constraint::Percentage(100)]), .widths(&[Constraint::Percentage(100)]),
margined_draw_loc, margined_draw_loc,
column_state, column_state,
@ -907,5 +859,4 @@ impl ProcessTableWidget for Painter {
} }
} }
} }
}
} }

View File

@ -27,18 +27,10 @@ static TEMP_HEADERS_LENS: Lazy<Vec<u16>> = Lazy::new(|| {
.collect::<Vec<_>>() .collect::<Vec<_>>()
}); });
pub trait TempTableWidget { pub fn draw_temp_table<B: Backend>(
fn draw_temp_table<B: Backend>( painter: &Painter, f: &mut Frame<'_, B>, app_state: &mut app::AppState, draw_loc: Rect,
&self, f: &mut Frame<'_, B>, app_state: &mut app::AppState, draw_loc: Rect,
draw_border: bool, widget_id: u64, draw_border: bool, widget_id: u64,
); ) {
}
impl TempTableWidget for Painter {
fn draw_temp_table<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut app::AppState, draw_loc: Rect,
draw_border: bool, widget_id: u64,
) {
let recalculate_column_widths = app_state.should_get_widget_bounds(); let recalculate_column_widths = app_state.should_get_widget_bounds();
if let Some(temp_widget_state) = app_state.temp_state.widget_states.get_mut(&widget_id) { if let Some(temp_widget_state) = app_state.temp_state.widget_states.get_mut(&widget_id) {
let table_gap = if draw_loc.height < TABLE_GAP_HEIGHT_LIMIT { let table_gap = if draw_loc.height < TABLE_GAP_HEIGHT_LIMIT {
@ -48,7 +40,7 @@ impl TempTableWidget for Painter {
}; };
let start_position = get_start_position( let start_position = get_start_position(
usize::from( usize::from(
(draw_loc.height + (1 - table_gap)).saturating_sub(self.table_height_offset), (draw_loc.height + (1 - table_gap)).saturating_sub(painter.table_height_offset),
), ),
&temp_widget_state.scroll_state.scroll_direction, &temp_widget_state.scroll_state.scroll_direction,
&mut temp_widget_state.scroll_state.previous_scroll_position, &mut temp_widget_state.scroll_state.previous_scroll_position,
@ -100,10 +92,13 @@ impl TempTableWidget for Painter {
let dcw = &temp_widget_state.table_width_state.desired_column_widths; let dcw = &temp_widget_state.table_width_state.desired_column_widths;
let ccw = &temp_widget_state.table_width_state.calculated_column_widths; let ccw = &temp_widget_state.table_width_state.calculated_column_widths;
let temperature_rows = let temperature_rows = sliced_vec.iter().map(|temp_row| {
sliced_vec.iter().map(|temp_row| { let truncated_data =
let truncated_data = temp_row.iter().zip(&hard_widths).enumerate().map( temp_row
|(itx, (entry, width))| { .iter()
.zip(&hard_widths)
.enumerate()
.map(|(itx, (entry, width))| {
if width.is_none() { if width.is_none() {
if let (Some(desired_col_width), Some(calculated_col_width)) = if let (Some(desired_col_width), Some(calculated_col_width)) =
(dcw.get(itx), ccw.get(itx)) (dcw.get(itx), ccw.get(itx))
@ -135,19 +130,18 @@ impl TempTableWidget for Painter {
} else { } else {
Text::raw(entry) Text::raw(entry)
} }
}, });
);
Row::new(truncated_data) Row::new(truncated_data)
}); });
let (border_style, highlight_style) = if is_on_widget { let (border_style, highlight_style) = if is_on_widget {
( (
self.colours.highlighted_border_style, painter.colours.highlighted_border_style,
self.colours.currently_selected_text_style, painter.colours.currently_selected_text_style,
) )
} else { } else {
(self.colours.border_style, self.colours.text_style) (painter.colours.border_style, painter.colours.text_style)
}; };
let title_base = if app_state.app_config_fields.show_table_scroll_position { let title_base = if app_state.app_config_fields.show_table_scroll_position {
@ -186,16 +180,13 @@ impl TempTableWidget for Painter {
}; };
Spans::from(vec![ Spans::from(vec![
Span::styled(chosen_title_base, self.colours.widget_title_style), Span::styled(chosen_title_base, painter.colours.widget_title_style),
Span::styled( Span::styled(
format!( format!(
"─{}─ Esc to go back ", "─{}─ Esc to go back ",
"".repeat( "".repeat(
usize::from(draw_loc.width).saturating_sub( usize::from(draw_loc.width).saturating_sub(
UnicodeSegmentation::graphemes( UnicodeSegmentation::graphemes(expanded_title_base.as_str(), true)
expanded_title_base.as_str(),
true
)
.count() .count()
+ 2 + 2
) )
@ -205,7 +196,7 @@ impl TempTableWidget for Painter {
), ),
]) ])
} else { } else {
Spans::from(Span::styled(title_base, self.colours.widget_title_style)) Spans::from(Span::styled(title_base, painter.colours.widget_title_style))
}; };
let temp_block = if draw_border { let temp_block = if draw_border {
@ -216,7 +207,7 @@ impl TempTableWidget for Painter {
} else if is_on_widget { } else if is_on_widget {
Block::default() Block::default()
.borders(*SIDE_BORDERS) .borders(*SIDE_BORDERS)
.border_style(self.colours.highlighted_border_style) .border_style(painter.colours.highlighted_border_style)
} else { } else {
Block::default().borders(Borders::NONE) Block::default().borders(Borders::NONE)
}; };
@ -232,12 +223,12 @@ impl TempTableWidget for Painter {
Table::new(temperature_rows) Table::new(temperature_rows)
.header( .header(
Row::new(TEMP_HEADERS.to_vec()) Row::new(TEMP_HEADERS.to_vec())
.style(self.colours.table_header_style) .style(painter.colours.table_header_style)
.bottom_margin(table_gap), .bottom_margin(table_gap),
) )
.block(temp_block) .block(temp_block)
.highlight_style(highlight_style) .highlight_style(highlight_style)
.style(self.colours.text_style) .style(painter.colours.text_style)
.widths( .widths(
&(temp_widget_state &(temp_widget_state
.table_width_state .table_width_state
@ -262,5 +253,4 @@ impl TempTableWidget for Painter {
} }
} }
} }
}
} }

View File

@ -64,6 +64,7 @@ pub enum BottomEvent {
KeyInput(KeyEvent), KeyInput(KeyEvent),
MouseInput(MouseEvent), MouseInput(MouseEvent),
Update(Box<data_harvester::Data>), Update(Box<data_harvester::Data>),
Resize { width: u16, height: u16 },
Clean, Clean,
} }
@ -635,7 +636,11 @@ pub fn create_input_thread(
} }
} }
}, },
Event::Resize(_, _) => {} Event::Resize(width, height) => {
if sender.send(BottomEvent::Resize { width, height }).is_err() {
break;
}
}
} }
} }
} }