]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Initial support for scalable gfxmenu
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 29 Dec 2009 16:31:02 +0000 (17:31 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 29 Dec 2009 16:31:02 +0000 (17:31 +0100)
13 files changed:
gfxmenu/gui_box.c
gfxmenu/gui_canvas.c
gfxmenu/gui_circular_progress.c
gfxmenu/gui_image.c
gfxmenu/gui_label.c
gfxmenu/gui_list.c
gfxmenu/gui_progress_bar.c
gfxmenu/gui_string_util.c
gfxmenu/theme_loader.c
gfxmenu/view.c
include/grub/gui.h
include/grub/gui_string_util.h
include/grub/video.h

index 4fe131f981909bdde39f62a1b119001cd52ea513..45028e5b181bacfed561bf7d15b9d9adcab4de32 100644 (file)
@@ -32,17 +32,16 @@ struct component_node
 typedef struct grub_gui_box *grub_gui_box_t;
 
 typedef void (*layout_func_t) (grub_gui_box_t self, int modify_layout,
-                               int *width, int *height);
+                               unsigned *minimal_width,
+                              unsigned *minimal_height);
 
 struct grub_gui_box
 {
-  struct grub_gui_container_ops *container;
+  struct grub_gui_container container;
 
   grub_gui_container_t parent;
   grub_video_rect_t bounds;
   char *id;
-  int preferred_width;
-  int preferred_height;
 
   /* Doubly linked list of components with dummy head & tail nodes.  */
   struct component_node chead;
@@ -87,82 +86,158 @@ box_is_instance (void *vself __attribute__((unused)), const char *type)
 
 static void
 layout_horizontally (grub_gui_box_t self, int modify_layout,
-                     int *width, int *height)
+                     unsigned *min_width, unsigned *min_height)
 {
   /* Start at the left (chead) and set the x coordinates as we go right.  */
   /* All components have their width set to the box's width.  */
 
   struct component_node *cur;
-  int x = 0;
-  if (height)
-    *height = 0;
+  unsigned w = 0, mwfrac = 0, h = 0, x = 0;
+  grub_fixed_unsigned_t wfrac = 0;
+  int bogus_frac = 0;
+
   for (cur = self->chead.next; cur != &self->ctail; cur = cur->next)
     {
       grub_gui_component_t c = cur->component;
+      unsigned mw = 0, mh = 0;
+
+      if (c->ops->get_minimal_size)
+       c->ops->get_minimal_size (c, &mw, &mh);
+
+      if (!c->ishfrac && c->h > h)
+       h = c->h;
+      if (mh > h)
+       h = mh;
+      if (!c->iswfrac)
+       w += mw > c->w ? mw : c->w;
+      if (c->iswfrac)
+       {
+         wfrac += c->wfrac;
+         mwfrac += mw;
+       }
+    }
+  if (wfrac > GRUB_FIXED_1 || (w > 0 && wfrac == GRUB_FIXED_1))
+    bogus_frac = 1;
+
+  if (min_width)
+    {
+      if (wfrac < GRUB_FIXED_1)
+       *min_width = grub_fixed_ufu_divide (w, GRUB_FIXED_1 - wfrac);
+      else
+       *min_width = w;
+      if (*min_width < w + mwfrac)
+       *min_width = w + mwfrac;
+    }
+  if (min_height)
+    *min_height = h;
+
+  if (!modify_layout)
+    return;
+
+  for (cur = self->chead.next; cur != &self->ctail; cur = cur->next)
+    {
       grub_video_rect_t r;
+      grub_gui_component_t c = cur->component;
+      unsigned mw = 0, mh = 0;
 
-      c->ops->get_preferred_size (c, &r.width, &r.height);
+      r.x = x;
+      r.y = 0;
+      r.width = 32;
+      r.height = h;
 
-      /* Check and possibly update the maximum width, if non-null.  */
-      if (height && r.height > *height)
-        *height = r.height;
+      if (c->ops->get_minimal_size)
+       c->ops->get_minimal_size (c, &mw, &mh);
 
-      /* Set the component's bounds, if the flag is set.  */
-      if (modify_layout)
-        {
-          r.x = x;
-          r.y = 0;
-          /* Width comes from the component's preferred size.  */
-          r.height = self->bounds.height;
-          c->ops->set_bounds (c, &r);
-        }
+      if (!c->iswfrac)
+       r.width = c->w;
+      if (c->iswfrac && !bogus_frac)
+       r.width = grub_fixed_ufu_multiply (self->bounds.width, c->wfrac);
+
+      if (r.width < mw)
+       r.width = mw;
+
+      c->ops->set_bounds (c, &r);
 
       x += r.width;
     }
-
-  /* Return the sum of the children's preferred widths.  */
-  if (width)
-    *width = x;
 }
 
 static void
 layout_vertically (grub_gui_box_t self, int modify_layout,
-                   int *width, int *height)
+                     unsigned *min_width, unsigned *min_height)
 {
-  /* Start at the top (chead) and set the y coordinates as we go down.  */
-  /* All components have their width set to the vbox's width.  */
+  /* Start at the top (chead) and set the y coordinates as we go rdown.  */
+  /* All components have their height set to the box's height.  */
 
   struct component_node *cur;
-  int y = 0;
-  if (width)
-    *width = 0;
+  unsigned h = 0, mhfrac = 0, w = 0, y = 0;
+  grub_fixed_unsigned_t hfrac = 0;
+  int bogus_frac = 0;
+
   for (cur = self->chead.next; cur != &self->ctail; cur = cur->next)
     {
       grub_gui_component_t c = cur->component;
+      unsigned mw = 0, mh = 0;
+
+      if (c->ops->get_minimal_size)
+       c->ops->get_minimal_size (c, &mw, &mh);
+
+      if (!c->iswfrac && c->w > w)
+       w = c->w;
+      if (mw > w)
+       w = mw;
+      if (!c->ishfrac)
+       h += mh > c->h ? mh : c->h;
+      if (c->ishfrac)
+       {
+         hfrac += c->hfrac;
+         mhfrac += mh;
+       }
+    }
+  if (hfrac > GRUB_FIXED_1 || (h > 0 && hfrac == GRUB_FIXED_1))
+    bogus_frac = 1;
+
+  if (min_height)
+    {
+      if (hfrac < GRUB_FIXED_1)
+       *min_height = grub_fixed_ufu_divide (h, GRUB_FIXED_1 - hfrac);
+      else
+       *min_height = h;
+      if (*min_height < h + mhfrac)
+       *min_height = h + mhfrac;
+    }
+  if (min_width)
+    *min_width = w;
+
+  if (!modify_layout)
+    return;
+
+  for (cur = self->chead.next; cur != &self->ctail; cur = cur->next)
+    {
       grub_video_rect_t r;
+      grub_gui_component_t c = cur->component;
+      unsigned mw = 0, mh = 0;
 
-      c->ops->get_preferred_size (c, &r.width, &r.height);
+      r.x = 0;
+      r.y = y;
+      r.width = w;
+      r.height = 32;
 
-      /* Check and possibly update the maximum width, if non-null.  */
-      if (width && r.width > *width)
-        *width = r.width;
+      if (c->ops->get_minimal_size)
+       c->ops->get_minimal_size (c, &mw, &mh);
 
-      /* Set the component's bounds, if the flag is set.  */
-      if (modify_layout)
-        {
-          r.x = 0;
-          r.y = y;
-          r.width = self->bounds.width;
-          /* Height comes from the component's preferred size.  */
-          c->ops->set_bounds (c, &r);
-        }
+      if (!c->ishfrac)
+       r.height = c->h;
+      if (c->ishfrac)
+       r.height = grub_fixed_ufu_multiply (self->bounds.height, c->hfrac);
+
+      if (r.height < mh)
+       r.height = mh;
+
+      c->ops->set_bounds (c, &r);
 
       y += r.height;
     }
-
-  /* Return the sum of the children's preferred heights.  */
-  if (height)
-    *height = y;
 }
 
 static void
@@ -213,16 +288,10 @@ box_get_bounds (void *vself, grub_video_rect_t *bounds)
 /* The box's preferred size is based on the preferred sizes
    of its children.  */
 static void
-box_get_preferred_size (void *vself, int *width, int *height)
+box_get_minimal_size (void *vself, unsigned *width, unsigned *height)
 {
   grub_gui_box_t self = vself;
   self->layout_func (self, 0, width, height);   /* Just calculate the size.  */
-
-  /* Allow preferred dimensions to override the computed dimensions.  */
-  if (self->preferred_width >= 0)
-    *width = self->preferred_width;
-  if (self->preferred_height >= 0)
-    *height = self->preferred_height;
 }
 
 static grub_err_t
@@ -241,15 +310,6 @@ box_set_property (void *vself, const char *name, const char *value)
       else
         self->id = 0;
     }
-  else if (grub_strcmp (name, "preferred_size") == 0)
-    {
-      int w;
-      int h;
-      if (grub_gui_parse_2_tuple (value, &w, &h) != GRUB_ERR_NONE)
-        return grub_errno;
-      self->preferred_width = w;
-      self->preferred_height = h;
-    }
 
   return grub_errno;
 }
@@ -303,21 +363,22 @@ box_iterate_children (void *vself,
     cb (cur->component, userdata);
 }
 
+static struct grub_gui_component_ops box_comp_ops =
+  {
+    .destroy = box_destroy,
+    .get_id = box_get_id,
+    .is_instance = box_is_instance,
+    .paint = box_paint,
+    .set_parent = box_set_parent,
+    .get_parent = box_get_parent,
+    .set_bounds = box_set_bounds,
+    .get_bounds = box_get_bounds,
+    .get_minimal_size = box_get_minimal_size,
+    .set_property = box_set_property
+  };
+
 static struct grub_gui_container_ops box_ops =
 {
-  .component =
-    {
-      .destroy = box_destroy,
-      .get_id = box_get_id,
-      .is_instance = box_is_instance,
-      .paint = box_paint,
-      .set_parent = box_set_parent,
-      .get_parent = box_get_parent,
-      .set_bounds = box_set_bounds,
-      .get_bounds = box_get_bounds,
-      .get_preferred_size = box_get_preferred_size,
-      .set_property = box_set_property
-    },
   .add = box_add,
   .remove = box_remove,
   .iterate_children = box_iterate_children
@@ -329,24 +390,13 @@ static grub_gui_box_t
 box_new (layout_func_t layout_func)
 {
   grub_gui_box_t box;
-  box = grub_malloc (sizeof (*box));
+  box = grub_zalloc (sizeof (*box));
   if (! box)
     return 0;
-  box->container = &box_ops;
-  box->parent = 0;
-  box->bounds.x = 0;
-  box->bounds.y = 0;
-  box->bounds.width = 0;
-  box->bounds.height = 0;
-  box->id = 0;
-  box->preferred_width = -1;
-  box->preferred_height = -1;
-  box->chead.component = 0;
-  box->chead.prev = 0;
+  box->container.ops = &box_ops;
+  box->container.component.ops = &box_comp_ops;
   box->chead.next = &box->ctail;
-  box->ctail.component = 0;
   box->ctail.prev = &box->chead;
-  box->ctail.next = 0;
   box->layout_func = layout_func;
   return box;
 }
index d155364d73e94830abbd390bf237f92c7e766bfa..8b55b2a731c5e996f25c60a8ac5340ab8c283086 100644 (file)
@@ -32,13 +32,11 @@ struct component_node
 
 struct grub_gui_canvas
 {
-  struct grub_gui_container_ops *container;
+  struct grub_gui_container container;
 
   grub_gui_container_t parent;
   grub_video_rect_t bounds;
   char *id;
-  int preferred_width;
-  int preferred_height;
   /* Component list (dummy head node).  */
   struct component_node components;
 };
@@ -88,22 +86,52 @@ canvas_paint (void *vself, const grub_video_rect_t *region)
   grub_gui_set_viewport (&self->bounds, &vpsave);
   for (cur = self->components.next; cur; cur = cur->next)
     {
-      int pw;
-      int ph;
       grub_video_rect_t r;
       grub_gui_component_t comp;
 
       comp = cur->component;
 
-      /* Give the child its preferred size.  */
-      comp->ops->get_preferred_size (comp, &pw, &ph);
-      comp->ops->get_bounds (comp, &r);
-      if (r.width != pw || r.height != ph)
-        {
-          r.width = pw;
-          r.height = ph;
-          comp->ops->set_bounds (comp, &r);
-        }
+      r.x = 0;
+      r.y = 0;
+      r.width = 32;
+      r.height = 32;
+
+      if (!comp->iswfrac && comp->w)
+       r.width = comp->w;
+
+      if (!comp->ishfrac && comp->h)
+       r.height = comp->h;
+
+      if (!comp->isxfrac && comp->x)
+       r.x = comp->x;
+
+      if (!comp->isyfrac && comp->y)
+       r.y = comp->y;
+
+      if (comp->ishfrac && comp->hfrac)
+       r.height = grub_fixed_ufu_multiply (self->bounds.height, comp->hfrac);
+
+      if (comp->iswfrac && comp->wfrac)
+       r.width = grub_fixed_ufu_multiply (self->bounds.width, comp->wfrac);
+
+      if (comp->isxfrac && comp->xfrac)
+       r.x = grub_fixed_ufu_multiply (self->bounds.width, comp->xfrac);
+
+      if (comp->isyfrac && comp->yfrac)
+       r.y = grub_fixed_ufu_multiply (self->bounds.height, comp->yfrac);
+
+      if (comp->ops->get_minimal_size)
+       {
+         unsigned mw;
+         unsigned mh;
+         comp->ops->get_minimal_size (comp, &mw, &mh);
+         if (r.width < mw)
+           r.width = mw;
+         if (r.height < mh)
+           r.height = mh;
+       }
+
+      comp->ops->set_bounds (comp, &r);
 
       /* Paint the child.  */
       if (grub_video_have_common_points (region, &r))
@@ -140,20 +168,6 @@ canvas_get_bounds (void *vself, grub_video_rect_t *bounds)
   *bounds = self->bounds;
 }
 
-static void
-canvas_get_preferred_size (void *vself, int *width, int *height)
-{
-  grub_gui_canvas_t self = vself;
-  *width = 0;
-  *height = 0;
-
-  /* Allow preferred dimensions to override the empty dimensions.  */
-  if (self->preferred_width >= 0)
-    *width = self->preferred_width;
-  if (self->preferred_height >= 0)
-    *height = self->preferred_height;
-}
-
 static grub_err_t
 canvas_set_property (void *vself, const char *name, const char *value)
 {
@@ -170,15 +184,6 @@ canvas_set_property (void *vself, const char *name, const char *value)
       else
         self->id = 0;
     }
-  else if (grub_strcmp (name, "preferred_size") == 0)
-    {
-      int w;
-      int h;
-      if (grub_gui_parse_2_tuple (value, &w, &h) != GRUB_ERR_NONE)
-        return grub_errno;
-      self->preferred_width = w;
-      self->preferred_height = h;
-    }
   return grub_errno;
 }
 
@@ -227,21 +232,21 @@ canvas_iterate_children (void *vself,
     cb (cur->component, userdata);
 }
 
+static struct grub_gui_component_ops canvas_comp_ops =
+{
+  .destroy = canvas_destroy,
+  .get_id = canvas_get_id,
+  .is_instance = canvas_is_instance,
+  .paint = canvas_paint,
+  .set_parent = canvas_set_parent,
+  .get_parent = canvas_get_parent,
+  .set_bounds = canvas_set_bounds,
+  .get_bounds = canvas_get_bounds,
+  .set_property = canvas_set_property
+};
+
 static struct grub_gui_container_ops canvas_ops =
 {
-  .component =
-    {
-      .destroy = canvas_destroy,
-      .get_id = canvas_get_id,
-      .is_instance = canvas_is_instance,
-      .paint = canvas_paint,
-      .set_parent = canvas_set_parent,
-      .get_parent = canvas_get_parent,
-      .set_bounds = canvas_set_bounds,
-      .get_bounds = canvas_get_bounds,
-      .get_preferred_size = canvas_get_preferred_size,
-      .set_property = canvas_set_property
-    },
   .add = canvas_add,
   .remove = canvas_remove,
   .iterate_children = canvas_iterate_children
@@ -251,19 +256,10 @@ grub_gui_container_t
 grub_gui_canvas_new (void)
 {
   grub_gui_canvas_t canvas;
-  canvas = grub_malloc (sizeof (*canvas));
+  canvas = grub_zalloc (sizeof (*canvas));
   if (! canvas)
     return 0;
-  canvas->container = &canvas_ops;
-  canvas->parent = 0;
-  canvas->bounds.x = 0;
-  canvas->bounds.y = 0;
-  canvas->bounds.width = 0;
-  canvas->bounds.height = 0;
-  canvas->id = 0;
-  canvas->preferred_width = -1;
-  canvas->preferred_height = -1;
-  canvas->components.component = 0;
-  canvas->components.next = 0;
+  canvas->container.ops = &canvas_ops;
+  canvas->container.component.ops = &canvas_comp_ops;
   return (grub_gui_container_t) canvas;
 }
index f3c8bc3af67ae2c6e86eef9befec0c6c01cd0679..e57d1c23699c236d6db7c2f19b54e95cb470cbdc 100644 (file)
 
 struct grub_gui_circular_progress
 {
-  struct grub_gui_component_ops *circprog_ops;
+  struct grub_gui_component comp;
 
   grub_gui_container_t parent;
   grub_video_rect_t bounds;
   char *id;
-  int preferred_width;
-  int preferred_height;
   int visible;
   int start;
   int end;
@@ -209,21 +207,6 @@ circprog_get_bounds (void *vself, grub_video_rect_t *bounds)
   *bounds = self->bounds;
 }
 
-static void
-circprog_get_preferred_size (void *vself, int *width, int *height)
-{
-  circular_progress_t self = vself;
-
-  *width = 0;
-  *height = 0;
-
-  /* Allow preferred dimensions to override the circprog dimensions.  */
-  if (self->preferred_width >= 0)
-    *width = self->preferred_width;
-  if (self->preferred_height >= 0)
-    *height = self->preferred_height;
-}
-
 static grub_err_t
 circprog_set_property (void *vself, const char *name, const char *value)
 {
@@ -270,15 +253,6 @@ circprog_set_property (void *vself, const char *name, const char *value)
       grub_free (self->theme_dir);
       self->theme_dir = value ? grub_strdup (value) : 0;
     }
-  else if (grub_strcmp (name, "preferred_size") == 0)
-    {
-      int w;
-      int h;
-      if (grub_gui_parse_2_tuple (value, &w, &h) != GRUB_ERR_NONE)
-        return grub_errno;
-      self->preferred_width = w;
-      self->preferred_height = h;
-    }
   else if (grub_strcmp (name, "visible") == 0)
     {
       self->visible = grub_strcmp (value, "false") != 0;
@@ -304,7 +278,6 @@ static struct grub_gui_component_ops circprog_ops =
   .get_parent = circprog_get_parent,
   .set_bounds = circprog_set_bounds,
   .get_bounds = circprog_get_bounds,
-  .get_preferred_size = circprog_get_preferred_size,
   .set_property = circprog_set_property
 };
 
@@ -312,32 +285,13 @@ grub_gui_component_t
 grub_gui_circular_progress_new (void)
 {
   circular_progress_t self;
-  self = grub_malloc (sizeof (*self));
+  self = grub_zalloc (sizeof (*self));
   if (! self)
     return 0;
-  self->circprog_ops = &circprog_ops;
-  self->parent = 0;
-  self->bounds.x = 0;
-  self->bounds.y = 0;
-  self->bounds.width = 0;
-  self->bounds.height = 0;
-  self->id = 0;
-  self->preferred_width = -1;
-  self->preferred_height = -1;
+  self->comp.ops = &circprog_ops;
   self->visible = 1;
-  self->start = 0;
-  self->end = 0;
-  self->value = 0;
   self->num_ticks = 64;
   self->start_angle = -64;
-  self->ticks_disappear = 0;
-
-  self->theme_dir = 0;
-  self->need_to_load_pixmaps = 0;
-  self->center_file = 0;
-  self->tick_file = 0;
-  self->center_bitmap = 0;
-  self->tick_bitmap = 0;
 
   return (grub_gui_component_t) self;
 }
index eb2ff1ee0f87e1847fa7b32069fb29430f22dd6b..ef8bcbe9afd34a1328bb71095084bd6cac5233ce 100644 (file)
 
 struct grub_gui_image
 {
-  struct grub_gui_component_ops *image;
+  struct grub_gui_component component;
 
   grub_gui_container_t parent;
   grub_video_rect_t bounds;
   char *id;
-  int preferred_width;
-  int preferred_height;
   struct grub_video_bitmap *raw_bitmap;
   struct grub_video_bitmap *bitmap;
 };
@@ -172,8 +170,9 @@ image_get_bounds (void *vself, grub_video_rect_t *bounds)
   *bounds = self->bounds;
 }
 
+/* FIXME: inform rendering system it's not forced minimum.  */
 static void
-image_get_preferred_size (void *vself, int *width, int *height)
+image_get_minimal_size (void *vself, unsigned *width, unsigned *height)
 {
   grub_gui_image_t self = vself;
 
@@ -187,12 +186,6 @@ image_get_preferred_size (void *vself, int *width, int *height)
       *width = 0;
       *height = 0;
     }
-
-  /* Allow preferred dimensions to override the image dimensions.  */
-  if (self->preferred_width >= 0)
-    *width = self->preferred_width;
-  if (self->preferred_height >= 0)
-    *height = self->preferred_height;
 }
 
 static grub_err_t
@@ -217,15 +210,6 @@ image_set_property (void *vself, const char *name, const char *value)
   grub_gui_image_t self = vself;
   if (grub_strcmp (name, "file") == 0)
     return load_image (self, value);
-  else if (grub_strcmp (name, "preferred_size") == 0)
-    {
-      int w;
-      int h;
-      if (grub_gui_parse_2_tuple (value, &w, &h) != GRUB_ERR_NONE)
-        return grub_errno;
-      self->preferred_width = w;
-      self->preferred_height = h;
-    }
   else if (grub_strcmp (name, "id") == 0)
     {
       grub_free (self->id);
@@ -247,7 +231,7 @@ static struct grub_gui_component_ops image_ops =
   .get_parent = image_get_parent,
   .set_bounds = image_set_bounds,
   .get_bounds = image_get_bounds,
-  .get_preferred_size = image_get_preferred_size,
+  .get_minimal_size = image_get_minimal_size,
   .set_property = image_set_property
 };
 
@@ -255,20 +239,10 @@ grub_gui_component_t
 grub_gui_image_new (void)
 {
   grub_gui_image_t image;
-  image = grub_malloc (sizeof (*image));
+  image = grub_zalloc (sizeof (*image));
   if (! image)
     return 0;
-  image->image = &image_ops;
-  image->parent = 0;
-  image->bounds.x = 0;
-  image->bounds.y = 0;
-  image->bounds.width = 0;
-  image->bounds.height = 0;
-  image->id = 0;
-  image->preferred_width = -1;
-  image->preferred_height = -1;
-  image->raw_bitmap = 0;
-  image->bitmap = 0;
+  image->component.ops = &image_ops;
   return (grub_gui_component_t) image;
 }
 
index 30474f52f00e1b7fbba516ade4769e8c3cbb3332..b2835ea1ab7d737085a12dc64f4598899b196795 100644 (file)
@@ -39,13 +39,11 @@ enum align_mode {
 
 struct grub_gui_label
 {
-  struct grub_gui_component_ops *label;
+  struct grub_gui_component comp;
 
   grub_gui_container_t parent;
   grub_video_rect_t bounds;
   char *id;
-  int preferred_width;
-  int preferred_height;
   int visible;
   char *text;
   grub_font_t font;
@@ -140,18 +138,12 @@ label_get_bounds (void *vself, grub_video_rect_t *bounds)
 }
 
 static void
-label_get_preferred_size (void *vself, int *width, int *height)
+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));
-
-  /* Allow preferred dimensions to override the computed dimensions.  */
-  if (self->preferred_width >= 0)
-    *width = self->preferred_width;
-  if (self->preferred_height >= 0)
-    *height = self->preferred_height;
 }
 
 static grub_err_t
@@ -189,16 +181,6 @@ label_set_property (void *vself, const char *name, const char *value)
     {
       self->visible = grub_strcmp (value, "false") != 0;
     }
-  else if (grub_strcmp (name, "preferred_size") == 0)
-    {
-      int w;
-      int h;
-      if (grub_gui_parse_2_tuple (value, &w, &h) == GRUB_ERR_NONE)
-        {
-          self->preferred_width = w;
-          self->preferred_height = h;
-        }
-    }
   else if (grub_strcmp (name, "id") == 0)
     {
       grub_free (self->id);
@@ -220,7 +202,7 @@ static struct grub_gui_component_ops label_ops =
   .get_parent = label_get_parent,
   .set_bounds = label_set_bounds,
   .get_bounds = label_get_bounds,
-  .get_preferred_size = label_get_preferred_size,
+  .get_minimal_size = label_get_minimal_size,
   .set_property = label_set_property
 };
 
@@ -228,18 +210,10 @@ grub_gui_component_t
 grub_gui_label_new (void)
 {
   grub_gui_label_t label;
-  label = grub_malloc (sizeof (*label));
+  label = grub_zalloc (sizeof (*label));
   if (! label)
     return 0;
-  label->label = &label_ops;
-  label->parent = 0;
-  label->bounds.x = 0;
-  label->bounds.y = 0;
-  label->bounds.width = 0;
-  label->bounds.height = 0;
-  label->id = 0;
-  label->preferred_width = -1;
-  label->preferred_height = -1;
+  label->comp.ops = &label_ops;
   label->visible = 1;
   label->text = grub_strdup ("");
   label->font = grub_font_get ("Helvetica 10");
index bf6d94657bef0f805ab27d9f9d2bba8489dc4faa..c55cfd85cf101582b352127ab578dcfd23722d91 100644 (file)
 
 struct grub_gui_list_impl
 {
-  struct grub_gui_list_ops *list_ops;
+  struct grub_gui_list list;
 
   grub_gui_container_t parent;
   grub_video_rect_t bounds;
   char *id;
-  int preferred_width;
-  int preferred_height;
   int visible;
 
   int icon_width;
@@ -357,7 +355,7 @@ list_get_bounds (void *vself, grub_video_rect_t *bounds)
 }
 
 static void
-list_get_preferred_size (void *vself, int *width, int *height)
+list_get_minimal_size (void *vself, unsigned *width, unsigned *height)
 {
   list_impl_t self = vself;
 
@@ -387,12 +385,6 @@ list_get_preferred_size (void *vself, int *width, int *height)
       *width = 0;
       *height = 0;
     }
-
-  /* Allow preferred dimensions to override the computed dimensions.  */
-  if (self->preferred_width >= 0)
-    *width = self->preferred_width;
-  if (self->preferred_height >= 0)
-    *height = self->preferred_height;
 }
 
 static grub_err_t
@@ -507,15 +499,6 @@ list_set_property (void *vself, const char *name, const char *value)
       grub_free (self->theme_dir);
       self->theme_dir = value ? grub_strdup (value) : 0;
     }
-  else if (grub_strcmp (name, "preferred_size") == 0)
-    {
-      int w;
-      int h;
-      if (grub_gui_parse_2_tuple (value, &w, &h) != GRUB_ERR_NONE)
-        return grub_errno;
-      self->preferred_width = w;
-      self->preferred_height = h;
-    }
   else if (grub_strcmp (name, "id") == 0)
     {
       grub_free (self->id);
@@ -538,21 +521,22 @@ list_set_view_info (void *vself,
   self->menu = menu;
 }
 
+static struct grub_gui_component_ops list_comp_ops =
+  {
+    .destroy = list_destroy,
+    .get_id = list_get_id,
+    .is_instance = list_is_instance,
+    .paint = list_paint,
+    .set_parent = list_set_parent,
+    .get_parent = list_get_parent,
+    .set_bounds = list_set_bounds,
+    .get_bounds = list_get_bounds,
+    .get_minimal_size = list_get_minimal_size,
+    .set_property = list_set_property
+  };
+
 static struct grub_gui_list_ops list_ops =
 {
-  .component_ops =
-    {
-      .destroy = list_destroy,
-      .get_id = list_get_id,
-      .is_instance = list_is_instance,
-      .paint = list_paint,
-      .set_parent = list_set_parent,
-      .get_parent = list_get_parent,
-      .set_bounds = list_set_bounds,
-      .get_bounds = list_get_bounds,
-      .get_preferred_size = list_get_preferred_size,
-      .set_property = list_set_property
-    },
   .set_view_info = list_set_view_info
 };
 
@@ -564,19 +548,13 @@ grub_gui_list_new (void)
   grub_gui_color_t default_fg_color;
   grub_gui_color_t default_bg_color;
 
-  self = grub_malloc (sizeof (*self));
+  self = grub_zalloc (sizeof (*self));
   if (! self)
     return 0;
 
-  self->list_ops = &list_ops;
-  self->parent = 0;
-  self->bounds.x = 0;
-  self->bounds.y = 0;
-  self->bounds.width = 0;
-  self->bounds.height = 0;
-  self->id = 0;
-  self->preferred_width = -1;
-  self->preferred_height = -1;
+  self->list.ops = &list_ops;
+  self->list.component.ops = &list_comp_ops;
+
   self->visible = 1;
 
   default_font = grub_font_get ("Helvetica 12");
@@ -617,7 +595,7 @@ grub_gui_list_new (void)
   self->icon_manager = grub_gfxmenu_icon_manager_new ();
   if (! self->icon_manager)
     {
-      self->list_ops->component_ops.destroy (self);
+      self->list.component.ops->destroy (self);
       return 0;
     }
   grub_gfxmenu_icon_manager_set_icon_size (self->icon_manager,
index 49871116990b9ea1fc4ba71ad9c7544813affd05..9af93cff5a59ef960a3892317c451e8c704ddcde 100644 (file)
 
 struct grub_gui_progress_bar
 {
-  struct grub_gui_component_ops *progress_bar;
+  struct grub_gui_component component;
 
   grub_gui_container_t parent;
   grub_video_rect_t bounds;
   char *id;
-  int preferred_width;
-  int preferred_height;
   int visible;
   int start;
   int end;
@@ -221,18 +219,11 @@ progress_bar_get_bounds (void *vself, grub_video_rect_t *bounds)
 }
 
 static void
-progress_bar_get_preferred_size (void *vself, int *width, int *height)
+progress_bar_get_minimal_size (void *vself __attribute__ ((unused)),
+                              unsigned *width, unsigned *height)
 {
-  grub_gui_progress_bar_t self = vself;
-
   *width = 200;
   *height = 28;
-
-  /* Allow preferred dimensions to override the progress_bar dimensions.  */
-  if (self->preferred_width >= 0)
-    *width = self->preferred_width;
-  if (self->preferred_height >= 0)
-    *height = self->preferred_height;
 }
 
 static grub_err_t
@@ -296,15 +287,6 @@ progress_bar_set_property (void *vself, const char *name, const char *value)
       grub_free (self->theme_dir);
       self->theme_dir = value ? grub_strdup (value) : 0;
     }
-  else if (grub_strcmp (name, "preferred_size") == 0)
-    {
-      int w;
-      int h;
-      if (grub_gui_parse_2_tuple (value, &w, &h) != GRUB_ERR_NONE)
-        return grub_errno;
-      self->preferred_width = w;
-      self->preferred_height = h;
-    }
   else if (grub_strcmp (name, "visible") == 0)
     {
       self->visible = grub_strcmp (value, "false") != 0;
@@ -334,7 +316,7 @@ static struct grub_gui_component_ops progress_bar_ops =
   .get_parent = progress_bar_get_parent,
   .set_bounds = progress_bar_set_bounds,
   .get_bounds = progress_bar_get_bounds,
-  .get_preferred_size = progress_bar_get_preferred_size,
+  .get_minimal_size = progress_bar_get_minimal_size,
   .set_property = progress_bar_set_property
 };
 
@@ -342,22 +324,11 @@ grub_gui_component_t
 grub_gui_progress_bar_new (void)
 {
   grub_gui_progress_bar_t self;
-  self = grub_malloc (sizeof (*self));
+  self = grub_zalloc (sizeof (*self));
   if (! self)
     return 0;
-  self->progress_bar = &progress_bar_ops;
-  self->parent = 0;
-  self->bounds.x = 0;
-  self->bounds.y = 0;
-  self->bounds.width = 0;
-  self->bounds.height = 0;
-  self->id = 0;
-  self->preferred_width = -1;
-  self->preferred_height = -1;
+  self->component.ops = &progress_bar_ops;
   self->visible = 1;
-  self->start = 0;
-  self->end = 0;
-  self->value = 0;
   self->show_text = 1;
   self->text = grub_strdup ("");
   self->font = grub_font_get ("Helvetica 10");
@@ -369,12 +340,5 @@ grub_gui_progress_bar_new (void)
   self->bg_color = gray;
   self->fg_color = lightgray;
 
-  self->theme_dir = 0;
-  self->need_to_recreate_pixmaps = 0;
-  self->bar_pattern = 0;
-  self->highlight_pattern = 0;
-  self->bar_box = 0;
-  self->highlight_box = 0;
-
   return (grub_gui_component_t) self;
 }
index 8ea7c497b3601bce886f05e679b3a12dbf208ea1..8c51e396a692f6cafee55ab87954ec037502fe10 100644 (file)
@@ -325,41 +325,3 @@ grub_gui_parse_color (const char *s, grub_gui_color_t *color)
     *color = c;
   return grub_errno;
 }
-
-/* Parse a value in the form "(x, y)", storing the first element (x) into
-   *PX and the second element (y) into *PY.
-   Returns GRUB_ERR_NONE if successfully parsed.  */
-grub_err_t
-grub_gui_parse_2_tuple (const char *s, int *px, int *py)
-{
-  int x;
-  int y;
-
-  while (*s && grub_isspace (*s))
-    s++;
-  if (*s != '(')
-    return grub_error (GRUB_ERR_BAD_ARGUMENT,
-                       "missing `(' in 2-tuple `%s'", s);
-
-  /* Skip the opening parentheses.  */
-  s++;
-  if (*s == 0)
-    return grub_error (GRUB_ERR_BAD_ARGUMENT,
-                       "unexpected end of 2-tuple after `(' in `%s'", s);
-
-  /* Parse the first element.  */
-  x = grub_strtol (s, 0, 10);
-  if ((s = grub_strchr (s, ',')) == 0)
-    return grub_error (GRUB_ERR_BAD_ARGUMENT,
-                       "missing comma in 2-tuple `%s'", s);
-
-  /* Skip the element separator (the comma).  */
-  s++;
-  /* Parse the second element.  */
-  y = grub_strtol (s, 0, 10);
-
-  *px = x;
-  *py = y;
-
-  return grub_errno;
-}
index 3512c7bf148e79aeb224fc2e6e5ef27096d49a4f..29bc1d2a62ab086258e6f6030d8e01969e257db4 100644 (file)
@@ -510,35 +510,73 @@ read_object (struct parsebuf *p, grub_gui_container_t parent)
         }
 
       /* Handle the property value.  */
-      if (grub_strcmp (property, "position") == 0)
+      if (grub_strcmp (property, "left") == 0)
         {
-          /* Special case for position value.  */
-          int x;
-          int y;
-
-          if (grub_gui_parse_2_tuple (value, &x, &y) == GRUB_ERR_NONE)
-            {
-              grub_video_rect_t r;
-              component->ops->get_bounds (component, &r);
-              r.x = x;
-              r.y = y;
-              component->ops->set_bounds (component, &r);
-            }
+         unsigned num;
+         char *ptr;
+         num = grub_strtoul (value, &ptr, 0);
+         if (*ptr == '%')
+           {
+             component->isxfrac = 1;
+             component->xfrac
+               = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
+           }
+         else
+           {
+             component->isxfrac = 0;
+             component->x = num;
+           }
         }
-      else if (grub_strcmp (property, "size") == 0)
+      else if (grub_strcmp (property, "top") == 0)
         {
-          /* Special case for size value.  */
-          int w;
-          int h;
-
-          if (grub_gui_parse_2_tuple (value, &w, &h) == GRUB_ERR_NONE)
-            {
-              grub_video_rect_t r;
-              component->ops->get_bounds (component, &r);
-              r.width = w;
-              r.height = h;
-              component->ops->set_bounds (component, &r);
-            }
+         unsigned num;
+         char *ptr;
+         num = grub_strtoul (value, &ptr, 0);
+         if (*ptr == '%')
+           {
+             component->isyfrac = 1;
+             component->yfrac
+               = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
+           }
+         else
+           {
+             component->isyfrac = 0;
+             component->y = num;
+           }
+        }
+      else if (grub_strcmp (property, "width") == 0)
+        {
+         unsigned num;
+         char *ptr;
+         num = grub_strtoul (value, &ptr, 0);
+         if (*ptr == '%')
+           {
+             component->iswfrac = 1;
+             component->wfrac
+               = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
+           }
+         else
+           {
+             component->iswfrac = 0;
+             component->w = num;
+           }
+        }
+      else if (grub_strcmp (property, "height") == 0)
+        {
+         unsigned num;
+         char *ptr;
+         num = grub_strtoul (value, &ptr, 0);
+         if (*ptr == '%')
+           {
+             component->ishfrac = 1;
+             component->hfrac
+               = grub_fixed_fuf_divide (grub_unsigned_to_fixed (num), 100);
+           }
+         else
+           {
+             component->ishfrac = 0;
+             component->h = num;
+           }
         }
       else
         {
@@ -552,16 +590,6 @@ read_object (struct parsebuf *p, grub_gui_container_t parent)
         goto cleanup;
     }
 
-  /* Set the object's size to its preferred size unless the user has
-     explicitly specified the size.  */
-  component->ops->get_bounds (component, &bounds);
-  if (bounds.width == -1 || bounds.height == -1)
-    {
-      component->ops->get_preferred_size (component,
-                                          &bounds.width, &bounds.height);
-      component->ops->set_bounds (component, &bounds);
-    }
-
 cleanup:
   grub_free (name);
   return grub_errno;
@@ -665,7 +693,7 @@ grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path)
     }
 
   if (view->canvas)
-    view->canvas->ops->component.destroy (view->canvas);
+    view->canvas->component.ops->destroy (view->canvas);
 
   view->canvas = grub_gui_canvas_new ();
   ((grub_gui_component_t) view->canvas)
@@ -708,7 +736,7 @@ grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path)
 fail:
   if (view->canvas)
     {
-      view->canvas->ops->component.destroy (view->canvas);
+      view->canvas->component.ops->destroy (view->canvas);
       view->canvas = 0;
     }
 
index e2348b6ef51a7e4ee8b07a8a7c763bc17e8af8c8..414541ddab00e37bd2c14fa247a145e41d082886 100644 (file)
@@ -146,7 +146,7 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view)
   grub_free (view->progress_message_text);
   grub_free (view->theme_path);
   if (view->canvas)
-    view->canvas->ops->component.destroy (view->canvas);
+    view->canvas->component.ops->destroy (view->canvas);
   grub_free (view);
 
   set_text_mode ();
@@ -354,7 +354,7 @@ grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view,
 
   redraw_background (view, region);
   if (view->canvas)
-    view->canvas->ops->component.paint (view->canvas, region);
+    view->canvas->component.ops->paint (view->canvas, region);
   draw_title (view);
   if (grub_video_have_common_points (&view->progress_message_frame, region))
     draw_message (view);
index 385c0962be10fe319ae1b32682392b41fc6943b2..873d29e7665734794f35a8508659176bd4616687 100644 (file)
@@ -55,14 +55,13 @@ struct grub_gui_component_ops
   grub_gui_container_t (*get_parent) (void *self);
   void (*set_bounds) (void *self, const grub_video_rect_t *bounds);
   void (*get_bounds) (void *self, grub_video_rect_t *bounds);
-  void (*get_preferred_size) (void *self, int *width, int *height);
+  void (*get_minimal_size) (void *self, unsigned *width, unsigned *height);
   grub_err_t (*set_property) (void *self, const char *name, const char *value);
   void (*repaint) (void *self, int second_pass);
 };
 
 struct grub_gui_container_ops
 {
-  struct grub_gui_component_ops component;
   void (*add) (void *self, grub_gui_component_t comp);
   void (*remove) (void *self, grub_gui_component_t comp);
   void (*iterate_children) (void *self,
@@ -71,24 +70,78 @@ struct grub_gui_container_ops
 
 struct grub_gui_list_ops
 {
-  struct grub_gui_component_ops component_ops;
   void (*set_view_info) (void *self,
                          const char *theme_path,
                          grub_gfxmenu_model_t menu);
 };
 
+typedef grub_uint32_t grub_fixed_unsigned_t;
+#define GRUB_FIXED_1 0x10000
+
+static inline unsigned
+grub_fixed_ufu_divide (grub_uint32_t a, grub_fixed_unsigned_t b)
+{
+  return (a << 16) / b;
+}
+
+static inline grub_fixed_unsigned_t
+grub_fixed_fuf_divide (grub_fixed_unsigned_t a, grub_uint32_t b)
+{
+  return a / b;
+}
+
+static inline unsigned
+grub_fixed_ufu_multiply (grub_uint32_t a, grub_fixed_unsigned_t b)
+{
+  return (a * b) >> 16;
+}
+
+static inline unsigned
+grub_fixed_to_unsigned (grub_fixed_unsigned_t in)
+{
+  return in >> 16;
+}
+
+static inline grub_fixed_unsigned_t
+grub_unsigned_to_fixed (unsigned in)
+{
+  return in << 16;
+}
+
 struct grub_gui_component
 {
   struct grub_gui_component_ops *ops;
+  int isxfrac:1;
+  int isyfrac:1;
+  int iswfrac:1;
+  int ishfrac:1;
+  union {
+    unsigned x;
+    grub_fixed_unsigned_t xfrac;
+  };
+  union {
+    unsigned y;
+    grub_fixed_unsigned_t yfrac;
+  };
+  union {
+    unsigned w;
+    grub_fixed_unsigned_t wfrac;
+  };
+  union {
+    unsigned h;
+    grub_fixed_unsigned_t hfrac;
+  };
 };
 
 struct grub_gui_container
 {
+  struct grub_gui_component component;
   struct grub_gui_container_ops *ops;
 };
 
 struct grub_gui_list
 {
+  struct grub_gui_component component;
   struct grub_gui_list_ops *ops;
 };
 
index 7b5fbb3eaaedd8e896b089bdda8830c116e8372a..1baa2eedee42ad138c9955a8d89e72b33993326a 100644 (file)
@@ -34,6 +34,4 @@ int grub_gui_get_named_color (const char *name, grub_gui_color_t *color);
 
 grub_err_t grub_gui_parse_color (const char *s, grub_gui_color_t *color);
 
-grub_err_t grub_gui_parse_2_tuple (const char *s, int *px, int *py);
-
 #endif /* GRUB_GUI_STRING_UTIL_HEADER */
index 833df04c87916bae75ee57f3160b8f2cca4f8b04..868e87871e15b834f25d7c0cfd5de7b31d3372c2 100644 (file)
@@ -160,10 +160,10 @@ struct grub_video_mode_info
 /* A 2D rectangle type.  */
 struct grub_video_rect
 {
-  int x;
-  int y;
-  int width;
-  int height;
+  unsigned x;
+  unsigned y;
+  unsigned width;
+  unsigned height;
 };
 typedef struct grub_video_rect grub_video_rect_t;