summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorClementTsang <cjhtsang@uwaterloo.ca>2022-05-16 04:53:39 -0400
committerClementTsang <cjhtsang@uwaterloo.ca>2022-05-16 04:53:41 -0400
commitcc6d7b8ad7435e5d207fd9670c568b1204619bbf (patch)
tree213716ce7ad7c9b85deefd05b94d4259194b6d02 /src
parent0831a56341538b490c3caecc387f9bd2609b2919 (diff)
bug: fix a variety of bugs
Bugs squashed: - Incorrect column sizing for flex cases - Case where the sort menu bounds were still existing despite being hidden - Proc widget not actually taking into account the calculated row widths in some cases during data conversion.
Diffstat (limited to 'src')
-rw-r--r--src/app.rs45
-rw-r--r--src/app/states/table_state.rs27
-rw-r--r--src/app/widgets/process_widget.rs44
-rw-r--r--src/bin/main.rs8
-rw-r--r--src/canvas/components/text_table.rs88
-rw-r--r--src/canvas/components/time_graph.rs12
-rw-r--r--src/canvas/widgets/process_table.rs11
-rw-r--r--src/lib.rs6
8 files changed, 124 insertions, 117 deletions
diff --git a/src/app.rs b/src/app.rs
index 5df1aa9d..d139f60f 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -217,26 +217,25 @@ impl App {
} else {
match self.current_widget.widget_type {
BottomWidgetType::Proc => {
- if let Some(current_proc_state) = self
+ if let Some(pws) = self
.proc_state
.get_mut_widget_state(self.current_widget.widget_id)
{
- if current_proc_state.is_search_enabled() || current_proc_state.is_sort_open
- {
- current_proc_state.proc_search.search_state.is_enabled = false;
- current_proc_state.is_sort_open = false;
+ if pws.is_search_enabled() || pws.is_sort_open {
+ pws.proc_search.search_state.is_enabled = false;
+ pws.is_sort_open = false;
self.is_force_redraw = true;
return;
}
}
}
BottomWidgetType::ProcSearch => {
- if let Some(current_proc_state) = self
+ if let Some(pws) = self
.proc_state
.get_mut_widget_state(self.current_widget.widget_id - 1)
{
- if current_proc_state.is_search_enabled() {
- current_proc_state.proc_search.search_state.is_enabled = false;
+ if pws.is_search_enabled() {
+ pws.proc_search.search_state.is_enabled = false;
self.move_widget_selection(&WidgetDirection::Up);
self.is_force_redraw = true;
return;
@@ -244,12 +243,12 @@ impl App {
}
}
BottomWidgetType::ProcSort => {
- if let Some(current_proc_state) = self
+ if let Some(pws) = self
.proc_state
.get_mut_widget_state(self.current_widget.widget_id - 2)
{
- if current_proc_state.is_sort_open {
- current_proc_state.is_sort_open = false;
+ if pws.is_sort_open {
+ pws.is_sort_open = false;
self.move_widget_selection(&WidgetDirection::Right);
self.is_force_redraw = true;
return;
@@ -345,11 +344,12 @@ impl App {
if let Some(pws) = self.proc_state.get_mut_widget_state(widget_id) {
pws.is_sort_open = !pws.is_sort_open;
- pws.force_update = true;
+ pws.force_rerender = true;
// If the sort is now open, move left. Otherwise, if the proc sort was selected, force move right.
if pws.is_sort_open {
if let SortState::Sortable(st) = &pws.table_state.sort_state {
+ pws.sort_table_state.scroll_bar = 0;
pws.sort_table_state.current_scroll_position = st
.current_index
.clamp(0, pws.num_enabled_columns().saturating_sub(1));
@@ -358,6 +358,7 @@ impl App {
} else if let BottomWidgetType::ProcSort = self.current_widget.widget_type {
self.move_widget_selection(&WidgetDirection::Right);
}
+ self.is_force_redraw = true;
}
}
@@ -376,7 +377,7 @@ impl App {
&mut proc_widget_state.table_state.sort_state
{
state.toggle_order();
- proc_widget_state.force_update = true;
+ proc_widget_state.force_data_update();
}
}
}
@@ -396,7 +397,7 @@ impl App {
.get_mut(&self.current_widget.widget_id)
{
proc_widget_state.toggle_mem_percentage();
- proc_widget_state.force_update = true;
+ proc_widget_state.force_data_update();
}
}
_ => {}
@@ -414,7 +415,6 @@ impl App {
if is_in_search_widget && proc_widget_state.is_search_enabled() {
proc_widget_state.proc_search.search_toggle_ignore_case();
proc_widget_state.update_query();
- proc_widget_state.force_update = true;
// Remember, it's the opposite (ignoring case is case "in"sensitive)
is_case_sensitive = Some(!proc_widget_state.proc_search.is_ignoring_case);
@@ -465,7 +465,6 @@ impl App {
if is_in_search_widget && proc_widget_state.is_search_enabled() {
proc_widget_state.proc_search.search_toggle_whole_word();
proc_widget_state.update_query();
- proc_widget_state.force_update = true;
is_searching_whole_word =
Some(proc_widget_state.proc_search.is_searching_whole_word);
@@ -520,7 +519,6 @@ impl App {
if is_in_search_widget && proc_widget_state.is_search_enabled() {
proc_widget_state.proc_search.search_toggle_regex();
proc_widget_state.update_query();
- proc_widget_state.force_update = true;
is_searching_with_regex =
Some(proc_widget_state.proc_search.is_searching_with_regex);
@@ -569,13 +567,13 @@ impl App {
match proc_widget_state.mode {
ProcWidgetMode::Tree { .. } => {
proc_widget_state.mode = ProcWidgetMode::Normal;
- proc_widget_state.force_update = true;
+ proc_widget_state.force_rerender_and_update();
}
ProcWidgetMode::Normal => {
proc_widget_state.mode = ProcWidgetMode::Tree {
collapsed_pids: Default::default(),
};
- proc_widget_state.force_update = true;
+ proc_widget_state.force_rerender_and_update();
}
ProcWidgetMode::Grouped => {}
}
@@ -617,6 +615,7 @@ impl App {
{
proc_widget_state.use_sort_table_value();
self.move_widget_selection(&WidgetDirection::Right);
+ self.is_force_redraw = true;
}
}
}
@@ -662,7 +661,6 @@ impl App {
);
proc_widget_state.update_query();
- proc_widget_state.force_update = true;
}
} else {
self.start_killing_process()
@@ -714,7 +712,6 @@ impl App {
CursorDirection::Left;
proc_widget_state.update_query();
- proc_widget_state.force_update = true;
}
}
}
@@ -1077,7 +1074,6 @@ impl App {
.get_mut(&(self.current_widget.widget_id - 1))
{
proc_widget_state.clear_search();
- proc_widget_state.force_update = true;
}
}
}
@@ -1141,7 +1137,6 @@ impl App {
proc_widget_state.proc_search.search_state.cursor_direction = CursorDirection::Left;
proc_widget_state.update_query();
- proc_widget_state.force_update = true;
}
}
}
@@ -1245,7 +1240,6 @@ impl App {
UnicodeWidthChar::width(caught_char).unwrap_or(0);
proc_widget_state.update_query();
- proc_widget_state.force_update = true;
proc_widget_state.proc_search.search_state.cursor_direction =
CursorDirection::Right;
@@ -2555,7 +2549,6 @@ impl App {
if (x >= tlc_x && y >= tlc_y) && (x < brc_x && y < brc_y) {
if let Some(new_widget) = self.widget_map.get(new_widget_id) {
self.current_widget = new_widget.clone();
-
match &self.current_widget.widget_type {
BottomWidgetType::Temp
| BottomWidgetType::Proc
@@ -2716,7 +2709,7 @@ impl App {
&mut proc_widget_state.table_state.sort_state
{
if st.try_select_location(x, y).is_some() {
- proc_widget_state.force_update = true;
+ proc_widget_state.force_data_update();
}
}
}
diff --git a/src/app/states/table_state.rs b/src/app/states/table_state.rs
index fea36464..c6ce3b46 100644
--- a/src/app/states/table_state.rs
+++ b/src/app/states/table_state.rs
@@ -400,20 +400,18 @@ impl<H: TableComponentHeader> TableComponentState<H> {
continue;
}
- let space_taken = min(
- max(
- if let Some(max_percentage) = max_percentage {
- // TODO: Rust doesn't have an `into()` or `try_into()` for floats to integers.
- ((*max_percentage * f32::from(total_width)).ceil()) as u16
- } else {
- *desired
- },
- min_width,
- ),
- total_width_left,
+ let soft_limit = max(
+ if let Some(max_percentage) = max_percentage {
+ // TODO: Rust doesn't have an `into()` or `try_into()` for floats to integers.
+ ((*max_percentage * f32::from(total_width)).ceil()) as u16
+ } else {
+ *desired
+ },
+ min_width,
);
+ let space_taken = min(min(soft_limit, *desired), total_width_left);
- if min_width == 0 {
+ if min_width > space_taken || min_width == 0 {
skip_iter = true;
} else if space_taken > 0 {
total_width_left = total_width_left.saturating_sub(space_taken + 1);
@@ -452,6 +450,7 @@ impl<H: TableComponentHeader> TableComponentState<H> {
let mut num_dist = num_columns;
let amount_per_slot = total_width_left / num_dist;
total_width_left %= num_dist;
+
for column in self.columns.iter_mut() {
if num_dist == 0 {
break;
@@ -607,7 +606,7 @@ mod test {
test_calculation(&mut state, 8, vec![1, 1, 4]);
test_calculation(&mut state, 14, vec![2, 2, 7]);
test_calculation(&mut state, 20, vec![2, 4, 11]);
- test_calculation(&mut state, 100, vec![12, 24, 61]);
+ test_calculation(&mut state, 100, vec![27, 35, 35]);
state.sort_state = SortState::Sortable(SortableState::new(1, SortOrder::Ascending, vec![]));
@@ -622,7 +621,7 @@ mod test {
test_calculation(&mut state, 8, vec![3, 3]);
test_calculation(&mut state, 14, vec![2, 2, 7]);
test_calculation(&mut state, 20, vec![3, 4, 10]);
- test_calculation(&mut state, 100, vec![13, 24, 60]);
+ test_calculation(&mut state, 100, vec![27, 35, 35]);
}
#[test]
diff --git a/src/app/widgets/process_widget.rs b/src/app/widgets/process_widget.rs
index dcd1503c..86a8c25e 100644
--- a/src/app/widgets/process_widget.rs
+++ b/src/app/widgets/process_widget.rs
@@ -311,7 +311,8 @@ pub struct ProcWidget {
pub sort_table_state: TableComponentState,
pub is_sort_open: bool,
- pub force_update: bool,
+ pub force_rerender: bool,
+ pub force_update_data: bool,
pub table_data: TableData,
}
@@ -396,7 +397,8 @@ impl ProcWidget {
sort_table_state,
is_sort_open: false,
mode,
- force_update: false,
+ force_rerender: true,
+ force_update_data: false,
table_data: TableData::default(),
}
}
@@ -418,7 +420,6 @@ impl ProcWidget {
/// This function *only* updates the displayed process data. If there is a need to update the actual *stored* data,
/// call it before this function.
pub fn update_displayed_process_data(&mut self, data_collection: &DataCollection) {
- // Now update everything else.
let search_query = if self.proc_search.search_state.is_invalid_or_blank_search() {
&None
} else {
@@ -821,14 +822,7 @@ impl ProcWidget {
let cmd_pid_map = &data_collection.process_data.cmd_pid_map;
let name_pid_map = &data_collection.process_data.name_pid_map;
- let mut col_widths = vec![
- 0;
- self.table_state
- .columns
- .iter()
- .filter(|c| c.is_skipped())
- .count()
- ];
+ let mut col_widths = vec![0; self.table_state.columns.len()];
let data = process_data
.iter()
@@ -858,10 +852,23 @@ impl ProcWidget {
if let Some(ProcWidgetColumn::Memory { show_percentage }) = self.get_mut_proc_col(Self::MEM)
{
*show_percentage = !*show_percentage;
- self.force_update = true;
+ self.force_data_update();
}
}
+ /// Forces an update of the data stored.
+ #[inline]
+ pub fn force_data_update(&mut self) {
+ self.force_update_data = true;
+ }
+
+ /// Forces an entire rerender and update of the data stored.
+ #[inline]
+ pub fn force_rerender_and_update(&mut self) {
+ self.force_rerender = true;
+ self.force_update_data = true;
+ }
+
/// Marks the selected column as hidden, and automatically resets the selected column if currently selected.
fn hide_column(&mut self, index: usize) {
if let Some(col) = self.table_state.columns.get_mut(index) {
@@ -887,7 +894,7 @@ impl ProcWidget {
pub fn select_column(&mut self, new_sort_index: usize) {
if let SortState::Sortable(state) = &mut self.table_state.sort_state {
state.update_sort_index(new_sort_index);
- self.force_update = true;
+ self.force_data_update();
}
}
@@ -902,7 +909,7 @@ impl ProcWidget {
if !collapsed_pids.remove(&pid) {
collapsed_pids.insert(pid);
}
- self.force_update = true;
+ self.force_data_update();
}
}
}
@@ -924,7 +931,7 @@ impl ProcWidget {
}
}
- self.force_update = true;
+ self.force_rerender_and_update();
}
}
}
@@ -958,7 +965,7 @@ impl ProcWidget {
self.show_column(Self::STATE);
self.mode = ProcWidgetMode::Normal;
}
- self.force_update = true;
+ self.force_rerender_and_update();
}
}
}
@@ -1011,10 +1018,13 @@ impl ProcWidget {
}
self.table_state.scroll_bar = 0;
self.table_state.current_scroll_position = 0;
+
+ self.force_data_update();
}
pub fn clear_search(&mut self) {
self.proc_search.search_state.reset();
+ self.force_data_update();
}
pub fn search_walk_forward(&mut self, start_position: usize) {
@@ -1064,7 +1074,7 @@ impl ProcWidget {
st.update_sort_index(self.sort_table_state.current_scroll_position);
self.is_sort_open = false;
- self.force_update = true;
+ self.force_rerender_and_update();
}
}
}
diff --git a/src/bin/main.rs b/src/bin/main.rs
index 6ae223eb..e3a86315 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -130,11 +130,11 @@ fn main() -> Result<()> {
if handle_key_event_or_break(event, &mut app, &collection_thread_ctrl_sender) {
break;
}
- handle_force_redraws(&mut app);
+ update_data(&mut app);
}
BottomEvent::MouseInput(event) => {
handle_mouse_event(event, &mut app);
- handle_force_redraws(&mut app);
+ update_data(&mut app);
}
BottomEvent::Update(data) => {
app.data_collection.eat_data(data);
@@ -207,7 +207,7 @@ fn main() -> Result<()> {
// Processes
if app.used_widgets.use_proc {
for proc in app.proc_state.widget_states.values_mut() {
- proc.force_update = true;
+ proc.force_data_update();
}
}
@@ -220,7 +220,7 @@ fn main() -> Result<()> {
}
}
- handle_force_redraws(&mut app);
+ update_data(&mut app);
}
}
BottomEvent::Clean => {
diff --git a/src/canvas/components/text_table.rs b/src/canvas/components/text_table.rs
index fe94ffa5..f5fc31e7 100644
--- a/src/canvas/components/text_table.rs
+++ b/src/canvas/components/text_table.rs
@@ -184,7 +184,10 @@ impl<'a> TextTable<'a> {
desired,
max_percentage: _,
} => {
- *desired = max(column.header.header_text().len(), *data_width) as u16;
+ *desired = max(
+ *desired,
+ max(column.header.header_text().len(), *data_width) as u16,
+ );
}
WidthBounds::CellWidth => {}
WidthBounds::Hard(_width) => {}
@@ -193,20 +196,19 @@ impl<'a> TextTable<'a> {
state.calculate_column_widths(inner_width, self.left_to_right);
if let SortState::Sortable(st) = &mut state.sort_state {
- st.update_visual_index(
- inner_rect,
- &state
- .columns
- .iter()
- .filter_map(|c| {
- if c.calculated_width == 0 {
- None
- } else {
- Some(c.calculated_width)
- }
- })
- .collect::<Vec<_>>(),
- );
+ let row_widths = state
+ .columns
+ .iter()
+ .filter_map(|c| {
+ if c.calculated_width == 0 {
+ None
+ } else {
+ Some(c.calculated_width)
+ }
+ })
+ .collect::<Vec<_>>();
+
+ st.update_visual_index(inner_rect, &row_widths);
}
// Update draw loc in widget map
@@ -236,35 +238,39 @@ impl<'a> TextTable<'a> {
}))
});
- let widget = {
- let mut table = Table::new(table_rows)
- .block(block)
- .highlight_style(self.highlighted_text_style)
- .style(self.text_style);
+ if !table_data.data.is_empty() {
+ let widget = {
+ let mut table = Table::new(table_rows)
+ .block(block)
+ .highlight_style(self.highlighted_text_style)
+ .style(self.text_style);
- if show_header {
- table = table.header(header);
- }
+ if show_header {
+ table = table.header(header);
+ }
- table
- };
+ table
+ };
- f.render_stateful_widget(
- widget.widths(
- &(columns
- .iter()
- .filter_map(|c| {
- if c.calculated_width == 0 {
- None
- } else {
- Some(Constraint::Length(c.calculated_width))
- }
- })
- .collect::<Vec<_>>()),
- ),
- margined_draw_loc,
- &mut state.table_state,
- );
+ f.render_stateful_widget(
+ widget.widths(
+ &(columns
+ .iter()
+ .filter_map(|c| {
+ if c.calculated_width == 0 {
+ None
+ } else {
+ Some(Constraint::Length(c.calculated_width))
+ }
+ })
+ .collect::<Vec<_>>()),
+ ),
+ margined_draw_loc,
+ &mut state.table_state,
+ );
+ } else {
+ f.render_widget(block, margined_draw_loc);
+ }
}
}
}
diff --git a/src/canvas/components/time_graph.rs b/src/canvas/components/time_graph.rs
index 723483be..7448ff5c 100644
--- a/src/canvas/components/time_graph.rs
+++ b/src/canvas/components/time_graph.rs
@@ -143,14 +143,14 @@ impl<'a> TimeGraph<'a> {
.collect()
};
+ let block = Block::default()
+ .title(self.generate_title(draw_loc))
+ .borders(Borders::ALL)
+ .border_style(self.border_style);
+
f.render_widget(
TimeChart::new(data)
- .block(
- Block::default()
- .title(self.generate_title(draw_loc))
- .borders(Borders::ALL)
- .border_style(self.border_style),
- )
+ .block(block)
.x_axis(x_axis)
.y_axis(y_axis)
.hidden_legend_constraints(
diff --git a/src/canvas/widgets/process_table.rs b/src/canvas/widgets/process_table.rs
index 306aac20..b38d09cb 100644
--- a/src/canvas/widgets/process_table.rs
+++ b/src/canvas/widgets/process_table.rs
@@ -65,14 +65,14 @@ impl Painter {
if let Some(proc_widget_state) = app_state.proc_state.widget_states.get_mut(&widget_id) {
// Reset redraw marker.
- if proc_widget_state.force_update {
- proc_widget_state.force_update = false;
+ if proc_widget_state.force_rerender {
+ proc_widget_state.force_rerender = false;
}
}
}
/// Draws the process sort box.
- /// - `widget_id` represents the widget ID of the process widget itself.
+ /// - `widget_id` represents the widget ID of the process widget itself.an
///
/// This should not be directly called.
fn draw_processes_table<B: Backend>(
@@ -81,9 +81,8 @@ impl Painter {
) {
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) {
- // TODO: [PROC] this might be too aggressive...
let recalculate_column_widths =
- should_get_widget_bounds || proc_widget_state.force_update;
+ should_get_widget_bounds || proc_widget_state.force_rerender;
let is_on_widget = widget_id == app_state.current_widget.widget_id;
let (border_style, highlighted_text_style) = if is_on_widget {
@@ -350,7 +349,7 @@ impl Painter {
app_state.proc_state.widget_states.get_mut(&(widget_id - 2))
{
let recalculate_column_widths =
- should_get_widget_bounds || proc_widget_state.force_update;
+ should_get_widget_bounds || proc_widget_state.force_rerender;
let is_on_widget = widget_id == app_state.current_widget.widget_id;
let (border_style, highlighted_text_style) = if is_on_widget {
diff --git a/src/lib.rs b/src/lib.rs
index 4042226b..735ace77 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -302,11 +302,11 @@ pub fn panic_hook(panic_info: &PanicInfo<'_>) {
.unwrap();
}
-pub fn handle_force_redraws(app: &mut App) {
+pub fn update_data(app: &mut App) {
for proc in app.proc_state.widget_states.values_mut() {
- if proc.force_update {
- // NB: Currently, the "force update" gets fixed in the draw.
+ if proc.force_update_data {
proc.update_displayed_process_data(&app.data_collection);
+ proc.force_update_data = false;
}
}