I would like to implement menus (MenuBar
, MenuItem
) using the declarative approach via UiBinder in GWT 2.0.
I have run into two problems:
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.
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!
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
...
}
For (1) JavaDoc says:
Use in UiBinder Templates MenuBar elements in UiBinder template files can have a vertical boolean attribute (which defaults to false), and may have only MenuItem elements as children. MenuItems may contain HTML and MenuBars.
For example:
<g:MenuBar>
<g:MenuItem>Higgledy
<g:MenuBar vertical="true">
<g:MenuItem>able</g:MenuItem>
<g:MenuItem>baker</g:MenuItem>
<g:MenuItem>charlie</g:MenuItem>
</g:MenuBar>
</g:MenuItem>
<g:MenuItem>Piggledy
<g:MenuBar vertical="true">
<g:MenuItem>foo</g:MenuItem>
<g:MenuItem>bar</g:MenuItem>
<g:MenuItem>baz</g:MenuItem>
</g:MenuBar>
</g:MenuItem>
<g:MenuItem><b>Pop!</b>
<g:MenuBar vertical="true">
<g:MenuItem>uno</g:MenuItem>
<g:MenuItem>dos</g:MenuItem>
<g:MenuItem>tres</g:MenuItem>
</g:MenuBar>
</g:MenuItem>
</g:MenuBar>
Taking the hint from the words "only MenuItem elements as children", my guess is that MenuItemSeparators are not supported
Here's an example of my solution to this, which seems to work pretty well with GWT 2.4.0.
UiBinder:
<g:MenuBar vertical='true' ui:field='mainMenu'>
<g:MenuItem ui:field='item1'>Item 1</g:MenuItem>
<g:MenuItem ui:field='item2'>Item 2</g:MenuItem>
<g:MenuItemSeparator />
<g:MenuItem ui:field='sub' enabled='false'>
Submenu
<g:MenuBar vertical='true' ui:field='subMenu' />
</g:MenuItem>
</g:MenuBar>
Java:
@UiField MenuItem item1;
@UiField MenuItem item2;
@UiField MenuBar subMenu;
@UiField MenuItem sub;
...
this.setWidget(uiBinder.createAndBindUi(this));
item1.setCommand(new Command() {
public void execute() {
History.newItem("item1");
}
});
Overall not too bad.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With