[tor-commits] [arm/release] Added support for multiple menu levels.

atagar at torproject.org atagar at torproject.org
Sun Jul 17 06:08:21 UTC 2011


commit 46a1023c71f395c62a37a30c13e14db7b851640a
Author: Kamran Riaz Khan <krkhan at inspirated.com>
Date:   Tue May 31 02:31:23 2011 +0500

    Added support for multiple menu levels.
    
    Once the menus have "dropped-down", handling of subsequent "levels"
    followed the same logical steps. Therefore *SecondLevel() methods have
    been replaced by *NLevel() equivalents.
    
    If a parent item is selected using any of the selection keys, its
    children are brought up instead of doing nothing.
---
 src/cli/menu.py      |  192 +++++++++++++++++++++++++++++++++++---------------
 src/util/menuItem.py |    6 +--
 2 files changed, 136 insertions(+), 62 deletions(-)

diff --git a/src/cli/menu.py b/src/cli/menu.py
index 69538e0..8ce97c4 100644
--- a/src/cli/menu.py
+++ b/src/cli/menu.py
@@ -8,7 +8,7 @@ import cli.controller
 import popups
 from util import log, panel, uiTools, menuItem
 
-TOPLEVEL, SECONDLEVEL = range(2)
+PARENTLEVEL, TOPLEVEL = (-1, 0)
 
 class Menu():
   """Displays a popup menu and sends keys to appropriate panels"""
@@ -22,23 +22,61 @@ class Menu():
         menuItem.MenuItem(label="Clear"               , callback=self._callbackDefault),
         menuItem.MenuItem(label="Save"                , callback=self._callbackDefault),
         menuItem.MenuItem(label="Filter"              , callback=self._callbackDefault),
-        menuItem.MenuItem(label="Duplicates"          , callback=self._callbackDefault),)),
+        menuItem.MenuItem(label="Duplicates"          , children=(
+          menuItem.MenuItem(label="Hidden"            , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Visible"           , callback=self._callbackDefault),))
+        )),
       menuItem.MenuItem(label="View"          , children=(
         menuItem.MenuItem(label="Graph"               , callback=self._callbackDefault),
         menuItem.MenuItem(label="Connections"         , callback=self._callbackDefault),
         menuItem.MenuItem(label="Configuration"       , callback=self._callbackDefault),
         menuItem.MenuItem(label="Configuration File"  , callback=self._callbackDefault),)),
       menuItem.MenuItem(label="Graph"         , children=(
-        menuItem.MenuItem(label="Stats"               , callback=self._callbackDefault),
-        menuItem.MenuItem(label="Size"                , callback=self._callbackDefault),
-        menuItem.MenuItem(label="Update Interval"     , callback=self._callbackDefault),
-        menuItem.MenuItem(label="Bounds"              , callback=self._callbackDefault),)),
+        menuItem.MenuItem(label="Stats"               , children=(
+          menuItem.MenuItem(label="Bandwidth"         , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Connections"       , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Resources"         , callback=self._callbackDefault),
+        )),
+        menuItem.MenuItem(label="Size"                , children=(
+          menuItem.MenuItem(label="Increase"          , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Decrease"          , callback=self._callbackDefault),
+        )),
+        menuItem.MenuItem(label="Update Interval"     , children=(
+          menuItem.MenuItem(label="Each second"       , callback=self._callbackDefault),
+          menuItem.MenuItem(label="5 seconds"         , callback=self._callbackDefault),
+          menuItem.MenuItem(label="30 seconds"        , callback=self._callbackDefault),
+          menuItem.MenuItem(label="1 minute"          , callback=self._callbackDefault),
+          menuItem.MenuItem(label="30 minutes"        , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Hourly"            , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Daily"             , callback=self._callbackDefault),
+        )),
+        menuItem.MenuItem(label="Bounds"              , children=(
+          menuItem.MenuItem(label="Local Max"         , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Global Max"        , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Tight"             , callback=self._callbackDefault),
+        )),)),
       menuItem.MenuItem(label="Connections"   , children=(
-        menuItem.MenuItem(label="Identity"            , callback=self._callbackDefault),
-        menuItem.MenuItem(label="Resolver"            , callback=self._callbackDefault),
+        menuItem.MenuItem(label="Identity"            , children=(
+          menuItem.MenuItem(label="IP"                , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Fingerprints"      , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Nicknames"             , callback=self._callbackDefault),
+        )),
+        menuItem.MenuItem(label="Resolver"            , children=(
+          menuItem.MenuItem(label="auto"              , callback=self._callbackDefault),
+          menuItem.MenuItem(label="proc"              , callback=self._callbackDefault),
+          menuItem.MenuItem(label="netstat"           , callback=self._callbackDefault),
+          menuItem.MenuItem(label="ss"                , callback=self._callbackDefault),
+          menuItem.MenuItem(label="lsof"              , callback=self._callbackDefault),
+          menuItem.MenuItem(label="sockstat"          , callback=self._callbackDefault),
+          menuItem.MenuItem(label="sockstat (bsd)"    , callback=self._callbackDefault),
+          menuItem.MenuItem(label="procstat (bsd)"    , callback=self._callbackDefault),
+        )),
         menuItem.MenuItem(label="Sort Order"          , callback=self._callbackDefault),)),
       menuItem.MenuItem(label="Configuration" , children=(
-        menuItem.MenuItem(label="Comments"            , callback=self._callbackDefault),
+        menuItem.MenuItem(label="Comments"            , children=(
+          menuItem.MenuItem(label="Hidden"            , callback=self._callbackDefault),
+          menuItem.MenuItem(label="Visible"           , callback=self._callbackDefault),
+        )),
         menuItem.MenuItem(label="Reload"              , callback=self._callbackDefault),
         menuItem.MenuItem(label="Reset Tor"           , callback=self._callbackDefault),))
       ))
@@ -67,15 +105,12 @@ class Menu():
           key = control.getScreen().getch()
 
           if key == curses.KEY_RIGHT:
-            if len(self._selection) == 1:
-              self._moveTopLevelRight(width)
+            self._moveTopLevelRight(width)
           elif key == curses.KEY_LEFT:
-            if len(self._selection) == 1:
-              self._moveTopLevelLeft(width)
+            self._moveTopLevelLeft(width)
           elif key == curses.KEY_DOWN:
-            if len(self._selection) == 1:
-              self._dropSecondLevel()
-              break
+            self._showNLevel()
+            break
           elif uiTools.isSelectionKey(key):
             self._handleEvent()
             break
@@ -87,6 +122,21 @@ class Menu():
     index = self._first[TOPLEVEL] + self._selection[TOPLEVEL]
     return self._rootItem.getChildren()[index]
 
+  def _getCurrentItem(self, level=0):
+    item = self._rootItem
+    if level == 0:
+      sums = [sum(values) for values in zip(self._first, self._selection)]
+    else:
+      sums = [sum(values) for values in zip(self._first[:level], self._selection[:level])]
+
+    for index in sums:
+      if item.isParent():
+        item = item.getChildren()[index]
+      else:
+        break
+
+    return item
+
   def _calculateTopLevelWidths(self, width=0):
     labels = [menuItem.getLabel() for menuItem in self._rootItem.getChildren()]
 
@@ -119,6 +169,33 @@ class Menu():
 
     return printable if printable else parent.getChildrenCount()
 
+  def _calculateNLevelWidths(self, level=0):
+    parent = self._getCurrentItem(level)
+
+    if parent.isLeaf():
+      return 0
+
+    labels = [menuItem.getLabel() for menuItem in parent.getChildren()]
+
+    labelwidth = max(map(len, labels))
+
+    return labelwidth
+
+  def _calculateNLevelHeights(self, height=0, level=0):
+    control = cli.controller.getController()
+    height, _ = control.getScreen().getmaxyx()
+    topSize = sum(stickyPanel.getHeight() for stickyPanel in control.getStickyPanels())
+    height = height - topSize
+
+    parent = self._getCurrentItem(level)
+
+    if parent.isLeaf():
+      return 0
+
+    printable = min(height - 4, parent.getChildrenCount())
+
+    return printable if printable else parent.getChildrenCount()
+
   def _moveTopLevelRight(self, width):
     _, printable = self._calculateTopLevelWidths(width)
 
@@ -165,12 +242,17 @@ class Menu():
     popup.addch(top, left, curses.ACS_VLINE)
     left = left + 1
 
-  def _dropSecondLevel(self):
+  def _showNLevel(self):
     self._first.append(0)
     self._selection.append(0)
 
-    labelwidth = self._calculateSecondLevelWidths()
-    printable = self._calculateSecondLevelHeights()
+    parent = self._getCurrentItem(level=PARENTLEVEL)
+
+    if parent.isLeaf():
+      return
+
+    labelwidth = self._calculateNLevelWidths(level=PARENTLEVEL)
+    printable = self._calculateNLevelHeights(level=PARENTLEVEL)
 
     toplabelwidth, _ = self._calculateTopLevelWidths()
     left = (toplabelwidth + 2) * self._selection[TOPLEVEL]
@@ -183,7 +265,7 @@ class Menu():
           popup.win.erase()
           popup.win.box()
 
-          self._drawSecondLevel(popup, width, height)
+          self._drawNLevel(popup, width, height)
 
           popup.win.refresh()
 
@@ -191,9 +273,12 @@ class Menu():
           key = control.getScreen().getch()
 
           if key == curses.KEY_DOWN:
-              self._moveSecondLevelDown(height)
+            self._moveNLevelDown(height)
           elif key == curses.KEY_UP:
-              self._moveSecondLevelUp(height)
+            self._moveNLevelUp(height)
+          elif key == curses.KEY_RIGHT:
+            self._showNLevel()
+            break
           elif uiTools.isSelectionKey(key):
             self._handleEvent()
             self._first.pop()
@@ -203,64 +288,57 @@ class Menu():
       finally:
         popups.finalize()
 
-  def _drawSecondLevel(self, popup, width, height):
-    printable = self._calculateSecondLevelHeights()
-    parent = self._getCurrentTopLevelItem()
-    children = parent.getChildren()[self._first[SECONDLEVEL]:self._first[SECONDLEVEL] + printable]
-
-    toplabelwidth, _ = self._calculateTopLevelWidths(width)
+  def _drawNLevel(self, popup, width, height):
+    printable = self._calculateNLevelHeights(level=PARENTLEVEL)
+    parent = self._getCurrentItem(level=PARENTLEVEL)
+    children = parent.getChildren()[self._first[PARENTLEVEL]:self._first[PARENTLEVEL] + printable]
 
     top = 1
     left = 1
     for (index, item) in enumerate(children):
-      labelformat = curses.A_STANDOUT if index == self._selection[SECONDLEVEL] else curses.A_NORMAL
+      labelformat = curses.A_STANDOUT if index == self._selection[PARENTLEVEL] else curses.A_NORMAL
 
       popup.addstr(top, left, item.getLabel(), labelformat)
       top = top + 1
 
-  def _moveSecondLevelDown(self, height):
-    printable = self._calculateSecondLevelHeights()
-    parent = self._getCurrentTopLevelItem()
+  def _moveNLevelDown(self, height):
+    printable = self._calculateNLevelHeights(level=PARENTLEVEL)
+    parent = self._getCurrentItem(level=PARENTLEVEL)
 
-    if self._selection[SECONDLEVEL] < printable - 1:
-      self._selection[SECONDLEVEL] = self._selection[SECONDLEVEL] + 1
+    if self._selection[PARENTLEVEL] < printable - 1:
+      self._selection[PARENTLEVEL] = self._selection[PARENTLEVEL] + 1
     else:
-      self._selection[SECONDLEVEL] = 0
+      self._selection[PARENTLEVEL] = 0
       if printable < parent.getChildrenCount():
-        self._first[SECONDLEVEL] = (self._first[SECONDLEVEL] + printable) % parent.getChildrenCount()
+        self._first[PARENTLEVEL] = (self._first[PARENTLEVEL] + printable) % parent.getChildrenCount()
 
-    if self._first[SECONDLEVEL] + self._selection[SECONDLEVEL] == parent.getChildrenCount():
-      self._first[SECONDLEVEL] = 0
-      self._selection[SECONDLEVEL] = 0
+    if self._first[PARENTLEVEL] + self._selection[PARENTLEVEL] == parent.getChildrenCount():
+      self._first[PARENTLEVEL] = 0
+      self._selection[PARENTLEVEL] = 0
 
-  def _moveSecondLevelUp(self, height):
+  def _moveNLevelUp(self, height):
     printable = self._calculateSecondLevelHeights()
-    parent = self._getCurrentTopLevelItem()
+    parent = self._getCurrentItem(level=PARENTLEVEL)
 
-    if self._selection[SECONDLEVEL] > 0:
-      self._selection[SECONDLEVEL] = self._selection[SECONDLEVEL] - 1
+    if self._selection[PARENTLEVEL] > 0:
+      self._selection[PARENTLEVEL] = self._selection[PARENTLEVEL] - 1
     else:
-      if self._first[SECONDLEVEL] == 0:
-        self._first[SECONDLEVEL] = ((parent.getChildrenCount() / printable) * printable) % parent.getChildrenCount()
+      if self._first[PARENTLEVEL] == 0:
+        self._first[PARENTLEVEL] = ((parent.getChildrenCount() / printable) * printable) % parent.getChildrenCount()
       else:
-        self._first[SECONDLEVEL] = abs(self._first[SECONDLEVEL] - printable) % parent.getChildrenCount()
-      self._selection[SECONDLEVEL] = parent.getChildrenCount() - self._first[SECONDLEVEL] - 1
+        self._first[PARENTLEVEL] = abs(self._first[PARENTLEVEL] - printable) % parent.getChildrenCount()
+      self._selection[PARENTLEVEL] = parent.getChildrenCount() - self._first[PARENTLEVEL] - 1
 
-    if self._selection[SECONDLEVEL] > printable:
-      self._selection[SECONDLEVEL] = printable - 1
+    if self._selection[PARENTLEVEL] > printable:
+      self._selection[PARENTLEVEL] = printable - 1
 
   def _handleEvent(self):
-    item = self._rootItem
-    sums = [sum(values) for values in zip(self._first, self._selection)]
-
-    for index in sums:
-      if item.isParent():
-        item = item.getChildren()[index]
-      else:
-        break
+    item = self._getCurrentItem()
 
     if item.isLeaf():
       item.select()
+    else:
+      self._showNLevel()
 
   def _callbackDefault(self, item):
     log.log(log.NOTICE, "%s selected" % item.getLabel())
diff --git a/src/util/menuItem.py b/src/util/menuItem.py
index 4800a0f..3dbf922 100644
--- a/src/util/menuItem.py
+++ b/src/util/menuItem.py
@@ -5,11 +5,10 @@ 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):
+  def __init__(self, label=None, callback=None, children=[]):
     self._label = label
     self._callback = callback
     self._children = children
-    self._parent = parent
 
   def getLabel(self):
     return self._label
@@ -23,9 +22,6 @@ class MenuItem():
   def getChildren(self):
     return self._children
 
-  def getParent(self):
-    return self._parent
-
   def getChildrenCount(self):
     return len(self._children)
 





More information about the tor-commits mailing list