1use densa_core::{Color, Point, Size};
2use densa_draw::Canvas;
3use densa_ui::{AccessNode, Constraints, EventCx, LayoutCx, PaintCx, Role, Theme, Widget};
4
5use crate::text::Text;
6
7#[derive(Debug)]
9pub struct Label {
10 text: Text,
11 dim: bool,
12 centered: bool,
13}
14
15impl Label {
16 pub fn new(text: impl Into<String>) -> Self {
18 Self {
19 text: Text::new(text),
20 dim: false,
21 centered: false,
22 }
23 }
24
25 #[must_use]
27 pub fn dim(mut self) -> Self {
28 self.dim = true;
29 self
30 }
31
32 #[must_use]
34 pub fn with_size(mut self, size: f32) -> Self {
35 self.text.set_size(size);
36 self
37 }
38
39 #[must_use]
41 pub fn wrapping(mut self) -> Self {
42 self.text.set_wrap(true);
43 self
44 }
45
46 #[must_use]
48 pub fn centered(mut self) -> Self {
49 self.centered = true;
50 self
51 }
52
53 pub fn text(&self) -> &str {
55 self.text.as_str()
56 }
57
58 pub fn set_text(&mut self, cx: &mut EventCx<'_>, text: impl Into<String>) {
60 self.text.set(text);
61 cx.request_layout();
62 }
63
64 fn color(&self, theme: &Theme) -> Color {
65 if self.dim {
66 theme.text_dim
67 } else {
68 theme.text
69 }
70 }
71}
72
73impl Widget for Label {
74 fn accessibility(&self, _: &PaintCx<'_>, node: &mut AccessNode) {
75 node.set_role(Role::Label);
76 node.set_value(self.text.as_str());
77 }
78
79 fn measure(&mut self, cx: &mut LayoutCx<'_>, constraints: Constraints) -> Size {
80 let color = self.color(cx.theme());
81 self.text.measure(cx, constraints, color)
82 }
83
84 fn layout(&mut self, cx: &mut LayoutCx<'_>, size: Size) {
85 let color = self.color(cx.theme());
86 self.text.fit(cx, size.width, color);
87 }
88
89 fn paint(&mut self, cx: &PaintCx<'_>, canvas: &mut Canvas<'_>) {
90 let content = cx.content_rect();
91 let size = self.text.size();
92 let mut origin = crate::paint::centered(content, size.width, size.height);
93 if !self.centered {
94 origin = Point::new(content.left(), origin.y);
95 }
96 self.text.paint(canvas, origin);
97 }
98}