listitemmanager: Add GtkListHeaderBase and vfuncs

This is plumbing for section handling.

The vfuncs don't do anything, this is just the infrastructure.
This commit is contained in:
Benjamin Otte
2023-04-09 14:24:26 +02:00
parent c93eaa49b5
commit c474e0ac92
8 changed files with 229 additions and 10 deletions

View File

@@ -1954,11 +1954,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)
@@ -1968,7 +1982,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;

View 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,

105
gtk/gtklistheaderbase.c Normal file
View File

@@ -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;
}

View File

@@ -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

View 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);

View 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);

View File

@@ -271,6 +271,7 @@ gtk_public_sources = files([
'gtklinkbutton.c',
'gtklistbox.c',
'gtklistfactorywidget.c',
'gtklistheaderbase.c',
'gtklistitem.c',
'gtklistitembase.c',
'gtklistitemfactory.c',

View 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);