[gnome-software] Break out the feature tile as a separate widget



commit ffaab0aeedb68b537cf6223474e113b14d245cc3
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Sep 7 00:48:54 2013 -0400

    Break out the feature tile as a separate widget
    
    At the same time, move to a separate template.

 src/Makefile.am                  |    2 +
 src/feature-tile.ui              |   62 +++++++++++++
 src/gnome-software.gresource.xml |    1 +
 src/gnome-software.ui            |   52 +-----------
 src/gs-feature-tile.c            |  184 ++++++++++++++++++++++++++++++++++++++
 src/gs-feature-tile.h            |   64 +++++++++++++
 src/gs-shell-overview.c          |  104 ++++++----------------
 7 files changed, 340 insertions(+), 129 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index d6c089f..0158216 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,6 +41,8 @@ gnome_software_SOURCES =                              \
        gs-app-widget.h                                 \
        gs-popular-tile.c                               \
        gs-popular-tile.h                               \
+       gs-feature-tile.c                               \
+       gs-feature-tile.h                               \
        gs-box.h                                        \
        gs-box.c                                        \
        gs-plugin.c                                     \
diff --git a/src/feature-tile.ui b/src/feature-tile.ui
new file mode 100644
index 0000000..2d8673b
--- /dev/null
+++ b/src/feature-tile.ui
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.10 -->
+  <template class="GsFeatureTile" parent="GtkBin">
+    <property name="visible">True</property>
+    <child>
+      <object class="GtkButton" id="button">
+        <property name="visible">True</property>
+        <property name="halign">fill</property>
+        <style>
+          <class name="featured-tile"/>
+        </style>
+        <child>
+          <object class="GtkBox" id="box">
+            <property name="visible">True</property>
+            <property name="orientation">horizontal</property>
+            <property name="hexpand">True</property>
+            <child>
+              <object class="GtkImage" id="image">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <style>
+                  <class name="featured-image"/>
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkBox" id="box2">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <property name="margin">40</property>
+                <child>
+                  <object class="GtkLabel" id="title">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="halign">start</property>
+                    <property name="valign">end</property>
+                    <attributes>
+                      <attribute name="scale" value="2.5"/>
+                      <attribute name="weight" value="700"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="subtitle">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="halign">start</property>
+                    <property name="valign">start</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index c7964ad..c792bd7 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -4,6 +4,7 @@
   <file preprocess="xml-stripblanks">gnome-software.ui</file>
   <file preprocess="xml-stripblanks">app-menu.ui</file>
   <file preprocess="xml-stripblanks">popular-tile.ui</file>
+  <file preprocess="xml-stripblanks">feature-tile.ui</file>
   <file>gtk-style.css</file>
   <file>shadow.png</file>
   <file>shadow-active.png</file>
diff --git a/src/gnome-software.ui b/src/gnome-software.ui
index c2c4fc4..d2ad943 100644
--- a/src/gnome-software.ui
+++ b/src/gnome-software.ui
@@ -314,61 +314,11 @@
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkButton" id="featured_button">
+                          <object class="GtkAlignment" id="feature">
                             <property name="visible">True</property>
-                            <property name="receives_default">False</property>
                             <property name="halign">fill</property>
                             <property name="margin_left">12</property>
                             <property name="margin_right">12</property>
-                            <style>
-                              <class name="featured-tile"/>
-                            </style>
-                            <child>
-                              <object class="GtkBox" id="featured_box">
-                                <property name="visible">True</property>
-                                <property name="orientation">horizontal</property>
-                                <property name="hexpand">True</property>
-                                <child>
-                                  <object class="GtkImage" id="featured_image">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                            <style>
-                              <class name="featured-image"/>
-                            </style>
-                                  </object>
-                                </child>
-                                <child>
-                                  <object class="GtkBox" id="featured_title_box">
-                                    <property name="visible">True</property>
-                                    <property name="orientation">vertical</property>
-                                    <property name="margin">40</property>
-                                    <child>
-                                      <object class="GtkLabel" id="featured_title">
-                                        <property name="visible">True</property>
-                                        <property name="xalign">0</property>
-                                        <property name="halign">start</property>
-                                        <property name="valign">end</property>
-                                        <attributes>
-                                          <attribute name="scale" value="2.5"/>
-                                          <attribute name="weight" value="700"/>
-                                        </attributes>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">True</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkLabel" id="featured_subtitle">
-                                        <property name="visible">True</property>
-                                        <property name="xalign">0</property>
-                                        <property name="halign">start</property>
-                                        <property name="valign">start</property>
-                                      </object>
-                                    </child>
-                                  </object>
-                                </child>
-                              </object>
-                            </child>
                           </object>
                           <packing>
                             <property name="expand">False</property>
diff --git a/src/gs-feature-tile.c b/src/gs-feature-tile.c
new file mode 100644
index 0000000..e5ec014
--- /dev/null
+++ b/src/gs-feature-tile.c
@@ -0,0 +1,184 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gs-feature-tile.h"
+
+struct _GsFeatureTilePrivate
+{
+       GsApp           *app;
+       GtkWidget       *button;
+       GtkWidget       *image;
+       GtkWidget       *title;
+       GtkWidget       *subtitle;
+        GtkCssProvider  *provider;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsFeatureTile, gs_feature_tile, GTK_TYPE_BIN)
+
+enum {
+       SIGNAL_CLICKED,
+       SIGNAL_LAST
+};
+
+static guint signals [SIGNAL_LAST] = { 0 };
+
+GsApp *
+gs_feature_tile_get_app (GsFeatureTile *tile)
+{
+        GsFeatureTilePrivate *priv;
+
+       g_return_val_if_fail (GS_IS_FEATURE_TILE (tile), NULL);
+
+        priv = gs_feature_tile_get_instance_private (tile);
+       return priv->app;
+}
+
+void
+gs_feature_tile_set_app (GsFeatureTile *tile, GsApp *app)
+{
+        GsFeatureTilePrivate *priv;
+        gchar *data;
+
+       g_return_if_fail (GS_IS_FEATURE_TILE (tile));
+       g_return_if_fail (GS_IS_APP (app));
+
+        priv = gs_feature_tile_get_instance_private (tile);
+
+        g_clear_object (&priv->app);
+       priv->app = g_object_ref (app);
+
+        gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image),
+                                   gs_app_get_featured_pixbuf (priv->app));
+        gtk_label_set_label (GTK_LABEL (priv->title),
+                             gs_app_get_metadata_item (app, "featured-title"));
+        gtk_label_set_label (GTK_LABEL (priv->subtitle),
+                             gs_app_get_metadata_item (app, "featured-subtitle"));
+        data = g_strdup_printf (
+                ".button.featured-tile {\n"
+                "  padding: 0;\n"
+                "  border-radius: 0;\n"
+                "  border-width: 1px;\n"
+                "  border-image: none;\n"
+                "  border-color: %s;\n"
+                "  color: %s;\n"
+                "  -GtkWidget-focus-padding: 0;\n"
+                "  outline-color: alpha(%s, 0.75);\n"
+                "  outline-style: dashed;\n"
+                "  outline-offset: 2px;\n"
+                "  background-image: -gtk-gradient(linear,\n"
+                "                       0 0, 0 1,\n"
+                "                       color-stop(0,%s),\n"
+                "                       color-stop(1,%s));\n"
+                "}\n"
+                ".button.featured-tile:hover {\n"
+                "  background-image: -gtk-gradient(linear,\n"
+                "                       0 0, 0 1,\n"
+                "                       color-stop(0,alpha(%s,0.80)),\n"
+                "                       color-stop(1,alpha(%s,0.80)));\n"
+                "}\n",
+                gs_app_get_metadata_item (app, "featured-stroke-color"),
+                gs_app_get_metadata_item (app, "featured-text-color"),
+                gs_app_get_metadata_item (app, "featured-text-color"),
+                gs_app_get_metadata_item (app, "featured-gradient1-color"),
+                gs_app_get_metadata_item (app, "featured-gradient2-color"),
+                gs_app_get_metadata_item (app, "featured-gradient1-color"),
+                gs_app_get_metadata_item (app, "featured-gradient2-color"));
+
+        gtk_css_provider_load_from_data (priv->provider, data, -1, NULL);
+        g_free (data);
+}
+
+static void
+gs_feature_tile_destroy (GtkWidget *widget)
+{
+       GsFeatureTile *tile = GS_FEATURE_TILE (widget);
+       GsFeatureTilePrivate *priv;
+
+        priv = gs_feature_tile_get_instance_private (tile);
+
+       g_clear_object (&priv->app);
+       g_clear_object (&priv->provider);
+
+       GTK_WIDGET_CLASS (gs_feature_tile_parent_class)->destroy (widget);
+}
+
+static void
+button_clicked (GsFeatureTile *tile)
+{
+        g_signal_emit (tile, signals[SIGNAL_CLICKED], 0);
+}
+
+static void
+gs_feature_tile_init (GsFeatureTile *tile)
+{
+        GsFeatureTilePrivate *priv;
+
+        gtk_widget_set_has_window (GTK_WIDGET (tile), FALSE);
+        gtk_widget_init_template (GTK_WIDGET (tile));
+        priv = gs_feature_tile_get_instance_private (tile);
+        g_signal_connect_swapped (priv->button, "clicked",
+                                  G_CALLBACK (button_clicked), tile);
+
+        priv->provider = gtk_css_provider_new ();
+        gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+                                                   GTK_STYLE_PROVIDER (priv->provider),
+                                                   GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
+
+static void
+gs_feature_tile_class_init (GsFeatureTileClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       widget_class->destroy = gs_feature_tile_destroy;
+
+       signals [SIGNAL_CLICKED] =
+               g_signal_new ("clicked",
+                             G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GsFeatureTileClass, clicked),
+                             NULL, NULL, g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+
+        gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/software/feature-tile.ui");
+
+        gtk_widget_class_bind_template_child_private (widget_class, GsFeatureTile, button);
+        gtk_widget_class_bind_template_child_private (widget_class, GsFeatureTile, image);
+        gtk_widget_class_bind_template_child_private (widget_class, GsFeatureTile, title);
+        gtk_widget_class_bind_template_child_private (widget_class, GsFeatureTile, subtitle);
+}
+
+GtkWidget *
+gs_feature_tile_new (GsApp *app)
+{
+        GsFeatureTile *tile;
+
+        tile = g_object_new (GS_TYPE_FEATURE_TILE, NULL);
+        gs_feature_tile_set_app (tile, app);
+
+        return GTK_WIDGET (tile);
+}
+
diff --git a/src/gs-feature-tile.h b/src/gs-feature-tile.h
new file mode 100644
index 0000000..e52a0b5
--- /dev/null
+++ b/src/gs-feature-tile.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef GS_FEATURE_TILE_H
+#define GS_FEATURE_TILE_H
+
+#include <gtk/gtk.h>
+
+#include "gs-app.h"
+
+#define GS_TYPE_FEATURE_TILE           (gs_feature_tile_get_type())
+#define GS_FEATURE_TILE(obj)           (G_TYPE_CHECK_INSTANCE_CAST((obj), GS_TYPE_FEATURE_TILE, 
GsFeatureTile))
+#define GS_FEATURE_TILE_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST((cls), GS_TYPE_FEATURE_TILE, 
GsFeatureTileClass))
+#define GS_IS_FEATURE_TILE(obj)                (G_TYPE_CHECK_INSTANCE_TYPE((obj), GS_TYPE_FEATURE_TILE))
+#define GS_IS_FEATURE_TILE_CLASS(cls)  (G_TYPE_CHECK_CLASS_TYPE((cls), GS_TYPE_FEATURE_TILE))
+#define GS_FEATURE_TILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GS_TYPE_FEATURE_TILE, 
GsFeatureTileClass))
+
+G_BEGIN_DECLS
+
+typedef struct _GsFeatureTile                  GsFeatureTile;
+typedef struct _GsFeatureTileClass             GsFeatureTileClass;
+typedef struct _GsFeatureTilePrivate           GsFeatureTilePrivate;
+
+struct _GsFeatureTile
+{
+       GtkBin                   parent;
+       GsFeatureTilePrivate    *priv;
+};
+
+struct _GsFeatureTileClass
+{
+       GtkBinClass              parent_class;
+
+       void                    (*clicked)      (GsFeatureTile  *feature_tile);
+};
+
+GType           gs_feature_tile_get_type               (void);
+GtkWidget      *gs_feature_tile_new                    (GsApp *app);
+GsApp          *gs_feature_tile_get_app                (GsFeatureTile  *feature_tile);
+void            gs_feature_tile_set_app                (GsFeatureTile  *feature_tile,
+                                                        GsApp          *app);
+
+G_END_DECLS
+
+#endif /* GS_FEATURE_TILE_H */
+
diff --git a/src/gs-shell-overview.c b/src/gs-shell-overview.c
index ea5deff..9f33986 100644
--- a/src/gs-shell-overview.c
+++ b/src/gs-shell-overview.c
@@ -28,6 +28,7 @@
 #include "gs-app.h"
 #include "gs-category.h"
 #include "gs-popular-tile.h"
+#include "gs-feature-tile.h"
 #include "gs-utils.h"
 
 static void    gs_shell_overview_finalize      (GObject        *object);
@@ -64,16 +65,6 @@ gs_shell_overview_invalidate (GsShellOverview *shell_overview)
 }
 
 static void
-app_tile_clicked (GtkButton *button, gpointer data)
-{
-       GsShellOverview *shell_overview = GS_SHELL_OVERVIEW (data);
-       GsApp *app;
-
-       app = g_object_get_data (G_OBJECT (button), "app");
-        gs_shell_show_app (shell_overview->priv->shell, app);
-}
-
-static void
 popular_tile_clicked (GsPopularTile *tile, gpointer data)
 {
        GsShellOverview *shell = GS_SHELL_OVERVIEW (data);
@@ -155,30 +146,31 @@ create_category_tile (GsShellOverview *shell_overview, GsCategory *category)
        return button;
 }
 
-/**
- * gs_shell_overview_get_featured_cb:
- **/
+static void
+feature_tile_clicked (GsFeatureTile *tile, gpointer data)
+{
+       GsShellOverview *shell = GS_SHELL_OVERVIEW (data);
+        GsApp *app;
+
+        app = gs_feature_tile_get_app (tile);
+        gs_shell_show_app (shell->priv->shell, app);
+}
+
 static void
 gs_shell_overview_get_featured_cb (GObject *source_object,
                                           GAsyncResult *res,
                                   gpointer user_data)
 {
-       GdkPixbuf *pixbuf;
-       GError *error = NULL;
-       GList *list;
-       GsApp *app;
-       GsShellOverview *shell_overview = GS_SHELL_OVERVIEW (user_data);
-       GsShellOverviewPrivate *priv = shell_overview->priv;
+       GsShellOverview *shell = GS_SHELL_OVERVIEW (user_data);
+       GsShellOverviewPrivate *priv = shell->priv;
        GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
-       GtkImage *image;
-       GtkWidget *button;
-       GtkWidget *widget;
-        const gchar *text;
-        gchar *css;
+       GtkWidget *tile;
+       GtkWidget *box;
+        GList *list;
+        GError *error = NULL;
+        GsApp *app;
 
-       list = gs_plugin_loader_get_featured_finish (plugin_loader,
-                                                    res,
-                                                    &error);
+       list = gs_plugin_loader_get_featured_finish (plugin_loader, res, &error);
        if (list == NULL) {
                g_warning ("failed to get featured apps: %s", error->message);
                g_error_free (error);
@@ -187,64 +179,20 @@ gs_shell_overview_get_featured_cb (GObject *source_object,
 
        /* at the moment, we only care about the first app */
        app = GS_APP (list->data);
-       image = GTK_IMAGE (gtk_builder_get_object (priv->builder, "featured_image"));
-       pixbuf = gs_app_get_featured_pixbuf (app);
-       gtk_image_set_from_pixbuf (image, pixbuf);
-
-       widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "featured_title"));
-        text = gs_app_get_metadata_item (app, "featured-title");
-        gtk_label_set_label (GTK_LABEL (widget), text);
+        box = GTK_WIDGET (gtk_builder_get_object (priv->builder, "feature"));
+        tile = gs_feature_tile_new (app);
+       g_signal_connect (tile, "clicked",
+                         G_CALLBACK (feature_tile_clicked), shell);
 
-       widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "featured_subtitle"));
-        text = gs_app_get_metadata_item (app, "featured-subtitle");
-        gtk_label_set_label (GTK_LABEL (widget), text);
-
-       button = GTK_WIDGET (gtk_builder_get_object (priv->builder, "featured_button"));
-       g_object_set_data_full (G_OBJECT (button), "app", app, g_object_unref);
-       g_signal_connect (button, "clicked",
-                         G_CALLBACK (app_tile_clicked), shell_overview);
-
-        css = g_strdup_printf (
-                ".button.featured-tile {\n"
-                "  padding: 0;\n"
-                "  border-radius: 0;\n"
-                "  border-width: 1px;\n"
-                "  border-image: none;\n"
-                "  border-color: %s;\n"
-                "  color: %s;\n"
-                "  -GtkWidget-focus-padding: 0;\n"
-                "  outline-color: alpha(%s, 0.75);\n"
-                "  outline-style: dashed;\n"
-                "  outline-offset: 2px;\n"
-                "  background-image: -gtk-gradient(linear,\n"
-                "                       0 0, 0 1,\n"
-                "                       color-stop(0,%s),\n"
-                "                       color-stop(1,%s));\n"
-                "}\n"
-                ".button.featured-tile:hover {\n"
-                "  background-image: -gtk-gradient(linear,\n"
-                "                       0 0, 0 1,\n"
-                "                       color-stop(0,alpha(%s,0.80)),\n"
-                "                       color-stop(1,alpha(%s,0.80)));\n"
-                "}\n",
-                gs_app_get_metadata_item (app, "featured-stroke-color"),
-                gs_app_get_metadata_item (app, "featured-text-color"),
-                gs_app_get_metadata_item (app, "featured-text-color"),
-                gs_app_get_metadata_item (app, "featured-gradient1-color"),
-                gs_app_get_metadata_item (app, "featured-gradient2-color"),
-                gs_app_get_metadata_item (app, "featured-gradient1-color"),
-                gs_app_get_metadata_item (app, "featured-gradient2-color"));
-
-        gtk_css_provider_load_from_data (priv->feature_style, css, -1, NULL);
-
-        g_free (css);
+        gs_container_remove_all (GTK_CONTAINER (box));
+        gtk_container_add (GTK_CONTAINER (box), tile);
 
 out:
        g_list_free (list);
 
         priv->refresh_count--;
         if (priv->refresh_count == 0)
-                g_signal_emit (shell_overview, signals[SIGNAL_REFRESHED], 0);
+                g_signal_emit (shell, signals[SIGNAL_REFRESHED], 0);
 }
 
 /**


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