I said in my recent post jit + gwt: a low-cost solution that the new event system of gwt 1.6 is “neat”. Well, I wasn’t neat enough for it. The way I implemented the event ClickLabelEvent resulted in all clicks on any type of Widget with gwt would now fire a ClickLabelEvent instead of the original ClickEvent.
The problem was that ClickLabelEvent extended DomEvent and its Type was new Type("click", new ClickLabelEvent()). This line overshadows the original “click” event implementation and fires a ClickLabelEvent from now on. I list the wrong implementation below followed by the corrected code. I updated the original post to show the corrected code. The correct implementation is to extend GwtEvent, thus, ClickLabelEvent is not a native event anymore. In order to instantiate this event type it it’s necessary to add a static void fire(HasClickLabelHandlers source, boolean rightclick) method to the class. This method is used in the “glue code” that converts native events into gwt + jit events (JitWidget.forwardEvent, see below).
Wrong implementation:
import com.google.gwt.event.dom.client.DomEvent;
public class ClickLabelEvent extends DomEvent {
protected ClickLabelEvent() {
}
public static Type getType() {
return TYPE;
}
@Override
protected void dispatch(ClickLabelHandler handler) {
int x = this.getNativeEvent().getScreenX();
int y = this.getNativeEvent().getScreenY();
if (1000000 == x && 0 == y) {
handler.onClickLabel(this);
} else if (0 == x && 1000000 == y) {
handler.onRightClickLabel(this);
}
}
@Override
public final Type getAssociatedType() {
return TYPE;
}
private static Type TYPE = new Type("click", new ClickLabelEvent());
}
Corrected implementation:import com.google.gwt.event.shared.GwtEvent;
public class ClickLabelEvent extends GwtEvent<ClickLabelHandler> {
protected ClickLabelEvent(boolean rightclick) {
this.rightclick = rightclick;
}
public static Type getType() {
return TYPE;
}
public static void fire(HasClickLabelHandlers source, boolean rightclick) {
ClickLabelEvent event = new ClickLabelEvent(rightclick);
source.fireEvent(event);
}
@Override
protected void dispatch(ClickLabelHandler handler) {
if (rightclick) {
handler.onRightClickLabel(this);
} else {
handler.onClickLabel(this);
}
}
@Override
public final Type getAssociatedType() {
return TYPE;
}
private final boolean rightclick;
private static Type TYPE<ClickLabelHandler> = new Type<ClickLabelHandler>();
}
Glue code:
public abstract class JitWidget extends Widget implements ResizeHandler, HasClickLabelHandlers,
HasMouseOverLabelHandlers, HasMouseOutLabelHandlers {
...
@SuppressWarnings("unused")
private final static void forwardEvent(String name, JavaScriptObject event, JavaScriptObject label,
JavaScriptObject node) {
NativeEvent received = (NativeEvent) (null == event ? null : event.cast());
Document document = Document.get();
JitWidget jit = jitgwtwrappers.get(name);
jit.setClickedLabel(label);
jit.setClickedNode(node);
String type = null == received ? "click" : received.getType();
if ("click".equals(type)) {
JSONObject nodeobject = new JSONObject(node);
String nodeid = nodeobject.get("id").toString();
nodeid = nodeid.substring(1, nodeid.length() - 1);
History.newItem(name + ";" + nodeid);
ClickLabelEvent.fire(jit, false);
} else if ("contextmenu".equals(type)) {
ClickLabelEvent.fire(jit, true);
} else if ("mouseover".equals(type)) {
MouseOverLabelEvent.fire(jit, received);
} else if ("mouseout".equals(type)) {
MouseOutLabelEvent.fire(jit, received);
} else {
GWT.log("not handled: " + type, null);
}
}
The glue code shows that I also added handling of two more event types to the class JitWidget: MouseOverLabelEvent and MouseOutLabelEvent.
Similar to ClickLabelEvent they are fired when the mouse is moved over or out of a label in a jit visualization. With these events it’s very easy to add a “ToolTip” hint to a label when you hover the mouse over it. Unlike some other implementations this only adds a tooltip for the “current” label which should show better performance.
Sample for “ToolTip”:
public void onModuleLoad() {
...
spacetree.addMouseOverLabelHandler(this);
spacetree.addMouseOutLabelHandler(this);
...
@Override
public void onMouseOverLabel(MouseOverLabelEvent event) {
JitWidget jit = (JitWidget) event.getSource();
JSONObject json = new JSONObject(jit.getClickedNode());
PopupPanel popup= new DecoratedPopupPanel();
StringBuilder b = new StringBuilder();
for (String k : json.keySet()) {
b.append(k);
b.append(" : ");
b.append(json.get(k).isString());
b.append("");
}
popup.setWidth("200px");
popup.setWidget(new HTML(b.toString()));
int x = event.getNativeEvent().getClientX();
int y = event.getNativeEvent().getClientY();
tooltip = new ToolTip(2000, popup, x, y); // show popup after 2000ms, if not cancelled
}
@Override
public void onMouseOutLabel(MouseOutLabelEvent event) {
tooltip.cancel();
}
This code uses a small helper class called “ToolTip”:
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RootPanel;
public class ToolTip extends Timer {
public ToolTip(int delay, PopupPanel popup, int x, int y) {
this.popup = popup;
this.x = x + 32;
this.y = y + 32;
schedule(delay);
scheduled = true;
}
@Override
public void run() {
popup.setPopupPosition(x, y);
popup.show();
int w = popup.getOffsetWidth();
int h = popup.getOffsetHeight();
x = x + Math.min(0, RootPanel.get().getOffsetWidth() - 32 - (x + w));
y = y + Math.min(0, RootPanel.get().getOffsetHeight() - 32 - (y + h));
popup.setPopupPosition(x, y);
}
@Override
public void cancel() {
if (scheduled) {
scheduled = false;
super.cancel();
popup.hide();
}
}
private final PopupPanel popup;
private boolean scheduled = false;
private int x;
private int y;
}
[...] jit + gwt: MouseOverLabelEvent/MouseOutLabelEvent July 7, 2009 Filed under: jit with gwt — weltermann17 @ 20:12 Tags: gwt, jit These event types were added to enable easy “tooltip” or “show details when hovering over jit labels” implementation. Their usage was described in the previous post. [...]