use tuirealm::command::{Cmd, CmdResult};
use tuirealm::component::Component;
use tuirealm::props::{
AttrValue, Attribute, Borders, Color, HorizontalAlignment, Props, QueryResult, Style,
TextModifiers, TextStatic, Title,
};
use tuirealm::ratatui::Frame;
use tuirealm::ratatui::layout::Rect;
use tuirealm::ratatui::widgets::{Paragraph as TuiParagraph, Wrap};
use tuirealm::state::State;
use crate::prop_ext::CommonProps;
use crate::utils;
#[derive(Debug, Default)]
#[must_use]
pub struct Paragraph {
common: CommonProps,
props: Props,
}
impl Paragraph {
pub fn foreground(mut self, fg: Color) -> Self {
self.attr(Attribute::Foreground, AttrValue::Color(fg));
self
}
pub fn background(mut self, bg: Color) -> Self {
self.attr(Attribute::Background, AttrValue::Color(bg));
self
}
pub fn modifiers(mut self, m: TextModifiers) -> Self {
self.attr(Attribute::TextProps, AttrValue::TextModifiers(m));
self
}
pub fn style(mut self, style: Style) -> Self {
self.attr(Attribute::Style, AttrValue::Style(style));
self
}
pub fn borders(mut self, b: Borders) -> Self {
self.attr(Attribute::Borders, AttrValue::Borders(b));
self
}
pub fn alignment_horizontal(mut self, a: HorizontalAlignment) -> Self {
self.attr(
Attribute::AlignmentHorizontal,
AttrValue::AlignmentHorizontal(a),
);
self
}
pub fn title<T: Into<Title>>(mut self, title: T) -> Self {
self.attr(Attribute::Title, AttrValue::Title(title.into()));
self
}
pub fn text<T>(mut self, text: T) -> Self
where
T: Into<TextStatic>,
{
self.attr(Attribute::Text, AttrValue::Text(text.into()));
self
}
pub fn wrap_trim(mut self, wrap: bool) -> Self {
self.attr(Attribute::TextWrap, AttrValue::Flag(wrap));
self
}
}
impl Component for Paragraph {
fn view(&mut self, render: &mut Frame, area: Rect) {
if !self.common.display {
return;
}
let text = self
.props
.get(Attribute::Text)
.and_then(AttrValue::as_text)
.map(utils::borrow_clone_text)
.unwrap_or_default();
let alignment: HorizontalAlignment = self
.props
.get(Attribute::AlignmentHorizontal)
.and_then(AttrValue::as_alignment_horizontal)
.unwrap_or(HorizontalAlignment::Left);
let trim = self
.props
.get(Attribute::TextWrap)
.and_then(AttrValue::as_flag)
.unwrap_or_default();
let mut paragraph = TuiParagraph::new(text)
.style(self.common.style)
.alignment(alignment)
.wrap(Wrap { trim });
if let Some(block) = self.common.get_block() {
paragraph = paragraph.block(block);
}
render.render_widget(paragraph, area);
}
fn query<'a>(&'a self, attr: Attribute) -> Option<QueryResult<'a>> {
if let Some(value) = self.common.get_for_query(attr) {
return Some(value);
}
self.props.get_for_query(attr)
}
fn attr(&mut self, attr: Attribute, value: AttrValue) {
if let Some(value) = self.common.set(attr, value) {
self.props.set(attr, value);
}
}
fn state(&self) -> State {
State::None
}
fn perform(&mut self, cmd: Cmd) -> CmdResult {
CmdResult::Invalid(cmd)
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use tuirealm::ratatui::style::Stylize;
use tuirealm::ratatui::text::{Line, Text};
use super::*;
#[test]
fn test_components_paragraph() {
let component = Paragraph::default()
.background(Color::Blue)
.foreground(Color::Red)
.modifiers(TextModifiers::BOLD)
.alignment_horizontal(HorizontalAlignment::Center)
.text(vec![
Line::from("Press "),
Line::from("<ESC>").fg(Color::Cyan).bold(),
Line::from(" to quit"),
])
.wrap_trim(true)
.title(Title::from("title").alignment(HorizontalAlignment::Center));
assert_eq!(component.state(), State::None);
}
#[test]
fn various_text_types() {
let _ = Paragraph::default().text(vec![Line::raw("hello")]);
let _ = Paragraph::default().text(Text::from("hello"));
}
}