Refactored table filtering and searching so that they are now relative to the table being filtered/searched on. Also created two new widgets for error messages and popups to make life easier moving forward. Going to refactor table sorting into StatefulTable's as well so all tables can be searched, filtered, and sorted moving forwards.
This commit is contained in:
@@ -40,7 +40,7 @@ impl<'a> Button<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
fn render_button_with_icon(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_button_with_icon(self, area: Rect, buf: &mut Buffer) {
|
||||
let [title_area, icon_area] = Layout::horizontal([
|
||||
Constraint::Length(self.title.len() as u16),
|
||||
Constraint::Percentage(25),
|
||||
@@ -63,7 +63,7 @@ impl<'a> Button<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_labeled_button(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_labeled_button(self, area: Rect, buf: &mut Buffer) {
|
||||
let [label_area, button_area] =
|
||||
Layout::horizontal([Constraint::Percentage(48), Constraint::Percentage(48)]).areas(area);
|
||||
let label_paragraph = Paragraph::new(Text::from(format!("\n{}: ", self.label.unwrap())))
|
||||
@@ -79,7 +79,7 @@ impl<'a> Button<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_button(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_button(self, area: Rect, buf: &mut Buffer) {
|
||||
Paragraph::new(Text::from(self.title))
|
||||
.block(layout_block())
|
||||
.alignment(Alignment::Center)
|
||||
|
||||
@@ -31,7 +31,7 @@ impl<'a> Checkbox<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
fn render_checkbox(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_checkbox(self, area: Rect, buf: &mut Buffer) {
|
||||
let check = if self.is_checked { "✔" } else { "" };
|
||||
let [label_area, checkbox_area] =
|
||||
Layout::horizontal([Constraint::Percentage(48), Constraint::Percentage(48)]).areas(area);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
use crate::ui::styles::ManagarrStyle;
|
||||
use crate::ui::utils::title_block_centered;
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::{Alignment, Rect};
|
||||
use ratatui::style::Stylize;
|
||||
use ratatui::text::Text;
|
||||
use ratatui::widgets::{Paragraph, Widget};
|
||||
|
||||
pub struct ErrorMessage<'a> {
|
||||
text: Text<'a>,
|
||||
}
|
||||
|
||||
impl<'a> ErrorMessage<'a> {
|
||||
pub fn new<T>(message: T) -> Self
|
||||
where
|
||||
T: Into<Text<'a>>,
|
||||
{
|
||||
ErrorMessage {
|
||||
text: message.into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn render_error_message(self, area: Rect, buf: &mut Buffer) {
|
||||
Paragraph::new(self.text)
|
||||
.failure()
|
||||
.alignment(Alignment::Center)
|
||||
.block(title_block_centered("Error").failure().bold())
|
||||
.render(area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Widget for ErrorMessage<'a> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
self.render_error_message(area, buf);
|
||||
}
|
||||
}
|
||||
@@ -47,12 +47,12 @@ impl<'a> InputBox<'a> {
|
||||
self.label = Some(label);
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
pub fn offset(mut self, offset: usize) -> InputBox<'a> {
|
||||
self.offset = offset;
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
pub fn cursor_after_string(mut self, cursor_after_string: bool) -> InputBox<'a> {
|
||||
self.cursor_after_string = cursor_after_string;
|
||||
self
|
||||
@@ -89,7 +89,7 @@ impl<'a> InputBox<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_input_box(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_input_box(self, area: Rect, buf: &mut Buffer) {
|
||||
let style =
|
||||
if matches!(self.is_highlighted, Some(true)) && matches!(self.is_selected, Some(false)) {
|
||||
Style::new().system_function().bold()
|
||||
@@ -99,7 +99,7 @@ impl<'a> InputBox<'a> {
|
||||
|
||||
let input_box_paragraph = Paragraph::new(Text::from(self.content))
|
||||
.style(style)
|
||||
.block(self.block.clone());
|
||||
.block(self.block);
|
||||
|
||||
if let Some(label) = self.label {
|
||||
let [label_area, text_box_area] =
|
||||
|
||||
@@ -14,14 +14,14 @@ impl<'a> LoadingBlock<'a> {
|
||||
Self { is_loading, block }
|
||||
}
|
||||
|
||||
fn render_loading_block(&self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_loading_block(self, area: Rect, buf: &mut Buffer) {
|
||||
if self.is_loading {
|
||||
Paragraph::new(Text::from("\n\n Loading ...\n\n"))
|
||||
.system_function()
|
||||
.block(self.block.clone())
|
||||
.block(self.block)
|
||||
.render(area, buf);
|
||||
} else {
|
||||
self.block.clone().render(area, buf);
|
||||
self.block.render(area, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,12 +86,12 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn highlight_rows(mut self, hightlight_rows: bool) -> Self {
|
||||
self.highlight_rows = hightlight_rows;
|
||||
pub fn highlight_rows(mut self, highlight_rows: bool) -> Self {
|
||||
self.highlight_rows = highlight_rows;
|
||||
self
|
||||
}
|
||||
|
||||
fn render_table(&mut self, area: Rect, buf: &mut Buffer) {
|
||||
fn render_table(self, area: Rect, buf: &mut Buffer) {
|
||||
let table_area = if let Some(ref footer) = self.footer {
|
||||
let [content_area, footer_area] =
|
||||
Layout::vertical([Constraint::Fill(0), Constraint::Length(2)])
|
||||
@@ -109,18 +109,26 @@ where
|
||||
};
|
||||
let loading_block = LoadingBlock::new(self.is_loading, self.block.clone());
|
||||
|
||||
if let Some(ref mut content) = self.content {
|
||||
if !content.items.is_empty() {
|
||||
let rows = content.items.iter().map(&self.row_mapper);
|
||||
if let Some(content) = self.content {
|
||||
let (table_contents, table_state) = if content.filtered_items.is_some() {
|
||||
(
|
||||
content.filtered_items.as_ref().unwrap(),
|
||||
content.filtered_state.as_mut().unwrap(),
|
||||
)
|
||||
} else {
|
||||
(&content.items, &mut content.state)
|
||||
};
|
||||
if !table_contents.is_empty() {
|
||||
let rows = table_contents.iter().map(&self.row_mapper);
|
||||
|
||||
let headers = Row::new(self.table_headers.clone())
|
||||
let headers = Row::new(self.table_headers)
|
||||
.default()
|
||||
.bold()
|
||||
.bottom_margin(0);
|
||||
|
||||
let mut table = Table::new(rows, &self.constraints)
|
||||
.header(headers)
|
||||
.block(self.block.clone());
|
||||
.block(self.block);
|
||||
|
||||
if self.highlight_rows {
|
||||
table = table
|
||||
@@ -128,7 +136,7 @@ where
|
||||
.highlight_symbol(HIGHLIGHT_SYMBOL);
|
||||
}
|
||||
|
||||
StatefulWidget::render(table, table_area, buf, &mut content.state);
|
||||
StatefulWidget::render(table, table_area, buf, table_state);
|
||||
} else {
|
||||
loading_block.render(table_area, buf);
|
||||
}
|
||||
@@ -142,7 +150,7 @@ impl<'a, T, F> Widget for ManagarrTable<'a, T, F>
|
||||
where
|
||||
F: Fn(&T) -> Row<'a>,
|
||||
{
|
||||
fn render(mut self, area: Rect, buf: &mut Buffer) {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
self.render_table(area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
pub(super) mod button;
|
||||
pub(super) mod checkbox;
|
||||
pub(super) mod error_message;
|
||||
pub(super) mod input_box;
|
||||
pub(super) mod loading_block;
|
||||
pub(super) mod managarr_table;
|
||||
pub(super) mod popup;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
use crate::ui::utils::{background_block, centered_rect};
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::widgets::{Clear, Widget};
|
||||
|
||||
pub struct Popup<T: Widget> {
|
||||
widget: T,
|
||||
percent_x: u16,
|
||||
percent_y: u16,
|
||||
}
|
||||
|
||||
impl<T: Widget> Popup<T> {
|
||||
pub fn new(widget: T, percent_x: u16, percent_y: u16) -> Self {
|
||||
Self {
|
||||
widget,
|
||||
percent_x,
|
||||
percent_y,
|
||||
}
|
||||
}
|
||||
|
||||
fn render_popup(self, area: Rect, buf: &mut Buffer) {
|
||||
let popup_area = centered_rect(self.percent_x, self.percent_y, area);
|
||||
|
||||
Clear.render(popup_area, buf);
|
||||
background_block().render(popup_area, buf);
|
||||
self.widget.render(popup_area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Widget> Widget for Popup<T> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
self.render_popup(area, buf);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user