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)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
15 #include <fc_config.h>
18 #include <gdk/gdkkeysyms.h>
31 #include "chatline_g.h"
32 #include "citydlg_g.h"
33 #include "client_main.h"
35 #include "messagewin_g.h"
38 /* client/gui-gtk-3.0 */
41 #include "gui_stuff.h"
47 #define BUFFER_SIZE 64
49 #define SPECLIST_TAG dialog
50 #define SPECLIST_TYPE struct cma_dialog
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
,
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
,
72 static void cma_add_preset_callback(GtkWidget
*w
, gpointer data
);
73 static void cma_preset_add_popup_callback(gpointer data
, gint response
,
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 **************************************************************************/
89 dialog_list
= dialog_list_new();
92 /**************************************************************************
93 Free resources allocated for cma front end system
94 **************************************************************************/
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 */
111 gtk_widget_destroy(pdialog
->shell
);
114 /**************************************************************************
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
);
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
) {
134 } dialog_list_iterate_end
;
139 /**************************************************************************
140 User has pressed button in cma dialog
141 **************************************************************************/
142 static gboolean
button_press_callback(GtkTreeView
*view
, GdkEventButton
*ev
,
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
, ¶m
);
157 cma_put_city_under_agent(pdialog
->pcity
, ¶m
);
158 refresh_city_dialog(pdialog
->pcity
);
161 gtk_tree_path_free(path
);
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
;
184 struct cm_parameter param
;
187 gtk_tree_model_get(model
, it
, 0, &s1
, -1);
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
, ¶m
);
196 s2
= cmafec_get_short_descr(¶m
);
197 i2
= cmafec_preset_get_index_of_parameter(¶m
);
199 if (!strcmp(s1
, s2
) && i1
== i2
) {
200 g_object_set(G_OBJECT(cell
), "style", PANGO_STYLE_ITALIC
,
201 "weight", PANGO_WEIGHT_BOLD
, NULL
);
203 g_object_set(G_OBJECT(cell
), "style", PANGO_STYLE_NORMAL
,
204 "weight", PANGO_WEIGHT_NORMAL
, NULL
);
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
;
220 GtkCellRenderer
*rend
;
222 GtkTreeViewColumn
*column
;
225 cmafec_get_fe_parameter(pcity
, ¶m
);
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
,
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
,
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
);
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
);
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
],
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
),
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
],
420 G_CALLBACK(hscale_changed
), pdialog
);
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
),
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
),
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 */
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
, ¶m
);
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
, ¶m
));
474 /* if called from a hscale, we _don't_ want to do this */
475 if (refresh
!= DONT_REFRESH_HSCALES
) {
476 set_hscales(¶m
, 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
,
485 0, 0, NULL
, cma_active_callback
, NULL
);
486 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdialog
->active_command
),
488 g_signal_connect(pdialog
->active_command
, "clicked",
489 G_CALLBACK(cma_active_callback
), pdialog
);
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"));
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
];
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
;
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
);
569 if ((index
= gtk_tree_selection_get_row(pdialog
->selection
)) != -1) {
570 default_name
= cmafec_preset_get_descr(index
);
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?"),
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
,
588 struct cma_dialog
*pdialog
= (struct cma_dialog
*) data
;
591 if (response
== GTK_RESPONSE_OK
) {
592 struct cm_parameter param
;
594 cmafec_get_fe_parameter(pdialog
->pcity
, ¶m
);
595 cmafec_preset_add(input
, ¶m
);
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
,
612 struct cma_dialog
*pdialog
= (struct cma_dialog
*) data
;
615 if ((index
= gtk_tree_selection_get_row(pdialog
->selection
)) == -1) {
619 if (ev
->type
== GDK_KEY_PRESS
) {
620 switch (ev
->keyval
) {
622 cma_preset_remove(pdialog
, index
);
625 cma_add_preset_callback(NULL
, pdialog
);
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
;
644 if ((index
= gtk_tree_selection_get_row(pdialog
->selection
)) == -1) {
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
,
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
,
682 struct cma_dialog
*pdialog
= (struct cma_dialog
*) data
;
684 if (response
== GTK_RESPONSE_YES
) {
685 cmafec_preset_remove(pdialog
->id
);
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
);
707 struct cm_parameter param
;
709 cmafec_get_fe_parameter(pdialog
->pcity
, ¶m
);
710 cma_put_city_under_agent(pdialog
->pcity
, ¶m
);
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
)
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
);
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
) {
747 cmafec_get_fe_parameter(pdialog
->pcity
, ¶m
);
748 output_type_iterate(i
) {
749 param
.minimal_surplus
[i
] =
750 (int) (gtk_range_get_value(GTK_RANGE(pdialog
->minimal_surplus
[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);
757 (int) (gtk_range_get_value(GTK_RANGE(pdialog
->factor
[O_LAST
])));
759 /* save the change */
760 cmafec_set_fe_parameter(pdialog
->pcity
, ¶m
);
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
, ¶m
);
766 refresh_city_dialog(pdialog
->pcity
);
768 refresh_cma_dialog(pdialog
->pcity
, DONT_REFRESH_HSCALES
);