Smart GWT with FusionCharts

It is possible to render FusionCharts from a SmartGwt widget. The following discussion explains how to achieve this.

For rendering FusionCharts, code similar to this example is requierd:

<html>
  <head>
    <title>My First chart using FusionCharts</title>
    <script type="text/javascript" src="resources/chart/fusionChartsXT/FusionCharts.js">
    </script>
  </head>
  <body>
    <div id="chartContainer">FusionCharts will load here!</div>
    <script type="text/javascript">
      var myChart = new FusionCharts("Column3D", "myChartId", "400", "300");
      myChart.setXMLUrl("data.xml");
      myChart.render("chartContainer");
    </script>
  </body>
</html>

For a new standalone component that will be based on direct use of HTML, this is usually done by subclassing Canvas and overriding Canvas.getInnerHTML and returning an HTML string representing the components that needs to be created. More information is available about this here.

Firstly, import the necessary FusionCharts' javascript files. This is achieved by adding the following line of code within the <head> tag of the project's main html page.

<script type="text/javascript" language="javascript" src="resources/chart/fusionChartsXT/FusionCharts.js"></script>

Note: This line of code is already included in the example.

Additionally, the example has this line of code:

<script type="text/javascript" language="javascript" src="resources/chart/FusionChartsFree/FusionCharts.js"></script>

Either of these can be used, dependent upon whether a commercial version or the free (LGPL) version is being used.

To create a new SmartGwt widget,  the following code is needed:

public class FusionCharts extends Canvas {

    public FusionCharts() {
        setRedrawOnResize(false);
        setWidth(400);
        setHeight(200);
    }

    @Override
    public String getInnerHTML() {
        return "<div id='"+getID()+"_chartContainer'>FusionCharts will load here!</div>";
    }
}

Where:

1.- setRedrawOnResize(false);
By default, the component will redraw() if it is resized. This should be avoided because it would wipe out the widget every time it was resized, so setting redrawOnResize to false removes this issue..

2.- return "<div id='"getID()_"chartContainer'>FusionCharts will load here!</div>";
When the widget is drawn, the getInnerHTML() method is called and its content is displayed. In this case, there needs to be a <div> tag available, as this will contain the actual chart.

Next, a JSNI method is required, as shown below::

public native void getFusionChart(String data, String chartType, int width, int height, String chartId, String chartContainerID) /*-{
    var chart = new $wnd.FusionCharts(chartType, chartId, width, height);
    if (chart.setXMLData != null ) chart.setXMLData(data);
    else chart.setDataXML(data);
    chart.render(chartContainerID);
}-*/;

JSNI methods are needed so that javascript code can be executed. The code above is used to render the charts.

Finally, the new widget's code is shown below:

public class FusionCharts extends Canvas {

    public FusionCharts() {
        setRedrawOnResize(false);
        setWidth(400);
        setHeight(200);
    }

    @Override
    public String getInnerHTML() {
        return "<div id='"+getID()+"_chartContainer'>FusionCharts will load here!</div>";
    }

    public void resizeContainerAndActiveChart(String chartId, int width, int height) {
	setWidth(width);
        setHeight(height);
        resizeActiveChart(chartId, width, height);
    }

    public native void resizeActiveChart(String chartId, int width, int height) /*-{
 	try {
 	    var chart = $wnd.FusionCharts(chartId);
	    // resizeTo() does not exist in FusionCharts free version
	    if (chart.resizeTo != null) chart.resizeTo(width, height);
	} catch (e) {
	    // ignore
	}
    }-*/;

    /**
     * Remove a chart instance from page and memory
     * @param chartId
     */
    public native void removeChart(String chartId) /*-{
	try {
  	    var chart = $wnd.FusionCharts(chartId);
    	    // dispose() does not exist in FusionCharts free version
    	    if (chart.dispose != null) chart.dispose();
	} catch (e) {
	    // ignore
	}
    }-*/;

    public void getFusionChart(String data, String chartType, String chartId) {
	getFusionChart(data, chartType, getInnerWidth(), getInnerHeight(), chartId, getID()+"_chartContainer");
    }

    public native void getFusionChart(String data, String chartType, int width, int height, String chartId, String chartContainerID) /*-{
    	var chart = new $wnd.FusionCharts(chartType, chartId, width, height);
	if (chart.setXMLData != null ) chart.setXMLData(data);
	else chart.setDataXML(data);
	chart.render(chartContainerID);
    }-*/;

    public void getFusionMap(String data, String chartType, String chartId) {
	getFusionMap(data, chartType, getInnerWidth(), getInnerHeight(), chartId, getID()+"_chartContainer");
    }

    public native void getFusionMap(String data, String chartType, int width, int height, String chartId, String chartContainerID) /*-{
    	if ($wnd.FusionCharts.setCurrentRenderer != null) {
     	    $wnd.FusionCharts.setCurrentRenderer('javascript');
	    var chart = new $wnd.FusionCharts(chartType, chartId, width, height);
	    chart.setXMLData(data);
	    chart.render(chartContainerID);
	}
    }-*/;
}

This example's full code can be downloaded from here.

Below are a collection of example features and behaviors that can be achieved:

1.- Loading a FusionChart chart, which is a Dual Y Combination chart.

2.- Loading a PowerChart chart, which is a Candlestick chart.

3.- Resizing the chart by moving its borders.

When the chart needs to be resized, FusionCharts will not automatically perform this operation. To do this, call the resizeTo() method, which can be found in the FusionCharts's API.

To resize the chart by moving its borders, use this method:
      

final FusionCharts fusionChartLayout = new FusionCharts();
fusionChartLayout.setID("chart");
.......
fusionChartLayout.addResizedHandler(new ResizedHandler() {
    @Override
    public void onResized(ResizedEvent event) {
	fusionChartLayout.resizeActiveChart(activeChart, fusionChartLayout.getInnerWidth(), fusionChartLayout.getInnerHeight());
	form.setValue("width", fusionChartLayout.getInnerWidth());
	form.setValue("height", fusionChartLayout.getInnerHeight());
    }
});

4.- Moving the chart to a different parent by using the Move Chart button.  Drag & Drop functionality can also be used to move the chart to a different parent.

5.- Loading a FusionWidget chart, which is a Funnel Chart

6.- Loading a FusionMap chart, which is Sales data

7.- Resizing the chart by changing its properties from the form.

These charts are based on this gallery: http://www.fusioncharts.com/demos/gallery/.
Get access to FusionCharts by:

1.- Downloading the Free version, which can be found here.
2.- Buying and Downloading a commercial version, which can be found here.

This example works with both the paid version and the free version of FusionCharts. The only chart that is not possible to render with the free version is Fusion Maps.