diff --git a/server/client.c b/server/client.c index 2be51d1..7220772 100644 --- a/server/client.c +++ b/server/client.c @@ -20,6 +20,7 @@ #include "screenlist.h" #include "render.h" #include "input.h" +#include "menuscreens.h" #include "menuitem.h" #include "shared/report.h" #include "shared/LL.h" @@ -89,8 +90,11 @@ client_destroy (Client * c) LL_Destroy( c->screenlist); /* Destroy the client's menu, if it exists */ - if (c->menu) + if (c->menu) { + menuscreen_inform_item_destruction (c->menu); + menu_remove_item (c->menu->parent, c->menu); menuitem_destroy (c->menu); + } /* Forget client's key reservations */ input_release_client_keys (c); diff --git a/server/commands/menu_commands.c b/server/commands/menu_commands.c index a01ee56..8c4f5dc 100644 --- a/server/commands/menu_commands.c +++ b/server/commands/menu_commands.c @@ -157,6 +157,7 @@ menu_add_item_func (Client * c, int argc, char **argv) break; } menu_add_item (menu, item); + menuscreen_inform_item_modified (menu); sock_send_string(c->sock, "success\n"); return 0; } @@ -181,7 +182,7 @@ menu_del_item_func (Client * c, int argc, char **argv) if (!c->ack) return 1; - if ((argc < 4 )) { + if ((argc < 3 )) { sock_send_string (c->sock, "huh? Usage: menu_del_item \n"); return 0; } @@ -189,6 +190,12 @@ menu_del_item_func (Client * c, int argc, char **argv) menu_id = argv[1]; item_id = argv[2]; + /* Does the client have a menu already ? */ + if (!c->menu) { + sock_send_string (c->sock, "huh? Client has no menu\n"); + return 0; + } + if ( menu_id[0] == 0 ) { /* No menu specified = client's main menu */ menu = c->menu; @@ -206,9 +213,19 @@ menu_del_item_func (Client * c, int argc, char **argv) sock_send_string (c->sock, "huh? Cannot find item\n"); return 0; } + menuscreen_inform_item_destruction (item); menu_remove_item (menu, item); + menuscreen_inform_item_modified (item->parent); menuitem_destroy (item); + /* Was it the last item in the client's menu ? */ + if (menu_getfirst_item(c->menu) == NULL) { + menuscreen_inform_item_destruction (c->menu); + menu_remove_item (main_menu, c->menu); + menuscreen_inform_item_modified (main_menu); + menu_destroy (c->menu); + c->menu = NULL; + } sock_send_string(c->sock, "success\n"); return 0; } @@ -580,11 +597,7 @@ menu_set_item_func (Client * c, int argc, char **argv) argnr ++; continue; /* Skip current option and the invalid value */ } - if( active_menuitem && menuscreen ) { - /* We need to rebuild the screen */ - menuitem_build_screen( active_menuitem, menuscreen ); - menuitem_update_screen( active_menuitem, menuscreen ); - } + menuscreen_inform_item_modified (item); if( option_table[option_nr].attr_type != NOVALUE ) { /* Skip the now used argument */ argnr ++; @@ -645,7 +658,7 @@ MenuEventFunc (menu_commands_handler) buf[sizeof(buf)-1] = 0; /* Where should the message go to ? */ - for( i = item; i && i->parent != main_menu; i = item->parent ); + for( i = item; i && i->parent != main_menu; i = i->parent ); c = (Client *) i->data.menu.association; if( !c ) { report( RPT_ERR, "%s: Could not find client of item \"%s\"", __FUNCTION__, item->id ); diff --git a/server/menu.c b/server/menu.c index fb0e200..2e7c2aa 100644 --- a/server/menu.c +++ b/server/menu.c @@ -9,7 +9,8 @@ * 2002, Joris Robijn * * - * Handles a menu and all actions that can be performed on it. + * Handles a menu and all actions that can be performed on it. Note that a + * menu is itself also a menuitem. * * Menus are similar to "pull-down" menus, but have some extra features. * They can contain "normal" menu items, checkboxes, sliders, "movers", @@ -323,7 +324,7 @@ void menu_update_screen (MenuItem *menu, Screen *s) } } -MenuResult menu_handle_input (Menu *menu, MenuToken token, char * key) +MenuResult menu_process_input (Menu *menu, MenuToken token, char * key) { MenuItem *subitem; diff --git a/server/menu.h b/server/menu.h index 37e34ac..f50abaa 100644 --- a/server/menu.h +++ b/server/menu.h @@ -103,7 +103,7 @@ void menu_update_screen (Menu *menu, Screen *s); * DO NOT CALL THIS FUNCTION, CALL menuitem_build_screen INSTEAD ! */ -MenuResult menu_handle_input (Menu *menu, MenuToken token, char * key); +MenuResult menu_process_input (Menu *menu, MenuToken token, char * key); /* Does something with the given input. * key is only used if token is MENUTOKEN_OTHER. * DO NOT CALL THIS FUNCTION, CALL menuitem_build_screen INSTEAD ! diff --git a/server/menuitem.c b/server/menuitem.c index a681ff3..cba5751 100644 --- a/server/menuitem.c +++ b/server/menuitem.c @@ -37,9 +37,9 @@ void menuitem_destroy_alpha (MenuItem *item); void menuitem_reset_numeric (MenuItem *item); void menuitem_reset_alpha (MenuItem *item); -void menuitem_build_screen_slider (MenuItem *item, Screen *s); -void menuitem_build_screen_numeric (MenuItem *item, Screen *s); -void menuitem_build_screen_alpha (MenuItem *item, Screen *s); +void menuitem_rebuild_screen_slider (MenuItem *item, Screen *s); +void menuitem_rebuild_screen_numeric (MenuItem *item, Screen *s); +void menuitem_rebuild_screen_alpha (MenuItem *item, Screen *s); void menuitem_update_screen_slider (MenuItem *item, Screen *s); void menuitem_update_screen_numeric (MenuItem *item, Screen *s); @@ -79,9 +79,9 @@ void (*build_screen_table[NUM_ITEMTYPES] ) (MenuItem *item, Screen *s) = NULL, NULL, NULL, - menuitem_build_screen_slider, - menuitem_build_screen_numeric, - menuitem_build_screen_alpha + menuitem_rebuild_screen_slider, + menuitem_rebuild_screen_numeric, + menuitem_rebuild_screen_alpha }; void (*update_screen_table[NUM_ITEMTYPES] ) (MenuItem *item, Screen *s) = { @@ -96,7 +96,7 @@ void (*update_screen_table[NUM_ITEMTYPES] ) (MenuItem *item, Screen *s) = MenuResult (*process_input_table[NUM_ITEMTYPES] ) (MenuItem *item, MenuToken token, char *key) = { - menu_handle_input, + menu_process_input, NULL, NULL, NULL, @@ -351,7 +351,7 @@ void menuitem_reset_alpha (MenuItem *item) /******** MENU SCREEN BUILD FUNCTIONS ********/ -void menuitem_build_screen (MenuItem *item, Screen *s) +void menuitem_rebuild_screen (MenuItem *item, Screen *s) { Widget * w; void (*build_screen) (MenuItem *item, Screen *s); @@ -381,9 +381,12 @@ void menuitem_build_screen (MenuItem *item, Screen *s) report (RPT_ERR, "%s: given menuitem cannot be active", __FUNCTION__); return; } + + /* Also always call update_screen */ + menuitem_update_screen (item, s); } -void menuitem_build_screen_slider (MenuItem *item, Screen *s) +void menuitem_rebuild_screen_slider (MenuItem *item, Screen *s) { Widget * w; @@ -431,7 +434,7 @@ void menuitem_build_screen_slider (MenuItem *item, Screen *s) } } -void menuitem_build_screen_numeric (MenuItem *item, Screen *s) +void menuitem_rebuild_screen_numeric (MenuItem *item, Screen *s) { Widget * w; @@ -462,7 +465,7 @@ void menuitem_build_screen_numeric (MenuItem *item, Screen *s) } } -void menuitem_build_screen_alpha (MenuItem *item, Screen *s) +void menuitem_rebuild_screen_alpha (MenuItem *item, Screen *s) { Widget * w; diff --git a/server/menuitem.h b/server/menuitem.h index c1be5b4..66d37fd 100644 --- a/server/menuitem.h +++ b/server/menuitem.h @@ -258,8 +258,8 @@ void menuitem_reset (MenuItem *item); * Those items do not keep temporary data. */ -void menuitem_build_screen (MenuItem *item, Screen *s); -/* Builds the selected menuitem on screen using widgets. +void menuitem_rebuild_screen (MenuItem *item, Screen *s); +/* (Re)builds the selected menuitem on screen using widgets. * Should be re-called if menuitem data has been changed. * There are a few (logical) exceptions to this: * - the values diff --git a/server/menuscreens.c b/server/menuscreens.c index a982b4b..659a40a 100644 --- a/server/menuscreens.c +++ b/server/menuscreens.c @@ -44,7 +44,8 @@ MenuItem * active_menuitem; Menu * main_menu; Menu * screens_menu; - +/* Local prototypes */ +void menuscreen_switch_item (MenuItem * new_menuitem); void menuscreen_create_menu (); MenuEventFunc (heartbeat_handler); MenuEventFunc (backlight_handler); @@ -78,6 +79,27 @@ int init_menu() return 0; } + +void menuscreen_inform_item_destruction (MenuItem * item) +{ + MenuItem * i; + + /* Are we currently in (a subitem of) the given item ? */ + for( i = active_menuitem; i; i = i->parent ) { + if( i == item ) { + menuscreen_switch_item (item->parent); + } + } +} + +void menuscreen_inform_item_modified (MenuItem * item) +{ + /* Are we currently in the item or the parent of the item ? */ + if( active_menuitem == item || active_menuitem == item->parent ) { + menuitem_rebuild_screen( active_menuitem, menuscreen ); + } +} + bool is_menu_key (char * key) { if (strcmp (key, menu_key) == 0) @@ -86,6 +108,44 @@ bool is_menu_key (char * key) return false; } +void menuscreen_switch_item (MenuItem * new_menuitem) +/* This function changes the menuitem to the given one, and does necesary + * actions. + * The item will not be reset when the new item is a child of the last one. + */ +{ + MenuItem * old_menuitem = active_menuitem; + + /* First we do the switch */ + active_menuitem = new_menuitem; + + /* What was the state change ? */ + if (old_menuitem && !new_menuitem) { + /* Menu is being quit */ + + /* TODO: send menu to backgr */ + if (screenlist_remove (menuscreen) < 0) { + report (RPT_ERR, "%s: Error unqueueing menu screen", __FUNCTION__); + } + } else if (!old_menuitem && new_menuitem) { + /* Menu is becoming active */ + menuitem_reset (active_menuitem); + menuitem_rebuild_screen (active_menuitem, menuscreen); + + if (screenlist_add (menuscreen) < 0) { + report (RPT_ERR, "%s: Error queueing menu screen", __FUNCTION__); + } + /* TODO: raise it ! */ + return; + } else { + /* We're left with the usual case: a menu level switch */ + if( old_menuitem->parent != new_menuitem) { + menuitem_reset (new_menuitem); + } + menuitem_rebuild_screen (active_menuitem, menuscreen); + } +} + void menuscreen_key_handler (char *key) { char token = 0; @@ -112,16 +172,7 @@ void menuscreen_key_handler (char *key) /* Is the menu already active ? */ if (!active_menuitem) { debug (RPT_DEBUG, "%s: Activating menu screen", __FUNCTION__); - active_menuitem = main_menu; - menuitem_build_screen (active_menuitem, menuscreen); - menuitem_reset (active_menuitem); - menuitem_update_screen (active_menuitem, menuscreen); - - if (screenlist_add (menuscreen) < 0) { - report (RPT_ERR, "%s: Error queueing menu screen", __FUNCTION__); - } - /* TODO: raise it ! */ - + menuscreen_switch_item (main_menu); return; } @@ -132,42 +183,30 @@ void menuscreen_key_handler (char *key) report (RPT_ERR, "%s: Error from menu_handle_input", __FUNCTION__); break; case MENURESULT_NONE: + if (active_menuitem) { + menuitem_update_screen (active_menuitem, menuscreen); + /* No rebuild needed, only value can be changed */ + } /* Nothing extra to be done */ break; case MENURESULT_ENTER: - /* Enter the selected menuitem - * Note: this is not for checkboxes etc that don't have their - * own screen. The menu_handle_input function should do - * things like toggling checkboxes ! - */ + /* Enter the selected menuitem + * Note: this is not for checkboxes etc that don't have their + * own screen. The menu_handle_input function should do + * things like toggling checkboxes ! + */ debug (RPT_DEBUG, "%s: Entering subitem", __FUNCTION__); - active_menuitem = menu_get_current_item (active_menuitem); - menuitem_build_screen (active_menuitem, menuscreen); - menuitem_reset (active_menuitem); + menuscreen_switch_item (menu_get_current_item (active_menuitem)); break; case MENURESULT_CLOSE: debug (RPT_DEBUG, "%s: Closing item", __FUNCTION__); - active_menuitem = menuitem_get_parent (active_menuitem); - if (active_menuitem) { - /* We were in at least second level menu */ - menuitem_build_screen (active_menuitem, menuscreen); - break; - } - /* If first level menu, quit menu now - * Therefor no break; now. - */ + menuscreen_switch_item (active_menuitem->parent); + break; case MENURESULT_QUIT: debug (RPT_DEBUG, "%s: Closing menu screen", __FUNCTION__); - active_menuitem = NULL; - /* TODO: send menu to backgr */ - if (screenlist_remove (menuscreen) < 0) { - report (RPT_ERR, "%s: Error unqueueing menu screen", __FUNCTION__); - } + menuscreen_switch_item (NULL); break; } - if (active_menuitem) { - menuitem_update_screen (active_menuitem, menuscreen); - } } void menuscreen_create_menu () diff --git a/server/menuscreens.h b/server/menuscreens.h index cd58675..02479b8 100644 --- a/server/menuscreens.h +++ b/server/menuscreens.h @@ -15,10 +15,10 @@ #define MENUSCREENS_H #include "menu.h" +#include "menuitem.h" #include "screen.h" extern Screen * menuscreen; -extern MenuItem * active_menuitem; extern Menu * main_menu; int init_menu(); @@ -28,6 +28,16 @@ bool is_menu_key (char * key); * reserved menu key. */ +void menuscreen_inform_item_destruction (MenuItem * item); +/* Meant for other parts of the program to inform the menuscreen that the + * item is about to be removed. + */ + +void menuscreen_inform_item_modified (MenuItem * item); +/* Meant for other parts of the program to inform the menuscreen that some + * properties of the item have been modified. + */ + void menuscreen_key_handler (char *key); /* This handler handles the keypresses for the menu. */