Search code examples
gwtuibinder

GWT: Menus in UiBinder


I would like to implement menus (MenuBar, MenuItem) using the declarative approach via UiBinder in GWT 2.0.

I have run into two problems:

  1. Is there a way to add MenuItemSeparators in the .ui.xml file? So far, I have only managed to put MenuBar- and MenuItem-tags into the file.

  2. Using @UiHandler, GWT writes the boilerplate code for event handlers for me. For menus, I need to write commands. How am I supposed to do this using the UiBinder approach? Is there a command tag to put in the .ui.xml file? Do I have to write the boilerplate code for the command handlers myself?

Thanks for thinking about these questions!


Solution

  • I agree, if you try to put a MenuItemSeparator in, it will complain stating only a MenuItem can be a child when GWT tries to create the widget . Since this is not currently supported, I suggest that you request this as a future enhancement to the GWT team.

    In the meantime, you can add a separator programmatically and add a command in the following manner: The XML file:

    <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui">
    <g:HTMLPanel>
        <g:MenuBar ui:field="menuBar">
            <g:MenuItem ui:field="helpMenuItem">Help</g:MenuItem>
            <g:MenuItem ui:field="aboutMenuItem">About</g:MenuItem>
            <g:MenuItem ui:field="siteMapMenuItem">Site Map</g:MenuItem>
        </g:MenuBar>
    </g:HTMLPanel>
    

    The Java file(s):

    public class Menu extends Composite {
    ...
    @UiField MenuBar menuBar;
    @UiField MenuItem helpMenuItem;
    ...
    public Menu() {
        initWidget(uiBinder.createAndBindUi(this));
        // insert a separator
        menuBar.insertSeparator(1);
        // attach commands to a menu item
        helpMenuItem.setCommand(new MenuCommand(HistoryToken.Help));
        ...
    }  
    
    public class MenuCommand implements Command {
        final HistoryToken historyToken;
    
        public MenuCommand(HistoryToken historyToken) {
            this.historyToken = historyToken;
        }
    
        @Override
        public void execute() {
            historyToken.fire();
        }
    }  
    
    public enum HistoryToken {
        Help,About,SiteMap;
    
        public void fire(){
            History.newItem(this.toString());
        }
    }
    


    Elsewhere in my code, I implemented a HistoryListener to catch any changes, i.e.

    class HistoryManager implements ValueChangeHandler<String> {
        // 1. get token
        // 2. change it into a HistoryToken
        // 3. perform switch statement 
        // 4. change contents based upon HistoryToken found
    ...
    }