[gtk/wip/otte/listview: 106/113] listitem: Move position/item/selected tracking to widget



commit d3c6f8e1df505ffc7821f0ef445c24ea895f7b21
Author: Benjamin Otte <otte redhat com>
Date:   Sun Nov 3 03:34:56 2019 +0100

    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).

 gtk/gtklistitem.c        | 65 ++++++++++++----------------------------------
 gtk/gtklistitemprivate.h |  9 -------
 gtk/gtklistitemwidget.c  | 67 ++++++++++++++++++++++++++++++++++++------------
 3 files changed, 67 insertions(+), 74 deletions(-)
---
diff --git a/gtk/gtklistitem.c b/gtk/gtklistitem.c
index 58f26b1937..01175275c8 100644
--- a/gtk/gtklistitem.c
+++ b/gtk/gtklistitem.c
@@ -100,11 +100,13 @@ 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));
       break;
 
     case PROP_SELECTABLE:
@@ -112,7 +114,8 @@ 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));
       break;
 
     default:
@@ -261,7 +264,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);
 }
 
 /**
@@ -318,23 +324,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
@@ -349,21 +338,10 @@ gtk_list_item_get_position (GtkListItem *self)
 {
   g_return_val_if_fail (GTK_IS_LIST_ITEM (self), 0);
 
-  return self->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;
+  if (self->owner == NULL)
+    return GTK_INVALID_LIST_POSITION;
 
-  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_POSITION]);
+  return gtk_list_item_widget_get_position (self->owner);
 }
 
 /**
@@ -381,21 +359,10 @@ gtk_list_item_get_selected (GtkListItem *self)
 {
   g_return_val_if_fail (GTK_IS_LIST_ITEM (self), FALSE);
 
-  return self->selected;
-}
-
-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;
+  if (self->owner == NULL)
+    return FALSE;
 
-  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
+  return gtk_list_item_widget_get_selected (self->owner);
 }
 
 /**
diff --git a/gtk/gtklistitemprivate.h b/gtk/gtklistitemprivate.h
index b84057f838..d8f8833313 100644
--- a/gtk/gtklistitemprivate.h
+++ b/gtk/gtklistitemprivate.h
@@ -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
 
diff --git a/gtk/gtklistitemwidget.c b/gtk/gtklistitemwidget.c
index fe314db13a..54f1eb0c96 100644
--- a/gtk/gtklistitemwidget.c
+++ b/gtk/gtklistitemwidget.c
@@ -30,6 +30,7 @@
 #include "gtklistitemfactoryprivate.h"
 #include "gtklistitemprivate.h"
 #include "gtkmain.h"
+#include "gtkselectionmodel.h"
 #include "gtkwidget.h"
 #include "gtkwidgetprivate.h"
 
@@ -38,6 +39,10 @@ struct _GtkListItemWidgetPrivate
 {
   GtkListItemFactory *factory;
   GtkListItem *list_item;
+
+  GObject *item;
+  guint position;
+  gboolean selected;
 };
 
 enum
@@ -55,13 +60,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
@@ -122,6 +127,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);
@@ -136,7 +142,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);
@@ -144,7 +150,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
@@ -233,13 +239,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;
       GdkModifierType mask;
@@ -258,17 +264,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);
         }
     }
 
@@ -291,7 +297,7 @@ gtk_list_item_widget_focus_changed_cb (GtkEventControllerKey *controller,
       gtk_widget_activate_action (widget,
                                   "list.scroll-to-item",
                                   "u",
-                                  priv->list_item->position);
+                                  priv->position);
     }
 }
 
@@ -393,6 +399,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
@@ -408,6 +421,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
@@ -417,9 +437,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
@@ -449,7 +484,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
@@ -457,7 +492,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
@@ -465,6 +500,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;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]