[gtk/wip/otte/listview: 98/155] gridview: Implement list.scroll-to action



commit 864ef58ef3c9f260a1ea914e31926caeaa774c9f
Author: Benjamin Otte <otte redhat com>
Date:   Sun Oct 20 18:52:28 2019 +0200

    gridview: Implement list.scroll-to action

 gtk/gtkgridview.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 112 insertions(+)
---
diff --git a/gtk/gtkgridview.c b/gtk/gtkgridview.c
index 543a4b01d4..40ff8cddd9 100644
--- a/gtk/gtkgridview.c
+++ b/gtk/gtkgridview.c
@@ -1214,6 +1214,106 @@ gtk_grid_view_select_item_action (GtkWidget  *widget,
   gtk_grid_view_select_item (self, pos, modify, extend);
 }
 
+static void
+gtk_grid_view_compute_scroll_align (GtkGridView   *self,
+                                    GtkOrientation orientation,
+                                    int            cell_start,
+                                    int            cell_end,
+                                    double         current_align,
+                                    gboolean       current_start,
+                                    double        *new_align,
+                                    gboolean      *new_start)
+{
+  int visible_start, visible_size, visible_end;
+  int cell_size;
+
+  visible_start = gtk_adjustment_get_value (self->adjustment[orientation]);
+  visible_size = gtk_adjustment_get_page_size (self->adjustment[orientation]);
+  if (gtk_grid_view_adjustment_is_flipped (self, orientation))
+    visible_start = gtk_adjustment_get_upper (self->adjustment[orientation]) - visible_size - visible_start;
+  visible_end = visible_start + visible_size;
+  cell_size = cell_end - cell_start;
+
+  if (cell_size <= visible_size)
+    {
+      if (cell_start < visible_start)
+        {
+          *new_align = 0.0;
+          *new_start = TRUE;
+        }
+      else if (cell_end > visible_end)
+        {
+          *new_align = 1.0;
+          *new_start = FALSE;
+        }
+      else
+        {
+          /* XXX: start or end here? */
+          *new_start = TRUE;
+          *new_align = (double) (cell_start - visible_start) / visible_size;
+        }
+    }
+  else
+    {
+      /* This is the unlikely case of the cell being higher than the visible area */
+      if (cell_start > visible_start)
+        {
+          *new_align = 0.0;
+          *new_start = TRUE;
+        }
+      else if (cell_end < visible_end)
+        {
+          *new_align = 1.0;
+          *new_start = FALSE;
+        }
+      else
+        {
+          /* the cell already covers the whole screen */
+          *new_align = current_align;
+          *new_start = current_start;
+        }
+    }
+}
+
+static void
+gtk_grid_view_scroll_to_item (GtkWidget  *widget,
+                              const char *action_name,
+                              GVariant   *parameter)
+{
+  GtkGridView *self = GTK_GRID_VIEW (widget);
+  int start, end;
+  double xalign, yalign;
+  gboolean xstart, ystart;
+  guint pos;
+
+  if (!g_variant_check_format_string (parameter, "u", FALSE))
+    return;
+
+  g_variant_get (parameter, "u", &pos);
+
+  /* figure out primary orientation and if position is valid */
+  if (!gtk_grid_view_get_size_at_position (self, pos, &start, &end))
+    return;
+
+  end += start;
+  gtk_grid_view_compute_scroll_align (self,
+                                      self->orientation,
+                                      start, end,
+                                      self->anchor_yalign, self->anchor_ystart,
+                                      &yalign, &ystart);
+
+  /* now do the same thing with the other orientation */
+  start = floor (self->column_width * (pos % self->n_columns));
+  end = floor (self->column_width * ((pos % self->n_columns) + 1));
+  gtk_grid_view_compute_scroll_align (self,
+                                      OPPOSITE_ORIENTATION (self->orientation),
+                                      start, end,
+                                      self->anchor_xalign, self->anchor_xstart,
+                                      &xalign, &xstart);
+
+  gtk_grid_view_set_anchor (self, pos, xalign, xstart, yalign, ystart);
+}
+
 static void
 gtk_grid_view_activate_item (GtkWidget  *widget,
                              const char *action_name,
@@ -1388,6 +1488,18 @@ gtk_grid_view_class_init (GtkGridViewClass *klass)
                                    "(ubb)",
                                    gtk_grid_view_select_item_action);
 
+  /**
+   * GtkGridView|list.scroll-to-item:
+   * @position: position of item to scroll to
+   *
+   * Scrolls to the item given in @position with the minimum amount
+   * of scrolling required. If the item is already visible, nothing happens.
+   */
+  gtk_widget_class_install_action (widget_class,
+                                   "list.scroll-to-item",
+                                   "u",
+                                   gtk_grid_view_scroll_to_item);
+
   gtk_widget_class_set_css_name (widget_class, I_("flowbox"));
 
 }


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