Move to stateful except for CPU

This commit is contained in:
ClementTsang 2020-04-19 23:39:24 -04:00
parent 83dad154b9
commit 0574678746
8 changed files with 100 additions and 137 deletions

View file

@ -3,6 +3,8 @@ use std::{cmp::max, collections::HashMap, time::Instant};
use unicode_segmentation::GraphemeCursor; use unicode_segmentation::GraphemeCursor;
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
use tui::widgets::TableState;
use typed_builder::*; use typed_builder::*;
use data_farmer::*; use data_farmer::*;
@ -47,6 +49,7 @@ pub struct AppScrollWidgetState {
pub current_scroll_position: u64, pub current_scroll_position: u64,
pub previous_scroll_position: u64, pub previous_scroll_position: u64,
pub scroll_direction: ScrollDirection, pub scroll_direction: ScrollDirection,
pub table_state: TableState,
} }
#[derive(Default)] #[derive(Default)]
@ -91,7 +94,7 @@ pub struct AppConfigFields {
pub hide_time: bool, pub hide_time: bool,
pub autohide_time: bool, pub autohide_time: bool,
pub use_old_network_legend: bool, pub use_old_network_legend: bool,
pub table_gap: u16 pub table_gap: u16,
} }
/// AppSearchState deals with generic searching (I might do this in the future). /// AppSearchState deals with generic searching (I might do this in the future).

View file

@ -69,10 +69,11 @@ pub struct Painter {
layout_constraints: Vec<Vec<Vec<Vec<Constraint>>>>, layout_constraints: Vec<Vec<Vec<Vec<Constraint>>>>,
widget_layout: BottomLayout, widget_layout: BottomLayout,
derived_widget_draw_locs: Vec<Vec<Vec<Vec<Rect>>>>, derived_widget_draw_locs: Vec<Vec<Vec<Vec<Rect>>>>,
table_height_offset: i64,
} }
impl Painter { impl Painter {
pub fn init(widget_layout: BottomLayout) -> Self { pub fn init(widget_layout: BottomLayout, table_gap: u16) -> Self {
// Now for modularity; we have to also initialize the base layouts! // Now for modularity; we have to also initialize the base layouts!
// We want to do this ONCE and reuse; after this we can just construct // We want to do this ONCE and reuse; after this we can just construct
// based on the console size. // based on the console size.
@ -154,6 +155,7 @@ impl Painter {
layout_constraints, layout_constraints,
widget_layout, widget_layout,
derived_widget_draw_locs: Vec::new(), derived_widget_draw_locs: Vec::new(),
table_height_offset: 4 + table_gap as i64,
} }
} }

View file

@ -217,7 +217,7 @@ impl CpuGraphWidget for Painter {
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 num_rows = max(0, i64::from(draw_loc.height) - 5) as u64; let num_rows = max(0, i64::from(draw_loc.height) - self.table_height_offset) as u64;
let start_position = get_start_position( let start_position = get_start_position(
num_rows, num_rows,
&cpu_widget_state.scroll_state.scroll_direction, &cpu_widget_state.scroll_state.scroll_direction,
@ -225,13 +225,13 @@ impl CpuGraphWidget for Painter {
cpu_widget_state.scroll_state.current_scroll_position, cpu_widget_state.scroll_state.current_scroll_position,
app_state.is_resized, app_state.is_resized,
); );
let is_on_widget = widget_id == app_state.current_widget.widget_id;
let sliced_cpu_data = &cpu_data[start_position as usize..]; let sliced_cpu_data = &cpu_data[start_position as usize..];
let mut offset_scroll_index = let mut offset_scroll_index =
(cpu_widget_state.scroll_state.current_scroll_position - start_position) as usize; (cpu_widget_state.scroll_state.current_scroll_position - start_position) as usize;
let show_disabled_data = app_state.app_config_fields.show_disabled_data; let show_disabled_data = app_state.app_config_fields.show_disabled_data;
let current_widget_id = app_state.current_widget.widget_id;
let show_avg_cpu = app_state.app_config_fields.show_average_cpu; let show_avg_cpu = app_state.app_config_fields.show_average_cpu;
let cpu_rows = sliced_cpu_data.iter().enumerate().filter_map(|(itx, cpu)| { let cpu_rows = sliced_cpu_data.iter().enumerate().filter_map(|(itx, cpu)| {
@ -267,7 +267,7 @@ impl CpuGraphWidget for Painter {
} else { } else {
Some(Row::StyledData( Some(Row::StyledData(
cpu_string_row.into_iter(), cpu_string_row.into_iter(),
if current_widget_id == widget_id { if is_on_widget {
if itx == offset_scroll_index { if itx == offset_scroll_index {
self.colours.currently_selected_text_style self.colours.currently_selected_text_style
} else if show_avg_cpu && itx == 0 { } else if show_avg_cpu && itx == 0 {
@ -315,10 +315,13 @@ impl CpuGraphWidget for Painter {
"".to_string() "".to_string()
}; };
let title_and_border_style = if app_state.current_widget.widget_id == widget_id { let (border_and_title_style, highlight_style) = if is_on_widget {
self.colours.highlighted_border_style (
self.colours.highlighted_border_style,
self.colours.currently_selected_text_style,
)
} else { } else {
self.colours.border_style (self.colours.border_style, self.colours.text_style)
}; };
// Draw // Draw
@ -335,11 +338,12 @@ impl CpuGraphWidget for Painter {
.block( .block(
Block::default() Block::default()
.title(&title) .title(&title)
.title_style(title_and_border_style) .title_style(border_and_title_style)
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(title_and_border_style), .border_style(border_and_title_style),
) )
.header_style(self.colours.table_header_style) .header_style(self.colours.table_header_style)
.highlight_style(highlight_style)
.widths( .widths(
&(intrinsic_widths &(intrinsic_widths
.iter() .iter()

View file

@ -39,7 +39,7 @@ impl DiskTableWidget for Painter {
) { ) {
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 disk_data: &mut [Vec<String>] = &mut app_state.canvas_data.disk_data; let disk_data: &mut [Vec<String>] = &mut app_state.canvas_data.disk_data;
let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64; let num_rows = max(0, i64::from(draw_loc.height) - self.table_height_offset) as u64;
let start_position = get_start_position( let start_position = get_start_position(
num_rows, num_rows,
&disk_widget_state.scroll_state.scroll_direction, &disk_widget_state.scroll_state.scroll_direction,
@ -47,34 +47,14 @@ impl DiskTableWidget for Painter {
disk_widget_state.scroll_state.current_scroll_position, disk_widget_state.scroll_state.current_scroll_position,
app_state.is_resized, app_state.is_resized,
); );
let is_on_widget = app_state.current_widget.widget_id == widget_id;
let disk_table_state = &mut disk_widget_state.scroll_state.table_state;
disk_table_state.select(Some(
(disk_widget_state.scroll_state.current_scroll_position - start_position) as usize,
));
let sliced_vec = &mut disk_data[start_position as usize..]; let sliced_vec = &mut disk_data[start_position as usize..];
let mut disk_counter: i64 = 0; let disk_rows = sliced_vec.iter().map(|disk| Row::Data(disk.iter()));
let current_widget_id = app_state.current_widget.widget_id;
let disk_rows = sliced_vec.iter().map(|disk| {
Row::StyledData(
disk.iter(),
if current_widget_id == widget_id
&& disk_widget_state.scroll_state.current_scroll_position >= start_position
{
if disk_counter as u64
== disk_widget_state.scroll_state.current_scroll_position
- start_position
{
disk_counter = -1;
self.colours.currently_selected_text_style
} else {
if disk_counter >= 0 {
disk_counter += 1;
}
self.colours.text_style
}
} else {
self.colours.text_style
},
)
});
// Calculate widths // Calculate widths
// TODO: [PRETTY] Ellipsis on strings? // TODO: [PRETTY] Ellipsis on strings?
@ -101,10 +81,13 @@ impl DiskTableWidget for Painter {
" Disk ".to_string() " Disk ".to_string()
}; };
let border_and_title_style = if app_state.current_widget.widget_id == widget_id { let (border_and_title_style, highlight_style) = if is_on_widget {
self.colours.highlighted_border_style (
self.colours.highlighted_border_style,
self.colours.currently_selected_text_style,
)
} else { } else {
self.colours.border_style (self.colours.border_style, self.colours.text_style)
}; };
let disk_block = if draw_border { let disk_block = if draw_border {
@ -117,7 +100,7 @@ impl DiskTableWidget for Painter {
}) })
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(border_and_title_style) .border_style(border_and_title_style)
} else if app_state.current_widget.widget_id == widget_id { } else if is_on_widget {
Block::default() Block::default()
.borders(*SIDE_BORDERS) .borders(*SIDE_BORDERS)
.border_style(self.colours.highlighted_border_style) .border_style(self.colours.highlighted_border_style)
@ -127,21 +110,17 @@ impl DiskTableWidget for Painter {
let margined_draw_loc = Layout::default() let margined_draw_loc = Layout::default()
.constraints([Constraint::Percentage(100)].as_ref()) .constraints([Constraint::Percentage(100)].as_ref())
.horizontal_margin( .horizontal_margin(if is_on_widget || draw_border { 0 } else { 1 })
if app_state.current_widget.widget_id == widget_id || draw_border {
0
} else {
1
},
)
.direction(Direction::Horizontal) .direction(Direction::Horizontal)
.split(draw_loc); .split(draw_loc);
// Draw! // Draw!
f.render_widget( f.render_stateful_widget(
Table::new(DISK_HEADERS.iter(), disk_rows) Table::new(DISK_HEADERS.iter(), disk_rows)
.block(disk_block) .block(disk_block)
.header_style(self.colours.table_header_style) .header_style(self.colours.table_header_style)
.highlight_style(highlight_style)
.style(self.colours.text_style)
.widths( .widths(
&(intrinsic_widths &(intrinsic_widths
.iter() .iter()
@ -150,6 +129,7 @@ impl DiskTableWidget for Painter {
) )
.header_gap(app_state.app_config_fields.table_gap), .header_gap(app_state.app_config_fields.table_gap),
margined_draw_loc[0], margined_draw_loc[0],
disk_table_state,
); );
} }
} }

View file

@ -83,7 +83,7 @@ impl ProcessTableWidget for Painter {
// hit the process we've currently scrolled to. // hit the process we've currently scrolled to.
// We also need to move the list - we can // We also need to move the list - we can
// do so by hiding some elements! // do so by hiding some elements!
let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64; let num_rows = max(0, i64::from(draw_loc.height) - self.table_height_offset) as 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;
let position = get_start_position( let position = get_start_position(
@ -102,12 +102,18 @@ impl ProcessTableWidget for Painter {
}; };
let sliced_vec = &process_data[start_position as usize..]; let sliced_vec = &process_data[start_position as usize..];
let mut process_counter: i64 = 0; let proc_table_state = &mut proc_widget_state.scroll_state.table_state;
proc_table_state.select(Some(
(proc_widget_state.scroll_state.current_scroll_position - start_position)
as usize,
));
// Draw! // Draw!
let is_proc_widget_grouped = proc_widget_state.is_grouped;
let process_rows = sliced_vec.iter().map(|process| { let process_rows = sliced_vec.iter().map(|process| {
let stringified_process_vec: Vec<String> = vec![ Row::Data(
if proc_widget_state.is_grouped { vec![
if is_proc_widget_grouped {
process.group_pids.len().to_string() process.group_pids.len().to_string()
} else { } else {
process.pid.to_string() process.pid.to_string()
@ -120,25 +126,8 @@ impl ProcessTableWidget for Painter {
process.total_read.to_string(), process.total_read.to_string(),
process.total_write.to_string(), process.total_write.to_string(),
process.process_states.to_string(), process.process_states.to_string(),
]; ]
Row::StyledData( .into_iter(),
stringified_process_vec.into_iter(),
if is_on_widget {
if process_counter as u64
== proc_widget_state.scroll_state.current_scroll_position
- start_position
{
process_counter = -1;
self.colours.currently_selected_text_style
} else {
if process_counter >= 0 {
process_counter += 1;
}
self.colours.text_style
}
} else {
self.colours.text_style
},
) )
}); });
@ -223,10 +212,13 @@ impl ProcessTableWidget for Painter {
String::default() String::default()
}; };
let border_and_title_style = if is_on_widget { let (border_and_title_style, highlight_style) = if is_on_widget {
self.colours.highlighted_border_style (
self.colours.highlighted_border_style,
self.colours.currently_selected_text_style,
)
} else { } else {
self.colours.border_style (self.colours.border_style, self.colours.text_style)
}; };
let process_block = if draw_border { let process_block = if draw_border {
@ -253,10 +245,12 @@ impl ProcessTableWidget for Painter {
.direction(Direction::Horizontal) .direction(Direction::Horizontal)
.split(draw_loc); .split(draw_loc);
f.render_widget( f.render_stateful_widget(
Table::new(process_headers.iter(), process_rows) Table::new(process_headers.iter(), process_rows)
.block(process_block) .block(process_block)
.header_style(self.colours.table_header_style) .header_style(self.colours.table_header_style)
.highlight_style(highlight_style)
.style(self.colours.text_style)
.widths( .widths(
&(intrinsic_widths &(intrinsic_widths
.iter() .iter()
@ -267,6 +261,7 @@ impl ProcessTableWidget for Painter {
) )
.header_gap(app_state.app_config_fields.table_gap), .header_gap(app_state.app_config_fields.table_gap),
margined_draw_loc[0], margined_draw_loc[0],
proc_table_state,
); );
} }
} }

View file

@ -40,7 +40,7 @@ impl TempTableWidget for Painter {
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 temp_sensor_data: &mut [Vec<String>] = &mut app_state.canvas_data.temp_sensor_data; let temp_sensor_data: &mut [Vec<String>] = &mut app_state.canvas_data.temp_sensor_data;
let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64; let num_rows = max(0, i64::from(draw_loc.height) - self.table_height_offset) as u64;
let start_position = get_start_position( let start_position = get_start_position(
num_rows, num_rows,
&temp_widget_state.scroll_state.scroll_direction, &temp_widget_state.scroll_state.scroll_direction,
@ -48,32 +48,14 @@ impl TempTableWidget for Painter {
temp_widget_state.scroll_state.current_scroll_position, temp_widget_state.scroll_state.current_scroll_position,
app_state.is_resized, app_state.is_resized,
); );
let is_on_widget = widget_id == app_state.current_widget.widget_id;
let temp_table_state = &mut temp_widget_state.scroll_state.table_state;
temp_table_state.select(Some(
(temp_widget_state.scroll_state.current_scroll_position - start_position) as usize,
));
let sliced_vec = &temp_sensor_data[start_position as usize..]; let sliced_vec = &temp_sensor_data[start_position as usize..];
let mut temp_row_counter: i64 = 0; let temperature_rows = sliced_vec.iter().map(|temp_row| Row::Data(temp_row.iter()));
let current_widget_id = app_state.current_widget.widget_id;
let temperature_rows = sliced_vec.iter().map(|temp_row| {
Row::StyledData(
temp_row.iter(),
if current_widget_id == widget_id {
if temp_row_counter as u64
== temp_widget_state.scroll_state.current_scroll_position
- start_position
{
temp_row_counter = -1;
self.colours.currently_selected_text_style
} else {
if temp_row_counter >= 0 {
temp_row_counter += 1;
}
self.colours.text_style
}
} else {
self.colours.text_style
},
)
});
// Calculate widths // Calculate widths
let width = f64::from(draw_loc.width); let width = f64::from(draw_loc.width);
@ -100,25 +82,22 @@ impl TempTableWidget for Painter {
" Temperatures ".to_string() " Temperatures ".to_string()
}; };
let (border_and_title_style, highlight_style) = if is_on_widget {
(
self.colours.highlighted_border_style,
self.colours.currently_selected_text_style,
)
} else {
(self.colours.border_style, self.colours.text_style)
};
let temp_block = if draw_border { let temp_block = if draw_border {
Block::default() Block::default()
.title(&title) .title(&title)
.title_style(if app_state.is_expanded { .title_style(border_and_title_style)
if app_state.current_widget.widget_id == widget_id {
self.colours.highlighted_border_style
} else {
self.colours.border_style
}
} else {
self.colours.widget_title_style
})
.borders(Borders::ALL) .borders(Borders::ALL)
.border_style(if app_state.current_widget.widget_id == widget_id { .border_style(border_and_title_style)
self.colours.highlighted_border_style } else if is_on_widget {
} else {
self.colours.border_style
})
} else if app_state.current_widget.widget_id == widget_id {
Block::default() Block::default()
.borders(*SIDE_BORDERS) .borders(*SIDE_BORDERS)
.border_style(self.colours.highlighted_border_style) .border_style(self.colours.highlighted_border_style)
@ -128,21 +107,17 @@ impl TempTableWidget for Painter {
let margined_draw_loc = Layout::default() let margined_draw_loc = Layout::default()
.constraints([Constraint::Percentage(100)].as_ref()) .constraints([Constraint::Percentage(100)].as_ref())
.horizontal_margin( .horizontal_margin(if is_on_widget || draw_border { 0 } else { 1 })
if app_state.current_widget.widget_id == widget_id || draw_border {
0
} else {
1
},
)
.direction(Direction::Horizontal) .direction(Direction::Horizontal)
.split(draw_loc); .split(draw_loc);
// Draw // Draw
f.render_widget( f.render_stateful_widget(
Table::new(TEMP_HEADERS.iter(), temperature_rows) Table::new(TEMP_HEADERS.iter(), temperature_rows)
.block(temp_block) .block(temp_block)
.header_style(self.colours.table_header_style) .header_style(self.colours.table_header_style)
.highlight_style(highlight_style)
.style(self.colours.text_style)
.widths( .widths(
&(intrinsic_widths &(intrinsic_widths
.iter() .iter()
@ -151,6 +126,7 @@ impl TempTableWidget for Painter {
) )
.header_gap(app_state.app_config_fields.table_gap), .header_gap(app_state.app_config_fields.table_gap),
margined_draw_loc[0], margined_draw_loc[0],
temp_table_state,
); );
} }
} }

View file

@ -151,7 +151,10 @@ pub const DEFAULT_CONFIG_CONTENT: &str = r##"
#basic = false #basic = false
# Use the old network legend style # Use the old network legend style
#use_old_network_legend = true #use_old_network_legend = false
# Remove space in tables
#hide_table_gap = false
########################################################## ##########################################################

View file

@ -145,7 +145,7 @@ fn main() -> error::Result<()> {
app.used_widgets.clone(), app.used_widgets.clone(),
); );
let mut painter = canvas::Painter::init(widget_layout); let mut painter = canvas::Painter::init(widget_layout, app.app_config_fields.table_gap);
if let Err(config_check) = generate_config_colours(&config, &mut painter) { if let Err(config_check) = generate_config_colours(&config, &mut painter) {
cleanup_terminal(&mut terminal)?; cleanup_terminal(&mut terminal)?;
return Err(config_check); return Err(config_check);