06 June 2011

Using GWT Deferred-binding to use different implementation classes per browser

Salam,

Some times you face a situation where you need to do some think in GWT code like that:

if (Window.Navigator.getUserAgent().contains("Gecko")) // 
{
   // do some thing
}else if (Window.Navigator.getUserAgent().contains("MSIE 8.0")) // IE 8
{
   // do other thing
}else
{
   // do default
}

This is good in some cases, but in others, you should find a way to apply polymorphism in GWT.

The concept of polymorphism is applied using Deferred Binding, let's see an example.

Create a new GWT project and add a module "com.mycompany.project.client.ImageViewer"

First, Create a new Class "SayHello":
package com.mycompany.project.client;


public class SayHello
{
    public String sayHello()
    {
        return "Default";
    }
}


And create two classes "SayHelloGecko" and "SayHelloIE":

package com.mycompany.project.client;

public class SayHelloGecko extends SayHello
{
    @Override
    public String sayHello()
    {
        return "Gecko";
    }
}


package com.mycompany.project.client;

public class SayhelloIE extends SayHello
{
    @Override
    public String sayHello()
    {
        return "IE";
    }
}


And here's the code of the EntryPoint class:

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.HTML;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class ImageViewer implements EntryPoint
{
    public void onModuleLoad()
    {
        System.out.println(Window.Navigator.getUserAgent());
        RootPanel rootPanel = RootPanel.get();
        rootPanel.add(new HTML(((SayHello)GWT.create(SayHello.class)).sayHello()));
    }
}


Now, let's modify "ImageViewer.gwt.xml":
<module>
    <inherits name="com.google.gwt.user.User" />
    <inherits name="com.google.gwt.user.theme.standard.Standard" />
    <entry-point class="com.mycompany.project.client.ImageViewer" />

    <!-- Fall through to this rule is the browser isn't IE or Mozilla -->
    <replace-with class="com.mycompany.project.client.SayHello">
        <when-type-is class="com.mycompany.project.client.SayHello" />
    </replace-with>

    <!-- Mozilla needs a different SayHello implementation -->
    <replace-with class="com.mycompany.project.client.SayHelloGecko">
        <when-type-is class="com.mycompany.project.client.SayHello" />
        <any>
            <when-property-is name="user.agent" value="gecko" />
            <when-property-is name="user.agent" value="gecko1_8" />
        </any>
    </replace-with>

    <!-- IE has a completely different SayHello implementation -->
    <replace-with class="com.mycompany.project.client.SayhelloIE">
        <when-type-is class="com.mycompany.project.client.SayHello" />
        <when-property-is name="user.agent" value="ie8" />
    </replace-with>
</module>



Now let's test in FireFox:

And now in IE 8:

And in IE6:

1 comment:

Saeed Zarinfam said...

This is very nice sample.