Sooner or later, the simple menu structure in your WxRuby application just isn't going to meet your needs. One tool you can use to assist you is the sub-menu. Sub-menus can be created and used to reduce clutter in large menus and keep everything neat and tidy without overwhelming the user. When the mouse hovers over a sub-menu, another menu pops out to the right, giving a whole sub-set of choices for the user.
In the previous article on menus , menus were built using the generic append method. However, there are several other methods that can be used to build menus.
append - This will append a menu item to the menu, as discussed in the article on menus in WxRuby.
append_item - This can be used to append anything to a menu including menu items, separators, radio buttons, sub menus and more. This gives the most control over how the MenuItems will act. However, this does require you to construct MenuItem objects and is the most verbose way to add menu items.
append_menu - Appends a sub-menu item to the menu. Using this method, sub-menus are themselves built just like menus, then appended to another menu.
append_check_item - Appends a menu item that, when selected, will toggle on and off. When on, a check mark will appear next to the menu item.
append_radio_item - Appends an item as part of a radio item group. All consecutively added radio items will be grouped. Radio items act like check items, except that when one of the items is checked, all the others in the group are unchecked.
append_separator - Appends a separator to the menu. A separator is a menu item that is displayed as a horizontal line and cannot be selected. Its only purpose is to visually separate logical groups of menu items.
So, as you can see, to append a sub-menu, we have to pick the right append method. In this case, we want append_menu. The sub-menu itself is built in the same way as any other menu. Once its built, append it to the higher-level menu using append_menu and you're done.
The following is a modification of the example from the previous article on menus. Note: The portions of code pertaining to the sub-menu are highlighted in bold.
#!/usr/bin/env ruby require 'rubygems' require 'wx' class AppFrame < Wx::Frame def initialize(title) # Call parent class' initialize function, and add int # a few more arguments besides the title. Since this # is a top-level frame, there is no parent widget, so # use nil for the first argument. super( nil, :title => title, :size => [400, 300] ) # Create the Wx::MenuBar object. This holds all the # Wx::Menu objects to create the menu hierarchy. menu = Wx::MenuBar.new # Start with the File menu. Only a single thing here, # the Exit option. file = Wx::Menu.new # These won't do anything, they're just there for show file.append( Wx::ID_ANY, "&Open\tAlt-O", "Open File" ) file.append( Wx::ID_ANY, "&Close\tAlt-C", "Close File" ) # Use seperators between groups of menu options file.append_separator # The Exit option has a special ID, Wx::ID_EXIT, which # will do any platform-specific magic to translate and # put the Exit option in the correct place. file.append( Wx::ID_EXIT, "E&xit\tAlt-X", "Quit" ) menu.append( file, "&File" ) # Create the dummy menu # This is the top-level menu dummy = Wx::Menu.new dummy.append( Wx::ID_ANY, "Dummy 1" ) dummy.append( Wx::ID_ANY, "Dummy 2" ) dummy.append_separator # Create the SubDummy menu # This is the sub-menu of the Dummy menu subdummy = Wx::Menu.new subdummy.append( Wx::ID_ANY, "SubDummy 1" ) subdummy.append( Wx::ID_ANY, "SubDummy 2" ) dummy.append_menu( Wx::ID_ANY, "SubDummy", subdummy ) menu.append( dummy, "Dummy" ) # Create the Help menu help = Wx::Menu.new help.append( Wx::ID_ABOUT, "&About...\tF1", "Show about dialog" ) menu.append( help, "&Help" ) self.menu_bar = menu # Setup our callbacks to handle menu events evt_menu( Wx::ID_EXIT, :on_quit ) evt_menu( Wx::ID_ABOUT, :on_about ) end # Close the window when the user clicks Quit in the File # menu def on_quit close end # Display an "About this program" dialog def on_about Wx::about_box( :name => self.title, :version => "1.0", :description => "Menu example" ) end end class MyApp < Wx::App def on_init @frame = AppFrame.new("Menu test") @frame.show end end app = MyApp.new app.main_loop