1 /* Pioneers - Implementation of the excellent Settlers of Catan board game.
2  *   Go buy a copy.
3  *
4  * Copyright (C) 1999 Dave Cole
5  * Copyright (C) 2003,2006 Bas Wijnen <shevek@fmf.nl>
6  * Copyright (C) 2010 Roland Clobus <rclobus@rclobus.nl>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22 
23 #include "config.h"
24 #include <stdlib.h>
25 #include "frontend.h"
26 #include "player-icon.h"
27 #include "config-gnome.h"
28 #include "client.h"
29 #include "common_gtk.h"
30 
31 typedef struct {
32 	GtkWidget *dlg;
33 	GtkWidget *name_entry;
34 	GtkWidget *check_btn;
35 	GtkWidget *image;
36 	GtkWidget *style_hbox;
37 	GtkWidget *color_btn1;
38 	GtkWidget *color_btn2;
39 	GtkWidget *variant_btn;
40 	gchar *original_name;
41 	gchar *original_style;
42 	gchar *current_style;
43 	gulong name_change_cb_id;
44 } DialogData;
45 
46 static DialogData name_dialog;
47 
48 static void update_icon(DialogData * data);
49 
name_change_name_cb(NotifyingString * name)50 static void name_change_name_cb(NotifyingString * name)
51 {
52 	gchar *nm = notifying_string_get(name);
53 	gtk_entry_set_text(GTK_ENTRY(name_dialog.name_entry), nm);
54 	g_free(nm);
55 }
56 
change_name_cb(G_GNUC_UNUSED GtkDialog * dlg,int response_id,gpointer user_data)57 static void change_name_cb(G_GNUC_UNUSED GtkDialog * dlg, int response_id,
58 			   gpointer user_data)
59 {
60 	DialogData *dialog = user_data;
61 	g_signal_handler_disconnect(requested_name,
62 				    dialog->name_change_cb_id);
63 	if (response_id == GTK_RESPONSE_OK) {
64 		const gchar *new_name =
65 		    gtk_entry_get_text(GTK_ENTRY(dialog->name_entry));
66 		const gchar *new_style = dialog->current_style;
67 		if (0 != strcmp(new_name, dialog->original_name)) {
68 			notifying_string_set(requested_name, new_name);
69 		}
70 		if (0 != strcmp(new_style, dialog->original_style)) {
71 			notifying_string_set(requested_style, new_style);
72 		}
73 	}
74 	g_free(dialog->original_name);
75 	g_free(dialog->original_style);
76 	g_free(dialog->current_style);
77 	gtk_widget_destroy(GTK_WIDGET(dialog->dlg));
78 }
79 
realize_player_icon_cb(G_GNUC_UNUSED GtkWidget * widget,gpointer user_data)80 static void realize_player_icon_cb(G_GNUC_UNUSED GtkWidget * widget,
81 				   gpointer user_data)
82 {
83 	DialogData *dialog = user_data;
84 
85 	update_icon(dialog);
86 }
87 
change_style_cb(G_GNUC_UNUSED GtkWidget * widget,gpointer user_data)88 static void change_style_cb(G_GNUC_UNUSED GtkWidget * widget,
89 			    gpointer user_data)
90 {
91 	DialogData *dialog = user_data;
92 
93 	g_free(dialog->current_style);
94 	if (gtk_toggle_button_get_active
95 	    (GTK_TOGGLE_BUTTON(dialog->check_btn))) {
96 		GdkRGBA c1;
97 		GdkRGBA c2;
98 		guint variant;
99 		gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER
100 					   (dialog->color_btn1), &c1);
101 		gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER
102 					   (dialog->color_btn2), &c2);
103 		variant =
104 		    gtk_range_get_value(GTK_RANGE(dialog->variant_btn)) -
105 		    1;
106 		dialog->current_style =
107 		    playericon_create_human_style(&c1, variant, &c2);
108 	} else {
109 		dialog->current_style = g_strdup(default_player_style);
110 	}
111 	update_icon(dialog);
112 }
113 
activate_style_cb(GtkWidget * widget,gpointer user_data)114 static void activate_style_cb(GtkWidget * widget, gpointer user_data)
115 {
116 	DialogData *dialog = user_data;
117 	gtk_widget_set_sensitive(dialog->style_hbox,
118 				 gtk_toggle_button_get_active
119 				 (GTK_TOGGLE_BUTTON(dialog->check_btn)));
120 	change_style_cb(widget, user_data);
121 }
122 
name_create_dlg(void)123 void name_create_dlg(void)
124 {
125 	GtkWidget *dlg_vbox;
126 	GtkWidget *hbox;
127 	GtkWidget *lbl;
128 	GdkRGBA face_color, variant_color;
129 	guint variant;
130 	gboolean parse_ok;
131 	gint width;
132 	gint height;
133 
134 	if (name_dialog.dlg != NULL) {
135 		gtk_window_present(GTK_WINDOW(name_dialog.dlg));
136 		return;
137 	};
138 
139 	name_dialog.dlg = gtk_dialog_new_with_buttons(
140 							     /* Dialog caption */
141 							     _(""
142 							       "Change Player Name"),
143 							     GTK_WINDOW
144 							     (app_window),
145 							     GTK_DIALOG_DESTROY_WITH_PARENT,
146 							     /* Button text */
147 							     _("_Cancel"),
148 							     GTK_RESPONSE_CANCEL,
149 							     /* Button text */
150 							     _("_OK"),
151 							     GTK_RESPONSE_OK,
152 							     NULL);
153 	gtk_dialog_set_default_response(GTK_DIALOG(name_dialog.dlg),
154 					GTK_RESPONSE_OK);
155 	g_signal_connect(G_OBJECT(name_dialog.dlg), "destroy",
156 			 G_CALLBACK(gtk_widget_destroyed),
157 			 &name_dialog.dlg);
158 	gtk_widget_realize(name_dialog.dlg);
159 	gdk_window_set_functions(gtk_widget_get_window(name_dialog.dlg),
160 				 GDK_FUNC_MOVE | GDK_FUNC_CLOSE);
161 
162 	dlg_vbox =
163 	    gtk_dialog_get_content_area(GTK_DIALOG(name_dialog.dlg));
164 	gtk_widget_show(dlg_vbox);
165 
166 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
167 	gtk_widget_show(hbox);
168 	gtk_box_pack_start(GTK_BOX(dlg_vbox), hbox, FALSE, TRUE, 0);
169 	gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
170 
171 	/* Label */
172 	lbl = gtk_label_new(_("Player name:"));
173 	gtk_widget_show(lbl);
174 	gtk_box_pack_start(GTK_BOX(hbox), lbl, FALSE, TRUE, 0);
175 	gtk_label_set_xalign(GTK_LABEL(lbl), 1.0);
176 
177 	name_dialog.name_entry = gtk_entry_new();
178 	gtk_entry_set_max_length(GTK_ENTRY(name_dialog.name_entry),
179 				 MAX_NAME_LENGTH);
180 	gtk_widget_show(name_dialog.name_entry);
181 	gtk_box_pack_start(GTK_BOX(hbox), name_dialog.name_entry, TRUE,
182 			   TRUE, 0);
183 	gtk_entry_set_width_chars(GTK_ENTRY(name_dialog.name_entry),
184 				  MAX_NAME_LENGTH);
185 	name_dialog.original_name = notifying_string_get(requested_name);
186 	gtk_entry_set_text(GTK_ENTRY(name_dialog.name_entry),
187 			   name_dialog.original_name);
188 
189 	gtk_entry_set_activates_default(GTK_ENTRY(name_dialog.name_entry),
190 					TRUE);
191 	name_dialog.name_change_cb_id =
192 	    g_signal_connect(requested_name, "changed",
193 			     G_CALLBACK(name_change_name_cb), NULL);
194 
195 	name_dialog.original_style = notifying_string_get(requested_style);
196 	name_dialog.current_style = notifying_string_get(requested_style);
197 	parse_ok =
198 	    playericon_parse_human_style(name_dialog.current_style,
199 					 &face_color, &variant,
200 					 &variant_color);
201 
202 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
203 	gtk_widget_show(hbox);
204 	gtk_box_pack_start(GTK_BOX(dlg_vbox), hbox, FALSE, TRUE, 0);
205 	gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
206 
207 	name_dialog.style_hbox =
208 	    gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
209 	gtk_widget_set_sensitive(name_dialog.style_hbox, FALSE);
210 
211 	name_dialog.check_btn = gtk_check_button_new();
212 	gtk_widget_show(name_dialog.check_btn);
213 	gtk_box_pack_start(GTK_BOX(hbox), name_dialog.check_btn, FALSE,
214 			   TRUE, 0);
215 	g_signal_connect(name_dialog.check_btn, "toggled",
216 			 G_CALLBACK(activate_style_cb), &name_dialog);
217 
218 	name_dialog.image = gtk_image_new();
219 	gtk_icon_size_lookup(GTK_ICON_SIZE_DIALOG, &width, &height);
220 	gtk_widget_set_size_request(name_dialog.image, width, height);
221 	gtk_widget_show(name_dialog.image);
222 	gtk_box_pack_start(GTK_BOX(hbox), name_dialog.image, FALSE, TRUE,
223 			   0);
224 	g_signal_connect(G_OBJECT(name_dialog.image), "realize",
225 			 G_CALLBACK(realize_player_icon_cb), &name_dialog);
226 
227 	gtk_widget_show(name_dialog.style_hbox);
228 	gtk_box_pack_start(GTK_BOX(hbox), name_dialog.style_hbox, TRUE,
229 			   TRUE, 0);
230 	gtk_container_set_border_width(GTK_CONTAINER
231 				       (name_dialog.style_hbox), 5);
232 
233 	/* Label: set player icon preferences */
234 	lbl = gtk_label_new(_("Face:"));
235 	gtk_widget_show(lbl);
236 	gtk_box_pack_start(GTK_BOX(name_dialog.style_hbox), lbl, FALSE,
237 			   TRUE, 0);
238 	gtk_label_set_xalign(GTK_LABEL(lbl), 1.0);
239 
240 	name_dialog.color_btn1 =
241 	    gtk_color_button_new_with_rgba(&face_color);
242 	gtk_widget_show(name_dialog.color_btn1);
243 	gtk_box_pack_start(GTK_BOX(name_dialog.style_hbox),
244 			   name_dialog.color_btn1, FALSE, TRUE, 0);
245 	g_signal_connect(name_dialog.color_btn1, "color-set",
246 			 G_CALLBACK(change_style_cb), &name_dialog);
247 
248 	/* Label: set player icon preferences */
249 	lbl = gtk_label_new(_("Variant:"));
250 	gtk_widget_show(lbl);
251 	gtk_box_pack_start(GTK_BOX(name_dialog.style_hbox), lbl, FALSE,
252 			   TRUE, 0);
253 	gtk_label_set_xalign(GTK_LABEL(lbl), 1.0);
254 
255 	name_dialog.color_btn2 =
256 	    gtk_color_button_new_with_rgba(&variant_color);
257 	gtk_widget_show(name_dialog.color_btn2);
258 	gtk_box_pack_start(GTK_BOX(name_dialog.style_hbox),
259 			   name_dialog.color_btn2, FALSE, TRUE, 0);
260 	g_signal_connect(name_dialog.color_btn2, "color-set",
261 			 G_CALLBACK(change_style_cb), &name_dialog);
262 
263 	name_dialog.variant_btn =
264 	    gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 1.0,
265 				     playericon_human_style_count(), 1.0);
266 	gtk_widget_set_size_request(name_dialog.variant_btn, width, -1);
267 	gtk_scale_set_digits(GTK_SCALE(name_dialog.variant_btn), 0);
268 	gtk_scale_set_value_pos(GTK_SCALE(name_dialog.variant_btn),
269 				GTK_POS_LEFT);
270 	gtk_range_set_value(GTK_RANGE(name_dialog.variant_btn),
271 			    variant + 1);
272 	gtk_widget_show(name_dialog.variant_btn);
273 	gtk_box_pack_start(GTK_BOX(name_dialog.style_hbox),
274 			   name_dialog.variant_btn, TRUE, TRUE, 0);
275 	g_signal_connect(name_dialog.variant_btn, "value-changed",
276 			 G_CALLBACK(change_style_cb), &name_dialog);
277 	/* destroy dialog when OK or Cancel button gets clicked */
278 	g_signal_connect(name_dialog.dlg, "response",
279 			 G_CALLBACK(change_name_cb), &name_dialog);
280 
281 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
282 				     (name_dialog.check_btn), parse_ok);
283 
284 	gtk_widget_show(name_dialog.dlg);
285 	gtk_widget_grab_focus(name_dialog.name_entry);
286 }
287 
update_icon(DialogData * data)288 void update_icon(DialogData * data)
289 {
290 	GdkPixbuf *pixbuf;
291 	cairo_surface_t *surface;
292 	GtkAllocation allocation;
293 
294 	if (!gtk_widget_get_realized(data->image)) {
295 		return;
296 	}
297 	gtk_widget_get_allocation(data->image, &allocation);
298 	surface = playericon_create_icon(data->current_style,
299 					 player_or_spectator_color
300 					 (my_player_num()), FALSE, TRUE,
301 					 allocation.width,
302 					 allocation.height);
303 	pixbuf =
304 	    gdk_pixbuf_get_from_surface(surface, 0, 0, allocation.width,
305 					allocation.height);
306 	cairo_surface_destroy(surface);
307 
308 	gtk_image_set_from_pixbuf(GTK_IMAGE(data->image), pixbuf);
309 	g_object_unref(pixbuf);
310 }
311