static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
{
struct scene *scn = menu->obj.scene;
+ const bool stack = scn->expo->popup;
const struct scene_menitem *item;
int ret;
return log_msg_ret("ptr", ret);
}
+ if (stack) {
+ point &= scn->highlight_id == menu->obj.id;
+ scene_obj_flag_clrset(scn, item->label_id, SCENEOF_POINT,
+ point ? SCENEOF_POINT : 0);
+ }
+
return 0;
}
int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
{
+ const bool open = menu->obj.flags & SCENEOF_OPEN;
+ struct expo *exp = scn->expo;
+ const bool stack = exp->popup;
struct scene_menitem *item;
uint sel_id;
- int y, cur_y;
+ int x, y;
int ret;
+ x = menu->obj.dim.x;
y = menu->obj.dim.y;
if (menu->title_id) {
ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y);
if (ret < 0)
return log_msg_ret("hei", ret);
- y += ret * 2;
+ if (stack)
+ x += 200;
+ else
+ y += ret * 2;
}
/*
*/
sel_id = menu->cur_item_id;
list_for_each_entry(item, &menu->item_head, sibling) {
+ bool selected;
int height;
- ret = scene_obj_get_hw(scn, item->desc_id, NULL);
+ ret = scene_obj_get_hw(scn, item->label_id, NULL);
if (ret < 0)
return log_msg_ret("get", ret);
height = ret;
if (!sel_id)
sel_id = item->id;
+ selected = sel_id == item->id;
+
/*
* Put the label on the left, then leave a space for the
* pointer, then the key and the description
*/
- if (item->label_id) {
- ret = scene_obj_set_pos(scn, item->label_id, menu->obj.dim.x,
- y);
- if (ret < 0)
- return log_msg_ret("nam", ret);
- }
-
- ret = scene_obj_set_pos(scn, item->key_id, menu->obj.dim.x + 230,
- y);
+ ret = scene_obj_set_pos(scn, item->label_id, x, y);
if (ret < 0)
- return log_msg_ret("key", ret);
+ return log_msg_ret("nam", ret);
+ scene_obj_set_hide(scn, item->label_id,
+ stack && !open && !selected);
- ret = scene_obj_set_pos(scn, item->desc_id, menu->obj.dim.x + 280,
- y);
- if (ret < 0)
- return log_msg_ret("des", ret);
+ if (item->key_id) {
+ ret = scene_obj_set_pos(scn, item->key_id, x + 230, y);
+ if (ret < 0)
+ return log_msg_ret("key", ret);
+ }
- if (menu->cur_item_id == item->id)
- cur_y = y;
+ if (item->desc_id) {
+ ret = scene_obj_set_pos(scn, item->desc_id, x + 280, y);
+ if (ret < 0)
+ return log_msg_ret("des", ret);
+ }
if (item->preview_id) {
bool hide;
return log_msg_ret("hid", ret);
}
- y += height;
+ if (!stack || open)
+ y += height;
}
if (sel_id)
return log_msg_ret("find", -ENOENT);
/* Check that the text ID is valid */
- if (!scene_obj_find(scn, desc_id, SCENEOBJT_TEXT))
+ if (!scene_obj_find(scn, label_id, SCENEOBJT_TEXT))
return log_msg_ret("txt", -EINVAL);
item = calloc(1, sizeof(struct scene_obj_menu));
* @action: Action selected by user. At present only one is supported, with the
* type set to EXPOACT_NONE if there is no action
* @text_mode: true to use text mode for the menu (no vidconsole)
+ * @popup: true to use popup menus, instead of showing all items
* @priv: Private data for the controller
* @theme: Information about fonts styles, etc.
* @scene_head: List of scenes
uint next_id;
struct expo_action action;
bool text_mode;
+ bool popup;
void *priv;
struct expo_theme theme;
struct list_head scene_head;
* @name: Name of the scene (allocated)
* @id: ID number of the scene
* @title_id: String ID of title of the scene (allocated)
+ * @highlight_id: ID of highlighted object, if any
* @sibling: Node to link this scene to its siblings
* @obj_head: List of objects in the scene
*/
char *name;
uint id;
uint title_id;
+ uint highlight_id;
struct list_head sibling;
struct list_head obj_head;
};
* enum scene_obj_flags_t - flags for objects
*
* @SCENEOF_HIDE: object should be hidden
+ * @SCENEOF_POINT: object should be highlighted
+ * @SCENEOF_OPEN: object should be opened (e.g. menu is opened so that an option
+ * can be selected)
*/
enum scene_obj_flags_t {
SCENEOF_HIDE = 1 << 0,
+ SCENEOF_POINT = 1 << 1,
+ SCENEOF_OPEN = 1 << 2,
};
/**