Found difficulties in some versions of Opera with exercising CSS properties like .myclass[disabled] {...}. Also I haven't found any solution how to sink events for disabled widgets. Seems like they are totally non-interactive (however :hover property still does some effect) speaking in terms of standard events, available for handling. Manually implemented enabled/disabled state has been the only suitable solution, which I'd found till present.
There's one good article
about preview native event. In a nutshell you may examine what current event is about and cancel it before browser starts any propagation. Also I found
this article quite useful to keep up on date with modern API. Here's a very concise piece of code:
In some singleton filter class (e.g. NativePreviewHandlerForHasEnabled):
*************************
private final Map<Element, HasEnabled> elementToWidgetMap = new HashMap<Element, HasEnabled>();
private NativePreviewHandlerForHasEnabled() {
assert instance == null : "Only one instance is allowed.";
elementToWidgetMap = new HashMap<Element, HasEnabled>();
Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
public void onPreviewNativeEvent(NativePreviewEvent pEvent) {
final Element target = pEvent.getNativeEvent().getEventTarget().cast();
HasEnabled widget = elementToWidgetMap.get(target);
if (widget != null && !widget.isEnabled()) {
// Let it work, cause we may need to e.g. hide tool tip when mouse is out
if (pEvent.getTypeInt() != Event.ONMOUSEOUT) {
pEvent.cancel();
}
}
}
});
}
public <T extends Widget & HasEnabled> void registerWidget(T widget) {
elementToWidgetMap.put(widget.getElement(), widget);
}
*************************
For our widget:
@Override
public void setEnabled(boolean enabled) {
this.enabled = enabled;
// super.setEnabled(enabled); // don't do this!
}
It's not perfect. Map can grow up fast depending on scale of your app. To enhance the performance store HandlerRegistration objects upon Event.addNativePreviewHandler call for later disposing, when the time comes.