401. How to set up menu with images as menu items - Part 1?

Problem

Suppose you would like to set up menu with images (e.g. standard .gif, .jpg or .png image files) as menu items as shown below:

How to set up menu with images as menu items - Part 1?


Solution


Sample Code

Note: The following image files are required by the sample code below. Please save a copy of the image files and put them in the same directory where you store the sample code.

 square_yellow.jpg
 square_green.jpg
 square_blue.jpg

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
17   
18   
19   
20   
21   
22   
23   
24   
25   
26   
27   
28   
29   
30   
31   
33   
34   
35   
36   
37   
38   
39   
40   
41   
42   
43   
44   
45   
46   
47   
48   
50   
51   
52   
53   
54   
56   
57   
58   
59   
60   
61   
62   
63   
64   
65   
66   
67   
68   
69   
70   
71   
72   
73   
75   
76   
77   
78   
79   
80   
81   
82   
83   
84   
85   
86   
88   
95   
96   
97   
98   
102   
103   
104   
105   
106   
107   
108   
109   
110   
111   
112   
114   
115   
116   
117   
118   
119   
120   
121   
122   
123   
124   
125   
126   
127   
128   
129   
130   
132   
133   
134   
135   
136   
137   
138   
139   
140   
141   
143   
144   
145   
146   
147   
148   
149   
<?php
$window = new GtkWindow();
$window->set_title($argv[0]);
$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(
    '_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'),
    '_Test' => array('Test_1|1', 'Test_2|2', 'Test_3|3', '<hr>',
                array('Selection 1', 'Selection 2', 'Selection 3'),
                '<hr>', 'Test_4|4'),
    '_Background' => array('Yellow|Y', 'Green|G', 'Blue|B')
);

$image_files = array('Yellow' => 'square_yellow.jpg',
    'Green' => 'square_green.jpg',
    'Blue' => 'square_blue.jpg');
setup_menu($vbox, $menu_definition);

// display title
$title = new GtkLabel("Menu with images as menu items - Part 1");
$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;
    $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) {
                $accel_key = '';
            } else {
                list($submenu, $accel_key) = explode('|', $submenu);
            }

            if (is_array($submenu)) {
                $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 {
                        if ($toplevel == '_Background') {
                            global $image_files;
                            $image_file = $image_files[$submenu];
                            $menu_item = setup_image_menuitem( 
                                            $submenu, $image_file); // note 1
                        } else {
                            $menu_item = new GtkMenuItem($submenu);
                        }
                    }
                    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', 'on_menu_select');
                }
            }
        }
    }
}

// setup menuitem with background color
function setup_image_menuitem($menuitem_label, $image_file) {
    $menu_item = new GtkMenuItem($menuitem_label);
    $label = $menu_item->child;
    $menu_item->remove($label); // note 2
    $hbox = new GtkHBox();
    $menu_item->add($hbox); // note 3
    $image = GtkImage::new_from_file($image_file); // note 4
    $hbox->pack_start($image, 0); // note 4
    $label = new GtkLabel($menuitem_label);
    $label->set_alignment(0, 0.5);
    $hbox->pack_start($label); // note 5
    return $menu_item;
}

// 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) {
    if (method_exists($menu_item->child, 'get_label')) {
        $item = $menu_item->child->get_label();
        echo "menu selected: $item\n";
        if ($item=='_Quit') Gtk::main_quit();
    } elseif ($menu_item->child->get_name()=='GtkHBox') {
        $widgets = $menu_item->child->get_children(); // note 6
        $item = $widgets[1]->get_label(); // note 6
        echo "menu item (with image) selected: $item\n";
    }
}

?>

Output

As shown above.
 

Explanation

The above makes use of the code from How to set up menu and radio menu - Part 3 - add accelerators?

What's new here:

  1. Set up image menuitems.
  2. First remove the default GtkLabel.
  3. Then attach a GtkHBox.
  4. Load the image and stuff it into GtkHBox.
  5. Next stuff the label in the GtkHBox.
  6. Take note of how we retrieve back the label of the image menuitem.

Note

Compare the technique used here with that of How to set up menu items with background colors?

Related Links

Add comment


Security code
Refresh