From 38844fef4d798feb1908e341a7f69b600e4c7706 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 9 Apr 2023 14:24:26 +0200 Subject: listitemmanager: Add GtkListHeaderBase and vfuncs This is plumbing for section handling. The vfuncs don't do anything, this is just the infrastructure. --- gtk/gtklistbase.c | 20 +++++++- gtk/gtklistbaseprivate.h | 4 ++ gtk/gtklistheaderbase.c | 105 ++++++++++++++++++++++++++++++++++++++++ gtk/gtklistheaderbaseprivate.h | 63 ++++++++++++++++++++++++ gtk/gtklistitemmanager.c | 14 ++++-- gtk/gtklistitemmanagerprivate.h | 5 +- gtk/meson.build | 1 + testsuite/gtk/listitemmanager.c | 27 +++++++++-- 8 files changed, 229 insertions(+), 10 deletions(-) create mode 100644 gtk/gtklistheaderbase.c create mode 100644 gtk/gtklistheaderbaseprivate.h diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c index 0a7dbb0b02..00ac9c571d 100644 --- a/gtk/gtklistbase.c +++ b/gtk/gtklistbase.c @@ -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; diff --git a/gtk/gtklistbaseprivate.h b/gtk/gtklistbaseprivate.h index 7aa596ffde..fad3872cdc 100644 --- a/gtk/gtklistbaseprivate.h +++ b/gtk/gtklistbaseprivate.h @@ -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 index 0000000000..2ba119e665 --- /dev/null +++ b/gtk/gtklistheaderbase.c @@ -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 . + * + * Authors: Benjamin Otte + */ + +#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 index 0000000000..fa3fa45f22 --- /dev/null +++ b/gtk/gtklistheaderbaseprivate.h @@ -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 . + * + * Authors: Benjamin Otte + */ + +#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 + diff --git a/gtk/gtklistitemmanager.c b/gtk/gtklistitemmanager.c index a9c15982b3..66ff55fedd 100644 --- a/gtk/gtklistitemmanager.c +++ b/gtk/gtklistitemmanager.c @@ -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); diff --git a/gtk/gtklistitemmanagerprivate.h b/gtk/gtklistitemmanagerprivate.h index 29d24a4925..cc92ef74a9 100644 --- a/gtk/gtklistitemmanagerprivate.h +++ b/gtk/gtklistitemmanagerprivate.h @@ -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); diff --git a/gtk/meson.build b/gtk/meson.build index 1ea9b37e25..9f6a6dd57c 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -271,6 +271,7 @@ gtk_public_sources = files([ 'gtklinkbutton.c', 'gtklistbox.c', 'gtklistfactorywidget.c', + 'gtklistheaderbase.c', 'gtklistitem.c', 'gtklistitembase.c', 'gtklistitemfactory.c', diff --git a/testsuite/gtk/listitemmanager.c b/testsuite/gtk/listitemmanager.c index 828a281745..d883aca063 100644 --- a/testsuite/gtk/listitemmanager.c +++ b/testsuite/gtk/listitemmanager.c @@ -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); -- cgit v1.2.1