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
;