← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 10579: (GIS) Thematic layer 3 and 4 added.

 

Merge authors:
  Jan Henrik Øverland (janhenrik-overland)
------------------------------------------------------------
revno: 10579 [merge]
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2013-04-16 13:13:30 +0200
message:
  (GIS) Thematic layer 3 and 4 added.
added:
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic3_14.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic3_20.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic4_14.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic4_20.png
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/Thematic3.js
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/Thematic4.js
modified:
  dhis-2/dhis-web/dhis-web-mapping/src/main/resources/org/hisp/dhis/mapping/i18n_module.properties
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/index.html
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/app.js
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/core.js
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/plugin.js
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/styles/style.css
  dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/i18n.vm
  dhis-2/dhis-web/dhis-web-pivot/src/main/java/org/hisp/dhis/pivot/action/InitializeAction.java
  dhis-2/dhis-web/dhis-web-pivot/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js
  dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/jsonInitialize.vm


--
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/resources/org/hisp/dhis/mapping/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/resources/org/hisp/dhis/mapping/i18n_module.properties	2013-04-11 16:47:32 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/resources/org/hisp/dhis/mapping/i18n_module.properties	2013-04-16 10:02:32 +0000
@@ -354,6 +354,8 @@
 layer_stack_transparency=Layer stack / transparency
 thematic_layer_1_legend=Thematic layer 1 legend
 thematic_layer_2_legend=Thematic layer 2 legend
+thematic_layer_3_legend=Thematic layer 3 legend
+thematic_layer_4_legend=Thematic layer 4 legend
 facility_layer_legend=Facility layer legend
 facility_layer_export_currently_not_supported=Facility layer export currently not supported
 link_=Link

=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic3_14.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic3_14.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic3_14.png	2013-04-16 10:02:32 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic3_20.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic3_20.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic3_20.png	2013-04-16 10:02:32 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic4_14.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic4_14.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic4_14.png	2013-04-16 10:02:32 +0000 differ
=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic4_20.png'
Binary files dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic4_20.png	1970-01-01 00:00:00 +0000 and dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/images/thematic4_20.png	2013-04-16 10:02:32 +0000 differ
=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/index.html'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/index.html	2013-04-10 15:15:53 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/index.html	2013-04-16 10:46:17 +0000
@@ -12,10 +12,6 @@
 
 <body>
 	<div id="layerItems"></div>
-	<div id="boundaryLegend"></div>
-	<div id="thematic2Legend"></div>
-	<div id="facilityLegend"></div>
-	<div id="symbolLegend"></div>
 
 	<form id="exportForm" method="post">
         <input type="hidden" id="svgField" name="svg"/>
@@ -51,6 +47,8 @@
     <script type="text/javascript" src="scripts/mapfish/core/GeoStat/Boundary.js"></script>
     <script type="text/javascript" src="scripts/mapfish/core/GeoStat/Thematic1.js"></script>
     <script type="text/javascript" src="scripts/mapfish/core/GeoStat/Thematic2.js"></script>
+    <script type="text/javascript" src="scripts/mapfish/core/GeoStat/Thematic3.js"></script>
+    <script type="text/javascript" src="scripts/mapfish/core/GeoStat/Thematic4.js"></script>
     <script type="text/javascript" src="scripts/mapfish/core/GeoStat/Facility.js"></script>
     <script type="text/javascript" src="scripts/mapfish/core/GeoStat/Symbol.js"></script>
     <script type="text/javascript" src="scripts/mapfish/core/Util.js"></script>

=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/app.js	2013-04-11 16:47:32 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/app.js	2013-04-16 10:46:17 +0000
@@ -4774,6 +4774,16 @@
 							width: 26
 						});
 						a.push({
+							iconCls: 'gis-btn-icon-' + gis.layer.thematic3.id,
+							menu: gis.layer.thematic3.menu,
+							width: 26
+						});
+						a.push({
+							iconCls: 'gis-btn-icon-' + gis.layer.thematic4.id,
+							menu: gis.layer.thematic4.menu,
+							width: 26
+						});
+						a.push({
 							iconCls: 'gis-btn-icon-' + gis.layer.facility.id,
 							menu: gis.layer.facility.menu,
 							width: 26
@@ -4927,7 +4937,6 @@
 					},
 					{
 						title: GIS.i18n.thematic_layer_2_legend,
-						contentEl: 'thematic2Legend',
 						bodyStyle: 'padding: 4px 6px 6px; border: 0 none',
 						collapsible: true,
 						collapsed: true,
@@ -4939,8 +4948,31 @@
 						}
 					},
 					{
+						title: GIS.i18n.thematic_layer_3_legend,
+						bodyStyle: 'padding: 4px 6px 6px; border: 0 none',
+						collapsible: true,
+						collapsed: true,
+						animCollapse: false,
+						listeners: {
+							added: function() {
+								gis.layer.thematic3.legendPanel = this;
+							}
+						}
+					},
+					{
+						title: GIS.i18n.thematic_layer_4_legend,
+						bodyStyle: 'padding: 4px 6px 6px; border: 0 none',
+						collapsible: true,
+						collapsed: true,
+						animCollapse: false,
+						listeners: {
+							added: function() {
+								gis.layer.thematic4.legendPanel = this;
+							}
+						}
+					},
+					{
 						title: GIS.i18n.facility_layer_legend,
-						contentEl: 'facilityLegend',
 						bodyStyle: 'padding: 4px 6px 6px; border: 0 none',
 						collapsible: true,
 						collapsed: true,
@@ -5064,6 +5096,18 @@
 			layer.window = GIS.app.WidgetWindow(layer);
 			GIS.core.createSelectHandlers(gis, layer);
 
+			layer = gis.layer.thematic3;
+			layer.menu = GIS.app.LayerMenu(layer);
+			layer.widget = GIS.app.LayerWidgetThematic(layer);
+			layer.window = GIS.app.WidgetWindow(layer);
+			GIS.core.createSelectHandlers(gis, layer);
+
+			layer = gis.layer.thematic4;
+			layer.menu = GIS.app.LayerMenu(layer);
+			layer.widget = GIS.app.LayerWidgetThematic(layer);
+			layer.window = GIS.app.WidgetWindow(layer);
+			GIS.core.createSelectHandlers(gis, layer);
+
 			layer = gis.layer.facility;
 			layer.menu = GIS.app.LayerMenu(layer);
 			layer.widget = GIS.app.LayerWidgetFacility(layer);

=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/core.js'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/core.js	2013-04-10 15:15:53 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/core.js	2013-04-16 11:11:50 +0000
@@ -258,6 +258,8 @@
 		gis.layer.boundary.core.reset();
 		gis.layer.thematic1.core.reset();
 		gis.layer.thematic2.core.reset();
+		gis.layer.thematic3.core.reset();
+		gis.layer.thematic4.core.reset();
 		gis.layer.facility.core.reset();
 	};
 
@@ -336,6 +338,18 @@
 		gis: gis
 	});
 
+	layers.thematic3 = GIS.core.VectorLayer(gis, 'thematic3', 'Thematic layer 3', {opacity: 0.8});
+	layers.thematic3.core = new mapfish.GeoStat.Thematic3(gis.olmap, {
+		layer: layers.thematic3,
+		gis: gis
+	});
+
+	layers.thematic4 = GIS.core.VectorLayer(gis, 'thematic4', 'Thematic layer 4', {opacity: 0.8});
+	layers.thematic4.core = new mapfish.GeoStat.Thematic4(gis.olmap, {
+		layer: layers.thematic4,
+		gis: gis
+	});
+
 	layers.facility = GIS.core.VectorLayer(gis, 'facility', 'Facility layer', {opacity: 0.8});
 	layers.facility.core = new mapfish.GeoStat.Facility(gis.olmap, {
 		layer: layers.facility,

=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/Thematic3.js'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/Thematic3.js	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/Thematic3.js	2013-04-16 10:02:32 +0000
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2007  Camptocamp
+ *
+ * This file is part of MapFish Client
+ *
+ * MapFish Client is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MapFish Client is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MapFish Client.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @requires core/GeoStat.js
+ */
+
+mapfish.GeoStat.Thematic3 = OpenLayers.Class(mapfish.GeoStat, {
+
+    colors: [new mapfish.ColorRgb(120, 120, 0), new mapfish.ColorRgb(255, 0, 0)],
+    method: mapfish.GeoStat.Distribution.CLASSIFY_BY_QUANTILS,
+    numClasses: 5,
+    bounds: null,
+	minSize: 3,
+	maxSize: 20,
+	minVal: null,
+	maxVal: null,
+    defaultSymbolizer: {'fillOpacity': 1},
+    classification: null,
+    colorInterpolation: null,
+
+	gis: null,
+    view: null,
+    featureStore: Ext.create('Ext.data.Store', {
+		fields: ['id', 'name'],
+		features: [],
+		loadFeatures: function(features) {
+			if (features && features.length) {
+				var data = [];
+				for (var i = 0; i < features.length; i++) {
+					data.push([features[i].attributes.id, features[i].attributes.name]);
+				}
+				this.loadData(data);
+				this.sortStore();
+
+				this.features = features;
+			}
+			else {
+				this.removeAll();
+			}
+		},
+		sortStore: function() {
+			this.sort('name', 'ASC');
+		}
+	}),
+
+    initialize: function(map, options) {
+        mapfish.GeoStat.prototype.initialize.apply(this, arguments);
+    },
+
+    getLoader: function() {
+		return GIS.core.LayerLoaderThematic(this.gis, this.layer);
+	},
+
+	reset: function() {
+		this.layer.destroyFeatures();
+		this.featureStore.loadFeatures(this.layer.features.slice(0));
+
+		// Legend
+		this.layer.legendPanel.update('');
+		this.layer.legendPanel.collapse();
+
+		// Widget
+		if (this.layer.widget) {
+			this.layer.widget.reset();
+		}
+	},
+
+	extendView: function(view, config) {
+		view = view || this.view;
+
+		view.valueType = config.valueType || view.valueType;
+		view.indicatorGroup = config.indicatorGroup || view.indicatorGroup;
+		view.indicator = config.indicator || view.indicator;
+		view.dataElementGroup = config.dataElementGroup || view.dataElementGroup;
+		view.dataElement = config.dataElement || view.dataElement;
+		view.periodType = config.periodType || view.periodType;
+		view.period = config.period || view.period;
+		view.legendType = config.legendType || view.legendType;
+		view.legendSet = config.legendSet || view.legendSet;
+		view.classes = config.classes || view.classes;
+		view.method = config.method || view.method;
+		view.colorLow = config.colorLow || view.colorLow;
+		view.colorHigh = config.colorHigh || view.colorHigh;
+		view.radiusLow = config.radiusLow || view.radiusLow;
+		view.radiusHigh = config.radiusHigh || view.radiusHigh;
+		view.organisationUnitLevel = config.organisationUnitLevel || view.organisationUnitLevel;
+		view.parentOrganisationUnit = config.parentOrganisationUnit || view.parentOrganisationUnit;
+		view.parentLevel = config.parentLevel || view.parentLevel;
+		view.parentGraph = config.parentGraph || view.parentGraph;
+		view.opacity = config.opacity || view.opacity;
+
+		return view;
+	},
+
+	getLegendConfig: function() {
+		var indicator = this.view.indicator,
+			dataElement = this.view.dataElement,
+			period = this.view.period,
+			orgUnit = this.view.parentOrganisationUnit,
+			orgUnitLevel = this.view.organisationUnitLevel,
+			parent = orgUnit ? orgUnit.name : '',
+			level = orgUnitLevel ? orgUnitLevel.name : '',
+			what = indicator ? indicator.name : (dataElement ? dataElement.name : ''),
+			when = period ? period.id : '',
+			where = parent + ' / ' + level;
+
+		return {
+			what: what,
+			when: when,
+			where: where
+		};
+	},
+
+	getImageLegendConfig: function() {
+		var bins = this.classification.bins,
+			rgb = this.colorInterpolation,
+			config = [];
+
+		for (var i = 0; i < bins.length; i++) {
+			config.push({
+				color: rgb[i].toHexString(),
+				label: bins[i].lowerBound.toFixed(1) + ' - ' + bins[i].upperBound.toFixed(1) + ' (' + bins[i].nbVal + ')'
+			});
+		}
+
+		return config;
+	},
+
+    updateOptions: function(newOptions) {
+        var oldOptions = OpenLayers.Util.extend({}, this.options);
+        this.addOptions(newOptions);
+        if (newOptions) {
+            this.setClassification();
+        }
+    },
+
+    createColorInterpolation: function() {
+        var numColors = this.classification.bins.length;
+
+        if (this.view.legendType === this.gis.conf.finals.widget.legendtype_automatic) {
+			this.colorInterpolation = mapfish.ColorRgb.getColorsArrayByRgbInterpolation(this.colors[0], this.colors[1], numColors);
+		}
+    },
+
+    setClassification: function() {
+        var values = [];
+        for (var i = 0; i < this.layer.features.length; i++) {
+            values.push(this.layer.features[i].attributes[this.indicator]);
+        }
+
+        var distOptions = {
+            labelGenerator: this.options.labelGenerator
+        };
+        var dist = new mapfish.GeoStat.Distribution(values, distOptions);
+
+		this.minVal = dist.minVal;
+        this.maxVal = dist.maxVal;
+
+        if (this.view.legendType === this.gis.conf.finals.widget.legendtype_predefined) {
+			if (this.bounds[0] > this.minVal) {
+				this.bounds.unshift(this.minVal);
+                //if (this.widget == centroid) { this.widget.symbolizerInterpolation.unshift('blank');
+				this.colorInterpolation.unshift(new mapfish.ColorRgb(240,240,240));
+			}
+
+			if (this.bounds[this.bounds.length-1] < this.maxVal) {
+				this.bounds.push(this.maxVal);
+                //todo if (this.widget == centroid) { G.vars.activeWidget.symbolizerInterpolation.push('blank');
+				this.colorInterpolation.push(new mapfish.ColorRgb(240,240,240));
+			}
+		}
+
+        this.classification = dist.classify(
+            this.method,
+            this.numClasses,
+            this.bounds
+        );
+
+        this.createColorInterpolation();
+    },
+
+    applyClassification: function(options, legend) {
+        this.updateOptions(options, legend);
+
+		var calculateRadius = OpenLayers.Function.bind(
+			function(feature) {
+				var value = feature.attributes[this.indicator];
+                var size = (value - this.minVal) / (this.maxVal - this.minVal) *
+					(this.maxSize - this.minSize) + this.minSize;
+                return size || this.minSize;
+            },	this
+		);
+		this.extendStyle(null, {'pointRadius': '${calculateRadius}'}, {'calculateRadius': calculateRadius});
+
+        var boundsArray = this.classification.getBoundsArray();
+        var rules = new Array(boundsArray.length - 1);
+        for (var i = 0; i < boundsArray.length - 1; i++) {
+            var rule = new OpenLayers.Rule({
+                symbolizer: {fillColor: this.colorInterpolation[i].toHexString()},
+                filter: new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.BETWEEN,
+                    property: this.indicator,
+                    lowerBoundary: boundsArray[i],
+                    upperBoundary: boundsArray[i + 1]
+                })
+            });
+            rules[i] = rule;
+        }
+
+        this.extendStyle(rules);
+        mapfish.GeoStat.prototype.applyClassification.apply(this, arguments);
+    },
+
+    updateLegend: function() {
+		var	element = document.createElement("div"),
+			child,
+			legendType = this.view.legendType,
+			automatic = this.gis.conf.finals.widget.legendtype_automatic,
+			predefined = this.gis.conf.finals.widget.legendtype_predefined,
+			legendNames = this.view.legendSet.names,
+			config = this.getLegendConfig();
+
+        for (var key in config) {
+			if (config.hasOwnProperty(key)) {
+				child = document.createElement("div");
+				child.style.height = "14px";
+				child.style.overflow = "hidden";
+				child.title = config[key];
+				child.innerHTML = config[key];
+				element.appendChild(child);
+
+				child = document.createElement("div");
+				child.style.clear = "left";
+				element.appendChild(child);
+			}
+		}
+
+        child = document.createElement("div");
+        child.style.width = "1px";
+        child.style.height = "5px";
+		element.appendChild(child);
+
+        if (legendType === automatic) {
+            for (var i = 0; i < this.classification.bins.length; i++) {
+                child = document.createElement("div");
+                child.style.backgroundColor = this.colorInterpolation[i].toHexString();
+                child.style.width = "30px";
+                child.style.height = "15px";
+                child.style.cssFloat = "left";
+                child.style.marginRight = "8px";
+				element.appendChild(child);
+
+                child = document.createElement("div");
+                child.innerHTML = this.classification.bins[i].label;
+				element.appendChild(child);
+
+                child = document.createElement("div");
+                child.style.clear = "left";
+				element.appendChild(child);
+            }
+        }
+        else if (legendType === predefined) {
+            for (var i = 0; i < this.classification.bins.length; i++) {
+                child = document.createElement("div");
+                child.style.backgroundColor = this.colorInterpolation[i].toHexString();
+                child.style.width = "30px";
+                child.style.height = legendNames[i] ? "25px" : "20px";
+                child.style.cssFloat = "left";
+                child.style.marginRight = "8px";
+				element.appendChild(child);
+
+                child = document.createElement("div");
+                child.style.lineHeight = legendNames[i] ? "12px" : "7px";
+                child.innerHTML = '<b style="color:#222; font-size:10px !important">' + (legendNames[i] || '') + '</b><br/>' + this.classification.bins[i].label;
+				element.appendChild(child);
+
+                child = document.createElement("div");
+                child.style.clear = "left";
+				element.appendChild(child);
+            }
+        }
+
+        this.layer.legendPanel.update(element.outerHTML);
+    },
+
+    CLASS_NAME: "mapfish.GeoStat.Thematic3"
+});

=== added file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/Thematic4.js'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/Thematic4.js	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/mapfish/core/GeoStat/Thematic4.js	2013-04-16 10:02:32 +0000
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2007  Camptocamp
+ *
+ * This file is part of MapFish Client
+ *
+ * MapFish Client is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MapFish Client is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with MapFish Client.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @requires core/GeoStat.js
+ */
+
+mapfish.GeoStat.Thematic4 = OpenLayers.Class(mapfish.GeoStat, {
+
+    colors: [new mapfish.ColorRgb(120, 120, 0), new mapfish.ColorRgb(255, 0, 0)],
+    method: mapfish.GeoStat.Distribution.CLASSIFY_BY_QUANTILS,
+    numClasses: 5,
+    bounds: null,
+	minSize: 3,
+	maxSize: 20,
+	minVal: null,
+	maxVal: null,
+    defaultSymbolizer: {'fillOpacity': 1},
+    classification: null,
+    colorInterpolation: null,
+
+	gis: null,
+    view: null,
+    featureStore: Ext.create('Ext.data.Store', {
+		fields: ['id', 'name'],
+		features: [],
+		loadFeatures: function(features) {
+			if (features && features.length) {
+				var data = [];
+				for (var i = 0; i < features.length; i++) {
+					data.push([features[i].attributes.id, features[i].attributes.name]);
+				}
+				this.loadData(data);
+				this.sortStore();
+
+				this.features = features;
+			}
+			else {
+				this.removeAll();
+			}
+		},
+		sortStore: function() {
+			this.sort('name', 'ASC');
+		}
+	}),
+
+    initialize: function(map, options) {
+        mapfish.GeoStat.prototype.initialize.apply(this, arguments);
+    },
+
+    getLoader: function() {
+		return GIS.core.LayerLoaderThematic(this.gis, this.layer);
+	},
+
+	reset: function() {
+		this.layer.destroyFeatures();
+		this.featureStore.loadFeatures(this.layer.features.slice(0));
+
+		// Legend
+		this.layer.legendPanel.update('');
+		this.layer.legendPanel.collapse();
+
+		// Widget
+		if (this.layer.widget) {
+			this.layer.widget.reset();
+		}
+	},
+
+	extendView: function(view, config) {
+		view = view || this.view;
+
+		view.valueType = config.valueType || view.valueType;
+		view.indicatorGroup = config.indicatorGroup || view.indicatorGroup;
+		view.indicator = config.indicator || view.indicator;
+		view.dataElementGroup = config.dataElementGroup || view.dataElementGroup;
+		view.dataElement = config.dataElement || view.dataElement;
+		view.periodType = config.periodType || view.periodType;
+		view.period = config.period || view.period;
+		view.legendType = config.legendType || view.legendType;
+		view.legendSet = config.legendSet || view.legendSet;
+		view.classes = config.classes || view.classes;
+		view.method = config.method || view.method;
+		view.colorLow = config.colorLow || view.colorLow;
+		view.colorHigh = config.colorHigh || view.colorHigh;
+		view.radiusLow = config.radiusLow || view.radiusLow;
+		view.radiusHigh = config.radiusHigh || view.radiusHigh;
+		view.organisationUnitLevel = config.organisationUnitLevel || view.organisationUnitLevel;
+		view.parentOrganisationUnit = config.parentOrganisationUnit || view.parentOrganisationUnit;
+		view.parentLevel = config.parentLevel || view.parentLevel;
+		view.parentGraph = config.parentGraph || view.parentGraph;
+		view.opacity = config.opacity || view.opacity;
+
+		return view;
+	},
+
+	getLegendConfig: function() {
+		var indicator = this.view.indicator,
+			dataElement = this.view.dataElement,
+			period = this.view.period,
+			orgUnit = this.view.parentOrganisationUnit,
+			orgUnitLevel = this.view.organisationUnitLevel,
+			parent = orgUnit ? orgUnit.name : '',
+			level = orgUnitLevel ? orgUnitLevel.name : '',
+			what = indicator ? indicator.name : (dataElement ? dataElement.name : ''),
+			when = period ? period.id : '',
+			where = parent + ' / ' + level;
+
+		return {
+			what: what,
+			when: when,
+			where: where
+		};
+	},
+
+	getImageLegendConfig: function() {
+		var bins = this.classification.bins,
+			rgb = this.colorInterpolation,
+			config = [];
+
+		for (var i = 0; i < bins.length; i++) {
+			config.push({
+				color: rgb[i].toHexString(),
+				label: bins[i].lowerBound.toFixed(1) + ' - ' + bins[i].upperBound.toFixed(1) + ' (' + bins[i].nbVal + ')'
+			});
+		}
+
+		return config;
+	},
+
+    updateOptions: function(newOptions) {
+        var oldOptions = OpenLayers.Util.extend({}, this.options);
+        this.addOptions(newOptions);
+        if (newOptions) {
+            this.setClassification();
+        }
+    },
+
+    createColorInterpolation: function() {
+        var numColors = this.classification.bins.length;
+
+        if (this.view.legendType === this.gis.conf.finals.widget.legendtype_automatic) {
+			this.colorInterpolation = mapfish.ColorRgb.getColorsArrayByRgbInterpolation(this.colors[0], this.colors[1], numColors);
+		}
+    },
+
+    setClassification: function() {
+        var values = [];
+        for (var i = 0; i < this.layer.features.length; i++) {
+            values.push(this.layer.features[i].attributes[this.indicator]);
+        }
+
+        var distOptions = {
+            labelGenerator: this.options.labelGenerator
+        };
+        var dist = new mapfish.GeoStat.Distribution(values, distOptions);
+
+		this.minVal = dist.minVal;
+        this.maxVal = dist.maxVal;
+
+        if (this.view.legendType === this.gis.conf.finals.widget.legendtype_predefined) {
+			if (this.bounds[0] > this.minVal) {
+				this.bounds.unshift(this.minVal);
+                //if (this.widget == centroid) { this.widget.symbolizerInterpolation.unshift('blank');
+				this.colorInterpolation.unshift(new mapfish.ColorRgb(240,240,240));
+			}
+
+			if (this.bounds[this.bounds.length-1] < this.maxVal) {
+				this.bounds.push(this.maxVal);
+                //todo if (this.widget == centroid) { G.vars.activeWidget.symbolizerInterpolation.push('blank');
+				this.colorInterpolation.push(new mapfish.ColorRgb(240,240,240));
+			}
+		}
+
+        this.classification = dist.classify(
+            this.method,
+            this.numClasses,
+            this.bounds
+        );
+
+        this.createColorInterpolation();
+    },
+
+    applyClassification: function(options, legend) {
+        this.updateOptions(options, legend);
+
+		var calculateRadius = OpenLayers.Function.bind(
+			function(feature) {
+				var value = feature.attributes[this.indicator];
+                var size = (value - this.minVal) / (this.maxVal - this.minVal) *
+					(this.maxSize - this.minSize) + this.minSize;
+                return size || this.minSize;
+            },	this
+		);
+		this.extendStyle(null, {'pointRadius': '${calculateRadius}'}, {'calculateRadius': calculateRadius});
+
+        var boundsArray = this.classification.getBoundsArray();
+        var rules = new Array(boundsArray.length - 1);
+        for (var i = 0; i < boundsArray.length - 1; i++) {
+            var rule = new OpenLayers.Rule({
+                symbolizer: {fillColor: this.colorInterpolation[i].toHexString()},
+                filter: new OpenLayers.Filter.Comparison({
+                    type: OpenLayers.Filter.Comparison.BETWEEN,
+                    property: this.indicator,
+                    lowerBoundary: boundsArray[i],
+                    upperBoundary: boundsArray[i + 1]
+                })
+            });
+            rules[i] = rule;
+        }
+
+        this.extendStyle(rules);
+        mapfish.GeoStat.prototype.applyClassification.apply(this, arguments);
+    },
+
+    updateLegend: function() {
+		var	element = document.createElement("div"),
+			child,
+			legendType = this.view.legendType,
+			automatic = this.gis.conf.finals.widget.legendtype_automatic,
+			predefined = this.gis.conf.finals.widget.legendtype_predefined,
+			legendNames = this.view.legendSet.names,
+			config = this.getLegendConfig();
+
+        for (var key in config) {
+			if (config.hasOwnProperty(key)) {
+				child = document.createElement("div");
+				child.style.height = "14px";
+				child.style.overflow = "hidden";
+				child.title = config[key];
+				child.innerHTML = config[key];
+				element.appendChild(child);
+
+				child = document.createElement("div");
+				child.style.clear = "left";
+				element.appendChild(child);
+			}
+		}
+
+        child = document.createElement("div");
+        child.style.width = "1px";
+        child.style.height = "5px";
+		element.appendChild(child);
+
+        if (legendType === automatic) {
+            for (var i = 0; i < this.classification.bins.length; i++) {
+                child = document.createElement("div");
+                child.style.backgroundColor = this.colorInterpolation[i].toHexString();
+                child.style.width = "30px";
+                child.style.height = "15px";
+                child.style.cssFloat = "left";
+                child.style.marginRight = "8px";
+				element.appendChild(child);
+
+                child = document.createElement("div");
+                child.innerHTML = this.classification.bins[i].label;
+				element.appendChild(child);
+
+                child = document.createElement("div");
+                child.style.clear = "left";
+				element.appendChild(child);
+            }
+        }
+        else if (legendType === predefined) {
+            for (var i = 0; i < this.classification.bins.length; i++) {
+                child = document.createElement("div");
+                child.style.backgroundColor = this.colorInterpolation[i].toHexString();
+                child.style.width = "30px";
+                child.style.height = legendNames[i] ? "25px" : "20px";
+                child.style.cssFloat = "left";
+                child.style.marginRight = "8px";
+				element.appendChild(child);
+
+                child = document.createElement("div");
+                child.style.lineHeight = legendNames[i] ? "12px" : "7px";
+                child.innerHTML = '<b style="color:#222; font-size:10px !important">' + (legendNames[i] || '') + '</b><br/>' + this.classification.bins[i].label;
+				element.appendChild(child);
+
+                child = document.createElement("div");
+                child.style.clear = "left";
+				element.appendChild(child);
+            }
+        }
+
+        this.layer.legendPanel.update(element.outerHTML);
+    },
+
+    CLASS_NAME: "mapfish.GeoStat.Thematic4"
+});

=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/plugin.js'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/plugin.js	2013-04-02 08:48:30 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/scripts/plugin.js	2013-04-16 10:02:32 +0000
@@ -209,6 +209,22 @@
 								}
 							},
 							{
+								title: GIS.i18n.thematic_layer_3_legend,
+								listeners: {
+									added: function() {
+										gis.layer.thematic3.legendPanel = this;
+									}
+								}
+							},
+							{
+								title: GIS.i18n.thematic_layer_4_legend,
+								listeners: {
+									added: function() {
+										gis.layer.thematic4.legendPanel = this;
+									}
+								}
+							},
+							{
 								title: GIS.i18n.facility_layer_legend,
 								listeners: {
 									added: function() {
@@ -257,6 +273,8 @@
 			GIS.core.createSelectHandlers(gis, gis.layer.boundary);
 			GIS.core.createSelectHandlers(gis, gis.layer.thematic1);
 			GIS.core.createSelectHandlers(gis, gis.layer.thematic2);
+			GIS.core.createSelectHandlers(gis, gis.layer.thematic3);
+			GIS.core.createSelectHandlers(gis, gis.layer.thematic4);
 			GIS.core.createSelectHandlers(gis, gis.layer.facility);
 
 			gis.map = {

=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/styles/style.css'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/styles/style.css	2013-03-19 17:53:03 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/app/styles/style.css	2013-04-16 10:02:32 +0000
@@ -310,6 +310,8 @@
 	.x-toolbar .gis-btn-icon-boundary,
 	.x-toolbar .gis-btn-icon-thematic1,
 	.x-toolbar .gis-btn-icon-thematic2,
+	.x-toolbar .gis-btn-icon-thematic3,
+	.x-toolbar .gis-btn-icon-thematic4,
 	.x-toolbar .gis-btn-icon-facility,
 	.x-toolbar .gis-btn-icon-symbol {
 		width: 24px !important;
@@ -324,6 +326,12 @@
 	.x-toolbar .gis-btn-icon-thematic2 {
 		background: url('../images/thematic2_20.png') no-repeat;
 	}
+	.x-toolbar .gis-btn-icon-thematic3 {
+		background: url('../images/thematic3_20.png') no-repeat;
+	}
+	.x-toolbar .gis-btn-icon-thematic4 {
+		background: url('../images/thematic4_20.png') no-repeat;
+	}
 	.x-toolbar .gis-btn-icon-facility {
 		background: url('../images/facility_20.png') no-repeat;
 	}
@@ -486,6 +494,12 @@
 .gis-window-title-icon-thematic2 {
 	background: url('../images/thematic2_14.png') no-repeat;
 }
+.gis-window-title-icon-thematic3 {
+	background: url('../images/thematic3_14.png') no-repeat;
+}
+.gis-window-title-icon-thematic4 {
+	background: url('../images/thematic4_14.png') no-repeat;
+}
 .gis-window-title-icon-facility {
 	background: url('../images/facility_14.png') no-repeat;
 }

=== modified file 'dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/i18n.vm'
--- dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/i18n.vm	2013-04-11 16:47:32 +0000
+++ dhis-2/dhis-web/dhis-web-mapping/src/main/webapp/dhis-web-mapping/i18n.vm	2013-04-16 10:02:32 +0000
@@ -378,6 +378,8 @@
     layer_stack_transparency: '$encoder.jsEscape($i18n.getString( 'layer_stack_transparency' ) , "'")',
     thematic_layer_1_legend: '$encoder.jsEscape($i18n.getString( 'thematic_layer_1_legend' ) , "'")',
     thematic_layer_2_legend: '$encoder.jsEscape($i18n.getString( 'thematic_layer_2_legend' ) , "'")',
+    thematic_layer_3_legend: '$encoder.jsEscape($i18n.getString( 'thematic_layer_3_legend' ) , "'")',
+    thematic_layer_4_legend: '$encoder.jsEscape($i18n.getString( 'thematic_layer_4_legend' ) , "'")',
     facility_layer_legend: '$encoder.jsEscape($i18n.getString( 'facility_layer_legend' ) , "'")',
     facility_layer_export_currently_not_supported: '$encoder.jsEscape($i18n.getString( 'facility_layer_export_currently_not_supported' ) , "'")',
     link_: '$encoder.jsEscape($i18n.getString( 'link_' ) , "'")',

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/java/org/hisp/dhis/pivot/action/InitializeAction.java'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/java/org/hisp/dhis/pivot/action/InitializeAction.java	2013-03-07 09:42:11 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/java/org/hisp/dhis/pivot/action/InitializeAction.java	2013-04-15 20:44:56 +0000
@@ -36,6 +36,8 @@
 import org.hisp.dhis.dataelement.DataElementGroupSet;
 import org.hisp.dhis.dataelement.DataElementService;
 import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.mapping.MapLegendSet;
+import org.hisp.dhis.mapping.MappingService;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitGroupService;
 import org.hisp.dhis.organisationunit.OrganisationUnitGroupSet;
@@ -84,6 +86,13 @@
     {
         this.periodService = periodService;
     }
+    
+    private MappingService mappingService;
+
+    public void setMappingService( MappingService mappingService )
+    {
+        this.mappingService = mappingService;
+    }
 
     private I18nFormat format;
 
@@ -193,6 +202,13 @@
     {
         return last5Years;
     }
+
+    private Collection<MapLegendSet> legendSets;
+
+    public Collection<MapLegendSet> getLegendSets()
+    {
+        return legendSets;
+    }
     
     // -------------------------------------------------------------------------
     // Action implementation
@@ -245,6 +261,8 @@
 
         rp.clear().setLast5Years( true );
         last5Years = periodService.reloadPeriods( setNames( rp.getRelativePeriods() ) );
+        
+        legendSets = mappingService.getAllMapLegendSets();
 
         return SUCCESS;
     }

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/resources/META-INF/dhis/beans.xml	2013-02-25 15:39:41 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/resources/META-INF/dhis/beans.xml	2013-04-15 20:44:56 +0000
@@ -17,6 +17,7 @@
     <property name="dataElementService" ref="org.hisp.dhis.dataelement.DataElementService" />
     <property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
     <property name="organisationUnitGroupService" ref="org.hisp.dhis.organisationunit.OrganisationUnitGroupService" />
+    <property name="mappingService" ref="org.hisp.dhis.mapping.MappingService" />
   </bean>
 
   <!-- OrganisationUnit -->

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js	2013-04-15 10:41:32 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/app.js	2013-04-16 10:02:32 +0000
@@ -3894,7 +3894,7 @@
 				downloadButton: downloadButton,
 				userOrganisationUnit: userOrganisationUnit,
 				userOrganisationUnitChildren: userOrganisationUnitChildren,
-				setFavorite: setFavorite,					
+				setFavorite: setFavorite,
 				items: [
 					westRegion,
 					centerRegion

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js	2013-04-12 09:40:13 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/app/scripts/core.js	2013-04-15 20:44:56 +0000
@@ -1041,7 +1041,7 @@
 					if (!(config && Ext.isObject(config))) {
 						return '';
 					}
-
+					
 					cls = config.cls ? config.cls : '';
 					cls += config.hidden ? ' td-hidden' : '';
 					cls += config.collapsed ? ' td-collapsed' : '';

=== modified file 'dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/jsonInitialize.vm'
--- dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/jsonInitialize.vm	2013-03-13 19:09:29 +0000
+++ dhis-2/dhis-web/dhis-web-pivot/src/main/webapp/dhis-web-pivot/jsonInitialize.vm	2013-04-15 20:44:56 +0000
@@ -5,6 +5,7 @@
 "ouc":[#foreach($ou in $currentUser.getOrganisationUnit().getSortedChildren()){"id":"$ou.uid","name":"$ou.name"}#if($velocityCount < $oucSize),#end#end]},
 "rootNodes":[#foreach($node in $rootNodes){"id": "$!{node.uid}","text": "$!encoder.jsonEncode( ${node.name} )","level": 1,"hasChildrenWithCoordinates": $!{node.hasChildrenWithCoordinates()},"expanded": true}#if($velocityCount<$rootNodes.size()),#end#end],
 "ougs":[#foreach($ougs in $organisationUnitGroupSets){"id":"$!{ougs.uid}","name":"$!encoder.jsonEncode($!{ougs.name})","items":[#foreach($oug in $ougs.getSortedGroups()){"id":"$!{oug.uid}","name":"$!encoder.jsonEncode($!{oug.name})"}#if($velocityCount<$ougs.getSortedGroups().size()),#end#end]}#if($velocityCount<$organisationUnitGroupSets.size()),#end#end],
-"degs":[#foreach($degs in $dataElementGroupSets){"id":"$!{degs.uid}","name":"$!encoder.jsonEncode($!{degs.name})","items":[#foreach($deg in $degs.getSortedGroups()){"id":"$!{deg.uid}","name":"$!encoder.jsonEncode($!{deg.name})"}#if($velocityCount<$degs.getSortedGroups().size()),#end#end]}#if($velocityCount<$dataElementGroupSets.size()),#end#end]
+"degs":[#foreach($degs in $dataElementGroupSets){"id":"$!{degs.uid}","name":"$!encoder.jsonEncode($!{degs.name})","items":[#foreach($deg in $degs.getSortedGroups()){"id":"$!{deg.uid}","name":"$!encoder.jsonEncode($!{deg.name})"}#if($velocityCount<$degs.getSortedGroups().size()),#end#end]}#if($velocityCount<$dataElementGroupSets.size()),#end#end],
+"legendSets":[#foreach($set in $legendSets){"id":"$!{set.uid}","name":"$!encoder.jsonEncode($!{set.name})","legends":[#foreach($legend in $set.getMapLegends()){"id":"$!{legend.uid}","name":"$!encoder.jsonEncode($!{legend.name})","startValue":"$!{legend.startValue}","endValue":"$!{legend.endValue}","color":"$!encoder.jsonEncode($!{legend.color})","image":"$!encoder.jsonEncode($!{legend.image})"}#if($velocityCount<$set.getMapLegends().size()),#end#end]}#if($velocityCount<$legendSets.size()),#end#end]							
 }
 															
\ No newline at end of file