listitemfactory: Simplify

Instead of 6 vfuncs, we now have 3 and rely on the factory keeping track
of what it needs to do.

We're doing lots of dancing from one object to another here, but this
will hopefully get simpler with further commits.
This commit is contained in:
Benjamin Otte 2019-11-03 02:23:46 +01:00 committed by Matthias Clasen
parent b33c56819b
commit 1af004361c
9 changed files with 127 additions and 56 deletions

View File

@ -84,13 +84,14 @@ static GParamSpec *properties[N_PROPS] = { NULL, };
static void
gtk_builder_list_item_factory_setup (GtkListItemFactory *factory,
GtkListItemWidget *widget,
GtkListItem *list_item)
{
GtkBuilderListItemFactory *self = GTK_BUILDER_LIST_ITEM_FACTORY (factory);
GtkBuilder *builder;
GError *error = NULL;
GTK_LIST_ITEM_FACTORY_CLASS (gtk_builder_list_item_factory_parent_class)->setup (factory, list_item);
GTK_LIST_ITEM_FACTORY_CLASS (gtk_builder_list_item_factory_parent_class)->setup (factory, widget, list_item);
builder = gtk_builder_new ();

View File

@ -43,18 +43,23 @@ G_DEFINE_TYPE (GtkFunctionsListItemFactory, gtk_functions_list_item_factory, GTK
static void
gtk_functions_list_item_factory_setup (GtkListItemFactory *factory,
GtkListItemWidget *widget,
GtkListItem *list_item)
{
GtkFunctionsListItemFactory *self = GTK_FUNCTIONS_LIST_ITEM_FACTORY (factory);
GTK_LIST_ITEM_FACTORY_CLASS (gtk_functions_list_item_factory_parent_class)->setup (factory, list_item);
if (self->setup_func)
self->setup_func (list_item, self->user_data);
GTK_LIST_ITEM_FACTORY_CLASS (gtk_functions_list_item_factory_parent_class)->setup (factory, widget, list_item);
if (gtk_list_item_get_item (list_item) != NULL && self->bind_func)
self->bind_func (list_item, self->user_data);
}
static void
gtk_functions_list_item_factory_update (GtkListItemFactory *factory,
GtkListItemWidget *widget,
GtkListItem *list_item,
guint position,
gpointer item,
@ -62,7 +67,7 @@ gtk_functions_list_item_factory_update (GtkListItemFactory *factory,
{
GtkFunctionsListItemFactory *self = GTK_FUNCTIONS_LIST_ITEM_FACTORY (factory);
GTK_LIST_ITEM_FACTORY_CLASS (gtk_functions_list_item_factory_parent_class)->update (factory, list_item, position, item, selected);
GTK_LIST_ITEM_FACTORY_CLASS (gtk_functions_list_item_factory_parent_class)->update (factory, widget, list_item, position, item, selected);
if (item != NULL && self->bind_func)
self->bind_func (list_item, self->user_data);

View File

@ -239,17 +239,10 @@ gtk_list_item_init (GtkListItem *self)
}
GtkListItem *
gtk_list_item_new (GtkListItemWidget *owner)
gtk_list_item_new (void)
{
GtkListItem *result;
g_return_val_if_fail (owner != NULL, NULL);
result = g_object_new (GTK_TYPE_LIST_ITEM,
NULL);
result->owner = owner;
return result;
return g_object_new (GTK_TYPE_LIST_ITEM,
NULL);
}
/**

View File

@ -75,29 +75,31 @@ G_DEFINE_TYPE (GtkListItemFactory, gtk_list_item_factory, G_TYPE_OBJECT)
static void
gtk_list_item_factory_default_setup (GtkListItemFactory *self,
GtkListItemWidget *widget,
GtkListItem *list_item)
{
gtk_list_item_widget_default_setup (widget, list_item);
}
static void
gtk_list_item_factory_default_teardown (GtkListItemFactory *self,
GtkListItemWidget *widget,
GtkListItem *list_item)
{
gtk_list_item_set_child (list_item, NULL);
gtk_list_item_set_selectable (list_item, TRUE);
gtk_list_item_widget_default_teardown (widget, list_item);
gtk_list_item_set_child (list_item, NULL);
}
static void
gtk_list_item_factory_default_update (GtkListItemFactory *self,
GtkListItemWidget *widget,
GtkListItem *list_item,
guint position,
gpointer item,
gboolean selected)
{
gtk_list_item_set_item (list_item, item);
gtk_list_item_set_position (list_item, position);
gtk_list_item_set_selected (list_item, selected);
gtk_list_item_widget_default_update (widget, list_item, position, item, selected);
}
static void
@ -115,35 +117,49 @@ gtk_list_item_factory_init (GtkListItemFactory *self)
void
gtk_list_item_factory_setup (GtkListItemFactory *self,
GtkListItem *list_item)
GtkListItemWidget *widget)
{
GtkListItem *list_item;
g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (self));
GTK_LIST_ITEM_FACTORY_GET_CLASS (self)->setup (self, list_item);
list_item = gtk_list_item_new ();
GTK_LIST_ITEM_FACTORY_GET_CLASS (self)->setup (self, widget, list_item);
}
void
gtk_list_item_factory_teardown (GtkListItemFactory *self,
GtkListItem *list_item)
GtkListItemWidget *widget)
{
GtkListItem *list_item;
g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (self));
GTK_LIST_ITEM_FACTORY_GET_CLASS (self)->teardown (self, list_item);
list_item = gtk_list_item_widget_get_list_item (widget);
GTK_LIST_ITEM_FACTORY_GET_CLASS (self)->teardown (self, widget, list_item);
g_object_unref (list_item);
}
void
gtk_list_item_factory_update (GtkListItemFactory *self,
GtkListItem *list_item,
GtkListItemWidget *widget,
guint position,
gpointer item,
gboolean selected)
{
GtkListItem *list_item;
g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (self));
g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
g_return_if_fail (GTK_IS_LIST_ITEM_WIDGET (widget));
list_item = gtk_list_item_widget_get_list_item (widget);
g_object_freeze_notify (G_OBJECT (list_item));
GTK_LIST_ITEM_FACTORY_GET_CLASS (self)->update (self, list_item, position, item, selected);
GTK_LIST_ITEM_FACTORY_GET_CLASS (self)->update (self, widget, list_item, position, item, selected);
g_object_thaw_notify (G_OBJECT (list_item));
}

View File

@ -22,8 +22,7 @@
#define __GTK_LIST_ITEM_FACTORY_PRIVATE_H__
#include <gtk/gtklistitem.h>
#include <gtk/gtklistitemfactory.h>
#include <gtk/gtklistview.h>
#include "gtk/gtklistitemwidgetprivate.h"
G_BEGIN_DECLS
@ -38,14 +37,17 @@ struct _GtkListItemFactoryClass
/* setup @list_item so it can be bound */
void (* setup) (GtkListItemFactory *self,
GtkListItemWidget *widget,
GtkListItem *list_item);
/* undo the effects of GtkListItemFactoryClass::setup() */
void (* teardown) (GtkListItemFactory *self,
GtkListItemWidget *widget,
GtkListItem *list_item);
/* Update properties on @list_item to the given @item, which is in @position and @selected state.
* One or more of those properties might be unchanged. */
void (* update) (GtkListItemFactory *self,
GtkListItemWidget *widget,
GtkListItem *list_item,
guint position,
gpointer item,
@ -53,12 +55,12 @@ struct _GtkListItemFactoryClass
};
void gtk_list_item_factory_setup (GtkListItemFactory *self,
GtkListItem *list_item);
GtkListItemWidget *widget);
void gtk_list_item_factory_teardown (GtkListItemFactory *self,
GtkListItem *list_item);
GtkListItemWidget *widget);
void gtk_list_item_factory_update (GtkListItemFactory *self,
GtkListItem *list_item,
GtkListItemWidget *widget,
guint position,
gpointer item,
gboolean selected);

View File

@ -41,7 +41,7 @@ struct _GtkListItem
guint selected : 1;
};
GtkListItem * gtk_list_item_new (GtkListItemWidget *owner);
GtkListItem * gtk_list_item_new (void);
void gtk_list_item_set_item (GtkListItem *self,
gpointer item);

View File

@ -106,9 +106,8 @@ gtk_list_item_widget_dispose (GObject *object)
if (self->item)
{
gtk_list_item_factory_teardown (self->factory, self->item);
self->item->owner = NULL;
g_clear_object (&self->item);
gtk_list_item_factory_teardown (self->factory, self);
g_assert (self->item == NULL);
}
g_clear_object (&self->factory);
@ -313,8 +312,6 @@ gtk_list_item_widget_init (GtkListItemWidget *self)
controller = gtk_event_controller_focus_new ();
g_signal_connect (controller, "enter", G_CALLBACK (gtk_list_item_widget_enter_cb), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
self->item = gtk_list_item_new (self);
}
GtkWidget *
@ -332,7 +329,8 @@ gtk_list_item_widget_new (GtkListItemFactory *factory,
{
result->factory = g_object_ref (factory);
gtk_list_item_factory_setup (factory, result->item);
gtk_list_item_factory_setup (factory, result);
g_assert (result->item != NULL);
}
return GTK_WIDGET (result);
@ -344,7 +342,8 @@ gtk_list_item_widget_update (GtkListItemWidget *self,
gpointer item,
gboolean selected)
{
gtk_list_item_factory_update (self->factory, self->item, position, item, selected);
if (self->factory)
gtk_list_item_factory_update (self->factory, self, position, item, selected);
if (selected)
gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED, FALSE);
@ -352,6 +351,42 @@ gtk_list_item_widget_update (GtkListItemWidget *self,
gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED);
}
void
gtk_list_item_widget_default_setup (GtkListItemWidget *self,
GtkListItem *list_item)
{
self->item = list_item;
list_item->owner = self;
if (list_item->child)
gtk_list_item_widget_add_child (self, list_item->child);
}
void
gtk_list_item_widget_default_teardown (GtkListItemWidget *self,
GtkListItem *list_item)
{
g_assert (self->item == list_item);
self->item = NULL;
list_item->owner = NULL;
if (list_item->child)
gtk_list_item_widget_remove_child (self, list_item->child);
}
void
gtk_list_item_widget_default_update (GtkListItemWidget *self,
GtkListItem *list_item,
guint position,
gpointer item,
gboolean selected)
{
gtk_list_item_set_item (list_item, item);
gtk_list_item_set_position (list_item, position);
gtk_list_item_set_selected (list_item, selected);
}
void
gtk_list_item_widget_add_child (GtkListItemWidget *self,
GtkWidget *child)
@ -366,6 +401,12 @@ gtk_list_item_widget_remove_child (GtkListItemWidget *self,
gtk_widget_unparent (child);
}
GtkListItem *
gtk_list_item_widget_get_list_item (GtkListItemWidget *self)
{
return self->item;
}
guint
gtk_list_item_widget_get_position (GtkListItemWidget *self)
{

View File

@ -59,6 +59,17 @@ void gtk_list_item_widget_update (GtkListItemWidg
guint position,
gpointer item,
gboolean selected);
GtkListItem * gtk_list_item_widget_get_list_item (GtkListItemWidget *self);
void gtk_list_item_widget_default_setup (GtkListItemWidget *self,
GtkListItem *list_item);
void gtk_list_item_widget_default_teardown (GtkListItemWidget *self,
GtkListItem *list_item);
void gtk_list_item_widget_default_update (GtkListItemWidget *self,
GtkListItem *list_item,
guint position,
gpointer item,
gboolean selected);
void gtk_list_item_widget_add_child (GtkListItemWidget *self,
GtkWidget *child);

View File

@ -81,18 +81,14 @@ struct _GtkSignalListItemFactoryClass
{
GtkListItemFactoryClass parent_class;
void (* setup) (GtkListItemFactory *self,
GtkListItem *list_item);
void (* teardown) (GtkListItemFactory *self,
GtkListItem *list_item);
void (* bind) (GtkListItemFactory *self,
GtkListItem *list_item,
guint position,
gpointer item,
gboolean selected);
void (* unbind) (GtkListItemFactory *self,
GtkListItem *list_item);
void (* setup) (GtkSignalListItemFactory *self,
GtkListItem *list_item);
void (* teardown) (GtkSignalListItemFactory *self,
GtkListItem *list_item);
void (* bind) (GtkSignalListItemFactory *self,
GtkListItem *list_item);
void (* unbind) (GtkSignalListItemFactory *self,
GtkListItem *list_item);
};
enum {
@ -109,15 +105,20 @@ static guint signals[LAST_SIGNAL] = { 0 };
static void
gtk_signal_list_item_factory_setup (GtkListItemFactory *factory,
GtkListItemWidget *widget,
GtkListItem *list_item)
{
GTK_LIST_ITEM_FACTORY_CLASS (gtk_signal_list_item_factory_parent_class)->setup (factory, list_item);
g_signal_emit (factory, signals[SETUP], 0, list_item);
GTK_LIST_ITEM_FACTORY_CLASS (gtk_signal_list_item_factory_parent_class)->setup (factory, widget, list_item);
if (gtk_list_item_get_item (list_item))
g_signal_emit (factory, signals[BIND], 0, list_item);
}
static void
gtk_signal_list_item_factory_update (GtkListItemFactory *factory,
GtkListItemWidget *widget,
GtkListItem *list_item,
guint position,
gpointer item,
@ -126,7 +127,7 @@ gtk_signal_list_item_factory_update (GtkListItemFactory *factory,
if (gtk_list_item_get_item (list_item))
g_signal_emit (factory, signals[UNBIND], 0, list_item);
GTK_LIST_ITEM_FACTORY_CLASS (gtk_signal_list_item_factory_parent_class)->update (factory, list_item, position, item, selected);
GTK_LIST_ITEM_FACTORY_CLASS (gtk_signal_list_item_factory_parent_class)->update (factory, widget, list_item, position, item, selected);
if (item)
g_signal_emit (factory, signals[BIND], 0, list_item);
@ -134,14 +135,15 @@ gtk_signal_list_item_factory_update (GtkListItemFactory *factory,
static void
gtk_signal_list_item_factory_teardown (GtkListItemFactory *factory,
GtkListItemWidget *widget,
GtkListItem *list_item)
{
if (gtk_list_item_get_item (list_item))
g_signal_emit (factory, signals[UNBIND], 0, list_item);
g_signal_emit (factory, signals[TEARDOWN], 0, list_item);
GTK_LIST_ITEM_FACTORY_CLASS (gtk_signal_list_item_factory_parent_class)->teardown (factory, widget, list_item);
GTK_LIST_ITEM_FACTORY_CLASS (gtk_signal_list_item_factory_parent_class)->teardown (factory, list_item);
g_signal_emit (factory, signals[TEARDOWN], 0, list_item);
}
static void