package org.gcube.portlets.admin.accountingmanager.client.maindata.charts.service; import java.util.Date; import org.gcube.portlets.admin.accountingmanager.client.maindata.charts.ChartTimeMeasure; import org.gcube.portlets.admin.accountingmanager.client.resource.AccountingManagerResources; import org.gcube.portlets.admin.accountingmanager.client.state.AccountingStateData; import org.gcube.portlets.admin.accountingmanager.shared.data.response.SeriesService; import org.gcube.portlets.admin.accountingmanager.shared.data.response.SeriesServiceData; import com.allen_sauer.gwt.log.client.Log; import com.github.highcharts4gwt.client.view.widget.HighchartsLayoutPanel; import com.github.highcharts4gwt.model.array.api.ArrayNumber; import com.github.highcharts4gwt.model.array.api.ArrayString; import com.github.highcharts4gwt.model.factory.api.HighchartsOptionFactory; import com.github.highcharts4gwt.model.factory.jso.JsoHighchartsOptionFactory; import com.github.highcharts4gwt.model.highcharts.option.api.ChartOptions; import com.github.highcharts4gwt.model.highcharts.option.api.SeriesArea; import com.github.highcharts4gwt.model.highcharts.option.api.SeriesColumn; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat; import com.sencha.gxt.cell.core.client.ButtonCell.ButtonArrowAlign; import com.sencha.gxt.cell.core.client.ButtonCell.IconAlign; import com.sencha.gxt.core.client.util.Margins; import com.sencha.gxt.widget.core.client.button.TextButton; import com.sencha.gxt.widget.core.client.button.ToggleButton; import com.sencha.gxt.widget.core.client.container.BoxLayoutContainer.BoxLayoutData; import com.sencha.gxt.widget.core.client.container.MarginData; import com.sencha.gxt.widget.core.client.container.SimpleContainer; import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer; import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData; import com.sencha.gxt.widget.core.client.event.SelectEvent; import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler; import com.sencha.gxt.widget.core.client.menu.Item; import com.sencha.gxt.widget.core.client.menu.Menu; import com.sencha.gxt.widget.core.client.menu.MenuItem; import com.sencha.gxt.widget.core.client.toolbar.ToolBar; /** * * @author giancarlo email: g.panichi@isti.cnr.it * */ public class VariableAxisChart extends SimpleContainer { private static final String DOWNLOAD = "Download"; private static final String DOWNLOAD_PNG = "Download PNG Image"; private static final String DOWNLOAD_JPG = "Download JPG Image"; private static final String DOWNLOAD_PDF = "Download PDF Document"; private static final String DOWNLOAD_SVG = "Download SVG Vector Image"; private static final String SINGLE_AXIS = "Single Axis"; private AccountingStateData accountingStateData; private HighchartsLayoutPanel highchartsLayoutPanel; // Replace Menu private MenuItem downloadPNGItem; private MenuItem downloadJPGItem; private MenuItem downloadPDFItem; private MenuItem downloadSVGItem; ChartOptions options; public VariableAxisChart(AccountingStateData accountingStateData) { this.accountingStateData = accountingStateData; forceLayoutOnResize = true; create(); } private void create() { ToolBar toolBar = new ToolBar(); toolBar.setSpacing(2); // Download final TextButton downloadButton = new TextButton(DOWNLOAD, AccountingManagerResources.INSTANCE .accountingChartVariableAxis24()); //downloadButton.setScale(ButtonScale.MEDIUM); downloadButton.setIconAlign(IconAlign.RIGHT); downloadButton.setArrowAlign(ButtonArrowAlign.RIGHT); downloadButton.setMenu(createDownloadMenu()); //toolBar.add(downloadButton, new BoxLayoutData(new Margins(0))); // Single Axis final ToggleButton toggleButton = new ToggleButton(SINGLE_AXIS); toggleButton.setIcon(AccountingManagerResources.INSTANCE .accountingChartVariableAxis24()); toggleButton.setIconAlign(IconAlign.RIGHT); toggleButton.setValue(false); toggleButton.addSelectHandler(new SelectHandler() { @Override public void onSelect(SelectEvent event) { if (toggleButton.getValue()) { createSingleAxisChart(); highchartsLayoutPanel.renderChart(options); } else { createMultiAxisChart(); highchartsLayoutPanel.renderChart(options); } forceLayout(); } }); toolBar.add(toggleButton, new BoxLayoutData(new Margins(0))); // createMultiAxisChart(); highchartsLayoutPanel = new HighchartsLayoutPanel(); highchartsLayoutPanel.renderChart(options); // VerticalLayoutContainer vert = new VerticalLayoutContainer(); vert.add(toolBar, new VerticalLayoutData(1, -1, new Margins(0))); vert.add(highchartsLayoutPanel, new VerticalLayoutData(1, 1, new Margins(0))); add(vert, new MarginData(0)); } private Menu createDownloadMenu() { Menu menuDownload = new Menu(); downloadPNGItem = new MenuItem(DOWNLOAD_PNG, AccountingManagerResources.INSTANCE .accountingChartVariableAxis24()); downloadJPGItem = new MenuItem(DOWNLOAD_JPG, AccountingManagerResources.INSTANCE .accountingChartVariableAxis24()); downloadPDFItem = new MenuItem(DOWNLOAD_PDF, AccountingManagerResources.INSTANCE .accountingChartVariableAxis24()); downloadSVGItem = new MenuItem(DOWNLOAD_SVG, AccountingManagerResources.INSTANCE .accountingChartVariableAxis24()); downloadPNGItem.addSelectionHandler(new SelectionHandler() { @Override public void onSelection(SelectionEvent event) { onDownloadPNG(); } }); downloadJPGItem.addSelectionHandler(new SelectionHandler() { @Override public void onSelection(SelectionEvent event) { onDownloadPNG(); } }); downloadPDFItem.addSelectionHandler(new SelectionHandler() { @Override public void onSelection(SelectionEvent event) { options.exporting(); } }); downloadSVGItem.addSelectionHandler(new SelectionHandler() { @Override public void onSelection(SelectionEvent event) { onDownloadPNG(); } }); menuDownload.add(downloadPNGItem); menuDownload.add(downloadJPGItem); menuDownload.add(downloadPDFItem); menuDownload.add(downloadSVGItem); return menuDownload; } public static native void onDownloadPNG() /*-{ console.log($wnd.Highcharts.Chart); }-*/; private void createMultiAxisChart() { SeriesService seriesService = (SeriesService) accountingStateData .getSeriesResponse(); double minRange = ChartTimeMeasure .calculateMinRange(accountingStateData.getSeriesRequest() .getAccountingPeriod()); double interval = ChartTimeMeasure .calculateInterval(accountingStateData.getSeriesRequest() .getAccountingPeriod()); Date dateStart = new Date(accountingStateData.getSeriesRequest() .getAccountingPeriod().getStartDate().getTime()); dateStart.setTime(dateStart.getTime() + ChartTimeMeasure.timeZoneOffset()*ChartTimeMeasure.MINUTE); Log.debug("BuildChart DateStart: " + DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_FULL) .format(dateStart)); HighchartsOptionFactory highchartsFactory = new JsoHighchartsOptionFactory(); options = highchartsFactory.createChartOptions(); options.navigation().buttonOptions().enabled(true); options.chart().zoomType("xy"); options.title().text("Accounting Service"); /* * options.subtitle().text("Click and drag in the plot area to zoom in"); */ ArrayString colors = options.colors(); // colors.setValue(0, "#cc0038"); // colors.setValue(1, "#32cd32"); // xAxis options.xAxis().type("datetime").minRange(minRange); // yAxis String multiAxis = "[{" + " \"id\": \"OperationCount\"," + " \"labels\": { " + " \"format\": \"{value}\"," + " \"style\": { " + " \"color\": \"" + colors.get(1) + "\"" + " }" + " }," + " \"title\": { " + " \"text\": \"Operation Count\"," + " \"style\": {" + " \"color\": \"" + colors.get(1) + "\"" + " }" + " }" + "} , {" + " \"id\": \"Duration\", " + " \"title\": {" + " \"text\": \"Duration\"," + " \"style\": {" + " \"color\": \"" + colors.get(0) + "\"" + " }" + " }," + " \"labels\": {" + " \"format\": \"{value} ms\"," + " \"style\": {" + " \"color\": \"" + colors.get(0) + "\"" + " }" + " }," + " \"opposite\": \"true\"" + ", \"showFirstLabel\": \"false\"" + "} , {" + " \"id\": \"MaxInvocationTime\", " + " \"title\": {" + " \"text\": \"Max Invocation Time\"," + " \"style\": {" + " \"color\": \"" + colors.get(2) + "\"" + " }" + " }," + " \"labels\": {" + " \"format\": \"{value} ms\"," + " \"style\": {" + " \"color\": \"" + colors.get(2) + "\"" + " }" + " }," + " \"opposite\": \"true\"" + ", \"showFirstLabel\": \"false\"" + "} , {" + " \"id\": \"MinInvocationTime\", " + " \"title\": {" + " \"text\": \"Min Invocation Time\"," + " \"style\": {" + " \"color\": \"" + colors.get(3) + "\"" + " }" + " }," + " \"labels\": {" + " \"format\": \"{value} ms\"," + " \"style\": {" + " \"color\": \"" + colors.get(3) + "\"" + " }" + " }," + " \"opposite\": \"true\"" + ", \"showFirstLabel\": \"false\"" + "}]" ; options.setFieldAsJsonObject("yAxis", multiAxis); // TODO does not seem to be working String fillcolor = "{" + "\"linearGradient\": {" + "\"x1\": 0," + "\"y1\": 0," + "\"x2\": 0," + "\"y2\": 1" + "}," + "\"stops\": [" + "[" + "0, \"#058DC7\"" + "]," + "[" + "1, \"#FFFFFF\"" + "]" + "]" + "}"; options.plotOptions().area() .setFieldAsJsonObject("fillColor", fillcolor).marker() .radius(2).lineWidth(1).states().hover().lineWidth(1); SeriesColumn seriesOperationCount = highchartsFactory .createSeriesColumn(); seriesOperationCount.name("Operation Count"); seriesOperationCount.color(colors.get(1)); seriesOperationCount.type("column"); ArrayNumber dataOperationCount = seriesOperationCount .dataAsArrayNumber(); seriesOperationCount.pointInterval(interval).pointStart( dateStart.getTime()); SeriesArea seriesDuration = highchartsFactory.createSeriesArea(); seriesDuration.name("Duration"); seriesDuration.color(colors.get(0)); seriesDuration.yAxisAsString("Duration"); ArrayNumber dataDuration = seriesDuration.dataAsArrayNumber(); seriesDuration.pointInterval(interval).pointStart(dateStart.getTime()); SeriesArea seriesMaxInvocationTime = highchartsFactory .createSeriesArea(); seriesMaxInvocationTime.name("Max Invocation Time"); seriesMaxInvocationTime.color(colors.get(2)); seriesMaxInvocationTime.yAxisAsString("MaxInvocationTime"); ArrayNumber dataMaxInvocationTime = seriesMaxInvocationTime .dataAsArrayNumber(); seriesMaxInvocationTime.pointInterval(interval).pointStart( dateStart.getTime()); SeriesArea seriesMinInvocationTime = highchartsFactory .createSeriesArea(); seriesMinInvocationTime.name("Min Invocation Time"); seriesMinInvocationTime.color(colors.get(3)); seriesMinInvocationTime.yAxisAsString("MinInvocationTime"); ArrayNumber dataMinInvocationTime = seriesMinInvocationTime .dataAsArrayNumber(); seriesMinInvocationTime.pointInterval(interval).pointStart( dateStart.getTime()); for (SeriesServiceData seriesServiceData : seriesService.getSeries()) { dataOperationCount.push(seriesServiceData.getOperationCount()); dataDuration.push(seriesServiceData.getDuration()); dataMaxInvocationTime .push(seriesServiceData.getMaxInvocationTime()); dataMinInvocationTime .push(seriesServiceData.getMinInvocationTime()); } options.series().addToEnd(seriesOperationCount); options.series().addToEnd(seriesDuration); options.series().addToEnd(seriesMaxInvocationTime); options.series().addToEnd(seriesMinInvocationTime); options.chart().showAxes(true); options.legend().enabled(true); // options.legend().layout("vertical"); // options.legend().align("left"); // options.legend().x(120); // options.legend().verticalAlign("top"); // options.legend().y(100); // options.legend().floating(true); // options.legend() // .backgroundColor( // "(Highcharts.theme && Highcharts.theme.legendBackgroundColor) || 'white'"); return; } private void createSingleAxisChart() { SeriesService seriesService = (SeriesService) accountingStateData .getSeriesResponse(); double minRange = ChartTimeMeasure .calculateMinRange(accountingStateData.getSeriesRequest() .getAccountingPeriod()); double interval = ChartTimeMeasure .calculateInterval(accountingStateData.getSeriesRequest() .getAccountingPeriod()); Date dateStart = new Date(accountingStateData.getSeriesRequest() .getAccountingPeriod().getStartDate().getTime()); dateStart.setTime(dateStart.getTime() + ChartTimeMeasure.timeZoneOffset()*ChartTimeMeasure.MINUTE); Log.debug("BuildChart DateStart: " + DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_FULL) .format(dateStart)); HighchartsOptionFactory highchartsFactory = new JsoHighchartsOptionFactory(); options = highchartsFactory.createChartOptions(); options.navigation().buttonOptions().enabled(true); options.chart().zoomType("xy"); options.title().text("Accounting Service"); /* * options.subtitle().text("Click and drag in the plot area to zoom in"); */ ArrayString colors = options.colors(); // colors.setValue(0, "#cc0038"); // colors.setValue(1, "#32cd32"); // xAxis options.xAxis().type("datetime").minRange(minRange); // yAxis // options.yAxis().title().text("Exchange rate"); // Highcharts.getOptions().colors[0] String multiAxis = "[{" + " \"id\": \"OperationCount\"," + " \"labels\": { " + " \"format\": \"{value}\"," + " \"style\": { " + " \"color\": \"" + colors.get(1) + "\"" + " }" + " }," + " \"title\": { " + " \"text\": \"Operation Count\"," + " \"style\": {" + " \"color\": \"" + colors.get(1) + "\"" + " }" + " }" + "} , {" + " \"id\": \"ServiceData\", " + " \"linkedTo\": \"0\"," + " \"gridLineWidth\": \"0\"," + " \"title\": {" + " \"text\": \"\"," + " \"style\": {" + " \"color\": \"" + colors.get(1) + "\"" + " }" + " }," + " \"labels\": {" + " \"format\": \"{value} ms\"," + " \"style\": {" + " \"color\": \"" + colors.get(1) + "\"" + " }" + " }," + " \"opposite\": \"true\"" + // + // ", \"showFirstLabel\": \"false\"" // + "}]"; options.setFieldAsJsonObject("yAxis", multiAxis); // TODO does not seem to be working String fillcolor = "{" + "\"linearGradient\": {" + "\"x1\": 0," + "\"y1\": 0," + "\"x2\": 0," + "\"y2\": 1" + "}," + "\"stops\": [" + "[" + "0, \"#058DC7\"" + "]," + "[" + "1, \"#FFFFFF\"" + "]" + "]" + "}"; options.plotOptions().area() .setFieldAsJsonObject("fillColor", fillcolor).marker() .radius(2).lineWidth(1).states().hover().lineWidth(1); SeriesColumn seriesOperationCount = highchartsFactory .createSeriesColumn(); seriesOperationCount.name("Operation Count"); seriesOperationCount.color(colors.get(1)); seriesOperationCount.type("column"); ArrayNumber dataOperationCount = seriesOperationCount .dataAsArrayNumber(); seriesOperationCount.pointInterval(interval).pointStart( dateStart.getTime()); SeriesArea seriesDuration = highchartsFactory.createSeriesArea(); seriesDuration.name("Duration"); seriesDuration.color(colors.get(0)); ArrayNumber dataDuration = seriesDuration.dataAsArrayNumber(); seriesDuration.pointInterval(interval).pointStart(dateStart.getTime()); SeriesArea seriesMaxInvocationTime = highchartsFactory .createSeriesArea(); seriesMaxInvocationTime.name("Max Invocation Time"); seriesMaxInvocationTime.color(colors.get(2)); ArrayNumber dataMaxInvocationTime = seriesMaxInvocationTime .dataAsArrayNumber(); seriesMaxInvocationTime.pointInterval(interval).pointStart( dateStart.getTime()); SeriesArea seriesMinInvocationTime = highchartsFactory .createSeriesArea(); seriesMinInvocationTime.name("Min Invocation Time"); seriesMinInvocationTime.color(colors.get(3)); // seriesMinInvocationTime.yAxisAsString("MinInvocationTime"); ArrayNumber dataMinInvocationTime = seriesMinInvocationTime .dataAsArrayNumber(); seriesMinInvocationTime.pointInterval(interval).pointStart( dateStart.getTime()); for (SeriesServiceData seriesServiceData : seriesService.getSeries()) { dataOperationCount.push(seriesServiceData.getOperationCount()); dataDuration.push(seriesServiceData.getDuration()); dataMaxInvocationTime .push(seriesServiceData.getMaxInvocationTime()); dataMinInvocationTime .push(seriesServiceData.getMinInvocationTime()); } options.series().addToEnd(seriesOperationCount); options.series().addToEnd(seriesDuration); options.series().addToEnd(seriesMaxInvocationTime); options.series().addToEnd(seriesMinInvocationTime); options.chart().showAxes(true); options.legend().enabled(true); return; } }