1 #include <glib-object.h>
2 #include <glib/gi18n.h>
3 #include <libchimara/chimara-glk.h>
4 #include <libchimara/chimara-if.h>
10 typedef struct _ChimaraPlayerPrivate {
12 } ChimaraPlayerPrivate;
14 #define CHIMARA_PLAYER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), CHIMARA_TYPE_PLAYER, ChimaraPlayerPrivate))
15 #define CHIMARA_PLAYER_USE_PRIVATE ChimaraPlayerPrivate *priv = CHIMARA_PLAYER_PRIVATE(self)
17 G_DEFINE_TYPE(ChimaraPlayer, chimara_player, GTK_TYPE_WINDOW);
20 change_window_title(ChimaraGlk *glk, GParamSpec *pspec, GtkWindow *window)
22 gchar *program_name, *story_name, *title;
23 g_object_get(glk, "program-name", &program_name, "story-name", &story_name, NULL);
25 gtk_window_set_title(window, "Chimara");
29 title = g_strdup_printf("%s - Chimara", program_name);
31 title = g_strdup_printf("%s - %s - Chimara", program_name, story_name);
35 gtk_window_set_title(window, title);
40 chimara_player_dispose(GObject *object)
42 ChimaraPlayer *self = CHIMARA_PLAYER(object);
43 if(chimara_glk_get_running(CHIMARA_GLK(self->glk))) {
44 chimara_glk_stop(CHIMARA_GLK(self->glk));
45 g_printerr("Stopping...\n");
46 chimara_glk_wait(CHIMARA_GLK(self->glk));
47 g_printerr("Done Waiting\n");
51 G_OBJECT_CLASS(chimara_player_parent_class)->dispose(object);
55 chimara_player_finalize(GObject *object)
57 g_printerr("Unreffing\n");
58 g_object_unref(CHIMARA_PLAYER(object)->glk);
61 G_OBJECT_CLASS(chimara_player_parent_class)->finalize(object);
65 chimara_player_class_init(ChimaraPlayerClass *klass)
67 /* Override methods of parent classes */
68 GObjectClass *object_class = G_OBJECT_CLASS(klass);
69 //object_class->set_property = chimara_if_set_property;
70 //object_class->get_property = chimara_if_get_property;
71 object_class->dispose = chimara_player_dispose;
72 object_class->finalize = chimara_player_finalize;
79 g_type_class_add_private(klass, sizeof(ChimaraPlayerPrivate));
83 chimara_player_init(ChimaraPlayer *self)
86 ChimaraApp *theapp = chimara_app_get();
88 /* Set parent properties */
90 "title", _("Chimara"),
92 "default-height", 800,
95 /* Construct user interface */
96 char *object_ids[] = {
101 GtkBuilder *builder = new_builder_with_objects(object_ids);
103 GtkActionGroup *actiongroup = GTK_ACTION_GROUP(load_object(builder, "actiongroup"));
105 /* Set the default value of the "View/Toolbar" menu item upon creation of a
106 new window to the "show-toolbar-default" setting, but bind the setting
107 one-way only - we don't want toolbars to disappear suddenly */
108 GtkToggleAction *toolbar_action = GTK_TOGGLE_ACTION(load_object(builder, "toolbar"));
109 //gtk_toggle_action_set_active(toolbar_action, g_settings_get_boolean(state_settings, "show-toolbar-default"));
110 //g_settings_bind(state_settings, "show-toolbar-default", toolbar_action, "active", G_SETTINGS_BIND_SET);
112 self->glk = chimara_if_new();
113 g_object_set(self->glk,
114 "ignore-errors", TRUE,
115 /*"interpreter-number", CHIMARA_IF_ZMACHINE_TANDY_COLOR,*/
117 char *default_css = get_data_file_path("style.css");
118 if( !chimara_glk_set_css_from_file(CHIMARA_GLK(self->glk), default_css, &error) ) {
119 error_dialog(self, error, "Couldn't open default CSS file: ");
122 /* DON'T UNCOMMENT THIS your eyes will burn
123 but it is a good test of programmatically altering just one style
124 chimara_glk_set_css_from_string(CHIMARA_GLK(glk),
125 "buffer.normal { font-family: 'Comic Sans MS'; }");*/
127 GtkUIManager *uimanager = new_ui_manager("player.menus");
128 gtk_ui_manager_insert_action_group(uimanager, actiongroup, 0);
129 gtk_ui_manager_insert_action_group(uimanager, chimara_app_get_action_group(theapp), 1);
130 GtkWidget *menubar = gtk_ui_manager_get_widget(uimanager, "/player_menu");
131 self->toolbar = gtk_ui_manager_get_widget(uimanager, "/player_toolbar");
132 gtk_widget_set_no_show_all(self->toolbar, TRUE);
133 if(gtk_toggle_action_get_active(toolbar_action))
134 gtk_widget_show(self->toolbar);
136 gtk_widget_hide(self->toolbar);
138 /* Connect the accelerators */
139 GtkAccelGroup *accels = gtk_ui_manager_get_accel_group(uimanager);
140 gtk_window_add_accel_group(GTK_WINDOW(self), accels);
142 GtkBox *vbox = GTK_BOX(load_object(builder, "player-vbox"));
143 gtk_box_pack_end(vbox, self->glk, TRUE, TRUE, 0);
144 g_object_ref(self->glk); /* add an extra reference to keep it alive while
145 the Glk program shuts down */
146 gtk_box_pack_start(vbox, menubar, FALSE, FALSE, 0);
147 gtk_box_pack_start(vbox, self->toolbar, FALSE, FALSE, 0);
148 gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(vbox));
150 gtk_builder_connect_signals(builder, self);
151 g_signal_connect(self->glk, "notify::program-name", G_CALLBACK(change_window_title), self);
152 g_signal_connect(self->glk, "notify::story-name", G_CALLBACK(change_window_title), self);
154 g_object_unref(builder);
155 g_object_unref(uimanager);
158 /* PUBLIC FUNCTIONS */
161 chimara_player_new(void)
163 return GTK_WIDGET(g_object_new(CHIMARA_TYPE_PLAYER,
164 "type", GTK_WINDOW_TOPLEVEL,
168 /* GLADE CALLBACKS */
171 /* If a game is running in @glk, warn the user that they will quit the currently
172 running game if they open a new one. Returns TRUE if no game was running.
173 Returns FALSE if the user cancelled. Returns TRUE and shuts down the running
174 game if the user wishes to continue. */
176 confirm_open_new_game(ChimaraGlk *glk)
178 g_return_val_if_fail(glk && CHIMARA_IS_GLK(glk), FALSE);
180 GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk)));
182 if(chimara_glk_get_running(glk)) {
183 GtkWidget *dialog = gtk_message_dialog_new(window,
184 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
187 _("Are you sure you want to open a new game?"));
188 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
189 _("If you open a new game, you will quit the one you are currently playing."));
190 gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OPEN, GTK_RESPONSE_OK);
191 gint response = gtk_dialog_run(GTK_DIALOG(dialog));
192 gtk_widget_destroy(dialog);
194 if(response != GTK_RESPONSE_OK)
197 chimara_glk_stop(glk);
198 chimara_glk_wait(glk);
205 on_stop_activate(GtkAction *action, ChimaraPlayer *player)
207 chimara_glk_stop(CHIMARA_GLK(player->glk));
211 on_copy_activate(GtkAction *action, ChimaraPlayer *player)
213 GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
214 /* Call "copy clipboard" on any widget that defines it */
215 if(GTK_IS_LABEL(focus) || GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
216 g_signal_emit_by_name(focus, "copy-clipboard");
220 on_paste_activate(GtkAction *action, ChimaraPlayer *player)
222 GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
223 /* Call "paste clipboard" on any widget that defines it */
224 if(GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
225 g_signal_emit_by_name(focus, "paste-clipboard");
229 on_toolbar_toggled(GtkToggleAction *action, ChimaraPlayer *player)
231 if(gtk_toggle_action_get_active(action))
232 gtk_widget_show(player->toolbar);
234 gtk_widget_hide(player->toolbar);
238 on_undo_activate(GtkAction *action, ChimaraPlayer *player)
240 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "undo");
244 on_save_activate(GtkAction *action, ChimaraPlayer *player)
246 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "save");
250 on_restore_activate(GtkAction *action, ChimaraPlayer *player)
252 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restore");
256 on_restart_activate(GtkAction *action, ChimaraPlayer *player)
258 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restart");
262 on_quit_activate(GtkAction *action, ChimaraPlayer *player)
264 chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "quit");