listitem: Move position/item/selected tracking to widget

This way, we can ensure it's always there when we need it (before the
item gets created) and gone when we don't (if some GC language holds on
to the item after we've destroyed the widget).
This commit is contained in:
Benjamin Otte 2019-11-03 03:34:56 +01:00 committed by Matthias Clasen
parent 32eedec565
commit 9d86020d4c
3 changed files with 72 additions and 75 deletions

View File

@ -98,11 +98,15 @@ gtk_list_item_get_property (GObject *object,
break;
case PROP_ITEM:
g_value_set_object (value, self->item);
if (self->owner)
g_value_set_object (value, gtk_list_item_widget_get_item (self->owner));
break;
case PROP_POSITION:
g_value_set_uint (value, self->position);
if (self->owner)
g_value_set_uint (value, gtk_list_item_widget_get_position (self->owner));
else
g_value_set_uint (value, GTK_INVALID_LIST_POSITION);
break;
case PROP_SELECTABLE:
@ -110,7 +114,10 @@ gtk_list_item_get_property (GObject *object,
break;
case PROP_SELECTED:
g_value_set_boolean (value, self->selected);
if (self->owner)
g_value_set_boolean (value, gtk_list_item_widget_get_selected (self->owner));
else
g_value_set_boolean (value, FALSE);
break;
default:
@ -259,7 +266,10 @@ gtk_list_item_get_item (GtkListItem *self)
{
g_return_val_if_fail (GTK_IS_LIST_ITEM (self), NULL);
return self->item;
if (self->owner == NULL)
return NULL;
return gtk_list_item_widget_get_item (self->owner);
}
/**
@ -316,23 +326,6 @@ gtk_list_item_set_child (GtkListItem *self,
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ITEM]);
}
void
gtk_list_item_set_item (GtkListItem *self,
gpointer item)
{
g_return_if_fail (GTK_IS_LIST_ITEM (self));
g_return_if_fail (item == NULL || G_IS_OBJECT (item));
if (self->item == item)
return;
g_clear_object (&self->item);
if (item)
self->item = g_object_ref (item);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ITEM]);
}
/**
* gtk_list_item_get_position:
* @self: a #GtkListItem
@ -345,23 +338,12 @@ gtk_list_item_set_item (GtkListItem *self,
guint
gtk_list_item_get_position (GtkListItem *self)
{
g_return_val_if_fail (GTK_IS_LIST_ITEM (self), 0);
g_return_val_if_fail (GTK_IS_LIST_ITEM (self), GTK_INVALID_LIST_POSITION);
return self->position;
}
if (self->owner == NULL)
return GTK_INVALID_LIST_POSITION;
void
gtk_list_item_set_position (GtkListItem *self,
guint position)
{
g_return_if_fail (GTK_IS_LIST_ITEM (self));
if (self->position == position)
return;
self->position = position;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_POSITION]);
return gtk_list_item_widget_get_position (self->owner);
}
/**
@ -379,21 +361,10 @@ gtk_list_item_get_selected (GtkListItem *self)
{
g_return_val_if_fail (GTK_IS_LIST_ITEM (self), FALSE);
return self->selected;
}
if (self->owner == NULL)
return FALSE;
void
gtk_list_item_set_selected (GtkListItem *self,
gboolean selected)
{
g_return_if_fail (GTK_IS_LIST_ITEM (self));
if (self->selected == selected)
return;
self->selected = selected;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
return gtk_list_item_widget_get_selected (self->owner);
}
/**

View File

@ -32,23 +32,14 @@ struct _GtkListItem
GtkListItemWidget *owner; /* has a reference */
GObject *item;
GtkWidget *child;
guint position;
guint activatable : 1;
guint selectable : 1;
guint selected : 1;
};
GtkListItem * gtk_list_item_new (void);
void gtk_list_item_set_item (GtkListItem *self,
gpointer item);
void gtk_list_item_set_position (GtkListItem *self,
guint position);
void gtk_list_item_set_selected (GtkListItem *self,
gboolean selected);
G_END_DECLS

View File

@ -29,6 +29,7 @@
#include "gtklistitemfactoryprivate.h"
#include "gtklistitemprivate.h"
#include "gtkmain.h"
#include "gtkselectionmodel.h"
#include "gtkwidget.h"
#include "gtkwidgetprivate.h"
@ -37,6 +38,10 @@ struct _GtkListItemWidgetPrivate
{
GtkListItemFactory *factory;
GtkListItem *list_item;
GObject *item;
guint position;
gboolean selected;
};
enum
@ -54,13 +59,13 @@ gtk_list_item_widget_activate_signal (GtkListItemWidget *self)
{
GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
if (!priv->list_item->activatable)
if (priv->list_item && !priv->list_item->activatable)
return;
gtk_widget_activate_action (GTK_WIDGET (self),
"list.activate-item",
"u",
priv->list_item->position);
priv->position);
}
static gboolean
@ -121,6 +126,7 @@ gtk_list_item_widget_dispose (GObject *object)
gtk_list_item_factory_teardown (priv->factory, self);
g_assert (priv->list_item == NULL);
}
g_clear_object (&priv->item);
g_clear_object (&priv->factory);
G_OBJECT_CLASS (gtk_list_item_widget_parent_class)->dispose (object);
@ -135,7 +141,7 @@ gtk_list_item_widget_select_action (GtkWidget *widget,
GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
gboolean modify, extend;
if (!priv->list_item->selectable)
if (priv->list_item && !priv->list_item->selectable)
return;
g_variant_get (parameter, "(bb)", &modify, &extend);
@ -143,7 +149,7 @@ gtk_list_item_widget_select_action (GtkWidget *widget,
gtk_widget_activate_action (GTK_WIDGET (self),
"list.select-item",
"(ubb)",
priv->list_item->position, modify, extend);
priv->position, modify, extend);
}
static void
@ -229,13 +235,13 @@ gtk_list_item_widget_click_gesture_pressed (GtkGestureClick *gesture,
GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
GtkWidget *widget = GTK_WIDGET (self);
if (!priv->list_item->selectable && !priv->list_item->activatable)
if (priv->list_item && !priv->list_item->selectable && !priv->list_item->activatable)
{
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
return;
}
if (priv->list_item->selectable)
if (!priv->list_item || priv->list_item->selectable)
{
GdkModifierType state;
GdkEvent *event;
@ -250,17 +256,17 @@ gtk_list_item_widget_click_gesture_pressed (GtkGestureClick *gesture,
gtk_widget_activate_action (GTK_WIDGET (self),
"list.select-item",
"(ubb)",
priv->list_item->position, modify, extend);
priv->position, modify, extend);
}
if (priv->list_item->activatable)
if (!priv->list_item || priv->list_item->activatable)
{
if (n_press == 2)
{
gtk_widget_activate_action (GTK_WIDGET (self),
"list.activate-item",
"u",
priv->list_item->position);
priv->position);
}
}
@ -280,7 +286,7 @@ gtk_list_item_widget_enter_cb (GtkEventControllerFocus *controller,
gtk_widget_activate_action (widget,
"list.scroll-to-item",
"u",
priv->list_item->position);
priv->position);
}
static void
@ -381,6 +387,13 @@ gtk_list_item_widget_default_setup (GtkListItemWidget *self,
if (list_item->child)
gtk_list_item_widget_add_child (self, list_item->child);
if (priv->item)
g_object_notify (G_OBJECT (list_item), "item");
if (priv->position != GTK_INVALID_LIST_POSITION)
g_object_notify (G_OBJECT (list_item), "position");
if (priv->selected)
g_object_notify (G_OBJECT (list_item), "selected");
}
void
@ -396,6 +409,13 @@ gtk_list_item_widget_default_teardown (GtkListItemWidget *self,
if (list_item->child)
gtk_list_item_widget_remove_child (self, list_item->child);
if (priv->item)
g_object_notify (G_OBJECT (list_item), "item");
if (priv->position != GTK_INVALID_LIST_POSITION)
g_object_notify (G_OBJECT (list_item), "position");
if (priv->selected)
g_object_notify (G_OBJECT (list_item), "selected");
}
void
@ -405,9 +425,24 @@ gtk_list_item_widget_default_update (GtkListItemWidget *self,
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);
GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
/* FIXME: It's kinda evil to notify external objects from here... */
if (g_set_object (&priv->item, item))
g_object_notify (G_OBJECT (list_item), "item");
if (priv->position != position)
{
priv->position = position;
g_object_notify (G_OBJECT (list_item), "position");
}
if (priv->selected != selected)
{
priv->selected = selected;
g_object_notify (G_OBJECT (list_item), "selected");
}
}
void
@ -437,7 +472,7 @@ gtk_list_item_widget_get_position (GtkListItemWidget *self)
{
GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
return priv->list_item->position;
return priv->position;
}
gpointer
@ -445,7 +480,7 @@ gtk_list_item_widget_get_item (GtkListItemWidget *self)
{
GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
return priv->list_item->item;
return priv->item;
}
gboolean
@ -453,6 +488,6 @@ gtk_list_item_widget_get_selected (GtkListItemWidget *self)
{
GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
return priv->list_item->selected;
return priv->selected;
}