[recipes] Change strategy for tile backgrounds



commit d01a69c1b058597cd89c99e170e1002ae335ab14
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Jan 2 10:19:17 2017 -0500

    Change strategy for tile backgrounds
    
    Instead of creating a custom per-widget style provider
    that needs to load the image again, generate just a single
    style provider that provides the style for all recipes
    and another one for all the chefs. This avoids lots of
    image reloading and speeds up the list pages quite a bit.

 src/gr-chef-tile.c    |   88 +++++++++++++++++++++++++++---------
 src/gr-chef-tile.h    |    3 +
 src/gr-list-page.c    |   44 +++++--------------
 src/gr-recipe-tile.c  |  119 +++++++++++++++++++++++++++++++++++++-----------
 src/gr-recipe-tile.h  |    2 +
 src/gr-recipe-tile.ui |    2 +
 src/gr-recipes-page.c |    6 +++
 7 files changed, 182 insertions(+), 82 deletions(-)
---
diff --git a/src/gr-chef-tile.c b/src/gr-chef-tile.c
index 3473e9c..5160608 100644
--- a/src/gr-chef-tile.c
+++ b/src/gr-chef-tile.c
@@ -73,45 +73,91 @@ gr_chef_tile_class_init (GrChefTileClass *klass)
 }
 
 static void
-chef_tile_set_chef (GrChefTile *tile,
-                    GrChef     *chef)
+add_chef_css (GrChef  *chef,
+              GString *css)
 {
-        const char *name;
+        const char *id;
         const char *image_path;
-        GtkStyleContext *context;
-        g_autofree char *css = NULL;
-        g_autoptr(GtkCssProvider) provider = NULL;
 
-        g_set_object (&tile->chef, chef);
-
-        name = gr_chef_get_name (chef);
+        id = gr_chef_get_id (chef);
         image_path = gr_chef_get_image (chef);
 
-        gtk_label_set_label (GTK_LABEL (tile->label), name);
-
         if (image_path != NULL && image_path[0] != '\0')
-                css = g_strdup_printf ("image.chef {\n"
+                g_string_append_printf (css,
+                                       "image.chef.%s {\n"
                                        "  background: url('%s');\n"
                                        "  background-size: 64px;\n"
                                        "  min-width: 64px;\n"
                                        "  min-height: 64px;\n"
-                                       "}", image_path);
+                                       "}\n\n", id, image_path);
         else
-                css = g_strdup_printf ("image.chef {\n"
+                g_string_append_printf (css,
+                                       "image.chef.%s {\n"
                                        "  background: rgb(%d,%d,%d);\n"
                                        "  min-width: 64px;\n"
                                        "  min-height: 64px;\n"
-                                       "}",
+                                       "}\n\n",
+                                       id,
                                        g_random_int_range (0, 255),
                                        g_random_int_range (0, 255),
                                        g_random_int_range (0, 255));
+}
+
+static GtkCssProvider *provider = NULL;
+
+void
+gr_chef_tile_recreate_css (void)
+{
+        GrRecipeStore *store;
+        g_autofree char **keys = NULL;
+        guint length;
+        g_autoptr(GString) css = NULL;
+        int i;
+
+        store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));
+        keys = gr_recipe_store_get_chef_keys (store, &length);
+
+        css = g_string_new ("");
+
+        for (i = 0; i < length; i++) {
+                g_autoptr (GrChef) chef = NULL;
+                chef = gr_recipe_store_get_chef (store, keys[i]);
+                add_chef_css (chef, css);
+        }
+
+        if (provider == NULL) {
+                provider = gtk_css_provider_new ();
+                gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+                                                           GTK_STYLE_PROVIDER (provider),
+                                                           GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+        }
+
+        gtk_css_provider_load_from_data (provider, css->str, css->len, NULL);
+}
+
+static void
+chef_tile_set_chef (GrChefTile *tile,
+                    GrChef     *chef)
+{
+        if (tile->chef) {
+                const char *elem;
+
+                elem = gr_chef_get_id (tile->chef);
+                gtk_style_context_remove_class (gtk_widget_get_style_context (tile->image), elem);
+        }
+
+        g_set_object (&tile->chef, chef);
+
+        if (tile->chef) {
+                const char *elem;
+                const char *name;
+
+                elem = gr_chef_get_id (tile->chef);
+                gtk_style_context_add_class (gtk_widget_get_style_context (tile->image), elem);
 
-        provider = gtk_css_provider_new ();
-        gtk_css_provider_load_from_data (provider, css, -1, NULL);
-        context = gtk_widget_get_style_context (tile->image);
-        gtk_style_context_add_provider (context,
-                                        GTK_STYLE_PROVIDER (provider),
-                                        GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+                name = gr_chef_get_name (chef);
+                gtk_label_set_label (GTK_LABEL (tile->label), name);
+        }
 }
 
 GtkWidget *
diff --git a/src/gr-chef-tile.h b/src/gr-chef-tile.h
index f255a70..b44123f 100644
--- a/src/gr-chef-tile.h
+++ b/src/gr-chef-tile.h
@@ -32,4 +32,7 @@ G_DECLARE_FINAL_TYPE (GrChefTile, gr_chef_tile, GR, CHEF_TILE, GtkBox)
 GtkWidget       *gr_chef_tile_new      (GrChef     *chef);
 GrChef          *gr_chef_tile_get_chef (GrChefTile *tile);
 
+void            gr_chef_tile_recreate_css (void);
+
+
 G_END_DECLS
diff --git a/src/gr-list-page.c b/src/gr-list-page.c
index 81386cc..9fdb264 100644
--- a/src/gr-list-page.c
+++ b/src/gr-list-page.c
@@ -32,7 +32,6 @@
 #include "gr-season.h"
 #include "gr-category-tile.h"
 
-
 struct _GrListPage
 {
         GtkBox parent_instance;
@@ -66,6 +65,11 @@ static void connect_store_signals (GrListPage *page);
 static void
 clear_data (GrListPage *self)
 {
+        if (self->chef) {
+                gtk_style_context_remove_class (gtk_widget_get_style_context (self->chef_image),
+                                                gr_chef_get_id (self->chef));
+        }
+
         g_clear_object (&self->chef);
         self->diet = 0;
         self->favorites = FALSE;
@@ -289,17 +293,16 @@ gr_list_page_populate_from_chef (GrListPage *self,
         GrRecipeStore *store;
         const char *id;
         char *tmp;
-        const char *image_path;
         const char *description;
-        GtkStyleContext *context;
-        g_autofree char *css = NULL;
-        g_autoptr(GtkCssProvider) provider = NULL;
         g_autofree char *term = NULL;
 
         g_object_ref (chef);
         clear_data (self);
         self->chef = chef;
 
+        gtk_style_context_add_class (gtk_widget_get_style_context (self->chef_image),
+                                     gr_chef_get_id (self->chef));
+
         gtk_widget_show (self->chef_grid);
         gtk_widget_show (self->heading);
         gtk_widget_hide (self->diet_description);
@@ -308,32 +311,6 @@ gr_list_page_populate_from_chef (GrListPage *self,
         description = gr_chef_get_translated_description (chef);
         gtk_label_set_markup (GTK_LABEL (self->chef_description), description);
 
-        image_path = gr_chef_get_image (chef);
-
-        if (image_path != NULL && image_path[0] != '\0')
-                css = g_strdup_printf ("image.chef {\n"
-                                       "  background: url('%s');\n"
-                                       "  background-size: 64px;\n"
-                                       "  min-width: 64px;\n"
-                                       "  min-height: 64px;\n"
-                                       "}", image_path);
-        else
-                css = g_strdup_printf ("image.chef {\n"
-                                       "  background: rgb(%d,%d,%d);\n"
-                                       "  min-width: 64px;\n"
-                                       "  min-height: 64px;\n"
-                                       "}",
-                                       g_random_int_range (0, 255),
-                                       g_random_int_range (0, 255),
-                                       g_random_int_range (0, 255));
-
-        provider = gtk_css_provider_new ();
-        gtk_css_provider_load_from_data (provider, css, -1, NULL);
-        context = gtk_widget_get_style_context (self->chef_image);
-        gtk_style_context_add_provider (context,
-                                        GTK_STYLE_PROVIDER (provider),
-                                        GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-
         tmp = g_strdup_printf (_("Recipes by %s"), gr_chef_get_name (chef));
         gtk_label_set_label (GTK_LABEL (self->heading), tmp);
         g_free (tmp);
@@ -349,11 +326,12 @@ gr_list_page_populate_from_chef (GrListPage *self,
         else
                 gtk_label_set_label (GTK_LABEL (self->empty_subtitle), _("Sorry about this."));
 
-        id = gr_chef_get_id (chef);
-
         gr_recipe_search_stop (self->search);
         gtk_stack_set_visible_child_name (GTK_STACK (self->list_stack), "list");
+
+        id = gr_chef_get_id (chef);
         term = g_strconcat ("by:", id, NULL);
+
         gr_recipe_search_set_query (self->search, term);
 }
 
diff --git a/src/gr-recipe-tile.c b/src/gr-recipe-tile.c
index 109f7cc..0c72d3c 100644
--- a/src/gr-recipe-tile.c
+++ b/src/gr-recipe-tile.c
@@ -54,37 +54,32 @@ show_details (GrRecipeTile *tile)
 }
 
 static void
-recipe_tile_set_recipe (GrRecipeTile *tile,
-                        GrRecipe     *recipe)
+add_recipe_css (GrRecipe *recipe,
+                GString  *css)
 {
-        const char *name;
+        const char *id;
         const char *author;
-        g_autofree char *tmp = NULL;
+        g_autoptr(GrChef) chef = NULL;
         g_autoptr(GArray) images = NULL;
         const char *color;
         GrRecipeStore *store;
-        g_autoptr(GrChef) chef = NULL;
-
-        g_set_object (&tile->recipe, recipe);
-        if (!recipe)
-                return;
 
         store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));
 
-        name = gr_recipe_get_translated_name (recipe);
+        id = gr_recipe_get_id (recipe);
         author = gr_recipe_get_author (recipe);
         chef = gr_recipe_store_get_chef (store, author);
 
         g_object_get (recipe, "images", &images, NULL);
 
         if (images->len > 0) {
-                g_autofree char *css = NULL;
                 GrRotatedImage *ri = &g_array_index (images, GrRotatedImage, 0);
 
-                css = g_strdup_printf ("  background: url('%s');\n"
-                                       "  background-size: 100%%;\n"
-                                       "  background-repeat: no-repeat;\n", ri->path);
-                gr_utils_widget_set_css_simple (tile->box, css);
+                g_string_append_printf (css, "box.recipe.%s {\n", id);
+                g_string_append_printf (css, "  background: url('%s');\n"
+                                             "  background-size: 100%%;\n"
+                                             "  background-repeat: no-repeat;\n", ri->path);
+                g_string_append (css, "}\n\n");
 
                 if (ri->dark_text)
                         color = "black";
@@ -96,23 +91,91 @@ recipe_tile_set_recipe (GrRecipeTile *tile,
         }
 
         if (color) {
-                g_autofree char *css = NULL;
-                css = g_strdup_printf (" color: %s;\n"
-                                       " margin: 0 20px 0 20px;\n"
-                                       " font-weight: bold;\n"
-                                       " font-size: 24pt;\n", color);
-                gr_utils_widget_set_css_simple (tile->label, css);
-
-                g_free (css);
-                css = g_strdup_printf (" color: %s;\n"
+                g_string_append_printf (css, "label.recipe.name.%s {\n", id);
+                g_string_append_printf (css, " color: %s;\n"
+                                             " margin: 0 20px 0 20px;\n"
+                                             " font-weight: bold;\n"
+                                             " font-size: 24pt;\n", color);
+                g_string_append (css, "}\n\n");
+
+                g_string_append_printf (css, "label.recipe.author.%s {\n", id);
+                g_string_append_printf (css, " color: %s;\n"
                                        " margin: 10px 20px 20px 20px;\n"
                                        " font-size: 12pt;\n", color);
-                gr_utils_widget_set_css_simple (tile->author, css);
+                g_string_append (css, "}\n\n");
         }
+}
 
-        gtk_label_set_label (GTK_LABEL (tile->label), name);
-        tmp = g_strdup_printf (_("by %s"), chef ? gr_chef_get_name (chef) : _("Anonymous"));
-        gtk_label_set_label (GTK_LABEL (tile->author), tmp);
+static GtkCssProvider *provider = NULL;
+
+void
+gr_recipe_tile_recreate_css (void)
+{
+        GrRecipeStore *store;
+        g_autofree char **keys = NULL;
+        guint length;
+        g_autoptr(GString) css = NULL;
+        int i;
+
+        store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));
+        keys = gr_recipe_store_get_recipe_keys (store, &length);
+
+        css = g_string_new ("");
+
+        for (i = 0; i < length; i++) {
+                g_autoptr (GrRecipe) recipe = NULL;
+                recipe = gr_recipe_store_get_recipe (store, keys[i]);
+                add_recipe_css (recipe, css);
+        }
+
+        if (provider == NULL) {
+                provider = gtk_css_provider_new ();
+                gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+                                                           GTK_STYLE_PROVIDER (provider),
+                                                           GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+        }
+
+        gtk_css_provider_load_from_data (provider, css->str, css->len, NULL);
+}
+
+static void
+recipe_tile_set_recipe (GrRecipeTile *tile,
+                        GrRecipe     *recipe)
+{
+        GrRecipeStore *store;
+
+        store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));
+
+        if (tile->recipe) {
+                const char *elem;
+                elem = gr_recipe_get_id (tile->recipe);
+                gtk_style_context_remove_class (gtk_widget_get_style_context (tile->box), elem);
+                gtk_style_context_remove_class (gtk_widget_get_style_context (tile->label), elem);
+                gtk_style_context_remove_class (gtk_widget_get_style_context (tile->author), elem);
+        }
+
+        g_set_object (&tile->recipe, recipe);
+
+        if (tile->recipe) {
+                const char *elem;
+                const char *name;
+                const char *author;
+                g_autoptr(GrChef) chef = NULL;
+                g_autofree char *tmp = NULL;
+
+                elem = gr_recipe_get_id (tile->recipe);
+                gtk_style_context_add_class (gtk_widget_get_style_context (tile->box), elem);
+                gtk_style_context_add_class (gtk_widget_get_style_context (tile->label), elem);
+                gtk_style_context_add_class (gtk_widget_get_style_context (tile->author), elem);
+
+                name = gr_recipe_get_translated_name (recipe);
+                author = gr_recipe_get_author (recipe);
+                chef = gr_recipe_store_get_chef (store, author);
+
+                gtk_label_set_label (GTK_LABEL (tile->label), name);
+                tmp = g_strdup_printf (_("by %s"), chef ? gr_chef_get_name (chef) : _("Anonymous"));
+                gtk_label_set_label (GTK_LABEL (tile->author), tmp);
+        }
 }
 
 static void
diff --git a/src/gr-recipe-tile.h b/src/gr-recipe-tile.h
index fd38761..66c1a29 100644
--- a/src/gr-recipe-tile.h
+++ b/src/gr-recipe-tile.h
@@ -33,4 +33,6 @@ G_DECLARE_FINAL_TYPE (GrRecipeTile, gr_recipe_tile, GR, RECIPE_TILE, GtkButton)
 GtkWidget      *gr_recipe_tile_new        (GrRecipe     *recipe);
 GrRecipe       *gr_recipe_tile_get_recipe (GrRecipeTile *tile);
 
+void            gr_recipe_tile_recreate_css (void);
+
 G_END_DECLS
diff --git a/src/gr-recipe-tile.ui b/src/gr-recipe-tile.ui
index 71ed006..1621879 100644
--- a/src/gr-recipe-tile.ui
+++ b/src/gr-recipe-tile.ui
@@ -40,6 +40,7 @@
                 <property name="max-width-chars">12</property>
                 <style>
                   <class name="recipe"/>
+                  <class name="name"/>
                 </style>
               </object>
             </child>
@@ -53,6 +54,7 @@
                 <property name="max-width-chars">12</property>
                 <style>
                   <class name="recipe"/>
+                  <class name="author"/>
                 </style>
               </object>
             </child>
diff --git a/src/gr-recipes-page.c b/src/gr-recipes-page.c
index 5c2d12e..80c32fc 100644
--- a/src/gr-recipes-page.c
+++ b/src/gr-recipes-page.c
@@ -122,6 +122,8 @@ gr_recipes_page_init (GrRecipesPage *page)
         populate_diets_from_store (page);
         populate_recipes_from_store (page);
         populate_chefs_from_store (page);
+        gr_recipe_tile_recreate_css ();
+        gr_chef_tile_recreate_css ();
         connect_store_signals (page);
 }
 
@@ -271,6 +273,8 @@ repopulate_recipes (GrRecipesPage *self)
 {
         populate_recipes_from_store (self);
         populate_diets_from_store (self);
+        gr_recipe_tile_recreate_css ();
+        gr_chef_tile_recreate_css ();
 }
 
 static void
@@ -281,6 +285,8 @@ populate_chefs_from_store (GrRecipesPage *self)
         guint length;
         int i;
 
+        gr_chef_tile_recreate_css ();
+
         container_remove_all (GTK_CONTAINER (self->chefs_box));
 
         store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));


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