From e9eb52f51edd782850c526f4014fada8f5568fcf Mon Sep 17 00:00:00 2001
From: Benedikt Meurer <benny@xfce.org>
Date: Tue, 28 Feb 2006 12:12:51 +0000
Subject: [PATCH] 2006-02-28	Benedikt Meurer <benny@xfce.org>

	* thunar/thunar-details-view.c, thunar/thunar-icon-view.c,
	  thunar/thunar-standard-view.{c,h}: Remember the scroll offset when
	  changing directory and apply saved scroll offset once a folder is
	  loaded again.




(Old svn revision: 20131)
---
 ChangeLog                     |  7 +++
 thunar/thunar-details-view.c  | 32 ++++++++++--
 thunar/thunar-icon-view.c     | 27 ++++++++--
 thunar/thunar-standard-view.c | 93 +++++++++++++++++++++++++++++++----
 thunar/thunar-standard-view.h | 10 +++-
 5 files changed, 152 insertions(+), 17 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8c6095383..82f8e94b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-02-28	Benedikt Meurer <benny@xfce.org>
+
+	* thunar/thunar-details-view.c, thunar/thunar-icon-view.c,
+	  thunar/thunar-standard-view.{c,h}: Remember the scroll offset when
+	  changing directory and apply saved scroll offset once a folder is
+	  loaded again.
+
 2006-02-27	Benedikt Meurer <benny@xfce.org>
 
 	* thunar/thunar-path-entry.c(thunar_path_entry_common_prefix_append): Do
diff --git a/thunar/thunar-details-view.c b/thunar/thunar-details-view.c
index c27107836..b68f27f52 100644
--- a/thunar/thunar-details-view.c
+++ b/thunar/thunar-details-view.c
@@ -40,10 +40,16 @@ static void         thunar_details_view_set_cursor            (ThunarStandardVie
                                                                GtkTreePath            *path,
                                                                gboolean                start_editing);
 static void         thunar_details_view_scroll_to_path        (ThunarStandardView     *standard_view,
-                                                               GtkTreePath            *path);
+                                                               GtkTreePath            *path,
+                                                               gboolean                use_align,
+                                                               gfloat                  row_align,
+                                                               gfloat                  col_align);
 static GtkTreePath *thunar_details_view_get_path_at_pos       (ThunarStandardView     *standard_view,
                                                                gint                    x,
                                                                gint                    y);
+static gboolean     thunar_details_view_get_visible_range     (ThunarStandardView     *standard_view,
+                                                               GtkTreePath           **start_path,
+                                                               GtkTreePath           **end_path);
 static void         thunar_details_view_highlight_path        (ThunarStandardView     *standard_view,
                                                                GtkTreePath            *path);
 static void         thunar_details_view_notify_model          (GtkTreeView            *tree_view,
@@ -128,6 +134,7 @@ thunar_details_view_class_init (ThunarDetailsViewClass *klass)
   thunarstandard_view_class->set_cursor = thunar_details_view_set_cursor;
   thunarstandard_view_class->scroll_to_path = thunar_details_view_scroll_to_path;
   thunarstandard_view_class->get_path_at_pos = thunar_details_view_get_path_at_pos;
+  thunarstandard_view_class->get_visible_range = thunar_details_view_get_visible_range;
   thunarstandard_view_class->highlight_path = thunar_details_view_highlight_path;
   thunarstandard_view_class->zoom_level_property_name = "last-details-view-zoom-level";
 }
@@ -349,7 +356,10 @@ thunar_details_view_set_cursor (ThunarStandardView *standard_view,
 
 static void
 thunar_details_view_scroll_to_path (ThunarStandardView *standard_view,
-                                    GtkTreePath        *path)
+                                    GtkTreePath        *path,
+                                    gboolean            use_align,
+                                    gfloat              row_align,
+                                    gfloat              col_align)
 {
   GtkTreeViewColumn *column;
 
@@ -357,7 +367,7 @@ thunar_details_view_scroll_to_path (ThunarStandardView *standard_view,
 
   /* tell the tree view to scroll to the given row */
   column = gtk_tree_view_get_column (GTK_TREE_VIEW (GTK_BIN (standard_view)->child), 0);
-  gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (GTK_BIN (standard_view)->child), path, column, FALSE, 0.0f, 0.0f);
+  gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (GTK_BIN (standard_view)->child), path, column, use_align, row_align, col_align);
 }
 
 
@@ -379,6 +389,22 @@ thunar_details_view_get_path_at_pos (ThunarStandardView *standard_view,
 
 
 
+static gboolean
+thunar_details_view_get_visible_range (ThunarStandardView *standard_view,
+                                       GtkTreePath       **start_path,
+                                       GtkTreePath       **end_path)
+{
+  g_return_val_if_fail (THUNAR_IS_DETAILS_VIEW (standard_view), FALSE);
+
+#if GTK_CHECK_VERSION(2,8,0)
+  return gtk_tree_view_get_visible_range (GTK_TREE_VIEW (GTK_BIN (standard_view)->child), start_path, end_path);
+#else
+  return FALSE;
+#endif
+}
+
+
+
 static void
 thunar_details_view_highlight_path (ThunarStandardView *standard_view,
                                     GtkTreePath        *path)
diff --git a/thunar/thunar-icon-view.c b/thunar/thunar-icon-view.c
index 552471230..f6da88414 100644
--- a/thunar/thunar-icon-view.c
+++ b/thunar/thunar-icon-view.c
@@ -59,10 +59,16 @@ static void         thunar_icon_view_set_cursor             (ThunarStandardView
                                                              GtkTreePath         *path,
                                                              gboolean             start_editing);
 static void         thunar_icon_view_scroll_to_path         (ThunarStandardView  *standard_view,
-                                                             GtkTreePath         *path);
+                                                             GtkTreePath         *path,
+                                                             gboolean             use_align,
+                                                             gfloat               row_align,
+                                                             gfloat               col_align);
 static GtkTreePath *thunar_icon_view_get_path_at_pos        (ThunarStandardView  *standard_view,
                                                              gint                 x,
                                                              gint                 y);
+static gboolean     thunar_icon_view_get_visible_range      (ThunarStandardView  *standard_view,
+                                                             GtkTreePath        **start_path,
+                                                             GtkTreePath        **end_path);
 static void         thunar_icon_view_highlight_path         (ThunarStandardView  *standard_view,
                                                              GtkTreePath         *path);
 static GtkAction   *thunar_icon_view_gesture_action         (ThunarIconView      *icon_view);
@@ -200,6 +206,7 @@ thunar_icon_view_class_init (ThunarIconViewClass *klass)
   thunarstandard_view_class->set_cursor = thunar_icon_view_set_cursor;
   thunarstandard_view_class->scroll_to_path = thunar_icon_view_scroll_to_path;
   thunarstandard_view_class->get_path_at_pos = thunar_icon_view_get_path_at_pos;
+  thunarstandard_view_class->get_visible_range = thunar_icon_view_get_visible_range;
   thunarstandard_view_class->highlight_path = thunar_icon_view_highlight_path;
   thunarstandard_view_class->zoom_level_property_name = "last-icon-view-zoom-level";
 
@@ -423,10 +430,13 @@ thunar_icon_view_set_cursor (ThunarStandardView *standard_view,
 
 static void
 thunar_icon_view_scroll_to_path (ThunarStandardView *standard_view,
-                                 GtkTreePath        *path)
+                                 GtkTreePath        *path,
+                                 gboolean            use_align,
+                                 gfloat              row_align,
+                                 gfloat              col_align)
 {
   g_return_if_fail (THUNAR_IS_ICON_VIEW (standard_view));
-  exo_icon_view_scroll_to_path (EXO_ICON_VIEW (GTK_BIN (standard_view)->child), path, FALSE, 0.0f, 0.0f);
+  exo_icon_view_scroll_to_path (EXO_ICON_VIEW (GTK_BIN (standard_view)->child), path, use_align, row_align, col_align);
 }
 
 
@@ -442,6 +452,17 @@ thunar_icon_view_get_path_at_pos (ThunarStandardView *standard_view,
 
 
 
+static gboolean
+thunar_icon_view_get_visible_range (ThunarStandardView *standard_view,
+                                    GtkTreePath       **start_path,
+                                    GtkTreePath       **end_path)
+{
+  g_return_val_if_fail (THUNAR_IS_ICON_VIEW (standard_view), FALSE);
+  return exo_icon_view_get_visible_range (EXO_ICON_VIEW (GTK_BIN (standard_view)->child), start_path, end_path);
+}
+
+
+
 static void
 thunar_icon_view_highlight_path (ThunarStandardView *standard_view,
                                  GtkTreePath        *path)
diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c
index cb94ec318..07d326d17 100644
--- a/thunar/thunar-standard-view.c
+++ b/thunar/thunar-standard-view.c
@@ -113,6 +113,8 @@ static ThunarFile          *thunar_standard_view_get_current_directory      (Thu
 static void                 thunar_standard_view_set_current_directory      (ThunarNavigator          *navigator,
                                                                              ThunarFile               *current_directory);
 static gboolean             thunar_standard_view_get_loading                (ThunarView               *view);
+static void                 thunar_standard_view_set_loading                (ThunarStandardView       *standard_view,
+                                                                             gboolean                  loading);
 static const gchar         *thunar_standard_view_get_statusbar_text         (ThunarView               *view);
 static gboolean             thunar_standard_view_get_show_hidden            (ThunarView               *view);
 static void                 thunar_standard_view_set_show_hidden            (ThunarView               *view,
@@ -276,6 +278,9 @@ struct _ThunarStandardViewPrivate
    * new files are created by a ThunarVfsJob associated with this view
    */
   GClosure               *new_files_closure;
+
+  /* scroll offsets (-> GtkTreePath indices) per VFS path */
+  GHashTable             *scroll_offsets;
 };
 
 
@@ -513,6 +518,10 @@ thunar_standard_view_init (ThunarStandardView *standard_view)
   standard_view->priv->drag_scroll_timer_id = -1;
   standard_view->priv->drag_timer_id = -1;
 
+  /* setup the scroll paths offset table */
+  standard_view->priv->scroll_offsets = g_hash_table_new_full (thunar_vfs_path_hash, thunar_vfs_path_equal,
+                                                               (GDestroyNotify) thunar_vfs_path_unref, NULL);
+
   /* grab a reference on the preferences */
   standard_view->preferences = thunar_preferences_get ();
 
@@ -726,6 +735,9 @@ thunar_standard_view_finalize (GObject *object)
   /* release our list of currently selected files */
   thunar_file_list_free (standard_view->selected_files);
 
+  /* destroy the scroll offset table */
+  g_hash_table_destroy (standard_view->priv->scroll_offsets);
+
   /* free the statusbar text (if any) */
   g_free (standard_view->statusbar_text);
 
@@ -785,7 +797,6 @@ thunar_standard_view_set_property (GObject      *object,
                                    GParamSpec   *pspec)
 {
   ThunarStandardView *standard_view = THUNAR_STANDARD_VIEW (object);
-  gboolean            loading;
 
   switch (prop_id)
     {
@@ -794,13 +805,8 @@ thunar_standard_view_set_property (GObject      *object,
       break;
 
     case PROP_LOADING:
-      loading = g_value_get_boolean (value);
-      if (G_LIKELY (loading != standard_view->loading))
-        {
-          standard_view->loading = loading;
-          g_object_notify (object, "loading");
-          g_object_notify (object, "statusbar-text");
-        }
+      thunar_standard_view_set_loading (standard_view, g_value_get_boolean (value));
+      break;
       break;
       
     case PROP_SELECTED_FILES:
@@ -973,7 +979,7 @@ thunar_standard_view_set_selected_files (ThunarComponent *component,
         }
 
       /* scroll to the first path (previously determined) */
-      (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->scroll_to_path) (standard_view, first_path);
+      (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->scroll_to_path) (standard_view, first_path, FALSE, 0.0f, 0.0f);
 
       /* release the tree paths */
       g_list_foreach (paths, (GFunc) gtk_tree_path_free, NULL);
@@ -1084,9 +1090,33 @@ thunar_standard_view_set_current_directory (ThunarNavigator *navigator,
 {
   ThunarStandardView *standard_view = THUNAR_STANDARD_VIEW (navigator);
   ThunarFolder       *folder;
+  GtkTreePath        *path;
+  ThunarFile         *file;
+  gint                offset;
 
   g_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
   g_return_if_fail (current_directory == NULL || THUNAR_IS_FILE (current_directory));
+  
+  /* determine the (previous) current directory */
+  file = thunar_navigator_get_current_directory (navigator);
+  if (G_LIKELY (file != NULL))
+    {
+      /* determine the first visible tree path */
+      if ((*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->get_visible_range) (standard_view, &path, NULL))
+        {
+          /* determine the scroll offset from the tree path */
+          offset = gtk_tree_path_get_indices (path)[0] + 1;
+          gtk_tree_path_free (path);
+        }
+      else
+        {
+          /* just use the first available path */
+          offset = 0;
+        }
+
+      /* remember the scroll offset for the directory */
+      g_hash_table_replace (standard_view->priv->scroll_offsets, thunar_vfs_path_ref (thunar_file_get_path (file)), GINT_TO_POINTER (offset));
+    }
 
   /* disconnect any previous "loading" binding */
   if (G_LIKELY (standard_view->loading_binding != NULL))
@@ -1134,6 +1164,49 @@ thunar_standard_view_get_loading (ThunarView *view)
 
 
 
+static void
+thunar_standard_view_set_loading (ThunarStandardView *standard_view,
+                                  gboolean            loading)
+{
+  GtkTreePath *path;
+  ThunarFile  *file;
+  gint         offset;
+
+  loading = !!loading;
+
+  /* check if we're already in that state */
+  if (G_UNLIKELY (standard_view->loading == loading))
+    return;
+
+  /* apply the new state */
+  standard_view->loading = loading;
+
+  /* check if this state change was due to a "loading complete" event */
+  if (G_LIKELY (!loading))
+    {
+      /* determine the current directory */
+      file = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view));
+      if (G_LIKELY (file != NULL))
+        {
+          /* determine the scroll offset for this folder */
+          offset = GPOINTER_TO_INT (g_hash_table_lookup (standard_view->priv->scroll_offsets, thunar_file_get_path (file)));
+          if (G_LIKELY (offset > 0))
+            {
+              /* scroll to the path for the offset */
+              path = gtk_tree_path_new_from_indices (offset - 1, -1);
+              (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->scroll_to_path) (standard_view, path, TRUE, 0.0f, 0.0f);
+              gtk_tree_path_free (path);
+            }
+        }
+    }
+
+  /* notify listeners */
+  g_object_notify (G_OBJECT (standard_view), "loading");
+  g_object_notify (G_OBJECT (standard_view), "statusbar-text");
+}
+
+
+
 static const gchar*
 thunar_standard_view_get_statusbar_text (ThunarView *view)
 {
@@ -2123,7 +2196,7 @@ thunar_standard_view_action_rename (GtkAction          *action,
                   if (G_LIKELY (path_list != NULL))
                     {
                       /* place the cursor on the file and scroll the new position */
-                      (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->scroll_to_path) (standard_view, path_list->data);
+                      (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->scroll_to_path) (standard_view, path_list->data, FALSE, 0.0f, 0.0f);
 
                       /* update the selection, so we get updated actions, statusbar,
                        * etc. with the new file name and probably new mime type.
diff --git a/thunar/thunar-standard-view.h b/thunar/thunar-standard-view.h
index 03c01dcf6..0e3103317 100644
--- a/thunar/thunar-standard-view.h
+++ b/thunar/thunar-standard-view.h
@@ -78,7 +78,10 @@ struct _ThunarStandardViewClass
    * scroll the view to the given path.
    */
   void         (*scroll_to_path)        (ThunarStandardView *standard_view,
-                                         GtkTreePath        *path);
+                                         GtkTreePath        *path,
+                                         gboolean            use_align,
+                                         gfloat              row_align,
+                                         gfloat              col_align);
 
   /* Returns the path at the given position or NULL if no item/row
    * is located at that coordinates. The path is freed by the caller.
@@ -87,6 +90,11 @@ struct _ThunarStandardViewClass
                                          gint                x,
                                          gint                y);
 
+  /* Returns the visible range */
+  gboolean     (*get_visible_range)     (ThunarStandardView *standard_view,
+                                         GtkTreePath       **start_path,
+                                         GtkTreePath       **end_path);
+
   /* Sets the item/row that is highlighted for feedback. NULL is
    * passed for path to disable the highlighting.
    */
-- 
GitLab