Apr 07

Gwt-Ext and Google Maps

Tag: Ext, Gwt, Java, Maps, Programming, WebAbhijeet Maharana @ 9:14 pm

Dahisar on a Google Map

Sometime back, I uploaded few pics to Picasa. While creating an album, it asked for an optional “Location” information. I did provide it and when I went to view the album, it displayed the location on a map. I liked it. Few days later, Gwt-Ext 2.0.3 got released with some cool features. One of them is a map API built on top of Mapstraction. Mapstraction lets you use maps from different providers such as Yahoo, Google, Microsoft and lets you switch between them easily. I had not worked with maps before and thought this would be a good opportunity to try it. I wanted to create something like the one I had seen on Picasa.

I have written a small Gwt-Ext application which marks user supplied addresses on a Google Map. Click thumbnail above for a larger image of the output. It took quite some time to figure out how to geocode an address to obtain the latitude and longitude information. But at the end, it works! I have used Google Maps specific code. However, Gwt-Ext provides powerful abstraction, thanks to Mapstraction, and you may want to use that instead.

Code is given below with brief explanation. The entry point looks like this:

1
2
3
4
5
6
public void onModuleLoad() {
	createMapPanel();
	addMapControls();
	new Viewport(mapPanel);
	updateMap("mumbai", JavaScriptObjectHelper.createObject(), this);
}

In createMapPanel(), I create the panel which will hold the map:

1
2
3
4
5
6
7
8
private void createMapPanel()
{
	mapPanel = new GoogleMap();
	mapPanel.setTitle("Google Maps using Gwt-Ext [http://abhijeetmaharana.com]");
	mapPanel.setHeight(400);
	mapPanel.setWidth(400);
	mapPanel.addLargeControls();
}

mapPanel.addLargeControls() adds controls to the map which let you zoom, pan and select image type (map / satellite / hybrid).

Then, I add a textfield and a button in the top toolbar of the panel to accept user input:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void addMapControls()
{
	final MainModule thisModule = this;
 
	addressField = new TextField();
	addressField.setValue("mumbai");
	refreshMapButton = new ToolbarButton("Refresh map", new ButtonListenerAdapter() {
		public void onClick(Button button, EventObject e) {
			String address = addressField.getText();
			if (!address.trim().equals(""))
				updateMap(address, JavaScriptObjectHelper.createObject(), thisModule);
		}
	});
 
	Toolbar toolbar = new Toolbar();
	toolbar.addText("Enter an address: ");
	toolbar.addField(addressField);
	toolbar.addSpacer();
	toolbar.addButton(refreshMapButton);
 
	mapPanel.setTopToolbar(toolbar);
}

On line 11, updateMap() is called when user clicks “Refresh map” after supplying an address. This is a native method which uses has Javascript code to obtain the latitude and longitude of the provided address. If it can obtain valid results, it calls renderMap() to display the location. I had to resort to JSNI to geocode the address. There might be a cleaner way which would avoid any native code. I have posted a question in the Gwt-Ext forum. Lets see what comes up.

Below is the code for updateMap() and renderMap():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public native void updateMap(String locationAddress, JavaScriptObject llp, MainModule thisModule) /*-{
	var geo = new $wnd.GClientGeocoder();
 
	geo.getLocations(locationAddress, 
		function(response) 		// callback method to be executed when result arrives from server
		{
			if (!response || response.Status.code != 200) 
			{
   				alert("Unable to geocode that address");
			} 
			else 
	      		{
		    		var place = response.Placemark[0];
		    		llp.lat = place.Point.coordinates[1];
		    		llp.lon = place.Point.coordinates[0];
 
		    		thisModule.@com.maharana.gwtextmaps.client.MainModule::renderMap(Lcom/google/gwt/core/client/JavaScriptObject;)(llp);
	      		}
      		}
      	);
}-*/;
 
 
public void renderMap(JavaScriptObject jsObj)
{
	double lat = Double.parseDouble(JavaScriptObjectHelper.getAttribute(jsObj, "lat"));
	double lon = Double.parseDouble(JavaScriptObjectHelper.getAttribute(jsObj, "lon"));
 
	LatLonPoint latLonPoint = new LatLonPoint(lat, lon);
	mapPanel.setCenterAndZoom(latLonPoint, 12);
	mapPanel.addMarker(new Marker(latLonPoint));
}

You will need to include code below in the host HTML file to use GClientGeocoder and other Google Maps / Mapstraction related Javascript objects:

<script type="text/javascript" src="js/map/mapstraction.js"></script>
 
<!-- Replace **PLACEHOLDER** in this line with your API key -->
<script type="text/javascript" src="http://maps.google.com/maps?file=api&amp;v=2.x&amp;key=**PLACEHOLDER**"></script>

You can obtain a Google Maps API key from http://code.google.com/apis/maps/signup.html.
Do let me know what you think. Specially about geocoding addresses without making a JSNI call.

Download Eclipse project from Gwt-Ext.com or Rapidshare.

UPDATE (8 Apr):
Sanjiv has clarified in the forum that geocoding support is not available yet. So we will have to stick with JSNI code for the time being. Also, since the url in host mode is localhost:8888, you can use this key for Google Maps:

<script type="text/javascript" src="http://maps.google.com/maps?file=api&amp;v=2.x&amp;key=ABQIAAAARrCK38aboqQKDotehUjrPhTb-vLQlFZmc2N8bgWI8YDPp5FEVBQ-MFjXfKfAvdbsbp3pa0q7fQNDDA">
</script>

25 Responses to “Gwt-Ext and Google Maps”

  1. Shweta says:

    Great work abhijit !! :)

  2. Weekly GWT Links for 4/12/08 | GWT Site says:

    [...] Gwt-Ext and Google Maps Abhijeet Maharana has written up a nice tutorial on how to use the new Gwt-Ext Mapstraction API. [...]

  3. Thejesh GN says:

    Gr8 work. GWT+maptraction would make it easy to code any geo app.

  4. Abhijeet Maharana says:

    Yep … and one can have ExtJS’s polished controls right next to the map.

    @Shweta: Thanks!

  5. Abhijeet Maharana » Gwt-Ext and Google Maps - II (handle click) says:

    [...] have modified the demo I posted in my earlier blog entry to include this. You can download it from [...]

  6. Jason Pratt says:

    looks good, but i can’t get it to work. can you post an complete example with the HTML and related xml files required by GWT. The maps demo in the source is a bit confusing.

    thanks!

  7. Abhijeet Maharana says:

    Umm… I have already posted the Eclipse project with all necessary files here: http://gwt-ext.com/users/abhijeet/GwtExtMaps.zip
    You can import in into your workspace.

    If you are referring to setting up Gwt and Cypal Studio for Eclipse then maybe these videos will help: http://showmedo.com/videos/video?name=2040000;fromSeriesID=204

    Let me know if this is not what you meant.

  8. Jason Pratt says:

    thanks that was a great help!
    when using in a borderlayout with the map being in the center region, how would dynamically resize the map to fit the viewport? when i tried what seemed to make sense the map did not even show up!

    jason

  9. Abhijeet Maharana says:

    Ok … this took quite some time and after a lot of head banging, I think this works.

    1. Remove any width/height settings from mapPanel

    2. Declare a boolean variable mapRendered and set it to true when MAP_RENDERED_EVENT of mapPanel is fired. There should actually be a getter isMapRendered() in MapPanel. I have created an issue at http://code.google.com/p/gwt-ext/issues/detail?id=354

    3. Add a onResize handler to mapPanel which calls mapPanel.resizeTo(…) if mapRendered is true.

    I have posted the Eclipse project at http://gwt-ext.com/users/abhijeet/GwtExtMapsWithClickHandler_BorderLayout.zip. Let me know if it works as expected at your end.

  10. Jason Pratt says:

    yes that did it! awesome thanks for the help. i believe i am understanding to use maps with gwt-ext now!
    keep up the great work.

  11. Aysu says:

    Thanks Abhijeet! its a very goog work!
    I try this and I did it but I should resize the map. I need a smaller map.I change the mapPanels size but it doesnt work, I write a native fonksion
    public native void setSize(int width, int height) /*-{
    var D = document.getElementById(“map”)
    D.style.height = ;
    D.style.width = ;
    }-*/;

    It doesnt work again,
    I try to change css file , but I couldn’t

    I add this to the css file
    .map {
    width: 400px!important;
    height: 400px!important;
    width: 400px;
    height: 400px;
    margin: 20px!important;
    margin: 30px 10px 20px 20px;

    }

    I could not chnage map.

    Could you help me about this issue?

    Thanks very much again for your good work!

    aysu

  12. Abhijeet Maharana says:

    Hi Aysu, thanks for dropping by. I can’t reproduce the problem you have mentioned. I just ran the project again and mapPanel.setSize() works just fine.

    Are you trying to change the map’s size after rendering mapPanel? Or passing mapPanel to your ViewPort constructor? In that case, you will need to call mapPanel.resizeTo(). I have posted the explanation and complete Eclipse project in the previous comment. Try running that and lemme know if it solves your issue.

    http://gwt-ext.com/users/abhijeet/GwtExtMapsWithClickHandler_BorderLayout.zip
    or
    http://rapidshare.com/files/123626036/GwtExtMapsWithClickHandler_BorderLayout.zip

    Regards,
    Abhijeet.

  13. Aysu says:

    Hi Abhijeet !

    Thanks! I did it! my problem is cause I have another panel which name is module panel.I have added map panel to it but I don t know that I must change new Viewport(mapPanel);
    when I change it to new Viewport(modulePanel); it is done.

    Thanks for helping me!

    aysu

  14. Karthik says:

    Hello Abhijeet,

    Your work really impressed me, you are doing a great job congrats.

    If you could post the same for other map services also it will be a great help.
    One place for all GWT map issues and solutions.!!!!

    Regards

    Karthik

  15. Abhijeet Maharana says:

    Hi Karthik,
    Thanks! Switching map providers shouldn’t be difficult since GWT-Ext maps wrap the mapstraction library. Check out the multi maps sample in showcase http://gwt-ext.com/demo-maps/#multipleMaps. I think that’s what you are looking for!

    Also, there is a forum thread for maps related issues (and solutions!) http://gwt-ext.com/forum/viewtopic.php?f=9&t=1554 and a blog post on using maps with Grails http://www.spenceruresk.com/2008/06/15/grails-gwt-with-gwt-ext-googlemaps-maxmind-sample-application/

  16. aj says:

    Hi,

    Gr8 work. I’m getting my feet wet with GWT and wanted to try to get your example running under netbeans 6.1 on linux.
    I’ve tried to import the GwtExtMaps examples as a new webproject but seem to be getting three errors in MainModule.java.

    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.core.client.JavaScriptObject;
    import com.google.gwt.user.client.Window;

    I’m using ext2.0.2 for my other projects which seem to works fine but have a feeling this might be due to some library conflicts or the simple fact that this cannot be imported under netbeans?? Some expert insight would be cool ;-)

    Cheers

  17. Abhijeet Maharana says:

    Hi aj, those are core GWT classes and should be gone if your project references the GWT library correctly. I don’t use Netbeans so I cant say if it has options to directly import Eclipse projects.

    Try setting up a skeleton GWT-Ext Netbeans project and then just import the source file from my project and make changes to your host HTML as outlined above.

    These links should be helpful:
    http://zer0d4y.blogspot.com/2008/09/preparing-gwt-ext-with-netbeans-61.html
    http://gwt-ext.com/forum/viewtopic.php?f=9&t=2519.

  18. aj says:

    Hi Abhijeet,

    Yeah i thought of that “after posting” :) . The whole web-project builds ok but after running the project the center panel where the map should be displayed is blank. I’m definitely missing something here: Any ideas off the bat where i might have to look?
    Edit: Thought it could be a problem with the mapstraction – added the path to WelcomeGWT.html, i.e.,
    but to no avail :-(
    The Netbeans Project Folder: http://www.mediafire.com/file/yu2qy402ty1/GWTSkeleton.zip

  19. Yulia says:

    Hi aj,

    I had the same problem.
    I add folowing code in gwt.xml file instead of host HTML file and it helps:

  20. Yulia says:

    Sorry, it seems that html isn’t allowed in comments :) I moved script tags with mapstraction and Google Maps to gwt.xml file and removed type attribute.

  21. Abhijeet Maharana says:

    @aj: I didn’t get a chance to run the Netbeans project you linked to. Sorry for that.
    @Yulia: Many thanks for sharing your experience!

    – Abhijeet.

  22. Cihan Aksu says:

    Thanks a lot for this and also google map api for localhost.I love it.

  23. Rocs says:

    Hi Abhijeet, I’m facing difficulties in using MapPanel in a GWT Ext Panel on IE8. This works find in Mozilla and Chrome. But on IE8, the setSize is not working. The code is:

    I am creating a widget, the class is inheriting from Panel.

    mapPanel = new GoogleMap();
    mapPanel.setTitle(“Sites”);
    mapPanel.setWidth(800);
    mapPanel.setHeight(600);
    mapPanel.addLargeControls();
    mapPanel.autoCenterAndZoom();

    add(mapPanel,new AnchorLayoutData(“100%”));

    //Updates etc

    Pls let me know what could be the issue

    -Rocs

  24. Jocelyn says:

    Hi Abhijeet. After reading your blog, I programmed my application with GWT-EXT and the MapAbstraction widgets and it worked perfectly well until Google did an update a few days ago (mid-august) to their Map API. I cannot display Google maps anymore in MapPanel .. only text is showing in panel. According to Google recommendations, I changed the way I call the javascript in the HTML entry point but no map is showing up yet (by the way, this is the only modification I made to the code, so the problem seems to be on Google side). Any idea?

    - jocelyn

  25. sandrar says:

    Hi! I was surfing and found your blog post… nice! I love your blog. :) Cheers! Sandra. R.

Leave a Reply