[tor-commits] [arm/release] Moving Kamran's menu to avoid namespace conflicts
atagar at torproject.org
atagar at torproject.org
Sun Jul 17 06:08:22 UTC 2011
commit 856226d684220b746b44c2f44a1c3d3d03f8384b
Author: Damian Johnson <atagar at torproject.org>
Date: Sat Jun 4 14:05:23 2011 -0700
Moving Kamran's menu to avoid namespace conflicts
My 'src/cli/menu' module was conflicting with his 'src/cli/menu.py' class so
I've moved his implementation to 'src/cli/menu_alt'.
---
src/cli/__init__.py | 2 +-
src/cli/controller.py | 6 +-
src/cli/menu.py | 438 -----------------------------------------
src/cli/menu_alt/__init__.py | 6 +
src/cli/menu_alt/menu.py | 439 ++++++++++++++++++++++++++++++++++++++++++
src/cli/menu_alt/menuItem.py | 41 ++++
src/util/menuItem.py | 41 ----
7 files changed, 490 insertions(+), 483 deletions(-)
diff --git a/src/cli/__init__.py b/src/cli/__init__.py
index 81fabeb..1564f68 100644
--- a/src/cli/__init__.py
+++ b/src/cli/__init__.py
@@ -2,5 +2,5 @@
Panels, popups, and handlers comprising the arm user interface.
"""
-__all__ = ["configPanel", "controller", "descriptorPopup", "headerPanel", "logPanel", "menu", "popups", "torrcPanel"]
+__all__ = ["configPanel", "controller", "descriptorPopup", "headerPanel", "logPanel", "popups", "torrcPanel"]
diff --git a/src/cli/controller.py b/src/cli/controller.py
index fac43a4..997d9d3 100644
--- a/src/cli/controller.py
+++ b/src/cli/controller.py
@@ -7,8 +7,8 @@ import time
import curses
import threading
-import cli.menu
import cli.menu.menu
+import cli.menu_alt.menu
import cli.popups
import cli.headerPanel
import cli.logPanel
@@ -512,10 +512,10 @@ def drawTorMonitor(stdscr, startTime):
elif key == ord('p') or key == ord('P'):
control.setPaused(not control.isPaused())
elif key == ord('n') or key == ord('N'):
- menu = cli.menu.Menu()
+ menu = cli.menu_alt.menu.Menu()
menuKeys = menu.showMenu(keys=menuKeys)
if menuKeys != []:
- for key in (ord('m'), ord('q'), ord('x')):
+ for key in (ord('n'), ord('q'), ord('x')):
if key in menuKeys:
menuKeys.remove(key)
overrideKey = key
diff --git a/src/cli/menu.py b/src/cli/menu.py
deleted file mode 100644
index 47e8d09..0000000
--- a/src/cli/menu.py
+++ /dev/null
@@ -1,438 +0,0 @@
-"""
-A drop-down menu for sending actions to panels.
-"""
-
-import curses
-
-import cli.controller
-import popups
-
-from cli.graphing.graphPanel import Bounds as GraphBounds
-from util import log, panel, uiTools, menuItem
-
-PARENTLEVEL, TOPLEVEL = (-1, 0)
-
-class Menu():
- """Displays a popup menu and sends keys to appropriate panels"""
-
- def __init__(self, item=None):
- DEFAULT_ROOT = menuItem.MenuItem(label="Root", children=(
- menuItem.MenuItem(label="File", children=(
- menuItem.MenuItem(label="Exit",
- callback=lambda item: self._callbackReturnKey(ord('q'))),)),
- menuItem.MenuItem(label="Logs", children=(
- menuItem.MenuItem(label="Events",
- callback=lambda item: self._callbackPressKey('log', ord('e'))),
- menuItem.MenuItem(label="Clear",
- callback=lambda item: self._callbackPressKey('log', ord('c'))),
- menuItem.MenuItem(label="Save",
- callback=lambda item: self._callbackPressKey('log', ord('a'))),
- menuItem.MenuItem(label="Filter",
- callback=lambda item: self._callbackPressKey('log', ord('f'))),
- menuItem.MenuItem(label="Duplicates", children=(
- menuItem.MenuItem(label="Hidden",
- callback=lambda item: self._callbackSet('log', 'showDuplicates', False, ord('u')),
- enabled=lambda: self._getItemEnabled('log', 'showDuplicates', False)),
- menuItem.MenuItem(label="Visible",
- callback=lambda item: self._callbackSet('log', 'showDuplicates', True, ord('u')),
- enabled=lambda: self._getItemEnabled('log', 'showDuplicates', True)),
- )))),
- menuItem.MenuItem(label="View", children=(
- menuItem.MenuItem(label="Graph",
- callback=lambda item: self._callbackView('graph')),
- menuItem.MenuItem(label="Connections",
- callback=lambda item: self._callbackView('conn')),
- menuItem.MenuItem(label="Configuration",
- callback=lambda item: self._callbackView('configState')),
- menuItem.MenuItem(label="Configuration File",
- callback=lambda item: self._callbackView('configFile')),)),
- menuItem.MenuItem(label="Graph", children=(
- menuItem.MenuItem(label="Stats",
- callback=lambda item: self._callbackPressKey('graph', ord('s'))),
- menuItem.MenuItem(label="Size", children=(
- menuItem.MenuItem(label="Increase",
- callback=lambda item: self._callbackPressKey('graph', ord('m'))),
- menuItem.MenuItem(label="Decrease",
- callback=lambda item: self._callbackPressKey('graph', ord('n'))),
- )),
- menuItem.MenuItem(label="Update Interval",
- callback=lambda item: self._callbackPressKey('graph', ord('i'))),
- menuItem.MenuItem(label="Bounds", children=(
- menuItem.MenuItem(label="Local Max",
- callback=lambda item: self._callbackSet('graph', 'bounds', GraphBounds.LOCAL_MAX, ord('b')),
- enabled=lambda: self._getItemEnabled('graph', 'bounds', GraphBounds.LOCAL_MAX)),
- menuItem.MenuItem(label="Global Max",
- callback=lambda item: self._callbackSet('graph', 'bounds', GraphBounds.GLOBAL_MAX, ord('b')),
- enabled=lambda: self._getItemEnabled('graph', 'bounds', GraphBounds.GLOBAL_MAX)),
- menuItem.MenuItem(label="Tight",
- callback=lambda item: self._callbackSet('graph', 'bounds', GraphBounds.TIGHT, ord('b')),
- enabled=lambda: self._getItemEnabled('graph', 'bounds', GraphBounds.TIGHT)),
- )),)),
- menuItem.MenuItem(label="Connections", children=(
- menuItem.MenuItem(label="Identity",
- callback=lambda item: self._callbackPressKey('conn', ord('l'))),
- menuItem.MenuItem(label="Resolver",
- callback=lambda item: self._callbackPressKey('conn', ord('u'))),
- menuItem.MenuItem(label="Sort Order",
- callback=lambda item: self._callbackPressKey('conn', ord('s'))),
- )),
- menuItem.MenuItem(label="Configuration" , children=(
- menuItem.MenuItem(label="Comments", children=(
- menuItem.MenuItem(label="Hidden",
- callback=lambda item: self._callbackSet('configFile', 'stripComments', True, ord('s')),
- enabled=lambda: self._getItemEnabled('configFile', 'stripComments', True)),
- menuItem.MenuItem(label="Visible",
- callback=lambda item: self._callbackSet('configFile', 'stripComments', False, ord('s')),
- enabled=lambda: self._getItemEnabled('configFile', 'stripComments', False)),
- )),
- menuItem.MenuItem(label="Reload",
- callback=lambda item: self._callbackPressKey('configFile', ord('r'))),
- menuItem.MenuItem(label="Reset Tor",
- callback=lambda item: self._callbackReturnKey(ord('x'))),))
- ))
-
- self._first = [0]
- self._selection = [0]
-
- if item and item.isParent():
- self._rootItem = item
- else:
- self._rootItem = DEFAULT_ROOT
-
- def showMenu(self, keys=[]):
- keys.reverse()
- returnkeys = []
-
- popup, width, height = popups.init(height=3)
- if popup:
- try:
- while True:
- popup.win.erase()
- popup.win.box()
-
- self._drawTopLevel(popup, width, height)
-
- popup.win.refresh()
-
- control = cli.controller.getController()
-
- if keys == []:
- key = control.getScreen().getch()
- else:
- key = keys.pop()
-
- if key == curses.KEY_RIGHT:
- self._moveTopLevelRight(width)
- elif key == curses.KEY_LEFT:
- self._moveTopLevelLeft(width)
- elif key == curses.KEY_DOWN:
- cascaded, returnkeys = self._cascadeNLevel()
- break
- elif key == 27:
- break
- elif uiTools.isSelectionKey(key):
- self._handleEvent()
- break
-
- finally:
- popups.finalize()
-
- return returnkeys
-
- def _appendLevel(self):
- self._first.append(0)
- self._selection.append(0)
-
- def _removeLevel(self):
- self._first.pop()
- self._selection.pop()
-
- def _getCurrentTopLevelItem(self):
- 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()]
-
- # width per label is set according to the longest label
- labelwidth = max(map(len, labels)) + 2
-
- # total number of labels that can be printed in supplied width
- printable = min(width / labelwidth - 1, self._rootItem.getChildrenCount())
-
- return (labelwidth, printable)
-
- 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)
-
- if self._selection[TOPLEVEL] < printable - 1:
- self._selection[TOPLEVEL] = self._selection[TOPLEVEL] + 1
- else:
- self._selection[TOPLEVEL] = 0
- if printable < self._rootItem.getChildrenCount():
- self._first[TOPLEVEL] = (self._first[TOPLEVEL] + printable) % self._rootItem.getChildrenCount()
-
- 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[TOPLEVEL] > 0:
- self._selection[TOPLEVEL] = self._selection[TOPLEVEL] - 1
- else:
- if self._first[TOPLEVEL] == 0:
- self._first[TOPLEVEL] = ((self._rootItem.getChildrenCount() / printable) * printable) % self._rootItem.getChildrenCount()
- 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[TOPLEVEL] > printable:
- self._selection[TOPLEVEL] = printable - 1
-
- def _drawTopLevel(self, popup, width, height):
- labelwidth, printable = self._calculateTopLevelWidths(width)
- children = self._rootItem.getChildren()[self._first[TOPLEVEL]:self._first[TOPLEVEL] + printable]
-
- top = 1
- left = 1
- 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, item.getLabel().center(labelwidth), labelformat)
- left = left + labelwidth
-
- popup.addch(top, left, curses.ACS_VLINE)
- left = left + 1
-
- def _cascadeNLevel(self):
- parent = self._getCurrentItem()
-
- if parent.isLeaf():
- return (False, [])
-
- self._appendLevel()
-
- labelwidth = self._calculateNLevelWidths(level=PARENTLEVEL)
- printable = self._calculateNLevelHeights(level=PARENTLEVEL)
-
- toplabelwidth, _ = self._calculateTopLevelWidths()
- left = (toplabelwidth + 2) * self._selection[TOPLEVEL]
-
- popup, width, height = popups.init(height=printable+2, width=labelwidth+2, top=2, left=left)
-
- while self._getCurrentItem().isEnabled() == False:
- self._moveNLevelDown(height)
-
- if popup.win:
- returnkeys = []
- try:
- while True:
- popup.win.erase()
- popup.win.box()
-
- self._drawNLevel(popup, width, height)
-
- popup.win.refresh()
-
- control = cli.controller.getController()
- key = control.getScreen().getch()
-
- if key == curses.KEY_DOWN:
- self._moveNLevelDown(height)
- elif key == curses.KEY_UP:
- self._moveNLevelUp(height)
- elif key == curses.KEY_RIGHT:
- cascaded, returnkeys = self._cascadeNLevel()
- if cascaded == False:
- index = self._first[TOPLEVEL] + self._selection[TOPLEVEL] + 1
- returnkeys.append(ord('m'))
- for i in range(index):
- returnkeys.append(curses.KEY_RIGHT)
- returnkeys.append(curses.KEY_DOWN)
- break
- elif key == curses.KEY_LEFT:
- index = self._first[TOPLEVEL] + self._selection[TOPLEVEL] - 1
- index = index % self._rootItem.getChildrenCount()
- returnkeys.append(ord('m'))
- for i in range(index):
- returnkeys.append(curses.KEY_RIGHT)
- returnkeys.append(curses.KEY_DOWN)
- break
- elif key == 27:
- self._removeLevel()
- break
- elif uiTools.isSelectionKey(key):
- returnkey = self._handleEvent()
- if returnkey:
- returnkeys.append(returnkey)
- self._removeLevel()
- break
-
- finally:
- popups.finalize()
-
- return (True, returnkeys)
-
- return (False, [])
-
- 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[PARENTLEVEL] else curses.A_NORMAL
-
- if not item.isEnabled():
- labelformat = labelformat | uiTools.getColor('yellow')
-
- popup.addstr(top, left, item.getLabel(), labelformat)
- top = top + 1
-
- def _moveNLevelDown(self, height):
- printable = self._calculateNLevelHeights(level=PARENTLEVEL)
- parent = self._getCurrentItem(level=PARENTLEVEL)
-
- if self._selection[PARENTLEVEL] < printable - 1:
- self._selection[PARENTLEVEL] = self._selection[PARENTLEVEL] + 1
- else:
- self._selection[PARENTLEVEL] = 0
- if printable < parent.getChildrenCount():
- self._first[PARENTLEVEL] = (self._first[PARENTLEVEL] + printable) % parent.getChildrenCount()
-
- if self._first[PARENTLEVEL] + self._selection[PARENTLEVEL] == parent.getChildrenCount():
- self._first[PARENTLEVEL] = 0
- self._selection[PARENTLEVEL] = 0
-
- while self._getCurrentItem().isEnabled() == False:
- self._moveNLevelDown(height)
-
- def _moveNLevelUp(self, height):
- printable = self._calculateNLevelHeights(level=PARENTLEVEL)
- parent = self._getCurrentItem(level=PARENTLEVEL)
-
- if self._selection[PARENTLEVEL] > 0:
- self._selection[PARENTLEVEL] = self._selection[PARENTLEVEL] - 1
- else:
- if self._first[PARENTLEVEL] == 0:
- self._first[PARENTLEVEL] = ((parent.getChildrenCount() / printable) * printable) % parent.getChildrenCount()
- else:
- self._first[PARENTLEVEL] = abs(self._first[PARENTLEVEL] - printable) % parent.getChildrenCount()
- self._selection[PARENTLEVEL] = parent.getChildrenCount() - self._first[PARENTLEVEL] - 1
-
- if self._selection[PARENTLEVEL] > printable:
- self._selection[PARENTLEVEL] = printable - 1
-
- while self._getCurrentItem().isEnabled() == False:
- self._moveNLevelUp(height)
-
- def _handleEvent(self):
- item = self._getCurrentItem()
-
- if item.isLeaf():
- return item.select()
- else:
- self._cascadeNLevel()
-
- def _callbackDefault(self, item):
- log.log(log.NOTICE, "%s selected" % item.getLabel())
-
- def _callbackView(self, panelname):
- control = cli.controller.getController()
-
- start = control.getPage()
- panels = control.getDisplayPanels(includeSticky=False)
- panelnames = [panel.getName() for panel in panels]
- while not panelname in panelnames:
- control.nextPage()
- panels = control.getDisplayPanels(includeSticky=False)
- panelnames = [panel.getName() for panel in panels]
-
- if control.getPage() == start:
- log.log(log.ERR, "Panel %s not found" % panelname)
- break
-
- def _getItemEnabled(self, panel, attr, value):
- control = cli.controller.getController()
- if control:
- panel = control.getPanel(panel)
-
- if panel:
- return getattr(panel, attr, None) != value
-
- return False
-
- def _callbackSet(self, panel, attr, value, key=None):
- control = cli.controller.getController()
- panel = control.getPanel(panel)
-
- panelattr = getattr(panel, attr, None)
-
- if panelattr != None:
- if hasattr(panelattr, '__call__'):
- panelattr(value)
- elif panelattr != value and key != None:
- start = panelattr
- while panelattr != value:
- panel.handleKey(key)
- panelattr = getattr(panel, attr, None)
- if panelattr == start:
- log.log(log.ERR, "Could not set %s.%s" % (panel, attr))
- break
-
- def _callbackPressKey(self, panel, key):
- control = cli.controller.getController()
- panel = control.getPanel(panel)
- panel.handleKey(key)
-
- def _callbackReturnKey(self, key):
- return key
-
diff --git a/src/cli/menu_alt/__init__.py b/src/cli/menu_alt/__init__.py
new file mode 100644
index 0000000..6d7b6b7
--- /dev/null
+++ b/src/cli/menu_alt/__init__.py
@@ -0,0 +1,6 @@
+"""
+Resources for displaying the menu.
+"""
+
+__all__ = ["menuItem", "menu"]
+
diff --git a/src/cli/menu_alt/menu.py b/src/cli/menu_alt/menu.py
new file mode 100644
index 0000000..7e10366
--- /dev/null
+++ b/src/cli/menu_alt/menu.py
@@ -0,0 +1,439 @@
+"""
+A drop-down menu for sending actions to panels.
+"""
+
+import curses
+
+import cli.controller
+import cli.menu_alt.menuItem as menuItem
+import cli.popups
+
+from cli.graphing.graphPanel import Bounds as GraphBounds
+from util import log, panel, uiTools
+
+PARENTLEVEL, TOPLEVEL = (-1, 0)
+
+class Menu():
+ """Displays a popup menu and sends keys to appropriate panels"""
+
+ def __init__(self, item=None):
+ DEFAULT_ROOT = menuItem.MenuItem(label="Root", children=(
+ menuItem.MenuItem(label="File", children=(
+ menuItem.MenuItem(label="Exit",
+ callback=lambda item: self._callbackReturnKey(ord('q'))),)),
+ menuItem.MenuItem(label="Logs", children=(
+ menuItem.MenuItem(label="Events",
+ callback=lambda item: self._callbackPressKey('log', ord('e'))),
+ menuItem.MenuItem(label="Clear",
+ callback=lambda item: self._callbackPressKey('log', ord('c'))),
+ menuItem.MenuItem(label="Save",
+ callback=lambda item: self._callbackPressKey('log', ord('a'))),
+ menuItem.MenuItem(label="Filter",
+ callback=lambda item: self._callbackPressKey('log', ord('f'))),
+ menuItem.MenuItem(label="Duplicates", children=(
+ menuItem.MenuItem(label="Hidden",
+ callback=lambda item: self._callbackSet('log', 'showDuplicates', False, ord('u')),
+ enabled=lambda: self._getItemEnabled('log', 'showDuplicates', False)),
+ menuItem.MenuItem(label="Visible",
+ callback=lambda item: self._callbackSet('log', 'showDuplicates', True, ord('u')),
+ enabled=lambda: self._getItemEnabled('log', 'showDuplicates', True)),
+ )))),
+ menuItem.MenuItem(label="View", children=(
+ menuItem.MenuItem(label="Graph",
+ callback=lambda item: self._callbackView('graph')),
+ menuItem.MenuItem(label="Connections",
+ callback=lambda item: self._callbackView('conn')),
+ menuItem.MenuItem(label="Configuration",
+ callback=lambda item: self._callbackView('configState')),
+ menuItem.MenuItem(label="Configuration File",
+ callback=lambda item: self._callbackView('configFile')),)),
+ menuItem.MenuItem(label="Graph", children=(
+ menuItem.MenuItem(label="Stats",
+ callback=lambda item: self._callbackPressKey('graph', ord('s'))),
+ menuItem.MenuItem(label="Size", children=(
+ menuItem.MenuItem(label="Increase",
+ callback=lambda item: self._callbackPressKey('graph', ord('m'))),
+ menuItem.MenuItem(label="Decrease",
+ callback=lambda item: self._callbackPressKey('graph', ord('n'))),
+ )),
+ menuItem.MenuItem(label="Update Interval",
+ callback=lambda item: self._callbackPressKey('graph', ord('i'))),
+ menuItem.MenuItem(label="Bounds", children=(
+ menuItem.MenuItem(label="Local Max",
+ callback=lambda item: self._callbackSet('graph', 'bounds', GraphBounds.LOCAL_MAX, ord('b')),
+ enabled=lambda: self._getItemEnabled('graph', 'bounds', GraphBounds.LOCAL_MAX)),
+ menuItem.MenuItem(label="Global Max",
+ callback=lambda item: self._callbackSet('graph', 'bounds', GraphBounds.GLOBAL_MAX, ord('b')),
+ enabled=lambda: self._getItemEnabled('graph', 'bounds', GraphBounds.GLOBAL_MAX)),
+ menuItem.MenuItem(label="Tight",
+ callback=lambda item: self._callbackSet('graph', 'bounds', GraphBounds.TIGHT, ord('b')),
+ enabled=lambda: self._getItemEnabled('graph', 'bounds', GraphBounds.TIGHT)),
+ )),)),
+ menuItem.MenuItem(label="Connections", children=(
+ menuItem.MenuItem(label="Identity",
+ callback=lambda item: self._callbackPressKey('conn', ord('l'))),
+ menuItem.MenuItem(label="Resolver",
+ callback=lambda item: self._callbackPressKey('conn', ord('u'))),
+ menuItem.MenuItem(label="Sort Order",
+ callback=lambda item: self._callbackPressKey('conn', ord('s'))),
+ )),
+ menuItem.MenuItem(label="Configuration" , children=(
+ menuItem.MenuItem(label="Comments", children=(
+ menuItem.MenuItem(label="Hidden",
+ callback=lambda item: self._callbackSet('configFile', 'stripComments', True, ord('s')),
+ enabled=lambda: self._getItemEnabled('configFile', 'stripComments', True)),
+ menuItem.MenuItem(label="Visible",
+ callback=lambda item: self._callbackSet('configFile', 'stripComments', False, ord('s')),
+ enabled=lambda: self._getItemEnabled('configFile', 'stripComments', False)),
+ )),
+ menuItem.MenuItem(label="Reload",
+ callback=lambda item: self._callbackPressKey('configFile', ord('r'))),
+ menuItem.MenuItem(label="Reset Tor",
+ callback=lambda item: self._callbackReturnKey(ord('x'))),))
+ ))
+
+ self._first = [0]
+ self._selection = [0]
+
+ if item and item.isParent():
+ self._rootItem = item
+ else:
+ self._rootItem = DEFAULT_ROOT
+
+ def showMenu(self, keys=[]):
+ keys.reverse()
+ returnkeys = []
+
+ popup, width, height = cli.popups.init(height=3)
+ if popup:
+ try:
+ while True:
+ popup.win.erase()
+ popup.win.box()
+
+ self._drawTopLevel(popup, width, height)
+
+ popup.win.refresh()
+
+ control = cli.controller.getController()
+
+ if keys == []:
+ key = control.getScreen().getch()
+ else:
+ key = keys.pop()
+
+ if key == curses.KEY_RIGHT:
+ self._moveTopLevelRight(width)
+ elif key == curses.KEY_LEFT:
+ self._moveTopLevelLeft(width)
+ elif key == curses.KEY_DOWN:
+ cascaded, returnkeys = self._cascadeNLevel()
+ break
+ elif key == 27:
+ break
+ elif uiTools.isSelectionKey(key):
+ self._handleEvent()
+ break
+
+ finally:
+ cli.popups.finalize()
+
+ return returnkeys
+
+ def _appendLevel(self):
+ self._first.append(0)
+ self._selection.append(0)
+
+ def _removeLevel(self):
+ self._first.pop()
+ self._selection.pop()
+
+ def _getCurrentTopLevelItem(self):
+ 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()]
+
+ # width per label is set according to the longest label
+ labelwidth = max(map(len, labels)) + 2
+
+ # total number of labels that can be printed in supplied width
+ printable = min(width / labelwidth - 1, self._rootItem.getChildrenCount())
+
+ return (labelwidth, printable)
+
+ 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)
+
+ if self._selection[TOPLEVEL] < printable - 1:
+ self._selection[TOPLEVEL] = self._selection[TOPLEVEL] + 1
+ else:
+ self._selection[TOPLEVEL] = 0
+ if printable < self._rootItem.getChildrenCount():
+ self._first[TOPLEVEL] = (self._first[TOPLEVEL] + printable) % self._rootItem.getChildrenCount()
+
+ 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[TOPLEVEL] > 0:
+ self._selection[TOPLEVEL] = self._selection[TOPLEVEL] - 1
+ else:
+ if self._first[TOPLEVEL] == 0:
+ self._first[TOPLEVEL] = ((self._rootItem.getChildrenCount() / printable) * printable) % self._rootItem.getChildrenCount()
+ 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[TOPLEVEL] > printable:
+ self._selection[TOPLEVEL] = printable - 1
+
+ def _drawTopLevel(self, popup, width, height):
+ labelwidth, printable = self._calculateTopLevelWidths(width)
+ children = self._rootItem.getChildren()[self._first[TOPLEVEL]:self._first[TOPLEVEL] + printable]
+
+ top = 1
+ left = 1
+ 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, item.getLabel().center(labelwidth), labelformat)
+ left = left + labelwidth
+
+ popup.addch(top, left, curses.ACS_VLINE)
+ left = left + 1
+
+ def _cascadeNLevel(self):
+ parent = self._getCurrentItem()
+
+ if parent.isLeaf():
+ return (False, [])
+
+ self._appendLevel()
+
+ labelwidth = self._calculateNLevelWidths(level=PARENTLEVEL)
+ printable = self._calculateNLevelHeights(level=PARENTLEVEL)
+
+ toplabelwidth, _ = self._calculateTopLevelWidths()
+ left = (toplabelwidth + 2) * self._selection[TOPLEVEL]
+
+ popup, width, height = cli.popups.init(height=printable+2, width=labelwidth+2, top=2, left=left)
+
+ while self._getCurrentItem().isEnabled() == False:
+ self._moveNLevelDown(height)
+
+ if popup.win:
+ returnkeys = []
+ try:
+ while True:
+ popup.win.erase()
+ popup.win.box()
+
+ self._drawNLevel(popup, width, height)
+
+ popup.win.refresh()
+
+ control = cli.controller.getController()
+ key = control.getScreen().getch()
+
+ if key == curses.KEY_DOWN:
+ self._moveNLevelDown(height)
+ elif key == curses.KEY_UP:
+ self._moveNLevelUp(height)
+ elif key == curses.KEY_RIGHT:
+ cascaded, returnkeys = self._cascadeNLevel()
+ if cascaded == False:
+ index = self._first[TOPLEVEL] + self._selection[TOPLEVEL] + 1
+ returnkeys.append(ord('n'))
+ for i in range(index):
+ returnkeys.append(curses.KEY_RIGHT)
+ returnkeys.append(curses.KEY_DOWN)
+ break
+ elif key == curses.KEY_LEFT:
+ index = self._first[TOPLEVEL] + self._selection[TOPLEVEL] - 1
+ index = index % self._rootItem.getChildrenCount()
+ returnkeys.append(ord('n'))
+ for i in range(index):
+ returnkeys.append(curses.KEY_RIGHT)
+ returnkeys.append(curses.KEY_DOWN)
+ break
+ elif key == 27:
+ self._removeLevel()
+ break
+ elif uiTools.isSelectionKey(key):
+ returnkey = self._handleEvent()
+ if returnkey:
+ returnkeys.append(returnkey)
+ self._removeLevel()
+ break
+
+ finally:
+ cli.popups.finalize()
+
+ return (True, returnkeys)
+
+ return (False, [])
+
+ 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[PARENTLEVEL] else curses.A_NORMAL
+
+ if not item.isEnabled():
+ labelformat = labelformat | uiTools.getColor('yellow')
+
+ popup.addstr(top, left, item.getLabel(), labelformat)
+ top = top + 1
+
+ def _moveNLevelDown(self, height):
+ printable = self._calculateNLevelHeights(level=PARENTLEVEL)
+ parent = self._getCurrentItem(level=PARENTLEVEL)
+
+ if self._selection[PARENTLEVEL] < printable - 1:
+ self._selection[PARENTLEVEL] = self._selection[PARENTLEVEL] + 1
+ else:
+ self._selection[PARENTLEVEL] = 0
+ if printable < parent.getChildrenCount():
+ self._first[PARENTLEVEL] = (self._first[PARENTLEVEL] + printable) % parent.getChildrenCount()
+
+ if self._first[PARENTLEVEL] + self._selection[PARENTLEVEL] == parent.getChildrenCount():
+ self._first[PARENTLEVEL] = 0
+ self._selection[PARENTLEVEL] = 0
+
+ while self._getCurrentItem().isEnabled() == False:
+ self._moveNLevelDown(height)
+
+ def _moveNLevelUp(self, height):
+ printable = self._calculateNLevelHeights(level=PARENTLEVEL)
+ parent = self._getCurrentItem(level=PARENTLEVEL)
+
+ if self._selection[PARENTLEVEL] > 0:
+ self._selection[PARENTLEVEL] = self._selection[PARENTLEVEL] - 1
+ else:
+ if self._first[PARENTLEVEL] == 0:
+ self._first[PARENTLEVEL] = ((parent.getChildrenCount() / printable) * printable) % parent.getChildrenCount()
+ else:
+ self._first[PARENTLEVEL] = abs(self._first[PARENTLEVEL] - printable) % parent.getChildrenCount()
+ self._selection[PARENTLEVEL] = parent.getChildrenCount() - self._first[PARENTLEVEL] - 1
+
+ if self._selection[PARENTLEVEL] > printable:
+ self._selection[PARENTLEVEL] = printable - 1
+
+ while self._getCurrentItem().isEnabled() == False:
+ self._moveNLevelUp(height)
+
+ def _handleEvent(self):
+ item = self._getCurrentItem()
+
+ if item.isLeaf():
+ return item.select()
+ else:
+ self._cascadeNLevel()
+
+ def _callbackDefault(self, item):
+ log.log(log.NOTICE, "%s selected" % item.getLabel())
+
+ def _callbackView(self, panelname):
+ control = cli.controller.getController()
+
+ start = control.getPage()
+ panels = control.getDisplayPanels(includeSticky=False)
+ panelnames = [panel.getName() for panel in panels]
+ while not panelname in panelnames:
+ control.nextPage()
+ panels = control.getDisplayPanels(includeSticky=False)
+ panelnames = [panel.getName() for panel in panels]
+
+ if control.getPage() == start:
+ log.log(log.ERR, "Panel %s not found" % panelname)
+ break
+
+ def _getItemEnabled(self, panel, attr, value):
+ control = cli.controller.getController()
+ if control:
+ panel = control.getPanel(panel)
+
+ if panel:
+ return getattr(panel, attr, None) != value
+
+ return False
+
+ def _callbackSet(self, panel, attr, value, key=None):
+ control = cli.controller.getController()
+ panel = control.getPanel(panel)
+
+ panelattr = getattr(panel, attr, None)
+
+ if panelattr != None:
+ if hasattr(panelattr, '__call__'):
+ panelattr(value)
+ elif panelattr != value and key != None:
+ start = panelattr
+ while panelattr != value:
+ panel.handleKey(key)
+ panelattr = getattr(panel, attr, None)
+ if panelattr == start:
+ log.log(log.ERR, "Could not set %s.%s" % (panel, attr))
+ break
+
+ def _callbackPressKey(self, panel, key):
+ control = cli.controller.getController()
+ panel = control.getPanel(panel)
+ panel.handleKey(key)
+
+ def _callbackReturnKey(self, key):
+ return key
+
diff --git a/src/cli/menu_alt/menuItem.py b/src/cli/menu_alt/menuItem.py
new file mode 100644
index 0000000..277c78a
--- /dev/null
+++ b/src/cli/menu_alt/menuItem.py
@@ -0,0 +1,41 @@
+"""
+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=[], enabled=None):
+ self._label = label
+ self._callback = callback
+ self._children = children
+ self._enabled = enabled
+
+ def getLabel(self):
+ return self._label
+
+ def isLeaf(self):
+ return self._children == []
+
+ def isParent(self):
+ return self._children != []
+
+ def isEnabled(self):
+ if self._enabled == None:
+ return True
+ elif hasattr(self._enabled, '__call__'):
+ return self._enabled()
+ else:
+ return self._enabled
+
+ def getChildren(self):
+ return self._children
+
+ def getChildrenCount(self):
+ return len(self._children)
+
+ def select(self):
+ return self._callback(self)
+
diff --git a/src/util/menuItem.py b/src/util/menuItem.py
deleted file mode 100644
index 277c78a..0000000
--- a/src/util/menuItem.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"""
-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=[], enabled=None):
- self._label = label
- self._callback = callback
- self._children = children
- self._enabled = enabled
-
- def getLabel(self):
- return self._label
-
- def isLeaf(self):
- return self._children == []
-
- def isParent(self):
- return self._children != []
-
- def isEnabled(self):
- if self._enabled == None:
- return True
- elif hasattr(self._enabled, '__call__'):
- return self._enabled()
- else:
- return self._enabled
-
- def getChildren(self):
- return self._children
-
- def getChildrenCount(self):
- return len(self._children)
-
- def select(self):
- return self._callback(self)
-
More information about the tor-commits
mailing list