Do not return NULL as boolean from wonder_is_lost() nor wonder_is_built()
[freeciv.git] / client / gui-gtk-3.0 / gamedlgs.c
blob868b69cbe1ba6e4820c6d07e56820b1fdd838b0d
1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
22 #include <gtk/gtk.h>
23 #include <gdk/gdkkeysyms.h>
25 /* utility */
26 #include "log.h"
27 #include "shared.h"
28 #include "string_vector.h"
29 #include "support.h"
31 /* common */
32 #include "events.h"
33 #include "fcintl.h"
34 #include "government.h"
35 #include "multipliers.h"
37 /* client */
38 #include "client_main.h"
39 #include "options.h"
41 /* client/gui-gtk-3.0 */
42 #include "chatline.h"
43 #include "cityrep.h"
44 #include "dialogs.h"
45 #include "gui_main.h"
46 #include "gui_stuff.h"
47 #include "ratesdlg.h"
49 #include "gamedlgs.h"
51 /******************************************************************/
52 static GtkWidget *rates_dialog_shell;
53 static GtkWidget *rates_gov_label;
54 static GtkWidget *rates_tax_toggle, *rates_lux_toggle, *rates_sci_toggle;
55 static GtkWidget *rates_tax_label, *rates_lux_label, *rates_sci_label;
56 static GtkWidget *rates_tax_scale, *rates_lux_scale, *rates_sci_scale;
58 static GtkWidget *multiplier_dialog_shell;
59 static GtkWidget *multipliers_scale[MAX_NUM_MULTIPLIERS];
61 static gulong rates_tax_sig, rates_lux_sig, rates_sci_sig;
62 /******************************************************************/
64 static int rates_tax_value, rates_lux_value, rates_sci_value;
66 static void rates_changed_callback(GtkWidget *range);
68 /**************************************************************************
69 Set tax values to display
70 **************************************************************************/
71 static void rates_set_values(int tax, int no_tax_scroll,
72 int lux, int no_lux_scroll,
73 int sci, int no_sci_scroll)
75 char buf[64];
76 int tax_lock, lux_lock, sci_lock;
77 int maxrate;
79 tax_lock = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rates_tax_toggle));
80 lux_lock = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rates_lux_toggle));
81 sci_lock = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rates_sci_toggle));
83 if (NULL != client.conn.playing) {
84 maxrate = get_player_bonus(client.conn.playing, EFT_MAX_RATES);
85 } else {
86 maxrate = 100;
89 /* This's quite a simple-minded "double check".. */
90 tax = MIN(tax, maxrate);
91 lux = MIN(lux, maxrate);
92 sci = MIN(sci, maxrate);
94 if (tax + sci + lux != 100) {
95 if (tax != rates_tax_value) {
96 if (!lux_lock) {
97 lux = MIN(MAX(100 - tax - sci, 0), maxrate);
99 if (!sci_lock) {
100 sci = MIN(MAX(100 - tax - lux, 0), maxrate);
102 } else if (lux != rates_lux_value) {
103 if (!tax_lock) {
104 tax = MIN(MAX(100 - lux - sci, 0), maxrate);
106 if (!sci_lock) {
107 sci = MIN(MAX(100 - lux - tax, 0), maxrate);
109 } else if (sci != rates_sci_value) {
110 if (!lux_lock) {
111 lux = MIN(MAX(100 - tax - sci, 0), maxrate);
113 if (!tax_lock) {
114 tax = MIN(MAX(100 - lux - sci, 0), maxrate);
118 if (tax + sci + lux != 100) {
119 tax = rates_tax_value;
120 lux = rates_lux_value;
121 sci = rates_sci_value;
123 rates_tax_value = -1;
124 rates_lux_value = -1;
125 rates_sci_value = -1;
127 no_tax_scroll = 0;
128 no_lux_scroll = 0;
129 no_sci_scroll = 0;
133 if (tax != rates_tax_value) {
134 fc_snprintf(buf, sizeof(buf), "%3d%%", tax);
136 if (strcmp(buf, gtk_label_get_text(GTK_LABEL(rates_tax_label))) != 0) {
137 gtk_label_set_text(GTK_LABEL(rates_tax_label), buf);
139 if (!no_tax_scroll) {
140 g_signal_handler_block(rates_tax_scale, rates_tax_sig);
141 gtk_range_set_value(GTK_RANGE(rates_tax_scale), tax / 10);
142 g_signal_handler_unblock(rates_tax_scale, rates_tax_sig);
144 rates_tax_value = tax;
147 if (lux != rates_lux_value) {
148 fc_snprintf(buf, sizeof(buf), "%3d%%", lux);
150 if (strcmp(buf, gtk_label_get_text(GTK_LABEL(rates_lux_label))) != 0) {
151 gtk_label_set_text(GTK_LABEL(rates_lux_label), buf);
153 if (!no_lux_scroll) {
154 g_signal_handler_block(rates_lux_scale, rates_lux_sig);
155 gtk_range_set_value(GTK_RANGE(rates_lux_scale), lux / 10);
156 g_signal_handler_unblock(rates_lux_scale, rates_lux_sig);
158 rates_lux_value = lux;
161 if (sci != rates_sci_value) {
162 fc_snprintf(buf, sizeof(buf), "%3d%%", sci);
164 if (strcmp(buf, gtk_label_get_text(GTK_LABEL(rates_sci_label))) != 0) {
165 gtk_label_set_text(GTK_LABEL(rates_sci_label), buf);
167 if (!no_sci_scroll) {
168 g_signal_handler_block(rates_sci_scale, rates_sci_sig);
169 gtk_range_set_value(GTK_RANGE(rates_sci_scale), sci / 10);
170 g_signal_handler_unblock(rates_sci_scale, rates_sci_sig);
172 rates_sci_value = sci;
176 /**************************************************************************
177 User changes rates
178 **************************************************************************/
179 static void rates_changed_callback(GtkWidget *range)
181 int percent = gtk_range_get_value(GTK_RANGE(range));
183 if (range == rates_tax_scale) {
184 int tax_value;
186 tax_value = 10 * percent;
187 tax_value = MIN(tax_value, 100);
188 rates_set_values(tax_value, 1, rates_lux_value, 0, rates_sci_value, 0);
189 } else if (range == rates_lux_scale) {
190 int lux_value;
192 lux_value = 10 * percent;
193 lux_value = MIN(lux_value, 100);
194 rates_set_values(rates_tax_value, 0, lux_value, 1, rates_sci_value, 0);
195 } else {
196 int sci_value;
198 sci_value = 10 * percent;
199 sci_value = MIN(sci_value, 100);
200 rates_set_values(rates_tax_value, 0, rates_lux_value, 0, sci_value, 1);
204 /**************************************************************************
205 User has responded to rates dialog
206 **************************************************************************/
207 static void rates_command_callback(GtkWidget *w, gint response_id)
209 if (response_id == GTK_RESPONSE_OK) {
210 dsend_packet_player_rates(&client.conn, rates_tax_value, rates_lux_value,
211 rates_sci_value);
213 gtk_widget_destroy(rates_dialog_shell);
216 /**************************************************************************
217 Convert real multiplier display value to scale value
218 **************************************************************************/
219 static int mult_to_scale(const struct multiplier *pmul, int val)
221 return (val - pmul->start) / pmul->step;
224 /**************************************************************************
225 Convert scale units to real multiplier display value
226 **************************************************************************/
227 static int scale_to_mult(const struct multiplier *pmul, int scale)
229 return scale * pmul->step + pmul->start;
232 /**************************************************************************
233 Format value for multiplier scales
234 **************************************************************************/
235 static gchar *multiplier_value_callback(GtkScale *scale, gdouble value,
236 void *udata)
238 const struct multiplier *pmul = udata;
240 return g_strdup_printf("%d", scale_to_mult(pmul, value));
243 /**************************************************************************
244 User has responded to multipliers dialog
245 **************************************************************************/
246 static void multipliers_command_callback(GtkWidget *w, gint response_id)
248 struct packet_player_multiplier mul;
250 if (response_id == GTK_RESPONSE_OK && can_client_issue_orders()) {
251 multipliers_iterate(m) {
252 Multiplier_type_id i = multiplier_index(m);
253 int value = gtk_range_get_value(GTK_RANGE(multipliers_scale[i]));
255 mul.multipliers[i] = scale_to_mult(m, value);
256 } multipliers_iterate_end;
257 mul.count = multiplier_count();
258 send_packet_player_multiplier(&client.conn, &mul);
260 gtk_widget_destroy(multiplier_dialog_shell);
263 /**************************************************************************
264 Update values in multipliers dialog
265 **************************************************************************/
266 static void multiplier_dialog_update_values(bool set_positions)
268 multipliers_iterate(pmul) {
269 Multiplier_type_id multiplier = multiplier_index(pmul);
270 int val = player_multiplier_value(client_player(), pmul);
271 int target = player_multiplier_target_value(client_player(), pmul);
273 fc_assert(multiplier < ARRAY_SIZE(multipliers_scale));
274 fc_assert(scale_to_mult(pmul, mult_to_scale(pmul, val)) == val);
275 fc_assert(scale_to_mult(pmul, mult_to_scale(pmul, target)) == target);
277 gtk_scale_clear_marks(GTK_SCALE(multipliers_scale[multiplier]));
278 gtk_scale_add_mark(GTK_SCALE(multipliers_scale[multiplier]),
279 mult_to_scale(pmul, val), GTK_POS_BOTTOM,
280 /* TRANS: current value of policy in force */
281 Q_("?multiplier:Cur"));
283 if (set_positions) {
284 gtk_range_set_value(GTK_RANGE(multipliers_scale[multiplier]),
285 mult_to_scale(pmul, target));
287 } multipliers_iterate_end;
290 /**************************************************************************
291 Callback when server indicates multiplier values have changed
292 **************************************************************************/
293 void real_multipliers_dialog_update(void)
295 if (!multiplier_dialog_shell) {
296 return;
299 /* If dialog belongs to a player rather than an observer, we don't
300 * want to lose any local changes made by the player.
301 * This dialog should be the only way the values can change, anyway. */
302 multiplier_dialog_update_values(!can_client_issue_orders());
305 /****************************************************************
306 Create multipliers dialog
307 ****************************************************************/
308 static GtkWidget *create_multiplier_dialog(void)
310 GtkWidget *shell, *content;
311 GtkWidget *label, *scale;
313 if (can_client_issue_orders()) {
314 shell = gtk_dialog_new_with_buttons(_("Change policies"),
315 NULL,
317 GTK_STOCK_CANCEL,
318 GTK_RESPONSE_CANCEL,
319 GTK_STOCK_OK,
320 GTK_RESPONSE_OK,
321 NULL);
322 } else {
323 shell = gtk_dialog_new_with_buttons(_("Policies"),
324 NULL,
326 GTK_STOCK_CLOSE,
327 GTK_RESPONSE_CLOSE,
328 NULL);
330 setup_dialog(shell, toplevel);
332 gtk_window_set_position(GTK_WINDOW(shell), GTK_WIN_POS_MOUSE);
333 content = gtk_dialog_get_content_area(GTK_DIALOG(shell));
335 if (can_client_issue_orders()) {
336 label = gtk_label_new(_("Changes will not take effect until next turn."));
337 gtk_box_pack_start( GTK_BOX( content ), label, FALSE, FALSE, 0);
340 multipliers_iterate(pmul) {
341 Multiplier_type_id multiplier = multiplier_index(pmul);
343 fc_assert(multiplier < ARRAY_SIZE(multipliers_scale));
344 label = gtk_label_new(multiplier_name_translation(pmul));
345 /* Map each multiplier step to a single step on the UI, to enforce
346 * the step size. */
347 scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,
348 mult_to_scale(pmul, pmul->start),
349 mult_to_scale(pmul, pmul->stop), 1);
350 multipliers_scale[multiplier] = scale;
351 gtk_range_set_increments(GTK_RANGE(multipliers_scale[multiplier]),
352 1, MAX(2, mult_to_scale(pmul, pmul->stop) / 10));
353 g_signal_connect(multipliers_scale[multiplier], "format-value",
354 G_CALLBACK(multiplier_value_callback), pmul);
355 g_signal_connect(multipliers_scale[multiplier], "destroy",
356 G_CALLBACK(gtk_widget_destroyed),
357 &multipliers_scale[multiplier]);
358 gtk_box_pack_start( GTK_BOX( content ), label, TRUE, TRUE, 5 );
359 gtk_box_pack_start( GTK_BOX( content ), scale, TRUE, TRUE, 5 );
360 gtk_widget_set_sensitive(multipliers_scale[multiplier],
361 can_client_issue_orders());
362 } multipliers_iterate_end;
364 multiplier_dialog_update_values(TRUE);
366 g_signal_connect(shell, "destroy",
367 G_CALLBACK(gtk_widget_destroyed), &multiplier_dialog_shell);
369 g_signal_connect(shell, "response",
370 G_CALLBACK(multipliers_command_callback), NULL);
372 gtk_widget_show_all(content);
374 return shell;
377 /****************************************************************
378 Popup multipliers dialog
379 *****************************************************************/
380 void popup_multiplier_dialog(void)
382 if (!multiplier_dialog_shell) {
383 multiplier_dialog_shell = create_multiplier_dialog();
386 if (!multiplier_dialog_shell) {
387 return;
390 gtk_window_present(GTK_WINDOW(multiplier_dialog_shell));
393 /****************************************************************
394 Create rates dialog
395 *****************************************************************/
396 static GtkWidget *create_rates_dialog(void)
398 GtkWidget *shell, *content;
399 GtkWidget *frame, *hgrid;
400 int i;
402 if (!can_client_issue_orders()) {
403 return NULL;
406 shell = gtk_dialog_new_with_buttons(_("Select tax, luxury and science rates"),
407 NULL,
409 GTK_STOCK_CANCEL,
410 GTK_RESPONSE_CANCEL,
411 GTK_STOCK_OK,
412 GTK_RESPONSE_OK,
413 NULL);
414 setup_dialog(shell, toplevel);
415 gtk_dialog_set_default_response(GTK_DIALOG(shell), GTK_RESPONSE_OK);
416 gtk_window_set_position(GTK_WINDOW(shell), GTK_WIN_POS_MOUSE);
417 content = gtk_dialog_get_content_area(GTK_DIALOG(shell));
419 rates_gov_label = gtk_label_new("");
420 gtk_box_pack_start( GTK_BOX( content ), rates_gov_label, TRUE, TRUE, 5 );
422 frame = gtk_frame_new( _("Tax") );
423 gtk_box_pack_start( GTK_BOX( content ), frame, TRUE, TRUE, 5 );
425 hgrid = gtk_grid_new();
426 gtk_grid_set_column_spacing(GTK_GRID(hgrid), 10);
427 gtk_container_add(GTK_CONTAINER(frame), hgrid);
429 rates_tax_scale =
430 gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 10, 1);
431 gtk_range_set_increments(GTK_RANGE(rates_tax_scale), 1, 1);
432 for (i = 0; i <= 10; i++) {
433 gtk_scale_add_mark(GTK_SCALE(rates_tax_scale), i, GTK_POS_TOP, NULL);
435 gtk_widget_set_size_request(rates_tax_scale, 300, 40);
436 gtk_scale_set_digits(GTK_SCALE(rates_tax_scale), 0);
437 gtk_scale_set_draw_value(GTK_SCALE(rates_tax_scale), FALSE);
438 gtk_container_add(GTK_CONTAINER(hgrid), rates_tax_scale);
440 rates_tax_label = gtk_label_new(" 0%");
441 gtk_container_add(GTK_CONTAINER(hgrid), rates_tax_label);
442 gtk_widget_set_size_request(rates_tax_label, 40, -1);
444 rates_tax_toggle = gtk_check_button_new_with_label( _("Lock") );
445 gtk_container_add(GTK_CONTAINER(hgrid), rates_tax_toggle);
447 frame = gtk_frame_new( _("Luxury") );
448 gtk_box_pack_start( GTK_BOX( content ), frame, TRUE, TRUE, 5 );
450 hgrid = gtk_grid_new();
451 gtk_grid_set_column_spacing(GTK_GRID(hgrid), 10);
452 gtk_container_add(GTK_CONTAINER(frame), hgrid);
454 rates_lux_scale =
455 gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 10, 1);
456 gtk_range_set_increments(GTK_RANGE(rates_lux_scale), 1, 1);
457 for (i = 0; i <= 10; i++) {
458 gtk_scale_add_mark(GTK_SCALE(rates_lux_scale), i, GTK_POS_TOP, NULL);
460 gtk_widget_set_size_request(rates_lux_scale, 300, 40);
461 gtk_scale_set_digits(GTK_SCALE(rates_lux_scale), 0);
462 gtk_scale_set_draw_value(GTK_SCALE(rates_lux_scale), FALSE);
463 gtk_container_add(GTK_CONTAINER(hgrid), rates_lux_scale);
465 rates_lux_label = gtk_label_new(" 0%");
466 gtk_container_add(GTK_CONTAINER(hgrid), rates_lux_label);
467 gtk_widget_set_size_request(rates_lux_label, 40, -1);
469 rates_lux_toggle = gtk_check_button_new_with_label( _("Lock") );
470 gtk_container_add(GTK_CONTAINER(hgrid), rates_lux_toggle);
472 frame = gtk_frame_new( _("Science") );
473 gtk_box_pack_start( GTK_BOX( content ), frame, TRUE, TRUE, 5 );
475 hgrid = gtk_grid_new();
476 gtk_grid_set_column_spacing(GTK_GRID(hgrid), 10);
477 gtk_container_add(GTK_CONTAINER(frame), hgrid);
479 rates_sci_scale =
480 gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 10, 1);
481 gtk_range_set_increments(GTK_RANGE(rates_sci_scale), 1, 1);
482 for (i = 0; i <= 10; i++) {
483 gtk_scale_add_mark(GTK_SCALE(rates_sci_scale), i, GTK_POS_TOP, NULL);
485 gtk_widget_set_size_request(rates_sci_scale, 300, 40);
486 gtk_scale_set_digits(GTK_SCALE(rates_sci_scale), 0);
487 gtk_scale_set_draw_value(GTK_SCALE(rates_sci_scale), FALSE);
488 gtk_container_add(GTK_CONTAINER(hgrid), rates_sci_scale);
490 rates_sci_label = gtk_label_new(" 0%");
491 gtk_container_add(GTK_CONTAINER(hgrid), rates_sci_label);
492 gtk_widget_set_size_request(rates_sci_label, 40, -1);
494 rates_sci_toggle = gtk_check_button_new_with_label( _("Lock") );
495 gtk_container_add(GTK_CONTAINER(hgrid), rates_sci_toggle);
498 g_signal_connect(shell, "response",
499 G_CALLBACK(rates_command_callback), NULL);
500 g_signal_connect(shell, "destroy",
501 G_CALLBACK(gtk_widget_destroyed), &rates_dialog_shell);
503 gtk_widget_show_all(shell);
505 rates_tax_value=-1;
506 rates_lux_value=-1;
507 rates_sci_value=-1;
509 rates_tax_sig =
510 g_signal_connect_after(rates_tax_scale, "value-changed",
511 G_CALLBACK(rates_changed_callback), NULL);
513 rates_lux_sig =
514 g_signal_connect_after(rates_lux_scale, "value-changed",
515 G_CALLBACK(rates_changed_callback), NULL);
517 rates_sci_sig =
518 g_signal_connect_after(rates_sci_scale, "value-changed",
519 G_CALLBACK(rates_changed_callback), NULL);
521 rates_set_values(client.conn.playing->economic.tax, 0,
522 client.conn.playing->economic.luxury, 0,
523 client.conn.playing->economic.science, 0);
524 return shell;
528 /****************************************************************
529 Popup rates dialog
530 *****************************************************************/
531 void popup_rates_dialog(void)
533 if (!can_client_issue_orders()) {
534 return;
537 if (!rates_dialog_shell) {
538 rates_dialog_shell = create_rates_dialog();
540 if (!rates_dialog_shell) {
541 return;
544 gchar *buf = g_strdup_printf(_("%s max rate: %d%%"),
545 government_name_for_player(client.conn.playing),
546 get_player_bonus(client.conn.playing, EFT_MAX_RATES));
547 gtk_label_set_text(GTK_LABEL(rates_gov_label), buf);
548 g_free(buf);
549 gtk_range_set_fill_level(GTK_RANGE(rates_tax_scale),
550 get_player_bonus(client.conn.playing,
551 EFT_MAX_RATES)/10);
552 gtk_range_set_fill_level(GTK_RANGE(rates_lux_scale),
553 get_player_bonus(client.conn.playing,
554 EFT_MAX_RATES)/10);
555 gtk_range_set_fill_level(GTK_RANGE(rates_sci_scale),
556 get_player_bonus(client.conn.playing,
557 EFT_MAX_RATES)/10);
559 gtk_window_present(GTK_WINDOW(rates_dialog_shell));