From 01712503a0ae4c9923b82a9378a2acd4d31faa56 Mon Sep 17 00:00:00 2001 From: Stephen Boddy Date: Wed, 23 Nov 2016 06:10:25 +0100 Subject: [PATCH] Fixes zero-sized terminals after rotate --- terminatorlib/paned.py | 61 +++++++++++++++++++++++++++++++++-------- terminatorlib/window.py | 25 ++++++++--------- 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/terminatorlib/paned.py b/terminatorlib/paned.py index 9fee0673..519ebbeb 100755 --- a/terminatorlib/paned.py +++ b/terminatorlib/paned.py @@ -403,8 +403,17 @@ class Paned(Container): """We don't want focus, we want a Terminal to have it""" self.get_child1().grab_focus() - def rotate(self, widget, clockwise): - """Default rotation. This should be implemented by subclasses""" + def rotate_recursive(self, parent, w, h, clockwise): + """ + Recursively rotate "self" into a new paned that'll have "w" x "h" size. Attach it to "parent". + + As discussed in LP#1522542, we should build up the new layout (including the separator positions) + in a single step. We can't rely on Gtk+ computing the allocation sizes yet, so we have to do the + computation ourselves and carry the resulting paned sizes all the way down the widget tree. + """ + maker = Factory() + handle_size = self.get_handlesize() + if isinstance(self, HPaned): container = VPaned() reverse = not clockwise @@ -413,17 +422,34 @@ class Paned(Container): reverse = clockwise container.ratio = self.ratio - - self.get_parent().replace(self, container) - children = self.get_children() if reverse: container.ratio = 1 - container.ratio children.reverse() - for child in children: - self.remove(child) - container.add(child) + if isinstance(self, HPaned): + w1 = w2 = w + h1 = pos = self.position_by_ratio(h, handle_size, container.ratio) + h2 = max(h - h1 - handle_size, 0) + else: + h1 = h2 = h + w1 = pos = self.position_by_ratio(w, handle_size, container.ratio) + w2 = max(w - w1 - handle_size, 0) + + container.set_pos(pos) + parent.add(container) + + if maker.isinstance(children[0], 'Terminal'): + children[0].get_parent().remove(children[0]) + container.add(children[0]) + else: + children[0].rotate_recursive(container, w1, h1, clockwise) + + if maker.isinstance(children[1], 'Terminal'): + children[1].get_parent().remove(children[1]) + container.add(children[1]) + else: + children[1].rotate_recursive(container, w2, h2, clockwise) def new_size(self, widget, allocation): if self.get_toplevel().set_pos_by_ratio: @@ -431,13 +457,26 @@ class Paned(Container): else: self.set_position(self.get_position()) + def position_by_ratio(self, total_size, handle_size, ratio): + non_separator_size = max(total_size, handle_size, 0) + ratio = min(max(ratio, 0.0), 1.0) + return int(round(non_separator_size * ratio)) + + def ratio_by_position(self, total_size, handle_size, position): + non_separator_size = max(total_size, handle_size, 0) + if non_separator_size == 0: + return None + position = min(max(position, 0), non_separator_size) + return float(position) / float(non_separator_size) + def set_position_by_ratio(self): handle_size = handle_size = self.get_handlesize() - self.set_pos(int((self.ratio*self.get_length())-(handle_size/2.0))) + self.set_pos(self.position_by_ratio(self.get_length(), self.get_handlesize(), self.ratio)) def set_position(self, pos): - handle_size = handle_size = self.get_handlesize() - self.ratio = float(pos + (handle_size/2.0)) / self.get_length() + newratio = self.ratio_by_position(self.get_length(), self.get_handlesize(), pos) + if newratio is not None: + self.ratio = newratio self.set_pos(pos) class HPaned(Paned, Gtk.HPaned): diff --git a/terminatorlib/window.py b/terminatorlib/window.py index f6f38e59..52c113dc 100755 --- a/terminatorlib/window.py +++ b/terminatorlib/window.py @@ -533,8 +533,6 @@ class Window(Container, Gtk.Window): """Rotate children in this window""" self.set_pos_by_ratio = True maker = Factory() - # collect all paned children in breadth-first order - paned = [] child = self.get_child() # If our child is a Notebook, reset to work from its visible child @@ -543,19 +541,18 @@ class Window(Container, Gtk.Window): child = child.get_nth_page(pagenum) if maker.isinstance(child, 'Paned'): - paned.append(child) - for p in paned: - for child in p.get_children(): - if child not in paned and maker.isinstance(child, 'Paned'): - paned.append(child) - # then propagate the rotation - for p in paned: - p.rotate(widget, clockwise) - self.show_all() + parent = child.get_parent() + # Need to get the allocation before we remove the child, + # otherwise _sometimes_ we get incorrect values. + alloc = child.get_allocation() + parent.remove(child) + child.rotate_recursive(parent, alloc.width, alloc.height, clockwise) + + self.show_all() + while Gtk.events_pending(): + Gtk.main_iteration_do(False) + widget.grab_focus() - while Gtk.events_pending(): - Gtk.main_iteration_do(False) - widget.grab_focus() self.set_pos_by_ratio = False def get_visible_terminals(self):