1 /***********************************************************************
2 Freeciv - Copyright (C) 2005 - The Freeciv Project
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>
24 #include <gdk/gdkkeysyms.h>
33 #include "connection.h"
35 #include "government.h"
39 #include "chatline_common.h"
40 #include "client_main.h"
42 #include "mapview_common.h"
45 #include "dialogs_g.h"
47 /* client/gui-gtk-2.0 */
52 #include "gui_stuff.h"
56 enum tool_value_selector_columns
{
64 enum player_pov_combo_columns
{
72 enum tool_applied_player_columns
{
80 enum spin_button_types
{
85 struct tool_value_selector
{
86 struct editbar
*editbar_parent
;
94 static struct tool_value_selector
*
95 create_tool_value_selector(struct editbar
*eb_parent
,
96 enum editor_tool_type ett
);
97 static void editinfobox_refresh(struct editinfobox
*ei
);
98 static void editbar_player_pov_combobox_changed(GtkComboBox
*combo
,
100 static void editbar_mode_button_toggled(GtkToggleButton
*tb
,
102 static void editbar_tool_button_toggled(GtkToggleButton
*tb
,
104 static void try_to_set_editor_tool(enum editor_tool_type ett
);
106 static struct editbar
*editor_toolbar
;
107 static struct editinfobox
*editor_infobox
;
109 /****************************************************************************
110 Refresh the buttons in the given editbar according to the current
112 ****************************************************************************/
113 static void refresh_all_buttons(struct editbar
*eb
)
115 enum editor_tool_type ett
;
116 enum editor_tool_mode etm
;
117 GtkWidget
*tb
= NULL
;
124 ett
= editor_get_tool();
125 etm
= editor_tool_get_mode(ett
);
127 for (i
= 0; i
< NUM_EDITOR_TOOL_MODES
; i
++) {
128 tb
= eb
->mode_buttons
[i
];
132 disable_gobject_callback(G_OBJECT(tb
),
133 G_CALLBACK(editbar_mode_button_toggled
));
134 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tb
), i
== etm
);
135 enable_gobject_callback(G_OBJECT(tb
),
136 G_CALLBACK(editbar_mode_button_toggled
));
137 gtk_widget_set_sensitive(tb
, editor_tool_has_mode(ett
, i
));
140 if (0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
141 && eb
->tool_buttons
[ett
] != NULL
) {
142 tb
= eb
->tool_buttons
[ett
];
143 disable_gobject_callback(G_OBJECT(tb
),
144 G_CALLBACK(editbar_tool_button_toggled
));
145 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tb
), TRUE
);
146 enable_gobject_callback(G_OBJECT(tb
),
147 G_CALLBACK(editbar_tool_button_toggled
));
151 /****************************************************************************
152 Callback for all tool mode toggle buttons.
153 ****************************************************************************/
154 static void editbar_mode_button_toggled(GtkToggleButton
*tb
,
158 enum editor_tool_mode etm
;
159 enum editor_tool_type ett
;
161 etm
= GPOINTER_TO_INT(userdata
);
162 if (!(0 <= etm
&& etm
< NUM_EDITOR_TOOL_MODES
)) {
166 active
= gtk_toggle_button_get_active(tb
);
167 ett
= editor_get_tool();
169 editor_tool_set_mode(ett
, active
? etm
: ETM_PAINT
);
173 /****************************************************************************
174 Try to set the given tool as the current editor tool. If the tool is
175 unavailable (editor_tool_is_usable) an error popup is displayed.
176 ****************************************************************************/
177 static void try_to_set_editor_tool(enum editor_tool_type ett
)
179 if (!(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
183 if (!editor_tool_is_usable(ett
)) {
185 dialog
= gtk_message_dialog_new(GTK_WINDOW(toplevel
),
186 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
187 GTK_MESSAGE_ERROR
, GTK_BUTTONS_CLOSE
, "%s",
188 _("The current ruleset does not define any "
189 "objects corresponding to this editor tool."));
190 gtk_window_set_title(GTK_WINDOW(dialog
), editor_tool_get_name(ett
));
191 gtk_dialog_run(GTK_DIALOG(dialog
));
192 gtk_widget_destroy(dialog
);
194 editor_set_tool(ett
);
198 /****************************************************************************
199 Callback to handle toggling of any of the tool buttons.
200 ****************************************************************************/
201 static void editbar_tool_button_toggled(GtkToggleButton
*tb
,
205 enum editor_tool_type ett
;
207 active
= gtk_toggle_button_get_active(tb
);
208 ett
= GPOINTER_TO_INT(userdata
);
211 try_to_set_editor_tool(ett
);
216 /****************************************************************************
217 Refresh the player point-of-view indicator based on the client and
220 NB: The convention is that the first entry (index 0) in the combo box
221 corresponds to the "global observer".
222 ****************************************************************************/
223 static void refresh_player_pov_indicator(struct editbar
*eb
)
231 if (eb
== NULL
|| eb
->player_pov_store
== NULL
) {
235 store
= eb
->player_pov_store
;
236 gtk_list_store_clear(store
);
238 gtk_list_store_append(store
, &iter
);
239 gtk_list_store_set(store
, &iter
, PPV_COL_NAME
, _("Global Observer"),
240 PPV_COL_PLAYER_NO
, -1, -1);
243 players_iterate(pplayer
) {
244 gtk_list_store_append(store
, &iter
);
245 gtk_list_store_set(store
, &iter
, PPV_COL_NAME
, player_name(pplayer
),
246 PPV_COL_PLAYER_NO
, player_number(pplayer
), -1);
248 if (pplayer
->nation
!= NO_NATION_SELECTED
) {
249 flag
= get_flag(pplayer
->nation
);
252 gtk_list_store_set(store
, &iter
, PPV_COL_FLAG
, flag
, -1);
253 g_object_unref(flag
);
256 if (pplayer
== client_player()) {
260 } players_iterate_end
;
262 if (client_is_global_observer()) {
266 combo
= eb
->player_pov_combobox
;
267 gtk_combo_box_set_active(GTK_COMBO_BOX(combo
), index
);
270 /****************************************************************************
271 Callback to handle selection of a player/global observer in the
272 player pov indicator.
274 NB: The convention is that the first entry (index 0) in the combo box
275 corresponds to the "global observer".
276 ****************************************************************************/
277 static void editbar_player_pov_combobox_changed(GtkComboBox
*combo
,
280 struct editbar
*eb
= user_data
;
282 struct player
*pplayer
;
286 if (eb
== NULL
|| eb
->widget
== NULL
287 || !GTK_WIDGET_VISIBLE(eb
->widget
)) {
291 if (!gtk_combo_box_get_active_iter(combo
, &iter
)) {
295 model
= gtk_combo_box_get_model(combo
);
296 gtk_tree_model_get(model
, &iter
, PPV_COL_PLAYER_NO
, &id
, -1);
298 if ((client_is_global_observer() && id
== -1)
299 || client_player_number() == id
) {
303 /* Ugh... hard-coded server command strings. :( */
305 send_chat("/observe");
309 pplayer
= player_by_number(id
);
310 if (pplayer
!= NULL
) {
311 send_chat_printf("/take \"%s\"", pplayer
->name
);
315 /****************************************************************************
316 Run the tool value selection dialog and return the value ID selected.
317 Returns -1 if cancelled.
318 ****************************************************************************/
319 static int tool_value_selector_run(struct tool_value_selector
*tvs
)
323 GtkTreeSelection
*sel
;
332 dialog
= tvs
->dialog
;
333 res
= gtk_dialog_run(GTK_DIALOG(dialog
));
334 gtk_widget_hide(dialog
);
336 if (res
!= GTK_RESPONSE_ACCEPT
) {
340 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(tvs
->view
));
341 if (!gtk_tree_selection_get_selected(sel
, &model
, &iter
)) {
345 gtk_tree_model_get(model
, &iter
, TVS_COL_ID
, &id
, -1);
350 /****************************************************************************
351 Run the tool value selector for the given tool type. Sets the editor state
352 and refreshes the editor GUI depending on the user's choices.
354 Returns FALSE if running the dialog is not possible.
355 ****************************************************************************/
356 static bool editgui_run_tool_selection(enum editor_tool_type ett
)
359 struct tool_value_selector
*tvs
;
362 eb
= editgui_get_editbar();
363 if (eb
== NULL
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
367 if (!editor_tool_has_value(ett
)) {
371 tvs
= eb
->tool_selectors
[ett
];
376 res
= tool_value_selector_run(tvs
);
379 editor_tool_set_value(ett
, res
);
380 editinfobox_refresh(editgui_get_editinfobox());
386 /****************************************************************************
387 Handle a mouse click on any of the tool buttons.
388 ****************************************************************************/
389 static gboolean
editbar_tool_button_mouse_click(GtkWidget
*w
,
395 if (ev
->button
!= 3) {
396 return FALSE
; /* Propagate event further. */
399 ett
= GPOINTER_TO_INT(userdata
);
400 return editgui_run_tool_selection(ett
);
403 /****************************************************************************
404 A helper function to create a toolbar button for the given editor tool.
405 Packs the newly created button into the hbox 'eb->widget'.
406 ****************************************************************************/
407 static void editbar_add_tool_button(struct editbar
*eb
,
408 enum editor_tool_type ett
)
411 GtkWidget
*image
, *button
, *hbox
;
412 GtkRadioButton
*parent
= NULL
;
413 struct sprite
*sprite
;
416 if (!eb
|| !(0 <= ett
&& ett
< NUM_EDITOR_TOOL_TYPES
)) {
420 for (i
= 0; i
< NUM_EDITOR_TOOL_TYPES
; i
++) {
421 if (eb
->tool_buttons
[i
] != NULL
) {
422 parent
= GTK_RADIO_BUTTON(eb
->tool_buttons
[i
]);
427 if (parent
== NULL
) {
428 button
= gtk_radio_button_new(NULL
);
430 button
= gtk_radio_button_new_from_widget(parent
);
433 sprite
= editor_tool_get_sprite(ett
);
434 fc_assert_ret(sprite
!= NULL
);
435 pixbuf
= sprite_get_pixbuf(sprite
);
436 image
= gtk_image_new_from_pixbuf(pixbuf
);
438 gtk_container_add(GTK_CONTAINER(button
), image
);
439 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(button
), FALSE
);
440 gtk_widget_set_tooltip_text(button
, editor_tool_get_tooltip(ett
));
441 gtk_size_group_add_widget(eb
->size_group
, button
);
442 gtk_button_set_relief(GTK_BUTTON(button
), GTK_RELIEF_NONE
);
443 gtk_button_set_focus_on_click(GTK_BUTTON(button
), FALSE
);
445 g_signal_connect(button
, "toggled",
446 G_CALLBACK(editbar_tool_button_toggled
), GINT_TO_POINTER(ett
));
447 g_signal_connect(button
, "button_press_event",
448 G_CALLBACK(editbar_tool_button_mouse_click
), GINT_TO_POINTER(ett
));
451 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, FALSE
, 0);
452 eb
->tool_buttons
[ett
] = button
;
454 if (editor_tool_has_value(ett
)) {
455 eb
->tool_selectors
[ett
] = create_tool_value_selector(eb
, ett
);
459 /****************************************************************************
460 Handle a click on the player properties button in the editor toolbar.
461 ****************************************************************************/
462 static void editbar_player_properties_button_clicked(GtkButton
*b
,
465 struct property_editor
*pe
;
467 pe
= editprop_get_property_editor();
468 property_editor_reload(pe
, OBJTYPE_GAME
);
469 property_editor_reload(pe
, OBJTYPE_PLAYER
);
470 property_editor_popup(pe
, OBJTYPE_PLAYER
);
473 /****************************************************************************
474 Helper function to add a tool mode button to the editor toolbar. The
475 button will be packed into the start of the hbox 'eb->widget'.
476 ****************************************************************************/
477 static void editbar_add_mode_button(struct editbar
*eb
,
478 enum editor_tool_mode etm
)
481 GtkWidget
*image
, *button
, *hbox
;
482 struct sprite
*sprite
;
485 if (!eb
|| !(0 <= etm
&& etm
< NUM_EDITOR_TOOL_MODES
)) {
489 button
= gtk_toggle_button_new();
491 sprite
= editor_get_mode_sprite(etm
);
492 fc_assert_ret(sprite
!= NULL
);
493 pixbuf
= sprite_get_pixbuf(sprite
);
494 image
= gtk_image_new_from_pixbuf(pixbuf
);
496 gtk_container_add(GTK_CONTAINER(button
), image
);
497 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(button
), FALSE
);
498 tooltip
= editor_get_mode_tooltip(etm
);
499 if (tooltip
!= NULL
) {
500 gtk_widget_set_tooltip_text(button
, tooltip
);
502 gtk_size_group_add_widget(eb
->size_group
, button
);
503 gtk_button_set_relief(GTK_BUTTON(button
), GTK_RELIEF_NONE
);
504 gtk_button_set_focus_on_click(GTK_BUTTON(button
), FALSE
);
506 g_signal_connect(button
, "toggled",
507 G_CALLBACK(editbar_mode_button_toggled
), GINT_TO_POINTER(etm
));
510 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, FALSE
, 0);
511 eb
->mode_buttons
[etm
] = button
;
514 /****************************************************************************
515 Create and return an editor toolbar.
516 ****************************************************************************/
517 static struct editbar
*editbar_create(void)
520 GtkWidget
*hbox
, *button
, *combo
, *image
, *separator
, *vbox
, *evbox
;
522 GtkCellRenderer
*cell
;
524 const struct editor_sprites
*sprites
;
526 eb
= fc_calloc(1, sizeof(struct editbar
));
528 hbox
= gtk_hbox_new(FALSE
, 4);
530 eb
->size_group
= gtk_size_group_new(GTK_SIZE_GROUP_BOTH
);
532 sprites
= get_editor_sprites(tileset
);
534 editbar_add_mode_button(eb
, ETM_ERASE
);
536 separator
= gtk_vseparator_new();
537 gtk_box_pack_start(GTK_BOX(hbox
), separator
, FALSE
, FALSE
, 0);
539 editbar_add_tool_button(eb
, ETT_TERRAIN
);
540 editbar_add_tool_button(eb
, ETT_TERRAIN_RESOURCE
);
541 editbar_add_tool_button(eb
, ETT_TERRAIN_SPECIAL
);
542 editbar_add_tool_button(eb
, ETT_ROAD
);
543 editbar_add_tool_button(eb
, ETT_MILITARY_BASE
);
544 editbar_add_tool_button(eb
, ETT_UNIT
);
545 editbar_add_tool_button(eb
, ETT_CITY
);
546 editbar_add_tool_button(eb
, ETT_VISION
);
547 editbar_add_tool_button(eb
, ETT_STARTPOS
);
548 editbar_add_tool_button(eb
, ETT_COPYPASTE
);
550 separator
= gtk_vseparator_new();
551 gtk_box_pack_start(GTK_BOX(hbox
), separator
, FALSE
, FALSE
, 0);
553 /* Player POV indicator. */
554 vbox
= gtk_vbox_new(FALSE
, 0);
555 gtk_box_pack_start(GTK_BOX(hbox
), vbox
, FALSE
, FALSE
, 0);
557 store
= gtk_list_store_new(PPV_NUM_COLS
,
561 eb
->player_pov_store
= store
;
563 combo
= gtk_combo_box_new_with_model(GTK_TREE_MODEL(store
));
565 cell
= gtk_cell_renderer_pixbuf_new();
566 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo
), cell
, FALSE
);
567 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo
),
568 cell
, "pixbuf", PPV_COL_FLAG
);
570 cell
= gtk_cell_renderer_text_new();
571 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo
), cell
, TRUE
);
572 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo
),
573 cell
, "text", PPV_COL_NAME
);
575 gtk_widget_set_size_request(combo
, 140, -1);
576 g_signal_connect(combo
, "changed",
577 G_CALLBACK(editbar_player_pov_combobox_changed
), eb
);
579 evbox
= gtk_event_box_new();
580 gtk_widget_set_tooltip_text(evbox
,
581 _("Switch player point-of-view. Use this to edit "
582 "from the perspective of different players, or "
583 "even as a global observer."));
584 gtk_container_add(GTK_CONTAINER(evbox
), combo
);
585 gtk_box_pack_start(GTK_BOX(vbox
), evbox
, TRUE
, FALSE
, 0);
586 eb
->player_pov_combobox
= combo
;
588 /* Property editor button. */
589 button
= gtk_button_new();
590 pixbuf
= sprite_get_pixbuf(sprites
->properties
);
591 image
= gtk_image_new_from_pixbuf(pixbuf
);
592 gtk_container_add(GTK_CONTAINER(button
), image
);
593 gtk_widget_set_tooltip_text(button
, _("Show the property editor."));
594 gtk_size_group_add_widget(eb
->size_group
, button
);
595 gtk_button_set_relief(GTK_BUTTON(button
), GTK_RELIEF_NONE
);
596 gtk_button_set_focus_on_click(GTK_BUTTON(button
), FALSE
);
597 g_signal_connect(button
, "clicked",
598 G_CALLBACK(editbar_player_properties_button_clicked
), eb
);
599 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, FALSE
, 0);
600 eb
->player_properties_button
= button
;
605 /****************************************************************************
606 Refresh the tool value selector in the given toolbar for the given tool
607 type with data from the editor state.
608 ****************************************************************************/
609 static void refresh_tool_value_selector(struct editbar
*eb
,
610 enum editor_tool_type ett
)
612 GtkTreeSelection
*sel
;
615 int value
, store_value
;
616 struct tool_value_selector
*tvs
;
618 if (!editor_is_active() || !eb
|| !editor_tool_has_value(ett
)) {
622 tvs
= eb
->tool_selectors
[ett
];
628 value
= editor_tool_get_value(ett
);
629 model
= GTK_TREE_MODEL(tvs
->store
);
630 if (!gtk_tree_model_get_iter_first(model
, &iter
)) {
635 gtk_tree_model_get(model
, &iter
, TVS_COL_ID
, &store_value
, -1);
636 if (value
== store_value
) {
637 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(tvs
->view
));
638 gtk_tree_selection_select_iter(sel
, &iter
);
641 } while (gtk_tree_model_iter_next(model
, &iter
));
644 /****************************************************************************
645 Refresh all tool value selectors in the given toolbar according to the
646 current editor state.
647 ****************************************************************************/
648 static void refresh_all_tool_value_selectors(struct editbar
*eb
)
656 for (ett
= 0; ett
< NUM_EDITOR_TOOL_TYPES
; ett
++) {
657 if (editor_tool_has_value(ett
)) {
658 refresh_tool_value_selector(eb
, ett
);
663 /****************************************************************************
664 Refresh the given toolbar according to the current editor state.
665 ****************************************************************************/
666 static void editbar_refresh(struct editbar
*eb
)
668 if (eb
== NULL
|| eb
->widget
== NULL
) {
672 if (!editor_is_active()) {
673 gtk_widget_hide_all(eb
->widget
);
677 refresh_all_buttons(eb
);
678 refresh_all_tool_value_selectors(eb
);
679 refresh_player_pov_indicator(eb
);
681 gtk_widget_show_all(eb
->widget
);
684 /****************************************************************************
685 Create a pixbuf containing a representative image for the given extra
686 type, to be used as an icon in the GUI.
688 May return NULL on error.
690 NB: You must call g_object_unref on the non-NULL return value when you
692 ****************************************************************************/
693 static GdkPixbuf
*create_extra_pixbuf(const struct extra_type
*pextra
)
695 struct drawn_sprite sprs
[80];
696 int count
, w
, h
, canvas_x
, canvas_y
;
698 struct canvas canvas
;
700 w
= tileset_tile_width(tileset
);
701 h
= tileset_tile_height(tileset
);
703 pixbuf
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, TRUE
, 8, w
, h
);
704 if (pixbuf
== NULL
) {
707 gdk_pixbuf_fill(pixbuf
, 0x00000000);
709 canvas
.type
= CANVAS_PIXBUF
;
710 canvas
.v
.pixbuf
= pixbuf
;
714 count
= fill_basic_extra_sprite_array(tileset
, sprs
, pextra
);
715 put_drawn_sprites(&canvas
, 1.0, canvas_x
, canvas_y
, count
, sprs
, FALSE
);
720 /****************************************************************************
721 Create a pixbuf containing a representative image for the given terrain
722 type, to be used as an icon in the GUI.
724 May return NULL on error.
726 NB: You must call g_object_unref on the non-NULL return value when you
728 ****************************************************************************/
729 static GdkPixbuf
*create_terrain_pixbuf(struct terrain
*pterrain
)
731 struct drawn_sprite sprs
[80];
732 int count
, w
, h
, canvas_x
, canvas_y
, i
;
734 struct canvas canvas
;
736 w
= tileset_tile_width(tileset
);
737 h
= tileset_tile_height(tileset
);
739 pixbuf
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, TRUE
, 8, w
, h
);
740 if (pixbuf
== NULL
) {
743 gdk_pixbuf_fill(pixbuf
, 0x00000000);
745 canvas
.type
= CANVAS_PIXBUF
;
746 canvas
.v
.pixbuf
= pixbuf
;
750 for (i
= 0; i
< 3; i
++) {
751 count
= fill_basic_terrain_layer_sprite_array(tileset
, sprs
,
753 put_drawn_sprites(&canvas
, 1.0, canvas_x
, canvas_y
, count
, sprs
, FALSE
);
759 /****************************************************************************
760 Reload all tool value data from the tileset for the given toolbar.
761 ****************************************************************************/
762 static void editbar_reload_tileset(struct editbar
*eb
)
767 struct sprite
*sprite
;
768 struct tool_value_selector
*tvs
;
770 if (eb
== NULL
|| tileset
== NULL
) {
775 /* Reload terrains. */
777 tvs
= eb
->tool_selectors
[ETT_TERRAIN
];
779 gtk_list_store_clear(store
);
781 terrain_type_iterate(pterrain
) {
782 gtk_list_store_append(store
, &iter
);
783 gtk_list_store_set(store
, &iter
,
784 TVS_COL_ID
, terrain_number(pterrain
),
785 TVS_COL_NAME
, terrain_name_translation(pterrain
),
787 pixbuf
= create_terrain_pixbuf(pterrain
);
788 if (pixbuf
!= NULL
) {
789 gtk_list_store_set(store
, &iter
, TVS_COL_IMAGE
, pixbuf
, -1);
790 g_object_unref(pixbuf
);
792 } terrain_type_iterate_end
;
795 /* Reload terrain resources. */
797 tvs
= eb
->tool_selectors
[ETT_TERRAIN_RESOURCE
];
799 gtk_list_store_clear(store
);
801 resource_type_iterate(presource
) {
802 gtk_list_store_append(store
, &iter
);
803 gtk_list_store_set(store
, &iter
,
804 TVS_COL_ID
, resource_number(presource
),
805 TVS_COL_NAME
, resource_name_translation(presource
),
807 sprite
= get_resource_sprite(tileset
, presource
);
808 if (sprite
== NULL
) {
811 pixbuf
= sprite_get_pixbuf(sprite
);
812 if (pixbuf
!= NULL
) {
813 gtk_list_store_set(store
, &iter
, TVS_COL_IMAGE
, pixbuf
, -1);
814 /* pixbuf unref will happen automatically when the sprite it was gotten
815 * from gets freed. */
817 } resource_type_iterate_end
;
820 /* Reload terrain specials. */
822 tvs
= eb
->tool_selectors
[ETT_TERRAIN_SPECIAL
];
824 gtk_list_store_clear(store
);
826 extra_type_by_cause_iterate(EC_SPECIAL
, pextra
) {
827 gtk_list_store_append(store
, &iter
);
828 gtk_list_store_set(store
, &iter
,
829 TVS_COL_ID
, extra_index(pextra
),
830 TVS_COL_NAME
, extra_name_translation(pextra
),
832 pixbuf
= create_extra_pixbuf(pextra
);
833 if (pixbuf
!= NULL
) {
834 gtk_list_store_set(store
, &iter
, TVS_COL_IMAGE
, pixbuf
, -1);
835 g_object_unref(pixbuf
);
837 } extra_type_by_cause_iterate_end
;
839 tvs
= eb
->tool_selectors
[ETT_ROAD
];
841 gtk_list_store_clear(store
);
843 extra_type_by_cause_iterate(EC_ROAD
, pextra
) {
844 gtk_list_store_append(store
, &iter
);
845 gtk_list_store_set(store
, &iter
,
846 TVS_COL_ID
, extra_index(pextra
),
847 TVS_COL_NAME
, extra_name_translation(pextra
),
849 pixbuf
= create_extra_pixbuf(pextra
);
850 if (pixbuf
!= NULL
) {
851 gtk_list_store_set(store
, &iter
, TVS_COL_IMAGE
, pixbuf
, -1);
852 g_object_unref(pixbuf
);
854 } extra_type_by_cause_iterate_end
;
856 /* Reload military bases. */
858 tvs
= eb
->tool_selectors
[ETT_MILITARY_BASE
];
860 gtk_list_store_clear(store
);
862 extra_type_by_cause_iterate(EC_BASE
, pextra
) {
863 gtk_list_store_append(store
, &iter
);
864 gtk_list_store_set(store
, &iter
,
865 TVS_COL_ID
, extra_index(pextra
),
866 TVS_COL_NAME
, extra_name_translation(pextra
),
868 pixbuf
= create_extra_pixbuf(pextra
);
869 if (pixbuf
!= NULL
) {
870 gtk_list_store_set(store
, &iter
, TVS_COL_IMAGE
, pixbuf
, -1);
871 g_object_unref(pixbuf
);
873 } extra_type_by_cause_iterate_end
;
876 /* Reload unit types. */
878 tvs
= eb
->tool_selectors
[ETT_UNIT
];
880 gtk_list_store_clear(store
);
882 unit_type_iterate(putype
) {
883 gtk_list_store_append(store
, &iter
);
884 gtk_list_store_set(store
, &iter
,
885 TVS_COL_ID
, utype_number(putype
),
886 TVS_COL_NAME
, utype_name_translation(putype
),
888 sprite
= get_unittype_sprite(tileset
, putype
, direction8_invalid(),
890 if (sprite
== NULL
) {
893 pixbuf
= sprite_get_pixbuf(sprite
);
894 if (pixbuf
!= NULL
) {
895 gtk_list_store_set(store
, &iter
, TVS_COL_IMAGE
, pixbuf
, -1);
896 /* pixbuf unref will happen automatically when the sprite it was gotten
897 * from gets freed. */
899 } unit_type_iterate_end
;
902 /****************************************************************************
903 Convert gdk modifier values to editor modifier values.
904 ****************************************************************************/
905 static int convert_modifiers(int gdk_event_state
)
907 int modifiers
= EKM_NONE
;
909 if (gdk_event_state
& GDK_SHIFT_MASK
) {
910 modifiers
|= EKM_SHIFT
;
912 if (gdk_event_state
& GDK_CONTROL_MASK
) {
913 modifiers
|= EKM_CTRL
;
915 if (gdk_event_state
& GDK_MOD1_MASK
) {
916 modifiers
|= EKM_ALT
;
922 /****************************************************************************
923 Convert gdk mouse button values to editor mouse button values.
924 ****************************************************************************/
925 static int convert_mouse_button(int gdk_mouse_button
)
927 switch (gdk_mouse_button
) {
929 return MOUSE_BUTTON_LEFT
;
932 return MOUSE_BUTTON_MIDDLE
;
935 return MOUSE_BUTTON_RIGHT
;
941 return MOUSE_BUTTON_OTHER
;
944 /****************************************************************************
945 Pass on the gdk mouse event to the editor's handler.
946 ****************************************************************************/
947 gboolean
handle_edit_mouse_button_press(GdkEventButton
*ev
)
949 if (ev
->type
!= GDK_BUTTON_PRESS
) {
953 editor_mouse_button_press(ev
->x
, ev
->y
,
954 convert_mouse_button(ev
->button
),
955 convert_modifiers(ev
->state
));
960 /****************************************************************************
961 Pass on the gdk mouse event to the editor's handler.
962 ****************************************************************************/
963 gboolean
handle_edit_mouse_button_release(GdkEventButton
*ev
)
965 if (ev
->type
!= GDK_BUTTON_RELEASE
) {
969 editor_mouse_button_release(ev
->x
, ev
->y
,
970 convert_mouse_button(ev
->button
),
971 convert_modifiers(ev
->state
));
975 /****************************************************************************
976 Pass on the gdk mouse event to the editor's handler.
977 ****************************************************************************/
978 gboolean
handle_edit_mouse_move(GdkEventMotion
*ev
)
980 editor_mouse_move(ev
->x
, ev
->y
, convert_modifiers(ev
->state
));
984 /****************************************************************************
985 Handle a double-click on the tool value list.
986 ****************************************************************************/
987 static void tool_value_selector_treeview_row_activated(GtkTreeView
*view
,
989 GtkTreeViewColumn
*col
,
992 struct tool_value_selector
*tvs
= user_data
;
994 gtk_dialog_response(GTK_DIALOG(tvs
->dialog
), GTK_RESPONSE_ACCEPT
);
997 /****************************************************************************
998 Create a tool value selection dialog for the given toolbar.
999 ****************************************************************************/
1000 static struct tool_value_selector
*
1001 create_tool_value_selector(struct editbar
*eb
,
1002 enum editor_tool_type ett
)
1004 struct tool_value_selector
*tvs
;
1005 GtkWidget
*vbox
, *view
, *scrollwin
;
1006 GtkCellRenderer
*cell
;
1007 GtkListStore
*store
;
1008 GtkTreeViewColumn
*col
;
1009 GtkTreeSelection
*sel
;
1011 tvs
= fc_calloc(1, sizeof(struct tool_value_selector
));
1013 tvs
->editbar_parent
= eb
;
1015 tvs
->dialog
= gtk_dialog_new_with_buttons(_("Select Tool Value"),
1016 GTK_WINDOW(toplevel
), GTK_DIALOG_MODAL
,
1017 GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
,
1018 GTK_STOCK_CANCEL
, GTK_RESPONSE_REJECT
,
1020 vbox
= GTK_DIALOG(tvs
->dialog
)->vbox
;
1022 store
= gtk_list_store_new(TVS_NUM_COLS
,
1028 scrollwin
= gtk_scrolled_window_new(NULL
, NULL
);
1029 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin
),
1030 GTK_SHADOW_ETCHED_IN
);
1031 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin
),
1033 GTK_POLICY_AUTOMATIC
);
1034 gtk_box_pack_start(GTK_BOX(vbox
), scrollwin
, TRUE
, TRUE
, 0);
1036 view
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(tvs
->store
));
1037 gtk_widget_set_size_request(view
, -1, 10 * tileset_tile_height(tileset
));
1038 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view
), TRUE
);
1039 gtk_tree_view_set_search_column(GTK_TREE_VIEW(view
), TVS_COL_NAME
);
1040 g_signal_connect(view
, "row-activated",
1041 G_CALLBACK(tool_value_selector_treeview_row_activated
), tvs
);
1043 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(view
));
1044 gtk_tree_selection_set_mode(sel
, GTK_SELECTION_SINGLE
);
1046 cell
= gtk_cell_renderer_pixbuf_new();
1047 col
= gtk_tree_view_column_new_with_attributes(editor_tool_get_name(ett
),
1049 TVS_COL_IMAGE
, NULL
);
1050 gtk_tree_view_column_set_resizable(col
, FALSE
);
1051 gtk_tree_view_column_set_sizing(col
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1052 gtk_tree_view_column_set_reorderable(col
, FALSE
);
1053 gtk_tree_view_column_set_clickable(col
, FALSE
);
1054 gtk_tree_view_append_column(GTK_TREE_VIEW(view
), col
);
1056 cell
= gtk_cell_renderer_text_new();
1057 col
= gtk_tree_view_column_new_with_attributes("ID", cell
,
1058 "text", TVS_COL_ID
, NULL
);
1059 gtk_tree_view_column_set_resizable(col
, FALSE
);
1060 gtk_tree_view_column_set_sizing(col
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1061 gtk_tree_view_column_set_reorderable(col
, FALSE
);
1062 gtk_tree_view_column_set_clickable(col
, FALSE
);
1063 gtk_tree_view_column_set_sort_column_id(col
, TVS_COL_ID
);
1064 gtk_tree_view_append_column(GTK_TREE_VIEW(view
), col
);
1066 cell
= gtk_cell_renderer_text_new();
1067 col
= gtk_tree_view_column_new_with_attributes("Name", cell
,
1068 "text", TVS_COL_NAME
, NULL
);
1069 gtk_tree_view_column_set_resizable(col
, FALSE
);
1070 gtk_tree_view_column_set_sizing(col
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1071 gtk_tree_view_column_set_reorderable(col
, FALSE
);
1072 gtk_tree_view_column_set_clickable(col
, FALSE
);
1073 gtk_tree_view_column_set_sort_column_id(col
, TVS_COL_NAME
);
1074 gtk_tree_view_append_column(GTK_TREE_VIEW(view
), col
);
1076 gtk_container_add(GTK_CONTAINER(scrollwin
), view
);
1079 /* Show everything but the window itself. */
1080 gtk_widget_show_all(vbox
);
1085 /****************************************************************************
1086 Handle a mouse click on the tool image area in the editor info box.
1087 ****************************************************************************/
1088 static gboolean
editinfobox_handle_tool_image_button_press(GtkWidget
*evbox
,
1092 editgui_run_tool_selection(editor_get_tool());
1096 /****************************************************************************
1097 Handle a mouse click on the mode image area in the editor info box.
1098 ****************************************************************************/
1099 static gboolean
editinfobox_handle_mode_image_button_press(GtkWidget
*evbox
,
1103 editor_tool_cycle_mode(editor_get_tool());
1109 /****************************************************************************
1110 Callback for spin button changes in the editor info box.
1111 ****************************************************************************/
1112 static void editinfobox_spin_button_value_changed(GtkSpinButton
*spinbutton
,
1115 struct editinfobox
*ei
;
1117 enum editor_tool_type ett
;
1119 ei
= editgui_get_editinfobox();
1125 value
= gtk_spin_button_get_value_as_int(spinbutton
);
1126 which
= GPOINTER_TO_INT(userdata
);
1127 ett
= editor_get_tool();
1130 case SPIN_BUTTON_SIZE
:
1131 editor_tool_set_size(ett
, value
);
1133 case SPIN_BUTTON_COUNT
:
1134 editor_tool_set_count(ett
, value
);
1141 editinfobox_refresh(ei
);
1144 /****************************************************************************
1145 Callback for changes in the applied player combobox in the editor
1147 ****************************************************************************/
1148 static void editinfobox_tool_applied_player_changed(GtkComboBox
*combo
,
1151 struct editinfobox
*ei
= userdata
;
1153 GtkTreeModel
*model
;
1160 if (!gtk_combo_box_get_active_iter(combo
, &iter
)) {
1164 model
= gtk_combo_box_get_model(combo
);
1165 gtk_tree_model_get(model
, &iter
, TAP_COL_PLAYER_NO
, &player_no
, -1);
1167 editor_tool_set_applied_player(editor_get_tool(), player_no
);
1170 /****************************************************************************
1171 Create and return an editor info box widget bundle.
1172 ****************************************************************************/
1173 static struct editinfobox
*editinfobox_create(void)
1175 GtkWidget
*label
, *vbox
, *frame
, *hbox
, *vbox2
, *image
, *evbox
;
1176 GtkWidget
*spin
, *combo
;
1177 GtkListStore
*store
;
1178 GtkCellRenderer
*cell
;
1179 struct editinfobox
*ei
;
1182 ei
= fc_calloc(1, sizeof(*ei
));
1184 frame
= gtk_frame_new(_("Editor Tool"));
1185 gtk_container_set_border_width(GTK_CONTAINER(frame
), 4);
1188 vbox
= gtk_vbox_new(FALSE
, 8);
1189 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 4);
1190 gtk_container_add(GTK_CONTAINER(frame
), vbox
);
1193 hbox
= gtk_hbox_new(FALSE
, 8);
1194 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
1196 evbox
= gtk_event_box_new();
1197 gtk_widget_set_tooltip_text(evbox
, _("Click to change value if applicable."));
1198 g_signal_connect(evbox
, "button_press_event",
1199 G_CALLBACK(editinfobox_handle_tool_image_button_press
), NULL
);
1200 gtk_box_pack_start(GTK_BOX(hbox
), evbox
, FALSE
, FALSE
, 0);
1202 image
= gtk_image_new();
1203 gtk_container_add(GTK_CONTAINER(evbox
), image
);
1204 ei
->tool_image
= image
;
1206 vbox2
= gtk_vbox_new(FALSE
, 4);
1207 gtk_box_pack_start(GTK_BOX(hbox
), vbox2
, FALSE
, FALSE
, 0);
1209 label
= gtk_label_new(NULL
);
1210 gtk_misc_set_alignment(GTK_MISC(label
), 0.0, 0.5);
1211 gtk_box_pack_start(GTK_BOX(vbox2
), label
, FALSE
, FALSE
, 0);
1212 ei
->tool_label
= label
;
1214 label
= gtk_label_new(NULL
);
1215 gtk_misc_set_alignment(GTK_MISC(label
), 0.0, 0.5);
1216 gtk_box_pack_start(GTK_BOX(vbox2
), label
, FALSE
, FALSE
, 0);
1217 ei
->tool_value_label
= label
;
1220 hbox
= gtk_hbox_new(FALSE
, 8);
1221 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
1223 evbox
= gtk_event_box_new();
1224 gtk_widget_set_tooltip_text(evbox
, _("Click to change tool mode."));
1225 g_signal_connect(evbox
, "button_press_event",
1226 G_CALLBACK(editinfobox_handle_mode_image_button_press
), NULL
);
1227 gtk_box_pack_start(GTK_BOX(hbox
), evbox
, FALSE
, FALSE
, 0);
1229 image
= gtk_image_new();
1230 gtk_container_add(GTK_CONTAINER(evbox
), image
);
1231 ei
->mode_image
= image
;
1233 vbox2
= gtk_vbox_new(FALSE
, 4);
1234 gtk_box_pack_start(GTK_BOX(hbox
), vbox2
, FALSE
, FALSE
, 0);
1236 label
= gtk_label_new(NULL
);
1237 fc_snprintf(buf
, sizeof(buf
), "<span weight=\"bold\">%s</span>",
1239 gtk_label_set_markup(GTK_LABEL(label
), buf
);
1240 gtk_misc_set_alignment(GTK_MISC(label
), 0.0, 0.5);
1241 gtk_box_pack_start(GTK_BOX(vbox2
), label
, FALSE
, FALSE
, 0);
1243 label
= gtk_label_new(NULL
);
1244 gtk_misc_set_alignment(GTK_MISC(label
), 0.0, 0.5);
1245 gtk_box_pack_start(GTK_BOX(vbox2
), label
, FALSE
, FALSE
, 0);
1246 ei
->mode_label
= label
;
1248 /* spinner section */
1249 hbox
= gtk_hbox_new(FALSE
, 8);
1250 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
1251 ei
->size_hbox
= hbox
;
1252 spin
= gtk_spin_button_new_with_range(1, 255, 1);
1253 gtk_widget_set_tooltip_text(spin
,
1254 _("Use this to change the \"size\" parameter for the tool. "
1255 "This parameter controls for example the half-width "
1256 "of the square of tiles that will be affected by the "
1257 "tool, or the size of a created city."));
1258 g_signal_connect(spin
, "value-changed",
1259 G_CALLBACK(editinfobox_spin_button_value_changed
),
1260 GINT_TO_POINTER(SPIN_BUTTON_SIZE
));
1261 gtk_box_pack_start(GTK_BOX(hbox
), spin
, FALSE
, FALSE
, 0);
1262 ei
->size_spin_button
= spin
;
1263 label
= gtk_label_new(_("Size"));
1264 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
1266 hbox
= gtk_hbox_new(FALSE
, 8);
1267 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
1268 ei
->count_hbox
= hbox
;
1269 spin
= gtk_spin_button_new_with_range(1, 255, 1);
1270 gtk_widget_set_tooltip_text(spin
,
1271 _("Use this to change the tool's \"count\" parameter. "
1272 "This controls for example how many units are placed "
1273 "at once with the unit tool."));
1274 g_signal_connect(spin
, "value-changed",
1275 G_CALLBACK(editinfobox_spin_button_value_changed
),
1276 GINT_TO_POINTER(SPIN_BUTTON_COUNT
));
1277 gtk_box_pack_start(GTK_BOX(hbox
), spin
, FALSE
, FALSE
, 0);
1278 ei
->count_spin_button
= spin
;
1279 label
= gtk_label_new(_("Count"));
1280 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
1283 store
= gtk_list_store_new(TAP_NUM_COLS
,
1287 ei
->tool_applied_player_store
= store
;
1288 combo
= gtk_combo_box_new_with_model(GTK_TREE_MODEL(store
));
1290 cell
= gtk_cell_renderer_pixbuf_new();
1291 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo
), cell
, FALSE
);
1292 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo
),
1293 cell
, "pixbuf", TAP_COL_FLAG
);
1295 cell
= gtk_cell_renderer_text_new();
1296 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo
), cell
, TRUE
);
1297 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo
),
1298 cell
, "text", TAP_COL_NAME
);
1300 gtk_widget_set_size_request(combo
, 132, -1);
1301 g_signal_connect(combo
, "changed",
1302 G_CALLBACK(editinfobox_tool_applied_player_changed
), ei
);
1304 evbox
= gtk_event_box_new();
1305 gtk_widget_set_tooltip_text(evbox
,
1306 _("Use this to change the \"applied player\" tool parameter. "
1307 "This controls for example under which player units and cities "
1309 gtk_container_add(GTK_CONTAINER(evbox
), combo
);
1310 gtk_box_pack_start(GTK_BOX(vbox
), evbox
, FALSE
, FALSE
, 0);
1311 ei
->tool_applied_player_combobox
= combo
;
1313 /* We add a ref to the editinfobox widget so that it is
1314 * not destroyed when replaced by the unit info box when
1315 * we leave edit mode. See editinfobox_refresh(). */
1316 g_object_ref(ei
->widget
);
1318 /* The edit info box starts with no parent, so we have to
1319 * show its internal widgets manually. */
1320 gtk_widget_show_all(ei
->widget
);
1325 /****************************************************************************
1326 Refresh the given editinfobox's applied player combobox according to the
1327 current editor state.
1328 ****************************************************************************/
1329 static void refresh_tool_applied_player_combo(struct editinfobox
*ei
)
1331 enum editor_tool_type ett
;
1332 GtkListStore
*store
;
1342 ett
= editor_get_tool();
1343 combo
= ei
->tool_applied_player_combobox
;
1344 store
= ei
->tool_applied_player_store
;
1346 if (!combo
|| !store
) {
1350 if (!editor_tool_has_applied_player(ett
)) {
1351 gtk_widget_hide(combo
);
1355 gtk_list_store_clear(store
);
1357 apno
= editor_tool_get_applied_player(ett
);
1361 players_iterate(pplayer
) {
1362 gtk_list_store_append(store
, &iter
);
1363 gtk_list_store_set(store
, &iter
,
1364 TAP_COL_PLAYER_NO
, player_number(pplayer
),
1365 TAP_COL_NAME
, player_name(pplayer
), -1);
1367 if (pplayer
->nation
!= NO_NATION_SELECTED
) {
1368 flag
= get_flag(pplayer
->nation
);
1371 gtk_list_store_set(store
, &iter
, TAP_COL_FLAG
, flag
, -1);
1372 g_object_unref(flag
);
1375 if (apno
== player_number(pplayer
)) {
1379 } players_iterate_end
;
1382 if (player_count() > 0) {
1385 editor_tool_set_applied_player(ett
, index
);
1387 gtk_combo_box_set_active(GTK_COMBO_BOX(combo
), index
);
1388 gtk_widget_show(combo
);
1391 /****************************************************************************
1392 Return a pixbuf containing an image for the given editor tool sub-value,
1395 NB: Can return NULL. Must call g_object_unref on non-NULL when done.
1396 ****************************************************************************/
1397 static GdkPixbuf
*get_tool_value_pixbuf(enum editor_tool_type ett
,
1400 struct sprite
*sprite
= NULL
;
1401 GdkPixbuf
*pixbuf
= NULL
;
1402 struct terrain
*pterrain
;
1403 struct resource
*presource
;
1404 struct unit_type
*putype
;
1405 const struct editor_sprites
*sprites
;
1407 sprites
= get_editor_sprites(tileset
);
1414 pterrain
= terrain_by_number(value
);
1416 pixbuf
= create_terrain_pixbuf(pterrain
);
1419 case ETT_TERRAIN_RESOURCE
:
1420 presource
= resource_by_number(value
);
1422 sprite
= get_resource_sprite(tileset
, presource
);
1425 case ETT_TERRAIN_SPECIAL
:
1427 case ETT_MILITARY_BASE
:
1429 pixbuf
= create_extra_pixbuf(extra_by_number(value
));
1433 putype
= utype_by_number(value
);
1435 sprite
= get_unittype_sprite(tileset
, putype
, direction8_invalid(),
1440 sprite
= sprites
->city
;
1443 sprite
= sprites
->vision
;
1446 sprite
= sprites
->startpos
;
1449 sprite
= sprites
->copypaste
;
1456 pixbuf
= sprite_get_pixbuf(sprite
);
1458 g_object_ref(pixbuf
);
1466 /****************************************************************************
1467 Return a pixbuf containing an image suitable for use as an icon
1468 respresenting the given editor tool mode.
1470 NB: May return NULL. Must call g_object_unref on non-NULL when done.
1471 ****************************************************************************/
1472 static GdkPixbuf
*get_tool_mode_pixbuf(enum editor_tool_mode etm
)
1474 struct sprite
*sprite
= NULL
;
1475 GdkPixbuf
*pixbuf
= NULL
;
1477 sprite
= editor_get_mode_sprite(etm
);
1480 pixbuf
= sprite_get_pixbuf(sprite
);
1482 g_object_ref(pixbuf
);
1489 /****************************************************************************
1490 NB: Assumes that widget 'old' has enough references to not be destroyed
1491 when removed from its parent container, and that the parent container
1492 is a GtkBox (or is descended from it).
1493 ****************************************************************************/
1494 static void replace_widget(GtkWidget
*old
, GtkWidget
*new)
1498 parent
= gtk_widget_get_parent(old
);
1503 gtk_container_remove(GTK_CONTAINER(parent
), old
);
1504 gtk_box_pack_start(GTK_BOX(parent
), new, FALSE
, FALSE
, 0);
1507 /****************************************************************************
1508 Refresh the given editinfobox according to the current editor state.
1509 ****************************************************************************/
1510 static void editinfobox_refresh(struct editinfobox
*ei
)
1512 GdkPixbuf
*pixbuf
= NULL
;
1514 enum editor_tool_type ett
;
1515 enum editor_tool_mode etm
;
1523 if (!editor_is_active()) {
1524 replace_widget(ei
->widget
, unit_info_box
);
1528 ett
= editor_get_tool();
1529 etm
= editor_tool_get_mode(ett
);
1530 value
= editor_tool_get_value(ett
);
1532 label
= GTK_LABEL(ei
->mode_label
);
1533 gtk_label_set_text(label
, editor_tool_get_mode_name(ett
, etm
));
1535 pixbuf
= get_tool_mode_pixbuf(etm
);
1536 gtk_image_set_from_pixbuf(GTK_IMAGE(ei
->mode_image
), pixbuf
);
1538 g_object_unref(pixbuf
);
1542 fc_snprintf(buf
, sizeof(buf
), "<span weight=\"bold\">%s</span>",
1543 editor_tool_get_name(ett
));
1544 gtk_label_set_markup(GTK_LABEL(ei
->tool_label
), buf
);
1546 if (etm
== ETM_COPY
|| etm
== ETM_PASTE
) {
1547 struct edit_buffer
*ebuf
;
1551 ebuf
= editor_get_copy_buffer();
1552 edit_buffer_get_status_string(ebuf
, status
, sizeof(status
));
1553 gtk_label_set_text(GTK_LABEL(ei
->tool_value_label
), status
);
1555 spr
= editor_tool_get_sprite(ett
);
1556 pixbuf
= spr
? sprite_get_pixbuf(spr
) : NULL
;
1557 gtk_image_set_from_pixbuf(GTK_IMAGE(ei
->tool_image
), pixbuf
);
1560 pixbuf
= get_tool_value_pixbuf(ett
, value
);
1561 gtk_image_set_from_pixbuf(GTK_IMAGE(ei
->tool_image
), pixbuf
);
1563 g_object_unref(pixbuf
);
1566 gtk_label_set_text(GTK_LABEL(ei
->tool_value_label
),
1567 editor_tool_get_value_name(ett
, value
));
1570 if (editor_tool_has_size(ett
)) {
1571 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ei
->size_spin_button
),
1572 editor_tool_get_size(ett
));
1573 gtk_widget_show(ei
->size_hbox
);
1575 gtk_widget_hide(ei
->size_hbox
);
1578 if (editor_tool_has_count(ett
)) {
1579 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ei
->count_spin_button
),
1580 editor_tool_get_count(ett
));
1581 gtk_widget_show(ei
->count_hbox
);
1583 gtk_widget_hide(ei
->count_hbox
);
1586 refresh_tool_applied_player_combo(ei
);
1588 replace_widget(unit_info_box
, ei
->widget
);
1591 /****************************************************************************
1592 Handle ctrl+<key> combinations.
1593 ****************************************************************************/
1594 static gboolean
handle_edit_key_press_with_ctrl(GdkEventKey
*ev
)
1596 return FALSE
; /* Don't gobble. */
1599 /****************************************************************************
1600 Handle shift+<key> combinations.
1601 ****************************************************************************/
1602 static gboolean
handle_edit_key_press_with_shift(GdkEventKey
*ev
)
1604 enum editor_tool_type ett
;
1606 ett
= editor_get_tool();
1607 switch (ev
->keyval
) {
1609 editor_tool_toggle_mode(ett
, ETM_ERASE
);
1612 editor_set_tool(ETT_COPYPASTE
);
1613 editor_tool_toggle_mode(ett
, ETM_COPY
);
1616 editor_set_tool(ETT_COPYPASTE
);
1617 editor_tool_toggle_mode(ett
, ETM_PASTE
);
1620 editgui_run_tool_selection(ETT_TERRAIN
);
1623 editgui_run_tool_selection(ETT_TERRAIN_RESOURCE
);
1626 editgui_run_tool_selection(ETT_TERRAIN_SPECIAL
);
1629 editgui_run_tool_selection(ETT_ROAD
);
1632 editgui_run_tool_selection(ETT_MILITARY_BASE
);
1635 editgui_run_tool_selection(ETT_UNIT
);
1638 return TRUE
; /* Gobble? */
1647 /****************************************************************************
1648 Handle any kind of key press event.
1649 ****************************************************************************/
1650 gboolean
handle_edit_key_press(GdkEventKey
*ev
)
1652 enum editor_tool_type ett
, new_ett
= NUM_EDITOR_TOOL_TYPES
;
1654 if (ev
->state
& GDK_SHIFT_MASK
) {
1655 return handle_edit_key_press_with_shift(ev
);
1658 if (ev
->state
& GDK_CONTROL_MASK
) {
1659 return handle_edit_key_press_with_ctrl(ev
);
1662 ett
= editor_get_tool();
1664 switch (ev
->keyval
) {
1666 new_ett
= ETT_TERRAIN
;
1669 new_ett
= ETT_TERRAIN_RESOURCE
;
1672 new_ett
= ETT_TERRAIN_SPECIAL
;
1678 new_ett
= ETT_MILITARY_BASE
;
1687 new_ett
= ETT_VISION
;
1690 new_ett
= ETT_STARTPOS
;
1695 if (editor_tool_has_size(ett
)) {
1696 int size
= editor_tool_get_size(ett
);
1697 editor_tool_set_size(ett
, size
+ 1);
1698 } else if (editor_tool_has_count(ett
)) {
1699 int count
= editor_tool_get_count(ett
);
1700 editor_tool_set_count(ett
, count
+ 1);
1704 case GDK_underscore
:
1705 case GDK_KP_Subtract
:
1706 if (editor_tool_has_size(ett
)) {
1707 int size
= editor_tool_get_size(ett
);
1708 editor_tool_set_size(ett
, size
- 1);
1709 } else if (editor_tool_has_count(ett
)) {
1710 int count
= editor_tool_get_count(ett
);
1711 editor_tool_set_count(ett
, count
- 1);
1723 if (editor_tool_has_size(ett
)) {
1724 editor_tool_set_size(ett
, ev
->keyval
- GDK_1
+ 1);
1725 } else if (editor_tool_has_count(ett
)) {
1726 editor_tool_set_count(ett
, ev
->keyval
- GDK_1
+ 1);
1730 editor_apply_tool_to_selection();
1733 editgui_run_tool_selection(ett
);
1747 return FALSE
; /* Allow default handler. */
1750 return TRUE
; /* Gobbled... */
1754 if (new_ett
!= NUM_EDITOR_TOOL_TYPES
) {
1755 try_to_set_editor_tool(new_ett
);
1763 /****************************************************************************
1764 Key release handler.
1765 ****************************************************************************/
1766 gboolean
handle_edit_key_release(GdkEventKey
*ev
)
1771 /****************************************************************************
1772 Get the pointer for the editbar embedded in the client's GUI.
1773 ****************************************************************************/
1774 struct editbar
*editgui_get_editbar(void)
1776 return editor_toolbar
;
1779 /****************************************************************************
1780 Refresh all editor GUI widgets according to the current editor state.
1781 ****************************************************************************/
1782 void editgui_refresh(void)
1784 struct property_editor
*pe
;
1786 struct editinfobox
*ei
;
1788 eb
= editgui_get_editbar();
1790 editbar_refresh(eb
);
1793 ei
= editgui_get_editinfobox();
1795 editinfobox_refresh(ei
);
1798 pe
= editprop_get_property_editor();
1799 if (!editor_is_active()) {
1800 property_editor_clear(pe
);
1801 property_editor_popdown(pe
);
1805 /****************************************************************************
1806 Create all editor GUI widgets.
1807 ****************************************************************************/
1808 void editgui_create_widgets(void)
1810 if (editor_toolbar
== NULL
) {
1811 editor_toolbar
= editbar_create();
1813 if (editor_infobox
== NULL
) {
1814 editor_infobox
= editinfobox_create();
1818 /****************************************************************************
1819 Return a pointer to the editor info box embedded in the client's GUI.
1820 ****************************************************************************/
1821 struct editinfobox
*editgui_get_editinfobox(void)
1823 return editor_infobox
;
1826 /****************************************************************************
1827 Update all editor widget internal data for the new tileset. Call this
1828 after a new tileset has finished loading.
1829 ****************************************************************************/
1830 void editgui_tileset_changed(void)
1832 editbar_reload_tileset(editgui_get_editbar());
1833 editinfobox_refresh(editgui_get_editinfobox());
1836 /****************************************************************************
1837 Popup the property editor. If 'tiles' is non-NULL, the tiles, units and
1838 cities in those tiles are added to the property editor's object list. If
1839 'objtype' is a valid object type, the corresponding page of the property
1840 editor notebook is focused. Otherwise which page is focused depends on
1841 what was loaded from 'tiles'.
1842 ****************************************************************************/
1843 void editgui_popup_properties(const struct tile_list
*tiles
, int objtype
)
1845 struct property_editor
*pe
;
1847 pe
= editprop_get_property_editor();
1848 property_editor_clear(pe
);
1849 property_editor_reload(pe
, OBJTYPE_PLAYER
);
1850 property_editor_reload(pe
, OBJTYPE_GAME
);
1851 property_editor_load_tiles(pe
, tiles
);
1852 property_editor_popup(pe
, objtype
);
1855 /****************************************************************************
1856 Popup all dialog window of the editor.
1857 ****************************************************************************/
1858 void editgui_popdown_all(void)
1860 struct property_editor
*pe
;
1862 pe
= editprop_get_property_editor();
1863 property_editor_popdown(pe
);
1864 property_editor_clear(pe
); /* And clear it. */
1867 /****************************************************************************
1868 This is called to notify the editor GUI that some object (e.g. tile, unit,
1869 etc.) has changed (usually because the corresponding packet was received)
1870 and that widgets displaying the object should be updated.
1872 Currently this is used to notify the property editor that some object
1873 has been removed or some property value has changed at the server.
1874 ****************************************************************************/
1875 void editgui_notify_object_changed(int objtype
, int object_id
, bool removal
)
1877 struct property_editor
*pe
;
1879 if (!editor_is_active()) {
1883 pe
= editprop_get_property_editor();
1884 property_editor_handle_object_changed(pe
, objtype
, object_id
, removal
);
1887 /****************************************************************************
1888 Pass on the object creation notification to the property editor.
1889 ****************************************************************************/
1890 void editgui_notify_object_created(int tag
, int id
)
1892 struct property_editor
*pe
;
1894 if (!editor_is_active()) {
1898 pe
= editprop_get_property_editor();
1899 property_editor_handle_object_created(pe
, tag
, id
);