Tuesday, April 28, 2009

Gwt Composite Widget with Event Listeners

In this article we will discuss of creating our own widgets and adding event listeners to them. So lets start creating a sampleWidget.

We will write a sample widget which extends Composite class and implements SouceClickEvents.

By implementing this interface we will allow the widget to source the events defined by the ClickListener interfaces. Similarly we have SouceMouseEvents,SourceFocusEvents and even SouceKeyBoardEvents and other.we can implement any SouceEvent interface according to our requirement.
In addition to the above classes , we need to know about the ClickListenerCollection class [for click events]which is a helper class for the implementers of the SourceClickEvents classes. This subclass of ArrayList assumes that all objects added to it will be of type ClickListener.

We will use the ClickListenerCollection class in our widget. The below is the code for creating a widget with click listeners

public class SampleWidget extends Composite implements SourcesClickEvents {

private HorizontalPanel panel;
private ClickListenerCollection listenerCollection;

public SampleWidget() {
panel=new HorizontalPanel();
panel.add(new Label("This is Sample Widget"));
panel.setBorderWidth(1);
initWidget(panel);
sinkEvents(Event.ONCLICK);
}


public void addClickListener(ClickListener listener) {
if(listenerCollection==null) {
listenerCollection=new ClickListenerCollection();
}
listenerCollection.add(listener);
}


public void removeClickListener(ClickListener listener) {
if(listenerCollection!=null) {
listenerCollection.remove(listener);
}
}

public void onBrowserEvent(Event event) {
int eventType=DOM.eventGetType(event);
switch(eventType) {
case Event.ONCLICK:listenerCollection.fireClick(this);
}
}
}

Let us move through the code .

As u can see in the constructor , I have created a HorizontalPanel and added a label to it.
I initialized the horizontalPanel.i have written a method called sinkEvents();.This method allows us to add a set of events to be sunk by our widget. That is we are adding a set of events to our widget.

When we implement the SourceClickEvents , we will be needed to override 2 methods
addClickListener() and removeClickListener().

In the addClickListener() method I checked whether ClickListenerCollection is initialized or not . if not initialize it and add the listener to the collection.in removeClickListener() , I removed the listener.

Meanwhile when we sinkevents() ,we need to override the onBrowserEvent() method so that we can check the event type and call appropriate event .this method allows us to fire an event whenever the browser receives an event.

In our example I checked for the onClick event .when the browser receives the OnClick event I allowed to made our widget to generate fireClick() event.

Now we can use the above code as below,

SampleWidget widget=new SampleWidget();
widget.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
Window.alert("You Clicked On The Sample Widget");
}
});
Read More

Composite Widgets In Gwt

Hi EveryOne , today we will be working on creating our own widgets in Gwt.actually there are 3 ways creating our own widgets in gwt .

1.by extending a Class called “Composite”

2. by extending any Widget class like “button” , “label”

3.by extending Widget class.

Today we will see how we can create a new widget by using these 3 types

1.By extending Composite widget

When we extends a Composite class to create a new widget , we need to call the initWidget(widget) method compulsory in their constructors as it initializes the widget.

Lets take a look at the sample example of creating a new widget which contains a button and a label set to a horizontalPanel.

public class SampleWidget extends Composite {

private Button smallButton;

private Label myLabel;

private HorizontalPanel panel;

public SampleWidget() {

panel=new HorizontalPanel();

panel.setBorderWidth(1);

smallButton=new Button("Sample Button",new ClickListener() {

public void onClick(Widget sender) {

Window.alert("You Clicked On Sample Button");

}

});

myLabel=new Label("Sample Label");

panel.add(myLabel);

panel.add(smallButton);

initWidget(panel);

}

}

In the above code , I just created a button and a label and added them to the horizontalpanel.i called the initWidget(panel) in order to initialize the panel.

Now we can use the widget like ,

SampleWidget widget=new SampleWidget();

U can create a new as you like with different widgets in it.

2. the second way of creating a new widget by extending any widget class like

Button , Label e.t.c . below is the code snippet where I extended the Button class.

public class SampleWidget extends Button {

SampleWidget(){

this.setText("Sample Widget");

this.addClickListener(new ClickListener() {

public void onClick(Widget sender) {

Window.alert("You Clicked On The Sample Widget");

}

});

}

}

U can use this similarly as above

SampleWidget widget=new SampleWidget();

3. the third one is by extending Widget class.

public class SampleWidget extends Widget {

SampleWidget(){

this.setElement(DOM.createButton());

getElement().setInnerHTML("Sample Widget");

}

}

In this class , I have extended the widget class.in order to create a button element DOM.createButton() and added by using the method setElement() method, I have used DOM(document Object Model) in order to work.

This setElement(DOM.createButton()); method wraps a button element

I set the text for the button by using getElement().setInnerHtml(“SampleWidget”);



In next article we will discuss of creating our own widget with event listeners.

Read More

Wednesday, April 15, 2009

Internationalization

Today we will be seeing how to use Internationalization in a Gwt Application.in order to use Internationalization file in Gwt we need to write a properties file and access it during runtime.

Firstly we will create a properties file with the name “MyConstants.properties” .
This file contains 2 key-value pairs


My_Name=jagadesh
Your_Name=ashok


In Gwt we will create a multi-way of accessing a Constants file. We will be creating a java Interface file which extends another interface called “Constants”. According to the Gwt api, this interface allows us to bind the properties file at compile time .

We will create a Interface called “MyConstants.java”

public interface MyConstants extends Constants {
String My_Name();
String Your_Name();
}

We will be accessing the constants by creating an instance of the java file by using
GWT.create(MyConstants.class);

Now I will access the constants in my Application as ,

public class Application implements EntryPoint {
private MyConstants constants;
public Button showMyName,showYourName;

//OnModuleLoad
public void onModuleLoad() {

constants=(MyConstants)GWT.create(MyConstants.class);

showMyName=new Button("ShowMyName");
showYourName=new Button("ShowYourName");

showMyName.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
Window.alert(constants.My_Name());
}
});

showYourName.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
Window.alert(constants.Your_Name());
}
});

RootPanel.get().add(showMyName);
RootPanel.get().add(showYourName);


}//OnModuleLoad()
}

You can see how I access the properties .

In order to use Internationalization , we need to add the package to our Gwt.xml file

<inherits name="com.google.gwt.i18n.I18N"/>

Another way to use constants with the Gwt is by extending the Messages Interface. This allows us to send arguments at dynamic time where properties are populated with the arguments sent by us. Consider the sample example,

My Properties file looks like this

turnsLeft = Turns left for player {0}:{1}
currentScore = Current score: {0}

in which the turnsLeft takes 2 arguments and second one takes one argument.

Now my Constants interface look as

public interface MyConstants extends Messages {

String turnsLeft(String username, int numTurns);
String currentScore(int numPoints);

}

And from my OnModuleLoad() load I will call as ,

public class Application implements EntryPoint {
private MyConstants constants;
public Button showMyName,showYourName;

//OnModuleLoad
public void onModuleLoad() {

constants=(MyConstants)GWT.create(MyConstants.class);

showMyName=new Button("ShowMyName");
showYourName=new Button("ShowYourName");

showMyName.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
Window.alert(constants.turnsLeft("jagadesh", 3));
}
});

showYourName.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
//Window.alert(constants.Your_Name());
}
});

RootPanel.get().add(showMyName);
RootPanel.get().add(showYourName);


}//OnModuleLoad()
}

You can check the Response.

U need to take care at one thing , Compile-time checks are performed to ensure that the number of placeholders in a message template (e.g. {0}) matches the number of parameters supplied.

Now lets write a sample code on how to use multiple locale. We may be at a stage where we need to develop a application for multiple language . now iam going to write a sample application where it displays constants for language ‘s English and French.

Let start creating properties files both English and French.

MyConstants.properties

locale=en
turnsLeft = Turns left for player {0}:{1}
currentScore = Current score: {0}

MyConstans_fr.properties

locale=fr
turnsLeft = Turns left for player For French {0}:{1}
currentScore = Current score For French : {0}


u can see the difference for both the constants file. for English the turnsLeft is “Turns left for player {0}:{1}” and for French is “Turns left for player For French {0}:{1}” .

now iam creating a MyConstants Interface.

public interface MyConstants extends Messages {
String locale();
String turnsLeft(String username, int numTurns);
String currentScore(int numPoints);
}

And in my Application.java file

public class Application implements EntryPoint {
private MyConstants constants;
public Button showMyName,showYourName;

//OnModuleLoad
public void onModuleLoad() {

constants=(MyConstants)GWT.create(MyConstants.class);

showMyName=new Button("ShowMyName");
showYourName=new Button("ShowYourName");

showMyName.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
Window.alert(constants.turnsLeft("jagadesh", 3));
}
});

showYourName.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
//Window.alert(constants.Your_Name());
}
});

RootPanel.get().add(showMyName);
RootPanel.get().add(showYourName);
}//OnModuleLoad()
}

In order to run the application with different locales . we need to add the locale definations in .gwt.xml file.



I added the locale definition for French and English. When u run the application u can see the response for English ,




And if you want to see the response for French format , u can just add the locale string to the url in hosted mode browser window .for example , if u have
http://localhost:8888/com.example.Application/Application.html and if u add the locale it looks
http://localhost:8888/com.example.Application/Application.html?locale=fr.when u run the application with url above the application will load the French locale file and response will be like this.




We can add the locale String to the properties file to get which locale is currently in use rather than getting it from the java script using jsni.
Read More

Tuesday, April 14, 2009

Java Script Native Interface-3

In this 3 part of jsni we will see some more parts of java Script native interface. As we have seen in out previous blogs how to access a java script function written in Html page from out Gwt code. So see some more complex examples,

We can even assign a value to the existing field in the Html page , consider the sample code,

I have just placed a input element in html page

<input type="text" name=firstName value="Click Me"/>

So now from my Gwt application , I can assign the value for the “firstName” element by using

public native static void setValue(String s)/*-{
$wnd.firstName.value=s;
}-*/;


Some times we need to include a 3rd party java script file into out application.The easiest way would be to use the application .Gwt.xml .We can use

What happens when we include a 3rd party java script file into our module tag.This indicates the Gwt compiler that the file should be loaded before the application get started.The file is to be placed inside the public package.

Lets create a sample example as how to access a 3rd party java script library

Lets say we have written a java script file called “Script.js” .the contents will very simple

function alertBuddy(){
alert("This Is A Call From Gwt");
}

Save this as “Script.js” and save the file in public package

So now we are going to access the java Script functions that are defined in other Script file and we are going to access them from out Gwt Code.

Include the above <Script> code in your application .gwt.xml file.

The src tag is self-explanatory. It tells the location of the JavaScript file. This code is a java script written in Jsni code. This return “true” if the file loaded correctly or false if not.Even though we can include the src file in the plain html file, but we want the script to be loaded and work by the single threaded java script interpreter.

So now in out Gwt application we can call the function defined in our “Script.js” file like

public class JsniApplication implements EntryPoint {

public void onModuleLoad() {

RootPanel.get().add(new Button("Click Me", new ClickListener() {
public void onClick(Widget sender) {
callMe();
}
}));

}//Close of OnModuleLoad()


public native static void callMe()/*-{
$wnd.alertBuddy();
}-*/;

}

U can see I have just written a jsni method to call the function I have written.


Now we be looking at the magic Overlay Types . There is an object called “JavaScriptObject” in Gwt which helps to represent as a form java Object.Many times wee need to include java script methods deeply to interact with the data. Some times it becomes more complicate, so we need a Object which interacts with the Java script object and should be usefull as a java Object . JavaScriptObject gives us the flexiablilty.

An Overlay Type is defined as a sub-class of JavaScriptObjecct.An Overlay type can be describes as a Java Object overlaying on the Java Script Object.

Restriction’s of an OverLay Type

All Methods in a overlay type should be final or a member of a final class or private , since these methods should not be overridden.

Overlay types cannot implement interfaces that define methods.
Overlay types cannot have instance methods or instance fields.
Should contain a protected, zero-args constructor. This constructor should be empty.
New Keyword cannot be used with overlay types.This eliminates creating a new Instance using the new Keyword. A new Instance can only be generated from the jsni.

Now lets check a sample code of accessing a json data from java script using Overlay types,

Iam creating a OverLay Object called “person”.here is how Person class looks

public class Person extends JavaScriptObject {

protected Person(){

}

public native final String getFirstName()
/*-{
return this.firstName;
}-*/;

public native final String getLastName()
/*-{
return this.lastName;
}-*/;

}


Now in out Application.html file , create a script tag and place the
Array as follows.

<script type="text/javascript">

var jsonData = [
{ "firstName" : "Jimmy", "lastName" : "Webber" }
];

</script>

This is an example of json data . iam now returning a json object containing both “firstName” and “lastName”.In my Application.java class looks like this ,

public class Application implements EntryPoint {

//OnModuleLoad
public void onModuleLoad() {
RootPanel.get().add(new Button("Click Me", new ClickListener() {
public void onClick(Widget sender) {
Person p=getPersonData();
Window.alert(p.getFirstName());

}
}));
}//OnModuleLoad()

public static native Person getPersonData()/*-{
return $wnd.jsonData[0];
}-*/;

}

Hi by this I complete the basics of jsni part , you can get more information about jsni from gwt Official Site.
Read More

Thursday, April 9, 2009

Java Native Script Interface-2

In my next article of Jsni ,we will be discussing some more points on jsni and I will show you a few more code samples.

Now lets look at an example of accessing the functions defined in the java script to out Gwt page . for this lets modify a html page “Application.html” generated in our Gwt project.

<script type="text/javascript" language="javascript" src="com.example.Application.nocache.js">script>

<script type="text/javascript">

function getFirstName() {

return form.firstName.value;

}

function getLastName(){

return form.lastName.value;

}

</script>

<head>

<body>

<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0">iframe>

<form name="form">

<b>First Nameb>:<input type=text name="firstName" value="">br>

<b>Last Nameb>:<input type=text name="lastName" value="">br>

</form>

</body>

Just copy these both script and body elements into your html file. I have just placed 2 input type elements as firstName and lastName . I have written 2 function’s in java script as getFirstName() and getLastName() which return both the values respectively.So now iam going to access both the methods and display the values that are entered in the html page.

Here Is the code in OnModuleLoad(),

public class Application implements EntryPoint {

//OnModuleLoad

public void onModuleLoad() {

RootPanel.get().add(new Button("Click Me", new ClickListener() {

public void onClick(Widget sender) {

Window.alert(getFirstName());

Window.alert(getLastName());

}

}));

}//OnModuleLoad()

public static native String getFirstName() /*-{

return $wnd.getFirstName();

}-*/;

public static native String getLastName() /*-{

return $wnd.getLastName();

}-*/;

}

In rare cases the methods that are provided by the gwt may not be sufficient for accessing the browser . so we need to write the jsni methods to access the browser window , documents. But the way Gwt loads doesnot allow to directly access the Window and Document . so Gwt provides variables $wnd and $doc for accessing the browser Window and Document as you can see in the above example. In the above Gwt code I have written 2 jsni scripts which access functions defined in java script by using $wnd. $wnd and $doc are representations of java Script Window and Document respectively

Returning Strings , Booleans are simpler from java script to java as they convert directly according to the type..check I have just said to return the values entered.One main we need to take care is when returning “null” value , because null in java script and java are completely different.java script returns “undefined” as a “null” . java script “undefined” is completely differently from java “null” . so we need to manually check whether the value returned from jsni method is null or undefined.unpredictable results can occur if it is not clearly maintained

According to Gwt site, When returning a undefined value from jsni method , the following idiom is to be used

retrun (value==null)?null:value; to avoid returning “undefined”

now lets check another code snippet to acces methods and arguments sent ,

public class Application implements EntryPoint {

public void doSomeThingWithString(String s) {

Window.alert(s);

}

public static void doSomeThingWithInt(int i) {

Window.alert(String.valueOf(i));

}

//OnModuleLoad

public void onModuleLoad() {

RootPanel.get().add(new Button("Click Me", new ClickListener() {

public void onClick(Widget sender) {

doSomeThing("jagadesh",10);

}

}));

}//OnModuleLoad()

public native void doSomeThing(String s,int i)/*-{

@com.example.client.Application::doSomeThingWithInt(I)(i);

this.@com.example.client.Application::doSomeThingWithString(Ljava/lang/String;)(s);

}-*/;

}

Handling Exceptions : it is better to handle exceptions belonging to java script in jsni methods and java exceptions in java code . since when an exception occurred in the jsni method and comes out to java code , the exception becomes one and only “javaScriptException” .so it is always better to use try –catch blocks and use methods to in java script to handle the exception.

Read More