subclassing wxMenuBar...

Tom Jenkins tjenkins at devis.com
Tue Jun 5 09:27:57 EDT 2001


Tom Jenkins <tjenkins at devis.com> wrote in message news:<mailman.991661708.12433.python-list at python.org>...
> Bjorn Pettersen wrote:
> 
> > I was stepping through the wxPython tutorial, and came across the part
> > where they're creating the menus. It seemed like a good idea to put the
> > menu definition in a datafile instead of specifying it programatically,
> > so I though it would be a good chance to get some xml experience too...
> > 
[snip]
> 
> Well I wouldn't subclass wxMenuBar; instead I'd create a helper class 
> that would handle reading the xml and loading it into the wxMenuBar.  I 
> took your code and changed it to work as a helper.  Along the way I 
> added some functionality.

[snip]
Err... well it looks like the mailing list -> newsgroup bridge
stripped out the attachment that contained the code for the helper
class.  So let me follow up by putting it directly in the message
<grin>

#----------------------------------
'''
XMLMenuLoader: Class to handle loading a wxMenuBar with menu items
defined in XML

author: Tom Jenkins <tjenkins at devis.com>
based on code by Bjorn Pettersen <BPettersen at NAREX.com>

#*TODO*: refactor load into base class that handles loading the menu
in another way so we can have ListMenuLoader, StreamMenuLoader, etc...


'''

from xml.dom import minidom
from wxPython.wx import *
  
def filterText(nodelist):
   return [ x for x in nodelist if x.nodeType != x.TEXT_NODE ]
  
class XMLMenuLoader:
   def __init__(self, filename, wxMenuBar = None):
		'''Save the filename and menubar to use'''
		self._filename = filename
		self.setMenuBar(wxMenuBar)
	
   def setMenuBar(self, wxMenuBar = None):
		''' set the menubar property to the given menubar
		wxMenuBar -> the root menubar of the frame'''
		self._wxMenuBar = wxMenuBar
	
   def menuBar(self):
		'''Return the stored menubar'''
		return self._wxMenuBar
	
   def load(self, wxMenuBar = None, controller = None):
		'''Load the menubar with the menu items stored in XML format in
                   the instance's filename property
		wxMenuBar -> the root menubar of the frame; if given will become
                the instances new menubar property
		controller -> the class instance that will receive any callbacks
                stored in the menu items' callback attribute
		'''
		if wxMenuBar != None:
			self.setMenuBar(wxMenuBar)
		
		menubar = minidom.parse(self._filename)
		# loop over and process all of the menu elements in the menubar
		for menu in menubar.getElementsByTagName('menu'):
			menuName = menu.attributes['name'].nodeValue.replace('_', '&')
			wxmenu = wxMenu()
	   
			for menuItem in filterText(menu.childNodes):
				if menuItem.tagName == 'menuitem':
						attrs = menuItem.attributes
						idTag = int( attrs['id'].nodeValue )
						name = attrs['name'].nodeValue.replace('_', '&')
						info = attrs['info'].nodeValue
						wxmenu.Append(idTag, name, info)
				# only load the callbacks if there is a controller
				if controller:
					try:
						callback = attrs['callback'].nodeValue
						handler = getattr(controller, callback, None)
						if handler:
							EVT_MENU(controller, idTag, handler)
					except KeyError, ex:
						# didn't have a callback attribute - skip
						#*TODO*: check if there is a better way; maybe a has_key test?
						pass
						
				elif menuItem.tagName == 'separator':
						wxmenu.AppendSeparator()
			 
			self.menuBar().Append(wxmenu, menuName)
#----------------------------------


> 
> Thanks for the initial post Bjorn, I had fun working on this...

Didn't-have-fun-getting-the-code-out-to-you-though-ly, yours
Tom



More information about the Python-list mailing list