Don't swap menus while you're navigating on the same traitbox
[crapvine.git] / menu.py
blob955041fe1ce774cf9c21381027b4dce9471aeebf
1 ## This file is part of Crapvine.
2 ##
3 ## Copyright (C) 2007 Andrew Sayman <lorien420@myrealbox.com>
4 ##
5 ## Crapvine is free software; you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or
8 ## (at your option) any later version.
9 ##
10 ## Crapvine is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ## GNU General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with this program. If not, see <http://www.gnu.org/licenses/>.
18 from xml.sax import ContentHandler
19 import string
20 import gtk
21 import gobject
22 import copy
23 import operator
24 from grapevine_xml import AttributeReader
26 def normalize_whitespace(text):
27 "Remove redundant whitespace from a string"
28 return ' '.join(text.split())
30 class MenuLoader(ContentHandler):
31 def __init__(self):
32 self.menus = {}
33 self.current_menu = None
35 def add_menu(self, menu):
36 self.menus[menu.name] = menu
38 def __recursive_item_append(self, core_menu, new_menu):
39 for item in core_menu.items:
40 if isinstance(item, MenuReference) and item.tagname == 'include':
41 print 'Found an include'
42 if self.menus.has_key(item.reference):
43 self.__recursive_item_append(self.menus[item.reference], new_menu)
44 else:
45 new_menu.add_item(copy.copy(item))
47 def __find_real_menu_name(self, menu_name):
48 if self.menus.has_key(menu_name):
49 return menu_name
50 if self.menus.has_key(menu_name.capitalize()):
51 return menu_name.capitalize()
52 split_str = menu_name.split(' ')
53 if split_str[0] == 'Negative':
54 test_out = '%s, %s' % (split_str[1], split_str[0])
55 if self.menus.has_key(test_out):
56 return test_out
57 return None
59 def get_expanded_menu(self, menu_name):
60 real_menu_name = self.__find_real_menu_name(menu_name)
61 if not real_menu_name:
62 return None
63 core_menu = self.menus[real_menu_name]
64 new_menu = Menu(core_menu.name, core_menu.category, core_menu.alphabetical, core_menu.required, core_menu.display, core_menu.negative, core_menu.autonote)
65 self.__recursive_item_append(core_menu, new_menu)
66 if new_menu.alphabetical:
67 new_menu.items.sort(key=operator.attrgetter('name'))
68 return new_menu
70 def has_menu(self, menu_name):
71 return menu_name in self.menus
73 def startElement(self, name, attrs):
74 if name == 'menu':
75 if not attrs.has_key('name'):
76 return
77 menu = Menu(attrs.get('name'))
78 r = AttributeReader(attrs)
79 menu.category = r.text('category', '1')
80 menu.alphabetical = r.boolean('abc')
81 menu.required = r.boolean('required')
82 menu.display = r.text('display', '0')
83 menu.autonote = r.boolean('autonote')
84 menu.negative = r.boolean('negative')
85 self.current_menu = menu
87 elif name == 'item':
88 if not attrs.has_key('name'):
89 return
90 item = MenuItem(attrs.get('name'))
91 r = AttributeReader(attrs)
92 item.cost = r.text('cost', '1')
93 item.note = r.text('note', '')
94 self.current_menu.add_item(item)
96 elif name == 'submenu' or name == 'include':
97 if not attrs.has_key('name'):
98 return
99 link = MenuReference(name, attrs.get('name'))
100 r = AttributeReader(attrs)
101 link.reference = r.text('link', link.name)
102 self.current_menu.add_item(link)
104 def endElement(self, name):
105 if name == 'menu':
106 self.add_menu(self.current_menu)
107 self.current_menu = None
109 class Menu:
110 """ Note that negative is whether they values should be calculated as a negative value when computing the base character spend points """
111 def __init__(self, name, category='1', alphabetical=False, required=False, display='0', negative=False, autonote=False):
112 self.name = name
113 self.category = category
114 self.alphabetical = alphabetical
115 self.required = required
116 self.display = display
117 self.negative = negative
118 self.autonote = autonote
119 self.items = []
121 def add_item(self, item):
122 self.items.append(item)
124 def get_display_length(self):
125 includes = [inc for inc in self.items if isinstance(inc, MenuReference)]
126 print includes
128 def get_xml(self, indent):
129 outs = ['%s<menu name="%s"' % (indent, self.name)]
130 if not self.category == '1':
131 outs.append('category="%s"' % (self.category))
132 if self.alphabetical:
133 outs.append('abc="yes"')
134 if self.negative:
135 outs.append('negative="yes"')
136 if self.required:
137 outs.append('required="yes"')
138 if self.autonote:
139 outs.append('autonote="yes"')
140 outs.append('display="%s"' % (self.display))
141 outs.append(">\n")
142 local_indent = '%s ' % (indent)
143 for item in self.items:
144 outs.append(item.get_xml(local_indent))
145 outs.append('%s<menu/>' % (indent))
146 outs.append("\n")
147 return ' '.join(outs)
149 class MenuItem:
150 def __init__(self, name, cost='1', note=''):
151 self.name = name
152 self.cost = cost
153 self.note = note
155 def get_xml(self, indent):
156 outs = ['%s<item name="%s"' % (indent, self.name)]
157 if not self.cost == '1':
158 outs.append('cost="%s"' % (self.cost))
159 if not self.note == '':
160 outs.append('note="%s"' % (self.note))
161 outs.append("/>\n")
162 return ' '.join(outs)
164 class MenuReference:
165 def __init__(self, tagname, name, reference=''):
166 self.name = name
167 self.reference = reference
168 self.tagname = tagname
170 def get_xml(self, indent):
171 outs = ['%s<%s name="%s"' % (indent, self.tagname, self.name)]
172 if self.reference != self.name:
173 outs.append('link="%s"' % (self.reference))
174 outs.append("/>\n")
175 return ' '.join(outs)
177 class MenuModel(gtk.GenericTreeModel):
178 def __init__(self, menu):
179 gtk.GenericTreeModel.__init__(self)
180 self.menu = menu
181 assert menu is not None
182 self.menu.items.insert(0, MenuReference('submenu', '(back)', '(back)'))
183 def get_item(self, index):
184 return self.menu.items[index]
185 def get_item_from_path(self, path):
186 return self.menu.items[path[0]]
187 def on_get_flags(self):
188 return gtk.TREE_MODEL_LIST_ONLY|gtk.TREE_MODEL_ITERS_PERSIST
189 def on_get_n_columns(self):
190 return 1
191 def on_get_column_type(self, index):
192 return gobject.TYPE_STRING
193 def on_get_path(self, iter):
194 return (iter, )
195 def on_get_iter(self, path):
196 return path[0]
197 def on_get_value(self, index, column):
198 assert column == 0
199 menu_item = self.menu.items[index]
200 ret_name = menu_item.name
201 if isinstance(menu_item, MenuReference) and menu_item.tagname == 'submenu':
202 ret_name += ':'
203 return ret_name
204 def on_iter_next(self, index):
205 if index >= (len(self.menu.items) - 1):
206 return None
207 return index + 1
208 def on_iter_children(self, node):
209 return None
210 def on_iter_has_child(self, node):
211 return False
212 def on_iter_n_children(self, iter):
213 if iter:
214 return 0
215 return len(self.menu.items)
216 def on_iter_nth_child(self, parent, n):
217 if parent:
218 return None
219 try:
220 self.menu.items[n]
221 except IndexError:
222 return None
223 else:
224 return n
225 def on_iter_parent(self, node):
226 return None