From 756c9559e60a0ef8434128205adced937240925d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 1 Jun 2023 10:22:57 -0600 Subject: [PATCH] expo: Draw popup menus in both opened and closed states When a popup menu is closed it shows only the selected item. When it is open it shows a background and all items, with a highlight that can be moved between the items. Add the drawing logic for this. Signed-off-by: Simon Glass --- boot/scene.c | 66 +++++++++++++++++++++++++++++++++++++++++-- boot/scene_internal.h | 7 +++++ boot/scene_menu.c | 29 +++++++++++++++++++ include/expo.h | 30 ++++++++++++++++++++ 4 files changed, 130 insertions(+), 2 deletions(-) diff --git a/boot/scene.c b/boot/scene.c index 4dbe12a2b7..fb199ef295 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -345,14 +345,44 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) } if (ret && ret != -ENOSYS) return log_msg_ret("font", ret); - vidconsole_set_cursor_pos(cons, x, y); str = expo_get_str(exp, txt->str_id); - if (str) + if (str) { + struct video_priv *vid_priv; + struct vidconsole_colour old; + enum colour_idx fore, back; + + if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) { + fore = VID_BLACK; + back = VID_WHITE; + } else { + fore = VID_LIGHT_GRAY; + back = VID_BLACK; + } + + vid_priv = dev_get_uclass_priv(dev); + if (obj->flags & SCENEOF_POINT) { + vidconsole_push_colour(cons, fore, back, &old); + video_fill_part(dev, x, y, + x + obj->dim.w, y + obj->dim.h, + vid_priv->colour_bg); + } + vidconsole_set_cursor_pos(cons, x, y); vidconsole_put_string(cons, str); + if (obj->flags & SCENEOF_POINT) + vidconsole_pop_colour(cons, &old); + } break; } case SCENEOBJT_MENU: { struct scene_obj_menu *menu = (struct scene_obj_menu *)obj; + + if (exp->popup && (obj->flags & SCENEOF_OPEN)) { + if (!cons) + return -ENOTSUPP; + + /* draw a background behind the menu items */ + scene_menu_render(menu); + } /* * With a vidconsole, the text and item pointer are rendered as * normal objects so we don't need to do anything here. The menu @@ -494,3 +524,35 @@ int scene_apply_theme(struct scene *scn, struct expo_theme *theme) return 0; } + +void scene_set_highlight_id(struct scene *scn, uint id) +{ + scn->highlight_id = id; +} + +void scene_highlight_first(struct scene *scn) +{ + struct scene_obj *obj; + + list_for_each_entry(obj, &scn->obj_head, sibling) { + switch (obj->type) { + case SCENEOBJT_MENU: + scene_set_highlight_id(scn, obj->id); + return; + default: + break; + } + } +} + +int scene_set_open(struct scene *scn, uint id, bool open) +{ + int ret; + + ret = scene_obj_flag_clrset(scn, id, SCENEOF_OPEN, + open ? SCENEOF_OPEN : 0); + if (ret) + return log_msg_ret("flg", ret); + + return 0; +} diff --git a/boot/scene_internal.h b/boot/scene_internal.h index 3387a90761..2544c961da 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -153,6 +153,13 @@ int scene_render(struct scene *scn); */ int scene_send_key(struct scene *scn, int key, struct expo_action *event); +/** + * scene_menu_render() - Render the background behind a menu + * + * @menu: Menu to render + */ +void scene_menu_render(struct scene_obj_menu *menu); + /** * scene_menu_calc_dims() - Calculate the dimensions of a menu * diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 892099557a..20ded91fb3 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -515,3 +515,32 @@ int scene_menu_display(struct scene_obj_menu *menu) return -ENOTSUPP; } + +void scene_menu_render(struct scene_obj_menu *menu) +{ + struct expo *exp = menu->obj.scene->expo; + const struct expo_theme *theme = &exp->theme; + struct vidconsole_bbox bbox, label_bbox; + struct udevice *dev = exp->display; + struct video_priv *vid_priv; + struct udevice *cons = exp->cons; + struct vidconsole_colour old; + enum colour_idx fore, back; + + if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) { + fore = VID_BLACK; + back = VID_WHITE; + } else { + fore = VID_LIGHT_GRAY; + back = VID_BLACK; + } + + scene_menu_calc_bbox(menu, &bbox, &label_bbox); + vidconsole_push_colour(cons, fore, back, &old); + vid_priv = dev_get_uclass_priv(dev); + video_fill_part(dev, label_bbox.x0 - theme->menu_inset, + label_bbox.y0 - theme->menu_inset, + label_bbox.x1, label_bbox.y1 + theme->menu_inset, + vid_priv->colour_fg); + vidconsole_pop_colour(cons, &old); +} diff --git a/include/expo.h b/include/expo.h index 0f43888978..0699cdb4c1 100644 --- a/include/expo.h +++ b/include/expo.h @@ -412,6 +412,36 @@ int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp); */ struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id); +/** + * scene_highlight_first() - Highlight the first item in a scene + * + * This highlights the first item, so that the user can see that it is pointed + * to + * + * @scn: Scene to update + */ +void scene_highlight_first(struct scene *scn); + +/** + * scene_set_highlight_id() - Set the object which is highlighted + * + * Sets a new object to highlight in the scene + * + * @scn: Scene to update + * @id: ID of object to highlight + */ +void scene_set_highlight_id(struct scene *scn, uint id); + +/** + * scene_set_open() - Set whether an item is open or not + * + * @scn: Scene to update + * @id: ID of object to update + * @open: true to open the object, false to close it + * Returns: 0 if OK, -ENOENT if @id is invalid + */ +int scene_set_open(struct scene *scn, uint id, bool open); + /** * scene_title_set() - set the scene title * -- 2.39.5