summaryrefslogtreecommitdiffstats
path: root/src/gs-category-tile.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gs-category-tile.c')
-rw-r--r--src/gs-category-tile.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/src/gs-category-tile.c b/src/gs-category-tile.c
new file mode 100644
index 0000000..34fced1
--- /dev/null
+++ b/src/gs-category-tile.c
@@ -0,0 +1,219 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2013 Matthias Clasen <mclasen@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * SECTION:gs-category-tile
+ * @short_description: A UI tile for presenting a category
+ *
+ * #GsCategoryTile is a UI widget to show a category to the user. It’s generally
+ * aimed to be used in a list box, to provide navigation options to all the
+ * categories.
+ *
+ * It will display the category’s name, and potentially a background image which
+ * is styled to match the category’s content.
+ *
+ * Since: 41
+ */
+
+#include "config.h"
+
+#include "gs-category-tile.h"
+#include "gs-common.h"
+
+struct _GsCategoryTile
+{
+ GtkButton parent_instance;
+
+ GsCategory *category; /* (owned) (not nullable) */
+ GtkWidget *label;
+ GtkWidget *image;
+ GtkBox *box;
+};
+
+G_DEFINE_TYPE (GsCategoryTile, gs_category_tile, GTK_TYPE_BUTTON)
+
+typedef enum {
+ PROP_CATEGORY = 1,
+} GsCategoryTileProperty;
+
+static GParamSpec *obj_props[PROP_CATEGORY + 1] = { NULL, };
+
+static void
+gs_category_tile_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GsCategoryTile *self = GS_CATEGORY_TILE (object);
+
+ switch ((GsCategoryTileProperty) prop_id) {
+ case PROP_CATEGORY:
+ g_value_set_object (value, gs_category_tile_get_category (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_category_tile_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GsCategoryTile *self = GS_CATEGORY_TILE (object);
+
+ switch ((GsCategoryTileProperty) prop_id) {
+ case PROP_CATEGORY:
+ gs_category_tile_set_category (self, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * gs_category_tile_get_category:
+ * @tile: a #GsCategoryTile
+ *
+ * Get the value of #GsCategoryTile:category.
+ *
+ * Returns: (transfer none) (not nullable): a category
+ * Since: 41
+ */
+GsCategory *
+gs_category_tile_get_category (GsCategoryTile *tile)
+{
+ g_return_val_if_fail (GS_IS_CATEGORY_TILE (tile), NULL);
+
+ return tile->category;
+}
+
+static void
+gs_category_tile_refresh (GsCategoryTile *tile)
+{
+ GtkStyleContext *context;
+ const gchar *icon_name = gs_category_get_icon_name (tile->category);
+
+ /* set labels */
+ gtk_label_set_label (GTK_LABEL (tile->label),
+ gs_category_get_name (tile->category));
+
+ gtk_image_set_from_icon_name (GTK_IMAGE (tile->image), icon_name);
+ gtk_widget_set_visible (tile->image, icon_name != NULL);
+
+ /* Update the icon class. */
+ context = gtk_widget_get_style_context (GTK_WIDGET (tile));
+ if (icon_name != NULL)
+ gtk_style_context_remove_class (context, "category-tile-iconless");
+ else
+ gtk_style_context_add_class (context, "category-tile-iconless");
+
+ /* The label should be left-aligned for iconless categories and centred otherwise. */
+ gtk_widget_set_halign (GTK_WIDGET (tile->box),
+ (icon_name != NULL) ? GTK_ALIGN_CENTER : GTK_ALIGN_START);
+}
+
+/**
+ * gs_category_tile_set_category:
+ * @tile: a #GsCategoryTile
+ * @cat: (transfer none) (not nullable): a #GsCategory
+ *
+ * Set the value of #GsCategoryTile:category to @cat.
+ *
+ * Since: 41
+ */
+void
+gs_category_tile_set_category (GsCategoryTile *tile, GsCategory *cat)
+{
+ GtkStyleContext *context;
+
+ g_return_if_fail (GS_IS_CATEGORY_TILE (tile));
+ g_return_if_fail (GS_IS_CATEGORY (cat));
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (tile));
+
+ /* Remove the old category ID. */
+ if (tile->category != NULL) {
+ g_autofree gchar *class_name = g_strdup_printf ("category-%s", gs_category_get_id (tile->category));
+ gtk_style_context_remove_class (context, class_name);
+ }
+
+ if (g_set_object (&tile->category, cat)) {
+ g_autofree gchar *class_name = g_strdup_printf ("category-%s", gs_category_get_id (tile->category));
+
+ /* Add the new category’s ID as a CSS class, to get
+ * category-specific styling. */
+ gtk_style_context_add_class (context, class_name);
+
+ gs_category_tile_refresh (tile);
+ g_object_notify_by_pspec (G_OBJECT (tile), obj_props[PROP_CATEGORY]);
+ }
+}
+
+static void
+gs_category_tile_dispose (GObject *object)
+{
+ GsCategoryTile *tile = GS_CATEGORY_TILE (object);
+
+ g_clear_object (&tile->category);
+
+ G_OBJECT_CLASS (gs_category_tile_parent_class)->dispose (object);
+}
+
+static void
+gs_category_tile_init (GsCategoryTile *tile)
+{
+ gtk_widget_init_template (GTK_WIDGET (tile));
+}
+
+static void
+gs_category_tile_class_init (GsCategoryTileClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = gs_category_tile_get_property;
+ object_class->set_property = gs_category_tile_set_property;
+ object_class->dispose = gs_category_tile_dispose;
+
+ /**
+ * GsCategoryTile:category: (not nullable)
+ *
+ * The category to display in this tile.
+ *
+ * This must not be %NULL.
+ *
+ * Since: 41
+ */
+ obj_props[PROP_CATEGORY] =
+ g_param_spec_object ("category", NULL, NULL,
+ GS_TYPE_CATEGORY,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_props), obj_props);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-category-tile.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GsCategoryTile, label);
+ gtk_widget_class_bind_template_child (widget_class, GsCategoryTile, image);
+ gtk_widget_class_bind_template_child (widget_class, GsCategoryTile, box);
+}
+
+/**
+ * gs_category_tile_new:
+ * @cat: (transfer none) (not nullable): a #GsCategory
+ *
+ * Create a new #GsCategoryTile to represent @cat.
+ *
+ * Returns: (transfer full) (type GsCategoryTile): a new #GsCategoryTile
+ * Since: 41
+ */
+GtkWidget *
+gs_category_tile_new (GsCategory *cat)
+{
+ return g_object_new (GS_TYPE_CATEGORY_TILE,
+ "category", cat,
+ NULL);
+}