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;
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
/* 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
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;
}
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
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;
}
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;
};
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))
*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)
{
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;
}
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
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;
}
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;
*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)
{
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;
.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
};
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;
}
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;
};
*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;
*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
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);
.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
};
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;
}
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;
}
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
{
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);
.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
};
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");
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;
}
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;
*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
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);
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
};
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");
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,
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;
}
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
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;
.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
};
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");
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;
}
*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;
-}
}
/* 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
{
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;
}
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)
fail:
if (view->canvas)
{
- view->canvas->ops->component.destroy (view->canvas);
+ view->canvas->component.ops->destroy (view->canvas);
view->canvas = 0;
}
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 ();
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);
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,
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;
};
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 */
/* 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;