mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-23 13:45:12 +02:00
refactor: Add back scroll position and expanded
This commit is contained in:
parent
d8a6a2344e
commit
955840b412
@ -1140,6 +1140,7 @@ pub fn create_layout_tree(
|
||||
.width(width)
|
||||
.height(height)
|
||||
.basic_mode(app_config_fields.use_basic_mode)
|
||||
.show_scroll_index(app_config_fields.show_table_scroll_position)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
@ -1151,6 +1152,7 @@ pub fn create_layout_tree(
|
||||
.width(width)
|
||||
.height(height)
|
||||
.basic_mode(app_config_fields.use_basic_mode)
|
||||
.show_scroll_index(app_config_fields.show_table_scroll_position)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
@ -1161,6 +1163,7 @@ pub fn create_layout_tree(
|
||||
.width(width)
|
||||
.height(height)
|
||||
.basic_mode(app_config_fields.use_basic_mode)
|
||||
.show_scroll_index(app_config_fields.show_table_scroll_position)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ pub trait Widget {
|
||||
/// Returns a [`Widget`]'s "pretty" display name.
|
||||
fn get_pretty_name(&self) -> &'static str;
|
||||
|
||||
/// Returns a new [`BlockBuilder`], which can become a [`Block`] if [`BlockBuilder::build`] is called.
|
||||
/// Returns a new [`BlockBuilder`], which can become a [`tui::widgets::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())
|
||||
@ -126,6 +126,7 @@ pub trait Widget {
|
||||
/// Draws a [`Widget`]. The default implementation draws nothing.
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
expanded: bool,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,15 @@ impl Scrollable {
|
||||
self.current_index
|
||||
}
|
||||
|
||||
/// Returns the text indicator [`String`].
|
||||
pub fn text_indicator(&self) -> String {
|
||||
format!(
|
||||
"({} of {})",
|
||||
min(self.current_index + 1, self.num_items),
|
||||
self.num_items
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the start of the [`Scrollable`] when displayed.
|
||||
pub fn get_list_start(&mut self, num_visible_rows: usize) -> usize {
|
||||
// So it's probably confusing - what is the "window index"?
|
||||
|
@ -1,8 +1,11 @@
|
||||
use crossterm::event::{KeyEvent, MouseEvent};
|
||||
use tui::{backend::Backend, layout::Rect, widgets::Block, Frame};
|
||||
use tui::{backend::Backend, layout::Rect, Frame};
|
||||
|
||||
use crate::{
|
||||
app::{event::WidgetEventResult, text_table::SimpleColumn, Component, TextTable},
|
||||
app::{
|
||||
event::WidgetEventResult, text_table::SimpleColumn, widgets::tui_stuff::BlockBuilder,
|
||||
Component, TextTable,
|
||||
},
|
||||
canvas::Painter,
|
||||
};
|
||||
|
||||
@ -42,7 +45,7 @@ impl SortMenu {
|
||||
|
||||
/// Draws a [`tui::widgets::Table`] on screen corresponding to the sort columns of this [`SortableTextTable`].
|
||||
pub fn draw_sort_menu<B: Backend, C: SortableColumn>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, columns: &[C], block: Block<'_>,
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, columns: &[C], block: BlockBuilder,
|
||||
block_area: Rect,
|
||||
) {
|
||||
self.set_bounds(block_area);
|
||||
@ -53,7 +56,7 @@ impl SortMenu {
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
self.table
|
||||
.draw_tui_table(painter, f, &data, block, block_area, true);
|
||||
.draw_tui_table(painter, f, &data, block, block_area, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind};
|
||||
use tui::{backend::Backend, layout::Rect, widgets::Block, Frame};
|
||||
use tui::{backend::Backend, layout::Rect, Frame};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
event::{ReturnSignal, WidgetEventResult},
|
||||
widgets::tui_stuff::BlockBuilder,
|
||||
Component, TextTable,
|
||||
},
|
||||
canvas::Painter,
|
||||
@ -371,10 +372,18 @@ where
|
||||
/// it will only create as many columns as it can grab data from both sources from.
|
||||
pub fn draw_tui_table<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, data: &TextTableDataRef,
|
||||
block: Block<'_>, block_area: Rect, show_selected_entry: bool,
|
||||
block: BlockBuilder, block_area: Rect, show_selected_entry: bool,
|
||||
show_scroll_position: bool,
|
||||
) {
|
||||
self.table
|
||||
.draw_tui_table(painter, f, data, block, block_area, show_selected_entry);
|
||||
self.table.draw_tui_table(
|
||||
painter,
|
||||
f,
|
||||
data,
|
||||
block,
|
||||
block_area,
|
||||
show_selected_entry,
|
||||
show_scroll_position,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,13 +9,13 @@ use tui::{
|
||||
layout::{Constraint, Rect},
|
||||
style::Style,
|
||||
text::Text,
|
||||
widgets::{Block, Table},
|
||||
widgets::Table,
|
||||
Frame,
|
||||
};
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use crate::{
|
||||
app::{event::WidgetEventResult, Component, Scrollable},
|
||||
app::{event::WidgetEventResult, widgets::tui_stuff::BlockBuilder, Component, Scrollable},
|
||||
canvas::Painter,
|
||||
constants::TABLE_GAP_HEIGHT_LIMIT,
|
||||
};
|
||||
@ -381,10 +381,21 @@ where
|
||||
/// Draws a [`Table`] on screen corresponding to the [`TextTable`].
|
||||
pub fn draw_tui_table<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, data: &TextTableDataRef,
|
||||
block: Block<'_>, block_area: Rect, show_selected_entry: bool,
|
||||
block: BlockBuilder, block_area: Rect, show_selected_entry: bool,
|
||||
show_scroll_position: bool,
|
||||
) {
|
||||
use tui::widgets::Row;
|
||||
|
||||
self.set_num_items(data.len());
|
||||
|
||||
let block = block
|
||||
.extra_text(if show_scroll_position {
|
||||
Some(self.scrollable.text_indicator())
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.build(painter, block_area);
|
||||
|
||||
let inner_area = block.inner(block_area);
|
||||
if inner_area.height < 1 {
|
||||
f.render_widget(block, block_area);
|
||||
@ -396,7 +407,6 @@ where
|
||||
1
|
||||
};
|
||||
|
||||
self.set_num_items(data.len());
|
||||
self.set_border_bounds(block_area);
|
||||
self.set_bounds(inner_area);
|
||||
let table_extras = 1 + table_gap;
|
||||
|
@ -59,6 +59,7 @@ impl Widget for BasicCpu {
|
||||
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
_expanded: bool,
|
||||
) {
|
||||
const CONSTRAINTS: [Constraint; 2 * REQUIRED_COLUMNS - 1] = [
|
||||
Constraint::Ratio(1, REQUIRED_COLUMNS as u32),
|
||||
|
@ -8,8 +8,7 @@ use tui::{
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
event::WidgetEventResult, widgets::tui_stuff::PipeGauge, Component, DataCollection,
|
||||
Widget,
|
||||
event::WidgetEventResult, widgets::tui_stuff::PipeGauge, Component, DataCollection, Widget,
|
||||
},
|
||||
canvas::Painter,
|
||||
constants::SIDE_BORDERS,
|
||||
@ -73,6 +72,7 @@ impl Widget for BasicMem {
|
||||
|
||||
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)
|
||||
|
@ -68,6 +68,7 @@ impl Widget for BasicNet {
|
||||
|
||||
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)
|
||||
|
@ -177,12 +177,14 @@ impl Widget for BatteryTable {
|
||||
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
expanded: bool,
|
||||
) {
|
||||
let block = self
|
||||
.block()
|
||||
.selected(selected)
|
||||
.borders(self.block_border)
|
||||
.build(painter);
|
||||
.expanded(expanded)
|
||||
.build(painter, area);
|
||||
|
||||
let inner_area = block.inner(area);
|
||||
const CONSTRAINTS: [Constraint; 2] = [Constraint::Length(1), Constraint::Min(0)];
|
||||
|
@ -4,7 +4,6 @@ use crossterm::event::{KeyEvent, MouseEvent};
|
||||
use tui::{
|
||||
backend::Backend,
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
widgets::{Block, Borders},
|
||||
Frame,
|
||||
};
|
||||
|
||||
@ -164,6 +163,7 @@ impl Widget for CpuGraph {
|
||||
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
expanded: bool,
|
||||
) {
|
||||
let constraints = {
|
||||
const CPU_LEGEND_MIN_WIDTH: u16 = 10;
|
||||
@ -230,7 +230,8 @@ impl Widget for CpuGraph {
|
||||
let graph_block = self
|
||||
.block()
|
||||
.selected(selected && matches!(&self.selected, CpuGraphSelection::Graph))
|
||||
.build(painter);
|
||||
.expanded(expanded)
|
||||
.build(painter, graph_block_area);
|
||||
|
||||
self.graph.draw_tui_chart(
|
||||
painter,
|
||||
@ -243,17 +244,11 @@ impl Widget for CpuGraph {
|
||||
graph_block_area,
|
||||
);
|
||||
|
||||
let legend_block = Block::default()
|
||||
.border_style(if selected {
|
||||
if let CpuGraphSelection::Legend = &self.selected {
|
||||
painter.colours.highlighted_border_style
|
||||
} else {
|
||||
painter.colours.border_style
|
||||
}
|
||||
} else {
|
||||
painter.colours.border_style
|
||||
})
|
||||
.borders(Borders::ALL);
|
||||
let legend_block = self
|
||||
.block()
|
||||
.selected(selected && matches!(&self.selected, CpuGraphSelection::Legend))
|
||||
.expanded(expanded)
|
||||
.hide_title(true);
|
||||
|
||||
let legend_data = self
|
||||
.display_data
|
||||
@ -294,6 +289,7 @@ impl Widget for CpuGraph {
|
||||
legend_block,
|
||||
legend_block_area,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ pub struct DiskTable {
|
||||
width: LayoutRule,
|
||||
height: LayoutRule,
|
||||
block_border: Borders,
|
||||
show_scroll_index: bool,
|
||||
}
|
||||
|
||||
impl Default for DiskTable {
|
||||
@ -69,6 +70,7 @@ impl Default for DiskTable {
|
||||
width: LayoutRule::default(),
|
||||
height: LayoutRule::default(),
|
||||
block_border: Borders::ALL,
|
||||
show_scroll_index: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,6 +96,12 @@ impl DiskTable {
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets whether to show the scroll index.
|
||||
pub fn show_scroll_index(mut self, show_scroll_index: bool) -> Self {
|
||||
self.show_scroll_index = show_scroll_index;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for DiskTable {
|
||||
@ -121,15 +129,23 @@ impl Widget for DiskTable {
|
||||
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
expanded: bool,
|
||||
) {
|
||||
let block = self
|
||||
.block()
|
||||
.selected(selected)
|
||||
.borders(self.block_border)
|
||||
.build(painter);
|
||||
.expanded(expanded);
|
||||
|
||||
self.table
|
||||
.draw_tui_table(painter, f, &self.display_data, block, area, selected);
|
||||
self.table.draw_tui_table(
|
||||
painter,
|
||||
f,
|
||||
&self.display_data,
|
||||
block,
|
||||
area,
|
||||
selected,
|
||||
self.show_scroll_index,
|
||||
);
|
||||
}
|
||||
|
||||
fn update_data(&mut self, data_collection: &DataCollection) {
|
||||
|
@ -87,9 +87,13 @@ impl Widget for MemGraph {
|
||||
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &crate::canvas::Painter, f: &mut tui::Frame<'_, B>, area: Rect,
|
||||
selected: bool,
|
||||
selected: bool, expanded: bool,
|
||||
) {
|
||||
let block = self.block().selected(selected).build(painter);
|
||||
let block = self
|
||||
.block()
|
||||
.selected(selected)
|
||||
.expanded(expanded)
|
||||
.build(painter, area);
|
||||
|
||||
let mut chart_data = Vec::with_capacity(2);
|
||||
if let Some((label_percent, label_frac)) = &self.mem_labels {
|
||||
|
@ -3,14 +3,14 @@ use std::{borrow::Cow, collections::HashMap, time::Instant};
|
||||
use tui::{
|
||||
backend::Backend,
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
widgets::{Block, Borders},
|
||||
Frame,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
data_farmer::DataCollection, text_table::SimpleColumn, time_graph::TimeGraphData,
|
||||
AppConfigFields, AxisScaling, Component, TextTable, TimeGraph, Widget,
|
||||
widgets::tui_stuff::BlockBuilder, AppConfigFields, AxisScaling, Component, TextTable,
|
||||
TimeGraph, Widget,
|
||||
},
|
||||
canvas::Painter,
|
||||
data_conversion::convert_network_data_points,
|
||||
@ -517,8 +517,13 @@ impl Widget for NetGraph {
|
||||
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
expanded: bool,
|
||||
) {
|
||||
let block = self.block().selected(selected).build(painter);
|
||||
let block = self
|
||||
.block()
|
||||
.selected(selected)
|
||||
.expanded(expanded)
|
||||
.build(painter, area);
|
||||
|
||||
self.set_draw_cache();
|
||||
|
||||
@ -660,6 +665,7 @@ impl Widget for OldNetGraph {
|
||||
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
expanded: bool,
|
||||
) {
|
||||
const CONSTRAINTS: [Constraint; 2] = [Constraint::Min(0), Constraint::Length(4)];
|
||||
|
||||
@ -671,15 +677,10 @@ impl Widget for OldNetGraph {
|
||||
let graph_area = split_area[0];
|
||||
let table_area = split_area[1];
|
||||
|
||||
self.net_graph.draw(painter, f, graph_area, selected);
|
||||
self.net_graph
|
||||
.draw(painter, f, graph_area, selected, expanded);
|
||||
|
||||
let table_block = Block::default()
|
||||
.border_style(if selected {
|
||||
painter.colours.highlighted_border_style
|
||||
} else {
|
||||
painter.colours.border_style
|
||||
})
|
||||
.borders(Borders::ALL);
|
||||
let table_block = BlockBuilder::new("").hide_title(true);
|
||||
|
||||
self.table.draw_tui_table(
|
||||
painter,
|
||||
@ -701,6 +702,7 @@ impl Widget for OldNetGraph {
|
||||
table_block,
|
||||
table_area,
|
||||
selected,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -789,6 +789,8 @@ pub struct ProcessManager {
|
||||
|
||||
width: LayoutRule,
|
||||
height: LayoutRule,
|
||||
|
||||
show_scroll_index: bool,
|
||||
}
|
||||
|
||||
impl ProcessManager {
|
||||
@ -825,6 +827,7 @@ impl ProcessManager {
|
||||
block_border: Borders::ALL,
|
||||
width: LayoutRule::default(),
|
||||
height: LayoutRule::default(),
|
||||
show_scroll_index: false,
|
||||
};
|
||||
|
||||
manager.set_tree_mode(process_defaults.is_tree);
|
||||
@ -856,6 +859,12 @@ impl ProcessManager {
|
||||
self.in_tree_mode = in_tree_mode;
|
||||
}
|
||||
|
||||
/// Sets whether to show the scroll index.
|
||||
pub fn show_scroll_index(mut self, show_scroll_index: bool) -> Self {
|
||||
self.show_scroll_index = show_scroll_index;
|
||||
self
|
||||
}
|
||||
|
||||
fn open_search(&mut self) -> WidgetEventResult {
|
||||
if let ProcessManagerSelection::Search = self.selected {
|
||||
WidgetEventResult::NoRedraw
|
||||
@ -1147,6 +1156,7 @@ impl Widget for ProcessManager {
|
||||
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
expanded: bool,
|
||||
) {
|
||||
let area = if self.show_search {
|
||||
const SEARCH_CONSTRAINTS: [Constraint; 2] = [Constraint::Min(0), Constraint::Length(4)];
|
||||
@ -1209,17 +1219,10 @@ impl Widget for ProcessManager {
|
||||
.constraints(SORT_CONSTRAINTS)
|
||||
.split(area);
|
||||
|
||||
let sort_block = Block::default()
|
||||
.border_style(if selected {
|
||||
if let ProcessManagerSelection::Sort = self.selected {
|
||||
painter.colours.highlighted_border_style
|
||||
} else {
|
||||
painter.colours.border_style
|
||||
}
|
||||
} else {
|
||||
painter.colours.border_style
|
||||
})
|
||||
.borders(Borders::ALL);
|
||||
let sort_block = self
|
||||
.block()
|
||||
.selected(selected && matches!(self.selected, ProcessManagerSelection::Sort))
|
||||
.hide_title(true);
|
||||
self.sort_menu.draw_sort_menu(
|
||||
painter,
|
||||
f,
|
||||
@ -1237,7 +1240,7 @@ impl Widget for ProcessManager {
|
||||
.block()
|
||||
.selected(selected && matches!(self.selected, ProcessManagerSelection::Processes))
|
||||
.borders(self.block_border)
|
||||
.build(painter);
|
||||
.expanded(expanded && !self.show_sort && !self.show_search);
|
||||
|
||||
self.process_table.draw_tui_table(
|
||||
painter,
|
||||
@ -1246,6 +1249,7 @@ impl Widget for ProcessManager {
|
||||
process_block,
|
||||
area,
|
||||
selected,
|
||||
self.show_scroll_index,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@ pub struct TempTable {
|
||||
width: LayoutRule,
|
||||
height: LayoutRule,
|
||||
block_border: Borders,
|
||||
show_scroll_index: bool,
|
||||
}
|
||||
|
||||
impl Default for TempTable {
|
||||
@ -74,6 +75,7 @@ impl Default for TempTable {
|
||||
width: LayoutRule::default(),
|
||||
height: LayoutRule::default(),
|
||||
block_border: Borders::ALL,
|
||||
show_scroll_index: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -105,6 +107,12 @@ impl TempTable {
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets whether to show the scroll index.
|
||||
pub fn show_scroll_index(mut self, show_scroll_index: bool) -> Self {
|
||||
self.show_scroll_index = show_scroll_index;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for TempTable {
|
||||
@ -132,15 +140,23 @@ impl Widget for TempTable {
|
||||
|
||||
fn draw<B: Backend>(
|
||||
&mut self, painter: &Painter, f: &mut Frame<'_, B>, area: Rect, selected: bool,
|
||||
expanded: bool,
|
||||
) {
|
||||
let block = self
|
||||
.block()
|
||||
.selected(selected)
|
||||
.borders(self.block_border)
|
||||
.build(painter);
|
||||
.expanded(expanded);
|
||||
|
||||
self.table
|
||||
.draw_tui_table(painter, f, &self.display_data, block, area, selected);
|
||||
self.table.draw_tui_table(
|
||||
painter,
|
||||
f,
|
||||
&self.display_data,
|
||||
block,
|
||||
area,
|
||||
selected,
|
||||
self.show_scroll_index,
|
||||
);
|
||||
}
|
||||
|
||||
fn update_data(&mut self, data_collection: &DataCollection) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use tui::{
|
||||
layout::Rect,
|
||||
text::Span,
|
||||
widgets::{Block, Borders},
|
||||
};
|
||||
@ -11,6 +12,7 @@ pub struct BlockBuilder {
|
||||
selected: bool,
|
||||
expanded: bool,
|
||||
name: &'static str,
|
||||
hide_title: bool,
|
||||
extra_text: Option<String>,
|
||||
}
|
||||
|
||||
@ -22,6 +24,7 @@ impl BlockBuilder {
|
||||
selected: false,
|
||||
expanded: false,
|
||||
name,
|
||||
hide_title: false,
|
||||
extra_text: None,
|
||||
}
|
||||
}
|
||||
@ -39,8 +42,8 @@ impl BlockBuilder {
|
||||
}
|
||||
|
||||
/// 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);
|
||||
pub fn extra_text(mut self, extra_text: Option<String>) -> Self {
|
||||
self.extra_text = extra_text;
|
||||
self
|
||||
}
|
||||
|
||||
@ -50,9 +53,16 @@ impl BlockBuilder {
|
||||
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);
|
||||
/// Forcibly hides the title of the built [`Block`].
|
||||
pub fn hide_title(mut self, hide_title: bool) -> Self {
|
||||
self.hide_title = hide_title;
|
||||
self
|
||||
}
|
||||
|
||||
/// Converts the [`BlockBuilder`] into an actual [`Block`].
|
||||
pub fn build(self, painter: &Painter, area: Rect) -> Block<'static> {
|
||||
let has_title = !self.hide_title
|
||||
&& (self.borders.contains(Borders::TOP) || self.borders.contains(Borders::BOTTOM));
|
||||
|
||||
let block = Block::default()
|
||||
.border_style(if self.selected {
|
||||
@ -62,11 +72,54 @@ impl BlockBuilder {
|
||||
})
|
||||
.borders(self.borders);
|
||||
|
||||
if has_top_bottom_border {
|
||||
block.title(Span::styled(
|
||||
let inner_width = block.inner(area).width as usize;
|
||||
|
||||
if has_title {
|
||||
let name = Span::styled(
|
||||
format!(" {} ", self.name),
|
||||
painter.colours.widget_title_style,
|
||||
))
|
||||
);
|
||||
let mut title_len = name.width();
|
||||
let mut title = vec![name, Span::from(""), Span::from(""), Span::from("")];
|
||||
|
||||
if self.expanded {
|
||||
const EXPAND_TEXT: &str = " Esc to go back ";
|
||||
const EXPAND_TEXT_LEN: usize = EXPAND_TEXT.len();
|
||||
|
||||
let expand_span =
|
||||
Span::styled(EXPAND_TEXT, painter.colours.highlighted_border_style);
|
||||
|
||||
if title_len + EXPAND_TEXT_LEN <= inner_width {
|
||||
title_len += EXPAND_TEXT_LEN;
|
||||
title[3] = expand_span;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(extra_text) = self.extra_text {
|
||||
let extra_span = Span::styled(
|
||||
format!("{} ", extra_text),
|
||||
painter.colours.widget_title_style,
|
||||
);
|
||||
let width = extra_span.width();
|
||||
if title_len + width <= inner_width {
|
||||
title_len += width;
|
||||
title[1] = extra_span;
|
||||
}
|
||||
}
|
||||
|
||||
if self.expanded {
|
||||
let difference = inner_width.saturating_sub(title_len);
|
||||
title[2] = Span::styled(
|
||||
"─".repeat(difference),
|
||||
if self.selected {
|
||||
painter.colours.highlighted_border_style
|
||||
} else {
|
||||
painter.colours.border_style
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
block.title(title)
|
||||
} else {
|
||||
block
|
||||
}
|
||||
|
@ -336,7 +336,7 @@ impl Painter {
|
||||
.get_mut(&app_state.selected_widget)
|
||||
{
|
||||
current_widget.set_bounds(draw_area);
|
||||
current_widget.draw(self, f, draw_area, true);
|
||||
current_widget.draw(self, f, draw_area, true, true);
|
||||
}
|
||||
} else {
|
||||
/// A simple traversal through the `arena`, drawing all leaf elements.
|
||||
@ -398,12 +398,13 @@ impl Painter {
|
||||
f,
|
||||
remaining_area,
|
||||
selected_id == to_draw_node,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
widget.set_bounds(area);
|
||||
widget.draw(painter, f, area, selected_id == node);
|
||||
widget.draw(painter, f, area, selected_id == node, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user