Commit 63744c06 authored by Kai Willadsen's avatar Kai Willadsen

Use line offsets from textview for drawing DiffMap (closes bgo#589540)

Previously, we assumed a constant line height, which breaks badly when
line wrapping is enabled. This commit changes to ask our textviews for
offsets, which is slower but reliable.
parent 3ebfed6d
......@@ -39,25 +39,20 @@ class DiffMap(gtk.DrawingArea):
self._h_offset = 0
self._scroll_y = 0
self._scroll_height = 0
self._num_lines = 0
def setup(self, scrollbar, textbuffer, change_chunk_fn):
def setup(self, scrollbar, change_chunk_fn):
for (o, h) in self._handlers:
o.disconnect(h)
self._scrolladj = scrollbar.get_adjustment()
self.on_scrollbar_style_set(scrollbar, None)
self.on_scrollbar_size_allocate(scrollbar, scrollbar.allocation)
self.on_textbuffer_changed(textbuffer)
scroll_style_hid = scrollbar.connect("style-set",
self.on_scrollbar_style_set)
scroll_size_hid = scrollbar.connect("size-allocate",
self.on_scrollbar_size_allocate)
buffer_changed_hid = textbuffer.connect("changed",
self.on_textbuffer_changed)
self._handlers = [(scrollbar, scroll_style_hid),
(scrollbar, scroll_size_hid),
(textbuffer, buffer_changed_hid)]
(scrollbar, scroll_size_hid)]
self._difffunc = change_chunk_fn
self.queue_draw()
......@@ -84,15 +79,8 @@ class DiffMap(gtk.DrawingArea):
self._scroll_height = allocation.height
self.queue_draw()
def on_textbuffer_changed(self, textbuffer):
num_lines = textbuffer.get_line_count()
if num_lines != self._num_lines:
self._num_lines = num_lines
self.queue_draw()
def do_expose_event(self, event):
height = self._scroll_height - self._h_offset - 1
scale = float(height) / self._num_lines
y_start = self._scroll_y - self.allocation.y + self._y_offset + 1
xpad = self.style_get_property('x-padding')
x0 = xpad
......@@ -110,10 +98,9 @@ class DiffMap(gtk.DrawingArea):
"delete": (0.75686274509803919, 1.0, 0.75686274509803919)}
darken = lambda color: [x * 0.8 for x in color]
for c in self._difffunc():
color = ctab[c[0]]
y0 = round(scale * c[1]) - 0.5
y1 = round(scale * c[2]) - 0.5
for c, y0, y1 in self._difffunc():
color = ctab[c]
y0, y1 = round(y0 * height) - 0.5, round(y1 * height) - 0.5
context.set_source_rgb(*color)
context.rectangle(x0, y0, x1, int(y1 - y0))
context.fill_preserve()
......
......@@ -637,6 +637,11 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
elif key == "edit_wrap_lines":
for t in self.textview:
t.set_wrap_mode(self.prefs.edit_wrap_lines)
# FIXME: On changing wrap mode, we get one redraw using cached
# coordinates, followed by a second redraw (e.g., on refocus) with
# correct coordinates. Overly-aggressive textview lazy calculation?
self.diffmap0.queue_draw()
self.diffmap1.queue_draw()
elif key == "spaces_instead_of_tabs":
for t in self.textview:
t.set_insert_spaces_instead_of_tabs(value)
......@@ -1375,11 +1380,27 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
self.actiongroup.get_action("MakePatch").set_sensitive(n > 1)
def chunk_change_fn(i):
return lambda: self.linediffer.single_changes(i)
def coords_iter(i):
buf_index = 2 if i == 1 and self.num_panes == 3 else i
get_end_iter = self.textbuffer[buf_index].get_end_iter
get_iter_at_line = self.textbuffer[buf_index].get_iter_at_line
get_line_yrange = self.textview[buf_index].get_line_yrange
def coords_by_chunk():
y, h = get_line_yrange(get_end_iter())
max_y = float(y + h)
for c in self.linediffer.single_changes(i):
y0, _ = get_line_yrange(get_iter_at_line(c[1]))
if c[1] == c[2]:
y, h = y0, 0
else:
y, h = get_line_yrange(get_iter_at_line(c[2] - 1))
yield c[0], y0 / max_y, (y + h) / max_y
return coords_by_chunk
for (w, i) in zip(self.diffmap, (0, self.num_panes - 1)):
scroll = self.scrolledwindow[i].get_vscrollbar()
w.setup(scroll, self.textbuffer[i], chunk_change_fn(i))
w.setup(scroll, coords_iter(i))
for i in range(self.num_panes):
if self.bufferdata[i].modified:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment