Cleaned up some code with some macros
This commit is contained in:
@@ -62,3 +62,18 @@ fn handle_prompt_toggle(app: &mut App, key: &Key) {
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! handle_text_box_keys {
|
||||||
|
($self:expr, $key:expr, $input:expr) => {
|
||||||
|
match $self.key {
|
||||||
|
_ if *$key == DEFAULT_KEYBINDINGS.backspace.key => {
|
||||||
|
$input.pop();
|
||||||
|
}
|
||||||
|
Key::Char(character) => {
|
||||||
|
$input.push(*character);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
|||||||
use crate::models::radarr_models::{MinimumAvailability, Monitor};
|
use crate::models::radarr_models::{MinimumAvailability, Monitor};
|
||||||
use crate::models::{Scrollable, StatefulTable};
|
use crate::models::{Scrollable, StatefulTable};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{App, Key};
|
use crate::{handle_text_box_keys, App, Key};
|
||||||
|
|
||||||
pub(super) struct AddMovieHandler<'a> {
|
pub(super) struct AddMovieHandler<'a> {
|
||||||
key: &'a Key,
|
key: &'a Key,
|
||||||
@@ -259,15 +259,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
|
|||||||
fn handle_char_key_event(&mut self) {
|
fn handle_char_key_event(&mut self) {
|
||||||
let key = self.key;
|
let key = self.key;
|
||||||
if self.active_radarr_block == &ActiveRadarrBlock::AddMovieSearchInput {
|
if self.active_radarr_block == &ActiveRadarrBlock::AddMovieSearchInput {
|
||||||
match self.key {
|
handle_text_box_keys!(self, key, self.app.data.radarr_data.search)
|
||||||
_ if *key == DEFAULT_KEYBINDINGS.backspace.key => {
|
|
||||||
self.app.data.radarr_data.search.pop();
|
|
||||||
}
|
|
||||||
Key::Char(character) => {
|
|
||||||
self.app.data.radarr_data.search.push(*character);
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler
|
|||||||
use crate::models::Scrollable;
|
use crate::models::Scrollable;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::utils::strip_non_alphanumeric_characters;
|
use crate::utils::strip_non_alphanumeric_characters;
|
||||||
use crate::{App, Key};
|
use crate::{handle_text_box_keys, App, Key};
|
||||||
|
|
||||||
mod add_movie_handler;
|
mod add_movie_handler;
|
||||||
mod collection_details_handler;
|
mod collection_details_handler;
|
||||||
@@ -425,24 +425,12 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
|||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::SearchMovie | ActiveRadarrBlock::SearchCollection => match self.key {
|
ActiveRadarrBlock::SearchMovie | ActiveRadarrBlock::SearchCollection => {
|
||||||
_ if *key == DEFAULT_KEYBINDINGS.backspace.key => {
|
handle_text_box_keys!(self, key, self.app.data.radarr_data.search)
|
||||||
self.app.data.radarr_data.search.pop();
|
}
|
||||||
}
|
ActiveRadarrBlock::FilterMovies | ActiveRadarrBlock::FilterCollections => {
|
||||||
Key::Char(character) => {
|
handle_text_box_keys!(self, key, self.app.data.radarr_data.filter)
|
||||||
self.app.data.radarr_data.search.push(*character);
|
}
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
},
|
|
||||||
ActiveRadarrBlock::FilterMovies | ActiveRadarrBlock::FilterCollections => match self.key {
|
|
||||||
_ if *key == DEFAULT_KEYBINDINGS.backspace.key => {
|
|
||||||
self.app.data.radarr_data.filter.pop();
|
|
||||||
}
|
|
||||||
Key::Char(character) => {
|
|
||||||
self.app.data.radarr_data.filter.push(*character);
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
},
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::app::radarr::ActiveRadarrBlock;
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::{Scrollable, StatefulTable};
|
use crate::models::Scrollable;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
|
||||||
pub(super) struct MovieDetailsHandler<'a> {
|
pub(super) struct MovieDetailsHandler<'a> {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|||||||
+81
-147
@@ -27,172 +27,106 @@ pub trait Scrollable {
|
|||||||
fn scroll_to_bottom(&mut self);
|
fn scroll_to_bottom(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StatefulList<T> {
|
macro_rules! stateful_iterable {
|
||||||
pub state: ListState,
|
($name:ident, $state:ty) => {
|
||||||
pub items: Vec<T>,
|
pub struct $name<T> {
|
||||||
}
|
pub state: $state,
|
||||||
|
pub items: Vec<T>,
|
||||||
impl<T> Default for StatefulList<T> {
|
|
||||||
fn default() -> StatefulList<T> {
|
|
||||||
StatefulList {
|
|
||||||
state: ListState::default(),
|
|
||||||
items: Vec::new(),
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Scrollable for StatefulList<T> {
|
impl<T> Default for $name<T> {
|
||||||
fn scroll_down(&mut self) {
|
fn default() -> $name<T> {
|
||||||
let selected_row = match self.state.selected() {
|
$name {
|
||||||
Some(i) => {
|
state: <$state>::default(),
|
||||||
if i >= self.items.len() - 1 {
|
items: Vec::new(),
|
||||||
0
|
|
||||||
} else {
|
|
||||||
i + 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => 0,
|
}
|
||||||
};
|
|
||||||
|
|
||||||
self.state.select(Some(selected_row));
|
impl<T> Scrollable for $name<T> {
|
||||||
}
|
fn scroll_down(&mut self) {
|
||||||
|
let selected_row = match self.state.selected() {
|
||||||
|
Some(i) => {
|
||||||
|
if i >= self.items.len() - 1 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
|
||||||
fn scroll_up(&mut self) {
|
self.state.select(Some(selected_row));
|
||||||
let selected_row = match self.state.selected() {
|
}
|
||||||
Some(i) => {
|
|
||||||
if i == 0 {
|
fn scroll_up(&mut self) {
|
||||||
self.items.len() - 1
|
let selected_row = match self.state.selected() {
|
||||||
} else {
|
Some(i) => {
|
||||||
i - 1
|
if i == 0 {
|
||||||
|
self.items.len() - 1
|
||||||
|
} else {
|
||||||
|
i - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.state.select(Some(selected_row));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scroll_to_top(&mut self) {
|
||||||
|
self.state.select(Some(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scroll_to_bottom(&mut self) {
|
||||||
|
self.state.select(Some(self.items.len() - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> $name<T>
|
||||||
|
where
|
||||||
|
T: Clone + PartialEq + Eq + Debug,
|
||||||
|
{
|
||||||
|
pub fn set_items(&mut self, items: Vec<T>) {
|
||||||
|
let items_len = items.len();
|
||||||
|
self.items = items;
|
||||||
|
if !self.items.is_empty() {
|
||||||
|
let selected_row = self.state.selected().map_or(0, |i| {
|
||||||
|
if i > 0 && i < items_len {
|
||||||
|
i
|
||||||
|
} else if i >= items_len {
|
||||||
|
items_len - 1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.state.select(Some(selected_row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.state.select(Some(selected_row));
|
pub fn current_selection(&self) -> &T {
|
||||||
}
|
&self.items[self.state.selected().unwrap_or(0)]
|
||||||
|
}
|
||||||
|
|
||||||
fn scroll_to_top(&mut self) {
|
pub fn current_selection_clone(&self) -> T {
|
||||||
self.state.select(Some(0));
|
self.items[self.state.selected().unwrap_or(0)].clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_to_bottom(&mut self) {
|
|
||||||
self.state.select(Some(self.items.len() - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone + PartialEq + Eq + Debug> StatefulList<T> {
|
|
||||||
pub fn set_items(&mut self, items: Vec<T>) {
|
|
||||||
let items_len = items.len();
|
|
||||||
self.items = items;
|
|
||||||
if !self.items.is_empty() {
|
|
||||||
let selected_row = self.state.selected().map_or(0, |i| {
|
|
||||||
if i > 0 && i < items_len {
|
|
||||||
i
|
|
||||||
} else if i >= items_len {
|
|
||||||
items_len - 1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.state.select(Some(selected_row));
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
pub fn current_selection(&self) -> &T {
|
|
||||||
&self.items[self.state.selected().unwrap_or(0)]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_selection_clone(&self) -> T {
|
|
||||||
self.items[self.state.selected().unwrap_or(0)].clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StatefulTable<T> {
|
stateful_iterable!(StatefulList, ListState);
|
||||||
pub state: TableState,
|
stateful_iterable!(StatefulTable, TableState);
|
||||||
pub items: Vec<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Default for StatefulTable<T> {
|
|
||||||
fn default() -> StatefulTable<T> {
|
|
||||||
StatefulTable {
|
|
||||||
state: TableState::default(),
|
|
||||||
items: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone + PartialEq + Eq + Debug> StatefulTable<T> {
|
|
||||||
pub fn set_items(&mut self, items: Vec<T>) {
|
|
||||||
let items_len = items.len();
|
|
||||||
self.items = items;
|
|
||||||
if !self.items.is_empty() {
|
|
||||||
let selected_row = self.state.selected().map_or(0, |i| {
|
|
||||||
if i > 0 && i < items_len {
|
|
||||||
i
|
|
||||||
} else if i >= items_len {
|
|
||||||
items_len - 1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
});
|
|
||||||
self.state.select(Some(selected_row));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_selection(&self) -> &T {
|
|
||||||
&self.items[self.state.selected().unwrap_or(0)]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn current_selection_clone(&self) -> T {
|
|
||||||
self.items[self.state.selected().unwrap_or(0)].clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
impl<T> StatefulTable<T>
|
||||||
|
where
|
||||||
|
T: Clone + PartialEq + Eq + Debug,
|
||||||
|
{
|
||||||
pub fn select_index(&mut self, index: Option<usize>) {
|
pub fn select_index(&mut self, index: Option<usize>) {
|
||||||
self.state.select(index);
|
self.state.select(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Scrollable for StatefulTable<T> {
|
|
||||||
fn scroll_down(&mut self) {
|
|
||||||
let selected_row = match self.state.selected() {
|
|
||||||
Some(i) => {
|
|
||||||
if i >= self.items.len() - 1 {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
i + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.state.select(Some(selected_row));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scroll_up(&mut self) {
|
|
||||||
let selected_row = match self.state.selected() {
|
|
||||||
Some(i) => {
|
|
||||||
if i == 0 {
|
|
||||||
self.items.len() - 1
|
|
||||||
} else {
|
|
||||||
i - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.state.select(Some(selected_row));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scroll_to_top(&mut self) {
|
|
||||||
self.state.select(Some(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scroll_to_bottom(&mut self) {
|
|
||||||
self.state.select(Some(self.items.len() - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ScrollableText {
|
pub struct ScrollableText {
|
||||||
pub items: Vec<String>,
|
pub items: Vec<String>,
|
||||||
|
|||||||
+6
-10
@@ -1,6 +1,5 @@
|
|||||||
use tui::backend::Backend;
|
use tui::backend::Backend;
|
||||||
use tui::layout::{Alignment, Constraint, Rect};
|
use tui::layout::{Alignment, Constraint, Rect};
|
||||||
use tui::style::Modifier;
|
|
||||||
use tui::text::{Span, Spans, Text};
|
use tui::text::{Span, Spans, Text};
|
||||||
use tui::widgets::Paragraph;
|
use tui::widgets::Paragraph;
|
||||||
use tui::widgets::Row;
|
use tui::widgets::Row;
|
||||||
@@ -14,10 +13,11 @@ use crate::app::App;
|
|||||||
use crate::models::{Route, StatefulList, StatefulTable, TabState};
|
use crate::models::{Route, StatefulList, StatefulTable, TabState};
|
||||||
use crate::ui::utils::{
|
use crate::ui::utils::{
|
||||||
borderless_block, centered_rect, horizontal_chunks, horizontal_chunks_with_margin, layout_block,
|
borderless_block, centered_rect, horizontal_chunks, horizontal_chunks_with_margin, layout_block,
|
||||||
layout_block_top_border, layout_button_paragraph, layout_button_paragraph_borderless, logo_block,
|
layout_block_top_border, layout_button_paragraph, layout_button_paragraph_borderless,
|
||||||
style_button_highlight, style_default_bold, style_failure, style_help, style_highlight,
|
layout_paragraph_borderless, logo_block, style_button_highlight, style_default_bold,
|
||||||
style_primary, style_secondary, style_system_function, title_block, title_block_centered,
|
style_failure, style_help, style_highlight, style_primary, style_secondary,
|
||||||
vertical_chunks, vertical_chunks_with_margin,
|
style_system_function, title_block, title_block_centered, vertical_chunks,
|
||||||
|
vertical_chunks_with_margin,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod radarr_ui;
|
mod radarr_ui;
|
||||||
@@ -338,11 +338,7 @@ pub fn draw_prompt_box_with_content<B: Backend>(
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let prompt_paragraph = Paragraph::new(Text::from(prompt))
|
let prompt_paragraph = layout_paragraph_borderless(prompt);
|
||||||
.block(borderless_block())
|
|
||||||
.style(style_primary().add_modifier(Modifier::BOLD))
|
|
||||||
.wrap(Wrap { trim: false })
|
|
||||||
.alignment(Alignment::Center);
|
|
||||||
f.render_widget(prompt_paragraph, chunks[0]);
|
f.render_widget(prompt_paragraph, chunks[0]);
|
||||||
|
|
||||||
let horizontal_chunks = horizontal_chunks(
|
let horizontal_chunks = horizontal_chunks(
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
use tui::backend::Backend;
|
use tui::backend::Backend;
|
||||||
use tui::layout::{Alignment, Constraint, Rect};
|
use tui::layout::{Alignment, Constraint, Rect};
|
||||||
use tui::style::Modifier;
|
|
||||||
use tui::text::Text;
|
use tui::text::Text;
|
||||||
use tui::widgets::{Cell, ListItem, Paragraph, Row, Wrap};
|
use tui::widgets::{Cell, ListItem, Paragraph, Row};
|
||||||
use tui::Frame;
|
use tui::Frame;
|
||||||
|
|
||||||
use crate::app::radarr::ActiveRadarrBlock;
|
use crate::app::radarr::ActiveRadarrBlock;
|
||||||
use crate::models::radarr_models::AddMovieSearchResult;
|
use crate::models::radarr_models::AddMovieSearchResult;
|
||||||
use crate::models::Route;
|
use crate::models::Route;
|
||||||
use crate::ui::utils::{
|
use crate::ui::utils::{
|
||||||
borderless_block, get_width, horizontal_chunks, layout_block, show_cursor, style_default,
|
borderless_block, get_width, horizontal_chunks, layout_block, layout_paragraph_borderless,
|
||||||
style_help, style_primary, title_block_centered, vertical_chunks_with_margin,
|
show_cursor, style_default, style_help, style_primary, title_block_centered,
|
||||||
|
vertical_chunks_with_margin,
|
||||||
};
|
};
|
||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
draw_button, draw_drop_down_list, draw_drop_down_menu_button, draw_drop_down_popup,
|
draw_button, draw_drop_down_list, draw_drop_down_menu_button, draw_drop_down_popup,
|
||||||
@@ -293,11 +293,7 @@ fn draw_confirmation_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, pro
|
|||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
let prompt_paragraph = Paragraph::new(Text::from(prompt))
|
let prompt_paragraph = layout_paragraph_borderless(&prompt);
|
||||||
.block(borderless_block())
|
|
||||||
.style(style_primary().add_modifier(Modifier::BOLD))
|
|
||||||
.wrap(Wrap { trim: false })
|
|
||||||
.alignment(Alignment::Center);
|
|
||||||
f.render_widget(prompt_paragraph, chunks[0]);
|
f.render_widget(prompt_paragraph, chunks[0]);
|
||||||
|
|
||||||
let horizontal_chunks = horizontal_chunks(
|
let horizontal_chunks = horizontal_chunks(
|
||||||
@@ -331,13 +327,13 @@ fn draw_confirmation_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, pro
|
|||||||
draw_button(
|
draw_button(
|
||||||
f,
|
f,
|
||||||
horizontal_chunks[0],
|
horizontal_chunks[0],
|
||||||
"Yes",
|
"Add",
|
||||||
*yes_no_value && highlight_yes_no,
|
*yes_no_value && highlight_yes_no,
|
||||||
);
|
);
|
||||||
draw_button(
|
draw_button(
|
||||||
f,
|
f,
|
||||||
horizontal_chunks[1],
|
horizontal_chunks[1],
|
||||||
"No",
|
"Cancel",
|
||||||
!*yes_no_value && highlight_yes_no,
|
!*yes_no_value && highlight_yes_no,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ use crate::models::radarr_models::{Credit, MovieHistoryItem, Release};
|
|||||||
use crate::models::Route;
|
use crate::models::Route;
|
||||||
use crate::ui::utils::{
|
use crate::ui::utils::{
|
||||||
borderless_block, get_width, layout_block_bottom_border, layout_block_top_border,
|
borderless_block, get_width, layout_block_bottom_border, layout_block_top_border,
|
||||||
spans_info_default, spans_info_primary, style_bold, style_default, style_failure, style_primary,
|
spans_info_default, style_bold, style_default, style_failure, style_primary, style_success,
|
||||||
style_success, style_warning, vertical_chunks,
|
style_warning, vertical_chunks,
|
||||||
};
|
};
|
||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
draw_medium_popup_over, draw_prompt_box, draw_prompt_box_with_content, draw_prompt_popup_over,
|
draw_prompt_box, draw_prompt_box_with_content, draw_prompt_popup_over, draw_small_popup_over,
|
||||||
draw_small_popup_over, draw_table, draw_tabs, loading, TableProps,
|
draw_table, draw_tabs, loading, TableProps,
|
||||||
};
|
};
|
||||||
use crate::utils::convert_to_gb;
|
use crate::utils::convert_to_gb;
|
||||||
|
|
||||||
|
|||||||
+9
-1
@@ -2,7 +2,7 @@ use tui::backend::Backend;
|
|||||||
use tui::layout::{Alignment, Constraint, Direction, Layout, Rect};
|
use tui::layout::{Alignment, Constraint, Direction, Layout, Rect};
|
||||||
use tui::style::{Color, Modifier, Style};
|
use tui::style::{Color, Modifier, Style};
|
||||||
use tui::text::{Span, Spans, Text};
|
use tui::text::{Span, Spans, Text};
|
||||||
use tui::widgets::{Block, Borders, LineGauge, Paragraph};
|
use tui::widgets::{Block, Borders, LineGauge, Paragraph, Wrap};
|
||||||
use tui::{symbols, Frame};
|
use tui::{symbols, Frame};
|
||||||
|
|
||||||
pub fn horizontal_chunks(constraints: Vec<Constraint>, size: Rect) -> Vec<Rect> {
|
pub fn horizontal_chunks(constraints: Vec<Constraint>, size: Rect) -> Vec<Rect> {
|
||||||
@@ -83,6 +83,14 @@ pub fn layout_button_paragraph_borderless(
|
|||||||
.style(style_button_highlight(is_selected))
|
.style(style_button_highlight(is_selected))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn layout_paragraph_borderless(string: &str) -> Paragraph {
|
||||||
|
Paragraph::new(Text::from(string))
|
||||||
|
.block(borderless_block())
|
||||||
|
.style(style_primary().add_modifier(Modifier::BOLD))
|
||||||
|
.wrap(Wrap { trim: false })
|
||||||
|
.alignment(Alignment::Center)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn borderless_block<'a>() -> Block<'a> {
|
pub fn borderless_block<'a>() -> Block<'a> {
|
||||||
Block::default()
|
Block::default()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user