PHP-GTK2 Newsletter

PHP-GTK2 Tips & Techniques
FREE Newsletter
by kksou



Sample Code 214: How to set up menu and radio menu - Part 5 - add submenus?
Written by kksou   
Wednesday, 11 April 2007
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:

How to set up menu and radio menu - Part 5 - add submenus?


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
  1. The menu definitions. Note how the multiple levels of submenus are defined.
  2. Call the method setup_submenu() recursively to set up each levels of submenus.
  3. 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.

 
< Prev   Next >

Blog - Forum - Privacy Policy - Contact Us
Copyright © 2006-2008. kksou.com. All Rights Reserved