1 /*
2     GNUbik -- A 3 dimensional magic cube game.
3     Copyright (C) 2003, 2004, 2011  John Darrington
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 3 of the License,  or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <config.h>
20 #include <gtk/gtk.h>
21 #include "dialogs.h"
22 #include <stdlib.h>
23 
24 #include "cube.h"
25 #include "version.h"
26 #include "drwBlock.h"
27 #include "menus.h"
28 
29 #include "game.h"
30 
31 #include <glib.h>
32 #include <assert.h>
33 
34 #include <libintl.h>
35 #define _(String) gettext (String)
36 #define N_(String) (String)
37 
38 #define BOX_PADDING 10
39 
40 struct preferences_state
41 {
42   GObject *adj[3];
43   GtkWidget *entry[3];
44 };
45 
46 static struct preferences_state *
pref_state_create(GtkBox * parent,const GbkGame * game)47 pref_state_create (GtkBox * parent, const GbkGame * game)
48 {
49   gint i;
50   struct preferences_state *ps = g_malloc (sizeof (*ps));
51 
52   for (i = 0; i < 3; ++i)
53     {
54       ps->adj[i] = G_OBJECT (
55 	gtk_adjustment_new (gbk_cube_get_size (game->cube, 0), 1, G_MAXFLOAT,
56 			    1, 1, 0));
57       g_object_ref (ps->adj[i]);
58       ps->entry[i] = gtk_spin_button_new (GTK_ADJUSTMENT (ps->adj[i]), 0, 0);
59       g_object_ref (ps->entry[i]);
60       gtk_box_pack_start (parent, ps->entry[i], FALSE, FALSE, 0);
61     }
62 
63   return ps;
64 }
65 
66 static void
pref_state_destroy(struct preferences_state * ps)67 pref_state_destroy (struct preferences_state *ps)
68 {
69   int i;
70   for (i = 0; i < 3; ++i)
71     {
72       g_object_unref (ps->adj[i]);
73       g_object_unref (ps->entry[i]);
74     }
75 
76   g_free (ps);
77 }
78 
79 
80 /* Allows only cubic cubes if the togglebutton is active */
81 static void
toggle_regular(GtkToggleButton * button,gpointer data)82 toggle_regular (GtkToggleButton * button, gpointer data)
83 {
84   gint i;
85   struct preferences_state *ps = data;
86 
87   if (gtk_toggle_button_get_active (button))
88     {
89       for (i = 0; i < 3; ++i)
90 	gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (ps->entry[i]),
91 					GTK_ADJUSTMENT (ps->adj[0]));
92       gtk_adjustment_value_changed (GTK_ADJUSTMENT (ps->adj[0]));
93     }
94   else
95     {
96       for (i = 0; i < 3; ++i)
97 	gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON (ps->entry[i]),
98 					GTK_ADJUSTMENT (ps->adj[i]));
99     }
100 }
101 
102 static struct preferences_state *
create_dimension_widget(GtkContainer * parent,const GbkGame * game)103 create_dimension_widget (GtkContainer * parent, const GbkGame * game)
104 {
105   gint i;
106   GtkWidget *label = gtk_label_new (_("Size of cube:"));
107 
108   GtkWidget *hbox = gtk_hbox_new (FALSE, BOX_PADDING);
109   GtkWidget *vbox = gtk_vbox_new (TRUE, BOX_PADDING);
110   GtkWidget *checkbox =
111     gtk_check_button_new_with_mnemonic (_("Re_gular cube"));
112   GtkWidget *vbox2 = gtk_vbox_new (TRUE, BOX_PADDING);
113 
114   struct preferences_state *ps = pref_state_create (GTK_BOX (vbox), game);
115 
116   gtk_widget_set_tooltip_text (vbox,
117 			       _("Sets the number of blocks in each side"));
118 
119   gtk_widget_set_tooltip_text (checkbox,
120 			       _
121 			       ("Allow only cubes with all sides equal size"));
122 
123   g_signal_connect (checkbox, "toggled", G_CALLBACK (toggle_regular), ps);
124 
125   gtk_box_pack_start (GTK_BOX (vbox2), label, TRUE, FALSE, 0);
126   gtk_box_pack_start (GTK_BOX (vbox2), checkbox, TRUE, FALSE, 0);
127 
128   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, FALSE, 0);
129   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, FALSE, 0);
130 
131   for (i = 0; i < 3; ++i)
132     gtk_spin_button_set_value (GTK_SPIN_BUTTON (ps->entry[i]),
133 			       gbk_cube_get_size (game->cube, i)),
134       gtk_widget_show_all (hbox);
135 
136   gtk_container_add (parent, hbox);
137 
138   return ps;
139 }
140 
141 
142 void
about_dialog(GtkWidget * w,GtkWindow * toplevel)143 about_dialog (GtkWidget * w, GtkWindow * toplevel)
144 {
145   /* Create the widgets */
146   GtkWidget *dialog = gtk_about_dialog_new ();
147 
148   gtk_window_set_icon_name (GTK_WINDOW (dialog), "gnubik");
149 
150   gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
151   gtk_window_set_transient_for (GTK_WINDOW (dialog), toplevel);
152 
153   gtk_about_dialog_set_program_name (GTK_ABOUT_DIALOG (dialog), _(PACKAGE_NAME));
154 
155   gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (dialog), PACKAGE_VERSION);
156 
157   gtk_about_dialog_set_website (GTK_ABOUT_DIALOG (dialog), PACKAGE_URL);
158 
159   gtk_about_dialog_set_license (GTK_ABOUT_DIALOG (dialog), copyleft_notice);
160 
161   gtk_about_dialog_set_logo_icon_name (GTK_ABOUT_DIALOG (dialog), "gnubik");
162 
163   gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG (dialog),
164 				 _("A 3 dimensional magic cube puzzle"));
165 
166   gtk_about_dialog_set_translator_credits (GTK_ABOUT_DIALOG (dialog),
167 					   /* TRANSLATORS: Do not translate this string. Instead, use it to list
168 					      the people who have helped with translation to your language. */
169 					   _("translator-credits"));
170 
171   gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG (dialog),
172 				  "Copyright © 1998, 2003 John Darrington;\n 2004 John Darrington, Dale Mellor;\n2011 John Darrington");
173 
174   gtk_dialog_run (GTK_DIALOG (dialog));
175 
176   gtk_widget_destroy (GTK_WIDGET (dialog));
177 }
178 
179 
180 
181 
182 
183 
184 void
new_game_dialog(GtkWidget * w,GbkGame * game)185 new_game_dialog (GtkWidget * w, GbkGame * game)
186 {
187   gint response;
188 
189   GtkWidget *dialog = gtk_dialog_new_with_buttons (_("New Game"),
190 						   game->toplevel,
191 						   GTK_DIALOG_MODAL |
192 						   GTK_DIALOG_DESTROY_WITH_PARENT,
193 						   GTK_STOCK_OK,
194 						   GTK_RESPONSE_ACCEPT,
195 						   GTK_STOCK_CANCEL,
196 						   GTK_RESPONSE_CANCEL,
197 						   NULL);
198 
199   GtkWidget *vbox = gtk_vbox_new (FALSE, 5);
200 
201   GtkWidget *frame_dimensions = gtk_frame_new (_("Dimensions"));
202 
203   g_object_set (frame_dimensions, "shadow-type", GTK_SHADOW_NONE, NULL);
204 
205   gtk_window_set_icon_name (GTK_WINDOW (dialog), "gnubik");
206 
207   gtk_window_set_transient_for (GTK_WINDOW (dialog), game->toplevel);
208 
209   struct preferences_state *ps =
210     create_dimension_widget (GTK_CONTAINER (frame_dimensions), game);
211 
212   GtkWidget *frame_pos = gtk_frame_new (_("Initial position"));
213   GtkWidget *bb = gtk_vbutton_box_new ();
214 
215   GtkWidget *random_state =
216     gtk_radio_button_new_with_mnemonic_from_widget (NULL, _("_Random"));
217   GtkWidget *solved_state =
218     gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON
219 						    (random_state),
220 						    _("_Solved"));
221 
222   g_object_set (frame_pos, "shadow-type", GTK_SHADOW_NONE, NULL);
223 
224   gtk_container_add (GTK_CONTAINER (bb), random_state);
225   gtk_container_add (GTK_CONTAINER (bb), solved_state);
226 
227   gtk_container_add (GTK_CONTAINER (frame_pos), bb);
228 
229   gtk_box_pack_start (GTK_BOX (vbox), frame_pos, FALSE, 0, 0);
230   gtk_box_pack_start (GTK_BOX (vbox), frame_dimensions, FALSE, 0, 0);
231 
232   gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), vbox);
233 
234   gtk_widget_show_all (gtk_dialog_get_content_area (GTK_DIALOG (dialog)));
235 
236   response = gtk_dialog_run (GTK_DIALOG (dialog));
237 
238   if (response == GTK_RESPONSE_ACCEPT)
239     {
240       start_new_game
241 	(game,
242 	 gtk_spin_button_get_value (GTK_SPIN_BUTTON (ps->entry[0])),
243 	 gtk_spin_button_get_value (GTK_SPIN_BUTTON (ps->entry[1])),
244 	 gtk_spin_button_get_value (GTK_SPIN_BUTTON (ps->entry[2])),
245 	 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (random_state)));
246     }
247 
248   pref_state_destroy (ps);
249 
250   gtk_widget_destroy (dialog);
251 }
252