[Freeciv-Dev] (PR#10575) city dialog tooltips
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=10575 >
Here's an updated patch. No changes, I just updated the city.[ch] bits
to the current CVS version. I also updated the capstring.
-jason
? gprof
Index: client/citydlg_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/citydlg_common.c,v
retrieving revision 1.55
diff -u -r1.55 citydlg_common.c
--- client/citydlg_common.c 30 Dec 2004 22:11:17 -0000 1.55
+++ client/citydlg_common.c 14 Jan 2005 17:27:40 -0000
@@ -390,6 +390,122 @@
}
/**************************************************************************
+ Return text describing the production output.
+**************************************************************************/
+void get_city_dialog_output_text(const struct city *pcity,
+ Output_type_id otype,
+ char *buf, size_t bufsz)
+{
+ int total = 0;
+ enum effect_type eft = get_output_bonus_effect(otype);
+ int tax[O_COUNT];
+
+ buf[0] = '\0';
+
+ cat_snprintf(buf, bufsz,
+ _("%+4d : Citizens\n"), pcity->citizen_base[otype]);
+ total += pcity->citizen_base[otype];
+
+ /* Hack to get around the ugliness of add_tax_income. */
+ memset(tax, 0, O_COUNT * sizeof(*tax));
+ tax[O_TRADE] = pcity->prod[O_TRADE];
+ add_tax_income(city_owner(pcity), tax);
+ tax[O_TRADE] = 0;
+ if (tax[otype] != 0) {
+ cat_snprintf(buf, bufsz, _("%+4d : Taxed from trade\n"), tax[otype]);
+ total += tax[otype];
+ }
+
+ /* Special cases for "bonus" production. See set_city_production in
+ * city.c. */
+ if (otype == O_TRADE) {
+ int routes = 0, i;
+
+ for (i = 0; i < NUM_TRADEROUTES; i++) {
+ routes += pcity->trade_value[i];
+ }
+ if (routes != 0) {
+ cat_snprintf(buf, bufsz, _("%+4d : Trade routes\n"), routes);
+ total += routes;
+ }
+ } else if (otype == O_GOLD) {
+ int tithes = get_city_tithes_bonus(pcity);
+
+ if (tithes != 0) {
+ cat_snprintf(buf, bufsz, _("%+4d : Building tithes\n"), tithes);
+ total += tithes;
+ }
+ }
+
+ if (eft != EFT_LAST) {
+ int base = total, bonus = 100;
+ struct effect_source_vector sources;
+
+ (void) get_city_bonus_sources(&sources, pcity, eft);
+
+ effect_source_vector_iterate(&sources, s) {
+ int new_total;
+
+ bonus += s->effect_value;
+ new_total = bonus * base / 100;
+ cat_snprintf(buf, bufsz,
+ _("%+4d : Bonus from %s (%+d%%)\n"),
+ (new_total - total), get_improvement_name(s->building),
+ s->effect_value);
+ total = new_total;
+ } effect_source_vector_iterate_end;
+ effect_source_vector_free(&sources);
+ }
+
+ if (pcity->waste[otype] != 0) {
+ cat_snprintf(buf, bufsz,
+ _("%+4d : Waste\n"), -pcity->waste[otype]);
+ total -= pcity->waste[otype];
+ }
+
+ if (pcity->unhappy_penalty[otype] != 0) {
+ cat_snprintf(buf, bufsz,
+ _("%+4d : Disorder\n"), -pcity->unhappy_penalty[otype]);
+ total -= pcity->unhappy_penalty[otype];
+ }
+
+ if (pcity->usage[otype] > 0) {
+ cat_snprintf(buf, bufsz,
+ _("%+4d : Used\n"), -pcity->usage[otype]);
+ total -= pcity->usage[otype];
+ }
+
+ cat_snprintf(buf, bufsz,
+ _("==== : Adds up to\n"));
+ cat_snprintf(buf, bufsz,
+ _("%4d : Total surplus"), pcity->surplus[otype]);
+}
+
+/**************************************************************************
+ Return text describing the pollution output.
+**************************************************************************/
+void get_city_dialog_pollution_text(const struct city *pcity,
+ char *buf, size_t bufsz)
+{
+ int pollu, prod, pop, mod;
+
+ pollu = city_pollution_types(pcity, pcity->prod[O_SHIELD],
+ &prod, &pop, &mod);
+ buf[0] = '\0';
+
+ cat_snprintf(buf, bufsz,
+ "%+4d : Pollution from shields\n", prod);
+ cat_snprintf(buf, bufsz,
+ "%+4d : Pollution from citizens\n", pop);
+ cat_snprintf(buf, bufsz,
+ "%+4d : Pollution modifier\n", mod);
+ cat_snprintf(buf, bufsz,
+ "==== : Adds up to\n");
+ cat_snprintf(buf, bufsz,
+ "%4d : Total surplus", pollu);
+}
+
+/**************************************************************************
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.28
diff -u -r1.28 citydlg_common.h
--- client/citydlg_common.h 2 Dec 2004 10:06:58 -0000 1.28
+++ client/citydlg_common.h 14 Jan 2005 17:27:40 -0000
@@ -56,6 +56,12 @@
void get_city_dialog_production_row(char *buf[], size_t column_size, int id,
bool is_unit, struct city *pcity);
+void get_city_dialog_output_text(const struct city *pcity,
+ Output_type_id otype,
+ char *buffer, size_t bufsz);
+void get_city_dialog_pollution_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.455
diff -u -r1.455 packhand.c
--- client/packhand.c 21 Dec 2004 03:36:18 -0000 1.455
+++ client/packhand.c 14 Jan 2005 17:27:40 -0000
@@ -449,6 +449,7 @@
output_type_iterate(o) {
pcity->surplus[o] = packet->surplus[o];
pcity->waste[o] = packet->waste[o];
+ pcity->unhappy_penalty[o] = packet->unhappy_penalty[o];
pcity->prod[o] = packet->prod[o];
pcity->citizen_base[o] = packet->citizen_base[o];
pcity->usage[o] = packet->usage[o];
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.108
diff -u -r1.108 citydlg.c
--- client/gui-gtk-2.0/citydlg.c 21 Dec 2004 04:18:53 -0000 1.108
+++ client/gui-gtk-2.0/citydlg.c 14 Jan 2005 17:27:40 -0000
@@ -128,6 +128,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;
@@ -141,6 +142,7 @@
GtkWidget *map_canvas;
GtkWidget *map_canvas_pixmap;
GtkWidget *widget;
+ GtkWidget *info_ebox[NUM_INFO_FIELDS];
GtkWidget *info_label[NUM_INFO_FIELDS];
} happiness;
@@ -186,7 +188,9 @@
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(struct city_dialog *pdialog,
+ 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);
@@ -199,7 +203,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);
@@ -360,7 +365,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);
@@ -375,7 +381,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);
@@ -485,14 +492,93 @@
return FALSE;
}
+/**************************************************************************
+...
+**************************************************************************/
+static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev,
+ gpointer data)
+{
+ gtk_grab_remove(w);
+ gdk_pointer_ungrab(GDK_CURRENT_TIME);
+ gtk_widget_destroy(w);
+ return FALSE;
+}
+
+enum { FIELD_FOOD, FIELD_SHIELD, FIELD_TRADE, FIELD_GOLD, FIELD_LUXURY,
+ FIELD_SCIENCE, FIELD_GRANARY, FIELD_GROWTH, FIELD_CORRUPTION,
+ FIELD_WASTE, FIELD_POLLUTION
+};
+
+/****************************************************************
+...
+*****************************************************************/
+static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev,
+ gpointer data)
+{
+ struct city_dialog *pdialog = g_object_get_data(G_OBJECT(w), "pdialog");
+
+ if (ev->button == 1) {
+ GtkWidget *p, *label;
+ char buf[1024];
+
+ switch (GPOINTER_TO_UINT(data)) {
+ case FIELD_FOOD:
+ get_city_dialog_output_text(pdialog->pcity, O_FOOD, buf, sizeof(buf));
+ break;
+ case FIELD_SHIELD:
+ get_city_dialog_output_text(pdialog->pcity, O_SHIELD,
+ buf, sizeof(buf));
+ break;
+ case FIELD_TRADE:
+ get_city_dialog_output_text(pdialog->pcity, O_TRADE, buf, sizeof(buf));
+ break;
+ case FIELD_GOLD:
+ get_city_dialog_output_text(pdialog->pcity, O_GOLD, buf, sizeof(buf));
+ break;
+ case FIELD_SCIENCE:
+ get_city_dialog_output_text(pdialog->pcity, O_SCIENCE,
+ buf, sizeof(buf));
+ break;
+ case FIELD_LUXURY:
+ get_city_dialog_output_text(pdialog->pcity, O_LUXURY,
+ buf, sizeof(buf));
+ break;
+ case FIELD_POLLUTION:
+ get_city_dialog_pollution_text(pdialog->pcity, buf, sizeof(buf));
+ break;
+ default:
+ return TRUE;
+ }
+
+ p = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_widget_set_name(p, "Freeciv");
+ gtk_container_set_border_width(GTK_CONTAINER(p), 4);
+ gtk_window_set_position(GTK_WINDOW(p), GTK_WIN_POS_MOUSE);
+
+ label = gtk_label_new(buf);
+ gtk_widget_set_name(label, "city info label");
+ gtk_container_add(GTK_CONTAINER(p), label);
+ gtk_widget_show_all(p);
+
+ gdk_pointer_grab(p->window, TRUE, GDK_BUTTON_RELEASE_MASK,
+ NULL, NULL, ev->time);
+ gtk_grab_add(p);
+
+ g_signal_connect_after(p, "button_release_event",
+ G_CALLBACK(show_info_button_release), NULL);
+ }
+ return TRUE;
+}
/****************************************************************
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(struct city_dialog *pdialog,
+ 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:"),
@@ -526,12 +612,20 @@
gtk_table_attach(GTK_TABLE(table), label, 0, 1, i, i + 1, GTK_FILL, 0,
0, 0);
+ ebox = gtk_event_box_new();
+ g_object_set_data(G_OBJECT(ebox), "pdialog", pdialog);
+ g_signal_connect(ebox, "button_press_event",
+ G_CALLBACK(show_info_popup), GUINT_TO_POINTER(i));
+ 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);
}
@@ -580,7 +674,9 @@
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,
+ pdialog->overview.info_ebox,
+ pdialog->overview.info_label);
gtk_container_add(GTK_CONTAINER(frame), table);
frame = gtk_frame_new(_("City map"));
@@ -867,7 +963,9 @@
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,
+ pdialog->happiness.info_ebox,
+ pdialog->happiness.info_label);
gtk_container_add(GTK_CONTAINER(align), table);
gtk_widget_show_all(page);
@@ -1075,6 +1173,9 @@
}
}
+
+
+
/****************************************************************
...
*****************************************************************/
@@ -1306,7 +1407,8 @@
/****************************************************************
...
*****************************************************************/
-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;
Index: common/capstr.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/capstr.c,v
retrieving revision 1.214
diff -u -r1.214 capstr.c
--- common/capstr.c 21 Dec 2004 03:37:38 -0000 1.214
+++ common/capstr.c 14 Jan 2005 17:27:40 -0000
@@ -82,7 +82,7 @@
* as long as possible. We want to maintain network compatibility with
* the stable branch for as long as possible.
*/
-#define CAPABILITY "+Freeciv.Devel.2004.Dec.21"
+#define CAPABILITY "+Freeciv.Devel.2004.Jan.14"
void init_our_capability(void)
{
Index: common/city.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.c,v
retrieving revision 1.304
diff -u -r1.304 city.c
--- common/city.c 12 Jan 2005 18:43:15 -0000 1.304
+++ common/city.c 14 Jan 2005 17:27:40 -0000
@@ -271,7 +271,7 @@
/**************************************************************************
Return the effect for the production bonus for this output type.
**************************************************************************/
-static inline enum effect_type get_output_bonus_effect(Output_type_id otype)
+inline enum effect_type get_output_bonus_effect(Output_type_id otype)
{
switch (otype) {
case O_SHIELD:
@@ -1949,39 +1949,64 @@
static inline void unhappy_city_check(struct city *pcity)
{
if (city_unhappy(pcity)) {
- pcity->prod[O_FOOD] = MIN(pcity->usage[O_FOOD], pcity->prod[O_FOOD]);
- pcity->prod[O_SHIELD] = MIN(pcity->usage[O_SHIELD], pcity->prod[O_SHIELD]);
- pcity->prod[O_GOLD] = 0;
- pcity->prod[O_SCIENCE] = 0;
+ pcity->unhappy_penalty[O_FOOD]
+ = MAX(pcity->prod[O_FOOD] - pcity->usage[O_FOOD], 0);
+ pcity->unhappy_penalty[O_SHIELD]
+ = MAX(pcity->prod[O_SHIELD] - pcity->usage[O_SHIELD], 0);
+ pcity->unhappy_penalty[O_GOLD] = pcity->prod[O_GOLD];
+ pcity->unhappy_penalty[O_SCIENCE] = pcity->prod[O_SCIENCE];
/* Trade and luxury are unaffected. */
+
+ output_type_iterate(o) {
+ pcity->prod[o] -= pcity->unhappy_penalty[o];
+ } output_type_iterate_end;
+ } else {
+ memset(pcity->unhappy_penalty, 0,
+ O_COUNT * sizeof(*pcity->unhappy_penalty));
}
}
/**************************************************************************
- Calculate pollution for the city. The shield_total must be passed in
- (most callers will want to pass pcity->prod[O_SHIELD]).
+ Calculate the pollution from production and population in the city.
**************************************************************************/
-int city_pollution(const struct city *pcity, int shield_total)
+int city_pollution_types(const struct city *pcity, int shield_total,
+ int *pollu_prod, int *pollu_pop, int *pollu_mod)
{
struct player *pplayer = city_owner(pcity);
- int mod, pollution;
+ int prod, pop, mod;
/* Add one one pollution per shield, multipled by the bonus. */
- mod = 100 + get_city_bonus(pcity, EFT_POLLU_PROD_PCT);
- mod = MAX(0, mod);
- pollution = shield_total * mod / 100;
+ prod = 100 + get_city_bonus(pcity, EFT_POLLU_PROD_PCT);
+ prod = shield_total * MAX(prod, 0) / 100;
/* Add one 1/4 pollution per citizen per tech, multiplied by the bonus. */
- mod = 100 + get_city_bonus(pcity, EFT_POLLU_POP_PCT);
- mod = MAX(0, mod);
- pollution += (pcity->size
- * num_known_tech_with_flag(pplayer,
- TF_POPULATION_POLLUTION_INC)
- * mod) / (4 * 100);
+ pop = 100 + get_city_bonus(pcity, EFT_POLLU_POP_PCT);
+ pop = (pcity->size
+ * num_known_tech_with_flag(pplayer, TF_POPULATION_POLLUTION_INC)
+ * MAX(pop, 0)) / (4 * 100);
- pollution = MAX(0, pollution - 20);
+ /* Then there's a base -20 pollution. */
+ mod = -20;
+
+ if (pollu_prod) {
+ *pollu_prod = prod;
+ }
+ if (pollu_pop) {
+ *pollu_pop = pop;
+ }
+ if (pollu_mod) {
+ *pollu_mod = mod;
+ }
+ return MAX(prod + pop + mod, 0);
+}
- return pollution;
+/**************************************************************************
+ Calculate pollution for the city. The shield_total must be passed in
+ (most callers will want to pass pcity->shield_prod).
+**************************************************************************/
+int city_pollution(const struct city *pcity, int shield_total)
+{
+ return city_pollution_types(pcity, shield_total, NULL, NULL, NULL);
}
/**************************************************************************
@@ -2477,6 +2502,8 @@
memset(pcity->surplus, 0, O_COUNT * sizeof(*pcity->surplus));
memset(pcity->waste, 0, O_COUNT * sizeof(*pcity->waste));
+ memset(pcity->unhappy_penalty, 0,
+ O_COUNT * sizeof(*pcity->unhappy_penalty));
memset(pcity->prod, 0, O_COUNT * sizeof(*pcity->prod));
memset(pcity->citizen_base, 0, O_COUNT * sizeof(*pcity->citizen_base));
output_type_iterate(o) {
Index: common/city.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/city.h,v
retrieving revision 1.194
diff -u -r1.194 city.h
--- common/city.h 12 Jan 2005 18:43:16 -0000 1.194
+++ common/city.h 14 Jan 2005 17:27:40 -0000
@@ -229,7 +229,8 @@
/* the productions */
int surplus[O_MAX]; /* Final surplus in each category. */
int waste[O_MAX]; /* Waste/corruption in each category. */
- int prod[O_MAX]; /* Production is total minus waste. */
+ int unhappy_penalty[O_MAX]; /* Penalty from unhappy cities. */
+ int prod[O_MAX]; /* Production is total minus waste and penalty. */
int citizen_base[O_MAX]; /* Base production from citizens. */
int usage[O_MAX]; /* Amount of each resource being used. */
@@ -354,6 +355,7 @@
const char *get_output_identifier(Output_type_id output);
const char *get_output_name(Output_type_id output);
+enum effect_type get_output_bonus_effect(Output_type_id otype);
/* properties */
@@ -510,6 +512,8 @@
void get_citizen_output(const struct city *pcity, int *output);
void add_tax_income(const struct player *pplayer, int *output);
int get_city_tithes_bonus(const struct city *pcity);
+int city_pollution_types(const struct city *pcity, int shield_total,
+ int *pollu_prod, int *pollu_pop, int *pollu_mod);
int city_pollution(const struct city *pcity, int shield_total);
/*
Index: common/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.86
diff -u -r1.86 packets.def
--- common/packets.def 6 Jan 2005 00:35:50 -0000 1.86
+++ common/packets.def 14 Jan 2005 17:27:40 -0000
@@ -402,6 +402,7 @@
SINT16 surplus[O_MAX];
UINT16 waste[O_MAX];
+ SINT16 unhappy_penalty[O_MAX];
UINT16 prod[O_MAX];
SINT16 citizen_base[O_MAX];
SINT16 usage[O_MAX];
Index: server/citytools.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/citytools.c,v
retrieving revision 1.300
diff -u -r1.300 citytools.c
--- server/citytools.c 12 Jan 2005 18:26:55 -0000 1.300
+++ server/citytools.c 14 Jan 2005 17:27:42 -0000
@@ -1536,6 +1536,7 @@
output_type_iterate(o) {
packet->surplus[o] = pcity->surplus[o];
packet->waste[o] = pcity->waste[o];
+ packet->unhappy_penalty[o] = pcity->unhappy_penalty[o];
packet->prod[o] = pcity->prod[o];
packet->citizen_base[o] = pcity->citizen_base[o];
packet->usage[o] = pcity->usage[o];
|
|