[tor-commits] [nyx/master] Revise selection dialog

atagar at torproject.org atagar at torproject.org
Sun Apr 3 22:36:37 UTC 2016


commit 196add96cc96422c31b843d0d3af36e81f8f930d
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Apr 3 14:58:31 2016 -0700

    Revise selection dialog
    
    Cleaning up another dialog of ours. This one provides a list of options for the
    user to select from.
---
 nyx/panel/connection.py |  9 +++--
 nyx/panel/graph.py      | 20 +++--------
 nyx/panel/log.py        | 15 ++++----
 nyx/popups.py           | 96 ++++++++++++++++++++++---------------------------
 test/popups.py          | 22 ++++++++++++
 5 files changed, 79 insertions(+), 83 deletions(-)

diff --git a/nyx/panel/connection.py b/nyx/panel/connection.py
index a59b41c..e8eb0b5 100644
--- a/nyx/panel/connection.py
+++ b/nyx/panel/connection.py
@@ -389,14 +389,13 @@ class ConnectionPanel(nyx.panel.Panel, threading.Thread):
 
     def _pick_connection_resolver():
       connection_tracker = nyx.tracker.get_connection_tracker()
+      resolver = connection_tracker.get_custom_resolver()
       options = ['auto'] + list(connection.Resolver) + list(nyx.tracker.CustomResolver)
 
-      resolver = connection_tracker.get_custom_resolver()
-      selected_index = 0 if resolver is None else options.index(resolver)
-      selected = nyx.popups.show_menu('Connection Resolver:', options, selected_index)
+      selected = nyx.popups.show_selector('Connection Resolver:', options, resolver if resolver else 'auto')
+      connection_tracker.set_custom_resolver(None if selected == 'auto' else selected)
 
-      if selected != -1:
-        connection_tracker.set_custom_resolver(None if selected == 0 else options[selected])
+      self.redraw(True)
 
     def _show_client_locales():
       nyx.popups.show_counts('Client Locales', self._client_locale_usage)
diff --git a/nyx/panel/graph.py b/nyx/panel/graph.py
index 4ef9af3..2b40390 100644
--- a/nyx/panel/graph.py
+++ b/nyx/panel/graph.py
@@ -506,31 +506,19 @@ class GraphPanel(nyx.panel.Panel):
 
   def key_handlers(self):
     def _pick_stats():
-      # provides a menu to pick the graphed stats
-
       available_stats = sorted(self.stat_options())
       options = ['None'] + [stat.capitalize() for stat in available_stats]
-      initial_selection = available_stats.index(self.displayed_stat) + 1 if self.displayed_stat else 0
-
-      selection = nyx.popups.show_menu('Graphed Stats:', options, initial_selection)
-
-      # applies new setting
+      previous_selection = options[available_stats.index(self.displayed_stat) + 1] if self.displayed_stat else 'None'
 
-      if selection == 0:
-        self.displayed_stat = None
-      elif selection != -1:
-        self.displayed_stat = available_stats[selection - 1]
+      selection = nyx.popups.show_selector('Graphed Stats:', options, previous_selection)
+      self.displayed_stat = None if selection == 'None' else available_stats[options.index(selection) - 1]
 
     def _next_bounds():
       self.bounds_type = Bounds.next(self.bounds_type)
       self.redraw(True)
 
     def _pick_interval():
-      selection = nyx.popups.show_menu('Update Interval:', list(Interval), list(Interval).index(self.update_interval))
-
-      if selection != -1:
-        self.update_interval = list(Interval)[selection]
-
+      self.update_interval = nyx.popups.show_selector('Update Interval:', list(Interval), self.update_interval)
       self.redraw(True)
 
     return (
diff --git a/nyx/panel/log.py b/nyx/panel/log.py
index e2d7676..765e251 100644
--- a/nyx/panel/log.py
+++ b/nyx/panel/log.py
@@ -235,17 +235,16 @@ class LogPanel(nyx.panel.Panel, threading.Thread):
 
     def _pick_filter():
       with nyx.curses.CURSES_LOCK:
-        initial_selection = 1 if self._filter.selection() else 0
         options = ['None'] + self._filter.latest_selections() + ['New...']
-        selection = nyx.popups.show_menu('Log Filter:', options, initial_selection)
+        initial_selection = self._filter.selection() if self._filter.selection() else 'None'
+        selection = nyx.popups.show_selector('Log Filter:', options, initial_selection)
 
-        if selection == 0:
+        if selection == 'None':
           self._filter.select(None)
-        elif selection == len(options) - 1:
-          # selected 'New...' option - prompt user to input regular expression
-          self.show_filter_prompt()
-        elif selection != -1:
-          self._filter.select(self._filter.latest_selections()[selection - 1])
+        elif selection == 'New...':
+          self.show_filter_prompt()  # prompt user to input regular expression
+        else:
+          self._filter.select(selection)
 
     def _toggle_deduplication():
       self.set_duplicate_visability(not self._show_duplicates)
diff --git a/nyx/popups.py b/nyx/popups.py
index b0cd48e..261cdce 100644
--- a/nyx/popups.py
+++ b/nyx/popups.py
@@ -199,6 +199,47 @@ def show_counts(title, counts, fill_char = ' '):
     nyx.curses.key_input()
 
 
+def show_selector(title, options, previous_selection):
+  """
+  Provides list of items the user can choose from.
+
+  :param str title: dialog title
+  :param list options: options that can be selected from
+  :param str previous_selection: previously selected option
+
+  :returns: **str** of selection or **previous_selection** if dialog is canceled
+  """
+
+  selected_index = options.index(previous_selection) if previous_selection in options else 0
+  top = nyx.controller.get_controller().header_panel().get_height()
+
+  def _render(subwindow):
+    subwindow.box()
+    subwindow.addstr(0, 0, title, HIGHLIGHT)
+
+    for i, option in enumerate(options):
+      if option == previous_selection:
+        subwindow.addstr(2, i + 1, '> ')
+
+      attr = HIGHLIGHT if i == selected_index else NORMAL
+      subwindow.addstr(4, i + 1, ' %s ' % option, attr)
+
+  with nyx.curses.CURSES_LOCK:
+    while True:
+      nyx.curses.draw(lambda subwindow: subwindow.addstr(0, 0, ' ' * 500), top = top, height = 1)  # hides title below us
+      nyx.curses.draw(_render, top = top, width = max(map(len, options)) + 9, height = len(options) + 2)
+      key = nyx.curses.key_input()
+
+      if key.match('up'):
+        selected_index = max(0, selected_index - 1)
+      elif key.match('down'):
+        selected_index = min(len(options) - 1, selected_index + 1)
+      elif key.is_selection():
+        return options[selected_index]
+      elif key.match('esc'):
+        return previous_selection
+
+
 def show_sort_dialog(title, options, previous_order, option_colors):
   """
   Provides sorting dialog of the form...
@@ -211,7 +252,7 @@ def show_sort_dialog(title, options, previous_order, option_colors):
   :param str title: dialog title
   :param list options: sort options to be provided
   :param list previous_order: previous ordering
-  :param dict optoin_colors: mapping of options to their color
+  :param dict option_colors: mapping of options to their color
 
   :returns: **list** of the new sort order or **None** if dialog is canceled
   """
@@ -270,59 +311,6 @@ def show_sort_dialog(title, options, previous_order, option_colors):
   return new_order
 
 
-def show_menu(title, options, old_selection):
-  """
-  Provides menu with options laid out in a single column. User can cancel
-  selection with the escape key, in which case this proives -1. Otherwise this
-  returns the index of the selection.
-
-  Arguments:
-    title        - title displayed for the popup window
-    options      - ordered listing of options to display
-    old_selection - index of the initially selected option (uses the first
-                   selection without a carrot if -1)
-  """
-
-  max_width = max(map(len, options)) + 9
-
-  with popup_window(len(options) + 2, max_width) as (popup, _, _):
-    if not popup:
-      return -1
-
-    selection = old_selection if old_selection != -1 else 0
-
-    with popup_window(1, -1) as (title_erase, _, _):
-      title_erase.addstr(0, 0, ' ' * 500)  # hide title of the panel below us
-
-      while True:
-        popup.win.erase()
-        popup.draw_box()
-        popup.addstr(0, 0, title, HIGHLIGHT)
-
-        for i in range(len(options)):
-          label = options[i]
-          format = HIGHLIGHT if i == selection else NORMAL
-          tab = '> ' if i == old_selection else '  '
-          popup.addstr(i + 1, 2, tab)
-          popup.addstr(i + 1, 4, ' %s ' % label, format)
-
-        popup.win.refresh()
-
-        key = nyx.curses.key_input()
-
-        if key.match('up'):
-          selection = max(0, selection - 1)
-        elif key.match('down'):
-          selection = min(len(options) - 1, selection + 1)
-        elif key.is_selection():
-          break
-        elif key.match('esc'):
-          selection = -1
-          break
-
-  return selection
-
-
 def show_descriptor_popup(fingerprint, color, max_width, is_close_key):
   """
   Provides a dialog showing the descriptors for a given relay.
diff --git a/test/popups.py b/test/popups.py
index 8a7e76b..f3d4963 100644
--- a/test/popups.py
+++ b/test/popups.py
@@ -53,6 +53,19 @@ Client Locales-----------------------------------------------------------------+
 +------------------------------------------------------------------------------+
 """.strip()
 
+EXPECTED_SELECTOR = """
+Update Interval:---+
+| >  each second   |
+|    5 seconds     |
+|    30 seconds    |
+|    minutely      |
+|    15 minute     |
+|    30 minute     |
+|    hourly        |
+|    daily         |
++------------------+
+""".strip()
+
 EXPECTED_SORT_DIALOG_START = """
 Config Option Ordering:--------------------------------------------------------+
 | Current Order: Man Page Entry, Name, Is Set                                  |
@@ -144,6 +157,15 @@ class TestPopups(unittest.TestCase):
     self.assertEqual(EXPECTED_COUNTS, rendered.content)
 
   @patch('nyx.controller.get_controller')
+  def test_selector(self, get_controller_mock):
+    get_controller_mock().header_panel().get_height.return_value = 0
+
+    options = ['each second', '5 seconds', '30 seconds', 'minutely', '15 minute', '30 minute', 'hourly', 'daily']
+    rendered = test.render(nyx.popups.show_selector, 'Update Interval:', options, 'each second')
+    self.assertEqual(EXPECTED_SELECTOR, rendered.content)
+    self.assertEqual('each second', rendered.return_value)
+
+  @patch('nyx.controller.get_controller')
   def test_sort_dialog(self, get_controller_mock):
     get_controller_mock().header_panel().get_height.return_value = 0
 



More information about the tor-commits mailing list