Freeciv-3.1
Loading...
Searching...
No Matches
cma_fe.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2001 - R. Falke, M. Kaufman
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 <gdk/gdkkeysyms.h>
19
20/* utility */
21#include "fcintl.h"
22#include "log.h"
23#include "mem.h"
24#include "support.h"
25
26/* common */
27#include "events.h"
28#include "game.h"
29
30/* client */
31#include "chatline_g.h"
32#include "citydlg_g.h"
33#include "client_main.h"
34#include "cma_fec.h"
35#include "messagewin_g.h"
36#include "options.h"
37
38/* client/gui-gtk-3.0 */
39#include "cityrep.h"
40#include "dialogs.h"
41#include "gui_main.h"
42#include "gui_stuff.h"
43#include "helpdlg.h"
44#include "inputdlg.h"
45
46#include "cma_fe.h"
47
48#define BUFFER_SIZE 64
49
50#define SPECLIST_TAG dialog
51#define SPECLIST_TYPE struct cma_dialog
52#include "speclist.h"
53
54#define dialog_list_iterate(dialoglist, pdialog) \
55 TYPED_LIST_ITERATE(struct cma_dialog, dialoglist, pdialog)
56#define dialog_list_iterate_end LIST_ITERATE_END
57
58static struct dialog_list *dialog_list;
59
60static int allow_refreshes = 1;
61
62static struct cma_dialog *get_cma_dialog(struct city *pcity);
63
64static void update_cma_preset_list(struct cma_dialog *pdialog);
65
66static gboolean cma_preset_key_pressed_callback(GtkWidget *w, GdkEventKey *ev,
67 gpointer data);
68static void cma_del_preset_callback(GtkWidget *w, gpointer data);
69static void cma_preset_remove(struct cma_dialog *pdialog, int preset_index);
70static void cma_preset_remove_response(GtkWidget *w, gint response,
71 gpointer data);
72
73static void cma_add_preset_callback(GtkWidget *w, gpointer data);
74static void cma_preset_add_popup_callback(gpointer data, gint response,
75 const char *input);
76
77static void cma_active_callback(GtkWidget *w, gpointer data);
78static void cma_activate_preset_callback(GtkTreeView *view, GtkTreePath *path,
79 GtkTreeViewColumn *col, gpointer data);
80
81static void hscale_changed(GtkWidget *get, gpointer data);
82static void set_hscales(const struct cm_parameter *const parameter,
83 struct cma_dialog *pdialog);
84
85/**********************************************************************/
88void cma_fe_init(void)
89{
90 dialog_list = dialog_list_new();
91}
92
93/**********************************************************************/
96void cma_fe_done(void)
97{
98 dialog_list_destroy(dialog_list);
99}
100
101/**********************************************************************/
105{
106 struct cma_dialog *pdialog = get_cma_dialog(pcity);
107
108 if (pdialog == NULL) {
109 /* A city which is being investigated doesn't contain cma dialog */
110 return;
111 }
112 gtk_widget_destroy(pdialog->shell);
113}
114
115/**********************************************************************/
118static void cma_dialog_destroy_callback(GtkWidget *w, gpointer data)
119{
120 struct cma_dialog *pdialog = (struct cma_dialog *) data;
121
122 dialog_list_remove(dialog_list, pdialog);
123 free(pdialog);
124}
125
126/**********************************************************************/
130{
132 if (pdialog->pcity == pcity) {
133 return pdialog;
134 }
136
137 return NULL;
138}
139
140/**********************************************************************/
143static gboolean button_press_callback(GtkTreeView *view, GdkEventButton *ev,
144 gpointer data)
145{
146 GtkTreePath *path;
147 GtkTreeViewColumn *column;
148
149 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(view),
150 ev->x, ev->y, &path, &column, NULL, NULL)) {
151 if (ev->type == GDK_BUTTON_PRESS) {
152 cma_activate_preset_callback(view, path, column, data);
153 } else if (ev->type == GDK_2BUTTON_PRESS) {
154 struct cma_dialog *pdialog = (struct cma_dialog *) data;
155 struct cm_parameter param;
156
157 cmafec_get_fe_parameter(pdialog->pcity, &param);
158 cma_put_city_under_agent(pdialog->pcity, &param);
159 refresh_city_dialog(pdialog->pcity);
160 }
161 }
162 gtk_tree_path_free(path);
163
164 return FALSE;
165}
166
167/**********************************************************************/
170static void help_callback(GtkWidget *w, gpointer data)
171{
173}
174
175/**********************************************************************/
178static void cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *cell,
179 GtkTreeModel *model, GtkTreeIter *it, gpointer data)
180{
181 struct cma_dialog *pdialog = (struct cma_dialog *) data;
182 gchararray s1;
183 const char *s2;
184 int i1, i2;
185 struct cm_parameter param;
186 GtkTreePath *path;
187
188 gtk_tree_model_get(model, it, 0, &s1, -1);
189 if (s1 == NULL) {
190 return;
191 }
192 path = gtk_tree_model_get_path(model, it);
193 i1 = gtk_tree_path_get_indices(path)[0];
194 gtk_tree_path_free(path);
195
196 cmafec_get_fe_parameter(pdialog->pcity, &param);
197 s2 = cmafec_get_short_descr(&param);
199
200 if (!strcmp(s1, s2) && i1 == i2) {
201 g_object_set(G_OBJECT(cell), "style", PANGO_STYLE_ITALIC,
202 "weight", PANGO_WEIGHT_BOLD, NULL);
203 } else {
204 g_object_set(G_OBJECT(cell), "style", PANGO_STYLE_NORMAL,
205 "weight", PANGO_WEIGHT_NORMAL, NULL);
206 }
207
208 g_free(s1);
209}
210
211/**********************************************************************/
214struct cma_dialog *create_cma_dialog(struct city *pcity, bool tiny)
215{
216 struct cma_dialog *pdialog;
217 struct cm_parameter param;
218 GtkWidget *frame, *page, *hbox, *label, *table;
219 GtkWidget *vbox, *sw, *hscale, *button, *image;
220 GtkListStore *store;
221 GtkCellRenderer *rend;
222 GtkWidget *view;
223 GtkTreeViewColumn *column;
224 gint layout_width;
225
226 cmafec_get_fe_parameter(pcity, &param);
227 pdialog = fc_malloc(sizeof(struct cma_dialog));
228 pdialog->pcity = pcity;
229 pdialog->shell = gtk_grid_new();
230 gtk_orientable_set_orientation(GTK_ORIENTABLE(pdialog->shell),
231 GTK_ORIENTATION_VERTICAL);
232 gtk_grid_set_row_spacing(GTK_GRID(pdialog->shell), 8);
233 gtk_container_set_border_width(GTK_CONTAINER(pdialog->shell), 8);
234 g_signal_connect(pdialog->shell, "destroy",
235 G_CALLBACK(cma_dialog_destroy_callback), pdialog);
236
237 page = gtk_grid_new();
238 gtk_grid_set_column_spacing(GTK_GRID(page), 12);
239 gtk_container_add(GTK_CONTAINER(pdialog->shell), page);
240
241 vbox = gtk_grid_new();
242 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
243 GTK_ORIENTATION_VERTICAL);
244 gtk_grid_set_row_spacing(GTK_GRID(pdialog->shell), 2);
245 gtk_container_add(GTK_CONTAINER(page), vbox);
246
247 sw = gtk_scrolled_window_new(NULL, NULL);
248 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
249 GTK_SHADOW_ETCHED_IN);
250 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
251 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
252
253 store = gtk_list_store_new(1, G_TYPE_STRING);
254 pdialog->store = store;
255
256 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
257 gtk_widget_set_hexpand(view, TRUE);
258 gtk_widget_set_vexpand(view, TRUE);
259 g_object_unref(store);
260 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
261 pdialog->preset_list = view;
262 pdialog->selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
263
264 g_signal_connect(pdialog->preset_list, "button_press_event",
265 G_CALLBACK(button_press_callback), pdialog);
266
267 gtk_widget_set_tooltip_text(view,
268 _("For information on\n"
269 "the citizen governor and governor presets,\n"
270 "including sample presets,\n"
271 "see README.governor."));
272
273 rend = gtk_cell_renderer_text_new();
274 column = gtk_tree_view_column_new_with_attributes(NULL, rend,
275 "text", 0, NULL);
276 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
277 gtk_tree_view_column_set_cell_data_func(column, rend, cell_data_func,
278 pdialog, NULL);
279
280 label = g_object_new(GTK_TYPE_LABEL,
281 "use-underline", TRUE,
282 "mnemonic-widget", view,
283 "label", _("Prese_ts:"),
284 "xalign", 0.0, "yalign", 0.5, NULL);
285 gtk_container_add(GTK_CONTAINER(vbox), label);
286
287 gtk_container_add(GTK_CONTAINER(sw), view);
288 gtk_container_add(GTK_CONTAINER(vbox), sw);
289
290 g_signal_connect(view, "row_activated",
291 G_CALLBACK(cma_activate_preset_callback), pdialog);
292 g_signal_connect(view, "key-press-event",
293 G_CALLBACK(cma_preset_key_pressed_callback), pdialog);
294
295 hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
296 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_EDGE);
297 gtk_container_add(GTK_CONTAINER(vbox), hbox);
298
299 button = gtk_button_new_with_mnemonic(_("Ne_w"));
300 image = gtk_image_new_from_stock(GTK_STOCK_NEW, GTK_ICON_SIZE_BUTTON);
301 gtk_button_set_image(GTK_BUTTON(button), image);
302 gtk_container_add(GTK_CONTAINER(hbox), button);
303 g_signal_connect(button, "clicked",
304 G_CALLBACK(cma_add_preset_callback), pdialog);
305 pdialog->add_preset_command = button;
306
307 pdialog->del_preset_command = gtk_button_new_from_stock(GTK_STOCK_DELETE);
308 gtk_container_add(GTK_CONTAINER(hbox), pdialog->del_preset_command);
309 g_signal_connect(pdialog->del_preset_command, "clicked",
310 G_CALLBACK(cma_del_preset_callback), pdialog);
311
312 /* the right-hand side */
313
314 vbox = gtk_grid_new();
315 g_object_set(vbox, "margin", 2, NULL);
316 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
317 GTK_ORIENTATION_VERTICAL);
318 gtk_container_add(GTK_CONTAINER(page), vbox);
319
320 /* Result */
321 if (!tiny) {
322 frame = gtk_frame_new(_("Results"));
323 gtk_widget_set_vexpand(frame, TRUE);
324 gtk_widget_set_valign(frame, GTK_ALIGN_CENTER);
325 gtk_container_add(GTK_CONTAINER(vbox), frame);
326
327 pdialog->result_label =
328 gtk_label_new("food\n prod\n trade\n\n people\n grow\n prod\n name");
329 gtk_widget_set_name(pdialog->result_label, "city_label");
330 gtk_container_add(GTK_CONTAINER(frame), pdialog->result_label);
331 gtk_label_set_justify(GTK_LABEL(pdialog->result_label), GTK_JUSTIFY_LEFT);
332 } else {
333 pdialog->result_label = NULL;
334 }
335
336 /* Minimal Surplus and Factor */
337
338 table = gtk_grid_new();
339 g_object_set(table, "margin", 2, NULL);
340 gtk_container_add(GTK_CONTAINER(vbox), table);
341
342 label = gtk_label_new(_("Minimal Surplus"));
343 gtk_widget_set_halign(label, GTK_ALIGN_START);
344 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
345 gtk_grid_attach(GTK_GRID(table), label, 1, 0, 1, 1);
346 label = gtk_label_new(_("Factor"));
347 gtk_widget_set_halign(label, GTK_ALIGN_START);
348 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
349 gtk_grid_attach(GTK_GRID(table), label, 2, 0, 1, 1);
350
352 label = gtk_label_new(get_output_name(i));
353 gtk_grid_attach(GTK_GRID(table), label, 0, i + 1, 1, 1);
354 gtk_widget_set_halign(label, GTK_ALIGN_START);
355 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
356
357 pdialog->minimal_surplus[i] = hscale =
358 gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, NULL);
359 gtk_range_set_range(GTK_RANGE(hscale),
360 GUI_GTK_OPTION(governor_range_min),
361 GUI_GTK_OPTION(governor_range_max));
362 gtk_range_set_increments(GTK_RANGE(hscale), 1, 1);
363 pango_layout_get_pixel_size(gtk_scale_get_layout(GTK_SCALE(hscale)),
364 &layout_width, NULL);
365 gtk_widget_set_size_request(hscale, layout_width + 51 * 2, -1);
366
367 gtk_grid_attach(GTK_GRID(table), hscale, 1, i + 1, 1, 1);
368 gtk_scale_set_digits(GTK_SCALE(hscale), 0);
369 gtk_scale_set_value_pos(GTK_SCALE(hscale), GTK_POS_LEFT);
370
371 g_signal_connect(pdialog->minimal_surplus[i],
372 "value-changed",
373 G_CALLBACK(hscale_changed), pdialog);
374
375 pdialog->factor[i] = hscale =
376 gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, NULL);
377 gtk_range_set_range(GTK_RANGE(hscale), 0, 25);
378 gtk_range_set_increments(GTK_RANGE(hscale), 1, 1);
379 pango_layout_get_pixel_size(gtk_scale_get_layout(GTK_SCALE(hscale)),
380 &layout_width, NULL);
381 gtk_widget_set_size_request(hscale, layout_width + 26 * 2, -1);
382
383 gtk_grid_attach(GTK_GRID(table), hscale, 2, i + 1, 1, 1);
384 gtk_scale_set_digits(GTK_SCALE(hscale), 0);
385 gtk_scale_set_value_pos(GTK_SCALE(hscale), GTK_POS_LEFT);
386
387 g_signal_connect(pdialog->factor[i], "value-changed",
388 G_CALLBACK(hscale_changed), pdialog);
390
391 /* Happy Surplus and Factor */
392 label = gtk_label_new(_("Celebrate"));
393 gtk_grid_attach(GTK_GRID(table), label, 0, O_LAST + 1, 1, 1);
394 gtk_widget_set_halign(label, GTK_ALIGN_START);
395 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
396
397 pdialog->happy_button = gtk_check_button_new();
398 gtk_widget_set_halign(pdialog->happy_button, GTK_ALIGN_END);
399 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdialog->happy_button),
400 FALSE);
401 gtk_grid_attach(GTK_GRID(table), pdialog->happy_button, 1, O_LAST + 1, 1, 1);
402
403 g_signal_connect(pdialog->happy_button, "toggled",
404 G_CALLBACK(hscale_changed), pdialog);
405
406 pdialog->factor[O_LAST] = hscale =
407 gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, NULL);
408 gtk_range_set_range(GTK_RANGE(hscale), 0, 50);
409 gtk_range_set_increments(GTK_RANGE(hscale), 1, 1);
410 pango_layout_get_pixel_size(gtk_scale_get_layout(GTK_SCALE(hscale)),
411 &layout_width, NULL);
412 gtk_widget_set_size_request(hscale, layout_width + 51 * 2, -1);
413
414 gtk_grid_attach(GTK_GRID(table), hscale, 2, O_LAST + 1, 1, 1);
415 gtk_scale_set_digits(GTK_SCALE(hscale), 0);
416 gtk_scale_set_value_pos(GTK_SCALE(hscale), GTK_POS_LEFT);
417
418 g_signal_connect(pdialog->factor[O_LAST],
419 "value-changed",
420 G_CALLBACK(hscale_changed), pdialog);
421
422 /* Maximize Growth */
423 label = gtk_label_new(_("Maximize growth"));
424 gtk_grid_attach(GTK_GRID(table), label, 0, O_LAST + 2, 1, 1);
425 gtk_widget_set_halign(label, GTK_ALIGN_START);
426 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
427
428 pdialog->growth_button = gtk_check_button_new();
429 gtk_widget_set_halign(pdialog->growth_button, GTK_ALIGN_END);
430 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdialog->growth_button),
431 FALSE);
432 gtk_grid_attach(GTK_GRID(table), pdialog->growth_button, 1, O_LAST + 2, 1, 1);
433
434 g_signal_connect(pdialog->growth_button, "toggled",
435 G_CALLBACK(hscale_changed), pdialog);
436
437 /* Buttons */
438 hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
439 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_EDGE);
440 gtk_container_add(GTK_CONTAINER(vbox), hbox);
441
442 button = gtk_button_new_from_stock(GTK_STOCK_HELP);
443 g_signal_connect(button, "clicked",
444 G_CALLBACK(help_callback), NULL);
445 gtk_container_add(GTK_CONTAINER(hbox), button);
446 gtk_button_box_set_child_non_homogeneous(GTK_BUTTON_BOX(hbox),
447 button, TRUE);
448
449 pdialog->active_command = gtk_toggle_button_new();
450 gtk_button_set_use_underline(GTK_BUTTON(pdialog->active_command), TRUE);
451 gtk_button_set_image_position(GTK_BUTTON(pdialog->active_command),
452 GTK_POS_TOP);
453 gtk_widget_set_name(pdialog->active_command, "comment_label");
454 gtk_container_add(GTK_CONTAINER(hbox), pdialog->active_command);
455
456 gtk_widget_show_all(pdialog->shell);
457
458 dialog_list_prepend(dialog_list, pdialog);
459
460 update_cma_preset_list(pdialog);
461
462 gtk_tree_view_focus(GTK_TREE_VIEW(view));
463
464 /* refresh is done in refresh_city_dialog */
465
466 return pdialog;
467}
468
469/**********************************************************************/
472void refresh_cma_dialog(struct city *pcity, enum cma_refresh refresh)
473{
474 struct cm_result *result = cm_result_new(pcity);
475 struct cm_parameter param;
476 struct cma_dialog *pdialog = get_cma_dialog(pcity);
477 int controlled = cma_is_city_under_agent(pcity, NULL);
478
480
481 if (pdialog->result_label != NULL) {
482 /* fill in result label */
484 gtk_label_set_text(GTK_LABEL(pdialog->result_label),
485 cmafec_get_result_descr(pcity, result, &param));
486 }
487
488 /* if called from a hscale, we _don't_ want to do this */
489 if (refresh != DONT_REFRESH_HSCALES) {
490 set_hscales(&param, pdialog);
491 }
492
493 gtk_widget_queue_draw(pdialog->preset_list);
494
495 gtk_widget_set_sensitive(pdialog->active_command, can_client_issue_orders());
496
497 g_signal_handlers_disconnect_matched(pdialog->active_command,
498 G_SIGNAL_MATCH_FUNC,
499 0, 0, NULL, cma_active_callback, NULL);
500 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdialog->active_command),
501 controlled);
502 g_signal_connect(pdialog->active_command, "clicked",
503 G_CALLBACK(cma_active_callback), pdialog);
504
505 if (controlled) {
506 GtkWidget *image = gtk_image_new_from_stock(
507 GTK_STOCK_YES, GTK_ICON_SIZE_DND);
508
509 gtk_button_set_image(GTK_BUTTON(pdialog->active_command), image);
510 gtk_button_set_label(GTK_BUTTON(pdialog->active_command),
511 _("Governor Enabl_ed"));
512 } else {
513 GtkWidget *image = gtk_image_new_from_stock(
514 GTK_STOCK_NO, GTK_ICON_SIZE_DND);
515
516 gtk_button_set_image(GTK_BUTTON(pdialog->active_command), image);
517 gtk_button_set_label(GTK_BUTTON(pdialog->active_command),
518 _("Governor Disabl_ed"));
519 }
520 gtk_button_set_always_show_image(GTK_BUTTON(pdialog->active_command), TRUE);
521
522 if (pdialog->result_label != NULL) {
523 gtk_widget_set_sensitive(pdialog->result_label, controlled);
524 }
525
526 cm_result_destroy(result);
527}
528
529/**********************************************************************/
532static void update_cma_preset_list(struct cma_dialog *pdialog)
533{
534 char buf[BUFFER_SIZE];
535 GtkTreeIter it;
536 int i;
537
538 /* Fill preset list */
539 gtk_list_store_clear(pdialog->store);
540
541 /* Append the presets */
542 if (cmafec_preset_num()) {
543 for (i = 0; i < cmafec_preset_num(); i++) {
544 fc_strlcpy(buf, cmafec_preset_get_descr(i), sizeof(buf));
545 gtk_list_store_append(pdialog->store, &it);
546 gtk_list_store_set(pdialog->store, &it, 0, buf, -1);
547 }
548 }
549}
550
551/**********************************************************************/
554static void cma_activate_preset_callback(GtkTreeView *view, GtkTreePath *path,
555 GtkTreeViewColumn *col, gpointer data)
556{
557 struct cma_dialog *pdialog = (struct cma_dialog *) data;
558 int preset_index;
559 const struct cm_parameter *pparam;
560
561 preset_index = gtk_tree_path_get_indices(path) [0];
562
563 pparam = cmafec_preset_get_parameter(preset_index);
564
565 /* Save the change */
566 cmafec_set_fe_parameter(pdialog->pcity, pparam);
567
568 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
569 cma_release_city(pdialog->pcity);
570 cma_put_city_under_agent(pdialog->pcity, pparam);
571 }
572 refresh_city_dialog(pdialog->pcity);
573}
574
575/**********************************************************************/
578static void cma_add_preset_callback(GtkWidget *w, gpointer data)
579{
580 struct cma_dialog *pdialog = (struct cma_dialog *) data;
581 const char *default_name;
582 GtkWidget *parent = gtk_widget_get_toplevel(pdialog->shell);
583 int index;
584
585 if ((index = gtk_tree_selection_get_row(pdialog->selection)) != -1) {
586 default_name = cmafec_preset_get_descr(index);
587 } else {
588 default_name = _("new preset");
589 }
590
591 pdialog->name_shell = input_dialog_create(GTK_WINDOW(parent),
592 _("Name new preset"),
593 _("What should we name the preset?"),
594 default_name,
596}
597
598/**********************************************************************/
601static void cma_preset_add_popup_callback(gpointer data, gint response,
602 const char *input)
603{
604 struct cma_dialog *pdialog = (struct cma_dialog *) data;
605
606 if (pdialog) {
607 if (response == GTK_RESPONSE_OK) {
608 struct cm_parameter param;
609
610 cmafec_get_fe_parameter(pdialog->pcity, &param);
611 cmafec_preset_add(input, &param);
612 update_cma_preset_list(pdialog);
614 /* If this or other cities have this set as "custom" */
616 } /* else CANCEL or DELETE_EVENT */
617
618 pdialog->name_shell = NULL;
619 }
620}
621
622/**********************************************************************/
625static gboolean cma_preset_key_pressed_callback(GtkWidget *w, GdkEventKey *ev,
626 gpointer data)
627{
628 struct cma_dialog *pdialog = (struct cma_dialog *) data;
629 int index;
630
631 if ((index = gtk_tree_selection_get_row(pdialog->selection)) == -1) {
632 return FALSE;
633 }
634
635 if (ev->type == GDK_KEY_PRESS) {
636 switch (ev->keyval) {
637 case GDK_KEY_Delete:
638 cma_preset_remove(pdialog, index);
639 break;
640 case GDK_KEY_Insert:
641 cma_add_preset_callback(NULL, pdialog);
642 break;
643 default:
644 return FALSE;
645 }
646 return TRUE;
647 }
648 return FALSE;
649}
650
651/**********************************************************************/
654static void cma_del_preset_callback(GtkWidget *w, gpointer data)
655{
656 struct cma_dialog *pdialog = (struct cma_dialog *) data;
657 int index;
658
659 if ((index = gtk_tree_selection_get_row(pdialog->selection)) == -1) {
660 return;
661 }
662
663 cma_preset_remove(pdialog, index);
664}
665
666/**********************************************************************/
669static void cma_preset_remove(struct cma_dialog *pdialog, int preset_index)
670{
671 GtkWidget *parent = gtk_widget_get_toplevel(pdialog->shell), *shl;
672
673 pdialog->id = preset_index;
674 shl = gtk_message_dialog_new(NULL,
675 GTK_DIALOG_DESTROY_WITH_PARENT,
676 GTK_MESSAGE_QUESTION,
677 GTK_BUTTONS_YES_NO,
678 _("Remove this preset?"));
679 setup_dialog(shl, parent);
680 pdialog->preset_remove_shell = shl;
681
682 gtk_window_set_title(GTK_WINDOW(shl), cmafec_preset_get_descr(preset_index));
683 gtk_window_set_position(GTK_WINDOW(shl), GTK_WIN_POS_CENTER_ON_PARENT);
684
685 g_signal_connect(shl, "response",
686 G_CALLBACK(cma_preset_remove_response), pdialog);
687
688 gtk_window_present(GTK_WINDOW(shl));
689}
690
691/**********************************************************************/
694static void cma_preset_remove_response(GtkWidget *w, gint response,
695 gpointer data)
696{
697 struct cma_dialog *pdialog = (struct cma_dialog *) data;
698
699 if (response == GTK_RESPONSE_YES) {
700 cmafec_preset_remove(pdialog->id);
701 pdialog->id = -1;
702 update_cma_preset_list(pdialog);
704 /* if this or other cities have this set, reset to "custom" */
706 }
707 gtk_widget_destroy(w);
708
709 pdialog->preset_remove_shell = NULL;
710}
711
712/**********************************************************************/
715static void cma_active_callback(GtkWidget *w, gpointer data)
716{
717 struct cma_dialog *pdialog = (struct cma_dialog *) data;
718
719 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
720 cma_release_city(pdialog->pcity);
721 } else {
722 struct cm_parameter param;
723
724 cmafec_get_fe_parameter(pdialog->pcity, &param);
725 cma_put_city_under_agent(pdialog->pcity, &param);
726 }
727 refresh_city_dialog(pdialog->pcity);
728}
729
730/**********************************************************************/
734static void set_hscales(const struct cm_parameter *const parameter,
735 struct cma_dialog *pdialog)
736{
737 allow_refreshes = 0;
739 gtk_range_set_value(GTK_RANGE(pdialog->minimal_surplus[i]),
740 parameter->minimal_surplus[i]);
741 gtk_range_set_value(GTK_RANGE(pdialog->factor[i]), parameter->factor[i]);
743 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdialog->happy_button),
744 parameter->require_happy);
745 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdialog->growth_button),
746 parameter->max_growth);
747 gtk_range_set_value(GTK_RANGE(pdialog->factor[O_LAST]),
748 parameter->happy_factor);
749 allow_refreshes = 1;
750}
751
752/**********************************************************************/
755static void hscale_changed(GtkWidget *get, gpointer data)
756{
757 struct cma_dialog *pdialog = (struct cma_dialog *) data;
758 struct cm_parameter param;
759
760 if (!allow_refreshes) {
761 return;
762 }
763
764 cmafec_get_fe_parameter(pdialog->pcity, &param);
766 param.minimal_surplus[i] =
767 (int) (gtk_range_get_value(GTK_RANGE(pdialog->minimal_surplus[i])));
768 param.factor[i] =
769 (int) (gtk_range_get_value(GTK_RANGE(pdialog->factor[i])));
771 param.require_happy =
772 (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pdialog->happy_button))
773 ? TRUE : FALSE);
774 param.max_growth =
775 (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pdialog->growth_button))
776 ? TRUE : FALSE);
777 param.happy_factor =
778 (int) (gtk_range_get_value(GTK_RANGE(pdialog->factor[O_LAST])));
779
780 /* Save the change */
781 cmafec_set_fe_parameter(pdialog->pcity, &param);
782
783 /* Refreshes the cma */
784 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
785 cma_release_city(pdialog->pcity);
786 cma_put_city_under_agent(pdialog->pcity, &param);
787 refresh_city_dialog(pdialog->pcity);
788 } else {
790 }
791}
const char * get_output_name(Output_type_id output)
Definition city.c:624
#define output_type_iterate(output)
Definition city.h:821
#define output_type_iterate_end
Definition city.h:827
void refresh_city_dialog(struct city *pcity)
void city_report_dialog_update(void)
bool can_client_issue_orders(void)
struct cm_result * cm_result_new(struct city *pcity)
Definition cm.c:343
void cm_result_from_main_map(struct cm_result *result, const struct city *pcity)
Definition cm.c:2259
void cm_result_destroy(struct cm_result *result)
Definition cm.c:366
bool cma_is_city_under_agent(const struct city *pcity, struct cm_parameter *parameter)
Definition cma_core.c:551
void cma_put_city_under_agent(struct city *pcity, const struct cm_parameter *const parameter)
Definition cma_core.c:523
void cma_release_city(struct city *pcity)
Definition cma_core.c:541
const char * cmafec_get_short_descr(const struct cm_parameter *const parameter)
Definition cma_fec.c:236
void cmafec_set_fe_parameter(struct city *pcity, const struct cm_parameter *const parameter)
Definition cma_fec.c:105
char * cmafec_preset_get_descr(int idx)
Definition cma_fec.c:169
const char * cmafec_get_result_descr(struct city *pcity, const struct cm_result *result, const struct cm_parameter *const parameter)
Definition cma_fec.c:322
const struct cm_parameter * cmafec_preset_get_parameter(int idx)
Definition cma_fec.c:182
void cmafec_preset_add(const char *descr_name, struct cm_parameter *pparam)
Definition cma_fec.c:136
int cmafec_preset_get_index_of_parameter(const struct cm_parameter *const parameter)
Definition cma_fec.c:196
void cmafec_preset_remove(int idx)
Definition cma_fec.c:153
int cmafec_preset_num(void)
Definition cma_fec.c:213
void cmafec_get_fe_parameter(struct city *pcity, struct cm_parameter *dest)
Definition cma_fec.c:115
@ O_LAST
Definition fc_types.h:91
#define _(String)
Definition fcintl.h:67
static gboolean button_press_callback(GtkTreeView *view, GdkEventButton *ev, gpointer data)
Definition cma_fe.c:143
static gboolean cma_preset_key_pressed_callback(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition cma_fe.c:625
static void cma_preset_remove(struct cma_dialog *pdialog, int preset_index)
Definition cma_fe.c:669
void close_cma_dialog(struct city *pcity)
Definition cma_fe.c:104
struct cma_dialog * create_cma_dialog(struct city *pcity, bool tiny)
Definition cma_fe.c:214
void refresh_cma_dialog(struct city *pcity, enum cma_refresh refresh)
Definition cma_fe.c:472
static void cma_del_preset_callback(GtkWidget *w, gpointer data)
Definition cma_fe.c:654
static void cma_dialog_destroy_callback(GtkWidget *w, gpointer data)
Definition cma_fe.c:118
void cma_fe_init(void)
Definition cma_fe.c:88
static void cma_add_preset_callback(GtkWidget *w, gpointer data)
Definition cma_fe.c:578
static void help_callback(GtkWidget *w, gpointer data)
Definition cma_fe.c:170
static void update_cma_preset_list(struct cma_dialog *pdialog)
Definition cma_fe.c:532
#define BUFFER_SIZE
Definition cma_fe.c:48
#define dialog_list_iterate_end
Definition cma_fe.c:56
static void hscale_changed(GtkWidget *get, gpointer data)
Definition cma_fe.c:755
static void cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *it, gpointer data)
Definition cma_fe.c:178
static void cma_preset_add_popup_callback(gpointer data, gint response, const char *input)
Definition cma_fe.c:601
static struct cma_dialog * get_cma_dialog(struct city *pcity)
Definition cma_fe.c:129
#define dialog_list_iterate(dialoglist, pdialog)
Definition cma_fe.c:54
static struct dialog_list * dialog_list
Definition cma_fe.c:58
static void cma_preset_remove_response(GtkWidget *w, gint response, gpointer data)
Definition cma_fe.c:694
static void cma_activate_preset_callback(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
Definition cma_fe.c:554
static void cma_active_callback(GtkWidget *w, gpointer data)
Definition cma_fe.c:715
static void set_hscales(const struct cm_parameter *const parameter, struct cma_dialog *pdialog)
Definition cma_fe.c:734
void cma_fe_done(void)
Definition cma_fe.c:96
static int allow_refreshes
Definition cma_fe.c:60
cma_refresh
Definition cma_fe.h:25
@ DONT_REFRESH_HSCALES
Definition cma_fe.h:28
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
void gtk_tree_view_focus(GtkTreeView *view)
Definition gui_stuff.c:230
gint gtk_tree_selection_get_row(GtkTreeSelection *selection)
Definition gui_stuff.c:209
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:281
void popup_help_dialog_string(const char *item)
Definition helpdlg.c:211
GtkWidget * input_dialog_create(GtkWindow *parent, const char *dialogname, const char *text, const char *postinputtest, input_dialog_callback_t response_callback, gpointer response_cli_data)
Definition inputdlg.c:66
#define HELP_CMA_ITEM
#define fc_malloc(sz)
Definition mem.h:34
Definition city.h:309
int factor[O_LAST]
Definition cm.h:47
bool max_growth
Definition cm.h:42
bool require_happy
Definition cm.h:43
int minimal_surplus[O_LAST]
Definition cm.h:41
int happy_factor
Definition cm.h:48
Definition cm.h:52
GtkWidget * preset_list
Definition cma_fe.h:36
GtkWidget * active_command
Definition cma_fe.h:40
GtkWidget * factor[O_LAST+1]
Definition cma_fe.h:44
GtkWidget * shell
Definition cma_fe.h:33
GtkWidget * happy_button
Definition cma_fe.h:42
GtkWidget * del_preset_command
Definition cma_fe.h:39
GtkWidget * growth_button
Definition cma_fe.h:43
GtkWidget * result_label
Definition cma_fe.h:37
GtkWidget * add_preset_command
Definition cma_fe.h:38
GtkWidget * minimal_surplus[O_LAST]
Definition cma_fe.h:41
GtkListStore * store
Definition cma_fe.h:46
GtkWidget * name_shell
Definition cma_fe.h:34
GtkWidget * preset_remove_shell
Definition cma_fe.h:35
int id
Definition cma_fe.h:47
struct city * pcity
Definition cma_fe.h:32
GtkTreeSelection * selection
Definition cma_fe.h:45
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:787
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47