GWT UiHandler on HTMLPanel - gwt

I'm writing a widget with the following markup:
<g:HTMLPanel ui:field="shortcutPanel" styleName="{style.shortcut}">
<g:Image ui:field="shortcutImage"></g:Image>
<span ui:field="shortcutLabel"></span>
</g:HTMLPanel>
So essentially a div that wraps and image and a label. Now, instead of adding the event handlers on the image/span, I'd like an onClick to be associated with the HTMLPanel. My problem however is that gwt tells me that
shortcutPanel doesn't not have an addClickHandler method associated
So I'm assuming the difference is that HTMLPanel doesn't implement HasClickHandlers or something along that line. I'm wondering then what is the standard way to attach a click handler to a Ui element such as an HTMLPanel or even better, is there such a GWT Widget that is essentially a div wrapper that I can easily attach events to with the #UiHandler annotation.

You are probably looking for FocusPanel - it has all the goodies: HasAllFocusHandlers, HasAllKeyHandlers, HasAllMouseHandlers, HasBlurHandlers, HasClickHandlers.... to name a few :) I find it to be the easiest and best way to attach click handlers to a Panel.

I haven't done this before, but you could do the following:
Create a custom class MyPanel that extends HTMLPanel and implements HasClickHandlers
Add the following method in MyPanel.java
public HandlerRegistration addClickHandler(ClickHandler handler) {
return addDomHandler(handler, ClickEvent.getType());
}
Then replace HTMLPanel with MyPanel in your ui.xml and its corresponding Java implementation.
You can always look at the implementation of HTMLTable to get an understanding of how the event propagation works. It's a Panel and implements HasClickHandlers.

If you want to use the #UiHandler annotation to register event handlers for your custom widget, you need to re-implement the addXXHandler methods. The GWT compiler doesn't seem to find those in superclasses. e.g. if you want to use
#UiHandler("myCustomWidget")
public void handleWidgetSelectionChangeEvent(final SelectionEvent<CountryDts> event) {
...
}
and your CustomWidget extends a class for which this is working, you might need to add the HasSelectionHandlers interface explicitly to your class:
public class CustomComboBox<D> extends ComboBox<D> implements HasSelectionHandlers<D> {
#Override
#SuppressWarnings("pmd.UselessOverridingMethod")
public HandlerRegistration addSelectionHandler(final SelectionHandler<D> handler) {
// GWT Compile doesn't recognize method in supertype for UIHandler
return super.addSelectionHandler(handler);
}
...
}

Related

add mousewheel event to absolute panel

can we add a mousewheel event to absolute panel in GWT. I have added a mousewheel event to absolute panel but it is not working .Why this problem is there but if I add it to label then its working properly.
Thanks,
It is because the AbsolutePanel does not implements the HasAllMouseHandlers interface specifically HasMouseWheelHandlers. Label implements HasMouseWheelHandlers interface. So it works for Label.
You have to extend AbsolutePanel and implement HasMouseWheelHandlers interface to make it work with AbsolutePanel. And behavior you have to define.
public class MyAbsolutePanel extends AbsolutePanel implements HasMouseWheelHandlers
{
public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler)
{
// Define the behavior here.
return addDomHandler(handler, MouseOutEvent.getType());
}
}

How to add a Behavior to a component inside another Behavior added to that component in Wicket

I would like to add an AttributeAppender to a Component inside an AjaxEventBehavior using Apache Wicket. A Behavior has a getComponent() method but in the Constructor getComponent() obvioulsy returns null.
Now I pass the component to the Constructor of the AjaxEventBehavior and it's working but is this a good way to achieve my goal..
Here's what I'm doing:
AjaxTooltipBehavior:
public class AjaxTooltipBehavior extends AjaxEventBehavior {
public AjaxTooltipBehaviour(String event, Component tooltippedComponent) {
super(event);
tooltippedComponent.add(new AttributeAppender("data-tooltip","wicketAjaxTooltip"));
}
...
}
And that's the way I use it:
...
final WebMarkupContainer icon = new WebMarkupContainer("icon"); //a tooltiped icon
icon2.add(new AjaxTooltipBehaviour("mouseover",icon2)
I asked myself if there isn't a way to add the AttributeAppender to the componet without passing the component to the AjaxTooltipBehavior.
Does anyone know if this is possible in wicket or if there are better solutions?
FYI: I'm using wicket 1.6.
Thanks in advance for your support!
Ronny
Generally you would override Behavior#onBind(Component), but this method is made final in AbstractAjaxBehavior. But it will call onBind() and you use getComponent() there:
#Override
protected void onBind() {
super.onBind();
getComponent().add(new AttributeAppender("data-tooltip","wicketAjaxTooltip"));
}
Because you have extended from AbstractAjaxBehavior (AjaxEventBehavior extends AbstractAjaxBehavior), you should gain access to getComponent(), which will give you the component the behavior is attached to.
I override Behavior#onConfigure(Component component) wich is possible the most suitable way to add Behaviors or do some other stuff with the component belonging to the Behavior.
#Override
protected void onConfigure(Component component) {
super.onConfigure();
component().add(new AttributeAppender("data-tooltip","wicketAjaxTooltip"));
}

GWT 2.4 customized ListBox doesn't fire Change event

I have added some extra functionality to the standard GWT ListBox by extending it like so:
public class FeatureListBox extends ListBox
{
public FeatureListBox()
{
}
public FeatureListBox(boolean isMultipleSelect)
{
super(isMultipleSelect);
}
public FeatureListBox(Element element)
{
super(element);
}
}
Nothing fancy here. However, the Change event is not firing now, or at least the handler (attached per below) is not getting invoked.
FeatureListBox listBox = new FeatureListBox();
listBox.addChangeHandler(new ChangeHandler()
{
public void onChange(ChangeEvent event)
{
// Do something here...
}
});
Any ideas why?
Either remove the no-argument constructor from FeatureListBox or call super() inside it, otherwise the initialization in the superclasses won't happen, which would probably result in what you're seeing.
The problem was in the way I was using my custom list box. In my application I wrap GWT Widgets around existing DOM elements on the page using the static wrap() methods of their widget classes in which the widgets get marked as attached, making them fire events. I didn't do that with my custom list box class originally, so I ended up implementing a static wrap() method similar to the one of the regular ListBox widget and using it in my code. Everything works like a charm now.

How to instantiate an Event Handler interface in GWT using uiBinder?

I'm trying to use a custom widget: gwtupload with it's custom handlers. The handlers are defined as interfaces, as in, Interface.OnCustomEventHandler and the method, according to the API, that I want to use is like this code, but I'm not sure how to implement this with uiBinder.:
void onCustomEvent (Interface interface)
Normally for uiBinder I use this code for the regular gwt widgets:
#Widget widget;
#UiHandler("widget")
void onClick(ClickEvent event){
//Handle the event processing here.
}
Presently, when I try this,
#UiHandler("widget")
void onCustomEvent(ICustomInterface customInterface){
...
I get this null pointer exception:
[ERROR] Generator 'com.google.gwt.uibinder.rebind.UiBinderGenerator' threw an exception while rebinding '...ViewImpl.ViewImplUiBinder'
java.lang.NullPointerException
Here is the new code I tried:
public class MUpld extends Composite {
private static MUpldUiBinder uiBinder = GWT.create(MUpldUiBinder.class);
interface MUpldUiBinder extends UiBinder<Widget, MUpld> {
}
#UiField MultiUploader uploader;
public MUpld() {
final IUploader.OnFinishUploaderHandler onFinishUploaderHandler = new IUploader.OnFinishUploaderHandler() {
#Override
public void onFinish(IUploader iUploader) {
if (uploader.getStatus() == Status.SUCCESS){
System.out.println("In the onFinish method!");
}
}
};
initWidget(uiBinder.createAndBindUi(this));
uploader.addOnFinishUploadHandler(onFinishUploaderHandler);
}
}
In the debugger, I saw the handler get attached to the uploader widget I defined, but then the current uploader became a different one once the code moved out of this class. I tried using the final modifier, as that is the only way I know to get a variable into an inner class, but gwt would complain with:
[ERROR] com.cdg.complexityCalculator.client.view.MUpld has no default (zero args) constructor.
To fix this, you can define a #UiFactory method on the UiBinder's owner, or annotate a constructor of MUpld with #UiConstructor.
I wasn't able to get either of those options to work, but I realized I had the last two lines of code switched, so I changed it to what I have now and the handler loaded up with the correct object.
Any ideas as to how to get this to work? Everything else is in place, I just need a way to capture this event after my servlet has finished processing.
When I changed the last two lines of code, the handler got loaded properly. Now the objects are being created with the handler binding to the correct object.
initWidget(uiBinder.createAndBindUi(this));
uploader.addOnFinishUploadHandler(onFinishUploaderHandler);
I had to wait until the uiBinder created the instance of the uploader widget, then I was able to add the handler to it.
One of the tricks I've learned is to add a handler in the constructor for a composite widget you create, that way it's more of an encapsulated component. It handles it's own events.

GWT adding a ClickHandler to a DOM element

lets say i have a custom widget which has a ClickHandler. Here's the example:
public class TestWidget extends Composite {
private static TestWidgetUiBinder uiBinder = GWT
.create(TestWidgetUiBinder.class);
interface TestWidgetUiBinder extends UiBinder<Widget, TestWidget> {
}
#UiField
Button button;
public TestWidget(String firstName) {
initWidget(uiBinder.createAndBindUi(this));
button.setText(firstName);
}
#UiHandler("button")
void onClick(ClickEvent e) {
Window.alert("Hello!");
}
}
When i try to add this Widget like this:
TestWidget testWidget = new TestWidget("myTestWidget");
RootPanel.get().add(testWidget);
everything is fine. If i click on my button i get the message i expect.
However if i add it like this:
TestWidget testWidget = new TestWidget("myTestWidget");
RootPanel.getBodyElement().appendChild(testWidget.getElement());
my click event is not being fired. I'm struggeling to understand why.
It would be nice if someone could explain this to me or link me to an resource where i can read this up. Finally i would like to know if it is possible to add the clickhandler afterwards i appended the child event and if that way is recommended. Thanks it advance for help.
kuku
When you call add(), Widget.onAttach() is called on the widget that is being added to the panel. onAttach does some work to register the widget to receive events. appendChild() simply attaches one DOM element to another and does nothing else. You should be able to get events working in the second case by doing this:
Element element = testWidget.getElement();
RootPanel.getBodyElement().appendChild(element);
DOM.sinkEvents(element,
Event.getTypeInt(ClickEvent.getType().getName())
| DOM.getEventsSunk(element);
However, I haven't tested this and I wouldn't recommend that you use it in a real application. Using add() is definitely preferred, using appendChild() in this way has no advantages and may lead to unexpected behaviour.