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 <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include <gtk/gtk.h>
23 
24 /* utility */
25 #include "fcintl.h"
26 #include "log.h"
27 
28 /* common */
29 #include "game.h"
30 #include "player.h"
31 
32 /* client */
33 #include "options.h"
34 
35 /* client/gui-gtk-3.0 */
36 #include "dialogs.h"
37 #include "gui_main.h"
38 #include "gui_stuff.h"
39 #include "mapview.h"
40 
41 #include "finddlg.h"
42 
43 static struct gui_dialog *find_dialog_shell;
44 static GtkWidget *find_view;
45 
46 static void update_find_dialog(GtkListStore *store);
47 
48 static void find_response(struct gui_dialog *dlg, int response, gpointer data);
49 static void find_destroy_callback(GtkWidget *w, gpointer data);
50 static void find_selection_callback(GtkTreeSelection *selection,
51                                     GtkTreeModel *model);
52 
53 static struct tile *pos;
54 
55 /****************************************************************
56 popup the dialog 10% inside the main-window
57 *****************************************************************/
popup_find_dialog(void)58 void popup_find_dialog(void)
59 {
60   if (!find_dialog_shell) {
61     GtkWidget         *label;
62     GtkWidget         *sw;
63     GtkListStore      *store;
64     GtkTreeSelection  *selection;
65     GtkCellRenderer   *renderer;
66     GtkTreeViewColumn *column;
67 
68     pos = get_center_tile_mapcanvas();
69 
70     gui_dialog_new(&find_dialog_shell, GTK_NOTEBOOK(bottom_notebook), NULL,
71                    TRUE);
72     gui_dialog_set_title(find_dialog_shell, _("Find City"));
73     gui_dialog_set_default_size(find_dialog_shell, -1, 240);
74 
75     gui_dialog_add_button(find_dialog_shell,
76 	GTK_STOCK_FIND, GTK_RESPONSE_ACCEPT);
77     gui_dialog_add_button(find_dialog_shell,
78 	GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
79 
80     gui_dialog_set_default_response(find_dialog_shell, GTK_RESPONSE_ACCEPT);
81 
82     gui_dialog_response_set_callback(find_dialog_shell, find_response);
83 
84     g_signal_connect(find_dialog_shell->vbox, "destroy",
85 	G_CALLBACK(find_destroy_callback), NULL);
86 
87     store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
88     gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store),
89 	0, GTK_SORT_ASCENDING);
90 
91     find_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
92     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(find_view));
93     g_object_unref(store);
94     gtk_tree_view_columns_autosize(GTK_TREE_VIEW(find_view));
95     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(find_view), FALSE);
96 
97     renderer = gtk_cell_renderer_text_new();
98     column = gtk_tree_view_column_new_with_attributes(NULL, renderer,
99 	"text", 0, NULL);
100     gtk_tree_view_column_set_sort_order(column, GTK_SORT_ASCENDING);
101     gtk_tree_view_append_column(GTK_TREE_VIEW(find_view), column);
102 
103     sw = gtk_scrolled_window_new(NULL, NULL);
104     g_object_set(sw, "margin", 2, NULL);
105     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
106 	GTK_SHADOW_ETCHED_IN);
107     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
108 	GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
109     gtk_container_add(GTK_CONTAINER(sw), find_view);
110 
111     gtk_widget_set_hexpand(GTK_WIDGET(find_view), TRUE);
112     gtk_widget_set_vexpand(GTK_WIDGET(find_view), TRUE);
113 
114     label = g_object_new(GTK_TYPE_LABEL,
115 	"use-underline", TRUE,
116 	"mnemonic-widget", find_view,
117 	"label", _("Ci_ties:"),
118 	"xalign", 0.0, "yalign", 0.5, NULL);
119     gtk_container_add(GTK_CONTAINER(find_dialog_shell->vbox), label);
120     gtk_container_add(GTK_CONTAINER(find_dialog_shell->vbox), sw);
121 
122     g_signal_connect(selection, "changed",
123 	G_CALLBACK(find_selection_callback), store);
124 
125     update_find_dialog(store);
126     gtk_tree_view_focus(GTK_TREE_VIEW(find_view));
127 
128     gui_dialog_show_all(find_dialog_shell);
129   }
130 
131   gui_dialog_raise(find_dialog_shell);
132 }
133 
134 
135 
136 /**************************************************************************
137   Update find dialog with current cities
138 **************************************************************************/
update_find_dialog(GtkListStore * store)139 static void update_find_dialog(GtkListStore *store)
140 {
141   GtkTreeIter it;
142 
143   gtk_list_store_clear(store);
144 
145   players_iterate(pplayer) {
146     city_list_iterate(pplayer->cities, pcity) {
147       GValue value = { 0, };
148 
149       gtk_list_store_append(store, &it);
150 
151       g_value_init(&value, G_TYPE_STRING);
152       g_value_set_static_string(&value, city_name_get(pcity));
153       gtk_list_store_set_value(store, &it, 0, &value);
154       g_value_unset(&value);
155 
156       gtk_list_store_set(store, &it, 1, pcity, -1);
157     } city_list_iterate_end;
158   } players_iterate_end;
159 }
160 
161 /**************************************************************************
162   User responded to find dialog
163 **************************************************************************/
find_response(struct gui_dialog * dlg,int response,gpointer data)164 static void find_response(struct gui_dialog *dlg, int response, gpointer data)
165 {
166   if (response == GTK_RESPONSE_ACCEPT) {
167     GtkTreeSelection *selection;
168     GtkTreeModel *model;
169     GtkTreeIter it;
170 
171     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(find_view));
172 
173     if (gtk_tree_selection_get_selected(selection, &model, &it)) {
174       struct city *pcity;
175 
176       gtk_tree_model_get(model, &it, 1, &pcity, -1);
177 
178       if (pcity) {
179 	pos = pcity->tile;
180       }
181     }
182   }
183   gui_dialog_destroy(dlg);
184 }
185 
186 /**************************************************************************
187   Find dialog destroyed
188 **************************************************************************/
find_destroy_callback(GtkWidget * w,gpointer data)189 static void find_destroy_callback(GtkWidget *w, gpointer data)
190 {
191   can_slide = FALSE;
192   center_tile_mapcanvas(pos);
193   can_slide = TRUE;
194 }
195 
196 /**************************************************************************
197   User selected city from find dialog
198 **************************************************************************/
find_selection_callback(GtkTreeSelection * selection,GtkTreeModel * model)199 static void find_selection_callback(GtkTreeSelection *selection,
200 				    GtkTreeModel *model)
201 {
202   GtkTreeIter it;
203   struct city *pcity;
204 
205   if (!gtk_tree_selection_get_selected(selection, NULL, &it))
206     return;
207 
208   gtk_tree_model_get(model, &it, 1, &pcity, -1);
209 
210   if (pcity) {
211     can_slide = FALSE;
212     center_tile_mapcanvas(pcity->tile);
213     can_slide = TRUE;
214   }
215 }
216