refactor: change up event handling logistics

Slightly move around the ideas of EventResult, ReturnSignalResult,
and how they all work.

The gist of it is that we now have widgets returning EventResults (and
renamed to WidgetEventResult), and the main app event handler returns
ReturnSignalResult (now named EventResult).

Also add a new signal to handle re-updating data inputs! This is needed
for the process, and any sortable/configurable widget.
This commit is contained in:
ClementTsang 2021-08-29 19:33:47 -04:00
parent 1ec203caa2
commit 48c572dbaf
22 changed files with 367 additions and 293 deletions

View File

@ -33,7 +33,7 @@ use crate::{
BottomEvent, Pid,
};
use self::event::{EventResult, ReturnSignal, ReturnSignalResult};
use self::event::{EventResult, ReturnSignal, WidgetEventResult};
const MAX_SEARCH_LENGTH: usize = 200;
@ -302,6 +302,26 @@ impl AppState {
}
}
/// Quick and dirty handler to convert [`WidgetEventResult`]s to [`EventResult`]s, and handle [`ReturnSignal`]s.
fn convert_widget_event_result(&mut self, w: WidgetEventResult) -> EventResult {
match w {
WidgetEventResult::Quit => EventResult::Quit,
WidgetEventResult::Redraw => EventResult::Redraw,
WidgetEventResult::NoRedraw => EventResult::NoRedraw,
WidgetEventResult::Signal(signal) => match signal {
ReturnSignal::KillProcess => {
todo!()
}
ReturnSignal::Update => {
if let Some(widget) = self.widget_lookup_map.get_mut(&self.selected_widget) {
widget.update_data(&self.data_collection);
}
EventResult::Redraw
}
},
}
}
/// Handles a [`BottomEvent`] and updates the [`AppState`] if needed. Returns an [`EventResult`] indicating
/// whether the app now requires a redraw.
pub fn handle_event(&mut self, event: BottomEvent) -> EventResult {
@ -312,7 +332,8 @@ impl AppState {
event_result
} else if let Some(widget) = self.widget_lookup_map.get_mut(&self.selected_widget) {
// If it isn't, send it to the current widget!
widget.handle_key_event(event)
let result = widget.handle_key_event(event);
self.convert_widget_event_result(result)
} else {
EventResult::NoRedraw
}
@ -327,7 +348,8 @@ impl AppState {
if let Some(widget) =
self.widget_lookup_map.get_mut(&self.selected_widget)
{
return widget.handle_mouse_event(event);
let result = widget.handle_mouse_event(event);
return self.convert_widget_event_result(result);
}
} else {
for (id, widget) in self.widget_lookup_map.iter_mut() {
@ -336,10 +358,12 @@ impl AppState {
self.selected_widget = *id;
if is_id_selected {
return widget.handle_mouse_event(event);
let result = widget.handle_mouse_event(event);
return self.convert_widget_event_result(result);
} else {
// If the aren't equal, *force* a redraw.
widget.handle_mouse_event(event);
let result = widget.handle_mouse_event(event);
let _ = self.convert_widget_event_result(result);
return EventResult::Redraw;
}
}
@ -349,7 +373,8 @@ impl AppState {
MouseEventKind::ScrollDown | MouseEventKind::ScrollUp => {
if let Some(widget) = self.widget_lookup_map.get_mut(&self.selected_widget)
{
return widget.handle_mouse_event(event);
let result = widget.handle_mouse_event(event);
return self.convert_widget_event_result(result);
}
}
_ => {}
@ -383,15 +408,6 @@ impl AppState {
}
}
/// Handles a [`ReturnSignal`], and returns an [`ReturnSignalResult`].
pub fn handle_return_signal(&mut self, return_signal: ReturnSignal) -> ReturnSignalResult {
match return_signal {
ReturnSignal::KillProcess => {
todo!()
}
}
}
pub fn on_esc(&mut self) {
self.reset_multi_tap_keys();
if self.is_in_dialog() {

View File

@ -14,7 +14,7 @@
/// more points as this is used!
use once_cell::sync::Lazy;
use std::{cell::RefCell, collections::HashMap, time::Instant, vec::Vec};
use std::{collections::HashMap, time::Instant, vec::Vec};
use crate::{
data_harvester::{batteries, cpu, disks, memory, network, processes, temperature, Data},
@ -23,8 +23,6 @@ use crate::{
};
use regex::Regex;
use super::data_harvester::processes::UserTable;
pub type TimeOffset = f64;
pub type Value = f64;
@ -65,8 +63,6 @@ pub struct DataCollection {
pub io_labels: Vec<(String, String)>,
pub temp_harvest: Vec<temperature::TempHarvest>,
pub battery_harvest: Vec<batteries::BatteryHarvest>,
#[cfg(target_family = "unix")]
pub user_table: RefCell<UserTable>,
}
impl Default for DataCollection {
@ -88,8 +84,6 @@ impl Default for DataCollection {
io_labels: Vec::default(),
temp_harvest: Vec::default(),
battery_harvest: Vec::default(),
#[cfg(target_family = "unix")]
user_table: RefCell::new(UserTable::default()),
}
}
}
@ -107,10 +101,6 @@ impl DataCollection {
self.io_labels_and_prev = Vec::default();
self.temp_harvest = Vec::default();
self.battery_harvest = Vec::default();
#[cfg(target_family = "unix")]
{
*self.user_table.borrow_mut() = UserTable::default();
}
}
pub fn set_frozen_time(&mut self) {

View File

@ -96,6 +96,9 @@ pub struct DataCollector {
battery_manager: Option<Manager>,
battery_list: Option<Vec<Battery>>,
filters: DataFilters,
#[cfg(target_family = "unix")]
user_table: self::processes::UserTable,
}
impl DataCollector {
@ -123,6 +126,8 @@ impl DataCollector {
battery_manager: None,
battery_list: None,
filters,
#[cfg(target_family = "unix")]
user_table: Default::default(),
}
}
@ -253,9 +258,19 @@ impl DataCollector {
.duration_since(self.last_collection_time)
.as_secs(),
self.mem_total_kb,
&mut self.user_table,
)
}
#[cfg(not(target_os = "linux"))]
#[cfg(target_os = "macos")]
{
processes::get_process_data(
&self.sys,
self.use_current_cpu_total,
self.mem_total_kb,
&mut self.user_table,
)
}
#[cfg(target_os = "windows")]
{
processes::get_process_data(
&self.sys,

View File

@ -23,6 +23,8 @@ cfg_if::cfg_if! {
}
}
use std::borrow::Cow;
use crate::Pid;
// TODO: Add value so we know if it's sorted ascending or descending by default?
@ -93,5 +95,8 @@ pub struct ProcessHarvest {
/// This is the *effective* user ID.
#[cfg(target_family = "unix")]
pub uid: Option<libc::uid_t>,
pub uid: libc::uid_t,
#[cfg(target_family = "unix")]
pub user: Cow<'static, str>,
}

View File

@ -5,7 +5,7 @@ use std::collections::hash_map::Entry;
use crate::utils::error::{self, BottomError};
use crate::Pid;
use super::ProcessHarvest;
use super::{ProcessHarvest, UserTable};
use sysinfo::ProcessStatus;
@ -117,6 +117,7 @@ fn get_linux_cpu_usage(
fn read_proc(
prev_proc: &PrevProcDetails, stat: &Stat, cpu_usage: f64, cpu_fraction: f64,
use_current_cpu_total: bool, time_difference_in_secs: u64, mem_total_kb: u64,
user_table: &mut UserTable,
) -> error::Result<(ProcessHarvest, u64)> {
use std::convert::TryFrom;
@ -196,7 +197,7 @@ fn read_proc(
(0, 0, 0, 0)
};
let uid = Some(process.owner);
let uid = process.owner;
Ok((
ProcessHarvest {
@ -214,6 +215,10 @@ fn read_proc(
process_state,
process_state_char,
uid,
user: user_table
.get_uid_to_username_mapping(uid)
.map(Into::into)
.unwrap_or("N/A".into()),
},
new_process_times,
))
@ -222,7 +227,7 @@ fn read_proc(
pub fn get_process_data(
prev_idle: &mut f64, prev_non_idle: &mut f64,
pid_mapping: &mut FxHashMap<Pid, PrevProcDetails>, use_current_cpu_total: bool,
time_difference_in_secs: u64, mem_total_kb: u64,
time_difference_in_secs: u64, mem_total_kb: u64, user_table: &mut UserTable,
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
// TODO: [PROC THREADS] Add threads
@ -265,6 +270,7 @@ pub fn get_process_data(
use_current_cpu_total,
time_difference_in_secs,
mem_total_kb,
user_table,
) {
prev_proc_details.cpu_time = new_process_times;
prev_proc_details.total_read_bytes =

View File

@ -1,6 +1,6 @@
//! Process data collection for macOS. Uses sysinfo.
use super::ProcessHarvest;
use super::{ProcessHarvest, UserTable};
use sysinfo::{ProcessExt, ProcessStatus, ProcessorExt, System, SystemExt};
fn get_macos_process_cpu_usage(
@ -35,7 +35,7 @@ fn get_macos_process_cpu_usage(
}
pub fn get_process_data(
sys: &System, use_current_cpu_total: bool, mem_total_kb: u64,
sys: &System, use_current_cpu_total: bool, mem_total_kb: u64, user_table: &mut UserTable,
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
let mut process_vector: Vec<ProcessHarvest> = Vec::new();
let process_hashmap = sys.get_processes();
@ -104,7 +104,11 @@ pub fn get_process_data(
total_write_bytes: disk_usage.total_written_bytes,
process_state: process_val.status().to_string(),
process_state_char: convert_process_status_to_char(process_val.status()),
uid: Some(process_val.uid),
uid: process_val.uid,
user: user_table
.get_uid_to_username_mapping(uid)
.map(Into::into)
.unwrap_or("N/A".into()),
});
}

View File

@ -2,15 +2,23 @@ use std::time::{Duration, Instant};
const MAX_TIMEOUT: Duration = Duration::from_millis(400);
/// These are "signals" that are sent along with an [`EventResult`] to signify a potential additional action
/// These are "signals" that are sent along with an [`WidgetEventResult`] to signify a potential additional action
/// that the caller must do, along with the "core" result of either drawing or redrawing.
pub enum ReturnSignal {
/// A signal returned when some process widget was told to try to kill a process (or group of processes).
///
/// This return signal should trigger a redraw when handled.
KillProcess,
/// A signal returned when a widget needs the app state to re-trigger its update call. Usually needed for
/// widgets where the displayed contents are built only on update.
///
/// This return signal should trigger a redraw when handled.
Update,
}
/// The results of handling a [`ReturnSignal`].
pub enum ReturnSignalResult {
/// The results of handling an event by the [`AppState`].
pub enum EventResult {
/// Kill the program.
Quit,
/// Trigger a redraw.
@ -19,9 +27,9 @@ pub enum ReturnSignalResult {
NoRedraw,
}
/// 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 {
/// The results of a widget handling some event, like a mouse or key event,
/// signifying what the program should then do next.
pub enum WidgetEventResult {
/// Kill the program.
Quit,
/// Trigger a redraw.

View File

@ -6,7 +6,7 @@ use tui::{backend::Backend, layout::Rect, widgets::TableState, Frame};
use crate::{
app::{
event::{EventResult, SelectionAction},
event::{WidgetEventResult, SelectionAction},
layout_manager::BottomWidgetType,
},
canvas::Painter,
@ -48,15 +48,15 @@ pub trait Component {
/// Handles a [`KeyEvent`].
///
/// Defaults to returning [`EventResult::NoRedraw`], indicating nothing should be done.
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
EventResult::NoRedraw
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
WidgetEventResult::NoRedraw
}
/// Handles a [`MouseEvent`].
///
/// Defaults to returning [`EventResult::Continue`], indicating nothing should be done.
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
EventResult::NoRedraw
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
WidgetEventResult::NoRedraw
}
/// Returns a [`Component`]'s bounding box. Note that these are defined in *global*, *absolute*

View File

@ -2,7 +2,7 @@ use crossterm::event::{KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEve
use tui::{layout::Rect, widgets::TableState};
use crate::app::{
event::{EventResult, MultiKey, MultiKeyResult},
event::{WidgetEventResult, MultiKey, MultiKeyResult},
Component,
};
@ -128,56 +128,56 @@ impl Scrollable {
}
}
fn skip_to_first(&mut self) -> EventResult {
fn skip_to_first(&mut self) -> WidgetEventResult {
if self.current_index != 0 {
self.update_index(0);
EventResult::Redraw
WidgetEventResult::Redraw
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}
fn skip_to_last(&mut self) -> EventResult {
fn skip_to_last(&mut self) -> WidgetEventResult {
let last_index = self.num_items - 1;
if self.current_index != last_index {
self.update_index(last_index);
EventResult::Redraw
WidgetEventResult::Redraw
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}
/// Moves *downward* by *incrementing* the current index.
fn move_down(&mut self, change_by: usize) -> EventResult {
fn move_down(&mut self, change_by: usize) -> WidgetEventResult {
if self.num_items == 0 {
return EventResult::NoRedraw;
return WidgetEventResult::NoRedraw;
}
let new_index = self.current_index + change_by;
if new_index >= self.num_items {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
} else if self.current_index == new_index {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
} else {
self.update_index(new_index);
EventResult::Redraw
WidgetEventResult::Redraw
}
}
/// Moves *upward* by *decrementing* the current index.
fn move_up(&mut self, change_by: usize) -> EventResult {
fn move_up(&mut self, change_by: usize) -> WidgetEventResult {
if self.num_items == 0 {
return EventResult::NoRedraw;
return WidgetEventResult::NoRedraw;
}
let new_index = self.current_index.saturating_sub(change_by);
if self.current_index == new_index {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
} else {
self.update_index(new_index);
EventResult::Redraw
WidgetEventResult::Redraw
}
}
@ -199,7 +199,7 @@ impl Scrollable {
}
impl Component for Scrollable {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
use crossterm::event::KeyCode::{Char, Down, Up};
if event.modifiers == KeyModifiers::NONE || event.modifiers == KeyModifiers::SHIFT {
@ -210,18 +210,18 @@ impl Component 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::NoRedraw,
MultiKeyResult::Rejected => EventResult::NoRedraw,
MultiKeyResult::Accepted => WidgetEventResult::NoRedraw,
MultiKeyResult::Rejected => WidgetEventResult::NoRedraw,
},
Char('G') => self.skip_to_last(),
_ => EventResult::NoRedraw,
_ => WidgetEventResult::NoRedraw,
}
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
match event.kind {
MouseEventKind::Down(MouseButton::Left) => {
if self.does_intersect_mouse(&event) {
@ -244,11 +244,11 @@ impl Component for Scrollable {
}
}
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
MouseEventKind::ScrollDown => self.move_down(1),
MouseEventKind::ScrollUp => self.move_up(1),
_ => EventResult::NoRedraw,
_ => WidgetEventResult::NoRedraw,
}
}

View File

@ -1,14 +1,13 @@
use std::borrow::Cow;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind};
use tui::{
backend::Backend,
layout::Rect,
widgets::{Block, Table, TableState},
};
use tui::{backend::Backend, layout::Rect, widgets::Block};
use crate::{
app::{event::EventResult, Component, TextTable},
app::{
event::{ReturnSignal, WidgetEventResult},
Component, TextTable,
},
canvas::Painter,
};
@ -243,6 +242,7 @@ impl<S> SortableTextTable<S>
where
S: SortableColumn,
{
/// Creates a new [`SortableTextTable`]. Note that `columns` cannot be empty.
pub fn new(columns: Vec<S>) -> Self {
let mut st = Self {
sort_index: 0,
@ -262,8 +262,13 @@ where
self
}
pub fn current_index(&self) -> usize {
self.table.current_index()
pub fn current_scroll_index(&self) -> usize {
self.table.current_scroll_index()
}
/// Returns the current column.
pub fn current_column(&self) -> &S {
&self.table.columns[self.sort_index]
}
pub fn columns(&self) -> &[S] {
@ -310,7 +315,7 @@ where
}
}
/// Draws a [`Table`] given the [`TextTable`] and the given data.
/// Draws a [`tui::widgets::Table`] on screen.
///
/// Note if the number of columns don't match in the [`TextTable`] and data,
/// it will only create as many columns as it can grab data from both sources from.
@ -327,12 +332,12 @@ impl<S> Component for SortableTextTable<S>
where
S: SortableColumn,
{
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
for (index, column) in self.table.columns.iter().enumerate() {
if let &Some((shortcut, _)) = column.shortcut() {
if shortcut == event {
self.set_sort_index(index);
return EventResult::Redraw;
return WidgetEventResult::Signal(ReturnSignal::Update);
}
}
}
@ -340,10 +345,10 @@ where
self.table.scrollable.handle_key_event(event)
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
if let MouseEventKind::Down(MouseButton::Left) = event.kind {
if !self.does_intersect_mouse(&event) {
return EventResult::NoRedraw;
return WidgetEventResult::NoRedraw;
}
// Note these are representing RELATIVE coordinates! They *need* the above intersection check for validity!
@ -355,7 +360,7 @@ where
if let Some((start, end)) = column.get_x_bounds() {
if x >= start && x <= end {
self.set_sort_index(index);
return EventResult::Redraw;
return WidgetEventResult::Signal(ReturnSignal::Update);
}
}
}

View File

@ -2,7 +2,7 @@ use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEvent};
use tui::layout::Rect;
use crate::app::{
event::EventResult::{self},
event::WidgetEventResult::{self},
Component,
};
@ -22,20 +22,20 @@ impl TextInput {
}
}
fn set_cursor(&mut self, new_cursor_index: usize) -> EventResult {
fn set_cursor(&mut self, new_cursor_index: usize) -> WidgetEventResult {
if self.cursor_index == new_cursor_index {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
} else {
self.cursor_index = new_cursor_index;
EventResult::Redraw
WidgetEventResult::Redraw
}
}
fn move_back(&mut self, amount_to_subtract: usize) -> EventResult {
fn move_back(&mut self, amount_to_subtract: usize) -> WidgetEventResult {
self.set_cursor(self.cursor_index.saturating_sub(amount_to_subtract))
}
fn move_forward(&mut self, amount_to_add: usize) -> EventResult {
fn move_forward(&mut self, amount_to_add: usize) -> WidgetEventResult {
let new_cursor = self.cursor_index + amount_to_add;
if new_cursor >= self.text.len() {
self.set_cursor(self.text.len() - 1)
@ -44,34 +44,34 @@ impl TextInput {
}
}
fn clear_text(&mut self) -> EventResult {
fn clear_text(&mut self) -> WidgetEventResult {
if self.text.is_empty() {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
} else {
self.text = String::default();
self.cursor_index = 0;
EventResult::Redraw
WidgetEventResult::Redraw
}
}
fn move_word_forward(&mut self) -> EventResult {
fn move_word_forward(&mut self) -> WidgetEventResult {
// TODO: Implement this
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
fn move_word_back(&mut self) -> EventResult {
fn move_word_back(&mut self) -> WidgetEventResult {
// TODO: Implement this
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
fn clear_previous_word(&mut self) -> EventResult {
fn clear_previous_word(&mut self) -> WidgetEventResult {
// TODO: Implement this
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
fn clear_previous_grapheme(&mut self) -> EventResult {
fn clear_previous_grapheme(&mut self) -> WidgetEventResult {
// TODO: Implement this
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
pub fn update(&mut self, new_text: String) {
@ -92,13 +92,13 @@ impl Component for TextInput {
self.bounds = new_bounds;
}
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
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,
_ => WidgetEventResult::NoRedraw,
}
} else if let KeyModifiers::CONTROL = event.modifiers {
match event.code {
@ -107,20 +107,20 @@ impl Component for TextInput {
KeyCode::Char('u') => self.clear_text(),
KeyCode::Char('w') => self.clear_previous_word(),
KeyCode::Char('h') => self.clear_previous_grapheme(),
_ => EventResult::NoRedraw,
_ => WidgetEventResult::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,
_ => WidgetEventResult::NoRedraw,
}
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
// We are assuming this is within bounds...
let x = event.column;
@ -133,6 +133,6 @@ impl Component for TextInput {
self.cursor_index = new_cursor_index;
}
EventResult::Redraw
WidgetEventResult::Redraw
}
}

View File

@ -15,7 +15,7 @@ use tui::{
use unicode_segmentation::UnicodeSegmentation;
use crate::{
app::{event::EventResult, Component, Scrollable},
app::{event::WidgetEventResult, Component, Scrollable},
canvas::Painter,
constants::TABLE_GAP_HEIGHT_LIMIT,
};
@ -186,7 +186,7 @@ where
}
}
pub fn current_index(&self) -> usize {
pub fn current_scroll_index(&self) -> usize {
self.scrollable.current_index()
}
@ -342,7 +342,7 @@ where
}
}
/// Draws a [`Table`] given the [`TextTable`] and the given data.
/// Draws a [`Table`] on screen..
///
/// Note if the number of columns don't match in the [`TextTable`] and data,
/// it will only create as many columns as it can grab data from both sources from.
@ -443,19 +443,19 @@ impl<C> Component for TextTable<C>
where
C: TableColumn,
{
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
if self.selectable {
self.scrollable.handle_key_event(event)
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
if self.selectable {
self.scrollable.handle_mouse_event(event)
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}

View File

@ -15,7 +15,7 @@ use tui::{
use crate::{
app::{
event::EventResult,
event::WidgetEventResult,
widgets::tui_widgets::{
custom_legend_chart::{Axis, Dataset},
TimeChart,
@ -155,58 +155,58 @@ impl TimeGraph {
}
/// Handles a char `c`.
fn handle_char(&mut self, c: char) -> EventResult {
fn handle_char(&mut self, c: char) -> WidgetEventResult {
match c {
'-' => self.zoom_out(),
'+' => self.zoom_in(),
'=' => self.reset_zoom(),
_ => EventResult::NoRedraw,
_ => WidgetEventResult::NoRedraw,
}
}
fn zoom_in(&mut self) -> EventResult {
fn zoom_in(&mut self) -> WidgetEventResult {
let new_time = self.current_display_time.saturating_sub(self.time_interval);
if new_time >= self.min_duration {
self.current_display_time = new_time;
self.autohide_timer.start_display_timer();
EventResult::Redraw
WidgetEventResult::Redraw
} else if new_time != self.min_duration {
self.current_display_time = self.min_duration;
self.autohide_timer.start_display_timer();
EventResult::Redraw
WidgetEventResult::Redraw
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}
fn zoom_out(&mut self) -> EventResult {
fn zoom_out(&mut self) -> WidgetEventResult {
let new_time = self.current_display_time + self.time_interval;
if new_time <= self.max_duration {
self.current_display_time = new_time;
self.autohide_timer.start_display_timer();
EventResult::Redraw
WidgetEventResult::Redraw
} else if new_time != self.max_duration {
self.current_display_time = self.max_duration;
self.autohide_timer.start_display_timer();
EventResult::Redraw
WidgetEventResult::Redraw
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}
fn reset_zoom(&mut self) -> EventResult {
fn reset_zoom(&mut self) -> WidgetEventResult {
if self.current_display_time == self.default_time_value {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
} else {
self.current_display_time = self.default_time_value;
self.autohide_timer.start_display_timer();
EventResult::Redraw
WidgetEventResult::Redraw
}
}
@ -296,24 +296,24 @@ impl TimeGraph {
}
impl Component for TimeGraph {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
use crossterm::event::KeyCode::Char;
if event.modifiers == KeyModifiers::NONE || event.modifiers == KeyModifiers::SHIFT {
match event.code {
Char(c) => self.handle_char(c),
_ => EventResult::NoRedraw,
_ => WidgetEventResult::NoRedraw,
}
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
match event.kind {
MouseEventKind::ScrollDown => self.zoom_out(),
MouseEventKind::ScrollUp => self.zoom_in(),
_ => EventResult::NoRedraw,
_ => WidgetEventResult::NoRedraw,
}
}

View File

@ -9,7 +9,7 @@ use tui::{
use crate::{
app::{
event::EventResult, sort_text_table::SimpleSortableColumn, time_graph::TimeGraphData,
event::WidgetEventResult, sort_text_table::SimpleSortableColumn, time_graph::TimeGraphData,
AppConfigFields, DataCollection,
},
canvas::Painter,
@ -120,22 +120,22 @@ impl CpuGraph {
}
impl Component for CpuGraph {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
match self.selected {
CpuGraphSelection::Graph => self.graph.handle_key_event(event),
CpuGraphSelection::Legend => self.legend.handle_key_event(event),
CpuGraphSelection::None => EventResult::NoRedraw,
CpuGraphSelection::None => WidgetEventResult::NoRedraw,
}
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
if self.graph.does_intersect_mouse(&event) {
if let CpuGraphSelection::Graph = self.selected {
self.graph.handle_mouse_event(event)
} else {
self.selected = CpuGraphSelection::Graph;
self.graph.handle_mouse_event(event);
EventResult::Redraw
WidgetEventResult::Redraw
}
} else if self.legend.does_intersect_mouse(&event) {
if let CpuGraphSelection::Legend = self.selected {
@ -143,10 +143,10 @@ impl Component for CpuGraph {
} else {
self.selected = CpuGraphSelection::Legend;
self.legend.handle_mouse_event(event);
EventResult::Redraw
WidgetEventResult::Redraw
}
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}
@ -184,7 +184,7 @@ impl Widget for CpuGraph {
const Y_BOUNDS: [f64; 2] = [0.0, 100.5];
let y_bound_labels: [Cow<'static, str>; 2] = ["0%".into(), "100%".into()];
let current_index = self.legend.current_index();
let current_index = self.legend.current_scroll_index();
let sliced_cpu_data = if current_index == 0 {
&self.display_data[..]
} else {
@ -301,6 +301,7 @@ impl Widget for CpuGraph {
}
fn update_data(&mut self, data_collection: &DataCollection) {
// TODO: *Maybe* look into only taking in enough data for the current retention? Though this isn't great, it means you have to be like process with the whole updating thing.
convert_cpu_data_points(data_collection, &mut self.display_data, false); // TODO: Again, the "is_frozen" is probably useless
self.load_avg_data = data_collection.load_avg_harvest;
}

View File

@ -9,7 +9,7 @@ use tui::{
};
use crate::{
app::{data_farmer::DataCollection, event::EventResult, sort_text_table::SimpleSortableColumn},
app::{data_farmer::DataCollection, event::WidgetEventResult, sort_text_table::SimpleSortableColumn},
canvas::Painter,
data_conversion::convert_disk_row,
};
@ -81,11 +81,11 @@ impl Default for DiskTable {
}
impl Component for DiskTable {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
self.table.handle_key_event(event)
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
self.table.handle_mouse_event(event)
}

View File

@ -8,7 +8,7 @@ use tui::{
};
use crate::{
app::{event::EventResult, time_graph::TimeGraphData, DataCollection},
app::{event::WidgetEventResult, time_graph::TimeGraphData, DataCollection},
data_conversion::{convert_mem_data_points, convert_mem_labels, convert_swap_data_points},
};
@ -75,11 +75,11 @@ impl MemGraph {
}
impl Component for MemGraph {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
self.graph.handle_key_event(event)
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
self.graph.handle_mouse_event(event)
}

View File

@ -523,13 +523,13 @@ impl Component for NetGraph {
fn handle_key_event(
&mut self, event: crossterm::event::KeyEvent,
) -> crate::app::event::EventResult {
) -> crate::app::event::WidgetEventResult {
self.graph.handle_key_event(event)
}
fn handle_mouse_event(
&mut self, event: crossterm::event::MouseEvent,
) -> crate::app::event::EventResult {
) -> crate::app::event::WidgetEventResult {
self.graph.handle_mouse_event(event)
}
}
@ -648,13 +648,13 @@ impl Component for OldNetGraph {
fn handle_key_event(
&mut self, event: crossterm::event::KeyEvent,
) -> crate::app::event::EventResult {
) -> crate::app::event::WidgetEventResult {
self.net_graph.handle_key_event(event)
}
fn handle_mouse_event(
&mut self, event: crossterm::event::MouseEvent,
) -> crate::app::event::EventResult {
) -> crate::app::event::WidgetEventResult {
self.net_graph.handle_mouse_event(event)
}
}

View File

@ -1,6 +1,8 @@
use std::collections::HashMap;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind};
use float_ord::FloatOrd;
use itertools::Itertools;
use unicode_segmentation::GraphemeCursor;
use tui::{
@ -12,20 +14,20 @@ use tui::{
use crate::{
app::{
event::{EventResult, MultiKey, MultiKeyResult},
data_harvester::processes::ProcessHarvest,
event::{MultiKey, MultiKeyResult, WidgetEventResult},
query::*,
DataCollection,
},
canvas::Painter,
data_conversion::{get_disk_io_strings, get_string_with_bytes},
data_conversion::get_string_with_bytes,
data_harvester::processes::{self, ProcessSorting},
options::ProcessDefaults,
utils::gen_util::{get_binary_bytes, GIBI_LIMIT},
};
use ProcessSorting::*;
use super::{
sort_text_table::{SimpleSortableColumn, SortableColumn},
sort_text_table::{SimpleSortableColumn, SortStatus, SortableColumn},
text_table::TextTableData,
AppScrollWidgetState, CanvasTableWidthState, Component, CursorDirection, ScrollDirection,
SortableTextTable, TextInput, TextTable, Widget,
@ -670,7 +672,7 @@ impl ProcessSortType {
ProcessSortType::Count => "Count",
ProcessSortType::Name => "Name",
ProcessSortType::Command => "Command",
ProcessSortType::Cpu => "Cpu",
ProcessSortType::Cpu => "CPU%",
ProcessSortType::Mem => "Mem",
ProcessSortType::MemPercent => "Mem%",
ProcessSortType::Rps => "R/s",
@ -708,7 +710,7 @@ impl ProcessSortType {
match self {
ProcessSortType::Pid => Hard(Some(7)),
ProcessSortType::Count => Hard(Some(8)),
ProcessSortType::Name => Flex(0.4),
ProcessSortType::Name => Flex(0.35),
ProcessSortType::Command => Flex(0.7),
ProcessSortType::Cpu => Hard(Some(8)),
ProcessSortType::Mem => Hard(Some(8)),
@ -717,8 +719,8 @@ impl ProcessSortType {
ProcessSortType::Wps => Hard(Some(8)),
ProcessSortType::TotalRead => Hard(Some(7)),
ProcessSortType::TotalWrite => Hard(Some(8)),
ProcessSortType::User => Flex(0.075),
ProcessSortType::State => Hard(Some(1)),
ProcessSortType::User => Flex(0.08),
ProcessSortType::State => Hard(Some(8)),
}
}
@ -891,23 +893,23 @@ impl ProcessManager {
self.in_tree_mode = in_tree_mode;
}
fn open_search(&mut self) -> EventResult {
fn open_search(&mut self) -> WidgetEventResult {
if let ProcessManagerSelection::Search = self.selected {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
} else {
self.show_search = true;
self.selected = ProcessManagerSelection::Search;
EventResult::Redraw
WidgetEventResult::Redraw
}
}
fn open_sort(&mut self) -> EventResult {
fn open_sort(&mut self) -> WidgetEventResult {
if let ProcessManagerSelection::Sort = self.selected {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
} else {
self.show_sort = true;
self.selected = ProcessManagerSelection::Sort;
EventResult::Redraw
WidgetEventResult::Redraw
}
}
@ -938,7 +940,7 @@ impl Component for ProcessManager {
self.bounds = new_bounds;
}
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
match self.selected {
ProcessManagerSelection::Processes => {
// Try to catch some stuff first...
@ -956,7 +958,7 @@ impl Component for ProcessManager {
// Kill the selected process(es)
}
MultiKeyResult::Accepted | MultiKeyResult::Rejected => {
return EventResult::NoRedraw;
return WidgetEventResult::NoRedraw;
}
}
}
@ -974,7 +976,7 @@ impl Component for ProcessManager {
}
KeyCode::Char('t') | KeyCode::F(5) => {
self.in_tree_mode = !self.in_tree_mode;
return EventResult::Redraw;
return WidgetEventResult::Redraw;
}
KeyCode::F(6) => {
return self.open_sort();
@ -1019,7 +1021,7 @@ impl Component for ProcessManager {
}
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
match &event.kind {
MouseEventKind::Down(MouseButton::Left) => {
if self.process_table.does_intersect_mouse(&event) {
@ -1027,8 +1029,13 @@ impl Component for ProcessManager {
self.process_table.handle_mouse_event(event)
} else {
self.selected = ProcessManagerSelection::Processes;
self.process_table.handle_mouse_event(event);
EventResult::Redraw
match self.process_table.handle_mouse_event(event) {
WidgetEventResult::Quit => WidgetEventResult::Quit,
WidgetEventResult::Redraw | WidgetEventResult::NoRedraw => {
WidgetEventResult::Redraw
}
WidgetEventResult::Signal(s) => WidgetEventResult::Signal(s),
}
}
} else if self.sort_table.does_intersect_mouse(&event) {
if let ProcessManagerSelection::Sort = self.selected {
@ -1036,7 +1043,7 @@ impl Component for ProcessManager {
} else {
self.selected = ProcessManagerSelection::Sort;
self.sort_table.handle_mouse_event(event);
EventResult::Redraw
WidgetEventResult::Redraw
}
} else if self.search_input.does_intersect_mouse(&event) {
if let ProcessManagerSelection::Search = self.selected {
@ -1044,10 +1051,10 @@ impl Component for ProcessManager {
} else {
self.selected = ProcessManagerSelection::Search;
self.search_input.handle_mouse_event(event);
EventResult::Redraw
WidgetEventResult::Redraw
}
} else {
EventResult::NoRedraw
WidgetEventResult::NoRedraw
}
}
MouseEventKind::ScrollDown | MouseEventKind::ScrollUp => match self.selected {
@ -1055,7 +1062,7 @@ impl Component for ProcessManager {
ProcessManagerSelection::Sort => self.sort_table.handle_mouse_event(event),
ProcessManagerSelection::Search => self.search_input.handle_mouse_event(event),
},
_ => EventResult::NoRedraw,
_ => WidgetEventResult::NoRedraw,
}
}
}
@ -1081,87 +1088,125 @@ impl Widget for ProcessManager {
}
fn update_data(&mut self, data_collection: &DataCollection) {
self.display_data = data_collection
let filtered_sorted_iterator = data_collection
.process_harvest
.iter()
.filter_map(|process| {
let row = self
.process_table
.columns()
.iter()
.map(|column| match &column.sort_type {
ProcessSortType::Pid => (process.pid.to_string().into(), None, None),
ProcessSortType::Count => ("".into(), None, None),
ProcessSortType::Name => (process.name.clone().into(), None, None),
ProcessSortType::Command => (process.command.clone().into(), None, None),
ProcessSortType::Cpu => (
format!("{:.1}%", process.cpu_usage_percent).into(),
None,
None,
),
ProcessSortType::Mem => (
get_string_with_bytes(process.mem_usage_bytes).into(),
None,
None,
),
ProcessSortType::MemPercent => (
format!("{:.1}%", process.mem_usage_percent).into(),
None,
None,
),
ProcessSortType::Rps => (
get_string_with_bytes(process.read_bytes_per_sec).into(),
None,
None,
),
ProcessSortType::Wps => (
get_string_with_bytes(process.write_bytes_per_sec).into(),
None,
None,
),
ProcessSortType::TotalRead => (
get_string_with_bytes(process.total_read_bytes).into(),
None,
None,
),
ProcessSortType::TotalWrite => (
get_string_with_bytes(process.total_write_bytes).into(),
None,
None,
),
ProcessSortType::User => {
let user = {
#[cfg(target_family = "unix")]
{
if let Some(uid) = process.uid {
data_collection
.user_table
.borrow_mut()
.get_uid_to_username_mapping(uid)
.map(|s| s.into())
.unwrap_or("N/A".into())
} else {
"N/A".into()
}
}
#[cfg(not(target_family = "unix"))]
{
"N/A".into()
}
};
(user, None, None)
}
ProcessSortType::State => (
process.process_state.clone().into(),
Some(process.process_state_char.to_string().into()),
None,
),
})
.collect::<Vec<_>>();
Some(row)
.filter(|process| {
// TODO: Filtering
true
})
.collect::<Vec<_>>();
.sorted_by(match self.process_table.current_column().sort_type {
ProcessSortType::Pid => {
|a: &&ProcessHarvest, b: &&ProcessHarvest| a.pid.cmp(&b.pid)
}
ProcessSortType::Count => {
todo!()
}
ProcessSortType::Name => {
|a: &&ProcessHarvest, b: &&ProcessHarvest| a.name.cmp(&b.name)
}
ProcessSortType::Command => {
|a: &&ProcessHarvest, b: &&ProcessHarvest| a.command.cmp(&b.command)
}
ProcessSortType::Cpu => |a: &&ProcessHarvest, b: &&ProcessHarvest| {
FloatOrd(a.cpu_usage_percent).cmp(&FloatOrd(b.cpu_usage_percent))
},
ProcessSortType::Mem => |a: &&ProcessHarvest, b: &&ProcessHarvest| {
a.mem_usage_bytes.cmp(&b.mem_usage_bytes)
},
ProcessSortType::MemPercent => |a: &&ProcessHarvest, b: &&ProcessHarvest| {
FloatOrd(a.mem_usage_percent).cmp(&FloatOrd(b.mem_usage_percent))
},
ProcessSortType::Rps => |a: &&ProcessHarvest, b: &&ProcessHarvest| {
a.read_bytes_per_sec.cmp(&b.read_bytes_per_sec)
},
ProcessSortType::Wps => |a: &&ProcessHarvest, b: &&ProcessHarvest| {
a.write_bytes_per_sec.cmp(&b.write_bytes_per_sec)
},
ProcessSortType::TotalRead => |a: &&ProcessHarvest, b: &&ProcessHarvest| {
a.total_read_bytes.cmp(&b.total_read_bytes)
},
ProcessSortType::TotalWrite => |a: &&ProcessHarvest, b: &&ProcessHarvest| {
a.total_write_bytes.cmp(&b.total_write_bytes)
},
ProcessSortType::User => {
#[cfg(target_family = "unix")]
{
|a: &&ProcessHarvest, b: &&ProcessHarvest| a.user.cmp(&b.user)
}
#[cfg(not(target_family = "unix"))]
{
|_a: &&ProcessHarvest, _b: &&ProcessHarvest| Ord::Eq
}
}
ProcessSortType::State => {
|a: &&ProcessHarvest, b: &&ProcessHarvest| a.process_state.cmp(&b.process_state)
}
});
self.display_data = if let SortStatus::SortDescending = self
.process_table
.current_column()
.sortable_column
.sorting_status()
{
itertools::Either::Left(filtered_sorted_iterator.rev())
} else {
itertools::Either::Right(filtered_sorted_iterator)
}
.map(|process| {
self.process_table
.columns()
.iter()
.map(|column| match &column.sort_type {
ProcessSortType::Pid => (process.pid.to_string().into(), None, None),
ProcessSortType::Count => ("".into(), None, None),
ProcessSortType::Name => (process.name.clone().into(), None, None),
ProcessSortType::Command => (process.command.clone().into(), None, None),
ProcessSortType::Cpu => (
format!("{:.1}%", process.cpu_usage_percent).into(),
None,
None,
),
ProcessSortType::Mem => (
get_string_with_bytes(process.mem_usage_bytes).into(),
None,
None,
),
ProcessSortType::MemPercent => (
format!("{:.1}%", process.mem_usage_percent).into(),
None,
None,
),
ProcessSortType::Rps => (
get_string_with_bytes(process.read_bytes_per_sec).into(),
None,
None,
),
ProcessSortType::Wps => (
get_string_with_bytes(process.write_bytes_per_sec).into(),
None,
None,
),
ProcessSortType::TotalRead => (
get_string_with_bytes(process.total_read_bytes).into(),
None,
None,
),
ProcessSortType::TotalWrite => (
get_string_with_bytes(process.total_write_bytes).into(),
None,
None,
),
ProcessSortType::User => (process.user.clone(), None, None),
ProcessSortType::State => (
process.process_state.clone().into(),
None, // Currently disabled; what happens if you try to sort in the shortened form?
None,
),
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
}
}

View File

@ -11,7 +11,7 @@ use tui::{
use crate::{
app::{
data_farmer::DataCollection, data_harvester::temperature::TemperatureType,
event::EventResult, sort_text_table::SimpleSortableColumn,
event::WidgetEventResult, sort_text_table::SimpleSortableColumn,
},
canvas::Painter,
data_conversion::convert_temp_row,
@ -89,11 +89,11 @@ impl TempTable {
}
impl Component for TempTable {
fn handle_key_event(&mut self, event: KeyEvent) -> EventResult {
fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
self.table.handle_key_event(event)
}
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
self.table.handle_mouse_event(event)
}

View File

@ -4,13 +4,7 @@
#[macro_use]
extern crate log;
use bottom::{
app::event::{EventResult, ReturnSignalResult},
canvas,
constants::*,
options::*,
*,
};
use bottom::{app::event::EventResult, canvas, constants::*, options::*, *};
use std::{
boxed::Box,
@ -134,17 +128,6 @@ fn main() -> Result<()> {
EventResult::NoRedraw => {
continue;
}
EventResult::Signal(signal) => match app.handle_return_signal(signal) {
ReturnSignalResult::Quit => {
break;
}
ReturnSignalResult::Redraw => {
try_drawing(&mut terminal, &mut app, &mut painter)?;
}
ReturnSignalResult::NoRedraw => {
continue;
}
},
}
}
}

View File

@ -621,11 +621,7 @@ pub fn convert_process_data(
let user = {
#[cfg(target_family = "unix")]
{
if let Some(uid) = process.uid {
user_table.get_uid_to_username_mapping(uid).ok()
} else {
None
}
user_table.get_uid_to_username_mapping(process.uid).ok()
}
#[cfg(not(target_family = "unix"))]
{

View File

@ -31,7 +31,7 @@ use crossterm::{
use app::{
data_harvester::{self, processes::ProcessSorting},
event::EventResult,
event::WidgetEventResult,
layout_manager::WidgetDirection,
AppState, UsedWidgets,
};
@ -76,27 +76,27 @@ pub enum ThreadControlEvent {
UpdateUpdateTime(u64),
}
pub fn handle_mouse_event(event: MouseEvent, app: &mut AppState) -> EventResult {
pub fn handle_mouse_event(event: MouseEvent, app: &mut AppState) -> WidgetEventResult {
match event.kind {
MouseEventKind::Down(MouseButton::Left) => {
app.on_left_mouse_up(event.column, event.row);
EventResult::Redraw
WidgetEventResult::Redraw
}
MouseEventKind::ScrollUp => {
app.handle_scroll_up();
EventResult::Redraw
WidgetEventResult::Redraw
}
MouseEventKind::ScrollDown => {
app.handle_scroll_down();
EventResult::Redraw
WidgetEventResult::Redraw
}
_ => EventResult::NoRedraw,
_ => WidgetEventResult::NoRedraw,
}
}
pub fn handle_key_event(
event: KeyEvent, app: &mut AppState, reset_sender: &std::sync::mpsc::Sender<ThreadControlEvent>,
) -> EventResult {
) -> WidgetEventResult {
// debug!("KeyEvent: {:?}", event);
// TODO: [PASTE] Note that this does NOT support some emojis like flags. This is due to us
@ -107,7 +107,7 @@ pub fn handle_key_event(
if event.modifiers.is_empty() {
// Required catch for searching - otherwise you couldn't search with q.
if event.code == KeyCode::Char('q') && !app.is_in_search_widget() {
return EventResult::Quit;
return WidgetEventResult::Quit;
}
match event.code {
KeyCode::End => app.skip_to_last(),
@ -129,7 +129,7 @@ pub fn handle_key_event(
KeyCode::F(6) => app.toggle_sort(),
KeyCode::F(9) => app.start_killing_process(),
_ => {
return EventResult::NoRedraw;
return WidgetEventResult::NoRedraw;
}
}
} else {
@ -145,7 +145,7 @@ pub fn handle_key_event(
}
} else if let KeyModifiers::CONTROL = event.modifiers {
if event.code == KeyCode::Char('c') {
return EventResult::Quit;
return WidgetEventResult::Quit;
}
match event.code {
@ -172,7 +172,7 @@ pub fn handle_key_event(
// are hard to iter while truncating last (eloquently).
// KeyCode::Backspace => app.skip_word_backspace(),
_ => {
return EventResult::NoRedraw;
return WidgetEventResult::NoRedraw;
}
}
} else if let KeyModifiers::SHIFT = event.modifiers {
@ -183,13 +183,13 @@ pub fn handle_key_event(
KeyCode::Down => app.move_widget_selection(&WidgetDirection::Down),
KeyCode::Char(caught_char) => app.on_char_key(caught_char),
_ => {
return EventResult::NoRedraw;
return WidgetEventResult::NoRedraw;
}
}
}
}
EventResult::Redraw
WidgetEventResult::Redraw
}
pub fn read_config(config_location: Option<&str>) -> error::Result<Option<PathBuf>> {