summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/expo.c24
-rw-r--r--boot/scene.c52
-rw-r--r--boot/scene_internal.h21
-rw-r--r--boot/scene_menu.c79
4 files changed, 176 insertions, 0 deletions
diff --git a/boot/expo.c b/boot/expo.c
index be11cfd4e9..67cae3c7e2 100644
--- a/boot/expo.c
+++ b/boot/expo.c
@@ -114,6 +114,30 @@ int expo_set_display(struct expo *exp, struct udevice *dev)
return 0;
}
+int expo_calc_dims(struct expo *exp)
+{
+ struct scene *scn;
+ int ret;
+
+ if (!exp->cons)
+ return log_msg_ret("dim", -ENOTSUPP);
+
+ list_for_each_entry(scn, &exp->scene_head, sibling) {
+ /*
+ * Do the menus last so that all the menus' text objects
+ * are dimensioned
+ */
+ ret = scene_calc_dims(scn, false);
+ if (ret)
+ return log_msg_ret("scn", ret);
+ ret = scene_calc_dims(scn, true);
+ if (ret)
+ return log_msg_ret("scn", ret);
+ }
+
+ return 0;
+}
+
void expo_set_text_mode(struct expo *exp, bool text_mode)
{
exp->text_mode = text_mode;
diff --git a/boot/scene.c b/boot/scene.c
index 981a18b3ba..6d5e3c1f03 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -207,6 +207,19 @@ int scene_obj_set_pos(struct scene *scn, uint id, int x, int y)
return 0;
}
+int scene_obj_set_size(struct scene *scn, uint id, int w, int h)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("find", -ENOENT);
+ obj->dim.w = w;
+ obj->dim.h = h;
+
+ return 0;
+}
+
int scene_obj_set_hide(struct scene *scn, uint id, bool hide)
{
int ret;
@@ -414,3 +427,42 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event)
return 0;
}
+
+int scene_calc_dims(struct scene *scn, bool do_menus)
+{
+ struct scene_obj *obj;
+ int ret;
+
+ list_for_each_entry(obj, &scn->obj_head, sibling) {
+ switch (obj->type) {
+ case SCENEOBJT_NONE:
+ case SCENEOBJT_TEXT:
+ case SCENEOBJT_IMAGE: {
+ int width;
+
+ if (!do_menus) {
+ ret = scene_obj_get_hw(scn, obj->id, &width);
+ if (ret < 0)
+ return log_msg_ret("get", ret);
+ obj->dim.w = width;
+ obj->dim.h = ret;
+ }
+ break;
+ }
+ case SCENEOBJT_MENU: {
+ struct scene_obj_menu *menu;
+
+ if (do_menus) {
+ menu = (struct scene_obj_menu *)obj;
+
+ ret = scene_menu_calc_dims(menu);
+ if (ret)
+ return log_msg_ret("men", ret);
+ }
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/boot/scene_internal.h b/boot/scene_internal.h
index 24a2ba6a6a..00085a2f55 100644
--- a/boot/scene_internal.h
+++ b/boot/scene_internal.h
@@ -66,6 +66,17 @@ int scene_obj_add(struct scene *scn, const char *name, uint id,
int scene_obj_flag_clrset(struct scene *scn, uint id, uint clr, uint set);
/**
+ * scene_calc_dims() - Calculate the dimensions of the scene objects
+ *
+ * Updates the width and height of all objects based on their contents
+ *
+ * @scn: Scene to update
+ * @do_menus: true to calculate only menus, false to calculate everything else
+ * Returns 0 if OK, -ENOTSUPP if there is no graphical console
+ */
+int scene_calc_dims(struct scene *scn, bool do_menus);
+
+/**
* scene_menu_arrange() - Set the position of things in the menu
*
* This updates any items associated with a menu to make sure they are
@@ -133,4 +144,14 @@ int scene_render(struct scene *scn);
*/
int scene_send_key(struct scene *scn, int key, struct expo_action *event);
+/**
+ * scene_menu_calc_dims() - Calculate the dimensions of a menu
+ *
+ * Updates the width and height of the menu based on its contents
+ *
+ * @menu: Menu to update
+ * Returns 0 if OK, -ENOTSUPP if there is no graphical console
+ */
+int scene_menu_calc_dims(struct scene_obj_menu *menu);
+
#endif /* __SCENE_INTERNAL_H */
diff --git a/boot/scene_menu.c b/boot/scene_menu.c
index eed7565f6a..fa79cecdbd 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -43,6 +43,85 @@ static void menu_point_to_item(struct scene_obj_menu *menu, uint item_id)
menu->cur_item_id = item_id;
}
+static int scene_bbox_union(struct scene *scn, uint id,
+ struct vidconsole_bbox *bbox)
+{
+ struct scene_obj *obj;
+
+ if (!id)
+ return 0;
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("obj", -ENOENT);
+ if (bbox->valid) {
+ bbox->x0 = min(bbox->x0, obj->dim.x);
+ bbox->y0 = min(bbox->y0, obj->dim.y);
+ bbox->x1 = max(bbox->x1, obj->dim.x + obj->dim.w);
+ bbox->y1 = max(bbox->y1, obj->dim.y + obj->dim.h);
+ } else {
+ bbox->x0 = obj->dim.x;
+ bbox->y0 = obj->dim.y;
+ bbox->x1 = obj->dim.x + obj->dim.w;
+ bbox->y1 = obj->dim.y + obj->dim.h;
+ bbox->valid = true;
+ }
+
+ return 0;
+}
+
+/**
+ * scene_menu_calc_bbox() - Calculate bounding boxes for the menu
+ *
+ * @menu: Menu to process
+ * @bbox: Returns bounding box of menu including prompts
+ * @label_bbox: Returns bounding box of labels
+ */
+static void scene_menu_calc_bbox(struct scene_obj_menu *menu,
+ struct vidconsole_bbox *bbox,
+ struct vidconsole_bbox *label_bbox)
+{
+ const struct scene_menitem *item;
+
+ bbox->valid = false;
+ scene_bbox_union(menu->obj.scene, menu->title_id, bbox);
+
+ label_bbox->valid = false;
+
+ list_for_each_entry(item, &menu->item_head, sibling) {
+ scene_bbox_union(menu->obj.scene, item->label_id, bbox);
+ scene_bbox_union(menu->obj.scene, item->key_id, bbox);
+ scene_bbox_union(menu->obj.scene, item->desc_id, bbox);
+ scene_bbox_union(menu->obj.scene, item->preview_id, bbox);
+
+ /* Get the bounding box of all labels */
+ scene_bbox_union(menu->obj.scene, item->label_id, label_bbox);
+ }
+}
+
+int scene_menu_calc_dims(struct scene_obj_menu *menu)
+{
+ struct vidconsole_bbox bbox, label_bbox;
+ const struct scene_menitem *item;
+
+ scene_menu_calc_bbox(menu, &bbox, &label_bbox);
+
+ /* Make all labels the same size */
+ if (label_bbox.valid) {
+ list_for_each_entry(item, &menu->item_head, sibling) {
+ scene_obj_set_size(menu->obj.scene, item->label_id,
+ label_bbox.x1 - label_bbox.x0,
+ label_bbox.y1 - label_bbox.y0);
+ }
+ }
+
+ if (bbox.valid) {
+ menu->obj.dim.w = bbox.x1 - bbox.x0;
+ menu->obj.dim.h = bbox.y1 - bbox.y0;
+ }
+
+ return 0;
+}
+
int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
{
struct scene_menitem *item;