commit c98081dddc0cf3930dbfa38db999311869742544 Author: Damian Johnson atagar@torproject.org Date: Wed Jul 13 09:12:17 2016 -0700
Drop legacy draw methods
Now that we draw using our Subwindow class we can drop the old curses methods from Panel. --- nyx/panel/__init__.py | 287 -------------------------------------------------- 1 file changed, 287 deletions(-)
diff --git a/nyx/panel/__init__.py b/nyx/panel/__init__.py index 06af3e1..fdd1480 100644 --- a/nyx/panel/__init__.py +++ b/nyx/panel/__init__.py @@ -6,16 +6,11 @@ Panels consisting the nyx interface. """
import collections -import curses import inspect import threading import time
import nyx.curses -import stem.util.log - -from nyx.curses import HIGHLIGHT -from stem.util import conf, str_tools
__all__ = [ 'config', @@ -26,16 +21,6 @@ __all__ = [ 'torrc', ]
- -def conf_handler(key, value): - if key == 'features.torrc.maxLineWrap': - return max(1, value) - - -CONFIG = conf.config_dict('nyx', { - 'features.maxLineWrap': 8, -}, conf_handler) - HALT_ACTIVITY = False # prevents curses redraws if set
@@ -119,16 +104,6 @@ class Panel(object): self.height = -1 self.width = -1
- # The panel's subwindow instance. This is made available to implementors - # via their draw method and shouldn't be accessed directly. - # - # This is None if either the subwindow failed to be created or needs to be - # remade before it's used. The later could be for a couple reasons: - # - The subwindow was never initialized. - # - Any of the parameters used for subwindow initialization have changed. - - self.win = None - self.max_y, self.max_x = -1, -1 # subwindow dimensions when last redrawn
def get_name(self): @@ -192,7 +167,6 @@ class Panel(object):
if self.top != top: self.top = top - self.win = None
def get_height(self): """ @@ -267,267 +241,6 @@ class Panel(object):
nyx.curses.draw(self.draw, top = self.top, width = width, height = height)
- def hline(self, y, x, length, *attributes): - """ - Draws a horizontal line. This should only be called from the context of a - panel's draw method. - - Arguments: - y - vertical location - x - horizontal location - length - length the line spans - attr - text attributes - """ - - format_attr = nyx.curses.curses_attr(*attributes) - - if self.win and self.max_x > x and self.max_y > y: - try: - draw_length = min(length, self.max_x - x) - self.win.hline(y, x, curses.ACS_HLINE | format_attr, draw_length) - except: - # in edge cases drawing could cause a _curses.error - pass - - def vline(self, y, x, length, *attributes): - """ - Draws a vertical line. This should only be called from the context of a - panel's draw method. - - Arguments: - y - vertical location - x - horizontal location - length - length the line spans - attr - text attributes - """ - - format_attr = nyx.curses.curses_attr(*attributes) - - if self.win and self.max_x > x and self.max_y > y: - try: - draw_length = min(length, self.max_y - y) - self.win.vline(y, x, curses.ACS_VLINE | format_attr, draw_length) - except: - # in edge cases drawing could cause a _curses.error - pass - - def addch(self, y, x, char, *attributes): - """ - Draws a single character. This should only be called from the context of a - panel's draw method. - - Arguments: - y - vertical location - x - horizontal location - char - character to be drawn - attr - text attributes - """ - - format_attr = nyx.curses.curses_attr(*attributes) - - if self.win and self.max_x > x and self.max_y > y: - try: - self.win.addch(y, x, char, format_attr) - return x + 1 - except: - # in edge cases drawing could cause a _curses.error - pass - - return x - - def addstr(self, y, x, msg, *attributes): - """ - Writes string to subwindow if able. This takes into account screen bounds - to avoid making curses upset. This should only be called from the context - of a panel's draw method. - - Arguments: - y - vertical location - x - horizontal location - msg - text to be added - attr - text attributes - """ - - format_attr = nyx.curses.curses_attr(*attributes) - - # subwindows need a single character buffer (either in the x or y - # direction) from actual content to prevent crash when shrank - - if self.win and self.max_x > x and self.max_y > y: - try: - drawn_msg = msg[:self.max_x - x] - self.win.addstr(y, x, drawn_msg, format_attr) - return x + len(drawn_msg) - except: - # this might produce a _curses.error during edge cases, for instance - # when resizing with visible popups - - pass - - return x - - def addstr_wrap(self, y, x, msg, width, min_x = 0, *attr): - orig_y = y - - while msg: - draw_msg, msg = str_tools.crop(msg, width - x, None, ending = None, get_remainder = True) - - if not draw_msg: - draw_msg, msg = str_tools.crop(msg, width - x), '' # first word is longer than the line - - x = self.addstr(y, x, draw_msg, *attr) - - if (y - orig_y + 1) >= CONFIG['features.maxLineWrap']: - break # maximum number we'll wrap - - if msg: - x, y = min_x, y + 1 - - return x, y - - def add_scroll_bar(self, top, bottom, size, draw_top = 0): - """ - Draws a left justified scroll bar reflecting position within a vertical - listing. This is shorted if necessary, and left undrawn if no space is - available. The bottom is squared off, having a layout like: - | - *| - *| - *| - | - -+ - - This should only be called from the context of a panel's draw method. - - Arguments: - top - list index for the top-most visible element - bottom - list index for the bottom-most visible element - size - size of the list in which the listed elements are contained - draw_top - starting row where the scroll bar should be drawn - """ - - if (self.max_y - draw_top) < 2: - return # not enough room - - # determines scrollbar dimensions - - scrollbar_height = self.max_y - draw_top - 1 - slider_top = scrollbar_height * top / size - slider_size = scrollbar_height * (bottom - top) / size - - # ensures slider isn't at top or bottom unless really at those extreme bounds - - if top > 0: - slider_top = max(slider_top, 1) - - if bottom != size: - slider_top = min(slider_top, scrollbar_height - slider_size - 2) - - # avoids a rounding error that causes the scrollbar to be too low when at - # the bottom - - if bottom == size: - slider_top = scrollbar_height - slider_size - 1 - - # draws scrollbar slider - - for i in range(scrollbar_height): - if i >= slider_top and i <= slider_top + slider_size: - self.addstr(i + draw_top, 0, ' ', HIGHLIGHT) - else: - self.addstr(i + draw_top, 0, ' ') - - # draws box around the scroll bar - - self.vline(draw_top, 1, self.max_y - 2) - self.addch(self.max_y - 1, 1, curses.ACS_LRCORNER) - self.addch(self.max_y - 1, 0, curses.ACS_HLINE) - - def _reset_subwindow(self): - """ - Create a new subwindow instance for the panel if: - - Panel currently doesn't have a subwindow (was uninitialized or - invalidated). - - There's room for the panel to grow vertically (curses automatically - lets subwindows regrow horizontally, but not vertically). - - The subwindow has been displaced. This is a curses display bug that - manifests if the terminal's shrank then re-expanded. Displaced - subwindows are never restored to their proper position, resulting in - graphical glitches if we draw to them. - - The preferred size is smaller than the actual size (should shrink). - - This returns True if a new subwindow instance was created, False otherwise. - """ - - new_height, new_width = self.get_preferred_size() - - if new_height == 0: - return False # subwindow would be outside its parent - - # determines if a new subwindow should be recreated - - recreate = self.win is None - - if self.win: - subwin_max_y, subwin_max_x = self.win.getmaxyx() - recreate |= subwin_max_y < new_height # check for vertical growth - recreate |= self.top > self.win.getparyx()[0] # check for displacement - recreate |= subwin_max_x > new_width or subwin_max_y > new_height # shrinking - - # I'm not sure if recreating subwindows is some sort of memory leak but the - # Python curses bindings seem to lack all of the following: - # - subwindow deletion (to tell curses to free the memory) - # - subwindow moving/resizing (to restore the displaced windows) - # so this is the only option (besides removing subwindows entirely which - # would mean far more complicated code and no more selective refreshing) - - if recreate: - with nyx.curses.raw_screen() as stdscr: - self.win = stdscr.subwin(new_height, new_width, self.top, self.left) - - # note: doing this log before setting win produces an infinite loop - stem.util.log.debug("recreating panel '%s' with the dimensions of %i/%i" % (self.get_name(), new_height, new_width)) - - return recreate - - def draw_box(self, top = 0, left = 0, width = -1, height = -1, *attributes): - """ - Draws a box in the panel with the given bounds. - - Arguments: - top - vertical position of the box's top - left - horizontal position of the box's left side - width - width of the drawn box - height - height of the drawn box - attr - text attributes - """ - - if width == -1 or height == -1: - panel_height, panel_width = self.get_preferred_size() - - if width == -1: - width = panel_width - left - - if height == -1: - height = panel_height - top - - # draws the top and bottom - - self.hline(top, left + 1, width - 2, *attributes) - self.hline(top + height - 1, left + 1, width - 2, *attributes) - - # draws the left and right sides - - self.vline(top + 1, left, height - 2, *attributes) - self.vline(top + 1, left + width - 1, height - 2, *attributes) - - # draws the corners - - self.addch(top, left, curses.ACS_ULCORNER, *attributes) - self.addch(top, left + width - 1, curses.ACS_URCORNER, *attributes) - self.addch(top + height - 1, left, curses.ACS_LLCORNER, *attributes) - self.addch(top + height - 1, left + width - 1, curses.ACS_LRCORNER, *attributes) -
class DaemonPanel(Panel, threading.Thread): def __init__(self, name, update_rate):
tor-commits@lists.torproject.org