From e95bdcf9642c704353f90bedaff83f1b040b0d99 Mon Sep 17 00:00:00 2001 From: Andre Hilsendeger Date: Wed, 4 Apr 2012 17:48:29 +0200 Subject: [PATCH] Add possibility to rotate the paned containers. --- doc/terminator.1 | 6 ++++ doc/terminator_config.5 | 8 +++++ terminatorlib/config.py | 2 ++ terminatorlib/container.py | 5 +++ terminatorlib/paned.py | 69 ++++++++++++++++++++++++++---------- terminatorlib/prefseditor.py | 2 ++ terminatorlib/terminal.py | 8 +++++ terminatorlib/window.py | 18 ++++++++++ 8 files changed, 99 insertions(+), 19 deletions(-) diff --git a/doc/terminator.1 b/doc/terminator.1 index ba37e3d3..4b746484 100644 --- a/doc/terminator.1 +++ b/doc/terminator.1 @@ -77,6 +77,12 @@ will be displayed .SH "KEYBINDINGS" The following keybindings can be used to control Terminator: .TP +.B Super+R +\fBR\fotate terminals clockwise. +.TP +.B Super+Shift+R +\fBR\fotate terminals counter-clockwise. +.TP .B Ctrl+Shift+O Split terminals H\fBo\fRrizontally. .TP diff --git a/doc/terminator_config.5 b/doc/terminator_config.5 index 96c8d224..677383ca 100644 --- a/doc/terminator_config.5 +++ b/doc/terminator_config.5 @@ -171,6 +171,14 @@ Default value: \fBLeft\fR Move cursor focus to the terminal to the right. Default value: \fBRight\fR .TP +.B rotate_cw +Rotate terminals clockwise. +Default value: \fBR\fR +.TP +.B rotate_ccw +Rotate terminals counter-clockwise. +Default value: \fBR\fR +.TP .B split_horiz Split the current terminal horizontally. Default value: \fBO\fR diff --git a/terminatorlib/config.py b/terminatorlib/config.py index fc9ed558..20a39cea 100755 --- a/terminatorlib/config.py +++ b/terminatorlib/config.py @@ -118,6 +118,8 @@ DEFAULTS = { 'go_down' : 'Down', 'go_left' : 'Left', 'go_right' : 'Right', + 'rotate_cw' : 'r', + 'rotate_ccw' : 'r', 'split_horiz' : 'o', 'split_vert' : 'e', 'close_term' : 'w', diff --git a/terminatorlib/container.py b/terminatorlib/container.py index 35abf981..bb14fb8b 100755 --- a/terminatorlib/container.py +++ b/terminatorlib/container.py @@ -80,6 +80,10 @@ class Container(object): """Default axis splitter. This should be implemented by subclasses""" raise NotImplementedError('split_axis') + def rotate(self, widget, clockwise): + """Rotate children in this container""" + raise NotImplementedError('rotate') + def add(self, widget, metadata=None): """Add a widget to the container""" raise NotImplementedError('add') @@ -265,4 +269,5 @@ the %s will also close all terminals within it.') % (reqtype, reqtype)) """Apply settings for our layout""" raise NotImplementedError('create_layout') + # vim: set expandtab ts=4 sw=4: diff --git a/terminatorlib/paned.py b/terminatorlib/paned.py index 2349a529..4272ac02 100755 --- a/terminatorlib/paned.py +++ b/terminatorlib/paned.py @@ -19,6 +19,7 @@ class Paned(Container): position = None maker = None + ratio = 0.5 def __init__(self): """Class initialiser""" @@ -31,19 +32,6 @@ class Paned(Container): 'param_types': (gobject.TYPE_STRING,)}) - # pylint: disable-msg=W0613 - def set_initial_position(self, widget, event): - """Set the initial position of the widget""" - if not self.position: - if isinstance(self, gtk.VPaned): - self.position = self.allocation.height / 2 - else: - self.position = self.allocation.width / 2 - - dbg("Paned::set_initial_position: Setting position to: %d" % self.position) - self.set_position(self.position) - self.cnxids.remove_signal(self, 'expose-event') - # pylint: disable-msg=W0613 def split_axis(self, widget, vertical=True, cwd=None, sibling=None, widgetfirst=True): @@ -76,13 +64,13 @@ class Paned(Container): def add(self, widget, metadata=None): """Add a widget to the container""" if len(self.children) == 0: - self.pack1(widget, True, True) + self.pack1(widget, False, True) self.children.append(widget) elif len(self.children) == 1: if self.get_child1(): - self.pack2(widget, True, True) + self.pack2(widget, False, True) else: - self.pack1(widget, True, True) + self.pack1(widget, False, True) self.children.append(widget) else: raise ValueError('Paned widgets can only have two children') @@ -94,6 +82,7 @@ class Paned(Container): 'split-vert': self.split_vert, 'title-change': self.propagate_title_change, 'resize-term': self.resizeterm, + 'size-allocate': self.new_size, 'zoom': top_window.zoom, 'tab-change': top_window.tab_change, 'group-all': top_window.group_all, @@ -103,7 +92,9 @@ class Paned(Container): 'move-tab': top_window.move_tab, 'maximise': [top_window.zoom, False], 'tab-new': [top_window.tab_new, widget], - 'navigate': top_window.navigate_terminal} + 'navigate': top_window.navigate_terminal, + 'rotate-cw': [top_window.rotate, True], + 'rotate-ccw': [top_window.rotate, False]} for signal in signals: args = [] @@ -118,6 +109,7 @@ class Paned(Container): elif isinstance(widget, gtk.Paned): try: self.connect_child(widget, 'resize-term', self.resizeterm) + self.connect_child(widget, 'size-allocate', self.new_size) except TypeError: err('Paned::add: %s has no signal resize-term' % widget) @@ -260,6 +252,35 @@ 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""" + if isinstance(self, HPaned): + container = VPaned() + reverse = not clockwise + else: + container = HPaned() + 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) + + def new_size(self, widget, allocation): + self.set_pos(int(self.ratio*self.get_length())) + + def set_position(self, pos): + self.ratio = float(pos) / self.get_length() + self.set_pos(pos) + class HPaned(Paned, gtk.HPaned): """Merge gtk.HPaned into our base Paned Container""" def __init__(self): @@ -267,7 +288,12 @@ class HPaned(Paned, gtk.HPaned): Paned.__init__(self) gtk.HPaned.__init__(self) self.register_signals(HPaned) - self.cnxids.new(self, 'expose-event', self.set_initial_position) + + def get_length(self): + return(self.allocation.width) + + def set_pos(self, pos): + gtk.HPaned.set_position(self, pos) class VPaned(Paned, gtk.VPaned): """Merge gtk.VPaned into our base Paned Container""" @@ -276,7 +302,12 @@ class VPaned(Paned, gtk.VPaned): Paned.__init__(self) gtk.VPaned.__init__(self) self.register_signals(VPaned) - self.cnxids.new(self, 'expose-event', self.set_initial_position) + + def get_length(self): + return(self.allocation.height) + + def set_pos(self, pos): + gtk.VPaned.set_position(self, pos) gobject.type_register(HPaned) gobject.type_register(VPaned) diff --git a/terminatorlib/prefseditor.py b/terminatorlib/prefseditor.py index 17ef7d8a..80153ea7 100755 --- a/terminatorlib/prefseditor.py +++ b/terminatorlib/prefseditor.py @@ -84,6 +84,8 @@ class PrefsEditor: 'go_down' : 'Focus the terminal below', 'go_left' : 'Focus the terminal left', 'go_right' : 'Focus the terminal right', + 'rotate_cw' : 'Rotate terminals clockwise', + 'rotate_ccw' : 'Rotate terminals counter-clockwise', 'split_horiz' : 'Split horizontally', 'split_vert' : 'Split vertically', 'close_term' : 'Close terminal', diff --git a/terminatorlib/terminal.py b/terminatorlib/terminal.py index 9c3f930f..c3961cc8 100755 --- a/terminatorlib/terminal.py +++ b/terminatorlib/terminal.py @@ -52,6 +52,8 @@ class Terminal(gtk.VBox): (gobject.TYPE_STRING,)), 'split-vert': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), + 'rotate-cw': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), + 'rotate-ccw': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), 'tab-new': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_BOOLEAN, gobject.TYPE_OBJECT)), 'tab-top-new': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), @@ -1509,6 +1511,12 @@ class Terminal(gtk.VBox): def key_split_vert(self): self.emit('split-vert', self.terminator.pid_cwd(self.pid)) + def key_rotate_cw(self): + self.emit('rotate-cw') + + def key_rotate_ccw(self): + self.emit('rotate-ccw') + def key_close_term(self): self.close() diff --git a/terminatorlib/window.py b/terminatorlib/window.py index 8fb4fbf7..85818ae8 100755 --- a/terminatorlib/window.py +++ b/terminatorlib/window.py @@ -479,6 +479,24 @@ class Window(Container, gtk.Window): self.zoom_data = None self.set_property('term_zoomed', False) + def rotate(self, widget, clockwise): + """Rotate children in this window""" + maker = Factory() + # collect all paned children in breadth-first order + paned = [] + for child in self.get_children(): + 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() + widget.grab_focus() + def get_visible_terminals(self): """Walk down the widget tree to find all of the visible terminals. Mostly using Container::get_visible_terminals()"""