mirror of
https://github.com/ClementTsang/bottom.git
synced 2026-07-18 02:17:07 +00:00
e7b9c72912
Adds back some of the general program keybinds, and fixes both a bug causing widget movement via keybinds to be incorrect, and not correcting the last selected widget in the layout tree rows/cols after clicking/setting the default widget!
165 lines
4.7 KiB
Rust
165 lines
4.7 KiB
Rust
use crossterm::event::{KeyCode, KeyEvent};
|
|
use tui::{
|
|
backend::Backend,
|
|
layout::{Constraint, Layout, Rect},
|
|
widgets::Block,
|
|
Frame,
|
|
};
|
|
|
|
use crate::{
|
|
app::{
|
|
event::WidgetEventResult, widgets::tui_stuff::PipeGauge, Component, DataCollection, Widget,
|
|
},
|
|
canvas::Painter,
|
|
constants::SIDE_BORDERS,
|
|
data_conversion::{convert_mem_data_points, convert_mem_labels, convert_swap_data_points},
|
|
options::layout_options::LayoutRule,
|
|
};
|
|
|
|
#[derive(Debug)]
|
|
pub struct BasicMem {
|
|
bounds: Rect,
|
|
width: LayoutRule,
|
|
mem_data: (f64, String, String),
|
|
swap_data: Option<(f64, String, String)>,
|
|
use_percent: bool,
|
|
}
|
|
|
|
impl Default for BasicMem {
|
|
fn default() -> Self {
|
|
Self {
|
|
bounds: Default::default(),
|
|
width: Default::default(),
|
|
mem_data: (0.0, "0.0B/0.0B".to_string(), "0%".to_string()),
|
|
swap_data: None,
|
|
use_percent: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BasicMem {
|
|
/// Sets the width.
|
|
pub fn width(mut self, width: LayoutRule) -> Self {
|
|
self.width = width;
|
|
self
|
|
}
|
|
}
|
|
|
|
impl Component for BasicMem {
|
|
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) -> WidgetEventResult {
|
|
match event.code {
|
|
KeyCode::Char('%') if event.modifiers.is_empty() => {
|
|
self.use_percent = !self.use_percent;
|
|
WidgetEventResult::Redraw
|
|
}
|
|
_ => WidgetEventResult::NoRedraw,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Widget for BasicMem {
|
|
fn get_pretty_name(&self) -> &'static str {
|
|
"Memory"
|
|
}
|
|
|
|
fn draw<B: Backend>(
|
|
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
|
_expanded: bool,
|
|
) {
|
|
let block = Block::default()
|
|
.borders(*SIDE_BORDERS)
|
|
.border_style(painter.colours.highlighted_border_style);
|
|
let inner_area = block.inner(area);
|
|
const CONSTRAINTS: [Constraint; 2] = [Constraint::Ratio(1, 2); 2];
|
|
let split_area = Layout::default()
|
|
.direction(tui::layout::Direction::Vertical)
|
|
.constraints(CONSTRAINTS)
|
|
.split(inner_area);
|
|
|
|
if selected {
|
|
f.render_widget(block, area);
|
|
}
|
|
|
|
let mut use_percentage =
|
|
self.use_percent || (split_area[0].width as usize) < self.mem_data.1.len() + 7;
|
|
|
|
if let Some(swap_data) = &self.swap_data {
|
|
use_percentage =
|
|
use_percentage || (split_area[1].width as usize) < swap_data.1.len() + 7;
|
|
|
|
f.render_widget(
|
|
PipeGauge::default()
|
|
.ratio(swap_data.0)
|
|
.style(painter.colours.swap_style)
|
|
.gauge_style(painter.colours.swap_style)
|
|
.start_label("SWP")
|
|
.end_label(if use_percentage {
|
|
swap_data.2.clone()
|
|
} else {
|
|
swap_data.1.clone()
|
|
}),
|
|
split_area[1],
|
|
);
|
|
}
|
|
f.render_widget(
|
|
PipeGauge::default()
|
|
.ratio(self.mem_data.0)
|
|
.style(painter.colours.ram_style)
|
|
.gauge_style(painter.colours.ram_style)
|
|
.start_label("RAM")
|
|
.end_label(if use_percentage {
|
|
self.mem_data.2.clone()
|
|
} else {
|
|
self.mem_data.1.clone()
|
|
}),
|
|
split_area[0],
|
|
);
|
|
}
|
|
|
|
fn update_data(&mut self, data_collection: &DataCollection) {
|
|
let (memory_labels, swap_labels) = convert_mem_labels(data_collection);
|
|
|
|
// TODO: [Data update optimization] Probably should just make another function altogether for basic mode.
|
|
self.mem_data = if let (Some(data), Some((_, fraction))) = (
|
|
convert_mem_data_points(data_collection).last(),
|
|
memory_labels,
|
|
) {
|
|
(
|
|
data.1 / 100.0,
|
|
fraction.trim().to_string(),
|
|
format!("{:3.0}%", data.1.round()),
|
|
)
|
|
} else {
|
|
(0.0, "0.0B/0.0B".to_string(), "0%".to_string())
|
|
};
|
|
self.swap_data = if let (Some(data), Some((_, fraction))) = (
|
|
convert_swap_data_points(data_collection).last(),
|
|
swap_labels,
|
|
) {
|
|
Some((
|
|
data.1 / 100.0,
|
|
fraction.trim().to_string(),
|
|
format!("{:3.0}%", data.1.round()),
|
|
))
|
|
} else {
|
|
None
|
|
};
|
|
}
|
|
|
|
fn width(&self) -> LayoutRule {
|
|
self.width
|
|
}
|
|
|
|
fn height(&self) -> LayoutRule {
|
|
LayoutRule::Length { length: 2 }
|
|
}
|
|
}
|