1use std::fmt;
2
3use crate::{cell::Cell, Color, Constraint, Element, Filled, Line, Paint, Size, Style};
4
5#[derive(Clone, Default, Debug)]
7pub struct Label(Paint<String>);
8
9impl Label {
10 pub fn new(s: &str) -> Self {
12 Self(Paint::new(cleanup(s)))
13 }
14
15 pub fn blank() -> Self {
17 Self(Paint::default())
18 }
19
20 pub fn is_blank(&self) -> bool {
22 self.content().is_empty()
23 }
24
25 pub fn content(&self) -> &str {
27 self.0.content()
28 }
29
30 pub fn space() -> Self {
32 Self(Paint::new(" ".to_owned()))
33 }
34
35 pub fn boxed(self) -> Box<dyn Element> {
37 Box::new(self)
38 }
39
40 pub fn fg(self, color: Color) -> Self {
42 Self(self.0.fg(color))
43 }
44
45 pub fn bg(self, color: Color) -> Self {
47 Self(self.0.bg(color))
48 }
49
50 pub fn style(self, style: Style) -> Self {
52 Self(self.0.with_style(style))
53 }
54
55 pub fn paint(&self) -> &Paint<String> {
57 &self.0
58 }
59
60 pub fn filled(self, color: Color) -> Filled<Self> {
62 Filled { item: self, color }
63 }
64
65 pub fn to_line(self) -> Line {
67 Line::from(self)
68 }
69}
70
71impl Element for Label {
72 fn size(&self, _parent: Constraint) -> Size {
73 Size::new(self.0.width(), 1)
74 }
75
76 fn render(&self, _parent: Constraint) -> Vec<Line> {
77 vec![Line::new(self.clone())]
78 }
79}
80
81impl fmt::Display for Label {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "{}", self.0)
84 }
85}
86
87impl Cell for Label {
88 type Padded = Self;
89 type Truncated = Self;
90
91 fn background(&self) -> Color {
92 self.paint().style.background
93 }
94
95 fn pad(&self, width: usize) -> Self::Padded {
96 Self(self.0.pad(width))
97 }
98
99 fn truncate(&self, width: usize, delim: &str) -> Self::Truncated {
100 Self(self.0.truncate(width, delim))
101 }
102
103 fn width(&self) -> usize {
104 Cell::width(&self.0)
105 }
106}
107
108impl<D: fmt::Display> From<Paint<D>> for Label {
109 fn from(paint: Paint<D>) -> Self {
110 Self(Paint {
111 item: cleanup(paint.item.to_string().as_str()),
112 style: paint.style,
113 })
114 }
115}
116
117impl From<String> for Label {
118 fn from(value: String) -> Self {
119 Self::new(value.as_str())
120 }
121}
122
123impl From<&str> for Label {
124 fn from(value: &str) -> Self {
125 Self::new(value)
126 }
127}
128
129pub fn label(s: impl Into<Paint<String>>) -> Label {
131 Label::from(s.into())
132}
133
134fn cleanup(input: &str) -> String {
136 input.chars().filter(|c| *c != '\n' && *c != '\r').collect()
137}