new option -prev, corrections for option -next

This commit is contained in:
boercher
2005-07-17 16:13:24 +00:00
parent 763207a64e
commit 6a212dd77c
3 changed files with 231 additions and 35 deletions
+117 -8
View File
@@ -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;
}
+18
View File
@@ -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
View File
@@ -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;
}
}