Qt client - remove right click menu from end turn sidebar
[freeciv.git] / client / gui-gtk-3.0 / cma_fe.c
blob05d98cde150af91c0c642cc978da49ef4165bdac
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.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <gdk/gdkkeysyms.h>
20 /* utility */
21 #include "fcintl.h"
22 #include "log.h"
23 #include "mem.h"
24 #include "support.h"
26 /* common */
27 #include "events.h"
28 #include "game.h"
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"
38 /* client/gui-gtk-3.0 */
39 #include "cityrep.h"
40 #include "dialogs.h"
41 #include "gui_stuff.h"
42 #include "helpdlg.h"
43 #include "inputdlg.h"
45 #include "cma_fe.h"
47 #define BUFFER_SIZE 64
49 #define SPECLIST_TAG dialog
50 #define SPECLIST_TYPE struct cma_dialog
51 #include "speclist.h"
53 #define dialog_list_iterate(dialoglist, pdialog) \
54 TYPED_LIST_ITERATE(struct cma_dialog, dialoglist, pdialog)
55 #define dialog_list_iterate_end LIST_ITERATE_END
57 static struct dialog_list *dialog_list;
59 static int allow_refreshes = 1;
61 static struct cma_dialog *get_cma_dialog(struct city *pcity);
63 static void update_cma_preset_list(struct cma_dialog *pdialog);
65 static gboolean cma_preset_key_pressed_callback(GtkWidget *w, GdkEventKey *ev,
66 gpointer data);
67 static void cma_del_preset_callback(GtkWidget *w, gpointer data);
68 static void cma_preset_remove(struct cma_dialog *pdialog, int preset_index);
69 static void cma_preset_remove_response(GtkWidget *w, gint response,
70 gpointer data);
72 static void cma_add_preset_callback(GtkWidget *w, gpointer data);
73 static void cma_preset_add_popup_callback(gpointer data, gint response,
74 const char *input);
76 static void cma_active_callback(GtkWidget *w, gpointer data);
77 static void cma_activate_preset_callback(GtkTreeView *view, GtkTreePath *path,
78 GtkTreeViewColumn *col, gpointer data);
80 static void hscale_changed(GtkWidget *get, gpointer data);
81 static void set_hscales(const struct cm_parameter *const parameter,
82 struct cma_dialog *pdialog);
84 /**************************************************************************
85 Initialize cma front end system
86 **************************************************************************/
87 void cma_fe_init()
89 dialog_list = dialog_list_new();
92 /**************************************************************************
93 Free resources allocated for cma front end system
94 **************************************************************************/
95 void cma_fe_done()
97 dialog_list_destroy(dialog_list);
100 /**************************************************************************
101 only called when the city dialog is closed.
102 **************************************************************************/
103 void close_cma_dialog(struct city *pcity)
105 struct cma_dialog *pdialog = get_cma_dialog(pcity);
107 if (pdialog == NULL) {
108 /* A city which is being investigated doesn't contain cma dialog */
109 return;
111 gtk_widget_destroy(pdialog->shell);
114 /**************************************************************************
115 Destroy cma dialog
116 **************************************************************************/
117 static void cma_dialog_destroy_callback(GtkWidget *w, gpointer data)
119 struct cma_dialog *pdialog = (struct cma_dialog *) data;
121 dialog_list_remove(dialog_list, pdialog);
122 free(pdialog);
125 /****************************************************************
126 return the cma_dialog for a given city.
127 *****************************************************************/
128 struct cma_dialog *get_cma_dialog(struct city *pcity)
130 dialog_list_iterate(dialog_list, pdialog) {
131 if (pdialog->pcity == pcity) {
132 return pdialog;
134 } dialog_list_iterate_end;
136 return NULL;
139 /**************************************************************************
140 User has pressed button in cma dialog
141 **************************************************************************/
142 static gboolean button_press_callback(GtkTreeView *view, GdkEventButton *ev,
143 gpointer data)
145 GtkTreePath *path;
146 GtkTreeViewColumn *column;
148 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(view),
149 ev->x, ev->y, &path, &column, NULL, NULL)) {
150 if (ev->type == GDK_BUTTON_PRESS) {
151 cma_activate_preset_callback(view, path, column, data);
152 } else if (ev->type == GDK_2BUTTON_PRESS) {
153 struct cma_dialog *pdialog = (struct cma_dialog *) data;
154 struct cm_parameter param;
156 cmafec_get_fe_parameter(pdialog->pcity, &param);
157 cma_put_city_under_agent(pdialog->pcity, &param);
158 refresh_city_dialog(pdialog->pcity);
161 gtk_tree_path_free(path);
163 return FALSE;
166 /**************************************************************************
167 User has requested help
168 **************************************************************************/
169 static void help_callback(GtkWidget *w, gpointer data)
171 popup_help_dialog_string(HELP_CMA_ITEM);
174 /**************************************************************************
175 Cell data function for cma dialog
176 **************************************************************************/
177 static void cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *cell,
178 GtkTreeModel *model, GtkTreeIter *it, gpointer data)
180 struct cma_dialog *pdialog = (struct cma_dialog *) data;
181 gchararray s1;
182 const char *s2;
183 int i1, i2;
184 struct cm_parameter param;
185 GtkTreePath *path;
187 gtk_tree_model_get(model, it, 0, &s1, -1);
188 if (s1 == NULL) {
189 return;
191 path = gtk_tree_model_get_path(model, it);
192 i1 = gtk_tree_path_get_indices(path)[0];
193 gtk_tree_path_free(path);
195 cmafec_get_fe_parameter(pdialog->pcity, &param);
196 s2 = cmafec_get_short_descr(&param);
197 i2 = cmafec_preset_get_index_of_parameter(&param);
199 if (!strcmp(s1, s2) && i1 == i2) {
200 g_object_set(G_OBJECT(cell), "style", PANGO_STYLE_ITALIC,
201 "weight", PANGO_WEIGHT_BOLD, NULL);
202 } else {
203 g_object_set(G_OBJECT(cell), "style", PANGO_STYLE_NORMAL,
204 "weight", PANGO_WEIGHT_NORMAL, NULL);
207 g_free(s1);
210 /**************************************************************************
211 Instantiates a new struct for each city_dialog window that is open.
212 **************************************************************************/
213 struct cma_dialog *create_cma_dialog(struct city *pcity, bool tiny)
215 struct cma_dialog *pdialog;
216 struct cm_parameter param;
217 GtkWidget *frame, *page, *hbox, *label, *table;
218 GtkWidget *vbox, *sw, *hscale, *button, *image;
219 GtkListStore *store;
220 GtkCellRenderer *rend;
221 GtkWidget *view;
222 GtkTreeViewColumn *column;
223 gint layout_width;
225 cmafec_get_fe_parameter(pcity, &param);
226 pdialog = fc_malloc(sizeof(struct cma_dialog));
227 pdialog->pcity = pcity;
228 pdialog->shell = gtk_grid_new();
229 gtk_orientable_set_orientation(GTK_ORIENTABLE(pdialog->shell),
230 GTK_ORIENTATION_VERTICAL);
231 gtk_grid_set_row_spacing(GTK_GRID(pdialog->shell), 8);
232 gtk_container_set_border_width(GTK_CONTAINER(pdialog->shell), 8);
233 g_signal_connect(pdialog->shell, "destroy",
234 G_CALLBACK(cma_dialog_destroy_callback), pdialog);
236 page = gtk_grid_new();
237 gtk_grid_set_column_spacing(GTK_GRID(page), 12);
238 gtk_container_add(GTK_CONTAINER(pdialog->shell), page);
240 vbox = gtk_grid_new();
241 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
242 GTK_ORIENTATION_VERTICAL);
243 gtk_grid_set_row_spacing(GTK_GRID(pdialog->shell), 2);
244 gtk_container_add(GTK_CONTAINER(page), vbox);
246 sw = gtk_scrolled_window_new(NULL, NULL);
247 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
248 GTK_SHADOW_ETCHED_IN);
249 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
250 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
252 store = gtk_list_store_new(1, G_TYPE_STRING);
253 pdialog->store = store;
255 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
256 gtk_widget_set_hexpand(view, TRUE);
257 gtk_widget_set_vexpand(view, TRUE);
258 g_object_unref(store);
259 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
260 pdialog->preset_list = view;
261 pdialog->selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
263 g_signal_connect(pdialog->preset_list, "button_press_event",
264 G_CALLBACK(button_press_callback), pdialog);
266 gtk_widget_set_tooltip_text(view,
267 _("For information on\n"
268 "the citizen governor and governor presets,\n"
269 "including sample presets,\n"
270 "see README.governor."));
272 rend = gtk_cell_renderer_text_new();
273 column = gtk_tree_view_column_new_with_attributes(NULL, rend,
274 "text", 0, NULL);
275 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
276 gtk_tree_view_column_set_cell_data_func(column, rend, cell_data_func,
277 pdialog, NULL);
279 label = g_object_new(GTK_TYPE_LABEL,
280 "use-underline", TRUE,
281 "mnemonic-widget", view,
282 "label", _("Prese_ts:"),
283 "xalign", 0.0, "yalign", 0.5, NULL);
284 gtk_container_add(GTK_CONTAINER(vbox), label);
286 gtk_container_add(GTK_CONTAINER(sw), view);
287 gtk_container_add(GTK_CONTAINER(vbox), sw);
289 g_signal_connect(view, "row_activated",
290 G_CALLBACK(cma_activate_preset_callback), pdialog);
291 g_signal_connect(view, "key-press-event",
292 G_CALLBACK(cma_preset_key_pressed_callback), pdialog);
294 hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
295 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_EDGE);
296 gtk_container_add(GTK_CONTAINER(vbox), hbox);
298 button = gtk_button_new_with_mnemonic(_("Ne_w"));
299 image = gtk_image_new_from_stock(GTK_STOCK_NEW, GTK_ICON_SIZE_BUTTON);
300 gtk_button_set_image(GTK_BUTTON(button), image);
301 gtk_container_add(GTK_CONTAINER(hbox), button);
302 g_signal_connect(button, "clicked",
303 G_CALLBACK(cma_add_preset_callback), pdialog);
304 pdialog->add_preset_command = button;
306 pdialog->del_preset_command = gtk_button_new_from_stock(GTK_STOCK_DELETE);
307 gtk_container_add(GTK_CONTAINER(hbox), pdialog->del_preset_command);
308 g_signal_connect(pdialog->del_preset_command, "clicked",
309 G_CALLBACK(cma_del_preset_callback), pdialog);
311 /* the right-hand side */
313 vbox = gtk_grid_new();
314 g_object_set(vbox, "margin", 2, NULL);
315 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
316 GTK_ORIENTATION_VERTICAL);
317 gtk_container_add(GTK_CONTAINER(page), vbox);
319 /* Result */
320 if (!tiny) {
321 frame = gtk_frame_new(_("Results"));
322 gtk_widget_set_vexpand(frame, TRUE);
323 gtk_widget_set_valign(frame, GTK_ALIGN_CENTER);
324 gtk_container_add(GTK_CONTAINER(vbox), frame);
326 pdialog->result_label =
327 gtk_label_new("food\n prod\n trade\n\n people\n grow\n prod\n name");
328 gtk_widget_set_name(pdialog->result_label, "city_label");
329 gtk_container_add(GTK_CONTAINER(frame), pdialog->result_label);
330 gtk_label_set_justify(GTK_LABEL(pdialog->result_label), GTK_JUSTIFY_LEFT);
331 } else {
332 pdialog->result_label = NULL;
335 /* Minimal Surplus and Factor */
337 table = gtk_grid_new();
338 g_object_set(table, "margin", 2, NULL);
339 gtk_container_add(GTK_CONTAINER(vbox), table);
341 label = gtk_label_new(_("Minimal Surplus"));
342 gtk_widget_set_halign(label, GTK_ALIGN_START);
343 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
344 gtk_grid_attach(GTK_GRID(table), label, 1, 0, 1, 1);
345 label = gtk_label_new(_("Factor"));
346 gtk_widget_set_halign(label, GTK_ALIGN_START);
347 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
348 gtk_grid_attach(GTK_GRID(table), label, 2, 0, 1, 1);
350 output_type_iterate(i) {
351 label = gtk_label_new(get_output_name(i));
352 gtk_grid_attach(GTK_GRID(table), label, 0, i + 1, 1, 1);
353 gtk_widget_set_halign(label, GTK_ALIGN_START);
354 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
356 pdialog->minimal_surplus[i] = hscale =
357 gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, NULL);
358 gtk_range_set_range(GTK_RANGE(hscale),
359 gui_options.gui_gtk3_governor_range_min,
360 gui_options.gui_gtk3_governor_range_max);
361 gtk_range_set_increments(GTK_RANGE(hscale), 1, 1);
362 pango_layout_get_pixel_size(gtk_scale_get_layout(GTK_SCALE(hscale)),
363 &layout_width, NULL);
364 gtk_widget_set_size_request(hscale, layout_width + 51 * 2, -1);
366 gtk_grid_attach(GTK_GRID(table), hscale, 1, i + 1, 1, 1);
367 gtk_scale_set_digits(GTK_SCALE(hscale), 0);
368 gtk_scale_set_value_pos(GTK_SCALE(hscale), GTK_POS_LEFT);
370 g_signal_connect(pdialog->minimal_surplus[i],
371 "value-changed",
372 G_CALLBACK(hscale_changed), pdialog);
374 pdialog->factor[i] = hscale =
375 gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, NULL);
376 gtk_range_set_range(GTK_RANGE(hscale), 0, 25);
377 gtk_range_set_increments(GTK_RANGE(hscale), 1, 1);
378 pango_layout_get_pixel_size(gtk_scale_get_layout(GTK_SCALE(hscale)),
379 &layout_width, NULL);
380 gtk_widget_set_size_request(hscale, layout_width + 26 * 2, -1);
382 gtk_grid_attach(GTK_GRID(table), hscale, 2, 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);
386 g_signal_connect(pdialog->factor[i], "value-changed",
387 G_CALLBACK(hscale_changed), pdialog);
388 } output_type_iterate_end;
390 /* 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);
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);
403 g_signal_connect(pdialog->happy_button, "toggled",
404 G_CALLBACK(hscale_changed), pdialog);
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);
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);
418 g_signal_connect(pdialog->factor[O_LAST],
419 "value-changed",
420 G_CALLBACK(hscale_changed), pdialog);
422 /* buttons */
424 hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
425 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_EDGE);
426 gtk_container_add(GTK_CONTAINER(vbox), hbox);
428 button = gtk_button_new_from_stock(GTK_STOCK_HELP);
429 g_signal_connect(button, "clicked",
430 G_CALLBACK(help_callback), NULL);
431 gtk_container_add(GTK_CONTAINER(hbox), button);
432 gtk_button_box_set_child_non_homogeneous(GTK_BUTTON_BOX(hbox),
433 button, TRUE);
435 pdialog->active_command = gtk_toggle_button_new();
436 gtk_button_set_use_underline(GTK_BUTTON(pdialog->active_command), TRUE);
437 gtk_button_set_image_position(GTK_BUTTON(pdialog->active_command),
438 GTK_POS_TOP);
439 gtk_widget_set_name(pdialog->active_command, "comment_label");
440 gtk_container_add(GTK_CONTAINER(hbox), pdialog->active_command);
442 gtk_widget_show_all(pdialog->shell);
444 dialog_list_prepend(dialog_list, pdialog);
446 update_cma_preset_list(pdialog);
448 gtk_tree_view_focus(GTK_TREE_VIEW(view));
450 /* refresh is done in refresh_city_dialog */
452 return pdialog;
455 /**************************************************************************
456 refreshes the cma dialog
457 **************************************************************************/
458 void refresh_cma_dialog(struct city *pcity, enum cma_refresh refresh)
460 struct cm_result *result = cm_result_new(pcity);
461 struct cm_parameter param;
462 struct cma_dialog *pdialog = get_cma_dialog(pcity);
463 int controlled = cma_is_city_under_agent(pcity, NULL);
465 cmafec_get_fe_parameter(pcity, &param);
467 if (pdialog->result_label != NULL) {
468 /* fill in result label */
469 cm_result_from_main_map(result, pcity);
470 gtk_label_set_text(GTK_LABEL(pdialog->result_label),
471 cmafec_get_result_descr(pcity, result, &param));
474 /* if called from a hscale, we _don't_ want to do this */
475 if (refresh != DONT_REFRESH_HSCALES) {
476 set_hscales(&param, pdialog);
479 gtk_widget_queue_draw(pdialog->preset_list);
481 gtk_widget_set_sensitive(pdialog->active_command, can_client_issue_orders());
483 g_signal_handlers_disconnect_matched(pdialog->active_command,
484 G_SIGNAL_MATCH_FUNC,
485 0, 0, NULL, cma_active_callback, NULL);
486 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdialog->active_command),
487 controlled);
488 g_signal_connect(pdialog->active_command, "clicked",
489 G_CALLBACK(cma_active_callback), pdialog);
491 if (controlled) {
492 GtkWidget *image = gtk_image_new_from_stock(
493 GTK_STOCK_YES, GTK_ICON_SIZE_DND);
494 gtk_button_set_image(GTK_BUTTON(pdialog->active_command), image);
495 gtk_button_set_label(GTK_BUTTON(pdialog->active_command),
496 _("Governor Enabl_ed"));
497 } else {
498 GtkWidget *image = gtk_image_new_from_stock(
499 GTK_STOCK_NO, GTK_ICON_SIZE_DND);
500 gtk_button_set_image(GTK_BUTTON(pdialog->active_command), image);
501 gtk_button_set_label(GTK_BUTTON(pdialog->active_command),
502 _("Governor Disabl_ed"));
504 gtk_button_set_always_show_image(GTK_BUTTON(pdialog->active_command), TRUE);
506 if (pdialog->result_label != NULL) {
507 gtk_widget_set_sensitive(pdialog->result_label, controlled);
510 cm_result_destroy(result);
513 /**************************************************************************
514 fills in the preset list
515 **************************************************************************/
516 static void update_cma_preset_list(struct cma_dialog *pdialog)
518 char buf[BUFFER_SIZE];
519 GtkTreeIter it;
520 int i;
522 /* Fill preset list */
523 gtk_list_store_clear(pdialog->store);
525 /* Append the presets */
526 if (cmafec_preset_num()) {
527 for (i = 0; i < cmafec_preset_num(); i++) {
528 fc_strlcpy(buf, cmafec_preset_get_descr(i), sizeof(buf));
529 gtk_list_store_append(pdialog->store, &it);
530 gtk_list_store_set(pdialog->store, &it, 0, buf, -1);
535 /****************************************************************
536 callback for selecting a preset from the preset view
537 *****************************************************************/
538 static void cma_activate_preset_callback(GtkTreeView *view, GtkTreePath *path,
539 GtkTreeViewColumn *col, gpointer data)
541 struct cma_dialog *pdialog = (struct cma_dialog *) data;
542 int preset_index;
543 const struct cm_parameter *pparam;
545 preset_index = gtk_tree_path_get_indices(path) [0];
547 pparam = cmafec_preset_get_parameter(preset_index);
549 /* save the change */
550 cmafec_set_fe_parameter(pdialog->pcity, pparam);
552 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
553 cma_release_city(pdialog->pcity);
554 cma_put_city_under_agent(pdialog->pcity, pparam);
556 refresh_city_dialog(pdialog->pcity);
559 /**************************************************************************
560 pops up a dialog to allow to name your new preset
561 **************************************************************************/
562 static void cma_add_preset_callback(GtkWidget *w, gpointer data)
564 struct cma_dialog *pdialog = (struct cma_dialog *) data;
565 const char *default_name;
566 GtkWidget *parent = gtk_widget_get_toplevel(pdialog->shell);
567 int index;
569 if ((index = gtk_tree_selection_get_row(pdialog->selection)) != -1) {
570 default_name = cmafec_preset_get_descr(index);
571 } else {
572 default_name = _("new preset");
575 pdialog->name_shell = input_dialog_create(GTK_WINDOW(parent),
576 _("Name new preset"),
577 _("What should we name the preset?"),
578 default_name,
579 cma_preset_add_popup_callback, pdialog);
582 /****************************************************************
583 callback for the add_preset popup
584 *****************************************************************/
585 static void cma_preset_add_popup_callback(gpointer data, gint response,
586 const char *input)
588 struct cma_dialog *pdialog = (struct cma_dialog *) data;
590 if (pdialog) {
591 if (response == GTK_RESPONSE_OK) {
592 struct cm_parameter param;
594 cmafec_get_fe_parameter(pdialog->pcity, &param);
595 cmafec_preset_add(input, &param);
596 update_cma_preset_list(pdialog);
597 refresh_cma_dialog(pdialog->pcity, DONT_REFRESH_HSCALES);
598 /* if this or other cities have this set as "custom" */
599 city_report_dialog_update();
600 } /* else CANCEL or DELETE_EVENT */
602 pdialog->name_shell = NULL;
606 /****************************************************************
607 Key pressed in preset list
608 *****************************************************************/
609 static gboolean cma_preset_key_pressed_callback(GtkWidget *w, GdkEventKey *ev,
610 gpointer data)
612 struct cma_dialog *pdialog = (struct cma_dialog *) data;
613 int index;
615 if ((index = gtk_tree_selection_get_row(pdialog->selection)) == -1) {
616 return FALSE;
619 if (ev->type == GDK_KEY_PRESS) {
620 switch (ev->keyval) {
621 case GDK_KEY_Delete:
622 cma_preset_remove(pdialog, index);
623 break;
624 case GDK_KEY_Insert:
625 cma_add_preset_callback(NULL, pdialog);
626 break;
627 default:
628 return FALSE;
630 return TRUE;
632 return FALSE;
636 /**************************************************************************
637 callback for del_preset
638 **************************************************************************/
639 static void cma_del_preset_callback(GtkWidget *w, gpointer data)
641 struct cma_dialog *pdialog = (struct cma_dialog *) data;
642 int index;
644 if ((index = gtk_tree_selection_get_row(pdialog->selection)) == -1) {
645 return;
648 cma_preset_remove(pdialog, index);
651 /**************************************************************************
652 pops up a dialog to remove a preset
653 **************************************************************************/
654 static void cma_preset_remove(struct cma_dialog *pdialog, int preset_index)
656 GtkWidget *parent = gtk_widget_get_toplevel(pdialog->shell), *shl;
658 pdialog->id = preset_index;
659 shl = gtk_message_dialog_new(NULL,
660 GTK_DIALOG_DESTROY_WITH_PARENT,
661 GTK_MESSAGE_QUESTION,
662 GTK_BUTTONS_YES_NO,
663 _("Remove this preset?"));
664 setup_dialog(shl, parent);
665 pdialog->preset_remove_shell = shl;
667 gtk_window_set_title(GTK_WINDOW(shl), cmafec_preset_get_descr(preset_index));
668 gtk_window_set_position(GTK_WINDOW(shl), GTK_WIN_POS_CENTER_ON_PARENT);
670 g_signal_connect(shl, "response",
671 G_CALLBACK(cma_preset_remove_response), pdialog);
673 gtk_window_present(GTK_WINDOW(shl));
676 /****************************************************************
677 callback for the remove_preset popup
678 *****************************************************************/
679 static void cma_preset_remove_response(GtkWidget *w, gint response,
680 gpointer data)
682 struct cma_dialog *pdialog = (struct cma_dialog *) data;
684 if (response == GTK_RESPONSE_YES) {
685 cmafec_preset_remove(pdialog->id);
686 pdialog->id = -1;
687 update_cma_preset_list(pdialog);
688 refresh_cma_dialog(pdialog->pcity, DONT_REFRESH_HSCALES);
689 /* if this or other cities have this set, reset to "custom" */
690 city_report_dialog_update();
692 gtk_widget_destroy(w);
694 pdialog->preset_remove_shell = NULL;
697 /**************************************************************************
698 activates/deactivates agent control.
699 **************************************************************************/
700 static void cma_active_callback(GtkWidget *w, gpointer data)
702 struct cma_dialog *pdialog = (struct cma_dialog *) data;
704 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
705 cma_release_city(pdialog->pcity);
706 } else {
707 struct cm_parameter param;
709 cmafec_get_fe_parameter(pdialog->pcity, &param);
710 cma_put_city_under_agent(pdialog->pcity, &param);
712 refresh_city_dialog(pdialog->pcity);
715 /****************************************************************
716 called to adjust the sliders when a preset is selected
717 notice that we don't want to call update_result here.
718 *****************************************************************/
719 static void set_hscales(const struct cm_parameter *const parameter,
720 struct cma_dialog *pdialog)
722 allow_refreshes = 0;
723 output_type_iterate(i) {
724 gtk_range_set_value(GTK_RANGE(pdialog->minimal_surplus[i]),
725 parameter->minimal_surplus[i]);
726 gtk_range_set_value(GTK_RANGE(pdialog->factor[i]), parameter->factor[i]);
727 } output_type_iterate_end;
728 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdialog->happy_button),
729 parameter->require_happy);
730 gtk_range_set_value(GTK_RANGE(pdialog->factor[O_LAST]),
731 parameter->happy_factor);
732 allow_refreshes = 1;
735 /************************************************************************
736 callback if we moved the sliders.
737 *************************************************************************/
738 static void hscale_changed(GtkWidget *get, gpointer data)
740 struct cma_dialog *pdialog = (struct cma_dialog *) data;
741 struct cm_parameter param;
743 if (!allow_refreshes) {
744 return;
747 cmafec_get_fe_parameter(pdialog->pcity, &param);
748 output_type_iterate(i) {
749 param.minimal_surplus[i] =
750 (int) (gtk_range_get_value(GTK_RANGE(pdialog->minimal_surplus[i])));
751 param.factor[i] =
752 (int) (gtk_range_get_value(GTK_RANGE(pdialog->factor[i])));
753 } output_type_iterate_end;
754 param.require_happy =
755 (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pdialog->happy_button)) ? 1 : 0);
756 param.happy_factor =
757 (int) (gtk_range_get_value(GTK_RANGE(pdialog->factor[O_LAST])));
759 /* save the change */
760 cmafec_set_fe_parameter(pdialog->pcity, &param);
762 /* refreshes the cma */
763 if (cma_is_city_under_agent(pdialog->pcity, NULL)) {
764 cma_release_city(pdialog->pcity);
765 cma_put_city_under_agent(pdialog->pcity, &param);
766 refresh_city_dialog(pdialog->pcity);
767 } else {
768 refresh_cma_dialog(pdialog->pcity, DONT_REFRESH_HSCALES);