[gtk/prop-list: 32/32] columview: Add autoscroll



commit 9a77a5c33282f75b2dd3a879e5586700d0c7aae7
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Dec 21 00:24:55 2019 -0500

    columview: Add autoscroll
    
    Autoscroll when the pointer gets close to the
    edge during column resizing or reordering. This
    is similar to what the treeview does, but it is
    implemented using a tick callback, and has
    variable speed.

 gtk/gtkcolumnview.c | 124 +++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 107 insertions(+), 17 deletions(-)
---
diff --git a/gtk/gtkcolumnview.c b/gtk/gtkcolumnview.c
index 8681878848..eb892268be 100644
--- a/gtk/gtkcolumnview.c
+++ b/gtk/gtkcolumnview.c
@@ -80,6 +80,10 @@ struct _GtkColumnView
   int drag_column_x;
 
   GtkGesture *drag_gesture;
+
+  guint autoscroll_id;
+  double autoscroll_x;
+  double autoscroll_delta;
 };
 
 struct _GtkColumnViewClass
@@ -546,6 +550,53 @@ gtk_column_view_class_init (GtkColumnViewClass *klass)
   gtk_widget_class_set_css_name (widget_class, I_("treeview"));
 }
 
+static void update_column_resize  (GtkColumnView *self,
+                                   double         x);
+static void update_column_reorder (GtkColumnView *self,
+                                   double         x);
+
+static gboolean
+autoscroll_cb (GtkWidget     *widget,
+               GdkFrameClock *frame_clock,
+               gpointer       data)
+{
+  GtkColumnView *self = data;
+
+  gtk_adjustment_set_value (self->hadjustment,
+                            gtk_adjustment_get_value (self->hadjustment) + self->autoscroll_delta);
+
+  self->autoscroll_x += self->autoscroll_delta;
+
+  if (self->in_column_resize)
+    update_column_resize (self, self->autoscroll_x);
+  else if (self->in_column_reorder)
+    update_column_reorder (self, self->autoscroll_x);
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+add_autoscroll (GtkColumnView *self,
+                double         x,
+                double         delta)
+{
+  self->autoscroll_x = x;
+  self->autoscroll_delta = delta;
+
+  if (self->autoscroll_id == 0)
+    self->autoscroll_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), autoscroll_cb, self, NULL);
+}
+
+static void
+remove_autoscroll (GtkColumnView *self)
+{
+  if (self->autoscroll_id != 0)
+    {
+      gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->autoscroll_id);
+      self->autoscroll_id = 0;
+    }
+}
+
 #define DRAG_WIDTH 6
 
 static gboolean
@@ -655,6 +706,8 @@ header_drag_end (GtkGestureDrag *gesture,
   gtk_gesture_drag_get_start_point (gesture, &start_x, NULL);
   x = start_x + offset_x;
 
+  remove_autoscroll (self);
+
   if (self->in_column_resize)
     {
       self->in_column_resize = FALSE;
@@ -703,6 +756,39 @@ header_drag_end (GtkGestureDrag *gesture,
     }
 }
 
+static void
+update_column_resize (GtkColumnView *self,
+                      double         x)
+{
+  GtkColumnViewColumn *column;
+
+  column = g_list_model_get_item (G_LIST_MODEL (self->columns), self->drag_pos);
+  gtk_column_view_column_set_fixed_width (column, MAX (x - self->drag_x, 0));
+  g_object_unref (column);
+}
+
+static void
+update_column_reorder (GtkColumnView *self,
+                       double         x)
+{
+  GtkColumnViewColumn *column;
+  int width;
+  int size;
+
+  column = g_list_model_get_item (G_LIST_MODEL (self->columns), self->drag_pos);
+
+  width = gtk_widget_get_allocated_width (GTK_WIDGET (self->header));
+  gtk_column_view_column_get_allocation (column, NULL, &size);
+
+  self->drag_x = CLAMP (x - self->drag_offset, 0, width - size);
+
+  gtk_widget_queue_allocate (GTK_WIDGET (self));
+  gtk_column_view_column_queue_resize (column);
+  g_object_unref (column);
+}
+
+#define SCROLL_EDGE_SIZE 15
+
 static void
 header_drag_update (GtkGestureDrag *gesture,
                     double          offset_x,
@@ -710,7 +796,6 @@ header_drag_update (GtkGestureDrag *gesture,
                     GtkColumnView  *self)
 {
   GdkEventSequence *sequence;
-  GtkColumnViewColumn *column;
   double start_x, x;
 
   sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
@@ -720,13 +805,15 @@ header_drag_update (GtkGestureDrag *gesture,
   if (self->drag_pos == -1)
     return;
 
-  column = g_list_model_get_item (G_LIST_MODEL (self->columns), self->drag_pos);
-
   if (!self->in_column_resize && !self->in_column_reorder)
     {
       if (gtk_drag_check_threshold (GTK_WIDGET (self), 0, 0, offset_x, 0))
         {
-          GtkWidget *header = gtk_column_view_column_get_header (column);
+          GtkColumnViewColumn *column;
+          GtkWidget *header;
+
+          column = g_list_model_get_item (G_LIST_MODEL (self->columns), self->drag_pos);
+          header = gtk_column_view_column_get_header (column);
 
           gtk_widget_insert_after (header, self->header, gtk_widget_get_last_child (self->header));
           gtk_style_context_add_class (gtk_widget_get_style_context (header), "dnd");
@@ -736,6 +823,8 @@ header_drag_update (GtkGestureDrag *gesture,
             gtk_widget_grab_focus (GTK_WIDGET (self));
 
           self->in_column_reorder = TRUE;
+
+          g_object_unref (column);
         }
     }
 
@@ -743,24 +832,25 @@ header_drag_update (GtkGestureDrag *gesture,
   x = start_x + offset_x;
 
   if (self->in_column_resize)
-    {
-      gtk_column_view_column_set_fixed_width (column, MAX (x - self->drag_x, 0));
-    }
+    update_column_resize (self, x);
   else if (self->in_column_reorder)
-    {
-      int width;
-      int size;
+    update_column_reorder (self, x);
 
-      width = gtk_widget_get_allocated_width (GTK_WIDGET (self->header));
-      gtk_column_view_column_get_allocation (column, NULL, &size);
+  if (self->in_column_resize || self->in_column_reorder)
+    {
+      double value, page_size, upper;
 
-      self->drag_x = CLAMP (x - self->drag_offset, 0, width - size);
+      value = gtk_adjustment_get_value (self->hadjustment);
+      page_size = gtk_adjustment_get_page_size (self->hadjustment);
+      upper = gtk_adjustment_get_upper (self->hadjustment);
 
-      gtk_widget_queue_allocate (GTK_WIDGET (self));
-      gtk_column_view_column_queue_resize (column);
+      if (x - value < SCROLL_EDGE_SIZE && value > 0)
+        add_autoscroll (self, x, - (SCROLL_EDGE_SIZE - (x - value))/3.0);
+      else if (value + page_size - x < SCROLL_EDGE_SIZE && value + page_size < upper)
+        add_autoscroll (self, x, (SCROLL_EDGE_SIZE - (value + page_size - x))/3.0);
+      else
+        remove_autoscroll (self);
     }
-
-  g_object_unref (column);
 }
 
 static void


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