tui_lipan/widgets/text/
mod.rs1mod layout;
4mod node;
5mod reconcile;
6
7pub use layout::measure_text_constrained;
8pub(crate) use layout::split_spans_on_newlines;
9pub use node::TextNode;
10pub use reconcile::reconcile_text;
11
12use std::sync::Arc;
13
14use crate::core::element::{Element, ElementKind};
15use crate::style::{Span, Style};
16
17#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
19pub enum Overflow {
20 #[default]
22 Auto,
23 Clip,
25 ClipStart,
27 Ellipsis,
29 Wrap,
31}
32
33#[derive(Clone, Debug)]
35pub struct Text {
36 pub spans: Vec<Span>,
38 pub style: Style,
40 pub overflow: Overflow,
42 pub width: crate::style::Length,
44 pub height: crate::style::Length,
46}
47
48impl Text {
49 pub fn new(content: impl Into<Arc<str>>) -> Self {
51 Self {
52 spans: vec![Span::new(content)],
53 style: Style::default(),
54 overflow: Overflow::Auto,
55 width: crate::style::Length::Auto,
56 height: crate::style::Length::Auto,
57 }
58 }
59
60 pub fn from_spans(spans: impl IntoIterator<Item = Span>) -> Self {
62 Self {
63 spans: spans.into_iter().collect(),
64 style: Style::default(),
65 overflow: Overflow::Auto,
66 width: crate::style::Length::Auto,
67 height: crate::style::Length::Auto,
68 }
69 }
70
71 pub fn from_ansi(input: &str) -> Self {
76 Self::from_spans(crate::style::ansi::parse_ansi(input))
77 }
78
79 pub fn span(mut self, span: impl Into<Span>) -> Self {
81 self.spans.push(span.into());
82 self
83 }
84
85 pub fn style(mut self, style: Style) -> Self {
87 self.style = style;
88 self
89 }
90
91 pub fn overflow(mut self, overflow: Overflow) -> Self {
93 self.overflow = overflow;
94 self
95 }
96
97 pub fn width(mut self, width: crate::style::Length) -> Self {
99 self.width = width;
100 self
101 }
102
103 pub fn height(mut self, height: crate::style::Length) -> Self {
105 self.height = height;
106 self
107 }
108
109 pub fn plain_content(&self) -> String {
111 let mut s = String::new();
112 for span in &self.spans {
113 s.push_str(&span.content);
114 }
115 s
116 }
117}
118
119impl From<TextNode> for Text {
121 fn from(node: TextNode) -> Self {
122 Self {
123 spans: node.spans,
124 style: node.style,
125 overflow: node.overflow,
126 width: node.widget_key.width,
127 height: node.widget_key.height,
128 }
129 }
130}
131
132impl From<Text> for Element {
133 fn from(value: Text) -> Self {
134 Element::new(ElementKind::Text(value))
135 }
136}
137
138impl Default for Text {
139 fn default() -> Self {
140 Self {
141 spans: Vec::new(),
142 style: Style::default(),
143 overflow: Overflow::Auto,
144 width: crate::style::Length::Auto,
145 height: crate::style::Length::Auto,
146 }
147 }
148}
149
150impl crate::layout::hash::LayoutHash for Text {
151 fn layout_hash(
152 &self,
153 hasher: &mut impl std::hash::Hasher,
154 _recurse: &dyn Fn(&Element) -> Option<u64>,
155 ) -> Option<()> {
156 use std::hash::Hash;
157 self.width.hash(hasher);
158 self.height.hash(hasher);
159 self.overflow.hash(hasher);
160 crate::layout::hash::hash_spans_content(&self.spans, hasher);
161 Some(())
162 }
163}