Complete.Org: Mailing Lists: Archives: freeciv-dev: November 1999:
[Freeciv-Dev] Patch for client/gui-gtk/cityrep.c
Home

[Freeciv-Dev] Patch for client/gui-gtk/cityrep.c

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] Patch for client/gui-gtk/cityrep.c
From: Sebastian Wilhelmi <wilhelmi@xxxxxxxxxx>
Date: Tue, 02 Nov 1999 14:58:11 +0000

Hi,

Freeciv is really great, but last time I played using the GTK-client, I
noticed, that the following doesn't work:

If I select some cities, I expect the change button to present all
improvements units, that can be built in at least one of the selected cities. 

This is not the current behaviour. So I sat down and did it. While doing it, I
also added a Select button to select cities according to some simple
properties:

1. all cities
2. no cities
3. invert selection

4. all coastal cities
5. all cities on the same island than the currently selected

6. all cities, that can build [submenu with list of improvements and units]
7. all cities, that have built [submenu with list of improvements]
8. all cities, that supports [submenu with list of units]
9. all cities, where [submenu with list of units] is present.

So now you can find out, which cities support settlers, which cities are
defended by phalaxes and so on.

Bye,
Sebastian
-- 
Sebastian Wilhelmi                   |            här ovanför alla molnen
mailto:wilhelmi@xxxxxxxxxx           |     är himmlen så förunderligt blå
http://goethe.ira.uka.de/~wilhelmi   |
Index: client/gui-gtk/cityrep.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/cityrep.c,v
retrieving revision 1.18
diff -u -b -B -u -r1.18 cityrep.c
--- cityrep.c   1999/10/07 19:59:01     1.18
+++ cityrep.c   1999/11/02 14:50:15
@@ -42,7 +42,6 @@
 #include "cityrep.h"
 
 extern GtkWidget *toplevel;
-extern GdkWindow *root_window;
 
 extern struct connection aconnection;
 extern int delay_report_update;
@@ -281,23 +278,24 @@
 void city_popup_callback(GtkWidget *widget, gpointer data);
 void city_buy_callback(GtkWidget *widget, gpointer data);
 void city_refresh_callback(GtkWidget *widget, gpointer data);
-void city_change_callback(GtkWidget *widget, gpointer data);
 void city_change_all_dialog_callback(GtkWidget *w, gpointer data);
 void city_change_all_callback(GtkWidget *w, gpointer data);
 void city_list_callback(GtkWidget *w, gint row, gint column);
-void city_list_ucallback(GtkWidget *w, gint row, gint column);
 void city_config_callback(GtkWidget *widget, gpointer data);
+static gboolean city_change_callback(GtkWidget *w, GdkEvent *event, gpointer 
data);
+static gboolean city_select_callback(GtkWidget *w, GdkEvent *event, gpointer 
data);
 
 GtkWidget *city_dialog_shell=NULL;
 GtkWidget *city_label;
 GtkWidget *city_list;
 GtkWidget *city_center_command, *city_popup_command, *city_buy_command,
          *city_refresh_command, *city_config_command;
-GtkWidget *city_change_command, *city_popupmenu;
+GtkWidget *city_change_command;
 GtkWidget *city_change_all_command;
 GtkWidget *city_change_all_dialog_shell;
 GtkWidget *city_change_all_from_list;
 GtkWidget *city_change_all_to_list;
+GtkWidget *city_select_command;
 
 int city_dialog_shell_is_modal;
 
@@ -381,14 +379,233 @@
 /****************************************************************
 ...
 *****************************************************************/
-static gint city_change_mbutton_callback(GtkWidget *w, GdkEvent *event)
+static struct city* 
+city_from_glist(GList* list)
+{
+  struct city* retval;
+
+  g_assert (list);
+  
+  retval = gtk_clist_get_row_data(GTK_CLIST(city_list),
+                                 GPOINTER_TO_INT(list->data));
+
+  g_assert (retval);
+
+  return retval;
+}
+
+typedef gboolean TestCityFunc(struct city *, gint);
+
+static gboolean city_can_build_imp_or_unit(struct city *pcity, gint number)
+{
+  if(number >= B_LAST)
+    return can_build_unit(pcity, number - B_LAST);
+  else
+    return can_build_improvement(pcity, number);
+}
+
+static void
+append_imp_or_unit_to_menu_sub(GtkWidget *menu,
+                              gchar *nothing_appended_text,
+                              gboolean append_units,
+                              gboolean append_wonders,
+                              gboolean change_prod,
+                              TestCityFunc test_func,
+                              GtkSignalFunc callback)
+{  
+  gint i;
+  gint first = append_units ? B_LAST : 0;
+  gint last = append_units ? game.num_unit_types + B_LAST : B_LAST;
+  gboolean something_appended = FALSE;
+  GtkWidget *item; 
+
+  for(i=first; i<last; i++)
+    {
+      gboolean append = FALSE;
+
+      /* Those many ! are to ensure TRUE is 1 and FALSE is 0 */
+      if( !append_units && ( !append_wonders != !is_wonder(i) ) )
+       continue;
+
+      if(!change_prod)
+       {  
+         city_list_iterate(game.player_ptr->cities, pcity) 
+           {
+             append |= test_func(pcity, i);    
+           } city_list_iterate_end;
+       }
+      else
+       {
+         GList *selection;
+
+         g_assert (GTK_CLIST(city_list)->selection);
+         selection = GTK_CLIST(city_list)->selection;
+         for(; selection; selection = g_list_next(selection))
+           append |= test_func(city_from_glist(selection), i);
+       }
+    
+      if(append) 
+       {
+         gint cost;
+         gchar* name;
+         
+         if(append_units)
+           {
+             cost = get_unit_type(i-B_LAST)->build_cost;
+             name = get_unit_name(i-B_LAST);
+           }
+         else
+           {
+             cost = get_improvement_type(i)->build_cost;
+             if(append_wonders)
+               {
+                 /* We need a city to get the right name for wonders */
+                 struct city *pcity = GTK_CLIST(city_list)->row_list->data;
+                 name = get_imp_name_ex(pcity, i);
+               }
+             else
+               name = get_improvement_name(i);
+           }
+         something_appended = TRUE;
+
+         if (change_prod)
+           {
+             gchar *label = g_strdup_printf("%s (%d)",name, cost);
+             item=gtk_menu_item_new_with_label( label );
+             g_free (label);
+           }
+         else
+           item=gtk_menu_item_new_with_label(name);
+         
+         gtk_menu_append(GTK_MENU(menu),item);
+         
+         gtk_signal_connect(GTK_OBJECT(item),"activate", callback, 
+                            GINT_TO_POINTER(i));
+       }
+    }
+
+  if(!something_appended)
+    {
+      item=gtk_menu_item_new_with_label( nothing_appended_text );
+      gtk_widget_set_sensitive(item, FALSE);
+      gtk_menu_append(GTK_MENU(menu),item);  
+    }
+}
+
+static
+void select_imp_or_unit_callback(GtkWidget *w, gpointer data)
+{
+  gint number = GPOINTER_TO_INT(data);
+  gint i;
+  GtkObject *parent = GTK_OBJECT(w->parent);
+  TestCityFunc *test_func = gtk_object_get_data(parent, "freeciv_test_func");
+  gboolean change_prod = 
+    GPOINTER_TO_INT(gtk_object_get_data(parent, "freeciv_change_prod"));
+
+  /* If this is not the change production button */
+  if(!change_prod)
+    {
+      gtk_clist_unselect_all( GTK_CLIST(city_list));
+
+      for(i = 0; i < GTK_CLIST(city_list)->rows; i++)
+       {
+         struct city* pcity = gtk_clist_get_row_data(GTK_CLIST(city_list),i);
+         if (test_func(pcity, number))
+           gtk_clist_select_row(GTK_CLIST(city_list),i,0);
+       }
+    }
+  else
+    {
+      gboolean is_unit = number >= B_LAST;
+      GList* selection = GTK_CLIST(city_list)->selection;
+
+      g_assert(selection);
+  
+      for(; selection; selection = g_list_next(selection))
+       {
+         struct packet_city_request packet;
+
+         if (is_unit)
+           number -= B_LAST;
+         
+         packet.city_id=city_from_glist(selection)->id;
+         packet.name[0]='\0';
+         packet.build_id=number;
+         packet.is_build_id_unit_id=is_unit;
+         send_packet_city_request(&aconnection, &packet, PACKET_CITY_CHANGE);
+       }
+    }
+}
+
+static void
+append_imp_or_unit_to_menu(GtkWidget *menu,
+                          gboolean change_prod,
+                          gboolean append_improvements,
+                          gboolean append_units,
+                          TestCityFunc test_func)
+{
+  if(append_improvements)
+    {
+      /* Add all buildings */
+      append_imp_or_unit_to_menu_sub(menu, _("No Buildings Available"),
+                                    FALSE, FALSE, change_prod,
+                                    (gboolean (*)(struct city*,gint))
+                                    test_func,
+                                    select_imp_or_unit_callback);
+      /* Add a separator */
+      gtk_menu_append(GTK_MENU(menu),gtk_menu_item_new ());  
+  
+      /* Add all wonders */
+      append_imp_or_unit_to_menu_sub(menu, _("No Wonders Available"),
+                                    FALSE, TRUE, change_prod,
+                                    (gboolean (*)(struct city*,gint))
+                                    test_func,
+                                    select_imp_or_unit_callback);
+      /* Add a separator */
+      if(append_units)
+       gtk_menu_append(GTK_MENU(menu),gtk_menu_item_new ());   
+    }
+  
+  if(append_units)
+    {
+      /* Add all units */
+      append_imp_or_unit_to_menu_sub(menu, _("No Units Available"),
+                                    TRUE, FALSE, change_prod,
+                                    test_func,
+                                    select_imp_or_unit_callback);
+    }
+  
+  gtk_object_set_data(GTK_OBJECT(menu), "freeciv_test_func", test_func);
+  gtk_object_set_data(GTK_OBJECT(menu), "freeciv_change_prod", 
+                     GINT_TO_POINTER(change_prod));
+}
+
+
+static gint 
+city_change_callback(GtkWidget *w, GdkEvent *event, gpointer data)
 {
+  static GtkWidget* menu = NULL;
   GdkEventButton *bevent = (GdkEventButton *)event;
   
   if ( event->type != GDK_BUTTON_PRESS )
     return FALSE;
+
+  /* This migth happen, whenever a selection is still in progress, while 
+     "Changed" is pressed (e.g. when holding the shift key) */
+  if(!GTK_CLIST(city_list)->selection)
+    return FALSE;
+
+  if (menu)
+    gtk_widget_destroy(menu);
+  
+  menu=gtk_menu_new();
+  
+  append_imp_or_unit_to_menu(menu, TRUE, TRUE, TRUE, 
+                            city_can_build_imp_or_unit);
 
-  gtk_menu_popup(GTK_MENU(city_popupmenu),
+  gtk_widget_show_all(menu);
+  
+  gtk_menu_popup(GTK_MENU(menu),
        NULL,NULL,NULL,NULL,bevent->button,bevent->time);
 
   return TRUE;
@@ -468,10 +685,8 @@
         city_change_command, TRUE, TRUE, 0 );
   GTK_WIDGET_SET_FLAGS( city_change_command, GTK_CAN_DEFAULT );
 
-  city_popupmenu=gtk_menu_new();
-
   gtk_signal_connect( GTK_OBJECT( city_change_command ), "event",
-       GTK_SIGNAL_FUNC( city_change_mbutton_callback ), NULL );
+       GTK_SIGNAL_FUNC( city_change_callback ), NULL );
 
   city_change_all_command = gtk_accelbutton_new(_("Change _All"), accel);
   gtk_box_pack_start( GTK_BOX( GTK_DIALOG(city_dialog_shell)->action_area ),
@@ -483,6 +698,14 @@
         city_refresh_command, TRUE, TRUE, 0 );
   GTK_WIDGET_SET_FLAGS( city_refresh_command, GTK_CAN_DEFAULT );
   
+  city_select_command  = gtk_accelbutton_new(_("_Select"), accel);
+  gtk_box_pack_start( GTK_BOX( GTK_DIALOG(city_dialog_shell)->action_area ),
+        city_select_command, TRUE, TRUE, 0 );
+  GTK_WIDGET_SET_FLAGS( city_select_command, GTK_CAN_DEFAULT );
+
+  gtk_signal_connect(GTK_OBJECT(city_select_command), "event",
+       GTK_SIGNAL_FUNC(city_select_callback), NULL);
+
   city_config_command  = gtk_accelbutton_new(_("Con_figure"), accel);
   gtk_box_pack_start( GTK_BOX( GTK_DIALOG(city_dialog_shell)->action_area ),
         city_config_command, TRUE, TRUE, 0 );
@@ -505,7 +729,7 @@
   gtk_signal_connect(GTK_OBJECT(city_list), "select_row",
        GTK_SIGNAL_FUNC(city_list_callback), NULL);
   gtk_signal_connect(GTK_OBJECT(city_list), "unselect_row",
-       GTK_SIGNAL_FUNC(city_list_ucallback), NULL);
+       GTK_SIGNAL_FUNC(city_list_callback), NULL);
 
   for ( i = 0;i < GTK_CLIST(city_list)->columns; i++ )
     gtk_signal_connect(GTK_OBJECT(GTK_CLIST(city_list)->column[i].button),
@@ -525,59 +749,12 @@
 *****************************************************************/
 void city_list_callback(GtkWidget *w, gint row, gint column)
 {
-  struct city *pcity;
-
-  if(row!=-1 && (pcity=gtk_clist_get_row_data(GTK_CLIST(city_list),row)))
+  if (GTK_CLIST(city_list)->selection)
   {
-    int flag;
-    size_t i;
-    char buf[512];
-
     gtk_widget_set_sensitive(city_change_command, TRUE);
     gtk_widget_set_sensitive(city_center_command, TRUE);
     gtk_widget_set_sensitive(city_popup_command, TRUE);
     gtk_widget_set_sensitive(city_buy_command, TRUE);
-    if (city_popupmenu)
-      gtk_widget_destroy(city_popupmenu);
-
-    city_popupmenu=gtk_menu_new();
-
-    flag = 0;
-
-    for(i=0; i<B_LAST; i++)
-      if(can_build_improvement(pcity, i)) 
-      {
-        GtkWidget *item;
-
-        sprintf(buf,"%s (%d)",get_imp_name_ex(pcity, 
i),get_improvement_type(i)->build_cost);
-        item=gtk_menu_item_new_with_label( buf );
-        gtk_menu_append(GTK_MENU(city_popupmenu),item);
-
-        gtk_signal_connect(GTK_OBJECT(item),"activate",
-            GTK_SIGNAL_FUNC(city_change_callback),
-            (gpointer)i);
-        flag=1;
-      }
-
-    for(i=0; i<game.num_unit_types; i++)
-      if(can_build_unit(pcity, i)) {
-        GtkWidget *item;
-
-        sprintf(buf,"%s (%d)", 
-                get_unit_name(i),get_unit_type(i)->build_cost);
-        item=gtk_menu_item_new_with_label( buf );
-        gtk_menu_append(GTK_MENU(city_popupmenu),item);
-
-        gtk_signal_connect(GTK_OBJECT(item),"activate",
-            GTK_SIGNAL_FUNC(city_change_callback),
-            (gpointer)(i+B_LAST));
-        flag = 1;
-      }
-
-    gtk_widget_show_all(city_popupmenu);
-
-    if(!flag)
-      gtk_widget_set_sensitive(city_change_command, FALSE);
   }
   else
   {
@@ -587,82 +764,221 @@
     gtk_widget_set_sensitive(city_buy_command, FALSE);
   }
 }
+
+gboolean
+city_select_all_callback(GtkWidget *w, gpointer data)
+{
+  gtk_clist_select_all( GTK_CLIST(city_list));
+  return TRUE;
+}
+
+gboolean
+city_unselect_all_callback(GtkWidget *w, gpointer data)
+{
+  gtk_clist_unselect_all( GTK_CLIST(city_list));
+  return TRUE;
+}
 
-void city_list_ucallback(GtkWidget *w, gint row, gint column)
+gboolean
+city_invert_selection_callback(GtkWidget *w, gpointer data)
 {
-  if (!GTK_CLIST( city_list )->selection)
+  gint i;
+  GList* row_list = GTK_CLIST(city_list)->row_list;
+  for(i = 0; i < GTK_CLIST(city_list)->rows; i++)
   {
-      gtk_widget_set_sensitive(city_change_command, FALSE);
-      gtk_widget_set_sensitive(city_center_command, FALSE);
-      gtk_widget_set_sensitive(city_popup_command, FALSE);
-      gtk_widget_set_sensitive(city_buy_command, FALSE);
+      GtkCListRow* row = GTK_CLIST_ROW(g_list_nth(row_list,i));
+      if(row->state == GTK_STATE_SELECTED)
+       gtk_clist_unselect_row(GTK_CLIST(city_list),i,0);
+      else
+       gtk_clist_select_row(GTK_CLIST(city_list),i,0);     
   }
+  return TRUE;
 }
 
-/****************************************************************
-...
-*****************************************************************/
-void city_refresh_callback(GtkWidget *w, gpointer data)
+gboolean
+city_select_coastal_callback(GtkWidget *w, gpointer data)
+{
+  gint i;
 
-{ /* added by Syela - I find this very useful */
-  GList *selection;
-  struct city *pcity;
-  struct packet_generic_integer packet;
+  gtk_clist_unselect_all( GTK_CLIST(city_list));
 
-  if ( !( selection = GTK_CLIST( city_list )->selection ) )
+  for(i = 0; i < GTK_CLIST(city_list)->rows; i++)
   {
-    packet.value = 0;
-    send_packet_generic_integer(&aconnection, PACKET_CITY_REFRESH, &packet);
+      struct city* pcity = gtk_clist_get_row_data(GTK_CLIST(city_list),i);
+
+      if (is_terrain_near_tile(pcity->x, pcity->y, T_OCEAN))
+       gtk_clist_select_row(GTK_CLIST(city_list),i,0);
   }
-  else
-  {
-    gint row = (gint)selection->data;
 
-    if(!(pcity = gtk_clist_get_row_data(GTK_CLIST(city_list),row)))
-      return;
+  return TRUE;
+}
 
-    packet.value = pcity->id;
-    send_packet_generic_integer(&aconnection, PACKET_CITY_REFRESH, &packet);
+gboolean
+city_select_same_island_callback(GtkWidget *w, gpointer data)
+{
+  gint i;
+  GList *selection = GTK_CLIST(city_list)->selection;
+  GList *copy = NULL;
+
+  for(; selection; selection = g_list_next(selection))
+    copy = g_list_append (copy, city_from_glist(selection));
+
+  for(i = 0; i < GTK_CLIST(city_list)->rows; i++)
+    {
+      struct city* pcity = gtk_clist_get_row_data(GTK_CLIST(city_list),i);
+      GList *current = copy;
+      
+      for(; current; current = g_list_next(current))
+       {
+         struct city* selectedcity = current->data;
+         if (map_same_continent(pcity->x,pcity->y,
+                                selectedcity->x,selectedcity->y))
+           {
+             gtk_clist_select_row(GTK_CLIST(city_list),i,0);
+             break;
+           }
+       }
   }
+
+  g_list_free(copy);
+  return TRUE;
 }
 
-/****************************************************************
-...
-*****************************************************************/
-void city_change_callback(GtkWidget *w, gpointer data)
+static gboolean
+city_unit_supported(struct city *pcity, gint unit)
 {
-  GList              *selection;
-  gint                row;
-  struct city *pcity;
+  struct unit_list *punit_list = &pcity->units_supported;
 
-  while((selection = GTK_CLIST(city_list)->selection) != NULL)
+  unit_list_iterate((*punit_list), punit) 
   {
-  row = (gint)selection->data;
+      if(punit->type == unit - B_LAST)
+       return TRUE;
+    } unit_list_iterate_end;
+  return FALSE;
+}
 
-  if((pcity=gtk_clist_get_row_data(GTK_CLIST(city_list),row)))
+static gboolean
+city_unit_present(struct city *pcity, gint unit)
+{
+  struct unit_list *punit_list = &map_get_tile(pcity->x,pcity->y)->units;
+
+  unit_list_iterate((*punit_list), punit) 
   {
-      struct packet_city_request packet;
-      int build_nr;
-      int unit;
+      if(punit->type == unit - B_LAST)
+       return TRUE;
+    } unit_list_iterate_end;
+  return FALSE;
+}
       
-      build_nr = (size_t) data;
+static gboolean
+city_select_callback(GtkWidget *w, GdkEvent *event, gpointer data)
+{
+  static GtkWidget* menu = NULL;
+  GtkWidget* submenu = NULL;
 
-      if (build_nr >= B_LAST)
-       {
-         build_nr -= B_LAST;
-         unit = 1;
-       }
-      else
-       unit = 0;
+  GtkWidget* item;
+  GdkEventButton *bevent = (GdkEventButton *)event;
 
-      packet.city_id=pcity->id;
-      packet.name[0]='\0';
-      packet.build_id=build_nr;
-      packet.is_build_id_unit_id=unit;
-      send_packet_city_request(&aconnection, &packet, PACKET_CITY_CHANGE);
+  if ( event->type != GDK_BUTTON_PRESS )
+    return FALSE;
+
+  if (menu)
+    gtk_widget_destroy(menu);
+
+  menu=gtk_menu_new();
+  
+  item=gtk_menu_item_new_with_label( _("All Cities") );
+  gtk_menu_append(GTK_MENU(menu),item);  
+  gtk_signal_connect(GTK_OBJECT(item),"activate",
+                    GTK_SIGNAL_FUNC(city_select_all_callback),
+                    NULL);
+
+  item=gtk_menu_item_new_with_label( _("No Cities") );
+  gtk_menu_append(GTK_MENU(menu),item);  
+  gtk_signal_connect(GTK_OBJECT(item),"activate",
+                    GTK_SIGNAL_FUNC(city_unselect_all_callback),
+                    NULL);
+
+  item=gtk_menu_item_new_with_label( _("Invert Selection") );
+  gtk_menu_append(GTK_MENU(menu),item);  
+  gtk_signal_connect(GTK_OBJECT(item),"activate",
+                    GTK_SIGNAL_FUNC(city_invert_selection_callback),
+                    NULL);
+
+  /* Add a separator */
+  gtk_menu_append(GTK_MENU(menu),gtk_menu_item_new ());  
+  
+  item=gtk_menu_item_new_with_label( _("Coastal Cities") );
+  gtk_menu_append(GTK_MENU(menu),item);  
+  gtk_signal_connect(GTK_OBJECT(item),"activate",
+                    GTK_SIGNAL_FUNC(city_select_coastal_callback),
+                    NULL);
+
+  item=gtk_menu_item_new_with_label( _("Same Island") );
+  gtk_menu_append(GTK_MENU(menu),item);  
+  gtk_signal_connect(GTK_OBJECT(item),"activate",
+                    GTK_SIGNAL_FUNC(city_select_same_island_callback),
+                    NULL);
+  if(!GTK_CLIST(city_list)->selection)
+    gtk_widget_set_sensitive(item,FALSE);
+
+  /* Add a separator */
+  gtk_menu_append(GTK_MENU(menu),gtk_menu_item_new ());  
+
+  item=gtk_menu_item_new_with_label( _("Supported Units") );
+  gtk_menu_append(GTK_MENU(menu),item);  
+  submenu = gtk_menu_new();
+  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+  append_imp_or_unit_to_menu(submenu, FALSE, FALSE, TRUE, city_unit_supported);
+
+  item=gtk_menu_item_new_with_label( _("Units Present") );
+  gtk_menu_append(GTK_MENU(menu),item);  
+  submenu = gtk_menu_new();
+  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+  append_imp_or_unit_to_menu(submenu, FALSE, FALSE, TRUE, city_unit_present);
+
+  item=gtk_menu_item_new_with_label( _("Available To Build") );
+  gtk_menu_append(GTK_MENU(menu),item);  
+  submenu = gtk_menu_new();
+  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+  append_imp_or_unit_to_menu(submenu, FALSE, TRUE, TRUE,
+                            city_can_build_imp_or_unit);
+
+  item=gtk_menu_item_new_with_label( _("Improvements in City") );
+  gtk_menu_append(GTK_MENU(menu),item);  
+  submenu = gtk_menu_new();
+  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
+  append_imp_or_unit_to_menu(submenu, FALSE, TRUE, FALSE,
+                            (TestCityFunc*)city_got_building);
 
+  gtk_widget_show_all(menu);
+  
+  gtk_menu_popup(GTK_MENU(menu), NULL,NULL,NULL,NULL,
+                bevent->button,bevent->time);
+
+  return TRUE;
+}
+
+/****************************************************************
+...
+*****************************************************************/
+void city_refresh_callback(GtkWidget *w, gpointer data)
+
+{ /* added by Syela - I find this very useful */
+  GList *selection = GTK_CLIST(city_list)->selection;
+  struct packet_generic_integer packet;
+
+  if ( !selection )
+  {
+    packet.value = 0;
+    send_packet_generic_integer(&aconnection, PACKET_CITY_REFRESH, &packet);
     }
-    gtk_clist_unselect_row(GTK_CLIST(city_list),row,0);
+  else
+    for(; selection; selection = g_list_next(selection))
+      {
+       packet.value = city_from_glist(selection)->id;
+       send_packet_generic_integer(&aconnection, PACKET_CITY_REFRESH, 
+                                   &packet);
   }
 }
 
@@ -892,16 +1208,13 @@
 *****************************************************************/
 void city_buy_callback(GtkWidget *w, gpointer data)
 {
-  GList              *selection;
-  gint                row;
-  struct city *pcity;
+  GList *current = GTK_CLIST(city_list)->selection;
 
-  while ((selection = GTK_CLIST(city_list)->selection) != NULL)
-  {
-  row = (gint)selection->data;
+  g_assert(current);
 
-  if((pcity=gtk_clist_get_row_data(GTK_CLIST(city_list),row)))
+  for(; current; current = g_list_next(current))
   {
+      struct city *pcity = city_from_glist (current);
       int value;
       char *name;
       char buf[512];
@@ -926,8 +1239,6 @@
          append_output_window(buf);
        }
   }
-    gtk_clist_unselect_row(GTK_CLIST(city_list),row,0);
-  }
 }
 
 /****************************************************************
@@ -947,16 +1258,13 @@
 *****************************************************************/
 void city_center_callback(GtkWidget *w, gpointer data)
 {
-  GList              *selection;
-  gint                row;
+  GList *current = GTK_CLIST(city_list)->selection;
   struct city        *pcity;
 
-  if ( !( selection = GTK_CLIST( city_list )->selection ) )
+  if (!current)
       return;
-
-  row = (gint)selection->data;
 
-  if((pcity=gtk_clist_get_row_data(GTK_CLIST(city_list),row)))
+  pcity = city_from_glist (current);
     center_tile_mapcanvas(pcity->x, pcity->y);
 }
 
@@ -965,20 +1273,24 @@
 *****************************************************************/
 void city_popup_callback(GtkWidget *w, gpointer data)
 {
-  GList              *selection;
-  gint                row;
+  GList *current = GTK_CLIST(city_list)->selection;
+  GList *copy = NULL;
   struct city        *pcity;
 
-  while((selection = GTK_CLIST(city_list)->selection) != NULL)
-  {
-  row = (gint)selection->data;
+  if (!current)
+    return;
 
-  if((pcity=gtk_clist_get_row_data(GTK_CLIST(city_list),row))){
+  pcity = city_from_glist (current);
     center_tile_mapcanvas(pcity->x, pcity->y);
-    popup_city_dialog(pcity, 0);
-  }
-    gtk_clist_unselect_row(GTK_CLIST(city_list),row,0);
-  }
+
+  /* We have to copy the list as the popup_city_dialog destroys the data */
+  for(; current; current = g_list_next(current))
+    copy = g_list_append (copy, city_from_glist(current));
+  
+  for(; copy; copy = g_list_next(copy))
+    popup_city_dialog(copy->data, 0);
+
+  g_list_free(copy);
 }
 
 /****************************************************************
@@ -994,6 +1306,8 @@
 *****************************************************************/
 void city_report_dialog_update(void)
 {
+  GList *selection = NULL;
+  GList *copy = NULL;
   if(city_dialog_shell) {
     char *row  [NUM_CREPORT_COLS];
     char  buf  [NUM_CREPORT_COLS][64];
@@ -1008,18 +1322,16 @@
     gtk_set_label(city_label, report_title);
     free(report_title);
 
-    if (city_popupmenu)
-      {
-       gtk_widget_destroy(city_popupmenu);
-       city_popupmenu = 0;
-      }    
-
     for (i=0, spec=city_report_specs;i<NUM_CREPORT_COLS;i++, spec++)
     {
       row[i] = buf[i];
       gtk_clist_set_column_visibility(GTK_CLIST(city_list), i, spec->show);
     }
 
+    for(selection = GTK_CLIST(city_list)->selection; 
+       selection; selection = g_list_next(selection))
+      copy = g_list_append (copy, city_from_glist(selection));
+
     gtk_clist_freeze(GTK_CLIST(city_list));
     gtk_clist_clear(GTK_CLIST(city_list));
 
@@ -1027,14 +1339,16 @@
       get_city_text(pcity,row);
       i=gtk_clist_append(GTK_CLIST(city_list), row);
       gtk_clist_set_row_data (GTK_CLIST(city_list), i, pcity);
+      if(g_list_find(copy,pcity))
+       gtk_clist_select_row(GTK_CLIST(city_list), i, -1);
     } city_list_iterate_end;
     gtk_clist_thaw(GTK_CLIST(city_list));
     gtk_widget_show_all(city_list);
 
-    gtk_widget_set_sensitive(city_change_command, FALSE);
-    gtk_widget_set_sensitive(city_center_command, FALSE);
-    gtk_widget_set_sensitive(city_popup_command, FALSE);
-    gtk_widget_set_sensitive(city_buy_command, FALSE);
+    g_list_free(copy);
+
+    /* Set sensitivity right. */
+    city_list_callback(NULL,0,0);
   }
 }
 
@@ -1059,6 +1373,8 @@
 
   if((i=gtk_clist_find_row_from_data(GTK_CLIST(city_list), pcity))!=-1)  {
     char *text;
+    gboolean selected = (gboolean) g_list_find(GTK_CLIST(city_list)->selection,
+                                              (gpointer)i);
 
     gtk_clist_get_text(GTK_CLIST(city_list),i,0,&text);
 
@@ -1068,6 +1384,8 @@
     gtk_clist_remove(GTK_CLIST(city_list),i);
     i=gtk_clist_append(GTK_CLIST(city_list),row);
     gtk_clist_set_row_data (GTK_CLIST(city_list), i, pcity);
+    if (selected)
+      gtk_clist_select_row(GTK_CLIST(city_list), i, -1);
     gtk_clist_thaw(GTK_CLIST(city_list));
     gtk_widget_show_all(city_list);
   }

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] Patch for client/gui-gtk/cityrep.c, Sebastian Wilhelmi <=