mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-04-08 17:05:59 +02:00
refactor: use a builder for block building
This commit is contained in:
parent
9ef38cbf1a
commit
d8a6a2344e
@ -3,13 +3,7 @@ use std::time::Instant;
|
||||
use crossterm::event::{KeyEvent, MouseEvent};
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use indextree::NodeId;
|
||||
use tui::{
|
||||
backend::Backend,
|
||||
layout::Rect,
|
||||
text::Span,
|
||||
widgets::{Block, Borders, TableState},
|
||||
Frame,
|
||||
};
|
||||
use tui::{backend::Backend, layout::Rect, widgets::TableState, Frame};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
@ -21,7 +15,7 @@ use crate::{
|
||||
options::layout_options::LayoutRule,
|
||||
};
|
||||
|
||||
mod tui_widgets;
|
||||
mod tui_stuff;
|
||||
|
||||
pub mod base;
|
||||
pub use base::*;
|
||||
@ -29,6 +23,8 @@ pub use base::*;
|
||||
pub mod bottom_widgets;
|
||||
pub use bottom_widgets::*;
|
||||
|
||||
use self::tui_stuff::BlockBuilder;
|
||||
|
||||
use super::data_farmer::DataCollection;
|
||||
|
||||
/// A trait for things that are drawn with state.
|
||||
@ -121,28 +117,10 @@ pub trait Widget {
|
||||
/// Returns a [`Widget`]'s "pretty" display name.
|
||||
fn get_pretty_name(&self) -> &'static str;
|
||||
|
||||
/// Returns a new [`Block`]. The default implementation returns
|
||||
/// a basic [`Block`] with different border colours based on selected state.
|
||||
fn block<'a>(&self, painter: &'a Painter, is_selected: bool, borders: Borders) -> Block<'a> {
|
||||
let has_top_bottom_border =
|
||||
borders.contains(Borders::TOP) || borders.contains(Borders::BOTTOM);
|
||||
|
||||
let block = Block::default()
|
||||
.border_style(if is_selected {
|
||||
painter.colours.highlighted_border_style
|
||||
} else {
|
||||
painter.colours.border_style
|
||||
})
|
||||
.borders(borders);
|
||||
|
||||
if has_top_bottom_border {
|
||||
block.title(Span::styled(
|
||||
format!(" {} ", self.get_pretty_name()),
|
||||
painter.colours.widget_title_style,
|
||||
))
|
||||
} else {
|
||||
block
|
||||
}
|
||||
/// Returns a new [`BlockBuilder`], which can become a [`Block`] if [`BlockBuilder::build`] is called.
|
||||
/// The default implementation builds a [`Block`] that has all 4 borders with no selection or expansion.
|
||||
fn block(&self) -> BlockBuilder {
|
||||
BlockBuilder::new(self.get_pretty_name())
|
||||
}
|
||||
|
||||
/// Draws a [`Widget`]. The default implementation draws nothing.
|
||||
|
@ -16,7 +16,7 @@ use tui::{
|
||||
use crate::{
|
||||
app::{
|
||||
event::WidgetEventResult,
|
||||
widgets::tui_widgets::{
|
||||
widgets::tui_stuff::{
|
||||
custom_legend_chart::{Axis, Dataset},
|
||||
TimeChart,
|
||||
},
|
||||
|
@ -8,7 +8,7 @@ use tui::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{widgets::tui_widgets::PipeGauge, AppConfigFields, Component, DataCollection, Widget},
|
||||
app::{widgets::tui_stuff::PipeGauge, AppConfigFields, Component, DataCollection, Widget},
|
||||
canvas::Painter,
|
||||
constants::SIDE_BORDERS,
|
||||
options::layout_options::LayoutRule,
|
||||
|
@ -8,7 +8,7 @@ use tui::{
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
event::WidgetEventResult, widgets::tui_widgets::PipeGauge, Component, DataCollection,
|
||||
event::WidgetEventResult, widgets::tui_stuff::PipeGauge, Component, DataCollection,
|
||||
Widget,
|
||||
},
|
||||
canvas::Painter,
|
||||
|
@ -15,7 +15,7 @@ use tui::{
|
||||
use crate::{
|
||||
app::{
|
||||
data_farmer::DataCollection, does_bound_intersect_coordinate, event::WidgetEventResult,
|
||||
widgets::tui_widgets::PipeGauge, Component, Widget,
|
||||
widgets::tui_stuff::PipeGauge, Component, Widget,
|
||||
},
|
||||
canvas::Painter,
|
||||
constants::TABLE_GAP_HEIGHT_LIMIT,
|
||||
@ -178,7 +178,11 @@ impl Widget for BatteryTable {
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
) {
|
||||
let block = self.block(painter, selected, self.block_border);
|
||||
let block = self
|
||||
.block()
|
||||
.selected(selected)
|
||||
.borders(self.block_border)
|
||||
.build(painter);
|
||||
|
||||
let inner_area = block.inner(area);
|
||||
const CONSTRAINTS: [Constraint; 2] = [Constraint::Length(1), Constraint::Min(0)];
|
||||
|
@ -227,11 +227,10 @@ impl Widget for CpuGraph {
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let graph_block = self.block(
|
||||
painter,
|
||||
selected && matches!(&self.selected, CpuGraphSelection::Graph),
|
||||
Borders::ALL,
|
||||
);
|
||||
let graph_block = self
|
||||
.block()
|
||||
.selected(selected && matches!(&self.selected, CpuGraphSelection::Graph))
|
||||
.build(painter);
|
||||
|
||||
self.graph.draw_tui_chart(
|
||||
painter,
|
||||
|
@ -122,7 +122,11 @@ impl Widget for DiskTable {
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
) {
|
||||
let block = self.block(painter, selected, self.block_border);
|
||||
let block = self
|
||||
.block()
|
||||
.selected(selected)
|
||||
.borders(self.block_border)
|
||||
.build(painter);
|
||||
|
||||
self.table
|
||||
.draw_tui_table(painter, f, &self.display_data, block, area, selected);
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{borrow::Cow, collections::HashMap, time::Instant};
|
||||
|
||||
use crossterm::event::{KeyEvent, MouseEvent};
|
||||
use tui::{backend::Backend, layout::Rect, widgets::Borders};
|
||||
use tui::{backend::Backend, layout::Rect};
|
||||
|
||||
use crate::{
|
||||
app::{event::WidgetEventResult, time_graph::TimeGraphData, DataCollection},
|
||||
@ -89,7 +89,7 @@ impl Widget for MemGraph {
|
||||
&mut self, painter: &crate::canvas::Painter, f: &mut tui::Frame<'_, B>, area: Rect,
|
||||
selected: bool,
|
||||
) {
|
||||
let block = self.block(painter, selected, Borders::ALL);
|
||||
let block = self.block().selected(selected).build(painter);
|
||||
|
||||
let mut chart_data = Vec::with_capacity(2);
|
||||
if let Some((label_percent, label_frac)) = &self.mem_labels {
|
||||
|
@ -518,7 +518,7 @@ impl Widget for NetGraph {
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
) {
|
||||
let block = self.block(painter, selected, Borders::ALL);
|
||||
let block = self.block().selected(selected).build(painter);
|
||||
|
||||
self.set_draw_cache();
|
||||
|
||||
|
@ -1233,11 +1233,11 @@ impl Widget for ProcessManager {
|
||||
area
|
||||
};
|
||||
|
||||
let process_block = self.block(
|
||||
painter,
|
||||
selected && matches!(self.selected, ProcessManagerSelection::Processes),
|
||||
self.block_border,
|
||||
);
|
||||
let process_block = self
|
||||
.block()
|
||||
.selected(selected && matches!(self.selected, ProcessManagerSelection::Processes))
|
||||
.borders(self.block_border)
|
||||
.build(painter);
|
||||
|
||||
self.process_table.draw_tui_table(
|
||||
painter,
|
||||
|
@ -133,7 +133,11 @@ impl Widget for TempTable {
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
) {
|
||||
let block = self.block(painter, selected, self.block_border);
|
||||
let block = self
|
||||
.block()
|
||||
.selected(selected)
|
||||
.borders(self.block_border)
|
||||
.build(painter);
|
||||
|
||||
self.table
|
||||
.draw_tui_table(painter, f, &self.display_data, block, area, selected);
|
||||
|
@ -3,3 +3,6 @@ pub use custom_legend_chart::TimeChart;
|
||||
|
||||
pub mod pipe_gauge;
|
||||
pub use pipe_gauge::PipeGauge;
|
||||
|
||||
pub mod block_builder;
|
||||
pub use block_builder::BlockBuilder;
|
74
src/app/widgets/tui_stuff/block_builder.rs
Normal file
74
src/app/widgets/tui_stuff/block_builder.rs
Normal file
@ -0,0 +1,74 @@
|
||||
use tui::{
|
||||
text::Span,
|
||||
widgets::{Block, Borders},
|
||||
};
|
||||
|
||||
use crate::canvas::Painter;
|
||||
|
||||
/// A factory pattern builder for a tui [`Block`].
|
||||
pub struct BlockBuilder {
|
||||
borders: Borders,
|
||||
selected: bool,
|
||||
expanded: bool,
|
||||
name: &'static str,
|
||||
extra_text: Option<String>,
|
||||
}
|
||||
|
||||
impl BlockBuilder {
|
||||
/// Creates a new [`BlockBuilder`] with the name of block.
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
Self {
|
||||
borders: Borders::ALL,
|
||||
selected: false,
|
||||
expanded: false,
|
||||
name,
|
||||
extra_text: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates that this block is currently selected, and should be drawn as such.
|
||||
pub fn selected(mut self, selected: bool) -> Self {
|
||||
self.selected = selected;
|
||||
self
|
||||
}
|
||||
|
||||
/// Indicates that this block is currently expanded, and should be drawn as such.
|
||||
pub fn expanded(mut self, expanded: bool) -> Self {
|
||||
self.expanded = expanded;
|
||||
self
|
||||
}
|
||||
|
||||
/// Indicates that this block has some extra text beyond the name.
|
||||
pub fn extra_text(mut self, extra_text: String) -> Self {
|
||||
self.extra_text = Some(extra_text);
|
||||
self
|
||||
}
|
||||
|
||||
/// Determines the borders of the built [`Block`].
|
||||
pub fn borders(mut self, borders: Borders) -> Self {
|
||||
self.borders = borders;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build<'a>(self, painter: &'a Painter) -> Block<'a> {
|
||||
let has_top_bottom_border =
|
||||
self.borders.contains(Borders::TOP) || self.borders.contains(Borders::BOTTOM);
|
||||
|
||||
let block = Block::default()
|
||||
.border_style(if self.selected {
|
||||
painter.colours.highlighted_border_style
|
||||
} else {
|
||||
painter.colours.border_style
|
||||
})
|
||||
.borders(self.borders);
|
||||
|
||||
if has_top_bottom_border {
|
||||
block.title(Span::styled(
|
||||
format!(" {} ", self.name),
|
||||
painter.colours.widget_title_style,
|
||||
))
|
||||
} else {
|
||||
block
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user