tui_realm_stdlib/components/
paragraph.rs1use tuirealm::command::{Cmd, CmdResult};
2use tuirealm::component::Component;
3use tuirealm::props::{
4 AttrValue, Attribute, Borders, Color, HorizontalAlignment, Props, QueryResult, Style,
5 TextModifiers, TextStatic, Title,
6};
7use tuirealm::ratatui::Frame;
8use tuirealm::ratatui::layout::Rect;
9use tuirealm::ratatui::widgets::{Paragraph as TuiParagraph, Wrap};
10use tuirealm::state::State;
11
12use crate::prop_ext::CommonProps;
13use crate::utils;
14
15#[derive(Debug, Default)]
22#[must_use]
23pub struct Paragraph {
24 common: CommonProps,
25 props: Props,
26}
27
28impl Paragraph {
29 pub fn foreground(mut self, fg: Color) -> Self {
31 self.attr(Attribute::Foreground, AttrValue::Color(fg));
32 self
33 }
34
35 pub fn background(mut self, bg: Color) -> Self {
37 self.attr(Attribute::Background, AttrValue::Color(bg));
38 self
39 }
40
41 pub fn modifiers(mut self, m: TextModifiers) -> Self {
43 self.attr(Attribute::TextProps, AttrValue::TextModifiers(m));
44 self
45 }
46
47 pub fn style(mut self, style: Style) -> Self {
51 self.attr(Attribute::Style, AttrValue::Style(style));
52 self
53 }
54
55 pub fn borders(mut self, b: Borders) -> Self {
57 self.attr(Attribute::Borders, AttrValue::Borders(b));
58 self
59 }
60
61 pub fn alignment_horizontal(mut self, a: HorizontalAlignment) -> Self {
63 self.attr(
64 Attribute::AlignmentHorizontal,
65 AttrValue::AlignmentHorizontal(a),
66 );
67 self
68 }
69
70 pub fn title<T: Into<Title>>(mut self, title: T) -> Self {
72 self.attr(Attribute::Title, AttrValue::Title(title.into()));
73 self
74 }
75
76 pub fn text<T>(mut self, text: T) -> Self
78 where
79 T: Into<TextStatic>,
80 {
81 self.attr(Attribute::Text, AttrValue::Text(text.into()));
82 self
83 }
84
85 pub fn wrap_trim(mut self, wrap: bool) -> Self {
89 self.attr(Attribute::TextWrap, AttrValue::Flag(wrap));
90 self
91 }
92}
93
94impl Component for Paragraph {
95 fn view(&mut self, render: &mut Frame, area: Rect) {
96 if !self.common.display {
97 return;
98 }
99
100 let text = self
102 .props
103 .get(Attribute::Text)
104 .and_then(AttrValue::as_text)
105 .map(utils::borrow_clone_text)
106 .unwrap_or_default();
107
108 let alignment: HorizontalAlignment = self
110 .props
111 .get(Attribute::AlignmentHorizontal)
112 .and_then(AttrValue::as_alignment_horizontal)
113 .unwrap_or(HorizontalAlignment::Left);
114 let trim = self
116 .props
117 .get(Attribute::TextWrap)
118 .and_then(AttrValue::as_flag)
119 .unwrap_or_default();
120
121 let mut paragraph = TuiParagraph::new(text)
122 .style(self.common.style)
123 .alignment(alignment)
124 .wrap(Wrap { trim });
125
126 if let Some(block) = self.common.get_block() {
127 paragraph = paragraph.block(block);
128 }
129
130 render.render_widget(paragraph, area);
131 }
132
133 fn query<'a>(&'a self, attr: Attribute) -> Option<QueryResult<'a>> {
134 if let Some(value) = self.common.get_for_query(attr) {
135 return Some(value);
136 }
137
138 self.props.get_for_query(attr)
139 }
140
141 fn attr(&mut self, attr: Attribute, value: AttrValue) {
142 if let Some(value) = self.common.set(attr, value) {
143 self.props.set(attr, value);
144 }
145 }
146
147 fn state(&self) -> State {
148 State::None
149 }
150
151 fn perform(&mut self, cmd: Cmd) -> CmdResult {
152 CmdResult::Invalid(cmd)
153 }
154}
155
156#[cfg(test)]
157mod tests {
158
159 use pretty_assertions::assert_eq;
160 use tuirealm::ratatui::style::Stylize;
161 use tuirealm::ratatui::text::{Line, Text};
162
163 use super::*;
164
165 #[test]
166 fn test_components_paragraph() {
167 let component = Paragraph::default()
168 .background(Color::Blue)
169 .foreground(Color::Red)
170 .modifiers(TextModifiers::BOLD)
171 .alignment_horizontal(HorizontalAlignment::Center)
172 .text(vec![
173 Line::from("Press "),
174 Line::from("<ESC>").fg(Color::Cyan).bold(),
175 Line::from(" to quit"),
176 ])
177 .wrap_trim(true)
178 .title(Title::from("title").alignment(HorizontalAlignment::Center));
179 assert_eq!(component.state(), State::None);
181 }
182
183 #[test]
184 fn various_text_types() {
185 let _ = Paragraph::default().text(vec![Line::raw("hello")]);
187 let _ = Paragraph::default().text(Text::from("hello"));
189 }
190}