1 #include <glib-object.h>
2 #include <libchimara/chimara-glk.h>
3 #include <libchimara/chimara-if.h>
8 typedef struct _ChimaraPlayerPrivate {
10 } ChimaraPlayerPrivate;
12 #define CHIMARA_PLAYER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), CHIMARA_TYPE_PLAYER, ChimaraPlayerPrivate))
13 #define CHIMARA_PLAYER_USE_PRIVATE ChimaraPlayerPrivate *priv = CHIMARA_PLAYER_PRIVATE(self)
15 G_DEFINE_TYPE(ChimaraPlayer, chimara_player, GTK_TYPE_WINDOW);
18 load_object(GtkBuilder *builder, const gchar *name)
21 if( (retval = gtk_builder_get_object(builder, name)) == NULL) {
22 error_dialog(NULL, NULL, "Error while getting object '%s'", name);
23 g_error("Error while getting object '%s'", name);
29 change_window_title(ChimaraGlk *glk, GParamSpec *pspec, GtkWindow *window)
31 gchar *program_name, *story_name, *title;
32 g_object_get(glk, "program-name", &program_name, "story-name", &story_name, NULL);
34 gtk_window_set_title(window, "Chimara");
38 title = g_strdup_printf("%s - Chimara", program_name);
40 title = g_strdup_printf("%s - %s - Chimara", program_name, story_name);
44 gtk_window_set_title(window, title);
49 chimara_player_dispose(GObject *object)
51 ChimaraPlayer *self = CHIMARA_PLAYER(object);
52 if(chimara_glk_get_running(CHIMARA_GLK(self->glk))) {
53 chimara_glk_stop(CHIMARA_GLK(self->glk));
54 g_printerr("Stopping...\n");
55 chimara_glk_wait(CHIMARA_GLK(self->glk));
56 g_printerr("Done Waiting\n");
60 G_OBJECT_CLASS(chimara_player_parent_class)->dispose(object);
64 chimara_player_finalize(GObject *object)
66 g_printerr("Unreffing\n");
67 g_object_unref(CHIMARA_PLAYER(object)->glk);
70 G_OBJECT_CLASS(chimara_player_parent_class)->finalize(object);
74 chimara_player_class_init(ChimaraPlayerClass *klass)
76 /* Override methods of parent classes */
77 GObjectClass *object_class = G_OBJECT_CLASS(klass);
78 //object_class->set_property = chimara_if_set_property;
79 //object_class->get_property = chimara_if_get_property;
80 object_class->dispose = chimara_player_dispose;
81 object_class->finalize = chimara_player_finalize;
88 g_type_class_add_private(klass, sizeof(ChimaraPlayerPrivate));
92 chimara_player_init(ChimaraPlayer *self)
96 GtkBuilder *builder = gtk_builder_new();
97 char *object_ids[] = {
103 if( !gtk_builder_add_objects_from_file(builder, PACKAGE_DATA_DIR "/chimara.ui", object_ids, &error) ) {
107 if( !gtk_builder_add_objects_from_file(builder, PACKAGE_SRC_DIR "/chimara.ui", object_ids, &error) ) {
109 error_dialog(NULL, error, "Error while building interface: ");
116 GtkActionGroup *actiongroup = GTK_ACTION_GROUP(load_object(builder, "actiongroup"));
118 /* Set the default value of the "View/Toolbar" menu item upon creation of a
119 new window to the "show-toolbar-default" setting, but bind the setting
120 one-way only - we don't want toolbars to disappear suddenly */
121 GtkToggleAction *toolbar_action = GTK_TOGGLE_ACTION(load_object(builder, "toolbar"));
122 //gtk_toggle_action_set_active(toolbar_action, g_settings_get_boolean(state_settings, "show-toolbar-default"));
123 //g_settings_bind(state_settings, "show-toolbar-default", toolbar_action, "active", G_SETTINGS_BIND_SET);
125 GtkUIManager *uimanager = gtk_ui_manager_new();
126 if( !gtk_ui_manager_add_ui_from_file(uimanager, PACKAGE_DATA_DIR "/chimara.menus", &error) ) {
130 if( !gtk_ui_manager_add_ui_from_file(uimanager, PACKAGE_SRC_DIR "/chimara.menus", &error) ) {
132 error_dialog(NULL, error, "Error while building interface: ");
139 self->glk = chimara_if_new();
140 g_object_set(self->glk,
141 "ignore-errors", TRUE,
142 /*"interpreter-number", CHIMARA_IF_ZMACHINE_TANDY_COLOR,*/
144 if( !chimara_glk_set_css_from_file(CHIMARA_GLK(self->glk), PACKAGE_DATA_DIR "/style.css", &error) ) {
148 if( !chimara_glk_set_css_from_file(CHIMARA_GLK(self->glk), PACKAGE_SRC_DIR "/style.css", &error) ) {
150 error_dialog(NULL, error, "Couldn't open CSS file: ");
157 /* DON'T UNCOMMENT THIS your eyes will burn
158 but it is a good test of programmatically altering just one style
159 chimara_glk_set_css_from_string(CHIMARA_GLK(glk),
160 "buffer.normal { font-family: 'Comic Sans MS'; }");*/
162 GtkBox *vbox = GTK_BOX(load_object(builder, "vbox"));
164 ChimaraApp *theapp = chimara_app_get();
166 gtk_ui_manager_insert_action_group(uimanager, actiongroup, 0);
167 gtk_ui_manager_insert_action_group(uimanager, chimara_app_get_action_group(theapp), 1);
168 GtkWidget *menubar = gtk_ui_manager_get_widget(uimanager, "/player_menu");
169 self->toolbar = gtk_ui_manager_get_widget(uimanager, "/player_toolbar");
170 gtk_widget_set_no_show_all(self->toolbar, TRUE);
171 if(gtk_toggle_action_get_active(toolbar_action))
172 gtk_widget_show(self->toolbar);
174 gtk_widget_hide(self->toolbar);
176 /* Connect the accelerators */
177 GtkAccelGroup *accels = gtk_ui_manager_get_accel_group(uimanager);
178 gtk_window_add_accel_group(GTK_WINDOW(self), accels);
180 gtk_box_pack_end(vbox, self->glk, TRUE, TRUE, 0);
181 g_object_ref(self->glk); /* add an extra reference to keep it alive while
182 the Glk program shuts down */
183 gtk_box_pack_start(vbox, menubar, FALSE, FALSE, 0);
184 gtk_box_pack_start(vbox, self->toolbar, FALSE, FALSE, 0);
185 gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(vbox));
187 gtk_builder_connect_signals(builder, self);
188 g_signal_connect(self->glk, "notify::program-name", G_CALLBACK(change_window_title), self);
189 g_signal_connect(self->glk, "notify::story-name", G_CALLBACK(change_window_title), self);
191 g_object_unref( G_OBJECT(builder) );
192 g_object_unref( G_OBJECT(uimanager) );
195 /* PUBLIC FUNCTIONS */
198 chimara_player_new(void)
200 return GTK_WIDGET(g_object_new(CHIMARA_TYPE_PLAYER,
201 "type", GTK_WINDOW_TOPLEVEL,
205 /* GLADE CALLBACKS */
208 /* If a game is running in @glk, warn the user that they will quit the currently
209 running game if they open a new one. Returns TRUE if no game was running.
210 Returns FALSE if the user cancelled. Returns TRUE and shuts down the running
211 game if the user wishes to continue. */
213 confirm_open_new_game(ChimaraGlk *glk)
215 g_return_val_if_fail(glk && CHIMARA_IS_GLK(glk), FALSE);
217 GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk)));
219 if(chimara_glk_get_running(glk)) {
220 GtkWidget *dialog = gtk_message_dialog_new(window,
221 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
224 _("Are you sure you want to open a new game?"));
225 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
226 _("If you open a new game, you will quit the one you are currently playing."));
227 gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OPEN, GTK_RESPONSE_OK);
228 gint response = gtk_dialog_run(GTK_DIALOG(dialog));
229 gtk_widget_destroy(dialog);
231 if(response != GTK_RESPONSE_OK)
234 chimara_glk_stop(glk);
235 chimara_glk_wait(glk);
242 on_stop_activate(GtkAction *action, ChimaraPlayer *player)
244 chimara_glk_stop(CHIMARA_GLK(player->glk));
248 on_copy_activate(GtkAction *action, ChimaraPlayer *player)
250 GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
251 /* Call "copy clipboard" on any widget that defines it */
252 if(GTK_IS_LABEL(focus) || GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
253 g_signal_emit_by_name(focus, "copy-clipboard");
257 on_paste_activate(GtkAction *action, ChimaraPlayer *player)
259 GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
260 /* Call "paste clipboard" on any widget that defines it */
261 if(GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
262 g_signal_emit_by_name(focus, "paste-clipboard");
266 on_toolbar_toggled(GtkToggleAction *action, ChimaraPlayer *player)
268 if(gtk_toggle_action_get_active(action))
269 gtk_widget_show(player->toolbar);
271 gtk_widget_hide(player->toolbar);
275 on_undo_activate(GtkAction *action, ChimaraPlayer *player)
277 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "undo");
281 on_save_activate(GtkAction *action, ChimaraPlayer *player)
283 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "save");
287 on_restore_activate(GtkAction *action, ChimaraPlayer *player)
289 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restore");
293 on_restart_activate(GtkAction *action, ChimaraPlayer *player)
295 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restart");
299 on_quit_activate(GtkAction *action, ChimaraPlayer *player)
301 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "quit");
305 on_window_delete_event(GtkWidget *widget, GdkEvent *event, ChimaraPlayer *player)