mirror of
https://github.com/ClementTsang/bottom.git
synced 2026-09-18 00:25:40 +00:00
232 lines
6.4 KiB
Rust
232 lines
6.4 KiB
Rust
use std::time::Instant;
|
|
|
|
use crossterm::event::{KeyEvent, MouseEvent};
|
|
use enum_dispatch::enum_dispatch;
|
|
use tui::{backend::Backend, layout::Rect, widgets::TableState, Frame};
|
|
|
|
use crate::{
|
|
app::{
|
|
event::{EventResult, SelectionAction},
|
|
layout_manager::BottomWidgetType,
|
|
},
|
|
canvas::{DisplayableData, Painter},
|
|
constants,
|
|
};
|
|
|
|
pub mod base;
|
|
pub use base::*;
|
|
|
|
pub mod process;
|
|
pub use process::*;
|
|
|
|
pub mod net;
|
|
pub use net::*;
|
|
|
|
pub mod mem;
|
|
pub use mem::*;
|
|
|
|
pub mod cpu;
|
|
pub use cpu::*;
|
|
|
|
pub mod disk;
|
|
pub use disk::*;
|
|
|
|
pub mod battery;
|
|
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 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
|
|
}
|
|
|
|
/// Handles a [`MouseEvent`].
|
|
///
|
|
/// Defaults to returning [`EventResult::Continue`], indicating nothing should be done.
|
|
fn handle_mouse_event(&mut self, event: MouseEvent) -> EventResult {
|
|
EventResult::NoRedraw
|
|
}
|
|
|
|
/// Returns a [`Component`]'s bounding box. Note that these are defined in *global*, *absolute*
|
|
/// coordinates.
|
|
fn bounds(&self) -> Rect;
|
|
|
|
/// Updates a [`Component`]s bounding box to `new_bounds`.
|
|
fn set_bounds(&mut self, new_bounds: Rect);
|
|
|
|
/// Returns whether a [`MouseEvent`] intersects a [`Component`].
|
|
fn does_intersect_mouse(&self, event: &MouseEvent) -> bool {
|
|
let x = event.column;
|
|
let y = event.row;
|
|
let rect = self.bounds();
|
|
x >= rect.left() && x <= rect.right() && y >= rect.top() && y <= rect.bottom()
|
|
}
|
|
}
|
|
|
|
/// A trait for actual fully-fledged widgets to be displayed in bottom.
|
|
#[enum_dispatch]
|
|
#[allow(unused_variables)]
|
|
pub trait Widget {
|
|
/// Updates a [`Widget`] given some data. Defaults to doing nothing.
|
|
fn update(&mut self) {}
|
|
|
|
/// Handles what to do when trying to respond to a widget selection movement to the left.
|
|
/// Defaults to just moving to the next-possible widget in that direction.
|
|
fn handle_widget_selection_left(&mut self) -> SelectionAction {
|
|
SelectionAction::NotHandled
|
|
}
|
|
|
|
/// Handles what to do when trying to respond to a widget selection movement to the right.
|
|
/// Defaults to just moving to the next-possible widget in that direction.
|
|
fn handle_widget_selection_right(&mut self) -> SelectionAction {
|
|
SelectionAction::NotHandled
|
|
}
|
|
|
|
/// Handles what to do when trying to respond to a widget selection movement upward.
|
|
/// Defaults to just moving to the next-possible widget in that direction.
|
|
fn handle_widget_selection_up(&mut self) -> SelectionAction {
|
|
SelectionAction::NotHandled
|
|
}
|
|
|
|
/// Handles what to do when trying to respond to a widget selection movement downward.
|
|
/// Defaults to just moving to the next-possible widget in that direction.
|
|
fn handle_widget_selection_down(&mut self) -> SelectionAction {
|
|
SelectionAction::NotHandled
|
|
}
|
|
|
|
/// Returns a [`Widget`]'s "pretty" display name.
|
|
fn get_pretty_name(&self) -> &'static str;
|
|
|
|
/// Draws a [`Widget`]. Defaults to doing nothing.
|
|
fn draw<B: Backend>(
|
|
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, data: &DisplayableData,
|
|
selected: bool,
|
|
) {
|
|
// TODO: Remove the default implementation in the future!
|
|
// TODO: Do another pass on ALL of the draw code - currently it's just glue, it should eventually be done properly!
|
|
}
|
|
}
|
|
|
|
/// The "main" widgets that are used by bottom to display information!
|
|
#[allow(clippy::large_enum_variant)]
|
|
#[enum_dispatch(Component, Widget)]
|
|
pub enum TmpBottomWidget {
|
|
MemGraph,
|
|
TempTable,
|
|
DiskTable,
|
|
CpuGraph,
|
|
NetGraph,
|
|
OldNetGraph,
|
|
ProcessManager,
|
|
BatteryTable,
|
|
}
|
|
|
|
// ----- Old stuff below -----
|
|
|
|
#[derive(Debug)]
|
|
pub enum ScrollDirection {
|
|
// UP means scrolling up --- this usually DECREMENTS
|
|
Up,
|
|
// DOWN means scrolling down --- this usually INCREMENTS
|
|
Down,
|
|
}
|
|
|
|
impl Default for ScrollDirection {
|
|
fn default() -> Self {
|
|
ScrollDirection::Down
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum CursorDirection {
|
|
Left,
|
|
Right,
|
|
}
|
|
|
|
/// AppScrollWidgetState deals with fields for a scrollable app's current state.
|
|
#[derive(Default)]
|
|
pub struct AppScrollWidgetState {
|
|
pub current_scroll_position: usize,
|
|
pub previous_scroll_position: usize,
|
|
pub scroll_direction: ScrollDirection,
|
|
pub table_state: TableState,
|
|
}
|
|
|
|
#[derive(PartialEq)]
|
|
pub enum KillSignal {
|
|
Cancel,
|
|
Kill(usize),
|
|
}
|
|
|
|
impl Default for KillSignal {
|
|
#[cfg(target_family = "unix")]
|
|
fn default() -> Self {
|
|
KillSignal::Kill(15)
|
|
}
|
|
#[cfg(target_os = "windows")]
|
|
fn default() -> Self {
|
|
KillSignal::Kill(1)
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct AppDeleteDialogState {
|
|
pub is_showing_dd: bool,
|
|
pub selected_signal: KillSignal,
|
|
/// tl x, tl y, br x, br y, index/signal
|
|
pub button_positions: Vec<(u16, u16, u16, u16, usize)>,
|
|
pub keyboard_signal_select: usize,
|
|
pub last_number_press: Option<Instant>,
|
|
pub scroll_pos: usize,
|
|
}
|
|
|
|
pub struct AppHelpDialogState {
|
|
pub is_showing_help: bool,
|
|
pub scroll_state: ParagraphScrollState,
|
|
pub index_shortcuts: Vec<u16>,
|
|
}
|
|
|
|
impl Default for AppHelpDialogState {
|
|
fn default() -> Self {
|
|
AppHelpDialogState {
|
|
is_showing_help: false,
|
|
scroll_state: ParagraphScrollState::default(),
|
|
index_shortcuts: vec![0; constants::HELP_TEXT.len()],
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Meant for canvas operations involving table column widths.
|
|
#[derive(Default)]
|
|
pub struct CanvasTableWidthState {
|
|
pub desired_column_widths: Vec<u16>,
|
|
pub calculated_column_widths: Vec<u16>,
|
|
}
|
|
|
|
pub struct BasicTableWidgetState {
|
|
// Since this is intended (currently) to only be used for ONE widget, that's
|
|
// how it's going to be written. If we want to allow for multiple of these,
|
|
// then we can expand outwards with a normal BasicTableState and a hashmap
|
|
pub currently_displayed_widget_type: BottomWidgetType,
|
|
pub currently_displayed_widget_id: u64,
|
|
pub widget_id: i64,
|
|
pub left_tlc: Option<(u16, u16)>,
|
|
pub left_brc: Option<(u16, u16)>,
|
|
pub right_tlc: Option<(u16, u16)>,
|
|
pub right_brc: Option<(u16, u16)>,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct ParagraphScrollState {
|
|
pub current_scroll_index: u16,
|
|
pub max_scroll_index: u16,
|
|
}
|