]>
Commit | Line | Data |
---|---|---|
d920a32a CB |
1 | /* gui_progress_bar.c - GUI progress bar component. */ |
2 | /* | |
3 | * GRUB -- GRand Unified Bootloader | |
4 | * Copyright (C) 2008,2009 Free Software Foundation, Inc. | |
5 | * | |
6 | * GRUB is free software: you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation, either version 3 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * GRUB is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with GRUB. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include <grub/mm.h> | |
21 | #include <grub/misc.h> | |
22 | #include <grub/gui.h> | |
23 | #include <grub/font.h> | |
24 | #include <grub/gui_string_util.h> | |
25 | #include <grub/gfxmenu_view.h> | |
26 | #include <grub/gfxwidgets.h> | |
27 | ||
28 | struct grub_gui_progress_bar | |
29 | { | |
9a175884 | 30 | struct grub_gui_component component; |
d920a32a CB |
31 | |
32 | grub_gui_container_t parent; | |
33 | grub_video_rect_t bounds; | |
34 | char *id; | |
d920a32a CB |
35 | int visible; |
36 | int start; | |
37 | int end; | |
38 | int value; | |
39 | int show_text; | |
40 | char *text; | |
41 | grub_font_t font; | |
42 | grub_gui_color_t text_color; | |
43 | grub_gui_color_t border_color; | |
44 | grub_gui_color_t bg_color; | |
45 | grub_gui_color_t fg_color; | |
46 | ||
47 | char *theme_dir; | |
48 | int need_to_recreate_pixmaps; | |
49 | char *bar_pattern; | |
50 | char *highlight_pattern; | |
51 | grub_gfxmenu_box_t bar_box; | |
52 | grub_gfxmenu_box_t highlight_box; | |
53 | }; | |
54 | ||
55 | typedef struct grub_gui_progress_bar *grub_gui_progress_bar_t; | |
56 | ||
57 | static void | |
58 | progress_bar_destroy (void *vself) | |
59 | { | |
60 | grub_gui_progress_bar_t self = vself; | |
61 | grub_free (self); | |
62 | } | |
63 | ||
64 | static const char * | |
65 | progress_bar_get_id (void *vself) | |
66 | { | |
67 | grub_gui_progress_bar_t self = vself; | |
68 | return self->id; | |
69 | } | |
70 | ||
71 | static int | |
72 | progress_bar_is_instance (void *vself __attribute__((unused)), const char *type) | |
73 | { | |
74 | return grub_strcmp (type, "component") == 0; | |
75 | } | |
76 | ||
77 | static int | |
78 | check_pixmaps (grub_gui_progress_bar_t self) | |
79 | { | |
80 | if (self->need_to_recreate_pixmaps) | |
81 | { | |
82 | grub_gui_recreate_box (&self->bar_box, | |
83 | self->bar_pattern, | |
84 | self->theme_dir); | |
85 | ||
86 | grub_gui_recreate_box (&self->highlight_box, | |
87 | self->highlight_pattern, | |
88 | self->theme_dir); | |
89 | ||
90 | self->need_to_recreate_pixmaps = 0; | |
91 | } | |
92 | ||
93 | return (self->bar_box != 0 && self->highlight_box != 0); | |
94 | } | |
95 | ||
96 | static void | |
97 | draw_filled_rect_bar (grub_gui_progress_bar_t self) | |
98 | { | |
99 | /* Set the progress bar's frame. */ | |
100 | grub_video_rect_t f; | |
101 | f.x = 1; | |
102 | f.y = 1; | |
103 | f.width = self->bounds.width - 2; | |
104 | f.height = self->bounds.height - 2; | |
105 | ||
106 | /* Border. */ | |
107 | grub_video_fill_rect (grub_gui_map_color (self->border_color), | |
108 | f.x - 1, f.y - 1, | |
109 | f.width + 2, f.height + 2); | |
110 | ||
111 | /* Bar background. */ | |
112 | int barwidth = (f.width | |
113 | * (self->value - self->start) | |
114 | / (self->end - self->start)); | |
115 | grub_video_fill_rect (grub_gui_map_color (self->bg_color), | |
116 | f.x + barwidth, f.y, | |
117 | f.width - barwidth, f.height); | |
118 | ||
119 | /* Bar foreground. */ | |
120 | grub_video_fill_rect (grub_gui_map_color (self->fg_color), | |
121 | f.x, f.y, | |
122 | barwidth, f.height); | |
123 | } | |
124 | ||
125 | static void | |
126 | draw_pixmap_bar (grub_gui_progress_bar_t self) | |
127 | { | |
128 | grub_gfxmenu_box_t bar = self->bar_box; | |
129 | grub_gfxmenu_box_t hl = self->highlight_box; | |
130 | int w = self->bounds.width; | |
131 | int h = self->bounds.height; | |
132 | int bar_l_pad = bar->get_left_pad (bar); | |
133 | int bar_r_pad = bar->get_right_pad (bar); | |
134 | int bar_t_pad = bar->get_top_pad (bar); | |
135 | int bar_b_pad = bar->get_bottom_pad (bar); | |
136 | int bar_h_pad = bar_l_pad + bar_r_pad; | |
137 | int bar_v_pad = bar_t_pad + bar_b_pad; | |
138 | int tracklen = w - bar_h_pad; | |
139 | int trackheight = h - bar_v_pad; | |
140 | bar->set_content_size (bar, tracklen, trackheight); | |
141 | ||
142 | int barwidth = (tracklen | |
143 | * (self->value - self->start) | |
144 | / (self->end - self->start)); | |
145 | hl->set_content_size (hl, barwidth, h - bar_v_pad); | |
146 | ||
147 | bar->draw (bar, 0, 0); | |
148 | hl->draw (hl, bar_l_pad, bar_t_pad); | |
149 | } | |
150 | ||
151 | static void | |
152 | draw_text (grub_gui_progress_bar_t self) | |
153 | { | |
154 | const char *text = self->text; | |
155 | if (text && self->show_text) | |
156 | { | |
157 | grub_font_t font = self->font; | |
158 | grub_video_color_t text_color = grub_gui_map_color (self->text_color); | |
159 | int width = self->bounds.width; | |
160 | int height = self->bounds.height; | |
161 | ||
162 | /* Center the text. */ | |
163 | int text_width = grub_font_get_string_width (font, text); | |
164 | int x = (width - text_width) / 2; | |
165 | int y = ((height - grub_font_get_descent (font)) / 2 | |
166 | + grub_font_get_ascent (font) / 2); | |
167 | grub_font_draw_string (text, font, text_color, x, y); | |
168 | } | |
169 | } | |
170 | ||
171 | static void | |
947fa16c | 172 | progress_bar_paint (void *vself, const grub_video_rect_t *region) |
d920a32a CB |
173 | { |
174 | grub_gui_progress_bar_t self = vself; | |
175 | if (! self->visible) | |
176 | return; | |
947fa16c VS |
177 | if (!grub_video_have_common_points (region, &self->bounds)) |
178 | return; | |
d920a32a CB |
179 | |
180 | grub_video_rect_t vpsave; | |
181 | grub_gui_set_viewport (&self->bounds, &vpsave); | |
182 | ||
183 | if (check_pixmaps (self)) | |
184 | draw_pixmap_bar (self); | |
185 | else | |
186 | draw_filled_rect_bar (self); | |
187 | ||
188 | draw_text (self); | |
189 | ||
190 | grub_gui_restore_viewport (&vpsave); | |
191 | } | |
192 | ||
193 | static void | |
194 | progress_bar_set_parent (void *vself, grub_gui_container_t parent) | |
195 | { | |
196 | grub_gui_progress_bar_t self = vself; | |
197 | self->parent = parent; | |
198 | } | |
199 | ||
200 | static grub_gui_container_t | |
201 | progress_bar_get_parent (void *vself) | |
202 | { | |
203 | grub_gui_progress_bar_t self = vself; | |
204 | return self->parent; | |
205 | } | |
206 | ||
207 | static void | |
208 | progress_bar_set_bounds (void *vself, const grub_video_rect_t *bounds) | |
209 | { | |
210 | grub_gui_progress_bar_t self = vself; | |
211 | self->bounds = *bounds; | |
212 | } | |
213 | ||
214 | static void | |
215 | progress_bar_get_bounds (void *vself, grub_video_rect_t *bounds) | |
216 | { | |
217 | grub_gui_progress_bar_t self = vself; | |
218 | *bounds = self->bounds; | |
219 | } | |
220 | ||
221 | static void | |
9a175884 VS |
222 | progress_bar_get_minimal_size (void *vself __attribute__ ((unused)), |
223 | unsigned *width, unsigned *height) | |
d920a32a | 224 | { |
d920a32a CB |
225 | *width = 200; |
226 | *height = 28; | |
d920a32a CB |
227 | } |
228 | ||
229 | static grub_err_t | |
230 | progress_bar_set_property (void *vself, const char *name, const char *value) | |
231 | { | |
232 | grub_gui_progress_bar_t self = vself; | |
233 | if (grub_strcmp (name, "value") == 0) | |
234 | { | |
235 | self->value = grub_strtol (value, 0, 10); | |
236 | } | |
237 | else if (grub_strcmp (name, "start") == 0) | |
238 | { | |
239 | self->start = grub_strtol (value, 0, 10); | |
240 | } | |
241 | else if (grub_strcmp (name, "end") == 0) | |
242 | { | |
243 | self->end = grub_strtol (value, 0, 10); | |
244 | } | |
245 | else if (grub_strcmp (name, "text") == 0) | |
246 | { | |
247 | grub_free (self->text); | |
248 | if (! value) | |
249 | value = ""; | |
250 | self->text = grub_strdup (value); | |
251 | } | |
252 | else if (grub_strcmp (name, "font") == 0) | |
253 | { | |
254 | self->font = grub_font_get (value); | |
255 | } | |
256 | else if (grub_strcmp (name, "text_color") == 0) | |
257 | { | |
258 | grub_gui_parse_color (value, &self->text_color); | |
259 | } | |
260 | else if (grub_strcmp (name, "border_color") == 0) | |
261 | { | |
262 | grub_gui_parse_color (value, &self->border_color); | |
263 | } | |
264 | else if (grub_strcmp (name, "bg_color") == 0) | |
265 | { | |
266 | grub_gui_parse_color (value, &self->bg_color); | |
267 | } | |
268 | else if (grub_strcmp (name, "fg_color") == 0) | |
269 | { | |
270 | grub_gui_parse_color (value, &self->fg_color); | |
271 | } | |
272 | else if (grub_strcmp (name, "bar_style") == 0) | |
273 | { | |
274 | self->need_to_recreate_pixmaps = 1; | |
275 | grub_free (self->bar_pattern); | |
276 | self->bar_pattern = value ? grub_strdup (value) : 0; | |
277 | } | |
278 | else if (grub_strcmp (name, "highlight_style") == 0) | |
279 | { | |
280 | self->need_to_recreate_pixmaps = 1; | |
281 | grub_free (self->highlight_pattern); | |
282 | self->highlight_pattern = value ? grub_strdup (value) : 0; | |
283 | } | |
284 | else if (grub_strcmp (name, "theme_dir") == 0) | |
285 | { | |
286 | self->need_to_recreate_pixmaps = 1; | |
287 | grub_free (self->theme_dir); | |
288 | self->theme_dir = value ? grub_strdup (value) : 0; | |
289 | } | |
d920a32a CB |
290 | else if (grub_strcmp (name, "visible") == 0) |
291 | { | |
292 | self->visible = grub_strcmp (value, "false") != 0; | |
293 | } | |
294 | else if (grub_strcmp (name, "show_text") == 0) | |
295 | { | |
296 | self->show_text = grub_strcmp (value, "false") != 0; | |
297 | } | |
298 | else if (grub_strcmp (name, "id") == 0) | |
299 | { | |
300 | grub_free (self->id); | |
301 | if (value) | |
302 | self->id = grub_strdup (value); | |
303 | else | |
304 | self->id = 0; | |
305 | } | |
306 | return grub_errno; | |
307 | } | |
308 | ||
309 | static struct grub_gui_component_ops progress_bar_ops = | |
310 | { | |
311 | .destroy = progress_bar_destroy, | |
312 | .get_id = progress_bar_get_id, | |
313 | .is_instance = progress_bar_is_instance, | |
314 | .paint = progress_bar_paint, | |
315 | .set_parent = progress_bar_set_parent, | |
316 | .get_parent = progress_bar_get_parent, | |
317 | .set_bounds = progress_bar_set_bounds, | |
318 | .get_bounds = progress_bar_get_bounds, | |
9a175884 | 319 | .get_minimal_size = progress_bar_get_minimal_size, |
d920a32a CB |
320 | .set_property = progress_bar_set_property |
321 | }; | |
322 | ||
323 | grub_gui_component_t | |
324 | grub_gui_progress_bar_new (void) | |
325 | { | |
326 | grub_gui_progress_bar_t self; | |
9a175884 | 327 | self = grub_zalloc (sizeof (*self)); |
d920a32a CB |
328 | if (! self) |
329 | return 0; | |
9a175884 | 330 | self->component.ops = &progress_bar_ops; |
d920a32a | 331 | self->visible = 1; |
d920a32a CB |
332 | self->show_text = 1; |
333 | self->text = grub_strdup (""); | |
334 | self->font = grub_font_get ("Helvetica 10"); | |
335 | grub_gui_color_t black = { .red = 0, .green = 0, .blue = 0, .alpha = 255 }; | |
336 | grub_gui_color_t gray = { .red = 128, .green = 128, .blue = 128, .alpha = 255 }; | |
337 | grub_gui_color_t lightgray = { .red = 200, .green = 200, .blue = 200, .alpha = 255 }; | |
338 | self->text_color = black; | |
339 | self->border_color = black; | |
340 | self->bg_color = gray; | |
341 | self->fg_color = lightgray; | |
342 | ||
d920a32a CB |
343 | return (grub_gui_component_t) self; |
344 | } |