Freeciv-3.1: /fast/freeciv/nightly/S3_1/client/gui-gtk-4.0/cma_fe.c Source File

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