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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
use piston_window::*;
use crate::widget::config::*;
use crate::widget::widget::*;
mod private {
use piston_window::character::CharacterCache;
use piston_window::types::FontSize;
use piston_window::Graphics;
pub struct TextHelper {
pub font_size: FontSize,
}
impl TextHelper {
pub fn new(font_size: FontSize) -> TextHelper {
TextHelper { font_size }
}
pub fn determine_size<C, G>(
&self,
text: &str,
cache: &mut C,
_: &mut G,
) -> Result<(i32, i32), C::Error>
where
C: CharacterCache,
G: Graphics<Texture = <C as CharacterCache>::Texture>,
{
let mut x = 0.0;
let mut y = 0.0;
for ch in text.chars() {
let character = cache.character(self.font_size, ch)?;
x += character.width();
y += character.height();
}
Ok((x as i32, y as i32))
}
}
}
pub enum TextJustify {
Left,
Center,
Right,
}
pub struct TextWidget {
config: Configurable,
font_cache: Glyphs,
font_size: u32,
justify: TextJustify,
desired_size: (i32, i32),
}
impl TextWidget {
pub fn new(
factory: &mut GfxFactory,
font_name: String,
text: String,
font_size: u32,
justify: TextJustify,
) -> Self {
let assets = find_folder::Search::ParentsThenKids(3, 3)
.for_folder("assets")
.unwrap();
let ref font = assets.join(font_name.clone());
let glyphs = Glyphs::new(font, factory.clone(), TextureSettings::new()).unwrap();
let mut configurable = Configurable::new();
configurable.set(CONFIG_DISPLAY_TEXT, Config::Text(text.clone()));
Self {
config: configurable,
font_cache: glyphs,
font_size,
justify,
desired_size: (0, 0),
}
}
fn draw_text(&mut self, c: Context, g: &mut G2d, clip: &DrawState) {
let size: crate::core::point::Size = self.config().get_size(CONFIG_BODY_SIZE);
if self.desired_size.0 == 0 {
self.desired_size = private::TextHelper::new(self.font_size)
.determine_size(
self.config().get_text(CONFIG_DISPLAY_TEXT).as_str(),
&mut self.font_cache,
g,
)
.unwrap();
if self.desired_size.0 != 0 || self.desired_size.1 != 0 {
eprintln!("Desired size={:?} bounds={:?}", self.desired_size, size);
}
}
let start_x = match self.justify {
TextJustify::Left => 0.0,
TextJustify::Center => ((size.w - self.desired_size.0) / 2) as f64,
TextJustify::Right => (size.w - self.desired_size.0) as f64,
};
let start_y = (self.font_size - 2 + size.h as u32) / 2 - 1;
Text::new_color(self.config().get_color(CONFIG_TEXT_COLOR), self.font_size)
.draw(
self.config().get_text(CONFIG_DISPLAY_TEXT).as_str(),
&mut self.font_cache,
clip,
c.transform.trans(start_x, start_y as f64),
g,
)
.unwrap();
}
}
impl Widget for TextWidget {
fn config(&mut self) -> &mut Configurable {
&mut self.config
}
fn set_config(&mut self, config: u8, config_value: Config) {
self.config().set(config, config_value.clone());
self.invalidate();
}
fn draw(&mut self, c: Context, g: &mut G2d, clip: &DrawState) {
self.draw_text(c, g, &clip);
self.clear_invalidate();
}
}