GWT Widget.addHandler - gwt

I am trying to utilize Widget.addHandler(). However, the handler never gets called. Below is my sample code. What do I need to change to fix this?
My Handler Implementation:
public class CustomMouseMoveHandler
extends GwtEvent.Type<MouseMoveHandler>
implements MouseMoveHandler
{
#Override
public void onMouseMove(MouseMoveEvent event) {
System.out.println("----> onMouseMove.");
}
}
My EntryPoint.OnModuleLoad():
ContentPanel cp = new ContentPanel();
cp.setHeaderVisible(false);
cp.setHeight(com.google.gwt.user.client.Window.getClientHeight());
CustomMouseMoveHandler handler = new CustomMouseMoveHandler();
cp.addHandler(handler, handler);
RootPanel.get().add(cp);
/////
Added on 7/1/2011.
The following complete GWT simple code does not work either (with Jason's hint applied). Please help me out. Thanks
package tut.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class GwtHandler implements EntryPoint, MouseMoveHandler {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
TextArea comp = new TextArea();
comp.setSize("200px", "200px");
comp.setText("Testing Text");
comp.addHandler(this, MouseMoveEvent.getType());
RootPanel.get().add(comp);
}
#Override
public void onMouseMove(MouseMoveEvent event) {
com.google.gwt.user.client.Window.alert("onMouseMove");
}
}

GwtEvent.Type is used to dispatch events based on an event specific and unique object (object equality - == - is used to match event types). Passing your CustomMouseMoveHandler as the Type to addHandler indicates an event type other than that used for MouseMoveEvents (Indeed in this case every CustomMouseMoveHandler would be assigned to a different event Type since each object is different).
Instead of extending GwtEvent.Type<MouseMoveHandler> in your handler you need to get the event Type from MouseMoveEvent itself (using the static getType() method).
Don't extend GwtEvent.Type in your CustomMouseMoveHandler:
public class CustomMouseMoveHandler
implements MouseMoveHandler
{
...
}
And to add the handler:
cp.addDomHandler(handler, MouseMoveEvent.getType());

DomEvents have to be registered using addDomHandler, or you have to sinkEvents for their event type. addDomHandler is a shortcut for sinkEvents+addHandler.

Here's how I solved my problem. I wanted to add handlers to a NumberLabel. This is what worked:
final NumberLabel<Long> label = new NumberLabel<Long>();
label.setValue(2000l);
label.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
MouseOverHandler handler = new MouseOverHandler() {
public void onMouseOver(MouseOverEvent event) {
System.out.println("mouse over");
}
};
Widget widget = label.asWidget();
widget.addDomHandler(handler, MouseOverEvent.getType());
Treating is as a Widget did the trick.
By the way, System.out.println worked.

Related

GWT / GWTBootstrap3 Extending Tooltip: Exception with addHandler in C'tor

I created the following class as an extension of gwtbootstrap3 Tooltip. There are at least 2 reasons why I want to derive the gwtbootstrap3 Tooltip class:
1.) Add a onWindowClosing Handler when the tooltip is shown so I can hide() the tooltip when the user leaves the page (this is - as far as I understand - a feature which is also not supported in Bootstrap, is it?)
2.) I want to prevent Tooltips from being shown when the page is displayed on iPads or iPhones as they behave strange when tooltips are involved (first tip shows the tooltip , the second tip executes the button, which is not exactly what the user expects)
Please note that the class given below is still not finished ... but already at this stage I get an exception when adding a handler.
Please also note that it throws an exception no matter what type of Handler (ShowHandler, ShownHandler, etc.) I add.
Any help greatly appreciated.
package com.mypackage.client.widgets.featureWidgets;
import org.gwtbootstrap3.client.shared.event.ShowEvent;
import org.gwtbootstrap3.client.shared.event.ShowHandler;
import org.gwtbootstrap3.client.ui.constants.Trigger;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.ClosingEvent;
public class Tooltip extends org.gwtbootstrap3.client.ui.Tooltip {
private boolean isMobile;
private HandlerRegistration windowClosingHandlerRegistration;
private final Tooltip tooltip;
public Tooltip() {
super();
tooltip = this;
this.addShowHandler(new ShowHandler() {
#Override
public void onShow(final ShowEvent showEvent) {
// TODO Auto-generated method stub
if (windowClosingHandlerRegistration == null) {
windowClosingHandlerRegistration = Window.addWindowClosingHandler(new Window.ClosingHandler() {
#Override
public void onWindowClosing(final ClosingEvent arg0) {
tooltip.hide();
}
});
}
}
});
}
}
When I create a instance of this tooltip using the following:
[...]
<b:ButtonToolBar ui:field="itemButtonToolBar" addStyleNames="hiddenPrint">
<b:ButtonGroup>
<a:Tooltip title="{msgs.buttomTitleAddItem}" container="body">
<b:Button ui:field="addItemButton" icon="PLUS"/>
</a:Tooltip>
[...]
I get the following exception when trying to add the Handler, why?
SEVERE: (TypeError) : Cannot read property 'addHandler_11_g$' of undefinedcom.google.gwt.core.client.JavaScriptException: (TypeError) : Cannot read property 'addHandler_11_g$' of undefined
at Unknown.addShowHandler_2_g$(meetingApp-0.js#26:57195)
at Unknown.Tooltip_6_g$(meetingApp-0.js#8:57685)
at Unknown.build_f_Tooltip2_0_g$(meetingApp-0.js#55:31606)
at Unknown.get_f_Tooltip2_0_g$(meetingApp-0.js#15:31831)
at Unknown.build_f_ButtonGroup1_0_g$(meetingApp-0.js#38:31524)
at Unknown.get_f_ButtonGroup1_0_g$(meetingApp-0.js#15:31791)
at Unknown.build_itemButtonToolBar_0_g$(meetingApp-0.js#41:31696)
at Unknown.get_itemButtonToolBar_0_g$(meetingApp-0.js#15:31876)
at Unknown.createAndBindUi_58_g$(meetingApp-0.js#91:31437)
at Unknown.createAndBindUi_59_g$(meetingApp-0.js#15:31441)
at Unknown.ItemButtonGroup_2_g$(meetingApp-0.js#56:30733)
at Unknown.$init_589_g$(meetingApp-0.js#31:37722)
at Unknown.SummaryWidget_1_g$(meetingApp-0.js#8:37686)
at Unknown.loadSummaryWidget_0_g$(meetingApp-0.js#26:4991)
at Unknown.setSummary_1_g$(meetingApp-0.js#10:5028)
at Unknown.onSuccess_8_g$(meetingApp-0.js#21:3312)
at Unknown.onSuccess_9_g$(meetingApp-0.js#8:3317)
at Unknown.onResponseReceived_0_g$(meetingApp-0.js#26:156917)
at Unknown.fireOnResponseReceived_0_g$(meetingApp-0.js#17:129224)
at Unknown.onReadyStateChange_0_g$(meetingApp-0.js#28:129532)
at Unknown.<anonymous>(meetingApp-0.js#18:172082)
at Unknown.apply_0_g$(meetingApp-0.js#28:104636)
at Unknown.entry0_0_g$(meetingApp-0.js#16:104692)
at Unknown.<anonymous>(meetingApp-0.js#14:104672)
Disclaimer: I use gwtbootstrap3 v0.9.2 and I believe it's the same version as you use as I got the same error for your code.
A Tooltip needs a Widget to operate on (in your case the Button is a Tooltip's widget). Tooltip uses it's widget to do all events handling - see source code for addShowHandler for example.
Now you need to understand how the whole structure is built:
first the Tooltip is created (wit no widget set)
then the Button is created
Tooltip's setWidget method is called to set the button as a widget
So when you use addShowHandler method in your constructor, you actually call widget.addHandler while widget is null.
You can check it by Window.alert(tooltip.getWidget() == null ? "null" : tooltip.getWidget().toString());
There are few ways to make it work (the later the better):
wait for DOM structure to be built by scheduling a deferred command (if you are sure that the widget will be eventually set):
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
// set up events handling
}
});
override setWidget method (note thet there are two methods: setWidget(Widget w) and setWidget(IsWidget w)):
#Override
public void setWidget(Widget w) {
super.setWidget(w);
// set up events handling
}
you don't need to addWindowClosingHandler in the showEvent handler, you can do it directly in the constructor:
public class Tooltip extends org.gwtbootstrap3.client.ui.Tooltip {
private boolean isMobile;
private final Tooltip tooltip;
public Tooltip() {
super();
tooltip = this;
Window.addWindowClosingHandler(new Window.ClosingHandler() {
#Override
public void onWindowClosing(final ClosingEvent arg0) {
tooltip.hide();
}
});
}
}

Resty-GWT custom callback on async start and end

I use resty gwt for all server communication. I would like some indicator that would show the operation is in progress.
I consider 2 aproaches:
progressbar, which will show in progress percentage;
animation, that will be showed while operation is in progress, but without any percantage.
I've assumed that I need to add custom filter with callback.
I would like to fire events like: RestyGwtComunicationStart and RestyGwtComunicationEnd, or callback to fire onComunicationStarted and
onComunicationEnded. I would like to have this declared in one place, RestyGWT Dispatcher configuration. Also if there was an error I would like to fetch the error.
But I don't know where to start. There is no word about it in documentations.
Can I ask You for help? How can I do this?
So if you want to know that a request has been sent it is up to you in your GWT app to treat that. You can send an event when you trigger your request. You have multiple way of doing this.
Have a look at Request Dispatcher inside the doc https://resty-gwt.github.io/documentation/restygwt-user-guide.html
Then if you want to get progress info, as HTTP calls are synchronous. So there is no way to do this easily.
The way I have been doing it is the following:
1) Create a first call to initiate a processing on the backend with a POST, this will return the ID of your processing
2) Then do a GET on your processing ID that will return the progress. Once the progress is 100% it will return the ID of the result
3) GET the result with the result ID
(You can mix 2 and 3 together eventually and return result when progress is 100% in the same DTO)
Another option is to replace 2) by pushing info from backend to front end (html5 websocket)
Someone already did it as a pull-request to resty. Guess you can give it a try:
https://github.com/resty-gwt/resty-gwt/pull/151
Unfortunately "Dispatcher/Callback filters" feature does not described in the official documentation. But I can suggest next solution (this code should be placed in EntryPoint implementation of your module):
public void onModuleLoad() {
//...
//used to show busy indicator before send HTTP request
DispatcherFilter busyIndicatorDispatcherFilter = new DispatcherFilter() {
#Override
public boolean filter(Method method, RequestBuilder builder) {
BusyIndicator.show();
return true;
}
};
//used to show busy indicator after HTTP response recieved
CallbackFilter busyIndicatorCallbackFilter = new CallbackFilter() {
#Override
public RequestCallback filter(Method method, Response response, RequestCallback callback) {
BusyIndicator.hide();
return callback;
}
};
//registering FilterawareDispatcher (and busy indicator filters) as default Dispatcher
Defaults.setDispatcher(new DefaultFilterawareDispatcher(
busyIndicatorDispatcherFilter,
new DefaultDispatcherFilter(new DefaultCallbackFactory(busyIndicatorCallbackFilter))));
//...
}
Unfortunately I did not get adequate answer, So I developed my own solution.
At first I've added Resty configuration RestyGwtConfig to my Module configuration
public class ClientModule extends AbstractPresenterModule {
#Override
protected void configure() {
bind(RestyGwtConfig.class).asEagerSingleton();
install(new DefaultModule.Builder()
.defaultPlace(Routing.HOME.url)
.errorPlace(Routing.ERROR.url)
.unauthorizedPlace(Routing.LOGIN.url)
.tokenFormatter(RouteTokenFormatter.class).build());
install(new AppModule());
install(new GinFactoryModuleBuilder().build(AssistedInjectionFactory.class));
bind(ResourceLoader.class).asEagerSingleton();
}
}
then I've set Custom distpatcher for all my comunication requests of resty gwt.
import org.fusesource.restygwt.client.Defaults;
import org.fusesource.restygwt.client.Resource;
import pl.korbeldaniel.cms.shared.ServiceRouting;
import com.google.gwt.core.client.GWT;
import com.google.inject.Inject;
public class RestyGwtConfig {
#Inject
public RestyGwtConfig(RestyDispatcher dispatcher) {
Defaults.setDispatcher(dispatcher);
}
}
Then I've added custom filter (ProgressIndicatorFilter) to handle communication's start and end callbacks:
import org.fusesource.restygwt.client.Method;
import org.fusesource.restygwt.client.dispatcher.DefaultFilterawareDispatcher;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestException;
import com.google.inject.Inject;
public class RestyDispatcher extends DefaultFilterawareDispatcher {
#Inject
public RestyDispatcher(ProgressIndicatorFilter progressIndicatorFilter) {
addFilter(progressIndicatorFilter);
}
}
in filter class method overriden filter I've added an event trigger (eventBus.fireEvent(new IndicatorEvent("Rest-Gwt Comunication started"));) and registered callback, here is whole code:
import org.fusesource.restygwt.client.Method;
import org.fusesource.restygwt.client.dispatcher.DispatcherFilter;
import pl.korbeldaniel.cms.client.template.progressIndicator.IndicatorEvent;
import com.google.gwt.http.client.RequestBuilder;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
class ProgressIndicatorFilter implements DispatcherFilter {
private AssistedInjectionFactory factory;
private EventBus eventBus;
#Inject
public ProgressIndicatorFilter(AssistedInjectionFactory factory, EventBus eventBus) {
this.factory = factory;
this.eventBus = eventBus;
}
#Override
public boolean filter(Method method, RequestBuilder builder) {
builder.setCallback(factory.createProgressIndicatorCallback(method));
eventBus.fireEvent(new IndicatorEvent("Resty-Gwt Comunication started"));
return true;
}
}
Registering a callback couldn't be done straight forward, like
new ProgressIndicatorDispatcherCallback()
cause I use dependency injection. So I've created a factory to assist injection as follow:
public interface AssistedInjectionFactory {
ProgressIndicatorDispatcherCallback createProgressIndicatorCallback(Method method);
}
Here and here You can find more Assisted Injection info.
Here is the callback code:
class ProgressIndicatorDispatcherCallback implements RequestCallback {
private RequestCallback requestCallback;
private EventBus eventBus;
#Inject
public ProgressIndicatorDispatcherCallback(#Assisted Method method, EventBus eventBus) {
this.requestCallback = method.builder.getCallback();
this.eventBus = eventBus;
}
#Override
public void onResponseReceived(Request request, Response response) {
endComunicationFireIvent();
requestCallback.onResponseReceived(request, response);
}
#Override
public void onError(Request request, Throwable exception) {
endComunicationFireIvent();
requestCallback.onError(request, exception);
}
private void endComunicationFireIvent() {
eventBus.fireEvent(new IndicatorEvent("Rest-Gwt Comunication ended"));
}
}

Getting user data in NewProjectCreationPage in Eclipse Plugin

I have been successful in making a plugin. However now i need that on project creation page i add some more textboxes to get the user information. Also i need to use this information to add into the auto generated .php files made in project directory.
I want to know how can i override the WizardNewProjectCreationPage to add some more textboxes to the already given layout. I am pretty new to plugin development. Here is the code for my custom wizard.
import java.net.URI;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
import rudraxplugin.pages.MyPageOne;
import rudraxplugin.projects.RudraxSupport;
public class CustomProjectNewWizard extends Wizard implements INewWizard, IExecutableExtension {
private WizardNewProjectCreationPage _pageOne;
protected MyPageOne one;
private IConfigurationElement _configurationElement;
public CustomProjectNewWizard() {
// TODO Auto-generated constructor stub
setWindowTitle("RudraX");
}
#Override
public void init(IWorkbench workbench, IStructuredSelection selection) {
// TODO Auto-generated method stub
}
#Override
public void addPages() {
super.addPages();
_pageOne = new WizardNewProjectCreationPage("From Scratch Project Wizard");
_pageOne.setTitle("From Scratch Project");
_pageOne.setDescription("Create something from scratch.");
addPage(one);
addPage(_pageOne);
}
#Override
public boolean performFinish() {
String name = _pageOne.getProjectName();
URI location = null;
if (!_pageOne.useDefaults()) {
location = _pageOne.getLocationURI();
System.err.println("location: " + location.toString()); //$NON-NLS-1$
} // else location == null
RudraxSupport.createProject(name, location);
// Add this
BasicNewProjectResourceWizard.updatePerspective(_configurationElement);
return true;
}
#Override
public void setInitializationData(IConfigurationElement config,
String propertyName, Object data) throws CoreException {
_configurationElement = config;
// TODO Auto-generated method stub
}
}
Ask for any other code required. Any help is appreciated. Thank You.
Instead of using WizardNewProjectCreationPage directly create a new class extending WizardNewProjectCreationPage and override the createControl method to create new controls:
class MyNewProjectCreationPage extends WizardNewProjectCreationPage
{
#Override
public void createControl(Composite parent)
{
super.createControl(parent);
Composite body = (Composite)getControl();
... create new controls here
}
}

afterCompose never executes on initialization

I have a controller that extends window and implments IdSpace, AfterCompose.
But the function afterCompose never executes when the controller is initialized. A cant figure out what I am missing. My code for this part:
DataTemplateWindowController.java
public class DataTemplateWindowController extends Window implements IdSpace, AfterCompose {
...
public DataTemplateWindowController() {
Executions.createComponents("dataTemplate.zul", this, null);
Selectors.wireComponents(this, this, false);
Selectors.wireEventListeners(this, this);
}
#Override
public void afterCompose() {
Do something smart!!
}
}
And the initializetion.
HomeWindowController.java
public class HomeWindowController extends SelectorComposer<Component> {
...
#Wire
Window homeWindow;
DataTemplateWindowController fa2;
public void setDataTemplate() {
fa2 = new FA2WindowController();
fa2.setParent(homeWindow);
}
}
The page loads fine, but the afterCompose function never executes.
I know that i can just avoid implementing AfterCompose and then run the function fa2.afterCompose() after initialization but I expect AfterCompose to be able to do the job for me.
As you can see in the javadoc of AfterCompose (of org.zkoss.zk.ui.ext.AfterCompose) interface :
Implemented by a component if it wants to know when ZK loader created
it. If this interface is implemented, {#link #afterCompose} is called,
after ZK loader creates this component, all of its children, and
assigns all properties defined in the ZUML page. It is so-called
"compose".
So the method : "afterCompose" will never be call automatically by your own java code (the code in your method setDataTemplate() in your example). It will only be called if you use your component in a ZUL page.
And you can also see in the Javadoc of org.zkoss.zk.ui.ext.AfterCompose:
If it is created manually, it is caller's job to invoke {#link#afterCompose}.
If you don't need to set any properties or child in you afterCompose process, just don't use this interface and put your code in the constructor, otherwise, you will have to call it manually when you need it (usually in the doAfterCompose of your SelectorComposer) :
public class HomeWindowController extends SelectorComposer<Component> {
...
#Wire
Window homeWindow;
DataTemplateWindowController fa2;
#Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
setDataTemplate();
}
public void setDataTemplate() {
fa2 = new FA2WindowController();
fa2.setParent(homeWindow);
fa2.afterCompose();
}
}

How to close a window in GWT

I was required to put a "Done" button in a GWT Composite (despite already having the close icon), it should simply close the window upon clicking. Unfortunately, I can't find a .close() method to implement it. How can it be done?
I have a UserDialog class that contains a Composite component, which I named UserComposite. UserDialog extends to CustomDialogBox, which extends to DialogBox class:
public class UserDialog extends CustomDialogBox {
private UserComposite c = new UserComposite();
// more codes here
private FlowPanel getFlowPanel() {
if (p instanceof Panel && c instanceof Composite) {
p.setSize(WIDTH, HEIGHT);
p.add(c);
}
return p;
}
}
and then this is my UserComposite
public class UserComposite extends Composite {
// codes here
#UiHandler("doneButton")
void onDoneButtonClick(ClickEvent event) {
this.removeFromParent();
}
}
I tried removeFromParent() but the UserComposite was only removed from parent which resulted to an empty DialogBox.
You need to hide the dialog, not the composite. One way to do this is to pass a reference to the dialog box to the UserComposite constructor, and then use that reference to call hide() on the dialog. It could be something along these lines:
public class UserDialog extends CustomDialogBox {
private UserComposite c = new UserComposite(this);
...
}
public class UserComposite extends Composite {
private DialogBox parentDialog;
public UserComposite(DialogBox parentDialog) {
this.parentDialog = parentDialog;
}
#UiHandler("doneButton")
void onDoneButtonClick(ClickEvent event) {
parentDialog.hide();
}
}
#Mr. Xymon, By window if you mean instance of PopupPanel or instance of any subclass of PopupPanel, you can use the following :
popupPanel.hide();