Freeciv-3.1
Loading...
Searching...
No Matches
gamedlgs.c
Go to the documentation of this file.
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.
7
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***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include <gtk/gtk.h>
23#include <gdk/gdkkeysyms.h>
24
25/* utility */
26#include "log.h"
27#include "shared.h"
28#include "string_vector.h"
29#include "support.h"
30
31/* common */
32#include "events.h"
33#include "fcintl.h"
34#include "government.h"
35#include "multipliers.h"
36
37/* client */
38#include "client_main.h"
39#include "options.h"
40
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"
48
49#include "gamedlgs.h"
50
51/******************************************************************/
52static GtkWidget *rates_dialog_shell;
53static GtkWidget *rates_gov_label;
57
58static GtkWidget *multiplier_dialog_shell;
60
62/******************************************************************/
63
65
66static void rates_changed_callback(GtkWidget *range);
67
68/**********************************************************************/
71static void rates_set_values(int tax, int no_tax_scroll,
72 int lux, int no_lux_scroll,
73 int sci, int no_sci_scroll)
74{
75 char buf[64];
76 int tax_lock, lux_lock, sci_lock;
77 int maxrate;
78
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));
82
83 if (NULL != client.conn.playing) {
84 maxrate = get_player_bonus(client.conn.playing, EFT_MAX_RATES);
85 } else {
86 maxrate = 100;
87 }
88
89 /* This's quite a simple-minded "double check".. */
90 tax = MIN(tax, maxrate);
91 lux = MIN(lux, maxrate);
92 sci = MIN(sci, maxrate);
93
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);
98 }
99 if (!sci_lock) {
100 sci = MIN(MAX(100 - tax - lux, 0), maxrate);
101 }
102 } else if (lux != rates_lux_value) {
103 if (!tax_lock) {
104 tax = MIN(MAX(100 - lux - sci, 0), maxrate);
105 }
106 if (!sci_lock) {
107 sci = MIN(MAX(100 - lux - tax, 0), maxrate);
108 }
109 } else if (sci != rates_sci_value) {
110 if (!lux_lock) {
111 lux = MIN(MAX(100 - tax - sci, 0), maxrate);
112 }
113 if (!tax_lock) {
114 tax = MIN(MAX(100 - lux - sci, 0), maxrate);
115 }
116 }
117
118 if (tax + sci + lux != 100) {
119 tax = rates_tax_value;
120 lux = rates_lux_value;
121 sci = rates_sci_value;
122
123 rates_tax_value = -1;
124 rates_lux_value = -1;
125 rates_sci_value = -1;
126
127 no_tax_scroll = 0;
128 no_lux_scroll = 0;
129 no_sci_scroll = 0;
130 }
131 }
132
133 if (tax != rates_tax_value) {
134 fc_snprintf(buf, sizeof(buf), "%3d%%", tax);
135
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);
138 }
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);
143 }
144 rates_tax_value = tax;
145 }
146
147 if (lux != rates_lux_value) {
148 fc_snprintf(buf, sizeof(buf), "%3d%%", lux);
149
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);
152 }
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);
157 }
158 rates_lux_value = lux;
159 }
160
161 if (sci != rates_sci_value) {
162 fc_snprintf(buf, sizeof(buf), "%3d%%", sci);
163
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);
166 }
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);
171 }
172 rates_sci_value = sci;
173 }
174}
175
176/**********************************************************************/
179static void rates_changed_callback(GtkWidget *range)
180{
181 int percent = gtk_range_get_value(GTK_RANGE(range));
182
183 if (range == rates_tax_scale) {
184 int tax_value;
185
186 tax_value = 10 * percent;
187 tax_value = MIN(tax_value, 100);
189 } else if (range == rates_lux_scale) {
190 int lux_value;
191
192 lux_value = 10 * percent;
193 lux_value = MIN(lux_value, 100);
195 } else {
196 int sci_value;
197
198 sci_value = 10 * percent;
199 sci_value = MIN(sci_value, 100);
201 }
202}
203
204/**********************************************************************/
207static void rates_command_callback(GtkWidget *w, gint response_id)
208{
209 if (response_id == GTK_RESPONSE_OK) {
212 }
213 gtk_widget_destroy(rates_dialog_shell);
214}
215
216/**********************************************************************/
219static int mult_to_scale(const struct multiplier *pmul, int val)
220{
221 return (val - pmul->start) / pmul->step;
222}
223
224/**********************************************************************/
227static int scale_to_mult(const struct multiplier *pmul, int scale)
228{
229 return scale * pmul->step + pmul->start;
230}
231
232/**********************************************************************/
235static gchar *multiplier_value_callback(GtkScale *scale, gdouble value,
236 void *udata)
237{
238 const struct multiplier *pmul = udata;
239
240 return g_strdup_printf("%d", scale_to_mult(pmul, value));
241}
242
243/**********************************************************************/
246static void multipliers_command_callback(GtkWidget *w, gint response_id)
247{
248 struct packet_player_multiplier mul;
249
250 if (response_id == GTK_RESPONSE_OK && can_client_issue_orders()) {
253 int value = gtk_range_get_value(GTK_RANGE(multipliers_scale[i]));
254
255 mul.multipliers[i] = scale_to_mult(m, value);
257 mul.count = multiplier_count();
259 }
260 gtk_widget_destroy(multiplier_dialog_shell);
261}
262
263/**********************************************************************/
266static void multiplier_dialog_update_values(bool set_positions)
267{
268 multipliers_iterate(pmul) {
270 int val = player_multiplier_value(client_player(), pmul);
271 int target = player_multiplier_target_value(client_player(), pmul);
272
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);
276
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:Now"));
282
283 if (set_positions) {
284 gtk_range_set_value(GTK_RANGE(multipliers_scale[multiplier]),
285 mult_to_scale(pmul, target));
286 }
288}
289
290/**********************************************************************/
294{
296 return;
297 }
298
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. */
303}
304
305/**********************************************************************/
308static GtkWidget *create_multiplier_dialog(void)
309{
310 GtkWidget *shell, *content;
311 GtkWidget *label, *scale;
312
314 shell = gtk_dialog_new_with_buttons(_("Change policies"),
315 NULL,
316 0,
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,
325 0,
326 GTK_STOCK_CLOSE,
327 GTK_RESPONSE_CLOSE,
328 NULL);
329 }
331
332 gtk_window_set_position(GTK_WINDOW(shell), GTK_WIN_POS_MOUSE);
333 content = gtk_dialog_get_content_area(GTK_DIALOG(shell));
334
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);
338 }
339
340 multipliers_iterate(pmul) {
342 int mscale;
343
345 label = gtk_label_new(multiplier_name_translation(pmul));
346 /* Map each multiplier step to a single step on the UI, to enforce
347 * the step size. */
348 scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,
349 mult_to_scale(pmul, pmul->start),
350 mult_to_scale(pmul, pmul->stop), 1);
352 mscale = mult_to_scale(pmul, pmul->stop) / 10;
353 gtk_range_set_increments(GTK_RANGE(multipliers_scale[multiplier]),
354 1, MAX(2, mscale));
355 g_signal_connect(multipliers_scale[multiplier], "format-value",
356 G_CALLBACK(multiplier_value_callback), pmul);
357 g_signal_connect(multipliers_scale[multiplier], "destroy",
358 G_CALLBACK(gtk_widget_destroyed),
360 gtk_box_pack_start( GTK_BOX( content ), label, TRUE, TRUE, 5 );
361 gtk_box_pack_start( GTK_BOX( content ), scale, TRUE, TRUE, 5 );
362 gtk_widget_set_sensitive(multipliers_scale[multiplier],
366
368
369 g_signal_connect(shell, "destroy",
370 G_CALLBACK(gtk_widget_destroyed), &multiplier_dialog_shell);
371
372 g_signal_connect(shell, "response",
373 G_CALLBACK(multipliers_command_callback), NULL);
374
375 gtk_widget_show_all(content);
376
377 return shell;
378}
379
380/**********************************************************************/
384{
387 }
388
390 return;
391 }
392
393 gtk_window_present(GTK_WINDOW(multiplier_dialog_shell));
394}
395
396/**********************************************************************/
399static GtkWidget *create_rates_dialog(void)
400{
401 GtkWidget *shell, *content;
402 GtkWidget *frame, *hgrid;
403 int i;
404
406 return NULL;
407 }
408
409 shell = gtk_dialog_new_with_buttons(_("Select tax, luxury and science rates"),
410 NULL,
411 0,
412 GTK_STOCK_CANCEL,
413 GTK_RESPONSE_CANCEL,
414 GTK_STOCK_OK,
415 GTK_RESPONSE_OK,
416 NULL);
418 gtk_dialog_set_default_response(GTK_DIALOG(shell), GTK_RESPONSE_OK);
419 gtk_window_set_position(GTK_WINDOW(shell), GTK_WIN_POS_MOUSE);
420 content = gtk_dialog_get_content_area(GTK_DIALOG(shell));
421
422 rates_gov_label = gtk_label_new("");
423 gtk_box_pack_start( GTK_BOX( content ), rates_gov_label, TRUE, TRUE, 5 );
424
425 frame = gtk_frame_new( _("Tax") );
426 gtk_box_pack_start( GTK_BOX( content ), frame, TRUE, TRUE, 5 );
427
428 hgrid = gtk_grid_new();
429 gtk_grid_set_column_spacing(GTK_GRID(hgrid), 10);
430 gtk_container_add(GTK_CONTAINER(frame), hgrid);
431
433 gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 10, 1);
434 gtk_range_set_increments(GTK_RANGE(rates_tax_scale), 1, 1);
435 for (i = 0; i <= 10; i++) {
436 gtk_scale_add_mark(GTK_SCALE(rates_tax_scale), i, GTK_POS_TOP, NULL);
437 }
438 gtk_widget_set_size_request(rates_tax_scale, 300, 40);
439 gtk_scale_set_digits(GTK_SCALE(rates_tax_scale), 0);
440 gtk_scale_set_draw_value(GTK_SCALE(rates_tax_scale), FALSE);
441 gtk_container_add(GTK_CONTAINER(hgrid), rates_tax_scale);
442
443 rates_tax_label = gtk_label_new(" 0%");
444 gtk_container_add(GTK_CONTAINER(hgrid), rates_tax_label);
445 gtk_widget_set_size_request(rates_tax_label, 40, -1);
446
447 rates_tax_toggle = gtk_check_button_new_with_label( _("Lock") );
448 gtk_container_add(GTK_CONTAINER(hgrid), rates_tax_toggle);
449
450 frame = gtk_frame_new( _("Luxury") );
451 gtk_box_pack_start( GTK_BOX( content ), frame, TRUE, TRUE, 5 );
452
453 hgrid = gtk_grid_new();
454 gtk_grid_set_column_spacing(GTK_GRID(hgrid), 10);
455 gtk_container_add(GTK_CONTAINER(frame), hgrid);
456
458 gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 10, 1);
459 gtk_range_set_increments(GTK_RANGE(rates_lux_scale), 1, 1);
460 for (i = 0; i <= 10; i++) {
461 gtk_scale_add_mark(GTK_SCALE(rates_lux_scale), i, GTK_POS_TOP, NULL);
462 }
463 gtk_widget_set_size_request(rates_lux_scale, 300, 40);
464 gtk_scale_set_digits(GTK_SCALE(rates_lux_scale), 0);
465 gtk_scale_set_draw_value(GTK_SCALE(rates_lux_scale), FALSE);
466 gtk_container_add(GTK_CONTAINER(hgrid), rates_lux_scale);
467
468 rates_lux_label = gtk_label_new(" 0%");
469 gtk_container_add(GTK_CONTAINER(hgrid), rates_lux_label);
470 gtk_widget_set_size_request(rates_lux_label, 40, -1);
471
472 rates_lux_toggle = gtk_check_button_new_with_label( _("Lock") );
473 gtk_container_add(GTK_CONTAINER(hgrid), rates_lux_toggle);
474
475 frame = gtk_frame_new( _("Science") );
476 gtk_box_pack_start( GTK_BOX( content ), frame, TRUE, TRUE, 5 );
477
478 hgrid = gtk_grid_new();
479 gtk_grid_set_column_spacing(GTK_GRID(hgrid), 10);
480 gtk_container_add(GTK_CONTAINER(frame), hgrid);
481
483 gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 10, 1);
484 gtk_range_set_increments(GTK_RANGE(rates_sci_scale), 1, 1);
485 for (i = 0; i <= 10; i++) {
486 gtk_scale_add_mark(GTK_SCALE(rates_sci_scale), i, GTK_POS_TOP, NULL);
487 }
488 gtk_widget_set_size_request(rates_sci_scale, 300, 40);
489 gtk_scale_set_digits(GTK_SCALE(rates_sci_scale), 0);
490 gtk_scale_set_draw_value(GTK_SCALE(rates_sci_scale), FALSE);
491 gtk_container_add(GTK_CONTAINER(hgrid), rates_sci_scale);
492
493 rates_sci_label = gtk_label_new(" 0%");
494 gtk_container_add(GTK_CONTAINER(hgrid), rates_sci_label);
495 gtk_widget_set_size_request(rates_sci_label, 40, -1);
496
497 rates_sci_toggle = gtk_check_button_new_with_label( _("Lock") );
498 gtk_container_add(GTK_CONTAINER(hgrid), rates_sci_toggle);
499
500
501 g_signal_connect(shell, "response",
502 G_CALLBACK(rates_command_callback), NULL);
503 g_signal_connect(shell, "destroy",
504 G_CALLBACK(gtk_widget_destroyed), &rates_dialog_shell);
505
506 gtk_widget_show_all(shell);
507
511
513 g_signal_connect_after(rates_tax_scale, "value-changed",
514 G_CALLBACK(rates_changed_callback), NULL);
515
517 g_signal_connect_after(rates_lux_scale, "value-changed",
518 G_CALLBACK(rates_changed_callback), NULL);
519
521 g_signal_connect_after(rates_sci_scale, "value-changed",
522 G_CALLBACK(rates_changed_callback), NULL);
523
527 return shell;
528}
529
530/**********************************************************************/
534{
536 return;
537 }
538
539 if (!rates_dialog_shell) {
541 }
542 if (!rates_dialog_shell) {
543 return;
544 }
545
546 gchar *buf = g_strdup_printf(_("%s max rate: %d%%"),
548 get_player_bonus(client.conn.playing, EFT_MAX_RATES));
549
550 gtk_label_set_text(GTK_LABEL(rates_gov_label), buf);
551 g_free(buf);
552 gtk_range_set_fill_level(GTK_RANGE(rates_tax_scale),
554 EFT_MAX_RATES)/10);
555 gtk_range_set_fill_level(GTK_RANGE(rates_lux_scale),
557 EFT_MAX_RATES)/10);
558 gtk_range_set_fill_level(GTK_RANGE(rates_sci_scale),
560 EFT_MAX_RATES)/10);
561
562 gtk_window_present(GTK_WINDOW(rates_dialog_shell));
563}
struct civclient client
bool can_client_issue_orders(void)
#define client_player()
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:771
#define MAX_NUM_MULTIPLIERS
Definition fc_types.h:55
int Multiplier_type_id
Definition fc_types.h:356
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
const char * government_name_for_player(const struct player *pplayer)
Definition government.c:153
static void multipliers_command_callback(GtkWidget *w, gint response_id)
Definition gamedlgs.c:246
static gulong rates_sci_sig
Definition gamedlgs.c:61
static GtkWidget * rates_tax_scale
Definition gamedlgs.c:56
static gulong rates_tax_sig
Definition gamedlgs.c:61
static GtkWidget * rates_tax_toggle
Definition gamedlgs.c:54
static int rates_lux_value
Definition gamedlgs.c:64
static GtkWidget * multiplier_dialog_shell
Definition gamedlgs.c:58
static GtkWidget * rates_gov_label
Definition gamedlgs.c:53
static int rates_sci_value
Definition gamedlgs.c:64
static GtkWidget * rates_sci_label
Definition gamedlgs.c:55
static void rates_changed_callback(GtkWidget *range)
Definition gamedlgs.c:179
static GtkWidget * create_rates_dialog(void)
Definition gamedlgs.c:399
static GtkWidget * rates_sci_scale
Definition gamedlgs.c:56
static GtkWidget * rates_lux_scale
Definition gamedlgs.c:56
static GtkWidget * create_multiplier_dialog(void)
Definition gamedlgs.c:308
static gulong rates_lux_sig
Definition gamedlgs.c:61
void popup_multiplier_dialog(void)
Definition gamedlgs.c:383
static GtkWidget * rates_lux_label
Definition gamedlgs.c:55
static GtkWidget * rates_lux_toggle
Definition gamedlgs.c:54
void popup_rates_dialog(void)
Definition gamedlgs.c:533
static void rates_command_callback(GtkWidget *w, gint response_id)
Definition gamedlgs.c:207
static void rates_set_values(int tax, int no_tax_scroll, int lux, int no_lux_scroll, int sci, int no_sci_scroll)
Definition gamedlgs.c:71
static GtkWidget * rates_tax_label
Definition gamedlgs.c:55
static int rates_tax_value
Definition gamedlgs.c:64
void real_multipliers_dialog_update(void *unused)
Definition gamedlgs.c:293
static int scale_to_mult(const struct multiplier *pmul, int scale)
Definition gamedlgs.c:227
static int mult_to_scale(const struct multiplier *pmul, int val)
Definition gamedlgs.c:219
static GtkWidget * rates_sci_toggle
Definition gamedlgs.c:54
static gchar * multiplier_value_callback(GtkScale *scale, gdouble value, void *udata)
Definition gamedlgs.c:235
static GtkWidget * multipliers_scale[MAX_NUM_MULTIPLIERS]
Definition gamedlgs.c:59
static void multiplier_dialog_update_values(bool set_positions)
Definition gamedlgs.c:266
static GtkWidget * rates_dialog_shell
Definition gamedlgs.c:52
GtkWidget * toplevel
Definition gui_main.c:124
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:281
static struct gui_dialog * shell
Definition messagedlg.c:39
#define fc_assert(condition)
Definition log.h:176
Multiplier_type_id multiplier_count(void)
Definition multipliers.c:88
const char * multiplier_name_translation(const struct multiplier *pmul)
Definition multipliers.c:97
bool multiplier_can_be_changed(struct multiplier *pmul, struct player *pplayer)
Multiplier_type_id multiplier_index(const struct multiplier *pmul)
Definition multipliers.c:80
#define multipliers_iterate(_mul_)
Definition multipliers.h:61
#define multipliers_iterate_end
Definition multipliers.h:67
int dsend_packet_player_rates(struct connection *pc, int tax, int luxury, int science)
int send_packet_player_multiplier(struct connection *pc, const struct packet_player_multiplier *packet)
int player_multiplier_target_value(const struct player *pplayer, const struct multiplier *pmul)
Definition player.c:1945
int player_multiplier_value(const struct player *pplayer, const struct multiplier *pmul)
Definition player.c:1922
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define MAX(x, y)
Definition shared.h:54
struct connection conn
Definition client_main.h:96
struct player * playing
Definition connection.h:156
int multipliers[MAX_NUM_MULTIPLIERS]
struct player_economic economic
Definition player.h:284
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47