Freeciv-3.4
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
122
123 struct {
124 GtkTreeStore *store;
125 GtkWidget *page;
127 GtkTreePath *path;
128
131};
132
133/* The unit selection dialog; should only be used in usdlg_get(). */
135
136static struct unit_select_dialog *usdlg_get(bool create);
137static struct unit_select_dialog *usdlg_create(void);
138static void usdlg_destroy(void);
139static void usdlg_destroy_callback(GObject *object, gpointer data);
140static void usdlg_tile(struct unit_select_dialog *pdialog,
141 struct tile *ptile);
142static void usdlg_refresh(struct unit_select_dialog *pdialog);
143
144static void usdlg_tab_select(struct unit_select_dialog *pdialog,
145 const char *title,
148static bool usdlg_tab_update(struct unit_select_dialog *pdialog,
149 struct usdata_hash *ushash,
153 const struct unit_type *putype,
154 GtkTreeIter *it);
157 const struct unit_type *putype,
158 enum unit_activity act,
159 int count, GtkTreeIter *it,
161static void usdlg_tab_append_units(struct unit_select_dialog *pdialog,
163 enum unit_activity act,
164 const struct unit *punit,
165 bool transported, GtkTreeIter *it,
167
168static void usdlg_cmd_ready(GObject *object, gpointer data);
169static void usdlg_cmd_sentry(GObject *object, gpointer data);
170static void usdlg_cmd_select(GObject *object, gpointer data);
171static void usdlg_cmd_deselect(GObject *object, gpointer data);
172static void usdlg_cmd_exec(GObject *object, gpointer mode_data,
173 enum usdlg_cmd cmd);
174static void usdlg_cmd_exec_unit(struct unit *punit, enum usdlg_cmd cmd);
175static void usdlg_cmd_center(GObject *object, gpointer data);
176static void usdlg_cmd_focus(GObject *object, gpointer data);
181
182
183/*************************************************************************/
186void unit_select_dialog_popup_main(struct tile *ptile, bool create)
187{
188 struct unit_select_dialog *pdialog;
189
190 /* Create the dialog if it is requested. */
191 pdialog = usdlg_get(create);
192
193 /* Present the unit selection dialog if it exists. */
194 if (pdialog) {
195 /* Show all. */
197 /* Update tile. */
198 usdlg_tile(pdialog, ptile);
199 /* Refresh data and hide unused tabs. */
200 usdlg_refresh(pdialog);
201 }
202}
203
204/*************************************************************************/
208{
210}
211
212/*************************************************************************/
216static struct unit_select_dialog *usdlg_get(bool create)
217{
218 if (unit_select_dlg) {
219 /* Return existing dialog. */
220 return unit_select_dlg;
221 } else if (create) {
222 /* Create new dialog. */
224 return unit_select_dlg;
225 } else {
226 /* Nothing. */
227 return NULL;
228 }
229}
230
231/*************************************************************************/
235{
236 GtkWidget *vbox;
238 struct unit_select_dialog *pdialog;
239
240 /* Create a container for the dialog. */
241 pdialog = fc_calloc(1, sizeof(*pdialog));
242
243 /* No tile defined. */
244 pdialog->ptile = NULL;
245
246 /* Create the dialog. */
247 pdialog->shell = gtk_dialog_new();
248 gtk_window_set_title(GTK_WINDOW(pdialog->shell), _("Unit selection"));
249 setup_dialog(pdialog->shell, toplevel);
250 g_signal_connect(pdialog->shell, "destroy",
252 gtk_widget_realize(pdialog->shell);
253
255
256 /* Notebook. */
257 pdialog->notebook = gtk_notebook_new();
261
262 /* Append pages. */
263 usdlg_tab_select(pdialog, _("_Units"), SELLOC_UNITS);
264 usdlg_tab_select(pdialog, _("_Tile"), SELLOC_TILE);
265 usdlg_tab_select(pdialog, _("C_ontinent"), SELLOC_CONT);
266 usdlg_tab_select(pdialog, _("_Land"), SELLOC_LAND);
267 usdlg_tab_select(pdialog, _("_Sea"), SELLOC_SEA);
268 usdlg_tab_select(pdialog, _("_Both"), SELLOC_BOTH);
269 usdlg_tab_select(pdialog, _("_World"), SELLOC_WORLD);
270
271 /* Buttons. */
273 _("_Close"), GTK_RESPONSE_CLOSE);
276 g_signal_connect(close_cmd, "clicked",
278
279 return pdialog;
280}
281
282/*************************************************************************/
293
294/*************************************************************************/
297static void usdlg_destroy_callback(GObject *object, gpointer data)
298{
300}
301
302/*************************************************************************/
305static void usdlg_tile(struct unit_select_dialog *pdialog,
306 struct tile *ptile)
307{
308 if (!pdialog) {
309 return;
310 }
311
312 /* Check for a valid tile. */
313 if (ptile != NULL) {
314 pdialog->ptile = ptile;
315 } else if (pdialog->ptile == NULL) {
317
318 if (punit) {
319 pdialog->ptile = unit_tile(punit);
321 } else {
322 pdialog->ptile = get_center_tile_mapcanvas();
323 }
324 }
325}
326
327/*************************************************************************/
330static void usdlg_refresh(struct unit_select_dialog *pdialog)
331{
332 struct usdata_hash *ushash = NULL;
334
335 if (!pdialog) {
336 return;
337 }
338
339 /* Sort units into the hash. */
340 ushash = usdlg_data_new(pdialog->ptile);
341 /* Update all tabs. */
345 bool show = usdlg_tab_update(pdialog, ushash, loc);
346
347 if (!show) {
349 } else {
351
352 if (pdialog->tabs[loc].path) {
354 pdialog->tabs[loc].path,FALSE);
356 pdialog->tabs[loc].path, NULL, FALSE);
357 gtk_tree_path_free(pdialog->tabs[loc].path);
358 pdialog->tabs[loc].path = NULL;
359 }
360 }
361 }
362
363 /* Destroy the hash. */
365}
366
367/*************************************************************************/
380static void usdlg_tab_select(struct unit_select_dialog *pdialog,
381 const char *title,
383{
384 GtkWidget *page, *label, *hgrid, *vgrid, *view, *sw;
385 GtkTreeStore *store;
386 static bool titles_done;
387 int i;
388 int page_row = 0;
389 int grid_col = 0;
390 int grid_row = 0;
391
392 page = gtk_grid_new();
399 pdialog->tabs[loc].page = page;
400
402 gtk_notebook_append_page(GTK_NOTEBOOK(pdialog->notebook), page, label);
403
405 gtk_grid_attach(GTK_GRID(page), hgrid, 0, page_row++, 1, 1);
406
407 store = usdlg_tab_store_new();
408 pdialog->tabs[loc].store = store;
409
413 gtk_widget_add_css_class(GTK_WIDGET(view), "large-pixbufs");
414 pdialog->tabs[loc].view = view;
415 g_object_unref(store);
416
419 g_signal_connect(view, "cursor-changed",
421
422 /* Translate titles. */
424
425 for (i = 0; i < USDLG_COLUMNS_SHOW; i++) {
427 GtkCellRenderer *renderer = NULL;
428
429 switch (usdlg_col_types[i]) {
430 case COL_PIXBUF:
431 renderer = gtk_cell_renderer_pixbuf_new();
433 usdlg_col_titles[i], renderer, "pixbuf", i, NULL);
435 break;
436 case COL_TEXT:
437 renderer = gtk_cell_renderer_text_new();
439 usdlg_col_titles[i], renderer, "text", i,
440 "style", USDLG_COL_STYLE, "weight", USDLG_COL_WEIGHT, NULL);
442 break;
443 case COL_INT:
444 renderer = gtk_cell_renderer_text_new();
446 usdlg_col_titles[i], renderer, "text", i,
447 "style", USDLG_COL_STYLE, "weight", USDLG_COL_WEIGHT, NULL);
448 g_object_set(renderer, "xalign", 1.0, NULL);
451 break;
452 }
453
456 }
457
464 gtk_grid_attach(GTK_GRID(hgrid), sw, grid_col++, 0, 1, 1);
465
470
471 /* button box 1: ready, sentry */
472
473 pdialog->tabs[loc].cmd[USDLG_CMD_READY]
476 pdialog->tabs[loc].cmd[USDLG_CMD_READY],
477 0, grid_row++, 1, 1);
478 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_READY], "clicked",
482
483 pdialog->tabs[loc].cmd[USDLG_CMD_SENTRY]
484 = gtk_button_new_with_mnemonic(_("Sentry"));
486 GTK_WIDGET(pdialog->tabs[loc].cmd[USDLG_CMD_SENTRY]), 10);
488 pdialog->tabs[loc].cmd[USDLG_CMD_SENTRY],
489 0, grid_row++, 1, 1);
490 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_SENTRY], "clicked",
494
495 /* button box 2: select, deselect */
496
497 pdialog->tabs[loc].cmd[USDLG_CMD_SELECT]
498 = gtk_button_new_with_mnemonic(_("_Select"));
500 pdialog->tabs[loc].cmd[USDLG_CMD_SELECT],
501 0, grid_row++, 1, 1);
502 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_SELECT], "clicked",
506
507 pdialog->tabs[loc].cmd[USDLG_CMD_DESELECT]
508 = gtk_button_new_with_mnemonic(_("_Deselect"));
510 GTK_WIDGET(pdialog->tabs[loc].cmd[USDLG_CMD_DESELECT]), 10);
512 pdialog->tabs[loc].cmd[USDLG_CMD_DESELECT],
513 0, grid_row++, 1, 1);
514 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_DESELECT], "clicked",
518
519 /* button box 3: center, focus */
520
521 pdialog->tabs[loc].cmd[USDLG_CMD_CENTER]
522 = gtk_button_new_with_mnemonic(_("C_enter"));
524 pdialog->tabs[loc].cmd[USDLG_CMD_CENTER],
525 0, grid_row++, 1, 1);
526 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_CENTER], "clicked",
530
531 pdialog->tabs[loc].cmd[USDLG_CMD_FOCUS]
532 = gtk_button_new_with_mnemonic(_("_Focus"));
534 pdialog->tabs[loc].cmd[USDLG_CMD_FOCUS],
535 0, grid_row++, 1, 1);
536 g_signal_connect(pdialog->tabs[loc].cmd[USDLG_CMD_FOCUS], "clicked",
540}
541
542/*************************************************************************/
546{
547 GtkTreeStore *store;
549 int i;
550
551 for (i = 0; i < USDLG_COLUMNS_ALL; i++) {
552 switch (usdlg_col_types[i]) {
553 case COL_PIXBUF:
555 break;
556 case COL_TEXT:
558 break;
559 case COL_INT:
561 break;
562 }
563 }
564
566
567 return store;
568}
569
570/*************************************************************************/
573static bool usdlg_tab_update(struct unit_select_dialog *pdialog,
574 struct usdata_hash *ushash,
576{
577 bool show = FALSE;
578 GtkTreeStore *store;
579
581 fc_assert_ret_val(pdialog != NULL, FALSE);
582
583 store = pdialog->tabs[loc].store;
584
585 /* clear current store. */
587
588 /* Iterate over all unit types. */
589 if (loc == SELLOC_UNITS) {
590 /* Special case - show all units on this tile in their transports. */
591 unit_type_iterate(utype) {
592 struct usdata *data;
593
595
596 if (!data) {
597 continue;
598 }
599
601 if (unit_list_size(data->units[loc][act]) == 0) {
602 continue;
603 }
604
605 unit_list_iterate(data->units[loc][act], punit) {
607
608 usdlg_tab_append_units(pdialog, loc, act, punit, FALSE,
609 &it_unit, NULL);
611
612 /* Show this tab. */
613 show = TRUE;
616 } else {
618 struct usdata *data;
619 bool first = TRUE;
621 GtkTreePath *path;
622 int count = 0;
623
625
626 if (!data) {
627 continue;
628 }
629
632
633 if (unit_list_size(data->units[loc][act]) == 0) {
634 continue;
635 }
636
637 /* Level 1: Display unit type. */
638 if (first) {
640 &it_utype);
641 first = FALSE;
642 }
643
644 /* Level 2: Display unit activities. */
646 act, unit_list_size(data->units[loc][act]),
647 &it_act, &it_utype);
648
649 /* Level 3: Display all units with this activity
650 * (and transported units in further level(s)). */
651 unit_list_iterate(data->units[loc][act], punit) {
653
654 usdlg_tab_append_units(pdialog, loc, act, punit, FALSE,
655 &it_unit, &it_act);
657
658 count += unit_list_size(data->units[loc][act]);
659
660 /* Update sum of units with this type. */
661 gtk_tree_store_set(GTK_TREE_STORE(store), &it_utype, 2, count, -1);
662
663 /* Expand to the activities. */
664 path
666 &it_utype);
668 FALSE);
669 gtk_tree_path_free(path);
670
671 /* Show this tab. */
672 show = TRUE;
675 }
676
677 return show;
678}
679
680/*************************************************************************/
685 const struct unit_type *putype,
686 GtkTreeIter *it)
687{
688 GdkPixbuf *pix;
689 char buf[128];
690
691 fc_assert_ret(store != NULL);
693
694 /* Add this item. */
696
697 /* Create a icon */
698 {
700
703
704 put_unittype(putype, &canvas_store, 1.0, 0, 0);
708 }
709
710 /* The name of the unit. */
712
713 /* Add it to the tree. */
715 0, pix, /* Unit pixmap */
716 1, buf, /* Text */
717 2, -1, /* will be set later */ /* Number of units */
718 3, utype_index(putype), /* Unit type ID */
719 /* 4: not set */ /* Unit ID */
720 5, loc, /* Unit location */
721 /* 6: not set */ /* Unit activity */
722 7, ROW_UNITTYPE, /* Row type */
723 8, PANGO_STYLE_NORMAL, /* Style */
724 9, PANGO_WEIGHT_BOLD, /* Weight */
725 -1);
726 g_object_unref(pix);
727}
728
729/*************************************************************************/
734 const struct unit_type *putype,
735 enum unit_activity act,
736 int count, GtkTreeIter *it,
738{
739 char buf[128] = "";
740
741 fc_assert_ret(store != NULL);
743
744 /* Add this item. */
746
747 /* The activity. */
748 fc_snprintf(buf, sizeof(buf), "%s", get_activity_text(act));
749
750 /* Add it to the tree. */
752 /* 0: not set */ /* Unit pixmap */
753 1, buf, /* Text */
754 2, count, /* Number of units */
755 3, utype_index(putype), /* Unit type ID */
756 /* 4: not set */ /* Unit ID */
757 5, loc, /* Unit location */
758 6, act, /* Unit activity */
759 7, ROW_ACTIVITY, /* Row type */
760 8, PANGO_STYLE_NORMAL, /* Style */
761 9, PANGO_WEIGHT_NORMAL, /* Weight */
762 -1);
763}
764
765/*************************************************************************/
786
787/*************************************************************************/
791const char *usdlg_get_unit_descr(const struct unit *punit)
792{
793 static char buf[248] = "";
794 char buf2[248] = "";
795 struct city *phome;
796
798 if (phome) {
799 fc_snprintf(buf2, sizeof(buf2), "%s", city_name_get(phome));
800 } else if (unit_owner(punit) == client_player()
802 /* TRANS: used in place of unit home city name */
803 sz_strlcpy(buf2, _("no home city"));
804 } else {
805 /* TRANS: used in place of unit home city name */
806 sz_strlcpy(buf2, _("unknown"));
807 }
808#ifdef FREECIV_DEBUG
809 /* Strings only used in debug builds, don't bother with i18n */
810 fc_snprintf(buf, sizeof(buf), "%s [Unit ID %d]\n(%s)\nCoordinates: (%d,%d)",
813 {
815
816 if (ptrans) {
817 cat_snprintf(buf, sizeof(buf), "\nTransported by unit ID %d",
818 ptrans->id);
819 }
820 }
821#else /* FREECIV_DEBUG */
822 /* TRANS: unit type and home city, e.g. "Transport\n(New Orleans)" */
823 fc_snprintf(buf, sizeof(buf), _("%s\n(%s)"), unit_name_translation(punit),
824 buf2);
825#endif /* FREECIV_DEBUG */
826
827 return buf;
828}
829
830/*************************************************************************/
833static void usdlg_tab_append_units(struct unit_select_dialog *pdialog,
835 enum unit_activity act,
836 const struct unit *punit,
837 bool transported, GtkTreeIter *it,
839{
840 const char *text;
841 GdkPixbuf *pix;
843 int style = PANGO_STYLE_NORMAL;
844 int weight = PANGO_WEIGHT_NORMAL;
845 GtkTreeStore *store;
846
847 fc_assert_ret(pdialog != NULL);
849
850 store = pdialog->tabs[loc].store;
851
852
853 /* Add this item. */
855
856 /* Unit gfx */
858
860
861 if (transported) {
862 weight = PANGO_WEIGHT_NORMAL;
863 style = PANGO_STYLE_ITALIC;
865 }
866
867 /* Add it to the tree. */
869 0, pix, /* Unit pixmap */
870 1, text, /* Text */
871 2, 1, /* Number of units */
872 3, utype_index(unit_type_get(punit)), /* Unit type ID */
873 4, punit->id, /* Unit ID */
874 5, loc, /* Unit location */
875 6, act, /* Unit activity */
876 7, row, /* Row type */
877 8, style, /* Style */
878 9, weight, /* Weight */
879 -1);
880 g_object_unref(pix);
881
885
886 usdlg_tab_append_units(pdialog, loc, act, pcargo, TRUE, &it_cargo, it);
888 }
889
890 if (!transported && unit_is_in_focus(punit)
891 && get_num_units_in_focus() == 1) {
892 /* Put the keyboard focus on the selected unit. It isn't transported.
893 * Selection maps to keyboard focus since it alone is selected. */
894 fc_assert_action(pdialog->tabs[loc].path == NULL,
895 /* Don't leak memory. */
896 gtk_tree_path_free(pdialog->tabs[loc].path));
897
898 pdialog->tabs[loc].path
900 }
901}
902
903/*************************************************************************/
906static void usdlg_cmd_ready(GObject *object, gpointer data)
907{
908 usdlg_cmd_exec(object, data, USDLG_CMD_READY);
909}
910
911/*************************************************************************/
914static void usdlg_cmd_sentry(GObject *object, gpointer data)
915{
916 usdlg_cmd_exec(object, data, USDLG_CMD_SENTRY);
917}
918
919/*************************************************************************/
922static void usdlg_cmd_select(GObject *object, gpointer data)
923{
924 usdlg_cmd_exec(object, data, USDLG_CMD_SELECT);
925}
926
927/*************************************************************************/
930static void usdlg_cmd_deselect(GObject *object, gpointer data)
931{
932 usdlg_cmd_exec(object, data, USDLG_CMD_DESELECT);
933}
934
935/*************************************************************************/
939 enum usdlg_cmd cmd)
940{
944 GtkTreeSelection *selection;
945 GtkTreeModel *model;
946 GtkTreeIter it;
947 gint row;
948 struct unit_select_dialog *pdialog = usdlg_get(FALSE);
949
950 fc_assert_ret(pdialog != NULL);
952
954 return;
955 }
956
957 view = GTK_TREE_VIEW(pdialog->tabs[loc_mode].view);
959
960 if (!gtk_tree_selection_get_selected(selection, &model, &it)) {
961 log_debug("No selection");
962 return;
963 }
964 gtk_tree_model_get(model, &it, USDLG_COL_ROW_TYPE, &row, -1);
965
966 switch (row) {
967 case ROW_UNITTYPE:
968 {
969 gint loc, utid;
970 struct usdata_hash *ushash;
971 struct usdata *data;
972
974 USDLG_COL_UTID, &utid, -1);
975
976 /* We can't be sure that all units still exists - recalc the data. */
977 ushash = usdlg_data_new(pdialog->ptile);
978
980 if (data != NULL) {
982 if (unit_list_size(data->units[loc][act]) == 0) {
983 continue;
984 }
985
986 unit_list_iterate(data->units[loc][act], punit) {
990 }
991
992 /* Destroy the hash. */
994 }
995 break;
996 case ROW_ACTIVITY:
997 {
998 gint loc, act, utid;
999 struct usdata_hash *ushash;
1000 struct usdata *data;
1001
1002 gtk_tree_model_get(model, &it, USDLG_COL_ACTIVITY, &act,
1004
1005 /* We can't be sure that all units still exists - recalc the data. */
1006 ushash = usdlg_data_new(pdialog->ptile);
1007
1009 if (data != NULL
1010 && unit_list_size(data->units[loc][act]) != 0) {
1011 unit_list_iterate(data->units[loc][act], punit) {
1014 }
1015
1016 /* Destroy the hash. */
1018 }
1019 break;
1020 case ROW_UNIT:
1022 {
1023 gint uid;
1024 struct unit *punit;
1025
1026 gtk_tree_model_get(model, &it, USDLG_COL_UID, &uid, -1);
1027
1029
1030 if (!punit) {
1031 log_debug("Unit vanished (Unit ID %d)!", uid);
1032 return;
1033 }
1034
1036 }
1037 break;
1038 }
1039
1040 /* Update focus. */
1042 /* Refresh dialog. */
1043 usdlg_refresh(pdialog);
1044}
1045
1046/*************************************************************************/
1049static void usdlg_cmd_exec_unit(struct unit *punit, enum usdlg_cmd cmd)
1050{
1052
1053 switch (cmd) {
1054 case USDLG_CMD_SELECT:
1055 if (!unit_is_in_focus(punit)) {
1057 }
1058 break;
1059 case USDLG_CMD_DESELECT:
1060 if (unit_is_in_focus(punit)) {
1062 }
1063 break;
1064 case USDLG_CMD_READY:
1065 if (punit->activity != ACTIVITY_IDLE) {
1067 }
1068 break;
1069 case USDLG_CMD_SENTRY:
1070 if (punit->activity != ACTIVITY_SENTRY) {
1072 }
1073 break;
1074 case USDLG_CMD_CENTER:
1075 case USDLG_CMD_FOCUS:
1076 /* Nothing here. It is done in its own functions. */
1077 break;
1078 case USDLG_CMD_LAST:
1079 /* Should never happen. */
1081 break;
1082 }
1083}
1084
1085/*************************************************************************/
1088static void usdlg_cmd_center(GObject *object, gpointer data)
1089{
1093 GtkTreeSelection *selection;
1094 GtkTreeModel *model;
1095 GtkTreeIter it;
1096 gint row;
1097 struct unit_select_dialog *pdialog = usdlg_get(FALSE);
1098
1099 fc_assert_ret(pdialog != NULL);
1101
1102 view = GTK_TREE_VIEW(pdialog->tabs[loc].view);
1103 selection = gtk_tree_view_get_selection(view);
1104
1105 if (!gtk_tree_selection_get_selected(selection, &model, &it)) {
1106 log_debug("No selection");
1107 return;
1108 }
1109 gtk_tree_model_get(model, &it, USDLG_COL_ROW_TYPE, &row, -1);
1110
1111 if (row == ROW_UNIT || row == ROW_UNIT_TRANSPORTED) {
1112 gint uid;
1113 struct unit *punit;
1114
1115 gtk_tree_model_get(model, &it, USDLG_COL_UID, &uid, -1);
1116
1118 if (punit) {
1120 }
1121 }
1122}
1123
1124/*************************************************************************/
1127static void usdlg_cmd_focus(GObject *object, gpointer data)
1128{
1131 struct unit_select_dialog *pdialog = usdlg_get(FALSE);
1132
1133 fc_assert_ret(pdialog != NULL);
1135
1137}
1138
1139/*************************************************************************/
1147
1148/*************************************************************************/
1152{
1154 GtkTreeModel *model;
1155 GtkTreeIter it;
1156 gint row;
1157
1159 return;
1160 }
1161
1162 if (!gtk_tree_selection_get_selected(selection, &model, &it)) {
1163 log_debug("No selection");
1164 return;
1165 }
1166 gtk_tree_model_get(model, &it, USDLG_COL_ROW_TYPE, &row, -1);
1167
1168 if (row == ROW_UNIT || row == ROW_UNIT_TRANSPORTED) {
1169 gint uid;
1170 struct unit *punit;
1171
1172 gtk_tree_model_get(model, &it, USDLG_COL_UID, &uid, -1);
1173
1175 if (punit && unit_owner(punit) == client_player()) {
1176 /* FIXME: If unit is not idle to begin with, we can only request
1177 * idling, and as we have no server reply yet,
1178 * the unit_focus_try() below will fail. */
1181 usdlg_destroy();
1182 }
1183 }
1184}
1185
1186/*************************************************************************/
1190{
1193 GtkTreeSelection *selection;
1194 GtkTreeModel *model;
1195 GtkTreeIter it;
1196 gint row, uid;
1197 struct unit_select_dialog *pdialog = usdlg_get(FALSE);
1198 struct unit *punit;
1200 int cmd_id;
1201
1203
1204 if (pdialog == NULL) {
1205 /* Dialog closed, nothing we can do */
1206 return;
1207 }
1208
1209 selection = gtk_tree_view_get_selection(view);
1210 if (!gtk_tree_selection_get_selected(selection, &model, &it)) {
1211 log_debug("No selection");
1212 return;
1213 }
1215 &uid, -1);
1216
1217 switch (row) {
1218 case ROW_UNITTYPE:
1219 case ROW_ACTIVITY:
1220 /* Button status for rows unittype and activity:
1221 * player observer
1222 * ready TRUE FALSE
1223 * sentry TRUE FALSE
1224 * select TRUE FALSE
1225 * deselect TRUE FALSE
1226 * center FALSE FALSE
1227 * focus FALSE FALSE */
1233 } else {
1238 }
1239
1242 break;
1243 case ROW_UNIT:
1245 /* Button status for rows unit and unit (transported):
1246 * player observer
1247 * ready !IDLE FALSE
1248 * sentry !SENTRY FALSE
1249 * select !FOCUS FALSE
1250 * deselect FOCUS FALSE
1251 * center TRUE TRUE
1252 * focus !FOCUS FALSE */
1254
1256 if (punit->activity == ACTIVITY_IDLE) {
1258 } else {
1260 }
1261
1262 if (punit->activity == ACTIVITY_SENTRY) {
1264 } else {
1266 }
1267
1268 if (!unit_is_in_focus(punit)) {
1272 } else {
1276 }
1277 } else {
1280
1283
1285 }
1286
1288 break;
1289
1290 default:
1292 for (cmd_id = 0; cmd_id < USDLG_CMD_LAST; cmd_id++) {
1294 }
1295 break;
1296 }
1297
1298 /* Set widget status. */
1299 for (cmd_id = 0; cmd_id < USDLG_CMD_LAST; cmd_id++) {
1302 }
1303}
const char * city_name_get(const struct city *pcity)
Definition city.c:1141
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:77
bool unit_is_in_focus(const struct unit *punit)
Definition control.c:388
void unit_focus_add(struct unit *punit)
Definition control.c:573
void unit_focus_try(struct unit *punit)
Definition control.c:502
void unit_focus_remove(struct unit *punit)
Definition control.c:603
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:801
void request_new_unit_activity(struct unit *punit, enum unit_activity act)
Definition control.c:1941
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:126
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:894
static void usdlg_cmd_deselect(GObject *object, gpointer data)
Definition unitselect.c:918
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:758
const char * usdlg_get_unit_descr(const struct unit *punit)
Definition unitselect.c:779
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:821
static void usdlg_tile(struct unit_select_dialog *pdialog, struct tile *ptile)
Definition unitselect.c:306
#define USDLG_COL_UTID
Definition unitselect.c:64
static void usdlg_cmd_sentry(GObject *object, gpointer data)
Definition unitselect.c:902
static struct unit_select_dialog * usdlg_get(bool create)
Definition unitselect.c:216
#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:720
static struct unit_select_dialog * usdlg_create(void)
Definition unitselect.c:234
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:926
#define USDLG_COLUMNS_ALL
Definition unitselect.c:73
static void usdlg_destroy_callback(GObject *object, gpointer data)
Definition unitselect.c:298
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:910
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:134
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:186
static void usdlg_cmd_row_activated(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
void unit_select_dialog_popdown(void)
Definition unitselect.c:207
static void usdlg_tab_append_utype(GtkTreeStore *store, enum unit_select_location_mode loc, const struct unit_type *putype, GtkTreeIter *it)
Definition unitselect.c:671
#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:380
static bool usdlg_tab_update(struct unit_select_dialog *pdialog, struct usdata_hash *ushash, enum unit_select_location_mode loc)
Definition unitselect.c:561
static void usdlg_refresh(struct unit_select_dialog *pdialog)
Definition unitselect.c:331
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:286
static GtkTreeStore * usdlg_tab_store_new(void)
Definition unitselect.c:533
#define show(id)
Definition widget.h:235
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
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:1217
#define ARRAY_SIZE(x)
Definition shared.h:85
cairo_surface_t * surface
Definition canvas.h:23
Definition city.h:318
Definition tile.h:50
struct tile * ptile
Definition unitselect.c:118
GtkTreePath * path
Definition unitselect.c:127
GtkWidget * shell
Definition unitselect.c:120
GtkWidget * view
Definition unitselect.c:126
GtkWidget * cmd[USDLG_CMD_LAST]
Definition unitselect.c:129
GtkWidget * notebook
Definition unitselect.c:121
GtkTreeStore * store
Definition unitselect.c:124
struct unit_select_dialog::@163 tabs[SELLOC_COUNT]
GtkWidget * page
Definition unitselect.c:125
Definition unit.h:140
enum unit_activity activity
Definition unit.h:159
int id
Definition unit.h:147
int homecity
Definition unit.h:148
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:960
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
#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:815
int tileset_full_tile_width(const struct tileset *t)
Definition tilespec.c:802
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1847
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2545
const char * get_activity_text(enum unit_activity activity)
Definition unit.c:657
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2555
#define unit_tile(_pu)
Definition unit.h:407
#define unit_owner(_pu)
Definition unit.h:406
#define activity_type_iterate(_act_)
Definition unit.h:287
#define activity_type_iterate_end
Definition unit.h:292
#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:126
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1595
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:93
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
#define unit_type_iterate(_p)
Definition unittype.h:863
#define unit_type_iterate_end
Definition unittype.h:870