# This file is part of ranger, the console file manager. # License: GNU GPL version 3, see the file "AUTHORS" for details. """The pager displays text and allows you to scroll inside it.""" from . import Widget from ranger.core.loader import CommandLoader from ranger.gui import ansi from ranger.ext.direction import Direction from ranger.ext.img_display import ImgDisplayUnsupportedException # TODO: Scrolling in embedded pager class Pager(Widget): source = None source_is_stream = False old_source = None old_scroll_begin = 0 old_startx = 0 need_clear_image = False need_redraw_image = False max_width = None def __init__(self, win, embedded=False): Widget.__init__(self, win) self.embedded = embedded self.scroll_begin = 0 self.startx = 0 self.markup = None self.lines = [] self.image = None self.image_drawn = False def open(self): self.scroll_begin = 0 self.markup = None self.max_width = 0 self.startx = 0 self.need_redraw = True def clear_image(self, force=False): if (force or self.need_clear_image) and self.image_drawn: self.fm.image_displayer.clear(self.x, self.y, self.wid, self.hei) self.need_clear_image = False self.image_drawn = False def close(self): if self.image: self.need_clear_image = True self.clear_image() if self.source and self.source_is_stream: self.source.close() def destroy(self): self.clear_image(force=True) Widget.destroy(self) def finalize(self): self.fm.ui.win.move(self.y, self.x) def draw(self): if self.need_clear_image: self.need_redraw = True if self.old_source != self.source: self.old_source = self.source self.need_redraw = True if self.old_scroll_begin != self.scroll_begin or \ self.old_startx != self.startx: self.old_startx = self.startx self.old_scroll_begin = self.scroll_begin self.need_redraw = True if self.need_redraw: self.win.erase() self.need_redraw_image = True self.clear_image() if not self.image: line_gen = self._generate_lines( starty=self.scroll_begin, startx=self.startx) for line, i in zip(line_gen, range(self.hei)): self._draw_line(i, line) self.need_redraw = False def draw_image(self): if self.image and self.need_redraw_image: self.source = None self.need_redraw_image = False try: self.fm.image_displayer.draw(self.image, self.x, self.y, self.wid, self.hei) except ImgDisplayUnsupportedException: self.fm.settings.preview_images = False except Exception as e: self.fm.notify(e, bad=True) else: self.image_drawn = True def _draw_line(self, i, line): if self.markup is None: self.addstr(i, 0, line) elif self.markup == 'ansi': try: self.win.move(i, 0) except Exception: pass else: for chunk in ansi.text_with_fg_bg_attr(line): if isinstance(chunk, tuple): self.set_fg_bg_attr(*chunk) else: self.addstr(chunk) def move(self, narg=None, **kw): direction = Direction(kw) if direction.horizontal(): self.startx = direction.move( direction=direction.right(), override=narg, maximum=self.max_width, current=self.startx, pagesize=self.wid, offset=-self.wid + 1) if direction.vertical(): movement = dict( direction=direction.down(), override=narg, current=self.scroll_begin, pagesize=self.hei, offset