Context Menus

The Pivot framework provides platform support for context menus via the MenuPopup class, a subclass of Window that contains an instance of Menu. Though it is possible to instantiate and open a MenuPopup directly, it is often more convenient to use the MenuHandler interface. When an instance of MenuHandler is attached to a component, the Pivot platform automatically handles many of the details associated with menu processing. MenuHandler defines the following methods:

public void configureMenuBar(Component component, MenuBar menuBar);
public void cleanupMenuBar(Component component, MenuBar menuBar);
public boolean configureContextMenu(Component component, Menu menu, int x, int y);

The first two methods are related to menu bars and are discussed in the next section. The third method can be used to automatically present a context menu when the user right-clicks on a component to which the handler is attached. For example, the following application uses a menu handler to present a simple context-sensitive help menu that describes what the user clicked on:

The BXML source for the example is shown below. It simply instantiates four image view components and places a description of the image shown in each in the component's user data:

            
            <menus:ContextMenus title="Context Menus" maximized="true"
                xmlns:bxml="http://pivot.apache.org/bxml"
                xmlns:menus="org.apache.pivot.tutorials.menus"
                xmlns="org.apache.pivot.wtk">
                <Border styles="{color:10}">
                    <TablePane styles="{horizontalSpacing:1, verticalSpacing:1,
                        showHorizontalGridLines:true, showVerticalGridLines:true,
                        horizontalGridColor:10, verticalGridColor:10}">
                        <columns>
                            <TablePane.Column width="1*"/>
                            <TablePane.Column width="1*"/>
                        </columns>

                        <TablePane.Row height="1*">
                            <ImageView image="@battery.png">
                                <userData description="battery"/>
                            </ImageView>
                            <ImageView image="@emblem-favorite.png">
                                <userData description="heart"/>
                            </ImageView>
                        </TablePane.Row>

                        <TablePane.Row height="1*">
                            <ImageView image="@edit-paste.png">
                                <userData description="clipboard"/>
                            </ImageView>
                            <ImageView image="@face-smile.png">
                                <userData description="smiley face"/>
                            </ImageView>
                        </TablePane.Row>
                    </TablePane>
                </Border>
            </menus:ContextMenus>
            
        

The Java source is shown below. The application class defines an anonymous inner class instance that extends MenuHandler.Adapter and overrides the configureContextMenu() method to add a menu section containing a single "What is this?" menu item. The Pivot platform handles the details of detecting the right click and instantiating and configuring the menu popup. It walks the ancestry of the component over which the mouse click occurred from the top down, calling configureContextMenu() for each menu handler it encounters along the way. This allows handlers attached to sub-components to override any menu configuration performed by an ancestor.

Menu.Item is actually a subclass of Button, so it can be assigned an Action like any other button. The example code below creates an Action that displays a prompt containing a description of the selected item when the item is pressed:

            
            package org.apache.pivot.tutorials.menus;

            import java.net.URL;

            import org.apache.pivot.beans.Bindable;
            import org.apache.pivot.collections.Map;
            import org.apache.pivot.util.Resources;
            import org.apache.pivot.wtk.Action;
            import org.apache.pivot.wtk.Component;
            import org.apache.pivot.wtk.Menu;
            import org.apache.pivot.wtk.MenuHandler;
            import org.apache.pivot.wtk.Prompt;
            import org.apache.pivot.wtk.Window;

            public class ContextMenus extends Window implements Bindable {
                private MenuHandler menuHandler = new MenuHandler.Adapter() {
                    @Override
                    public boolean configureContextMenu(Component component, Menu menu, int x, int y) {
                        final Component descendant = getDescendantAt(x, y);

                        Menu.Section menuSection = new Menu.Section();
                        menu.getSections().add(menuSection);

                        Menu.Item whatIsThisMenuItem = new Menu.Item("What is this?");
                        whatIsThisMenuItem.setAction(new Action() {
                            @Override
                            public void perform(Component source) {
                                String description = (String)descendant.getUserData().get("description");
                                String message = "This is a " + description + ".";

                                Prompt.prompt(message, ContextMenus.this);
                            }
                        });

                        menuSection.add(whatIsThisMenuItem);

                        return false;
                    }
                };

                @Override
                public void initialize(Map<String, Object> namespace, URL location, Resources resources) {
                    setMenuHandler(menuHandler);
                }
            }
            
        

When the menu closes, the platform takes care of cleaning up the menu instance - no further interaction by the handler is required.

Next: Menu Bars