2 * Copyright (C) 2008, 2009, 2010, 2011 Philip Chimento and Marijn van Vliet.
5 * Chimara is free software copyrighted by Philip Chimento and Marijn van Vliet.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 * 3. Neither of the names Philip Chimento or Marijn van Vliet, nor the name of
16 * any other contributor may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 #include <glib-object.h>
34 #include <glib/gi18n.h>
36 #include <libchimara/chimara-glk.h>
37 #include <libchimara/chimara-if.h>
43 typedef struct _ChimaraPlayerPrivate {
45 } ChimaraPlayerPrivate;
47 #define CHIMARA_PLAYER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), CHIMARA_TYPE_PLAYER, ChimaraPlayerPrivate))
48 #define CHIMARA_PLAYER_USE_PRIVATE ChimaraPlayerPrivate *priv = CHIMARA_PLAYER_PRIVATE(self)
50 G_DEFINE_TYPE(ChimaraPlayer, chimara_player, GTK_TYPE_WINDOW);
53 change_window_title(ChimaraGlk *glk, GParamSpec *pspec, GtkWindow *window)
55 gchar *program_name, *story_name, *title;
56 g_object_get(glk, "program-name", &program_name, "story-name", &story_name, NULL);
58 gtk_window_set_title(window, "Chimara");
62 title = g_strdup_printf("%s - Chimara", program_name);
64 title = g_strdup_printf("%s - %s - Chimara", program_name, story_name);
68 gtk_window_set_title(window, title);
73 chimara_player_dispose(GObject *object)
75 ChimaraPlayer *self = CHIMARA_PLAYER(object);
76 if(chimara_glk_get_running(CHIMARA_GLK(self->glk))) {
77 chimara_glk_stop(CHIMARA_GLK(self->glk));
78 g_printerr("Stopping...\n");
79 chimara_glk_wait(CHIMARA_GLK(self->glk));
80 g_printerr("Done Waiting\n");
84 G_OBJECT_CLASS(chimara_player_parent_class)->dispose(object);
88 chimara_player_finalize(GObject *object)
90 g_printerr("Unreffing\n");
91 g_object_unref(CHIMARA_PLAYER(object)->glk);
94 G_OBJECT_CLASS(chimara_player_parent_class)->finalize(object);
98 chimara_player_class_init(ChimaraPlayerClass *klass)
100 /* Override methods of parent classes */
101 GObjectClass *object_class = G_OBJECT_CLASS(klass);
102 //object_class->set_property = chimara_if_set_property;
103 //object_class->get_property = chimara_if_get_property;
104 object_class->dispose = chimara_player_dispose;
105 object_class->finalize = chimara_player_finalize;
112 g_type_class_add_private(klass, sizeof(ChimaraPlayerPrivate));
116 chimara_player_init(ChimaraPlayer *self)
118 GError *error = NULL;
119 ChimaraApp *theapp = chimara_app_get();
121 /* Set parent properties */
123 "title", _("Chimara"),
124 "default-width", 600,
125 "default-height", 800,
128 /* Construct user interface */
129 char *object_ids[] = {
134 GtkBuilder *builder = new_builder_with_objects(object_ids);
136 GtkActionGroup *actiongroup = GTK_ACTION_GROUP(load_object(builder, "actiongroup"));
138 /* Set the default value of the "View/Toolbar" menu item upon creation of a
139 new window to the "show-toolbar-default" setting, but bind the setting
140 one-way only - we don't want toolbars to disappear suddenly */
141 GtkToggleAction *toolbar_action = GTK_TOGGLE_ACTION(load_object(builder, "toolbar"));
142 gtk_toggle_action_set_active(toolbar_action, g_settings_get_boolean(theapp->state_settings, "show-toolbar-default"));
143 g_settings_bind(theapp->state_settings, "show-toolbar-default", toolbar_action, "active", G_SETTINGS_BIND_SET);
145 self->glk = chimara_if_new();
146 g_object_set(self->glk,
147 "ignore-errors", TRUE,
148 /*"interpreter-number", CHIMARA_IF_ZMACHINE_TANDY_COLOR,*/
150 char *default_css = get_data_file_path("style.css");
151 if( !chimara_glk_set_css_from_file(CHIMARA_GLK(self->glk), default_css, &error) ) {
152 error_dialog(GTK_WINDOW(self), error, "Couldn't open default CSS file: ");
155 /* DON'T UNCOMMENT THIS your eyes will burn
156 but it is a good test of programmatically altering just one style
157 chimara_glk_set_css_from_string(CHIMARA_GLK(glk),
158 "buffer.normal { font-family: 'Comic Sans MS'; }");*/
160 GtkUIManager *uimanager = new_ui_manager("player.menus");
161 gtk_ui_manager_insert_action_group(uimanager, actiongroup, 0);
162 gtk_ui_manager_insert_action_group(uimanager, chimara_app_get_action_group(theapp), 1);
163 GtkWidget *menubar = gtk_ui_manager_get_widget(uimanager, "/player_menu");
164 self->toolbar = gtk_ui_manager_get_widget(uimanager, "/player_toolbar");
165 gtk_widget_set_no_show_all(self->toolbar, TRUE);
166 if(gtk_toggle_action_get_active(toolbar_action))
167 gtk_widget_show(self->toolbar);
169 gtk_widget_hide(self->toolbar);
171 /* Connect the accelerators */
172 GtkAccelGroup *accels = gtk_ui_manager_get_accel_group(uimanager);
173 gtk_window_add_accel_group(GTK_WINDOW(self), accels);
175 GtkBox *vbox = GTK_BOX(load_object(builder, "player-vbox"));
176 gtk_box_pack_end(vbox, self->glk, TRUE, TRUE, 0);
177 g_object_ref(self->glk); /* add an extra reference to keep it alive while
178 the Glk program shuts down */
179 gtk_box_pack_start(vbox, menubar, FALSE, FALSE, 0);
180 gtk_box_pack_start(vbox, self->toolbar, FALSE, FALSE, 0);
181 gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(vbox));
183 gtk_builder_connect_signals(builder, self);
184 g_signal_connect(self->glk, "notify::program-name", G_CALLBACK(change_window_title), self);
185 g_signal_connect(self->glk, "notify::story-name", G_CALLBACK(change_window_title), self);
187 g_object_unref(builder);
188 g_object_unref(uimanager);
191 /* PUBLIC FUNCTIONS */
194 chimara_player_new(void)
196 return GTK_WIDGET(g_object_new(CHIMARA_TYPE_PLAYER,
197 "type", GTK_WINDOW_TOPLEVEL,
201 /* GLADE CALLBACKS */
204 /* If a game is running in @glk, warn the user that they will quit the currently
205 running game if they open a new one. Returns TRUE if no game was running.
206 Returns FALSE if the user cancelled. Returns TRUE and shuts down the running
207 game if the user wishes to continue. */
209 confirm_open_new_game(ChimaraGlk *glk)
211 g_return_val_if_fail(glk && CHIMARA_IS_GLK(glk), FALSE);
213 GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk)));
215 if(chimara_glk_get_running(glk)) {
216 GtkWidget *dialog = gtk_message_dialog_new(window,
217 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
220 _("Are you sure you want to open a new game?"));
221 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
222 _("If you open a new game, you will quit the one you are currently playing."));
223 gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OPEN, GTK_RESPONSE_OK);
224 gint response = gtk_dialog_run(GTK_DIALOG(dialog));
225 gtk_widget_destroy(dialog);
227 if(response != GTK_RESPONSE_OK)
230 chimara_glk_stop(glk);
231 chimara_glk_wait(glk);
238 on_stop_activate(GtkAction *action, ChimaraPlayer *player)
240 chimara_glk_stop(CHIMARA_GLK(player->glk));
244 on_copy_activate(GtkAction *action, ChimaraPlayer *player)
246 GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
247 /* Call "copy clipboard" on any widget that defines it */
248 if(GTK_IS_LABEL(focus) || GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
249 g_signal_emit_by_name(focus, "copy-clipboard");
253 on_paste_activate(GtkAction *action, ChimaraPlayer *player)
255 GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
256 /* Call "paste clipboard" on any widget that defines it */
257 if(GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
258 g_signal_emit_by_name(focus, "paste-clipboard");
262 on_toolbar_toggled(GtkToggleAction *action, ChimaraPlayer *player)
264 if(gtk_toggle_action_get_active(action))
265 gtk_widget_show(player->toolbar);
267 gtk_widget_hide(player->toolbar);
271 on_undo_activate(GtkAction *action, ChimaraPlayer *player)
273 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "undo");
277 on_save_activate(GtkAction *action, ChimaraPlayer *player)
279 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "save");
283 on_restore_activate(GtkAction *action, ChimaraPlayer *player)
285 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restore");
289 on_restart_activate(GtkAction *action, ChimaraPlayer *player)
291 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restart");
295 on_quit_activate(GtkAction *action, ChimaraPlayer *player)
297 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "quit");