new option -prev, corrections for option -next
This commit is contained in:
+117
-8
@@ -64,6 +64,34 @@ menu_get_subitem(Menu * menu, int index)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a subitem with id item_id. This function ignores hidden
|
||||
* entries completely.
|
||||
*
|
||||
* @return index of subitem if found and -1 otherwise. */
|
||||
static int
|
||||
menu_get_index_of(Menu * menu, char * item_id)
|
||||
{
|
||||
MenuItem * item;
|
||||
int i = 0;
|
||||
|
||||
debug (RPT_DEBUG, "%s( menu=[%s], item_id=%s )", __FUNCTION__,
|
||||
((menu != NULL) ? menu->id : "(null)"), item_id);
|
||||
for (item = LL_GetFirst(menu->data.menu.contents);
|
||||
item != NULL;
|
||||
item = LL_GetNext(menu->data.menu.contents))
|
||||
{
|
||||
if ( ! item->is_hidden)
|
||||
{
|
||||
if (strcmp(item_id, item->id) == 0)
|
||||
return i;
|
||||
/* hidden items don't count at all... */
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
menu_visible_item_count(Menu * menu)
|
||||
{
|
||||
@@ -473,10 +501,57 @@ void menu_update_screen (MenuItem *menu, Screen *s)
|
||||
report (RPT_ERR, "%s: could not find widget: %s", __FUNCTION__, "downscroller");
|
||||
}
|
||||
|
||||
MenuResult menu_process_input (Menu *menu, MenuToken token, char * key, bool extended)
|
||||
MenuItem * menu_get_item_for_predecessor_check(Menu *menu)
|
||||
{
|
||||
MenuItem *subitem = menu_get_subitem(menu, menu->data.menu.selector_pos);
|
||||
if ( ! subitem)
|
||||
return NULL;
|
||||
switch (subitem->type) {
|
||||
case MENUITEM_ACTION:
|
||||
case MENUITEM_CHECKBOX:
|
||||
case MENUITEM_RING:
|
||||
// for types without own screen: look for menu's
|
||||
// predecessor if its subitem doesn't have one. (Since
|
||||
// menus can't have successors this problem arises
|
||||
// only for predecessors.)
|
||||
if (subitem->predecessor_id == NULL)
|
||||
return menu;
|
||||
return subitem;
|
||||
case MENUITEM_MENU:
|
||||
case MENUITEM_SLIDER:
|
||||
case MENUITEM_NUMERIC:
|
||||
case MENUITEM_ALPHA:
|
||||
case MENUITEM_IP:
|
||||
return menu;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem * menu_get_item_for_successor_check(Menu *menu)
|
||||
{
|
||||
MenuItem *subitem = menu_get_subitem(menu, menu->data.menu.selector_pos);
|
||||
if ( ! subitem)
|
||||
return NULL;
|
||||
switch (subitem->type) {
|
||||
case MENUITEM_ACTION:
|
||||
case MENUITEM_CHECKBOX:
|
||||
case MENUITEM_RING:
|
||||
return subitem;
|
||||
case MENUITEM_MENU:
|
||||
case MENUITEM_SLIDER:
|
||||
case MENUITEM_NUMERIC:
|
||||
case MENUITEM_ALPHA:
|
||||
case MENUITEM_IP:
|
||||
return menu;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
MenuResult menu_process_input(Menu *menu, MenuToken token, char * key, bool extended)
|
||||
{
|
||||
MenuItem *subitem;
|
||||
|
||||
debug (RPT_DEBUG, "%s( menu=[%s], token=%d, key=\"%s\" )", __FUNCTION__,
|
||||
((menu != NULL) ? menu->id : "(null)"), token, key);
|
||||
|
||||
@@ -485,7 +560,11 @@ MenuResult menu_process_input (Menu *menu, MenuToken token, char * key, bool ext
|
||||
|
||||
switch (token) {
|
||||
case MENUTOKEN_MENU:
|
||||
return MENURESULT_CLOSE;
|
||||
subitem = menu_get_item_for_predecessor_check(menu);
|
||||
if ( ! subitem)
|
||||
return MENURESULT_ERROR;
|
||||
return menuitem_predecessor2menuresult(
|
||||
subitem->predecessor_id, MENURESULT_CLOSE);
|
||||
case MENUTOKEN_ENTER:
|
||||
subitem = menu_get_subitem (menu, menu->data.menu.selector_pos);
|
||||
if (!subitem)
|
||||
@@ -494,8 +573,8 @@ MenuResult menu_process_input (Menu *menu, MenuToken token, char * key, bool ext
|
||||
case MENUITEM_ACTION:
|
||||
if (subitem->event_func)
|
||||
subitem->event_func (subitem, MENUEVENT_SELECT);
|
||||
return subitem->data.action.menu_result;
|
||||
//return MENURESULT_QUIT;
|
||||
return menuitem_successor2menuresult(
|
||||
subitem->successor_id, MENURESULT_NONE);
|
||||
case MENUITEM_CHECKBOX:
|
||||
if (subitem->data.checkbox.allow_gray) {
|
||||
subitem->data.checkbox.value = (subitem->data.checkbox.value + 1) % 3;
|
||||
@@ -505,12 +584,14 @@ MenuResult menu_process_input (Menu *menu, MenuToken token, char * key, bool ext
|
||||
}
|
||||
if (subitem->event_func)
|
||||
subitem->event_func (subitem, MENUEVENT_UPDATE);
|
||||
return MENURESULT_NONE;
|
||||
return menuitem_successor2menuresult(
|
||||
subitem->successor_id, MENURESULT_NONE);
|
||||
case MENUITEM_RING:
|
||||
subitem->data.ring.value = (subitem->data.ring.value + 1) % LL_Length (subitem->data.ring.strings);
|
||||
if (subitem->event_func)
|
||||
subitem->event_func (subitem, MENUEVENT_UPDATE);
|
||||
return MENURESULT_NONE;
|
||||
return menuitem_successor2menuresult(
|
||||
subitem->successor_id, MENURESULT_NONE);
|
||||
case MENUITEM_MENU:
|
||||
case MENUITEM_SLIDER:
|
||||
case MENUITEM_NUMERIC:
|
||||
@@ -554,6 +635,8 @@ MenuResult menu_process_input (Menu *menu, MenuToken token, char * key, bool ext
|
||||
break;
|
||||
switch (subitem->type) {
|
||||
case MENUITEM_CHECKBOX:
|
||||
/* note: this dangerous looking code works since
|
||||
* CheckboxValue is an enum >= 0. */
|
||||
if (subitem->data.checkbox.allow_gray) {
|
||||
subitem->data.checkbox.value = (subitem->data.checkbox.value - 1) % 3;
|
||||
}
|
||||
@@ -564,7 +647,10 @@ MenuResult menu_process_input (Menu *menu, MenuToken token, char * key, bool ext
|
||||
subitem->event_func (subitem, MENUEVENT_UPDATE);
|
||||
return MENURESULT_NONE;
|
||||
case MENUITEM_RING:
|
||||
subitem->data.ring.value = (subitem->data.ring.value - 1) % LL_Length (subitem->data.ring.strings);
|
||||
/* ring: jump to the end if beginning is reached */
|
||||
subitem->data.ring.value = (subitem->data.ring.value < 1)
|
||||
? LL_Length (subitem->data.ring.strings) - 1
|
||||
: (subitem->data.ring.value - 1) % LL_Length (subitem->data.ring.strings);
|
||||
if (subitem->event_func)
|
||||
subitem->event_func (subitem, MENUEVENT_UPDATE);
|
||||
return MENURESULT_NONE;
|
||||
@@ -607,3 +693,26 @@ MenuResult menu_process_input (Menu *menu, MenuToken token, char * key, bool ext
|
||||
}
|
||||
return MENURESULT_ERROR;
|
||||
}
|
||||
|
||||
/** positions current item pointer on subitem subitem_id. If subitem_id is
|
||||
* hidden or not valid subitem of menu this function does nothing. */
|
||||
void menu_select_subitem(Menu *menu, char * subitem_id)
|
||||
{
|
||||
assert(menu != NULL);
|
||||
debug(RPT_DEBUG, "%s( menu=[%s], subitem_id=\"%s\" )", __FUNCTION__,
|
||||
menu->id, subitem_id);
|
||||
int position = menu_get_index_of(menu, subitem_id);
|
||||
if (position < 0)
|
||||
{
|
||||
debug(RPT_DEBUG, "%s: subitem \"%s\" not found"
|
||||
" or hidden in \"%s\", ignored",
|
||||
__FUNCTION__, subitem_id, menu->id);
|
||||
return;
|
||||
}
|
||||
// debug(RPT_DEBUG, "%s: %s->%s is at position %d,"
|
||||
// " current item is at menu position: %d, scroll: %d",
|
||||
// __FUNCTION__, menu->id, subitem_id, position,
|
||||
// menu->data.menu.selector_pos, menu->data.menu.scroll);
|
||||
menu->data.menu.selector_pos = position;
|
||||
menu->data.menu.scroll = position;
|
||||
}
|
||||
|
||||
@@ -103,10 +103,28 @@ void menu_build_screen (Menu *menu, Screen *s);
|
||||
*/
|
||||
void menu_update_screen (Menu *menu, Screen *s);
|
||||
|
||||
/**
|
||||
* For predecessor-Check: returns selected subitem of menu if this subitem
|
||||
* has no own screen (action, checkbox, ...) and this subitem has a
|
||||
* predecessor and menu otherwise.
|
||||
*
|
||||
* @return NULL on error. */
|
||||
MenuItem * menu_get_item_for_predecessor_check(Menu *menu);
|
||||
|
||||
/**
|
||||
* For successor-Check: returns selected subitem of menu if
|
||||
* this subitem has no own screen (action, checkbox, ...) or menu
|
||||
* otherwise.
|
||||
*
|
||||
* @return NULL on error. */
|
||||
MenuItem * menu_get_item_for_successor_check(Menu *menu);
|
||||
|
||||
/** Does something with the given input.
|
||||
* key is only used if token is MENUTOKEN_OTHER.
|
||||
* DO NOT CALL THIS FUNCTION, CALL menuitem_process_input INSTEAD !
|
||||
*/
|
||||
MenuResult menu_process_input (Menu *menu, MenuToken token, char * key, bool extended);
|
||||
|
||||
/** positions current item pointer on subitem subitem_id. */
|
||||
void menu_select_subitem(Menu *menu, char * subitem_id);
|
||||
#endif
|
||||
|
||||
+96
-27
@@ -57,6 +57,11 @@ Menu * custom_main_menu = NULL;
|
||||
Menu * screens_menu = NULL;
|
||||
|
||||
/* Local prototypes */
|
||||
static void handle_quit();
|
||||
static void handle_close();
|
||||
static void handle_none();
|
||||
static void handle_enter();
|
||||
static void handle_successor();
|
||||
void menuscreen_switch_item (MenuItem * new_menuitem);
|
||||
void menuscreen_create_menu ();
|
||||
Menu* menuscreen_get_main ();
|
||||
@@ -242,11 +247,13 @@ static void handle_close()
|
||||
debug (RPT_DEBUG, "%s: Closing item", __FUNCTION__);
|
||||
menuscreen_switch_item(
|
||||
(active_menuitem == menuscreen_get_main())
|
||||
? NULL : active_menuitem->parent);
|
||||
? NULL
|
||||
: active_menuitem->parent);
|
||||
}
|
||||
|
||||
static void handle_none()
|
||||
{
|
||||
debug (RPT_DEBUG, "%s: Staying in item", __FUNCTION__);
|
||||
if (active_menuitem)
|
||||
{
|
||||
menuitem_update_screen (active_menuitem, menuscreen);
|
||||
@@ -266,21 +273,86 @@ static void handle_enter()
|
||||
menuscreen_switch_item (menu_get_current_item (active_menuitem));
|
||||
}
|
||||
|
||||
static void handle_predecessor()
|
||||
{
|
||||
MenuItem* item = (active_menuitem->type == MENUITEM_MENU)
|
||||
? menu_get_item_for_predecessor_check(active_menuitem)
|
||||
: active_menuitem;
|
||||
assert(item != NULL);
|
||||
debug (RPT_DEBUG, "%s: Switching to registered predecessor '%s' of '%s'.",
|
||||
__FUNCTION__, item->predecessor_id, item->id);
|
||||
MenuItem *predecessor = menuitem_search(
|
||||
item->predecessor_id, (Client*)active_menuitem->client);
|
||||
if (predecessor == NULL)
|
||||
{
|
||||
// note: if _quit_, _close_, _none_ get here this
|
||||
// would be an implementation error - they should
|
||||
// have been handled via different MENURESULT codes.
|
||||
report (RPT_ERR, "%s: cannot find predecessor '%s' of '%s'.",
|
||||
__FUNCTION__, item->predecessor_id, item->id);
|
||||
return;
|
||||
}
|
||||
switch (predecessor->type) {
|
||||
case MENUITEM_ACTION:
|
||||
case MENUITEM_CHECKBOX:
|
||||
case MENUITEM_RING:
|
||||
if (active_menuitem != predecessor->parent)
|
||||
menuscreen_switch_item(predecessor->parent);
|
||||
// this won't work for hidden subitems
|
||||
menu_select_subitem(active_menuitem, item->predecessor_id);
|
||||
menuitem_update_screen(active_menuitem, menuscreen);
|
||||
break;
|
||||
default:
|
||||
if (predecessor->parent != NULL
|
||||
&& predecessor->parent->type == MENUITEM_MENU)
|
||||
{
|
||||
// update parent menu too
|
||||
menu_select_subitem(predecessor->parent, predecessor->id);
|
||||
}
|
||||
menuscreen_switch_item(predecessor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_successor()
|
||||
{
|
||||
debug (RPT_DEBUG, "%s: Switching to succeeding item %s.",
|
||||
__FUNCTION__, active_menuitem->successor_id);
|
||||
// FIXME: code duplication: see menu_commands:search_item()
|
||||
# ifdef LCDPROC_PERMISSIVE_MENU_GOTO
|
||||
MenuItem *top = ((Client*)active_menuitem->client)->menu;
|
||||
# else
|
||||
MenuItem *top = main_menu;
|
||||
# endif /* LCDPROC_PERMISSIVE_MENU_GOTO */
|
||||
MenuItem *item = menu_find_item(top, active_menuitem->successor_id, true);
|
||||
if (item == NULL)
|
||||
report (RPT_ERR, "%s: cannot find successor %s.", __FUNCTION__,
|
||||
active_menuitem->successor_id);
|
||||
menuscreen_switch_item(item);
|
||||
MenuItem* item = (active_menuitem->type == MENUITEM_MENU)
|
||||
? menu_get_item_for_successor_check(active_menuitem)
|
||||
: active_menuitem;
|
||||
assert(item != NULL);
|
||||
debug (RPT_DEBUG, "%s: Switching to registered successor '%s' of '%s'.",
|
||||
__FUNCTION__, item->successor_id, item->id);
|
||||
MenuItem *successor = menuitem_search(
|
||||
item->successor_id, (Client*)active_menuitem->client);
|
||||
if (successor == NULL)
|
||||
{
|
||||
// note: if _quit_, _close_, _none_ get here this
|
||||
// would be an implementation error - they should
|
||||
// have been handled via different MENURESULT codes.
|
||||
report (RPT_ERR, "%s: cannot find successor '%s' of '%s'.",
|
||||
__FUNCTION__, item->successor_id, item->id);
|
||||
return;
|
||||
}
|
||||
switch (successor->type) {
|
||||
case MENUITEM_ACTION:
|
||||
case MENUITEM_CHECKBOX:
|
||||
case MENUITEM_RING:
|
||||
if (active_menuitem != successor->parent)
|
||||
menuscreen_switch_item(successor->parent);
|
||||
// this won't work for hidden subitems
|
||||
menu_select_subitem(active_menuitem, item->successor_id);
|
||||
menuitem_update_screen(active_menuitem, menuscreen);
|
||||
break;
|
||||
default:
|
||||
if (successor->parent != NULL
|
||||
&& successor->parent->type == MENUITEM_MENU)
|
||||
{
|
||||
// update parent menu too
|
||||
menu_select_subitem(successor->parent, successor->id);
|
||||
}
|
||||
menuscreen_switch_item(successor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void menuscreen_key_handler (char *key)
|
||||
@@ -333,23 +405,20 @@ void menuscreen_key_handler (char *key)
|
||||
handle_enter();
|
||||
break;
|
||||
case MENURESULT_CLOSE:
|
||||
if (active_menuitem->successor_id != NULL)
|
||||
{
|
||||
if (strcmp("_quit_", active_menuitem->successor_id) == 0)
|
||||
handle_quit();
|
||||
else if (strcmp("_close_", active_menuitem->successor_id) == 0)
|
||||
handle_close();
|
||||
else if (strcmp("_none_", active_menuitem->successor_id) == 0)
|
||||
handle_none();
|
||||
else
|
||||
handle_successor();
|
||||
}
|
||||
else
|
||||
handle_close();
|
||||
handle_close();
|
||||
break;
|
||||
case MENURESULT_QUIT:
|
||||
handle_quit();
|
||||
break;
|
||||
case MENURESULT_PREDECESSOR:
|
||||
handle_predecessor();
|
||||
break;
|
||||
case MENURESULT_SUCCESSOR:
|
||||
handle_successor();
|
||||
break;
|
||||
default:
|
||||
assert(!"unexpected menuresult");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user