columnview: add a (private) focus-column
authorBenjamin Otte <otte@redhat.com>
Thu, 23 Mar 2023 02:35:04 +0000 (03:35 +0100)
committerBenjamin Otte <otte@redhat.com>
Thu, 23 Mar 2023 03:51:20 +0000 (04:51 +0100)
Make setting the focus column scroll to it, too.

gtk/gtkcolumnview.c
gtk/gtkcolumnviewprivate.h
gtk/gtkcolumnviewrowwidget.c

index e564a12d4e3bb7c4e74c362ce7fa6f099821e7aa..bf0876dfcbad08df6442e5f325fb938cdab17160 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "gtkcolumnviewprivate.h"
 
+#include "gtkadjustment.h"
 #include "gtkboxlayout.h"
 #include "gtkbuildable.h"
 #include "gtkcolumnviewcolumnprivate.h"
@@ -31,9 +32,8 @@
 #include "gtkmain.h"
 #include "gtkprivate.h"
 #include "gtkscrollable.h"
-#include "gtkwidgetprivate.h"
 #include "gtksizerequest.h"
-#include "gtkadjustment.h"
+#include "gtkwidgetprivate.h"
 #include "gtkgesturedrag.h"
 #include "gtkeventcontrollermotion.h"
 #include "gtkdragsourceprivate.h"
@@ -166,6 +166,8 @@ struct _GtkColumnView
 
   GListStore *columns;
 
+  GtkColumnViewColumn *focus_column;
+
   GtkWidget *header;
 
   GtkListView *listview;
@@ -495,6 +497,8 @@ gtk_column_view_dispose (GObject *object)
       g_object_unref (column);
     }
 
+  g_assert (self->focus_column == NULL);
+
   g_clear_pointer (&self->header, gtk_widget_unparent);
 
   g_clear_pointer ((GtkWidget **) &self->listview, gtk_widget_unparent);
@@ -1547,6 +1551,20 @@ gtk_column_view_remove_column (GtkColumnView       *self,
   gtk_column_view_sorter_remove_column (GTK_COLUMN_VIEW_SORTER (self->sorter), column);
   gtk_column_view_column_set_column_view (column, NULL);
   g_list_store_remove (self->columns, i);
+
+  if (self->focus_column == column)
+    {
+      GtkColumnViewColumn *item;
+
+      if (i < g_list_model_get_n_items (G_LIST_MODEL (self->columns)))
+        item = g_list_model_get_item (G_LIST_MODEL (self->columns), i);
+      else if (i > 0)
+        item = g_list_model_get_item (G_LIST_MODEL (self->columns), i - 1);
+      else
+        item = NULL;
+
+      gtk_column_view_set_focus_column (self, item);
+    }
 }
 
 /**
@@ -1603,6 +1621,43 @@ gtk_column_view_insert_column (GtkColumnView       *self,
   g_object_unref (column);
 }
 
+static void
+gtk_column_view_scroll_to_column (GtkColumnView       *self,
+                                  GtkColumnViewColumn *column)
+{
+  int col_x, col_width, adj_x, adj_width;
+
+  gtk_column_view_column_get_header_allocation (column, &col_x, &col_width);
+  adj_x = gtk_adjustment_get_value (self->hadjustment);
+  adj_width = gtk_adjustment_get_page_size (self->hadjustment);
+
+  if (col_x < adj_x)
+    gtk_adjustment_set_value (self->hadjustment, col_x);
+  else if (col_x + col_width > adj_x + adj_width)
+    gtk_adjustment_set_value (self->hadjustment, adj_x + adj_width - col_width);
+}
+
+void
+gtk_column_view_set_focus_column (GtkColumnView       *self,
+                                  GtkColumnViewColumn *column)
+{
+  g_assert (column == NULL || gtk_column_view_column_get_column_view (column) == self);
+
+  if (self->focus_column == column)
+    return;
+
+  self->focus_column = column;
+
+  if (column)
+    gtk_column_view_scroll_to_column (self, column);
+}
+
+GtkColumnViewColumn *
+gtk_column_view_get_focus_column (GtkColumnView *self)
+{
+  return self->focus_column;
+}
+
 void
 gtk_column_view_measure_across (GtkColumnView *self,
                                 int           *minimum,
index a1433a8dbb7a764ca5d670e28ee44201c4b80121..65bc3679e83bf1880037c62bdc7a695f1282b64b 100644 (file)
@@ -38,4 +38,8 @@ void                    gtk_column_view_distribute_width        (GtkColumnView
                                                                  int                     width,
                                                                  GtkRequestedSize       *sizes);
 
+void                    gtk_column_view_set_focus_column        (GtkColumnView          *self,
+                                                                 GtkColumnViewColumn    *focus_column);
+GtkColumnViewColumn *   gtk_column_view_get_focus_column        (GtkColumnView          *self);
+
 #endif  /* __GTK_COLUMN_VIEW_PRIVATE_H__ */
index b4f4ef9fa7bb7e0a28b492132a8511cda39ef573..cf2c4343566fb5b2960b37e769846db03d976be9 100644 (file)
@@ -53,6 +53,17 @@ gtk_column_view_row_widget_is_header (GtkColumnViewRowWidget *self)
   return gtk_widget_get_css_name (GTK_WIDGET (self)) == g_intern_static_string ("header");
 }
 
+static GtkColumnViewColumn *
+gtk_column_view_row_child_get_column (GtkWidget *child)
+{
+  if (GTK_IS_COLUMN_VIEW_CELL (child))
+    return gtk_column_view_cell_get_column (GTK_COLUMN_VIEW_CELL (child));
+  else
+    return gtk_column_view_title_get_column (GTK_COLUMN_VIEW_TITLE (child));
+
+  g_return_val_if_reached (NULL);
+}
+
 static void
 gtk_column_view_row_widget_update (GtkListItemBase *base,
                                    guint            position,
@@ -192,6 +203,21 @@ gtk_column_view_row_widget_grab_focus (GtkWidget *widget)
   return GTK_WIDGET_CLASS (gtk_column_view_row_widget_parent_class)->grab_focus (widget);
 }
 
+static void
+gtk_column_view_row_widget_set_focus_child (GtkWidget *widget,
+                                            GtkWidget *child)
+{
+  GtkColumnViewRowWidget *self = GTK_COLUMN_VIEW_ROW_WIDGET (widget);
+
+  GTK_WIDGET_CLASS (gtk_column_view_row_widget_parent_class)->set_focus_child (widget, child);
+
+  if (child)
+    {
+      gtk_column_view_set_focus_column (gtk_column_view_row_widget_get_column_view (self),
+                                        gtk_column_view_row_child_get_column (child));
+    }
+}
+
 static void
 gtk_column_view_row_widget_root (GtkWidget *widget)
 {
@@ -341,10 +367,7 @@ gtk_column_view_row_widget_allocate (GtkWidget *widget,
       if (!gtk_widget_should_layout (child))
         continue;
 
-      if (GTK_IS_COLUMN_VIEW_CELL (child))
-        column = gtk_column_view_cell_get_column (GTK_COLUMN_VIEW_CELL (child));
-      else
-        column = gtk_column_view_title_get_column (GTK_COLUMN_VIEW_TITLE (child));
+      column = gtk_column_view_row_child_get_column (child);
       gtk_column_view_column_get_header_allocation (column, &col_x, &col_width);
 
       gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL);
@@ -388,6 +411,7 @@ gtk_column_view_row_widget_class_init (GtkColumnViewRowWidgetClass *klass)
 
   widget_class->focus = gtk_column_view_row_widget_focus;
   widget_class->grab_focus = gtk_column_view_row_widget_grab_focus;
+  widget_class->set_focus_child = gtk_column_view_row_widget_set_focus_child;
   widget_class->measure = gtk_column_view_row_widget_measure;
   widget_class->size_allocate = gtk_column_view_row_widget_allocate;
   widget_class->root = gtk_column_view_row_widget_root;