listitemmanager: Add GtkListHeaderBase and vfuncs
authorBenjamin Otte <otte@redhat.com>
Sun, 9 Apr 2023 12:24:26 +0000 (14:24 +0200)
committerBenjamin Otte <otte@redhat.com>
Tue, 9 May 2023 15:00:40 +0000 (17:00 +0200)
This is plumbing for section handling.

The vfuncs don't do anything, this is just the infrastructure.

gtk/gtklistbase.c
gtk/gtklistbaseprivate.h
gtk/gtklistheaderbase.c [new file with mode: 0644]
gtk/gtklistheaderbaseprivate.h [new file with mode: 0644]
gtk/gtklistitemmanager.c
gtk/gtklistitemmanagerprivate.h
gtk/meson.build
testsuite/gtk/listitemmanager.c

index 0a7dbb0b025d7080dd67783cddf409c31bda774c..00ac9c571d9b8dbcf2e8c67b9d402689df2941d9 100644 (file)
@@ -1959,11 +1959,25 @@ gtk_list_base_split_func (GtkWidget   *widget,
 }
 
 static GtkListItemBase *
-gtk_list_base_create_widget_func (GtkWidget *widget)
+gtk_list_base_create_list_widget_func (GtkWidget *widget)
 {
   return GTK_LIST_BASE_GET_CLASS (widget)->create_list_widget (GTK_LIST_BASE (widget));
 }
 
+static void
+gtk_list_base_prepare_section_func (GtkWidget   *widget,
+                                    GtkListTile *tile,
+                                    guint        pos)
+{
+  GTK_LIST_BASE_GET_CLASS (widget)->prepare_section (GTK_LIST_BASE (widget), tile, pos);
+}
+
+static GtkListHeaderBase *
+gtk_list_base_create_header_widget_func (GtkWidget *widget)
+{
+  return GTK_LIST_BASE_GET_CLASS (widget)->create_header_widget (GTK_LIST_BASE (widget));
+}
+
 static void
 gtk_list_base_init_real (GtkListBase      *self,
                          GtkListBaseClass *g_class)
@@ -1973,7 +1987,9 @@ gtk_list_base_init_real (GtkListBase      *self,
 
   priv->item_manager = gtk_list_item_manager_new (GTK_WIDGET (self),
                                                   gtk_list_base_split_func,
-                                                  gtk_list_base_create_widget_func);
+                                                  gtk_list_base_create_list_widget_func,
+                                                  gtk_list_base_prepare_section_func,
+                                                  gtk_list_base_create_header_widget_func);
   priv->anchor = gtk_list_item_tracker_new (priv->item_manager);
   priv->anchor_side_along = GTK_PACK_START;
   priv->anchor_side_across = GTK_PACK_START;
index 7aa596ffde423557ea924003305aeb65531f1b60..fad3872cdc09433de5e255a687a3c98fe58640bf 100644 (file)
@@ -37,6 +37,10 @@ struct _GtkListBaseClass
                                                                  GtkListTile            *tile,
                                                                  guint                   n_items);
   GtkListItemBase *    (* create_list_widget)                   (GtkListBase            *self);
+  void                 (* prepare_section)                      (GtkListBase            *self,
+                                                                 GtkListTile            *tile,
+                                                                 guint                   position);
+  GtkListHeaderBase *  (* create_header_widget)                 (GtkListBase            *self);
 
   gboolean             (* get_allocation)                       (GtkListBase            *self,
                                                                  guint                   pos,
diff --git a/gtk/gtklistheaderbase.c b/gtk/gtklistheaderbase.c
new file mode 100644 (file)
index 0000000..2ba119e
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright © 2023 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include "config.h"
+
+#include "gtklistheaderbaseprivate.h"
+
+typedef struct _GtkListHeaderBasePrivate GtkListHeaderBasePrivate;
+struct _GtkListHeaderBasePrivate
+{
+  GObject *item;
+  guint start;
+  guint end;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkListHeaderBase, gtk_list_header_base, GTK_TYPE_WIDGET)
+
+static void
+gtk_list_header_base_default_update (GtkListHeaderBase *self,
+                                     gpointer           item,
+                                     guint              start,
+                                     guint              end)
+{
+  GtkListHeaderBasePrivate *priv = gtk_list_header_base_get_instance_private (self);
+
+  g_set_object (&priv->item, item);
+  priv->start = start;
+  priv->end = end;
+}
+
+static void
+gtk_list_header_base_dispose (GObject *object)
+{
+  GtkListHeaderBase *self = GTK_LIST_HEADER_BASE (object);
+  GtkListHeaderBasePrivate *priv = gtk_list_header_base_get_instance_private (self);
+
+  g_clear_object (&priv->item);
+
+  G_OBJECT_CLASS (gtk_list_header_base_parent_class)->dispose (object);
+}
+
+static void
+gtk_list_header_base_class_init (GtkListHeaderBaseClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  klass->update = gtk_list_header_base_default_update;
+
+  gobject_class->dispose = gtk_list_header_base_dispose;
+}
+
+static void
+gtk_list_header_base_init (GtkListHeaderBase *self)
+{
+}
+
+void
+gtk_list_header_base_update (GtkListHeaderBase *self,
+                             gpointer           item,
+                             guint              start,
+                             guint              end)
+{
+  GTK_LIST_HEADER_BASE_GET_CLASS (self)->update (self, item, start, end);
+}
+
+guint
+gtk_list_header_base_get_start (GtkListHeaderBase *self)
+{
+  GtkListHeaderBasePrivate *priv = gtk_list_header_base_get_instance_private (self);
+
+  return priv->start;
+}
+
+guint
+gtk_list_header_base_get_end (GtkListHeaderBase *self)
+{
+  GtkListHeaderBasePrivate *priv = gtk_list_header_base_get_instance_private (self);
+
+  return priv->end;
+}
+
+gpointer
+gtk_list_header_base_get_item (GtkListHeaderBase *self)
+{
+  GtkListHeaderBasePrivate *priv = gtk_list_header_base_get_instance_private (self);
+
+  return priv->item;
+}
+
diff --git a/gtk/gtklistheaderbaseprivate.h b/gtk/gtklistheaderbaseprivate.h
new file mode 100644 (file)
index 0000000..fa3fa45
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2023 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#pragma once
+
+#include "gtkwidget.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_LIST_HEADER_BASE         (gtk_list_header_base_get_type ())
+#define GTK_LIST_HEADER_BASE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_LIST_HEADER_BASE, GtkListHeaderBase))
+#define GTK_LIST_HEADER_BASE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_LIST_HEADER_BASE, GtkListHeaderBaseClass))
+#define GTK_IS_LIST_HEADER_BASE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_LIST_HEADER_BASE))
+#define GTK_IS_LIST_HEADER_BASE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_LIST_HEADER_BASE))
+#define GTK_LIST_HEADER_BASE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_LIST_HEADER_BASE, GtkListHeaderBaseClass))
+
+typedef struct _GtkListHeaderBase GtkListHeaderBase;
+typedef struct _GtkListHeaderBaseClass GtkListHeaderBaseClass;
+
+struct _GtkListHeaderBase
+{
+  GtkWidget parent_instance;
+};
+
+struct _GtkListHeaderBaseClass
+{
+  GtkWidgetClass parent_class;
+
+  void                  (* update)                              (GtkListHeaderBase      *self,
+                                                                 gpointer                item,
+                                                                 guint                   start,
+                                                                 guint                   end);
+};
+
+GType                   gtk_list_header_base_get_type           (void) G_GNUC_CONST;
+
+void                    gtk_list_header_base_update             (GtkListHeaderBase      *self,
+                                                                 gpointer                item,
+                                                                 guint                   start,
+                                                                 guint                   end);
+
+guint                   gtk_list_header_base_get_start          (GtkListHeaderBase      *self);
+guint                   gtk_list_header_base_get_end            (GtkListHeaderBase      *self);
+gpointer                gtk_list_header_base_get_item           (GtkListHeaderBase      *self);
+
+G_END_DECLS
+
index a9c15982b3b5bd85db2d1a5e8c70ea0457f54669..66ff55feddd88417be6932992470ff0320138942 100644 (file)
@@ -39,6 +39,8 @@ struct _GtkListItemManager
 
   GtkListTile * (* split_func) (GtkWidget *, GtkListTile *, guint);
   GtkListItemBase * (* create_widget) (GtkWidget *);
+  void (* prepare_section) (GtkWidget *, GtkListTile *, guint);
+  GtkListHeaderBase * (* create_header_widget) (GtkWidget *);
 };
 
 struct _GtkListItemManagerClass
@@ -156,9 +158,11 @@ gtk_list_item_manager_clear_node (gpointer _tile)
 }
 
 GtkListItemManager *
-gtk_list_item_manager_new (GtkWidget         *widget,
-                           GtkListTile *      (* split_func) (GtkWidget *, GtkListTile *, guint),
-                           GtkListItemBase *  (* create_widget) (GtkWidget *))
+gtk_list_item_manager_new (GtkWidget          *widget,
+                           GtkListTile *       (* split_func) (GtkWidget *, GtkListTile *, guint),
+                           GtkListItemBase *   (* create_widget) (GtkWidget *),
+                           void                (* prepare_section) (GtkWidget *, GtkListTile *, guint),
+                           GtkListHeaderBase * (* create_header_widget) (GtkWidget *))
 {
   GtkListItemManager *self;
 
@@ -170,6 +174,8 @@ gtk_list_item_manager_new (GtkWidget         *widget,
   self->widget = widget;
   self->split_func = split_func;
   self->create_widget = create_widget;
+  self->prepare_section = prepare_section;
+  self->create_header_widget = create_header_widget;
 
   self->items = gtk_rb_tree_new_for_size (sizeof (GtkListTile),
                                           sizeof (GtkListTileAugment),
@@ -1141,6 +1147,8 @@ gtk_list_item_manager_insert_section (GtkListItemManager *self,
     }
   else
     {
+      self->prepare_section (self->widget, tile, pos);
+
       other = gtk_rb_tree_insert_before (self->items, tile);
       gtk_list_tile_set_type (other, header_type);
       other = gtk_rb_tree_insert_before (self->items, other);
index 29d24a4925d36dfeb27e5df86c0e92ba35171d16..cc92ef74a9db6145a7ffa0496d170cd4d32cd9f3 100644 (file)
@@ -24,6 +24,7 @@
 #include "gtk/gtkenums.h"
 
 #include "gtk/gtklistitembaseprivate.h"
+#include "gtk/gtklistheaderbaseprivate.h"
 #include "gtk/gtklistitemfactory.h"
 #include "gtk/gtkrbtreeprivate.h"
 #include "gtk/gtkselectionmodel.h"
@@ -79,7 +80,9 @@ GType                   gtk_list_item_manager_get_type          (void) G_GNUC_CO
 
 GtkListItemManager *    gtk_list_item_manager_new               (GtkWidget              *widget,
                                                                  GtkListTile *           (* split_func) (GtkWidget *, GtkListTile *, guint),
-                                                                 GtkListItemBase *       (* create_widget) (GtkWidget *));
+                                                                 GtkListItemBase *       (* create_widget) (GtkWidget *),
+                                                                 void                    (* prepare_section) (GtkWidget *, GtkListTile *, guint),
+                                                                 GtkListHeaderBase *     (* create_header_widget) (GtkWidget *));
 
 void                    gtk_list_item_manager_get_tile_bounds   (GtkListItemManager     *self,
                                                                  GdkRectangle           *out_bounds);
index 1ea9b37e25a3eff7921ddcd43bb91402b00fc9b3..9f6a6dd57cbd7688c9538463daa84de17a05da3a 100644 (file)
@@ -271,6 +271,7 @@ gtk_public_sources = files([
   'gtklinkbutton.c',
   'gtklistbox.c',
   'gtklistfactorywidget.c',
+  'gtklistheaderbase.c',
   'gtklistitem.c',
   'gtklistitembase.c',
   'gtklistitemfactory.c',
index 828a2817456776ce3a5017b92f6fc07a8097564f..d883aca0639f2d4ec17661e17cd27c2a91bed754 100644 (file)
@@ -270,12 +270,25 @@ split_simple (GtkWidget   *widget,
   return gtk_list_tile_split (items, tile, n_items);
 }
 
+static void
+prepare_simple (GtkWidget   *widget,
+                GtkListTile *tile,
+                guint        n_items)
+{
+}
+
 static GtkListItemBase *
-create_simple (GtkWidget *widget)
+create_simple_item (GtkWidget *widget)
 {
   return g_object_new (GTK_TYPE_LIST_ITEM_BASE, NULL);
 }
 
+static GtkListHeaderBase *
+create_simple_header (GtkWidget *widget)
+{
+  return g_object_new (GTK_TYPE_LIST_HEADER_BASE, NULL);
+}
+
 static void
 test_create (void)
 {
@@ -285,7 +298,9 @@ test_create (void)
   widget = gtk_window_new ();
   items = gtk_list_item_manager_new (widget,
                                      split_simple,
-                                     create_simple);
+                                     create_simple_item,
+                                     prepare_simple,
+                                     create_simple_header);
   g_object_set_data_full (G_OBJECT (widget), "the-items", items, g_object_unref);
 
   gtk_window_destroy (GTK_WINDOW (widget));
@@ -302,7 +317,9 @@ test_create_with_items (void)
   widget = gtk_window_new ();
   items = gtk_list_item_manager_new (widget,
                                      split_simple,
-                                     create_simple);
+                                     create_simple_item,
+                                     prepare_simple,
+                                     create_simple_header);
   g_object_set_data_full (G_OBJECT (widget), "the-items", items, g_object_unref);
 
   source = create_source_model (1, 50);
@@ -352,7 +369,9 @@ test_exhaustive (void)
   widget = gtk_window_new ();
   items = gtk_list_item_manager_new (widget,
                                      split_simple,
-                                     create_simple);
+                                     create_simple_item,
+                                     prepare_simple,
+                                     create_simple_header);
   for (i = 0; i < N_TRACKERS; i++)
     trackers[i] = gtk_list_item_tracker_new (items);