060. How to set up menu and radio menu - Part 3 - add accelerators?

Problem

You have set up menus with stock images in Part 2.

How to set up menu and radio menu - Part 2 - add stock images?

Now you would like to add accelerator keys to the menu items as shown below:

How to set up menu and radio menu - Part 3 - add accelerators?


Solution


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   
27   
28   
29   
30   
31   
32   
33   
34   
35   
36   
37   
38   
39   
40   
41   
42   
44   
45   
46   
47   
48   
50   
51   
52   
53   
54   
55   
56   
57   
58   
59   
60   
61   
62   
63   
64   
65   
66   
67   
69   
70   
71   
72   
73   
74   
80   
81   
82   
83   
87   
88   
89   
90   
91   
92   
93   
94   
95   
96   
97   
98   
99   
101   
102   
103   
104   
105   
106   
107   
108   
109   
110   
111   
<?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(); // create a new accelerator
$window->add_accel_group($accel_group); // attach it to the window

// define menu definition
$menu_definition = array( // note 1
    '_File' => array('_New|N', '_Open|O', '_Close|C', '<hr>',
                    '_Save|S', 'Save _As','<hr>', '_Quit'),
    '_Edit' => array('Cut|X', 'Copy|C', '_Paste|V', '<hr>',
                    'Select All|A', '<hr>', '_Undo|Z','_Redo|Y'),
    '_Test' => array('Test_1|1', 'Test_2|2', 'Test_3|3', '<hr>',
                array('Selection 1', 'Selection 2', 'Selection 3'),
                '<hr>', 'Test_4|4')
);
setup_menu($vbox, $menu_definition);

// display title
$title = new GtkLabel("Menu and RadioMenuItem - Part 3\n".
"                add accelerators");
$title->modify_font(new PangoFontDescription("Times New Roman Italic 10"));
$title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff"));
$vbox->pack_start($title);
$vbox->pack_start(new GtkLabel(''));

$window->show_all();
Gtk::main();

// setup menu
function setup_menu($vbox, $menus) {
    global $accel_group; // don't forget this
    $menubar = new GtkMenuBar();
    $vbox->pack_start($menubar, 0, 0);
    foreach($menus as $toplevel => $sublevels) {
        $menubar->append($top_menu = new GtkMenuItem($toplevel));
        $menu = new GtkMenu();
        $top_menu->set_submenu($menu);
        foreach($sublevels as $submenu) {
            if (strpos("$submenu", '|') === false) { // note 2
                $accel_key = ''; 
            } else { 
                list($submenu, $accel_key) = explode('|', $submenu); 
            } 

            if (is_array($submenu)) { // set up radio menus
                $i=0;
                $radio[0] = null;
                foreach($submenu as $radio_item) {
                    $radio[$i] = new GtkRadioMenuItem($radio[0], $radio_item);
                    $radio[$i]->connect('toggled', "on_toggle");
                    $menu->append($radio[$i]);
                    ++$i;
                }
                $radio[0]->set_active(1); // select the first item
            } else {
                if ($submenu=='<hr>') {
                    $menu->append(new GtkSeparatorMenuItem());
                } else {
                    $submenu2 = str_replace('_', '', $submenu);
                    $submenu2 = str_replace(' ', '_', $submenu2);
                    $stock_image_name = 'Gtk::STOCK_'.strtoupper($submenu2);
                    if (defined($stock_image_name)) {
                        $menu_item = new GtkImageMenuItem(
                                        constant($stock_image_name));
                    } else {
                        $menu_item = new GtkMenuItem($submenu);
                    }
                    if ($accel_key!='') { 
                        $menu_item->add_accelerator("activate", $accel_group, 
                        ord($accel_key), Gdk::CONTROL_MASK, 1); // note 3
                    } 

                    $menu->append($menu_item);
                    $menu_item->connect('activate', 'on_menu_select');
                }
            }
        }
    }
}

// process radio menu selection
function on_toggle($radio) {
    $label = $radio->child->get_label();
    $active = $radio->get_active();
    echo("radio menu selected: $label\n");
}

// process menu item selection
function on_menu_select($menu_item) {
    $item = $menu_item->child->get_label();
    echo "menu selected: $item\n";
    if ($item=='_Quit') Gtk::main_quit();
}

?>

Output

As shown above.
 

Explanation

  1. Note that we modified the menu definition a bit. To specify an accelerator key, simply put a '|' followed by the accelerator key, for example, 'Cut|X', 'Copy|C', '_Paste|V'.
  2. The purpose of the codes here is just to extract any accelerator key from the menu definition.
  3. If an accelerator key is specified, we add it using GtkWidget::add_accelerator().

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

Add comment


Security code
Refresh