using the MVC pattern for the client side faced me the problem that I
could not find an event system in GWT. If I have a modell e.g. for a
login session, I cannot raise my own events like loginSucceded to
update my views. So I decided to implement the observer pattern and my
own events managed by an EventManager class. The EventManager class
should be able to attach listeners to a certain event type but I
discovered, that the jse Object.getClass() function is not present.
According to some posts I found out that I could use
EventManager.attach(GWT.getTypeName(new Event()), MyListener) to
implement this behaviour but it does not feel right to create a new
event just to register a listener.
Is there any other way to get the class type without creating an
instance? Maybe you know another way to use user-defined events?
regards,
Dominik
why you need getClass() and all that stuff?
// EVENT
package com.mycompany.project.client;
import java.util.EventObject;
import com.google.gwt.core.client.GWT;
public abstract class CustomEventObject extends EventObject {
protected String type;
public Object data;
public CustomEventObject(Object source) {
super(source);
}
public String getType() {
return type;
}
/* @Ovveride */
public Object getSource() {
return super.getSource();
}
/* @Override */
public String toString() {
return "Event: " + GWT.getTypeName(this) + " type: " + getType()
+ " target: " + GWT.getTypeName(getSource());
}
}
// LISTENER
package com.mycompany.project.client;
import java.util.EventListener;
public interface CustomEventListener extends EventListener {
public void onEvent(CustomEventObject event);
}
// EVENT MANAGER
package com.mycompany.project.client;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
public class EventManager {
private static final EventManager instance = new EventManager();
private static final Map listeners = new HashMap();
public static EventManager getInstance() {
return instance;
}
public void addEventListener(String type, CustomEventListener
listener) {
List typeListeners = null;
if (listeners.containsKey(type) == false) {
listeners.put(type, new EventListenersCollection());
}
typeListeners = (List) listeners.get(type);
typeListeners.add(listener);
}
public void removeEventListener(String type, CustomEventListener
listener) {
List typeListeners = null;
if (listeners.containsKey(type) == true) {
typeListeners = (List) listeners.get(type);
typeListeners.remove(listener);
}
}
public void dispatchEvent(final CustomEventObject event) {
if (listeners.containsKey(event.getType()) == true) {
final EventListenersCollection typeListeners =
(EventListenersCollection) listeners
.get(event.getType());
DeferredCommand.addCommand(new Command() {
public void execute() {
typeListeners.onEvent(event);
}
});
}
}
static class EventListenersCollection extends ArrayList {
private static final long serialVersionUID = 3425680778337656685L;
public void onEvent(CustomEventObject event) {
for (Iterator it = iterator(); it.hasNext();) {
CustomEventListener listener = (CustomEventListener) it.next();
listener.onEvent(event);
}
}
}
}
///
now example concrete events/listeners;
package com.mycompany.project.client;
public class LoginEvent extends CustomEventObject {
private static final long serialVersionUID = -6066074958503856659L;
public static final String LOGIN_EVENT = "loginEvent";
private String login;
public LoginEvent(Object source, String login) {
super(source);
this.type = LOGIN_EVENT;
this.login = login;
}
public String getLogin() {
return login;
}
}
package com.mycompany.project.client;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
public class LoginEventListener implements CustomEventListener {
public void onEvent(CustomEventObject event) {
System.out.println(event.toString());
LoginEvent loginEvent = (LoginEvent) event;
final Button btn = (Button) loginEvent.getSource();
final String btnLabel = btn.getText();
btn.setEnabled(false);
btn.setText("Validating...");
final String userLogin = loginEvent.getLogin();
Timer t = new Timer() {
public void run() {
btn.setEnabled(true);
btn.setText(btnLabel);
Window.alert("Connected as: " + userLogin);
}
};
t.schedule(2000);
}
}
package com.mycompany.project.client;
public class MyCustomEvent extends CustomEventObject {
private static final long serialVersionUID = 4254389761616981854L;
public static final String CUSTOM_ON_LOAD_EVENT =
"customOnLoadEvent";
public static final String CUSTOM_LOADED_EVENT = "customLoadedEvent";
public static final String CUSTOM_BROWSER_RESIZED_EVENT =
"customBrowserResizedEvent";
public MyCustomEvent(String type, Object source) {
super(source);
this.type = type;
}
}
example usage:
package com.mycompany.project.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class ExampleModule implements EntryPoint {
OnLoadListener onLoadListener;
public ExampleModule() {
onLoadListener = new OnLoadListener() {
public void onEvent(CustomEventObject event) {
super.onEvent(event);
Window.alert("Loaded");
}
};
EventManager.getInstance().addEventListener(OnLoadEvent.ON_LOAD_EVENT,
onLoadListener);
}
public void onModuleLoad() {
RootPanel rootPanel = RootPanel.get();
final VerticalPanel submitForm = new VerticalPanel();
rootPanel.add(submitForm, 5, 5);
final HorizontalPanel horizontalPanel = new HorizontalPanel();
submitForm.add(horizontalPanel);
horizontalPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
final Label loginLabel = new Label("Login:");
horizontalPanel.add(loginLabel);
final TextBox loginInput = new TextBox();
horizontalPanel.add(loginInput);
loginInput.setWidth("150px");
loginInput.setName("login");
final Button loginButton = new Button();
submitForm.add(loginButton);
loginButton.setWidth("150px");
submitForm.setCellHorizontalAlignment(loginButton,
HasHorizontalAlignment.ALIGN_RIGHT);
loginButton.addClickListener(new ClickListener() {
public void onClick(final Widget sender) {
if (loginInput.getText() != null
&& loginInput.getText().trim().length() > 0) {
// DISPATCH LOGIN EVENT
EventManager.getInstance().dispatchEvent(
new LoginEvent(sender, loginInput.getText()));
}
}
});
loginButton.setText("LOGIN");
//
EventManager manager = EventManager.getInstance();
// ADD LOGIN EVENT LISTENER
manager.addEventListener(LoginEvent.LOGIN_EVENT,
new LoginEventListener());
//
CustomEventListener customListener = new CustomEventListener() {
public void onEvent(CustomEventObject event) {
System.out.println(event.toString());
System.out.println("Hello from " + event.data.toString());
};
};
// ADD CUSTOM EVENT
manager.addEventListener(MyCustomEvent.CUSTOM_LOADED_EVENT,
customListener);
CustomEventObject event = new OnLoadEvent(this);
CustomEventObject customEvent = new MyCustomEvent(
MyCustomEvent.CUSTOM_LOADED_EVENT, this);
customEvent.data = "Peter";
//
manager.dispatchEvent(customEvent);
manager.dispatchEvent(event);
}
/* @Override */
public String toString() {
return GWT.getTypeName(this);
}
}
// OUTPUT:
Event: com.mycompany.project.client.MyCustomEvent type:
customLoadedEvent target: com.mycompany.project.client.ExampleModule
Hello from Peter
Event: com.mycompany.project.client.OnLoadEvent type: onLoadEvent
target: com.mycompany.project.client.ExampleModule
Event: com.mycompany.project.client.LoginEvent type: loginEvent
target: com.google.gwt.user.client.ui.Button
and handling from LoginListener should be delegated to e.g. command
pattern,
regards,
Peter
On Nov 4, 6:55 pm, "blys...@googlemail.com" <blys...@googlemail.com>
wrote:
thanks for the nice example, I definitely learned a few things of it!
The point is, I wanted to map the listeners to the event class type,
so there would be no need to store the type in a string like you did
in e.g. LOGIN_EVENT. Imagine you rename your EventClass, you might
have to rename the variable names and the strings as well to make it
fit a new naming.
On the other hand, your solution is more flexible and powerful in
general usage.
It would be nice to see other implementations on this topic, just to
see different ideas and perspectives.
pozdrawiam
Dominik
On Nov 5, 5:08 am, Peter Blazejewicz <peter.blazejew...@gmail.com>
wrote:
the idea of haveing "type" field is that given instance of Event
object can be used for different purposes,
say I don't need to declare only single type,
if I make it not strictly realted to existing java evnet objects and
declare it that way:
package com.mycompany.project.client;
import com.google.gwt.core.client.GWT;
public class GlaxEvent {
private String type;
public Object data;
public GlaxEvent(String type) {
this.type = type;
}
public void dispatch() {
GlaxEventManager.getInstance().dispatchEvent(this);
}
public String getType() {
return type;
}
/* @Override */
public String toString() {
return "Event: " + GWT.getTypeName(this) + " type: " + getType();
}
}
(supposing there is a "Glax" framework"),
then I can define as many types for given event as I want:
event = new GlaxEvent(ON_LOAD_EVENT);
manager.addEventListener(ON_LOAD_EVENT, myListener);
event = new GlaxEVent(ON_FOCUS_EVENT);
manager.addEventListener(ON_FOCUS_EVENT, myListener);
manager.addEventListener(ON_FOCUS_EVENT, myOtherListener);
and even implement concrete types that way:
package com.mycompany.project.client;
public class LoginEvent extends GlaxEvent {
public static final String LOGIN_EVENT = "loginEvent";
public String username;
public String password;
public LoginEvent(String username, String password) {
super(LOGIN_EVENT);
this.username = username;
this.password = password;
}
}
There are IDE tools that allow to avoid issues with class name
refactoring,
there are JUnit tests that allow to avoid issues with class fields
refactoring,
I would be glad to see getClass() in jre emulation but I can live
without that,
regards,
Peter
On Nov 5, 1:45 pm, "blys...@googlemail.com" <blys...@googlemail.com>
wrote:
> ...
>
> read more »
hi Dominik,
the idea of haveing "type" field is that given instance of Event
object can be used for different purposes,
say I don't need to declare only single type,
if I make it not strictly realted to existing java evnet objects and
declare it that way:import com.google.gwt.core.client.GWT;
package com.mycompany.project.client;
public class GlaxEvent {
private String type;
public Object data;
public GlaxEvent(String type) {
this.type = type;
}
public void dispatch() {
GlaxEventManager.getInstance().dispatchEvent(this);}/* @Override */
public String getType() {
return type;
}
public String toString() {
return "Event: " + GWT.getTypeName (this) + " type: " + getType();
> > if ( loginInput.getText() != null
> > && loginInput.getText().trim().length() > 0) {
> > // DISPATCH LOGIN EVENT
> > EventManager.getInstance().dispatchEvent(
> > new LoginEvent(sender, loginInput.getText()));
> > }
> > }
> > });
> > loginButton.setText("LOGIN");
> > //
> > EventManager manager = EventManager.getInstance();
> > // ADD LOGIN EVENT LISTENER
> > manager.addEventListener(LoginEvent.LOGIN_EVENT,
> > new LoginEventListener());
> > //
> > CustomEventListener customListener = new CustomEventListener() {
>
> ...
>
> read more >>