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