forked from HackerShackOfficial/Smart-Bartender
-
Notifications
You must be signed in to change notification settings - Fork 7
/
menu.py
129 lines (107 loc) · 3.42 KB
/
menu.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# menu.py
class MenuItem(object):
def __init__(self, type, name, attributes = None, visible = True):
self.type = type
self.name = name
self.attributes = attributes
self.visible = visible
class Back(MenuItem):
def __init__(self, name):
MenuItem.__init__(self, "back", name)
class Menu(MenuItem):
def __init__(self, name, attributes = None, visible = True):
MenuItem.__init__(self, "menu", name, attributes, visible)
self.options = []
self.selectedOption = 0
self.parent = None
def addOptions(self, options):
self.options = self.options + options
self.selectedOption = 0
def addOption(self, option):
self.options.append(option)
self.selectedOption = 0
def setParent(self, parent):
self.parent = parent
def nextSelection(self):
self.selectedOption = (self.selectedOption + 1) % len(self.options)
def getSelection(self):
return self.options[self.selectedOption]
class MenuContext(object):
def __init__(self, menu, delegate):
self.topLevelMenu = menu
self.currentMenu = menu
self.delegate = delegate
self.showMenu()
def showMenu(self):
"""
Shows the first selection of the current menu
"""
self.display(self.currentMenu.getSelection());
def setMenu(self, menu):
"""
Sets a new menu to the menu context.
raises ValueError if the menu has no options
"""
if (len(menu.options) == 0):
raise ValueError("Cannot setMenu on a menu with no options")
self.topLevelMenu = menu
self.currentMenu = menu
self.showMenu();
def display(self, menuItem):
"""
Tells the delegate to display the selection. Advances to the next selection if the
menuItem is visible==False
"""
self.delegate.prepareForRender(self.topLevelMenu)
if (not menuItem.visible):
self.advance()
else:
self.delegate.displayMenuItem(menuItem)
def advance(self):
"""
Advances the displayed menu to the next visible option
raises ValueError if all options are visible==False
"""
for i in self.currentMenu.options:
self.currentMenu.nextSelection()
selection = self.currentMenu.getSelection()
if (selection.visible):
self.display(selection)
return
raise ValueError("At least one option in a menu must be visible!")
def select(self):
"""
Selects the current menu option. Calls menuItemClicked first. If it returns false,
it uses the default logic. If true, it calls display with the current selection
defaults:
"menu" -> sets submenu as the current menu
"back" -> sets parent menu as the current menu
returns True if the default logic should be overridden
throws ValueError if navigating back on a top-level menu
"""
selection = self.currentMenu.getSelection()
if (not self.delegate.menuItemClicked(selection)):
if (selection.type is "menu"):
self.setMenu(selection)
elif (selection.type is "back"):
if (not self.currentMenu.parent):
raise ValueError("Cannot navigate back when parent is None")
self.setMenu(self.currentMenu.parent)
else:
self.display(self.currentMenu.getSelection())
class MenuDelegate(object):
def prepareForRender(self, menu):
"""
Called before the menu needs to display. Useful for changing visibility.
"""
raise NotImplementedError
def menuItemClicked(self, menuItem):
"""
Called when a menu item is selected. Useful for taking action on a menu item click.
"""
raise NotImplementedError
def displayMenuItem(self, menuItem):
"""
Called when the menu item should be displayed.
"""
raise NotImplementedError