gnome-games r8427 - in trunk: aisleriot blackjack/src libgames-support



Author: chpe
Date: Tue Jan  6 18:18:21 2009
New Revision: 8427
URL: http://svn.gnome.org/viewvc/gnome-games?rev=8427&view=rev

Log:
Continue refactoring the card themes: add GamesCardThemeInfo structure
holding basic info about a theme, and use that to load the theme. Make
GamesCardTheme only hold one theme ever, and adapt the apps to create
new themes from the theme infos when changing themes. Work-in-progress.

Modified:
   trunk/aisleriot/board-noclutter.c
   trunk/aisleriot/board.c
   trunk/aisleriot/board.h
   trunk/aisleriot/window.c
   trunk/blackjack/src/card.cpp
   trunk/blackjack/src/card.h
   trunk/blackjack/src/dialog.cpp
   trunk/libgames-support/games-card-images.c
   trunk/libgames-support/games-card-images.h
   trunk/libgames-support/games-card-selector.c
   trunk/libgames-support/games-card-selector.h
   trunk/libgames-support/games-card-theme-fixed.c
   trunk/libgames-support/games-card-theme-kde.c
   trunk/libgames-support/games-card-theme-preimage.c
   trunk/libgames-support/games-card-theme-private.h
   trunk/libgames-support/games-card-theme-sliced.c
   trunk/libgames-support/games-card-theme-svg.c
   trunk/libgames-support/games-card-theme.c
   trunk/libgames-support/games-card-theme.h
   trunk/libgames-support/games-files.c
   trunk/libgames-support/render-cards.c

Modified: trunk/aisleriot/board-noclutter.c
==============================================================================
--- trunk/aisleriot/board-noclutter.c	(original)
+++ trunk/aisleriot/board-noclutter.c	Tue Jan  6 18:18:21 2009
@@ -110,7 +110,6 @@
   GdkCursor *cursor[LAST_CURSOR];
 
   GamesCardTheme *theme;
-  char *card_theme;
   CardSize card_size;
 
   double width;
@@ -191,7 +190,6 @@
 
   guint show_selection : 1;
   guint show_highlight : 1;
-  guint scalable_cards : 1;
 
   guint force_geometry_update : 1;
 };
@@ -202,7 +200,6 @@
 {
   PROP_0,
   PROP_GAME,
-  PROP_SCALABLE_CARDS,
   PROP_THEME
 };
 
@@ -1416,6 +1413,9 @@
   GtkWidget *widget = GTK_WIDGET (board);
   const cairo_font_options_t *font_options;
 
+  if (!priv->theme)
+    return;
+
   font_options = gdk_screen_get_font_options (gtk_widget_get_screen (widget));
   games_card_theme_set_font_options (priv->theme, font_options);
 
@@ -3356,9 +3356,7 @@
 
   g_assert (priv->game != NULL);
 
-  /* Create this down here since we need to have the scalable_cards value */
-  priv->theme = games_card_theme_new ();
-  priv->images = games_card_images_new (priv->theme);
+  priv->images = games_card_images_new ();
 
   return object;
 }
@@ -3374,12 +3372,12 @@
                                         0, 0, NULL, NULL, board);
   g_object_unref (priv->game);
 
-  g_free (priv->card_theme);
-
   g_byte_array_free (priv->moving_cards, TRUE);
 
   g_object_unref (priv->images);
-  g_object_unref (priv->theme);
+
+  if (priv->theme)
+    g_object_unref (priv->theme);
 
 #if 0
   screen = gtk_widget_get_settings (widget);
@@ -3406,10 +3404,7 @@
 
   switch (prop_id) {
     case PROP_THEME:
-      g_value_set_string (value, aisleriot_board_get_card_theme (board));
-      break;
-    case PROP_SCALABLE_CARDS:
-      g_value_set_boolean (value, priv->scalable_cards);
+      g_value_set_object (value, aisleriot_board_get_card_theme (board));
       break;
   }
 }
@@ -3438,10 +3433,7 @@
 
       break;
     case PROP_THEME:
-      aisleriot_board_set_card_theme (board, g_value_get_string (value));
-      break;
-    case PROP_SCALABLE_CARDS:
-      priv->scalable_cards = g_value_get_boolean (value) != FALSE;
+      aisleriot_board_set_card_theme (board, g_value_get_object (value));
       break;
   }
 }
@@ -3555,16 +3547,9 @@
 
   g_object_class_install_property
     (gobject_class,
-     PROP_SCALABLE_CARDS,
-     g_param_spec_boolean ("scalable-cards", NULL, NULL,
-                           FALSE,
-                           G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_CONSTRUCT_ONLY));
-
-  g_object_class_install_property
-    (gobject_class,
      PROP_THEME,
-     g_param_spec_string ("theme", NULL, NULL,
-                          NULL,
+     g_param_spec_object ("theme", NULL, NULL,
+                          GAMES_TYPE_CARD_THEME,
                           G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
 
   gtk_widget_class_install_style_property
@@ -3638,53 +3623,62 @@
 /* public API */
 
 GtkWidget *
-aisleriot_board_new (AisleriotGame *game,
-                     gboolean scalable_cards)
+aisleriot_board_new (AisleriotGame *game)
 {
   return g_object_new (AISLERIOT_TYPE_BOARD,
                        "game", game,
-                       "scalable-cards", scalable_cards,
                        NULL);
 }
 
-gboolean
+void
 aisleriot_board_set_card_theme (AisleriotBoard *board,
-                                const char *card_theme)
+                                GamesCardTheme *theme)
 {
   AisleriotBoardPrivate *priv = board->priv;
-  gboolean retval;
+  GtkWidget *widget = GTK_WIDGET (board);
+
+  g_return_if_fail (AISLERIOT_IS_BOARD (board));
+  g_return_if_fail (GAMES_IS_CARD_THEME (theme));
 
-  g_return_val_if_fail (card_theme != NULL && card_theme[0] != '\0', FALSE);
+  if (theme == priv->theme)
+    return;
+
+  if (priv->theme) {
+    g_object_unref (priv->theme);
+  }
 
   priv->geometry_set = FALSE;
   priv->slot_image = NULL;
 
-  retval = games_card_theme_set_theme (priv->theme, NULL, card_theme);
+  if (gtk_widget_has_screen (widget)) {
+#warning FIXMEchpe move this to AisleriotWindow
+    const cairo_font_options_t *font_options;
 
-  /* NOTE! We need to do this even if setting the theme failed, since
-   * the attempt will have wiped out the old theme data!
-   */
-  if (GTK_WIDGET_REALIZED (board)) {
+    font_options = gdk_screen_get_font_options (gtk_widget_get_screen (widget));
+    games_card_theme_set_font_options (theme, font_options);
+  }
+
+  priv->theme = g_object_ref (theme);
+  
+  games_card_images_set_theme (priv->images, priv->theme);
+
+  if (GTK_WIDGET_REALIZED (widget)) {
     /* Update card size and slot locations for new card theme (might have changed aspect!)*/
     aisleriot_board_setup_geometry (board);
 
-    gtk_widget_queue_draw (GTK_WIDGET (board));
+#warning FIXMEchpe queue resize if the new card theme  has a minimum size / the old had one and the one doesnt
+    gtk_widget_queue_draw (widget);
   }
 
   g_object_notify (G_OBJECT (board), "theme");
-
-  return retval;
 }
 
-const char *
+GamesCardTheme *
 aisleriot_board_get_card_theme (AisleriotBoard *board)
 {
   AisleriotBoardPrivate *priv = board->priv;
-  const char *theme;
-
-  theme = games_card_theme_get_theme (priv->theme);
 
-  return theme != NULL ? theme : GAMES_CARD_THEME_DEFAULT;
+  return priv->theme;
 }
 
 void

Modified: trunk/aisleriot/board.c
==============================================================================
--- trunk/aisleriot/board.c	(original)
+++ trunk/aisleriot/board.c	Tue Jan  6 18:18:21 2009
@@ -117,7 +117,6 @@
   GdkCursor *cursor[LAST_CURSOR];
 
   GamesCardTheme *theme;
-  char *card_theme;
   CardSize card_size;
 
   double width;
@@ -205,7 +204,6 @@
 
   guint show_selection : 1;
   guint show_highlight : 1;
-  guint scalable_cards : 1;
 
   guint force_geometry_update : 1;
 
@@ -228,7 +226,6 @@
 {
   PROP_0,
   PROP_GAME,
-  PROP_SCALABLE_CARDS,
   PROP_THEME
 };
 
@@ -1486,6 +1483,9 @@
   GtkWidget *widget = GTK_WIDGET (board);
   const cairo_font_options_t *font_options;
 
+  if (!priv->theme)
+    return;
+
   font_options = gdk_screen_get_font_options (gtk_widget_get_screen (widget));
   games_card_theme_set_font_options (priv->theme, font_options);
 
@@ -3183,9 +3183,7 @@
 
   g_assert (priv->game != NULL);
 
-  /* Create this down here since we need to have the scalable_cards value */
-  priv->theme = games_card_theme_new ();
-  priv->images = games_card_images_new (priv->theme);
+  priv->images = games_card_images_new ();
   priv->textures = games_card_textures_cache_new (priv->images);
 
   return object;
@@ -3202,14 +3200,14 @@
                                         0, 0, NULL, NULL, board);
   g_object_unref (priv->game);
 
-  g_free (priv->card_theme);
-
   g_array_free (priv->removed_cards, TRUE);
 
   g_byte_array_free (priv->moving_cards, TRUE);
 
+  if (priv->theme) {
+    g_object_unref (priv->theme);
+  }
   g_object_unref (priv->images);
-  g_object_unref (priv->theme);
 
 #if 0
   screen = gtk_widget_get_settings (widget);
@@ -3257,14 +3255,10 @@
                               GParamSpec *pspec)
 {
   AisleriotBoard *board = AISLERIOT_BOARD (object);
-  AisleriotBoardPrivate *priv = board->priv;
 
   switch (prop_id) {
     case PROP_THEME:
-      g_value_set_string (value, aisleriot_board_get_card_theme (board));
-      break;
-    case PROP_SCALABLE_CARDS:
-      g_value_set_boolean (value, priv->scalable_cards);
+      g_value_set_object (value, aisleriot_board_get_card_theme (board));
       break;
   }
 }
@@ -3293,10 +3287,7 @@
 
       break;
     case PROP_THEME:
-      aisleriot_board_set_card_theme (board, g_value_get_string (value));
-      break;
-    case PROP_SCALABLE_CARDS:
-      priv->scalable_cards = g_value_get_boolean (value) != FALSE;
+      aisleriot_board_set_card_theme (board, g_value_get_object (value));
       break;
   }
 }
@@ -3410,16 +3401,9 @@
 
   g_object_class_install_property
     (gobject_class,
-     PROP_SCALABLE_CARDS,
-     g_param_spec_boolean ("scalable-cards", NULL, NULL,
-                           FALSE,
-                           G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_CONSTRUCT_ONLY));
-
-  g_object_class_install_property
-    (gobject_class,
      PROP_THEME,
-     g_param_spec_string ("theme", NULL, NULL,
-                          NULL,
+     g_param_spec_object ("theme", NULL, NULL,
+                          GAMES_TYPE_CARD_THEME,
                           G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
 
   gtk_widget_class_install_style_property
@@ -3493,52 +3477,62 @@
 /* public API */
 
 GtkWidget *
-aisleriot_board_new (AisleriotGame *game,
-                     gboolean scalable_cards)
+aisleriot_board_new (AisleriotGame *game)
 {
   return g_object_new (AISLERIOT_TYPE_BOARD,
                        "game", game,
-                       "scalable-cards", scalable_cards,
                        NULL);
 }
 
-gboolean
+void
 aisleriot_board_set_card_theme (AisleriotBoard *board,
-                                const char *card_theme)
+                                GamesCardTheme *theme)
 {
   AisleriotBoardPrivate *priv = board->priv;
-  gboolean retval;
+  GtkWidget *widget = GTK_WIDGET (board);
+
+  g_return_if_fail (AISLERIOT_IS_BOARD (board));
+  g_return_if_fail (GAMES_IS_CARD_THEME (theme));
 
-  g_return_val_if_fail (card_theme != NULL && card_theme[0] != '\0', FALSE);
+  if (theme == priv->theme)
+    return;
+
+  if (priv->theme) {
+    g_object_unref (priv->theme);
+  }
 
   priv->geometry_set = FALSE;
 
-  retval = games_card_theme_set_theme (priv->theme, NULL, card_theme);
+  if (gtk_widget_has_screen (widget)) {
+    const cairo_font_options_t *font_options;
 
-  /* NOTE! We need to do this even if setting the theme failed, since
-   * the attempt will have wiped out the old theme data!
-   */
-  if (GTK_WIDGET_REALIZED (board)) {
+#warning FIXMEchpe move this to AisleriotWindow
+    font_options = gdk_screen_get_font_options (gtk_widget_get_screen (widget));
+    games_card_theme_set_font_options (theme, font_options);
+  }
+
+  priv->theme = g_object_ref (theme);
+
+  games_card_images_set_theme (priv->images, priv->theme);
+  games_card_textures_cache_clear (priv->textures); // FIXMEchpe make this automatic
+
+  if (GTK_WIDGET_REALIZED (widget)) {
     /* Update card size and slot locations for new card theme (might have changed aspect!)*/
     aisleriot_board_setup_geometry (board);
 
-    gtk_widget_queue_draw (GTK_WIDGET (board));
+#warning FIXMEchpe queue a resize if minimum-card-size changed
+    gtk_widget_queue_draw (widget);
   }
 
   g_object_notify (G_OBJECT (board), "theme");
-
-  return retval;
 }
 
-const char *
+GamesCardTheme *
 aisleriot_board_get_card_theme (AisleriotBoard *board)
 {
   AisleriotBoardPrivate *priv = board->priv;
-  const char *theme;
-
-  theme = games_card_theme_get_theme (priv->theme);
 
-  return theme != NULL ? theme : GAMES_CARD_THEME_DEFAULT;
+  return priv->theme;
 }
 
 void

Modified: trunk/aisleriot/board.h
==============================================================================
--- trunk/aisleriot/board.h	(original)
+++ trunk/aisleriot/board.h	Tue Jan  6 18:18:21 2009
@@ -21,6 +21,9 @@
 #define AISLERIOT_BOARD_H
 
 #include <gtk/gtk.h>
+
+#include <libgames-support/games-card-theme.h>
+
 #include "game.h"
 
 G_BEGIN_DECLS
@@ -58,13 +61,12 @@
 
 GType aisleriot_board_get_type (void);
 
-GtkWidget *aisleriot_board_new (AisleriotGame * game,
-                                gboolean scalable_cards);
+GtkWidget *aisleriot_board_new (AisleriotGame *game);
 
-gboolean aisleriot_board_set_card_theme (AisleriotBoard * board,
-                                         const char *card_theme);
+void aisleriot_board_set_card_theme (AisleriotBoard * board,
+                                     GamesCardTheme *theme);
 
-const char *aisleriot_board_get_card_theme (AisleriotBoard * board);
+GamesCardTheme *aisleriot_board_get_card_theme (AisleriotBoard * board);
 
 void aisleriot_board_set_click_to_move (AisleriotBoard * board,
                                         gboolean click_to_move);

Modified: trunk/aisleriot/window.c
==============================================================================
--- trunk/aisleriot/window.c	(original)
+++ trunk/aisleriot/window.c	Tue Jan  6 18:18:21 2009
@@ -95,6 +95,7 @@
 {
   AisleriotGame *game;
   AisleriotBoard *board;
+  GamesCardTheme *theme;
 
 #ifdef HAVE_HILDON
   GtkLabel *game_message_label;
@@ -1439,15 +1440,32 @@
                        AisleriotWindow *window)
 {
   AisleriotWindowPrivate *priv = window->priv;
-  const char *theme;
+  GamesCardThemeInfo *info;
+  GamesCardTheme *theme;
 
   if (!gtk_toggle_action_get_active (action))
     return;
 
-  theme = g_object_get_data (G_OBJECT (action), "card-theme");
-  g_return_if_fail (theme != NULL);
+  info = g_object_get_data (G_OBJECT (action), "card-theme-info");
+  g_return_if_fail (info != NULL);
 
-#ifdef HAVE_GNOME
+  if (priv->theme != NULL &&
+      info == games_card_theme_get_theme (priv->theme))
+    return;
+
+  theme = games_card_theme_get (info);
+  if (!theme)
+    return; // FIXMEchpe re-set the right radio action to active!!
+
+  if (priv->theme) {
+    g_object_unref (priv->theme);
+  }
+  priv->theme = theme;
+
+  aisleriot_board_set_card_theme (priv->board, theme);
+
+  //XXX FIXMEchpe
+#if 0//#ifdef HAVE_GNOME
   /* Compatibility with old settings */
   if (g_str_has_suffix (theme, ".svg")) {
     *g_strrstr (theme, ".svg") = '\0';
@@ -1456,9 +1474,10 @@
   }
 #endif /* HAVE_GNOME */
 
-  if (aisleriot_board_set_card_theme (priv->board, theme)) {
-    games_conf_set_string (NULL, aisleriot_conf_get_key (CONF_THEME), theme);
-  }
+//  if (aisleriot_board_set_card_theme (priv->board, info)) {
+    // XXX FIXMEchpe
+    //games_conf_set_string (NULL, aisleriot_conf_get_key (CONF_THEME), theme);
+//  }
 }
 
 static void
@@ -1467,7 +1486,7 @@
   AisleriotWindowPrivate *priv = window->priv;
   GList *list, *l;
   GSList *radio_group = NULL;
-  const char *card_theme;
+  //GamesCardThemeInfo *card_theme;
   guint i = 0;
 
   /* Clean out the old menu */
@@ -1483,11 +1502,11 @@
   /* See gtk bug #424448 */
   gtk_ui_manager_ensure_update (priv->ui_manager);
 
-  list = games_card_theme_get_themes ();
+  list = games_card_theme_get_all ();
 
   /* No need to install the menu when there's only one theme available anyway */
   if (list == NULL || list->next == NULL) {
-    g_list_foreach (list, (GFunc) g_free, NULL);
+    g_list_foreach (list, (GFunc) games_card_theme_info_unref, NULL);
     g_list_free (list);
     return;
   }
@@ -1498,15 +1517,16 @@
 
   priv->card_themes_merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
 
-  card_theme = aisleriot_board_get_card_theme (priv->board);
+ // FIXMEchpe
+//  card_theme = aisleriot_board_get_card_theme (priv->board);
 
   for (l = list; l != NULL; l = l->next) {
-    const char *theme = (const char *) l->data;
+    GamesCardThemeInfo *info = (GamesCardThemeInfo *) l->data;
     GtkRadioAction *action;
     char actionname[32];
     char *display_name, *tooltip;
 
-    display_name = aisleriot_util_get_display_filename (theme);
+    display_name = g_strdup (games_card_theme_info_get_display_name (info)); //aisleriot_util_get_display_filename (theme);
 
     g_snprintf (actionname, sizeof (actionname), "Theme%d", i);
 #ifdef HAVE_HILDON
@@ -1521,14 +1541,15 @@
     gtk_radio_action_set_group (action, radio_group);
     radio_group = gtk_radio_action_get_group (action);
 
+ // FIXMEchpe
     /* Check if this is the current theme's action. Do this before connecting the callback */
-    if (strcmp (card_theme, theme) == 0) {
-      gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
-    }
-
-    /* We steal the data from the list. A bit hackish, but works fine for now */
-    g_object_set_data_full (G_OBJECT (action), "card-theme",
-                            l->data, (GDestroyNotify) g_free);
+//     if (games_card_theme_info_equal (card_theme, info)) {
+//       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+//     }
+
+    /* We steal the data from the list */
+    g_object_set_data_full (G_OBJECT (action), "card-theme-info",
+                            l->data, (GDestroyNotify) games_card_theme_info_unref);
     l->data = NULL;
 
     g_signal_connect (action, "toggled",
@@ -1545,7 +1566,7 @@
     ++i;
   }
 
-  g_list_foreach (list, (GFunc) g_free, NULL);
+  /* The list elements' data's refcount has been adopted above */
   g_list_free (list);
 }
 
@@ -2263,7 +2284,7 @@
   GtkWidget *main_vbox;
   GtkAccelGroup *accel_group;
   GtkAction *action;
-  char *theme;
+//FIXMEchpe  char *theme;
   guint i;
 #ifdef HAVE_HILDON
   GtkToolItem *tool_item;
@@ -2310,10 +2331,14 @@
 
 #endif /* HAVE_MAEMO */
 
-  priv->board = AISLERIOT_BOARD (aisleriot_board_new (priv->game, priv->scalable_cards));
+  priv->board = AISLERIOT_BOARD (aisleriot_board_new (priv->game));
 
   aisleriot_board_set_pixbuf_drawing (priv->board, priv->use_pixbuf_drawing);
 
+  aisleriot_board_set_card_theme (priv->board, games_card_theme_get_any ());
+
+#if 0
+  // FIXMEchpe
   theme = games_conf_get_string (NULL, aisleriot_conf_get_key (CONF_THEME), NULL);
   if (!theme || !theme[0]) {
     g_free (theme);
@@ -2330,6 +2355,7 @@
 
   aisleriot_board_set_card_theme (priv->board, theme);
   g_free (theme);
+#endif
 
   priv->action_group = gtk_action_group_new ("MenuActions");
   gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE);
@@ -2578,6 +2604,10 @@
     g_assert (priv->stats_dialog == NULL);
   }
 
+  if (priv->theme) {
+    g_object_unref (priv->theme);
+  }
+
   g_signal_handlers_disconnect_matched (priv->game,
                                         G_SIGNAL_MATCH_DATA,
                                         0, 0, NULL, NULL, window);

Modified: trunk/blackjack/src/card.cpp
==============================================================================
--- trunk/blackjack/src/card.cpp	(original)
+++ trunk/blackjack/src/card.cpp	Tue Jan  6 18:18:21 2009
@@ -27,6 +27,7 @@
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <libgames-support/games-card-theme.h>
 #include <libgames-support/games-card-images.h>
+#include <libgames-support/games-card-selector.h>
 #include "card.h"
 #include "chips.h"
 #include "draw.h"
@@ -120,21 +121,25 @@
 
         if (!theme) {
                 char *card_theme;
-                gboolean scalable;
 
-                theme = games_card_theme_svg_new ();
+                card_theme = bj_get_card_style ();
+                theme = games_card_theme_get_by_name (card_theme);
+                if (!theme) {
+                        g_warning ("Failed to load theme %s!", card_theme);
+                        theme = games_card_theme_get_any ();
+                }
+                if (!theme) {
+                        g_warning ("Failed to load any theme !");
+                        exit (1);
+                }
+                g_free (card_theme);
 
-                images = games_card_images_new (theme);
+                images = games_card_images_new ();
+                games_card_images_set_theme (images, theme);
                 g_object_unref (theme);
 
                 games_card_images_set_cache_mode (images, CACHE_PIXMAPS);
                 games_card_images_set_drawable (images, playing_area->window);
-
-                card_theme = bj_get_card_style ();
-                if (!games_card_theme_set_theme (theme, NULL, card_theme)) {
-                        g_warning ("Failed to load theme %s!", card_theme);
-                }
-                g_free (card_theme);
         }
 
         games_card_theme_set_size (theme, width, height, 1.0);
@@ -150,9 +155,41 @@
 void
 bj_card_set_theme (gchar *card_theme)
 {
-        games_card_theme_set_theme (theme, NULL, card_theme);
+        GamesCardTheme *new_theme;
+
+        new_theme = games_card_theme_get_by_name (card_theme);
+        if (!new_theme) {
+          g_warning ("Failed to load theme %s\n", card_theme);
+          return;
+        }
+
+        games_card_images_set_theme (images, theme);
+        
+        theme = new_theme;
+        g_object_unref (theme);
 
         bj_draw_rescale_cards ();
         mask = games_card_images_get_card_mask (images);
         gdk_gc_set_clip_mask (draw_gc, mask);
 }
+
+void
+card_deck_options_changed (GtkWidget *w, GamesCardThemeInfo *info, gpointer data)
+{
+#warning FIXMEchpe
+}
+
+GtkWidget *
+bj_get_card_theme_selector ()
+{
+  GtkWidget *selector;
+
+  if (!theme)
+    return NULL;
+
+  selector = games_card_selector_new (games_card_theme_get_theme (theme));
+  g_signal_connect (selector, "changed",
+                    G_CALLBACK (card_deck_options_changed), NULL);
+
+  return selector;
+}

Modified: trunk/blackjack/src/card.h
==============================================================================
--- trunk/blackjack/src/card.h	(original)
+++ trunk/blackjack/src/card.h	Tue Jan  6 18:18:21 2009
@@ -65,4 +65,6 @@
 void bj_card_set_size (gint width, gint height);
 void bj_card_set_theme (gchar * theme);
 
+GtkWidget *bj_get_card_theme_selector ();
+
 #endif

Modified: trunk/blackjack/src/dialog.cpp
==============================================================================
--- trunk/blackjack/src/dialog.cpp	(original)
+++ trunk/blackjack/src/dialog.cpp	Tue Jan  6 18:18:21 2009
@@ -25,7 +25,7 @@
 #include <stdlib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
-#include <libgames-support/games-card-selector.h>
+#include <libgames-support/games-frame.h>
 #include "blackjack.h"
 #include "menu.h"
 #include "dialog.h"
@@ -139,12 +139,6 @@
 }
 
 void
-card_deck_options_changed (GtkWidget *w, gchar *name, gpointer data)
-{
-        bj_set_card_style (name);
-}
-
-void
 show_probabilities_toggle_cb (GtkToggleButton *w, gpointer data)
 {
         gboolean is_on = gtk_toggle_button_get_active (w);
@@ -419,12 +413,9 @@
                 g_free (current_rule);
                 
                 // Cards Tab
-                deck_edit = games_card_selector_new (TRUE, bj_get_card_style ());
+                deck_edit = bj_get_card_theme_selector ();
                 gtk_box_pack_start (GTK_BOX (top_vbox), deck_edit, FALSE, FALSE, 0);
 
-                g_signal_connect (deck_edit, "changed",
-                                  G_CALLBACK (card_deck_options_changed), NULL);
-                
                 // General signals
                 g_signal_connect (pref_dialog, "response",
                                   G_CALLBACK (pref_dialog_response), NULL);

Modified: trunk/libgames-support/games-card-images.c
==============================================================================
--- trunk/libgames-support/games-card-images.c	(original)
+++ trunk/libgames-support/games-card-images.c	Tue Jan  6 18:18:21 2009
@@ -212,27 +212,42 @@
   games_card_images_clear_cache (images);
   g_free (images->cache);
 
-  g_signal_handlers_disconnect_by_func
-    (images->theme, G_CALLBACK (games_card_images_theme_changed_cb), images);
+  if (images->theme)
+    g_signal_handlers_disconnect_by_func (images->theme,
+                                          G_CALLBACK (games_card_images_theme_changed_cb),
+                                          images);
+
   g_object_unref (images->theme);
 
   G_OBJECT_CLASS (games_card_images_parent_class)->finalize (object);
 }
 
 static void
-games_card_images_set_property (GObject * object,
+games_card_images_set_property (GObject *object,
                                 guint prop_id,
-                                const GValue * value, GParamSpec * pspec)
+                                const GValue *value,
+                                GParamSpec *pspec)
 {
   GamesCardImages *images = GAMES_CARD_IMAGES (object);
 
   switch (prop_id) {
   case PROP_THEME:
-    images->theme = GAMES_CARD_THEME (g_value_dup_object (value));
-    g_assert (images->theme);
+    games_card_images_set_theme (images, g_value_get_object (value));
+    break;
+  }
+}
 
-    g_signal_connect (images->theme, "changed",
-                      G_CALLBACK (games_card_images_theme_changed_cb), images);
+static void
+games_card_images_get_property (GObject *object,
+                                guint prop_id,
+                                GValue *value,
+                                GParamSpec * pspec)
+{
+  GamesCardImages *images = GAMES_CARD_IMAGES (object);
+
+  switch (prop_id) {
+  case PROP_THEME:
+    g_value_set_object (value, games_card_images_get_theme (images));
     break;
   }
 }
@@ -242,6 +257,7 @@
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
 
+  gobject_class->get_property = games_card_images_get_property;
   gobject_class->set_property = games_card_images_set_property;
   gobject_class->finalize = games_card_images_finalize;
 
@@ -250,29 +266,71 @@
      PROP_THEME,
      g_param_spec_object ("theme", NULL, NULL,
                           GAMES_TYPE_CARD_THEME,
-                          G_PARAM_WRITABLE |
+                          G_PARAM_READWRITE |
                           G_PARAM_STATIC_NAME |
                           G_PARAM_STATIC_NICK |
-                          G_PARAM_STATIC_BLURB |
-                          G_PARAM_CONSTRUCT_ONLY));
+                          G_PARAM_STATIC_BLURB));
 }
 
 /* public API */
 
 /**
  * games_card_images_new:
- * @theme_dir: the directory to load the theme data from, or %NULL to use
- * the default directory
- * @theme: the #GamesCardTheme to cache images from
  *
  * Returns: a new #GamesCardImages
  */
 GamesCardImages *
-games_card_images_new (GamesCardTheme * theme)
+games_card_images_new (void)
+{
+  return g_object_new (GAMES_TYPE_CARD_IMAGES, NULL);
+}
+
+/**
+ * games_card_images_set_theme:
+ * @images:
+ * @theme: a #GamesCardTheme
+ *
+ * Sets @theme in @images.
+ */
+void
+games_card_images_set_theme (GamesCardImages *images,
+                             GamesCardTheme *theme)
 {
-  return g_object_new (GAMES_TYPE_CARD_IMAGES,
-                       "theme", theme,
-                       NULL);
+  g_return_if_fail (GAMES_IS_CARD_IMAGES (images));
+  g_return_if_fail (GAMES_IS_CARD_THEME (theme));
+
+  if (images->theme == theme)
+    return;
+
+  if (images->theme) {
+    g_signal_handlers_disconnect_by_func (images->theme,
+                                          G_CALLBACK (games_card_images_theme_changed_cb),
+                                          images);
+    games_card_images_clear_cache (images);
+  }
+
+  images->theme = theme;
+  if (theme) {
+    g_object_ref (images->theme);
+    g_signal_connect (images->theme, "changed",
+                      G_CALLBACK (games_card_images_theme_changed_cb), images);
+  }
+
+  g_object_notify (G_OBJECT (images), "theme");
+}
+
+/**
+ * games_card_images_get_theme:
+ * @images:
+ *
+ * Returns the #GamesCardTheme currently in use in @images.
+ */
+GamesCardTheme *
+games_card_images_get_theme (GamesCardImages *images)
+{
+  g_return_val_if_fail (GAMES_IS_CARD_IMAGES (images), NULL);
+
+  return images->theme;
 }
 
 /**

Modified: trunk/libgames-support/games-card-images.h
==============================================================================
--- trunk/libgames-support/games-card-images.h	(original)
+++ trunk/libgames-support/games-card-images.h	Tue Jan  6 18:18:21 2009
@@ -36,7 +36,7 @@
 #define GAMES_CARD_IMAGES_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_IMAGES, GamesCardImagesClass))
 #define GAMES_IS_CARD_IMAGES(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_IMAGES))
 #define GAMES_IS_CARD_IMAGES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_IMAGES))
-#define GAMES_CARD_IMAGES_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_IMAGES))
+#define GAMES_CARD_IMAGES_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_IMAGES, GamesCardImagesClass))
 
 typedef enum
 {
@@ -63,7 +63,12 @@
 
 GType games_card_images_get_type (void);
 
-GamesCardImages *games_card_images_new (GamesCardTheme * theme);
+GamesCardImages *games_card_images_new (void);
+
+void games_card_images_set_theme (GamesCardImages *images,
+                                  GamesCardTheme *theme);
+
+GamesCardTheme *games_card_images_get_theme (GamesCardImages *images);
 
 void games_card_images_set_cache_mode (GamesCardImages * images,
                                        GamesCardImagesCacheMode mode);

Modified: trunk/libgames-support/games-card-selector.c
==============================================================================
--- trunk/libgames-support/games-card-selector.c	(original)
+++ trunk/libgames-support/games-card-selector.c	Tue Jan  6 18:18:21 2009
@@ -31,10 +31,16 @@
 
 #include "games-card-selector.h"
 
+enum {
+  COL_INFO,
+  COL_NAME,
+  N_COLUMNS
+};
+
 enum
 {
-	CHANGED,
-	LAST_SIGNAL
+  CHANGED,
+  LAST_SIGNAL
 };
 
 static guint signals[LAST_SIGNAL];
@@ -42,76 +48,68 @@
 G_DEFINE_TYPE (GamesCardSelector, games_card_selector, GAMES_TYPE_FRAME);
 
 static void
-signal_propagator (GtkWidget * widget, GamesCardSelector * selector)
+combo_changed_cb (GtkComboBox *combo,
+                  GamesCardSelector *selector)
 {
-  GList *l;
-  const char *name;
+  GtkTreeIter iter;
+  GamesCardThemeInfo *info;
 
-  l = g_list_nth (selector->files,
-                  gtk_combo_box_get_active (GTK_COMBO_BOX (selector->combobox)));
-  if (!l)
+  if (!gtk_combo_box_get_active_iter (combo, &iter))
     return;
 
-  name = l->data;
-
-  g_signal_emit (selector, signals[CHANGED], 0, name);
+  gtk_tree_model_get (GTK_TREE_MODEL (gtk_combo_box_get_model (combo)), &iter,
+                      COL_INFO, &info,
+                      -1);
+  g_assert (info != NULL);
+  
+  g_signal_emit (selector, signals[CHANGED], 0, info);
+  games_card_theme_info_unref (info);
 }
 
 static GtkWidget *
-create_combo_box (GList *filelist,
-                  const gchar * selection,
-                  guint flags)
-{
-  gint itemno;
-  GtkComboBox *widget;
-  gchar *visible, *string;
-  gboolean found = FALSE;
-
-  widget = GTK_COMBO_BOX (gtk_combo_box_new_text ());
-
-  itemno = 0;
-  while (filelist) {
-    gchar *s;
-
-    string = (gchar *) filelist->data;
-    visible = g_strdup (string);
-
-    /* These are a bit hackish, but we don't yet have a good regexp
-     * library in glib. There are probably some ways these could
-     * seriously mangle unicode strings. */
-    if (flags & GAMES_FILE_LIST_REMOVE_EXTENSION) {
-      s = g_strrstr (visible, ".");
-      if (s)
-        *s = '\0';
-    }
-    if (flags & GAMES_FILE_LIST_REPLACE_UNDERSCORES) {
-      s = visible;
-      while (*s) {
-        if (*s == '_')
-          *s = ' ';
-        s++;
-      }
+create_combo_box (GamesCardThemeInfo *selected_info)
+{
+  GtkListStore *store;
+  GtkTreeIter iter, selection_iter;
+  GtkCellRenderer *renderer;
+  gboolean selection_iter_set = FALSE;
+  GList *themes, *l;
+  GtkWidget *combo;
+
+  store = gtk_list_store_new (N_COLUMNS, GAMES_TYPE_CARD_THEME_INFO, G_TYPE_STRING);
+
+  themes = games_card_theme_get_all ();
+  for (l = themes; l != NULL; l = l->next) {
+    GamesCardThemeInfo *info = l->data;
+
+    gtk_list_store_insert_with_values (store, &iter, -1,
+                                       COL_INFO, info,
+                                       COL_NAME, games_card_theme_info_get_display_name (info),
+                                       -1);
+    if (info == selected_info) {
+      selection_iter = iter;
+      selection_iter_set = TRUE;
     }
+  }
 
-    gtk_combo_box_append_text (widget, visible);
-    if (selection && (!strcmp (string, selection))) {
-      gtk_combo_box_set_active (widget, itemno);
-      found = TRUE;
-    }
+  combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+  g_object_unref (store);
 
-    g_free (visible);
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
+                                  "text", COL_NAME,
+                                  NULL);
 
-    itemno++;
-    filelist = g_list_next (filelist);
+  if (selection_iter_set) {
+    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &selection_iter);
   }
-  if (!found)
-    gtk_combo_box_set_active (widget, 0);
 
-  return GTK_WIDGET (widget);
+  return combo;
 }
 
 GtkWidget *
-games_card_selector_new (gboolean scalable, const gchar * current)
+games_card_selector_new (GamesCardThemeInfo *selected_info)
 {
   GamesCardSelector *selector;
 
@@ -119,29 +117,14 @@
 
   games_frame_set_label (GAMES_FRAME (selector), _("Card Style"));
 
-  selector->files = games_card_theme_get_themes ();
-
-  selector->combobox = create_combo_box (selector->files,
-                                         current,
-                                         GAMES_FILE_LIST_REPLACE_UNDERSCORES);
+  selector->combobox = create_combo_box (selected_info);
+  g_signal_connect (selector->combobox, "changed",
+		    G_CALLBACK (combo_changed_cb), selector);
 
   gtk_container_add (GTK_CONTAINER (selector), selector->combobox);
 
-  g_signal_connect (G_OBJECT (selector->combobox), "changed",
-		    G_CALLBACK (signal_propagator), selector);
-
   return GTK_WIDGET (selector);
 }
-static void
-games_card_selector_finalize (GObject *object)
-{
-  GamesCardSelector *selector = GAMES_CARD_SELECTOR (object);
-
-  g_list_foreach (selector->files, (GFunc) g_free, NULL);
-  g_list_free (selector->files);
-
-  G_OBJECT_CLASS (games_card_selector_parent_class)->finalize (object);
-}
 
 static void
 games_card_selector_init (GamesCardSelector * selector)
@@ -149,18 +132,14 @@
 }
 
 static void
-games_card_selector_class_init (GamesCardSelectorClass * class)
+games_card_selector_class_init (GamesCardSelectorClass *klass)
 {
-  GObjectClass *oclass = G_OBJECT_CLASS (class);
-
-  oclass->finalize = games_card_selector_finalize;
-
   signals[CHANGED] =
     g_signal_new ("changed",
-		  GAMES_TYPE_CARD_SELECTOR,
+		  G_OBJECT_CLASS_TYPE (klass),
 		  G_SIGNAL_RUN_FIRST,
 		  G_STRUCT_OFFSET (GamesCardSelectorClass, changed),
 		  NULL, NULL,
-		  g_cclosure_marshal_VOID__STRING,
-		  G_TYPE_NONE, 1, G_TYPE_STRING);
+		  g_cclosure_marshal_VOID__BOXED,
+		  G_TYPE_NONE, 1, GAMES_TYPE_CARD_THEME_INFO);
 }

Modified: trunk/libgames-support/games-card-selector.h
==============================================================================
--- trunk/libgames-support/games-card-selector.h	(original)
+++ trunk/libgames-support/games-card-selector.h	Tue Jan  6 18:18:21 2009
@@ -23,8 +23,9 @@
 #define GAMES_CARD_SELECTOR_H
 
 #include <gtk/gtk.h>
+
 #include "games-frame.h"
-#include "games-files.h"
+#include "games-card-theme.h"
 
 G_BEGIN_DECLS
 
@@ -32,13 +33,13 @@
   GamesFrame parent;
 
   GtkWidget *combobox;
-  GList *files;
 } GamesCardSelector;
 
 typedef struct _GamesCardSelectorClass {
   GamesFrameClass parent;
 
-  void (*changed) (GamesCardSelector * selector, gchar * name);
+  void (*changed) (GamesCardSelector * selector,
+                   GamesCardThemeInfo *info);
 } GamesCardSelectorClass;
 
 #define GAMES_TYPE_CARD_SELECTOR            (games_card_selector_get_type ())
@@ -50,7 +51,7 @@
 
 GType games_card_selector_get_type (void);
 
-GtkWidget *games_card_selector_new (gboolean scalable, const gchar * current);
+GtkWidget *games_card_selector_new (GamesCardThemeInfo *selected_info);
 
 G_END_DECLS
 

Modified: trunk/libgames-support/games-card-theme-fixed.c
==============================================================================
--- trunk/libgames-support/games-card-theme-fixed.c	(original)
+++ trunk/libgames-support/games-card-theme-fixed.c	Tue Jan  6 18:18:21 2009
@@ -40,9 +40,6 @@
 struct _GamesCardThemeFixed {
   GamesCardTheme parent_instance;
 
-  char *theme_dir;
-  char *theme_name;
-
   /* Switched on GamesCardThemeFixed.use_scalable */
   char *themesizepath;
   CardSize *card_sizes;
@@ -51,12 +48,8 @@
   CardSize slot_size;
   CardSize card_size;
 
-  guint use_scalable : 1;
   guint theme_loaded : 1;
   guint size_available : 1;
-
-  guint subrender : 1;
-  guint prescaled : 1;
 };
 
 /* #defining this prints out the time it takes to render the theme */
@@ -70,61 +63,20 @@
 
 G_DEFINE_TYPE (GamesCardThemeFixed, games_card_theme_fixed, GAMES_TYPE_CARD_THEME);
 
-static void
-games_card_theme_fixed_clear_theme_data (GamesCardThemeFixed *theme)
-{
-#ifdef INSTRUMENT_LOADING
-  /* Reset the time */
-  totaltime = 0;
-#endif
-
-  g_free (theme->theme_name);
-  theme->theme_name = NULL;
-
-  g_free (theme->theme_dir);
-  theme->theme_dir = NULL;
-
-  g_free (theme->card_sizes);
-  theme->card_sizes = NULL;
-  theme->n_card_sizes = 0;
-
-  g_free (theme->themesizepath);
-  theme->themesizepath = NULL;
-
-  theme->size_available = FALSE;
-
-  theme->theme_loaded = FALSE;
-
-  theme->card_size.width = theme->card_size.height = theme->slot_size.width =
-    theme->slot_size.width = -1;
-}
-
 static gboolean
-games_card_theme_fixed_load_theme (GamesCardTheme *card_theme,
-                                   const char *theme_dir,
-                                   const char *theme_name,
-                                   GError **error__)
+games_card_theme_fixed_load (GamesCardTheme *card_theme,
+                             GError **error__)
 {
   GamesCardThemeFixed *theme = (GamesCardThemeFixed *) card_theme;
+  GamesCardThemeInfo *theme_info = card_theme->theme_info;
   GKeyFile *key_file;
-  char *filename, *path;
+  char *path;
   GError *error = NULL;
   int *sizes = NULL;
   gsize n_sizes, i;
   gboolean retval = FALSE;
 
-  if (theme->theme_name != NULL &&
-      strcmp (theme_name, theme->theme_name) == 0)
-    return TRUE;
-
-  games_card_theme_fixed_clear_theme_data (theme);
-
-  if (!theme_dir)
-    return FALSE;
-
-  filename = g_strdup_printf ("%s.card-theme", theme_name);
-  path = g_build_filename (theme_dir, filename, NULL);
-  g_free (filename);
+  path = g_build_filename (theme_info->path, theme_info->filename, NULL);
 
   key_file = g_key_file_new ();
   if (!g_key_file_load_from_file (key_file, path, 0, &error)) {
@@ -179,11 +131,6 @@
 
   retval = TRUE;
     
-  theme->theme_name = g_strdup (theme_name);
-  theme->theme_dir = g_strdup (theme_dir);
-
-  theme->theme_loaded = TRUE;
-
 loser:
 
   g_free (sizes);
@@ -191,12 +138,6 @@
   g_key_file_free (key_file);
   g_free (path);
 
-  if (!retval) {
-    games_card_theme_fixed_clear_theme_data (theme);
-  }
-
-  _games_card_theme_emit_changed (card_theme);
-
   return retval;
 }
 
@@ -209,11 +150,9 @@
   char name[64], filename[64];
   char *path;
 
-  if (!theme->theme_loaded || !theme->size_available)
+  if (!theme->size_available)
     return NULL;
 
-  g_return_val_if_fail (!theme->use_scalable, NULL);
-
   games_card_get_name_by_id_snprintf (name, sizeof (name), card_id);
   g_snprintf (filename, sizeof (filename), "%s.png", name);
   path = g_build_filename (theme->themesizepath, filename, NULL);
@@ -231,28 +170,31 @@
 }
 
 static void
-games_card_theme_fixed_finalize (GObject * object)
+games_card_theme_fixed_init (GamesCardThemeFixed *theme)
 {
-  GamesCardThemeFixed *theme = GAMES_CARD_THEME_FIXED (object);
+  theme->card_size.width = theme->card_size.height = -1;
 
-  games_card_theme_fixed_clear_theme_data (theme);
+  theme->card_sizes = NULL;
+  theme->n_card_sizes = 0;
+  theme->themesizepath = NULL;
 
-  G_OBJECT_CLASS (games_card_theme_fixed_parent_class)->finalize (object);
+  theme->size_available = FALSE;
+
+  theme->theme_loaded = FALSE;
+
+  theme->card_size.width = theme->card_size.height = theme->slot_size.width =
+    theme->slot_size.width = -1;
 }
 
 static void
-games_card_theme_fixed_init (GamesCardThemeFixed *theme)
+games_card_theme_fixed_finalize (GObject * object)
 {
-  theme->card_size.width = theme->card_size.height = -1;
-  theme->theme_name = NULL;
-}
+  GamesCardThemeFixed *theme = GAMES_CARD_THEME_FIXED (object);
 
-static const gchar *
-games_card_theme_fixed_get_theme_name (GamesCardTheme *card_theme)
-{
-  GamesCardThemeFixed *theme = (GamesCardThemeFixed *) card_theme;
+  g_free (theme->card_sizes);
+  g_free (theme->themesizepath);
 
-  return theme->theme_name;
+  G_OBJECT_CLASS (games_card_theme_fixed_parent_class)->finalize (object);
 }
 
 static gboolean
@@ -262,11 +204,7 @@
                                       double proportion)
 {
   GamesCardThemeFixed *theme = (GamesCardThemeFixed *) card_theme;
-
-  if (!theme->theme_loaded) {
-    g_warning ("Theme not loaded yet; cannot set size!");
-    return FALSE;
-  }
+  GamesCardThemeInfo *theme_info = card_theme->theme_info;
 
   if ((width == theme->slot_size.width) &&
       (height == theme->slot_size.height))
@@ -313,7 +251,7 @@
 
       g_snprintf (sizestr, sizeof (sizestr), "%d", size.width);
       theme->themesizepath =
-        g_build_filename (theme->theme_dir, theme->theme_name, sizestr, NULL);
+        g_build_filename (theme_info->path, theme_info->theme_name, sizestr, NULL);
 
       theme->size_available = TRUE;
       theme->card_size = size;
@@ -376,23 +314,30 @@
   return pixbuf;
 }
 
-static const char *
-games_card_theme_fixed_get_default_theme_path (GamesCardThemeClass *klass)
+static GamesCardThemeInfo *
+games_card_theme_fixed_class_get_theme_info (GamesCardThemeClass *klass,
+                                             const char *path,
+                                             const char *filename)
 {
-  const char *env;
-
-  if ((env = g_getenv ("GAMES_CARD_THEME_PATH_FIXED")))
-    return env;
-  if ((env = g_getenv ("GAMES_CARD_THEME_PATH")))
-    return env;
+  if (!g_str_has_suffix (filename, ".card-theme"))
+    return NULL;
 
-  return games_runtime_get_directory (GAMES_RUNTIME_PRERENDERED_CARDS_DIRECTORY);
+  return _games_card_theme_info_new (G_OBJECT_CLASS_TYPE (klass),
+                                     path,
+                                     filename, /* FIXME */
+                                     filename, /* FIXME */
+                                     NULL, NULL);
 }
 
-static const char *
-games_card_theme_fixed_get_theme_glob (GamesCardThemeClass *klass)
+static void
+games_card_theme_fixed_class_get_theme_infos (GamesCardThemeClass *klass,
+                                              GList **list)
 {
-  return "*.card-theme";
+  _games_card_theme_class_append_theme_info_foreach_env
+    (klass, "GAMES_CARD_THEME_PATH_FIXED", list);
+
+  _games_card_theme_class_append_theme_info_foreach
+    (klass, games_runtime_get_directory (GAMES_RUNTIME_PRERENDERED_CARDS_DIRECTORY), list);
 }
 
 static void
@@ -403,10 +348,10 @@
 
   gobject_class->finalize = games_card_theme_fixed_finalize;
 
-  theme_class->get_default_theme_path = games_card_theme_fixed_get_default_theme_path;
-  theme_class->get_theme_glob = games_card_theme_fixed_get_theme_glob;
-  theme_class->load_theme = games_card_theme_fixed_load_theme;
-  theme_class->get_theme_name = games_card_theme_fixed_get_theme_name;
+  theme_class->get_theme_info = games_card_theme_fixed_class_get_theme_info;
+  theme_class->get_theme_infos = games_card_theme_fixed_class_get_theme_infos;
+
+  theme_class->load = games_card_theme_fixed_load;
   theme_class->set_card_size = games_card_theme_fixed_set_card_size;
   theme_class->get_card_size = games_card_theme_fixed_get_card_size;
   theme_class->get_card_aspect = games_card_theme_fixed_get_card_aspect;

Modified: trunk/libgames-support/games-card-theme-kde.c
==============================================================================
--- trunk/libgames-support/games-card-theme-kde.c	(original)
+++ trunk/libgames-support/games-card-theme-kde.c	Tue Jan  6 18:18:21 2009
@@ -63,10 +63,8 @@
 G_DEFINE_TYPE (GamesCardThemeKDE, games_card_theme_kde, GAMES_TYPE_CARD_THEME_PREIMAGE);
 
 static gboolean
-games_card_theme_kde_load_theme (GamesCardTheme *card_theme,
-                                 const char *theme_dir,
-                                 const char *theme_name,
-                                 GError **error)
+games_card_theme_kde_load (GamesCardTheme *card_theme,
+                           GError **error)
 {
   GamesCardThemePreimage *preimage_card_theme = (GamesCardThemePreimage *) card_theme;
   gboolean retval = FALSE;
@@ -77,8 +75,7 @@
   t1 = clock ();
 #endif
 
-  if (!GAMES_CARD_THEME_CLASS (games_card_theme_kde_parent_class)->load_theme
-    (card_theme, theme_dir, theme_name, error))
+  if (!GAMES_CARD_THEME_CLASS (games_card_theme_kde_parent_class)->load (card_theme, error))
     goto out;
 
 #ifndef HAVE_RSVG_BBOX
@@ -119,9 +116,6 @@
   RsvgDimensionData dimension;
   RsvgPositionData position;
 
-  if (!preimage_card_theme->theme_loaded)
-    return NULL;
-
   suit = card_id / 13;
   rank = card_id % 13;
 
@@ -168,10 +162,30 @@
 {
 }
 
-static const char *
-games_card_theme_preimage_get_theme_glob (GamesCardThemeClass *klass)
+static GamesCardThemeInfo *
+games_card_theme_kde_class_get_theme_info (GamesCardThemeClass *klass,
+                                           const char *path,
+                                           const char *filename)
+{
+  if (!g_str_has_suffix (filename, ".svgz")) // FIXMEchpe 
+    return NULL;
+
+  return _games_card_theme_info_new (G_OBJECT_CLASS_TYPE (klass),
+                                     path,
+                                     filename, /* FIXME */
+                                     filename, /* FIXME */
+                                     NULL, NULL);
+}
+
+static void
+games_card_theme_kde_class_get_theme_infos (GamesCardThemeClass *klass,
+                                            GList **list)
 {
-  return "*.svgz";
+  _games_card_theme_class_append_theme_info_foreach_env
+    (klass, "GAMES_CARD_THEME_PATH_KDE", list);
+
+  _games_card_theme_class_append_theme_info_foreach
+    (klass, games_runtime_get_directory (GAMES_RUNTIME_SCALABLE_CARDS_DIRECTORY), list);
 }
 
 static void
@@ -179,12 +193,14 @@
 {
   GamesCardThemeClass *theme_class = GAMES_CARD_THEME_CLASS (klass);
 
-  theme_class->get_theme_glob = games_card_theme_preimage_get_theme_glob;
-  theme_class->load_theme = games_card_theme_kde_load_theme;
+  theme_class->get_theme_info = games_card_theme_kde_class_get_theme_info;
+  theme_class->get_theme_infos = games_card_theme_kde_class_get_theme_infos;
+
+  theme_class->load = games_card_theme_kde_load;
   theme_class->get_card_pixbuf = games_card_theme_kde_get_card_pixbuf;
 }
 
-/* public API */
+/* private API */
 
 /**
  * games_card_theme_kde_new:

Modified: trunk/libgames-support/games-card-theme-preimage.c
==============================================================================
--- trunk/libgames-support/games-card-theme-preimage.c	(original)
+++ trunk/libgames-support/games-card-theme-preimage.c	Tue Jan  6 18:18:21 2009
@@ -64,42 +64,15 @@
 #endif
 }
 
-static void
-games_card_theme_preimage_clear_theme_data (GamesCardThemePreimage *theme)
-{
-  _games_card_theme_preimage_clear_sized_theme_data (theme);
-
-  if (theme->cards_preimage != NULL) {
-    g_object_unref (theme->cards_preimage);
-    theme->cards_preimage = NULL;
-  }
-  if (theme->slot_preimage != NULL) {
-    g_object_unref (theme->slot_preimage);
-    theme->slot_preimage = NULL;
-  }
-
-  g_free (theme->theme_name);
-  theme->theme_name = NULL;
-
-  theme->subsize.width = -1;
-  theme->subsize.height = -1;
-
-  theme->theme_loaded = FALSE;
-
-  theme->card_size.width = theme->card_size.height = theme->slot_size.width =
-    theme->slot_size.width = -1;
-}
-
 static gboolean
-games_card_theme_preimage_load_theme (GamesCardTheme *card_theme,
-                                      const char *theme_dir,
-                                      const char *theme_name,
-                                      GError **error)
+games_card_theme_preimage_load (GamesCardTheme *card_theme,
+                                GError **error)
 {
   GamesCardThemePreimage *theme = (GamesCardThemePreimage *) card_theme;
+  GamesCardThemeInfo *theme_info = card_theme->theme_info;
   GamesPreimage *preimage;
   const char *slot_dir;
-  gchar *filename, *path;
+  char *path;
 
 #ifdef INSTRUMENT_LOADING
   clock_t t1, t2;
@@ -107,36 +80,23 @@
   t1 = clock ();
 #endif
 
-  if (theme->theme_name != NULL &&
-      strcmp (theme_name, theme->theme_name) == 0)
-    return TRUE;
-
-  games_card_theme_preimage_clear_theme_data (theme);
-
-  if (!theme_dir)
-    return FALSE;
-
-  // FIXMEchpe wtf?
-  if (theme->cards_preimage != NULL)
-    return TRUE;
-
+  // XXX FIXMEchpe remove this crap
   /* First try and load the given file. */
-  filename = g_strdup_printf ("%s.svg", theme_name);
-  path = g_build_filename (theme_dir, filename, NULL);
+  //filename = g_strdup_printf ("%s.svg", theme_name);
+  path = g_build_filename (theme_info->path, theme_info->filename, NULL);
   preimage = games_preimage_new_from_file (path, NULL);
   g_free (path);
 
   /* Failing that, try and find a similar file (e.g. a suffix change). */
   if (!preimage) {
-    path = games_find_similar_file (filename, theme_dir);
+    // FIXMEchpe remove this crap
+    path = games_find_similar_file (theme_info->filename, theme_info->path);
     if (path) {
       preimage = games_preimage_new_from_file (path, NULL);
       g_free (path);
     }
   }
 
-  g_free (filename);
-
   if (!preimage)
     goto out;
 
@@ -152,6 +112,7 @@
   path = g_build_filename (slot_dir, "slot.svg", NULL);
   theme->slot_preimage = games_preimage_new_from_file (path, NULL);
   g_free (path);
+  // FIXMEchpe fix this
   g_return_val_if_fail (theme->slot_preimage != NULL, FALSE);
 
   if (theme->font_options) {
@@ -169,19 +130,22 @@
            totaltime * 1.0 / CLOCKS_PER_SEC);
 #endif
 
-  if (theme->cards_preimage != NULL) {
-    theme->theme_name = g_strdup (theme_name);
+  return theme->cards_preimage != NULL;
+}
 
-    theme->theme_loaded = TRUE;
+static void
+games_card_theme_preimage_init (GamesCardThemePreimage *theme)
+{
+  theme->cards_preimage = NULL;
+  theme->slot_preimage = NULL;
 
-    _games_card_theme_emit_changed (card_theme);
-    return TRUE;
-  }
+  theme->subsize.width = -1;
+  theme->subsize.height = -1;
 
-  games_card_theme_preimage_clear_theme_data (theme);
-  _games_card_theme_emit_changed (card_theme);
+  theme->theme_loaded = FALSE;
 
-  return FALSE;
+  theme->card_size.width = theme->card_size.height = theme->slot_size.width =
+    theme->slot_size.width = -1;
 }
 
 static void
@@ -189,10 +153,14 @@
 {
   GamesCardThemePreimage *theme = GAMES_CARD_THEME_PREIMAGE (object);
 
-  games_card_theme_preimage_clear_theme_data (theme);
+  _games_card_theme_preimage_clear_sized_theme_data (theme);
 
-  g_free (theme->theme_name);
-  g_free (theme->theme_dir);
+  if (theme->cards_preimage != NULL) {
+    g_object_unref (theme->cards_preimage);
+  }
+  if (theme->slot_preimage != NULL) {
+    g_object_unref (theme->slot_preimage);
+  }
 
   if (theme->font_options) {
     cairo_font_options_destroy (theme->font_options);
@@ -202,15 +170,8 @@
 }
 
 static void
-games_card_theme_preimage_init (GamesCardThemePreimage * theme)
-{
-  theme->card_size.width = theme->card_size.height = -1;
-  theme->theme_name = NULL;
-}
-
-static void
 games_card_theme_preimage_set_font_options (GamesCardTheme *card_theme,
-                                       const cairo_font_options_t *font_options)
+                                            const cairo_font_options_t *font_options)
 {
   GamesCardThemePreimage *theme = (GamesCardThemePreimage *) card_theme;
 
@@ -233,28 +194,15 @@
   _games_card_theme_emit_changed (card_theme);
 }
 
-static const gchar *
-games_card_theme_preimage_get_theme_name (GamesCardTheme *card_theme)
-{
-  GamesCardThemePreimage *theme = (GamesCardThemePreimage *) card_theme;
-
-  return theme->theme_name;
-}
-
 static gboolean
 games_card_theme_preimage_set_card_size (GamesCardTheme *card_theme,
-                                    int width,
-                                    int height,
-                                    double proportion)
+                                         int width,
+                                         int height,
+                                         double proportion)
 {
   GamesCardThemePreimage *theme = (GamesCardThemePreimage *) card_theme;
   double aspect_ratio, twidth, theight;
 
-  if (!theme->theme_loaded) {
-    g_warning ("Theme not loaded yet; cannot set size!");
-    return FALSE;
-  }
-
   if ((width == theme->slot_size.width) &&
       (height == theme->slot_size.height))
     return FALSE;
@@ -301,10 +249,7 @@
 {
   GamesCardThemePreimage *theme = (GamesCardThemePreimage *) card_theme;
   double aspect;
-
-  g_return_val_if_fail (GAMES_IS_CARD_THEME_PREIMAGE (theme), 1.0);
-
-  aspect =
+aspect =
       (((double) games_preimage_get_width (theme->cards_preimage))
        * N_ROWS) /
       (((double) games_preimage_get_height (theme->cards_preimage))
@@ -313,23 +258,31 @@
   return aspect;
 }
 
-static const char *
-games_card_theme_preimage_get_default_theme_path (GamesCardThemeClass *klass)
-{
-  const char *env;
-
-  if ((env = g_getenv ("GAMES_CARD_THEME_PATH_PREIMAGE")))
-    return env;
-  if ((env = g_getenv ("GAMES_CARD_THEME_PATH")))
-    return env;
-
-  return games_runtime_get_directory (GAMES_RUNTIME_SCALABLE_CARDS_DIRECTORY);
+static GamesCardThemeInfo *
+games_card_theme_preimage_class_get_theme_info (GamesCardThemeClass *klass,
+                                                const char *path,
+                                                const char *filename)
+{
+  if (!g_str_has_suffix (filename, ".svg")) // FIXMEchpe .svgz
+    return NULL;
+
+  return _games_card_theme_info_new (G_OBJECT_CLASS_TYPE (klass),
+                                     path,
+                                     filename, /* FIXME */
+                                     filename, /* FIXME */
+                                     NULL, NULL);
 }
 
-static const char *
-games_card_theme_preimage_get_theme_glob (GamesCardThemeClass *klass)
+// FIXMEchpe move this to derived classes
+static void
+games_card_theme_preimage_class_get_theme_infos (GamesCardThemeClass *klass,
+                                                 GList **list)
 {
-  return "*.svg"; // FIXMEchpe: svgz ?
+  _games_card_theme_class_append_theme_info_foreach_env
+    (klass, "GAMES_CARD_THEME_PATH_PREIMAGE", list);
+
+  _games_card_theme_class_append_theme_info_foreach
+    (klass, games_runtime_get_directory (GAMES_RUNTIME_SCALABLE_CARDS_DIRECTORY), list);
 }
 
 static void
@@ -340,15 +293,13 @@
 
   gobject_class->finalize = games_card_theme_preimage_finalize;
 
-  theme_class->get_default_theme_path = games_card_theme_preimage_get_default_theme_path;
-  theme_class->get_theme_glob = games_card_theme_preimage_get_theme_glob;
-  theme_class->load_theme = games_card_theme_preimage_load_theme;
-  theme_class->get_theme_name = games_card_theme_preimage_get_theme_name;
+  theme_class->get_theme_info = games_card_theme_preimage_class_get_theme_info;
+  theme_class->get_theme_infos = games_card_theme_preimage_class_get_theme_infos;
+
+  theme_class->load = games_card_theme_preimage_load;
   theme_class->set_card_size = games_card_theme_preimage_set_card_size;
   theme_class->get_card_size = games_card_theme_preimage_get_card_size;
   theme_class->get_card_aspect = games_card_theme_preimage_get_card_aspect;
   theme_class->get_card_pixbuf = NULL;
   theme_class->set_font_options = games_card_theme_preimage_set_font_options;
 }
-
-/* No public API */

Modified: trunk/libgames-support/games-card-theme-private.h
==============================================================================
--- trunk/libgames-support/games-card-theme-private.h	(original)
+++ trunk/libgames-support/games-card-theme-private.h	Tue Jan  6 18:18:21 2009
@@ -14,29 +14,53 @@
 
    You should have received a copy of the GNU Library General Public License
    along with this library; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-/* Authors:   Callum McKenzie <callum physics otago ac nz> */
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
 
 #define FLOAT_TO_INT_CEIL(f) ((int) (f + 0.5f))
 
+/* GamesCardThemeInfo */
+
+struct _GamesCardThemeInfo {
+  int ref_count;
+  GType type;
+  char *path;
+  char *filename;
+  char *theme_name; /* filename without extension, FIXMEchpe */
+  char *display_name;
+
+  gpointer data;
+  GDestroyNotify destroy_notify;
+};
+
+GamesCardThemeInfo *_games_card_theme_info_new (GType type,
+                                                const char *path,
+                                                const char *filename,
+                                                const char *display_name,
+                                                gpointer data,
+                                                GDestroyNotify destroy_notify);
+
+gboolean _games_card_theme_info_equal (GamesCardThemeInfo *a,
+                                       GamesCardThemeInfo *b);
+
+int _games_card_theme_info_collate (GamesCardThemeInfo *a,
+                                    GamesCardThemeInfo *b);
+
 /* GamesCardTheme */
 
 struct _GamesCardThemeClass {
   GObjectClass parent_class;
 
   /* class vfuncs */
-  const char * (* get_default_theme_path) (GamesCardThemeClass *klass);
-  const char * (* get_theme_glob)         (GamesCardThemeClass *klass);
-  GList *      (* get_themes_list)        (GamesCardThemeClass *klass,
-                                           const char *theme_dir);
+  void                 (* get_theme_infos)  (GamesCardThemeClass *klass,
+                                             GList **list /* inout */);
+  GamesCardThemeInfo * (* get_theme_info)   (GamesCardThemeClass *klass,
+                                             const char *dir,
+                                             const char *filename);
 
   /* vfuncs */
-  gboolean    (* load_theme)        (GamesCardTheme *theme,
-                                     const char *theme_dir,
-                                     const char *theme_name,
+  gboolean    (* load)              (GamesCardTheme *theme,
                                      GError **error);
-  const char* (* get_theme_name)    (GamesCardTheme *theme);
   gboolean    (* set_card_size)     (GamesCardTheme *theme,
                                      int width,
                                      int height,
@@ -57,16 +81,35 @@
 
   GamesCardThemeClass *klass;
 
-  char *theme_name;
+  GamesCardThemeInfo *theme_info;
 };
 
-const char *_games_card_theme_class_get_default_theme_path (GamesCardThemeClass *klass);
-const char *_games_card_theme_class_get_theme_glob (GamesCardThemeClass *klass);
-GList *_games_card_theme_class_get_themes_list (GamesCardThemeClass *klass);
+void _games_card_theme_class_get_theme_infos (GamesCardThemeClass *klass,
+                                              GList **list);
+GamesCardThemeInfo *_games_card_theme_class_get_theme_info (GamesCardThemeClass *klass,
+                                                            const char *dir,
+                                                            const char *filename);
+
+void _games_card_theme_class_append_theme_info_foreach (GamesCardThemeClass *klass,
+                                                        const char *path,
+                                                        GList **list);
+void _games_card_theme_class_append_theme_info_foreach_env (GamesCardThemeClass *klass,
+                                                            const char *env,
+                                                            GList **list);
 
 void _games_card_theme_emit_changed (GamesCardTheme *theme);
 
-/* GamesCardThemePreimage */
+/* GamesCardThemePreimage (abstract) */
+
+#define GAMES_TYPE_CARD_THEME_PREIMAGE            (games_card_theme_preimage_get_type ())
+#define GAMES_CARD_THEME_PREIMAGE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_PREIMAGE, GamesCardThemePreimage))
+#define GAMES_CARD_THEME_PREIMAGE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_PREIMAGE, GamesCardThemePreimageClass))
+#define GAMES_IS_CARD_THEME_PREIMAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_PREIMAGE))
+#define GAMES_IS_CARD_THEME_PREIMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_PREIMAGE))
+#define GAMES_CARD_THEME_PREIMAGE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_PREIMAGE, GamesCardThemePreimageClass))
+
+typedef struct _GamesCardThemePreimageClass GamesCardThemePreimageClass;
+typedef struct _GamesCardThemePreimage      GamesCardThemePreimage;
 
 #ifndef HAVE_HILDON
 
@@ -96,6 +139,74 @@
   cairo_font_options_t *font_options;
 };
 
+#endif /* !HAVE_HILDON */
+
+GType games_card_theme_preimage_get_type (void);
+
 void _games_card_theme_preimage_clear_sized_theme_data (GamesCardThemePreimage *theme);
 
-#endif /* !HAVE_HILDON */
+/* GamesCardThemeSVG */
+
+#define GAMES_TYPE_CARD_THEME_SVG            (games_card_theme_svg_get_type ())
+#define GAMES_CARD_THEME_SVG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_SVG, GamesCardThemeSVG))
+#define GAMES_CARD_THEME_SVG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_SVG, GamesCardThemeSVGClass))
+#define GAMES_IS_CARD_THEME_SVG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_SVG))
+#define GAMES_IS_CARD_THEME_SVG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_SVG))
+#define GAMES_CARD_THEME_SVG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_SVG, GamesCardThemeSVGClass))
+
+typedef struct _GamesCardThemeSVGClass GamesCardThemeSVGClass;
+typedef struct _GamesCardThemeSVG      GamesCardThemeSVG;
+
+GType games_card_theme_svg_get_type (void);
+
+GamesCardTheme* games_card_theme_svg_new (void);
+
+/* GamesCardThemeSliced */
+
+#define GAMES_TYPE_CARD_THEME_SLICED            (games_card_theme_sliced_get_type ())
+#define GAMES_CARD_THEME_SLICED(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_SLICED, GamesCardThemeSliced))
+#define GAMES_CARD_THEME_SLICED_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_SLICED, GamesCardThemeSlicedClass))
+#define GAMES_IS_CARD_THEME_SLICED(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_SLICED))
+#define GAMES_IS_CARD_THEME_SLICED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_SLICED))
+#define GAMES_CARD_THEME_SLICED_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_SLICED, GamesCardThemeSlicedClass))
+
+typedef struct _GamesCardThemeSlicedClass GamesCardThemeSlicedClass;
+typedef struct _GamesCardThemeSliced      GamesCardThemeSliced;
+
+GType games_card_theme_sliced_get_type (void);
+
+GamesCardTheme* games_card_theme_sliced_new (void);
+
+/* GamesCardThemeKDE */
+
+#define GAMES_TYPE_CARD_THEME_KDE            (games_card_theme_kde_get_type ())
+#define GAMES_CARD_THEME_KDE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_KDE, GamesCardThemeKDE))
+#define GAMES_CARD_THEME_KDE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_KDE, GamesCardThemeKDEClass))
+#define GAMES_IS_CARD_THEME_KDE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_KDE))
+#define GAMES_IS_CARD_THEME_KDE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_KDE))
+#define GAMES_CARD_THEME_KDE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_KDE, GamesCardThemeKDEClass))
+
+typedef struct _GamesCardThemeKDEClass GamesCardThemeKDEClass;
+typedef struct _GamesCardThemeKDE      GamesCardThemeKDE;
+
+GType games_card_theme_kde_get_type (void);
+
+GamesCardTheme* games_card_theme_kde_new (void);
+
+/* GamesCardThemeFixed */
+
+#define GAMES_TYPE_CARD_THEME_FIXED            (games_card_theme_fixed_get_type ())
+#define GAMES_CARD_THEME_FIXED(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_FIXED, GamesCardThemeFixed))
+#define GAMES_CARD_THEME_FIXED_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_FIXED, GamesCardThemeFixedClass))
+#define GAMES_IS_CARD_THEME_FIXED(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_FIXED))
+#define GAMES_IS_CARD_THEME_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_FIXED))
+#define GAMES_CARD_THEME_FIXED_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_FIXED, GamesCardThemeFixedClass))
+
+typedef struct _GamesCardThemeFixedClass GamesCardThemeFixedClass;
+typedef struct _GamesCardThemeFixed      GamesCardThemeFixed;
+
+GType games_card_theme_fixed_get_type (void);
+
+GamesCardTheme* games_card_theme_fixed_new (void);
+
+/* Utilities */

Modified: trunk/libgames-support/games-card-theme-sliced.c
==============================================================================
--- trunk/libgames-support/games-card-theme-sliced.c	(original)
+++ trunk/libgames-support/games-card-theme-sliced.c	Tue Jan  6 18:18:21 2009
@@ -78,10 +78,8 @@
 }
 
 static gboolean
-games_card_theme_sliced_load_theme (GamesCardTheme *card_theme,
-                                    const char *theme_dir,
-                                    const char *theme_name,
-                                    GError **error)
+games_card_theme_sliced_load (GamesCardTheme *card_theme,
+                              GError **error)
 {
   GamesCardThemePreimage *preimage_card_theme = (GamesCardThemePreimage *) card_theme;
   GamesCardThemeSliced *theme = (GamesCardThemeSliced *) card_theme;
@@ -93,8 +91,7 @@
   t1 = clock ();
 #endif
 
-  if (!GAMES_CARD_THEME_CLASS (games_card_theme_sliced_parent_class)->load_theme
-    (card_theme, theme_dir, theme_name, error))
+  if (!GAMES_CARD_THEME_CLASS (games_card_theme_sliced_parent_class)->load (card_theme, error))
     goto out;
 
   /* If we don't have a scalable format, build a scaled pixbuf that we'll cut up later */
@@ -129,7 +126,7 @@
   t1 = clock ();
 #endif
 
-  g_return_val_if_fail (preimage_card_theme->cards_preimage != NULL, FALSE);
+  // FIXMEchpe this doesn't look right
   g_return_val_if_fail (theme->prescaled
                         || theme->source != NULL, FALSE);
 
@@ -214,13 +211,13 @@
   GamesCardThemeClass *theme_class = GAMES_CARD_THEME_CLASS (klass);
   GamesCardThemePreimageClass *preimage_theme_class = GAMES_CARD_THEME_PREIMAGE_CLASS (klass);
 
-  theme_class->load_theme = games_card_theme_sliced_load_theme;
+  theme_class->load = games_card_theme_sliced_load;
   theme_class->get_card_pixbuf = games_card_theme_sliced_get_card_pixbuf;
 
   preimage_theme_class->clear_sized_theme_data = games_card_theme_sliced_clear_sized_theme_data;
 }
 
-/* public API */
+/* private API */
 
 /**
  * games_card_theme_sliced_new:

Modified: trunk/libgames-support/games-card-theme-svg.c
==============================================================================
--- trunk/libgames-support/games-card-theme-svg.c	(original)
+++ trunk/libgames-support/games-card-theme-svg.c	Tue Jan  6 18:18:21 2009
@@ -58,10 +58,8 @@
 G_DEFINE_TYPE (GamesCardThemeSVG, games_card_theme_svg, GAMES_TYPE_CARD_THEME_PREIMAGE);
 
 static gboolean
-games_card_theme_svg_load_theme (GamesCardTheme *card_theme,
-                                 const char *theme_dir,
-                                 const char *theme_name,
-                                 GError **error)
+games_card_theme_svg_load (GamesCardTheme *card_theme,
+                           GError **error)
 {
   GamesCardThemePreimage *preimage_card_theme = (GamesCardThemePreimage *) card_theme;
   gboolean retval = FALSE;
@@ -72,8 +70,7 @@
   t1 = clock ();
 #endif
 
-  if (!GAMES_CARD_THEME_CLASS (games_card_theme_svg_parent_class)->load_theme
-    (card_theme, theme_dir, theme_name, error))
+  if (!GAMES_CARD_THEME_CLASS (games_card_theme_svg_parent_class)->load (card_theme, error))
     goto out;
 
   if (!games_preimage_is_scalable (preimage_card_theme->cards_preimage))
@@ -108,9 +105,6 @@
   double zoomx, zoomy;
   char node[64];
 
-  if (!preimage_card_theme->theme_loaded)
-    return NULL;
-
   suit = card_id / 13;
   rank = card_id % 13;
 
@@ -156,11 +150,11 @@
 {
   GamesCardThemeClass *theme_class = GAMES_CARD_THEME_CLASS (klass);
 
-  theme_class->load_theme = games_card_theme_svg_load_theme;
+  theme_class->load = games_card_theme_svg_load;
   theme_class->get_card_pixbuf = games_card_theme_svg_get_card_pixbuf;
 }
 
-/* public API */
+/* private API */
 
 /**
  * games_card_theme_svg_new:

Modified: trunk/libgames-support/games-card-theme.c
==============================================================================
--- trunk/libgames-support/games-card-theme.c	(original)
+++ trunk/libgames-support/games-card-theme.c	Tue Jan  6 18:18:21 2009
@@ -34,12 +34,19 @@
 #include "games-card-theme-private.h"
 
 enum {
+  PROP_0,
+  PROP_THEME_INFO
+};
+
+enum {
   CHANGED,
   LAST_SIGNAL
 };
 
 static guint signals[LAST_SIGNAL];
 
+static GList *theme_infos;
+
 /* #defining this prints out the time it takes to render the theme */
 /* #define INSTRUMENT_LOADING */
 
@@ -48,6 +55,7 @@
 static long totaltime = 0;
 #endif
 
+#if 0
 static GType
 get_default_theme_type (void)
 {
@@ -81,19 +89,47 @@
 
   return type;
 }
+#endif
 
-static gboolean
-games_card_theme_load_theme (GamesCardTheme *theme,
-                             const char *theme_dir,
-                             const char *theme_name)
+static void
+_games_card_theme_ensure_theme_infos (void)
 {
-  return theme->klass->load_theme (theme, theme_dir, theme_name, NULL);
+  if (theme_infos)
+    return;
+
+  /* FIXME: take env vars and prefs into account on ordering here */
+  GType types[] = {
+#ifdef HAVE_RSVG
+    GAMES_TYPE_CARD_THEME_SVG,
+    GAMES_TYPE_CARD_THEME_KDE,
+#endif
+#ifndef HAVE_HILDON
+    GAMES_TYPE_CARD_THEME_SLICED,
+#endif
+    GAMES_TYPE_CARD_THEME_FIXED
+  };
+  guint i;
+
+  theme_infos = NULL;
+
+  for (i = 0; i < G_N_ELEMENTS (types); ++i) {
+    GamesCardThemeClass *klass;
+
+    klass = g_type_class_ref (types[i]);
+    if (!klass)
+      continue;
+
+    klass->get_theme_infos (klass, &theme_infos);
+    g_type_class_unref (klass);
+  }
+
+  theme_infos = g_list_reverse (theme_infos);
 }
 
+#if 0
 static gboolean
 games_card_theme_load_theme_with_fallback (GamesCardTheme *theme,
-                                           const char *theme_dir,
-                                           const char *theme_name)
+                                           GamesCardThemeInfo *info)
 {
   const char *env;
 
@@ -126,7 +162,10 @@
   g_warning ("Failed to load fallback theme!");
 
   return FALSE;
+  //FIXMEchpe how to design fallback now...
+//  return games_card_theme_load_theme (theme, info);
 }
+#endif
 
 /* Class implementation */
 
@@ -150,6 +189,8 @@
 
   theme = GAMES_CARD_THEME (object);
 
+  g_assert (theme->theme_info != NULL);
+
   /* NOTE! We have to do this here, since it returns the wrong class
    * (GamesCardThemeClass) when called in games_card_theme_init() !
    */
@@ -158,6 +199,40 @@
   return object;
 }
 
+static void
+games_card_theme_finalize (GObject *object)
+{
+  GamesCardTheme *theme = GAMES_CARD_THEME (object);
+
+  games_card_theme_info_unref (theme->theme_info);
+
+  G_OBJECT_CLASS (games_card_theme_parent_class)->finalize (object);
+}
+
+static void
+games_card_theme_set_property (GObject * object,
+                               guint prop_id,
+                               const GValue * value, GParamSpec * pspec)
+{
+  GamesCardTheme *theme = GAMES_CARD_THEME (object);
+
+  switch (prop_id) {
+    case PROP_THEME_INFO:
+      theme->theme_info = g_value_dup_boxed (value);
+      break;
+  }
+}
+
+static GamesCardThemeInfo *
+games_card_theme_class_get_theme_info (GamesCardThemeClass *klass,
+                                       const char *dir,
+                                       const char *filename)
+{
+  return NULL;
+}
+
+#if 0
+
 static GList *
 games_card_theme_get_themes_list (GamesCardThemeClass *klass,
                                   const char *theme_dir)
@@ -165,6 +240,7 @@
   GamesFileList *files;
   GList *l, *list;
   const char *glob;
+  GamesCardThemeInfo * (* get_theme_info) (GamesCardThemeClass *, const char *) = klass->get_theme_info;
 
   glob = _games_card_theme_class_get_theme_glob (klass);
 
@@ -193,15 +269,29 @@
 
   return list;
 }
+#endif
 
 static void
 games_card_theme_class_init (GamesCardThemeClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
+  gobject_class->set_property = games_card_theme_set_property;
   gobject_class->constructor = games_card_theme_constructor;
+  gobject_class->finalize = games_card_theme_finalize;
+
+  klass->get_theme_info = games_card_theme_class_get_theme_info;
 
-  klass->get_themes_list = games_card_theme_get_themes_list;
+  g_object_class_install_property
+    (gobject_class,
+     PROP_THEME_INFO,
+     g_param_spec_boxed ("theme-info", NULL, NULL,
+                         GAMES_TYPE_CARD_THEME_INFO,
+                         G_PARAM_WRITABLE |
+                         G_PARAM_STATIC_NAME |
+                         G_PARAM_STATIC_NICK |
+                         G_PARAM_STATIC_BLURB |
+                         G_PARAM_CONSTRUCT_ONLY));
 
   /**
    * GamesCardTheme:changed:
@@ -230,52 +320,64 @@
   g_signal_emit (theme, signals[CHANGED], 0);
 }
 
-/**
- * games_card_theme_class_get_default_theme_path:
- * @klass:
- *
- * Returns: the default theme path for @klass. The string is owned by
- * @klass and must not be modified or freed.
- */
-const char *
-_games_card_theme_class_get_default_theme_path (GamesCardThemeClass *klass)
+GamesCardThemeInfo *
+_games_card_theme_class_get_theme_info (GamesCardThemeClass *klass,
+                                        const char *dir,
+                                        const char *filename)
 {
-  if (klass->get_default_theme_path)
-    return klass->get_default_theme_path (klass);
-
-  return NULL;
+  return klass->get_theme_info (klass, dir, filename);
 }
 
-/**
- * games_card_theme_class_get_theme_glob:
- * @klass:
- *
- * Returns: the default theme path for @klass. The string is owned by
- * @klass and must not be modified or freed.
- */
-const char *
-_games_card_theme_class_get_theme_glob (GamesCardThemeClass *klass)
+void
+_games_card_theme_class_append_theme_info_foreach (GamesCardThemeClass *klass,
+                                                   const char *path,
+                                                   GList **list)
 {
-  if (klass->get_theme_glob)
-    return klass->get_theme_glob (klass);
+  GDir *iter;
+  const char *filename;
 
-  return NULL;
+  iter = g_dir_open (path, 0, NULL);
+  if (!iter)
+    return;
+
+  while ((filename = g_dir_read_name (iter)) != NULL) {
+    GamesCardThemeInfo *info;
+
+    info = _games_card_theme_class_get_theme_info (klass, path, filename);
+    if (info)
+      *list = g_list_prepend (*list, info);
+  }
+      
+  g_dir_close (iter);
 }
 
-/**
- * games_card_theme_class_get_themes_list:
- * @klass:
- *
- * Returns: a newly allocated list of newly allocated strings of
- * containing the names of the themes found for @klass.
- */
-GList *
-_games_card_theme_class_get_themes_list (GamesCardThemeClass *klass)
-{
-  if (klass->get_themes_list)
-    return klass->get_themes_list (klass, NULL);
+void
+_games_card_theme_class_append_theme_info_foreach_env (GamesCardThemeClass *klass,
+                                                       const char *env,
+                                                       GList **list)
+{
+  const char *value;
+  char **paths;
+  guint i;
 
-  return NULL;
+  value = g_getenv (env);
+  if (!value || !value[0])
+    return;
+
+  paths = g_strsplit (value, ":", -1);
+  if (!paths)
+    return;
+
+  for (i = 0; paths[i]; ++i) {
+    const char *path = paths[i];
+
+    if (!paths[0])
+      continue;
+
+    _games_card_theme_class_append_theme_info_foreach (klass, path, list);
+  }
+
+  g_strfreev (paths);
 }
 
 /* public API */
@@ -303,44 +405,19 @@
 
 #endif /* GTK 2.10.0 */
 
-/**
- * games_card_theme_set_theme:
- * @theme:
- * @theme_dir: the theme directory, or %NULL to use the default
- * @theme_name: the name of the theme to load
- *
- * Loads the card theme @theme_name. If the card theme cannot be loaded,
- * it falls back to the default card theme, if present.
- * After changing the theme, the card size will be undefined; you need
- * to call games_card_theme_set_size() to set it before getting a
- * card from @theme again.
- * 
- * Returns: %TRUE iff loading the new card theme succeeded
- */
-gboolean
-games_card_theme_set_theme (GamesCardTheme *theme,
-                            const char *theme_dir,
-                            const char *theme_name)
-{
-  g_return_val_if_fail (GAMES_IS_CARD_THEME (theme), FALSE);
-  g_return_val_if_fail (theme_name != NULL && theme_name[0] != '\0', FALSE);
-
-  return games_card_theme_load_theme_with_fallback (theme, theme_dir, theme_name);
-}
 
 /**
  * games_card_theme_get_theme:
  * @theme:
  *
- * Returns: the name of the currently loaded card theme, or %NULL if no theme
- * is loaded
+ * Returns: the #GamesCardThemeInfo corresponding to @theme.
  */
-const char *
+GamesCardThemeInfo *
 games_card_theme_get_theme (GamesCardTheme *theme)
 {
   g_return_val_if_fail (GAMES_IS_CARD_THEME (theme), NULL);
 
-  return theme->klass->get_theme_name (theme);
+  return theme->theme_info;
 }
 
 /**
@@ -433,31 +510,287 @@
 }
 
 /**
- * games_card_theme_new:
+ * games_card_theme_get:
+ * @info: a #GamesCardThemeInfo
+ *
+ * Returns: a new #GamesCardTheme for @info, or %NULL if there was an
+ *  error while loading the theme.
+ */
+GamesCardTheme *
+games_card_theme_get (GamesCardThemeInfo *info)
+{
+  GamesCardTheme *theme;
+  GError *error = NULL;
+
+  g_return_val_if_fail (info != NULL, NULL);
+
+  if (info->type == G_TYPE_INVALID)
+    return NULL;
+
+  theme = g_object_new (info->type, "theme-info", info, NULL);
+  if (!theme->klass->load (theme, &error)) {
+    g_clear_error (&error);
+    g_object_unref (theme);
+    return NULL;
+  }
+
+  return theme;
+}
+
+/**
+ * games_card_theme_get_by_name:
+ * @theme_name: a theme name
  *
- * Returns: a new #GamesCardTheme
+ * This function exists only for backward compatibility with
+ * older aisleriot versions' preferences.
+ * 
+ * Returns: a new #GamesCardTheme for @name, or %NULL if there was an
+ *  error while loading the theme.
  */
 GamesCardTheme *
-games_card_theme_new (void)
+games_card_theme_get_by_name (const char *theme_name)
 {
+  GList *l;
+
+  //XXX FIXMEchpe .svg / .png suffix stripping
+  g_return_val_if_fail (theme_name != NULL, NULL);
+
+  _games_card_theme_ensure_theme_infos ();
+
+  for (l = theme_infos; l != NULL; l = l->next) {
+    GamesCardThemeInfo *info = (GamesCardThemeInfo *) l->data;
 
-  return g_object_new (get_default_theme_type (), NULL);
+    // FIXMEchpe
+    if (g_str_has_prefix (theme_name, info->filename))
+      return games_card_theme_get (info);
+  }
+
+  return NULL;
 }
 
 /**
- * games_card_theme_get_themes:
+ * games_card_theme_get_any:
  *
- * Returns: 
+ * FIXMEchpe
+ * Loads the card theme @theme_name. If the card theme cannot be loaded,
+ * it falls back to the default card theme, if present.
+ * After changing the theme, the card size will be undefined; you need
+ * to call games_card_theme_set_size() to set it before getting a
+ * card from @theme again.
+ * 
+ * Returns:
+ */
+GamesCardTheme *
+games_card_theme_get_any (void)
+{
+  _games_card_theme_ensure_theme_infos ();
+
+  if (!theme_infos)
+    return NULL;
+
+  // FIXMEchpe obviously
+  return games_card_theme_get ((GamesCardThemeInfo *) theme_infos->data);
+  return games_card_theme_get_by_name (GAMES_CARD_THEME_DEFAULT);
+  // FIXMEchpe put the fallback in here
+  return NULL;
+}
+
+/**
+ * games_card_theme_get_all:
+ *
+ * Returns:
  */
 GList *
-games_card_theme_get_themes (void)
+games_card_theme_get_all (void)
 {
-  GamesCardThemeClass *klass;
   GList *list;
 
-  klass = g_type_class_ref (get_default_theme_type ());
-  list = games_card_theme_get_themes_list (klass, NULL);
-  g_type_class_unref (klass);
+  _games_card_theme_ensure_theme_infos ();
+
+  list = g_list_copy (theme_infos);
+  g_list_foreach (list, (GFunc) games_card_theme_info_ref, NULL);
 
   return list;
+  // FIXMEchpe
+//  return g_list_sort (list, (GCompareFunc) _games_card_theme_info_collate, NULL);
+}
+
+/* GamesCardThemeInfo impl */
+
+/* private API */
+
+/**
+ * _games_card_theme_info_new:
+ * @type:
+ * @path:
+ * @name:
+ * @diplay_name:
+ *
+ * Returns: a new #GamesCardThemeInfo with refcount 1
+ */
+GamesCardThemeInfo *
+_games_card_theme_info_new (GType type,
+                            const char *path,
+                            const char *filename,
+                            const char *display_name,
+                            gpointer data /* adopted */,
+                            GDestroyNotify destroy_notify)
+{
+  GamesCardThemeInfo *info;
+
+#if GLIB_CHECK_VERSION (2, 10, 0)
+  info = g_slice_new (GamesCardThemeInfo);
+#else
+  info = g_new (GamesCardThemeInfo, 1);
+#endif
+
+  info->ref_count = 1;
+  info->type = type;
+  info->path = g_strdup (path);
+  info->filename = g_strdup (filename);
+  { char *p; info->theme_name = g_strdup (filename); p = strrchr (info->theme_name, '.'); if (p) *p = '\0'; }
+  info->display_name = g_strdup (display_name);
+  info->data = data;
+  info->destroy_notify = destroy_notify;
+
+  return info;
+}
+
+/**
+ * _games_card_theme_info_equal:
+ * @a:
+ * @b:
+ *
+ * Compares @a and @b.
+ *
+ * Returns: %TRUE iff @a and @b refer to the same card theme
+ */
+gboolean
+_games_card_theme_info_equal (GamesCardThemeInfo *a,
+                              GamesCardThemeInfo *b)
+{
+  g_return_val_if_fail (a != NULL && b != NULL, FALSE);
+
+  return _games_card_theme_info_collate (a, b) == 0;
+}
+
+/**
+ * _games_card_theme_info_collate:
+ * @a:
+ * @b:
+ *
+ * Compares @a and @b.
+ *
+ * Returns: %-1 if @a comes before @b, %1 if @b comes before @a, or
+ * %0 if @a and @b are equal.
+ */
+int
+_games_card_theme_info_collate (GamesCardThemeInfo *a,
+                                GamesCardThemeInfo *b)
+{
+  int val;
+
+  g_return_val_if_fail (a != NULL && b != NULL, 0);
+
+  if (a->type != b->type)
+    return a->type - b->type;
+
+  val = g_utf8_collate (a->display_name, b->display_name);
+  if (val != 0)
+    return val;
+
+  val = strcmp (a->display_name, b->display_name);
+  if (val != 0)
+    return val;
+
+  val = strcmp (a->path, b->path);
+  if (val != 0)
+    return val;
+
+  val = strcmp (a->filename, b->filename);
+  if (val != 0)
+    return val;
+
+  return 0;
+}
+
+/* public API */
+
+#if defined(G_DEFINE_BOXED_TYPE)
+G_DEFINE_BOXED_TYPE (GamesCardThemeInfo, games_card_theme_info,
+                     games_card_theme_info_ref,
+                     games_card_theme_info_unref);
+#else
+GType
+games_card_theme_info_get_type (void)
+{
+  static GType type = 0;
+
+  if (G_UNLIKELY (type == 0)) {
+    type = g_boxed_type_register_static ("GamesCardThemeInfo",
+                                         (GBoxedCopyFunc) games_card_theme_info_ref,
+                                         (GBoxedFreeFunc) games_card_theme_info_unref);
+  }
+
+  return type;
+}
+#endif /* defined(G_DEFINE_BOXED_TYPE) */
+
+/**
+ * games_card_theme_info_ref:
+ * @info:
+ *
+ * Refs @info.
+ *
+ * Returns: @info
+ */
+GamesCardThemeInfo *
+games_card_theme_info_ref (GamesCardThemeInfo *info)
+{
+  g_return_val_if_fail (info != NULL, NULL);
+
+  info->ref_count++;
+  return info;
+}
+
+/**
+ * games_card_theme_info_unref:
+ * @info:
+ *
+ * Unrefs @info. If the refcount reaches %0, @info is freed.
+ */
+void
+games_card_theme_info_unref (GamesCardThemeInfo *info)
+{
+  g_return_if_fail (info != NULL);
+
+  if (--info->ref_count > 0)
+    return;
+
+  g_free (info->path);
+  g_free (info->filename);
+  g_free (info->display_name);
+
+  if (info->data && info->destroy_notify)
+    info->destroy_notify (info->data);
+
+#if GLIB_CHECK_VERSION (2, 10, 0)
+  g_slice_free (GamesCardThemeInfo, info);
+#else
+  g_free (info);
+#endif
+}
+
+/**
+ * games_card_theme_info_unref:
+ * @info:
+ *
+ * Unrefs @info. If the refcount reaches %0, frees @info.
+ */
+const char *
+games_card_theme_info_get_display_name (GamesCardThemeInfo *info)
+{
+  g_return_val_if_fail (info != NULL, NULL);
+
+  return info->display_name;
 }

Modified: trunk/libgames-support/games-card-theme.h
==============================================================================
--- trunk/libgames-support/games-card-theme.h	(original)
+++ trunk/libgames-support/games-card-theme.h	Tue Jan  6 18:18:21 2009
@@ -34,6 +34,20 @@
   GAMES_CARD_THEME_ERROR_GENERIC = 0
 } GamesCardThemeError;
 
+/* GamesCardThemeInfo (boxed) */
+
+#define GAMES_TYPE_CARD_THEME_INFO (games_card_theme_info_get_type ())
+
+typedef struct _GamesCardThemeInfo GamesCardThemeInfo;
+
+GType games_card_theme_info_get_type (void);
+
+GamesCardThemeInfo *games_card_theme_info_ref (GamesCardThemeInfo *info);
+
+void games_card_theme_info_unref (GamesCardThemeInfo *info);
+
+const char *games_card_theme_info_get_display_name (GamesCardThemeInfo *info);
+
 /* GamesCardTheme (abstract) */
 
 #define GAMES_TYPE_CARD_THEME            (games_card_theme_get_type ())
@@ -59,10 +73,9 @@
 #endif
 
 gboolean games_card_theme_set_theme (GamesCardTheme *theme,
-                                     const char *theme_dir,
-                                     const char *theme_name);
+                                     GamesCardThemeInfo *info);
 
-const gchar *games_card_theme_get_theme (GamesCardTheme * theme);
+GamesCardThemeInfo *games_card_theme_get_theme (GamesCardTheme * theme);
 
 gboolean games_card_theme_set_size (GamesCardTheme * theme,
                                     int width,
@@ -76,90 +89,16 @@
 GdkPixbuf *games_card_theme_get_card_pixbuf (GamesCardTheme * theme,
                                              int cardid);
 
-/* GamesCardThemePreimage (abstract) */
-
-#define GAMES_TYPE_CARD_THEME_PREIMAGE            (games_card_theme_preimage_get_type ())
-#define GAMES_CARD_THEME_PREIMAGE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_PREIMAGE, GamesCardThemePreimage))
-#define GAMES_CARD_THEME_PREIMAGE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_PREIMAGE, GamesCardThemePreimageClass))
-#define GAMES_IS_CARD_THEME_PREIMAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_PREIMAGE))
-#define GAMES_IS_CARD_THEME_PREIMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_PREIMAGE))
-#define GAMES_CARD_THEME_PREIMAGE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_PREIMAGE, GamesCardThemePreimageClass))
-
-typedef struct _GamesCardThemePreimageClass GamesCardThemePreimageClass;
-typedef struct _GamesCardThemePreimage      GamesCardThemePreimage;
-
-GType games_card_theme_preimage_get_type (void);
-
-/* GamesCardThemeSVG */
-
-#define GAMES_TYPE_CARD_THEME_SVG            (games_card_theme_svg_get_type ())
-#define GAMES_CARD_THEME_SVG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_SVG, GamesCardThemeSVG))
-#define GAMES_CARD_THEME_SVG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_SVG, GamesCardThemeSVGClass))
-#define GAMES_IS_CARD_THEME_SVG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_SVG))
-#define GAMES_IS_CARD_THEME_SVG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_SVG))
-#define GAMES_CARD_THEME_SVG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_SVG, GamesCardThemeSVGClass))
-
-typedef struct _GamesCardThemeSVGClass GamesCardThemeSVGClass;
-typedef struct _GamesCardThemeSVG      GamesCardThemeSVG;
-
-GType games_card_theme_svg_get_type (void);
-
-GamesCardTheme* games_card_theme_svg_new (void);
-
-/* GamesCardThemeSliced */
-
-#define GAMES_TYPE_CARD_THEME_SLICED            (games_card_theme_sliced_get_type ())
-#define GAMES_CARD_THEME_SLICED(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_SLICED, GamesCardThemeSliced))
-#define GAMES_CARD_THEME_SLICED_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_SLICED, GamesCardThemeSlicedClass))
-#define GAMES_IS_CARD_THEME_SLICED(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_SLICED))
-#define GAMES_IS_CARD_THEME_SLICED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_SLICED))
-#define GAMES_CARD_THEME_SLICED_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_SLICED, GamesCardThemeSlicedClass))
-
-typedef struct _GamesCardThemeSlicedClass GamesCardThemeSlicedClass;
-typedef struct _GamesCardThemeSliced      GamesCardThemeSliced;
-
-GType games_card_theme_sliced_get_type (void);
-
-GamesCardTheme* games_card_theme_sliced_new (void);
-
-/* GamesCardThemeKDE */
-
-#define GAMES_TYPE_CARD_THEME_KDE            (games_card_theme_kde_get_type ())
-#define GAMES_CARD_THEME_KDE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_KDE, GamesCardThemeKDE))
-#define GAMES_CARD_THEME_KDE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_KDE, GamesCardThemeKDEClass))
-#define GAMES_IS_CARD_THEME_KDE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_KDE))
-#define GAMES_IS_CARD_THEME_KDE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_KDE))
-#define GAMES_CARD_THEME_KDE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_KDE, GamesCardThemeKDEClass))
-
-typedef struct _GamesCardThemeKDEClass GamesCardThemeKDEClass;
-typedef struct _GamesCardThemeKDE      GamesCardThemeKDE;
-
-GType games_card_theme_kde_get_type (void);
-
-GamesCardTheme* games_card_theme_kde_new (void);
-
-/* GamesCardThemeFixed */
+/* Utility functions */
 
-#define GAMES_TYPE_CARD_THEME_FIXED            (games_card_theme_fixed_get_type ())
-#define GAMES_CARD_THEME_FIXED(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMES_TYPE_CARD_THEME_FIXED, GamesCardThemeFixed))
-#define GAMES_CARD_THEME_FIXED_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GAMES_TYPE_CARD_THEME_FIXED, GamesCardThemeFixedClass))
-#define GAMES_IS_CARD_THEME_FIXED(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMES_TYPE_CARD_THEME_FIXED))
-#define GAMES_IS_CARD_THEME_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMES_TYPE_CARD_THEME_FIXED))
-#define GAMES_CARD_THEME_FIXED_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GAMES_TYPE_CARD_THEME_FIXED, GamesCardThemeFixedClass))
+GamesCardTheme *games_card_theme_get (GamesCardThemeInfo *info);
 
-typedef struct _GamesCardThemeFixedClass GamesCardThemeFixedClass;
-typedef struct _GamesCardThemeFixed      GamesCardThemeFixed;
+GamesCardTheme *games_card_theme_get_by_name (const char *theme_name);
 
-GType games_card_theme_fixed_get_type (void);
+GamesCardTheme *games_card_theme_get_any (void);
 
-GamesCardTheme* games_card_theme_fixed_new (void);
+GList *games_card_theme_get_all (void);
 
 G_END_DECLS
 
-/* Utility functions */
-
-GamesCardTheme *games_card_theme_new (void);
-
-GList *games_card_theme_get_themes (void);
-
 #endif /* GAMES_CARD_THEME_H */

Modified: trunk/libgames-support/games-files.c
==============================================================================
--- trunk/libgames-support/games-files.c	(original)
+++ trunk/libgames-support/games-files.c	Tue Jan  6 18:18:21 2009
@@ -432,51 +432,3 @@
 games_file_list_init (GamesFileList * filelist)
 {
 }
-
-/**
- * games_file_list_card_themes:
- * @scalable: whether to look for scalable or prerendered themes
- *
- * Note that the returned #GamesFileList's list contains the found
- * theme names in the filename encoding!
- * 
- * Returns: a new #GamesFileList containing the found themes
- */
-GamesFileList *games_file_list_card_themes (gboolean scalable);
-
-GamesFileList *
-games_file_list_card_themes (gboolean scalable)
-{
-  GamesFileList *files;
-  GList *l;
-  GamesRuntimeDirectory dir;
-  const char *glob, *path;
-
-#ifdef HAVE_RSVG
-  if (scalable) {
-    glob = "*.svg";
-    dir = GAMES_RUNTIME_SCALABLE_CARDS_DIRECTORY;
-  } else
-#endif /* HAVE_RSVG */
-  {
-    glob = "*.card-theme";
-    dir = GAMES_RUNTIME_PRERENDERED_CARDS_DIRECTORY;
-  }
-
-  path = games_runtime_get_directory (dir);
-  files = games_file_list_new (glob, path, NULL);
-
-  games_file_list_transform_basename (files);
-
-  for (l = files->list; l != NULL; l = l->next) {
-    const char *filename = (const char *) l->data;
-    char *dot;
-
-    dot = strrchr (filename, '.');
-    if (dot) {
-      *dot = '\0';
-    }
-  }
-
-  return files;
-}

Modified: trunk/libgames-support/render-cards.c
==============================================================================
--- trunk/libgames-support/render-cards.c	(original)
+++ trunk/libgames-support/render-cards.c	Tue Jan  6 18:18:21 2009
@@ -1,5 +1,5 @@
 /*
- *  Copyright  2007 Christian Persch
+ *  Copyright  2007, 2008 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
@@ -14,8 +14,6 @@
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- *  $Id$
  */
 
 #include <config.h>
@@ -29,12 +27,14 @@
 #include <gtk/gtk.h>
 
 #include "games-card-theme.h"
+#include "games-card-theme-private.h"
 
 int
 main (int argc, char *argv[])
 {
   GError *err = NULL;
   char *basepath = NULL, *kfname, *kfpath;
+  GamesCardThemeInfo *theme_info = NULL;
   GamesCardTheme *theme = NULL;
   GKeyFile *key_file = NULL;
   int i;
@@ -130,7 +130,18 @@
     goto loser;
   }
 
-  theme = games_card_theme_svg_new ();
+
+  theme_info = _games_card_theme_info_new (GAMES_TYPE_CARD_THEME_SVG,
+                                           theme_dir,
+                                           theme_name /* FIXMEchpe append .svg */,
+                                           theme_name,
+                                           NULL, NULL);
+  theme = games_card_theme_get (theme_info);
+  if (!theme) {
+    /* FIXMEchpe print real error */
+    g_warning ("Failed to load theme '%s'\n", theme_name);
+    goto loser;
+  }
 
   if (antialias_set) {
     cairo_font_options_t *font_options;
@@ -142,11 +153,6 @@
     cairo_font_options_destroy (font_options);
   }
 
-  if (!games_card_theme_set_theme (theme, theme_dir, theme_name)) {
-    g_warning ("Failed to load theme '%s'\n", theme_name);
-    goto loser;
-  }
-
   if (g_mkdir_with_parents (outpath, 0755) < 0) {
     g_warning ("Failed to create path %s: %s\n", outpath, g_strerror (errno));
     goto loser;
@@ -253,6 +259,8 @@
   g_strfreev (args);
   if (theme)
     g_object_unref (theme);
+  if (theme_info)
+    games_card_theme_info_unref (theme_info);
   if (key_file)
     g_key_file_free (key_file);
 



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