return 0;
}
+int expo_calc_dims(struct expo *exp)
+{
+ struct scene *scn;
+ int ret;
+
+ if (!exp->cons)
+ return log_msg_ret("dim", -ENOTSUPP);
+
+ list_for_each_entry(scn, &exp->scene_head, sibling) {
+ /*
+ * Do the menus last so that all the menus' text objects
+ * are dimensioned
+ */
+ ret = scene_calc_dims(scn, false);
+ if (ret)
+ return log_msg_ret("scn", ret);
+ ret = scene_calc_dims(scn, true);
+ if (ret)
+ return log_msg_ret("scn", ret);
+ }
+
+ return 0;
+}
+
void expo_set_text_mode(struct expo *exp, bool text_mode)
{
exp->text_mode = text_mode;
return 0;
}
+int scene_obj_set_size(struct scene *scn, uint id, int w, int h)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("find", -ENOENT);
+ obj->dim.w = w;
+ obj->dim.h = h;
+
+ return 0;
+}
+
int scene_obj_set_hide(struct scene *scn, uint id, bool hide)
{
int ret;
return 0;
}
+
+int scene_calc_dims(struct scene *scn, bool do_menus)
+{
+ struct scene_obj *obj;
+ int ret;
+
+ list_for_each_entry(obj, &scn->obj_head, sibling) {
+ switch (obj->type) {
+ case SCENEOBJT_NONE:
+ case SCENEOBJT_TEXT:
+ case SCENEOBJT_IMAGE: {
+ int width;
+
+ if (!do_menus) {
+ ret = scene_obj_get_hw(scn, obj->id, &width);
+ if (ret < 0)
+ return log_msg_ret("get", ret);
+ obj->dim.w = width;
+ obj->dim.h = ret;
+ }
+ break;
+ }
+ case SCENEOBJT_MENU: {
+ struct scene_obj_menu *menu;
+
+ if (do_menus) {
+ menu = (struct scene_obj_menu *)obj;
+
+ ret = scene_menu_calc_dims(menu);
+ if (ret)
+ return log_msg_ret("men", ret);
+ }
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
*/
int scene_obj_flag_clrset(struct scene *scn, uint id, uint clr, uint set);
+/**
+ * scene_calc_dims() - Calculate the dimensions of the scene objects
+ *
+ * Updates the width and height of all objects based on their contents
+ *
+ * @scn: Scene to update
+ * @do_menus: true to calculate only menus, false to calculate everything else
+ * Returns 0 if OK, -ENOTSUPP if there is no graphical console
+ */
+int scene_calc_dims(struct scene *scn, bool do_menus);
+
/**
* scene_menu_arrange() - Set the position of things in the menu
*
*/
int scene_send_key(struct scene *scn, int key, struct expo_action *event);
+/**
+ * scene_menu_calc_dims() - Calculate the dimensions of a menu
+ *
+ * Updates the width and height of the menu based on its contents
+ *
+ * @menu: Menu to update
+ * Returns 0 if OK, -ENOTSUPP if there is no graphical console
+ */
+int scene_menu_calc_dims(struct scene_obj_menu *menu);
+
#endif /* __SCENE_INTERNAL_H */
menu->cur_item_id = item_id;
}
+static int scene_bbox_union(struct scene *scn, uint id,
+ struct vidconsole_bbox *bbox)
+{
+ struct scene_obj *obj;
+
+ if (!id)
+ return 0;
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("obj", -ENOENT);
+ if (bbox->valid) {
+ bbox->x0 = min(bbox->x0, obj->dim.x);
+ bbox->y0 = min(bbox->y0, obj->dim.y);
+ bbox->x1 = max(bbox->x1, obj->dim.x + obj->dim.w);
+ bbox->y1 = max(bbox->y1, obj->dim.y + obj->dim.h);
+ } else {
+ bbox->x0 = obj->dim.x;
+ bbox->y0 = obj->dim.y;
+ bbox->x1 = obj->dim.x + obj->dim.w;
+ bbox->y1 = obj->dim.y + obj->dim.h;
+ bbox->valid = true;
+ }
+
+ return 0;
+}
+
+/**
+ * scene_menu_calc_bbox() - Calculate bounding boxes for the menu
+ *
+ * @menu: Menu to process
+ * @bbox: Returns bounding box of menu including prompts
+ * @label_bbox: Returns bounding box of labels
+ */
+static void scene_menu_calc_bbox(struct scene_obj_menu *menu,
+ struct vidconsole_bbox *bbox,
+ struct vidconsole_bbox *label_bbox)
+{
+ const struct scene_menitem *item;
+
+ bbox->valid = false;
+ scene_bbox_union(menu->obj.scene, menu->title_id, bbox);
+
+ label_bbox->valid = false;
+
+ list_for_each_entry(item, &menu->item_head, sibling) {
+ scene_bbox_union(menu->obj.scene, item->label_id, bbox);
+ scene_bbox_union(menu->obj.scene, item->key_id, bbox);
+ scene_bbox_union(menu->obj.scene, item->desc_id, bbox);
+ scene_bbox_union(menu->obj.scene, item->preview_id, bbox);
+
+ /* Get the bounding box of all labels */
+ scene_bbox_union(menu->obj.scene, item->label_id, label_bbox);
+ }
+}
+
+int scene_menu_calc_dims(struct scene_obj_menu *menu)
+{
+ struct vidconsole_bbox bbox, label_bbox;
+ const struct scene_menitem *item;
+
+ scene_menu_calc_bbox(menu, &bbox, &label_bbox);
+
+ /* Make all labels the same size */
+ if (label_bbox.valid) {
+ list_for_each_entry(item, &menu->item_head, sibling) {
+ scene_obj_set_size(menu->obj.scene, item->label_id,
+ label_bbox.x1 - label_bbox.x0,
+ label_bbox.y1 - label_bbox.y0);
+ }
+ }
+
+ if (bbox.valid) {
+ menu->obj.dim.w = bbox.x1 - bbox.x0;
+ menu->obj.dim.h = bbox.y1 - bbox.y0;
+ }
+
+ return 0;
+}
+
int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
{
struct scene_menitem *item;
- Add a Kconfig option to drop the names to save code / data space
- Add a Kconfig option to disable vidconsole support to save code / data space
- Support both graphical and text menus at the same time on different devices
-- Implement proper measurement of object bounding boxes, to permit more exact
- layout. This would tidy up the layout when Truetype is not used
- Support unicode
- Support curses for proper serial-terminal menus
*/
int expo_set_display(struct expo *exp, struct udevice *dev);
+/**
+ * expo_calc_dims() - Calculate the dimensions of the objects
+ *
+ * Updates the width and height of all objects based on their contents
+ *
+ * @exp: Expo to update
+ * Returns 0 if OK, -ENOTSUPP if there is no graphical console
+ */
+int expo_calc_dims(struct expo *exp);
+
/**
* expo_set_scene_id() - Set the current scene ID
*
*/
int scene_obj_set_pos(struct scene *scn, uint id, int x, int y);
+/**
+ * scene_obj_set_size() - Set the size of an object
+ *
+ * @scn: Scene to update
+ * @id: ID of object to update
+ * @w: width in pixels
+ * @h: height in pixels
+ * Returns: 0 if OK, -ENOENT if @id is invalid
+ */
+int scene_obj_set_size(struct scene *scn, uint id, int w, int h);
+
/**
* scene_obj_set_hide() - Set whether an object is hidden
*
/* render without a scene */
ut_asserteq(-ECHILD, expo_render(exp));
+ ut_assertok(expo_calc_dims(exp));
+ ut_assertok(scene_arrange(scn));
+
+ /* check dimensions of text */
+ obj = scene_obj_find(scn, OBJ_TEXT, SCENEOBJT_NONE);
+ ut_assertnonnull(obj);
+ ut_asserteq(400, obj->dim.x);
+ ut_asserteq(100, obj->dim.y);
+ ut_asserteq(126, obj->dim.w);
+ ut_asserteq(40, obj->dim.h);
+
+ /* check dimensions of image */
+ obj = scene_obj_find(scn, OBJ_LOGO, SCENEOBJT_NONE);
+ ut_assertnonnull(obj);
+ ut_asserteq(50, obj->dim.x);
+ ut_asserteq(20, obj->dim.y);
+ ut_asserteq(160, obj->dim.w);
+ ut_asserteq(160, obj->dim.h);
+
+ /* check dimensions of menu labels - both should be the same width */
+ obj = scene_obj_find(scn, ITEM1_LABEL, SCENEOBJT_NONE);
+ ut_assertnonnull(obj);
+ ut_asserteq(50, obj->dim.x);
+ ut_asserteq(436, obj->dim.y);
+ ut_asserteq(29, obj->dim.w);
+ ut_asserteq(18, obj->dim.h);
+
+ obj = scene_obj_find(scn, ITEM2_LABEL, SCENEOBJT_NONE);
+ ut_assertnonnull(obj);
+ ut_asserteq(50, obj->dim.x);
+ ut_asserteq(454, obj->dim.y);
+ ut_asserteq(29, obj->dim.w);
+ ut_asserteq(18, obj->dim.h);
+
+ /* check dimensions of menu */
+ obj = scene_obj_find(scn, OBJ_MENU, SCENEOBJT_NONE);
+ ut_assertnonnull(obj);
+ ut_asserteq(50, obj->dim.x);
+ ut_asserteq(400, obj->dim.y);
+ ut_asserteq(160, obj->dim.w);
+ ut_asserteq(160, obj->dim.h);
+
/* render it */
expo_set_scene_id(exp, SCENE1);
ut_assertok(expo_render(exp));