Made ChimaraApp class
[projects/chimara/chimara.git] / player / callbacks.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * callbacks.c
4  * Copyright (C) Philip en Marijn 2008 <>
5  * 
6  * callbacks.c is free software copyrighted by Philip en Marijn.
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name ``Philip en Marijn'' nor the name of any other
17  *    contributor may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  * 
20  * callbacks.c IS PROVIDED BY Philip en Marijn ``AS IS'' AND ANY EXPRESS
21  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Philip en Marijn OR ANY OTHER CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <glib.h>
34 #include <glib/gi18n.h>
35 #include <gtk/gtk.h>
36 #include <libchimara/chimara-glk.h>
37 #include <libchimara/chimara-if.h>
38 #include <config.h>
39 #include "error.h"
40 #include "player.h"
41 #include "app.h"
42
43 #if 0
44 /* If a game is running in @glk, warn the user that they will quit the currently
45 running game if they open a new one. Returns TRUE if no game was running.
46 Returns FALSE if the user cancelled. Returns TRUE and shuts down the running
47 game if the user wishes to continue. */
48 static gboolean
49 confirm_open_new_game(ChimaraGlk *glk)
50 {
51         g_return_val_if_fail(glk && CHIMARA_IS_GLK(glk), FALSE);
52         
53         GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk)));
54         
55         if(chimara_glk_get_running(glk)) {
56                 GtkWidget *dialog = gtk_message_dialog_new(window,
57                     GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
58                     GTK_MESSAGE_WARNING,
59                     GTK_BUTTONS_CANCEL,
60                     _("Are you sure you want to open a new game?"));
61                 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
62                     _("If you open a new game, you will quit the one you are currently playing."));
63                 gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OPEN, GTK_RESPONSE_OK);
64                 gint response = gtk_dialog_run(GTK_DIALOG(dialog));
65                 gtk_widget_destroy(dialog);
66                 
67                 if(response != GTK_RESPONSE_OK)
68                         return FALSE;
69
70                 chimara_glk_stop(glk);
71                 chimara_glk_wait(glk);
72         }
73         return TRUE;
74 }
75 #endif
76
77 /* Internal function: See if there is a corresponding graphics file. If so,
78 return its path. If not, return NULL. */
79 static char *
80 search_for_graphics_file(const char *filename)
81 {
82         ChimaraApp *theapp = chimara_app_get();
83
84         /* First get the name of the story file */
85         char *scratch = g_path_get_basename(filename);
86         *(strrchr(scratch, '.')) = '\0';
87
88         /* Check in the stored resource path, if set */
89         char *resource_path;
90         g_settings_get(theapp->prefs_settings, "resource-path", "ms", &resource_path);
91
92         /* Otherwise check in the current directory */
93         if(!resource_path)
94                 resource_path = g_path_get_dirname(filename);
95
96         char *blorbfile = g_strconcat(resource_path, "/", scratch, ".blb", NULL);
97         g_free(scratch);
98         g_free(resource_path);
99
100         if(g_file_test(blorbfile, G_FILE_TEST_EXISTS))
101                 return blorbfile;
102
103         g_free(blorbfile);
104         return NULL;
105 }
106
107 void
108 on_open_activate(GtkAction *action, ChimaraApp *theapp)
109 {
110         //if(!confirm_open_new_game(CHIMARA_GLK(player->glk)))
111         //      return;
112
113         GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Open Game"),
114             NULL, // FIXME
115             GTK_FILE_CHOOSER_ACTION_OPEN,
116             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
117             GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
118             NULL);
119
120         /* Get last opened path */
121         gchar *path;
122         g_settings_get(theapp->state_settings, "last-open-path", "ms", &path);
123         if(path) {
124                 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
125                 g_free(path);
126         }
127
128         if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
129                 GError *error = NULL;
130                 char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
131
132                 /* Open a new player window */
133                 ChimaraPlayer *player = CHIMARA_PLAYER(chimara_player_new());
134                 gtk_widget_show_all(GTK_WIDGET(player));
135                 gtk_window_present(GTK_WINDOW(player));
136
137                 gchar *blorbfile = search_for_graphics_file(filename);
138                 if(blorbfile) {
139                         g_object_set(player->glk, "graphics-file", blorbfile, NULL);
140                         g_free(blorbfile);
141                 }
142                 if(!chimara_if_run_game(CHIMARA_IF(player->glk), filename, &error)) {
143                         error_dialog(GTK_WINDOW(player), error, _("Could not open game file '%s': "), filename);
144                         g_free(filename);
145                         gtk_widget_destroy(dialog);
146                         return;
147                 }
148                 
149                 path = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
150                 if(path) {
151                         g_settings_set(theapp->state_settings, "last-open-path", "ms", path);
152                         g_free(path);
153                 }
154
155                 /* Add file to recent files list */
156                 GtkRecentManager *manager = gtk_recent_manager_get_default();
157                 gchar *uri;
158                 
159                 if(!(uri = g_filename_to_uri(filename, NULL, &error)))
160                         g_warning(_("Could not convert filename '%s' to URI: %s"), filename, error->message);
161                 else {
162                         if(!gtk_recent_manager_add_item(manager, uri))
163                                 g_warning(_("Could not add URI '%s' to recent files list."), uri);
164                         g_free(uri);
165                 }
166                 g_free(filename);
167         }
168         gtk_widget_destroy(dialog);
169 }
170
171 void
172 on_recent_item_activated(GtkRecentChooser *chooser, ChimaraApp *theapp)
173 {
174         GError *error = NULL;
175         gchar *uri = gtk_recent_chooser_get_current_uri(chooser);
176         gchar *filename;
177         if(!(filename = g_filename_from_uri(uri, NULL, &error))) {
178                 error_dialog(NULL /* FIXME */, error, _("Could not open game file '%s': "), uri);
179                 goto finally;
180         }
181         
182         //if(!confirm_open_new_game(CHIMARA_GLK(player->glk)))
183         //      goto finally2;
184
185         /* Open a new player window */
186         ChimaraPlayer *player = CHIMARA_PLAYER(chimara_player_new());
187         gtk_widget_show_all(GTK_WIDGET(player));
188         gtk_window_present(GTK_WINDOW(player));
189         
190         char *blorbfile = search_for_graphics_file(filename);
191         if(blorbfile) {
192                 g_object_set(player->glk, "graphics-file", blorbfile, NULL);
193                 g_free(blorbfile);
194         }
195         if(!chimara_if_run_game(CHIMARA_IF(player->glk), filename, &error)) {
196                 error_dialog(GTK_WINDOW(player), error, _("Could not open game file '%s': "), filename);
197                 goto finally2;
198         }
199         
200         /* Add file to recent files list again, this updates it to most recently used */
201         GtkRecentManager *manager = gtk_recent_manager_get_default();
202         if(!gtk_recent_manager_add_item(manager, uri))
203                 g_warning(_("Could not add URI '%s' to recent files list."), uri);
204
205 finally2:
206         g_free(filename);
207 finally:
208         g_free(uri);
209 }
210
211 void
212 on_stop_activate(GtkAction *action, ChimaraPlayer *player)
213 {
214         chimara_glk_stop(CHIMARA_GLK(player->glk));
215 }
216
217 void 
218 on_quit_chimara_activate(GtkAction *action, ChimaraApp *theapp)
219 {
220         gtk_main_quit();
221 }
222
223 void
224 on_copy_activate(GtkAction *action, ChimaraPlayer *player)
225 {
226         GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
227         /* Call "copy clipboard" on any widget that defines it */
228         if(GTK_IS_LABEL(focus) || GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
229                 g_signal_emit_by_name(focus, "copy-clipboard");
230 }
231
232 void
233 on_paste_activate(GtkAction *action, ChimaraPlayer *player)
234 {
235         GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
236         /* Call "paste clipboard" on any widget that defines it */
237         if(GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
238                 g_signal_emit_by_name(focus, "paste-clipboard");
239 }
240
241 void
242 on_preferences_activate(GtkAction *action, ChimaraApp *theapp)
243 {
244         gtk_window_present(GTK_WINDOW(theapp->prefswindow));
245 }
246
247 void
248 on_toolbar_toggled(GtkToggleAction *action, ChimaraPlayer *player)
249 {
250         if(gtk_toggle_action_get_active(action))
251                 gtk_widget_show(player->toolbar);
252         else
253                 gtk_widget_hide(player->toolbar);
254 }
255
256 void
257 on_undo_activate(GtkAction *action, ChimaraPlayer *player)
258 {
259         chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "undo");
260 }
261
262 void 
263 on_save_activate(GtkAction *action, ChimaraPlayer *player)
264 {
265         chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "save");
266 }
267
268 void 
269 on_restore_activate(GtkAction *action, ChimaraPlayer *player)
270 {
271         chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restore");
272 }
273
274 void 
275 on_restart_activate(GtkAction *action, ChimaraPlayer *player)
276 {
277         chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restart");
278 }
279
280 void 
281 on_quit_activate(GtkAction *action, ChimaraPlayer *player)
282 {
283         chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "quit");
284 }
285
286 void
287 on_about_activate(GtkAction *action, ChimaraApp *theapp)
288 {
289         gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(theapp->aboutwindow), PACKAGE_VERSION);
290         gtk_window_present(GTK_WINDOW(theapp->aboutwindow));
291 }
292
293 gboolean 
294 on_window_delete_event(GtkWidget *widget, GdkEvent *event, ChimaraPlayer *player) 
295 {
296         gtk_main_quit();
297         return TRUE;
298 }