Author: sveinung Date: Tue Aug 23 13:08:13 2016 New Revision: 33686 URL: http://svn.gna.org/viewcvs/freeciv?rev=33686&view=rev Log: Gtk 3 clients: add the "Go to and..." menu.
Make it work like the Qt client's "Go to and..." menu for now. The user selects the action before clicking on the map. No checks for action legality are performed. This allows the player to order an action that will become legal before the unit reaches the target tile. Example: join the city that will be built at the target tile next turn. Implementing a more beginner friendly alternative UI like the one suggested in bug #16905 has been left for later. See patch #7644 Modified: trunk/client/gui-gtk-3.0/menu.c trunk/client/gui-gtk-3.x/menu.c trunk/data/gtk3_menus.xml trunk/data/gtk3x_menus.xml Modified: trunk/client/gui-gtk-3.0/menu.c URL: http://svn.gna.org/viewcvs/freeciv/trunk/client/gui-gtk-3.0/menu.c?rev=33686&r1=33685&r2=33686&view=diff ============================================================================== --- trunk/client/gui-gtk-3.0/menu.c (original) +++ trunk/client/gui-gtk-3.0/menu.c Tue Aug 23 13:08:13 2016 @@ -462,6 +462,7 @@ G_CALLBACK(unit_done_callback), MGROUP_UNIT }, { "UNIT_GOTO", N_("Go to"), GDK_KEY_g, 0, G_CALLBACK(unit_goto_callback), MGROUP_UNIT }, + { "MENU_GOTO_AND", N_("Go to and..."), 0, 0, NULL, MGROUP_UNIT }, { "UNIT_GOTO_CITY", N_("Go to/Airlift to City"), GDK_KEY_t, 0, G_CALLBACK(unit_goto_city_callback), MGROUP_UNIT }, { "UNIT_RETURN", N_("Return to Nearest City"), GDK_KEY_g, GDK_SHIFT_MASK, @@ -1383,6 +1384,23 @@ key_unit_goto(); } +/************************************************************************** + Activate the goto system with an action to perform once there. +**************************************************************************/ +static void unit_goto_and_callback(GtkMenuItem *item, gpointer data) +{ + struct action *action = data; + + /* This menu doesn't support specifying a detailed target (think + * "Go to and..."->"Industrial Sabotage"->"City Walls") for the + * action order. */ + fc_assert_ret_msg(!action_requires_details(action->id), + "Underspecified target for %s.", + action_get_ui_name(action->id)); + + request_unit_goto(ORDER_PERFORM_ACTION, action->id, EXTRA_NONE); +} + /**************************************************************** Item "UNIT_GOTO_CITY" callback. *****************************************************************/ @@ -2211,6 +2229,38 @@ } } g_list_free(list); + } + + /* Set Go to and... action visibility. */ + if ((menu = find_menu("<MENU>/GOTO_AND"))) { + GList *list, *iter; + struct action *paction; + + bool can_do_something = FALSE; + + /* Enable a menu item if it is theoretically possible that one of the + * selected units can perform it. Checking if the action can be performed + * at the current tile is pointless since it should be performed at the + * target tile. */ + list = gtk_container_get_children(GTK_CONTAINER(menu)); + for (iter = list; NULL != iter; iter = g_list_next(iter)) { + paction = g_object_get_data(G_OBJECT(iter->data), "end_action"); + if (NULL != paction) { + if (units_can_do_action(get_units_in_focus(), + paction->id, TRUE)) { + gtk_widget_set_visible(GTK_WIDGET(iter->data), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(iter->data), TRUE); + can_do_something = TRUE; + } else { + gtk_widget_set_visible(GTK_WIDGET(iter->data), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(iter->data), FALSE); + } + } + } + g_list_free(list); + + /* Only sensitive if an action may be possible. */ + menu_entry_set_sensitive("MENU_GOTO_AND", can_do_something); } /* Enable the button for adding to a city in all cases, so we @@ -2628,6 +2678,61 @@ } extra_type_by_cause_iterate_end; } + /* Initialize the Go to and... actions. */ + if ((menu = find_menu("<MENU>/GOTO_AND"))) { + GList *list, *iter; + GtkWidget *item; + int tgt_kind_group; + + /* Remove previous action entries. */ + list = gtk_container_get_children(GTK_CONTAINER(menu)); + for (iter = list; NULL != iter; iter = g_list_next(iter)) { + gtk_widget_destroy(GTK_WIDGET(iter->data)); + } + g_list_free(list); + + /* Add the new action entries grouped by target kind. */ + for (tgt_kind_group = 0; tgt_kind_group < ATK_COUNT; tgt_kind_group++) { + action_iterate(action_id) { + struct action *paction = action_by_number(action_id); + + if (action_get_actor_kind(action_id) != AAK_UNIT) { + /* This action isn't performed by a unit. */ + continue; + } + + if (action_get_target_kind(action_id) != tgt_kind_group) { + /* Wrong group. */ + continue; + } + + if (action_requires_details(action_id)) { + /* This menu doesn't support specifying a detailed target (think + * "Go to and..."->"Industrial Sabotage"->"City Walls") for the + * action order. */ + continue; + } + + if (action_by_number(action_id)->max_distance > 1) { + /* The order system doesn't support actions that can be done to a + * target that isn't at or next to the actor unit's tile. + * + * Full explanation in handle_unit_orders(). */ + continue; + } + + /* Create and add the menu item. It will be hidden or shown based on + * unit type. */ + item = gtk_menu_item_new_with_label(action_get_ui_name(action_id)); + g_object_set_data(G_OBJECT(item), "end_action", paction); + g_signal_connect(item, "activate", + G_CALLBACK(unit_goto_and_callback), paction); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show(item); + } action_iterate_end; + } + } + menu_entry_group_set_sensitive(MGROUP_SAFE, TRUE); menu_entry_group_set_sensitive(MGROUP_PLAYER, client_has_player()); Modified: trunk/client/gui-gtk-3.x/menu.c URL: http://svn.gna.org/viewcvs/freeciv/trunk/client/gui-gtk-3.x/menu.c?rev=33686&r1=33685&r2=33686&view=diff ============================================================================== --- trunk/client/gui-gtk-3.x/menu.c (original) +++ trunk/client/gui-gtk-3.x/menu.c Tue Aug 23 13:08:13 2016 @@ -461,6 +461,7 @@ G_CALLBACK(unit_done_callback), MGROUP_UNIT }, { "UNIT_GOTO", N_("Go to"), GDK_KEY_g, 0, G_CALLBACK(unit_goto_callback), MGROUP_UNIT }, + { "MENU_GOTO_AND", N_("Go to and..."), 0, 0, NULL, MGROUP_UNIT }, { "UNIT_GOTO_CITY", N_("Go to/Airlift to City"), GDK_KEY_t, 0, G_CALLBACK(unit_goto_city_callback), MGROUP_UNIT }, { "UNIT_RETURN", N_("Return to Nearest City"), GDK_KEY_g, GDK_SHIFT_MASK, @@ -1382,6 +1383,23 @@ key_unit_goto(); } +/************************************************************************** + Activate the goto system with an action to perform once there. +**************************************************************************/ +static void unit_goto_and_callback(GtkMenuItem *item, gpointer data) +{ + struct action *action = data; + + /* This menu doesn't support specifying a detailed target (think + * "Go to and..."->"Industrial Sabotage"->"City Walls") for the + * action order. */ + fc_assert_ret_msg(!action_requires_details(action->id), + "Underspecified target for %s.", + action_get_ui_name(action->id)); + + request_unit_goto(ORDER_PERFORM_ACTION, action->id, EXTRA_NONE); +} + /**************************************************************** Item "UNIT_GOTO_CITY" callback. *****************************************************************/ @@ -2210,6 +2228,38 @@ } } g_list_free(list); + } + + /* Set Go to and... action visibility. */ + if ((menu = find_menu("<MENU>/GOTO_AND"))) { + GList *list, *iter; + struct action *paction; + + bool can_do_something = FALSE; + + /* Enable a menu item if it is theoretically possible that one of the + * selected units can perform it. Checking if the action can be performed + * at the current tile is pointless since it should be performed at the + * target tile. */ + list = gtk_container_get_children(GTK_CONTAINER(menu)); + for (iter = list; NULL != iter; iter = g_list_next(iter)) { + paction = g_object_get_data(G_OBJECT(iter->data), "end_action"); + if (NULL != paction) { + if (units_can_do_action(get_units_in_focus(), + paction->id, TRUE)) { + gtk_widget_set_visible(GTK_WIDGET(iter->data), TRUE); + gtk_widget_set_sensitive(GTK_WIDGET(iter->data), TRUE); + can_do_something = TRUE; + } else { + gtk_widget_set_visible(GTK_WIDGET(iter->data), FALSE); + gtk_widget_set_sensitive(GTK_WIDGET(iter->data), FALSE); + } + } + } + g_list_free(list); + + /* Only sensitive if an action may be possible. */ + menu_entry_set_sensitive("MENU_GOTO_AND", can_do_something); } /* Enable the button for adding to a city in all cases, so we @@ -2613,6 +2663,61 @@ } extra_type_by_cause_iterate_end; } + /* Initialize the Go to and... actions. */ + if ((menu = find_menu("<MENU>/GOTO_AND"))) { + GList *list, *iter; + GtkWidget *item; + int tgt_kind_group; + + /* Remove previous action entries. */ + list = gtk_container_get_children(GTK_CONTAINER(menu)); + for (iter = list; NULL != iter; iter = g_list_next(iter)) { + gtk_widget_destroy(GTK_WIDGET(iter->data)); + } + g_list_free(list); + + /* Add the new action entries grouped by target kind. */ + for (tgt_kind_group = 0; tgt_kind_group < ATK_COUNT; tgt_kind_group++) { + action_iterate(action_id) { + struct action *paction = action_by_number(action_id); + + if (action_get_actor_kind(action_id) != AAK_UNIT) { + /* This action isn't performed by a unit. */ + continue; + } + + if (action_get_target_kind(action_id) != tgt_kind_group) { + /* Wrong group. */ + continue; + } + + if (action_requires_details(action_id)) { + /* This menu doesn't support specifying a detailed target (think + * "Go to and..."->"Industrial Sabotage"->"City Walls") for the + * action order. */ + continue; + } + + if (action_by_number(action_id)->max_distance > 1) { + /* The order system doesn't support actions that can be done to a + * target that isn't at or next to the actor unit's tile. + * + * Full explanation in handle_unit_orders(). */ + continue; + } + + /* Create and add the menu item. It will be hidden or shown based on + * unit type. */ + item = gtk_menu_item_new_with_label(action_get_ui_name(action_id)); + g_object_set_data(G_OBJECT(item), "end_action", paction); + g_signal_connect(item, "activate", + G_CALLBACK(unit_goto_and_callback), paction); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show(item); + } action_iterate_end; + } + } + menu_entry_group_set_sensitive(MGROUP_SAFE, TRUE); menu_entry_group_set_sensitive(MGROUP_PLAYER, client_has_player()); Modified: trunk/data/gtk3_menus.xml URL: http://svn.gna.org/viewcvs/freeciv/trunk/data/gtk3_menus.xml?rev=33686&r1=33685&r2=33686&view=diff ============================================================================== --- trunk/data/gtk3_menus.xml (original) +++ trunk/data/gtk3_menus.xml Tue Aug 23 13:08:13 2016 @@ -258,6 +258,13 @@ <object class="GtkMenu" id="<MENU>/UNIT"> <child> <object class="GtkMenuItem" id="UNIT_GOTO" /> + </child> + <child> + <object class="GtkMenuItem" id="MENU_GOTO_AND" > + <child type="submenu"> + <object class="GtkMenu" id="<MENU>/GOTO_AND" /> + </child> + </object> </child> <child> <object class="GtkMenuItem" id="UNIT_GOTO_CITY" /> Modified: trunk/data/gtk3x_menus.xml URL: http://svn.gna.org/viewcvs/freeciv/trunk/data/gtk3x_menus.xml?rev=33686&r1=33685&r2=33686&view=diff ============================================================================== --- trunk/data/gtk3x_menus.xml (original) +++ trunk/data/gtk3x_menus.xml Tue Aug 23 13:08:13 2016 @@ -258,6 +258,13 @@ <object class="GtkMenu" id="<MENU>/UNIT"> <child> <object class="GtkMenuItem" id="UNIT_GOTO" /> + </child> + <child> + <object class="GtkMenuItem" id="MENU_GOTO_AND" > + <child type="submenu"> + <object class="GtkMenu" id="<MENU>/GOTO_AND" /> + </child> + </object> </child> <child> <object class="GtkMenuItem" id="UNIT_GOTO_CITY" /> _______________________________________________ Freeciv-commits mailing list Freeciv-commits@gna.org https://mail.gna.org/listinfo/freeciv-commits