/*
* Ext GWT - Ext for GWT
* Copyright(c) 2007-2009, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/
package com.extjs.gxt.ui.client.util;
import com.extjs.gxt.ui.client.GXT;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.BaseObservable;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.KeyboardEvents;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.widget.Component;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.KeyCodes;
/**
* Provides a convenient wrapper for normalized keyboard navigation. Provides an
* easy way to implement custom navigation schemes for any UI component.
*/
public class KeyNav<E extends ComponentEvent> extends BaseObservable implements Listener<E> {
private static EventType keyEvent;
private Component component;
private boolean cancelBubble;
private boolean preventDefault;
static {
// mods press up
// Safari no yes
// IE yes yes
// FF yes no
// Opera yes no
// nav press down
// IE no yes
// FF yes yes
// Safari no yes
// Opera yes yes
if (GXT.isIE || GXT.isWebKit || GXT.isGecko) {
keyEvent = Events.OnKeyDown;
} else {
keyEvent = Events.OnKeyPress;
}
}
public static EventType getKeyEvent() {
return keyEvent;
}
/**
* Creates a new KeyNav without a target component. Events must be passed to
* the {@link #handleEvent(BaseEvent)} method.
*/
public KeyNav() {
}
/**
* Creates a new key nav for the specified target. The KeyNav will listen for
* the key events.
*
* @param target the target component
*/
public KeyNav(Component target) {
bind(target);
}
public void addKeyNavListener(KeyNavListener listener) {
addListener(KeyboardEvents.Alt, listener);
addListener(KeyboardEvents.BackSpace, listener);
addListener(KeyboardEvents.Control, listener);
addListener(KeyboardEvents.Delete, listener);
addListener(KeyboardEvents.Down, listener);
addListener(KeyboardEvents.End, listener);
addListener(KeyboardEvents.Enter, listener);
addListener(KeyboardEvents.Escape, listener);
addListener(KeyboardEvents.Home, listener);
addListener(KeyboardEvents.Left, listener);
addListener(KeyboardEvents.PageDown, listener);
addListener(KeyboardEvents.PageUp, listener);
addListener(KeyboardEvents.Right, listener);
addListener(KeyboardEvents.Shift, listener);
addListener(KeyboardEvents.Tab, listener);
addListener(KeyboardEvents.Up, listener);
}
/**
* Binds the key nav to the component.
*
* @param target the target component
*/
public void bind(final Component target) {
if (this.component != null) {
this.component.removeListener(keyEvent, this);
}
if (target != null) {
target.addListener(keyEvent, this);
target.sinkEvents(keyEvent.getEventCode());
}
this.component = target;
}
/**
* Returns the cancel bubble state.
*
* @return true if bubbling is cancelled
*/
public boolean getCancelBubble() {
return cancelBubble;
}
/**
* Returns the target component.
*
* @return the target component
*/
public Component getComponent() {
return component;
}
/**
* Returns true if the default event action is being cancelled.
*
* @return true if preventing default
*/
public boolean getPreventDefault() {
return preventDefault;
}
@SuppressWarnings("unchecked")
public void handleEvent(ComponentEvent ce) {
if (ce.getType() == keyEvent) {
if (component.getElement() != (Element) ce.getEvent().getCurrentEventTarget().cast()) {
return;
}
if (cancelBubble) {
ce.cancelBubble();
}
if (preventDefault) {
ce.preventDefault();
}
int code = ce.getKeyCode();
E e = (E) ce;
onKeyPress(e);
switch (code) {
case KeyCodes.KEY_ALT:
onAlt(e);
break;
case KeyCodes.KEY_BACKSPACE:
onBackspace(e);
break;
case KeyCodes.KEY_CTRL:
onControl(e);
break;
case KeyCodes.KEY_DELETE:
onDelete(e);
break;
case KeyCodes.KEY_DOWN:
onDown(e);
break;
case KeyCodes.KEY_END:
onEnd(e);
break;
case KeyCodes.KEY_ENTER:
onEnter(e);
break;
case KeyCodes.KEY_ESCAPE:
onEsc(e);
break;
case KeyCodes.KEY_HOME:
onHome(e);
break;
case KeyCodes.KEY_LEFT:
onLeft(e);
break;
case KeyCodes.KEY_PAGEDOWN:
onPageDown(e);
break;
case KeyCodes.KEY_PAGEUP:
onPageUp(e);
break;
case KeyCodes.KEY_SHIFT:
onShift(e);
break;
case KeyCodes.KEY_TAB:
onTab(e);
break;
case KeyCodes.KEY_RIGHT:
onRight(e);
break;
case KeyCodes.KEY_UP:
onUp(e);
break;
}
fireEvent(new EventType(code), e);
}
}
public void onKeyPress(E ce) {
}
public void onAlt(E ce) {
}
public void onBackspace(E ce) {
}
public void onControl(E ce) {
}
public void onDelete(E ce) {
}
public void onDown(E ce) {
}
public void onEnd(E ce) {
}
public void onEnter(E ce) {
}
public void onEsc(E ce) {
}
public void onHome(E ce) {
}
public void onLeft(E ce) {
}
public void onPageDown(E ce) {
}
public void onPageUp(E ce) {
}
public void onRight(E ce) {
}
public void onShift(E ce) {
}
public void onTab(E ce) {
}
public void onUp(E ce) {
}
public void removeKeyNavListener(KeyNavListener listener) {
removeListener(KeyboardEvents.Alt, listener);
removeListener(KeyboardEvents.BackSpace, listener);
removeListener(KeyboardEvents.Control, listener);
removeListener(KeyboardEvents.Delete, listener);
removeListener(KeyboardEvents.Down, listener);
removeListener(KeyboardEvents.End, listener);
removeListener(KeyboardEvents.Enter, listener);
removeListener(KeyboardEvents.Escape, listener);
removeListener(KeyboardEvents.Home, listener);
removeListener(KeyboardEvents.Left, listener);
removeListener(KeyboardEvents.PageDown, listener);
removeListener(KeyboardEvents.PageUp, listener);
removeListener(KeyboardEvents.Right, listener);
removeListener(KeyboardEvents.Shift, listener);
removeListener(KeyboardEvents.Tab, listener);
removeListener(KeyboardEvents.Up, listener);
}
/**
* True to stop event bubbling when the key nav intercepts a key (defaults to
* false).
*
* @param cancelBubble the cancel bubble state
*/
public void setCancelBubble(boolean cancelBubble) {
this.cancelBubble = cancelBubble;
}
/**
* True to prevent the default action of the key event when the key nav
* intercepts a key (defaults to false).
*
* @param preventDefault true to prevent the default
*/
public void setPreventDefault(boolean preventDefault) {
this.preventDefault = preventDefault;
}
}