|
Problem This article extends How to set up menu and radio menu - Part 3 - add accelerators? to allow display of multiple levels of submenus as shown below:

Solution
Usage:
- Display a menu with sub-menus is just a one-liner:
$menu = new Menu($vbox, $menu_definition)
- To display just one level of menu, use the following menu_definition:
'M1' => array('M1.1', 'M1.2', 'M1.3')
- Suppose
M1.3 has submenus, use the following:
'M1' => array('M1.1', 'M1.2',
'M1.3' => array('M1.3.1', 'M1.3.2', 'M1.3.3'))
- Suppose
M1.3.3 has another level of submenus, use the following:
'M1' => array('M1.1', 'M1.2',
'M1.3' => array('M1.3.1', 'M1.3.2',
'M1.3.3' => array('M1.3.3.1', 'M1.3.3.2', 'M1.3.3.3')))
Sample Code 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
| <?php $window = new GtkWindow(); $window->set_size_request(400, 150); $window->connect_simple('destroy', array('Gtk','main_quit')); $window->add($vbox = new GtkVBox()); $accel_group = new GtkAccelGroup(); $window->add_accel_group($accel_group);
// define menu definition
$menu_definition = array( // note 1
'_File' => array('_New|N', '_Open|O', '_Close|C', '<hr>', '_Save|S', 'Save _As','<hr>','E_xit'), '_Edit' => array('_Undo|Z','_Redo|Y','<hr>', 'Cu_t|X', '_Copy|C', '_Paste|V', '<hr>', '_Select' => array('_All|A', '_Paragraph', '_Word|W'), '_Go to' => array('_Line', '_Bookmark', 'Level 2'=>array('Level 2.1','Level 2.2', 'Level 2.3' => array('Level 2.3.1','Level 2.3.2','Level 2.3.3'))) ), ); $menu = new Menu($vbox, $menu_definition);
// display title
$title = new GtkLabel("Menu and RadioMenuItem\n". "Part 5 - Add Submenus"); $title->modify_font(new PangoFontDescription("Times New Roman Italic 10")); $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff")); $title->set_size_request(-1, 40); $title->set_justify(Gtk::JUSTIFY_CENTER); $alignment = new GtkAlignment(0.5, 0, 0, 0); $alignment->add($title); $vbox->pack_start($alignment, 0, 0); $vbox->pack_start(new GtkLabel(), 0, 0);
$window->show_all(); Gtk::main();
// class Menu
class Menu { var $prev_keyval = 0; var $prev_state = 0; var $prev_keypress = ''; function Menu($vbox, $menu_definition) { $this->menu_definition = $menu_definition; $menubar = new GtkMenuBar(); $vbox->pack_start($menubar, 0, 0); foreach($menu_definition as $toplevel => $sublevels) { $top_menu = new GtkMenuItem($toplevel); $menubar->append($top_menu); $this->setup_submenu($top_menu, $sublevels, $toplevel); // note 2
} }
function setup_submenu($parent_menu, $sublevels, $toplevel) { global $accel_group;
$menu = new GtkMenu(); $parent_menu->set_submenu($menu);
foreach($sublevels as $k=>$submenu) { if (strpos("$submenu", '|') === false) { $accel_key = ''; } else { list($submenu, $accel_key) = explode('|', $submenu); }
if (is_array($submenu)) { // set up radio menus
if (preg_match("/^\d+$/", $k)) { // it's a toggle
$i=0; $radio[0] = null; foreach($submenu as $radio_item) { $radio[$i] = new GtkRadioMenuItem($radio[0], $radio_item); $radio[$i]->connect('toggled', array(&$this, "on_toggle")); $menu->append($radio[$i]); ++$i; } $radio[0]->set_active(1); // select the first item
} else { // it's a submenu
$menu_item = new GtkMenuItem($k); if ($accel_key!='') { $menu_item->add_accelerator("activate", $accel_group, ord($accel_key), Gdk::CONTROL_MASK, 1); } $menu->append($menu_item); $menu_item->connect('activate', array(&$this, 'on_menu_select')); $this->setup_submenu($menu_item, $submenu, $toplevel); // note 3
}
} else { if ($submenu=='<hr>') {
|
- Note that this is only 70% of the sample code. You have to be a registered member to see the entire sample code. Please login or register.
- Registration is free and immediate.
- Have some doubt about the registration? Please read this forum article.
Explanation
- The menu definitions. Note how the multiple levels of submenus are defined.
- Call the method
setup_submenu() recursively to set up each levels of submenus.
- If there's another submenu definition, we make another recursive call to the method
setup_submenu().
Note
Note that accelerators are different from mnemonics. For example, you can choose File Open using mnemonics by pressing Alt-F followed by O. Or you can use the accelerator key Ctrl-O.
Related Links
User reviews There are no user reviews yet. Note: You have to be a registered member to leave a comment. Free registration here. |