Este problema se me presentó ayer y me parece bueno aportar en esto ya que todo lo que sea Menu/MenuBar/MenuItem en GWT no parece tener buen manejo de handlers, buen.. en cuanto a MenuItem directamente no lo tiene.
El problema en sí es el siguiente: ¿Que pasa si yo quiero capturar eventos del teclado junto con el click en algún item del menu?... El constructor de MenuItem espera un Command el cual va a ser ejecutado cuando se hace click en dicho elemento, pero no da la posibilidad de capturar otros eventos como Doble click, o teclas como Ctrl., Alt., Shift, etc.
La solución que encontré puede que no sea la mejor, pero resuelve el problema (:
Primero que nada creamos la clase
MenuBarAdv que extiende de
MenuBar
/**
* MenuBarAdv.java
* 06/09/2011 12:28:52
* @author Cristian N. Miranda
*/
package ar.com.gwt.menu.events.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.MenuBar;
/**
* @author Cristian N. Miranda
*/
public class MenuBarAdv extends MenuBar {
private boolean ctrlKeyPressed;
/**
* Constructor
*/
public MenuBarAdv() {
super(false);
}
/**
* Creates an empty menu bar.
*
* @param vertical
* < code >true< /code > to orient the menu bar vertically
*/
public MenuBarAdv(boolean vertical) {
super(vertical, GWT.< Resources > create(Resources.class));
}
@Override
public void onBrowserEvent(Event event) {
MenuItemEvents.setCurrentMenuBarAdv(this);
switch (DOM.eventGetType(event)) {
case Event.ONCLICK: {
if(event.getCtrlKey()){
ctrlKeyPressed = true;
}else{
ctrlKeyPressed = false;
}
break;
}
}
super.onBrowserEvent(event);
}
/**
* Get Ctrl. Key Pressed Status
* @author Cristian N. Miranda
* @return
*/
public boolean getCtrlKeyPressed(){
return this.ctrlKeyPressed;
}
}
Ahí es donde capturamos los eventos que se generen sobre el MenuBar con el método onBrowserEvent() ...
Luego en nuestro EntryPoint..
package ar.com.gwt.menu.events.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.RootPanel;
public class MenuItemEvents implements EntryPoint {
private static MenuBarAdv currentMenuBarAdv;
private final MenuBarAdv menutop = new MenuBarAdv();
private final MenuBarAdv menutwo = new MenuBarAdv(true);
public void onModuleLoad() {
// A command for general use
Command command = new Command(){
@Override
public void execute() {
Window.alert("Ctrl. key pressed: " + String.valueOf(currentMenuBarAdv.getCtrlKeyPressed()));
}
};
// Top-level menu
menutop.addStyleName("demo-MenuItem");
// Item to fire a command
MenuItem fireone = new MenuItem("Fire One", command);
// Level-two menu - vertical=true
menutwo.addStyleName("demo-MenuItem");
// Items for menu two
MenuItem firetwo = new MenuItem("Fire Two", command);
MenuItem firethree = new MenuItem("Fire Three", command);
MenuItem firefour = new MenuItem("Fire Four", command);
// Assemble the menu system
menutop.addItem(fireone); // Adds existing item
menutop.addItem("SubMenu", menutwo); // Creates item and adds menutwo
menutwo.addItem(firetwo);
menutwo.addItem(firethree);
menutwo.addItem(firefour);
RootPanel.get().add(menutop);
}
/**
* Obtains the current MenuBar clicked
* @author Cristian N. Miranda
* @param menuBarAdv
*/
public static void setCurrentMenuBarAdv(MenuBarAdv menuBarAdv){
currentMenuBarAdv = menuBarAdv;
}
}
Ahi es donde obtenemos la instancia del MenuBarAdv clickeado y verificamos los flags de las teclas o cualquier otro evento deseado.. todo dentro de nuestro método execute() del Command para cada MenuItem.
Post en Google groups haciendo referencia al problema:
http://code.google.com/p/google-web-toolkit/issues/detail?id=3559 (Titulado:
MenuItem should better use ClickHandler instead of Command)
Código de ejemplo:
http://code.google.com/p/gwt-menuitem-keyboard-events/downloads/list
Cualquier cosa avisan.
Saludos.