gui_label.c 7.03 KB
Newer Older
Colin D Bennett's avatar
Colin D Bennett committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* 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>
25
#include <grub/i18n.h>
26
#include <grub/color.h>
Colin D Bennett's avatar
Colin D Bennett committed
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

static const char *align_options[] =
{
  "left",
  "center",
  "right",
  0
};

enum align_mode {
  align_left,
  align_center,
  align_right
};

struct grub_gui_label
{
44
  struct grub_gui_component comp;
Colin D Bennett's avatar
Colin D Bennett committed
45 46 47 48 49 50

  grub_gui_container_t parent;
  grub_video_rect_t bounds;
  char *id;
  int visible;
  char *text;
51
  char *template;
Colin D Bennett's avatar
Colin D Bennett committed
52
  grub_font_t font;
53
  grub_video_rgba_color_t color;
54
  int value;
Colin D Bennett's avatar
Colin D Bennett committed
55 56 57 58 59 60 61 62 63
  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;
64
  grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
Colin D Bennett's avatar
Colin D Bennett committed
65
  grub_free (self->text);
66
  grub_free (self->template);
Colin D Bennett's avatar
Colin D Bennett committed
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
  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
84
label_paint (void *vself, const grub_video_rect_t *region)
Colin D Bennett's avatar
Colin D Bennett committed
85 86 87 88 89 90
{
  grub_gui_label_t self = vself;

  if (! self->visible)
    return;

91 92 93
  if (!grub_video_have_common_points (region, &self->bounds))
    return;

Colin D Bennett's avatar
Colin D Bennett committed
94 95 96 97 98
  /* Calculate the starting x coordinate.  */
  int left_x;
  if (self->align == align_left)
    left_x = 0;
  else if (self->align == align_center)
99 100
    left_x = (self->bounds.width
	      - grub_font_get_string_width (self->font, self->text)) / 2;
Colin D Bennett's avatar
Colin D Bennett committed
101 102 103 104 105 106
  else if (self->align == align_right)
    left_x = (self->bounds.width
              - grub_font_get_string_width (self->font, self->text));
  else
    return;   /* Invalid alignment.  */

107 108 109
  if (left_x < 0 || left_x > (int) self->bounds.width)
    left_x = 0;

Colin D Bennett's avatar
Colin D Bennett committed
110 111 112 113
  grub_video_rect_t vpsave;
  grub_gui_set_viewport (&self->bounds, &vpsave);
  grub_font_draw_string (self->text,
                         self->font,
114
                         grub_video_map_rgba_color (self->color),
Colin D Bennett's avatar
Colin D Bennett committed
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
                         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
149
label_get_minimal_size (void *vself, unsigned *width, unsigned *height)
Colin D Bennett's avatar
Colin D Bennett committed
150 151 152 153 154 155 156
{
  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));
}

157 158
#pragma GCC diagnostic ignored "-Wformat-nonliteral"

159 160 161 162 163 164 165 166 167 168 169
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);
}

170
static grub_err_t
Colin D Bennett's avatar
Colin D Bennett committed
171 172 173 174 175 176
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);
177
      grub_free (self->template);
Colin D Bennett's avatar
Colin D Bennett committed
178
      if (! value)
179 180 181 182 183 184
	{
	  self->template = NULL;
	  self->text = grub_strdup ("");
	}
      else
	{
185 186
	   if (grub_strcmp (value, "@KEYMAP_LONG@") == 0)
	    value = _("Press enter to boot the selected OS, "
187 188
	       "`e' to edit the commands before booting "
	       "or `c' for a command-line. ESC to return previous menu.");
189 190
           else if (grub_strcmp (value, "@KEYMAP_MIDDLE@") == 0)
	    value = _("Press enter to boot the selected OS, "
191 192
	       "`e' to edit the commands before booting "
	       "or `c' for a command-line.");
193
	   else if (grub_strcmp (value, "@KEYMAP_SHORT@") == 0)
194
	    value = _("enter: boot, `e': options, `c': cmd-line");
195
	   /* FIXME: Add more templates here if needed.  */
196 197 198
	  self->template = grub_strdup (value);
	  self->text = grub_xasprintf (value, self->value);
	}
Colin D Bennett's avatar
Colin D Bennett committed
199 200 201 202 203 204 205
    }
  else if (grub_strcmp (name, "font") == 0)
    {
      self->font = grub_font_get (value);
    }
  else if (grub_strcmp (name, "color") == 0)
    {
206
      grub_video_parse_color (value, &self->color);
Colin D Bennett's avatar
Colin D Bennett committed
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
    }
  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)
    {
226
      grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self);
Colin D Bennett's avatar
Colin D Bennett committed
227 228 229 230 231
      grub_free (self->id);
      if (value)
        self->id = grub_strdup (value);
      else
        self->id = 0;
232 233 234 235
      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);
Colin D Bennett's avatar
Colin D Bennett committed
236
    }
237
  return GRUB_ERR_NONE;
Colin D Bennett's avatar
Colin D Bennett committed
238 239
}

240 241
#pragma GCC diagnostic error "-Wformat-nonliteral"

Colin D Bennett's avatar
Colin D Bennett committed
242 243 244 245 246 247 248 249 250 251
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,
252
  .get_minimal_size = label_get_minimal_size,
Colin D Bennett's avatar
Colin D Bennett committed
253 254 255 256 257 258 259
  .set_property = label_set_property
};

grub_gui_component_t
grub_gui_label_new (void)
{
  grub_gui_label_t label;
260
  label = grub_zalloc (sizeof (*label));
Colin D Bennett's avatar
Colin D Bennett committed
261 262
  if (! label)
    return 0;
263
  label->comp.ops = &label_ops;
Colin D Bennett's avatar
Colin D Bennett committed
264 265
  label->visible = 1;
  label->text = grub_strdup ("");
266
  label->font = grub_font_get ("Unknown Regular 16");
Colin D Bennett's avatar
Colin D Bennett committed
267 268 269 270 271 272 273
  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;
}