[gnome-software: 86/110] gs-summary-tile: Use a specialized layout manager to handle allocation




commit 848806d0bb95e5208a61e623836311af731ada69
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Thu Aug 26 12:40:46 2021 -0300

    gs-summary-tile: Use a specialized layout manager to handle allocation
    
    The 'measure' vfunc isn't called when a layout manager is set, and sadly
    this is the case for GsAppTile, so we need to replace it with another
    layout manager that does what we want to.
    
    Add GsSummaryTileLayout, which is basically just a GtkBinLayout with
    an extra step limiting the natural width to a custom value.

 src/gs-summary-tile-layout.c | 114 +++++++++++++++++++++++++++++++++++++++++++
 src/gs-summary-tile-layout.h |  25 ++++++++++
 src/gs-summary-tile.c        |  44 +++--------------
 src/meson.build              |   1 +
 4 files changed, 146 insertions(+), 38 deletions(-)
---
diff --git a/src/gs-summary-tile-layout.c b/src/gs-summary-tile-layout.c
new file mode 100644
index 000000000..5e738f16c
--- /dev/null
+++ b/src/gs-summary-tile-layout.c
@@ -0,0 +1,114 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Endless OS Foundation LLC
+ *
+ * Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "gs-summary-tile-layout.h"
+
+struct _GsSummaryTileLayout
+{
+       GtkLayoutManager        parent_instance;
+
+       gint                    preferred_width;
+};
+
+G_DEFINE_TYPE (GsSummaryTileLayout, gs_summary_tile_layout, GTK_TYPE_LAYOUT_MANAGER)
+
+static void
+gs_summary_tile_layout_layout_measure (GtkLayoutManager *layout_manager,
+                                      GtkWidget        *widget,
+                                      GtkOrientation    orientation,
+                                      gint              for_size,
+                                      gint             *minimum,
+                                      gint             *natural,
+                                      gint             *minimum_baseline,
+                                      gint             *natural_baseline)
+{
+       GsSummaryTileLayout *self = GS_SUMMARY_TILE_LAYOUT (layout_manager);
+       GtkWidget *child;
+       gint min = 0;
+       gint nat = 0;
+
+       for (child = gtk_widget_get_first_child (widget);
+            child != NULL;
+            child = gtk_widget_get_next_sibling (child)) {
+               gint child_min_baseline = -1;
+               gint child_nat_baseline = -1;
+               gint child_min = 0;
+               gint child_nat = 0;
+
+               if (!gtk_widget_should_layout (child))
+                       continue;
+
+               gtk_widget_measure (child, orientation,
+                                   for_size,
+                                   &child_min, &child_nat,
+                                   &child_min_baseline,
+                                   &child_nat_baseline);
+
+               min = MAX (min, child_min);
+               nat = MAX (nat, child_nat);
+
+               if (child_min_baseline > -1)
+                       *minimum_baseline = MAX (*minimum_baseline, child_min_baseline);
+               if (child_nat_baseline > -1)
+                   *natural_baseline = MAX (*natural_baseline, child_nat_baseline);
+       }
+
+       *minimum = min;
+       *natural = nat;
+
+       /* Limit the natural width */
+       if (self->preferred_width > 0 && orientation == GTK_ORIENTATION_HORIZONTAL)
+               *natural = MAX (min, self->preferred_width);
+}
+
+static void
+gs_summary_tile_layout_layout_allocate (GtkLayoutManager *layout_manager,
+                                        GtkWidget        *widget,
+                                        gint              width,
+                                        gint              height,
+                                        gint              baseline)
+{
+       GtkWidget *child;
+
+       for (child = gtk_widget_get_first_child (widget);
+            child != NULL;
+            child = gtk_widget_get_next_sibling (child)) {
+               if (child && gtk_widget_should_layout (child))
+                       gtk_widget_allocate (child, width, height, baseline, NULL);
+       }
+}
+
+static void
+gs_summary_tile_layout_class_init (GsSummaryTileLayoutClass *klass)
+{
+       GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
+
+       layout_manager_class->measure = gs_summary_tile_layout_layout_measure;
+       layout_manager_class->allocate = gs_summary_tile_layout_layout_allocate;
+}
+
+static void
+gs_summary_tile_layout_init (GsSummaryTileLayout *self)
+{
+       self->preferred_width = -1;
+}
+
+void
+gs_summary_tile_layout_set_preferred_width (GsSummaryTileLayout *self,
+                                            gint                 preferred_width)
+{
+       g_return_if_fail (GS_IS_SUMMARY_TILE_LAYOUT (self));
+
+       if (self->preferred_width == preferred_width)
+               return;
+
+       self->preferred_width = preferred_width;
+       gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (self));
+}
diff --git a/src/gs-summary-tile-layout.h b/src/gs-summary-tile-layout.h
new file mode 100644
index 000000000..55d3c1be2
--- /dev/null
+++ b/src/gs-summary-tile-layout.h
@@ -0,0 +1,25 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Endless OS Foundation LLC
+ *
+ * Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_SUMMARY_TILE_LAYOUT (gs_summary_tile_layout_get_type ())
+G_DECLARE_FINAL_TYPE (GsSummaryTileLayout, gs_summary_tile_layout, GS, SUMMARY_TILE_LAYOUT, GtkLayoutManager)
+
+void   gs_summary_tile_layout_set_preferred_width      (GsSummaryTileLayout *self,
+                                                        gint                 preferred_width);
+
+G_END_DECLS
diff --git a/src/gs-summary-tile.c b/src/gs-summary-tile.c
index d6c248d27..f20f7e323 100644
--- a/src/gs-summary-tile.c
+++ b/src/gs-summary-tile.c
@@ -12,6 +12,7 @@
 #include <glib/gi18n.h>
 
 #include "gs-summary-tile.h"
+#include "gs-summary-tile-layout.h"
 #include "gs-common.h"
 
 struct _GsSummaryTile
@@ -131,11 +132,14 @@ gs_summary_tile_set_property (GObject *object,
                                 GParamSpec *pspec)
 {
        GsSummaryTile *app_tile = GS_SUMMARY_TILE (object);
+       GtkLayoutManager *layout_manager;
 
        switch ((GsSummaryTileProperty) prop_id) {
        case PROP_PREFERRED_WIDTH:
                app_tile->preferred_width = g_value_get_int (value);
-               gtk_widget_queue_resize (GTK_WIDGET (app_tile));
+               layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (app_tile));
+               gs_summary_tile_layout_set_preferred_width (GS_SUMMARY_TILE_LAYOUT (layout_manager),
+                                                           g_value_get_int (value));
                g_object_notify_by_pspec (object, obj_props[PROP_PREFERRED_WIDTH]);
                break;
        default:
@@ -144,41 +148,6 @@ gs_summary_tile_set_property (GObject *object,
        }
 }
 
-static void
-gs_summary_tile_measure (GtkWidget      *widget,
-                         GtkOrientation  orientation,
-                         gint            for_size,
-                         gint           *minimum,
-                         gint           *natural,
-                         gint           *minimum_baseline,
-                         gint           *natural_baseline)
-{
-       gint m;
-       GsSummaryTile *app_tile = GS_SUMMARY_TILE (widget);
-
-       if (app_tile->preferred_width < 0 || orientation == GTK_ORIENTATION_VERTICAL) {
-               /* Just retrieve the default values */
-               GTK_WIDGET_CLASS (gs_summary_tile_parent_class)->measure (widget,
-                                                                         orientation,
-                                                                         for_size,
-                                                                         minimum,
-                                                                         natural,
-                                                                         minimum_baseline,
-                                                                         natural_baseline);
-               return;
-       }
-
-       GTK_WIDGET_CLASS (gs_summary_tile_parent_class)->measure (widget,
-                                                                 orientation,
-                                                                 for_size,
-                                                                 &m, NULL,
-                                                                 NULL, NULL);
-       if (minimum != NULL)
-               *minimum = m;
-       if (natural != NULL)
-               *natural = MAX (m, app_tile->preferred_width);
-}
-
 static void
 gs_summary_tile_class_init (GsSummaryTileClass *klass)
 {
@@ -189,8 +158,6 @@ gs_summary_tile_class_init (GsSummaryTileClass *klass)
        object_class->get_property = gs_summary_tile_get_property;
        object_class->set_property = gs_summary_tile_set_property;
 
-       widget_class->measure = gs_summary_tile_measure;
-
        tile_class->refresh = gs_summary_tile_refresh;
 
        /**
@@ -216,6 +183,7 @@ gs_summary_tile_class_init (GsSummaryTileClass *klass)
 
        gtk_widget_class_set_css_name (widget_class, "summary-tile");
        gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-summary-tile.ui");
+       gtk_widget_class_set_layout_manager_type (widget_class, GS_TYPE_SUMMARY_TILE_LAYOUT);
 
        gtk_widget_class_bind_template_child (widget_class, GsSummaryTile,
                                              image);
diff --git a/src/meson.build b/src/meson.build
index 94fe23bdf..a214c7abd 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -80,6 +80,7 @@ gnome_software_sources = [
   'gs-star-widget.c',
   'gs-storage-context-dialog.c',
   'gs-summary-tile.c',
+  'gs-summary-tile-layout.c',
   'gs-update-dialog.c',
   'gs-update-list.c',
   'gs-update-monitor.c',


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