Complete.Org: Mailing Lists: Archives: freeciv-dev: October 2004:
[Freeciv-Dev] (PR#10575) city dialog tooltips
Home

[Freeciv-Dev] (PR#10575) city dialog tooltips

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#10575) city dialog tooltips
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 16 Oct 2004 23:39:33 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=10575 >

In Master of Magic, if you click on an output type it will show you the 
sources or sinks of such output (actually sources and sinks are shown 
separately, but this is a misfeature).  Freeciv should do this as well: 
we can do it as a tooltip.

The attached patch is a demonstration of this for food only.  Hovering 
over the food info label gives a tooltip:

  +5 : Farmers
  -2 : Consumed by citizens
  -1 : Unit upkeep
=== : Adds up to
  +2 : Total surplus

this needs some work, but is a step forward.

Problems include:

- GTK labels can't have tooltips, so they have to be packed in eboxes.
- The label is pretty small, and you have to wait a second before the 
tooltip comes up (the latter can be changed, if we want).
- The text is not fixed-width so it doesn't line up well like it does 
above (this may be fixable, or maybe it doesn't matter).
- The === line is pretty ugly.  Maybe this line should be dropped.  Then 
the last line just shows "2 : Total surplus".
- "Total" in "Total surplus" is misleading.  In the code the "total" is 
the sum of all sources, before sinks are accounted for (I think).  See 
pcity->tax_total, etc.  Although for food it's pcity->food_prod.
- We can write a tooltip for each type of output.  Of course they'll all 
have exactly the same format, so there's lots of duplicated code.  This 
is an example of code that will be much simpler under gen-output.

Eventually I think a tooltip should replace the happiness tab, which is 
rather confusing (since it doesn't give actual numbers) and quite 
wasteful of space.

jason

? newtiles
Index: client/citydlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.c,v
retrieving revision 1.50
diff -u -r1.50 citydlg_common.c
--- client/citydlg_common.c     16 Oct 2004 00:00:10 -0000      1.50
+++ client/citydlg_common.c     17 Oct 2004 06:30:46 -0000
@@ -380,6 +380,28 @@
 }
 
 /**************************************************************************
+  Return text describing the food input.
+**************************************************************************/
+void get_city_dialog_food_text(const struct city *pcity,
+                              char *buf, size_t bufsz)
+{
+  buf[0] = '\0';
+
+  my_snprintf(buf + strlen(buf), bufsz - strlen(buf),
+             "%+3d : Farmers\n", pcity->food_prod);
+  my_snprintf(buf + strlen(buf), bufsz - strlen(buf),
+             "%+3d : Consumed by citizens\n", -2 * pcity->size);
+  if (pcity->food_upkeep > 0) {
+    my_snprintf(buf + strlen(buf), bufsz - strlen(buf),
+               "%+3d : Unit upkeep\n", -pcity->food_upkeep);
+  }
+  my_snprintf(buf + strlen(buf), bufsz - strlen(buf),
+             "=== : Adds up to\n");
+  my_snprintf(buf + strlen(buf), bufsz - strlen(buf),
+             "%3d : Total surplus", pcity->food_surplus);
+}
+
+/**************************************************************************
   Provide a list of all citizens in the city, in order.  "index"
   should be the happiness index (currently [0..4]; 4 = final
   happiness).  "citizens" should be an array large enough to hold all
Index: client/citydlg_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.h,v
retrieving revision 1.27
diff -u -r1.27 citydlg_common.h
--- client/citydlg_common.h     29 Sep 2004 02:24:18 -0000      1.27
+++ client/citydlg_common.h     17 Oct 2004 06:30:46 -0000
@@ -54,6 +54,9 @@
 void get_city_dialog_production_row(char *buf[], size_t column_size, int id,
                                    bool is_unit, struct city *pcity);
 
+void get_city_dialog_food_text(const struct city *pcity,
+                              char *buffer, size_t bufsz);
+
 void get_city_citizen_types(struct city *pcity, int index,
                            struct citizen_type *citizens);
 void city_rotate_specialist(struct city *pcity, int citizen_index);
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.408
diff -u -r1.408 packhand.c
--- client/packhand.c   1 Oct 2004 17:40:27 -0000       1.408
+++ client/packhand.c   17 Oct 2004 06:30:47 -0000
@@ -453,7 +453,10 @@
   pcity->tile_trade=packet->tile_trade;
   pcity->corruption=packet->corruption;
   pcity->shield_waste=packet->shield_waste;
-    
+
+  pcity->food_upkeep = packet->food_upkeep;
+  pcity->shield_upkeep = packet->shield_upkeep;
+
   pcity->luxury_total=packet->luxury_total;
   pcity->tax_total=packet->tax_total;
   pcity->science_total=packet->science_total;
@@ -724,6 +727,8 @@
     pcity->shield_surplus     = 0;
     pcity->trade_prod         = 0;
     pcity->corruption         = 0;
+    pcity->food_upkeep = 0;
+    pcity->shield_upkeep = 0;
     pcity->luxury_total       = 0;
     pcity->tax_total          = 0;
     pcity->science_total      = 0;
Index: client/gui-gtk-2.0/citydlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/citydlg.c,v
retrieving revision 1.95
diff -u -r1.95 citydlg.c
--- client/gui-gtk-2.0/citydlg.c        29 Sep 2004 02:24:21 -0000      1.95
+++ client/gui-gtk-2.0/citydlg.c        17 Oct 2004 06:30:47 -0000
@@ -127,6 +127,7 @@
     struct unit_node_vector supported_units;
     struct unit_node_vector present_units;
 
+    GtkWidget *info_ebox[NUM_INFO_FIELDS];
     GtkWidget *info_label[NUM_INFO_FIELDS];
   } overview;
  
@@ -140,6 +141,7 @@
     GtkWidget *map_canvas;
     GtkWidget *map_canvas_pixmap;
     GtkWidget *widget;
+    GtkWidget *info_ebox[NUM_INFO_FIELDS];
     GtkWidget *info_label[NUM_INFO_FIELDS];
   } happiness;
 
@@ -185,7 +187,8 @@
 static gboolean keyboard_handler(GtkWidget * widget, GdkEventKey * event,
                                 struct city_dialog *pdialog);
 
-static GtkWidget *create_city_info_table(GtkWidget **info_label);
+static GtkWidget *create_city_info_table(GtkWidget **info_ebox,
+                                        GtkWidget **info_label);
 static void create_and_append_overview_page(struct city_dialog *pdialog);
 static void create_and_append_worklist_page(struct city_dialog *pdialog);
 static void create_and_append_happiness_page(struct city_dialog *pdialog);
@@ -198,7 +201,8 @@
 
 static void city_dialog_update_title(struct city_dialog *pdialog);
 static void city_dialog_update_citizens(struct city_dialog *pdialog);
-static void city_dialog_update_information(GtkWidget **info_label,
+static void city_dialog_update_information(GtkWidget **info_ebox,
+                                          GtkWidget **info_label,
                                            struct city_dialog *pdialog);
 static void city_dialog_update_map(struct city_dialog *pdialog);
 static void city_dialog_update_building(struct city_dialog *pdialog);
@@ -357,7 +361,8 @@
 
   city_dialog_update_title(pdialog);
   city_dialog_update_citizens(pdialog);
-  city_dialog_update_information(pdialog->overview.info_label, pdialog);
+  city_dialog_update_information(pdialog->overview.info_ebox,
+                                pdialog->overview.info_label, pdialog);
   city_dialog_update_map(pdialog);
   city_dialog_update_building(pdialog);
   city_dialog_update_improvement_list(pdialog);
@@ -372,7 +377,8 @@
 
     refresh_worklist(pdialog->production.worklist);
 
-    city_dialog_update_information(pdialog->happiness.info_label, pdialog);
+    city_dialog_update_information(pdialog->happiness.info_ebox,
+                                  pdialog->happiness.info_label, pdialog);
     refresh_happiness_dialog(pdialog->pcity);
 
     refresh_cma_dialog(pdialog->pcity, REFRESH_ALL);
@@ -486,10 +492,11 @@
  used once in the overview page and once in the happiness page
  **info_label points to the info_label in the respective struct
 ****************************************************************/
-static GtkWidget *create_city_info_table(GtkWidget **info_label)
+static GtkWidget *create_city_info_table(GtkWidget **info_ebox,
+                                        GtkWidget **info_label)
 {
   int i;
-  GtkWidget *hbox, *table, *label;
+  GtkWidget *hbox, *table, *label, *ebox;
 
   static const char *output_label[NUM_INFO_FIELDS] = { N_("Food:"),
     N_("Prod:"),
@@ -523,12 +530,17 @@
     gtk_table_attach(GTK_TABLE(table), label, 0, 1, i, i + 1, GTK_FILL, 0,
                     0, 0);
 
+    ebox = gtk_event_box_new();
+    info_ebox[i] = ebox;
+
     label = gtk_label_new("");
     info_label[i] = label;
     gtk_widget_set_name(label, "city label");  /* ditto */
     gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 
-    gtk_table_attach(GTK_TABLE(table), label, 1, 2, i, i + 1, GTK_FILL, 0,
+    gtk_container_add(GTK_CONTAINER(ebox), label);
+
+    gtk_table_attach(GTK_TABLE(table), ebox, 1, 2, i, i + 1, GTK_FILL, 0,
                     0, 0);
   }
 
@@ -577,7 +589,8 @@
   frame = gtk_frame_new(_("Info"));
   gtk_box_pack_start(GTK_BOX(top), frame, FALSE, FALSE, 0);
 
-  table = create_city_info_table(pdialog->overview.info_label);
+  table = create_city_info_table(pdialog->overview.info_ebox,
+                                pdialog->overview.info_label);
   gtk_container_add(GTK_CONTAINER(frame), table);
 
   frame = gtk_frame_new(_("City map"));
@@ -864,7 +877,8 @@
   align = gtk_alignment_new(0.5, 0.5, 0, 0);
   gtk_container_add(GTK_CONTAINER(vbox), align);
   
-  table = create_city_info_table(pdialog->happiness.info_label);
+  table = create_city_info_table(pdialog->happiness.info_ebox,
+                                pdialog->happiness.info_label);
   gtk_container_add(GTK_CONTAINER(align), table);
 
   gtk_widget_show_all(page);
@@ -1299,11 +1313,13 @@
 /****************************************************************
 ...
 *****************************************************************/
-static void city_dialog_update_information(GtkWidget **info_label,
+static void city_dialog_update_information(GtkWidget **info_ebox,
+                                          GtkWidget **info_label,
                                            struct city_dialog *pdialog)
 {
   int i, style;
   char buf[NUM_INFO_FIELDS][512];
+  char tooltips[NUM_INFO_FIELDS][1024];
   struct city *pcity = pdialog->pcity;
   int granaryturns;
   enum { FOOD, SHIELD, TRADE, GOLD, LUXURY, SCIENCE, 
@@ -1314,21 +1330,34 @@
 
   my_snprintf(buf[FOOD], sizeof(buf[FOOD]), "%2d (%+2d)",
              pcity->food_prod, pcity->food_surplus);
+  get_city_dialog_food_text(pdialog->pcity,
+                           tooltips[FOOD], sizeof(tooltips[FOOD]));
   my_snprintf(buf[SHIELD], sizeof(buf[SHIELD]), "%2d (%+2d)",
              pcity->shield_prod + pcity->shield_waste,
              pcity->shield_surplus);
+  tooltips[SHIELD][0] = '\0';
   my_snprintf(buf[TRADE], sizeof(buf[TRADE]), "%2d (%+2d)",
              pcity->trade_prod + pcity->corruption, pcity->trade_prod);
+  tooltips[TRADE][0] = '\0';
   my_snprintf(buf[GOLD], sizeof(buf[GOLD]), "%2d (%+2d)",
              pcity->tax_total, city_gold_surplus(pcity, pcity->tax_total));
+  tooltips[GOLD][0] = '\0';
   my_snprintf(buf[LUXURY], sizeof(buf[LUXURY]), "%2d      ",
              pcity->luxury_total);
+  tooltips[LUXURY][0] = '\0';
 
   my_snprintf(buf[SCIENCE], sizeof(buf[SCIENCE]), "%2d",
              pcity->science_total);
+  tooltips[SCIENCE][0] = '\0';
 
   my_snprintf(buf[GRANARY], sizeof(buf[GRANARY]), "%d/%-d",
              pcity->food_stock, city_granary_size(pcity->size));
+  tooltips[GRANARY][0] = '\0';
+
+  tooltips[GROWTH][0] = '\0';
+  tooltips[CORRUPTION][0] = '\0';
+  tooltips[WASTE][0] = '\0';
+  tooltips[POLLUTION][0] = '\0';
        
   granaryturns = city_turns_to_grow(pcity);
   if (granaryturns == 0) {
@@ -1353,7 +1382,11 @@
 
   for (i = 0; i < NUM_INFO_FIELDS; i++) {
     gtk_label_set_text(GTK_LABEL(info_label[i]), buf[i]);
+    if (tooltips[i][0] != '\0') {
+      gtk_tooltips_set_tip(pdialog->tips, info_ebox[i], tooltips[i], "");
+    }
   }
+  gtk_tooltips_enable(pdialog->tips);
 
   /* 
    * Special style stuff for granary, growth and pollution below. The
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.251
diff -u -r1.251 city.c
--- common/city.c       15 Oct 2004 09:42:33 -0000      1.251
+++ common/city.c       17 Oct 2004 06:30:47 -0000
@@ -2038,6 +2038,8 @@
 
   /* loop over units, subtracting appropriate amounts of food, shields,
    * gold etc -- SKi */
+  pcity->food_upkeep = 0;
+  pcity->shield_upkeep = 0;
   unit_list_iterate(pcity->units_supported, this_unit) {
     struct unit_type *ut = unit_type(this_unit);
     int shield_cost = utype_shield_cost(ut, g);
@@ -2086,6 +2088,7 @@
     if (shield_cost > 0) {
       adjust_city_free_cost(&free_shield, &shield_cost);
       if (shield_cost > 0) {
+       pcity->shield_upkeep += shield_cost;
        pcity->shield_surplus -= shield_cost;
        this_unit->upkeep = shield_cost;
       }
@@ -2093,6 +2096,7 @@
     if (food_cost > 0) {
       adjust_city_free_cost(&free_food, &food_cost);
       if (food_cost > 0) {
+       pcity->food_upkeep += food_cost;
        pcity->food_surplus -= food_cost;
        this_unit->upkeep_food = food_cost;
       }
@@ -2391,7 +2395,8 @@
   int i;
   struct city *pcity;
 
-  pcity = fc_malloc(sizeof(struct city));
+  pcity = fc_malloc(sizeof(*pcity));
+  memset(pcity, 0, sizeof(*pcity));
 
   pcity->id = 0;
   pcity->owner = pplayer->player_no;
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.163
diff -u -r1.163 city.h
--- common/city.h       29 Sep 2004 02:24:22 -0000      1.163
+++ common/city.h       17 Oct 2004 06:30:48 -0000
@@ -240,6 +240,9 @@
   int shield_prod, shield_surplus, shield_waste; 
   int trade_prod, corruption, tile_trade;
 
+  /* Upkeeps (gold upkeep is done globally, not per-city). */
+  int food_upkeep, shield_upkeep;
+
   /* Cached values for CPU savings. */
   int shield_bonus, luxury_bonus, tax_bonus, science_bonus;
 
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.55
diff -u -r1.55 packets.def
--- common/packets.def  25 Sep 2004 22:18:41 -0000      1.55
+++ common/packets.def  17 Oct 2004 06:30:48 -0000
@@ -398,6 +398,7 @@
   UINT8 specialists[SP_COUNT];
 
   UINT16 food_prod, shield_prod, trade_prod;
+  UINT16 food_upkeep, shield_upkeep;
   SINT16 food_surplus, shield_surplus, tile_trade;
   UINT16 food_stock, shield_stock, corruption;
 
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.276
diff -u -r1.276 citytools.c
--- server/citytools.c  29 Sep 2004 02:24:23 -0000      1.276
+++ server/citytools.c  17 Oct 2004 06:30:49 -0000
@@ -1539,6 +1539,9 @@
   packet->trade_prod=pcity->trade_prod;
   packet->tile_trade=pcity->tile_trade;
   packet->corruption=pcity->corruption;
+
+  packet->food_upkeep = pcity->food_upkeep;
+  packet->shield_upkeep = pcity->shield_upkeep;
   
   packet->shield_waste=pcity->shield_waste;
     

[Prev in Thread] Current Thread [Next in Thread]