# codegen.py: code generator functions for wxMenuBar objects # $Id: codegen.py,v 1.21 2007/03/27 07:01:57 agriggio Exp $ # # Copyright (c) 2002-2007 Alberto Griggio # License: MIT (see license.txt) # THIS PROGRAM COMES WITH NO WARRANTY import common from MenuTree import * class PythonCodeGenerator: def get_properties_code(self, obj): return [] def get_init_code(self, obj): prop = obj.properties pygen = common.code_writers['python'] cn = pygen.cn out = [] append = out.append menus = obj.properties['menubar'] ids = [] def append_items(menu, items): for item in items: if item.name == '---': # item is a separator append('%s.AppendSeparator()\n' % menu) continue name, val = pygen.generate_code_id(None, item.id) if obj.preview or (not name and ( not val or val == '-1')): id = cn('wxNewId()') else: if name: ids.append(name) id = val if item.children: if item.name: name = item.name else: name = '%s_sub' % menu append(('%s = ' + cn('wxMenu') + '()\n') % name) ## if not obj.preview and item.id: # generating id ## tokens = item.id.split('=') ## if len(tokens) > 1: ## id = tokens[0] ## ids.append(' = '.join(tokens) + '\n') ## else: ## id = item.id ## else: id = 'wxNewId()' append_items(name, item.children) append('%s.AppendMenu(%s, %s, %s, %s)\n' % (menu, id, pygen.quote_str(item.label), name, pygen.quote_str(item.help_str))) else: ## if not obj.preview and item.id: # no ids for preview ## tokens = item.id.split('=') ## if len(tokens) > 1: ## id = tokens[0] ## ids.append(' = '.join(tokens) + '\n') ## else: ## id = item.id ## else: id = 'wxNewId()' item_type = cn('wxITEM_NORMAL') if item.checkable == '1': item_type = cn('wxITEM_CHECK') elif item.radio == '1': item_type = cn('wxITEM_RADIO') if item.name: # ALB 2004-18-07 name = 'self.%s' % item.name if item_type: append('%s = %s(%s, %s, %s, %s, %s)\n' % (name, cn('wxMenuItem'), menu, id, pygen.quote_str(item.label), pygen.quote_str(item.help_str), item_type)) else: append('%s = %s(%s, %s, %s, %s)\n' % (name, cn('wxMenuItem'), menu, id, pygen.quote_str(item.label), pygen.quote_str(item.help_str))) append('%s.AppendItem(%s)\n' % (menu, name)) else: if item_type: append('%s.Append(%s, %s, %s, %s)\n' % (menu, id, pygen.quote_str(item.label), pygen.quote_str(item.help_str), item_type)) else: append('%s.Append(%s, %s, %s)\n' % (menu, id, pygen.quote_str(item.label), pygen.quote_str(item.help_str))) #print 'menus = %s' % menus if obj.is_toplevel: obj_name = 'self' else: obj_name = 'self.' + obj.name for m in menus: menu = m.root if menu.name: name = 'self.' + menu.name else: name = 'wxglade_tmp_menu' append(('%s = ' + cn('wxMenu') + '()\n') % name) if menu.children: append_items(name, menu.children) append('%s.Append(%s, %s)\n' % (obj_name, name, pygen.quote_str(menu.label))) return ids + out def get_code(self, obj): """\ function that generates Python code for the menubar of a wxFrame. """ pygen = common.code_writers['python'] if obj.klass == obj.base: klass = pygen.cn(obj.klass) else: klass = obj.klass init = [ '\n', '# Menu Bar\n', 'self.%s = %s()\n' % (obj.name, klass) ] ## 'self.SetMenuBar(self.%s)\n' % obj.name ] init.extend(self.get_init_code(obj)) init.append('self.SetMenuBar(self.%s)\n' % obj.name) init.append('# Menu Bar end\n') return init, [], [] # 2004-12-05 def get_events(self, obj): pygen = common.code_writers['python'] cn = pygen.cn out = [] #print 'get_events', obj.properties['menubar'] def do_get(item): ret = [] if item.name and pygen.for_version > (2, 4): val = '#self.%s' % item.name # see py_codegen.py, ~480 else: name, val = pygen.generate_code_id(None, item.id) if not val: val = '-1' # but this is wrong anyway... if item.handler: ret.append((val, 'EVT_MENU', item.handler)) if item.children: for c in item.children: ret.extend(do_get(c)) return ret for menu in obj.properties['menubar']: out.extend(do_get(menu.root)) return out # end of class PythonCodeGenerator class MenuHandler: """Handler for menus and menu items of a menubar""" item_attrs = ('label', 'id', 'name', 'help_str', 'checkable', 'radio', 'handler') def __init__(self): self.menu_depth = 0 self.menus = [] self.curr_menu = None self.curr_item = None self.attr_val = [] def start_elem(self, name, attrs): if name == 'menu': self.menu_depth += 1 label = attrs['label'] if self.menu_depth == 1: t = MenuTree(attrs['name'], label) self.curr_menu = t.root self.menus.append(t) return id = attrs.get('itemid', '') handler = attrs.get('handler', '') node = MenuTree.Node(label=label, name=attrs['name'], id=id, handler=handler) node.parent = self.curr_menu self.curr_menu.children.append(node) self.curr_menu = node elif name == 'item': self.curr_item = MenuTree.Node() def end_elem(self, name, code_obj): if name == 'menus': code_obj.properties['menubar'] = self.menus return True if name == 'item' and self.curr_menu: self.curr_menu.children.append(self.curr_item) self.curr_item.parent = self.curr_menu elif name == 'menu': self.menu_depth -= 1 self.curr_menu = self.curr_menu.parent elif name in self.item_attrs: setattr(self.curr_item, name, "".join(self.attr_val)) self.attr_val = [] def char_data(self, data): self.attr_val.append(data) # end of class MenuHandler def xrc_code_generator(obj): """\ function that generates XRC code for the menubar of a wxFrame. """ from xml.sax.saxutils import escape, quoteattr xrcgen = common.code_writers['XRC'] class MenuBarXrcObject(xrcgen.DefaultXrcObject): def append_item(self, item, outfile, tabs): write = outfile.write if item.name == '---': # item is a separator write(' '*tabs + '\n') else: if item.children: name = self.get_name(item) if name: write(' '*tabs + '\n' % quoteattr(name)) else: write(' '*tabs + '\n') else: name = self.get_name(item) if name: write(' '*tabs + '\n' % quoteattr(name)) else: write(' '*tabs + '\n') if item.label: # translate & into _ as accelerator marker val = item.label.replace('&', '_') write(' '*(tabs+1) + '\n' % \ escape(val)) if item.help_str: write(' '*(tabs+1) + '%s\n' % \ escape(item.help_str)) if item.children: for c in item.children: self.append_item(c, outfile, tabs+1) elif item.checkable == '1': write(' '*(tabs+1) + '1\n') elif item.radio == '1': write(' '*(tabs+1) + '1\n') write(' '*tabs + '\n') def get_name(self, item): if item.name: return item.name.strip() tokens = item.id.split('=') if tokens: return tokens[0].strip() def write(self, outfile, tabs): menus = self.code_obj.properties['menubar'] write = outfile.write write(' '*tabs + '\n' % \ quoteattr(self.name)) for m in menus: self.append_item(m.root, outfile, tabs+1) write(' '*tabs + '\n') # end of class MenuBarXrcObject return MenuBarXrcObject(obj) class CppCodeGenerator: constructor = [] def get_code(self, obj): """\ generates C++ code for the menubar of a wxFrame. """ cppgen = common.code_writers['C++'] menus = obj.properties['menubar'] init = [ '%s = new %s();\n' % (obj.name, obj.klass) ] init.extend(self.get_properties_code(obj)) init.append('SetMenuBar(%s);\n' % obj.name) ids = self.get_ids_code(obj) return init, ids, [], [] def get_properties_code(self, obj): cppgen = common.code_writers['C++'] menus = obj.properties['menubar'] out = [] append = out.append def append_items(menu, items): for item in items: if item.name == '---': # item is a separator append('%s->AppendSeparator();\n' % menu) continue name, val = cppgen.generate_code_id(None, item.id) if not name and val == '-1': id = 'wxNewId()' else: #if name: ids.append(name) id = val if item.children: if item.name: name = item.name else: name = '%s_sub' % menu append('wxMenu* %s = new wxMenu();\n' % name) ## if item.id: # generating id ## tokens = item.id.split('=') ## if len(tokens) > 1: ## id = tokens[0] ## else: ## id = item.id ## else: id = 'wxNewId()' append_items(name, item.children) append('%s->Append(%s, %s, %s, %s);\n' % (menu, id, cppgen.quote_str(item.label), name, cppgen.quote_str(item.help_str))) else: ## if item.id: ## tokens = item.id.split('=') ## if len(tokens) > 1: ## id = tokens[0] ## else: ## id = item.id ## else: ## id = 'wxNewId()' item_type = 'wxITEM_NORMAL' if item.checkable == '1': item_type = 'wxITEM_CHECK' elif item.radio == '1': item_type = 'wxITEM_RADIO' if item_type: append('%s->Append(%s, %s, %s, %s);\n' % (menu, id, cppgen.quote_str(item.label), cppgen.quote_str(item.help_str), item_type)) else: append('%s->Append(%s, %s, %s);\n' % (menu, id, cppgen.quote_str(item.label), cppgen.quote_str(item.help_str))) #print 'menus = %s' % menus if obj.is_toplevel: obj_name = '' else: obj_name = obj.name + '->' i = 1 for m in menus: menu = m.root if menu.name: name = menu.name else: name = 'wxglade_tmp_menu_%s' % i i += 1 append('wxMenu* %s = new wxMenu();\n' % name) if menu.children: append_items(name, menu.children) append('%sAppend(%s, %s);\n' % (obj_name, name, cppgen.quote_str(menu.label))) return out def get_ids_code(self, obj): cppgen = common.code_writers['C++'] ids = [] menus = obj.properties['menubar'] def collect_ids(items): for item in items: if item.name == '---': # item is a separator continue # do nothing name, val = cppgen.generate_code_id(None, item.id) if name.find('=') != -1: ids.append(name) if item.children: ## if item.id: # generating id ## tokens = item.id.split('=') ## if len(tokens) > 1: ## id = tokens[0] ## ids.append(' = '.join(tokens)) collect_ids(item.children) ## else: ## if item.id: ## tokens = item.id.split('=') ## if len(tokens) > 1: ## id = tokens[0] ## ids.append(' = '.join(tokens)) for m in menus: if m.root.children: collect_ids(m.root.children) return ids def get_events(self, obj): cppgen = common.code_writers['C++'] out = [] def do_get(item): ret = [] name, val = cppgen.generate_code_id(None, item.id) if not val: val = '-1' # but this is wrong anyway... if item.handler: ret.append((val, 'EVT_MENU', item.handler, 'wxCommandEvent')) if item.children: for c in item.children: ret.extend(do_get(c)) return ret for menu in obj.properties['menubar']: out.extend(do_get(menu.root)) return out # end of class CppCodeGenerator def initialize(): common.class_names['EditMenuBar'] = 'wxMenuBar' common.toplevels['EditMenuBar'] = 1 pygen = common.code_writers.get('python') if pygen: pygen.add_widget_handler('wxMenuBar', PythonCodeGenerator()) pygen.add_property_handler('menus', MenuHandler) xrcgen = common.code_writers.get('XRC') if xrcgen: xrcgen.add_widget_handler('wxMenuBar', xrc_code_generator) xrcgen.add_property_handler('menus', MenuHandler) cppgen = common.code_writers.get('C++') if cppgen: cppgen.add_widget_handler('wxMenuBar', CppCodeGenerator()) cppgen.add_property_handler('menus', MenuHandler)