columnview: Add GtkColumnViewRowWidget
authorBenjamin Otte <otte@redhat.com>
Mon, 13 Mar 2023 04:04:29 +0000 (05:04 +0100)
committerBenjamin Otte <otte@redhat.com>
Thu, 23 Mar 2023 03:45:03 +0000 (04:45 +0100)
This is a copy/paste of GtkListItemWidget for now.

Modifications will happen in future commits.

gtk/gtkcolumnlistitemfactory.c
gtk/gtkcolumnlistitemfactoryprivate.h
gtk/gtkcolumnview.c
gtk/gtkcolumnviewcolumn.c
gtk/gtkcolumnviewprivate.h
gtk/gtkcolumnviewrowwidget.c [new file with mode: 0644]
gtk/gtkcolumnviewrowwidgetprivate.h [new file with mode: 0644]
gtk/meson.build

index d36d911f1450689a9b2d49c6bfacbc6821021dc0..cbf80b34bef3ad1d66f72e73dfd85d55cbb60a26 100644 (file)
@@ -49,7 +49,7 @@ gtk_column_list_item_factory_setup (GtkListItemFactory *factory,
                                     gpointer            data)
 {
   GtkColumnListItemFactory *self = GTK_COLUMN_LIST_ITEM_FACTORY (factory);
-  GtkListItemWidget *widget = data;
+  GtkColumnViewRowWidget *widget = data;
   GListModel *columns;
   guint i;
 
@@ -82,14 +82,14 @@ gtk_column_list_item_factory_teardown (GtkListItemFactory *factory,
                                        GFunc               func,
                                        gpointer            data)
 {
-  GtkListItemWidget *widget = data;
+  GtkColumnViewRowWidget *widget = data;
   GtkWidget *child;
 
   GTK_LIST_ITEM_FACTORY_CLASS (gtk_column_list_item_factory_parent_class)->teardown (factory, item, unbind, func, data);
 
   while ((child = gtk_widget_get_first_child (GTK_WIDGET (widget))))
     {
-      gtk_list_item_widget_remove_child (GTK_LIST_ITEM_WIDGET (widget), child);
+      gtk_column_view_row_widget_remove_child (GTK_COLUMN_VIEW_ROW_WIDGET (widget), child);
     }
 }
 
@@ -165,7 +165,7 @@ gtk_column_list_item_factory_new (GtkColumnView *view)
 
 void
 gtk_column_list_item_factory_add_column (GtkColumnListItemFactory *factory,
-                                         GtkListItemWidget        *list_item,
+                                         GtkColumnViewRowWidget   *list_item,
                                          GtkColumnViewColumn      *column,
                                          gboolean                  check_bind)
 {
@@ -173,7 +173,7 @@ gtk_column_list_item_factory_add_column (GtkColumnListItemFactory *factory,
   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_column_view_row_widget_add_child (GTK_COLUMN_VIEW_ROW_WIDGET (list_item), GTK_WIDGET (cell));
   gtk_list_item_base_update (GTK_LIST_ITEM_BASE (cell),
                              gtk_list_item_base_get_position (base),
                              gtk_list_item_base_get_item (base),
index acddf2f56ec5880fa0dcf438d463c91873ca5f54..320502b4e5493454459ef2a4f827ef2edb3d79c8 100644 (file)
@@ -20,8 +20,8 @@
 #ifndef __GTK_COLUMN_LIST_ITEM_FACTORY_H__
 #define __GTK_COLUMN_LIST_ITEM_FACTORY_H__
 
-#include <gtk/gtklistitemwidgetprivate.h>
 #include <gtk/gtkcolumnview.h>
+#include <gtk/gtkcolumnviewrowwidgetprivate.h>
 
 G_BEGIN_DECLS
 
@@ -47,12 +47,12 @@ GtkColumnListItemFactory *
                         gtk_column_list_item_factory_new        (GtkColumnView          *view);
 
 void                    gtk_column_list_item_factory_add_column (GtkColumnListItemFactory       *factory,
-                                                                 GtkListItemWidget              *list_item,
+                                                                 GtkColumnViewRowWidget         *list_item,
                                                                  GtkColumnViewColumn            *column,
                                                                  gboolean                        check_bind);
 void                    gtk_column_list_item_factory_remove_column
                                                                 (GtkColumnListItemFactory       *factory,
-                                                                 GtkListItemWidget              *list_item,
+                                                                 GtkColumnViewRowWidget         *list_item,
                                                                  guint                           col_pos,
                                                                  GtkColumnViewColumn            *column);
 
index ba1be8f42e548e70aab6a6b97fde4f57f5c3cc77..46878f5bbe8696848d4f6bda94d8a0e3ff85eb62 100644 (file)
@@ -142,7 +142,7 @@ gtk_column_list_view_create_list_widget (GtkListBase *base)
   GtkListView *self = GTK_LIST_VIEW (base);
   GtkWidget *result;
 
-  result = gtk_list_item_widget_new (self->factory,
+  result = gtk_column_view_row_widget_new (self->factory,
                                      "row",
                                      GTK_ACCESSIBLE_ROLE_ROW);
 
@@ -924,7 +924,7 @@ gtk_column_view_in_header (GtkColumnView       *self,
   GtkWidget *header;
   graphene_rect_t rect;
 
-header = gtk_column_view_column_get_header (column);
+  header = gtk_column_view_column_get_header (column);
 
   if (!gtk_widget_compute_bounds (header, self->header, &rect))
     return FALSE;
@@ -1288,7 +1288,7 @@ gtk_column_view_init (GtkColumnView *self)
 
   self->columns = g_list_store_new (GTK_TYPE_COLUMN_VIEW_COLUMN);
 
-  self->header = gtk_list_item_widget_new (NULL, "header", GTK_ACCESSIBLE_ROLE_ROW);
+  self->header = gtk_column_view_row_widget_new (NULL, "header", GTK_ACCESSIBLE_ROLE_ROW);
   gtk_widget_set_can_focus (self->header, FALSE);
   gtk_widget_set_layout_manager (self->header, gtk_column_view_layout_new (self));
   gtk_widget_set_parent (self->header, GTK_WIDGET (self));
@@ -1640,10 +1640,10 @@ gtk_column_view_measure_across (GtkColumnView *self,
   *natural = nat;
 }
 
-GtkListItemWidget *
+GtkColumnViewRowWidget *
 gtk_column_view_get_header_widget (GtkColumnView *self)
 {
-  return GTK_LIST_ITEM_WIDGET (self->header);
+  return GTK_COLUMN_VIEW_ROW_WIDGET (self->header);
 }
 
 GtkListView *
index 58432d7a330b2b8e6d7f85d2aad13d2411b0cf1d..beb88fd95cc0de3a8627a61deb940a7c463625ba 100644 (file)
@@ -23,9 +23,9 @@
 #include "gtkcolumnviewsorterprivate.h"
 
 #include "gtkcolumnviewprivate.h"
+#include "gtkcolumnviewrowwidgetprivate.h"
 #include "gtkcolumnviewtitleprivate.h"
 #include "gtklistbaseprivate.h"
-#include "gtklistitemwidgetprivate.h"
 #include "gtkmain.h"
 #include "gtkprivate.h"
 #include "gtkrbtreeprivate.h"
@@ -528,17 +528,17 @@ gtk_column_view_column_create_cells (GtkColumnViewColumn *self)
        row != NULL;
        row = gtk_widget_get_next_sibling (row))
     {
-      GtkListItemWidget *list_item;
+      GtkColumnViewRowWidget *list_item;
       GtkListItemBase *base;
       GtkWidget *cell;
 
       if (!gtk_widget_get_root (row))
         continue;
 
-      list_item = GTK_LIST_ITEM_WIDGET (row);
+      list_item = GTK_COLUMN_VIEW_ROW_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_column_view_row_widget_add_child (list_item, cell);
       gtk_list_item_base_update (GTK_LIST_ITEM_BASE (cell),
                                  gtk_list_item_base_get_position (base),
                                  gtk_list_item_base_get_item (base),
@@ -561,7 +561,7 @@ gtk_column_view_column_create_header (GtkColumnViewColumn *self)
 
   self->header = gtk_column_view_title_new (self);
   gtk_widget_set_visible (self->header, self->visible);
-  gtk_list_item_widget_add_child (gtk_column_view_get_header_widget (self->view),
+  gtk_column_view_row_widget_add_child (gtk_column_view_get_header_widget (self->view),
                                   self->header);
   gtk_column_view_column_queue_resize (self);
 }
@@ -572,7 +572,7 @@ gtk_column_view_column_remove_header (GtkColumnViewColumn *self)
   if (self->header == NULL)
     return;
 
-  gtk_list_item_widget_remove_child (gtk_column_view_get_header_widget (self->view),
+  gtk_column_view_row_widget_remove_child (gtk_column_view_get_header_widget (self->view),
                                      self->header);
   self->header = NULL;
   gtk_column_view_column_queue_resize (self);
@@ -634,16 +634,16 @@ gtk_column_view_column_set_position (GtkColumnViewColumn *self,
 {
   GtkColumnViewCell *cell;
 
-  gtk_list_item_widget_reorder_child (gtk_column_view_get_header_widget (self->view),
+  gtk_column_view_row_widget_reorder_child (gtk_column_view_get_header_widget (self->view),
                                       self->header,
                                       position);
 
   for (cell = self->first_cell; cell; cell = gtk_column_view_cell_get_next (cell))
     {
-      GtkListItemWidget *list_item;
+      GtkColumnViewRowWidget *list_item;
 
-      list_item = GTK_LIST_ITEM_WIDGET (gtk_widget_get_parent (GTK_WIDGET (cell)));
-      gtk_list_item_widget_reorder_child (list_item, GTK_WIDGET (cell), position);
+      list_item = GTK_COLUMN_VIEW_ROW_WIDGET (gtk_widget_get_parent (GTK_WIDGET (cell)));
+      gtk_column_view_row_widget_reorder_child (list_item, GTK_WIDGET (cell), position);
     }
 }
 
index 2d080b9aa5d3b324a5bc3921fc517b235e6c1bf0..a1433a8dbb7a764ca5d670e28ee44201c4b80121 100644 (file)
 #include "gtk/gtksizerequest.h"
 
 #include "gtk/gtkcolumnviewsorterprivate.h"
-#include "gtk/gtklistitemwidgetprivate.h"
+#include "gtk/gtkcolumnviewrowwidgetprivate.h"
 
-GtkListItemWidget *     gtk_column_view_get_header_widget       (GtkColumnView          *self);
+GtkColumnViewRowWidget *gtk_column_view_get_header_widget       (GtkColumnView          *self);
 GtkListView *           gtk_column_view_get_list_view           (GtkColumnView          *self);
 
 void                    gtk_column_view_measure_across          (GtkColumnView          *self,
                                                                  int                    *minimum,
                                                                  int                    *natural);
 
-void                    gtk_column_view_distribute_width        (GtkColumnView    *self,
-                                                                 int               width,
-                                                                 GtkRequestedSize *sizes);
+void                    gtk_column_view_distribute_width        (GtkColumnView          *self,
+                                                                 int                     width,
+                                                                 GtkRequestedSize       *sizes);
 
 #endif  /* __GTK_COLUMN_VIEW_PRIVATE_H__ */
diff --git a/gtk/gtkcolumnviewrowwidget.c b/gtk/gtkcolumnviewrowwidget.c
new file mode 100644 (file)
index 0000000..06a57b9
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright © 2018 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 "gtkcolumnviewrowwidgetprivate.h"
+
+#include "gtkbinlayout.h"
+#include "gtklistitemfactoryprivate.h"
+#include "gtklistbaseprivate.h"
+#include "gtkwidget.h"
+#include "gtkwidgetprivate.h"
+
+G_DEFINE_TYPE (GtkColumnViewRowWidget, gtk_column_view_row_widget, GTK_TYPE_LIST_FACTORY_WIDGET)
+
+static gboolean
+gtk_column_view_row_widget_focus (GtkWidget        *widget,
+                                  GtkDirectionType  direction)
+{
+  GtkWidget *child, *focus_child;
+
+  /* The idea of this function is the following:
+   * 1. If any child can take focus, do not ever attempt
+   *    to take focus.
+   * 2. Otherwise, if this item is selectable or activatable,
+   *    allow focusing this widget.
+   *
+   * This makes sure every item in a list is focusable for
+   * activation and selection handling, but no useless widgets
+   * get focused and moving focus is as fast as possible.
+   */
+
+  focus_child = gtk_widget_get_focus_child (widget);
+  if (focus_child && gtk_widget_child_focus (focus_child, direction))
+    return TRUE;
+
+  for (child = focus_child ? gtk_widget_get_next_sibling (focus_child)
+                           : gtk_widget_get_first_child (widget);
+       child;
+       child = gtk_widget_get_next_sibling (child))
+    {
+      if (gtk_widget_child_focus (child, direction))
+        return TRUE;
+    }
+
+  if (focus_child)
+    return FALSE;
+
+  if (gtk_widget_is_focus (widget))
+    return FALSE;
+
+  return gtk_widget_grab_focus (widget);
+}
+
+static gboolean
+gtk_column_view_row_widget_grab_focus (GtkWidget *widget)
+{
+  GtkWidget *child;
+
+  for (child = gtk_widget_get_first_child (widget);
+       child;
+       child = gtk_widget_get_next_sibling (child))
+    {
+      if (gtk_widget_grab_focus (child))
+        return TRUE;
+    }
+
+  if (!gtk_list_factory_widget_get_selectable (GTK_LIST_FACTORY_WIDGET (widget)))
+    return FALSE;
+
+  return GTK_WIDGET_CLASS (gtk_column_view_row_widget_parent_class)->grab_focus (widget);
+}
+
+static void
+gtk_column_view_row_widget_class_init (GtkColumnViewRowWidgetClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  widget_class->focus = gtk_column_view_row_widget_focus;
+  widget_class->grab_focus = gtk_column_view_row_widget_grab_focus;
+
+  /* This gets overwritten by gtk_column_view_row_widget_new() but better safe than sorry */
+  gtk_widget_class_set_css_name (widget_class, I_("row"));
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+}
+
+static void
+gtk_column_view_row_widget_init (GtkColumnViewRowWidget *self)
+{
+  gtk_widget_set_focusable (GTK_WIDGET (self), TRUE);
+}
+
+GtkWidget *
+gtk_column_view_row_widget_new (GtkListItemFactory *factory,
+                                const char         *css_name,
+                                GtkAccessibleRole   role)
+{
+  g_return_val_if_fail (css_name != NULL, NULL);
+
+  return g_object_new (GTK_TYPE_COLUMN_VIEW_ROW_WIDGET,
+                       "css-name", css_name,
+                       "accessible-role", role,
+                       "factory", factory,
+                       "selectable", TRUE,
+                       "activatable", TRUE,
+                       NULL);
+}
+
+void
+gtk_column_view_row_widget_add_child (GtkColumnViewRowWidget *self,
+                                      GtkWidget              *child)
+{
+  gtk_widget_set_parent (child, GTK_WIDGET (self));
+}
+
+void
+gtk_column_view_row_widget_reorder_child (GtkColumnViewRowWidget *self,
+                                          GtkWidget              *child,
+                                          guint                   position)
+{
+  GtkWidget *widget = GTK_WIDGET (self);
+  GtkWidget *sibling = NULL;
+
+  if (position > 0)
+    {
+      GtkWidget *c;
+      guint i;
+
+      for (c = gtk_widget_get_first_child (widget), i = 0;
+           c;
+           c = gtk_widget_get_next_sibling (c), i++)
+        {
+          if (i + 1 == position)
+            {
+              sibling = c;
+              break;
+            }
+        }
+    }
+
+  if (child != sibling)
+    gtk_widget_insert_after (child, widget, sibling);
+}
+
+void
+gtk_column_view_row_widget_remove_child (GtkColumnViewRowWidget *self,
+                                         GtkWidget              *child)
+{
+  gtk_widget_unparent (child);
+}
+
diff --git a/gtk/gtkcolumnviewrowwidgetprivate.h b/gtk/gtkcolumnviewrowwidgetprivate.h
new file mode 100644 (file)
index 0000000..b4ea9b2
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2018 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_COLUMN_VIEW_ROW_WIDGET_PRIVATE_H__
+#define __GTK_COLUMN_VIEW_ROW_WIDGET_PRIVATE_H__
+
+#include "gtklistfactorywidgetprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLUMN_VIEW_ROW_WIDGET         (gtk_column_view_row_widget_get_type ())
+#define GTK_COLUMN_VIEW_ROW_WIDGET(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLUMN_VIEW_ROW_WIDGET, GtkColumnViewRowWidget))
+#define GTK_COLUMN_VIEW_ROW_WIDGET_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_COLUMN_VIEW_ROW_WIDGET, GtkColumnViewRowWidgetClass))
+#define GTK_IS_COLUMN_VIEW_ROW_WIDGET(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLUMN_VIEW_ROW_WIDGET))
+#define GTK_IS_COLUMN_VIEW_ROW_WIDGET_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLUMN_VIEW_ROW_WIDGET))
+#define GTK_COLUMN_VIEW_ROW_WIDGET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLUMN_VIEW_ROW_WIDGET, GtkColumnViewRowWidgetClass))
+
+typedef struct _GtkColumnViewRowWidget GtkColumnViewRowWidget;
+typedef struct _GtkColumnViewRowWidgetClass GtkColumnViewRowWidgetClass;
+
+struct _GtkColumnViewRowWidget
+{
+  GtkListFactoryWidget parent_instance;
+};
+
+struct _GtkColumnViewRowWidgetClass
+{
+  GtkListFactoryWidgetClass parent_class;
+};
+
+GType                   gtk_column_view_row_widget_get_type             (void) G_GNUC_CONST;
+
+GtkWidget *             gtk_column_view_row_widget_new                  (GtkListItemFactory     *factory,
+                                                                         const char             *css_name,
+                                                                         GtkAccessibleRole       role);
+
+void                    gtk_column_view_row_widget_add_child            (GtkColumnViewRowWidget *self,
+                                                                         GtkWidget              *child);
+void                    gtk_column_view_row_widget_reorder_child        (GtkColumnViewRowWidget *self,
+                                                                         GtkWidget              *child,
+                                                                         guint                   position);
+void                    gtk_column_view_row_widget_remove_child         (GtkColumnViewRowWidget *self,
+                                                                         GtkWidget              *child);
+
+G_END_DECLS
+
+#endif  /* __GTK_COLUMN_VIEW_ROW_WIDGET_PRIVATE_H__ */
index c22900ff6025d25f542070843ac17c78d033636c..c43a916847d83219a6fd4939b5d05e2a0d0d4a57 100644 (file)
@@ -40,6 +40,7 @@ gtk_private_sources = files([
   'gtkcolorswatch.c',
   'gtkcolumnlistitemfactory.c',
   'gtkcolumnviewcell.c',
+  'gtkcolumnviewrowwidget.c',
   'gtkcolumnviewlayout.c',
   'gtkcolumnviewtitle.c',
   'gtkconstraintexpression.c',