[gitg/wip/albfan/keyboard-stage] Add keyboard for diff selection




commit 43a59cbc3151fe66dc6992cbe2f3a609b01c6e6e
Author: Alberto Fanjul <albertofanjul gmail com>
Date:   Sat Sep 3 11:48:02 2022 +0200

    Add keyboard for diff selection

 gitg/commit/gitg-commit.vala                       |  31 +++++-
 .../gitg-diff-view-file-renderer-text-split.vala   |  29 +++---
 libgitg/gitg-diff-view-file-renderer-text.vala     |  19 +++-
 libgitg/gitg-diff-view-file-selectable.vala        | 110 ++++++++++++++++++---
 libgitg/gitg-diff-view.vala                        |  89 +++++++++++++++++
 libgitg/gitg-sidebar.vala                          |  16 ++-
 6 files changed, 261 insertions(+), 33 deletions(-)
---
diff --git a/gitg/commit/gitg-commit.vala b/gitg/commit/gitg-commit.vala
index cb561a09..eb0d435e 100644
--- a/gitg/commit/gitg-commit.vala
+++ b/gitg/commit/gitg-commit.vala
@@ -143,14 +143,43 @@ namespace GitgCommit
 
                public bool on_key_pressed (Gdk.EventKey event) {
                        var mmask = Gtk.accelerator_get_default_mod_mask();
+                       var modifiers = event.state;
+                       bool control = Gdk.ModifierType.CONTROL_MASK in modifiers;
+                       bool shift = Gdk.ModifierType.SHIFT_MASK in modifiers;
 
-                       if ((mmask & event.state) == Gdk.ModifierType.CONTROL_MASK)
+                       if (control && shift)
+                       {
+                               if (event.keyval == Gdk.Key.Up)
+                               {
+                                       d_main.diff_view.move_highlight_mark_up ();
+                                       return true;
+                               } else if (event.keyval == Gdk.Key.Down)
+                               {
+                                       d_main.diff_view.move_highlight_mark_down ();
+                                       return true;
+                               } else if (event.keyval == Gdk.Key.Right)
+                               {
+                                       d_main.diff_view.move_highlight_mark_right ();
+                                       return true;
+                               } else if (event.keyval == Gdk.Key.Left)
+                               {
+                                       d_main.diff_view.move_highlight_mark_left ();
+                                       return true;
+                               }
+                       }
+
+                       if (control)
                        {
                                if ((event.keyval == Gdk.Key.Return || event.keyval == Gdk.Key.KP_Enter))
                                {
                                        on_commit_clicked ();
                                        return true;
                                }
+                               else if ((event.keyval == Gdk.Key.space || event.keyval == Gdk.Key.KP_Space))
+                               {
+                                       d_main.diff_view.selection_update (shift);
+                                       return true;
+                               }
                        }
                        return false;
                }
diff --git a/libgitg/gitg-diff-view-file-renderer-text-split.vala 
b/libgitg/gitg-diff-view-file-renderer-text-split.vala
index 4d1bafcc..97edb1ae 100644
--- a/libgitg/gitg-diff-view-file-renderer-text-split.vala
+++ b/libgitg/gitg-diff-view-file-renderer-text-split.vala
@@ -25,8 +25,8 @@ class Gitg.DiffViewFileRendererTextSplit : Gtk.Box, DiffSelectable, DiffViewFile
        [GtkChild( name = "scroll_right" )]
        private unowned Gtk.ScrolledWindow d_scroll_right;
 
-       private Gitg.DiffViewFileRendererText d_renderer_left;
-       private Gitg.DiffViewFileRendererText d_renderer_right;
+       public Gitg.DiffViewFileRendererText d_renderer_left;
+       public Gitg.DiffViewFileRendererText d_renderer_right;
 
        public DiffViewFileInfo info { get; construct set; }
 
@@ -107,12 +107,6 @@ class Gitg.DiffViewFileRendererTextSplit : Gtk.Box, DiffSelectable, DiffViewFile
                d_scroll_right.add(d_renderer_right);
        }
 
-       construct
-       {
-               //can_select = d_renderer_left.can_select() || d_renderer_right.can_select();
-               can_select = false;
-       }
-
        public void add_hunk(Ggit.DiffHunk hunk, Gee.ArrayList<Ggit.DiffLine> lines)
        {
                d_renderer_left.add_hunk(hunk, lines);
@@ -123,8 +117,7 @@ class Gitg.DiffViewFileRendererTextSplit : Gtk.Box, DiffSelectable, DiffViewFile
        {
                get
                {
-                       //return d_renderer_left.has_selection() || d_renderer_right.has_selection();
-                       return false;
+                       return d_renderer_left.has_selection || d_renderer_right.has_selection;
                }
        }
 
@@ -132,17 +125,21 @@ class Gitg.DiffViewFileRendererTextSplit : Gtk.Box, DiffSelectable, DiffViewFile
        {
        }
 
-       public bool can_select { get; construct set; }
+       public bool can_select {
+               get {
+                       return d_renderer_left.can_select || d_renderer_right.can_select;
+               }
+               construct set {}
+       }
 
        public PatchSet selection
        {
                owned get
                {
-                       /*if (d_renderer_left.has_selection())
-                               return d_renderer_left.get_selection();
-                       if (d_renderer_right.has_selection())
-                               return d_renderer_right.get_selection();
-                       */
+                       if (d_renderer_left.has_selection)
+                               return d_renderer_left.selection;
+                       if (d_renderer_right.has_selection)
+                               return d_renderer_right.selection;
                        return new PatchSet();
                }
        }
diff --git a/libgitg/gitg-diff-view-file-renderer-text.vala b/libgitg/gitg-diff-view-file-renderer-text.vala
index fe6c15d7..e9009c56 100644
--- a/libgitg/gitg-diff-view-file-renderer-text.vala
+++ b/libgitg/gitg-diff-view-file-renderer-text.vala
@@ -185,7 +185,7 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
 
        public DiffViewFileRendererText(DiffViewFileInfo info, bool can_select, Style style)
        {
-               Object(info: info, can_select: can_select, d_style: style);
+               Object(info: info, can_select: can_select, d_style: style, show_line_marks: true);
        }
 
        construct
@@ -260,6 +260,21 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
                highlight = true;
        }
 
+       public void move_highlight_mark_down ()
+       {
+               d_selectable.move_highlight_mark_down ();
+       }
+
+       public void move_highlight_mark_up ()
+       {
+               d_selectable.move_highlight_mark_up ();
+       }
+
+       public void selection_update (bool shiftPressed)
+       {
+               d_selectable.selection_update (shiftPressed);
+       }
+
        protected override void dispose()
        {
                base.dispose();
@@ -652,6 +667,7 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
                var header_attributes = new Gtk.SourceMarkAttributes();
                var added_attributes = new Gtk.SourceMarkAttributes();
                var removed_attributes = new Gtk.SourceMarkAttributes();
+               var empty_attributes = new Gtk.SourceMarkAttributes();
 
                var dark = new Theme().is_theme_dark();
 
@@ -671,6 +687,7 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
                this.set_mark_attributes("header", header_attributes, 0);
                this.set_mark_attributes("added", added_attributes, 0);
                this.set_mark_attributes("removed", removed_attributes, 0);
+               this.set_mark_attributes("empty", empty_attributes, 0);
        }
 
        protected override void constructed()
diff --git a/libgitg/gitg-diff-view-file-selectable.vala b/libgitg/gitg-diff-view-file-selectable.vala
index c80fe9a5..bcf11eb0 100644
--- a/libgitg/gitg-diff-view-file-selectable.vala
+++ b/libgitg/gitg-diff-view-file-selectable.vala
@@ -26,6 +26,7 @@ enum Gitg.DiffSelectionMode {
 class Gitg.DiffViewFileSelectable : Object
 {
        private string d_selection_category = "selection";
+       private string d_highlight_category = "highlight";
        private Gtk.TextTag d_selection_tag;
        private DiffSelectionMode d_selection_mode;
        private Gtk.TextMark d_start_selection_mark;
@@ -138,6 +139,8 @@ class Gitg.DiffViewFileSelectable : Object
        private void update_theme()
        {
                var selection_attributes = new Gtk.SourceMarkAttributes();
+               var highlight_attributes = new Gtk.SourceMarkAttributes();
+               highlight_attributes.icon_name = "pan-end-symbolic";
                var context = source_view.get_style_context();
 
                Gdk.RGBA theme_selected_bg_color, theme_selected_fg_color;
@@ -146,13 +149,14 @@ class Gitg.DiffViewFileSelectable : Object
                {
                        selection_attributes.background = theme_selected_bg_color;
                }
-               
+
                if (context.lookup_color("theme_selected_fg_color", out theme_selected_fg_color))
                {
                        d_selection_tag.foreground_rgba = theme_selected_fg_color;
                }
 
-               source_view.set_mark_attributes(d_selection_category, selection_attributes, 0);
+               source_view.set_mark_attributes(d_highlight_category, highlight_attributes, 0);
+               source_view.set_mark_attributes(d_selection_category, selection_attributes, 1);
        }
 
        private bool get_line_selected(Gtk.TextIter iter)
@@ -273,6 +277,11 @@ class Gitg.DiffViewFileSelectable : Object
                                        }
 
                                        buffer.apply_tag(d_selection_tag, current, line_end);
+                                       Gtk.TextIter start_iter, end_iter;
+                                       buffer.get_start_iter (out start_iter);
+                                       buffer.get_end_iter (out end_iter);
+                                       buffer.remove_source_marks (start_iter, end_iter, 
d_highlight_category);
+                                       buffer.create_source_mark(null, d_highlight_category, current);
                                }
                        }
 
@@ -359,6 +368,80 @@ class Gitg.DiffViewFileSelectable : Object
                update_selection_range(iter, end, select);
        }
 
+       public void move_highlight_mark_up() {
+               Gtk.TextIter start_iter, end_iter;
+               var buffer = source_view.buffer as Gtk.SourceBuffer;
+               buffer.get_start_iter (out start_iter);
+               buffer.get_end_iter (out end_iter);
+
+               Gtk.TextIter iter;
+               buffer.get_start_iter (out iter);
+               if (buffer.forward_iter_to_source_mark (ref iter, d_highlight_category))
+               {
+                       iter.backward_line ();
+               }
+               while (iter.get_line () >= start_iter.get_line ())
+               {
+                       if (get_line_is_diff(iter))
+                       {
+                               buffer.remove_source_marks (start_iter, end_iter, d_highlight_category);
+                               buffer.create_source_mark(null, d_highlight_category, iter);
+                               break;
+                       }
+                       if (!iter.backward_line ())
+                       {
+                               break;
+                       }
+               }
+       }
+
+       public void move_highlight_mark_down() {
+               Gtk.TextIter start_iter, end_iter;
+               var buffer = source_view.buffer as Gtk.SourceBuffer;
+               buffer.get_start_iter (out start_iter);
+               buffer.get_end_iter (out end_iter);
+
+               Gtk.TextIter iter;
+               buffer.get_start_iter(out iter);
+               if (buffer.forward_iter_to_source_mark (ref iter, d_highlight_category))
+               {
+                       iter.forward_line ();
+               }
+               while (iter.get_line () <= end_iter.get_line ())
+               {
+                       if (get_line_is_diff(iter))
+                       {
+                               buffer.remove_source_marks (start_iter, end_iter, d_highlight_category);
+                               buffer.create_source_mark(null, d_highlight_category, iter);
+                               break;
+                       }
+                       if (!iter.forward_line ())
+                       {
+                               break;
+                       }
+               }
+       }
+
+       public void selection_update(bool shiftPressed)
+       {
+               var buffer = source_view.buffer as Gtk.SourceBuffer;
+               Gtk.TextIter iter;
+               buffer.get_start_iter (out iter);
+               if (buffer.forward_iter_to_source_mark (ref iter, d_highlight_category))
+               {
+                       if (shiftPressed)
+                       {
+                               update_selection(iter);
+                       }
+                       else
+                       {
+                               toggle_selection(iter);
+                       }
+            update_has_selection();
+                       //TODO: Allow to highlight hunks to select them with shortcuts
+               }
+       }
+
        private bool button_press_event_on_view(Gdk.EventButton event)
        {
                if (event.button != 1)
@@ -375,7 +458,9 @@ class Gitg.DiffViewFileSelectable : Object
 
                var buffer = source_view.buffer;
 
-               if ((event.state & Gdk.ModifierType.SHIFT_MASK) != 0)
+               var mmask = Gtk.accelerator_get_default_mod_mask();
+
+               if ((mmask & event.state) == Gdk.ModifierType.SHIFT_MASK)
                {
                        update_selection(iter);
                        return true;
@@ -388,17 +473,16 @@ class Gitg.DiffViewFileSelectable : Object
                }
 
                d_is_rubber_band = true;
+               toggle_selection(iter);
+               return true;
+       }
 
-               var select = !get_line_selected(iter);
+       private void toggle_selection(Gtk.TextIter iter)
+       {
+               var buffer = source_view.buffer;
+               var select = get_line_selected(iter);
 
-               if (select)
-               {
-                       d_selection_mode = DiffSelectionMode.SELECTING;
-               }
-               else
-               {
-                       d_selection_mode = DiffSelectionMode.DESELECTING;
-               }
+               d_selection_mode = select ? DiffSelectionMode.DESELECTING : DiffSelectionMode.SELECTING;
 
                d_originally_selected.clear();
 
@@ -406,8 +490,6 @@ class Gitg.DiffViewFileSelectable : Object
                buffer.move_mark(d_end_selection_mark, iter);
 
                update_selection(iter);
-
-               return true;
        }
 
        private void update_selection(Gtk.TextIter cursor)
diff --git a/libgitg/gitg-diff-view.vala b/libgitg/gitg-diff-view.vala
index 0894bd26..3568c4db 100644
--- a/libgitg/gitg-diff-view.vala
+++ b/libgitg/gitg-diff-view.vala
@@ -1070,6 +1070,95 @@ public class Gitg.DiffView : Gtk.Grid
                }
        }
 
+       public void move_highlight_mark_down ()
+       {
+               //TODO: select only the current one
+               //TODO: There's a selection for any of them
+               //TODO: Remove all this pile of function call
+               //Make sure highlight file is shown (scroll)
+               foreach (var file in d_grid_files.get_children())
+               {
+                       var renderer_list = (file as Gitg.DiffViewFile).renderer_list;
+                       foreach (DiffViewFileRenderer renderer in renderer_list)
+                       {
+                               Gitg.DiffViewFileRendererText renderer_text = null;
+                               if (renderer is DiffViewFileRendererText)
+                                       renderer_text = renderer as DiffViewFileRendererText;
+                               else if (renderer is DiffViewFileRendererTextSplit) {
+                                       if (left)
+                                               renderer_text = (renderer as 
DiffViewFileRendererTextSplit).d_renderer_left;
+                                       else
+                                       renderer_text = (renderer as 
DiffViewFileRendererTextSplit).d_renderer_right;
+                               }
+                               if(renderer_text == null) {
+                                       continue;
+                               }
+                               renderer_text.move_highlight_mark_down ();
+                       }
+               }
+       }
+
+       public void move_highlight_mark_up ()
+       {
+               //TODO: select only the current one
+               foreach (var file in d_grid_files.get_children())
+               {
+                       var renderer_list = (file as Gitg.DiffViewFile).renderer_list;
+                       foreach (DiffViewFileRenderer renderer in renderer_list)
+                       {
+                               Gitg.DiffViewFileRendererText renderer_text = null;
+                               if (renderer is DiffViewFileRendererText)
+                                       renderer_text = renderer as DiffViewFileRendererText;
+                               else if (renderer is DiffViewFileRendererTextSplit) {
+                                       if (left)
+                                               renderer_text = (renderer as 
DiffViewFileRendererTextSplit).d_renderer_left;
+                                       else
+                                               renderer_text = (renderer as 
DiffViewFileRendererTextSplit).d_renderer_right;
+                               }
+                               if(renderer_text == null) {
+                                       continue;
+                               }
+                               renderer_text.move_highlight_mark_up ();
+                       }
+               }
+       }
+
+    bool left = true;
+
+       public void move_highlight_mark_right ()
+       {
+       left = false;
+       }
+
+       public void move_highlight_mark_left ()
+       {
+       left = true;
+       }
+
+       public void selection_update (bool shiftPressed)
+       {
+               //TODO: select only the current one
+               foreach (var file in d_grid_files.get_children())
+               {
+                       var renderer_list = (file as Gitg.DiffViewFile).renderer_list;
+                       foreach (DiffViewFileRenderer renderer in renderer_list)
+                       {
+                               Gitg.DiffViewFileRendererText renderer_text = null;
+                               if (renderer is DiffViewFileRendererText)
+                                       renderer_text = renderer as DiffViewFileRendererText;
+                               else if (renderer is DiffViewFileRendererTextSplit) {
+                                       if (left)
+                                               renderer_text = (renderer as 
DiffViewFileRendererTextSplit).d_renderer_left;
+                                       else
+                                               renderer_text = (renderer as 
DiffViewFileRendererTextSplit).d_renderer_right;
+                               }
+                               if(renderer_text == null) {
+                                       continue;
+                               }
+                               renderer_text.selection_update (shiftPressed);
+                       }
+               }
+       }
        private void update_hide_show_options(Gdk.Window window, int ex, int ey)
        {
                void *data;
diff --git a/libgitg/gitg-sidebar.vala b/libgitg/gitg-sidebar.vala
index deebbeae..f20c14ef 100644
--- a/libgitg/gitg-sidebar.vala
+++ b/libgitg/gitg-sidebar.vala
@@ -423,7 +423,21 @@ public class Sidebar : Gtk.TreeView
 
        protected override bool key_press_event(Gdk.EventKey event)
        {
-               if ((event.state & Gtk.accelerator_get_default_mod_mask()) != 0)
+               var mmask = Gtk.accelerator_get_default_mod_mask();
+               var modifiers = event.state;
+
+               if (Gdk.ModifierType.CONTROL_MASK in modifiers && Gdk.ModifierType.SHIFT_MASK in modifiers
+                       && (event.keyval == Gdk.Key.Up || event.keyval == Gdk.Key.Down))
+               {
+                       return false;
+               }
+
+               if (Gdk.ModifierType.CONTROL_MASK in modifiers && (event.keyval == Gdk.Key.space || 
event.keyval == Gdk.Key.KP_Space))
+               {
+                       return false;
+               }
+
+               if ((event.state & mmask) != 0)
                {
                        return base.key_press_event(event);
                }


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