[meld] diffgrid: Significantly rework size allocation



commit 1756aacab6f426b4d274a4155ccaf617ab4ffee1
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Sat Jun 28 08:43:45 2014 +1000

    diffgrid: Significantly rework size allocation
    
    The previous method worked as long as there was exactly 2 rows, and there
    were no widgets that spanned multiple columns. Unfortunately, that's
    exactly what the FindBar does, in row 3.
    
    The new model somewhat simplifies the grid allocation, and makes it more
    generic by allocating by child using grid location data, rather than
    doing allocation per-row, per-column (which doesn't work as soon as
    widgets span multiple rows or columns).
    
    There is still a lot of hard-coding of dimensions here, but this works
    for now.

 meld/diffgrid.py |   80 +++++++++++++++++++++++++++++++++++------------------
 1 files changed, 53 insertions(+), 27 deletions(-)
---
diff --git a/meld/diffgrid.py b/meld/diffgrid.py
index 556d0dd..6d404e2 100644
--- a/meld/diffgrid.py
+++ b/meld/diffgrid.py
@@ -13,6 +13,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from gi.repository import GObject
 from gi.repository import Gtk
 from gi.repository import Gdk
 
@@ -147,6 +148,8 @@ class DiffGrid(Gtk.Grid):
         wcols, hrows = self._get_min_sizes()
         yrows = [allocation.y,
                  allocation.y + hrows[0],
+                 # Roughly equivalent to hard-coding row 1 to expand=True
+                 allocation.y + (allocation.height - hrows[2]),
                  allocation.y + allocation.height]
 
         wmap1, wpane1, wlink1, wpane2, wlink2, wpane3, wmap2 = wcols
@@ -155,23 +158,51 @@ class DiffGrid(Gtk.Grid):
         pos1, pos2 = self._calculate_positions(xmin, xmax,
                                                wlink1, wlink2,
                                                wpane1, wpane2, wpane3)
-        xmap1 = allocation.x
-        xpane1 = xmin
-        wpane1 = pos1 - xpane1
+        wpane1 = pos1 - allocation.x + wmap1
         xlink1 = pos1
-        xpane2 = pos1 + wlink1
-        wpane2 = pos2 - xpane2
+        wpane2 = pos2 - pos1 + wlink1
         xlink2 = pos2
         xpane3 = pos2 + wlink2
         wpane3 = xmax - xpane3
-        xmap2 = xmax
-        self._set_column_allocation(0, xmap1, wmap1, yrows)
-        self._set_column_allocation(1, xpane1, wpane1, yrows)
-        self._set_column_allocation(2, xlink1, wlink1, yrows)
-        self._set_column_allocation(3, xpane2, wpane2, yrows)
-        self._set_column_allocation(4, xlink2, wlink2, yrows)
-        self._set_column_allocation(5, xpane3, wpane3, yrows)
-        self._set_column_allocation(6, xmap2, wmap2, yrows)
+        columns = [
+            allocation.x,
+            allocation.x + wmap1,
+            pos1,
+            pos1 + wlink1,
+            pos2,
+            pos2 + wlink2,
+            allocation.x + allocation.width - wmap2,
+            allocation.x + allocation.width,
+        ]
+
+        def get_child_prop_int(child, name):
+            prop = GObject.Value(int)
+            self.child_get_property(child, name, prop)
+            return prop.get_int()
+
+        def get_child_attach(child):
+            attach = [
+                get_child_prop_int(child, 'left-attach'),
+                get_child_prop_int(child, 'top-attach'),
+                get_child_prop_int(child, 'width'),
+                get_child_prop_int(child, 'height'),
+            ]
+            return attach
+
+        def child_allocate(child):
+            if not child.get_visible():
+                return
+            attach = get_child_attach(child)
+            left, top, width, height = attach
+            alloc = self.get_allocation()
+            alloc.x = columns[left]
+            alloc.y = yrows[top]
+            alloc.width = columns[left + width] - columns[left]
+            alloc.height = yrows[top + height] - yrows[top]
+            child.size_allocate(alloc)
+
+        for child in self.get_children():
+            child_allocate(child)
 
         if self.get_realized():
             mapped = self.get_mapped()
@@ -182,26 +213,21 @@ class DiffGrid(Gtk.Grid):
             self._handle2.set_visible(mapped and wlink2 > 0)
             self._handle2.move_resize(xlink2, ydrag, wlink2, hdrag)
 
-    def _set_column_allocation(self, col, x, width, rows):
-        for row in range(0, 2):
-            child = self.get_child_at(col, row)
-            if child and child.get_visible():
-                alloc = self.get_allocation()
-                alloc.x = x
-                alloc.y = rows[row]
-                alloc.width = width
-                alloc.height = rows[row+1] - alloc.y
-                child.size_allocate(alloc)
-
     def _get_min_sizes(self):
-        hrows = [0] * 2
+        hrows = [0] * 3
         wcols = [0] * 7
-        for row in range(0, 2):
+        for row in range(0, 3):
             for col in range(0, 7):
                 child = self.get_child_at(col, row)
                 if child and child.get_visible():
                     msize, nsize = child.get_preferred_size()
-                    wcols[col] = max(wcols[col], msize.width, nsize.width)
+                    # Ignore spanning columns in width calculations; we should
+                    # do this properly, but it's difficult.
+                    spanning = GObject.Value(int)
+                    self.child_get_property(child, 'width', spanning)
+                    spanning = spanning.get_int()
+                    if spanning == 1:
+                        wcols[col] = max(wcols[col], msize.width, nsize.width)
                     hrows[row] = max(hrows[row], msize.height, nsize.height)
         return wcols, hrows
 


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