Freeciv-3.2
Loading...
Searching...
No Matches
unitselect.c
Go to the documentation of this file.
1/*****************************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12*****************************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <gtk/gtk.h>
19
20/* utility */
21#include "fcintl.h"
22
23/* common */
24#include "fc_types.h"
25#include "game.h"
26#include "player.h"
27#include "unit.h"
28#include "unitlist.h"
29#include "unittype.h"
30
31/* client */
32#include "client_main.h"
33#include "control.h"
34#include "goto.h"
35#include "tilespec.h"
36#include "unitselect_common.h"
37
38/* client/gui-gtk-4.0 */
39#include "graphics.h"
40#include "gui_stuff.h"
41#include "gui_main.h"
42
43#include "unitselect.h"
44
45/* Activate this to get more columns (see below) */
46#undef DEBUG_USDLG
47
53
60
61/* Basic data (Unit, description, count) */
62#define USDLG_COLUMNS_DEFAULT 3
63/* Additional data; shown if DEBUG_USDLG */
64#define USDLG_COL_UTID USDLG_COLUMNS_DEFAULT + 0 /* Unit type ID */
65#define USDLG_COL_UID USDLG_COLUMNS_DEFAULT + 1 /* Unit ID */
66#define USDLG_COL_LOCATION USDLG_COLUMNS_DEFAULT + 2 /* Unit location */
67#define USDLG_COL_ACTIVITY USDLG_COLUMNS_DEFAULT + 3 /* Unit activity */
68#define USDLG_COL_ROW_TYPE USDLG_COLUMNS_DEFAULT + 4 /* Row type */
69#define USDLG_COLUMNS_DEBUG USDLG_COLUMNS_DEFAULT + 5
70/* Layout options; never shown */
71#define USDLG_COL_STYLE USDLG_COLUMNS_DEBUG + 0
72#define USDLG_COL_WEIGHT USDLG_COLUMNS_DEBUG + 1
73#define USDLG_COLUMNS_ALL USDLG_COLUMNS_DEBUG + 2
74
75#ifdef DEBUG_USDLG
76 #define USDLG_COLUMNS_SHOW USDLG_COLUMNS_DEBUG
77#else
78 #define USDLG_COLUMNS_SHOW USDLG_COLUMNS_DEFAULT
79#endif /* DEBUG_USDLG */
80
82 COL_PIXBUF, /* Unit */
83 COL_TEXT, /* Description */
84 COL_INT, /* Count */
85 COL_INT, /* Debug: unit type */
86 COL_INT, /* Debug: unit ID */
87 COL_INT, /* Debug: location */
88 COL_INT, /* Debug: activity */
89 COL_INT, /* Debug: row type */
90 COL_INT, /* Layout: style */
91 COL_INT /* Layout: width */
92};
93
94static const char *usdlg_col_titles[USDLG_COLUMNS_ALL] = {
95 N_("Unit"),
96 N_("Description"),
97 N_("Count"),
98 "[Unittype]", /* Only for debug, no translation! */
99 "[Unit ID]",
100 "[Location]",
101 "[Activity]",
102 "[Row type]",
103 "[Style]",
104 "[Width]"
105};
106
116
117struct unit_select_dialog {
118 struct tile *ptile;
119 int unit_id_focus;
120
123
124 struct {
125 GtkTreeStore *store;
127 GtkTreePath *path;
129
130 struct {
135
138};
139
140/* The unit selection dialog; should only be used in usdlg_get(). */
142
143static struct unit_select_dialog *usdlg_get(bool create);
144static struct unit_select_dialog *usdlg_create(void);
145static void usdlg_destroy(void);
146static void usdlg_destroy_callback(GObject *object, gpointer data);
147static void usdlg_tile(struct unit_select_dialog *pdialog,
148 struct tile *ptile);
149static void usdlg_refresh(struct unit_select_dialog *pdialog);
150
151static void usdlg_tab_select(struct unit_select_dialog *pdialog,
152 const char *title,
155static bool usdlg_tab_update(struct unit_select_dialog *pdialog,
156 struct usdata_hash *ushash,
160 const struct unit_type *putype,
161 GtkTreeIter *it);
164 const struct unit_type *putype,
165 enum unit_activity act,
166 int count, GtkTreeIter *it,
168static void usdlg_tab_append_units(struct unit_select_dialog *pdialog,
170 enum unit_activity act,
171 const struct unit *punit,
172 bool transported, GtkTreeIter *it,
174
175static void usdlg_cmd_ready(GObject *object, gpointer data);
176static void usdlg_cmd_sentry(GObject *object, gpointer data);
177static void usdlg_cmd_select(GObject *object, gpointer data);
178static void usdlg_cmd_deselect(GObject *object, gpointer data);
179static void usdlg_cmd_exec(GObject *object, gpointer mode_data,
180 enum usdlg_cmd cmd);
181static void usdlg_cmd_exec_unit(struct unit *punit, enum usdlg_cmd cmd);
182static void usdlg_cmd_center(GObject *object, gpointer data);
183static void usdlg_cmd_focus(GObject *object, gpointer data);
188
189
190/*************************************************************************/
193void unit_select_dialog_popup_main(struct tile *ptile, bool create)
194{
195 struct unit_select_dialog *pdialog;
196
197 /* Create the dialog if it is requested. */
198 pdialog = usdlg_get(create);
199
200 /* Present the unit selection dialog if it exists. */
201 if (pdialog) {
202 /* Show all. */
204 /* Update tile. */
205 usdlg_tile(pdialog, ptile);
206 /* Refresh data and hide unused tabs. */
207 usdlg_refresh(pdialog);
208 }
209}
210
211/*************************************************************************/
215{
217}
218
219/*************************************************************************/
223static struct unit_select_dialog *usdlg_get(bool create)
224{
225 if (unit_select_dlg) {
226 /* Return existing dialog. */
227 return unit_select_dlg;
228 } else if (create) {
229 /* Create new dialog. */
231 return unit_select_dlg;
232 } else {
233 /* Nothing. */
234 return NULL;
235 }
236}
237
238/*************************************************************************/
242{
243 GtkWidget *vbox;
245 struct unit_select_dialog *pdialog;
246
247 /* Create a container for the dialog. */
248 pdialog = fc_calloc(1, sizeof(*pdialog));
249
250 /* No tile defined. */
251 pdialog->ptile = NULL;
252
253 /* Create the dialog. */
254 pdialog->shell = gtk_dialog_new();
255 gtk_window_set_title(GTK_WINDOW(pdialog->shell), _("Unit selection"));
256 setup_dialog(pdialog->shell, toplevel);
257 g_signal_connect(pdialog->shell, "destroy",
259 gtk_widget_realize(pdialog->shell);
260
262
263 /* Notebook. */
264 pdialog->notebook = gtk_notebook_new();
268
269 /* Append pages. */
270 usdlg_tab_select(pdialog, _("_Units"), SELLOC_UNITS);
271 usdlg_tab_select(pdialog, _("_Tile"), SELLOC_TILE);
272 usdlg_tab_select(pdialog, _("C_ontinent"), SELLOC_CONT);
273 usdlg_tab_select(pdialog, _("_Land"), SELLOC_LAND);
274 usdlg_tab_select(pdialog, _("_Sea"), SELLOC_SEA);
275 usdlg_tab_select(pdialog, _("_Both"), SELLOC_BOTH);
276 usdlg_tab_select(pdialog, _("_World"), SELLOC_WORLD);
277
278 /* Buttons. */
280 _("_Close"), GTK_RESPONSE_CLOSE);
283 g_signal_connect(close_cmd, "clicked",
285
286 return pdialog;
287}
288
289/*************************************************************************/
300
301/*************************************************************************/
304static void usdlg_destroy_callback(GObject *object, gpointer data)
305{
307}
308
309/*************************************************************************/
312static void usdlg_tile(struct unit_select_dialog *pdialog,
313 struct tile *ptile)
314{
315 if (!pdialog) {
316 return;
317 }
318
319 /* Check for a valid tile. */
320 if (ptile != NULL) {
321 pdialog->ptile = ptile;
322 } else if (pdialog->ptile == NULL) {
324
325 if (punit) {
326 pdialog->ptile = unit_tile(punit);
328 } else {
329 pdialog->ptile = get_center_tile_mapcanvas();
330 }
331 }
332}
333
334/*************************************************************************/
337static void usdlg_refresh(struct unit_select_dialog *pdialog)
338{
339 struct usdata_hash *ushash = NULL;
341
342 if (!pdialog) {
343 return;
344 }
345
346 /* Sort units into the hash. */
347 ushash = usdlg_data_new(pdialog->ptile);
348 /* Update all tabs. */
352 bool show = usdlg_tab_update(pdialog, ushash, loc);
353
354 if (!show) {
356 } else {
358
359 if (pdialog->tabs[loc].path) {
361 pdialog->tabs[loc].path,FALSE);
363 pdialog->tabs[loc].path, NULL, FALSE);
364 gtk_tree_path_free(pdialog->tabs[loc].path);
365 pdialog->tabs[loc].path = NULL;
366 }
367 }
368 }
369
370 /* Destroy the hash. */
372}
373
374/*************************************************************************/
387static void usdlg_tab_select(struct unit_select_dialog *pdialog,
388 const char *title,
390{
391 GtkWidget *page, *label, *hgrid, *vgrid, *view, *sw;
392 GtkTreeStore *store;
393 static bool titles_done;
394 int i;
395 int page_row = 0;
396 int grid_col = 0;
397 int grid_row = 0;
398
399 page = gtk_grid_new();
406 pdialog->tabs[loc].page = page;
407
409 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
410
412 gtk_grid_attach(GTK_GRID(page), hgrid, 0, page_row++, 1, 1);
413
414 store = usdlg_tab_store_new();
415 pdialog->tabs[loc].store = store;
416
420 pdialog->tabs[loc].view = view;
421 g_object_unref(store);
422
425 g_signal_connect(view, "cursor-changed",
427
428 /* Translate titles. */
430
431 for (i = 0; i < USDLG_COLUMNS_SHOW; i++) {
433 GtkCellRenderer *renderer = NULL;
434
435 switch (usdlg_col_types[i]) {
436 case COL_PIXBUF:
437 renderer = gtk_cell_renderer_pixbuf_new();
439 usdlg_col_titles[i], renderer, "pixbuf", i, NULL);
441 break;
442 case COL_TEXT:
443 renderer = gtk_cell_renderer_text_new();
445 usdlg_col_titles[i], renderer, "text", i,
446 "style", USDLG_COL_STYLE, "weight", USDLG_COL_WEIGHT, NULL);
448 break;
449 case COL_INT:
450 renderer = gtk_cell_renderer_text_new();
452 usdlg_col_titles[i], renderer, "text", i,
453 "style", USDLG_COL_STYLE, "weight", USDLG_COL_WEIGHT, NULL);
454 g_object_set(renderer, "xalign", 1.0, NULL);
457 break;
458 }
459
462 }
463
470 gtk_grid_attach(GTK_GRID(hgrid), sw, grid_col++, 0, 1, 1);
471
476
477 /* button box 1: ready, sentry */
478
479 pdialog->tabs[loc].cmd[USDLG_CMD_READY]
482 pdialog->tabs[loc].cmd[USDLG_CMD_READY],
483 0, grid_row++, 1, 1);
484 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_READY], "clicked",
488
489 pdialog->tabs[loc].cmd[USDLG_CMD_SENTRY]
490 = gtk_button_new_with_mnemonic(_("Sentry"));
492 GTK_WIDGET(pdialog->tabs[loc].cmd[USDLG_CMD_SENTRY]), 10);
494 pdialog->tabs[loc].cmd[USDLG_CMD_SENTRY],
495 0, grid_row++, 1, 1);
496 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_SENTRY], "clicked",
500
501 /* button box 2: select, deselect */
502
503 pdialog->tabs[loc].cmd[USDLG_CMD_SELECT]
504 = gtk_button_new_with_mnemonic(_("_Select"));
506 pdialog->tabs[loc].cmd[USDLG_CMD_SELECT],
507 0, grid_row++, 1, 1);
508 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_SELECT], "clicked",
512
513 pdialog->tabs[loc].cmd[USDLG_CMD_DESELECT]
514 = gtk_button_new_with_mnemonic(_("_Deselect"));
516 GTK_WIDGET(pdialog->tabs[loc].cmd[USDLG_CMD_DESELECT]), 10);
518 pdialog->tabs[loc].cmd[USDLG_CMD_DESELECT],
519 0, grid_row++, 1, 1);
520 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_DESELECT], "clicked",
524
525 /* button box 3: center, focus */
526
527 pdialog->tabs[loc].cmd[USDLG_CMD_CENTER]
528 = gtk_button_new_with_mnemonic(_("C_enter"));
530 pdialog->tabs[loc].cmd[USDLG_CMD_CENTER],
531 0, grid_row++, 1, 1);
532 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_CENTER], "clicked",
536
537 pdialog->tabs[loc].cmd[USDLG_CMD_FOCUS]
538 = gtk_button_new_with_mnemonic(_("_Focus"));
540 pdialog->tabs[loc].cmd[USDLG_CMD_FOCUS],
541 0, grid_row++, 1, 1);
542 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_FOCUS], "clicked",
546}
547
548/*************************************************************************/
552{
553 GtkTreeStore *store;
555 int i;
556
557 for (i = 0; i < USDLG_COLUMNS_ALL; i++) {
558 switch (usdlg_col_types[i]) {
559 case COL_PIXBUF:
561 break;
562 case COL_TEXT:
564 break;
565 case COL_INT:
567 break;
568 }
569 }
570
572
573 return store;
574}
575
576/*************************************************************************/
579static bool usdlg_tab_update(struct unit_select_dialog *pdialog,
580 struct usdata_hash *ushash,
582{
583 bool show = FALSE;
584 GtkTreeStore *store;
585
587 fc_assert_ret_val(pdialog != NULL, FALSE);
588
589 store = pdialog->tabs[loc].store;
590
591 /* clear current store. */
593
594 /* Iterate over all unit types. */
595 if (loc == SELLOC_UNITS) {
596 /* Special case - show all units on this tile in their transports. */
597 unit_type_iterate(utype) {
598 struct usdata *data;
599
601
602 if (!data) {
603 continue;
604 }
605
607 if (unit_list_size(data->units[loc][act]) == 0) {
608 continue;
609 }
610
611 unit_list_iterate(data->units[loc][act], punit) {
613
614 usdlg_tab_append_units(pdialog, loc, act, punit, FALSE,
615 &it_unit, NULL);
617
618 /* Show this tab. */
619 show = TRUE;
622 } else {
624 struct usdata *data;
625 bool first = TRUE;
627 GtkTreePath *path;
628 int count = 0;
629
631
632 if (!data) {
633 continue;
634 }
635
638
639 if (unit_list_size(data->units[loc][act]) == 0) {
640 continue;
641 }
642
643 /* Level 1: Display unit type. */
644 if (first) {
646 &it_utype);
647 first = FALSE;
648 }
649
650 /* Level 2: Display unit activities. */
652 act, unit_list_size(data->units[loc][act]),
653 &it_act, &it_utype);
654
655 /* Level 3: Display all units with this activitiy
656 * (and transported units in further level(s)). */
657 unit_list_iterate(data->units[loc][act], punit) {
659
660 usdlg_tab_append_units(pdialog, loc, act, punit, FALSE,
661 &it_unit, &it_act);
663
664 count += unit_list_size(data->units[loc][act]);
665
666 /* Update sum of units with this type. */
667 gtk_tree_store_set(GTK_TREE_STORE(store), &it_utype, 2, count, -1);
668
669 /* Expand to the activities. */
670 path
672 &it_utype);
674 FALSE);
675 gtk_tree_path_free(path);
676
677 /* Show this tab. */
678 show = TRUE;
681 }
682
683 return show;
684}
685
686/*************************************************************************/
691 const struct unit_type *putype,
692 GtkTreeIter *it)
693{
694 GdkPixbuf *pix;
695 char buf[128];
696
697 fc_assert_ret(store != NULL);
699
700 /* Add this item. */
702
703 /* Create a icon */
704 {
706
709
710 put_unittype(putype, &canvas_store, 1.0, 0, 0);
714 }
715
716 /* The name of the unit. */
718
719 /* Add it to the tree. */
721 0, pix, /* Unit pixmap */
722 1, buf, /* Text */
723 2, -1, /* will be set later */ /* Number of units */
724 3, utype_index(putype), /* Unit type ID */
725 /* 4: not set */ /* Unit ID */
726 5, loc, /* Unit location */
727 /* 6: not set */ /* Unit activity */
728 7, ROW_UNITTYPE, /* Row type */
729 8, PANGO_STYLE_NORMAL, /* Style */
730 9, PANGO_WEIGHT_BOLD, /* Weight */
731 -1);
732 g_object_unref(pix);
733}
734
735/*************************************************************************/
740 const struct unit_type *putype,
741 enum unit_activity act,
742 int count, GtkTreeIter *it,
744{
745 char buf[128] = "";
746
747 fc_assert_ret(store != NULL);
749
750 /* Add this item. */
752
753 /* The activity. */
754 fc_snprintf(buf, sizeof(buf), "%s", get_activity_text(act));
755
756 /* Add it to the tree. */
758 /* 0: not set */ /* Unit pixmap */
759 1, buf, /* Text */
760 2, count, /* Number of units */
761 3, utype_index(putype), /* Unit type ID */
762 /* 4: not set */ /* Unit ID */
763 5, loc, /* Unit location */
764 6, act, /* Unit activity */
765 7, ROW_ACTIVITY, /* Row type */
766 8, PANGO_STYLE_NORMAL, /* Style */
767 9, PANGO_WEIGHT_NORMAL, /* Weight */
768 -1);
769}
770
771/*************************************************************************/
792
793/*************************************************************************/
797const char *usdlg_get_unit_descr(const struct unit *punit)
798{
799 static char buf[248] = "";
800 char buf2[248] = "";
801 struct city *phome;
802
804 if (phome) {
805 fc_snprintf(buf2, sizeof(buf2), "%s", city_name_get(phome));
806 } else if (unit_owner(punit) == client_player()
808 /* TRANS: used in place of unit home city name */
809 sz_strlcpy(buf2, _("no home city"));
810 } else {
811 /* TRANS: used in place of unit home city name */
812 sz_strlcpy(buf2, _("unknown"));
813 }
814#ifdef FREECIV_DEBUG
815 /* Strings only used in debug builds, don't bother with i18n */
816 fc_snprintf(buf, sizeof(buf), "%s [Unit ID %d]\n(%s)\nCoordinates: (%d,%d)",
819 {
821
822 if (ptrans) {
823 cat_snprintf(buf, sizeof(buf), "\nTransported by unit ID %d",
824 ptrans->id);
825 }
826 }
827#else /* FREECIV_DEBUG */
828 /* TRANS: unit type and home city, e.g. "Transport\n(New Orleans)" */
829 fc_snprintf(buf, sizeof(buf), _("%s\n(%s)"), unit_name_translation(punit),
830 buf2);
831#endif /* FREECIV_DEBUG */
832
833 return buf;
834}
835
836/*************************************************************************/
839static void usdlg_tab_append_units(struct unit_select_dialog *pdialog,
841 enum unit_activity act,
842 const struct unit *punit,
843 bool transported, GtkTreeIter *it,
845{
846 const char *text;
847 GdkPixbuf *pix;
849 int style = PANGO_STYLE_NORMAL;
850 int weight = PANGO_WEIGHT_NORMAL;
851 GtkTreeStore *store;
852
853 fc_assert_ret(pdialog != NULL);
855
856 store = pdialog->tabs[loc].store;
857
858
859 /* Add this item. */
861
862 /* Unit gfx */
864
866
867 if (transported) {
868 weight = PANGO_WEIGHT_NORMAL;
869 style = PANGO_STYLE_ITALIC;
871 }
872
873 /* Add it to the tree. */
875 0, pix, /* Unit pixmap */
876 1, text, /* Text */
877 2, 1, /* Number of units */
878 3, utype_index(unit_type_get(punit)), /* Unit type ID */
879 4, punit->id, /* Unit ID */
880 5, loc, /* Unit location */
881 6, act, /* Unit activity */
882 7, row, /* Row type */
883 8, style, /* Style */
884 9, weight, /* Weight */
885 -1);
886 g_object_unref(pix);
887
891
892 usdlg_tab_append_units(pdialog, loc, act, pcargo, TRUE, &it_cargo, it);
894 }
895
896 if (!transported && unit_is_in_focus(punit)
897 && get_num_units_in_focus() == 1) {
898 /* Put the keyboard focus on the selected unit. It isn't transported.
899 * Selection maps to keyboard focus since it alone is selected. */
900 fc_assert_action(pdialog->tabs[loc].path == NULL,
901 /* Don't leak memory. */
902 gtk_tree_path_free(pdialog->tabs[loc].path));
903
904 pdialog->tabs[loc].path
906 }
907}
908
909/*************************************************************************/
912static void usdlg_cmd_ready(GObject *object, gpointer data)
913{
914 usdlg_cmd_exec(object, data, USDLG_CMD_READY);
915}
916
917/*************************************************************************/
920static void usdlg_cmd_sentry(GObject *object, gpointer data)
921{
922 usdlg_cmd_exec(object, data, USDLG_CMD_SENTRY);
923}
924
925/*************************************************************************/
928static void usdlg_cmd_select(GObject *object, gpointer data)
929{
930 usdlg_cmd_exec(object, data, USDLG_CMD_SELECT);
931}
932
933/*************************************************************************/
936static void usdlg_cmd_deselect(GObject *object, gpointer data)
937{
938 usdlg_cmd_exec(object, data, USDLG_CMD_DESELECT);
939}
940
941/*************************************************************************/
945 enum usdlg_cmd cmd)
946{
950 GtkTreeSelection *selection;
951 GtkTreeModel *model;
952 GtkTreeIter it;
953 gint row;
954 struct unit_select_dialog *pdialog = usdlg_get(FALSE);
955
956 fc_assert_ret(pdialog != NULL);
958
960 return;
961 }
962
963 view = GTK_TREE_VIEW(pdialog->tabs[loc_mode].view);
965
966 if (!gtk_tree_selection_get_selected(selection, &model, &it)) {
967 log_debug("No selection");
968 return;
969 }
970 gtk_tree_model_get(model, &it, USDLG_COL_ROW_TYPE, &row, -1);
971
972 switch (row) {
973 case ROW_UNITTYPE:
974 {
975 gint loc, utid;
976 struct usdata_hash *ushash;
977 struct usdata *data;
978
980 USDLG_COL_UTID, &utid, -1);
981
982 /* We can't be sure that all units still exists - recalc the data. */
983 ushash = usdlg_data_new(pdialog->ptile);
984
986 if (data != NULL) {
988 if (unit_list_size(data->units[loc][act]) == 0) {
989 continue;
990 }
991
992 unit_list_iterate(data->units[loc][act], punit) {
996 }
997
998 /* Destroy the hash. */
1000 }
1001 break;
1002 case ROW_ACTIVITY:
1003 {
1004 gint loc, act, utid;
1005 struct usdata_hash *ushash;
1006 struct usdata *data;
1007
1008 gtk_tree_model_get(model, &it, USDLG_COL_ACTIVITY, &act,
1010
1011 /* We can't be sure that all units still exists - recalc the data. */
1012 ushash = usdlg_data_new(pdialog->ptile);
1013
1015 if (data != NULL
1016 && unit_list_size(data->units[loc][act]) != 0) {
1017 unit_list_iterate(data->units[loc][act], punit) {
1020 }
1021
1022 /* Destroy the hash. */
1024 }
1025 break;
1026 case ROW_UNIT:
1028 {
1029 gint uid;
1030 struct unit *punit;
1031
1032 gtk_tree_model_get(model, &it, USDLG_COL_UID, &uid, -1);
1033
1035
1036 if (!punit) {
1037 log_debug("Unit vanished (Unit ID %d)!", uid);
1038 return;
1039 }
1040
1042 }
1043 break;
1044 }
1045
1046 /* Update focus. */
1048 /* Refresh dialog. */
1049 usdlg_refresh(pdialog);
1050}
1051
1052/*************************************************************************/
1055static void usdlg_cmd_exec_unit(struct unit *punit, enum usdlg_cmd cmd)
1056{
1058
1059 switch (cmd) {
1060 case USDLG_CMD_SELECT:
1061 if (!unit_is_in_focus(punit)) {
1063 }
1064 break;
1065 case USDLG_CMD_DESELECT:
1066 if (unit_is_in_focus(punit)) {
1068 }
1069 break;
1070 case USDLG_CMD_READY:
1071 if (punit->activity != ACTIVITY_IDLE) {
1073 }
1074 break;
1075 case USDLG_CMD_SENTRY:
1076 if (punit->activity != ACTIVITY_SENTRY) {
1078 }
1079 break;
1080 case USDLG_CMD_CENTER:
1081 case USDLG_CMD_FOCUS:
1082 /* Nothing here. It is done in its own functions. */
1083 break;
1084 case USDLG_CMD_LAST:
1085 /* Should never happen. */
1087 break;
1088 }
1089}
1090
1091/*************************************************************************/
1094static void usdlg_cmd_center(GObject *object, gpointer data)
1095{
1099 GtkTreeSelection *selection;
1100 GtkTreeModel *model;
1101 GtkTreeIter it;
1102 gint row;
1103 struct unit_select_dialog *pdialog = usdlg_get(FALSE);
1104
1105 fc_assert_ret(pdialog != NULL);
1107
1108 view = GTK_TREE_VIEW(pdialog->tabs[loc].view);
1109 selection = gtk_tree_view_get_selection(view);
1110
1111 if (!gtk_tree_selection_get_selected(selection, &model, &it)) {
1112 log_debug("No selection");
1113 return;
1114 }
1115 gtk_tree_model_get(model, &it, USDLG_COL_ROW_TYPE, &row, -1);
1116
1117 if (row == ROW_UNIT || row == ROW_UNIT_TRANSPORTED) {
1118 gint uid;
1119 struct unit *punit;
1120
1121 gtk_tree_model_get(model, &it, USDLG_COL_UID, &uid, -1);
1122
1124 if (punit) {
1126 }
1127 }
1128}
1129
1130/*************************************************************************/
1133static void usdlg_cmd_focus(GObject *object, gpointer data)
1134{
1137 struct unit_select_dialog *pdialog = usdlg_get(FALSE);
1138
1139 fc_assert_ret(pdialog != NULL);
1141
1143}
1144
1145/*************************************************************************/
1153
1154/*************************************************************************/
1158{
1160 GtkTreeModel *model;
1161 GtkTreeIter it;
1162 gint row;
1163
1165 return;
1166 }
1167
1168 if (!gtk_tree_selection_get_selected(selection, &model, &it)) {
1169 log_debug("No selection");
1170 return;
1171 }
1172 gtk_tree_model_get(model, &it, USDLG_COL_ROW_TYPE, &row, -1);
1173
1174 if (row == ROW_UNIT || row == ROW_UNIT_TRANSPORTED) {
1175 gint uid;
1176 struct unit *punit;
1177
1178 gtk_tree_model_get(model, &it, USDLG_COL_UID, &uid, -1);
1179
1181 if (punit && unit_owner(punit) == client_player()) {
1183 usdlg_destroy();
1184 }
1185 }
1186}
1187
1188/*************************************************************************/
1192{
1195 GtkTreeSelection *selection;
1196 GtkTreeModel *model;
1197 GtkTreeIter it;
1198 gint row, uid;
1199 struct unit_select_dialog *pdialog = usdlg_get(FALSE);
1200 struct unit *punit;
1202 int cmd_id;
1203
1205
1206 if (pdialog == NULL) {
1207 /* Dialog closed, nothing we can do */
1208 return;
1209 }
1210
1211 selection = gtk_tree_view_get_selection(view);
1212 if (!gtk_tree_selection_get_selected(selection, &model, &it)) {
1213 log_debug("No selection");
1214 return;
1215 }
1217 &uid, -1);
1218
1219 switch (row) {
1220 case ROW_UNITTYPE:
1221 case ROW_ACTIVITY:
1222 /* Button status for rows unittype and activity:
1223 * player observer
1224 * ready TRUE FALSE
1225 * sentry TRUE FALSE
1226 * select TRUE FALSE
1227 * deselect TRUE FALSE
1228 * center FALSE FALSE
1229 * focus FALSE FALSE */
1235 } else {
1240 }
1241
1244 break;
1245 case ROW_UNIT:
1247 /* Button status for rows unit and unit (transported):
1248 * player observer
1249 * ready !IDLE FALSE
1250 * sentry !SENTRY FALSE
1251 * select !FOCUS FALSE
1252 * deselect FOCUS FALSE
1253 * center TRUE TRUE
1254 * focus !FOCUS FALSE */
1256
1258 if (punit->activity == ACTIVITY_IDLE) {
1260 } else {
1262 }
1263
1264 if (punit->activity == ACTIVITY_SENTRY) {
1266 } else {
1268 }
1269
1270 if (!unit_is_in_focus(punit)) {
1274 } else {
1278 }
1279 } else {
1282
1285
1287 }
1288
1290 break;
1291
1292 default:
1294 for (cmd_id = 0; cmd_id < USDLG_CMD_LAST; cmd_id++) {
1296 }
1297 break;
1298 }
1299
1300 /* Set widget status. */
1301 for (cmd_id = 0; cmd_id < USDLG_CMD_LAST; cmd_id++) {
1304 }
1305}
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
bool can_client_control(void)
bool client_is_global_observer(void)
bool can_client_change_view(void)
#define client_player()
char * incite_cost
Definition comments.c:75
bool unit_is_in_focus(const struct unit *punit)
Definition control.c:388
void unit_focus_add(struct unit *punit)
Definition control.c:561
void unit_focus_set(struct unit *punit)
Definition control.c:506
void unit_focus_remove(struct unit *punit)
Definition control.c:591
struct unit * head_of_units_in_focus(void)
Definition control.c:410
int get_num_units_in_focus(void)
Definition control.c:185
void unit_focus_update(void)
Definition control.c:789
void request_new_unit_activity(struct unit *punit, enum unit_activity act)
Definition control.c:1929
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct unit * game_unit_by_number(int id)
Definition game.c:116
struct city * game_city_by_number(int id)
Definition game.c:107
#define FC_STATIC_CANVAS_INIT
Definition canvas.h:28
struct tile * loc
Definition citydlg.c:227
GtkWidget * toplevel
Definition gui_main.c:125
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:287
void intl_slist(int n, const char **s, bool *done)
Definition gui_stuff.c:111
const char * title
Definition repodlgs.c:1314
GdkPixbuf * surface_get_pixbuf(cairo_surface_t *surf, int width, int height)
Definition sprite.c:418
#define USDLG_COL_LOCATION
Definition unitselect.c:66
static void usdlg_cmd_ready(GObject *object, gpointer data)
Definition unitselect.c:901
static void usdlg_cmd_deselect(GObject *object, gpointer data)
Definition unitselect.c:925
static void usdlg_cmd_center(GObject *object, gpointer data)
#define USDLG_COL_ROW_TYPE
Definition unitselect.c:68
static void usdlg_cmd_cursor_changed(GtkTreeView *view, gpointer data)
GdkPixbuf * usdlg_get_unit_image(const struct unit *punit)
Definition unitselect.c:765
const char * usdlg_get_unit_descr(const struct unit *punit)
Definition unitselect.c:786
static void usdlg_tab_append_units(struct unit_select_dialog *pdialog, enum unit_select_location_mode loc, enum unit_activity act, const struct unit *punit, bool transported, GtkTreeIter *it, GtkTreeIter *parent)
Definition unitselect.c:828
static void usdlg_tile(struct unit_select_dialog *pdialog, struct tile *ptile)
Definition unitselect.c:313
#define USDLG_COL_UTID
Definition unitselect.c:64
static void usdlg_cmd_sentry(GObject *object, gpointer data)
Definition unitselect.c:909
static struct unit_select_dialog * usdlg_get(bool create)
Definition unitselect.c:223
#define USDLG_COL_STYLE
Definition unitselect.c:71
#define USDLG_COL_UID
Definition unitselect.c:65
static void usdlg_cmd_exec_unit(struct unit *punit, enum usdlg_cmd cmd)
static void usdlg_tab_append_activity(GtkTreeStore *store, enum unit_select_location_mode loc, const struct unit_type *putype, enum unit_activity act, int count, GtkTreeIter *it, GtkTreeIter *parent)
Definition unitselect.c:727
static struct unit_select_dialog * usdlg_create(void)
Definition unitselect.c:241
static void usdlg_cmd_focus(GObject *object, gpointer data)
#define USDLG_COL_ACTIVITY
Definition unitselect.c:67
static void usdlg_cmd_exec(GObject *object, gpointer mode_data, enum usdlg_cmd cmd)
Definition unitselect.c:933
#define USDLG_COLUMNS_ALL
Definition unitselect.c:73
static void usdlg_destroy_callback(GObject *object, gpointer data)
Definition unitselect.c:305
usdlg_row_types
Definition unitselect.c:54
@ ROW_UNITTYPE
Definition unitselect.c:55
@ ROW_UNIT_TRANSPORTED
Definition unitselect.c:58
@ ROW_UNIT
Definition unitselect.c:57
@ ROW_ACTIVITY
Definition unitselect.c:56
static void usdlg_cmd_select(GObject *object, gpointer data)
Definition unitselect.c:917
static const char * usdlg_col_titles[USDLG_COLUMNS_ALL]
Definition unitselect.c:94
static void usdlg_cmd_focus_real(GtkTreeView *view)
#define USDLG_COLUMNS_SHOW
Definition unitselect.c:78
static struct unit_select_dialog * unit_select_dlg
Definition unitselect.c:141
enum usdlg_column_types usdlg_col_types[USDLG_COLUMNS_ALL]
Definition unitselect.c:81
void unit_select_dialog_popup_main(struct tile *ptile, bool create)
Definition unitselect.c:193
static void usdlg_cmd_row_activated(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
void unit_select_dialog_popdown(void)
Definition unitselect.c:214
static void usdlg_tab_append_utype(GtkTreeStore *store, enum unit_select_location_mode loc, const struct unit_type *putype, GtkTreeIter *it)
Definition unitselect.c:678
#define USDLG_COL_WEIGHT
Definition unitselect.c:72
static void usdlg_tab_select(struct unit_select_dialog *pdialog, const char *title, enum unit_select_location_mode loc)
Definition unitselect.c:387
static bool usdlg_tab_update(struct unit_select_dialog *pdialog, struct usdata_hash *ushash, enum unit_select_location_mode loc)
Definition unitselect.c:568
static void usdlg_refresh(struct unit_select_dialog *pdialog)
Definition unitselect.c:338
usdlg_column_types
Definition unitselect.c:48
@ COL_INT
Definition unitselect.c:51
@ COL_TEXT
Definition unitselect.c:50
@ COL_PIXBUF
Definition unitselect.c:49
usdlg_cmd
Definition unitselect.c:107
@ USDLG_CMD_FOCUS
Definition unitselect.c:113
@ USDLG_CMD_SENTRY
Definition unitselect.c:111
@ USDLG_CMD_LAST
Definition unitselect.c:114
@ USDLG_CMD_CENTER
Definition unitselect.c:112
@ USDLG_CMD_READY
Definition unitselect.c:110
@ USDLG_CMD_DESELECT
Definition unitselect.c:109
@ USDLG_CMD_SELECT
Definition unitselect.c:108
static void usdlg_destroy(void)
Definition unitselect.c:293
static GtkTreeStore * usdlg_tab_store_new(void)
Definition unitselect.c:540
@ USDLG_CMD_LAST
Definition unitselect.c:114
#define show(id)
Definition widget.h:235
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
struct tile * get_center_tile_mapcanvas(void)
void put_unit(const struct unit *punit, struct canvas *pcanvas, float zoom, int canvas_x, int canvas_y)
void put_unittype(const struct unit_type *putype, struct canvas *pcanvas, float zoom, int canvas_x, int canvas_y)
void center_tile_mapcanvas(const struct tile *ptile)
#define fc_calloc(n, esz)
Definition mem.h:38
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1229
#define ARRAY_SIZE(x)
Definition shared.h:85
cairo_surface_t * surface
Definition canvas.h:23
Definition city.h:320
Definition tile.h:50
struct tile * ptile
Definition unitselect.c:118
GtkTreePath * path
Definition unitselect.c:127
GtkWidget * shell
Definition unitselect.c:121
GtkWidget * view
Definition unitselect.c:126
struct unit_select_dialog::@159 units
struct unit_select_dialog::@160 tabs[SELLOC_COUNT]
GtkWidget * cmd[USDLG_CMD_LAST]
Definition unitselect.c:136
GtkWidget * notebook
Definition unitselect.c:122
GtkTreeStore * store
Definition unitselect.c:125
GtkWidget * page
Definition unitselect.c:132
Definition unit.h:138
enum unit_activity activity
Definition unit.h:157
int id
Definition unit.h:145
int homecity
Definition unit.h:146
struct unit_list * units[SELLOC_COUNT][ACTIVITY_LAST]
const struct unit_type * utype
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:1000
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define TILE_XY(ptile)
Definition tile.h:43
int tileset_full_tile_height(const struct tileset *t)
Definition tilespec.c:789
int tileset_full_tile_width(const struct tileset *t)
Definition tilespec.c:776
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1783
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2441
const char * get_activity_text(enum unit_activity activity)
Definition unit.c:614
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2451
#define unit_tile(_pu)
Definition unit.h:397
#define unit_owner(_pu)
Definition unit.h:396
#define activity_type_iterate(_act_)
Definition unit.h:284
#define activity_type_iterate_end
Definition unit.h:289
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
struct usdata_hash * usdlg_data_new(const struct tile *ptile)
void usdlg_data_destroy(struct usdata_hash *ushash)
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1569
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
#define unit_type_iterate(_p)
Definition unittype.h:855
#define unit_type_iterate_end
Definition unittype.h:862