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 crossterm::event::{KeyEvent, MouseEvent};
|
||||||
use enum_dispatch::enum_dispatch;
|
use enum_dispatch::enum_dispatch;
|
||||||
use indextree::NodeId;
|
use indextree::NodeId;
|
||||||
use tui::{
|
use tui::{backend::Backend, layout::Rect, widgets::TableState, Frame};
|
||||||
backend::Backend,
|
|
||||||
layout::Rect,
|
|
||||||
text::Span,
|
|
||||||
widgets::{Block, Borders, TableState},
|
|
||||||
Frame,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{
|
app::{
|
||||||
@ -21,7 +15,7 @@ use crate::{
|
|||||||
options::layout_options::LayoutRule,
|
options::layout_options::LayoutRule,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod tui_widgets;
|
mod tui_stuff;
|
||||||
|
|
||||||
pub mod base;
|
pub mod base;
|
||||||
pub use base::*;
|
pub use base::*;
|
||||||
@ -29,6 +23,8 @@ pub use base::*;
|
|||||||
pub mod bottom_widgets;
|
pub mod bottom_widgets;
|
||||||
pub use bottom_widgets::*;
|
pub use bottom_widgets::*;
|
||||||
|
|
||||||
|
use self::tui_stuff::BlockBuilder;
|
||||||
|
|
||||||
use super::data_farmer::DataCollection;
|
use super::data_farmer::DataCollection;
|
||||||
|
|
||||||
/// A trait for things that are drawn with state.
|
/// A trait for things that are drawn with state.
|
||||||
@ -121,28 +117,10 @@ pub trait Widget {
|
|||||||
/// Returns a [`Widget`]'s "pretty" display name.
|
/// Returns a [`Widget`]'s "pretty" display name.
|
||||||
fn get_pretty_name(&self) -> &'static str;
|
fn get_pretty_name(&self) -> &'static str;
|
||||||
|
|
||||||
/// Returns a new [`Block`]. The default implementation returns
|
/// Returns a new [`BlockBuilder`], which can become a [`Block`] if [`BlockBuilder::build`] is called.
|
||||||
/// a basic [`Block`] with different border colours based on selected state.
|
/// The default implementation builds a [`Block`] that has all 4 borders with no selection or expansion.
|
||||||
fn block<'a>(&self, painter: &'a Painter, is_selected: bool, borders: Borders) -> Block<'a> {
|
fn block(&self) -> BlockBuilder {
|
||||||
let has_top_bottom_border =
|
BlockBuilder::new(self.get_pretty_name())
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draws a [`Widget`]. The default implementation draws nothing.
|
/// Draws a [`Widget`]. The default implementation draws nothing.
|
||||||
|
@ -16,7 +16,7 @@ use tui::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::{
|
app::{
|
||||||
event::WidgetEventResult,
|
event::WidgetEventResult,
|
||||||
widgets::tui_widgets::{
|
widgets::tui_stuff::{
|
||||||
custom_legend_chart::{Axis, Dataset},
|
custom_legend_chart::{Axis, Dataset},
|
||||||
TimeChart,
|
TimeChart,
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@ use tui::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{widgets::tui_widgets::PipeGauge, AppConfigFields, Component, DataCollection, Widget},
|
app::{widgets::tui_stuff::PipeGauge, AppConfigFields, Component, DataCollection, Widget},
|
||||||
canvas::Painter,
|
canvas::Painter,
|
||||||
constants::SIDE_BORDERS,
|
constants::SIDE_BORDERS,
|
||||||
options::layout_options::LayoutRule,
|
options::layout_options::LayoutRule,
|
||||||
|
@ -8,7 +8,7 @@ use tui::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{
|
app::{
|
||||||
event::WidgetEventResult, widgets::tui_widgets::PipeGauge, Component, DataCollection,
|
event::WidgetEventResult, widgets::tui_stuff::PipeGauge, Component, DataCollection,
|
||||||
Widget,
|
Widget,
|
||||||
},
|
},
|
||||||
canvas::Painter,
|
canvas::Painter,
|
||||||
|
@ -15,7 +15,7 @@ use tui::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::{
|
app::{
|
||||||
data_farmer::DataCollection, does_bound_intersect_coordinate, event::WidgetEventResult,
|
data_farmer::DataCollection, does_bound_intersect_coordinate, event::WidgetEventResult,
|
||||||
widgets::tui_widgets::PipeGauge, Component, Widget,
|
widgets::tui_stuff::PipeGauge, Component, Widget,
|
||||||
},
|
},
|
||||||
canvas::Painter,
|
canvas::Painter,
|
||||||
constants::TABLE_GAP_HEIGHT_LIMIT,
|
constants::TABLE_GAP_HEIGHT_LIMIT,
|
||||||
@ -178,7 +178,11 @@ impl Widget for BatteryTable {
|
|||||||
fn draw<B: Backend>(
|
fn draw<B: Backend>(
|
||||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
&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);
|
let inner_area = block.inner(area);
|
||||||
const CONSTRAINTS: [Constraint; 2] = [Constraint::Length(1), Constraint::Min(0)];
|
const CONSTRAINTS: [Constraint; 2] = [Constraint::Length(1), Constraint::Min(0)];
|
||||||
|
@ -227,11 +227,10 @@ impl Widget for CpuGraph {
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let graph_block = self.block(
|
let graph_block = self
|
||||||
painter,
|
.block()
|
||||||
selected && matches!(&self.selected, CpuGraphSelection::Graph),
|
.selected(selected && matches!(&self.selected, CpuGraphSelection::Graph))
|
||||||
Borders::ALL,
|
.build(painter);
|
||||||
);
|
|
||||||
|
|
||||||
self.graph.draw_tui_chart(
|
self.graph.draw_tui_chart(
|
||||||
painter,
|
painter,
|
||||||
|
@ -122,7 +122,11 @@ impl Widget for DiskTable {
|
|||||||
fn draw<B: Backend>(
|
fn draw<B: Backend>(
|
||||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
&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
|
self.table
|
||||||
.draw_tui_table(painter, f, &self.display_data, block, area, selected);
|
.draw_tui_table(painter, f, &self.display_data, block, area, selected);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{borrow::Cow, collections::HashMap, time::Instant};
|
use std::{borrow::Cow, collections::HashMap, time::Instant};
|
||||||
|
|
||||||
use crossterm::event::{KeyEvent, MouseEvent};
|
use crossterm::event::{KeyEvent, MouseEvent};
|
||||||
use tui::{backend::Backend, layout::Rect, widgets::Borders};
|
use tui::{backend::Backend, layout::Rect};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{event::WidgetEventResult, time_graph::TimeGraphData, DataCollection},
|
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,
|
&mut self, painter: &crate::canvas::Painter, f: &mut tui::Frame<'_, B>, area: Rect,
|
||||||
selected: bool,
|
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);
|
let mut chart_data = Vec::with_capacity(2);
|
||||||
if let Some((label_percent, label_frac)) = &self.mem_labels {
|
if let Some((label_percent, label_frac)) = &self.mem_labels {
|
||||||
|
@ -518,7 +518,7 @@ impl Widget for NetGraph {
|
|||||||
fn draw<B: Backend>(
|
fn draw<B: Backend>(
|
||||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
&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();
|
self.set_draw_cache();
|
||||||
|
|
||||||
|
@ -1233,11 +1233,11 @@ impl Widget for ProcessManager {
|
|||||||
area
|
area
|
||||||
};
|
};
|
||||||
|
|
||||||
let process_block = self.block(
|
let process_block = self
|
||||||
painter,
|
.block()
|
||||||
selected && matches!(self.selected, ProcessManagerSelection::Processes),
|
.selected(selected && matches!(self.selected, ProcessManagerSelection::Processes))
|
||||||
self.block_border,
|
.borders(self.block_border)
|
||||||
);
|
.build(painter);
|
||||||
|
|
||||||
self.process_table.draw_tui_table(
|
self.process_table.draw_tui_table(
|
||||||
painter,
|
painter,
|
||||||
|
@ -133,7 +133,11 @@ impl Widget for TempTable {
|
|||||||
fn draw<B: Backend>(
|
fn draw<B: Backend>(
|
||||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
&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
|
self.table
|
||||||
.draw_tui_table(painter, f, &self.display_data, block, area, selected);
|
.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 mod pipe_gauge;
|
||||||
pub use pipe_gauge::PipeGauge;
|
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