[aisleriot/wip/redesign: 9/17] all: Move game options to prefs dialogue
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [aisleriot/wip/redesign: 9/17] all: Move game options to prefs dialogue
- Date: Wed, 3 Jul 2013 17:54:06 +0000 (UTC)
commit b1b649587b8f977e26842d04e51d7e911154c2d4
Author: Christian Persch <chpe gnome org>
Date: Wed Jul 3 13:24:40 2013 +0200
all: Move game options to prefs dialogue
src/ar-prefs.c | 141 +++++++++++++++++++++++++++++++++++++++-
src/game.c | 18 +++++-
src/window.c | 196 +++-----------------------------------------------------
src/window.h | 2 +
4 files changed, 165 insertions(+), 192 deletions(-)
---
diff --git a/src/ar-prefs.c b/src/ar-prefs.c
index 564c523..c5dfae1 100644
--- a/src/ar-prefs.c
+++ b/src/ar-prefs.c
@@ -27,10 +27,13 @@
#include "ar-debug.h"
#include "ar-defines.h"
#include "util.h"
+#include "game.h"
typedef struct {
AisleriotWindow *window;
GSettings *settings;
+ GtkWidget *game_label;
+ GtkWidget *options_box;
GtkWidget *click_checkbutton;
GtkWidget *sound_checkbutton;
GtkWidget *animations_checkbutton;
@@ -64,6 +67,74 @@ enum {
/* private functions */
static void
+apply_option (GtkToggleButton *button,
+ guint32 *changed_mask,
+ guint32 *changed_value)
+{
+ gboolean active;
+ guint32 value;
+
+ value = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button), "option-value"));
+
+ active = gtk_toggle_button_get_active (button);
+
+ /* g_print ("option %s changed, value=%x set=%d\n", gtk_button_get_label (GTK_BUTTON (button)), value,
active); */
+
+ *changed_mask |= value;
+ if (active)
+ *changed_value |= value;
+}
+
+static void
+option_toggled_cb (GtkToggleButton *button,
+ ArPrefs *prefs)
+{
+ ArPrefsPrivate *priv = prefs->priv;
+ AisleriotGame *game;
+ gboolean active;
+ guint32 changed_mask = 0, changed_value = 0;
+
+ /* Don't change the options if we're just installing the options menu */
+ // if (priv->changing_game_type)
+ // return;
+
+ active = gtk_toggle_button_get_active (button);
+
+ /* If we're toggling OFF a radio button, don't redeal now,
+ * since we'll get called another time right again when the new option
+ * is toggled ON.
+ * The game options will be updated when we get the toggled signal
+ * for the newly active action in this group.
+ */
+ if (GTK_IS_RADIO_BUTTON (button) && !active)
+ return;
+
+ if (GTK_IS_RADIO_BUTTON (button)) {
+ GSList *group, *l;
+
+ /* If toggling ON a radio button, we didn't turn off the other option
+ * earlier. So we need to refresh the whole group.
+ */
+
+ group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
+
+ for (l = group; l; l = l->next) {
+ apply_option (GTK_TOGGLE_BUTTON (l->data), &changed_mask, &changed_value);
+ }
+ } else {
+ apply_option (button, &changed_mask, &changed_value);
+ }
+
+ game = ar_window_get_game (priv->window);
+
+ changed_value = aisleriot_game_change_options (game, changed_mask, changed_value);
+
+ /* Now re-deal, so the option is applied */
+ aisleriot_game_new_game (game);
+}
+
+
+static void
response_cb (GtkWidget *dialog,
int response,
gpointer user_data)
@@ -151,17 +222,76 @@ G_DEFINE_TYPE (ArPrefs, ar_prefs, GTK_TYPE_DIALOG)
static void
ar_prefs_init (ArPrefs *prefs)
{
- ArApplication *application = AR_APP;
ArPrefsPrivate *priv;
- GList *list, *l;
- GtkListStore *store;
- ArCardThemes *card_themes;
priv = prefs->priv = G_TYPE_INSTANCE_GET_PRIVATE (prefs, AR_TYPE_PREFS, ArPrefsPrivate);
priv->settings = g_settings_new (AR_SETTINGS_SCHEMA);
gtk_widget_init_template (GTK_WIDGET (prefs));
+}
+
+static void
+ar_prefs_constructed (GObject *object)
+{
+ ArPrefs *prefs = AR_PREFS (object);
+ ArPrefsPrivate *priv = prefs->priv;
+ ArApplication *application = AR_APP;
+ GList *list, *l;
+ GtkListStore *store;
+ ArCardThemes *card_themes;
+ AisleriotGame *game;
+ GtkWidget *widget, *radio_button = NULL;
+ char *game_name;
+
+ G_OBJECT_CLASS (ar_prefs_parent_class)->constructed (object);
+
+ g_assert (priv->window != NULL);
+
+ /* Populate the game options */
+ game = ar_window_get_game (priv->window);
+ game_name = aisleriot_game_get_name (game);
+ gtk_label_set_text (GTK_LABEL (priv->game_label), game_name);
+ g_free (game_name);
+
+ /* To get radio buttons in the menu insert an atom into the option list
+ * in your scheme code. To get back out of radio-button mode insert
+ * another atom. The exact value of the atoms is irrelevant - they merely
+ * trigger a toggle - but descriptive names like begin-exclusive and
+ * end-exclusive are probably a good idea.
+ */
+ list = aisleriot_game_get_options (game);
+ if (list == NULL) {
+ widget = gtk_label_new (_("This game has no options."));
+ gtk_box_pack_start (GTK_BOX (priv->options_box), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+ } else for (l = list; l != NULL; l = l->next) {
+ AisleriotGameOption *option = (AisleriotGameOption *) l->data;
+
+ if (option->type == AISLERIOT_GAME_OPTION_CHECK) {
+ widget = gtk_check_button_new_with_label (option->display_name);
+ radio_button = NULL;
+ } else {
+ widget = gtk_radio_button_new_with_label (NULL, option->display_name);
+
+ if (radio_button)
+ gtk_radio_button_join_group (GTK_RADIO_BUTTON (widget), GTK_RADIO_BUTTON (radio_button));
+
+ radio_button = widget;
+ }
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), option->set);
+ g_signal_connect (widget, "toggled",
+ G_CALLBACK (option_toggled_cb), prefs);
+
+ gtk_box_pack_start (GTK_BOX (priv->options_box), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ g_object_set_data (G_OBJECT (widget), "option-value", GUINT_TO_POINTER (option->value));
+
+ aisleriot_game_option_free (option);
+ }
+ g_list_free (list); /* elements have been consumed */
/* Populate the card theme combo */
store = priv->theme_store = gtk_list_store_new (2, G_TYPE_STRING, AR_TYPE_CARD_THEME_INFO);
@@ -249,6 +379,7 @@ ar_prefs_class_init (ArPrefsClass *klass)
g_type_class_add_private (klass, sizeof (ArPrefsPrivate));
+ object_class->constructed = ar_prefs_constructed;
object_class->finalize = ar_prefs_finalize;
object_class->set_property = ar_prefs_set_property;
@@ -267,6 +398,8 @@ ar_prefs_class_init (ArPrefsClass *klass)
G_PARAM_STATIC_STRINGS));
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/aisleriot/ui/prefs.ui");
+ gtk_widget_class_bind_child (widget_class, ArPrefsPrivate, game_label);
+ gtk_widget_class_bind_child (widget_class, ArPrefsPrivate, options_box);
gtk_widget_class_bind_child (widget_class, ArPrefsPrivate, click_checkbutton);
gtk_widget_class_bind_child (widget_class, ArPrefsPrivate, sound_checkbutton);
gtk_widget_class_bind_child (widget_class, ArPrefsPrivate, animations_checkbutton);
diff --git a/src/game.c b/src/game.c
index 83e7f8e..b9e2e0e 100644
--- a/src/game.c
+++ b/src/game.c
@@ -88,6 +88,7 @@ struct _AisleriotGame
{
GObject parent_instance;
+ GSettings *options_settings;
GSettings *scores_settings;
GPtrArray *slots;
@@ -1223,6 +1224,7 @@ aisleriot_game_finalize (GObject *object)
free (game->score);
+ g_clear_object (&game->options_settings);
g_clear_object (&game->scores_settings);
app_game = NULL;
@@ -1731,8 +1733,10 @@ aisleriot_game_load_game (AisleriotGame *game,
const char *game_module,
GError **error)
{
+ ArApplication *app = AR_APP;
GObject *object = G_OBJECT (game);
GError *err = NULL;
+ guint options;
int i;
g_return_val_if_fail (game_module != NULL && game_module[0] != '\0', FALSE);
@@ -1785,8 +1789,14 @@ aisleriot_game_load_game (AisleriotGame *game,
set_game_state (game, GAME_LOADED);
g_clear_object (&game->scores_settings);
- game->scores_settings = ar_application_scores_settings_new (AR_APPLICATION (g_application_get_default ()),
- game_module);
+ game->scores_settings = ar_application_scores_settings_new (app, game_module);
+
+ g_clear_object (&game->options_settings);
+ game->options_settings = ar_application_options_settings_new (app, game_module);
+
+ /* Restore options */
+ options = g_settings_get_uint (game->options_settings, AR_OPTIONS_KEY);
+ aisleriot_game_change_options (game, AISLERIOT_GAME_OPTIONS_MAX, options);
g_object_notify (object, "game-file");
@@ -2402,6 +2412,10 @@ aisleriot_game_change_options (AisleriotGame *game,
game_scm_call (game->lambdas[APPLY_OPTIONS_LAMBDA], &options_list, 1, NULL);
scm_remember_upto_here_1 (options_list);
+
+ /* Remember options */
+ g_settings_set_uint (game->options_settings, AR_OPTIONS_KEY, value);
+
return value;
}
diff --git a/src/window.c b/src/window.c
index 51c5a84..2398973 100644
--- a/src/window.c
+++ b/src/window.c
@@ -79,7 +79,6 @@ struct _AisleriotWindowPrivate
{
GSettings *settings;
GSettings *state_settings;
- GSettings *game_options_settings;
AisleriotGame *game;
ArStyle *board_style;
@@ -1059,170 +1058,6 @@ action_deal_cb (GSimpleAction *action,
aisleriot_game_deal_cards (priv->game);
}
-/* The "Game Options" menu */
-
-#if 0
-static void
-apply_option (GtkToggleAction *action,
- guint32 *changed_mask,
- guint32 *changed_value)
-{
- gboolean active;
- const char *action_name;
- guint32 value;
-
- active = gtk_toggle_action_get_active (action);
-
- action_name = gtk_action_get_name (GTK_ACTION (action));
- value = g_ascii_strtoull (action_name + strlen ("Option"), NULL, 10);
-
- /* g_print ("option %s changed, value=%x set=%d\n", action_name, value, active); */
-
- *changed_mask |= value;
- if (active)
- *changed_value |= value;
-}
-
-static void
-option_cb (GtkToggleAction *action,
- AisleriotWindow *window)
-{
- AisleriotWindowPrivate *priv = window->priv;
- gboolean active;
- guint32 changed_mask = 0, changed_value = 0, value;
-
- /* Don't change the options if we're just installing the options menu */
- if (priv->changing_game_type)
- return;
-
- active = gtk_toggle_action_get_active (action);
-
- /* If we're toggling OFF a radio action, don't redeal now,
- * since we'll get called another time right again when the new option
- * is toggled ON.
- * The game options will be updated when we get the toggled signal
- * for the newly active action in this group.
- */
- if (GTK_IS_RADIO_ACTION (action) &&
- !active)
- return;
-
- if (GTK_IS_RADIO_ACTION (action)) {
- GSList *group, *l;
-
- /* If toggling ON a radio action, we didn't turn off the other option
- * earlier. So we need to refresh the whole group.
- */
-
- group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
-
- for (l = group; l; l = l->next) {
- apply_option (GTK_TOGGLE_ACTION (l->data), &changed_mask, &changed_value);
- }
- } else {
- apply_option (action, &changed_mask, &changed_value);
- }
-
- value = aisleriot_game_change_options (priv->game, changed_mask, changed_value);
-
- g_settings_set_uint (priv->game_options_settings, AR_OPTIONS_KEY, value);
-
- /* Now re-deal, so the option is applied */
- aisleriot_game_new_game (priv->game);
-}
-
-#endif // 0
-
-static void
-install_options_menu (AisleriotWindow *window)
-{
-#if 0
- AisleriotWindowPrivate *priv = window->priv;
- GList *options, *l;
- int options_value = 0;
- GSList *radiogroup = NULL;
- int radion = 0;
-
- if (priv->options_merge_id != 0) {
- gtk_ui_manager_remove_ui (priv->ui_manager, priv->options_merge_id);
- priv->options_merge_id = 0;
- }
-
- if (priv->options_group) {
- gtk_ui_manager_remove_action_group (priv->ui_manager, priv->options_group);
- priv->options_group = NULL;
- }
-
- /* See gtk bug #424448 */
- gtk_ui_manager_ensure_update (priv->ui_manager);
-
- /* Only apply the options if they exist. Otherwise the options in the menu
- * and the real game options are out of sync until first changed by the user.
- */
- options_value = g_settings_get_uint (priv->game_options_settings, AR_OPTIONS_KEY);
- aisleriot_game_change_options (priv->game, AISLERIOT_GAME_OPTIONS_MAX, options_value);
-
- /* To get radio buttons in the menu insert an atom into the option list
- * in your scheme code. To get back out of radio-button mode insert
- * another atom. The exact value of the atoms is irrelevant - they merely
- * trigger a toggle - but descriptive names like begin-exclusive and
- * end-exclusive are probably a good idea.
- */
- options = aisleriot_game_get_options (priv->game);
- if (!options)
- return;
-
- priv->options_group = gtk_action_group_new ("Options");
- gtk_ui_manager_insert_action_group (priv->ui_manager, priv->options_group, -1);
- g_object_unref (priv->options_group);
-
- priv->options_merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
-
- for (l = options; l != NULL; l = l->next) {
- AisleriotGameOption *option = (AisleriotGameOption *) l->data;
- GtkToggleAction *action;
- gchar actionname[32];
-
- g_snprintf (actionname, sizeof (actionname), "Option%u", option->value);
-
- if (option->type == AISLERIOT_GAME_OPTION_CHECK) {
- action = gtk_toggle_action_new (actionname,
- option->display_name,
- NULL,
- NULL /* tooltip */);
- radiogroup = NULL; /* make sure to start a new radio group when the next RADIO option comes */
- radion = 0;
- } else {
- action = GTK_TOGGLE_ACTION (gtk_radio_action_new (actionname,
- option->display_name,
- NULL,
- NULL /* tooltip */,
- radion++));
- gtk_radio_action_set_group (GTK_RADIO_ACTION (action),
- radiogroup);
- radiogroup = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
- }
-
- gtk_toggle_action_set_active (action, option->set);
- g_signal_connect (action, "toggled",
- G_CALLBACK (option_cb), window);
-
- gtk_action_group_add_action (priv->options_group, GTK_ACTION (action));
- g_object_unref (action);
-
- gtk_ui_manager_add_ui (priv->ui_manager,
- priv->options_merge_id,
- OPTIONS_MENU_PATH,
- actionname, actionname,
- GTK_UI_MANAGER_MENUITEM, FALSE);
-
- aisleriot_game_option_free (option);
- }
-
- g_list_free (options);
-#endif // 0
-}
-
/* The "Recent Games" menu */
/*
@@ -1352,16 +1187,6 @@ sync_game_state (AisleriotGame *game,
state = aisleriot_game_get_state (priv->game);
-#if 0 // fixme
- /* Can only change options before the game start.
- * Set all the options insensitive, not the menu item in the main menu,
- * since the HIG disapproves of that.
- */
- if (priv->options_group != NULL) {
- gtk_action_group_set_sensitive (priv->options_group, state <= GAME_BEGIN);
- }
-#endif
-
/* Can only get hints while the game is running */
action = g_action_map_lookup_action (G_ACTION_MAP (window), "hint");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
@@ -1440,11 +1265,6 @@ game_type_changed_cb (AisleriotGame *game,
game_name = aisleriot_game_get_name (game);
-#if 0 // fixme
- g_object_set (priv->action[ACTION_HELP_GAME], "label", game_name, NULL);
- g_object_set (priv->action[ACTION_OPTIONS_MENU], "label", game_name, NULL);
-#endif
-
gtk_window_set_title (GTK_WINDOW (window), game_name);
g_free (game_name);
@@ -1452,11 +1272,7 @@ game_type_changed_cb (AisleriotGame *game,
game_module = aisleriot_game_get_game_module (game);
add_recently_played_game (window, game_module);
- g_clear_object (&priv->game_options_settings);
- priv->game_options_settings = ar_application_options_settings_new (AR_APPLICATION
(g_application_get_default ()),
- game_module);
-
- install_options_menu (window);
+ /* install_options_menu (window); */
update_statistics_display (window);
@@ -1999,7 +1815,6 @@ aisleriot_window_dispose (GObject *object)
}
g_clear_object (&priv->state_settings);
- g_clear_object (&priv->game_options_settings);
G_OBJECT_CLASS (aisleriot_window_parent_class)->dispose (object);
}
@@ -2206,3 +2021,12 @@ aisleriot_window_get_game_module (AisleriotWindow *window)
return aisleriot_game_get_game_module (priv->game);
}
+
+
+AisleriotGame *
+ar_window_get_game (AisleriotWindow *window)
+{
+ AisleriotWindowPrivate *priv = window->priv;
+
+ return priv->game;
+}
diff --git a/src/window.h b/src/window.h
index 4b8c791..ede98f0 100644
--- a/src/window.h
+++ b/src/window.h
@@ -56,6 +56,8 @@ void aisleriot_window_set_game_module (AisleriotWindow * window,
const char *aisleriot_window_get_game_module (AisleriotWindow *window);
+AisleriotGame *ar_window_get_game (AisleriotWindow *window);
+
void aisleriot_window_new_game (AisleriotWindow * window);
void aisleriot_window_change_game (AisleriotWindow * window);
void aisleriot_window_show_statistics_dialog (AisleriotWindow * window);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]