Flex: Traffic Timeline Chart #2

Okay, so this is a bit better:

flexTraffic timeline

What we are looking at here is an interesting mix of stuff from Ely Greenfields Flex Charting blog. Ely is the guy who wrote Flex Charts so his site is a first stop if you are considering using the charting controls.

There are two things going on here, the first is that I have used Elys DataDrawingCanvas to delineate the chart sections across the time ‘now’. There other is the range selector (see RangeSelector in Elys Chart Sampler).

Because the x-axis of the chart is a DateTime axis I have modified the rendering of the selection labels to display the time. You can look at this hacked code here.

You can see that all I’ve done is pass the millisecond values for the axis into a Date object and then used the FlexLib DateUtil function to render the time string.


override protected function commitProperties():void
{	
super.commitProperties();

_labelTop.text = Math.round(dTop).toString();
_labelBottom.text = Math.round(dBottom).toString();

// This looks like milliseconds but it doesn'e parse to that
dateValue.setTime(dLeft);
_labelLeft.text = DateUtil.toW3CDTF(dateValue);

dateValue.setTime(dRight);
_labelRight.text = DateUtil.toW3CDTF(dateValue);
}

I want to use this to zoom in and out of the graph elements but as yet am clueless how to do this (although I’m sure it’s doable). The chart should also render the bar items to a maximum width to stop one item stretching out to the entire height of the window which looks really naff.

Flex: Traffic Timeline Chart

Does this look familiar?

flexTraffic timeline

Looks bad I think, but this is work in progress. I will post this code up as soon as I finalise the look and feel. I think I will take out the text as doesn’t look very good.

Here is a first look at flexTraffic. Note the sliding panels. None of the look and feel is cast in stone and I might change my mind.

gTraffic: Version 2.2

I have fixed the problem with the map. The latest version of the map control 2.77 isn’t compatible with the GWT wrapper I use for the Google Map. As soon as I saw the javascript errors in the Firebug console pane I knew right away what it was. I pinned the map version at 2.76 and it all burst back into life again.

I have taken this point to remove the roadworks and VMS data options from the application. Sorry, but I can’t get the Python scripts to login to the XML feed for these anymore and I’ve no time to put into fixing it. This is better than looking at data that was from last year.

gTraffic: Problems

Aaaargh. I have just checked out gTraffic and there seems to be a problem. There are no events on the map! The weekend is upon us so I hope to find time to see what the problem is. In the meantime if you want to know what’s happening with UK traffic then checkout this.

Flex : Datagrid with embedded icon lookup

I am rewriting gTraffic in Flex. My intention is to open source the code when it’s complete to serve as an example for other people of a Flex map site. I have written quite a bit but mostly to integrate my initial prototype with the Cairngorm framework.

This article and hopefully other future articles will hopefully serve as a guide to the code. I intend to write them as I go along so here is the first…

The existing gTraffic site has the ability to list the loaded events from a region not only onto the map but onto a list view on the right hand side.

The events list contains a summary description of each event and also a panel icon coloured to indicate the severity (green=slight, yellow=medium and red=severe). In my flex implementation I use a DataGrid to display the events in a similar fashion. The data for the events list if fetched using an HTTPService and the xml is processed by the application using e4x into an mx:ArrayCollection of ‘Value Objects’ (basically objects which hold the fetched values).

The code for the DataGrid is as follows


[
    dataProvider="{ events }"
    change="updateSelectedEvent( event );"
    dragEnabled="false"
    variableRowHeight="true"
   height="100%" width="100%">

   
      

          
                 dataField="severity"
                 width="70"
                 itemRenderer="com.netthreads.traffic.view.renderer.PanelSeverityRenderer"/>

	         
	             dataField="summary"
		     wordWrap="true"
	             textAlign="left"/>

        
]

You will see that the first column of the grid uses an ItemRenderer to render the contents. This is a powerful and handy feature for the mx:DataGrid and means you can push visual components into the grid cell which don’t have to be text. For reasons which I can’t figure out the itemRenderer reference needs the full namespace path to the relevant component in the code space. That means you can’t just import the relevant class into the script area which is a bit of a pain.

What we want is a renderer which will take the current rows data item severity and place the appropriately coloured icon in the cell. I initially tried to see if this was possible with pure Actionscript and it does seem to be, but once I got into it I realised ‘why bother’. The mxml version is so straightforward in comparison that you would have to be some sort of Flex masochist to subject yourself to creating all the appropriate calls. That is, of course if you just need something simple like an image. You know I searched quite a bit for a straightforward example of this and I didn’t really find a good source so if you need to to something similar then this here is the renderer code.

The panel icons are stored in a class which has the icons embedded into it. A reference to each of these is stored against severity strings in a dictionary.


private function init():void
{
    if (dict==null)
    {
        dict = new Dictionary();

        dict[TXT_SEVERITY_UNKNOWN] = model.assets.transportPanelSlight;
        dict[TXT_SEVERITY_VERYSLIGHT] = model.assets.transportPanelSlight;
        dict[TXT_SEVERITY_SLIGHT] = model.assets.transportPanelSlight;
        dict[TXT_SEVERITY_UNSPECIFIED] = model.assets.transportPanelSlight;

        dict[TXT_SEVERITY_MEDIUM] = model.assets.transportPanelMedium;

        dict[TXT_SEVERITY_SEVERE] = model.assets.transportPanelSevere;
        dict[TXT_SEVERITY_VERYSEVERE] = model.assets.transportPanelSevere;
    }
}

This init function is called on the creation of each cell. But notice that I test to see if the static table has already be initialised. This mean that the dictionary object is only filled once.

The renderer creates an mx:Image object. This takes it source from the results of the ‘getSeverityIcon’ function (see the code).


public function getSeverityIcon(severity:String):Class
{
    var result : Class = null;

    result = dict[severity];
    if (result==null)
    {
        result = model.assets.transportPanelSlight;
    }

    return result;
}

The severity string from the value object is used as the lookup for the appropriate embedded image. If the result of the lookup is null then the severity string can’t find a match in the dictionary. If this is the case then a default of ‘slight’ is used.

And that’s it. Not rocket science but it might come in handy for someone else.

flexTraffic Events panel

Simile Timeline : Update

Well it’s been a while but I have finally got around to making an update to the gwt simile timeline. I had a request back in Dec last year (06) to add in the ability to load XML directly from a text string instead of having to use the AJAX loading mechanism. I thought it would be easy but when I went to look at it it turned out to be a bit involved.

Basically the event source object, which is the object which holds the data for a timeline, expects an XML document object to be supplied to load the data from. The AJAX call back mechanism automatically generates such an object in the request.responseStream of HTTPRequest object. Generating one of these from xml text isn’t straightforward as each browser has a different way to do it and you don’t have access to whatever magic the HTTPRequest is doing under the covers to create one.

I have had to add in a couple utility functions (see TimelineHelper.js in the code). This has been tested with Firefox, IE7 and Opera. I have no idea if it will work with Safari, I suspect not.

So, there are new calls to the EventSource object


public void loadXMLText(String xmlText)
{
    EventSourceImpl.loadXMLText(xmlText, GWT.getModuleBaseURL(), this);
}

and


public void loadJSON(String json) 
{
    EventSourceImpl.loadJSON(json, GWT.getModuleBaseURL(),this);
}

The loadJSON was a user contrubution from the Google Code site (thanks jdwyah whoever you are).

I started off writing a fancy JSON callback implementation then I realised that there are enough AJAX callback frameworks out there to handle however you want to get your data into the application so I haven’t put anything like that in. It just clutters up the interface anyway.

Look at the function processTextData in the DataHandler.java class to see an example of calling loadXMLText. It really couldn’t be easier.

I have bundled the latest MIT Simile timeline javascript code in with the source code zip. Keeping this locally makes the timeline boot up faster. Just be aware of this in case you have your own altered version.

Flex: Yahoo Map and gTraffic

I have to be honest, I have got lesson 13 in ‘Flex: Training from the source’ and I am struggling to keep some interest in punching in code (I do enough of that during the day) so I have started to put together a gTraffic-type site using Flex instead. This is mostly to keep my interest up and to apply what I have learned from reading this book (quite a lot and I’m only halfway really). If you manage to get through to lesson 12 I reckon you have enough to start on something so that’s what I am doing.

Flex is an interesting technology..I think I will put off what I think about it until I really get into using it.

Anyhoo..I have been putting a lot of time into examining the Flex Charts library and I reckon I can recreate the timeline graph using Flex. The author of the Flex Charts library over here has been doing some amazing stuff with the charts and although it is a commercial library I reckon it’s pretty good. You can tell the quality of the developer by his output and his output is excellent.

Back to my flex application. My biggest problem is I can’t debug the map control which is a pain. If I set a breakpoint I get an error in this error


undefined
	at flash.external::ExternalInterface$/call()
	at com.yahoo.webapis.maps.utils::
             ExternalInterfaceBuffer/com.yahoo.webapis.maps.utils:
             ExternalInterfaceBuffer::methodChurn()
             [C:Developmentflexyahooas3sourceas3comyahoowebapismaps
             utilsExternalInterfaceBuffer.as:104]
	at Function/http://adobe.com/AS3/2006/builtin::apply()
	at ()
	at flash.utils::SetIntervalTimer/flash.utils:SetIntervalTimer::onTimer()
	at flash.utils::Timer/flash.utils:Timer::_timerDispatch()
	at flash.utils::Timer/flash.utils:Timer::tick()

This is unfortunate as I was looking forward to trying out the Yahoo Map. I can find only one reference to this here and there isn’t much to go on.

I will try and chase up some leads but if there is no resolution then the Yahoo map is out and I will use an IFrame solution I have seen with the Google Map and use FABridge to talk to it.

It’s not my intention to replace the GWT version (it is called gTraffic after all) but this is simply a try-out at this stage.

I like Flex. I had a look at Open Lazlo ages ago and was initially quite excited about it but when I looked at a code examples I was horrified to see what a mess they were. I have caught some flack on the Ajaxian website for daring to slag-off Javascript in comparison to Java (a discussion about GWT) so I will say no more. Each has it’s place.