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



commit 63744c06c58d48b00255f82b5f10af16ded38958
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Mon Aug 30 08:55:18 2010 +1000

    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.

 meld/diffmap.py  |   23 +++++------------------
 meld/filediff.py |   27 ++++++++++++++++++++++++---
 2 files changed, 29 insertions(+), 21 deletions(-)
---
diff --git a/meld/diffmap.py b/meld/diffmap.py
index 8460d8b..1fac0b3 100644
--- a/meld/diffmap.py
+++ b/meld/diffmap.py
@@ -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()
diff --git a/meld/filediff.py b/meld/filediff.py
index e9252f4..d79fcfd 100644
--- a/meld/filediff.py
+++ b/meld/filediff.py
@@ -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:



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