[gitg/xiaoguang/split-view: 3/4] diff-view: Add split view function
- From: Alberto Fanjul <albfan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gitg/xiaoguang/split-view: 3/4] diff-view: Add split view function
- Date: Fri, 26 Oct 2018 14:49:03 +0000 (UTC)
commit f4f0465ce873c68b01c8d4e639c6558f4e1d9686
Author: Xiaoguang Wang <xwang suse com>
Date: Mon Jan 22 10:15:06 2018 +0800
diff-view: Add split view function
https://bugzilla.gnome.org/show_bug.cgi?id=792706
libgitg/gitg-diff-view-file-renderer-text.vala | 530 +++++++++++++++++++++++--
libgitg/gitg-diff-view-file.vala | 161 +++++++-
libgitg/gitg-diff-view-lines-renderer.vala | 78 +++-
libgitg/gitg-diff-view.vala | 22 +-
libgitg/resources/ui/gitg-diff-view-file.ui | 104 +++--
5 files changed, 814 insertions(+), 81 deletions(-)
---
diff --git a/libgitg/gitg-diff-view-file-renderer-text.vala b/libgitg/gitg-diff-view-file-renderer-text.vala
index b6735623..65d2ce30 100644
--- a/libgitg/gitg-diff-view-file-renderer-text.vala
+++ b/libgitg/gitg-diff-view-file-renderer-text.vala
@@ -27,6 +27,13 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
CONTEXT
}
+ public enum Style
+ {
+ ONE,
+ OLD,
+ NEW
+ }
+
private struct Region
{
public RegionType type;
@@ -58,6 +65,8 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
private Region[] d_regions;
private bool d_constructed;
+ public Style d_style { get; construct set; }
+
public bool new_is_workdir { get; construct set; }
public bool wrap_lines
@@ -166,29 +175,58 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
}
}
- public DiffViewFileRendererText(DiffViewFileInfo info, bool can_select)
+ public DiffViewFileRendererText(DiffViewFileInfo info, bool can_select, Style d_style)
{
- Object(info: info, can_select: can_select);
+ Object(info: info, can_select: can_select, d_style: d_style);
}
construct
{
var gutter = this.get_gutter(Gtk.TextWindowType.LEFT);
- d_old_lines = new DiffViewLinesRenderer(DiffViewLinesRenderer.Style.OLD);
- d_new_lines = new DiffViewLinesRenderer(DiffViewLinesRenderer.Style.NEW);
- d_sym_lines = new DiffViewLinesRenderer(DiffViewLinesRenderer.Style.SYMBOL);
+ if (this.d_style == Style.ONE)
+ {
+ d_old_lines = new DiffViewLinesRenderer(DiffViewLinesRenderer.Style.OLD);
+ d_new_lines = new DiffViewLinesRenderer(DiffViewLinesRenderer.Style.NEW);
+ d_sym_lines = new DiffViewLinesRenderer(DiffViewLinesRenderer.Style.SYMBOL);
- this.bind_property("maxlines", d_old_lines, "maxlines", BindingFlags.DEFAULT |
BindingFlags.SYNC_CREATE);
- this.bind_property("maxlines", d_new_lines, "maxlines", BindingFlags.DEFAULT |
BindingFlags.SYNC_CREATE);
+ this.bind_property("maxlines", d_old_lines, "maxlines", BindingFlags.DEFAULT |
BindingFlags.SYNC_CREATE);
+ this.bind_property("maxlines", d_new_lines, "maxlines", BindingFlags.DEFAULT |
BindingFlags.SYNC_CREATE);
- d_old_lines.xpad = 8;
- d_new_lines.xpad = 8;
- d_sym_lines.xpad = 6;
+ d_old_lines.xpad = 8;
+ d_new_lines.xpad = 8;
+ d_sym_lines.xpad = 6;
- gutter.insert(d_old_lines, 0);
- gutter.insert(d_new_lines, 1);
- gutter.insert(d_sym_lines, 2);
+ gutter.insert(d_old_lines, 0);
+ gutter.insert(d_new_lines, 1);
+ gutter.insert(d_sym_lines, 2);
+ }
+ else if (this.d_style == Style.OLD)
+ {
+ d_old_lines = new DiffViewLinesRenderer(DiffViewLinesRenderer.Style.OLD);
+ d_sym_lines = new DiffViewLinesRenderer(DiffViewLinesRenderer.Style.SYMBOL_OLD);
+
+ this.bind_property("maxlines", d_old_lines, "maxlines", BindingFlags.DEFAULT |
BindingFlags.SYNC_CREATE);
+
+ d_old_lines.xpad = 8;
+ d_sym_lines.xpad = 6;
+
+ gutter.insert(d_old_lines, 0);
+ gutter.insert(d_sym_lines, 1);
+ }
+ else if (this.d_style == Style.NEW)
+ {
+ d_new_lines = new DiffViewLinesRenderer(DiffViewLinesRenderer.Style.NEW);
+ d_sym_lines = new DiffViewLinesRenderer(DiffViewLinesRenderer.Style.SYMBOL_NEW);
+
+ this.bind_property("maxlines", d_new_lines, "maxlines", BindingFlags.DEFAULT |
BindingFlags.SYNC_CREATE);
+
+ d_new_lines.xpad = 8;
+ d_sym_lines.xpad = 6;
+
+ gutter.insert(d_new_lines, 0);
+ gutter.insert(d_sym_lines, 1);
+ }
this.set_border_window_size(Gtk.TextWindowType.TOP, 1);
@@ -520,15 +558,35 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
var ctx = this.get_style_context();
- var old_lines_width = d_old_lines.size + d_old_lines.xpad * 2;
- var new_lines_width = d_new_lines.size + d_new_lines.xpad * 2;
+ var old_lines_width = 0;
+ var new_lines_width = 0;
+
+ switch (this.d_style)
+ {
+ case Style.ONE:
+ old_lines_width = d_old_lines.size + d_old_lines.xpad * 2;
+ new_lines_width = d_new_lines.size + d_new_lines.xpad * 2;
+ break;
+
+ case Style.OLD:
+ old_lines_width = d_old_lines.size + d_old_lines.xpad * 2;
+ break;
+
+ case Style.NEW:
+ new_lines_width = d_new_lines.size + d_new_lines.xpad * 2;
+ break;
+ }
+
var sym_lines_width = d_sym_lines.size + d_sym_lines.xpad * 2;
- ctx.save();
- Gtk.cairo_transform_to_window(cr, this, win);
- ctx.add_class("diff-lines-separator");
- ctx.render_frame(cr, 0, 0, old_lines_width, win.get_height());
- ctx.restore();
+ if (this.d_style == Style.ONE)
+ {
+ ctx.save();
+ Gtk.cairo_transform_to_window(cr, this, win);
+ ctx.add_class("diff-lines-separator");
+ ctx.render_frame(cr, 0, 0, old_lines_width, win.get_height());
+ ctx.restore();
+ }
ctx.save();
Gtk.cairo_transform_to_window(cr, this, win);
@@ -574,6 +632,22 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
}
public void add_hunk(Ggit.DiffHunk hunk, Gee.ArrayList<Ggit.DiffLine> lines)
+ {
+ switch (this.d_style)
+ {
+ case Style.ONE:
+ add_hunk_one(hunk, lines);
+ break;
+ case Style.OLD:
+ add_hunk_left(hunk, lines);
+ break;
+ case Style.NEW:
+ add_hunk_right(hunk, lines);
+ break;
+ }
+ }
+
+ private void add_hunk_one(Ggit.DiffHunk hunk, Gee.ArrayList<Ggit.DiffLine> lines)
{
var buffer = this.buffer as Gtk.SourceBuffer;
@@ -604,8 +678,7 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
int buffer_line = iter.get_line();
- /* Diff Content */
- var content = new StringBuilder();
+ int line_hunk_start = iter.get_line();
var region = Region() {
type = RegionType.CONTEXT,
@@ -705,8 +778,31 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
text = text.slice(0, text.length - 1);
}
- content.append(text);
- buffer_line++;
+ if (rtype == RegionType.CONTEXT)
+ {
+ buffer.insert(ref iter, text, -1);
+ buffer_line++;
+ }
+
+ if (rtype == RegionType.REMOVED)
+ {
+ Gtk.TextIter t_iter;
+ buffer.get_end_iter(out t_iter);
+ buffer.create_source_mark(null, "removed", t_iter);
+
+ buffer.insert(ref iter, text, -1);
+ buffer_line++;
+ }
+
+ if (rtype == RegionType.ADDED)
+ {
+ Gtk.TextIter t_iter;
+ buffer.get_end_iter(out t_iter);
+ buffer.create_source_mark(null, "added", t_iter);
+
+ buffer.insert(ref iter, text, -1);
+ buffer_line++;
+ }
}
if (lines.size != 0)
@@ -714,36 +810,400 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
d_regions += region;
}
+ d_old_lines.add_hunk(line_hunk_start, iter.get_line(), hunk, buffer);
+ d_new_lines.add_hunk(line_hunk_start, iter.get_line(), hunk, buffer);
+ d_sym_lines.add_hunk(line_hunk_start, iter.get_line(), hunk, buffer);
+
+ this.thaw_notify();
+
+ sensitive = true;
+ }
+
+ private void add_hunk_left(Ggit.DiffHunk hunk, Gee.ArrayList<Ggit.DiffLine> lines)
+ {
+ var buffer = this.buffer as Gtk.SourceBuffer;
+
+ /* Diff hunk */
+ var h = hunk.get_header();
+ var pos = h.last_index_of("@@");
+
+ if (pos >= 0)
+ {
+ h = h.substring(pos + 2).chug();
+ }
+
+ h = h.chomp();
+
+ Gtk.TextIter iter;
+ buffer.get_end_iter(out iter);
+
+ if (!iter.is_start())
+ {
+ buffer.insert(ref iter, "\n", 1);
+ }
+
+ iter.set_line_offset(0);
+ buffer.create_source_mark(null, "header", iter);
+
+ var header = @"@@ -$(hunk.get_old_start()),$(hunk.get_old_lines())
+$(hunk.get_new_start()),$(hunk.get_new_lines()) @@ $h\n";
+ buffer.insert(ref iter, header, -1);
+
+ int buffer_line = iter.get_line();
+
int line_hunk_start = iter.get_line();
- buffer.insert(ref iter, (string)content.data, -1);
+ var region = Region() {
+ type = RegionType.CONTEXT,
+ buffer_line_start = 0,
+ source_line_start = 0,
+ length = 0
+ };
- d_old_lines.add_hunk(line_hunk_start, iter.get_line(), hunk, lines);
- d_new_lines.add_hunk(line_hunk_start, iter.get_line(), hunk, lines);
- d_sym_lines.add_hunk(line_hunk_start, iter.get_line(), hunk, lines);
+ this.freeze_notify();
+ var add_line_num = 0;
+ var remove_line_num = 0;
+ var in_change_line = false;
for (var i = 0; i < lines.size; i++)
{
var line = lines[i];
- string? category = null;
+ var text = line.get_text().replace("\r", "");
+ var added = false;
+ var removed = false;
+ var origin = line.get_origin();
+
+ var rtype = RegionType.CONTEXT;
- switch (line.get_origin())
+ switch (origin)
{
case Ggit.DiffLineType.ADDITION:
- category = "added";
+ added = true;
+ this.added++;
+
+ rtype = RegionType.ADDED;
break;
case Ggit.DiffLineType.DELETION:
- category = "removed";
+ removed = true;
+ this.removed++;
+
+ rtype = RegionType.REMOVED;
+ break;
+ case Ggit.DiffLineType.CONTEXT_EOFNL:
+ case Ggit.DiffLineType.ADD_EOFNL:
+ case Ggit.DiffLineType.DEL_EOFNL:
+ text = text.substring(1);
break;
}
- if (category != null)
+ if (i == 0 || rtype != region.type)
{
- buffer.get_iter_at_line(out iter, line_hunk_start + i);
- buffer.create_source_mark(null, category, iter);
+ if (i != 0)
+ {
+ d_regions += region;
+ }
+
+ int source_line_start;
+
+ if (rtype == RegionType.REMOVED)
+ {
+ source_line_start = line.get_old_lineno() - 1;
+ }
+ else
+ {
+ source_line_start = line.get_new_lineno() - 1;
+ }
+
+ region = Region() {
+ type = rtype,
+ buffer_line_start = buffer_line,
+ source_line_start = source_line_start,
+ length = 0
+ };
}
+
+ if (added || removed)
+ {
+ var offset = (size_t)line.get_content_offset();
+ var bytes = line.get_content();
+
+ var pset = PatchSet.Patch() {
+ type = added ? PatchSet.Type.ADD : PatchSet.Type.REMOVE,
+ old_offset = offset,
+ new_offset = offset,
+ length = bytes.length
+ };
+
+ if (added)
+ {
+ pset.old_offset = (size_t)((int64)pset.old_offset - d_doffset);
+ }
+ else
+ {
+ pset.new_offset = (size_t)((int64)pset.new_offset + d_doffset);
+ }
+
+ d_lines[buffer_line] = pset;
+ d_doffset += added ? (int64)bytes.length : -(int64)bytes.length;
+ }
+
+ if (i == lines.size - 1 && text.length > 0 && text[text.length - 1] == '\n')
+ {
+ text = text.slice(0, text.length - 1);
+ }
+
+ if (rtype == RegionType.CONTEXT)
+ {
+ if (in_change_line == true)
+ {
+ if (add_line_num > remove_line_num)
+ {
+ for (var l = 0; l < (add_line_num - remove_line_num); l++)
+ {
+ Gtk.TextIter t_iter;
+ buffer.get_end_iter(out t_iter);
+ buffer.create_source_mark(null, "empty", t_iter);
+
+ buffer.insert(ref iter, "\n", -1);
+ buffer_line++;
+ region.buffer_line_start = buffer_line;
+ }
+ }
+
+ add_line_num = 0;
+ remove_line_num = 0;
+ }
+
+ in_change_line = false;
+
+ buffer.insert(ref iter, text, -1);
+ buffer_line++;
+ region.length++;
+ }
+
+ if (rtype == RegionType.REMOVED)
+ {
+ Gtk.TextIter t_iter;
+ buffer.get_end_iter(out t_iter);
+ buffer.create_source_mark(null, "removed", t_iter);
+
+ buffer.insert(ref iter, text, -1);
+ buffer_line++;
+ region.length++;
+
+ remove_line_num++;
+ in_change_line = true;
+ }
+
+ if (rtype == RegionType.ADDED)
+ {
+ add_line_num++;
+ in_change_line = true;
+ }
+ }
+
+ if (lines.size != 0)
+ {
+ d_regions += region;
+ }
+
+ d_old_lines.add_hunk(line_hunk_start, iter.get_line(), hunk, buffer);
+ d_sym_lines.add_hunk(line_hunk_start, iter.get_line(), hunk, buffer);
+
+ this.thaw_notify();
+
+ sensitive = true;
+ }
+
+ private void add_hunk_right(Ggit.DiffHunk hunk, Gee.ArrayList<Ggit.DiffLine> lines)
+ {
+ var buffer = this.buffer as Gtk.SourceBuffer;
+
+ /* Diff hunk */
+ var h = hunk.get_header();
+ var pos = h.last_index_of("@@");
+
+ if (pos >= 0)
+ {
+ h = h.substring(pos + 2).chug();
+ }
+
+ h = h.chomp();
+
+ Gtk.TextIter iter;
+ buffer.get_end_iter(out iter);
+
+ if (!iter.is_start())
+ {
+ buffer.insert(ref iter, "\n", 1);
+ }
+
+ iter.set_line_offset(0);
+ buffer.create_source_mark(null, "header", iter);
+
+ var header = @"@@ -$(hunk.get_old_start()),$(hunk.get_old_lines())
+$(hunk.get_new_start()),$(hunk.get_new_lines()) @@ $h\n";
+ buffer.insert(ref iter, header, -1);
+
+ int buffer_line = iter.get_line();
+
+ int line_hunk_start = iter.get_line();
+
+ var region = Region() {
+ type = RegionType.CONTEXT,
+ buffer_line_start = 0,
+ source_line_start = 0,
+ length = 0
+ };
+
+ this.freeze_notify();
+
+ var add_line_num = 0;
+ var remove_line_num = 0;
+ var in_change_line = false;
+ for (var i = 0; i < lines.size; i++)
+ {
+ var line = lines[i];
+ var text = line.get_text().replace("\r", "");
+ var added = false;
+ var removed = false;
+ var origin = line.get_origin();
+
+ var rtype = RegionType.CONTEXT;
+
+ switch (origin)
+ {
+ case Ggit.DiffLineType.ADDITION:
+ added = true;
+ this.added++;
+
+ rtype = RegionType.ADDED;
+ break;
+ case Ggit.DiffLineType.DELETION:
+ removed = true;
+ this.removed++;
+
+ rtype = RegionType.REMOVED;
+ break;
+ case Ggit.DiffLineType.CONTEXT_EOFNL:
+ case Ggit.DiffLineType.ADD_EOFNL:
+ case Ggit.DiffLineType.DEL_EOFNL:
+ text = text.substring(1);
+ break;
+ }
+
+ if (i == 0 || rtype != region.type)
+ {
+ if (i != 0)
+ {
+ d_regions += region;
+ }
+
+ int source_line_start;
+
+ if (rtype == RegionType.REMOVED)
+ {
+ source_line_start = line.get_old_lineno() - 1;
+ }
+ else
+ {
+ source_line_start = line.get_new_lineno() - 1;
+ }
+
+ region = Region() {
+ type = rtype,
+ buffer_line_start = buffer_line,
+ source_line_start = source_line_start,
+ length = 0
+ };
+ }
+
+ if (added || removed)
+ {
+ var offset = (size_t)line.get_content_offset();
+ var bytes = line.get_content();
+
+ var pset = PatchSet.Patch() {
+ type = added ? PatchSet.Type.ADD : PatchSet.Type.REMOVE,
+ old_offset = offset,
+ new_offset = offset,
+ length = bytes.length
+ };
+
+ if (added)
+ {
+ pset.old_offset = (size_t)((int64)pset.old_offset - d_doffset);
+ }
+ else
+ {
+ pset.new_offset = (size_t)((int64)pset.new_offset + d_doffset);
+ }
+
+ d_lines[buffer_line] = pset;
+ d_doffset += added ? (int64)bytes.length : -(int64)bytes.length;
+ }
+
+ if (i == lines.size - 1 && text.length > 0 && text[text.length - 1] == '\n')
+ {
+ text = text.slice(0, text.length - 1);
+ }
+
+ if (rtype == RegionType.CONTEXT)
+ {
+ if (in_change_line == true)
+ {
+ if (remove_line_num > add_line_num)
+ {
+ for (var l = 0; l < (remove_line_num - add_line_num); l++)
+ {
+ Gtk.TextIter t_iter;
+ buffer.get_end_iter(out t_iter);
+ buffer.create_source_mark(null, "empty", t_iter);
+
+ buffer.insert(ref iter, "\n", -1);
+ buffer_line++;
+ region.buffer_line_start = buffer_line;
+ }
+ }
+
+ add_line_num = 0;
+ remove_line_num = 0;
+ }
+
+ in_change_line = false;
+
+ buffer.insert(ref iter, text, -1);
+ buffer_line++;
+ region.length++;
+ }
+
+ if (rtype == RegionType.ADDED)
+ {
+ Gtk.TextIter t_iter;
+ buffer.get_end_iter(out t_iter);
+ buffer.create_source_mark(null, "added", t_iter);
+
+ buffer.insert(ref iter, text, -1);
+ buffer_line++;
+ region.length++;
+
+ add_line_num++;
+ in_change_line = true;
+ }
+
+ if (rtype == RegionType.REMOVED)
+ {
+ remove_line_num++;
+ in_change_line = true;
+ }
+ }
+
+ if (lines.size != 0)
+ {
+ d_regions += region;
}
+ d_new_lines.add_hunk(line_hunk_start, iter.get_line(), hunk, buffer);
+ d_sym_lines.add_hunk(line_hunk_start, iter.get_line(), hunk, buffer);
+
this.thaw_notify();
sensitive = true;
diff --git a/libgitg/gitg-diff-view-file.vala b/libgitg/gitg-diff-view-file.vala
index afec0608..917fd267 100644
--- a/libgitg/gitg-diff-view-file.vala
+++ b/libgitg/gitg-diff-view-file.vala
@@ -32,15 +32,33 @@ class Gitg.DiffViewFile : Gtk.Grid
[GtkChild( name = "revealer_content" )]
private Gtk.Revealer d_revealer_content;
+ [GtkChild( name = "box_file_renderer" )]
+ private Gtk.Box d_box_file_renderer;
+
+ [GtkChild( name = "d_split_button" )]
+ private Gtk.ToggleButton d_split_button;
+
+ private Gtk.ScrolledWindow d_scrolledwindow;
+ private Gtk.ScrolledWindow d_scrolledwindow_left;
+ private Gtk.ScrolledWindow d_scrolledwindow_right;
+
private bool d_expanded;
private Binding? d_vexpand_binding;
+ private Binding? d_vexpand_binding_l;
+ private Binding? d_vexpand_binding_r;
+
+ private bool d_split { get; set; default = false; }
+
+ private DiffViewFileRenderer? d_renderer;
+ private DiffViewFileRenderer? d_renderer_left;
+ private DiffViewFileRenderer? d_renderer_right;
public DiffViewFileRenderer? renderer
{
owned get
{
- return d_revealer_content.get_child() as DiffViewFileRenderer;
+ return d_renderer;
}
construct set
@@ -57,15 +75,120 @@ class Gitg.DiffViewFile : Gtk.Grid
if (current != null)
{
- d_revealer_content.remove(current);
+ d_scrolledwindow.remove(current);
+ d_box_file_renderer.remove(d_scrolledwindow);
+ }
+
+ d_renderer = value;
+ d_scrolledwindow.add(value);
+ d_scrolledwindow.show();
+
+ if (!d_split)
+ {
+ d_box_file_renderer.pack_start(d_scrolledwindow, true, true, 0);
}
- d_revealer_content.add(value);
d_vexpand_binding = this.bind_property("vexpand", value, "vexpand",
BindingFlags.SYNC_CREATE);
}
}
}
+ public DiffViewFileRenderer? renderer_left
+ {
+ owned get
+ {
+ return d_renderer_left;
+ }
+
+ construct set
+ {
+ var current = this.renderer_left;
+
+ if (current != value)
+ {
+ if (d_vexpand_binding_l != null)
+ {
+ d_vexpand_binding_l.unbind();
+ d_vexpand_binding_l = null;
+ }
+
+ if (current != null)
+ {
+ d_scrolledwindow_left.remove(current);
+ d_box_file_renderer.remove(d_scrolledwindow_left);
+ }
+
+ d_renderer_left = value;
+ d_scrolledwindow_left.add(value);
+ d_scrolledwindow_left.show();
+
+ if (d_split)
+ {
+ d_box_file_renderer.pack_start(d_scrolledwindow_left, true, true, 0);
+ }
+
+ d_vexpand_binding_l = this.bind_property("vexpand", value, "vexpand",
BindingFlags.SYNC_CREATE);
+ }
+ }
+ }
+
+ public DiffViewFileRenderer? renderer_right
+ {
+ owned get
+ {
+ return d_renderer_right;
+ }
+
+ construct set
+ {
+ var current = this.renderer_right;
+
+ if (current != value)
+ {
+ if (d_vexpand_binding_r != null)
+ {
+ d_vexpand_binding_r.unbind();
+ d_vexpand_binding_r = null;
+ }
+
+ if (current != null)
+ {
+ d_scrolledwindow_right.remove(current);
+ d_box_file_renderer.remove(d_scrolledwindow_right);
+ }
+
+ d_renderer_right = value;
+ d_scrolledwindow_right.add(value);
+ d_scrolledwindow_right.show();
+
+ if (d_split)
+ {
+ d_box_file_renderer.pack_start(d_scrolledwindow_right, true, true, 0);
+ }
+
+ d_vexpand_binding_r = this.bind_property("vexpand", value, "vexpand",
BindingFlags.SYNC_CREATE);
+ }
+ }
+ }
+
+ [GtkCallback]
+ private void split_button_toggled(Gtk.ToggleButton button)
+ {
+ d_split = !d_split;
+ if (d_split)
+ {
+ d_box_file_renderer.remove(d_scrolledwindow);
+ d_box_file_renderer.pack_start(d_scrolledwindow_left, true, true, 0);
+ d_box_file_renderer.pack_end(d_scrolledwindow_right, true, true, 0);
+ }
+ else
+ {
+ d_box_file_renderer.remove(d_scrolledwindow_left);
+ d_box_file_renderer.remove(d_scrolledwindow_right);
+ d_box_file_renderer.pack_start(d_scrolledwindow, true, true, 0);
+ }
+ }
+
public bool new_is_workdir { get; construct set; }
public bool expanded
@@ -104,15 +227,40 @@ class Gitg.DiffViewFile : Gtk.Grid
Object(repository: repository, delta: delta);
}
+ construct
+ {
+ d_scrolledwindow = new Gtk.ScrolledWindow(null, null);
+ d_scrolledwindow_left = new Gtk.ScrolledWindow(null, null);
+ d_scrolledwindow_right = new Gtk.ScrolledWindow(null, null);
+
+ d_scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.NEVER);
+ d_scrolledwindow_left.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.NEVER);
+ d_scrolledwindow_right.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.NEVER);
+ }
+
public DiffViewFile.text(DiffViewFileInfo info, bool handle_selection)
{
this(info.repository, info.delta);
- this.renderer = new DiffViewFileRendererText(info, handle_selection);
+ this.renderer = new DiffViewFileRendererText(info, handle_selection,
DiffViewFileRendererText.Style.ONE);
this.renderer.show();
this.renderer.bind_property("added", d_diff_stat_file, "added");
this.renderer.bind_property("removed", d_diff_stat_file, "removed");
+
+ this.renderer_left = new DiffViewFileRendererText(info, handle_selection,
DiffViewFileRendererText.Style.OLD);
+ this.renderer_left.show();
+
+ this.renderer_left.bind_property("added", d_diff_stat_file, "added");
+ this.renderer_left.bind_property("removed", d_diff_stat_file, "removed");
+
+ this.renderer_right = new DiffViewFileRendererText(info, handle_selection,
DiffViewFileRendererText.Style.NEW);
+ this.renderer_right.show();
+
+ this.renderer_right.bind_property("added", d_diff_stat_file, "added");
+ this.renderer_right.bind_property("removed", d_diff_stat_file, "removed");
+
+ d_split_button.visible = true;
}
public DiffViewFile.binary(Repository? repository, Ggit.DiffDelta delta)
@@ -269,6 +417,11 @@ class Gitg.DiffViewFile : Gtk.Grid
public void add_hunk(Ggit.DiffHunk hunk, Gee.ArrayList<Ggit.DiffLine> lines)
{
this.renderer.add_hunk(hunk, lines);
+ if (this.renderer_left != null && this.renderer_right !=null)
+ {
+ this.renderer_left.add_hunk(hunk, lines);
+ this.renderer_right.add_hunk(hunk, lines);
+ }
}
}
diff --git a/libgitg/gitg-diff-view-lines-renderer.vala b/libgitg/gitg-diff-view-lines-renderer.vala
index 25614c0b..8566610b 100644
--- a/libgitg/gitg-diff-view-lines-renderer.vala
+++ b/libgitg/gitg-diff-view-lines-renderer.vala
@@ -23,7 +23,17 @@ class Gitg.DiffViewLinesRenderer : Gtk.SourceGutterRendererText
{
OLD,
NEW,
- SYMBOL
+ SYMBOL,
+ SYMBOL_OLD,
+ SYMBOL_NEW
+ }
+
+ private enum Line_Style
+ {
+ CONTEXT,
+ ADDED,
+ REMOVED,
+ EMPTY
}
private string d_num_digits_fmts;
@@ -104,7 +114,7 @@ class Gitg.DiffViewLinesRenderer : Gtk.SourceGutterRendererText
if (info == null || (line - info.start) >= info.line_infos.length)
{
- if (is_hunk && style != Style.SYMBOL)
+ if (is_hunk && style != Style.SYMBOL && style != Style.SYMBOL_OLD && style !=
Style.SYMBOL_NEW)
{
set_text("...", -1);
}
@@ -186,48 +196,87 @@ class Gitg.DiffViewLinesRenderer : Gtk.SourceGutterRendererText
d_num_digits_fill = string.nfill(num_digits, ' ');
}
- private string[] precalculate_line_strings(Ggit.DiffHunk hunk, Gee.ArrayList<Ggit.DiffLine> lines)
+ private Line_Style get_origin(int buffer_line, Gtk.SourceBuffer buffer)
+ {
+ var origin = Line_Style.CONTEXT;
+
+ var mark = buffer.get_source_marks_at_line(buffer_line, null);
+ if (mark != null)
+ {
+ mark.@foreach ((item) => {
+ switch (item.get_category())
+ {
+ case "added":
+ origin = Line_Style.ADDED;
+ break;
+ case "removed":
+ origin = Line_Style.REMOVED;
+ break;
+ case "empty":
+ origin = Line_Style.EMPTY;
+ break;
+ }
+ });
+ }
+
+ return origin;
+ }
+
+ private string[] precalculate_line_strings(Ggit.DiffHunk hunk, Gtk.SourceBuffer buffer, int
buffer_line_start)
{
var oldn = hunk.get_old_start();
var newn = hunk.get_new_start();
- var lns = lines;
+ Gtk.TextIter iter;
+ buffer.get_end_iter(out iter);
+ int buffer_line_end = iter.get_line();
- var line_infos = new string[lns.size];
+ var line_infos = new string[buffer_line_end - buffer_line_start + 1];
- for (var i = 0; i < lns.size; i++)
+ for (var i = 0; i <= (buffer_line_end - buffer_line_start); i++)
{
- var line = lns[i];
- var origin = line.get_origin();
+ var origin = get_origin(buffer_line_start + i, buffer);
string ltext = "";
switch (style)
{
case Style.NEW:
- if (origin == Ggit.DiffLineType.CONTEXT || origin ==
Ggit.DiffLineType.ADDITION)
+ if (origin == Line_Style.CONTEXT || origin == Line_Style.ADDED)
{
ltext = d_num_digits_fmts.printf(newn);
newn++;
}
break;
case Style.OLD:
- if (origin == Ggit.DiffLineType.CONTEXT || origin ==
Ggit.DiffLineType.DELETION)
+ if (origin == Line_Style.CONTEXT || origin == Line_Style.REMOVED)
{
ltext = d_num_digits_fmts.printf(oldn);
oldn++;
}
break;
case Style.SYMBOL:
- if (origin == Ggit.DiffLineType.ADDITION)
+ if (origin == Line_Style.ADDED)
{
ltext = "+";
}
- else if (origin == Ggit.DiffLineType.DELETION)
+ else if (origin == Line_Style.REMOVED)
+ {
+ ltext = "-";
+ }
+ break;
+ case Style.SYMBOL_OLD:
+ if (origin == Line_Style.REMOVED)
{
ltext = "-";
}
break;
+ case Style.SYMBOL_NEW:
+ if (origin == Line_Style.ADDED)
+ {
+ ltext = "+";
+ }
+ break;
}
line_infos[i] = ltext;
@@ -235,8 +284,7 @@ class Gitg.DiffViewLinesRenderer : Gtk.SourceGutterRendererText
return line_infos;
}
-
- public void add_hunk(int buffer_line_start, int buffer_line_end, Ggit.DiffHunk hunk,
Gee.ArrayList<Ggit.DiffLine> lines)
+ public void add_hunk(int buffer_line_start, int buffer_line_end, Ggit.DiffHunk hunk, Gtk.SourceBuffer
buffer)
{
HunkInfo info = HunkInfo();
@@ -246,7 +294,7 @@ class Gitg.DiffViewLinesRenderer : Gtk.SourceGutterRendererText
info.end = buffer_line_end;
info.hunk_line = buffer_line_start - 1;
info.hunk = hunk;
- info.line_infos = precalculate_line_strings(hunk, lines);
+ info.line_infos = precalculate_line_strings(hunk, buffer, buffer_line_start);
d_hunks_list.add(info);
diff --git a/libgitg/gitg-diff-view.vala b/libgitg/gitg-diff-view.vala
index f4076f5b..acd2b3c2 100644
--- a/libgitg/gitg-diff-view.vala
+++ b/libgitg/gitg-diff-view.vala
@@ -450,7 +450,7 @@ public class Gitg.DiffView : Gtk.Grid
if (current_file != null)
{
current_file.show();
- current_file.renderer.notify["has-selection"].connect(on_selection_changed);
+ current_file.renderer.notify["has-selection"].connect(on_selection_changed);
files.add(current_file);
@@ -529,6 +529,8 @@ public class Gitg.DiffView : Gtk.Grid
{
current_file = new Gitg.DiffViewFile.text(info,
handle_selection);
this.bind_property("highlight", current_file.renderer,
"highlight", BindingFlags.SYNC_CREATE);
+ this.bind_property("highlight", current_file.renderer_left,
"highlight", BindingFlags.SYNC_CREATE);
+ this.bind_property("highlight", current_file.renderer_left,
"highlight", BindingFlags.SYNC_CREATE);
}
return 0;
@@ -623,6 +625,24 @@ public class Gitg.DiffView : Gtk.Grid
this.bind_property("tab-width", renderer_text, "tab-width",
BindingFlags.DEFAULT | BindingFlags.SYNC_CREATE);
}
+ var renderer_left = file.renderer_left as DiffViewFileRendererText;
+ if (renderer_left != null)
+ {
+ renderer_left.maxlines = maxlines;
+
+ this.bind_property("wrap-lines", renderer_left, "wrap-lines",
BindingFlags.DEFAULT | BindingFlags.SYNC_CREATE);
+ this.bind_property("tab-width", renderer_left, "tab-width",
BindingFlags.DEFAULT | BindingFlags.SYNC_CREATE);
+ }
+
+ var renderer_right = file.renderer_right as DiffViewFileRendererText;
+ if (renderer_right != null)
+ {
+ renderer_right.maxlines = maxlines;
+
+ this.bind_property("wrap-lines", renderer_right, "wrap-lines",
BindingFlags.DEFAULT | BindingFlags.SYNC_CREATE);
+ this.bind_property("tab-width", renderer_right, "tab-width",
BindingFlags.DEFAULT | BindingFlags.SYNC_CREATE);
+ }
+
if (i == files.size - 1)
{
file.vexpand = true;
diff --git a/libgitg/resources/ui/gitg-diff-view-file.ui b/libgitg/resources/ui/gitg-diff-view-file.ui
index a55a7c5f..e37a35cd 100644
--- a/libgitg/resources/ui/gitg-diff-view-file.ui
+++ b/libgitg/resources/ui/gitg-diff-view-file.ui
@@ -11,44 +11,86 @@
<class name="gitg-file-header"/>
</style>
<child>
- <object class="GtkExpander" id="expander">
+ <object class="GtkBox" id="header_grid">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hexpand">True</property>
- <property name="margin_start">3</property>
- <child type="label">
- <object class="GtkGrid" id="grid_file_header">
+ <property name="can_focus">False</property>
+ <property name="homogeneous">False</property>
+ <property name="orientation">horizontal</property>
+ <child>
+ <object class="GtkExpander" id="expander">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
<property name="hexpand">True</property>
- <property name="row_spacing">6</property>
- <property name="column_spacing">12</property>
- <property name="orientation">horizontal</property>
- <child>
- <object class="GitgDiffStat" id="diff_stat_file">
+ <property name="margin_start">3</property>
+ <child type="label">
+ <object class="GtkGrid" id="grid_file_header">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="vexpand">False</property>
- <property name="valign">baseline</property>
- <property name="margin_top">6</property>
- <property name="margin_bottom">6</property>
- <style>
- <class name="no-frame"/>
- </style>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="orientation">horizontal</property>
+ <child>
+ <object class="GitgDiffStat" id="diff_stat_file">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">False</property>
+ <property name="valign">baseline</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <style>
+ <class name="no-frame"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_file_header">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label">the/file/header</property>
+ <property name="halign">start</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ </object>
+ </child>
</object>
</child>
+ </object>
+ <packing>
+ <property name="pack-type">start</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="d_split_button">
+ <property name="visible">False</property>
+ <property name="valign">center</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip-text" translatable="yes">Split view</property>
+ <property name="margin_end">6</property>
+ <signal name="toggled" handler="split_button_toggled" swapped="no"/>
+ <style>
+ <class name="text-button"/>
+ </style>
<child>
- <object class="GtkLabel" id="label_file_header">
+ <object class="GtkLabel" id="label_split_view">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="label">the/file/header</property>
- <property name="halign">start</property>
- <property name="margin_top">6</property>
- <property name="margin_bottom">6</property>
+ <property name="can_focus">True</property>
+ <property name="halign">center</property>
+ <property name="valign">baseline</property>
+ <property name="label" translatable="yes">Split View</property>
+ <property name="selectable">True</property>
+ <property name="ellipsize">end</property>
+ <property name="max-width-chars">12</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
</object>
</child>
</object>
+ <packing>
+ <property name="pack-type">end</property>
+ </packing>
</child>
</object>
</child>
@@ -57,6 +99,16 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">slide-down</property>
+ <child>
+ <object class="GtkBox" id="box_file_renderer">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="homogeneous">True</property>
+ <property name="orientation">horizontal</property>
+ <property name="margin_bottom">6</property>
+ </object>
+ </child>
</object>
</child>
</template>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]