refactor: move CPU graph over to new system

This commit is contained in:
ClementTsang 2022-05-04 04:41:32 -04:00
parent 9e63642e9c
commit c97126df22
7 changed files with 251 additions and 267 deletions

View File

@ -2228,8 +2228,8 @@ impl App {
.cpu_state .cpu_state
.get_mut_widget_state(self.current_widget.widget_id - 1) .get_mut_widget_state(self.current_widget.widget_id - 1)
{ {
cpu_widget_state.scroll_state.current_scroll_position = 0; cpu_widget_state.table_state.current_scroll_position = 0;
cpu_widget_state.scroll_state.scroll_direction = ScrollDirection::Up; cpu_widget_state.table_state.scroll_direction = ScrollDirection::Up;
} }
} }
@ -2306,8 +2306,8 @@ impl App {
{ {
let cap = self.canvas_data.cpu_data.len(); let cap = self.canvas_data.cpu_data.len();
if cap > 0 { if cap > 0 {
cpu_widget_state.scroll_state.current_scroll_position = cap - 1; cpu_widget_state.table_state.current_scroll_position = cap - 1;
cpu_widget_state.scroll_state.scroll_direction = ScrollDirection::Down; cpu_widget_state.table_state.scroll_direction = ScrollDirection::Down;
} }
} }
} }
@ -2380,7 +2380,7 @@ impl App {
.get_mut(&(self.current_widget.widget_id - 1)) .get_mut(&(self.current_widget.widget_id - 1))
{ {
cpu_widget_state cpu_widget_state
.scroll_state .table_state
.update_position(num_to_change_by, self.canvas_data.cpu_data.len()); .update_position(num_to_change_by, self.canvas_data.cpu_data.len());
} }
} }
@ -2957,7 +2957,7 @@ impl App {
.get_widget_state(self.current_widget.widget_id - 1) .get_widget_state(self.current_widget.widget_id - 1)
{ {
if let Some(visual_index) = if let Some(visual_index) =
cpu_widget_state.scroll_state.table_state.selected() cpu_widget_state.table_state.table_state.selected()
{ {
self.change_cpu_legend_position( self.change_cpu_legend_position(
offset_clicked_entry as i64 - visual_index as i64, offset_clicked_entry as i64 - visual_index as i64,

View File

@ -61,8 +61,19 @@ pub enum WidthBounds {
impl WidthBounds { impl WidthBounds {
pub const fn soft_from_str(name: &'static str, max_percentage: Option<f32>) -> WidthBounds { pub const fn soft_from_str(name: &'static str, max_percentage: Option<f32>) -> WidthBounds {
let len = name.len() as u16;
WidthBounds::Soft { WidthBounds::Soft {
min_width: name.len() as u16, min_width: len,
desired: len,
max_percentage,
}
}
pub const fn soft_from_str_with_alt(
name: &'static str, alt: &'static str, max_percentage: Option<f32>,
) -> WidthBounds {
WidthBounds::Soft {
min_width: alt.len() as u16,
desired: name.len() as u16, desired: name.len() as u16,
max_percentage, max_percentage,
} }
@ -75,6 +86,9 @@ pub struct TableComponentColumn {
/// A restriction on this column's width, if desired. /// A restriction on this column's width, if desired.
pub width_bounds: WidthBounds, pub width_bounds: WidthBounds,
/// The calculated width of the column.
pub calculated_width: u16,
} }
impl TableComponentColumn { impl TableComponentColumn {
@ -92,8 +106,13 @@ impl TableComponentColumn {
CellContent::Simple(name.into()) CellContent::Simple(name.into())
}, },
width_bounds, width_bounds,
calculated_width: 0,
} }
} }
pub fn should_skip(&self) -> bool {
self.calculated_width == 0
}
} }
/// [`TableComponentState`] deals with fields for a scrollable's current state. /// [`TableComponentState`] deals with fields for a scrollable's current state.
@ -104,7 +123,6 @@ pub struct TableComponentState {
pub scroll_direction: ScrollDirection, pub scroll_direction: ScrollDirection,
pub table_state: TableState, pub table_state: TableState,
pub columns: Vec<TableComponentColumn>, pub columns: Vec<TableComponentColumn>,
pub calculated_widths: Vec<u16>,
} }
impl TableComponentState { impl TableComponentState {
@ -115,7 +133,6 @@ impl TableComponentState {
scroll_direction: ScrollDirection::Down, scroll_direction: ScrollDirection::Down,
table_state: Default::default(), table_state: Default::default(),
columns, columns,
calculated_widths: Vec::default(),
} }
} }
@ -132,16 +149,18 @@ impl TableComponentState {
let mut total_width_left = total_width; let mut total_width_left = total_width;
let column_widths = &mut self.calculated_widths; for column in self.columns.iter_mut() {
*column_widths = vec![0; self.columns.len()]; column.calculated_width = 0;
}
let columns = if left_to_right { let columns = if left_to_right {
Either::Left(self.columns.iter().enumerate()) Either::Left(self.columns.iter_mut())
} else { } else {
Either::Right(self.columns.iter().enumerate().rev()) Either::Right(self.columns.iter_mut().rev())
}; };
for (itx, column) in columns { let mut num_columns = 0;
for column in columns {
match &column.width_bounds { match &column.width_bounds {
WidthBounds::Soft { WidthBounds::Soft {
min_width, min_width,
@ -161,9 +180,10 @@ impl TableComponentState {
if *min_width > space_taken { if *min_width > space_taken {
break; break;
} else { } else if space_taken > 0 {
total_width_left = total_width_left.saturating_sub(space_taken + 1); total_width_left = total_width_left.saturating_sub(space_taken + 1);
column_widths[itx] = space_taken; column.calculated_width = space_taken;
num_columns += 1;
} }
} }
WidthBounds::Hard(width) => { WidthBounds::Hard(width) => {
@ -171,27 +191,34 @@ impl TableComponentState {
if *width > space_taken { if *width > space_taken {
break; break;
} else { } else if space_taken > 0 {
total_width_left = total_width_left.saturating_sub(space_taken + 1); total_width_left = total_width_left.saturating_sub(space_taken + 1);
column_widths[itx] = space_taken; column.calculated_width = space_taken;
num_columns += 1;
} }
} }
} }
} }
while let Some(0) = column_widths.last() { if num_columns > 0 {
column_widths.pop();
}
if !column_widths.is_empty() {
// Redistribute remaining. // Redistribute remaining.
let amount_per_slot = total_width_left / column_widths.len() as u16; let mut num_dist = num_columns;
total_width_left %= column_widths.len() as u16; let amount_per_slot = total_width_left / num_dist;
for (index, width) in column_widths.iter_mut().enumerate() { total_width_left %= num_dist;
if index < total_width_left.into() { for column in self.columns.iter_mut() {
*width += amount_per_slot + 1; if num_dist == 0 {
} else { break;
*width += amount_per_slot; }
if column.calculated_width > 0 {
if total_width_left > 0 {
column.calculated_width += amount_per_slot + 1;
total_width_left -= 1;
} else {
column.calculated_width += amount_per_slot;
}
num_dist -= 1;
} }
} }
} }
@ -871,29 +898,13 @@ impl ProcState {
pub struct NetWidgetState { pub struct NetWidgetState {
pub current_display_time: u64, pub current_display_time: u64,
pub autohide_timer: Option<Instant>, pub autohide_timer: Option<Instant>,
// pub draw_max_range_cache: f64,
// pub draw_labels_cache: Vec<String>,
// pub draw_time_start_cache: f64,
// TODO: Re-enable these when we move net details state-side!
// pub unit_type: DataUnitTypes,
// pub scale_type: AxisScaling,
} }
impl NetWidgetState { impl NetWidgetState {
pub fn init( pub fn init(current_display_time: u64, autohide_timer: Option<Instant>) -> Self {
current_display_time: u64,
autohide_timer: Option<Instant>,
// unit_type: DataUnitTypes,
// scale_type: AxisScaling,
) -> Self {
NetWidgetState { NetWidgetState {
current_display_time, current_display_time,
autohide_timer, autohide_timer,
// draw_max_range_cache: 0.0,
// draw_labels_cache: vec![],
// draw_time_start_cache: 0.0,
// unit_type,
// scale_type,
} }
} }
} }
@ -924,20 +935,33 @@ pub struct CpuWidgetState {
pub current_display_time: u64, pub current_display_time: u64,
pub is_legend_hidden: bool, pub is_legend_hidden: bool,
pub autohide_timer: Option<Instant>, pub autohide_timer: Option<Instant>,
pub scroll_state: TableComponentState, pub table_state: TableComponentState,
pub is_multi_graph_mode: bool, pub is_multi_graph_mode: bool,
pub table_width_state: CanvasTableWidthState,
} }
impl CpuWidgetState { impl CpuWidgetState {
pub fn init(current_display_time: u64, autohide_timer: Option<Instant>) -> Self { pub fn init(current_display_time: u64, autohide_timer: Option<Instant>) -> Self {
const CPU_LEGEND_HEADER: [(Cow<'static, str>, Option<Cow<'static, str>>); 2] =
[(Cow::Borrowed("CPU"), None), (Cow::Borrowed("Use%"), None)];
const WIDTHS: [WidthBounds; CPU_LEGEND_HEADER.len()] = [
WidthBounds::soft_from_str("CPU", Some(0.5)),
WidthBounds::soft_from_str("Use%", Some(0.5)),
];
let table_state = TableComponentState::new(
CPU_LEGEND_HEADER
.iter()
.zip(WIDTHS)
.map(|(c, width)| TableComponentColumn::new(c.0.clone(), c.1.clone(), width))
.collect(),
);
CpuWidgetState { CpuWidgetState {
current_display_time, current_display_time,
is_legend_hidden: false, is_legend_hidden: false,
autohide_timer, autohide_timer,
scroll_state: TableComponentState::default(), table_state,
is_multi_graph_mode: false, is_multi_graph_mode: false,
table_width_state: CanvasTableWidthState::default(),
} }
} }
} }
@ -1166,7 +1190,6 @@ mod test {
scroll_direction: ScrollDirection::Down, scroll_direction: ScrollDirection::Down,
table_state: Default::default(), table_state: Default::default(),
columns: vec![], columns: vec![],
calculated_widths: vec![],
}; };
let s = &mut scroll; let s = &mut scroll;

View File

@ -17,6 +17,11 @@ use crate::{
data_conversion::{CellContent, TableData, TableRow}, data_conversion::{CellContent, TableData, TableRow},
}; };
pub struct TextTableTitle<'a> {
pub title: Cow<'a, str>,
pub is_expanded: bool,
}
pub struct TextTable<'a> { pub struct TextTable<'a> {
pub table_gap: u16, pub table_gap: u16,
pub is_force_redraw: bool, pub is_force_redraw: bool,
@ -31,11 +36,8 @@ pub struct TextTable<'a> {
/// The highlighted text style. /// The highlighted text style.
pub highlighted_text_style: Style, pub highlighted_text_style: Style,
/// The graph title. /// The graph title and whether it is expanded (if there is one).
pub title: Cow<'a, str>, pub title: Option<TextTableTitle<'a>>,
/// Whether this graph is expanded.
pub is_expanded: bool,
/// Whether this widget is selected. /// Whether this widget is selected.
pub is_on_widget: bool, pub is_on_widget: bool,
@ -58,42 +60,46 @@ pub struct TextTable<'a> {
impl<'a> TextTable<'a> { impl<'a> TextTable<'a> {
/// Generates a title for the [`TextTable`] widget, given the available space. /// Generates a title for the [`TextTable`] widget, given the available space.
fn generate_title(&self, draw_loc: Rect, pos: usize, total: usize) -> Spans<'_> { fn generate_title(&self, draw_loc: Rect, pos: usize, total: usize) -> Option<Spans<'_>> {
let title = if self.show_table_scroll_position { self.title
let title_string = concat_string!( .as_ref()
self.title, .map(|TextTableTitle { title, is_expanded }| {
"(", let title = if self.show_table_scroll_position {
pos.to_string(), let title_string = concat_string!(
" of ", title,
total.to_string(), "(",
") " pos.to_string(),
); " of ",
total.to_string(),
") "
);
if title_string.len() + 2 <= draw_loc.width.into() { if title_string.len() + 2 <= draw_loc.width.into() {
title_string title_string
} else { } else {
self.title.to_string() title.to_string()
} }
} else { } else {
self.title.to_string() title.to_string()
}; };
if self.is_expanded { if *is_expanded {
let title_base = concat_string!(title, "── Esc to go back "); let title_base = concat_string!(title, "── Esc to go back ");
let esc = concat_string!( let esc = concat_string!(
"", "",
"".repeat(usize::from(draw_loc.width).saturating_sub( "".repeat(usize::from(draw_loc.width).saturating_sub(
UnicodeSegmentation::graphemes(title_base.as_str(), true).count() + 2 UnicodeSegmentation::graphemes(title_base.as_str(), true).count() + 2
)), )),
"─ Esc to go back " "─ Esc to go back "
); );
Spans::from(vec![ Spans::from(vec![
Span::styled(title, self.title_style), Span::styled(title, self.title_style),
Span::styled(esc, self.border_style), Span::styled(esc, self.border_style),
]) ])
} else { } else {
Spans::from(Span::styled(title, self.title_style)) Spans::from(Span::styled(title, self.title_style))
} }
})
} }
pub fn draw_text_table<B: Backend>( pub fn draw_text_table<B: Backend>(
&self, f: &mut Frame<'_, B>, draw_loc: Rect, state: &mut TableComponentState, &self, f: &mut Frame<'_, B>, draw_loc: Rect, state: &mut TableComponentState,
@ -108,16 +114,19 @@ impl<'a> TextTable<'a> {
.split(draw_loc)[0]; .split(draw_loc)[0];
let disk_block = if self.draw_border { let disk_block = if self.draw_border {
let title = self.generate_title( let block = Block::default()
.borders(Borders::ALL)
.border_style(self.border_style);
if let Some(title) = self.generate_title(
draw_loc, draw_loc,
state.current_scroll_position.saturating_add(1), state.current_scroll_position.saturating_add(1),
table_data.data.len(), table_data.data.len(),
); ) {
block.title(title)
Block::default() } else {
.title(title) block
.borders(Borders::ALL) }
.border_style(self.border_style)
} else if self.is_on_widget { } else if self.is_on_widget {
Block::default() Block::default()
.borders(SIDE_BORDERS) .borders(SIDE_BORDERS)
@ -179,30 +188,32 @@ impl<'a> TextTable<'a> {
} }
let columns = &state.columns; let columns = &state.columns;
let widths = &state.calculated_widths; let header = Row::new(columns.iter().filter_map(|c| {
let header = Row::new( if c.calculated_width == 0 {
columns None
.iter() } else {
.zip(widths) Some(truncate_text(&c.name, c.calculated_width.into(), None))
.map(|(c, width)| truncate_text(&c.name, (*width).into(), None)), }
) }))
.style(self.header_style) .style(self.header_style)
.bottom_margin(table_gap); .bottom_margin(table_gap);
let disk_rows = sliced_vec.iter().map(|row| { let table_rows = sliced_vec.iter().map(|row| {
let (row, style) = match row { let (row, style) = match row {
TableRow::Raw(row) => (row, None), TableRow::Raw(row) => (row, None),
TableRow::Styled(row, style) => (row, Some(*style)), TableRow::Styled(row, style) => (row, Some(*style)),
}; };
Row::new( Row::new(row.iter().zip(columns).filter_map(|(cell, c)| {
row.iter() if c.calculated_width == 0 {
.zip(widths) None
.map(|(cell, width)| truncate_text(cell, (*width).into(), style)), } else {
) Some(truncate_text(cell, c.calculated_width.into(), style))
}
}))
}); });
let widget = { let widget = {
let mut table = Table::new(disk_rows) let mut table = Table::new(table_rows)
.block(disk_block) .block(disk_block)
.highlight_style(self.highlighted_text_style) .highlight_style(self.highlighted_text_style)
.style(self.text_style); .style(self.text_style);
@ -216,9 +227,15 @@ impl<'a> TextTable<'a> {
f.render_stateful_widget( f.render_stateful_widget(
widget.widths( widget.widths(
&(widths &(columns
.iter() .iter()
.map(|w| Constraint::Length(*w)) .filter_map(|c| {
if c.calculated_width == 0 {
None
} else {
Some(Constraint::Length(c.calculated_width))
}
})
.collect::<Vec<_>>()), .collect::<Vec<_>>()),
), ),
margined_draw_loc, margined_draw_loc,

View File

@ -1,38 +1,34 @@
use std::borrow::Cow; use std::{borrow::Cow, iter};
use crate::{ use crate::{
app::{layout_manager::WidgetDirection, App, CpuWidgetState}, app::{layout_manager::WidgetDirection, App, CpuWidgetState},
canvas::{ canvas::{
components::{GraphData, TimeGraph}, components::{GraphData, TextTable, TimeGraph},
drawing_utils::{get_column_widths, get_start_position, should_hide_x_label}, drawing_utils::should_hide_x_label,
Painter, Painter,
}, },
constants::*, data_conversion::{CellContent, ConvertedCpuData, TableData, TableRow},
data_conversion::ConvertedCpuData,
}; };
use concat_string::concat_string; use concat_string::concat_string;
use itertools::Either;
use tui::{ use tui::{
backend::Backend, backend::Backend,
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
terminal::Frame, terminal::Frame,
text::Text,
widgets::{Block, Borders, Row, Table},
}; };
const CPU_LEGEND_HEADER: [&str; 2] = ["CPU", "Use%"];
const AVG_POSITION: usize = 1; const AVG_POSITION: usize = 1;
const ALL_POSITION: usize = 0; const ALL_POSITION: usize = 0;
static CPU_LEGEND_HEADER_LENS: [usize; 2] =
[CPU_LEGEND_HEADER[0].len(), CPU_LEGEND_HEADER[1].len()];
impl Painter { impl Painter {
pub fn draw_cpu<B: Backend>( pub fn draw_cpu<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, widget_id: u64, &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, widget_id: u64,
) { ) {
if draw_loc.width as f64 * 0.15 <= 6.0 { let legend_width = (draw_loc.width as f64 * 0.15) as u16;
if legend_width < 6 {
// 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) {
if app_state.app_config_fields.left_legend { if app_state.app_config_fields.left_legend {
@ -55,18 +51,25 @@ impl Painter {
} }
} }
} else { } else {
let graph_width = draw_loc.width - legend_width;
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,
[Constraint::Percentage(15), Constraint::Percentage(85)], [
Constraint::Length(legend_width),
Constraint::Length(graph_width),
],
) )
} else { } else {
( (
0, 0,
1, 1,
[Constraint::Percentage(85), Constraint::Percentage(15)], [
Constraint::Length(graph_width),
Constraint::Length(legend_width),
],
) )
}; };
@ -121,7 +124,7 @@ impl Painter {
) -> Vec<GraphData<'a>> { ) -> Vec<GraphData<'a>> {
let show_avg_offset = if show_avg_cpu { AVG_POSITION } else { 0 }; let show_avg_offset = if show_avg_cpu { AVG_POSITION } else { 0 };
let current_scroll_position = cpu_widget_state.scroll_state.current_scroll_position; let current_scroll_position = cpu_widget_state.table_state.current_scroll_position;
if current_scroll_position == ALL_POSITION { if current_scroll_position == ALL_POSITION {
// This case ensures the other cases cannot have the position be equal to 0. // This case ensures the other cases cannot have the position be equal to 0.
cpu_data cpu_data
@ -224,149 +227,81 @@ impl Painter {
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; // TODO: This line (and the one above, see caller) is pretty dumb. // TODO: This line (and the one above, see caller) is pretty dumb but I guess needed.
let cpu_data: &mut [ConvertedCpuData] = &mut app_state.canvas_data.cpu_data; cpu_widget_state.is_legend_hidden = false;
let cpu_table_state = &mut cpu_widget_state.scroll_state.table_state;
let is_on_widget = widget_id == app_state.current_widget.widget_id;
let table_gap = if draw_loc.height < TABLE_GAP_HEIGHT_LIMIT {
0
} else {
app_state.app_config_fields.table_gap
};
let start_position = get_start_position(
usize::from(
(draw_loc.height + (1 - table_gap)).saturating_sub(self.table_height_offset),
),
&cpu_widget_state.scroll_state.scroll_direction,
&mut cpu_widget_state.scroll_state.scroll_bar,
cpu_widget_state.scroll_state.current_scroll_position,
app_state.is_force_redraw,
);
cpu_table_state.select(Some(
cpu_widget_state
.scroll_state
.current_scroll_position
.saturating_sub(start_position),
));
let sliced_cpu_data = &cpu_data[start_position..];
let offset_scroll_index = cpu_widget_state
.scroll_state
.current_scroll_position
.saturating_sub(start_position);
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_data = {
// Calculate widths let row_widths = vec![1, 3]; // TODO: Should change this to take const generics (usize) and an array.
if recalculate_column_widths { let colour_iter = if show_avg_cpu {
cpu_widget_state.table_width_state.desired_column_widths = vec![6, 4]; Either::Left(
cpu_widget_state.table_width_state.calculated_column_widths = get_column_widths( iter::once(&self.colours.all_colour_style)
draw_loc.width, .chain(iter::once(&self.colours.avg_colour_style))
&[None, None], .chain(self.colours.cpu_colour_styles.iter().cycle()),
&(CPU_LEGEND_HEADER_LENS )
.iter()
.map(|width| Some(*width as u16))
.collect::<Vec<_>>()),
&[Some(0.5), Some(0.5)],
&(cpu_widget_state
.table_width_state
.desired_column_widths
.iter()
.map(|width| Some(*width))
.collect::<Vec<_>>()),
false,
);
}
let dcw = &cpu_widget_state.table_width_state.desired_column_widths;
let ccw = &cpu_widget_state.table_width_state.calculated_column_widths;
let cpu_rows = sliced_cpu_data.iter().enumerate().map(|(itx, cpu)| {
let mut truncated_name =
if let (Some(desired_column_width), Some(calculated_column_width)) =
(dcw.get(0), ccw.get(0))
{
if *desired_column_width > *calculated_column_width {
Text::raw(&cpu.short_cpu_name)
} else {
Text::raw(&cpu.cpu_name)
}
} else {
Text::raw(&cpu.cpu_name)
};
let is_first_column_hidden = if let Some(calculated_column_width) = ccw.get(0) {
*calculated_column_width == 0
} else { } else {
false Either::Right(
iter::once(&self.colours.all_colour_style)
.chain(self.colours.cpu_colour_styles.iter().cycle()),
)
}; };
let truncated_legend = if is_first_column_hidden && cpu.legend_value.is_empty() { let data = {
// For the case where we only have room for one column, display "All" in the normally blank area. let iter = app_state.canvas_data.cpu_data.iter().zip(colour_iter);
Text::raw("All") const CPU_WIDTH_CHECK: u16 = 10; // This is hard-coded, it's terrible.
} else { if draw_loc.width < CPU_WIDTH_CHECK {
Text::raw(&cpu.legend_value) Either::Left(iter.map(|(cpu, style)| {
}; let row = vec![
CellContent::Simple("".into()),
if !is_first_column_hidden CellContent::Simple(if cpu.legend_value.is_empty() {
&& itx == offset_scroll_index cpu.cpu_name.clone().into()
&& itx + start_position == ALL_POSITION } else {
{ cpu.legend_value.clone().into()
truncated_name.patch_style(self.colours.currently_selected_text_style); }),
Row::new(vec![truncated_name, truncated_legend]) ];
} else { TableRow::Styled(row, *style)
let cpu_string_row = vec![truncated_name, truncated_legend]; }))
Row::new(cpu_string_row).style(if itx == offset_scroll_index {
self.colours.currently_selected_text_style
} else if itx + start_position == ALL_POSITION {
self.colours.all_colour_style
} else if show_avg_cpu {
if itx + start_position == AVG_POSITION {
self.colours.avg_colour_style
} else {
self.colours.cpu_colour_styles[(itx + start_position
- AVG_POSITION
- 1)
% self.colours.cpu_colour_styles.len()]
}
} else { } else {
self.colours.cpu_colour_styles[(itx + start_position - ALL_POSITION - 1) Either::Right(iter.map(|(cpu, style)| {
% self.colours.cpu_colour_styles.len()] let row = vec![
}) CellContent::HasAlt {
alt: cpu.short_cpu_name.clone().into(),
main: cpu.cpu_name.clone().into(),
},
CellContent::Simple(cpu.legend_value.clone().into()),
];
TableRow::Styled(row, *style)
}))
}
} }
}); .collect();
// Note we don't set highlight_style, as it should always be shown for this widget. TableData { data, row_widths }
let border_and_title_style = if is_on_widget { };
let is_on_widget = widget_id == app_state.current_widget.widget_id;
let border_style = if is_on_widget {
self.colours.highlighted_border_style self.colours.highlighted_border_style
} else { } else {
self.colours.border_style self.colours.border_style
}; };
// Draw TextTable {
f.render_stateful_widget( table_gap: app_state.app_config_fields.table_gap,
Table::new(cpu_rows) is_force_redraw: app_state.is_force_redraw,
.block( recalculate_column_widths,
Block::default() header_style: self.colours.table_header_style,
.borders(Borders::ALL) border_style,
.border_style(border_and_title_style), highlighted_text_style: self.colours.currently_selected_text_style, // We always highlight the selected CPU entry... not sure if I like this though.
) title: None,
.header( is_on_widget,
Row::new(CPU_LEGEND_HEADER.to_vec()) draw_border: true,
.style(self.colours.table_header_style) show_table_scroll_position: app_state.app_config_fields.show_table_scroll_position,
.bottom_margin(table_gap), title_style: self.colours.widget_title_style,
) text_style: self.colours.text_style,
.widths( left_to_right: false,
&(cpu_widget_state }
.table_width_state .draw_text_table(f, draw_loc, &mut cpu_widget_state.table_state, &cpu_data);
.calculated_column_widths
.iter()
.map(|calculated_width| Constraint::Length(*calculated_width as u16))
.collect::<Vec<_>>()),
),
draw_loc,
cpu_table_state,
);
} }
} }
} }

View File

@ -2,7 +2,10 @@ use tui::{backend::Backend, layout::Rect, terminal::Frame};
use crate::{ use crate::{
app, app,
canvas::{components::TextTable, Painter}, canvas::{
components::{TextTable, TextTableTitle},
Painter,
},
}; };
impl Painter { impl Painter {
@ -13,7 +16,6 @@ impl Painter {
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 is_on_widget = app_state.current_widget.widget_id == widget_id; let is_on_widget = app_state.current_widget.widget_id == widget_id;
let (border_style, highlighted_text_style) = if is_on_widget { let (border_style, highlighted_text_style) = if is_on_widget {
( (
self.colours.highlighted_border_style, self.colours.highlighted_border_style,
@ -29,8 +31,10 @@ impl Painter {
header_style: self.colours.table_header_style, header_style: self.colours.table_header_style,
border_style, border_style,
highlighted_text_style, highlighted_text_style,
title: " Disks ".into(), title: Some(TextTableTitle {
is_expanded: app_state.is_expanded, title: " Disks ".into(),
is_expanded: app_state.is_expanded,
}),
is_on_widget, is_on_widget,
draw_border, draw_border,
show_table_scroll_position: app_state.app_config_fields.show_table_scroll_position, show_table_scroll_position: app_state.app_config_fields.show_table_scroll_position,

View File

@ -2,7 +2,10 @@ use tui::{backend::Backend, layout::Rect, terminal::Frame};
use crate::{ use crate::{
app, app,
canvas::{components::TextTable, Painter}, canvas::{
components::{TextTable, TextTableTitle},
Painter,
},
}; };
impl Painter { impl Painter {
@ -29,8 +32,10 @@ impl Painter {
header_style: self.colours.table_header_style, header_style: self.colours.table_header_style,
border_style, border_style,
highlighted_text_style, highlighted_text_style,
title: " Temperatures ".into(), title: Some(TextTableTitle {
is_expanded: app_state.is_expanded, title: " Temperatures ".into(),
is_expanded: app_state.is_expanded,
}),
is_on_widget, is_on_widget,
draw_border, draw_border,
show_table_scroll_position: app_state.app_config_fields.show_table_scroll_position, show_table_scroll_position: app_state.app_config_fields.show_table_scroll_position,

View File

@ -238,7 +238,7 @@ pub fn convert_cpu_data_points(
if data.cpu_data.len() + 1 != existing_cpu_data.len() { if data.cpu_data.len() + 1 != existing_cpu_data.len() {
*existing_cpu_data = vec![ConvertedCpuData { *existing_cpu_data = vec![ConvertedCpuData {
cpu_name: "All".to_string(), cpu_name: "All".to_string(),
short_cpu_name: "All".to_string(), short_cpu_name: "".to_string(),
cpu_data: vec![], cpu_data: vec![],
legend_value: String::new(), legend_value: String::new(),
}]; }];