flux_tui/components/
label.rs1use std::num::NonZero;
2use unicode_width::UnicodeWidthStr;
3
4use crate::canvas::*;
5
6use super::*;
7
8pub struct Label {
17 has_focus: bool,
18 text: String,
19 text_alignment: HorizontalAlignment,
20 base: WidgetBase,
21 focus_color: Option<Color>,
22}
23
24impl Default for Label {
25 fn default() -> Self {
26 let mut s = Self {
27 has_focus: false,
28 text: String::default(),
29 text_alignment: HorizontalAlignment::Center,
30 base: WidgetBase::default(),
31 focus_color: None,
32 };
33 s.base.constraints.y.min = NonZero::<TSize>::MIN;
34 s.base.constraints.y.max = Size::Fixed(NonZero::<TSize>::MIN);
35 s
36 }
37}
38
39impl Label {
40 pub fn set_text_alignment(&mut self, alignment: HorizontalAlignment) {
42 self.text_alignment = alignment;
43 }
44
45 pub fn set_text(&mut self, text: &str) {
47 self.text.clear();
48 self.text.push_str(text);
49 let old = self.base.constraints.x.max;
50 self.base.constraints.x.max =
51 Size::Fixed(NonZero::new(self.text.width() as TSize).unwrap_or(NonZero::<TSize>::MIN));
52 if old != self.base.constraints.x.max {
53 self.provoke_changed_property(WindowProperty::Size);
54 }
55 }
56
57 pub fn get_text(&self) -> &str {
59 &self.text
60 }
61
62 pub fn set_focus_color(&mut self, color: Option<Color>) {
63 self.focus_color = color;
64 }
65}
66
67impl Window for Label {
68 fn render(&self, canvas: &mut Canvas) {
69 let fg = match self.base.enabled {
70 true => match self.has_focus {
71 true => self.focus_color,
72 false => None,
73 },
74 false => self.base.colors.disabled,
75 }
76 .or(self.base.colors.base_fg);
77
78 let mut row = canvas.get_row_variable_width(TSize::MIN).unwrap();
79 let text_w = self.text.width() as TSize;
80 match self.text_alignment {
81 HorizontalAlignment::Left => {}
82 HorizontalAlignment::Center => {
83 row.skip(row.width().checked_sub(text_w).unwrap_or_default() / 2);
84 }
85 HorizontalAlignment::Right => {
86 row.skip(row.width().checked_sub(text_w).unwrap_or_default());
87 }
88 }
89
90 row.add_string(
91 &self.text,
92 fg,
93 self.base.colors.base_bg,
94 Style::default(),
95 Some(VariableWidthGlyphRow::DOT3_REPLACEMENT),
96 )
97 .unwrap()
98 }
99
100 fn handle_event(&mut self, event: &mut WindowEvent) {
101 match event.raw() {
102 Event::FocusGained => self.has_focus = true,
103 Event::FocusLost => self.has_focus = false,
104 _ => {}
105 }
106 }
107
108 fn is_enabled(&self) -> bool {
109 self.base.enabled
110 }
111}
112
113impl WindowLayout for Label {
114 fn desired_size(&self, available_size: TPoint) -> TPoint {
115 self.base.desired_size(available_size)
116 }
117
118 fn alignment(&self) -> (super::HorizontalAlignment, super::VerticalAlignment) {
119 self.base.alignment
120 }
121
122 fn margin(&self) -> Thickness {
123 self.base.margin
124 }
125
126 fn border(&self) -> BorderStyle {
127 self.base.border
128 }
129
130 fn is_visible(&self) -> bool {
131 self.base.visibility
132 }
133}
134
135impl HasWindowUID for Label {
136 fn uid(&self) -> WindowUID {
137 self.base.uid
138 }
139}
140
141impl Widget for Label {
142 fn set_alignment(&mut self, horizontal: HorizontalAlignment, vertical: VerticalAlignment) {
143 self.base.alignment = (horizontal, vertical);
144 self.provoke_changed_property(WindowProperty::Alignment);
145 }
146
147 fn set_visibility(&mut self, visibility: bool) {
148 self.base.visibility = visibility;
149 self.provoke_changed_property(WindowProperty::IsVisible);
150 }
151
152 fn set_width(&mut self, width: super::Size) {
153 self.base.size.x = width;
154 self.provoke_changed_property(WindowProperty::Size);
155 }
156
157 fn set_height(&mut self, _: super::Size) {}
158
159 fn set_margin(&mut self, margin: Thickness) {
160 self.base.margin = margin;
161 self.provoke_changed_property(WindowProperty::Margin);
162 }
163
164 fn set_border(&mut self, border: BorderStyle) {
165 self.base.border = border;
166 self.provoke_changed_property(WindowProperty::Border);
167 }
168
169 fn set_enabled_state(&mut self, is_enabled: bool) {
170 self.base.enabled = is_enabled;
171 }
172
173 fn set_width_constraint(&mut self, width: SizeConstraint) {
174 self.base.constraints.x = width;
175 self.provoke_changed_property(WindowProperty::Size);
176 }
177
178 fn set_height_constraint(&mut self, _: SizeConstraint) {}
179}
180
181impl WidgetColors for Label {
182 fn set_disabled_color(&mut self, color: Option<Color>) {
183 self.base.colors.disabled = color;
184 }
185
186 fn set_base_fg_color(&mut self, color: Option<Color>) {
187 self.base.colors.base_fg = color;
188 }
189
190 fn set_base_bg_color(&mut self, color: Option<Color>) {
191 self.base.colors.base_bg = color;
192 }
193}