[gnome-builder/scrolloff] gb-source-vim: Add support for vim scrolloff



commit bdb83cb29fc8c70ac80624ddd4c2f023c448f0ec
Author: Carlos Soriano <carlos soriano89 gmail com>
Date:   Sun Jan 4 21:34:19 2015 +0100

    gb-source-vim: Add support for vim scrolloff
    
    Vim scrolloff allow the user to set a margin of a number of lines
    while moving through the buffer.
    Add support to it and add a setting to let the user adjust the number
    of lines.
    
    As a detail, a scrolloff greater than half of the number of lines in the
    buffer keeps the current line always in the middle.

 src/vim/gb-source-vim.c |  126 +++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 106 insertions(+), 20 deletions(-)
---
diff --git a/src/vim/gb-source-vim.c b/src/vim/gb-source-vim.c
index 5694d81..757cae8 100644
--- a/src/vim/gb-source-vim.c
+++ b/src/vim/gb-source-vim.c
@@ -17,7 +17,7 @@
  */
 
 #define G_LOG_DOMAIN "vim"
-#define SCROLL_OFF 3
+#define SCROLL_OFF 10
 
 #include <errno.h>
 #include <glib/gi18n.h>
@@ -108,6 +108,14 @@ typedef enum
 
 typedef enum
 {
+  GB_SOURCE_VIM_ALIGMENT_NONE,
+  GB_SOURCE_VIM_ALIGMENT_KEEP,
+  GB_SOURCE_VIM_ALIGMENT_TOP,
+  GB_SOURCE_VIM_ALIGMENT_BOTTOM
+} GbSourceVimAligment;
+
+typedef enum
+{
   GB_SOURCE_VIM_COMMAND_NOOP,
   GB_SOURCE_VIM_COMMAND_MOVEMENT,
   GB_SOURCE_VIM_COMMAND_CHANGE,
@@ -139,6 +147,12 @@ typedef struct
   GbSourceVimCommandFlags flags;
 } GbSourceVimCommand;
 
+typedef struct
+{
+  gfloat yalign;
+  gint   line;
+} GbSourceVimAdjustedScroll;
+
 typedef enum
 {
   GB_SOURCE_VIM_PHRASE_FAILED,
@@ -209,6 +223,10 @@ static void gb_source_vim_cmd_delete_to_end (GbSourceVim *vim,
 static void gb_source_vim_cmd_insert_before_line (GbSourceVim *vim,
                                                   guint        count,
                                                   gchar        modifier);
+static GbSourceVimAdjustedScroll
+gb_source_vim_adjust_scroll (GbSourceVim *vim,
+                             gint         line,
+                             GbSourceVimAligment aligment);
 
 GbSourceVim *
 gb_source_vim_new (GtkTextView *text_view)
@@ -1458,6 +1476,7 @@ gb_source_vim_move_down (GbSourceVim *vim)
   GtkTextIter selection;
   gboolean has_selection;
   guint line;
+  GbSourceVimAdjustedScroll scroll;
   guint offset;
 
   g_assert (GB_IS_SOURCE_VIM (vim));
@@ -1530,6 +1549,9 @@ select_to_end:
 move_mark:
   insert = gtk_text_buffer_get_insert (buffer);
   gtk_text_view_scroll_mark_onscreen (vim->priv->text_view, insert);
+  scroll= gb_source_vim_adjust_scroll (vim, line + 1, GB_SOURCE_VIM_ALIGMENT_NONE);
+  gtk_text_view_scroll_to_iter (vim->priv->text_view, &iter, 0.0,
+                                TRUE, 0.5, scroll.yalign);
 }
 
 static void
@@ -1542,6 +1564,7 @@ gb_source_vim_move_up (GbSourceVim *vim)
   GtkTextIter selection;
   gboolean has_selection;
   guint line;
+  GbSourceVimAdjustedScroll scroll;
   guint offset;
 
   g_assert (GB_IS_SOURCE_VIM (vim));
@@ -1598,6 +1621,9 @@ gb_source_vim_move_up (GbSourceVim *vim)
 move_mark:
   insert = gtk_text_buffer_get_insert (buffer);
   gtk_text_view_scroll_mark_onscreen (vim->priv->text_view, insert);
+  scroll= gb_source_vim_adjust_scroll (vim, line - 1, GB_SOURCE_VIM_ALIGMENT_NONE);
+  gtk_text_view_scroll_to_iter (vim->priv->text_view, &iter, 0.0,
+                                TRUE, 0.5, scroll.yalign);
 }
 
 static void
@@ -2626,6 +2652,72 @@ gb_source_vim_move_to_iter (GbSourceVim *vim,
                                 TRUE, 0.5, yalign);
 }
 
+static GbSourceVimAdjustedScroll
+gb_source_vim_adjust_scroll (GbSourceVim *vim,
+                             gint         line,
+                             GbSourceVimAligment aligment)
+{
+  GdkRectangle rect;
+  gint line_top, line_bottom, line_current;
+  gint page_lines, min_line, max_line;
+  gint adjusted_line;
+  GtkTextIter iter_top, iter_bottom, iter_current;
+  GtkTextBuffer *buffer;
+  gfloat adjusted_yalign, min_yalign, max_yalign, yalign;
+  GbSourceVimAdjustedScroll result;
+
+  g_assert (GB_IS_SOURCE_VIM (vim));
+
+  gtk_text_view_get_visible_rect (vim->priv->text_view, &rect);
+  gtk_text_view_get_iter_at_location (vim->priv->text_view, &iter_top,
+                                      rect.x, rect.y);
+  gtk_text_view_get_iter_at_location (vim->priv->text_view, &iter_bottom,
+                                      rect.x, rect.y + rect.height);
+
+  buffer = gtk_text_view_get_buffer (vim->priv->text_view);
+  gtk_text_buffer_get_selection_bounds (buffer, &iter_current, NULL);
+
+  line_top = gtk_text_iter_get_line (&iter_top);
+  line_bottom = gtk_text_iter_get_line (&iter_bottom);
+  line_current = gtk_text_iter_get_line (&iter_current);
+  page_lines = line_bottom - line_top;
+  min_yalign = MIN (SCROLL_OFF / (float) page_lines, 0.5);
+  max_yalign = 1.0 - min_yalign;
+  yalign = (line - line_top) / (float) page_lines;
+  min_line = MIN (SCROLL_OFF, page_lines / 2) + line_top;
+  max_line = line_bottom - MIN (SCROLL_OFF, page_lines / 2);
+
+  g_print ("min max %f, %f, %f \n", max_yalign, min_yalign, yalign);
+
+  switch (aligment)
+    {
+    case GB_SOURCE_VIM_ALIGMENT_NONE:
+        adjusted_yalign = CLAMP (yalign, min_yalign, max_yalign);
+        adjusted_line = line;
+      break;
+    case GB_SOURCE_VIM_ALIGMENT_KEEP:
+      adjusted_yalign = MAX (0.0, (float)(line_current - line_top) /
+                         (float)(line_bottom - line_top));
+      adjusted_line = line;
+      break;
+    case GB_SOURCE_VIM_ALIGMENT_TOP:
+        adjusted_yalign = CLAMP (0.0, min_yalign, max_yalign);
+        adjusted_line = line + adjusted_yalign * page_lines;
+      break;
+    case GB_SOURCE_VIM_ALIGMENT_BOTTOM:
+        adjusted_yalign = CLAMP (1.0, min_yalign, max_yalign);
+        adjusted_line = line - (1.0 - adjusted_yalign) * page_lines;
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  result.yalign = adjusted_yalign;
+  result.line = adjusted_line;
+
+  return result;
+}
+
 static void
 gb_source_vim_move_page (GbSourceVim                 *vim,
                          GbSourceVimPageDirectionType direction)
@@ -2635,7 +2727,8 @@ gb_source_vim_move_page (GbSourceVim                 *vim,
   guint offset;
   gint line, line_top, line_bottom, line_current;
   GtkTextBuffer *buffer;
-  gfloat yalign = 0.0;
+  GbSourceVimAdjustedScroll adjusted_scroll;
+  gfloat yalign;
 
   g_assert (GB_IS_SOURCE_VIM (vim));
 
@@ -2652,47 +2745,40 @@ gb_source_vim_move_page (GbSourceVim                 *vim,
   line_bottom = gtk_text_iter_get_line (&iter_bottom);
   line_current = gtk_text_iter_get_line (&iter_current);
 
-  if (direction == GB_SOURCE_VIM_HALF_PAGE_UP ||
-      direction == GB_SOURCE_VIM_HALF_PAGE_DOWN)
-    {
-      /* keep current yalign */
-      if (line_bottom != line_top)
-        yalign = MAX (0.0, (float)(line_current - line_top) /
-                           (float)(line_bottom - line_top));
-    }
+  g_print ("lines %i, %i. %i \n", line_top, line_bottom, line_current);
 
   switch (direction)
     {
     case GB_SOURCE_VIM_HALF_PAGE_UP:
       line = line_current - (line_bottom - line_top) / 2;
+      adjusted_scroll = gb_source_vim_adjust_scroll (vim, line, GB_SOURCE_VIM_ALIGMENT_KEEP);
       break;
     case GB_SOURCE_VIM_HALF_PAGE_DOWN:
       line = line_current + (line_bottom - line_top) / 2;
+      adjusted_scroll = gb_source_vim_adjust_scroll (vim, line, GB_SOURCE_VIM_ALIGMENT_KEEP);
       break;
     case GB_SOURCE_VIM_PAGE_UP:
-      yalign = 1.0;
-      line = gtk_text_iter_get_line (&iter_top) + SCROLL_OFF;
+      line = gtk_text_iter_get_line (&iter_top);
+      adjusted_scroll = gb_source_vim_adjust_scroll (vim, line, GB_SOURCE_VIM_ALIGMENT_BOTTOM);
       break;
     case GB_SOURCE_VIM_PAGE_DOWN:
-      yalign = 0.0;
-      /*
-       * rect.y + rect.height is the next line after the end of the buffer so
-       * now we have to decrease one more.
-       */
-      line = MAX (0, gtk_text_iter_get_line (&iter_bottom) - SCROLL_OFF - 1);
+      line = MAX (0, gtk_text_iter_get_line (&iter_bottom));
+      adjusted_scroll = gb_source_vim_adjust_scroll (vim, line, GB_SOURCE_VIM_ALIGMENT_TOP);
       break;
     default:
       g_assert_not_reached();
     }
 
-  gtk_text_iter_set_line (&iter_current, line);
+  g_print ("adjusted %f, %i \n", yalign, line);
+
+  gtk_text_iter_set_line (&iter_current, adjusted_scroll.line);
 
   for (offset = vim->priv->target_line_offset; offset; offset--)
     if (gtk_text_iter_ends_line (&iter_current) ||
         !gtk_text_iter_forward_char (&iter_current))
       break;
 
-  gb_source_vim_move_to_iter (vim, &iter_current, yalign);
+  gb_source_vim_move_to_iter (vim, &iter_current, adjusted_scroll.yalign);
 }
 
 static void


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