Skip to main content

densa_widgets/
label.rs

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/// Text, on one line or wrapped to its width, vertically centered in its rectangle.
8#[derive(Debug)]
9pub struct Label {
10    text: Text,
11    dim: bool,
12    centered: bool,
13}
14
15impl Label {
16    /// `text` on one line, in the theme's text color and size.
17    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    /// The label in the theme's secondary text color.
26    #[must_use]
27    pub fn dim(mut self) -> Self {
28        self.dim = true;
29        self
30    }
31
32    /// The label at `size` logical pixels instead of the theme's size.
33    #[must_use]
34    pub fn with_size(mut self, size: f32) -> Self {
35        self.text.set_size(size);
36        self
37    }
38
39    /// The label wrapped onto more lines at the width layout gives it.
40    #[must_use]
41    pub fn wrapping(mut self) -> Self {
42        self.text.set_wrap(true);
43        self
44    }
45
46    /// The label centered horizontally too.
47    #[must_use]
48    pub fn centered(mut self) -> Self {
49        self.centered = true;
50        self
51    }
52
53    /// The text shown.
54    pub fn text(&self) -> &str {
55        self.text.as_str()
56    }
57
58    /// Shows `text` instead, measured again at the next layout.
59    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}