diff --git a/boot/cedit.c b/boot/cedit.c index c29a2be14ce..5758cc5a0d6 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -51,10 +51,11 @@ struct cedit_iter_priv { int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) { + struct expo_arrange_info arr; struct scene_obj_txt *txt; struct scene_obj *obj; struct scene *scn; - int y; + int y, ret; scn = expo_lookup_scene_id(exp, scene_id); if (!scn) @@ -68,6 +69,11 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) if (txt) scene_obj_set_pos(scn, txt->obj.id, 200, 10); + memset(&arr, '\0', sizeof(arr)); + ret = scene_calc_arrange(scn, &arr); + if (ret < 0) + return log_msg_ret("arr", ret); + y = 100; list_for_each_entry(obj, &scn->obj_head, sibling) { switch (obj->type) { @@ -77,12 +83,13 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) break; case SCENEOBJT_MENU: scene_obj_set_pos(scn, obj->id, 50, y); - scene_menu_arrange(scn, (struct scene_obj_menu *)obj); + scene_menu_arrange(scn, &arr, + (struct scene_obj_menu *)obj); y += 50; break; case SCENEOBJT_TEXTLINE: scene_obj_set_pos(scn, obj->id, 50, y); - scene_textline_arrange(scn, + scene_textline_arrange(scn, &arr, (struct scene_obj_textline *)obj); y += 50; break; diff --git a/boot/expo.c b/boot/expo.c index ed01483f1d3..c7ce19e834b 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -258,6 +258,8 @@ int expo_apply_theme(struct expo *exp, ofnode node) ofnode_read_u32(node, "font-size", &theme->font_size); ofnode_read_u32(node, "menu-inset", &theme->menu_inset); ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y); + ofnode_read_u32(node, "menu-title-margin-x", + &theme->menu_title_margin_x); list_for_each_entry(scn, &exp->scene_head, sibling) { ret = scene_apply_theme(scn, theme); diff --git a/boot/scene.c b/boot/scene.c index 0135287cfcb..a4836000b28 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -471,11 +471,59 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) return 0; } -int scene_arrange(struct scene *scn) +int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr) { struct scene_obj *obj; + + arr->label_width = 0; + list_for_each_entry(obj, &scn->obj_head, sibling) { + uint label_id = 0; + int width; + + switch (obj->type) { + case SCENEOBJT_NONE: + case SCENEOBJT_IMAGE: + case SCENEOBJT_TEXT: + break; + case SCENEOBJT_MENU: { + struct scene_obj_menu *menu; + + menu = (struct scene_obj_menu *)obj, + label_id = menu->title_id; + break; + } + case SCENEOBJT_TEXTLINE: { + struct scene_obj_textline *tline; + + tline = (struct scene_obj_textline *)obj, + label_id = tline->label_id; + break; + } + } + + if (label_id) { + int ret; + + ret = scene_obj_get_hw(scn, label_id, &width); + if (ret < 0) + return log_msg_ret("hei", ret); + arr->label_width = max(arr->label_width, width); + } + } + + return 0; +} + +int scene_arrange(struct scene *scn) +{ + struct expo_arrange_info arr; + struct scene_obj *obj; int ret; + ret = scene_calc_arrange(scn, &arr); + if (ret < 0) + return log_msg_ret("arr", ret); + list_for_each_entry(obj, &scn->obj_head, sibling) { switch (obj->type) { case SCENEOBJT_NONE: @@ -486,7 +534,7 @@ int scene_arrange(struct scene *scn) struct scene_obj_menu *menu; menu = (struct scene_obj_menu *)obj, - ret = scene_menu_arrange(scn, menu); + ret = scene_menu_arrange(scn, &arr, menu); if (ret) return log_msg_ret("arr", ret); break; @@ -495,7 +543,7 @@ int scene_arrange(struct scene *scn) struct scene_obj_textline *tline; tline = (struct scene_obj_textline *)obj, - ret = scene_textline_arrange(scn, tline); + ret = scene_textline_arrange(scn, &arr, tline); if (ret) return log_msg_ret("arr", ret); break; diff --git a/boot/scene_internal.h b/boot/scene_internal.h index e72202c9821..be25f6a8b96 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -96,10 +96,12 @@ int scene_calc_dims(struct scene *scn, bool do_menus); * if not already done * * @scn: Scene to update + * @arr: Arrangement information * @menu: Menu to process * Returns: 0 if OK, -ve on error */ -int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu); +int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr, + struct scene_obj_menu *menu); /** * scene_textline_arrange() - Set the position of things in a textline @@ -108,10 +110,12 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu); * positioned correctly relative to the textline. * * @scn: Scene to update + * @arr: Arrangement information * @tline: textline to process * Returns: 0 if OK, -ve on error */ -int scene_textline_arrange(struct scene *scn, struct scene_obj_textline *tline); +int scene_textline_arrange(struct scene *scn, struct expo_arrange_info *arr, + struct scene_obj_textline *tline); /** * scene_apply_theme() - Apply a theme to a scene @@ -358,4 +362,16 @@ int scene_textline_open(struct scene *scn, struct scene_obj_textline *tline); */ int scene_textline_close(struct scene *scn, struct scene_obj_textline *tline); +/** + * scene_calc_arrange() - Calculate sizes needed to arrange a scene + * + * Checks the size of some objects and stores this info to help with a later + * scene arrangement + * + * @scn: Scene to check + * @arr: Place to put scene-arrangement info + * Returns: 0 if OK, -ve on error + */ +int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr); + #endif /* __SCENE_INTERNAL_H */ diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 80bd7457cb1..c331f6670cc 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -168,7 +168,8 @@ int scene_menu_calc_dims(struct scene_obj_menu *menu) return 0; } -int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) +int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr, + struct scene_obj_menu *menu) { const bool open = menu->obj.flags & SCENEOF_OPEN; struct expo *exp = scn->expo; @@ -182,16 +183,18 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) x = menu->obj.dim.x; y = menu->obj.dim.y; if (menu->title_id) { + int width; + ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y); if (ret < 0) return log_msg_ret("tit", ret); - ret = scene_obj_get_hw(scn, menu->title_id, NULL); + ret = scene_obj_get_hw(scn, menu->title_id, &width); if (ret < 0) return log_msg_ret("hei", ret); if (stack) - x += 200; + x += arr->label_width + theme->menu_title_margin_x; else y += ret * 2; } diff --git a/boot/scene_textline.c b/boot/scene_textline.c index bba8663b98d..6adef7cc173 100644 --- a/boot/scene_textline.c +++ b/boot/scene_textline.c @@ -87,7 +87,8 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline) return 0; } -int scene_textline_arrange(struct scene *scn, struct scene_obj_textline *tline) +int scene_textline_arrange(struct scene *scn, struct expo_arrange_info *arr, + struct scene_obj_textline *tline) { const bool open = tline->obj.flags & SCENEOF_OPEN; bool point; diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index c87b6ec8128..f7b636e5fc6 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -176,6 +176,10 @@ menu-inset menuitem-gap-y Number of pixels between menu items +menu-title-margin-x + Number of pixels between right side of menu title to the left size of the + menu labels + Pop-up mode ----------- diff --git a/include/expo.h b/include/expo.h index c235fa2709d..50e11cd118c 100644 --- a/include/expo.h +++ b/include/expo.h @@ -59,11 +59,14 @@ struct expo_action { * @font_size: Default font size for all text * @menu_inset: Inset width (on each side and top/bottom) for menu items * @menuitem_gap_y: Gap between menu items in pixels + * @menu_title_margin_x: Gap between right side of menu title and left size of + * menu label */ struct expo_theme { u32 font_size; u32 menu_inset; u32 menuitem_gap_y; + u32 menu_title_margin_x; }; /** @@ -341,6 +344,15 @@ struct scene_obj_textline { uint pos; }; +/** + * struct expo_arrange_info - Information used when arranging a scene + * + * @label_width: Maximum width of labels in scene + */ +struct expo_arrange_info { + int label_width; +}; + /** * expo_new() - create a new expo *