summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClementTsang <cjhtsang@uwaterloo.ca>2021-09-26 00:30:16 -0400
committerClementTsang <cjhtsang@uwaterloo.ca>2021-09-26 00:30:16 -0400
commit35ec66eaa70383cda591eeeaccc6560cfa921317 (patch)
tree6f1e350df90c1964f3ef0b71943269344db2783f
parentabcca77c1ddcd465906549263b27dc41e769a30a (diff)
refactor: cover almost all keybinds except killing processes
-rw-r--r--docs/content/usage/widgets/process.md1
-rw-r--r--src/app.rs80
-rw-r--r--src/app/event.rs4
-rw-r--r--src/app/layout_manager.rs895
-rw-r--r--src/app/widgets.rs24
-rw-r--r--src/app/widgets/base/text_input.rs38
-rw-r--r--src/app/widgets/bottom_widgets/carousel.rs25
-rw-r--r--src/app/widgets/bottom_widgets/empty.rs8
-rw-r--r--src/app/widgets/bottom_widgets/process.rs20
-rw-r--r--src/canvas.rs13
-rw-r--r--src/canvas/dialogs/dd_dialog.rs1
-rw-r--r--src/constants.rs6
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 |
diff --git a/src/app.rs b/src/app.rs
index 3b95a536..f40ea123 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -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