← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 5173: (DV) Export to PNG implemented for Chrome, Firefox, Opera and Safari + Chart title now integrated...

 

Merge authors:
  Jan Henrik Øverland (janhenrik-overland)
------------------------------------------------------------
revno: 5173 [merge]
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2011-11-16 15:53:06 +0000
message:
  (DV) Export to PNG implemented for Chrome, Firefox, Opera and Safari + Chart title now integrated in the chart.
added:
  dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/action/ExportImageAction.java
  dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/export/
  dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/export/SVGDocument.java
  dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/export/SVGUtils.java
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/exportimage.png
modified:
  dhis-2/dhis-web/dhis-web-mapping/src/main/java/org/hisp/dhis/mapping/action/ExportImageAction.java
  dhis-2/dhis-web/dhis-web-visualizer/pom.xml
  dhis-2/dhis-web/dhis-web-visualizer/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-visualizer/src/main/resources/struts.xml
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/app.js
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/css/style.css
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/datatable.png
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/index.html


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/java/org/hisp/dhis/mapping/action/ExportImageAction.java'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/java/org/hisp/dhis/mapping/action/ExportImageAction.java	2011-11-10 20:57:29 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/java/org/hisp/dhis/mapping/action/ExportImageAction.java	2011-11-16 13:24:53 +0000
@@ -199,7 +199,7 @@
     @Override
     protected String getFilename()
     {
-        return "DHIS_2_GIS.png";
+        return "DHIS2_GIS_" + this.title + ".png";
     }
     
     @Override

=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/pom.xml'
--- dhis-2/dhis-web/dhis-web-visualizer/pom.xml	2011-11-14 12:19:36 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/pom.xml	2011-11-16 13:24:53 +0000
@@ -61,6 +61,17 @@
 	  <classifier>jdk15</classifier>
 	</dependency>
 	
+	<!-- Batik -->
+
+    <dependency>
+      <groupId>org.apache.xmlgraphics</groupId>
+      <artifactId>batik-transcoder</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.xmlgraphics</groupId>
+      <artifactId>batik-codec</artifactId>
+    </dependency>
+	
   </dependencies>
 
   <properties>

=== added file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/action/ExportImageAction.java'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/action/ExportImageAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/action/ExportImageAction.java	2011-11-16 13:24:53 +0000
@@ -0,0 +1,126 @@
+package org.hisp.dhis.visualizer.action;
+
+/*
+ * Copyright (c) 2004-2010, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.io.OutputStream;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hisp.dhis.visualizer.export.SVGDocument;
+import org.hisp.dhis.visualizer.export.SVGUtils;
+import org.hisp.dhis.util.ContextUtils;
+import org.hisp.dhis.util.SessionUtils;
+import org.hisp.dhis.util.StreamActionSupport;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author Jan Henrik Overland
+ * @version $Id$
+ */
+
+public class ExportImageAction
+    extends StreamActionSupport
+{
+    private static final Log log = LogFactory.getLog( ExportImageAction.class );
+
+    private static final String SVGDOCUMENT = "SVGDOCUMENT";
+
+    // -------------------------------------------------------------------------
+    // Output & input
+    // -------------------------------------------------------------------------
+
+    private String svg;
+
+    public void setSvg( String svg )
+    {
+        this.svg = svg;
+    }
+
+    private Integer width;
+
+    public void setWidth( Integer width )
+    {
+        this.width = width;
+    }
+
+    private Integer height;
+
+    public void setHeight( Integer height )
+    {
+        this.height = height;
+    }
+
+    private SVGDocument svgDocument;
+
+    @Override
+    protected String execute( HttpServletResponse response, OutputStream out )
+        throws Exception
+    {
+        if ( svg == null || width == null || height == null )
+        {
+            log.info( "Export map from session" );
+
+            svgDocument = (SVGDocument) SessionUtils.getSessionVar( SVGDOCUMENT );
+        }
+        else
+        {
+            log.info( "Export map from request" );
+            
+            svgDocument = new SVGDocument();
+            
+            svgDocument.setSvg( this.svg );
+            svgDocument.setWidth( this.width );
+            svgDocument.setHeight( this.height );
+            
+            SessionUtils.setSessionVar( SVGDOCUMENT, svgDocument );
+        }
+        
+        SVGUtils.convertToPNG( svgDocument.getSVGForImage(), out, this.width, this.height );
+
+        return SUCCESS;
+    }
+
+    @Override
+    protected String getContentType()
+    {
+        return ContextUtils.CONTENT_TYPE_PNG;
+    }
+
+    @Override
+    protected String getFilename()
+    {
+        return "DHIS2_Visualizer.png";
+    }
+    
+    @Override
+    protected boolean disallowCache()
+    {
+        return true;
+    }
+}

=== added directory 'dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/export'
=== added file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/export/SVGDocument.java'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/export/SVGDocument.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/export/SVGDocument.java	2011-11-16 13:24:53 +0000
@@ -0,0 +1,93 @@
+package org.hisp.dhis.visualizer.export;
+
+/*
+ * Copyright (c) 2004-2010, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @author Jan Henrik Overland
+ * @version $Id$
+ */
+public class SVGDocument
+{
+    private static final String doctype = "<?xml version='1.0' encoding='UTF-8'?>"
+        + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"; ["
+        + "<!ATTLIST svg xmlns:attrib CDATA #IMPLIED> <!ATTLIST path attrib:divname CDATA #IMPLIED>]>";
+
+    private String svg;
+
+    private int width;
+
+    private int height;
+
+    public SVGDocument()
+    {
+    }
+
+    public StringBuffer getSVGForImage()
+    {
+        String svg_ = doctype + this.svg;
+
+        return new StringBuffer( svg_ );
+    }
+
+    @Override
+    public String toString()
+    {
+        return svg;
+    }
+
+    public String getSvg()
+    {
+        return svg;
+    }
+
+    public void setSvg( String svg )
+    {
+        this.svg = svg;
+
+    }
+
+    public int getWidth()
+    {
+        return width;
+    }
+
+    public void setWidth( int width )
+    {
+        this.width = width;
+    }
+
+    public int getHeight()
+    {
+        return height;
+    }
+
+    public void setHeight( int height )
+    {
+        this.height = height;
+    }
+}

=== added file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/export/SVGUtils.java'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/export/SVGUtils.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/java/org/hisp/dhis/visualizer/export/SVGUtils.java	2011-11-16 13:24:53 +0000
@@ -0,0 +1,71 @@
+package org.hisp.dhis.visualizer.export;
+
+/*
+ * Copyright (c) 2004-2010, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.awt.Color;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.StringReader;
+
+import org.apache.batik.transcoder.TranscoderException;
+import org.apache.batik.transcoder.TranscoderInput;
+import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.image.JPEGTranscoder;
+import org.apache.batik.transcoder.image.PNGTranscoder;
+
+/**
+ * @author Tran Thanh Tri
+ */
+public class SVGUtils
+{
+    public static void convertToPNG( StringBuffer buffer, OutputStream out, Integer width, Integer height )
+        throws TranscoderException, IOException
+    {
+        if ( width == null || width < 10 )
+        {
+            width = 500;
+        }
+
+        if ( height == null || height < 10 )
+        {
+            height = 500;
+        }
+
+        PNGTranscoder t = new PNGTranscoder();
+
+        t.addTranscodingHint( PNGTranscoder.KEY_HEIGHT, new Float( height ) );
+        t.addTranscodingHint( PNGTranscoder.KEY_WIDTH, new Float( width ) );
+        t.addTranscodingHint( JPEGTranscoder.KEY_BACKGROUND_COLOR, Color.WHITE );
+
+        TranscoderInput input = new TranscoderInput( new StringReader( buffer.toString() ) );
+
+        TranscoderOutput output = new TranscoderOutput( out );
+
+        t.transcode( input, output );
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/resources/META-INF/dhis/beans.xml	2011-11-08 15:53:59 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/resources/META-INF/dhis/beans.xml	2011-11-16 13:24:53 +0000
@@ -66,5 +66,10 @@
 		<property name="organisationUnitService"
 			ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 	</bean>
+
+	<!-- Export -->
+
+	<bean id="org.hisp.dhis.visualizer.action.ExportImageAction" class="org.hisp.dhis.visualizer.action.ExportImageAction"
+		scope="prototype"/>
 	
 </beans>

=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/resources/struts.xml	2011-11-08 15:53:59 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/resources/struts.xml	2011-11-16 13:24:53 +0000
@@ -60,6 +60,12 @@
             <result name="success" type="velocity-json">
                 /dhis-web-visualizer/jsonminAggregatedDataValuesPlugin.vm</result>
         </action>
+
+        <!-- Export -->
+
+		<action name="exportImage" class="org.hisp.dhis.visualizer.action.ExportImageAction">
+			<result name="success" type="outputStreamResult"/>
+		</action>
 		
 	</package>
 </struts>

=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/app.js'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/app.js	2011-11-14 19:20:10 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/app.js	2011-11-16 15:11:03 +0000
@@ -54,7 +54,8 @@
                     degrees: 330
                 }
             }
-        }
+        },
+        inset: 30
     },
     style: {
         label: {
@@ -343,11 +344,13 @@
             getEncodedSeriesName: function(text) {
                 return text.replace(/\./g,'');
             },
-            getLegend: function(len) {
+            getLegend: function() {
+                var len = DV.state.series.data.length;
                 return {
                     position: len > 6 ? 'right' : 'top',
                     boxStroke: '#ffffff',
-                    boxStrokeWidth: 0
+                    boxStrokeWidth: 0,
+                    padding: 0
                 };
             },
             getGrid: function() {
@@ -358,6 +361,18 @@
                     'stroke-width': 0.2
                 };
             },
+            getTitle: function() {
+                return {
+                    type: 'text',
+                    text: DV.init.isInit ? 'Example chart' : DV.state.filter.data[0],
+                    font: 'bold 15px arial',
+                    fill: '#222',
+                    width: 300,
+                    height: 20,
+                    x: 28,
+                    y: 16
+                };
+            },
             line: {
                 getSeriesArray: function() {
                     var a = [];
@@ -616,6 +631,7 @@
             dimension: DV.conf.finals.dimension.organisationunit.value,
             data: []
         },
+        svg: null,
         getState: function(exe) {
             this.resetState();
             
@@ -760,14 +776,13 @@
         },
         column: function(stacked) {
             this.chart = Ext.create('Ext.chart.Chart', {
-                width: DV.util.viewport.getSize().x,
-                height: DV.util.viewport.getSize().y,
                 animate: true,
                 store: DV.store.chart,
-                legend: DV.util.chart.getLegend(DV.state.series.data.length),
+                insetPadding: DV.conf.chart.inset,
+                items: DV.util.chart.getTitle(),
+                legend: DV.util.chart.getLegend(),
                 axes: [
                     {
-                        title: 'Value',
                         type: 'Numeric',
                         position: 'left',
                         minimum: 0,
@@ -780,7 +795,6 @@
                         }
                     },
                     {
-                        title: DV.init.isInit ? 'Categories' : DV.conf.finals.dimension[DV.state.category.dimension].rawvalue,
                         type: 'Category',
                         position: 'bottom',
                         fields: DV.store.chart.bottom,
@@ -806,11 +820,11 @@
         },
         bar: function(stacked) {
             this.chart = Ext.create('Ext.chart.Chart', {
-                width: DV.util.viewport.getSize().x,
-                height: DV.util.viewport.getSize().y,
                 animate: true,
                 store: DV.store.chart,
-                legend: DV.util.chart.getLegend(DV.state.series.data.length),
+                insetPadding: DV.conf.chart.inset,
+                items: DV.util.chart.getTitle(),
+                legend: DV.util.chart.getLegend(),
                 axes: [
                     {
                         title: DV.conf.finals.dimension[DV.state.category.dimension].rawvalue,
@@ -851,11 +865,11 @@
         },
         line: function() {
             this.chart = Ext.create('Ext.chart.Chart', {
-                width: DV.util.viewport.getSize().x,
-                height: DV.util.viewport.getSize().y,
                 animate: true,
                 store: DV.store.chart,
-                legend: DV.util.chart.getLegend(DV.state.series.data.length),
+                insetPadding: DV.conf.chart.inset,
+                items: DV.util.chart.getTitle(),
+                legend: DV.util.chart.getLegend(),
                 axes: [
                     {
                         title: 'Value',
@@ -883,11 +897,11 @@
         },
         area: function() {
             this.chart = Ext.create('Ext.chart.Chart', {
-                width: DV.util.viewport.getSize().x,
-                height: DV.util.viewport.getSize().y,
                 animate: true,
                 store: DV.store.chart,
-                legend: DV.util.chart.getLegend(DV.state.series.data.length),
+                insetPadding: DV.conf.chart.inset,
+                items: DV.util.chart.getTitle(),
+                legend: DV.util.chart.getLegend(),
                 axes: [
                     {
                         title: 'Value',
@@ -923,13 +937,12 @@
         },
         pie: function() {
             this.chart = Ext.create('Ext.chart.Chart', {
-                width: DV.util.viewport.getSize().x,
-                height: DV.util.viewport.getSize().y,
                 animate: true,
                 shadow: true,
                 store: DV.store.chart,
-                legend: DV.util.chart.getLegend(DV.state.category.data.length),
                 insetPadding: 60,
+                items: DV.util.chart.getTitle(),
+                legend: DV.util.chart.getLegend(),
                 series: [{
                     type: 'pie',
                     field: DV.store.chart.left[0],
@@ -957,10 +970,11 @@
             });
         },
         reload: function() {
-            var c = Ext.getCmp('center');
+            var c = Ext.getCmp('center'),
+                t = null;
             c.removeAll(true);
             c.add(this.chart);
-            c.down('label').setText(DV.state.filter.data[0] || 'Example chart');
+            DV.state.filter.data[0] = DV.state.filter.data[0] ? DV.state.filter.data[0] : 'Example chart';
             
             if (!DV.init.isInit) {
                 DV.store.getDataTableStore(true);
@@ -1815,12 +1829,29 @@
                                 }
                             }
                         },
-                        '-',' ',' ',
                         {
-                            xtype: 'label',
-                            text: 'Example chart',
-                            style: 'font-weight:bold; padding:0 4px;'
-                        },
+                            xtype: 'button',
+                            id: 'exportpng_b',
+                            text: '<b style="color:#444">Export image</b>',
+                            cls: 'x-btn-text-icon',
+                            icon: 'images/exportimage.png',
+                            handler: function(b) {
+                                var svg = document.getElementsByTagName('svg');
+                                
+                                if (svg.length < 1) {
+                                    alert('Please use Chrome, Firefox, Opera or Safari to export image');
+                                    return;
+                                }
+                                
+                                document.getElementById('svgField').value = svg[0].parentNode.innerHTML;
+                                document.getElementById('widthField').value = DV.util.viewport.getSize().x - 100;
+                                document.getElementById('heightField').value = DV.util.viewport.getSize().y - 100;
+                                
+                                var exportForm = document.getElementById('exportPNGForm');
+                                exportForm.action = '../exportImage.action';
+                                exportForm.submit();
+                            }
+                        }, '-',
                         '->',
                         {
                             xtype: 'button',

=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/css/style.css'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/css/style.css	2011-11-11 19:05:43 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/css/style.css	2011-11-16 13:24:53 +0000
@@ -323,7 +323,7 @@
 }
 
 /* Update button */
-#update_b, #datatable_b, #exit_b {
+#update_b, #datatable_b, #exportpng_b, #exit_b {
     border-width: 1px;
     padding: 3px 1px 3px 4px;
 }

=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/datatable.png'
Binary files dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/datatable.png	2011-10-11 11:21:03 +0000 and dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/datatable.png	2011-11-16 15:22:52 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/exportimage.png'
Binary files dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/exportimage.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/images/exportimage.png	2011-11-16 15:22:52 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/index.html'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/index.html	2011-10-10 12:12:21 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/index.html	2011-11-16 13:24:53 +0000
@@ -7,6 +7,12 @@
 
     <script type="text/javascript" src="lib/ext/ext-all.js"></script>
     <script type="text/javascript" src="app.js"></script>
+	
+    <form id="exportPNGForm" method="post">
+        <input type="hidden" id="svgField" name="svg"/>
+        <input type="hidden" id="widthField" name="width"/>
+        <input type="hidden" id="heightField" name="height"/>
+    </form>
     
 </head>