| /* gui_label.c - GUI component to display a line of text. */ |
| /* |
| * GRUB -- GRand Unified Bootloader |
| * Copyright (C) 2008,2009 Free Software Foundation, Inc. |
| * |
| * GRUB is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation, either version 3 of the License, or |
| * (at your option) any later version. |
| * |
| * GRUB is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with GRUB. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include <grub/mm.h> |
| #include <grub/misc.h> |
| #include <grub/gui.h> |
| #include <grub/font.h> |
| #include <grub/gui_string_util.h> |
| #include <grub/i18n.h> |
| #include <grub/color.h> |
| |
| static const char *align_options[] = |
| { |
| "left", |
| "center", |
| "right", |
| 0 |
| }; |
| |
| enum align_mode { |
| align_left, |
| align_center, |
| align_right |
| }; |
| |
| struct grub_gui_label |
| { |
| struct grub_gui_component comp; |
| |
| grub_gui_container_t parent; |
| grub_video_rect_t bounds; |
| char *id; |
| int visible; |
| char *text; |
| char *template; |
| grub_font_t font; |
| grub_video_rgba_color_t color; |
| int value; |
| enum align_mode align; |
| }; |
| |
| typedef struct grub_gui_label *grub_gui_label_t; |
| |
| static void |
| label_destroy (void *vself) |
| { |
| grub_gui_label_t self = vself; |
| grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self); |
| grub_free (self->text); |
| grub_free (self->template); |
| grub_free (self); |
| } |
| |
| static const char * |
| label_get_id (void *vself) |
| { |
| grub_gui_label_t self = vself; |
| return self->id; |
| } |
| |
| static int |
| label_is_instance (void *vself __attribute__((unused)), const char *type) |
| { |
| return grub_strcmp (type, "component") == 0; |
| } |
| |
| static void |
| label_paint (void *vself, const grub_video_rect_t *region) |
| { |
| grub_gui_label_t self = vself; |
| |
| if (! self->visible) |
| return; |
| |
| if (!grub_video_have_common_points (region, &self->bounds)) |
| return; |
| |
| /* Calculate the starting x coordinate. */ |
| int left_x; |
| if (self->align == align_left) |
| left_x = 0; |
| else if (self->align == align_center) |
| left_x = (self->bounds.width |
| - grub_font_get_string_width (self->font, self->text)) / 2; |
| else if (self->align == align_right) |
| left_x = (self->bounds.width |
| - grub_font_get_string_width (self->font, self->text)); |
| else |
| return; /* Invalid alignment. */ |
| |
| if (left_x < 0 || left_x > (int) self->bounds.width) |
| left_x = 0; |
| |
| grub_video_rect_t vpsave; |
| grub_gui_set_viewport (&self->bounds, &vpsave); |
| grub_font_draw_string (self->text, |
| self->font, |
| grub_video_map_rgba_color (self->color), |
| left_x, |
| grub_font_get_ascent (self->font)); |
| grub_gui_restore_viewport (&vpsave); |
| } |
| |
| static void |
| label_set_parent (void *vself, grub_gui_container_t parent) |
| { |
| grub_gui_label_t self = vself; |
| self->parent = parent; |
| } |
| |
| static grub_gui_container_t |
| label_get_parent (void *vself) |
| { |
| grub_gui_label_t self = vself; |
| return self->parent; |
| } |
| |
| static void |
| label_set_bounds (void *vself, const grub_video_rect_t *bounds) |
| { |
| grub_gui_label_t self = vself; |
| self->bounds = *bounds; |
| } |
| |
| static void |
| label_get_bounds (void *vself, grub_video_rect_t *bounds) |
| { |
| grub_gui_label_t self = vself; |
| *bounds = self->bounds; |
| } |
| |
| static void |
| label_get_minimal_size (void *vself, unsigned *width, unsigned *height) |
| { |
| grub_gui_label_t self = vself; |
| *width = grub_font_get_string_width (self->font, self->text); |
| *height = (grub_font_get_ascent (self->font) |
| + grub_font_get_descent (self->font)); |
| } |
| |
| #pragma GCC diagnostic ignored "-Wformat-nonliteral" |
| |
| static void |
| label_set_state (void *vself, int visible, int start __attribute__ ((unused)), |
| int current, int end __attribute__ ((unused))) |
| { |
| grub_gui_label_t self = vself; |
| self->value = -current; |
| self->visible = visible; |
| grub_free (self->text); |
| self->text = grub_xasprintf (self->template ? : "%d", self->value); |
| } |
| |
| static grub_err_t |
| label_set_property (void *vself, const char *name, const char *value) |
| { |
| grub_gui_label_t self = vself; |
| if (grub_strcmp (name, "text") == 0) |
| { |
| grub_free (self->text); |
| grub_free (self->template); |
| if (! value) |
| { |
| self->template = NULL; |
| self->text = grub_strdup (""); |
| } |
| else |
| { |
| if (grub_strcmp (value, "@KEYMAP_LONG@") == 0) |
| value = _("Press enter to boot the selected OS, " |
| "`e' to edit the commands before booting " |
| "or `c' for a command-line. ESC to return previous menu."); |
| else if (grub_strcmp (value, "@KEYMAP_MIDDLE@") == 0) |
| value = _("Press enter to boot the selected OS, " |
| "`e' to edit the commands before booting " |
| "or `c' for a command-line."); |
| else if (grub_strcmp (value, "@KEYMAP_SHORT@") == 0) |
| value = _("enter: boot, `e': options, `c': cmd-line"); |
| /* FIXME: Add more templates here if needed. */ |
| self->template = grub_strdup (value); |
| self->text = grub_xasprintf (value, self->value); |
| } |
| } |
| else if (grub_strcmp (name, "font") == 0) |
| { |
| self->font = grub_font_get (value); |
| } |
| else if (grub_strcmp (name, "color") == 0) |
| { |
| grub_video_parse_color (value, &self->color); |
| } |
| else if (grub_strcmp (name, "align") == 0) |
| { |
| int i; |
| for (i = 0; align_options[i]; i++) |
| { |
| if (grub_strcmp (align_options[i], value) == 0) |
| { |
| self->align = i; /* Set the alignment mode. */ |
| break; |
| } |
| } |
| } |
| else if (grub_strcmp (name, "visible") == 0) |
| { |
| self->visible = grub_strcmp (value, "false") != 0; |
| } |
| else if (grub_strcmp (name, "id") == 0) |
| { |
| grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self); |
| grub_free (self->id); |
| if (value) |
| self->id = grub_strdup (value); |
| else |
| self->id = 0; |
| if (self->id && grub_strcmp (self->id, GRUB_GFXMENU_TIMEOUT_COMPONENT_ID) |
| == 0) |
| grub_gfxmenu_timeout_register ((grub_gui_component_t) self, |
| label_set_state); |
| } |
| return GRUB_ERR_NONE; |
| } |
| |
| #pragma GCC diagnostic error "-Wformat-nonliteral" |
| |
| static struct grub_gui_component_ops label_ops = |
| { |
| .destroy = label_destroy, |
| .get_id = label_get_id, |
| .is_instance = label_is_instance, |
| .paint = label_paint, |
| .set_parent = label_set_parent, |
| .get_parent = label_get_parent, |
| .set_bounds = label_set_bounds, |
| .get_bounds = label_get_bounds, |
| .get_minimal_size = label_get_minimal_size, |
| .set_property = label_set_property |
| }; |
| |
| grub_gui_component_t |
| grub_gui_label_new (void) |
| { |
| grub_gui_label_t label; |
| label = grub_zalloc (sizeof (*label)); |
| if (! label) |
| return 0; |
| label->comp.ops = &label_ops; |
| label->visible = 1; |
| label->text = grub_strdup (""); |
| label->font = grub_font_get ("Unknown Regular 16"); |
| label->color.red = 0; |
| label->color.green = 0; |
| label->color.blue = 0; |
| label->color.alpha = 255; |
| label->align = align_left; |
| return (grub_gui_component_t) label; |
| } |