aboutsummaryrefslogtreecommitdiff
path: root/boot/scene_menu.c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2023-06-01 10:22:55 -0600
committerTom Rini <trini@konsulko.com>2023-07-14 12:54:51 -0400
commitd3db0216dc163594309a9930b31e3161261cd873 (patch)
tree824c21f2959322939d1720a5114712bc70e53358 /boot/scene_menu.c
parent8872bc7f9dabf923f245e9f737be8c4da0ca2a50 (diff)
expo: Support drawing of popup menus
At present only a single menu is supported. All items are shown and a pointer object points to the current item. Add support for multiple menus, one of which is highlighted, indicated by the highlight_id property in the scene. The highlighted menu item has a SCENEOF_POINT flag, indicating that it is currently pointed to. The popup menu is normally closed, in which case it shows only the current menu item. When it is opened, it shows all items, allowing the user to select one. Rather than requiring the menu item to have a description, require it to have a label. Use the label (only) for the popup menu. With this, most of the drawing and layout logic is complete. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'boot/scene_menu.c')
-rw-r--r--boot/scene_menu.c58
1 files changed, 37 insertions, 21 deletions
diff --git a/boot/scene_menu.c b/boot/scene_menu.c
index 154be7f012..f2832b4ddf 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -56,6 +56,7 @@ static struct scene_menitem *scene_menuitem_find(struct scene_obj_menu *menu,
static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
{
struct scene *scn = menu->obj.scene;
+ const bool stack = scn->expo->popup;
const struct scene_menitem *item;
int ret;
@@ -75,6 +76,12 @@ static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
return log_msg_ret("ptr", ret);
}
+ if (stack) {
+ point &= scn->highlight_id == menu->obj.id;
+ scene_obj_flag_clrset(scn, item->label_id, SCENEOF_POINT,
+ point ? SCENEOF_POINT : 0);
+ }
+
return 0;
}
@@ -172,11 +179,15 @@ int scene_menu_calc_dims(struct scene_obj_menu *menu)
int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
{
+ const bool open = menu->obj.flags & SCENEOF_OPEN;
+ struct expo *exp = scn->expo;
+ const bool stack = exp->popup;
struct scene_menitem *item;
uint sel_id;
- int y, cur_y;
+ int x, y;
int ret;
+ x = menu->obj.dim.x;
y = menu->obj.dim.y;
if (menu->title_id) {
ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y);
@@ -187,7 +198,10 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
if (ret < 0)
return log_msg_ret("hei", ret);
- y += ret * 2;
+ if (stack)
+ x += 200;
+ else
+ y += ret * 2;
}
/*
@@ -198,9 +212,10 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
*/
sel_id = menu->cur_item_id;
list_for_each_entry(item, &menu->item_head, sibling) {
+ bool selected;
int height;
- ret = scene_obj_get_hw(scn, item->desc_id, NULL);
+ ret = scene_obj_get_hw(scn, item->label_id, NULL);
if (ret < 0)
return log_msg_ret("get", ret);
height = ret;
@@ -212,29 +227,29 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
if (!sel_id)
sel_id = item->id;
+ selected = sel_id == item->id;
+
/*
* Put the label on the left, then leave a space for the
* pointer, then the key and the description
*/
- if (item->label_id) {
- ret = scene_obj_set_pos(scn, item->label_id, menu->obj.dim.x,
- y);
- if (ret < 0)
- return log_msg_ret("nam", ret);
- }
-
- ret = scene_obj_set_pos(scn, item->key_id, menu->obj.dim.x + 230,
- y);
+ ret = scene_obj_set_pos(scn, item->label_id, x, y);
if (ret < 0)
- return log_msg_ret("key", ret);
+ return log_msg_ret("nam", ret);
+ scene_obj_set_hide(scn, item->label_id,
+ stack && !open && !selected);
- ret = scene_obj_set_pos(scn, item->desc_id, menu->obj.dim.x + 280,
- y);
- if (ret < 0)
- return log_msg_ret("des", ret);
+ if (item->key_id) {
+ ret = scene_obj_set_pos(scn, item->key_id, x + 230, y);
+ if (ret < 0)
+ return log_msg_ret("key", ret);
+ }
- if (menu->cur_item_id == item->id)
- cur_y = y;
+ if (item->desc_id) {
+ ret = scene_obj_set_pos(scn, item->desc_id, x + 280, y);
+ if (ret < 0)
+ return log_msg_ret("des", ret);
+ }
if (item->preview_id) {
bool hide;
@@ -253,7 +268,8 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
return log_msg_ret("hid", ret);
}
- y += height;
+ if (!stack || open)
+ y += height;
}
if (sel_id)
@@ -380,7 +396,7 @@ int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id,
return log_msg_ret("find", -ENOENT);
/* Check that the text ID is valid */
- if (!scene_obj_find(scn, desc_id, SCENEOBJT_TEXT))
+ if (!scene_obj_find(scn, label_id, SCENEOBJT_TEXT))
return log_msg_ret("txt", -EINVAL);
item = calloc(1, sizeof(struct scene_obj_menu));