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
117
118
119
120
121
122
123
124
125
use Scalar;
use color::{Color, Colorable};
use elmesque::Element;
use graphics::character::CharacterCache;
use label::FontSize;
use theme::Theme;
use ui::GlyphCache;
use widget::{self, Widget};
#[derive(Clone, Debug)]
pub struct Label<'a> {
common: widget::CommonBuilder,
text: &'a str,
style: Style,
}
#[allow(missing_docs, missing_copy_implementations)]
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Style {
maybe_font_size: Option<FontSize>,
maybe_color: Option<Color>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct State(String);
impl<'a> Label<'a> {
pub fn new(text: &'a str) -> Label<'a> {
Label {
common: widget::CommonBuilder::new(),
text: text,
style: Style::new(),
}
}
#[inline]
pub fn font_size(mut self, size: FontSize) -> Label<'a> {
self.style.maybe_font_size = Some(size);
self
}
}
impl<'a> Widget for Label<'a> {
type State = State;
type Style = Style;
fn common(&self) -> &widget::CommonBuilder { &self.common }
fn common_mut(&mut self) -> &mut widget::CommonBuilder { &mut self.common }
fn unique_kind(&self) -> &'static str { "Label" }
fn init_state(&self) -> State { State(String::new()) }
fn style(&self) -> Style { self.style.clone() }
fn default_width<C: CharacterCache>(&self, theme: &Theme, glyph_cache: &GlyphCache<C>) -> Scalar {
glyph_cache.width(self.style.font_size(theme), self.text)
}
fn default_height(&self, theme: &Theme) -> Scalar {
self.style.font_size(theme) as Scalar
}
fn update<C: CharacterCache>(self, args: widget::UpdateArgs<Self, C>) {
let widget::UpdateArgs { state, .. } = args;
if &state.view().0[..] != self.text {
state.update(|state| *state = State(self.text.to_owned()));
}
}
fn draw<C: CharacterCache>(args: widget::DrawArgs<Self, C>) -> Element {
use elmesque::form::{text, collage};
use elmesque::text::Text;
let widget::DrawArgs { rect, state: &State(ref string), style, theme, .. } = args;
let size = style.font_size(theme);
let color = style.color(theme);
let (x, y, w, h) = rect.x_y_w_h();
let form = text(Text::from_string(string.clone())
.color(color)
.height(size as f64)).shift(x.floor(), y.floor());
collage(w as i32, h as i32, vec![form])
}
}
impl Style {
pub fn new() -> Style {
Style {
maybe_color: None,
maybe_font_size: None,
}
}
pub fn color(&self, theme: &Theme) -> Color {
self.maybe_color.unwrap_or(theme.label_color)
}
pub fn font_size(&self, theme: &Theme) -> FontSize {
self.maybe_font_size.unwrap_or(theme.font_size_medium)
}
}
impl<'a> Colorable for Label<'a> {
fn color(mut self, color: Color) -> Self {
self.style.maybe_color = Some(color);
self
}
}