/* * WBI Indicator Explorer * * Copyright 2015 Sebastian Nogara <snogaraleal@gmail.com> * * This file is part of WBI. * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package client.ui.components; import java.util.Collection; import java.util.Map; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.dom.client.DivElement; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONNumber; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONString; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; import client.ClientConf; import client.ui.components.utils.Script; /** * Widget displaying a chart. * http://www.flotcharts.org */ public class Chart extends Composite { /** * Series of data that can be displayed in a {@link Chart}. */ public static class Series { /** * Display name of the series. */ private String label; /** * Points to display. */ private Map<Integer, Double> points; /** * Initialize {@code Series}. * * @param label Display name of the series. * @param points Points to display. */ public Series(String label, Map<Integer, Double> points) { this.label = label; this.points = points; } /** * Get display name. * * @return Display name. */ public String getLabel() { return label; } /** * Get points. * * @return Series points. */ public Map<Integer, Double> getPoints() { return points; } /** * Name of the JSON key with the points of a {@code Series}. */ public static final String JS_OBJECT_POINTS = "data"; /** * Name of the JSON key with the label of a {@code Series}. */ public static final String JS_OBJECT_LABEL = "label"; /** * Name of the JSON key with the shadow size of a {@code Series}. */ public static final String JS_OBJECT_SHADOW_SIZE = "shadowSize"; /** * Get a {@code JSONObject} with the information in this * {@code Series} following the structure required by the library. * * @return Series {@code JSONObject}. */ public JSONObject toJSONObject() { String label = getLabel(); Map<Integer, Double> points = getPoints(); int pointsArrayIndex = 0; JSONArray pointsArray = new JSONArray(); for (Map.Entry<Integer, Double> pointEntry : points.entrySet()) { JSONArray pointArray = new JSONArray(); pointArray.set(0, new JSONNumber(pointEntry.getKey())); pointArray.set(1, new JSONNumber(pointEntry.getValue())); pointsArray.set(pointsArrayIndex, pointArray); pointsArrayIndex++; } JSONObject dataObject = new JSONObject(); dataObject.put(JS_OBJECT_POINTS, pointsArray); dataObject.put(JS_OBJECT_LABEL, new JSONString(label)); dataObject.put(JS_OBJECT_SHADOW_SIZE, new JSONNumber(0)); return dataObject; } } public interface ChartUiBinder extends UiBinder<Widget, Chart> {} private static ChartUiBinder uiBinder = GWT.create(ChartUiBinder.class); /** * Element containing the chart. */ @UiField public DivElement div; /** * Library base script. */ public static final String BASE_SCRIPT = ClientConf.asset("js/flot/jquery.flot.min.js"); /** * {@link Script.Loader} for {@link Chart#BASE_SCRIPT}. */ public static final Script.Loader BASE_SCRIPT_LOADER = new Script.Loader(BASE_SCRIPT, Script.JQUERY); /** * Initialize {@code Chart}. */ public Chart() { initWidget(uiBinder.createAndBindUi(this)); } /** * Load the required scripts. * * @param callback {@code Runnable} called when ready. */ private void load(Runnable callback) { BASE_SCRIPT_LOADER.load(callback); } /** * Get a {@code JavaScriptObject} with the information from a * {@code Series} as required by the library. * * @param series {@code Series} object. * @return {@code JavaScriptObject} as required by the library. */ private JavaScriptObject seriesToJSObject(Series series) { return series.toJSONObject().getJavaScriptObject(); } /** * Get a {@code JavaScriptObject} with the information from a collection * of {@code Series} as required by the library. * * @param seriesCollection Collection of {@code Series}. * @return {@code JavaScriptObject} as required by the library. */ private JavaScriptObject seriesListToJSObject( Collection<Series> seriesCollection) { if (seriesCollection == null) { return null; } int dataArrayIndex = 0; JSONArray dataArray = new JSONArray(); for (Series series : seriesCollection) { dataArray.set(dataArrayIndex, series.toJSONObject()); dataArrayIndex++; } return dataArray.getJavaScriptObject(); } /** * Display a collection of {@link Series}. * * @param seriesCollection Collection of {@code Series}. */ public void setSeries(final Collection<Series> seriesCollection) { load(new Runnable() { @Override public void run() { setSeries(seriesListToJSObject(seriesCollection)); } }); } /** * Plot the series information from the specified * {@code JavaScriptObject}. * * @param data Series information as required by the library. * @see Chart#seriesListToJSObject */ private native void setSeries(JavaScriptObject data) /*-{ (function (that, $) { var div = $(that.@client.ui.components.Chart::div); setTimeout(function () { $.plot(div, data, { series: { lines: { show: true, }, points: { show: true, } }, xaxis: { tickSize: 1, tickDecimals: 0 }, grid: { margin: 20, labelMargin: 20, axisMargin: 20, margin: 20, borderColor: 'transparent', hoverable: true }, legend: { noColumns: 6 } }); }); })(this, $wnd.jQuery); }-*/; }