Replaced all list uses with the SelectableList widget and popup widget. Simplified more popups to use the widgets
This commit is contained in:
+51
-8
@@ -1,37 +1,80 @@
|
||||
use crate::ui::utils::{background_block, centered_rect};
|
||||
use crate::ui::styles::ManagarrStyle;
|
||||
use crate::ui::utils::{background_block, centered_rect, layout_block_top_border};
|
||||
use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::widgets::{Clear, Widget};
|
||||
use ratatui::layout::{Alignment, Constraint, Layout, Rect};
|
||||
use ratatui::prelude::Text;
|
||||
use ratatui::widgets::{Block, Clear, Paragraph, Widget};
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "popup_tests.rs"]
|
||||
mod popup_tests;
|
||||
|
||||
pub struct Popup<T: Widget> {
|
||||
pub struct Popup<'a, T: Widget> {
|
||||
widget: T,
|
||||
percent_x: u16,
|
||||
percent_y: u16,
|
||||
block: Option<Block<'a>>,
|
||||
footer: Option<&'a str>,
|
||||
footer_alignment: Alignment,
|
||||
}
|
||||
|
||||
impl<T: Widget> Popup<T> {
|
||||
impl<'a, T: Widget> Popup<'a, T> {
|
||||
pub fn new(widget: T, percent_x: u16, percent_y: u16) -> Self {
|
||||
Self {
|
||||
widget,
|
||||
percent_x,
|
||||
percent_y,
|
||||
block: None,
|
||||
footer: None,
|
||||
footer_alignment: Alignment::Left,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn block(mut self, block: Block<'a>) -> Self {
|
||||
self.block = Some(block);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn footer(mut self, footer: &'a str) -> Self {
|
||||
self.footer = Some(footer);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn footer_alignment(mut self, alignment: Alignment) -> Self {
|
||||
self.footer_alignment = alignment;
|
||||
self
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if let Some(block) = self.block {
|
||||
block.render(popup_area, buf);
|
||||
}
|
||||
|
||||
let content_area = if let Some(footer) = self.footer {
|
||||
let [content_area, help_footer_area] =
|
||||
Layout::vertical([Constraint::Fill(0), Constraint::Length(2)])
|
||||
.margin(1)
|
||||
.areas(popup_area);
|
||||
|
||||
Paragraph::new(Text::from(format!(" {footer}").help()))
|
||||
.block(layout_block_top_border())
|
||||
.alignment(self.footer_alignment)
|
||||
.render(help_footer_area, buf);
|
||||
|
||||
content_area
|
||||
} else {
|
||||
popup_area
|
||||
};
|
||||
|
||||
self.widget.render(content_area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Widget> Widget for Popup<T> {
|
||||
impl<'a, T: Widget> Widget for Popup<'a, T> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
self.render_popup(area, buf);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
mod tests {
|
||||
use crate::ui::widgets::popup::Popup;
|
||||
use pretty_assertions::assert_eq;
|
||||
use ratatui::layout::Alignment;
|
||||
use ratatui::widgets::Block;
|
||||
|
||||
#[test]
|
||||
@@ -11,5 +12,44 @@ mod tests {
|
||||
assert_eq!(popup.widget, Block::new());
|
||||
assert_eq!(popup.percent_x, 50);
|
||||
assert_eq!(popup.percent_y, 50);
|
||||
assert_eq!(popup.block, None);
|
||||
assert_eq!(popup.footer, None);
|
||||
assert_eq!(popup.footer_alignment, Alignment::Left);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_popup_block() {
|
||||
let popup = Popup::new(Block::new(), 50, 50).block(Block::new());
|
||||
|
||||
assert_eq!(popup.block, Some(Block::new()));
|
||||
assert_eq!(popup.widget, Block::new());
|
||||
assert_eq!(popup.percent_x, 50);
|
||||
assert_eq!(popup.percent_y, 50);
|
||||
assert_eq!(popup.footer, None);
|
||||
assert_eq!(popup.footer_alignment, Alignment::Left);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_popup_footer() {
|
||||
let popup = Popup::new(Block::new(), 50, 50).footer("footer");
|
||||
|
||||
assert_eq!(popup.footer, Some("footer"));
|
||||
assert_eq!(popup.widget, Block::new());
|
||||
assert_eq!(popup.percent_x, 50);
|
||||
assert_eq!(popup.percent_y, 50);
|
||||
assert_eq!(popup.block, None);
|
||||
assert_eq!(popup.footer_alignment, Alignment::Left);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_popup_footer_alignment() {
|
||||
let popup = Popup::new(Block::new(), 50, 50).footer_alignment(Alignment::Center);
|
||||
|
||||
assert_eq!(popup.footer_alignment, Alignment::Center);
|
||||
assert_eq!(popup.widget, Block::new());
|
||||
assert_eq!(popup.percent_x, 50);
|
||||
assert_eq!(popup.percent_y, 50);
|
||||
assert_eq!(popup.block, None);
|
||||
assert_eq!(popup.footer, None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use ratatui::buffer::Buffer;
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::prelude::Widget;
|
||||
use ratatui::style::Style;
|
||||
use ratatui::widgets::{List, ListItem, StatefulWidget};
|
||||
use ratatui::widgets::{Block, List, ListItem, StatefulWidget};
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "selectable_list_tests.rs"]
|
||||
@@ -17,6 +17,8 @@ where
|
||||
{
|
||||
content: &'a mut StatefulList<T>,
|
||||
row_mapper: F,
|
||||
highlight_style: Style,
|
||||
block: Block<'a>,
|
||||
}
|
||||
|
||||
impl<'a, T, F> SelectableList<'a, T, F>
|
||||
@@ -27,15 +29,27 @@ where
|
||||
Self {
|
||||
content,
|
||||
row_mapper,
|
||||
highlight_style: Style::new().highlight(),
|
||||
block: layout_block(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn highlight_style(mut self, style: Style) -> Self {
|
||||
self.highlight_style = style;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn block(mut self, block: Block<'a>) -> Self {
|
||||
self.block = block;
|
||||
self
|
||||
}
|
||||
|
||||
fn render_list(self, area: Rect, buf: &mut Buffer) {
|
||||
let items: Vec<ListItem<'_>> = self.content.items.iter().map(&self.row_mapper).collect();
|
||||
|
||||
let selectable_list = List::new(items)
|
||||
.block(layout_block())
|
||||
.highlight_style(Style::new().highlight());
|
||||
.block(self.block)
|
||||
.highlight_style(self.highlight_style);
|
||||
|
||||
StatefulWidget::render(selectable_list, area, buf, &mut self.content.state);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::models::stateful_list::StatefulList;
|
||||
use crate::ui::styles::ManagarrStyle;
|
||||
use crate::ui::utils::{layout_block, title_block};
|
||||
use crate::ui::widgets::selectable_list::SelectableList;
|
||||
use pretty_assertions::assert_eq;
|
||||
use ratatui::style::{Style, Stylize};
|
||||
use ratatui::widgets::ListItem;
|
||||
|
||||
#[test]
|
||||
@@ -17,5 +20,41 @@ mod tests {
|
||||
let row_mapper = selectable_list.row_mapper;
|
||||
assert_eq!(selectable_list.content.items, items);
|
||||
assert_eq!(row_mapper(&"test"), ListItem::new("test"));
|
||||
assert_eq!(selectable_list.highlight_style, Style::new().highlight());
|
||||
assert_eq!(selectable_list.block, layout_block());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_selectable_list_highlight_style() {
|
||||
let items = vec!["test"];
|
||||
let mut stateful_list = StatefulList::default();
|
||||
stateful_list.set_items(items.clone());
|
||||
|
||||
let selectable_list =
|
||||
SelectableList::new(&mut stateful_list, |item| ListItem::new(item.to_string()))
|
||||
.highlight_style(Style::new().bold());
|
||||
|
||||
let row_mapper = selectable_list.row_mapper;
|
||||
assert_eq!(selectable_list.highlight_style, Style::new().bold());
|
||||
assert_eq!(selectable_list.content.items, items);
|
||||
assert_eq!(row_mapper(&"test"), ListItem::new("test"));
|
||||
assert_eq!(selectable_list.block, layout_block());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_selectable_list_block() {
|
||||
let items = vec!["test"];
|
||||
let mut stateful_list = StatefulList::default();
|
||||
stateful_list.set_items(items.clone());
|
||||
|
||||
let selectable_list =
|
||||
SelectableList::new(&mut stateful_list, |item| ListItem::new(item.to_string()))
|
||||
.block(title_block("test"));
|
||||
|
||||
let row_mapper = selectable_list.row_mapper;
|
||||
assert_eq!(selectable_list.block, title_block("test"));
|
||||
assert_eq!(selectable_list.content.items, items);
|
||||
assert_eq!(row_mapper(&"test"), ListItem::new("test"));
|
||||
assert_eq!(selectable_list.highlight_style, Style::new().highlight());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user