miércoles, 7 de septiembre de 2011

GWT MenuBar - Handling Keyboard Events

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.

No hay comentarios:

Publicar un comentario