Add possibility to rotate the paned containers.

This commit is contained in:
Andre Hilsendeger 2012-04-04 17:48:29 +02:00
parent f8b59348c6
commit e95bdcf964
8 changed files with 99 additions and 19 deletions

View File

@ -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

View File

@ -171,6 +171,14 @@ Default value: \fB<Alt>Left\fR
Move cursor focus to the terminal to the right.
Default value: \fB<Alt>Right\fR
.TP
.B rotate_cw
Rotate terminals clockwise.
Default value: \fB<Super>R\fR
.TP
.B rotate_ccw
Rotate terminals counter-clockwise.
Default value: \fB<Super><Shift>R\fR
.TP
.B split_horiz
Split the current terminal horizontally.
Default value: \fB<Ctrl><Shift>O\fR

View File

@ -118,6 +118,8 @@ DEFAULTS = {
'go_down' : '<Alt>Down',
'go_left' : '<Alt>Left',
'go_right' : '<Alt>Right',
'rotate_cw' : '<Super>r',
'rotate_ccw' : '<Super><Shift>r',
'split_horiz' : '<Shift><Control>o',
'split_vert' : '<Shift><Control>e',
'close_term' : '<Shift><Control>w',

View File

@ -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:

View File

@ -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)

View File

@ -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',

View File

@ -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()

View File

@ -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()"""