blob: e99f4426281503911a08ede7f04ec079f1ca62b0 [file] [log] [blame]
Simon Glass9f513932023-01-06 08:52:38 -06001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Implementation of a menu in a scene
4 *
5 * Copyright 2022 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
7 */
8
Simon Glassfe4c1e22023-06-01 10:22:43 -06009#define LOG_CATEGORY LOGC_EXPO
Simon Glass9f513932023-01-06 08:52:38 -060010
Simon Glass9f513932023-01-06 08:52:38 -060011#include <dm.h>
12#include <expo.h>
13#include <malloc.h>
14#include <mapmem.h>
15#include <menu.h>
16#include <video.h>
17#include <video_console.h>
18#include <linux/input.h>
19#include "scene_internal.h"
20
21static void scene_menuitem_destroy(struct scene_menitem *item)
22{
23 free(item->name);
24 free(item);
25}
26
27void scene_menu_destroy(struct scene_obj_menu *menu)
28{
29 struct scene_menitem *item, *next;
30
31 list_for_each_entry_safe(item, next, &menu->item_head, sibling)
32 scene_menuitem_destroy(item);
33}
34
Simon Glass5fd4f782023-08-14 16:40:32 -060035struct scene_menitem *scene_menuitem_find(const struct scene_obj_menu *menu,
36 int id)
Simon Glassc55eeba2023-06-01 10:22:54 -060037{
38 struct scene_menitem *item;
39
40 list_for_each_entry(item, &menu->item_head, sibling) {
41 if (item->id == id)
42 return item;
43 }
44
45 return NULL;
46}
47
Simon Glass4462fa32023-08-14 16:40:38 -060048struct scene_menitem *scene_menuitem_find_seq(const struct scene_obj_menu *menu,
49 uint seq)
50{
51 struct scene_menitem *item;
52 uint i;
53
54 i = 0;
55 list_for_each_entry(item, &menu->item_head, sibling) {
56 if (i == seq)
57 return item;
58 i++;
59 }
60
61 return NULL;
62}
63
Simon Glass100389f2024-10-14 16:31:58 -060064struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu,
65 int val)
66{
67 struct scene_menitem *item;
68 uint i;
69
70 i = 0;
71 list_for_each_entry(item, &menu->item_head, sibling) {
Simon Glass6f3e87a2024-10-14 16:32:00 -060072 if (item->value == INT_MAX ? val == i : item->value == val)
Simon Glass100389f2024-10-14 16:31:58 -060073 return item;
74 i++;
75 }
76
77 return NULL;
78}
79
Simon Glassc55eeba2023-06-01 10:22:54 -060080/**
81 * update_pointers() - Update the pointer object and handle highlights
82 *
83 * @menu: Menu to update
84 * @id: ID of menu item to select/deselect
85 * @point: true if @id is being selected, false if it is being deselected
86 */
87static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
88{
89 struct scene *scn = menu->obj.scene;
Simon Glassd353b752023-06-01 10:22:55 -060090 const bool stack = scn->expo->popup;
Simon Glassc55eeba2023-06-01 10:22:54 -060091 const struct scene_menitem *item;
92 int ret;
93
94 item = scene_menuitem_find(menu, id);
95 if (!item)
96 return log_msg_ret("itm", -ENOENT);
97
98 /* adjust the pointer object to point to the selected item */
99 if (menu->pointer_id && item && point) {
100 struct scene_obj *label;
101
102 label = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE);
103
104 ret = scene_obj_set_pos(scn, menu->pointer_id,
Simon Glassbc3a15f2025-05-02 08:46:31 -0600105 menu->obj.bbox.x0 + 200, label->bbox.y0);
Simon Glassc55eeba2023-06-01 10:22:54 -0600106 if (ret < 0)
107 return log_msg_ret("ptr", ret);
108 }
109
Simon Glassd353b752023-06-01 10:22:55 -0600110 if (stack) {
111 point &= scn->highlight_id == menu->obj.id;
112 scene_obj_flag_clrset(scn, item->label_id, SCENEOF_POINT,
113 point ? SCENEOF_POINT : 0);
114 }
115
Simon Glassc55eeba2023-06-01 10:22:54 -0600116 return 0;
117}
118
Simon Glass9f513932023-01-06 08:52:38 -0600119/**
120 * menu_point_to_item() - Point to a particular menu item
121 *
122 * Sets the currently pointed-to / highlighted menu item
123 */
Simon Glassbe04b962025-05-02 08:46:24 -0600124static int menu_point_to_item(struct scene_obj_menu *menu, uint item_id)
Simon Glass9f513932023-01-06 08:52:38 -0600125{
Simon Glassbe04b962025-05-02 08:46:24 -0600126 int ret;
127
128 if (menu->cur_item_id) {
129 ret = update_pointers(menu, menu->cur_item_id, false);
130 if (ret)
131 return log_msg_ret("mpi", ret);
132 }
Simon Glass9f513932023-01-06 08:52:38 -0600133 menu->cur_item_id = item_id;
Simon Glassbe04b962025-05-02 08:46:24 -0600134 ret = update_pointers(menu, item_id, true);
135 if (ret)
136 return log_msg_ret("mpu", ret);
137
138 return 0;
Simon Glass9f513932023-01-06 08:52:38 -0600139}
140
Simon Glassf0994692023-10-01 19:13:29 -0600141void scene_menu_calc_bbox(struct scene_obj_menu *menu,
Simon Glass96910ef2025-05-02 08:46:34 -0600142 struct vidconsole_bbox *bbox)
Simon Glass7a960052023-06-01 10:22:52 -0600143{
Simon Glass86f1ac52023-06-01 10:23:00 -0600144 const struct expo_theme *theme = &menu->obj.scene->expo->theme;
Simon Glass7a960052023-06-01 10:22:52 -0600145 const struct scene_menitem *item;
Simon Glass96910ef2025-05-02 08:46:34 -0600146 int inset = theme->menu_inset;
147 int i;
Simon Glass7a960052023-06-01 10:22:52 -0600148
Simon Glass96910ef2025-05-02 08:46:34 -0600149 for (i = 0; i < SCENEBB_count; i++)
150 bbox[i].valid = false;
Simon Glass7a960052023-06-01 10:22:52 -0600151
Simon Glass96910ef2025-05-02 08:46:34 -0600152 scene_bbox_union(menu->obj.scene, menu->title_id, 0,
153 &bbox[SCENEBB_all]);
Simon Glass7a960052023-06-01 10:22:52 -0600154
155 list_for_each_entry(item, &menu->item_head, sibling) {
Simon Glass96910ef2025-05-02 08:46:34 -0600156 struct vidconsole_bbox local;
Simon Glass7a960052023-06-01 10:22:52 -0600157
Simon Glass96910ef2025-05-02 08:46:34 -0600158 local.valid = false;
159 scene_bbox_union(menu->obj.scene, item->label_id, inset,
160 &local);
161 scene_bbox_union(menu->obj.scene, item->key_id, 0, &local);
162 scene_bbox_union(menu->obj.scene, item->desc_id, 0, &local);
163 scene_bbox_union(menu->obj.scene, item->preview_id, 0, &local);
164
165 scene_bbox_join(&local, 0, &bbox[SCENEBB_all]);
166
167 /* Get the bounding box of all individual fields */
168 scene_bbox_union(menu->obj.scene, item->label_id, inset,
169 &bbox[SCENEBB_label]);
170 scene_bbox_union(menu->obj.scene, item->key_id, inset,
171 &bbox[SCENEBB_key]);
172 scene_bbox_union(menu->obj.scene, item->desc_id, inset,
173 &bbox[SCENEBB_desc]);
174
175 if (menu->cur_item_id == item->id)
176 scene_bbox_join(&local, 0, &bbox[SCENEBB_curitem]);
Simon Glass7a960052023-06-01 10:22:52 -0600177 }
Simon Glass86f1ac52023-06-01 10:23:00 -0600178
179 /*
Simon Glass96910ef2025-05-02 08:46:34 -0600180 * subtract the final menuitem's gap to keep the inset the same top and
181 * bottom
Simon Glass86f1ac52023-06-01 10:23:00 -0600182 */
Simon Glass96910ef2025-05-02 08:46:34 -0600183 bbox[SCENEBB_label].y1 -= theme->menuitem_gap_y;
Simon Glass7a960052023-06-01 10:22:52 -0600184}
185
186int scene_menu_calc_dims(struct scene_obj_menu *menu)
187{
Simon Glass96910ef2025-05-02 08:46:34 -0600188 struct vidconsole_bbox bbox[SCENEBB_count], *cur;
Simon Glass7a960052023-06-01 10:22:52 -0600189 const struct scene_menitem *item;
190
Simon Glass96910ef2025-05-02 08:46:34 -0600191 scene_menu_calc_bbox(menu, bbox);
Simon Glass7a960052023-06-01 10:22:52 -0600192
193 /* Make all labels the same size */
Simon Glass96910ef2025-05-02 08:46:34 -0600194 cur = &bbox[SCENEBB_label];
195 if (cur->valid) {
Simon Glass7a960052023-06-01 10:22:52 -0600196 list_for_each_entry(item, &menu->item_head, sibling) {
197 scene_obj_set_size(menu->obj.scene, item->label_id,
Simon Glass96910ef2025-05-02 08:46:34 -0600198 cur->x1 - cur->x0,
199 cur->y1 - cur->y0);
Simon Glass7a960052023-06-01 10:22:52 -0600200 }
201 }
202
Simon Glass96910ef2025-05-02 08:46:34 -0600203 cur = &bbox[SCENEBB_all];
204 if (cur->valid) {
205 menu->obj.dims.x = cur->x1 - cur->x0;
206 menu->obj.dims.y = cur->y1 - cur->y0;
207
208 menu->obj.bbox.x1 = cur->x1;
209 menu->obj.bbox.y1 = cur->y1;
Simon Glass7a960052023-06-01 10:22:52 -0600210 }
211
212 return 0;
213}
214
Simon Glass377f18e2024-10-14 16:31:55 -0600215int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr,
216 struct scene_obj_menu *menu)
Simon Glass9f513932023-01-06 08:52:38 -0600217{
Simon Glassd353b752023-06-01 10:22:55 -0600218 const bool open = menu->obj.flags & SCENEOF_OPEN;
219 struct expo *exp = scn->expo;
220 const bool stack = exp->popup;
Simon Glass86f1ac52023-06-01 10:23:00 -0600221 const struct expo_theme *theme = &exp->theme;
Simon Glass9f513932023-01-06 08:52:38 -0600222 struct scene_menitem *item;
Simon Glassc55eeba2023-06-01 10:22:54 -0600223 uint sel_id;
Simon Glassd353b752023-06-01 10:22:55 -0600224 int x, y;
Simon Glass9f513932023-01-06 08:52:38 -0600225 int ret;
226
Simon Glassbc3a15f2025-05-02 08:46:31 -0600227 x = menu->obj.bbox.x0;
228 y = menu->obj.bbox.y0;
Simon Glass9f513932023-01-06 08:52:38 -0600229 if (menu->title_id) {
Simon Glass377f18e2024-10-14 16:31:55 -0600230 int width;
231
Simon Glassbc3a15f2025-05-02 08:46:31 -0600232 ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.bbox.x0, y);
Simon Glass9f513932023-01-06 08:52:38 -0600233 if (ret < 0)
234 return log_msg_ret("tit", ret);
235
Simon Glass377f18e2024-10-14 16:31:55 -0600236 ret = scene_obj_get_hw(scn, menu->title_id, &width);
Simon Glass9f513932023-01-06 08:52:38 -0600237 if (ret < 0)
238 return log_msg_ret("hei", ret);
239
Simon Glassd353b752023-06-01 10:22:55 -0600240 if (stack)
Simon Glass377f18e2024-10-14 16:31:55 -0600241 x += arr->label_width + theme->menu_title_margin_x;
Simon Glassd353b752023-06-01 10:22:55 -0600242 else
243 y += ret * 2;
Simon Glass9f513932023-01-06 08:52:38 -0600244 }
245
246 /*
247 * Currently everything is hard-coded to particular columns so this
248 * won't work on small displays and looks strange if the font size is
249 * small. This can be updated once text measuring is supported in
250 * vidconsole
251 */
Simon Glassc55eeba2023-06-01 10:22:54 -0600252 sel_id = menu->cur_item_id;
Simon Glass9f513932023-01-06 08:52:38 -0600253 list_for_each_entry(item, &menu->item_head, sibling) {
Simon Glassd353b752023-06-01 10:22:55 -0600254 bool selected;
Simon Glass9f513932023-01-06 08:52:38 -0600255 int height;
256
Simon Glassd353b752023-06-01 10:22:55 -0600257 ret = scene_obj_get_hw(scn, item->label_id, NULL);
Simon Glass9f513932023-01-06 08:52:38 -0600258 if (ret < 0)
259 return log_msg_ret("get", ret);
260 height = ret;
261
262 if (item->flags & SCENEMIF_GAP_BEFORE)
263 y += height;
264
265 /* select an item if not done already */
Simon Glassc55eeba2023-06-01 10:22:54 -0600266 if (!sel_id)
267 sel_id = item->id;
Simon Glass9f513932023-01-06 08:52:38 -0600268
Simon Glassd353b752023-06-01 10:22:55 -0600269 selected = sel_id == item->id;
270
Simon Glass9f513932023-01-06 08:52:38 -0600271 /*
272 * Put the label on the left, then leave a space for the
273 * pointer, then the key and the description
274 */
Simon Glass86f1ac52023-06-01 10:23:00 -0600275 ret = scene_obj_set_pos(scn, item->label_id,
276 x + theme->menu_inset, y);
Simon Glass9f513932023-01-06 08:52:38 -0600277 if (ret < 0)
Simon Glassd353b752023-06-01 10:22:55 -0600278 return log_msg_ret("nam", ret);
279 scene_obj_set_hide(scn, item->label_id,
280 stack && !open && !selected);
Simon Glass9f513932023-01-06 08:52:38 -0600281
Simon Glassd353b752023-06-01 10:22:55 -0600282 if (item->key_id) {
283 ret = scene_obj_set_pos(scn, item->key_id, x + 230, y);
284 if (ret < 0)
285 return log_msg_ret("key", ret);
286 }
Simon Glass9f513932023-01-06 08:52:38 -0600287
Simon Glassd353b752023-06-01 10:22:55 -0600288 if (item->desc_id) {
289 ret = scene_obj_set_pos(scn, item->desc_id, x + 280, y);
290 if (ret < 0)
291 return log_msg_ret("des", ret);
292 }
Simon Glass9f513932023-01-06 08:52:38 -0600293
294 if (item->preview_id) {
295 bool hide;
296
297 /*
298 * put all previews on top of each other, on the right
299 * size of the display
300 */
301 ret = scene_obj_set_pos(scn, item->preview_id, -4, y);
302 if (ret < 0)
303 return log_msg_ret("prev", ret);
304
305 hide = menu->cur_item_id != item->id;
306 ret = scene_obj_set_hide(scn, item->preview_id, hide);
307 if (ret < 0)
308 return log_msg_ret("hid", ret);
309 }
310
Simon Glassd353b752023-06-01 10:22:55 -0600311 if (!stack || open)
Simon Glass86f1ac52023-06-01 10:23:00 -0600312 y += height + theme->menuitem_gap_y;
Simon Glass9f513932023-01-06 08:52:38 -0600313 }
314
Simon Glassc55eeba2023-06-01 10:22:54 -0600315 if (sel_id)
316 menu_point_to_item(menu, sel_id);
Simon Glassebec4972025-05-02 08:46:33 -0600317 menu->obj.bbox.x1 = menu->obj.bbox.x0 + menu->obj.dims.x;
318 menu->obj.bbox.y1 = menu->obj.bbox.y0 + menu->obj.dims.y;
319 menu->obj.flags |= SCENEOF_SIZE_VALID;
Simon Glass9f513932023-01-06 08:52:38 -0600320
321 return 0;
322}
323
324int scene_menu(struct scene *scn, const char *name, uint id,
325 struct scene_obj_menu **menup)
326{
327 struct scene_obj_menu *menu;
328 int ret;
329
330 ret = scene_obj_add(scn, name, id, SCENEOBJT_MENU,
331 sizeof(struct scene_obj_menu),
332 (struct scene_obj **)&menu);
333 if (ret < 0)
334 return log_msg_ret("obj", -ENOMEM);
335
336 if (menup)
337 *menup = menu;
338 INIT_LIST_HEAD(&menu->item_head);
339
Simon Glass9f513932023-01-06 08:52:38 -0600340 return menu->obj.id;
341}
342
343static struct scene_menitem *scene_menu_find_key(struct scene *scn,
344 struct scene_obj_menu *menu,
345 int key)
346{
347 struct scene_menitem *item;
348
349 list_for_each_entry(item, &menu->item_head, sibling) {
350 if (item->key_id) {
351 struct scene_obj_txt *txt;
352 const char *str;
353
354 txt = scene_obj_find(scn, item->key_id, SCENEOBJT_TEXT);
355 if (txt) {
356 str = expo_get_str(scn->expo, txt->str_id);
357 if (str && *str == key)
358 return item;
359 }
360 }
361 }
362
363 return NULL;
364}
365
366int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key,
367 struct expo_action *event)
368{
Simon Glassf0e1e8c2023-06-01 10:22:59 -0600369 const bool open = menu->obj.flags & SCENEOF_OPEN;
Simon Glass9f513932023-01-06 08:52:38 -0600370 struct scene_menitem *item, *cur, *key_item;
371
372 cur = NULL;
373 key_item = NULL;
374
375 if (!list_empty(&menu->item_head)) {
376 list_for_each_entry(item, &menu->item_head, sibling) {
377 /* select an item if not done already */
378 if (menu->cur_item_id == item->id) {
379 cur = item;
380 break;
381 }
382 }
383 }
384
385 if (!cur)
386 return -ENOTTY;
387
388 switch (key) {
389 case BKEY_UP:
390 if (item != list_first_entry(&menu->item_head,
391 struct scene_menitem, sibling)) {
392 item = list_entry(item->sibling.prev,
393 struct scene_menitem, sibling);
Simon Glass719a3c62023-06-01 10:22:56 -0600394 event->type = EXPOACT_POINT_ITEM;
Simon Glass9f513932023-01-06 08:52:38 -0600395 event->select.id = item->id;
396 log_debug("up to item %d\n", event->select.id);
397 }
398 break;
399 case BKEY_DOWN:
400 if (!list_is_last(&item->sibling, &menu->item_head)) {
401 item = list_entry(item->sibling.next,
402 struct scene_menitem, sibling);
Simon Glass719a3c62023-06-01 10:22:56 -0600403 event->type = EXPOACT_POINT_ITEM;
Simon Glass9f513932023-01-06 08:52:38 -0600404 event->select.id = item->id;
405 log_debug("down to item %d\n", event->select.id);
406 }
407 break;
408 case BKEY_SELECT:
409 event->type = EXPOACT_SELECT;
410 event->select.id = item->id;
411 log_debug("select item %d\n", event->select.id);
412 break;
413 case BKEY_QUIT:
Simon Glassf0e1e8c2023-06-01 10:22:59 -0600414 if (scn->expo->popup && open) {
415 event->type = EXPOACT_CLOSE;
416 event->select.id = menu->obj.id;
417 } else {
418 event->type = EXPOACT_QUIT;
419 log_debug("menu quit\n");
420 }
Simon Glass9f513932023-01-06 08:52:38 -0600421 break;
422 case '0'...'9':
423 key_item = scene_menu_find_key(scn, menu, key);
424 if (key_item) {
425 event->type = EXPOACT_SELECT;
426 event->select.id = key_item->id;
427 }
428 break;
429 }
430
Simon Glass9f513932023-01-06 08:52:38 -0600431 return 0;
432}
433
434int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id,
435 uint key_id, uint label_id, uint desc_id, uint preview_id,
436 uint flags, struct scene_menitem **itemp)
437{
438 struct scene_obj_menu *menu;
439 struct scene_menitem *item;
Simon Glass9f513932023-01-06 08:52:38 -0600440
441 menu = scene_obj_find(scn, menu_id, SCENEOBJT_MENU);
442 if (!menu)
443 return log_msg_ret("find", -ENOENT);
444
445 /* Check that the text ID is valid */
Simon Glassd353b752023-06-01 10:22:55 -0600446 if (!scene_obj_find(scn, label_id, SCENEOBJT_TEXT))
Simon Glass9f513932023-01-06 08:52:38 -0600447 return log_msg_ret("txt", -EINVAL);
448
Dan Carpenter463be542023-07-31 17:08:29 +0300449 item = calloc(1, sizeof(struct scene_menitem));
Simon Glass9f513932023-01-06 08:52:38 -0600450 if (!item)
451 return log_msg_ret("item", -ENOMEM);
452 item->name = strdup(name);
453 if (!item->name) {
454 free(item);
455 return log_msg_ret("name", -ENOMEM);
456 }
457
458 item->id = resolve_id(scn->expo, id);
459 item->key_id = key_id;
460 item->label_id = label_id;
461 item->desc_id = desc_id;
462 item->preview_id = preview_id;
463 item->flags = flags;
Simon Glass100389f2024-10-14 16:31:58 -0600464 item->value = INT_MAX;
Simon Glass9f513932023-01-06 08:52:38 -0600465 list_add_tail(&item->sibling, &menu->item_head);
466
Simon Glass9f513932023-01-06 08:52:38 -0600467 if (itemp)
468 *itemp = item;
469
470 return item->id;
471}
472
473int scene_menu_set_title(struct scene *scn, uint id, uint title_id)
474{
475 struct scene_obj_menu *menu;
476 struct scene_obj_txt *txt;
477
478 menu = scene_obj_find(scn, id, SCENEOBJT_MENU);
479 if (!menu)
480 return log_msg_ret("menu", -ENOENT);
481
482 /* Check that the ID is valid */
483 if (title_id) {
484 txt = scene_obj_find(scn, title_id, SCENEOBJT_TEXT);
485 if (!txt)
486 return log_msg_ret("txt", -EINVAL);
487 }
488
489 menu->title_id = title_id;
490
491 return 0;
492}
493
494int scene_menu_set_pointer(struct scene *scn, uint id, uint pointer_id)
495{
496 struct scene_obj_menu *menu;
497 struct scene_obj *obj;
498
499 menu = scene_obj_find(scn, id, SCENEOBJT_MENU);
500 if (!menu)
501 return log_msg_ret("menu", -ENOENT);
502
503 /* Check that the ID is valid */
504 if (pointer_id) {
505 obj = scene_obj_find(scn, pointer_id, SCENEOBJT_NONE);
506 if (!obj)
507 return log_msg_ret("obj", -EINVAL);
508 }
509
510 menu->pointer_id = pointer_id;
511
512 return 0;
513}
514
Simon Glassbe04b962025-05-02 08:46:24 -0600515int scene_menu_select_item(struct scene *scn, uint id, uint cur_item_id)
516{
517 struct scene_obj_menu *menu;
518 int ret;
519
520 menu = scene_obj_find(scn, id, SCENEOBJT_MENU);
521 if (!menu)
522 return log_msg_ret("menu", -ENOENT);
523
524 ret = menu_point_to_item(menu, cur_item_id);
525 if (ret)
526 return log_msg_ret("msi", ret);
527
528 return 0;
529}
530
531int scene_menu_get_cur_item(struct scene *scn, uint id)
532{
533 struct scene_obj_menu *menu;
534
535 menu = scene_obj_find(scn, id, SCENEOBJT_MENU);
536 if (!menu)
537 return log_msg_ret("menu", -ENOENT);
538
539 return menu->cur_item_id;
540}
541
Simon Glass9f513932023-01-06 08:52:38 -0600542int scene_menu_display(struct scene_obj_menu *menu)
543{
544 struct scene *scn = menu->obj.scene;
545 struct scene_obj_txt *pointer;
546 struct expo *exp = scn->expo;
547 struct scene_menitem *item;
548 const char *pstr;
549
550 printf("U-Boot : Boot Menu\n\n");
551 if (menu->title_id) {
552 struct scene_obj_txt *txt;
553 const char *str;
554
555 txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_TEXT);
556 if (!txt)
557 return log_msg_ret("txt", -EINVAL);
558
559 str = expo_get_str(exp, txt->str_id);
560 printf("%s\n\n", str);
561 }
562
563 if (list_empty(&menu->item_head))
564 return 0;
565
566 pointer = scene_obj_find(scn, menu->pointer_id, SCENEOBJT_TEXT);
567 pstr = expo_get_str(scn->expo, pointer->str_id);
568
569 list_for_each_entry(item, &menu->item_head, sibling) {
570 struct scene_obj_txt *key = NULL, *label = NULL;
571 struct scene_obj_txt *desc = NULL;
572 const char *kstr = NULL, *lstr = NULL, *dstr = NULL;
573
574 key = scene_obj_find(scn, item->key_id, SCENEOBJT_TEXT);
575 if (key)
576 kstr = expo_get_str(exp, key->str_id);
577
578 label = scene_obj_find(scn, item->label_id, SCENEOBJT_TEXT);
579 if (label)
580 lstr = expo_get_str(exp, label->str_id);
581
582 desc = scene_obj_find(scn, item->desc_id, SCENEOBJT_TEXT);
583 if (desc)
584 dstr = expo_get_str(exp, desc->str_id);
585
586 printf("%3s %3s %-10s %s\n",
587 pointer && menu->cur_item_id == item->id ? pstr : "",
588 kstr, lstr, dstr);
589 }
590
591 return -ENOTSUPP;
592}
Simon Glass01922ec2023-06-01 10:22:57 -0600593
Simon Glass12f57732023-06-01 10:22:58 -0600594int scene_menu_render_deps(struct scene *scn, struct scene_obj_menu *menu)
595{
596 struct scene_menitem *item;
597
598 scene_render_deps(scn, menu->title_id);
599 scene_render_deps(scn, menu->cur_item_id);
600 scene_render_deps(scn, menu->pointer_id);
601
602 list_for_each_entry(item, &menu->item_head, sibling) {
603 scene_render_deps(scn, item->key_id);
604 scene_render_deps(scn, item->label_id);
605 scene_render_deps(scn, item->desc_id);
606 }
607
608 return 0;
609}