summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorClementTsang <cjhtsang@uwaterloo.ca>2022-05-02 18:27:09 -0400
committerClementTsang <cjhtsang@uwaterloo.ca>2022-05-07 20:53:52 -0400
commit2e51590bf5e819f4881b5f1b50ec54631ea0fd70 (patch)
treeba3b3c902bebca4c4d75eb10f6919edd74125b53 /src
parentc296b8bf5aacf200995db6312c0e92233b65b766 (diff)
refactor: don't draw header if too short
Diffstat (limited to 'src')
-rw-r--r--src/app/states.rs111
-rw-r--r--src/canvas/components/text_table.rs180
-rw-r--r--src/canvas/widgets/cpu_graph.rs102
-rw-r--r--src/canvas/widgets/disk_table.rs1
-rw-r--r--src/canvas/widgets/temp_table.rs1
5 files changed, 207 insertions, 188 deletions
diff --git a/src/app/states.rs b/src/app/states.rs
index 5d3ace9c..ebb28996 100644
--- a/src/app/states.rs
+++ b/src/app/states.rs
@@ -117,9 +117,7 @@ impl TableComponentState {
/// Calculates widths for the columns for this table.
///
- /// * `total_width` is the, well, total width available. **NOTE:** This function automatically
- /// takes away 2 from the width as part of the left/right
- /// bounds.
+ /// * `total_width` is the, well, total width available.
/// * `left_to_right` is a boolean whether to go from left to right if true, or right to left if
/// false.
///
@@ -128,71 +126,68 @@ impl TableComponentState {
use itertools::Either;
use std::cmp::{max, min};
- if total_width > 2 {
- let initial_width = total_width - 2;
- let mut total_width_left = initial_width;
+ let mut total_width_left = total_width;
- let column_widths = &mut self.calculated_widths;
- *column_widths = vec![0; self.columns.len()];
+ let column_widths = &mut self.calculated_widths;
+ *column_widths = vec![0; self.columns.len()];
- let columns = if left_to_right {
- Either::Left(self.columns.iter().enumerate())
- } else {
- Either::Right(self.columns.iter().enumerate().rev())
- };
-
- for (itx, column) in columns {
- match &column.width_bounds {
- WidthBounds::Soft {
- min_width,
- desired,
- max_percentage,
- } => {
- let soft_limit = max(
- if let Some(max_percentage) = max_percentage {
- // Rust doesn't have an `into()` or `try_into()` for floats to integers???
- ((*max_percentage * f32::from(initial_width)).ceil()) as u16
- } else {
- *desired
- },
- *min_width,
- );
- let space_taken = min(min(soft_limit, *desired), total_width_left);
-
- if *min_width > space_taken {
- break;
+ let columns = if left_to_right {
+ Either::Left(self.columns.iter().enumerate())
+ } else {
+ Either::Right(self.columns.iter().enumerate().rev())
+ };
+
+ for (itx, column) in columns {
+ match &column.width_bounds {
+ WidthBounds::Soft {
+ min_width,
+ desired,
+ max_percentage,
+ } => {
+ let soft_limit = max(
+ if let Some(max_percentage) = max_percentage {
+ // Rust doesn't have an `into()` or `try_into()` for floats to integers???
+ ((*max_percentage * f32::from(total_width)).ceil()) as u16
} else {
- total_width_left = total_width_left.saturating_sub(space_taken + 1);
- column_widths[itx] = space_taken;
- }
+ *desired
+ },
+ *min_width,
+ );
+ let space_taken = min(min(soft_limit, *desired), total_width_left);
+
+ if *min_width > space_taken {
+ break;
+ } else {
+ total_width_left = total_width_left.saturating_sub(space_taken + 1);
+ column_widths[itx] = space_taken;
}
- WidthBounds::Hard(width) => {
- let space_taken = min(*width, total_width_left);
+ }
+ WidthBounds::Hard(width) => {
+ let space_taken = min(*width, total_width_left);
- if *width > space_taken {
- break;
- } else {
- total_width_left = total_width_left.saturating_sub(space_taken + 1);
- column_widths[itx] = space_taken;
- }
+ if *width > space_taken {
+ break;
+ } else {
+ total_width_left = total_width_left.saturating_sub(space_taken + 1);
+ column_widths[itx] = space_taken;
}
}
}
+ }
- while let Some(0) = column_widths.last() {
- column_widths.pop();
- }
+ while let Some(0) = column_widths.last() {
+ column_widths.pop();
+ }
- if !column_widths.is_empty() {
- // Redistribute remaining.
- let amount_per_slot = total_width_left / column_widths.len() as u16;
- total_width_left %= column_widths.len() as u16;
- for (index, width) in column_widths.iter_mut().enumerate() {
- if index < total_width_left.into() {
- *width += amount_per_slot + 1;
- } else {
- *width += amount_per_slot;
- }
+ if !column_widths.is_empty() {
+ // Redistribute remaining.
+ let amount_per_slot = total_width_left / column_widths.len() as u16;
+ total_width_left %= column_widths.len() as u16;
+ for (index, width) in column_widths.iter_mut().enumerate() {
+ if index < total_width_left.into() {
+ *width += amount_per_slot + 1;
+ } else {
+ *width += amount_per_slot;
}
}
}
diff --git a/src/canvas/components/text_table.rs b/src/canvas/components/text_table.rs
index 767b8e6c..86cc5d1b 100644
--- a/src/canvas/components/text_table.rs
+++ b/src/canvas/components/text_table.rs
@@ -19,7 +19,6 @@ use crate::{
pub struct TextTable<'a> {
pub table_gap: u16,
- pub table_height_offset: u16,
pub is_force_redraw: bool,
pub recalculate_column_widths: bool,
@@ -100,71 +99,23 @@ impl<'a> TextTable<'a> {
&self, f: &mut Frame<'_, B>, draw_loc: Rect, state: &mut TableComponentState,
table_data: &TableData,
) -> Rect {
- let table_gap = if draw_loc.height < TABLE_GAP_HEIGHT_LIMIT {
- 0
- } else {
- self.table_gap
- };
+ let margined_draw_loc = Layout::default()
+ .constraints([Constraint::Percentage(100)])
+ .horizontal_margin(if self.is_on_widget || self.draw_border {
+ 0
+ } else {
+ 1
+ })
+ .direction(Direction::Horizontal)
+ .split(draw_loc)[0];
- let sliced_vec = {
- let num_rows = usize::from(
- (draw_loc.height + 1 - table_gap).saturating_sub(self.table_height_offset),
- );
- let start = get_start_position(
- num_rows,
- &state.scroll_direction,
- &mut state.scroll_bar,
- state.current_scroll_position,
- self.is_force_redraw,
+ let disk_block = if self.draw_border {
+ let title = self.generate_title(
+ draw_loc,
+ state.current_scroll_position.saturating_add(1),
+ table_data.data.len(),
);
- let end = min(table_data.data.len(), start + num_rows + 1);
- state
- .table_state
- .select(Some(state.current_scroll_position.saturating_sub(start)));
- &table_data.data[start..end]
- };
- // Calculate widths
- if self.recalculate_column_widths {
- state
- .columns
- .iter_mut()
- .zip(&table_data.row_widths)
- .for_each(|(column, data_width)| match &mut column.width_bounds {
- app::WidthBounds::Soft {
- min_width: _,
- desired,
- max_percentage: _,
- } => {
- *desired = std::cmp::max(column.name.len(), *data_width) as u16;
- }
- app::WidthBounds::Hard(_width) => {}
- });
-
- state.calculate_column_widths(draw_loc.width, self.left_to_right);
- }
-
- let columns = &state.columns;
- let widths = &state.calculated_widths;
- // TODO: Maybe truncate this too?
- let header = Row::new(columns.iter().map(|c| Text::raw(c.name.as_ref())))
- .style(self.header_style)
- .bottom_margin(table_gap);
- let disk_rows = sliced_vec.iter().map(|row| {
- Row::new(
- row.iter()
- .zip(widths)
- .map(|(cell, width)| truncate_text(cell, (*width).into())),
- )
- });
-
- let title = self.generate_title(
- draw_loc,
- state.current_scroll_position.saturating_add(1),
- table_data.data.len(),
- );
-
- let disk_block = if self.draw_border {
Block::default()
.title(title)
.borders(Borders::ALL)
@@ -177,34 +128,99 @@ impl<'a> TextTable<'a> {
Block::default().borders(Borders::NONE)
};
- let margined_draw_loc = Layout::default()
- .constraints([Constraint::Percentage(100)])
- .horizontal_margin(if self.is_on_widget || self.draw_border {
+ let (inner_width, inner_height) = {
+ let inner = disk_block.inner(margined_draw_loc);
+ (inner.width, inner.height)
+ };
+
+ if inner_width == 0 || inner_height == 0 {
+ f.render_widget(disk_block, margined_draw_loc);
+ margined_draw_loc
+ } else {
+ let show_header = inner_height > 1;
+ let header_height = if show_header { 1 } else { 0 };
+ let table_gap = if !show_header || draw_loc.height < TABLE_GAP_HEIGHT_LIMIT {
0
} else {
- 1
- })
- .direction(Direction::Horizontal)
- .split(draw_loc)[0];
+ self.table_gap
+ };
+
+ let sliced_vec = {
+ let num_rows = usize::from(inner_height.saturating_sub(table_gap + header_height));
+ let start = get_start_position(
+ num_rows,
+ &state.scroll_direction,
+ &mut state.scroll_bar,
+ state.current_scroll_position,
+ self.is_force_redraw,
+ );
+ let end = min(table_data.data.len(), start + num_rows + 1);
+ state
+ .table_state
+ .select(Some(state.current_scroll_position.saturating_sub(start)));
+ &table_data.data[start..end]
+ };
- // Draw!
- f.render_stateful_widget(
- Table::new(disk_rows)
- .block(disk_block)
- .header(header)
- .highlight_style(self.highlighted_text_style)
- .style(self.text_style)
- .widths(
+ // Calculate widths
+ if self.recalculate_column_widths {
+ state
+ .columns
+ .iter_mut()
+ .zip(&table_data.row_widths)
+ .for_each(|(column, data_width)| match &mut column.width_bounds {
+ app::WidthBounds::Soft {
+ min_width: _,
+ desired,
+ max_percentage: _,
+ } => {
+ *desired = std::cmp::max(column.name.len(), *data_width) as u16;
+ }
+ app::WidthBounds::Hard(_width) => {}
+ });
+
+ state.calculate_column_widths(inner_width, self.left_to_right);
+ }
+
+ let columns = &state.columns;
+ let widths = &state.calculated_widths;
+ // TODO: Maybe truncate this too?
+ let header = Row::new(columns.iter().map(|c| Text::raw(c.name.as_ref())))
+ .style(self.header_style)
+ .bottom_margin(table_gap);
+ let disk_rows = sliced_vec.iter().map(|row| {
+ Row::new(
+ row.iter()
+ .zip(widths)
+ .map(|(cell, width)| truncate_text(cell, (*width).into())),
+ )
+ });
+
+ let widget = {
+ let mut table = Table::new(disk_rows)
+ .block(disk_block)
+ .highlight_style(self.highlighted_text_style)
+ .style(self.text_style);
+
+ if show_header {
+ table = table.header(header);
+ }
+
+ table
+ };
+
+ f.render_stateful_widget(
+ widget.widths(
&(widths
.iter()
.map(|w| Constraint::Length(*w))
.collect::<Vec<_>>()),
),
- margined_draw_loc,
- &mut state.table_state,
- );
+ margined_draw_loc,
+ &mut state.table_state,
+ );
- margined_draw_loc
+ margined_draw_loc
+ }
}
}
diff --git a/src/canvas/widgets/cpu_graph.rs b/src/canvas/widgets/cpu_graph.rs
index fcb7daa2..36ba33e8 100644
--- a/src/canvas/widgets/cpu_graph.rs
+++ b/src/canvas/widgets/cpu_graph.rs
@@ -1,7 +1,7 @@
use std::borrow::Cow;
use crate::{
- app::{layout_manager::WidgetDirection, App},
+ app::{layout_manager::WidgetDirection, App, CpuWidgetState},
canvas::{
components::{GraphData, TimeGraph},
drawing_utils::{get_column_widths, get_start_position, should_hide_x_label},
@@ -115,6 +115,56 @@ impl Painter {
}
}
+ fn generate_points<'a>(
+ &self, cpu_widget_state: &CpuWidgetState, cpu_data: &'a [ConvertedCpuData],
+ show_avg_cpu: bool,
+ ) -> Vec<GraphData<'a>> {
+ let show_avg_offset = if show_avg_cpu { AVG_POSITION } else { 0 };
+
+ let current_scroll_position = cpu_widget_state.scroll_state.current_scroll_position;
+ if current_scroll_position == ALL_POSITION {
+ // This case ensures the other cases cannot have the position be equal to 0.
+ cpu_data
+ .iter()
+ .enumerate()
+ .rev()
+ .map(|(itx, cpu)| {
+ let style = if show_avg_cpu && itx == AVG_POSITION {
+ self.colours.avg_colour_style
+ } else if itx == ALL_POSITION {
+ self.colours.all_colour_style
+ } else {
+ let offset_position = itx - 1; // Because of the all position
+ self.colours.cpu_colour_styles[(offset_position - show_avg_offset)
+ % self.colours.cpu_colour_styles.len()]
+ };
+
+ GraphData {
+ points: &cpu.cpu_data[..],
+ style,
+ name: None,
+ }
+ })
+ .collect::<Vec<_>>()
+ } else if let Some(cpu) = cpu_data.get(current_scroll_position) {
+ let style = if show_avg_cpu && current_scroll_position == AVG_POSITION {
+ self.colours.avg_colour_style
+ } else {
+ let offset_position = current_scroll_position - 1; // Because of the all position
+ self.colours.cpu_colour_styles
+ [(offset_position - show_avg_offset) % self.colours.cpu_colour_styles.len()]
+ };
+
+ vec![GraphData {
+ points: &cpu.cpu_data[..],
+ style,
+ name: None,
+ }]
+ } else {
+ vec![]
+ }
+ }
+
fn draw_cpu_graph<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, widget_id: u64,
) {
@@ -131,52 +181,12 @@ impl Painter {
&mut cpu_widget_state.autohide_timer,
draw_loc,
);
- let show_avg_cpu = app_state.app_config_fields.show_average_cpu;
- let show_avg_offset = if show_avg_cpu { AVG_POSITION } else { 0 };
- let points = {
- let current_scroll_position = cpu_widget_state.scroll_state.current_scroll_position;
- if current_scroll_position == ALL_POSITION {
- // This case ensures the other cases cannot have the position be equal to 0.
- cpu_data
- .iter()
- .enumerate()
- .rev()
- .map(|(itx, cpu)| {
- let style = if show_avg_cpu && itx == AVG_POSITION {
- self.colours.avg_colour_style
- } else if itx == ALL_POSITION {
- self.colours.all_colour_style
- } else {
- let offset_position = itx - 1; // Because of the all position
- self.colours.cpu_colour_styles[(offset_position - show_avg_offset)
- % self.colours.cpu_colour_styles.len()]
- };
-
- GraphData {
- points: &cpu.cpu_data[..],
- style,
- name: None,
- }
- })
- .collect::<Vec<_>>()
- } else if let Some(cpu) = cpu_data.get(current_scroll_position) {
- let style = if show_avg_cpu && current_scroll_position == AVG_POSITION {
- self.colours.avg_colour_style
- } else {
- let offset_position = current_scroll_position - 1; // Because of the all position
- self.colours.cpu_colour_styles[(offset_position - show_avg_offset)
- % self.colours.cpu_colour_styles.len()]
- };
- vec![GraphData {
- points: &cpu.cpu_data[..],
- style,
- name: None,
- }]
- } else {
- vec![]
- }
- };
+ let points = self.generate_points(
+ &cpu_widget_state,
+ cpu_data,
+ app_state.app_config_fields.show_average_cpu,
+ );
// TODO: Maybe hide load avg if too long? Or maybe the CPU part.
let title = if cfg!(target_family = "unix") {
diff --git a/src/canvas/widgets/disk_table.rs b/src/canvas/widgets/disk_table.rs
index e897a770..fd667290 100644
--- a/src/canvas/widgets/disk_table.rs
+++ b/src/canvas/widgets/disk_table.rs
@@ -24,7 +24,6 @@ impl Painter {
};
let margined_draw_loc = TextTable {
table_gap: app_state.app_config_fields.table_gap,
- table_height_offset: self.table_height_offset,
is_force_redraw: app_state.is_force_redraw,
recalculate_column_widths,
header_style: self.colours.table_header_style,
diff --git a/src/canvas/widgets/temp_table.rs b/src/canvas/widgets/temp_table.rs
index 890411e2..bdd30134 100644
--- a/src/canvas/widgets/temp_table.rs
+++ b/src/canvas/widgets/temp_table.rs
@@ -24,7 +24,6 @@ impl Painter {
};
let margined_draw_loc = TextTable {
table_gap: app_state.app_config_fields.table_gap,
- table_height_offset: self.table_height_offset,
is_force_redraw: app_state.is_force_redraw,
recalculate_column_widths,
header_style: self.colours.table_header_style,