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
use crate::*;
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
#[derive(Debug)]
pub struct SelectableLabel {
selected: bool,
text: String,
text_style: Option<TextStyle>,
}
impl SelectableLabel {
#[allow(clippy::needless_pass_by_value)]
pub fn new(selected: bool, text: impl ToString) -> Self {
Self {
selected,
text: text.to_string(),
text_style: None,
}
}
pub fn text_style(mut self, text_style: TextStyle) -> Self {
self.text_style = Some(text_style);
self
}
}
impl Widget for SelectableLabel {
fn ui(self, ui: &mut Ui) -> Response {
let Self {
selected,
text,
text_style,
} = self;
let text_style = text_style
.or(ui.style().override_text_style)
.unwrap_or(TextStyle::Button);
let button_padding = ui.spacing().button_padding;
let total_extra = button_padding + button_padding;
let galley = if ui.wrap_text() {
ui.fonts()
.layout_multiline(text_style, text, ui.available_width() - total_extra.x)
} else {
ui.fonts().layout_no_wrap(text_style, text)
};
let mut desired_size = total_extra + galley.size;
desired_size.y = desired_size.y.at_least(ui.spacing().interact_size.y);
let (rect, response) = ui.allocate_at_least(desired_size, Sense::click());
response.widget_info(|| {
WidgetInfo::selected(WidgetType::SelectableLabel, selected, &galley.text)
});
let text_pos = ui
.layout()
.align_size_within_rect(galley.size, rect.shrink2(button_padding))
.min;
let visuals = ui.style().interact_selectable(&response, selected);
if selected || response.hovered() || response.has_focus() {
let rect = rect.expand(visuals.expansion);
let corner_radius = 2.0;
ui.painter()
.rect(rect, corner_radius, visuals.bg_fill, visuals.bg_stroke);
}
let text_color = ui
.style()
.visuals
.override_text_color
.unwrap_or_else(|| visuals.text_color());
ui.painter().galley(text_pos, galley, text_color);
response
}
}