Add keyboard for diff selection

This commit is contained in:
Alberto Fanjul 2022-09-03 11:48:02 +02:00
parent 5524ad8a19
commit 8cc5fd7d1a
6 changed files with 261 additions and 33 deletions

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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()

View File

@ -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)

View File

@ -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;

View File

@ -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);
}