[PATCH 33/40] expo: Draw popup menus in both opened and closed states
Simon Glass
sjg at chromium.org
Thu Jun 1 18:22:57 CEST 2023
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 <sjg at chromium.org>
---
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 4dbe12a2b740..fb199ef29538 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 3387a90761ab..2544c961dab4 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 892099557a99..20ded91fb3d6 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 0f4388897883..0699cdb4c19c 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.41.0.rc0.172.g3f132b7071-goog
More information about the U-Boot
mailing list