1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
== code
copy-array-object: # src: (addr array T), dest-ah: (addr handle array T)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
#
(copy-array Heap *(ebp+8) *(ebp+0xc))
$copy-array-object:end:
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
# create an independent copy of file src into dest
# there's no way to do this without knowing the filename
copy-file: # src: (addr buffered-file), dest-ah: (addr handle buffered-file), filename: (addr array byte)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
50/push-eax
51/push-ecx
52/push-edx
53/push-ebx
56/push-esi
57/push-edi
# esi = src
8b/-> *(ebp+8) 6/r32/esi
# var n/ecx: int = src->buffer->size + 16
8b/-> *(esi+0xc) 0/r32/eax
05/add-to-eax 0x10/imm32 # buffered-file fields before buffer contents
89/<- %ecx 0/r32/eax
#
(allocate Heap %ecx *(ebp+0xc))
# var dest/edi: (addr buffered-file) = lookup(*dest-ah)
8b/-> *(ebp+0xc) 0/r32/eax
(lookup *eax *(eax+4)) # =># This file is part of ranger, the console file manager.
# License: GNU GPL version 3, see the file "AUTHORS" for details.
"""ViewMiller arranges the view in miller columns"""
from __future__ import (absolute_import, division, print_function)
import curses
from ranger.container import settings
from ranger.gui.widgets.view_base import ViewBase
from .browsercolumn import BrowserColumn
from .pager import Pager
from ..displayable import DisplayableContainer
class ViewMiller(ViewBase): # pylint: disable=too-many-ancestors,too-many-instance-attributes
ratios = None
preview = True
is_collapsed = False
stretch_ratios = None
old_collapse = False
def __init__(self, win):
ViewBase.__init__(self, win)
self.preview = True
self.columns = []
self.rebuild()
for option in ('preview_directories', 'preview_files'):
self.settings.signal_bind('setopt.' + option,
self._request_clear_if_has_borders, weak=True)
self.settings.signal_bind('setopt.column_ratios', self.request_clear)
self.settings.signal_bind('setopt.column_ratios', self.rebuild,
priority=settings.SIGNAL_PRIORITY_AFTER_SYNC)
self.old_draw_borders = self.settings.draw_borders
def rebuild(self):
for child in self.container:
if isinstance(child, BrowserColumn):
self.remove_child(child)
child.destroy()
self.pager = Pager(self.win, embedded=True)
self.pager.visible = False
self.add_child(self.pager)
ratios = self.settings.column_ratios
for column in self.columns:
column.destroy()
self.remove_child(column)
self.columns = []
ratios_sum = sum(ratios)
self.ratios = tuple((x / ratios_sum) for x in ratios)
last = 0.1 if self.settings.padding_right else 0
if len(self.ratios) >= 2:
self.stretch_ratios = self.ratios[:-2] + \
((self.ratios[-2] + self.ratios[-1] * 1.0 - last),
(self.ratios[-1] * last))
offset = 1 - len(ratios)
if self.preview:
offset += 1
for level in range(len(ratios)):
column = BrowserColumn(self.win, level + offset)
self.add_child(column)
self.columns.append(column)
try:
self.main_column = self.columns[self.preview and -2 or -1]
except IndexError:
self.main_column = None
else:
self.main_column.display_infostring = True
self.main_column.main_column = True
self.resize(self.y, self.x, self.hei, self.wid)
def _request_clear_if_has_borders(self):
if self.settings.draw_borders:
self.request_clear()
def draw(self):
if self.need_clear:
self.win.erase()
self.need_redraw = True
self.need_clear = False
for tab in self.fm.tabs.values():
directory = tab.thisdir
if directory:
directory.load_content_if_outdated()
directory.use()
DisplayableContainer.draw(self)
if self.settings.draw_borders:
self._draw_borders()
if self.draw_bookmarks:
self._draw_bookmarks()
elif self.draw_hints:
self._draw_hints()
elif self.draw_info:
self._draw_info(self.draw_info)
def _draw_borders(self):
win = self.win
self.color('in_browser', 'border')
left_start = 0
right_end = self.wid - 1
for child in self.columns:
if not child.has_preview():
left_start = child.x + child.wid
else:
break
# Shift the rightmost vertical line to the left to create a padding,
# but only when padding_right is on, the preview column is collapsed
# and we did not open the pager to "zoom" in to the file.
if self.settings.padding_right and not self.pager.visible and self.is_collapsed:
right_end = self.columns[-1].x - 1
if right_end < left_start:
right_end = self.wid - 1
# Draw horizontal lines and the leftmost vertical line
try:
# pylint: disable=no-member
win.hline(0, left_start, curses.ACS_HLINE, right_end - left_start)
win.hline(self.hei - 1, left_start, curses.ACS_HLINE, right_end - left_start)
win.vline(1, left_start, curses.ACS_VLINE, self.hei - 2)
# pylint: enable=no-member
except curses.error:
pass
# Draw the vertical lines in the middle
for child in self.columns[:-1]:
if not child.has_preview():
continue
if child.main_column and self.pager.visible:
# If we "zoom in" with the pager, we have to
# skip the between main_column and pager.
break
x = child.x + child.wid
y = self.hei - 1
try:
# pylint: disable=no-member
win.vline(1, x, curses.ACS_VLINE, y - 1)
self.addch(0, x, curses.ACS_TTEE, 0)
self.addch(y, x, curses.ACS_BTEE, 0)
# pylint: enable=no-member
except curses.error:
# in case it's off the boundaries
pass
# Draw the last vertical line
try:
# pylint: disable=no-member
win.vline(1, right_end, curses.ACS_VLINE, self.hei - 2)
# pylint: enable=no-member
except curses.error:
pass
# pylint: disable=no-member
self.addch(0, left_start, curses.ACS_ULCORNER)
self.addch(self.hei - 1, left_start, curses.ACS_LLCORNER)
self.addch(0, right_end, curses.ACS_URCORNER)
self.addch(self.hei - 1, right_end, curses.ACS_LRCORNER)
# pylint: enable=no-member
def _collapse(self):
# Should the last column be cut off? (Because there is no preview)
if not self.settings.collapse_preview or not self.preview \
or not self.stretch_ratios:
return False
result = not self.columns[-1].has_preview()
target = self.columns[-1].target
if not result and target and target.is_file:
if self.fm.settings.preview_script and \
self.fm.settings.use_preview_script:
try:
result = not self.fm.previews[target.realpath]['foundpreview']
except KeyError:
return self.old_collapse
self.old_collapse = result
return result
def resize(self, y, x, hei=None, wid=None):
"""Resize all the columns according to the given ratio"""
ViewBase.resize(self, y, x, hei, wid)
borders = self.settings.draw_borders
pad = 1 if borders else 0
left = pad
self.is_collapsed = self._collapse()
if self.is_collapsed:
generator = enumerate(self.stretch_ratios)
else:
generator = enumerate(self.ratios)
last_i = len(self.ratios) - 1
for i, ratio in generator:
wid = int(ratio * self.wid)
cut_off = self.is_collapsed and not self.settings.padding_right
if i == last_i:
if not cut_off:
wid = int(self.wid - left + 1 - pad)
else:
self.columns[i].resize(pad, max(0, left - 1), hei - pad * 2, 1)
self.columns[i].visible = False
continue
if i == last_i - 1:
self.pager.resize(pad, left, hei - pad * 2, max(1, self.wid - left - pad))
if cut_off:
self.columns[i].resize(pad, left, hei - pad * 2, max(1, self.wid - left - pad))
continue
try:
self.columns[i].resize(pad, left, hei - pad * 2, max(1, wid - 1))
except KeyError:
pass
left += wid
def open_pager(self):
self.pager.visible = True
self.pager.focused = True
self.need_clear = True
self.pager.open()
try:
self.columns[-1].visible = False
self.columns[-2].visible = False
except IndexError:
pass
def close_pager(self):
self.pager.visible = False
self.pager.focused = False
self.need_clear = True
self.pager.close()
try:
self.columns[-1].visible = True
self.columns[-2].visible = True
except IndexError:
pass
def poke(self):
ViewBase.poke(self)
# Show the preview column when it has a preview but has
# been hidden (e.g. because of padding_right = False)
if not self.columns[-1].visible and self.columns[-1].has_preview() \
and not self.pager.visible:
self.columns[-1].visible = True
if self.preview and self.is_collapsed != self._collapse():
if self.fm.settings.preview_files:
# force clearing the image when resizing preview column
self.columns[-1].clear_image(force=True)
self.resize(self.y, self.x, self.hei, self.wid)
if self.old_draw_borders != self.settings.draw_borders:
self.resize(self.y, self.x, self.hei, self.wid)
self.old_draw_borders = self.settings.draw_borders
|