[aisleriot/wip/redesign: 9/17] all: Move game options to prefs dialogue



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]