listitemwidget: split out GtkListItemBase
authorBenjamin Otte <otte@redhat.com>
Sun, 12 Mar 2023 04:05:48 +0000 (05:05 +0100)
committerBenjamin Otte <otte@redhat.com>
Thu, 23 Mar 2023 03:45:03 +0000 (04:45 +0100)
There's 2 reasons for this:

1. Adding a custom widget for columnview rows
2. Using this as base class for sections

12 files changed:
gtk/a11y/gtkatspiselection.c
gtk/gtkcolumnlistitemfactory.c
gtk/gtkcolumnviewcolumn.c
gtk/gtkdropdown.c
gtk/gtklistbase.c
gtk/gtklistitem.c
gtk/gtklistitembase.c [new file with mode: 0644]
gtk/gtklistitembaseprivate.h [new file with mode: 0644]
gtk/gtklistitemmanager.c
gtk/gtklistitemwidget.c
gtk/gtklistitemwidgetprivate.h
gtk/meson.build

index db2c76c03e3ae540eb1f72cf132a514c01613314..7d67d5f062943e41b88d7d09c1c53cd5d4f55226 100644 (file)
@@ -256,7 +256,7 @@ listview_handle_method (GDBusConnection       *connection,
            child;
            child = gtk_widget_get_next_sibling (child))
         {
-          if (gtk_list_item_widget_get_selected (GTK_LIST_ITEM_WIDGET (child)))
+          if (gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (child)))
             {
               if (idx == 0)
                 break;
@@ -303,7 +303,7 @@ listview_handle_method (GDBusConnection       *connection,
           guint pos;
           gboolean ret;
 
-          pos = gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (child));
+          pos = gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (child));
           ret = gtk_selection_model_select_item (model, pos, FALSE);
 
           g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
@@ -335,7 +335,7 @@ listview_handle_method (GDBusConnection       *connection,
           guint pos;
           gboolean ret;
 
-          pos = gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (child));
+          pos = gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (child));
           ret = gtk_selection_model_unselect_item (model, pos);
 
           g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
@@ -353,7 +353,7 @@ listview_handle_method (GDBusConnection       *connection,
            child;
            child = gtk_widget_get_next_sibling (child))
         {
-          if (gtk_list_item_widget_get_selected (GTK_LIST_ITEM_WIDGET (child)))
+          if (gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (child)))
             {
               if (idx == 0)
                 break;
@@ -371,7 +371,7 @@ listview_handle_method (GDBusConnection       *connection,
           guint pos;
           gboolean ret;
 
-          pos = gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (child));
+          pos = gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (child));
           ret = gtk_selection_model_unselect_item (model, pos);
 
           g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
@@ -402,7 +402,7 @@ listview_handle_method (GDBusConnection       *connection,
         {
           gboolean ret;
 
-          ret = gtk_list_item_widget_get_selected (GTK_LIST_ITEM_WIDGET (child));
+          ret = gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (child));
 
           g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
         }
index 94a1695caaf747c7d63de09891900c6ad206c291..e60057ab10edfbd97d5762fa48d8e29618746c74 100644 (file)
@@ -114,10 +114,10 @@ gtk_column_list_item_factory_update (GtkListItemFactory *factory,
     {
       GtkListItem *cell_item;
 
-      gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (child),
-                                   gtk_list_item_get_position (list_item),
-                                   gtk_list_item_get_item (list_item),
-                                   gtk_list_item_get_selected (list_item));
+      gtk_list_item_base_update (GTK_LIST_ITEM_BASE (child),
+                                 gtk_list_item_get_position (list_item),
+                                 gtk_list_item_get_item (list_item),
+                                 gtk_list_item_get_selected (list_item));
 
        cell_item = gtk_list_item_widget_get_list_item (GTK_LIST_ITEM_WIDGET (child));
        if (cell_item)
@@ -169,12 +169,13 @@ gtk_column_list_item_factory_add_column (GtkColumnListItemFactory *factory,
                                          GtkColumnViewColumn      *column,
                                          gboolean                  check_bind)
 {
+  GtkListItemBase *base = GTK_LIST_ITEM_BASE (list_item);
   GtkWidget *cell;
 
   cell = gtk_column_view_cell_new (column);
   gtk_list_item_widget_add_child (GTK_LIST_ITEM_WIDGET (list_item), GTK_WIDGET (cell));
-  gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (cell),
-                               gtk_list_item_widget_get_position (list_item),
-                               gtk_list_item_widget_get_item (list_item),
-                               gtk_list_item_widget_get_selected (list_item));
+  gtk_list_item_base_update (GTK_LIST_ITEM_BASE (cell),
+                             gtk_list_item_base_get_position (base),
+                             gtk_list_item_base_get_item (base),
+                             gtk_list_item_base_get_selected (base));
 }
index c67fb50b0b2476eb0c84f56ed022bad398d8e414..58432d7a330b2b8e6d7f85d2aad13d2411b0cf1d 100644 (file)
@@ -529,18 +529,20 @@ gtk_column_view_column_create_cells (GtkColumnViewColumn *self)
        row = gtk_widget_get_next_sibling (row))
     {
       GtkListItemWidget *list_item;
+      GtkListItemBase *base;
       GtkWidget *cell;
 
       if (!gtk_widget_get_root (row))
         continue;
 
       list_item = GTK_LIST_ITEM_WIDGET (row);
+      base = GTK_LIST_ITEM_BASE (row);
       cell = gtk_column_view_cell_new (self);
       gtk_list_item_widget_add_child (list_item, cell);
-      gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (cell),
-                                   gtk_list_item_widget_get_position (list_item),
-                                   gtk_list_item_widget_get_item (list_item),
-                                   gtk_list_item_widget_get_selected (list_item));
+      gtk_list_item_base_update (GTK_LIST_ITEM_BASE (cell),
+                                 gtk_list_item_base_get_position (base),
+                                 gtk_list_item_base_get_item (base),
+                                 gtk_list_item_base_get_selected (base));
     }
 }
 
index 3fcfeb71f44713b4587572e137cfcf43907378a4..e0eea43d70090cadd06cdbdf717832b62c3372d5 100644 (file)
@@ -219,12 +219,12 @@ selection_changed (GtkSingleSelection *selection,
       gtk_stack_set_visible_child_name (GTK_STACK (self->button_stack), "item");
     }
 
-  if (selected != gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (self->button_item)))
+  if (selected != gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self->button_item)))
     {
-      gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (self->button_item),
-                                   selected,
-                                   gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (self->selection)),
-                                   FALSE);
+      gtk_list_item_base_update (GTK_LIST_ITEM_BASE (self->button_item),
+                                 selected,
+                                 gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (self->selection)),
+                                 FALSE);
     }
 
   /* reset the filter so positions are 1-1 */
@@ -246,12 +246,12 @@ selection_item_changed (GtkSingleSelection *selection,
 
   item = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (self->selection));
 
-  if (item != gtk_list_item_widget_get_item (GTK_LIST_ITEM_WIDGET (self->button_item)))
+  if (item != gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->button_item)))
     {
-      gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (self->button_item),
-                                   gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (self->selection)),
-                                   item,
-                                   FALSE);
+      gtk_list_item_base_update (GTK_LIST_ITEM_BASE (self->button_item),
+                                 gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (self->selection)),
+                                 item,
+                                 FALSE);
     }
 
   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]);
index 1adecc87f33f2c2631c8e86502890026fae8ad64..a9d6700bf1dca46bb2e85e83a8e8909b34a343f0 100644 (file)
@@ -896,10 +896,10 @@ gtk_list_base_set_focus_child (GtkWidget *widget,
 
   GTK_WIDGET_CLASS (gtk_list_base_parent_class)->set_focus_child (widget, child);
 
-  if (!GTK_IS_LIST_ITEM_WIDGET (child))
+  if (!GTK_IS_LIST_ITEM_BASE (child))
     return;
 
-  pos = gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (child));
+  pos = gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (child));
 
   if (pos != gtk_list_item_tracker_get_position (priv->item_manager, priv->focus))
     {
index 28614b62f8fbec25fc2187a475d0833c7cad6776..837784bd479a0793a0c32b3cf79db619d5dbce96 100644 (file)
@@ -94,12 +94,12 @@ gtk_list_item_get_property (GObject    *object,
 
     case PROP_ITEM:
       if (self->owner)
-        g_value_set_object (value, gtk_list_item_widget_get_item (self->owner));
+        g_value_set_object (value, gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->owner)));
       break;
 
     case PROP_POSITION:
       if (self->owner)
-        g_value_set_uint (value, gtk_list_item_widget_get_position (self->owner));
+        g_value_set_uint (value, gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self->owner)));
       else
         g_value_set_uint (value, GTK_INVALID_LIST_POSITION);
       break;
@@ -110,7 +110,7 @@ gtk_list_item_get_property (GObject    *object,
 
     case PROP_SELECTED:
       if (self->owner)
-        g_value_set_boolean (value, gtk_list_item_widget_get_selected (self->owner));
+        g_value_set_boolean (value, gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self->owner)));
       else
         g_value_set_boolean (value, FALSE);
       break;
@@ -268,7 +268,7 @@ gtk_list_item_get_item (GtkListItem *self)
   if (self->owner == NULL)
     return NULL;
 
-  return gtk_list_item_widget_get_item (self->owner);
+  return gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->owner));
 }
 
 /**
@@ -344,7 +344,7 @@ gtk_list_item_get_position (GtkListItem *self)
   if (self->owner == NULL)
     return GTK_INVALID_LIST_POSITION;
 
-  return gtk_list_item_widget_get_position (self->owner);
+  return gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self->owner));
 }
 
 /**
@@ -366,7 +366,7 @@ gtk_list_item_get_selected (GtkListItem *self)
   if (self->owner == NULL)
     return FALSE;
 
-  return gtk_list_item_widget_get_selected (self->owner);
+  return gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self->owner));
 }
 
 /**
diff --git a/gtk/gtklistitembase.c b/gtk/gtklistitembase.c
new file mode 100644 (file)
index 0000000..67bbf95
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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 "gtklistitembaseprivate.h"
+
+#include "gtkaccessible.h"
+
+typedef struct _GtkListItemBasePrivate GtkListItemBasePrivate;
+struct _GtkListItemBasePrivate
+{
+  GObject *item;
+  guint position;
+  gboolean selected;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkListItemBase, gtk_list_item_base, GTK_TYPE_WIDGET)
+
+static void
+gtk_list_item_base_default_update (GtkListItemBase *self,
+                                   guint            position,
+                                   gpointer         item,
+                                   gboolean         selected)
+{
+  GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self);
+
+  g_set_object (&priv->item, item);
+  priv->position = position;
+  priv->selected = selected;
+}
+
+static void
+gtk_list_item_base_dispose (GObject *object)
+{
+  GtkListItemBase *self = GTK_LIST_ITEM_BASE (object);
+  GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self);
+
+  g_clear_object (&priv->item);
+
+  G_OBJECT_CLASS (gtk_list_item_base_parent_class)->dispose (object);
+}
+
+static void
+gtk_list_item_base_class_init (GtkListItemBaseClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  klass->update = gtk_list_item_base_default_update;
+
+  gobject_class->dispose = gtk_list_item_base_dispose;
+}
+
+static void
+gtk_list_item_base_init (GtkListItemBase *self)
+{
+}
+
+void
+gtk_list_item_base_update (GtkListItemBase *self,
+                           guint            position,
+                           gpointer         item,
+                           gboolean         selected)
+{
+  GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self);
+  gboolean was_selected;
+
+  was_selected = priv->selected;
+
+  GTK_LIST_ITEM_BASE_GET_CLASS (self)->update (self, position, item, selected);
+
+  /* don't look at selected variable, it's not reentrancy safe */
+  if (was_selected != priv->selected)
+    {
+      if (priv->selected)
+        gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED, FALSE);
+      else
+        gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED);
+
+      gtk_accessible_update_state (GTK_ACCESSIBLE (self),
+                                   GTK_ACCESSIBLE_STATE_SELECTED, priv->selected,
+                                   -1);
+    }
+}
+
+guint
+gtk_list_item_base_get_position (GtkListItemBase *self)
+{
+  GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self);
+
+  return priv->position;
+}
+
+gpointer
+gtk_list_item_base_get_item (GtkListItemBase *self)
+{
+  GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self);
+
+  return priv->item;
+}
+
+gboolean
+gtk_list_item_base_get_selected (GtkListItemBase *self)
+{
+  GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self);
+
+  return priv->selected;
+}
+
diff --git a/gtk/gtklistitembaseprivate.h b/gtk/gtklistitembaseprivate.h
new file mode 100644 (file)
index 0000000..a5b48dd
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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>
+ */
+
+#ifndef __GTK_LIST_ITEM_BASE_PRIVATE_H__
+#define __GTK_LIST_ITEM_BASE_PRIVATE_H__
+
+#include "gtkwidget.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_LIST_ITEM_BASE         (gtk_list_item_base_get_type ())
+#define GTK_LIST_ITEM_BASE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_LIST_ITEM_BASE, GtkListItemBase))
+#define GTK_LIST_ITEM_BASE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_LIST_ITEM_BASE, GtkListItemBaseClass))
+#define GTK_IS_LIST_ITEM_BASE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_LIST_ITEM_BASE))
+#define GTK_IS_LIST_ITEM_BASE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_LIST_ITEM_BASE))
+#define GTK_LIST_ITEM_BASE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_LIST_ITEM_BASE, GtkListItemBaseClass))
+
+typedef struct _GtkListItemBase GtkListItemBase;
+typedef struct _GtkListItemBaseClass GtkListItemBaseClass;
+
+struct _GtkListItemBase
+{
+  GtkWidget parent_instance;
+};
+
+struct _GtkListItemBaseClass
+{
+  GtkWidgetClass parent_class;
+
+  void                  (* update)                              (GtkListItemBase        *self,
+                                                                 guint                   position,
+                                                                 gpointer                item,
+                                                                 gboolean                selected);
+};
+
+GType                   gtk_list_item_base_get_type             (void) G_GNUC_CONST;
+
+void                    gtk_list_item_base_update               (GtkListItemBase        *self,
+                                                                 guint                   position,
+                                                                 gpointer                item,
+                                                                 gboolean                selected);
+
+guint                   gtk_list_item_base_get_position         (GtkListItemBase        *self);
+gpointer                gtk_list_item_base_get_item             (GtkListItemBase        *self);
+gboolean                gtk_list_item_base_get_selected         (GtkListItemBase        *self);
+
+G_END_DECLS
+
+#endif  /* __GTK_LIST_ITEM_BASE_PRIVATE_H__ */
index b959406c7995323e8d04651f7c9dec8baf18759e..9f671b6168757ad8f4472dc6cf9c68ec86f65916 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "gtklistitemmanagerprivate.h"
 
+#include "gtklistitembaseprivate.h"
 #include "gtklistitemwidgetprivate.h"
 #include "gtkwidgetprivate.h"
 
@@ -49,7 +50,7 @@ struct _GtkListItemManagerClass
 struct _GtkListItemTracker
 {
   guint position;
-  GtkListItemWidget *widget;
+  GtkListItemBase *widget;
   guint n_before;
   guint n_after;
 };
@@ -874,7 +875,7 @@ gtk_list_item_manager_model_items_changed_cb (GListModel         *model,
       if (tracker->widget == NULL)
         continue;
 
-      if (g_hash_table_lookup (change, gtk_list_item_widget_get_item (tracker->widget)))
+      if (g_hash_table_lookup (change, gtk_list_item_base_get_item (tracker->widget)))
         break;
     }
 
@@ -952,7 +953,7 @@ gtk_list_item_manager_model_items_changed_cb (GListModel         *model,
         }
       else if (tracker->position >= position)
         {
-          if (g_hash_table_lookup (change, gtk_list_item_widget_get_item (tracker->widget)))
+          if (g_hash_table_lookup (change, gtk_list_item_base_get_item (tracker->widget)))
             {
               /* The item is gone. Guess a good new position */
               tracker->position = position + (tracker->position - position) * added / removed;
@@ -970,7 +971,7 @@ gtk_list_item_manager_model_items_changed_cb (GListModel         *model,
               /* item was put in its right place in the expensive loop above,
                * and we updated its position while at it. So grab it from there.
                */
-              tracker->position = gtk_list_item_widget_get_position (tracker->widget);
+              tracker->position = gtk_list_item_base_get_position (tracker->widget);
             }
         }
       else
@@ -997,7 +998,7 @@ gtk_list_item_manager_model_items_changed_cb (GListModel         *model,
       tile = gtk_list_item_manager_get_nth (self, tracker->position, NULL);
       g_assert (tile != NULL);
       g_assert (tile->widget);
-      tracker->widget = GTK_LIST_ITEM_WIDGET (tile->widget);
+      tracker->widget = GTK_LIST_ITEM_BASE (tile->widget);
     }
 
   g_hash_table_unref (change);
@@ -1118,7 +1119,7 @@ gtk_list_item_manager_set_factory (GtkListItemManager *self,
 
       tile = gtk_list_item_manager_get_nth (self, tracker->position, NULL);
       g_assert (tile);
-      tracker->widget = GTK_LIST_ITEM_WIDGET (tile->widget);
+      tracker->widget = GTK_LIST_ITEM_BASE (tile->widget);
     }
 }
 
@@ -1205,7 +1206,7 @@ gtk_list_item_manager_acquire_list_item (GtkListItemManager *self,
 
   item = g_list_model_get_item (G_LIST_MODEL (self->model), position);
   selected = gtk_selection_model_is_selected (self->model, position);
-  gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (result), position, item, selected);
+  gtk_list_item_base_update (GTK_LIST_ITEM_BASE (result), position, item, selected);
   g_object_unref (item);
   gtk_widget_insert_after (result, self->widget, prev_sibling);
 
@@ -1243,11 +1244,11 @@ gtk_list_item_manager_try_reacquire_list_item (GtkListItemManager *self,
   item = g_list_model_get_item (G_LIST_MODEL (self->model), position);
   if (g_hash_table_steal_extended (change, item, NULL, (gpointer *) &result))
     {
-      GtkListItemWidget *list_item = GTK_LIST_ITEM_WIDGET (result);
-      gtk_list_item_widget_update (list_item,
-                                   position,
-                                   gtk_list_item_widget_get_item (list_item),
-                                   gtk_selection_model_is_selected (self->model, position));
+      GtkListItemBase *list_item = GTK_LIST_ITEM_BASE (result);
+      gtk_list_item_base_update (list_item,
+                                 position,
+                                 gtk_list_item_base_get_item (list_item),
+                                 gtk_selection_model_is_selected (self->model, position));
       gtk_widget_insert_after (result, self->widget, prev_sibling);
       /* XXX: Should we let the listview do this? */
       gtk_widget_queue_resize (result);
@@ -1285,10 +1286,10 @@ gtk_list_item_manager_move_list_item (GtkListItemManager     *self,
 
   item = g_list_model_get_item (G_LIST_MODEL (self->model), position);
   selected = gtk_selection_model_is_selected (self->model, position);
-  gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (list_item),
-                               position,
-                               item,
-                               selected);
+  gtk_list_item_base_update (GTK_LIST_ITEM_BASE (list_item),
+                             position,
+                             item,
+                             selected);
   gtk_widget_insert_after (list_item, _gtk_widget_get_parent (list_item), prev_sibling);
   g_object_unref (item);
 }
@@ -1307,17 +1308,17 @@ gtk_list_item_manager_update_list_item (GtkListItemManager *self,
                                         GtkWidget          *item,
                                         guint               position)
 {
-  GtkListItemWidget *list_item = GTK_LIST_ITEM_WIDGET (item);
+  GtkListItemBase *list_item = GTK_LIST_ITEM_BASE (item);
   gboolean selected;
 
   g_return_if_fail (GTK_IS_LIST_ITEM_MANAGER (self));
-  g_return_if_fail (GTK_IS_LIST_ITEM_WIDGET (item));
+  g_return_if_fail (GTK_IS_LIST_ITEM_BASE (item));
 
   selected = gtk_selection_model_is_selected (self->model, position);
-  gtk_list_item_widget_update (list_item,
-                               position,
-                               gtk_list_item_widget_get_item (list_item),
-                               selected);
+  gtk_list_item_base_update (list_item,
+                             position,
+                             gtk_list_item_base_get_item (list_item),
+                             selected);
 }
 
 /*
@@ -1337,11 +1338,11 @@ gtk_list_item_manager_release_list_item (GtkListItemManager *self,
                                          GtkWidget          *item)
 {
   g_return_if_fail (GTK_IS_LIST_ITEM_MANAGER (self));
-  g_return_if_fail (GTK_IS_LIST_ITEM_WIDGET (item));
+  g_return_if_fail (GTK_IS_LIST_ITEM_BASE (item));
 
   if (change != NULL)
     {
-      if (!g_hash_table_replace (change, gtk_list_item_widget_get_item (GTK_LIST_ITEM_WIDGET (item)), item))
+      if (!g_hash_table_replace (change, gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (item)), item))
         {
           g_warning ("Duplicate item detected in list. Picking one randomly.");
         }
@@ -1437,7 +1438,7 @@ gtk_list_item_tracker_set_position (GtkListItemManager *self,
 
   tile = gtk_list_item_manager_get_nth (self, position, NULL);
   if (tile)
-    tracker->widget = GTK_LIST_ITEM_WIDGET (tile->widget);
+    tracker->widget = GTK_LIST_ITEM_BASE (tile->widget);
 
   gtk_widget_queue_resize (self->widget);
 }
index 0d66566dcb71ae4c93cb70af54653ec98be7466f..5b770bf0305f41dfde75b64973c8a3da52864594 100644 (file)
@@ -38,9 +38,6 @@ struct _GtkListItemWidgetPrivate
   GtkListItemFactory *factory;
   GtkListItem *list_item;
 
-  GObject *item;
-  guint position;
-  gboolean selected;
   gboolean single_click_activate;
 };
 
@@ -58,7 +55,7 @@ enum
   LAST_SIGNAL
 };
 
-G_DEFINE_TYPE_WITH_PRIVATE (GtkListItemWidget, gtk_list_item_widget, GTK_TYPE_WIDGET)
+G_DEFINE_TYPE_WITH_PRIVATE (GtkListItemWidget, gtk_list_item_widget, GTK_TYPE_LIST_ITEM_BASE)
 
 static GParamSpec *properties[N_PROPS] = { NULL, };
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -74,7 +71,7 @@ gtk_list_item_widget_activate_signal (GtkListItemWidget *self)
   gtk_widget_activate_action (GTK_WIDGET (self),
                               "list.activate-item",
                               "u",
-                              priv->position);
+                              gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)));
 }
 
 static gboolean
@@ -155,9 +152,9 @@ gtk_list_item_widget_setup_func (gpointer object,
   gtk_list_item_widget_set_activatable (self, list_item->activatable);
 
   gtk_list_item_do_notify (list_item,
-                           priv->item != NULL,
-                           priv->position != GTK_INVALID_LIST_POSITION,
-                           priv->selected);
+                           gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL,
+                           gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)) != GTK_INVALID_LIST_POSITION,
+                           gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self)));
 }
 
 static void
@@ -170,7 +167,7 @@ gtk_list_item_widget_setup_factory (GtkListItemWidget *self)
 
   gtk_list_item_factory_setup (priv->factory,
                                G_OBJECT (list_item),
-                               priv->item != NULL,
+                               gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL,
                                gtk_list_item_widget_setup_func,
                                self);
 
@@ -196,9 +193,9 @@ gtk_list_item_widget_teardown_func (gpointer object,
   gtk_list_item_widget_set_activatable (self, FALSE);
 
   gtk_list_item_do_notify (list_item,
-                           priv->item != NULL,
-                           priv->position != GTK_INVALID_LIST_POSITION,
-                           priv->selected);
+                           gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL,
+                           gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)) != GTK_INVALID_LIST_POSITION,
+                           gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self)));
 
   gtk_list_item_set_child (list_item, NULL);
 }
@@ -211,7 +208,7 @@ gtk_list_item_widget_teardown_factory (GtkListItemWidget *self)
 
   gtk_list_item_factory_teardown (priv->factory,
                                   G_OBJECT (list_item),
-                                  priv->item != NULL,
+                                  gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL,
                                   gtk_list_item_widget_teardown_func,
                                   self);
 
@@ -219,6 +216,62 @@ gtk_list_item_widget_teardown_factory (GtkListItemWidget *self)
   g_object_unref (list_item);
 }
 
+typedef struct {
+  GtkListItemWidget *widget;
+  guint position;
+  gpointer item;
+  gboolean selected;
+} GtkListItemWidgetUpdate;
+
+static void
+gtk_list_item_widget_update_func (gpointer object,
+                                  gpointer data)
+{
+  GtkListItemWidgetUpdate *update = data;
+  GtkListItem *list_item = object;
+  /* Track notify manually instead of freeze/thaw_notify for performance reasons. */
+  gboolean notify_item = FALSE, notify_position = FALSE, notify_selected = FALSE;
+  GtkListItemWidget *self = update->widget;
+  GtkListItemBase *base = GTK_LIST_ITEM_BASE (self);
+
+  /* FIXME: It's kinda evil to notify external objects from here... */
+  notify_item = gtk_list_item_base_get_item (base) != update->item;
+  notify_position = gtk_list_item_base_get_position (base) != update->position;
+  notify_selected = gtk_list_item_base_get_selected (base) != update->selected;
+
+  GTK_LIST_ITEM_BASE_CLASS (gtk_list_item_widget_parent_class)->update (base,
+                                                                        update->position,
+                                                                        update->item,
+                                                                        update->selected);
+  if (list_item)
+    gtk_list_item_do_notify (list_item, notify_item, notify_position, notify_selected);
+}
+
+static void
+gtk_list_item_widget_update (GtkListItemBase *base,
+                             guint            position,
+                             gpointer         item,
+                             gboolean         selected)
+{
+  GtkListItemWidget *self = GTK_LIST_ITEM_WIDGET (base);
+  GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
+  GtkListItemWidgetUpdate update = { self, position, item, selected };
+
+  if (priv->list_item)
+    {
+      gtk_list_item_factory_update (priv->factory,
+                                    G_OBJECT (priv->list_item),
+                                    gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL,
+                                    item != NULL,
+                                    gtk_list_item_widget_update_func,
+                                    &update);
+    }
+  else
+    {
+      gtk_list_item_widget_update_func (NULL, &update);
+    }
+}
+
 static void
 gtk_list_item_widget_root (GtkWidget *widget)
 {
@@ -275,7 +328,6 @@ gtk_list_item_widget_dispose (GObject *object)
 
   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);
@@ -298,7 +350,7 @@ gtk_list_item_widget_select_action (GtkWidget  *widget,
   gtk_widget_activate_action (GTK_WIDGET (self),
                               "list.select-item",
                               "(ubb)",
-                              priv->position, modify, extend);
+                              gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)), modify, extend);
 }
 
 static void
@@ -306,23 +358,23 @@ gtk_list_item_widget_scroll_to_action (GtkWidget  *widget,
                                        const char *action_name,
                                        GVariant   *parameter)
 {
-  GtkListItemWidget *self = GTK_LIST_ITEM_WIDGET (widget);
-  GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
-
-  gtk_widget_activate_action (GTK_WIDGET (self),
+  gtk_widget_activate_action (widget,
                               "list.scroll-to-item",
                               "u",
-                              priv->position);
+                              gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (widget)));
 }
 
 static void
 gtk_list_item_widget_class_init (GtkListItemWidgetClass *klass)
 {
+  GtkListItemBaseClass *base_class = GTK_LIST_ITEM_BASE_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   klass->activate_signal = gtk_list_item_widget_activate_signal;
 
+  base_class->update = gtk_list_item_widget_update;
+
   widget_class->focus = gtk_list_item_widget_focus;
   widget_class->grab_focus = gtk_list_item_widget_grab_focus;
   widget_class->root = gtk_list_item_widget_root;
@@ -438,7 +490,7 @@ gtk_list_item_widget_click_gesture_pressed (GtkGestureClick   *gesture,
           gtk_widget_activate_action (GTK_WIDGET (self),
                                       "list.activate-item",
                                       "u",
-                                      priv->position);
+                                      gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)));
         }
     }
 
@@ -463,7 +515,7 @@ gtk_list_item_widget_click_gesture_released (GtkGestureClick   *gesture,
           gtk_widget_activate_action (GTK_WIDGET (self),
                                       "list.activate-item",
                                       "u",
-                                      priv->position);
+                                      gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)));
           return;
         }
     }
@@ -484,7 +536,7 @@ gtk_list_item_widget_click_gesture_released (GtkGestureClick   *gesture,
       gtk_widget_activate_action (GTK_WIDGET (self),
                                   "list.select-item",
                                   "(ubb)",
-                                  priv->position, modify, extend);
+                                  gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)), modify, extend);
     }
 }
 
@@ -504,7 +556,7 @@ gtk_list_item_widget_hover_cb (GtkEventControllerMotion *controller,
       gtk_widget_activate_action (GTK_WIDGET (self),
                                   "list.select-item",
                                   "(ubb)",
-                                  priv->position, FALSE, FALSE);
+                                  gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)), FALSE, FALSE);
     }
 }
 
@@ -548,85 +600,6 @@ gtk_list_item_widget_new (GtkListItemFactory *factory,
                        NULL);
 }
 
-typedef struct {
-  GtkListItemWidget *widget;
-  guint position;
-  gpointer item;
-  gboolean selected;
-} GtkListItemWidgetUpdate;
-
-static void
-gtk_list_item_widget_update_func (gpointer object,
-                                  gpointer data)
-{
-  GtkListItemWidgetUpdate *update = data;
-  GtkListItem *list_item = object;
-  /* Track notify manually instead of freeze/thaw_notify for performance reasons. */
-  gboolean notify_item = FALSE, notify_position = FALSE, notify_selected = FALSE;
-  GtkListItemWidget *self = update->widget;
-  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, update->item))
-    notify_item = TRUE;
-
-  if (priv->position != update->position)
-    {
-      priv->position = update->position;
-      notify_position = TRUE;
-    }
-
-  if (priv->selected != update->selected)
-    {
-      priv->selected = update->selected;
-      notify_selected = TRUE;
-    }
-
-  if (list_item)
-    gtk_list_item_do_notify (list_item, notify_item, notify_position, notify_selected);
-}
-
-void
-gtk_list_item_widget_update (GtkListItemWidget *self,
-                             guint              position,
-                             gpointer           item,
-                             gboolean           selected)
-{
-  GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
-  GtkListItemWidgetUpdate update = { self, position, item, selected };
-  gboolean was_selected;
-
-  was_selected = priv->selected;
-
-  if (priv->list_item)
-    {
-      gtk_list_item_factory_update (priv->factory,
-                                    G_OBJECT (priv->list_item),
-                                    priv->item != NULL,
-                                    item != NULL,
-                                    gtk_list_item_widget_update_func,
-                                    &update);
-    }
-  else
-    {
-      gtk_list_item_widget_update_func (NULL, &update);
-    }
-
-  /* don't look at selected variable, it's not reentrancy safe */
-  if (was_selected != priv->selected)
-    {
-      if (priv->selected)
-        gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED, FALSE);
-      else
-        gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED);
-
-      gtk_accessible_update_state (GTK_ACCESSIBLE (self),
-                                   GTK_ACCESSIBLE_STATE_SELECTED, priv->selected,
-                                   -1);
-    }
-}
-
 void
 gtk_list_item_widget_set_factory (GtkListItemWidget  *self,
                                   GtkListItemFactory *factory)
@@ -729,27 +702,3 @@ gtk_list_item_widget_get_list_item (GtkListItemWidget *self)
   return priv->list_item;
 }
 
-guint
-gtk_list_item_widget_get_position (GtkListItemWidget *self)
-{
-  GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
-
-  return priv->position;
-}
-
-gpointer
-gtk_list_item_widget_get_item (GtkListItemWidget *self)
-{
-  GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
-
-  return priv->item;
-}
-
-gboolean
-gtk_list_item_widget_get_selected (GtkListItemWidget *self)
-{
-  GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self);
-
-  return priv->selected;
-}
-
index 7ac53df4134870ada36c369e3bde8215140f404b..5345419a193e9c16a7a54732edee6d949ecd260c 100644 (file)
@@ -20,8 +20,9 @@
 #ifndef __GTK_LIST_ITEM_WIDGET_PRIVATE_H__
 #define __GTK_LIST_ITEM_WIDGET_PRIVATE_H__
 
+#include "gtklistitembaseprivate.h"
+
 #include "gtklistitemfactory.h"
-#include "gtkwidget.h"
 
 G_BEGIN_DECLS
 
@@ -37,12 +38,12 @@ typedef struct _GtkListItemWidgetClass GtkListItemWidgetClass;
 
 struct _GtkListItemWidget
 {
-  GtkWidget parent_instance;
+  GtkListItemBase parent_instance;
 };
 
 struct _GtkListItemWidgetClass
 {
-  GtkWidgetClass parent_class;
+  GtkListItemBaseClass parent_class;
 
   void          (* activate_signal)                             (GtkListItemWidget            *self);
 };
@@ -53,10 +54,6 @@ GtkWidget *             gtk_list_item_widget_new                (GtkListItemFact
                                                                  const char             *css_name,
                                                                  GtkAccessibleRole       role);
 
-void                    gtk_list_item_widget_update             (GtkListItemWidget      *self,
-                                                                 guint                   position,
-                                                                 gpointer                item,
-                                                                 gboolean                selected);
 GtkListItem *           gtk_list_item_widget_get_list_item      (GtkListItemWidget      *self);
 
 void                    gtk_list_item_widget_set_factory        (GtkListItemWidget      *self,
@@ -74,10 +71,6 @@ void                    gtk_list_item_widget_reorder_child      (GtkListItemWidg
 void                    gtk_list_item_widget_remove_child       (GtkListItemWidget      *self,
                                                                  GtkWidget              *child);
 
-guint                   gtk_list_item_widget_get_position       (GtkListItemWidget      *self);
-gpointer                gtk_list_item_widget_get_item           (GtkListItemWidget      *self);
-gboolean                gtk_list_item_widget_get_selected       (GtkListItemWidget      *self);
-
 G_END_DECLS
 
 #endif  /* __GTK_LIST_ITEM_WIDGET_PRIVATE_H__ */
index a8e108846de45c8703a27b35fed438da9f9dbef5..bcb92fe4435ce461c5752d07bafec509172a1a5a 100644 (file)
@@ -270,6 +270,7 @@ gtk_public_sources = files([
   'gtklinkbutton.c',
   'gtklistbox.c',
   'gtklistitem.c',
+  'gtklistitembase.c',
   'gtklistitemfactory.c',
   'gtklistitemmanager.c',
   'gtklistitemwidget.c',