[tor-commits] [arm/master] Replaced namedtuples with MenuItem instances, fixed left arrow key on

atagar at torproject.org atagar at torproject.org
Sat Jun 4 21:12:30 UTC 2011


commit cf4ae8454debdf8a9ace9a4f4cc3e4536152d1dd
Author: Kamran Riaz Khan <krkhan at inspirated.com>
Date:   Sun May 29 15:32:34 2011 +0500

    Replaced namedtuples with MenuItem instances, fixed left arrow key on
    top level menu.
    
    The MenuItem class is added replacing LeafEntry and ParentEntry
    namedtuples. Replaced "entry" with "item" and defined the constant
    TOPLEVEL to improve readability.
    
    The scrolling calculations in _moveTopLevelLeft contained a bug, menus
    with large number of top items did not scroll to the end. Fixed by
    adding a check to see if we're "spilling" to left of first entry.
---
 src/cli/menu.py      |   98 +++++++++++++++++++++++++-------------------------
 src/util/menuItem.py |   34 +++++++++++++++++
 2 files changed, 83 insertions(+), 49 deletions(-)

diff --git a/src/cli/menu.py b/src/cli/menu.py
index bedb98e..71b56a4 100644
--- a/src/cli/menu.py
+++ b/src/cli/menu.py
@@ -3,34 +3,32 @@ A drop-down menu for sending actions to panels.
 """
 
 import curses
-from collections import namedtuple
 
 import cli.controller
 import popups
-from util import log, panel, uiTools
+from util import log, panel, uiTools, menuItem
 
-LeafEntry = namedtuple('LeafEntry', ['title', 'callback'])
-ParentEntry = namedtuple('ParentEntry', ['title', 'children'])
+TOPLEVEL = 0
 
 class Menu():
   """Displays a popup menu and sends keys to appropriate panels"""
 
-  def __init__(self, entry=None):
-    DEFAULT_ROOT = ParentEntry(title="Root", children=(
-      LeafEntry(title="File"          , callback=self._callbackDefault),
-      LeafEntry(title="Logs"          , callback=self._callbackDefault),
-      LeafEntry(title="View"          , callback=self._callbackDefault),
-      LeafEntry(title="Graph"         , callback=self._callbackDefault),
-      LeafEntry(title="Connections"   , callback=self._callbackDefault),
-      LeafEntry(title="Configuration" , callback=self._callbackDefault)))
+  def __init__(self, item=None):
+    DEFAULT_ROOT = menuItem.MenuItem(label="Root", children=(
+      menuItem.MenuItem(label="File"          , callback=self._callbackDefault),
+      menuItem.MenuItem(label="Logs"          , callback=self._callbackDefault),
+      menuItem.MenuItem(label="View"          , callback=self._callbackDefault),
+      menuItem.MenuItem(label="Graph"         , callback=self._callbackDefault),
+      menuItem.MenuItem(label="Connections"   , callback=self._callbackDefault),
+      menuItem.MenuItem(label="Configuration" , callback=self._callbackDefault)))
 
     self._first = [0]
     self._selection = [0]
 
-    if entry and isinstance(entry, ParentEntry):
-      self._rootEntry = entry
+    if item and item.isParent():
+      self._rootItem = item
     else:
-      self._rootEntry = DEFAULT_ROOT
+      self._rootItem = DEFAULT_ROOT
 
   def showMenu(self):
     popup, width, height = popups.init(height=3)
@@ -61,73 +59,75 @@ class Menu():
         popups.finalize()
 
   def _calculateTopLevelWidths(self, width):
-    titles = [menuItem.title for menuItem in self._rootEntry.children]
+    labels = [menuItem.getLabel() for menuItem in self._rootItem.getChildren()]
 
-    # width per title is set according to the longest title
-    titlewidth = max(map(len, titles)) + 2
+    # width per label is set according to the longest label
+    labelwidth = max(map(len, labels)) + 2
 
-    # total number of titles that can be printed in current width
-    printable = min(width / titlewidth - 1, len(self._rootEntry.children))
+    # total number of labels that can be printed in current width
+    printable = min(width / labelwidth - 1, self._rootItem.getChildrenCount())
 
-    return (titlewidth, printable)
+    return (labelwidth, printable)
 
   def _moveTopLevelRight(self, width):
     _, printable = self._calculateTopLevelWidths(width)
 
-    if self._selection[0] < printable - 1:
-      self._selection[0] = self._selection[0] + 1
+    if self._selection[TOPLEVEL] < printable - 1:
+      self._selection[TOPLEVEL] = self._selection[TOPLEVEL] + 1
     else:
-      self._selection[0] = 0
-      if printable < len(self._rootEntry.children):
-        self._first[0] = (self._first[0] + printable) % len(self._rootEntry.children)
+      self._selection[TOPLEVEL] = 0
+      if printable < self._rootItem.getChildrenCount():
+        self._first[TOPLEVEL] = (self._first[TOPLEVEL] + printable) % self._rootItem.getChildrenCount()
 
-    if self._first[0] + self._selection[0] == len(self._rootEntry.children):
-      self._first[0] = 0
-      self._selection[0] = 0
+    if self._first[TOPLEVEL] + self._selection[TOPLEVEL] == self._rootItem.getChildrenCount():
+      self._first[TOPLEVEL] = 0
+      self._selection[TOPLEVEL] = 0
 
   def _moveTopLevelLeft(self, width):
     _, printable = self._calculateTopLevelWidths(width)
 
-    if self._selection[0] > 0:
-      self._selection[0] = self._selection[0] - 1
+    if self._selection[TOPLEVEL] > 0:
+      self._selection[TOPLEVEL] = self._selection[TOPLEVEL] - 1
     else:
-      self._first[0] = abs(self._first[0] - printable) % len(self._rootEntry.children)
-      self._selection[0] = len(self._rootEntry.children) - self._first[0] - 1
+      if self._first[TOPLEVEL] == 0:
+        self._first[TOPLEVEL] = (self._rootItem.getChildrenCount() / printable) * printable
+      else:
+        self._first[TOPLEVEL] = abs(self._first[TOPLEVEL] - printable) % self._rootItem.getChildrenCount()
+      self._selection[TOPLEVEL] = self._rootItem.getChildrenCount() - self._first[TOPLEVEL] - 1
 
-    if self._selection[0] > printable:
-      self._selection[0] = printable - 1
+    if self._selection[TOPLEVEL] > printable:
+      self._selection[TOPLEVEL] = printable - 1
 
   def _drawTopLevel(self, popup, width, height):
-    titlewidth, printable = self._calculateTopLevelWidths(width)
-    children = self._rootEntry.children[self._first[0]:self._first[0] + printable]
+    labelwidth, printable = self._calculateTopLevelWidths(width)
+    children = self._rootItem.getChildren()[self._first[TOPLEVEL]:self._first[TOPLEVEL] + printable]
 
     top = 1
     left = 1
-    for (index, entry) in enumerate(children):
-      titleformat = curses.A_STANDOUT if index == self._selection[0] else curses.A_NORMAL
+    for (index, item) in enumerate(children):
+      labelformat = curses.A_STANDOUT if index == self._selection[TOPLEVEL] else curses.A_NORMAL
 
       popup.addch(top, left, curses.ACS_VLINE)
       left = left + 1
-      popup.addstr(top, left, entry.title.center(titlewidth), titleformat)
-      left = left + titlewidth
+      popup.addstr(top, left, item.getLabel().center(labelwidth), labelformat)
+      left = left + labelwidth
 
     popup.addch(top, left, curses.ACS_VLINE)
     left = left + 1
 
   def _handleEvent(self):
-    entry = self._rootEntry
+    item = self._rootItem
     sums = [sum(values) for values in zip(self._first, self._selection)]
 
     for index in sums:
-      if isinstance(entry, ParentEntry):
-        entry = entry.children[index]
+      if item.isParent():
+        item = item.getChildren()[index]
       else:
         break
 
-        log.log(log.ERR, "first: %d" % self._first[0])
-    if isinstance(entry, LeafEntry):
-      entry.callback(entry)
+    if item.isLeaf():
+      item.select()
 
-  def _callbackDefault(self, entry):
-    log.log(log.NOTICE, "%s selected" % entry.title)
+  def _callbackDefault(self, item):
+    log.log(log.NOTICE, "%s selected" % item.getLabel())
 
diff --git a/src/util/menuItem.py b/src/util/menuItem.py
new file mode 100644
index 0000000..4800a0f
--- /dev/null
+++ b/src/util/menuItem.py
@@ -0,0 +1,34 @@
+"""
+Menu Item class, used by the drop-down menus
+"""
+
+class MenuItem():
+  """Contains title, callback handler and possible children"""
+
+  def __init__(self, label=None, callback=None, children=[], parent=None):
+    self._label = label
+    self._callback = callback
+    self._children = children
+    self._parent = parent
+
+  def getLabel(self):
+    return self._label
+
+  def isLeaf(self):
+    return self._children == []
+
+  def isParent(self):
+    return self._children != []
+
+  def getChildren(self):
+    return self._children
+
+  def getParent(self):
+    return self._parent
+
+  def getChildrenCount(self):
+    return len(self._children)
+
+  def select(self):
+    self._callback(self)
+





More information about the tor-commits mailing list