1 /* preferences.c - preferences dialog
2  *
3  * This program is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU General Public
5  * License as published by the Free Software Foundation; either
6  * version 2 of the License, or (at your option) any later version.
7  */
8 #include <gtk/gtk.h>
9 #include <string.h>
10 
11 #include "gtkballs.h"
12 #include "gtkutils.h"
13 #include "prefs.h"
14 #include "gfx.h"
15 #include "theme.h"
16 #include "game.h"
17 #include "mainwin.h"
18 
19 enum {
20         PR_DIALOG,
21         PR_SHOW_NEXT,
22         PR_SHOW_PATH,
23         PR_SHOW_PAWS,
24         PR_SHOW_ANIM,
25         PR_SHOW_HL,
26         PR_HL_DR,
27         PR_HL_DG,
28         PR_HL_DB,
29         PR_TIME_LIMIT,
30         PR_TIME_VALUE,
31         PR_THEME_LIST,
32         PR_SIZE
33 };
34 
parent_toggled(GtkToggleButton * togglebutton,gpointer data)35 void parent_toggled(GtkToggleButton *togglebutton, gpointer data) {
36         gtk_widget_set_sensitive(GTK_WIDGET(data), gtk_toggle_button_get_active(togglebutton));
37 }
38 
preferences_destroy_cb(GtkWidget * widget,gpointer data)39 void preferences_destroy_cb(GtkWidget *widget, gpointer data) {
40         g_free(data);
41 }
42 
preferences_cancel(GtkWidget * widget,gpointer data)43 void preferences_cancel(GtkWidget *widget, gpointer data) {
44         GtkWidget **buttons = data;
45         gtk_widget_destroy(buttons[PR_DIALOG]);
46 }
47 
fix_draw_next_balls(gpointer data)48 gboolean fix_draw_next_balls(gpointer data) {
49         draw_next_balls();
50         return FALSE;
51 }
52 
preferences_apply(GtkWidget * widget,gpointer data)53 void preferences_apply(GtkWidget *widget, gpointer data) {
54         GtkWidget **buttons = data;
55         GtkTreeModel *model;
56         GtkTreeIter iter;
57         gchar *msg, *save, *themename;
58 
59 	gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(buttons[PR_THEME_LIST])), &model, &iter);
60         gtk_tree_model_get(model, &iter, 0, &themename, -1);
61 
62         if(strcmp(themename, pref_get_theme_name()) != 0) {
63                 save = g_strdup(pref_get_theme_name());
64                 pref_set_theme_name(themename);
65   		if(!load_theme(pref_get_theme_name())) {
66                         msg = g_strconcat(_("Failed loading theme \""), pref_get_theme_name(), "\"!\n", NULL);
67                         ut_simple_message_box(msg);
68                         g_free(msg);
69                         pref_set_theme_name(save);
70         	} else {
71                         set_jump_phase(0);
72                         remake_board(0, 1);
73                 	draw_next_balls();
74                 }
75                 g_free(save);
76         }
77         g_free(themename);
78 
79         pref_set_show_next_colors(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[PR_SHOW_NEXT])));
80         mw_show_hide_next_balls(pref_get_show_next_colors());
81 	g_timeout_add(50, fix_draw_next_balls, NULL);
82         pref_set_show_path(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[PR_SHOW_PATH])));
83         pref_set_show_footprints(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[PR_SHOW_PAWS])));
84         pref_set_show_destroy(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[PR_SHOW_ANIM])));
85 
86         pref_set_show_highlight(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[PR_SHOW_HL])));
87 
88         prefs_set_hl_dr(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buttons[PR_HL_DR])));
89         prefs_set_hl_dg(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buttons[PR_HL_DG])));
90         prefs_set_hl_db(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buttons[PR_HL_DB])));
91 
92 	gtkb_make_hl_pixmap(gtkbTheme);
93 
94         redraw_pointer();
95         if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[PR_TIME_LIMIT]))) {
96                 timer_start();
97                 timer_set_limit(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buttons[PR_TIME_VALUE])));
98         } else {
99                 timer_set_limit(-1);
100         }
101   	msg = save_preferences();
102         if(msg) {
103         	ut_simple_message_box(msg);
104                 g_free(msg);
105         }
106 }
107 
preferences_ok(GtkWidget * widget,gpointer data)108 void preferences_ok(GtkWidget *widget, gpointer data) {
109         GtkWidget **buttons = data;
110   	preferences_apply(widget, buttons);
111   	gtk_widget_destroy(buttons[PR_DIALOG]);
112 }
113 
preferences_dialog(void)114 void preferences_dialog(void) {
115         GtkWidget **buttons;
116   	GtkWidget *frame;
117   	GtkWidget *big_vbox, *vbox, *buttons_box;
118   	GtkWidget *theme_scrolled_window;
119   	GtkWidget *separator;
120   	gint i, st;
121         GtkListStore *store;
122         GtkTreeIter iter;
123         GtkTreePath *path;
124         GtkCellRenderer *renderer;
125         GtkTreeViewColumn *column;
126         gchar *pathstr;
127         gchar **themelist;
128 
129   	if(!(themelist = get_available_themes())) {
130                 ut_simple_message_box(_("No themes available! =(\n"));
131                 return;
132   	}
133 
134         buttons = g_malloc(PR_SIZE * sizeof(GtkWidget));
135 
136 	buttons[PR_DIALOG] = ut_window_new(_("Preferences"), "GtkBalls_Preferences", "GtkBalls", TRUE, TRUE, TRUE, 5);
137 	g_signal_connect(G_OBJECT(buttons[PR_DIALOG]), "destroy", G_CALLBACK(preferences_destroy_cb), buttons);
138 
139   	big_vbox = gtk_vbox_new(FALSE, 0);
140   	gtk_container_add(GTK_CONTAINER(buttons[PR_DIALOG]), big_vbox);
141 
142   	frame = gtk_frame_new(_("Preferences"));
143   	gtk_box_pack_start(GTK_BOX(big_vbox), frame, FALSE, FALSE, 0);
144 
145 	vbox = gtk_vbox_new(FALSE, 0);
146 	gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
147   	gtk_container_add(GTK_CONTAINER(frame), vbox);
148 
149         buttons[PR_SHOW_NEXT] = ut_check_button_new(_("Show colors that will appear on next turn"), pref_get_show_next_colors(), vbox);
150         buttons[PR_SHOW_PATH] = ut_check_button_new(_("Show path of the ball"), pref_get_show_path(), vbox);
151         buttons[PR_SHOW_PAWS] = ut_check_button_new(_("Show footprints of the ball"), pref_get_show_footprints(), vbox);
152         buttons[PR_SHOW_ANIM] = ut_check_button_new(_("Show animation of disappearing of the ball"), pref_get_show_destroy(), vbox);
153         buttons[PR_SHOW_HL]   = ut_check_button_new(_("Highlight \"active\" cell"), pref_get_show_highlight(), vbox);
154 
155         buttons[PR_HL_DR]     = ut_spin_button_start_new(_("Highlight red value: "), -128, 128, prefs_get_hl_dr(), vbox);
156         buttons[PR_HL_DG]     = ut_spin_button_start_new(_("Highlight green value: "), -128, 128, prefs_get_hl_dg(), vbox);
157         buttons[PR_HL_DB]     = ut_spin_button_start_new(_("Highlight blue value: "), -128, 128, prefs_get_hl_db(), vbox);
158         g_signal_connect(G_OBJECT(buttons[PR_SHOW_HL]), "toggled", G_CALLBACK(parent_toggled), buttons[PR_HL_DR]);
159         g_signal_connect(G_OBJECT(buttons[PR_SHOW_HL]), "toggled", G_CALLBACK(parent_toggled), buttons[PR_HL_DG]);
160         g_signal_connect(G_OBJECT(buttons[PR_SHOW_HL]), "toggled", G_CALLBACK(parent_toggled), buttons[PR_HL_DB]);
161         gtk_widget_set_sensitive(buttons[PR_HL_DR], pref_get_show_highlight());
162         gtk_widget_set_sensitive(buttons[PR_HL_DG], pref_get_show_highlight());
163         gtk_widget_set_sensitive(buttons[PR_HL_DB], pref_get_show_highlight());
164 
165         buttons[PR_TIME_LIMIT] = ut_check_button_new(_("Enable time limit"), timer_get_limit() > 0 ? 1 : 0, vbox);
166         buttons[PR_TIME_VALUE] = ut_spin_button_start_new(_("Time limit (seconds): "), 1, 3600, timer_get_limit() > 0 ? timer_get_limit() : 60, vbox);
167         g_signal_connect(G_OBJECT(buttons[PR_TIME_LIMIT]), "toggled", G_CALLBACK(parent_toggled), buttons[PR_TIME_VALUE]);
168         gtk_widget_set_sensitive(buttons[PR_TIME_VALUE], timer_get_limit() > 0 ? 1 : 0);
169 
170   	theme_scrolled_window = gtk_scrolled_window_new(NULL, NULL);
171         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(theme_scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
172         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(theme_scrolled_window), GTK_SHADOW_ETCHED_IN);
173   	gtk_box_pack_start(GTK_BOX(vbox), theme_scrolled_window, FALSE, FALSE, 5);
174 
175         store = gtk_list_store_new(1, G_TYPE_STRING);
176   	for(i = 0, st = 0; themelist[i] != NULL; i++) {
177                 gtk_list_store_append(store, &iter);
178                 gtk_list_store_set(store, &iter, 0, themelist[i], -1);
179         	if(!strcmp(themelist[i], pref_get_theme_name())) {
180                 	st = i;
181         	}
182                 g_free(themelist[i]);
183   	}
184         g_free(themelist);
185 
186       	buttons[PR_THEME_LIST] = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
187 	gtk_widget_set_size_request(buttons[PR_THEME_LIST], -1, 150);
188       	g_object_unref(G_OBJECT(store));
189       	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(buttons[PR_THEME_LIST]), TRUE);
190       	gtk_tree_view_set_search_column(GTK_TREE_VIEW(buttons[PR_THEME_LIST]), 0);
191         gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(buttons[PR_THEME_LIST])), GTK_SELECTION_BROWSE);
192   	gtk_container_add(GTK_CONTAINER(theme_scrolled_window), buttons[PR_THEME_LIST]);
193 
194         renderer = gtk_cell_renderer_text_new();
195         column = gtk_tree_view_column_new_with_attributes(_("Select Theme"), renderer, "text", 0, NULL);
196         gtk_tree_view_column_set_sort_column_id(column, 0);
197         gtk_tree_view_append_column(GTK_TREE_VIEW(buttons[PR_THEME_LIST]), column);
198 
199         pathstr = g_strdup_printf("%u", st);
200         if((path = gtk_tree_path_new_from_string(pathstr))) {
201 		gtk_tree_selection_select_path(gtk_tree_view_get_selection(GTK_TREE_VIEW(buttons[PR_THEME_LIST])), path);
202                 gtk_tree_view_set_cursor(GTK_TREE_VIEW(buttons[PR_THEME_LIST]), path, NULL, FALSE);
203                 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(buttons[PR_THEME_LIST]), path, NULL, TRUE, 0, 0);
204         	gtk_tree_path_free(path);
205         }
206         g_free(pathstr);
207 
208   	separator = gtk_hseparator_new();
209   	gtk_box_pack_start(GTK_BOX(big_vbox), separator, FALSE, FALSE, 5);
210 
211   	buttons_box = gtk_hbutton_box_new();
212         gtk_button_box_set_layout(GTK_BUTTON_BOX(buttons_box), GTK_BUTTONBOX_SPREAD);
213   	gtk_box_pack_start(GTK_BOX(big_vbox), buttons_box, TRUE, TRUE, 0);
214 
215         gtk_widget_grab_default(ut_button_new_stock(GTK_STOCK_OK, preferences_ok, buttons, buttons_box));
216 	ut_button_new_stock(GTK_STOCK_CANCEL, preferences_cancel, buttons, buttons_box);
217 	ut_button_new_stock(GTK_STOCK_APPLY, preferences_apply, buttons, buttons_box);
218 
219   	gtk_widget_show_all(buttons[PR_DIALOG]);
220 }
221