Add possibility to rotate the paned containers.
This commit is contained in:
parent
f8b59348c6
commit
e95bdcf964
|
@ -77,6 +77,12 @@ will be displayed
|
||||||
.SH "KEYBINDINGS"
|
.SH "KEYBINDINGS"
|
||||||
The following keybindings can be used to control Terminator:
|
The following keybindings can be used to control Terminator:
|
||||||
.TP
|
.TP
|
||||||
|
.B Super+R
|
||||||
|
\fBR\fotate terminals clockwise.
|
||||||
|
.TP
|
||||||
|
.B Super+Shift+R
|
||||||
|
\fBR\fotate terminals counter-clockwise.
|
||||||
|
.TP
|
||||||
.B Ctrl+Shift+O
|
.B Ctrl+Shift+O
|
||||||
Split terminals H\fBo\fRrizontally.
|
Split terminals H\fBo\fRrizontally.
|
||||||
.TP
|
.TP
|
||||||
|
|
|
@ -171,6 +171,14 @@ Default value: \fB<Alt>Left\fR
|
||||||
Move cursor focus to the terminal to the right.
|
Move cursor focus to the terminal to the right.
|
||||||
Default value: \fB<Alt>Right\fR
|
Default value: \fB<Alt>Right\fR
|
||||||
.TP
|
.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
|
.B split_horiz
|
||||||
Split the current terminal horizontally.
|
Split the current terminal horizontally.
|
||||||
Default value: \fB<Ctrl><Shift>O\fR
|
Default value: \fB<Ctrl><Shift>O\fR
|
||||||
|
|
|
@ -118,6 +118,8 @@ DEFAULTS = {
|
||||||
'go_down' : '<Alt>Down',
|
'go_down' : '<Alt>Down',
|
||||||
'go_left' : '<Alt>Left',
|
'go_left' : '<Alt>Left',
|
||||||
'go_right' : '<Alt>Right',
|
'go_right' : '<Alt>Right',
|
||||||
|
'rotate_cw' : '<Super>r',
|
||||||
|
'rotate_ccw' : '<Super><Shift>r',
|
||||||
'split_horiz' : '<Shift><Control>o',
|
'split_horiz' : '<Shift><Control>o',
|
||||||
'split_vert' : '<Shift><Control>e',
|
'split_vert' : '<Shift><Control>e',
|
||||||
'close_term' : '<Shift><Control>w',
|
'close_term' : '<Shift><Control>w',
|
||||||
|
|
|
@ -80,6 +80,10 @@ class Container(object):
|
||||||
"""Default axis splitter. This should be implemented by subclasses"""
|
"""Default axis splitter. This should be implemented by subclasses"""
|
||||||
raise NotImplementedError('split_axis')
|
raise NotImplementedError('split_axis')
|
||||||
|
|
||||||
|
def rotate(self, widget, clockwise):
|
||||||
|
"""Rotate children in this container"""
|
||||||
|
raise NotImplementedError('rotate')
|
||||||
|
|
||||||
def add(self, widget, metadata=None):
|
def add(self, widget, metadata=None):
|
||||||
"""Add a widget to the container"""
|
"""Add a widget to the container"""
|
||||||
raise NotImplementedError('add')
|
raise NotImplementedError('add')
|
||||||
|
@ -265,4 +269,5 @@ the %s will also close all terminals within it.') % (reqtype, reqtype))
|
||||||
"""Apply settings for our layout"""
|
"""Apply settings for our layout"""
|
||||||
raise NotImplementedError('create_layout')
|
raise NotImplementedError('create_layout')
|
||||||
|
|
||||||
|
|
||||||
# vim: set expandtab ts=4 sw=4:
|
# vim: set expandtab ts=4 sw=4:
|
||||||
|
|
|
@ -19,6 +19,7 @@ class Paned(Container):
|
||||||
|
|
||||||
position = None
|
position = None
|
||||||
maker = None
|
maker = None
|
||||||
|
ratio = 0.5
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Class initialiser"""
|
"""Class initialiser"""
|
||||||
|
@ -31,19 +32,6 @@ class Paned(Container):
|
||||||
'param_types': (gobject.TYPE_STRING,)})
|
'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
|
# pylint: disable-msg=W0613
|
||||||
def split_axis(self, widget, vertical=True, cwd=None, sibling=None,
|
def split_axis(self, widget, vertical=True, cwd=None, sibling=None,
|
||||||
widgetfirst=True):
|
widgetfirst=True):
|
||||||
|
@ -76,13 +64,13 @@ class Paned(Container):
|
||||||
def add(self, widget, metadata=None):
|
def add(self, widget, metadata=None):
|
||||||
"""Add a widget to the container"""
|
"""Add a widget to the container"""
|
||||||
if len(self.children) == 0:
|
if len(self.children) == 0:
|
||||||
self.pack1(widget, True, True)
|
self.pack1(widget, False, True)
|
||||||
self.children.append(widget)
|
self.children.append(widget)
|
||||||
elif len(self.children) == 1:
|
elif len(self.children) == 1:
|
||||||
if self.get_child1():
|
if self.get_child1():
|
||||||
self.pack2(widget, True, True)
|
self.pack2(widget, False, True)
|
||||||
else:
|
else:
|
||||||
self.pack1(widget, True, True)
|
self.pack1(widget, False, True)
|
||||||
self.children.append(widget)
|
self.children.append(widget)
|
||||||
else:
|
else:
|
||||||
raise ValueError('Paned widgets can only have two children')
|
raise ValueError('Paned widgets can only have two children')
|
||||||
|
@ -94,6 +82,7 @@ class Paned(Container):
|
||||||
'split-vert': self.split_vert,
|
'split-vert': self.split_vert,
|
||||||
'title-change': self.propagate_title_change,
|
'title-change': self.propagate_title_change,
|
||||||
'resize-term': self.resizeterm,
|
'resize-term': self.resizeterm,
|
||||||
|
'size-allocate': self.new_size,
|
||||||
'zoom': top_window.zoom,
|
'zoom': top_window.zoom,
|
||||||
'tab-change': top_window.tab_change,
|
'tab-change': top_window.tab_change,
|
||||||
'group-all': top_window.group_all,
|
'group-all': top_window.group_all,
|
||||||
|
@ -103,7 +92,9 @@ class Paned(Container):
|
||||||
'move-tab': top_window.move_tab,
|
'move-tab': top_window.move_tab,
|
||||||
'maximise': [top_window.zoom, False],
|
'maximise': [top_window.zoom, False],
|
||||||
'tab-new': [top_window.tab_new, widget],
|
'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:
|
for signal in signals:
|
||||||
args = []
|
args = []
|
||||||
|
@ -118,6 +109,7 @@ class Paned(Container):
|
||||||
elif isinstance(widget, gtk.Paned):
|
elif isinstance(widget, gtk.Paned):
|
||||||
try:
|
try:
|
||||||
self.connect_child(widget, 'resize-term', self.resizeterm)
|
self.connect_child(widget, 'resize-term', self.resizeterm)
|
||||||
|
self.connect_child(widget, 'size-allocate', self.new_size)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
err('Paned::add: %s has no signal resize-term' % widget)
|
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"""
|
"""We don't want focus, we want a Terminal to have it"""
|
||||||
self.get_child1().grab_focus()
|
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):
|
class HPaned(Paned, gtk.HPaned):
|
||||||
"""Merge gtk.HPaned into our base Paned Container"""
|
"""Merge gtk.HPaned into our base Paned Container"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -267,7 +288,12 @@ class HPaned(Paned, gtk.HPaned):
|
||||||
Paned.__init__(self)
|
Paned.__init__(self)
|
||||||
gtk.HPaned.__init__(self)
|
gtk.HPaned.__init__(self)
|
||||||
self.register_signals(HPaned)
|
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):
|
class VPaned(Paned, gtk.VPaned):
|
||||||
"""Merge gtk.VPaned into our base Paned Container"""
|
"""Merge gtk.VPaned into our base Paned Container"""
|
||||||
|
@ -276,7 +302,12 @@ class VPaned(Paned, gtk.VPaned):
|
||||||
Paned.__init__(self)
|
Paned.__init__(self)
|
||||||
gtk.VPaned.__init__(self)
|
gtk.VPaned.__init__(self)
|
||||||
self.register_signals(VPaned)
|
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(HPaned)
|
||||||
gobject.type_register(VPaned)
|
gobject.type_register(VPaned)
|
||||||
|
|
|
@ -84,6 +84,8 @@ class PrefsEditor:
|
||||||
'go_down' : 'Focus the terminal below',
|
'go_down' : 'Focus the terminal below',
|
||||||
'go_left' : 'Focus the terminal left',
|
'go_left' : 'Focus the terminal left',
|
||||||
'go_right' : 'Focus the terminal right',
|
'go_right' : 'Focus the terminal right',
|
||||||
|
'rotate_cw' : 'Rotate terminals clockwise',
|
||||||
|
'rotate_ccw' : 'Rotate terminals counter-clockwise',
|
||||||
'split_horiz' : 'Split horizontally',
|
'split_horiz' : 'Split horizontally',
|
||||||
'split_vert' : 'Split vertically',
|
'split_vert' : 'Split vertically',
|
||||||
'close_term' : 'Close terminal',
|
'close_term' : 'Close terminal',
|
||||||
|
|
|
@ -52,6 +52,8 @@ class Terminal(gtk.VBox):
|
||||||
(gobject.TYPE_STRING,)),
|
(gobject.TYPE_STRING,)),
|
||||||
'split-vert': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
|
'split-vert': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
|
||||||
(gobject.TYPE_STRING,)),
|
(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,
|
'tab-new': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
|
||||||
(gobject.TYPE_BOOLEAN, gobject.TYPE_OBJECT)),
|
(gobject.TYPE_BOOLEAN, gobject.TYPE_OBJECT)),
|
||||||
'tab-top-new': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
|
'tab-top-new': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
|
||||||
|
@ -1509,6 +1511,12 @@ class Terminal(gtk.VBox):
|
||||||
def key_split_vert(self):
|
def key_split_vert(self):
|
||||||
self.emit('split-vert', self.terminator.pid_cwd(self.pid))
|
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):
|
def key_close_term(self):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|
|
@ -479,6 +479,24 @@ class Window(Container, gtk.Window):
|
||||||
self.zoom_data = None
|
self.zoom_data = None
|
||||||
self.set_property('term_zoomed', False)
|
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):
|
def get_visible_terminals(self):
|
||||||
"""Walk down the widget tree to find all of the visible terminals.
|
"""Walk down the widget tree to find all of the visible terminals.
|
||||||
Mostly using Container::get_visible_terminals()"""
|
Mostly using Container::get_visible_terminals()"""
|
||||||
|
|
Loading…
Reference in New Issue