1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! Static text.
use alloc::string::{String, ToString};
use denise::Role;
use denise_render::Canvas;
use denise_text::TextStyle;
use crate::widget::{PaintCtx, Widget};
use crate::widgets::style::{Align, draw_aligned};
/// A run of text drawn in a content colour, aligned inside its bounds.
///
/// Not interactive and not focusable, so a label inside a button never intercepts
/// the click.
#[derive(Clone, Debug)]
pub struct Label {
text: String,
role: Role,
align: (Align, Align),
style: TextStyle,
}
impl Label {
/// A label in [`Role::BaseContent`], left-aligned and vertically centred, in
/// the built-in font at 16 px.
pub fn new(text: impl Into<String>) -> Self {
Self {
text: text.into(),
role: Role::BaseContent,
align: (Align::Start, Align::Center),
style: TextStyle::built_in(16),
}
}
/// Sets the colour role. Pass a `*Content` role, or a surface role to draw the
/// label *in* that colour rather than on it.
pub fn with_role(mut self, role: Role) -> Self {
self.role = role;
self
}
/// Sets horizontal and vertical alignment.
pub fn with_align(mut self, horizontal: Align, vertical: Align) -> Self {
self.align = (horizontal, vertical);
self
}
/// Sets the font and size.
pub fn with_style(mut self, style: TextStyle) -> Self {
self.style = style;
self
}
/// Sets the size, keeping the font.
pub fn with_size(mut self, size_px: u16) -> Self {
self.style.size_px = size_px;
self
}
/// The font and size this label draws in.
#[inline]
pub const fn style(&self) -> TextStyle {
self.style
}
/// The current text.
#[inline]
pub fn text(&self) -> &str {
&self.text
}
/// Replaces the text.
///
/// Reach this through [`Ui::widget_mut`](crate::Ui::widget_mut), which marks
/// the node dirty on the way in.
pub fn set_text(&mut self, text: impl Into<String>) {
self.text = text.into();
}
/// Replaces the font and size.
///
/// For an application that registers a font after building its tree, which is
/// the ordinary case: the tree has to exist before anyone knows whether the
/// font file was there.
pub fn set_style(&mut self, style: TextStyle) {
self.style = style;
}
/// Replaces the colour role.
pub fn set_role(&mut self, role: Role) {
self.role = role;
}
/// Replaces the text only if it differs, reporting whether it changed.
///
/// For the common case of writing a reading into a label every tick: an
/// unchanged value should not cost a repaint, and `widget_mut` cannot know
/// that on its own.
pub fn update(&mut self, text: &str) -> bool {
let changed = self.text != text;
if changed {
self.text = text.to_string();
}
changed
}
}
impl<M: 'static> Widget<M> for Label {
fn paint(&self, ctx: &mut PaintCtx<'_>, canvas: &mut Canvas<'_>) {
let color = ctx.theme.color(self.role);
draw_aligned(
canvas, ctx.text, self.style, ctx.bounds, self.align, &self.text, color,
);
}
}