summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClementTsang <cjhtsang@uwaterloo.ca>2021-08-23 16:50:02 -0400
committerClementTsang <cjhtsang@uwaterloo.ca>2021-08-23 17:34:52 -0400
commit64c6d0c8984616b2b1dba32ea2fc18d46caf540a (patch)
treeb0db48e9a54a9229f2de092c1c4441474e38c1fa
parente657fec2c04a1adabc7e28ff28c1292bb4c282e8 (diff)
refactor + change: write new movement logic
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml1
-rw-r--r--src/app/event.rs27
-rw-r--r--src/app/widgets/base/carousel.rs0
-rw-r--r--src/app/widgets/base/mod.rs2
-rw-r--r--src/app/widgets/base/scrollable.rs54
-rw-r--r--src/app/widgets/base/text_input.rs139
-rw-r--r--src/app/widgets/base/text_table.rs103
-rw-r--r--src/app/widgets/base/time_graph.rs28
-rw-r--r--src/app/widgets/basic_cpu.rs0
-rw-r--r--src/app/widgets/basic_mem.rs0
-rw-r--r--src/app/widgets/basic_net.rs0
-rw-r--r--src/app/widgets/battery.rs31
-rw-r--r--src/app/widgets/cpu.rs27
-rw-r--r--src/app/widgets/disk.rs15
-rw-r--r--src/app/widgets/mem.rs8
-rw-r--r--src/app/widgets/mod.rs339
-rw-r--r--src/app/widgets/net.rs39
-rw-r--r--src/app/widgets/process.rs212
-rw-r--r--src/app/widgets/temp.rs15
-rw-r--r--src/bin/main.rs4
-rw-r--r--src/lib.rs8
22 files changed, 900 insertions, 159 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e890a692..bb8569a0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -251,6 +251,7 @@ dependencies = [
"fxhash",
"heim",
"indexmap",
+ "indextree",
"itertools",
"libc",
"log",
@@ -883,6 +884,12 @@ dependencies = [
]
[[package]]
+name = "indextree"
+version = "4.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "990980c3d268c9b99df35e813eca2b8d1ee08606f6d2bb325edbd0b0c68f9ffe"
+
+[[package]]
name = "instant"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 4554ab27..a0505a43 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -48,6 +48,7 @@ futures = "0.3.14"
futures-timer = "3.0.2"
fxhash = "0.2.1"
indexmap = "1.6.2"
+indextree = "4.3.1"
itertools = "0.10.0"
once_cell = "1.5.2"
regex = "1.5.4"
diff --git a/src/app/event.rs b/src/app/event.rs
index 79efd9f5..d51a490e 100644
--- a/src/app/event.rs
+++ b/src/app/event.rs
@@ -1,11 +1,30 @@
use std::time::{Duration, Instant};
+const MAX_TIMEOUT: Duration = Duration::from_millis(400);
+
+/// The results of handling some user input event, like a mouse or key event, signifying what
+/// the program should then do next.
pub enum EventResult {
+ /// Kill the program.
Quit,
+
+ /// Trigger a redraw.
Redraw,
- Continue,
+
+ /// Don't trigger a redraw.
+ NoRedraw,
+}
+
+/// How a widget should handle a widget selection request.
+pub enum SelectionAction {
+ /// This event occurs if the widget internally handled the selection action.
+ Handled,
+
+ /// This event occurs if the widget did not handle the selection action; the caller must handle it.
+ NotHandled,
}
+/// The states a [`MultiKey`] can be in.
enum MultiKeyState {
/// Currently not waiting on any next input.
Idle,
@@ -36,16 +55,14 @@ pub enum MultiKeyResult {
pub struct MultiKey {
state: MultiKeyState,
pattern: Vec<char>,
- timeout: Duration,
}
impl MultiKey {
/// Creates a new [`MultiKey`] with a given pattern and timeout.
- pub fn register(pattern: Vec<char>, timeout: Duration) -> Self {
+ pub fn register(pattern: Vec<char>) -> Self {
Self {
state: MultiKeyState::Idle,
pattern,
- timeout,
}
}
@@ -81,7 +98,7 @@ impl MultiKey {
trigger_instant,
checked_index,
} => {
- if trigger_instant.elapsed() > self.timeout {
+ if trigger_instant.elapsed() > MAX_TIMEOUT {
// Just reset and recursively call (putting it into Idle).
self.reset();
self.input(c)
diff --git a/src/app/widgets/base/carousel.rs b/src/app/widgets/base/carousel.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/app/widgets/base/carousel.rs
diff --git a/src/app/widgets/base/mod.rs b/src/app/widgets/base/mod.rs
index 2a833b77..7176c1cc 100644
--- a/src/app/widgets/base/mod.rs
+++ b/src/app/widgets/base/mod.rs
@@ -1,4 +1,4 @@
-//! A collection of basic widgets.
+//! A collection of basic components.
pub mod text_table;
pub use text_table::TextTable;
diff --git a/src/app/widgets/base/scrollable.rs b/src/app/widgets/base/scrollable.rs
index 675dc558..4606b02b 100644
--- a/src/app/widgets/base/scrollable.rs
+++ b/src/app/widgets/base/scrollable.rs
@@ -1,11 +1,9 @@
-use std::time::Duration;
-
use crossterm::event::{KeyEvent, KeyModifiers, MouseButton, MouseEvent};
use tui::{layout::Rect, widgets::TableState};
use crate::app::{
event::{EventResult, MultiKey, MultiKeyResult},
- Widget,
+ Component,
};
pub enum ScrollDirection {
@@ -36,7 +34,7 @@ impl Scrollable {
scroll_direction: ScrollDirection::Down,
num_items,
tui_state: TableState::default(),
- gg_manager: MultiKey::register(vec!['g', 'g'], Duration::from_millis(400)),
+ gg_manager: MultiKey::register(vec!['g', 'g']), // TODO: Use a static arrayvec
bounds: Rect::default(),
}
}
@@ -79,7 +77,7 @@ impl Scrollable {
EventResult::Redraw
} else {
- EventResult::Continue
+ EventResult::NoRedraw
}
}
@@ -90,7 +88,7 @@ impl Scrollable {
EventResult::Redraw
} else {
- EventResult::Continue
+ EventResult::NoRedraw
}
}
@@ -104,7 +102,7 @@ impl Scrollable {
EventResult::Redraw
} else {
- EventResult::Continue
+ EventResult::NoRedraw
}
} else {
self.update_index(new_index);
@@ -121,18 +119,28 @@ impl Scrollable {
EventResult::Redraw
} else {
- EventResult::Continue
+ EventResult::NoRedraw
}
} else {
self.update_index(new_index);
EventResult::Redraw
}
}
-}
-impl Widget for Scrollable {
- type UpdateData = usize;
+ pub fn update_num_items(&mut self, num_items: usize) {
+ self.num_items = num_items;
+
+ if num_items <= self.current_index {
+ self.current_index = num_items - 1;
+ }
+
+ if num_items <= self.previous_index {
+ self.previous_index = num_items - 1;
+ }
+ }
+}
+impl Component for Scrollable {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
use crossterm::event::KeyCode::{Char, Down, Up};
@@ -144,14 +152,14 @@ impl Widget for Scrollable {
Char('k') => self.move_up(1),
Char('g') => match self.gg_manager.input('g') {
MultiKeyResult::Completed => self.skip_to_first(),
- MultiKeyResult::Accepted => EventResult::Continue,
- MultiKeyResult::Rejected => EventResult::Continue,
+ MultiKeyResult::Accepted => EventResult::NoRedraw,
+ MultiKeyResult::Rejected => EventResult::NoRedraw,
},
Char('G') => self.skip_to_last(),
- _ => EventResult::Continue,
+ _ => EventResult::NoRedraw,
}
} else {
- EventResult::Continue
+ EventResult::NoRedraw
}
}
@@ -176,23 +184,11 @@ impl Widget for Scrollable {
}
}
- EventResult::Continue
+ EventResult::NoRedraw
}
crossterm::event::MouseEventKind::ScrollDown => self.move_down(1),
crossterm::event::MouseEventKind::ScrollUp => self.move_up(1),
- _ => EventResult::Continue,
- }
- }
-
- fn update(&mut self, new_num_items: usize) {
- self.num_items = new_num_items;
-
- if new_num_items <= self.current_index {
- self.current_index = new_num_items - 1;
- }
-
- if new_num_items <= self.previous_index {
- self.previous_index = new_num_items - 1;
+ _ => EventResult::NoRedraw,
}
}
diff --git a/src/app/widgets/base/text_input.rs b/src/app/widgets/base/text_input.rs
index 2f9e648e..432c04b9 100644
--- a/src/app/widgets/base/text_input.rs
+++ b/src/app/widgets/base/text_input.rs
@@ -1 +1,138 @@
-pub struct TextInput {}
+use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEvent};
+use tui::layout::Rect;
+
+use crate::app::{
+ event::EventResult::{self},
+ Component,
+};
+
+#[derive(Default)]
+/// A single-line component for taking text inputs.
+pub struct TextInput {
+ text: String,
+ cursor_index: usize,
+ bounds: Rect,
+}
+
+impl TextInput {
+ /// Creates a new [`TextInput`].
+ pub fn new() -> Self {
+ Self {
+ ..Default::default()
+ }
+ }
+
+ fn set_cursor(&mut self, new_cursor_index: usize) -> EventResult {
+ if self.cursor_index == new_cursor_index {
+ EventResult::NoRedraw
+ } else {
+ self.cursor_index = new_cursor_index;
+ EventResult::Redraw
+ }
+ }
+
+ fn move_back(&mut self, amount_to_subtract: usize) -> EventResult {
+ self.set_cursor(self.cursor_index.saturating_sub(amount_to_subtract))
+ }
+
+ fn move_forward(&mut self, amount_to_add: usize) -> EventResult {
+ let new_cursor = self.cursor_index + amount_to_add;
+ if new_cursor >= self.text.len() {
+ self.set_cursor(self.text.len() - 1)
+ } else {
+ self.set_cursor(new_cursor)
+ }
+ }
+
+ fn clear_text(&mut self) -> EventResult {
+ if self.text.is_empty() {
+ EventResult::NoRedraw
+ } else {
+ self.text = String::default();
+ self.cursor_index = 0;
+ EventResult::Redraw
+ }
+ }
+
+ fn move_word_forward(&mut self) -> EventResult {
+ // TODO: Implement this
+ EventResult::NoRedraw
+ }
+
+ fn move_word_back(&mut self) -> EventResult {
+ // TODO: Implement this
+ EventResult::NoRedraw
+ }
+
+ fn clear_previous_word(&mut self) -> EventResult {
+ // TODO: Implement this
+ EventResult::NoRedraw
+ }
+
+ fn clear_previous_grapheme(&mut self) -> EventResult {
+ // TODO: Implement this
+ EventResult::NoRedraw
+ }
+
+ pub fn update(&mut self, new_text: String) {
+ self.text = new_text;
+
+ if self.cursor_index >= self.text.len() {
+ self.cursor_index = self.text.len() - 1;
+ }
+ }
+}
+
+impl Component for TextInput {
+ fn bounds(&self) -> Rect {
+ self.bounds
+ }
+
+ fn set_bounds(&mut self, new_bounds: Rect) {
+ self.bounds = new_bounds;
+ }
+
+ fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
+ if event.modifiers.is_empty() {
+ match event.code {
+ KeyCode::Left => self.move_back(1),
+ KeyCode::Right => self.move_forward(1),
+ KeyCode::Backspace => self.clear_previous_grapheme(),
+ _ => EventResult::NoRedraw,
+ }
+ } else if let KeyModifiers::CONTROL = event.modifiers {
+ match event.code {
+ KeyCode::Char('a') => self.set_cursor(0),
+ KeyCode::Char('e') => self.set_cursor(self.text.len()),
+ KeyCode::Char('u') => self.clear_text(),
+ KeyCode::Char('w') => self.clear_previous_word(),
+ KeyCode::Char('h') => self.clear_previous_grapheme(),
+ _ => EventResult::NoRedraw,
+ }
+ } else if let KeyModifiers::ALT = event.modifiers {
+ match event.code {
+ KeyCode::Char('b') => self.move_word_forward(),
+ KeyCode::Char('f') => self.move_word_back(),
+ _ => EventResult::NoRedraw,
+ }
+ } else {
+ EventResult::NoRedraw
+ }
+ }
+
+ fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
+ // We are assuming this is within bounds...
+
+ let x = event.column;
+ let widget_x = self.bounds.x;
+ let new_cursor_index = usize::from(x.saturating_sub(widget_x));
+
+ if new_cursor_index >= self.text.len() {
+ self.cursor_index = self.text.len() - 1;
+ } else {
+ self.cursor_index = new_cursor_index;
+ }
+
+ EventResult::Redraw
+ }
+}
diff --git a/src/app/widgets/base/text_table.rs b/src/app/widgets/base/text_table.rs
index 3e113568..6d6088bc 100644
--- a/src/app/widgets/base/text_table.rs
+++ b/src/app/widgets/base/text_table.rs
@@ -1,24 +1,32 @@
use crossterm::event::{KeyEvent, MouseEvent};
use tui::layout::Rect;
-use crate::app::{event::EventResult, Scrollable, Widget};
+use crate::app::{event::EventResult, Component, Scrollable};
-struct Column {
- name: &'static str,
+/// A [`Column`] represents some column in a [`TextTable`].
+pub struct Column {
+ pub name: &'static str,
+ pub shortcut: Option<KeyEvent>,
+ pub default_descending: bool,
// TODO: I would remove these in the future, storing them here feels weird...
- desired_column_width: u16,
- calculated_column_width: u16,
-
- x_bounds: (u16, u16),
+ pub desired_column_width: u16,
+ pub calculated_column_width: u16,
+ pub x_bounds: (u16, u16),
}
-impl Column {}
-
-/// The [`Widget::UpdateState`] of a [`TextTable`].
-pub struct TextTableUpdateData {
- num_items: Option<usize>,
- columns: Option<Vec<Column>>,
+impl Column {
+ /// Creates a new [`Column`], given a name and optional shortcut.
+ pub fn new(name: &'static str, shortcut: Option<KeyEvent>, default_descending: bool) -> Self {
+ Self {
+ name,
+ desired_column_width: 0,
+ calculated_column_width: 0,
+ x_bounds: (0, 0),
+ shortcut,
+ default_descending,
+ }
+ }
}
/// A sortable, scrollable table with columns.
@@ -37,24 +45,30 @@ pub struct TextTable {
/// Which index we're sorting by.
sort_index: usize,
+
+ /// Whether we're sorting by ascending order.
+ sort_ascending: bool,
}
impl TextTable {
- pub fn new(num_items: usize, columns: Vec<&'static str>) -> Self {
+ pub fn new(num_items: usize, columns: Vec<(&'static str, Option<KeyEvent>, bool)>) -> Self {
Self {
scrollable: Scrollable::new(num_items),
columns: columns
.into_iter()
- .map(|name| Column {
+ .map(|(name, shortcut, default_descending)| Column {
name,
desired_column_width: 0,
calculated_column_width: 0,
x_bounds: (0, 0),
+ shortcut,
+ default_descending,
})
.collect(),
show_gap: true,
bounds: Rect::default(),
sort_index: 0,
+ sort_ascending: true,
}
}
@@ -89,12 +103,42 @@ impl TextTable {
pub fn column_names(&self) -> Vec<&'static str> {
self.columns.iter().map(|column| column.name).collect()
}
-}
-impl Widget for TextTable {
- type UpdateData = TextTableUpdateData;
+ pub fn update_num_items(&mut self, num_items: usize) {
+ self.scrollable.update_num_items(num_items);
+ }
+
+ pub fn update_a_column(&mut self, index: usize, column: Column) {
+ if let Some(c) = self.columns.get_mut(index) {
+ *c = column;
+ }
+ }
+ pub fn update_columns(&mut self, columns: Vec<Column>) {
+ self.columns = columns;
+ if self.columns.len() <= self.sort_index {
+ self.sort_index = self.columns.len() - 1;
+ }
+ }
+}
+
+impl Component for TextTable {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
+ for (index, column) in self.columns.iter().enumerate() {
+ if let Some(shortcut) = column.shortcut {
+ if shortcut == event {
+ if self.sort_index == index {
+ // Just flip the sort if we're already sorting by this.
+ self.sort_ascending = !self.sort_ascending;
+ } else {
+ self.sort_index = index;
+ self.sort_ascending = !column.default_descending;
+ }
+ return EventResult::Redraw;
+ }
+ }
+ }
+
self.scrollable.handle_key_event(event)
}
@@ -107,29 +151,22 @@ impl Widget for TextTable {
for (index, column) in self.columns.iter().enumerate() {
let (start, end) = column.x_bounds;
if start >= x && end <= y {
- self.sort_index = index;
+ if self.sort_index == index {
+ // Just flip the sort if we're already sorting by this.
+ self.sort_ascending = !self.sort_ascending;
+ } else {
+ self.sort_index = index;
+ self.sort_ascending = !column.default_descending;
+ }
}
}
- EventResult::Continue
+ EventResult::NoRedraw
} else {
self.scrollable.handle_mouse_event(event)
}
}
- fn update(&mut self, update_data: Self::UpdateData) {
- if let Some(num_items) = update_data.num_items {
- self.scrollable.update(num_items);
- }
-
- if let Some(columns) = update_data.columns {
- self.columns = columns;
- if self.columns.len() <= self.sort_index {
- self.sort_index = self.columns.len() - 1;
- }
- }
- }
-
fn bounds(&self) -> Rect {
self.bounds
}
diff --git a/src/app/widgets/base/time_graph.rs b/src/app/widgets/base/time_graph.rs
index 26adfcb4..3c19bb0a 100644
--- a/src/app/widgets/base/time_graph.rs
+++ b/src/app/widgets/base/time_graph.rs
@@ -3,7 +3,7 @@ use std::time::{Duration, Instant};
use crossterm::event::{KeyEvent, KeyModifiers, MouseEvent};
use tui::layout::Rect;
-use crate::app::{event::EventResult, Widget};
+use crate::app::{event::EventResult, Component};
#[derive(Clone)]
pub enum AutohideTimerState {
@@ -23,7 +23,9 @@ pub enum AutohideTimer {
impl AutohideTimer {
fn trigger_display_timer(&mut self) {
match self {
- AutohideTimer::Disabled => todo!(),
+ AutohideTimer::Disabled => {
+ // Does nothing.
+ }
AutohideTimer::Enabled {
state,
show_duration: _,
@@ -35,7 +37,9 @@ impl AutohideTimer {
pub fn update_display_timer(&mut self) {
match self {
- AutohideTimer::Disabled => {}
+ AutohideTimer::Disabled => {
+ // Does nothing.
+ }
AutohideTimer::Enabled {
state,
show_duration,
@@ -87,7 +91,7 @@ impl TimeGraph {
'-' => self.zoom_out(),
'+' => self.zoom_in(),
'=' => self.reset_zoom(),
- _ => EventResult::Continue,
+ _ => EventResult::NoRedraw,
}
}
@@ -105,7 +109,7 @@ impl TimeGraph {
EventResult::Redraw
} else {
- EventResult::Continue
+ EventResult::NoRedraw
}
}
@@ -123,13 +127,13 @@ impl TimeGraph {
EventResult::Redraw
} else {
- EventResult::Continue
+ EventResult::NoRedraw
}
}
fn reset_zoom(&mut self) -> EventResult {
if self.current_display_time == self.default_time_value {
- EventResult::Continue
+ EventResult::NoRedraw
} else {
self.current_display_time = self.default_time_value;
self.autohide_timer.trigger_display_timer();
@@ -138,19 +142,17 @@ impl TimeGraph {
}
}
-impl Widget for TimeGraph {
- type UpdateData = ();
-
+impl Component for TimeGraph {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
use crossterm::event::KeyCode::Char;
if event.modifiers == KeyModifiers::NONE || event.modifiers == KeyModifiers::SHIFT {
match event.code {
Char(c) => self.handle_char(c),
- _ => EventResult::Continue,
+ _ => EventResult::NoRedraw,
}
} else {
- EventResult::Continue
+ EventResult::NoRedraw
}
}
@@ -158,7 +160,7 @@ impl Widget for TimeGraph {
match event.kind {
crossterm::event::MouseEventKind::ScrollDown => self.zoom_out(),
crossterm::event::MouseEventKind::ScrollUp => self.zoom_in(),
- _ => EventResult::Continue,
+ _ => EventResult::NoRedraw,
}
}
diff --git a/src/app/widgets/basic_cpu.rs b/src/app/widgets/basic_cpu.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/app/widgets/basic_cpu.rs
diff --git a/src/app/widgets/basic_mem.rs b/src/app/widgets/basic_mem.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/app/widgets/basic_mem.rs
diff --git a/src/app/widgets/basic_net.rs b/src/app/widgets/basic_net.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/app/widgets/basic_net.rs
diff --git a/src/app/widgets/battery.rs b/src/app/widgets/battery.rs
index 62f27d93..64236163 100644
--- a/src/app/widgets/battery.rs
+++ b/src/app/widgets/battery.rs
@@ -1,5 +1,9 @@
use std::collections::HashMap;
+use tui::layout::Rect;
+
+use super::{Component, Widget};
+
#[derive(Default)]
pub struct BatteryWidgetState {
pub currently_selected_battery_index: usize,
@@ -23,3 +27,30 @@ impl BatteryState {
self.widget_states.get(&widget_id)
}
}
+
+// TODO: Implement battery widget.
+/// A table displaying battery information on a per-battery basis.
+pub struct BatteryTable {
+ bounds: Rect,
+}
+
+impl BatteryTable {
+ /// Creates a new [`BatteryTable`].
+ pub fn new() -> Self {
+ Self {
+ bounds: Rect::default(),
+ }
+ }
+}
+
+impl Component for BatteryTable {
+ fn bounds(&self) -> tui::layout::Rect {
+ self.bounds
+ }
+
+ fn set_bounds(&mut self, new_bounds: tui::layout::Rect) {
+ self.bounds = new_bounds;
+ }
+}
+
+impl Widget for BatteryTable {}
diff --git a/src/app/widgets/cpu.rs b/src/app/widgets/cpu.rs
index 48c97dbc..ceb5e0d5 100644
--- a/src/app/widgets/cpu.rs
+++ b/src/app/widgets/cpu.rs
@@ -6,8 +6,8 @@ use tui::layout::Rect;
use crate::app::event::EventResult;
use super::{
- does_point_intersect_rect, text_table::TextTableUpdateData, AppScrollWidgetState,
- CanvasTableWidthState, TextTable, TimeGraph, Widget,
+ does_point_intersect_rect, AppScrollWidgetState, CanvasTableWidthState, Component, TextTable,
+ TimeGraph, Widget,
};
pub struct CpuWidgetState {
@@ -66,10 +66,6 @@ pub enum CpuGraphLegendPosition {
Right,
}
-pub struct CpuGraphUpdateData {
- pub legend_data: Option<TextTableUpdateData>,
-}
-
/// A widget designed to show CPU usage via a graph, along with a side legend implemented as a [`TextTable`].
pub struct CpuGraph {
graph: TimeGraph,
@@ -95,21 +91,16 @@ impl CpuGraph {
}
}
-impl Widget for CpuGraph {
- type UpdateData = CpuGraphUpdateData;
-
+impl Component for CpuGraph {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
match self.selected {
CpuGraphSelection::Graph => self.graph.handle_key_event(event),
CpuGraphSelection::Legend => self.legend.handle_key_event(event),
- CpuGraphSelection::None => EventResult::Continue,
+ CpuGraphSelection::None => EventResult::NoRedraw,
}
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
- // Check where we clicked (and switch the selected field if required) and fire the handler from there.
- // Note we assume that the
-
let global_x = event.column;
let global_y = event.row;
@@ -120,13 +111,7 @@ impl Widget for CpuGraph {
self.selected = CpuGraphSelection::Legend;
self.legend.handle_mouse_event(event)
} else {
- EventResult::Continue
- }
- }
-
- fn update(&mut self, update_data: Self::UpdateData) {
- if let Some(legend_data) = update_data.legend_data {
- self.legend.update(legend_data);
+ EventResult::NoRedraw
}
}
@@ -138,3 +123,5 @@ impl Widget for CpuGraph {
self.bounds = new_bounds;
}
}
+
+impl Widget for CpuGraph {}
diff --git a/src/app/widgets/disk.rs b/src/app/widgets/disk.rs
index 9142dac0..7ae70229 100644
--- a/src/app/widgets/disk.rs
+++ b/src/app/widgets/disk.rs
@@ -5,10 +5,7 @@ use tui::layout::Rect;
use crate::app::event::EventResult;
-use super::{
- text_table::TextTableUpdateData, AppScrollWidgetState, CanvasTableWidthState, TextTable,
- Widget,
-};
+use super::{AppScrollWidgetState, CanvasTableWidthState, Component, TextTable, Widget};
pub struct DiskWidgetState {
pub scroll_state: AppScrollWidgetState,
@@ -58,9 +55,7 @@ impl DiskTable {
}
}
-impl Widget for DiskTable {
- type UpdateData = TextTableUpdateData;
-
+impl Component for DiskTable {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
self.table.handle_key_event(event)
}
@@ -69,10 +64,6 @@ impl Widget for DiskTable {
self.table.handle_mouse_event(event)
}
- fn update(&mut self, update_data: Self::UpdateData) {
- self.table.update(update_data);
- }
-
fn bounds(&self) -> Rect {
self.bounds
}
@@ -81,3 +72,5 @@ impl Widget for DiskTable {
self.bounds = new_bounds;
}
}
+
+impl Widget for DiskTable {}
diff --git a/src/app/widgets/mem.rs b/src/app/widgets/mem.rs
index 9409b94c..a11d48a0 100644
--- a/src/app/widgets/mem.rs
+++ b/src/app/widgets/mem.rs
@@ -5,7 +5,7 @@ use tui::layout::Rect;
use crate::app::event::EventResult;
-use super::{TimeGraph, Widget};
+use super::{Component, TimeGraph, Widget};
pub struct MemWidgetState {
pub current_display_time: u64,
@@ -56,9 +56,7 @@ impl MemGraph {
}
}
-impl Widget for MemGraph {
- type UpdateData = ();
-
+impl Component for MemGraph {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
self.graph.handle_key_event(event)
}
@@ -75,3 +73,5 @@ impl Widget for MemGraph {
self.graph.set_bounds(new_bounds);
}
}
+
+impl Widget for MemGraph {}
diff --git a/src/app/widgets/mod.rs b/src/app/widgets/mod.rs
index e7f63b45..a80aa5dc 100644
--- a/src/app/widgets/mod.rs
+++ b/src/app/widgets/mod.rs
@@ -2,10 +2,14 @@ use std::time::Instant;
use crossterm::event::{KeyEvent, MouseEvent};
use enum_dispatch::enum_dispatch;
+use indextree::{Arena, NodeId};
use tui::{layout::Rect, widgets::TableState};
use crate::{
- app::{event::EventResult, layout_manager::BottomWidgetType},
+ app::{
+ event::{EventResult, SelectionAction},
+ layout_manager::BottomWidgetType,
+ },
constants,
};
@@ -33,37 +37,65 @@ pub use self::battery::*;
pub mod temp;
pub use temp::*;
+/// A trait for things that are drawn with state.
#[enum_dispatch]
#[allow(unused_variables)]
-pub trait Widget {
- type UpdateData;
-
+pub trait Component {
/// Handles a [`KeyEvent`].
///
- /// Defaults to returning [`EventResult::Continue`], indicating nothing should be done.
+ /// Defaults to returning [`EventResult::NoRedraw`], indicating nothing should be done.
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
- EventResult::Continue
+ EventResult::NoRedraw
}
/// Handles a [`MouseEvent