1
/* gui_progress_bar.c - GUI progress bar component. */
3
* GRUB -- GRand Unified Bootloader
4
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
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.
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.
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/>.
21
#include <grub/misc.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
#include <grub/i18n.h>
29
struct grub_gui_progress_bar
31
struct grub_gui_progress progress;
33
grub_gui_container_t parent;
34
grub_video_rect_t bounds;
43
grub_gui_color_t text_color;
44
grub_gui_color_t border_color;
45
grub_gui_color_t bg_color;
46
grub_gui_color_t fg_color;
49
int need_to_recreate_pixmaps;
50
int pixmapbar_available;
52
char *highlight_pattern;
53
grub_gfxmenu_box_t bar_box;
54
grub_gfxmenu_box_t highlight_box;
57
typedef struct grub_gui_progress_bar *grub_gui_progress_bar_t;
60
progress_bar_destroy (void *vself)
62
grub_gui_progress_bar_t self = vself;
63
grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
68
progress_bar_get_id (void *vself)
70
grub_gui_progress_bar_t self = vself;
75
progress_bar_is_instance (void *vself __attribute__((unused)), const char *type)
77
return grub_strcmp (type, "component") == 0;
81
check_pixmaps (grub_gui_progress_bar_t self)
83
if (!self->pixmapbar_available)
85
if (self->need_to_recreate_pixmaps)
87
grub_gui_recreate_box (&self->bar_box,
91
grub_gui_recreate_box (&self->highlight_box,
92
self->highlight_pattern,
95
self->need_to_recreate_pixmaps = 0;
98
return (self->bar_box != 0 && self->highlight_box != 0);
102
draw_filled_rect_bar (grub_gui_progress_bar_t self)
104
/* Set the progress bar's frame. */
108
f.width = self->bounds.width - 2;
109
f.height = self->bounds.height - 2;
112
grub_video_fill_rect (grub_gui_map_color (self->border_color),
114
f.width + 2, f.height + 2);
116
/* Bar background. */
117
int barwidth = (f.width
118
* (self->value - self->start)
119
/ (self->end - self->start));
120
grub_video_fill_rect (grub_gui_map_color (self->bg_color),
122
f.width - barwidth, f.height);
124
/* Bar foreground. */
125
grub_video_fill_rect (grub_gui_map_color (self->fg_color),
131
draw_pixmap_bar (grub_gui_progress_bar_t self)
133
grub_gfxmenu_box_t bar = self->bar_box;
134
grub_gfxmenu_box_t hl = self->highlight_box;
135
int w = self->bounds.width;
136
int h = self->bounds.height;
137
int bar_l_pad = bar->get_left_pad (bar);
138
int bar_r_pad = bar->get_right_pad (bar);
139
int bar_t_pad = bar->get_top_pad (bar);
140
int bar_b_pad = bar->get_bottom_pad (bar);
141
int bar_h_pad = bar_l_pad + bar_r_pad;
142
int bar_v_pad = bar_t_pad + bar_b_pad;
143
int tracklen = w - bar_h_pad;
144
int trackheight = h - bar_v_pad;
147
bar->set_content_size (bar, tracklen, trackheight);
149
barwidth = (tracklen * (self->value - self->start)
150
/ (self->end - self->start));
152
hl->set_content_size (hl, barwidth, h - bar_v_pad);
154
bar->draw (bar, 0, 0);
155
hl->draw (hl, bar_l_pad, bar_t_pad);
159
draw_text (grub_gui_progress_bar_t self)
163
grub_font_t font = self->font;
164
grub_video_color_t text_color = grub_gui_map_color (self->text_color);
165
int width = self->bounds.width;
166
int height = self->bounds.height;
168
text = grub_xasprintf (self->template,
169
self->value > 0 ? self->value : -self->value);
173
grub_errno = GRUB_ERR_NONE;
176
/* Center the text. */
177
int text_width = grub_font_get_string_width (font, text);
178
int x = (width - text_width) / 2;
179
int y = ((height - grub_font_get_descent (font)) / 2
180
+ grub_font_get_ascent (font) / 2);
181
grub_font_draw_string (text, font, text_color, x, y);
186
progress_bar_paint (void *vself, const grub_video_rect_t *region)
188
grub_gui_progress_bar_t self = vself;
189
grub_video_rect_t vpsave;
193
if (!grub_video_have_common_points (region, &self->bounds))
196
if (self->end == self->start)
199
grub_gui_set_viewport (&self->bounds, &vpsave);
201
if (check_pixmaps (self))
202
draw_pixmap_bar (self);
204
draw_filled_rect_bar (self);
208
grub_gui_restore_viewport (&vpsave);
212
progress_bar_set_parent (void *vself, grub_gui_container_t parent)
214
grub_gui_progress_bar_t self = vself;
215
self->parent = parent;
218
static grub_gui_container_t
219
progress_bar_get_parent (void *vself)
221
grub_gui_progress_bar_t self = vself;
226
progress_bar_set_bounds (void *vself, const grub_video_rect_t *bounds)
228
grub_gui_progress_bar_t self = vself;
229
self->bounds = *bounds;
233
progress_bar_get_bounds (void *vself, grub_video_rect_t *bounds)
235
grub_gui_progress_bar_t self = vself;
236
*bounds = self->bounds;
240
progress_bar_get_minimal_size (void *vself,
241
unsigned *width, unsigned *height)
243
unsigned text_width = 0, text_height = 0;
244
grub_gui_progress_bar_t self = vself;
248
text_width = grub_font_get_string_width (self->font, self->template);
249
text_width += grub_font_get_string_width (self->font, "XXXXXXXXXX");
250
text_height = grub_font_get_descent (self->font)
251
+ grub_font_get_ascent (self->font);
254
if (*width < text_width)
257
if (*height < text_height)
258
*height = text_height;
262
progress_bar_set_state (void *vself, int visible, int start,
263
int current, int end)
265
grub_gui_progress_bar_t self = vself;
266
self->visible = visible;
268
self->value = current;
273
progress_bar_set_property (void *vself, const char *name, const char *value)
275
grub_gui_progress_bar_t self = vself;
276
if (grub_strcmp (name, "text") == 0)
278
grub_free (self->template);
279
if (grub_strcmp (value, "@TIMEOUT_NOTIFICATION_LONG@") == 0)
281
= _("The highlighted entry will be executed automatically in %ds.");
282
else if (grub_strcmp (value, "@TIMEOUT_NOTIFICATION_MIDDLE@") == 0)
283
/* TRANSLATORS: 's' stands for seconds.
284
It's a standalone timeout notification.
285
Please use the short form in your language. */
286
value = _("%ds remaining.");
287
else if (grub_strcmp (value, "@TIMEOUT_NOTIFICATION_SHORT@") == 0)
288
/* TRANSLATORS: 's' stands for seconds.
289
It's a standalone timeout notification.
290
Please use the shortest form available in you language. */
293
self->template = grub_strdup (value);
295
else if (grub_strcmp (name, "font") == 0)
297
self->font = grub_font_get (value);
299
else if (grub_strcmp (name, "text_color") == 0)
301
grub_gui_parse_color (value, &self->text_color);
303
else if (grub_strcmp (name, "border_color") == 0)
305
grub_gui_parse_color (value, &self->border_color);
307
else if (grub_strcmp (name, "bg_color") == 0)
309
grub_gui_parse_color (value, &self->bg_color);
311
else if (grub_strcmp (name, "fg_color") == 0)
313
grub_gui_parse_color (value, &self->fg_color);
315
else if (grub_strcmp (name, "bar_style") == 0)
317
self->need_to_recreate_pixmaps = 1;
318
self->pixmapbar_available = 1;
319
grub_free (self->bar_pattern);
320
self->bar_pattern = value ? grub_strdup (value) : 0;
322
else if (grub_strcmp (name, "highlight_style") == 0)
324
self->need_to_recreate_pixmaps = 1;
325
self->pixmapbar_available = 1;
326
grub_free (self->highlight_pattern);
327
self->highlight_pattern = value ? grub_strdup (value) : 0;
329
else if (grub_strcmp (name, "theme_dir") == 0)
331
self->need_to_recreate_pixmaps = 1;
332
grub_free (self->theme_dir);
333
self->theme_dir = value ? grub_strdup (value) : 0;
335
else if (grub_strcmp (name, "id") == 0)
337
grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
338
grub_free (self->id);
340
self->id = grub_strdup (value);
343
/* if (self->id && grub_strcmp (self->id, GRUB_GFXMENU_TIMEOUT_COMPONENT_ID)
345
grub_gfxmenu_timeout_register ((grub_gui_component_t) self,
346
progress_bar_set_state);
351
static struct grub_gui_component_ops progress_bar_ops =
353
.destroy = progress_bar_destroy,
354
.get_id = progress_bar_get_id,
355
.is_instance = progress_bar_is_instance,
356
.paint = progress_bar_paint,
357
.set_parent = progress_bar_set_parent,
358
.get_parent = progress_bar_get_parent,
359
.set_bounds = progress_bar_set_bounds,
360
.get_bounds = progress_bar_get_bounds,
361
.get_minimal_size = progress_bar_get_minimal_size,
362
.set_property = progress_bar_set_property
365
static struct grub_gui_progress_ops progress_bar_pb_ops =
367
.set_state = progress_bar_set_state
371
grub_gui_progress_bar_new (void)
373
grub_gui_progress_bar_t self;
374
self = grub_zalloc (sizeof (*self));
378
self->progress.ops = &progress_bar_pb_ops;
379
self->progress.component.ops = &progress_bar_ops;
381
self->font = grub_font_get ("Unknown Regular 16");
382
grub_gui_color_t black = { .red = 0, .green = 0, .blue = 0, .alpha = 255 };
383
grub_gui_color_t gray = { .red = 128, .green = 128, .blue = 128, .alpha = 255 };
384
grub_gui_color_t lightgray = { .red = 200, .green = 200, .blue = 200, .alpha = 255 };
385
self->text_color = black;
386
self->border_color = black;
387
self->bg_color = gray;
388
self->fg_color = lightgray;
390
return (grub_gui_component_t) self;