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)
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 ***********************************************************************/
15 #include <fc_config.h>
23 #include <gdk/gdkkeysyms.h>
28 #include "string_vector.h"
34 #include "government.h"
35 #include "multipliers.h"
40 #include "client_main.h"
43 /* client/gui-gtk-2.0 */
48 #include "gui_stuff.h"
53 /******************************************************************/
54 static GtkWidget
*rates_dialog_shell
;
55 static GtkWidget
*rates_gov_label
;
56 static GtkWidget
*rates_tax_toggle
, *rates_lux_toggle
, *rates_sci_toggle
;
57 static GtkWidget
*rates_tax_label
, *rates_lux_label
, *rates_sci_label
;
58 static GtkObject
*rates_tax_adj
, *rates_lux_adj
, *rates_sci_adj
;
60 static GtkWidget
*multiplier_dialog_shell
;
61 static GtkWidget
*multipliers_scale
[MAX_NUM_MULTIPLIERS
];
63 static gulong rates_tax_sig
, rates_lux_sig
, rates_sci_sig
;
64 /******************************************************************/
66 static int rates_tax_value
, rates_lux_value
, rates_sci_value
;
68 static void rates_changed_callback(GtkAdjustment
*adj
);
70 /**************************************************************************
71 Set tax values to display
72 **************************************************************************/
73 static void rates_set_values(int tax
, int no_tax_scroll
,
74 int lux
, int no_lux_scroll
,
75 int sci
, int no_sci_scroll
)
78 int tax_lock
, lux_lock
, sci_lock
;
81 tax_lock
= GTK_TOGGLE_BUTTON(rates_tax_toggle
)->active
;
82 lux_lock
= GTK_TOGGLE_BUTTON(rates_lux_toggle
)->active
;
83 sci_lock
= GTK_TOGGLE_BUTTON(rates_sci_toggle
)->active
;
85 if (NULL
!= client
.conn
.playing
) {
86 maxrate
= get_player_bonus(client
.conn
.playing
, EFT_MAX_RATES
);
90 /* This's quite a simple-minded "double check".. */
91 tax
=MIN(tax
, maxrate
);
92 lux
=MIN(lux
, maxrate
);
93 sci
=MIN(sci
, maxrate
);
97 if((tax
!=rates_tax_value
))
100 lux
=MIN(MAX(100-tax
-sci
, 0), maxrate
);
102 sci
=MIN(MAX(100-tax
-lux
, 0), maxrate
);
104 else if((lux
!=rates_lux_value
))
107 tax
=MIN(MAX(100-lux
-sci
, 0), maxrate
);
109 sci
=MIN(MAX(100-lux
-tax
, 0), maxrate
);
111 else if((sci
!=rates_sci_value
))
114 lux
=MIN(MAX(100-tax
-sci
, 0), maxrate
);
116 tax
=MIN(MAX(100-lux
-sci
, 0), maxrate
);
119 if(tax
+sci
+lux
!=100) {
135 if (tax
!=rates_tax_value
) {
136 fc_snprintf(buf
, sizeof(buf
), "%3d%%", tax
);
137 if (strcmp(buf
, GTK_LABEL(rates_tax_label
)->label
) != 0)
138 gtk_label_set_text(GTK_LABEL(rates_tax_label
), buf
);
141 g_signal_handler_block(rates_tax_adj
, rates_tax_sig
);
142 gtk_adjustment_set_value(GTK_ADJUSTMENT(rates_tax_adj
), tax
/10 );
143 g_signal_handler_unblock(rates_tax_adj
, rates_tax_sig
);
148 if(lux
!=rates_lux_value
) {
149 fc_snprintf(buf
, sizeof(buf
), "%3d%%", lux
);
150 if (strcmp(buf
, GTK_LABEL(rates_lux_label
)->label
) != 0)
151 gtk_label_set_text(GTK_LABEL(rates_lux_label
), buf
);
154 g_signal_handler_block(rates_lux_adj
, rates_lux_sig
);
155 gtk_adjustment_set_value(GTK_ADJUSTMENT(rates_lux_adj
), lux
/10 );
156 g_signal_handler_unblock(rates_lux_adj
, rates_lux_sig
);
161 if(sci
!=rates_sci_value
) {
162 fc_snprintf(buf
, sizeof(buf
), "%3d%%", sci
);
163 if (strcmp(buf
, GTK_LABEL(rates_sci_label
)->label
) != 0)
164 gtk_label_set_text(GTK_LABEL(rates_sci_label
),buf
);
167 g_signal_handler_block(rates_sci_adj
, rates_sci_sig
);
168 gtk_adjustment_set_value(GTK_ADJUSTMENT(rates_sci_adj
), sci
/10 );
169 g_signal_handler_unblock(rates_sci_adj
, rates_sci_sig
);
176 /**************************************************************************
178 **************************************************************************/
179 static void rates_changed_callback(GtkAdjustment
*adj
)
181 int percent
=adj
->value
;
183 if(adj
==GTK_ADJUSTMENT(rates_tax_adj
)) {
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);
190 else if(adj
==GTK_ADJUSTMENT(rates_lux_adj
)) {
193 lux_value
=10*percent
;
194 lux_value
=MIN(lux_value
, 100);
195 rates_set_values(rates_tax_value
,0, lux_value
,1, rates_sci_value
,0);
200 sci_value
=10*percent
;
201 sci_value
=MIN(sci_value
, 100);
202 rates_set_values(rates_tax_value
,0, rates_lux_value
,0, sci_value
,1);
207 /**************************************************************************
208 User has responded to rates dialog
209 **************************************************************************/
210 static void rates_command_callback(GtkWidget
*w
, gint response_id
)
212 if (response_id
== GTK_RESPONSE_OK
) {
213 dsend_packet_player_rates(&client
.conn
, rates_tax_value
, rates_lux_value
,
216 gtk_widget_destroy(rates_dialog_shell
);
219 /**************************************************************************
220 Convert real multiplier display value to scale value
221 **************************************************************************/
222 static int mult_to_scale(const struct multiplier
*pmul
, int val
)
224 return (val
- pmul
->start
) / pmul
->step
;
227 /**************************************************************************
228 Convert scale units to real multiplier display value
229 **************************************************************************/
230 static int scale_to_mult(const struct multiplier
*pmul
, int scale
)
232 return scale
* pmul
->step
+ pmul
->start
;
235 /**************************************************************************
236 Format value for multiplier scales
237 **************************************************************************/
238 static gchar
*multiplier_value_callback(GtkScale
*scale
, gdouble value
,
241 const struct multiplier
*pmul
= udata
;
243 return g_strdup_printf("%d", scale_to_mult(pmul
, value
));
246 /**************************************************************************
247 User has responded to multipliers dialog
248 **************************************************************************/
249 static void multipliers_command_callback(GtkWidget
*w
, gint response_id
)
251 struct packet_player_multiplier mul
;
253 if (response_id
== GTK_RESPONSE_OK
&& can_client_issue_orders()) {
254 multipliers_iterate(m
) {
255 Multiplier_type_id i
= multiplier_index(m
);
256 int value
= gtk_range_get_value(GTK_RANGE(multipliers_scale
[i
]));
258 mul
.multipliers
[i
] = scale_to_mult(m
, value
);
259 } multipliers_iterate_end
;
260 mul
.count
= multiplier_count();
261 send_packet_player_multiplier(&client
.conn
, &mul
);
263 gtk_widget_destroy(multiplier_dialog_shell
);
266 /**************************************************************************
267 Update values in multipliers dialog
268 **************************************************************************/
269 static void multiplier_dialog_update_values(bool set_positions
)
271 multipliers_iterate(pmul
) {
272 Multiplier_type_id multiplier
= multiplier_index(pmul
);
273 int val
= player_multiplier_value(client_player(), pmul
);
274 int target
= player_multiplier_target_value(client_player(), pmul
);
276 fc_assert(multiplier
< ARRAY_SIZE(multipliers_scale
));
277 fc_assert(scale_to_mult(pmul
, mult_to_scale(pmul
, val
)) == val
);
278 fc_assert(scale_to_mult(pmul
, mult_to_scale(pmul
, target
)) == target
);
280 /* XXX: if building against ancient Gtk, manage without this bit of UI. */
281 #if GTK_CHECK_VERSION(2,16,0)
282 gtk_scale_clear_marks(GTK_SCALE(multipliers_scale
[multiplier
]));
283 gtk_scale_add_mark(GTK_SCALE(multipliers_scale
[multiplier
]),
284 mult_to_scale(pmul
, val
), GTK_POS_BOTTOM
,
285 /* TRANS: current value of policy in force */
286 Q_("?multiplier:Cur"));
290 gtk_range_set_value(GTK_RANGE(multipliers_scale
[multiplier
]),
291 mult_to_scale(pmul
, target
));
293 } multipliers_iterate_end
;
296 /**************************************************************************
297 Callback when server indicates multiplier values have changed
298 **************************************************************************/
299 void real_multipliers_dialog_update(void)
301 if (!multiplier_dialog_shell
) {
305 /* If dialog belongs to a player rather than an observer, we don't
306 * want to lose any local changes made by the player.
307 * This dialog should be the only way the values can change, anyway. */
308 multiplier_dialog_update_values(!can_client_issue_orders());
311 /****************************************************************
312 Create multipliers dialog
313 ****************************************************************/
314 static GtkWidget
*create_multiplier_dialog(void)
316 GtkWidget
*shell
, *content
;
317 GtkWidget
*label
, *scale
;
319 if (can_client_issue_orders()) {
320 shell
= gtk_dialog_new_with_buttons(_("Change policies"),
329 shell
= gtk_dialog_new_with_buttons(_("Policies"),
336 setup_dialog(shell
, toplevel
);
338 gtk_window_set_position(GTK_WINDOW(shell
), GTK_WIN_POS_MOUSE
);
339 content
= gtk_dialog_get_content_area(GTK_DIALOG(shell
));
341 if (can_client_issue_orders()) {
342 label
= gtk_label_new(_("Changes will not take effect until next turn."));
343 gtk_box_pack_start( GTK_BOX( content
), label
, FALSE
, FALSE
, 0);
346 multipliers_iterate(pmul
) {
347 Multiplier_type_id multiplier
= multiplier_index(pmul
);
349 fc_assert(multiplier
< ARRAY_SIZE(multipliers_scale
));
350 label
= gtk_label_new(multiplier_name_translation(pmul
));
351 /* Map each multiplier step to a single step on the UI, to enforce
353 scale
= gtk_hscale_new_with_range(mult_to_scale(pmul
, pmul
->start
),
354 mult_to_scale(pmul
, pmul
->stop
), 1);
355 multipliers_scale
[multiplier
] = scale
;
356 gtk_range_set_increments(GTK_RANGE(multipliers_scale
[multiplier
]),
357 1, MAX(2, mult_to_scale(pmul
, pmul
->stop
) / 10));
358 g_signal_connect(multipliers_scale
[multiplier
], "format-value",
359 G_CALLBACK(multiplier_value_callback
), pmul
);
360 g_signal_connect(multipliers_scale
[multiplier
], "destroy",
361 G_CALLBACK(gtk_widget_destroyed
),
362 &multipliers_scale
[multiplier
]);
363 gtk_box_pack_start( GTK_BOX( content
), label
, TRUE
, TRUE
, 5 );
364 gtk_box_pack_start( GTK_BOX( content
), scale
, TRUE
, TRUE
, 5 );
365 gtk_widget_set_sensitive(multipliers_scale
[multiplier
],
366 can_client_issue_orders());
367 } multipliers_iterate_end
;
369 multiplier_dialog_update_values(TRUE
);
371 g_signal_connect(shell
, "destroy",
372 G_CALLBACK(gtk_widget_destroyed
), &multiplier_dialog_shell
);
374 g_signal_connect(shell
, "response",
375 G_CALLBACK(multipliers_command_callback
), NULL
);
377 gtk_widget_show_all(content
);
382 /****************************************************************
383 Popup multipliers dialog
384 *****************************************************************/
385 void popup_multiplier_dialog(void)
387 if (!multiplier_dialog_shell
) {
388 multiplier_dialog_shell
= create_multiplier_dialog();
391 if (!multiplier_dialog_shell
) {
395 gtk_window_present(GTK_WINDOW(multiplier_dialog_shell
));
398 /****************************************************************
400 *****************************************************************/
401 static GtkWidget
*create_rates_dialog(void)
404 GtkWidget
*frame
, *hbox
;
408 if (!can_client_issue_orders()) {
412 shell
= gtk_dialog_new_with_buttons(_("Select tax, luxury and science rates"),
420 setup_dialog(shell
, toplevel
);
421 gtk_dialog_set_default_response(GTK_DIALOG(shell
), GTK_RESPONSE_OK
);
422 gtk_window_set_position(GTK_WINDOW(shell
), GTK_WIN_POS_MOUSE
);
424 rates_gov_label
= gtk_label_new("");
425 gtk_box_pack_start( GTK_BOX( GTK_DIALOG( shell
)->vbox
), rates_gov_label
, TRUE
, TRUE
, 5 );
427 frame
= gtk_frame_new( _("Tax") );
428 gtk_box_pack_start( GTK_BOX( GTK_DIALOG( shell
)->vbox
), frame
, TRUE
, TRUE
, 5 );
430 hbox
= gtk_hbox_new( FALSE
, 10 );
431 gtk_container_add( GTK_CONTAINER( frame
), hbox
);
433 rates_tax_adj
= gtk_adjustment_new( 0.0, 0.0, 11.0, 1.0, 1.0, 1.0 );
434 scale
= gtk_hscale_new( GTK_ADJUSTMENT( rates_tax_adj
) );
435 gtk_widget_set_size_request(scale
, 300, 40);
436 gtk_scale_set_digits( GTK_SCALE( scale
), 0 );
437 gtk_scale_set_draw_value( GTK_SCALE( scale
), FALSE
);
438 gtk_box_pack_start( GTK_BOX( hbox
), scale
, TRUE
, TRUE
, 0 );
440 rates_tax_label
= gtk_label_new(" 0%");
441 gtk_box_pack_start( GTK_BOX( hbox
), rates_tax_label
, TRUE
, TRUE
, 0 );
442 gtk_widget_set_size_request(rates_tax_label
, 40, -1);
444 rates_tax_toggle
= gtk_check_button_new_with_label( _("Lock") );
445 gtk_box_pack_start( GTK_BOX( hbox
), rates_tax_toggle
, TRUE
, TRUE
, 0 );
447 frame
= gtk_frame_new( _("Luxury") );
448 gtk_box_pack_start( GTK_BOX( GTK_DIALOG( shell
)->vbox
), frame
, TRUE
, TRUE
, 5 );
450 hbox
= gtk_hbox_new( FALSE
, 10 );
451 gtk_container_add( GTK_CONTAINER( frame
), hbox
);
453 rates_lux_adj
= gtk_adjustment_new( 0.0, 0.0, 11.0, 1.0, 1.0, 1.0 );
454 scale
= gtk_hscale_new( GTK_ADJUSTMENT( rates_lux_adj
) );
455 gtk_widget_set_size_request(scale
, 300, 40);
456 gtk_scale_set_digits( GTK_SCALE( scale
), 0 );
457 gtk_scale_set_draw_value( GTK_SCALE( scale
), FALSE
);
458 gtk_box_pack_start( GTK_BOX( hbox
), scale
, TRUE
, TRUE
, 0 );
460 rates_lux_label
= gtk_label_new(" 0%");
461 gtk_box_pack_start( GTK_BOX( hbox
), rates_lux_label
, TRUE
, TRUE
, 0 );
462 gtk_widget_set_size_request(rates_lux_label
, 40, -1);
464 rates_lux_toggle
= gtk_check_button_new_with_label( _("Lock") );
465 gtk_box_pack_start( GTK_BOX( hbox
), rates_lux_toggle
, TRUE
, TRUE
, 0 );
467 frame
= gtk_frame_new( _("Science") );
468 gtk_box_pack_start( GTK_BOX( GTK_DIALOG( shell
)->vbox
), frame
, TRUE
, TRUE
, 5 );
470 hbox
= gtk_hbox_new( FALSE
, 10 );
471 gtk_container_add( GTK_CONTAINER( frame
), hbox
);
473 rates_sci_adj
= gtk_adjustment_new( 0.0, 0.0, 11.0, 1.0, 1.0, 1.0 );
474 scale
= gtk_hscale_new( GTK_ADJUSTMENT( rates_sci_adj
) );
475 gtk_widget_set_size_request(scale
, 300, 40);
476 gtk_scale_set_digits( GTK_SCALE( scale
), 0 );
477 gtk_scale_set_draw_value( GTK_SCALE( scale
), FALSE
);
478 gtk_box_pack_start( GTK_BOX( hbox
), scale
, TRUE
, TRUE
, 0 );
480 rates_sci_label
= gtk_label_new(" 0%");
481 gtk_box_pack_start( GTK_BOX( hbox
), rates_sci_label
, TRUE
, TRUE
, 0 );
482 gtk_widget_set_size_request(rates_sci_label
, 40, -1);
484 rates_sci_toggle
= gtk_check_button_new_with_label( _("Lock") );
485 gtk_box_pack_start( GTK_BOX( hbox
), rates_sci_toggle
, TRUE
, TRUE
, 0 );
488 g_signal_connect(shell
, "response",
489 G_CALLBACK(rates_command_callback
), NULL
);
490 g_signal_connect(shell
, "destroy",
491 G_CALLBACK(gtk_widget_destroyed
), &rates_dialog_shell
);
493 gtk_widget_show_all( GTK_DIALOG( shell
)->vbox
);
494 gtk_widget_show_all( GTK_DIALOG( shell
)->action_area
);
501 g_signal_connect_after(rates_tax_adj
, "value_changed",
502 G_CALLBACK(rates_changed_callback
), NULL
);
505 g_signal_connect_after(rates_lux_adj
, "value_changed",
506 G_CALLBACK(rates_changed_callback
), NULL
);
509 g_signal_connect_after(rates_sci_adj
, "value_changed",
510 G_CALLBACK(rates_changed_callback
), NULL
);
512 rates_set_values(client
.conn
.playing
->economic
.tax
, 0,
513 client
.conn
.playing
->economic
.luxury
, 0,
514 client
.conn
.playing
->economic
.science
, 0);
519 /****************************************************************
521 *****************************************************************/
522 void popup_rates_dialog(void)
524 if (!can_client_issue_orders()) {
528 if (!rates_dialog_shell
) {
529 rates_dialog_shell
= create_rates_dialog();
531 if (!rates_dialog_shell
) {
535 gchar
*buf
= g_strdup_printf(_("%s max rate: %d%%"),
536 government_name_for_player(client
.conn
.playing
),
537 get_player_bonus(client
.conn
.playing
, EFT_MAX_RATES
));
538 gtk_label_set_text(GTK_LABEL(rates_gov_label
), buf
);
541 gtk_window_present(GTK_WINDOW(rates_dialog_shell
));