GWT: TrafficMap – GWT & Leaflet Map Example

Here is a nice GWT and Leaflet map application I wrote to ease myself back into GWT again after not having written a line of GWT code since 2009. It is a classic map and list type site which displays some sample data I downloaded from the UK Highways Agency traffic RSS feed.

Trafficmap

Not content to knock something together just to get it working I have as usual done it the hard way by embarking on learning about GWT UIBinder and the MVP design pattern which Google are promoting in the latest version of GWT. My intention is to eventually write something bigger after getting up to speed on GWT again. The result is a simple MVP application which utilises composite binder xml views and the GWT Leaflet map component. All mavenized for an easy(ish) build and deploy process.

You can download the project from here.

Highlights

Data

The data comes from the Highways Agency RSS feed here. This was downloaded and processed by my RSS parser which you can find here.

I used the Google JSON library to convert one of the feeds to a JSON file which was my sample data.

Map

The map is the GWT Leaflet component. The component attaches itself to an g:HTMLPanel defined in the MapView.xml UIBinder template.

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
	xmlns:g="urn:import:com.google.gwt.user.client.ui">
	<ui:style>
	.mapViewPanel {
		padding-left: 10px;
		padding-right: 10px;
	}
	</ui:style>
	<g:HTMLPanel ui:field="mainPanel" addStyleNames="{style.mapViewPanel}" >
	</g:HTMLPanel>
</ui:UiBinder> 

You cannot instantiate the map control directly in the constructor of the binder. You won’t see anything. It has to be created and attached in the onLoad method of the composite view i.e.

@Override
protected void onLoad()
{
	super.onLoad();

	// ---------------------------------------------------------------
	// Map Widget
	// ---------------------------------------------------------------

	MapWidget mapWidget = new MapWidget(MAP_DIV);
	mainPanel.add(mapWidget);
	mapWidget.setHeight("100%");
	mapWidget.setWidth("100%");

	// ---------------------------------------------------------------
	// Map Configuration
	// ---------------------------------------------------------------

	// Create Map instance
	MapOptions loptions = new MapOptions();
	loptions.setCenter(new LatLng(55.864237000000000000, -4.251805999999988000));
	loptions.setZoom(13);

	Options tileOptions = new Options();
	tileOptions.setProperty("attribution", MAP_ATTRIBUTION);
	TileLayer tileLayer = new TileLayer(MAP_URL, tileOptions);

	myMap = new Map(MAP_DIV, loptions);

	myMap.addLayer(tileLayer);

	myMap.invalidateSize(true);
}

A few things to point out.

  • I couldn’t get the the ‘fitBounds’ method to work which I believe should set the view bounds and zoom to the data set.
  • You must call ‘invalidateSize’ to force the map to redraw otherwise the map is kind of half-drawn.
  • The whole view is actually a composite of the left, middle and right panels. I.e.

    <!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
    <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    	xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:my="urn:import:com.netthreads.gwt.client.view">
    	<ui:style>
    	</ui:style>
    	<g:HTMLPanel ui:field="testLabel">
    		<my:TopView ui:field="topView" width="100%" height="100%"/>
    		<g:DockLayoutPanel width="100%" height="650px">
    			<g:west size="300.0">
    				<my:ListViewImpl ui:field="listView" width="100%" height="100%"/>
    			</g:west>
    			<g:center size="80.0">
    				<my:MapViewImpl ui:field="mapView" width="100%" height="100%" />
    			</g:center>
    			<g:east size="220.0">
    				<my:PropertiesViewImpl ui:field="propertiesView" width="100%" height="100%" />
    			</g:east>
    		</g:DockLayoutPanel>
    
    	</g:HTMLPanel>
    </ui:UiBinder>
    

    I had bit of trouble trying to get the data table to do a single selection when a row was clicked. After a fair bit of Googling and hunting around stackoverflow I found that you cannot define this in the binder template CSS. The only was to get this to work was to define a CSS resource and pass it into the constructor of the DataGrid.

    The css.

    .dataGridSelectedRowCell {
      border: selectionBorderWidth solid #ffffff; /*#628cd5;*/
    }
    
    /**
     * The keyboard selected cell is visible over selection.
     */
    .dataGridKeyboardSelectedCell {
      border: selectionBorderWidth solid #ffffff; /* #d7dde8;*/
    }
    

    The resource.

    package com.netthreads.gwt.client.view;
    
    import com.google.gwt.user.cellview.client.DataGrid;
    
    /**
     * Override the datagrid style resources.
     * 
     * http://stackoverflow.com/questions/7394151/datagrid-celltable-styling-frustration-overriding-row-styles
     *
     */
    public interface DataGridResource extends DataGrid.Resources
    {
    	@Source(
    	{
    	        DataGrid.Style.DEFAULT_CSS, "DataGridOverride.css"
    	})
    	DataGrid.Style dataGridStyle();
    };
    

    And the usage:

    	private DataGridResource resource = GWT.create(DataGridResource.class);
    	
    	@UiField(provided = true)
    	protected DataGrid<TrafficData> dataGrid = new DataGrid<TrafficData>(50, resource);
    

    I am going to write more GWT stuff again as I am heartily sick of javascript, css and html.

    Apache License 2.0

    GWT: gTraffic Usage

    I have Google stats activated for some of my websites including gTraffic the UK traffic Google map mashup. The site ticks over with fairly low stats of about 20 people a day (I salute you fellow traffic junkies). Occasionally when there is a bank weekend or a public holiday the stats jump to some fairly respectable figures. For example, there is a monday holiday coming up in the UK this weekend, check out the stats. Both spikes are holiday weekends:

    gTraffic usage

    This is interesting in all sorts of ways if you are into road traffic websites. Basically (and I can back this up from the commercial sites I have worked on), noone gives a hoot about the traffic on the road until they have to make a journey. Then they want to know if they are likely to get held up as the pack the kids into the 4×4 and make the journey down to Dover or north to the Lake District. For those of you who use gTraffic I thank you and have good holiday.

    GWT: gTraffic Timeline

    I occasionally have a look at my GWT traffic mashup to make sure it’s still working. I was looking at it again tonight and was struck by how many good ideas it seems to have. Good ideas that no one else seems to have bothered to pick up on. As an example take a look at the view (as of tonight) for the Berkshire area.

    gTraffic

    I was clicking around to make sure that the data seemed up to date and kept clicking on long running Roadworks. If you only had that view then it would be a chore to determine what was new and what was long running except that you have the ability to flick over to the time-line. Looking at that I could see right away what the latest events were. The time-line view is not perfect but I am still amazed no one else has copied this idea cos I think this is genuinely useful.

    gTraffic timeline

    Another one is the zoom-in/zoom-out buttons on the infowindow. My implementation jumps down to the street view and then back up to the last selected zoom level. I know this has been used elsewhere in sites connected to me but I would have thought this would be more widespread as, again, it’s a useful functionality.

    gTraffic zoom

    Maybe it’s just me but I think there are some good ideas here which are not represented in current traffic web sites.

    GWT: Flex integration

    Well done to Christian Voigt for putting GWT and Flex together in a way that works. He has written a small library and demo plus a clear explanation on his blog page for those interested here.

    I have had a look at his solution and it makes mine look horribly over-engineered which I guess it is (plus it didn’t work properly). It’s been a while since I looked at this stuff and I haven’t a clue what I was thinking with my fancy controllers and such!

    Flex: GWT: Developer Experience – Part 1

    This is the start of a three part article focusing on my experience of using GWT and then Adobe Flex to implement versions of my UK traffic information site gTraffic.

    You can compare the two by looking at the GWT version and the Flex version.

    As an inital primer I will talk about the original website the GWT and Flex version were based on before getting into description of my experience of the technologies of GWT and Flex.

    The intial version of the site was written using a combination of javascript and html with some AJAX to fetch and parse the data from the server side. It seems strange to contemplate that seems pretty ‘old-hat’ now but at the time it was really cutting edge. It was only just over a year ago really but how things have moved on!

    The data was intially supplied from the BBC TPEG data feed which was later moved to the BBC backstage site which provides a place for mashups using the BBC data. The traffic data in TPEG format was downloaded and massaged into a simpler form using a number of Python scripts.

    My intial thought was to use Java to parse the traffic data but it turned out that my ISP didn’t support this.

    Instead I tried Perl but the experience was so awful I switched to Python even though my desktop developer mentality screamed against using tabs to act and formatting for block statements. The Python IDE bundled with the development kit it usable but having experience of Eclipse I settled with Pydev which had a great debugger and integrates into Eclipse really well.

    The hardship of using CSS to layout the original site was a real pain. Although it looked okay it didn’t have great deal of appeal in terms of look and feel (you will have to take my word for this). I think my vision was sound as both the GWT and Flex versions adopt a similar layout but it was clearly a web page type of look and I was trying for something slicker.

    The original site was written off the back of the experience I had gained in developing a few few sites using JSP and Tomcat for my employer. I had enough knowledge of html and javascript to develop a Google Maps site which took the traffic feeds from the BBC and plot traffic events on a map, plus put in a few nice touches for navigation. Struggling with CSS and layout issues didn’t make for a straightforward experience though and I suspect this is the view of more then a few developers who come initially from a background in development for desktop applications.

    GWT came along at just the right time. I was looking for something that offered the ability to write an ‘application’ with real GUI controls and which ran in the browser. The added bonus was that it was using java which I already knew pretty well so it was tailor-made for my needs.

    Learning Flex

    I have implemented the majority of the edit grid functionality for gwt-yui-ext. I have a hit a snag though and keep meaning to get back to it.

    For now, I have been working my way through Adobe Flex 2: Training from the Source. I’m about a quarter of the way through so far and reckon it will take me another two weeks to finish since I am only getting about an hour each evening to look at this.

    The reason I started to look at Flex was because of my trial implementation of the Flex/GWT integration through FABridge. I figured I’d be better off knowing it well before I tried to skin some of the actionscript classes using GWT. Whether I’ll ever try this or not is debatable but in the meantime Flex has caught my interest. My only gripe so far is that FlexBuilder 2 is horrendously expensive! Particularly in the UK. I can’t afford it, so once the trial is up it’s back to the command line for me.

    Project Updates #1

    After getting gwt-jsviz out the door I feel it’s time to take stock of my current list of on-going projects.

      gwt-jsviz

    The gwt-jsvix API wrapper was something that I had been putting some time into on and off for quite a while so I am glad to have the first revision up and running. Already I have found stuff that I want to put into it. It’s just a case of getting round to it. The first version is purely a wrapper for the existing code, nothing else. I have a tabbed version of the demos but there is issues with this that I can see are going to take a wee while to resolve so anyone who wants to use this with GWT will have to stick with the vanilla version for now. It might seem a strange thing to bring to GWT but as soon as I saw Kyles demo of the music mashup I could see the potential for applying this to a combination of the Yahoo REST search API and the Timeline.There, I have given the game away and now someone will beat me to it. I am not surpised that Kyle Scholtz has been snapped up by Google as he is clearly a clever guy.

      gwtsimiletimeline

    I am quite proud of this as it was my first open source project and it’s probably the most complete. The core javascript ‘widget’ is beautifully written by the guys at MIT and it’s no surprise that it was relatively easy to wrap up and slots into GWT with very little effort. I have received a request to enable the timeline to read it’s XML from a text string and this is what I hope to put some time into. My gut feeling is that it’s ‘doable’ and will extend the core component in pure GWT fashion.

      gwt-yui-ext

    This is the most interesting (and time consuming) of all the GWT wrapper API’s I have attempted. I had a look at the source javascript, at the time I was writing the timeline stuff, and concluded that it was ‘doable’. In reality this has the the most real GWT code of them all as the way that it works involves manipulating the RootPanel DOM to hook into GWT.

    I started off with the most complex of the demos the BorderLayout. This proved a good idea as a lot of what I gleaned from doing this went into the BasicDialogPanel and LayoutDialogPanel.

    I have focussed on the original demos as this is the acid test for wrapping them to the GWT platform. There is still work to do on the current list of demos which is why I haven’t put them into a new release. Anyone wanting the code for these should just go to the source trunk and get the latest source image.

    I am a bit undecided on the targets for this library. There are a a few bugs in the current demos which need addressing so I think I will try to get those fixed for now.

      WORK IN PROGRESS

    – gwtsimiletimeline: Timeline to read text XML

    – gwt-jsviz: JSViz to have tabbed example.

    – gwt-yui-ext:
    . DialogPanel and LayoutDialog have bug where the background can become the focussed view stopping any further interaction with the main dialog.
    .There are issues with the resizable component namely, the transparent handles doesn’t work under IE and the animation for the control doesn’t work at all. I might drop some of this stuff from the next release.
    .The grid need a better example of inserting data.
    .The dialog examples need to show non-modal dialogs.

    Not too onerous a list.

      Other Stuff

    I had started to look at integrating Flex with GWT using the FABridge. I have big ideas for this but little time so we’ll see how it goes.

    Also, I knocked together an example of integrating MapBuilder with GWT which I will get around to adding to the links on the top right in due time.

      In conclusion

    I think that probably the best way to proceed will be to try and incorporate as much of this technology into the gtraffic site. It’s a great test bed and I can see ways that all this stuff could fit into it (yes even gwt-jsviz, just you wait and be amazed/baffled).

    gwt-yui-ext update #2

    I have made an important update to the gwt-yui-ext library. The grid control wasn’t much use if you couldn’t click on it and select items for editing etc so I have implemented the GridEventManager and GridEventListener classes. These will let you listen for clicks, double clicks etc and response by defining your own functions sub-classed from the GridEventListener.

    i.e.

    GridEventListener rowListener = new TestGridEventListener();
    GridEventManager.getInstance().addOnRowClickListener(
    rowListener, grid.getGrid());

    The onRowClick function in the class TestGridEventListener will get called when the use clicks on a row.

    I have to make some changed to the example to extract the row data when the row is selected or double-clicked to show this off. The example at the moment merely shows a window alert with the contents of the first column.

    The important point about this is now I can move the component parts of the gTraffic site into the yui-ext framework which will show this off better than the sample app ever could.

    Roadworks and VMS

    I am still trying to get the Roadworks and VMS (Variable Message Signs) feeds working again but I am having problems getting the authentication to work properly (I have username and password access to secured data).

    Please bear with me for the moment. Currently the data displayed for these map layers is woefully out of date. I know from the webstats that these are not really looked at that often but _somebody_ must be interested in them so I will do my best to try and get these going again.

    At some point I would like to come back and redo the application layout. I am open to suggestions so mail me at arutherford _at_Gmail.com if you have a suggestion.

    GWT Flex Bridge

    A recent thread on the GWT forum got me interested in the possibility of interfacing GWT to Adobe Flex. Adobe have released a javascript to flex ‘bridge’ component called FABridge.

    I have put together a (very) quick and dirty demo the two components talking to each other through the FABridge. This is far from finished but is does demonstrate the basic concepts.

    Download the zip file from here.

    If you examine the source code you will see that I have tried to enclose the embedding of the swf component within the ‘FlexWidget’ by writing the holder html straight into the main html view. The controller object is then supposed to pick up the embedded object in the JNSI code. This doesn’t work. I am looking into why not.

    GWT Flex demo here. Only works in Firefox/Mozilla/Opera browsers for the moment.

    Source code here.

    Next Page →