diff options
author | ClementTsang <cjhtsang@uwaterloo.ca> | 2021-09-26 00:30:16 -0400 |
---|---|---|
committer | ClementTsang <cjhtsang@uwaterloo.ca> | 2021-09-26 00:30:16 -0400 |
commit | 35ec66eaa70383cda591eeeaccc6560cfa921317 (patch) | |
tree | 6f1e350df90c1964f3ef0b71943269344db2783f | |
parent | abcca77c1ddcd465906549263b27dc41e769a30a (diff) |
refactor: cover almost all keybinds except killing processes
-rw-r--r-- | docs/content/usage/widgets/process.md | 1 | ||||
-rw-r--r-- | src/app.rs | 80 | ||||
-rw-r--r-- | src/app/event.rs | 4 | ||||
-rw-r--r-- | src/app/layout_manager.rs | 895 | ||||
-rw-r--r-- | src/app/widgets.rs | 24 | ||||
-rw-r--r-- | src/app/widgets/base/text_input.rs | 38 | ||||
-rw-r--r-- | src/app/widgets/bottom_widgets/carousel.rs | 25 | ||||
-rw-r--r-- | src/app/widgets/bottom_widgets/empty.rs | 8 | ||||
-rw-r--r-- | src/app/widgets/bottom_widgets/process.rs | 20 | ||||
-rw-r--r-- | src/canvas.rs | 13 | ||||
-rw-r--r-- | src/canvas/dialogs/dd_dialog.rs | 1 | ||||
-rw-r--r-- | src/constants.rs | 6 |
12 files changed, 196 insertions, 919 deletions
diff --git a/docs/content/usage/widgets/process.md b/docs/content/usage/widgets/process.md index c5f9c89b..ee21188f 100644 --- a/docs/content/usage/widgets/process.md +++ b/docs/content/usage/widgets/process.md @@ -198,7 +198,6 @@ Note that key bindings are generally case-sensitive. | ------------------------------------- | -------------------------------------------- | | ++left++ <br/> ++h++ <br/> ++alt+h++ | Moves the cursor left | | ++right++ <br/> ++l++ <br/> ++alt+l++ | Moves the cursor right | -| ++tab++ | Toggle between searching by PID or name | | ++esc++ | Close the search widget (retains the filter) | | ++ctrl+a++ | Skip to the start of the search query | | ++ctrl+e++ | Skip to the end of the search query | @@ -308,26 +308,36 @@ impl AppState { /// Moves to a widget. fn move_to_widget(&mut self, direction: MovementDirection) -> EventResult { - let layout_tree = &mut self.layout_tree; - let previous_selected = self.selected_widget; - if let Some(widget) = self.widget_lookup_map.get_mut(&self.selected_widget) { - match move_widget_selection(layout_tree, widget, self.selected_widget, direction) { - MoveWidgetResult::ForceRedraw(new_widget_id) => { - self.selected_widget = new_widget_id; + match if self.is_expanded { + move_expanded_widget_selection( + &mut self.widget_lookup_map, + self.selected_widget, + direction, + ) + } else { + let layout_tree = &mut self.layout_tree; + + move_widget_selection( + layout_tree, + &mut self.widget_lookup_map, + self.selected_widget, + direction, + ) + } { + MoveWidgetResult::ForceRedraw(new_widget_id) => { + self.selected_widget = new_widget_id; + EventResult::Redraw + } + MoveWidgetResult::NodeId(new_widget_id) => { + let previous_selected = self.selected_widget; + self.selected_widget = new_widget_id; + + if previous_selected != self.selected_widget { EventResult::Redraw - } - MoveWidgetResult::NodeId(new_widget_id) => { - self.selected_widget = new_widget_id; - - if previous_selected != self.selected_widget { - EventResult::Redraw - } else { - EventResult::NoRedraw - } + } else { + EventResult::NoRedraw } } - } else { - EventResult::NoRedraw } } @@ -448,33 +458,29 @@ impl AppState { for (id, widget) in self.widget_lookup_map.iter_mut() { if widget.does_border_intersect_mouse(&event) { let result = widget.handle_mouse_event(event); - - let new_id; match widget.selectable_type() { SelectableType::Selectable => { - new_id = *id; + let was_id_already_selected = self.selected_widget == *id; + self.selected_widget = *id; + + if was_id_already_selected { + returned_result = self.convert_widget_event_result(result); + break; + } else { + // If the weren't equal, *force* a redraw, and correct the layout tree. + correct_layout_last_selections( + &mut self.layout_tree, + self.selected_widget, + ); + let _ = self.convert_widget_event_result(result); + returned_result = EventResult::Redraw; + break; + } } SelectableType::Unselectable => { let result = widget.handle_mouse_event(event); return self.convert_widget_event_result(result); } - SelectableType::Redirect(redirected_id) => { - new_id = redirected_id; - } - } - - let was_id_already_selected = self.selected_widget == new_id; - self.selected_widget = new_id; - - if was_id_already_selected { - returned_result = self.convert_widget_event_result(result); - break; - } else { - // If the weren't equal, *force* a redraw, and correct the layout tree. - correct_layout_last_selections(&mut self.layout_tree, self.selected_widget); - let _ = self.convert_widget_event_result(result); - returned_result = EventResult::Redraw; - break; } } } diff --git a/src/app/event.rs b/src/app/event.rs index f727050d..31763159 100644 --- a/src/app/event.rs +++ b/src/app/event.rs @@ -44,8 +44,8 @@ pub enum ComponentEventResult { /// How a widget should handle a widget selection request. pub enum SelectionAction { - /// This event occurs if the widget internally handled the selection action. A redraw is required. + /// This occurs if the widget internally handled the selection action. A redraw is required. Handled, - /// This event occurs if the widget did not handle the selection action; the caller must handle it. + /// This occurs if the widget did not handle the selection action; the caller must handle it. NotHandled, } diff --git a/src/app/layout_manager.rs b/src/app/layout_manager.rs index 9f2c287b..b066a755 100644 --- a/src/app/layout_manager.rs +++ b/src/app/layout_manager.rs @@ -1,7 +1,7 @@ use crate::{ app::{ BasicCpu, BasicMem, BasicNet, BatteryTable, Carousel, DiskTable, Empty, MemGraph, NetGraph, - OldNetGraph, ProcessManager, TempTable, + OldNetGraph, ProcessManager, SelectableType, TempTable, }, error::{BottomError, Result}, options::{ @@ -11,12 +11,11 @@ use crate::{ }; use fxhash::FxHashMap; use indextree::{Arena, NodeId}; -use std::{cmp::min, collections::BTreeMap}; +use std::cmp::min; use tui::layout::Rect; use typed_builder::*; use crate::app::widgets::Widget; -use crate::constants::DEFAULT_WIDGET_ID; use super::{ event::SelectionAction, AppConfigFields, CpuGraph, TimeGraph, TmpBottomWidget, UsedWidgets, @@ -30,759 +29,6 @@ pub struct BottomLayout { pub total_row_height_ratio: u32, } -// Represents a start and end coordinate in some dimension. -type LineSegment = (u32, u32); - -type WidgetMappings = (u32, BTreeMap<LineSegment, u64>); -type ColumnRowMappings = (u32, BTreeMap<LineSegment, WidgetMappings>); -type ColumnMappings = (u32, BTreeMap<LineSegment, ColumnRowMappings>); - -impl BottomLayout { - pub fn get_movement_mappings(&mut self) { - #[allow(clippy::suspicious_operation_groupings)] // Have to enable this, clippy really doesn't like me doing this with tuples... - fn is_intersecting(a: LineSegment, b: LineSegment) -> bool { - a.0 >= b.0 && a.1 <= b.1 - || a.1 >= b.1 && a.0 <= b.0 - || a.0 <= b.0 && a.1 >= b.0 - || a.0 >= b.0 && a.0 < b.1 && a.1 >= b.1 - } - - fn get_distance(target: LineSegment, candidate: LineSegment) -> u32 { - if candidate.0 < target.0 { - candidate.1 - target.0 - } else if candidate.1 < target.1 { - candidate.1 - candidate.0 - } else { - target.1 - candidate.0 - } - } - - // Now we need to create the correct mapping for moving from a specific - // widget to another - - let mut layout_mapping: BTreeMap<LineSegment, ColumnMappings> = BTreeMap::new(); - let mut total_height = 0; - for row in &self.rows { - let mut row_width = 0; - let mut row_mapping: BTreeMap<LineSegment, ColumnRowMappings> = BTreeMap::new(); - let mut is_valid_row = false; - for col in &row.children { - let mut col_row_height = 0; - let mut col_mapping: BTreeMap<LineSegment, WidgetMappings> = BTreeMap::new(); - let mut is_valid_col = false; - - for col_row in &col.children { - let mut widget_width = 0; - let mut col_row_mapping: BTreeMap<LineSegment, u64> = BTreeMap::new(); - let mut is_valid_col_row = false; - for widget in &col_row.children { - match widget.widget_type { - BottomWidgetType::Empty => {} - _ => { - is_valid_col_row = true; - col_row_mapping.insert( - ( - widget_width * 100 / col_row.total_widget_ratio, - (widget_width + widget.width_ratio) * 100 - / col_row.total_widget_ratio, - ), - widget.widget_id, - ); - } - } - widget_width += widget.width_ratio; - } - if is_valid_col_row { - col_mapping.insert( - ( - col_row_height * 100 / col.total_col_row_ratio, - (col_row_height + col_row.col_row_height_ratio) * 100 - / col.total_col_row_ratio, - ), - (col.total_col_row_ratio, col_row_mapping), - ); - is_valid_col = true; - } - - col_row_height += col_row.col_row_height_ratio; - } - if is_valid_col { - row_mapping.insert( - ( - row_width * 100 / row.total_col_ratio, - (row_width + col.col_width_ratio) * 100 / row.total_col_ratio, - ), - (row.total_col_ratio, col_mapping), - ); - is_valid_row = true; - } - - row_width += col.col_width_ratio; - } - if is_valid_row { - layout_mapping.insert( - ( - total_height * 100 / self.total_row_height_ratio, - (total_height + row.row_height_ratio) * 100 / self.total_row_height_ratio, - ), - (self.total_row_height_ratio, row_mapping), - ); - } - total_height += row.row_height_ratio; - } - - // Now pass through a second time; this time we want to build up - // our neighbour profile. - let mut height_cursor = 0; - for row in &mut self.rows { - let mut col_cursor = 0; - let row_height_percentage_start = height_cursor * 100 / self.total_row_height_ratio; - let row_height_percentage_end = - (height_cursor + row.row_height_ratio) * 100 / self.total_row_height_ratio; - - for col in &mut row.children { - let mut col_row_cursor = 0; - let col_width_percentage_start = col_cursor * 100 / row.total_col_ratio; - let col_width_percentage_end = - (col_cursor + col.col_width_ratio) * 100 / row.total_col_ratio; - - for col_row in &mut col.children { - let mut widget_cursor = 0; - let col_row_height_percentage_start = - col_row_cursor * 100 / col.total_col_row_ratio; - let col_row_height_percentage_end = - (col_row_cursor + col_row.col_row_height_ratio) * 100 - / col.total_col_row_ratio; - let col_row_children_len = col_row.children.len(); - - for widget in &mut col_row.children { - // Bail if empty. - if let BottomWidgetType::Empty = widget.widget_type { - continue; - } - - let widget_width_percentage_start = - widget_cursor * 100 / col_row.total_widget_ratio; - let widget_width_percentage_end = - (widget_cursor + widget.width_ratio) * 100 / col_row.total_widget_ratio; - - if let Some(current_row) = layout_mapping - .get(&(row_height_percentage_start, row_height_percentage_end)) - { - // First check for within the same col_row for left and right - if let Some(current_col) = current_row - .1 - .get(&(col_width_percentage_start, col_width_percentage_end)) - { - if let Some(current_col_row) = current_col.1.get(&( - col_row_height_percentage_start, - col_row_height_percentage_end, - )) { - if let Some(to_left_widget) = current_col_row - .1 - .range( - ..( - widget_width_percentage_start, - widget_width_percentage_start, - ), - ) - .next_back() - { - widget.left_neighbour = Some(*to_left_widget.1); - } - - // Right - if let Some(to_right_neighbour) = current_col_row - .1 - .range( - ( - widget_width_percentage_end, - widget_width_percentage_end, - ).., - ) - .next() - { - widget.right_neighbour = Some(*to_right_neighbour.1); - } - } - } - - if widget.left_neighbour.is_none() { - if let Some(to_left_col) = current_row - .1 - .range( - ..(col_width_percentage_start, col_width_percentage_start), - ) - .next_back() - { - // Check left in same row - let mut current_best_distance = 0; - let mut current_best_widget_id = widget.widget_id; - - for widget_position in &(to_left_col.1).1 { - let candidate_start = (widget_position.0).0; - let candidate_end = (widget_position.0).1; - - if is_intersecting( - ( - col_row_height_percentage_start, - col_row_height_percentage_end, - ), - (candidate_start, candidate_end), - ) { - let candidate_distance = get_distance( - ( - col_row_height_percentage_start, - col_row_height_percentage_end, - ), - (candidate_start, candidate_end), - ); - - if current_best_distance < candidate_distance { - if let Some(new_best_widget) = - (widget_position.1).1.iter().next_back() - { - current_best_distance = candidate_distance + 1; - current_best_widget_id = *(new_best_widget.1); - } - } - } - } - if current_best_distance > 0 { - widget.left_neighbour = Some(current_best_widget_id); - } - } - } - - if widget.right_neighbour.is_none() { - if let Some(to_right_col) = current_row - .1 - .range((col_width_percentage_end, col_width_percentage_end)..) - .next() - { - // Check right in same row - let mut current_best_distance = 0; - let mut current_best_widget_id = widget.widget_id; - - for widget_position in &(to_right_col.1).1 { - let candidate_start = (widget_position.0).0; - let candidate_end = (widget_position.0).1; - - if is_intersecting( - ( - col_row_height_percentage_start, - col_row_height_percentage_end, - ), - (candidate_start, candidate_end), - ) { - let candidate_distance = get_distance( - ( - col_row_height_percentage_start, - col_row_height_percentage_end, - ), - (candidate_start, candidate_end), - ); - - if current_best_distance < candidate_distance { - if let Some(new_best_widget) = - (widget_position.1).1.iter().next() - { - current_best_distance = candidate_distance + 1; - current_best_widget_id = *(new_best_widget.1); - } - } - } - } - if current_best_distance > 0 { - widget.right_neighbour = Some(current_best_widget_id); - } - } - } - - // Check up/down within same row; - // else check up/down with other rows - if let Some(current_col) = current_row - .1 - .get(&(col_width_percentage_start, col_width_percentage_end)) - { - if let Some(to_up) = current_col - .1 - .range( - ..( - col_row_height_percentage_start, - col_row_height_percentage_start, - ), - ) - .next_back() - { - // Now check each widget_width and pick the best - for candidate_widget in &(to_up.1).1 { - let mut current_best_distance = 0; - let mut current_best_widget_id = widget.widget_id; - if is_intersecting( - ( - widget_width_percentage_start, - widget_width_percentage_end, - ), - ((candidate_widget.0).0, (candidate_widget.0).1), - ) { - let candidate_best_distance = get_distance( - ( - widget_width_percentage_start, - widget_width_percentage_end, - ), - ((candidate_widget.0).0, (candidate_widget.0).1), - ); - - if current_best_distance < candidate_best_distance { - current_best_distance = candidate_best_distance + 1; - current_best_widget_id = *candidate_widget.1; - } - } - - if current_best_distance > 0 { - widget.up_neighbour = Some(current_best_widget_id); - } - } - } else { - for next_row_up in layout_mapping - .range( - ..( - row_height_percentage_start, - row_height_percentage_start, - ), - ) - .rev() - { - let mut current_best_distance = 0; - let mut current_best_widget_id = widget.widget_id; - let (target_start_width, target_end_width) = - if col_row_children_len > 1 { - ( - col_width_percentage_start - + widget_width_percentage_start - * (col_width_percentage_end - - col_width_percentage_start) - / 100, - col_width_percentage_start - + widget_width_percentage_end - * (col_width_percentage_end - - col_width_percentage_start) - / 100, - ) - } else { - ( - col_width_percentage_start, - col_width_percentage_end, - ) - }; - - for col_position in &(next_row_up.1).1 { - if let Some(next_col_row) = - (col_position.1).1.iter().next_back() - { - let (candidate_col_start, candidate_col_end) = - ((col_position.0).0, (col_position.0).1); - let candidate_difference = - candidate_col_end - candidate_col_start; - for candidate_widget in &(next_col_row.1).1 { - let candidate_start = candidate_col_start - + (candidate_widget.0).0 - * candidate_difference - / 100; - let candidate_end = candidate_col_start - + (candidate_widget.0).1 - * candidate_difference - / 100; - - if is_intersecting( - (target_start_width, target_end_width), - (candidate_start, candidate_end), - ) { - let candidate_distance = get_distance( - (target_start_width, target_end_width), - (candidate_start, candidate_end), - ); - - if current_best_distance - < candidate_distance - { - current_best_distance = - candidate_distance + 1; - current_best_widget_id = - *(candidate_widget.1); - } - } - } - } - } - - if current_best_distance > 0 { - widget.up_neighbour = Some(current_best_widget_id); - break; - } - } - } - - if let Some(to_down) = current_col - .1 - .range( - ( - col_row_height_percentage_start + 1, - col_row_height_percentage_start + 1, - ).., - ) - .next() - { - for candidate_widget in &(to_down.1).1 { - let mut current_best_distance = 0; - let mut current_best_widget_id = widget.widget_id; - if is_intersecting( - ( - widget_width_percentage_start, - widget_width_percentage_end, - ), - ((candidate_widget.0).0, (candidate_widget.0).1), - ) { - let candidate_best_distance = get_distance( - ( - widget_width_percentage_start, - widget_width_percentage_end, - ), - ((candidate_widget.0).0, (candidate_widget.0).1), - ); - - if current_best_distance < candidate_best_distance { - current_best_distance = candidate_best_distance + 1; - current_best_widget_id = *candidate_widget.1; - } - } - - if current_best_distance > 0 { - widget.down_neighbour = Some(current_best_widget_id); - } - } - } else { - for next_row_down in layout_mapping.range( - ( - row_height_percentage_start + 1, - row_height_percentage_start + 1, - ).., - ) { - let mut current_best_distance = 0; - let mut current_best_widget_id = widget.widget_id; - let (target_start_width, target_end_width) = - if col_row_children_len > 1 { - ( - col_width_percentage_start - + widget_width_percentage_start - * (col_width_percentage_end - - col_width_percentage_start) - / 100, - col_width_percentage_start - + widget_width_percentage_end - * (col_width_percentage_end - - col_width_percentage_start) - / 100, - ) - } else { - ( - col_width_percentage_start, - col_width_percentage_end, - ) - }; - - for col_position in &(next_row_down.1).1 { - if let Some(next_col_row) = - (col_position.1).1.iter().next() - { - let (candidate_col_start, candidate_col_end) = - ((col_position.0).0, (col_position.0).1); - let candidate_difference = - candidate_col_end - candidate_col_start; - for candidate_widget in &(next_col_row.1).1 { - let candidate_start = candidate_col_start - + (candidate_widget.0).0 - * candidate_difference - / 100; - let candidate_end = candidate_col_start - + (candidate_widget.0).1 - * candidate_difference - / 100; - - if is_intersecting( - (target_start_width, target_end_width), - (candidate_start, candidate_end), - ) { - let candidate_distance = get_distance( - (target_start_width, target_end_width), - (candidate_start, candidate_end), - ); - - if current_best_distance - < candidate_distance - { - current_best_distance = - candidate_distance + 1; - current_best_widget_id = - *(candidate_widget.1); - } - } - } - } - } - - if current_best_distance > 0 { - widget.down_neighbour = Some(current_best_widget_id); - break; - } - } - } - } - } - widget_cursor += widget.width_ratio; - } - col_row_cursor += col_row.col_row_height_ratio; - } - col_cursor += col.col_width_ratio; - } - height_cursor += row.row_height_ratio; - } - } - - pub fn init_basic_default(use_battery: bool) -> Self { - let table_widgets = if use_battery { - vec![ - OldBottomCol::builder() - .canvas_handle_width(true) - .children(vec![BottomC |