/* * java-gnome, a UI library for writing GTK and GNOME programs from Java! * * Copyright © 2007 Vreixo Formoso * Copyright © 2007-2010 Operational Dynamics Consulting, Pty Ltd * * The code in this file, and the program it is a part of, is made available * to you by its authors as open source software: you can redistribute it * and/or modify it under the terms of the GNU General Public License version * 2 ("GPL") as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GPL for more details. * * You should have received a copy of the GPL along with this program. If not, * see http://www.gnu.org/licenses/. The authors of this program may be * contacted through http://java-gnome.sourceforge.net/. */ package menu; import org.gnome.gdk.Event; import org.gnome.gdk.Keyval; import org.gnome.gdk.ModifierType; import org.gnome.gtk.AcceleratorGroup; import org.gnome.gtk.CheckMenuItem; import org.gnome.gtk.Gtk; import org.gnome.gtk.ImageMenuItem; import org.gnome.gtk.Label; import org.gnome.gtk.Menu; import org.gnome.gtk.MenuBar; import org.gnome.gtk.MenuItem; import org.gnome.gtk.SeparatorMenuItem; import org.gnome.gtk.Stock; import org.gnome.gtk.VBox; import org.gnome.gtk.Widget; import org.gnome.gtk.Window; /** * How to use {@link Menu} and related Widgets. * * @author Vreixo Formoso * @author Andrew Cowie * @author Thijs Leibbrand */ public class ExampleSimpleMenu { public ExampleSimpleMenu() { final Window window; final VBox box; final Label label; final Menu fileMenu, editMenu, viewMenu; final MenuItem file, edit, view; final MenuItem save, copy, paste; final ImageMenuItem nouveau, close; final AcceleratorGroup group; final MenuBar bar; /* * Begin with the standard VBox in a Window setup: */ window = new Window(); box = new VBox(false, 3); window.add(box); label = new Label("Select an action in a menu"); label.setWidthChars(30); label.setAlignment(0.0f, 0.5f); /* * Most applications will use several Menus in a MenuBar: */ fileMenu = new Menu(); editMenu = new Menu(); viewMenu = new Menu(); /* * Create all of MenuItems that will be used: */ nouveau = new ImageMenuItem(Stock.NEW); save = new MenuItem("_Save"); close = new ImageMenuItem(Stock.CLOSE); copy = new MenuItem("_Edit"); paste = new MenuItem("_Paste"); /* * Create the AcceleratorGroup object and add it to the window. */ group = new AcceleratorGroup(); window.addAcceleratorGroup(group); /* * Now we add the keybindings for the menu items. This has to be done * before you append them to their Menus. */ save.setAccelerator(group, Keyval.s, ModifierType.CONTROL_MASK); copy.setAccelerator(group, Keyval.c, ModifierType.CONTROL_MASK); paste.setAccelerator(group, Keyval.v, ModifierType.CONTROL_MASK); /* * For ImageMenuItems you can activate the keybinding that comes with * the Stock item instead. */ nouveau.setAccelerator(group); /* * Despite 'close' also being an ImageMenuItem we could use the * keybinding that is set for Stock.CLOSE. But since we have already * set Control + C for editCopy we set this one manually to another * keybinding: */ close.setAccelerator(group, Keyval.w, ModifierType.CONTROL_MASK); /* * To ensure keybindings will work we also have set the * AcceleratorGroup to the menus containing the MenuItems with the * keybindings. * * Since we have not set a keybinding for hide text MenuItem we also * do not need to set the AcceleratorGroup of the Menu containing this * menu item. Also if a Menu only contains MenuItems with keybindings * set from Stock Items (and not set a keybinding manually) it is also * not needed. */ fileMenu.setAcceleratorGroup(group); editMenu.setAcceleratorGroup(group); /* * Now you can add MenuItems to the "file" Menu. */ fileMenu.append(nouveau); fileMenu.append(save); /* * A SeparatorMenuItem can be used to differentiate between unrelated * menu options; in practise, though, only use sparingly. */ fileMenu.append(new SeparatorMenuItem()); /* * And add the rest of the menu items. */ fileMenu.append(close); editMenu.append(copy); editMenu.append(paste); /* * Usually you will want to connect to the MenuItem.Activate signal, * that is emitted when the user "activates" the menu by either * clicking it with the mouse or navigating to it with the keyboard * and pressing <ENTER>. */ nouveau.connect(new MenuItem.Activate() { public void onActivate(MenuItem source) { label.setLabel("You have selected File->New menu."); } }); save.connect(new MenuItem.Activate() { public void onActivate(MenuItem source) { label.setLabel("You have selected File->Save."); } }); close.connect(new MenuItem.Activate() { public void onActivate(MenuItem source) { label.setLabel("You have selected File->Close."); } }); /* * Given that in most cases you will connect to the MenuItem.Activate * signal on MenuItems, a convenience constructor is provided: */ fileMenu.append(new MenuItem("_Quit", new MenuItem.Activate() { public void onActivate(MenuItem source) { Gtk.mainQuit(); } })); /* * And now add the actions for the items making up the "edit" Menu. */ copy.connect(new MenuItem.Activate() { public void onActivate(MenuItem source) { label.setLabel("You have selected Edit->Copy."); } }); paste.connect(new MenuItem.Activate() { public void onActivate(MenuItem source) { label.setLabel("You have selected Edit->Paste."); } }); /* * CheckMenuItems hold a boolean state. One use is to allow users to * hide some parts of the GUI, as in this example which we put into * the "view" Menu: */ viewMenu.append(new CheckMenuItem("Hide _text", new CheckMenuItem.Toggled() { public void onToggled(CheckMenuItem source) { if (source.getActive()) { label.hide(); } else { label.show(); } } })); /* * A MenuItem can have a "sub-menu", that will be expanded when the * user puts the mouse pointer over it. This is also used in creating * the elements for the top level MenuBar, but you can use it within * normal Menus as well. That said, submenus of Menus are considered * less "discoverable" because the user has to navigate through the * hierarchy to find out what options are available to them, rather * than seeing them at first glance. */ file = new MenuItem("_File"); file.setSubmenu(fileMenu); edit = new MenuItem("_Edit"); edit.setSubmenu(editMenu); view = new MenuItem("_View"); view.setSubmenu(viewMenu); /* * Finally, most applications make use of a MenuBar that is by * convention located at the top of the application Window. It * contains the top-level MenuItems. */ bar = new MenuBar(); bar.append(file); bar.append(edit); bar.append(view); /* * Finally, pack the Widgets into the VBox, and present. */ box.packStart(bar, false, false, 0); box.packStart(label, false, false, 0); window.showAll(); /* * And that's it! One last piece of house keeping, though: it is * always necessary to deal with the user closing (what is in this * case) the last Window in the application; otherwise the Java VM * will keep running even after the (sole) Window is closed - because * the main loop never returned. */ window.connect(new Window.DeleteEvent() { public boolean onDeleteEvent(Widget source, Event event) { Gtk.mainQuit(); return false; } }); } public static void main(String[] args) { Gtk.init(args); new ExampleSimpleMenu(); /* * Yes, you could have written all the Window creation code here in * main() but it is generally good practise to put that setup into a * constructor, as we have here. */ Gtk.main(); } }