[gnome-games] aisleriot: Refactor ArClutterEmbed



commit f230095ef98e4f9943bc9504b648030cbd4a7791
Author: Christian Persch <chpe gnome org>
Date:   Mon Jan 4 16:02:59 2010 +0100

    aisleriot: Refactor ArClutterEmbed
    
    Move the functions that deal with synching GtkWidget style properties
    and GtkSettings properties to ArStyle properties into ar-style-gtk.[ch].
    This is in preparation to making the non-clutter AisleriotBoard also use
    ArStyle.

 aisleriot/Makefile.am        |    3 +
 aisleriot/ar-clutter-embed.c |  346 ++---------------------------------
 aisleriot/ar-style-gtk.c     |  418 ++++++++++++++++++++++++++++++++++++++++++
 aisleriot/ar-style-gtk.h     |   36 ++++
 4 files changed, 470 insertions(+), 333 deletions(-)
---
diff --git a/aisleriot/Makefile.am b/aisleriot/Makefile.am
index faabcd9..1c4f4dd 100644
--- a/aisleriot/Makefile.am
+++ b/aisleriot/Makefile.am
@@ -109,6 +109,9 @@ sol_clutter_SOURCES = \
 	ar-game-chooser.h \
 	ar-style.c	\
 	ar-style.h	\
+	ar-style-private.h \
+	ar-style-gtk.c	\
+	ar-style-gtk.h	\
 	baize.c		\
 	baize.h		\
 	board.c		\
diff --git a/aisleriot/ar-clutter-embed.c b/aisleriot/ar-clutter-embed.c
index 611473f..ce37466 100644
--- a/aisleriot/ar-clutter-embed.c
+++ b/aisleriot/ar-clutter-embed.c
@@ -22,6 +22,7 @@
 
 #include "ar-style.h"
 #include "ar-style-private.h"
+#include "ar-style-gtk.h"
 
 /**
  * SECTION: ar-clutter-embed
@@ -47,127 +48,6 @@ struct _ArClutterEmbedPrivate
   GdkCursor *cursor[AR_LAST_CURSOR];
 };
 
-#define I_(string) (g_intern_static_string (string))
-
-/* private functions */
-
-static void
-sync_settings (GtkSettings *settings,
-               GParamSpec *pspec,
-               ArClutterEmbed *embed)
-{
-  ArClutterEmbedPrivate *embed_priv = embed->priv;
-  ArStyle *style = embed_priv->style;
-  ArStylePrivate *style_priv = style->priv;
-  GObject *style_object = G_OBJECT (style);
-  const char *pspec_name;
-
-  if (pspec)
-    pspec_name = pspec->name;
-  else
-    pspec_name = NULL;
-
-  g_object_freeze_notify (style_object);
-
-  if (pspec_name == NULL || pspec_name == I_("gtk-dnd-drag-threshold")) {
-    int threshold;
-
-    g_object_get (settings, "gtk-dnd-drag-threshold", &threshold, NULL);
-
-    if (threshold != style_priv->dnd_drag_threshold) {
-      style_priv->dnd_drag_threshold = threshold;
-
-      g_object_notify (style_object, AR_STYLE_PROP_DND_DRAG_THRESHOLD);
-    }
-  }
-
-  if (pspec_name == NULL || pspec_name == I_("gtk-double-click-time")) {
-    int double_click_time;
-
-    g_object_get (settings, "gtk-double-click-time", &double_click_time, NULL);
-
-    if (double_click_time != style_priv->double_click_time) {
-      style_priv->double_click_time = double_click_time;
-
-      g_object_notify (style_object, AR_STYLE_PROP_DOUBLE_CLICK_TIME);
-    }
-  }
-
-  if (pspec_name == NULL || pspec_name == I_("gtk-enable-animations")) {
-    gboolean enable;
-
-    g_object_get (settings, "gtk-enable-animations", &enable, NULL);
-
-    if (enable != style_priv->enable_animations_gtk) {
-      style_priv->enable_animations_gtk = enable;
-
-      /* FIXMEchpe: only notify if the effective setting changed */
-      g_object_notify (style_object, AR_STYLE_PROP_ENABLE_ANIMATIONS);
-    }
-  }
-
-#if GTK_CHECK_VERSION (2, 14, 0)
-  if (pspec_name == NULL || pspec_name == I_("gtk-enable-event-sounds")) {
-    gboolean enable;
-
-    g_object_get (settings, "gtk-enable-event-sounds", &enable, NULL);
-
-    if (enable != style_priv->enable_sound_gtk) {
-      style_priv->enable_sound_gtk = enable;
-
-      /* FIXMEchpe: only notify if the effective setting changed */
-      g_object_notify (style_object, AR_STYLE_PROP_ENABLE_SOUND);
-    }
-  }
-#endif /* GTK+ >= 2.14.0 */
-
-#if GTK_CHECK_VERSION (2, 10, 0)
-  if (pspec_name == NULL || pspec_name == I_("gtk-touchscreen-mode")) {
-    gboolean enable;
-
-    g_object_get (settings, "gtk-touchscreen-mode", &enable, NULL);
-
-    if (enable != style_priv->touchscreen_mode) {
-      style_priv->touchscreen_mode = enable;
-
-      /* FIXMEchpe: only notify if the effective setting changed */
-      g_object_notify (style_object, AR_STYLE_PROP_TOUCHSCREEN_MODE);
-    }
-  }
-#endif /* GTK+ >= 2.10.0 */
-
-  g_object_thaw_notify (style_object);
-}
-
-static void
-sync_direction (ArClutterEmbed *embed,
-                GtkTextDirection previous_direction)
-{
-
-  ArClutterEmbedPrivate *embed_priv = embed->priv;
-  ArStyle *style = embed_priv->style;
-  ArStylePrivate *style_priv = style->priv;
-  GObject *style_object = G_OBJECT (style);
-  GtkTextDirection direction;
-  gboolean rtl;
-
-  direction = gtk_widget_get_direction (GTK_WIDGET (embed));
-  if (direction == previous_direction)
-    return;
-
-  g_object_freeze_notify (style_object);
-
-  rtl = (direction == GTK_TEXT_DIR_RTL);
-
-  if (style_priv->rtl != rtl) {
-    style_priv->rtl = rtl;
-
-    g_object_notify (style_object, AR_STYLE_PROP_RTL);
-  }
-
-  g_object_thaw_notify (style_object);
-}
-
 /* GtkWidgetClass impl */
 
 static void
@@ -213,145 +93,6 @@ ar_clutter_embed_unrealize (GtkWidget *widget)
   GTK_WIDGET_CLASS (ar_clutter_embed_parent_class)->unrealize (widget);
 }
 
-static void
-ar_clutter_embed_screen_changed (GtkWidget *widget,
-                                  GdkScreen *previous_screen)
-{
-  ArClutterEmbed *embed = AR_CLUTTER_EMBED (widget);
-  ArClutterEmbedPrivate *priv = embed->priv;
-  GdkScreen *screen;
-  GtkSettings *settings;
-  void (* screen_changed) (GtkWidget*, GdkScreen *) =
-    GTK_WIDGET_CLASS (ar_clutter_embed_parent_class)->screen_changed;
-
-  if (screen_changed) {
-    screen_changed (widget, previous_screen);
-  }
-
-  g_assert (priv->style != NULL);
-
-  screen = gtk_widget_get_screen (widget);
-  if (screen == previous_screen)
-    return;
-
-  if (previous_screen != NULL) {
-    g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
-                                          G_CALLBACK (sync_settings),
-                                          embed);
-  }
-
-  if (screen == NULL)
-    return;
-
-  settings = gtk_settings_get_for_screen (screen);
-
-  sync_settings (settings, NULL, embed);
-  g_signal_connect (settings, "notify::gtk-double-click-time",
-                    G_CALLBACK (sync_settings), embed);
-  g_signal_connect (settings, "notify::gtk-enable-animations",
-                    G_CALLBACK (sync_settings), embed);
-#if GTK_CHECK_VERSION (2, 14, 0)
-  g_signal_connect (settings, "notify::gtk-enable-event-sounds",
-                    G_CALLBACK (sync_settings), embed);
-#endif /* GTK+ >= 2.14.0 */
-#if GTK_CHECK_VERSION (2, 10, 0)
-  g_signal_connect (settings, "notify::gtk-touchscreen-mode",
-                    G_CALLBACK (sync_settings), embed);
-#endif /* GTK+ >= 2.10.0 */
-}
-
-static void
-ar_clutter_embed_style_set (GtkWidget *widget,
-                             GtkStyle *previous_style)
-{
-  ArClutterEmbed *embed = AR_CLUTTER_EMBED (widget);
-  ArClutterEmbedPrivate *embed_priv = embed->priv;
-  ArStyle *style = embed_priv->style;
-  ArStylePrivate *style_priv = style->priv;
-  GObject *style_object = G_OBJECT (style);
-  GdkColor *color = NULL;
-  ClutterColor selection_color;
-  int focus_line_width, focus_padding;
-  gboolean interior_focus;
-  double card_slot_ratio, card_overhang, card_step;
-
-  GTK_WIDGET_CLASS (ar_clutter_embed_parent_class)->style_set (widget, previous_style);
-
-  g_object_freeze_notify (style_object);
-
-  gtk_widget_style_get (widget,
-                        "interior-focus", &interior_focus,
-                        "focus-line-width", &focus_line_width,
-                        "focus-padding", &focus_padding,
-                        "card-slot-ratio", &card_slot_ratio,
-                        "card-overhang", &card_overhang,
-                        "card-step", &card_step,
-                        "selection-color", &color,
-                        NULL);
-
-  if (style_priv->interior_focus != interior_focus) {
-    style_priv->interior_focus = interior_focus;
-
-    g_object_notify (style_object, AR_STYLE_PROP_INTERIOR_FOCUS);
-  }
-
-  if (style_priv->focus_line_width != focus_line_width) {
-    style_priv->focus_line_width = focus_line_width;
-
-    g_object_notify (style_object, AR_STYLE_PROP_FOCUS_LINE_WIDTH);
-  }
-
-  if (style_priv->focus_padding != focus_padding) {
-    style_priv->focus_padding = focus_padding;
-
-    g_object_notify (style_object, AR_STYLE_PROP_FOCUS_PADDING);
-  }
-
-  if (style_priv->card_slot_ratio != card_slot_ratio) {
-    style_priv->card_slot_ratio = card_slot_ratio;
-
-    g_object_notify (style_object, AR_STYLE_PROP_CARD_SLOT_RATIO);
-  }
-
-  if (style_priv->card_overhang != card_overhang) {
-    style_priv->card_overhang = card_overhang;
-
-    g_object_notify (style_object, AR_STYLE_PROP_CARD_OVERHANG);
-  }
-
-  if (style_priv->card_step != card_step) {
-    style_priv->card_step = card_step;
-
-    g_object_notify (style_object, AR_STYLE_PROP_CARD_STEP);
-  }
-
-  if (color != NULL) {
-    _ar_clutter_color_from_gdk_color (&selection_color, color);
-    gdk_color_free (color);
-  } else {
-    _ar_clutter_color_from_gdk_color (&selection_color, &default_selection_color);
-  }
-
-  if (!clutter_color_equal (&style_priv->selection_color, &selection_color)) {
-    style_priv->selection_color = selection_color;
-
-    g_object_notify (style_object, AR_STYLE_PROP_SELECTION_COLOR);
-  }
-
-  g_object_thaw_notify (style_object);
-}
-
-static void
-ar_clutter_embed_direction_changed (GtkWidget *widget,
-                                    GtkTextDirection previous_direction)
-{
-  ArClutterEmbed *embed = AR_CLUTTER_EMBED (widget);
-
-  GTK_WIDGET_CLASS (ar_clutter_embed_parent_class)->direction_changed (widget, previous_direction);
-
-  sync_direction (embed, previous_direction);
-}
-
 static gboolean
 ar_clutter_embed_focus_in (GtkWidget *widget,
                            GdkEventFocus *event)
@@ -426,32 +167,23 @@ static void
 ar_clutter_embed_dispose (GObject *object)
 {
   ArClutterEmbed *embed = AR_CLUTTER_EMBED (object);
-  GtkWidget *widget = GTK_WIDGET (embed);
-
-  g_signal_handlers_disconnect_by_func (gtk_widget_get_settings (widget),
-                                        G_CALLBACK (sync_settings),
-                                        embed);
-
-  G_OBJECT_CLASS (ar_clutter_embed_parent_class)->dispose (object);
-}
-
-static void
-ar_clutter_embed_finalize (GObject *object)
-{
-  ArClutterEmbed *embed = AR_CLUTTER_EMBED (object);
   ArClutterEmbedPrivate *priv = embed->priv;
 
-  g_assert (priv->style != NULL);
-  g_object_unref (priv->style);
+  if (priv->style != NULL) {
+    _ar_style_gtk_detach (priv->style, GTK_WIDGET (embed));
 
-  G_OBJECT_CLASS (ar_clutter_embed_parent_class)->finalize (object);
+    g_object_unref (priv->style);
+    priv->style = NULL;
+  }
+
+  G_OBJECT_CLASS (ar_clutter_embed_parent_class)->dispose (object);
 }
 
 static void
 ar_clutter_embed_set_property (GObject      *object,
-                                guint         property_id,
-                                const GValue *value,
-                                GParamSpec   *pspec)
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
 {
   ArClutterEmbed *embed = AR_CLUTTER_EMBED (object);
   ArClutterEmbedPrivate *priv = embed->priv;
@@ -459,10 +191,7 @@ ar_clutter_embed_set_property (GObject      *object,
   switch (property_id) {
     case PROP_STYLE:
       priv->style = g_value_dup_object (value);
-
-      /* This is necessary since we don't get an initial change notification! */
-      sync_direction (embed, GTK_TEXT_DIR_LTR);
-
+      _ar_style_gtk_attach (priv->style, GTK_WIDGET (embed));
       break;
 
     default:
@@ -480,13 +209,9 @@ ar_clutter_embed_class_init (ArClutterEmbedClass *klass)
 
   object_class->set_property = ar_clutter_embed_set_property;
   object_class->dispose = ar_clutter_embed_dispose;
-  object_class->finalize = ar_clutter_embed_finalize;
 
   widget_class->realize = ar_clutter_embed_realize;
   widget_class->unrealize = ar_clutter_embed_unrealize;
-  widget_class->style_set = ar_clutter_embed_style_set;
-  widget_class->direction_changed = ar_clutter_embed_direction_changed;
-  widget_class->screen_changed = ar_clutter_embed_screen_changed;
   widget_class->focus_in_event = ar_clutter_embed_focus_in;
   widget_class->focus_out_event = ar_clutter_embed_focus_out;
   widget_class->focus = ar_clutter_embed_focus;
@@ -505,52 +230,7 @@ ar_clutter_embed_class_init (ArClutterEmbedClass *klass)
                           G_PARAM_CONSTRUCT_ONLY |
                           G_PARAM_STATIC_STRINGS));
 
-  gtk_widget_class_install_style_property
-    (widget_class,
-     g_param_spec_boxed ("selection-color", NULL, NULL,
-                         GDK_TYPE_COLOR,
-                         G_PARAM_READWRITE |
-                         G_PARAM_STATIC_STRINGS));
-
-  /**
-   * ArClutterEmbed:card-slot-ratio:
-   *
-   * The ratio of card to slot size. Note that this is the ratio of
-   * card width/slot width and card height/slot height, not of
-   * card area/slot area.
-  */
-  gtk_widget_class_install_style_property
-    (widget_class,
-     g_param_spec_double ("card-slot-ratio", NULL, NULL,
-                          0.1, 1.0, DEFAULT_CARD_SLOT_RATIO,
-                          G_PARAM_READWRITE |
-                          G_PARAM_STATIC_STRINGS));
-
-  /**
-   * ArClutterEmbed:card-overhang:
-   *
-   * This controls how much of a card is allowed to hang off of the bottom
-   * of the screen. If set to %0.0, the last card is always fully visible.
-   */
-  gtk_widget_class_install_style_property
-    (widget_class,
-     g_param_spec_double ("card-overhang", NULL, NULL,
-                          0.0, 1.0, DEFAULT_CARD_OVERHANG,
-                          G_PARAM_READWRITE |
-                          G_PARAM_STATIC_STRINGS));
-
-  /**
-   * ArClutterEmbed:card-step:
-   *
-   * This controls how much one card is offset the previous one in card stacks.
-   * A game-specified a value for the card step takes precedence over this.
-   */
-  gtk_widget_class_install_style_property
-    (widget_class,
-     g_param_spec_double ("card-step", NULL, NULL,
-                          MIN_CARD_STEP, MAX_CARD_STEP, DEFAULT_CARD_STEP,
-                          G_PARAM_READWRITE |
-                          G_PARAM_STATIC_STRINGS));
+  _ar_style_gtk_class_install_style_properties (widget_class);
 }
 
 /* public API */
diff --git a/aisleriot/ar-style-gtk.c b/aisleriot/ar-style-gtk.c
new file mode 100644
index 0000000..a739562
--- /dev/null
+++ b/aisleriot/ar-style-gtk.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright © 1998, 2003 Jonathan Blandford <jrb mit edu>
+ * Copyright © 2007, 2008, 2009 Christian Persch
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "ar-style-gtk.h"
+
+#include "ar-style-private.h"
+
+#include <libgames-support/games-debug.h>
+
+/**
+ * SECTION: ar-style-gtk
+ * @short_description: common functions to set #ArStyle properties
+ *
+ * Tie #ArStyle properties to #GtkWidget style properties, and to
+ * #GtkSettings properties.
+ */
+
+#define I_(string) (g_intern_static_string (string))
+
+/* private functions */
+
+static void
+sync_settings (GtkSettings *settings,
+               GParamSpec *pspec,
+               ArStyle *style)
+{
+  ArStylePrivate *style_priv = style->priv;
+  GObject *style_object = G_OBJECT (style);
+  const char *pspec_name;
+
+  if (pspec)
+    pspec_name = pspec->name;
+  else
+    pspec_name = NULL;
+
+  _games_debug_print (GAMES_DEBUG_GAME_STYLE,
+                      "[ArStyle %p] Syncing GtkSettings:%s\n",
+                      style, pspec_name ? pspec_name : "*");
+
+  g_object_freeze_notify (style_object);
+
+  if (pspec_name == NULL || pspec_name == I_("gtk-dnd-drag-threshold")) {
+    int threshold;
+
+    g_object_get (settings, "gtk-dnd-drag-threshold", &threshold, NULL);
+
+    if (threshold != style_priv->dnd_drag_threshold) {
+      style_priv->dnd_drag_threshold = threshold;
+
+      g_object_notify (style_object, AR_STYLE_PROP_DND_DRAG_THRESHOLD);
+    }
+  }
+
+  if (pspec_name == NULL || pspec_name == I_("gtk-double-click-time")) {
+    int double_click_time;
+
+    g_object_get (settings, "gtk-double-click-time", &double_click_time, NULL);
+
+    if (double_click_time != style_priv->double_click_time) {
+      style_priv->double_click_time = double_click_time;
+
+      g_object_notify (style_object, AR_STYLE_PROP_DOUBLE_CLICK_TIME);
+    }
+  }
+
+  if (pspec_name == NULL || pspec_name == I_("gtk-enable-animations")) {
+    gboolean enable;
+
+    g_object_get (settings, "gtk-enable-animations", &enable, NULL);
+
+    if (enable != style_priv->enable_animations_gtk) {
+      style_priv->enable_animations_gtk = enable;
+
+      /* FIXMEchpe: only notify if the effective setting changed */
+      g_object_notify (style_object, AR_STYLE_PROP_ENABLE_ANIMATIONS);
+    }
+  }
+
+#if GTK_CHECK_VERSION (2, 14, 0)
+  if (pspec_name == NULL || pspec_name == I_("gtk-enable-event-sounds")) {
+    gboolean enable;
+
+    g_object_get (settings, "gtk-enable-event-sounds", &enable, NULL);
+
+    if (enable != style_priv->enable_sound_gtk) {
+      style_priv->enable_sound_gtk = enable;
+
+      /* FIXMEchpe: only notify if the effective setting changed */
+      g_object_notify (style_object, AR_STYLE_PROP_ENABLE_SOUND);
+    }
+  }
+#endif /* GTK+ >= 2.14.0 */
+
+#if GTK_CHECK_VERSION (2, 10, 0)
+  if (pspec_name == NULL || pspec_name == I_("gtk-touchscreen-mode")) {
+    gboolean enable;
+
+    g_object_get (settings, "gtk-touchscreen-mode", &enable, NULL);
+
+    if (enable != style_priv->touchscreen_mode) {
+      style_priv->touchscreen_mode = enable;
+
+      /* FIXMEchpe: only notify if the effective setting changed */
+      g_object_notify (style_object, AR_STYLE_PROP_TOUCHSCREEN_MODE);
+    }
+  }
+#endif /* GTK+ >= 2.10.0 */
+
+  g_object_thaw_notify (style_object);
+}
+
+static void
+direction_changed_cb (GtkWidget *widget,
+                      GtkTextDirection previous_direction,
+                      ArStyle *style)
+{
+  ArStylePrivate *style_priv = style->priv;
+  GObject *style_object = G_OBJECT (style);
+  GtkTextDirection direction;
+  gboolean rtl;
+
+  direction = gtk_widget_get_direction (widget);
+
+  _games_debug_print (GAMES_DEBUG_GAME_STYLE,
+                      "[ArStyle %p] Widget direction-changed direction %d previous-direction %d\n",
+                      style, direction, previous_direction);
+
+  if (direction == previous_direction)
+    return;
+
+  g_object_freeze_notify (style_object);
+
+  rtl = (direction == GTK_TEXT_DIR_RTL);
+
+  if (style_priv->rtl != rtl) {
+    style_priv->rtl = rtl;
+
+    g_object_notify (style_object, AR_STYLE_PROP_RTL);
+  }
+
+  g_object_thaw_notify (style_object);
+}
+
+static void
+screen_changed_cb (GtkWidget *widget,
+                   GdkScreen *previous_screen,
+                   ArStyle *style)
+{
+  GdkScreen *screen;
+  GtkSettings *settings;
+
+  g_assert (style != NULL);
+
+  screen = gtk_widget_get_screen (widget);
+
+  _games_debug_print (GAMES_DEBUG_GAME_STYLE,
+                      "[ArStyle %p] Widget screen-changed screen %p previous-screen %p\n",
+                      style, screen, previous_screen);
+
+  if (screen == previous_screen)
+    return;
+
+  if (previous_screen != NULL) {
+    g_signal_handlers_disconnect_by_func (gtk_settings_get_for_screen (previous_screen),
+                                          G_CALLBACK (sync_settings),
+                                          style);
+  }
+
+  if (screen == NULL)
+    return;
+
+  settings = gtk_settings_get_for_screen (screen);
+
+  sync_settings (settings, NULL, style);
+
+  g_signal_connect (settings, "notify::gtk-double-click-time",
+                    G_CALLBACK (sync_settings), style);
+  g_signal_connect (settings, "notify::gtk-enable-animations",
+                    G_CALLBACK (sync_settings), style);
+#if GTK_CHECK_VERSION (2, 14, 0)
+  g_signal_connect (settings, "notify::gtk-enable-event-sounds",
+                    G_CALLBACK (sync_settings), style);
+#endif /* GTK+ >= 2.14.0 */
+#if GTK_CHECK_VERSION (2, 10, 0)
+  g_signal_connect (settings, "notify::gtk-touchscreen-mode",
+                    G_CALLBACK (sync_settings), style);
+#endif /* GTK+ >= 2.10.0 */
+}
+
+static void
+style_set_cb (GtkWidget *widget,
+              GtkStyle *previous_style,
+              ArStyle *style)
+{
+  ArStylePrivate *style_priv = style->priv;
+  GObject *style_object = G_OBJECT (style);
+  GdkColor *color = NULL;
+  ClutterColor selection_color;
+  int focus_line_width, focus_padding;
+  gboolean interior_focus;
+  double card_slot_ratio, card_overhang, card_step;
+
+  _games_debug_print (GAMES_DEBUG_GAME_STYLE,
+                      "[ArStyle %p] Syncing widget style properties\n",
+                      style);
+
+  g_object_freeze_notify (style_object);
+
+  gtk_widget_style_get (widget,
+                        "interior-focus", &interior_focus,
+                        "focus-line-width", &focus_line_width,
+                        "focus-padding", &focus_padding,
+                        "card-slot-ratio", &card_slot_ratio,
+                        "card-overhang", &card_overhang,
+                        "card-step", &card_step,
+                        "selection-color", &color,
+                        NULL);
+
+  if (style_priv->interior_focus != interior_focus) {
+    style_priv->interior_focus = interior_focus;
+
+    g_object_notify (style_object, AR_STYLE_PROP_INTERIOR_FOCUS);
+  }
+
+  if (style_priv->focus_line_width != focus_line_width) {
+    style_priv->focus_line_width = focus_line_width;
+
+    g_object_notify (style_object, AR_STYLE_PROP_FOCUS_LINE_WIDTH);
+  }
+
+  if (style_priv->focus_padding != focus_padding) {
+    style_priv->focus_padding = focus_padding;
+
+    g_object_notify (style_object, AR_STYLE_PROP_FOCUS_PADDING);
+  }
+
+  if (style_priv->card_slot_ratio != card_slot_ratio) {
+    style_priv->card_slot_ratio = card_slot_ratio;
+
+    g_object_notify (style_object, AR_STYLE_PROP_CARD_SLOT_RATIO);
+  }
+
+  if (style_priv->card_overhang != card_overhang) {
+    style_priv->card_overhang = card_overhang;
+
+    g_object_notify (style_object, AR_STYLE_PROP_CARD_OVERHANG);
+  }
+
+  if (style_priv->card_step != card_step) {
+    style_priv->card_step = card_step;
+
+    g_object_notify (style_object, AR_STYLE_PROP_CARD_STEP);
+  }
+
+  if (color != NULL) {
+    _ar_clutter_color_from_gdk_color (&selection_color, color);
+    gdk_color_free (color);
+  } else {
+    _ar_clutter_color_from_gdk_color (&selection_color, &default_selection_color);
+  }
+
+  if (!clutter_color_equal (&style_priv->selection_color, &selection_color)) {
+    style_priv->selection_color = selection_color;
+
+    g_object_notify (style_object, AR_STYLE_PROP_SELECTION_COLOR);
+  }
+
+  g_object_thaw_notify (style_object);
+}
+
+/* private API */
+
+/**
+ * _ar_style_gtk_class_install_style_properties:
+ * @widget_class: a #GtkWidgetClass
+ *
+ * Installs style properties in @widget_class.
+ */
+void
+_ar_style_gtk_class_install_style_properties (GtkWidgetClass *widget_class)
+{
+  /**
+   * ArClutterEmbed:selection-color:
+   *
+   * The card selection colour.
+  */
+  gtk_widget_class_install_style_property
+    (widget_class,
+     g_param_spec_boxed ("selection-color", NULL, NULL,
+                         GDK_TYPE_COLOR,
+                         G_PARAM_READWRITE |
+                         G_PARAM_STATIC_STRINGS));
+
+  /**
+   * ArClutterEmbed:card-slot-ratio:
+   *
+   * The ratio of card to slot size. Note that this is the ratio of
+   * card width/slot width and card height/slot height, not of
+   * card area/slot area.
+  */
+  gtk_widget_class_install_style_property
+    (widget_class,
+     g_param_spec_double ("card-slot-ratio", NULL, NULL,
+                          0.1, 1.0, DEFAULT_CARD_SLOT_RATIO,
+                          G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS));
+
+  /**
+   * ArClutterEmbed:card-overhang:
+   *
+   * This controls how much of a card is allowed to hang off of the bottom
+   * of the screen. If set to %0.0, the last card is always fully visible.
+   */
+  gtk_widget_class_install_style_property
+    (widget_class,
+     g_param_spec_double ("card-overhang", NULL, NULL,
+                          0.0, 1.0, DEFAULT_CARD_OVERHANG,
+                          G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS));
+
+  /**
+   * ArClutterEmbed:card-step:
+   *
+   * This controls how much one card is offset the previous one in card stacks.
+   * A game-specified a value for the card step takes precedence over this.
+   */
+  gtk_widget_class_install_style_property
+    (widget_class,
+     g_param_spec_double ("card-step", NULL, NULL,
+                          MIN_CARD_STEP, MAX_CARD_STEP, DEFAULT_CARD_STEP,
+                          G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * _ar_style_gtk_attach:
+ * @style: a #ArStyle
+ * @widget: a #GtkWidget
+ *
+ * Attaches @style to @widget's style properties and the properties
+ * of its #GdkScreen's #GtkSettings object.
+ */
+void
+_ar_style_gtk_attach (ArStyle *style,
+                      GtkWidget *widget)
+{
+  g_return_if_fail (AR_IS_STYLE (style));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  _games_debug_print (GAMES_DEBUG_GAME_STYLE,
+                      "[ArStyle %p] Attaching to widget %p\n", style, widget);
+
+  g_assert (g_object_get_data (G_OBJECT (widget), "Ar::Style") == NULL);
+  g_object_set_data (G_OBJECT (widget), "Ar::Style", style);
+
+#if 0
+  if (gtk_widget_get_style (widget))
+    style_set_cb (widget, NULL, style);
+  if (gtk_widget_has_screen (widget))
+    screen_changed_cb (widget, NULL, style);
+#endif
+
+  /* This is necessary since we don't get an initial change notification! */
+  direction_changed_cb (widget, GTK_TEXT_DIR_LTR, style);
+
+  g_signal_connect (widget, "style-set",
+                    G_CALLBACK (style_set_cb), style);
+  g_signal_connect (widget, "screen-changed",
+                    G_CALLBACK (screen_changed_cb), style);
+  g_signal_connect (widget, "direction-changed",
+                    G_CALLBACK (direction_changed_cb), style);
+}
+
+/**
+ * _ar_style_gtk_detach:
+ * @style: a #ArStyle
+ * @widget: a #GtkWidget
+ *
+ * Detaches @style from @widget.
+ */
+void
+_ar_style_gtk_detach (ArStyle *style,
+                      GtkWidget *widget)
+{
+  g_return_if_fail (AR_IS_STYLE (style));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  _games_debug_print (GAMES_DEBUG_GAME_STYLE,
+                      "[ArStyle %p] Detaching from widget %p\n", style, widget);
+
+  g_assert (g_object_get_data (G_OBJECT (widget), "Ar::Style") == style);
+  g_object_set_data (G_OBJECT (widget), "Ar::Style", NULL);
+
+  g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (style_set_cb), style);
+  g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (screen_changed_cb), style);
+  g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (direction_changed_cb), style);
+
+  g_signal_handlers_disconnect_by_func (gtk_widget_get_settings (widget),
+                                        G_CALLBACK (sync_settings),
+                                        style);
+}
diff --git a/aisleriot/ar-style-gtk.h b/aisleriot/ar-style-gtk.h
new file mode 100644
index 0000000..14acd1f
--- /dev/null
+++ b/aisleriot/ar-style-gtk.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2009 Christian Persch <chpe gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AR_STYLE_GTK_H__
+#define __AR_STYLE_GTK_H__
+
+#include <gtk/gtk.h>
+
+#include "ar-style.h"
+
+G_BEGIN_DECLS
+
+void _ar_style_gtk_class_install_style_properties (GtkWidgetClass *widget_class);
+
+void _ar_style_gtk_attach (ArStyle *style,
+                           GtkWidget *widget);
+void _ar_style_gtk_detach (ArStyle *style,
+                           GtkWidget *widget);
+
+G_END_DECLS
+
+#endif /* __AR_STYLE_GTK_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]