1 #include <glib-object.h>
2 #include <glib/gi18n.h>
3 #include <libchimara/chimara-glk.h>
4 #include <libchimara/chimara-if.h>
9 typedef struct _ChimaraPlayerPrivate {
11 } ChimaraPlayerPrivate;
13 #define CHIMARA_PLAYER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), CHIMARA_TYPE_PLAYER, ChimaraPlayerPrivate))
14 #define CHIMARA_PLAYER_USE_PRIVATE ChimaraPlayerPrivate *priv = CHIMARA_PLAYER_PRIVATE(self)
16 G_DEFINE_TYPE(ChimaraPlayer, chimara_player, GTK_TYPE_WINDOW);
19 load_object(GtkBuilder *builder, const gchar *name)
22 if( (retval = gtk_builder_get_object(builder, name)) == NULL) {
23 error_dialog(NULL, NULL, "Error while getting object '%s'", name);
24 g_error("Error while getting object '%s'", name);
30 change_window_title(ChimaraGlk *glk, GParamSpec *pspec, GtkWindow *window)
32 gchar *program_name, *story_name, *title;
33 g_object_get(glk, "program-name", &program_name, "story-name", &story_name, NULL);
35 gtk_window_set_title(window, "Chimara");
39 title = g_strdup_printf("%s - Chimara", program_name);
41 title = g_strdup_printf("%s - %s - Chimara", program_name, story_name);
45 gtk_window_set_title(window, title);
50 chimara_player_dispose(GObject *object)
52 ChimaraPlayer *self = CHIMARA_PLAYER(object);
53 if(chimara_glk_get_running(CHIMARA_GLK(self->glk))) {
54 chimara_glk_stop(CHIMARA_GLK(self->glk));
55 g_printerr("Stopping...\n");
56 chimara_glk_wait(CHIMARA_GLK(self->glk));
57 g_printerr("Done Waiting\n");
61 G_OBJECT_CLASS(chimara_player_parent_class)->dispose(object);
65 chimara_player_finalize(GObject *object)
67 g_printerr("Unreffing\n");
68 g_object_unref(CHIMARA_PLAYER(object)->glk);
71 G_OBJECT_CLASS(chimara_player_parent_class)->finalize(object);
75 chimara_player_class_init(ChimaraPlayerClass *klass)
77 /* Override methods of parent classes */
78 GObjectClass *object_class = G_OBJECT_CLASS(klass);
79 //object_class->set_property = chimara_if_set_property;
80 //object_class->get_property = chimara_if_get_property;
81 object_class->dispose = chimara_player_dispose;
82 object_class->finalize = chimara_player_finalize;
89 g_type_class_add_private(klass, sizeof(ChimaraPlayerPrivate));
93 chimara_player_init(ChimaraPlayer *self)
97 /* Set parent properties */
99 "title", _("Chimara"),
100 "default-width", 600,
101 "default-height", 800,
104 /* Construct user interface */
105 GtkBuilder *builder = gtk_builder_new();
106 char *object_ids[] = {
112 if( !gtk_builder_add_objects_from_file(builder, PACKAGE_DATA_DIR "/chimara.ui", object_ids, &error) ) {
116 if( !gtk_builder_add_objects_from_file(builder, PACKAGE_SRC_DIR "/chimara.ui", object_ids, &error) ) {
118 error_dialog(NULL, error, "Error while building interface: ");
125 GtkActionGroup *actiongroup = GTK_ACTION_GROUP(load_object(builder, "actiongroup"));
127 /* Set the default value of the "View/Toolbar" menu item upon creation of a
128 new window to the "show-toolbar-default" setting, but bind the setting
129 one-way only - we don't want toolbars to disappear suddenly */
130 GtkToggleAction *toolbar_action = GTK_TOGGLE_ACTION(load_object(builder, "toolbar"));
131 //gtk_toggle_action_set_active(toolbar_action, g_settings_get_boolean(state_settings, "show-toolbar-default"));
132 //g_settings_bind(state_settings, "show-toolbar-default", toolbar_action, "active", G_SETTINGS_BIND_SET);
134 GtkUIManager *uimanager = gtk_ui_manager_new();
135 if( !gtk_ui_manager_add_ui_from_file(uimanager, PACKAGE_DATA_DIR "/player.menus", &error) ) {
139 if( !gtk_ui_manager_add_ui_from_file(uimanager, PACKAGE_SRC_DIR "/player.menus", &error) ) {
141 error_dialog(NULL, error, "Error while building interface: ");
148 self->glk = chimara_if_new();
149 g_object_set(self->glk,
150 "ignore-errors", TRUE,
151 /*"interpreter-number", CHIMARA_IF_ZMACHINE_TANDY_COLOR,*/
153 if( !chimara_glk_set_css_from_file(CHIMARA_GLK(self->glk), PACKAGE_DATA_DIR "/style.css", &error) ) {
157 if( !chimara_glk_set_css_from_file(CHIMARA_GLK(self->glk), PACKAGE_SRC_DIR "/style.css", &error) ) {
159 error_dialog(NULL, error, "Couldn't open CSS file: ");
166 /* DON'T UNCOMMENT THIS your eyes will burn
167 but it is a good test of programmatically altering just one style
168 chimara_glk_set_css_from_string(CHIMARA_GLK(glk),
169 "buffer.normal { font-family: 'Comic Sans MS'; }");*/
171 GtkBox *vbox = GTK_BOX(load_object(builder, "player-vbox"));
173 ChimaraApp *theapp = chimara_app_get();
175 gtk_ui_manager_insert_action_group(uimanager, actiongroup, 0);
176 gtk_ui_manager_insert_action_group(uimanager, chimara_app_get_action_group(theapp), 1);
177 GtkWidget *menubar = gtk_ui_manager_get_widget(uimanager, "/player_menu");
178 self->toolbar = gtk_ui_manager_get_widget(uimanager, "/player_toolbar");
179 gtk_widget_set_no_show_all(self->toolbar, TRUE);
180 if(gtk_toggle_action_get_active(toolbar_action))
181 gtk_widget_show(self->toolbar);
183 gtk_widget_hide(self->toolbar);
185 /* Connect the accelerators */
186 GtkAccelGroup *accels = gtk_ui_manager_get_accel_group(uimanager);
187 gtk_window_add_accel_group(GTK_WINDOW(self), accels);
189 gtk_box_pack_end(vbox, self->glk, TRUE, TRUE, 0);
190 g_object_ref(self->glk); /* add an extra reference to keep it alive while
191 the Glk program shuts down */
192 gtk_box_pack_start(vbox, menubar, FALSE, FALSE, 0);
193 gtk_box_pack_start(vbox, self->toolbar, FALSE, FALSE, 0);
194 gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(vbox));
196 gtk_builder_connect_signals(builder, self);
197 g_signal_connect(self->glk, "notify::program-name", G_CALLBACK(change_window_title), self);
198 g_signal_connect(self->glk, "notify::story-name", G_CALLBACK(change_window_title), self);
200 g_object_unref( G_OBJECT(builder) );
201 g_object_unref( G_OBJECT(uimanager) );
204 /* PUBLIC FUNCTIONS */
207 chimara_player_new(void)
209 return GTK_WIDGET(g_object_new(CHIMARA_TYPE_PLAYER,
210 "type", GTK_WINDOW_TOPLEVEL,
214 /* GLADE CALLBACKS */
217 /* If a game is running in @glk, warn the user that they will quit the currently
218 running game if they open a new one. Returns TRUE if no game was running.
219 Returns FALSE if the user cancelled. Returns TRUE and shuts down the running
220 game if the user wishes to continue. */
222 confirm_open_new_game(ChimaraGlk *glk)
224 g_return_val_if_fail(glk && CHIMARA_IS_GLK(glk), FALSE);
226 GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk)));
228 if(chimara_glk_get_running(glk)) {
229 GtkWidget *dialog = gtk_message_dialog_new(window,
230 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
233 _("Are you sure you want to open a new game?"));
234 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
235 _("If you open a new game, you will quit the one you are currently playing."));
236 gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OPEN, GTK_RESPONSE_OK);
237 gint response = gtk_dialog_run(GTK_DIALOG(dialog));
238 gtk_widget_destroy(dialog);
240 if(response != GTK_RESPONSE_OK)
243 chimara_glk_stop(glk);
244 chimara_glk_wait(glk);
251 on_stop_activate(GtkAction *action, ChimaraPlayer *player)
253 chimara_glk_stop(CHIMARA_GLK(player->glk));
257 on_copy_activate(GtkAction *action, ChimaraPlayer *player)
259 GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
260 /* Call "copy clipboard" on any widget that defines it */
261 if(GTK_IS_LABEL(focus) || GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
262 g_signal_emit_by_name(focus, "copy-clipboard");
266 on_paste_activate(GtkAction *action, ChimaraPlayer *player)
268 GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
269 /* Call "paste clipboard" on any widget that defines it */
270 if(GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
271 g_signal_emit_by_name(focus, "paste-clipboard");
275 on_toolbar_toggled(GtkToggleAction *action, ChimaraPlayer *player)
277 if(gtk_toggle_action_get_active(action))
278 gtk_widget_show(player->toolbar);
280 gtk_widget_hide(player->toolbar);
284 on_undo_activate(GtkAction *action, ChimaraPlayer *player)
286 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "undo");
290 on_save_activate(GtkAction *action, ChimaraPlayer *player)
292 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "save");
296 on_restore_activate(GtkAction *action, ChimaraPlayer *player)
298 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restore");
302 on_restart_activate(GtkAction *action, ChimaraPlayer *player)
304 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restart");
308 on_quit_activate(GtkAction *action, ChimaraPlayer *player)
310 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "quit");