IDEMPIERE-1583 Zk: Pluggable Chart Renderer Service.
This commit is contained in:
parent
69ca16cbd9
commit
a7db58fb5b
|
@ -0,0 +1,642 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. 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, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.adempiere.apps.graph;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.exceptions.DBException;
|
||||||
|
import org.compiere.model.MChart;
|
||||||
|
import org.compiere.model.MChartDatasource;
|
||||||
|
import org.compiere.model.MQuery;
|
||||||
|
import org.compiere.model.MRole;
|
||||||
|
import org.compiere.model.MTable;
|
||||||
|
import org.compiere.model.X_AD_Chart;
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.compiere.util.DB;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.compiere.util.Util;
|
||||||
|
import org.jfree.chart.ChartFactory;
|
||||||
|
import org.jfree.chart.JFreeChart;
|
||||||
|
import org.jfree.chart.axis.CategoryAxis;
|
||||||
|
import org.jfree.chart.axis.CategoryLabelPositions;
|
||||||
|
import org.jfree.chart.plot.CategoryPlot;
|
||||||
|
import org.jfree.chart.plot.PlotOrientation;
|
||||||
|
import org.jfree.chart.renderer.category.BarRenderer;
|
||||||
|
import org.jfree.chart.renderer.category.CategoryItemRenderer;
|
||||||
|
import org.jfree.chart.renderer.category.StandardBarPainter;
|
||||||
|
import org.jfree.data.category.CategoryDataset;
|
||||||
|
import org.jfree.data.category.DefaultCategoryDataset;
|
||||||
|
import org.jfree.data.general.Dataset;
|
||||||
|
import org.jfree.data.general.DefaultPieDataset;
|
||||||
|
import org.jfree.data.general.PieDataset;
|
||||||
|
import org.jfree.data.time.Day;
|
||||||
|
import org.jfree.data.time.Month;
|
||||||
|
import org.jfree.data.time.Quarter;
|
||||||
|
import org.jfree.data.time.RegularTimePeriod;
|
||||||
|
import org.jfree.data.time.TimeSeries;
|
||||||
|
import org.jfree.data.time.TimeSeriesCollection;
|
||||||
|
import org.jfree.data.time.Week;
|
||||||
|
import org.jfree.data.time.Year;
|
||||||
|
import org.jfree.data.xy.IntervalXYDataset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Paul Bowden, Adaxa Pty Ltd
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ChartBuilder {
|
||||||
|
|
||||||
|
private final static CLogger log = CLogger.getCLogger(ChartBuilder.class);
|
||||||
|
|
||||||
|
private MChart chartModel;
|
||||||
|
private HashMap<String,MQuery> queries;
|
||||||
|
private Dataset dataset;
|
||||||
|
|
||||||
|
public ChartBuilder(MChart chart) {
|
||||||
|
this.chartModel = chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* @return JFreeChart
|
||||||
|
*/
|
||||||
|
public JFreeChart createChart() {
|
||||||
|
|
||||||
|
String type = chartModel.getChartType();
|
||||||
|
|
||||||
|
if(MChart.CHARTTYPE_BarChart.equals(type))
|
||||||
|
{
|
||||||
|
if ( chartModel.isTimeSeries())
|
||||||
|
{
|
||||||
|
return createXYBarChart();
|
||||||
|
}
|
||||||
|
return createBarChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_3DBarChart.equals(type))
|
||||||
|
{
|
||||||
|
return create3DBarChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_StackedBarChart.equals(type))
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( chartModel.isTimeSeries())
|
||||||
|
return createXYBarChart();
|
||||||
|
|
||||||
|
return createStackedBarChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_3DStackedBarChart.equals(type))
|
||||||
|
{
|
||||||
|
return create3DStackedBarChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_3DPieChart.equals(type))
|
||||||
|
{
|
||||||
|
return create3DPieChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_PieChart.equals(type))
|
||||||
|
{
|
||||||
|
return createPieChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_3DLineChart.equals(type))
|
||||||
|
{
|
||||||
|
return create3DLineChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_AreaChart.equals(type))
|
||||||
|
{
|
||||||
|
return createAreaChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_StackedAreaChart.equals(type))
|
||||||
|
{
|
||||||
|
return createStackedAreaChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_LineChart.equals(type))
|
||||||
|
{
|
||||||
|
if ( chartModel.isTimeSeries() )
|
||||||
|
return createTimeSeriesChart();
|
||||||
|
return createLineChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_RingChart.equals(type))
|
||||||
|
{
|
||||||
|
return createRingChart();
|
||||||
|
}
|
||||||
|
else if (MChart.CHARTTYPE_WaterfallChart.equals(type))
|
||||||
|
{
|
||||||
|
return createWaterfallChart();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("unknown chart type=" + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadData() {
|
||||||
|
queries = new HashMap<String,MQuery>();
|
||||||
|
for ( MChartDatasource ds : chartModel.getDatasources() )
|
||||||
|
{
|
||||||
|
addData(ds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addData(MChartDatasource ds) {
|
||||||
|
|
||||||
|
String value = ds.getValueColumn();
|
||||||
|
String category;
|
||||||
|
String unit = "D";
|
||||||
|
|
||||||
|
if ( !chartModel.isTimeSeries() )
|
||||||
|
category = ds.getCategoryColumn();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( chartModel.getTimeUnit().equals(MChart.TIMEUNIT_Week))
|
||||||
|
{
|
||||||
|
unit = "W";
|
||||||
|
}
|
||||||
|
else if ( chartModel.getTimeUnit().equals(MChart.TIMEUNIT_Month))
|
||||||
|
{
|
||||||
|
unit = "MM";
|
||||||
|
}
|
||||||
|
else if ( chartModel.getTimeUnit().equals(MChart.TIMEUNIT_Quarter))
|
||||||
|
{
|
||||||
|
unit = "Q";
|
||||||
|
}
|
||||||
|
else if ( chartModel.getTimeUnit().equals(MChart.TIMEUNIT_Year))
|
||||||
|
{
|
||||||
|
unit = "Y";
|
||||||
|
}
|
||||||
|
|
||||||
|
category = " TRUNC(" + ds.getDateColumn() + ", '" + unit + "') ";
|
||||||
|
}
|
||||||
|
|
||||||
|
String series = DB.TO_STRING(ds.getName());
|
||||||
|
boolean hasSeries = false;
|
||||||
|
if (ds.getSeriesColumn() != null)
|
||||||
|
{
|
||||||
|
series = ds.getSeriesColumn();
|
||||||
|
hasSeries = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String where = ds.getWhereClause();
|
||||||
|
if ( !Util.isEmpty(where))
|
||||||
|
{
|
||||||
|
where = Env.parseContext(Env.getCtx(), chartModel.getWindowNo(), where, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasWhere = false;
|
||||||
|
|
||||||
|
String sql = "SELECT " + value + ", " + category + ", " + series
|
||||||
|
+ " FROM " + ds.getFromClause();
|
||||||
|
if ( !Util.isEmpty(where))
|
||||||
|
{
|
||||||
|
sql += " WHERE " + where;
|
||||||
|
hasWhere = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Date currentDate = Env.getContextAsDate(Env.getCtx(), "#Date");
|
||||||
|
Date startDate = null;
|
||||||
|
Date endDate = null;
|
||||||
|
|
||||||
|
int scope = chartModel.getTimeScope();
|
||||||
|
int offset = ds.getTimeOffset();
|
||||||
|
|
||||||
|
if ( chartModel.isTimeSeries() && scope != 0 )
|
||||||
|
{
|
||||||
|
offset += -scope;
|
||||||
|
startDate = increment(currentDate, chartModel.getTimeUnit(), offset);
|
||||||
|
endDate = increment(startDate, chartModel.getTimeUnit(), scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( startDate != null && endDate != null )
|
||||||
|
{
|
||||||
|
sql += hasWhere ? " AND " : " WHERE ";
|
||||||
|
sql += category + ">=TRUNC(" + DB.TO_DATE(new Timestamp(startDate.getTime())) + ", '" + unit + "') AND ";
|
||||||
|
sql += category + "<=TRUNC(" + DB.TO_DATE(new Timestamp(endDate.getTime())) + ", '" + unit + "') ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sql.indexOf('@') >= 0) {
|
||||||
|
sql = Env.parseContext(Env.getCtx(), 0, sql, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
MRole role = MRole.getDefault(Env.getCtx(), false);
|
||||||
|
sql = role.addAccessSQL(sql, null, true, false);
|
||||||
|
|
||||||
|
if (hasSeries)
|
||||||
|
sql += " GROUP BY " + series + ", " + category + " ORDER BY " + series + ", " + category;
|
||||||
|
else
|
||||||
|
sql += " GROUP BY " + category + " ORDER BY " + category;
|
||||||
|
|
||||||
|
log.log(Level.FINE, sql);
|
||||||
|
|
||||||
|
PreparedStatement pstmt = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
TimeSeries tseries = null;
|
||||||
|
Dataset dataset = getDataset();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pstmt = DB.prepareStatement(sql, null);
|
||||||
|
rs = pstmt.executeQuery();
|
||||||
|
while(rs.next())
|
||||||
|
{
|
||||||
|
|
||||||
|
String key = rs.getString(2);
|
||||||
|
String seriesName = rs.getString(3);
|
||||||
|
if (seriesName == null)
|
||||||
|
seriesName = ds.getName();
|
||||||
|
String queryWhere = "";
|
||||||
|
if ( hasWhere )
|
||||||
|
queryWhere += where + " AND ";
|
||||||
|
|
||||||
|
queryWhere += series + " = " + DB.TO_STRING(seriesName) + " AND " + category + " = " ;
|
||||||
|
|
||||||
|
if ( chartModel.isTimeSeries() && dataset instanceof TimeSeriesCollection )
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( tseries == null || !tseries.getKey().equals(seriesName))
|
||||||
|
{
|
||||||
|
if (tseries != null)
|
||||||
|
((TimeSeriesCollection) dataset).addSeries(tseries);
|
||||||
|
|
||||||
|
tseries = new TimeSeries(seriesName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Date date = rs.getDate(2);
|
||||||
|
RegularTimePeriod period = null;
|
||||||
|
|
||||||
|
if ( chartModel.getTimeUnit().equals(MChart.TIMEUNIT_Day))
|
||||||
|
period = new Day(date);
|
||||||
|
else if ( chartModel.getTimeUnit().equals(MChart.TIMEUNIT_Week))
|
||||||
|
period = new Week(date);
|
||||||
|
else if ( chartModel.getTimeUnit().equals(MChart.TIMEUNIT_Month))
|
||||||
|
period = new Month(date);
|
||||||
|
else if ( chartModel.getTimeUnit().equals(MChart.TIMEUNIT_Quarter))
|
||||||
|
period = new Quarter(date);
|
||||||
|
else if ( chartModel.getTimeUnit().equals(MChart.TIMEUNIT_Year))
|
||||||
|
period = new Year(date);
|
||||||
|
|
||||||
|
tseries.add(period, rs.getBigDecimal(1));
|
||||||
|
key = period.toString();
|
||||||
|
queryWhere += DB.TO_DATE(new Timestamp(date.getTime()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
queryWhere += DB.TO_STRING(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
MQuery query = new MQuery(ds.getAD_Table_ID());
|
||||||
|
String keyCol = MTable.get(Env.getCtx(), ds.getAD_Table_ID()).getKeyColumns()[0];
|
||||||
|
String whereClause = keyCol + " IN (SELECT " + ds.getKeyColumn() + " FROM "
|
||||||
|
+ ds.getFromClause() + " WHERE " + queryWhere + " )";
|
||||||
|
query.addRestriction(whereClause.toString());
|
||||||
|
query.setRecordCount(1);
|
||||||
|
|
||||||
|
HashMap<String, MQuery> map = getQueries();
|
||||||
|
|
||||||
|
if ( dataset instanceof DefaultPieDataset) {
|
||||||
|
((DefaultPieDataset) dataset).setValue(key, rs.getBigDecimal(1));
|
||||||
|
map.put(key, query);
|
||||||
|
}
|
||||||
|
else if ( dataset instanceof DefaultCategoryDataset ) {
|
||||||
|
((DefaultCategoryDataset) dataset).addValue(rs.getBigDecimal(1), seriesName, key);
|
||||||
|
map.put(seriesName + "__" + key, query);
|
||||||
|
}
|
||||||
|
else if (dataset instanceof TimeSeriesCollection )
|
||||||
|
{
|
||||||
|
map.put(seriesName + "__" + key, query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException e)
|
||||||
|
{
|
||||||
|
throw new DBException(e, sql);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
DB.close(rs, pstmt);
|
||||||
|
rs = null; pstmt = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tseries != null)
|
||||||
|
((TimeSeriesCollection) dataset).addSeries(tseries);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date increment(Date lastDate, String timeUnit, int qty) {
|
||||||
|
|
||||||
|
if ( lastDate == null )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(lastDate);
|
||||||
|
|
||||||
|
if ( timeUnit.equals(MChart.TIMEUNIT_Day))
|
||||||
|
cal.add(Calendar.DAY_OF_YEAR, qty);
|
||||||
|
else if ( timeUnit.equals(MChart.TIMEUNIT_Week))
|
||||||
|
cal.add(Calendar.WEEK_OF_YEAR, qty);
|
||||||
|
else if ( timeUnit.equals(MChart.TIMEUNIT_Month))
|
||||||
|
cal.add(Calendar.MONTH, qty);
|
||||||
|
else if ( timeUnit.equals(MChart.TIMEUNIT_Quarter))
|
||||||
|
cal.add(Calendar.MONTH, 3*qty);
|
||||||
|
else if ( timeUnit.equals(MChart.TIMEUNIT_Year))
|
||||||
|
cal.add(Calendar.YEAR, qty);
|
||||||
|
|
||||||
|
return cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CategoryDataset getCategoryDataset() {
|
||||||
|
dataset = new DefaultCategoryDataset();
|
||||||
|
loadData();
|
||||||
|
return (CategoryDataset) dataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntervalXYDataset getXYDataset() {
|
||||||
|
dataset = new TimeSeriesCollection();
|
||||||
|
loadData();
|
||||||
|
return (IntervalXYDataset) dataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PieDataset getPieDataset() {
|
||||||
|
dataset = new DefaultPieDataset();
|
||||||
|
loadData();
|
||||||
|
return (PieDataset) dataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dataset getDataset() {
|
||||||
|
return dataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, MQuery> getQueries() {
|
||||||
|
return queries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MQuery getQuery(String key) {
|
||||||
|
|
||||||
|
|
||||||
|
if ( queries.containsKey(key) )
|
||||||
|
{
|
||||||
|
return queries.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart createXYBarChart() {
|
||||||
|
JFreeChart chart = ChartFactory.createXYBarChart(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
true,
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getXYDataset(), // data
|
||||||
|
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(chartModel.getChartOrientation())
|
||||||
|
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart createTimeSeriesChart() {
|
||||||
|
JFreeChart chart = ChartFactory.createTimeSeriesChart(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getXYDataset(), // data
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart createWaterfallChart() {
|
||||||
|
JFreeChart chart = ChartFactory.createWaterfallChart(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getCategoryDataset(), // data
|
||||||
|
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(chartModel.getChartOrientation())
|
||||||
|
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
setupCategoryChart(chart);
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart createRingChart() {
|
||||||
|
final JFreeChart chart = ChartFactory.createRingChart(chartModel.getName(),
|
||||||
|
getPieDataset(), chartModel.isDisplayLegend(), true, true);
|
||||||
|
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart createPieChart() {
|
||||||
|
final JFreeChart chart = ChartFactory.createPieChart(chartModel.getName(),
|
||||||
|
getPieDataset(), false, true, true);
|
||||||
|
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart create3DPieChart() {
|
||||||
|
final JFreeChart chart = ChartFactory.createPieChart3D(chartModel.getName(),
|
||||||
|
getPieDataset(), false, true, true);
|
||||||
|
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart createBarChart() {
|
||||||
|
JFreeChart chart = ChartFactory.createBarChart(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getCategoryDataset(), // data
|
||||||
|
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(chartModel.getChartOrientation())
|
||||||
|
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
BarRenderer renderer = new BarRenderer();
|
||||||
|
renderer.setBarPainter(new StandardBarPainter());
|
||||||
|
|
||||||
|
CategoryPlot plot = chart.getCategoryPlot();
|
||||||
|
plot.setRenderer(renderer);
|
||||||
|
|
||||||
|
setupCategoryChart(chart);
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart create3DBarChart() {
|
||||||
|
JFreeChart chart = ChartFactory.createBarChart3D(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getCategoryDataset(), // data
|
||||||
|
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(chartModel.getChartOrientation())
|
||||||
|
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
setupCategoryChart(chart);
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart createStackedBarChart() {
|
||||||
|
JFreeChart chart = ChartFactory.createStackedBarChart(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getCategoryDataset(), // data
|
||||||
|
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(chartModel.getChartOrientation())
|
||||||
|
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
BarRenderer renderer = new BarRenderer();
|
||||||
|
renderer.setBarPainter(new StandardBarPainter());
|
||||||
|
|
||||||
|
CategoryPlot plot = chart.getCategoryPlot();
|
||||||
|
plot.setRenderer(renderer);
|
||||||
|
|
||||||
|
setupCategoryChart(chart);
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart create3DStackedBarChart() {
|
||||||
|
JFreeChart chart = ChartFactory.createStackedBarChart3D(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getCategoryDataset(), // data
|
||||||
|
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(chartModel.getChartOrientation())
|
||||||
|
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
setupCategoryChart(chart);
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart createAreaChart() {
|
||||||
|
// create the chart...
|
||||||
|
JFreeChart chart = ChartFactory.createAreaChart(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getCategoryDataset(), // data
|
||||||
|
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(chartModel.getChartOrientation())
|
||||||
|
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
setupCategoryChart(chart);
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart createStackedAreaChart() {
|
||||||
|
// create the chart...
|
||||||
|
JFreeChart chart = ChartFactory.createStackedAreaChart(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getCategoryDataset(), // data
|
||||||
|
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(chartModel.getChartOrientation())
|
||||||
|
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
setupCategoryChart(chart);
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart createLineChart() {
|
||||||
|
// create the chart...
|
||||||
|
JFreeChart chart = ChartFactory.createLineChart(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getCategoryDataset(), // data
|
||||||
|
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(chartModel.getChartOrientation())
|
||||||
|
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
setupCategoryChart(chart);
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JFreeChart create3DLineChart() {
|
||||||
|
// create the chart...
|
||||||
|
JFreeChart chart = ChartFactory.createLineChart3D(
|
||||||
|
chartModel.getName(), // chart title
|
||||||
|
chartModel.getDomainLabel(), // domain axis label
|
||||||
|
chartModel.getRangeLabel(), // range axis label
|
||||||
|
getCategoryDataset(), // data
|
||||||
|
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(chartModel.getChartOrientation())
|
||||||
|
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
||||||
|
chartModel.isDisplayLegend(), // include legend
|
||||||
|
true, // tooltips?
|
||||||
|
true // URLs?
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
setupCategoryChart(chart);
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupCategoryChart(JFreeChart chart) {
|
||||||
|
CategoryPlot plot = chart.getCategoryPlot();
|
||||||
|
CategoryAxis xAxis = (CategoryAxis)plot.getDomainAxis();
|
||||||
|
xAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
|
||||||
|
|
||||||
|
CategoryItemRenderer renderer = plot.getRenderer();
|
||||||
|
renderer.setSeriesPaint(0, Color.RED);
|
||||||
|
renderer.setSeriesPaint(1, Color.BLUE);
|
||||||
|
renderer.setSeriesPaint(2, Color.YELLOW);
|
||||||
|
renderer.setSeriesPaint(3, Color.GREEN);
|
||||||
|
renderer.setSeriesPaint(4, Color.ORANGE);
|
||||||
|
renderer.setSeriesPaint(5, Color.CYAN);
|
||||||
|
renderer.setSeriesPaint(6, Color.MAGENTA);
|
||||||
|
renderer.setSeriesPaint(7, Color.GRAY);
|
||||||
|
renderer.setSeriesPaint(8, Color.PINK);
|
||||||
|
|
||||||
|
plot.setRenderer(renderer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ package org.adempiere.apps.graph;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.compiere.model.MGoal;
|
import org.compiere.model.MGoal;
|
||||||
import org.compiere.model.MMeasure;
|
import org.compiere.model.MMeasure;
|
||||||
|
@ -245,6 +246,11 @@ public class GraphBuilder {
|
||||||
|
|
||||||
ArrayList<GraphColumn>list = measure.getGraphColumnList(getMGoal());
|
ArrayList<GraphColumn>list = measure.getGraphColumnList(getMGoal());
|
||||||
|
|
||||||
|
loadDataSet(list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadDataSet(List<GraphColumn> list) {
|
||||||
pieDataset = new DefaultPieDataset();
|
pieDataset = new DefaultPieDataset();
|
||||||
dataset = new DefaultCategoryDataset();
|
dataset = new DefaultCategoryDataset();
|
||||||
for (int i = 0; i < list.size(); i++){
|
for (int i = 0; i < list.size(); i++){
|
||||||
|
@ -260,6 +266,5 @@ public class GraphBuilder {
|
||||||
list.get(i).getLabel());
|
list.get(i).getLabel());
|
||||||
pieDataset.setValue(list.get(i).getLabel(), list.get(i).getValue());
|
pieDataset.setValue(list.get(i).getLabel(), list.get(i).getValue());
|
||||||
}
|
}
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,27 +1,10 @@
|
||||||
package org.compiere.model;
|
package org.compiere.model;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jfree.chart.ChartFactory;
|
|
||||||
import org.jfree.chart.JFreeChart;
|
|
||||||
import org.jfree.chart.axis.CategoryAxis;
|
|
||||||
import org.jfree.chart.axis.CategoryLabelPositions;
|
|
||||||
import org.jfree.chart.plot.CategoryPlot;
|
|
||||||
import org.jfree.chart.plot.PlotOrientation;
|
|
||||||
import org.jfree.chart.renderer.category.BarRenderer;
|
|
||||||
import org.jfree.chart.renderer.category.CategoryItemRenderer;
|
|
||||||
import org.jfree.chart.renderer.category.StandardBarPainter;
|
|
||||||
import org.jfree.data.category.CategoryDataset;
|
|
||||||
import org.jfree.data.category.DefaultCategoryDataset;
|
|
||||||
import org.jfree.data.general.Dataset;
|
|
||||||
import org.jfree.data.general.DefaultPieDataset;
|
|
||||||
import org.jfree.data.general.PieDataset;
|
|
||||||
import org.jfree.data.time.TimeSeriesCollection;
|
|
||||||
import org.jfree.data.xy.IntervalXYDataset;
|
|
||||||
|
|
||||||
public class MChart extends X_AD_Chart {
|
public class MChart extends X_AD_Chart {
|
||||||
|
|
||||||
|
@ -31,8 +14,6 @@ public class MChart extends X_AD_Chart {
|
||||||
private static final long serialVersionUID = -8851465915516536910L;
|
private static final long serialVersionUID = -8851465915516536910L;
|
||||||
|
|
||||||
private int windowNo=0;
|
private int windowNo=0;
|
||||||
private Dataset dataset;
|
|
||||||
private HashMap<String,MQuery> queries;
|
|
||||||
|
|
||||||
public MChart(Properties ctx, int AD_Chart_ID, String trxName) {
|
public MChart(Properties ctx, int AD_Chart_ID, String trxName) {
|
||||||
super(ctx, AD_Chart_ID, trxName);
|
super(ctx, AD_Chart_ID, trxName);
|
||||||
|
@ -42,46 +23,12 @@ public class MChart extends X_AD_Chart {
|
||||||
super(ctx, rs, trxName);
|
super(ctx, rs, trxName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadData() {
|
public List<MChartDatasource> getDatasources() {
|
||||||
queries = new HashMap<String,MQuery>();
|
|
||||||
for ( MChartDatasource ds : getDatasources() )
|
|
||||||
{
|
|
||||||
ds.addData(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CategoryDataset getCategoryDataset() {
|
|
||||||
dataset = new DefaultCategoryDataset();
|
|
||||||
loadData();
|
|
||||||
return (CategoryDataset) dataset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IntervalXYDataset getXYDataset() {
|
|
||||||
dataset = new TimeSeriesCollection();
|
|
||||||
loadData();
|
|
||||||
return (IntervalXYDataset) dataset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PieDataset getPieDataset() {
|
|
||||||
dataset = new DefaultPieDataset();
|
|
||||||
loadData();
|
|
||||||
return (PieDataset) dataset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dataset getDataset() {
|
|
||||||
return dataset;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<MChartDatasource> getDatasources() {
|
|
||||||
|
|
||||||
return new Query(getCtx(), MChartDatasource.Table_Name, MChart.COLUMNNAME_AD_Chart_ID + "=?", null)
|
return new Query(getCtx(), MChartDatasource.Table_Name, MChart.COLUMNNAME_AD_Chart_ID + "=?", null)
|
||||||
.setParameters(getAD_Chart_ID()).setOnlyActiveRecords(true).list();
|
.setParameters(getAD_Chart_ID()).setOnlyActiveRecords(true).list();
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashMap<String, MQuery> getQueries() {
|
|
||||||
return queries;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWindowNo(int windowNo) {
|
public void setWindowNo(int windowNo) {
|
||||||
this.windowNo = windowNo;
|
this.windowNo = windowNo;
|
||||||
}
|
}
|
||||||
|
@ -89,334 +36,4 @@ public class MChart extends X_AD_Chart {
|
||||||
public int getWindowNo() {
|
public int getWindowNo() {
|
||||||
return windowNo;
|
return windowNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MQuery getQuery(String key) {
|
|
||||||
|
|
||||||
|
|
||||||
if ( queries.containsKey(key) )
|
|
||||||
{
|
|
||||||
return queries.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* @return JFreeChart
|
|
||||||
*/
|
|
||||||
public JFreeChart createChart() {
|
|
||||||
|
|
||||||
String type = getChartType();
|
|
||||||
|
|
||||||
if(MChart.CHARTTYPE_BarChart.equals(type))
|
|
||||||
{
|
|
||||||
if ( isTimeSeries())
|
|
||||||
{
|
|
||||||
return createXYBarChart();
|
|
||||||
}
|
|
||||||
return createBarChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_3DBarChart.equals(type))
|
|
||||||
{
|
|
||||||
return create3DBarChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_StackedBarChart.equals(type))
|
|
||||||
{
|
|
||||||
|
|
||||||
if ( isTimeSeries())
|
|
||||||
return createXYBarChart();
|
|
||||||
|
|
||||||
return createStackedBarChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_3DStackedBarChart.equals(type))
|
|
||||||
{
|
|
||||||
return create3DStackedBarChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_3DPieChart.equals(type))
|
|
||||||
{
|
|
||||||
return create3DPieChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_PieChart.equals(type))
|
|
||||||
{
|
|
||||||
return createPieChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_3DLineChart.equals(type))
|
|
||||||
{
|
|
||||||
return create3DLineChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_AreaChart.equals(type))
|
|
||||||
{
|
|
||||||
return createAreaChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_StackedAreaChart.equals(type))
|
|
||||||
{
|
|
||||||
return createStackedAreaChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_LineChart.equals(type))
|
|
||||||
{
|
|
||||||
if ( isTimeSeries() )
|
|
||||||
return createTimeSeriesChart();
|
|
||||||
return createLineChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_RingChart.equals(type))
|
|
||||||
{
|
|
||||||
return createRingChart();
|
|
||||||
}
|
|
||||||
else if (MChart.CHARTTYPE_WaterfallChart.equals(type))
|
|
||||||
{
|
|
||||||
return createWaterfallChart();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("unknown chart type=" + type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart createXYBarChart() {
|
|
||||||
JFreeChart chart = ChartFactory.createXYBarChart(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
true,
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getXYDataset(), // data
|
|
||||||
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(getChartOrientation())
|
|
||||||
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart createTimeSeriesChart() {
|
|
||||||
JFreeChart chart = ChartFactory.createTimeSeriesChart(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getXYDataset(), // data
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart createWaterfallChart() {
|
|
||||||
JFreeChart chart = ChartFactory.createWaterfallChart(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getCategoryDataset(), // data
|
|
||||||
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(getChartOrientation())
|
|
||||||
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
setupCategoryChart(chart);
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart createRingChart() {
|
|
||||||
final JFreeChart chart = ChartFactory.createRingChart(getName(),
|
|
||||||
getPieDataset(), isDisplayLegend(), true, true);
|
|
||||||
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart createPieChart() {
|
|
||||||
final JFreeChart chart = ChartFactory.createPieChart(getName(),
|
|
||||||
getPieDataset(), false, true, true);
|
|
||||||
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart create3DPieChart() {
|
|
||||||
final JFreeChart chart = ChartFactory.createPieChart3D(getName(),
|
|
||||||
getPieDataset(), false, true, true);
|
|
||||||
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart createBarChart() {
|
|
||||||
JFreeChart chart = ChartFactory.createBarChart(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getCategoryDataset(), // data
|
|
||||||
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(getChartOrientation())
|
|
||||||
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
BarRenderer renderer = new BarRenderer();
|
|
||||||
renderer.setBarPainter(new StandardBarPainter());
|
|
||||||
|
|
||||||
CategoryPlot plot = chart.getCategoryPlot();
|
|
||||||
plot.setRenderer(renderer);
|
|
||||||
|
|
||||||
setupCategoryChart(chart);
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart create3DBarChart() {
|
|
||||||
JFreeChart chart = ChartFactory.createBarChart3D(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getCategoryDataset(), // data
|
|
||||||
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(getChartOrientation())
|
|
||||||
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
setupCategoryChart(chart);
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart createStackedBarChart() {
|
|
||||||
JFreeChart chart = ChartFactory.createStackedBarChart(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getCategoryDataset(), // data
|
|
||||||
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(getChartOrientation())
|
|
||||||
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
BarRenderer renderer = new BarRenderer();
|
|
||||||
renderer.setBarPainter(new StandardBarPainter());
|
|
||||||
|
|
||||||
CategoryPlot plot = chart.getCategoryPlot();
|
|
||||||
plot.setRenderer(renderer);
|
|
||||||
|
|
||||||
setupCategoryChart(chart);
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart create3DStackedBarChart() {
|
|
||||||
JFreeChart chart = ChartFactory.createStackedBarChart3D(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getCategoryDataset(), // data
|
|
||||||
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(getChartOrientation())
|
|
||||||
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
setupCategoryChart(chart);
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart createAreaChart() {
|
|
||||||
// create the chart...
|
|
||||||
JFreeChart chart = ChartFactory.createAreaChart(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getCategoryDataset(), // data
|
|
||||||
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(getChartOrientation())
|
|
||||||
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
setupCategoryChart(chart);
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart createStackedAreaChart() {
|
|
||||||
// create the chart...
|
|
||||||
JFreeChart chart = ChartFactory.createStackedAreaChart(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getCategoryDataset(), // data
|
|
||||||
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(getChartOrientation())
|
|
||||||
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
setupCategoryChart(chart);
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart createLineChart() {
|
|
||||||
// create the chart...
|
|
||||||
JFreeChart chart = ChartFactory.createLineChart(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getCategoryDataset(), // data
|
|
||||||
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(getChartOrientation())
|
|
||||||
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
setupCategoryChart(chart);
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JFreeChart create3DLineChart() {
|
|
||||||
// create the chart...
|
|
||||||
JFreeChart chart = ChartFactory.createLineChart3D(
|
|
||||||
getName(), // chart title
|
|
||||||
getDomainLabel(), // domain axis label
|
|
||||||
getRangeLabel(), // range axis label
|
|
||||||
getCategoryDataset(), // data
|
|
||||||
X_AD_Chart.CHARTORIENTATION_Horizontal.equals(getChartOrientation())
|
|
||||||
? PlotOrientation.HORIZONTAL : PlotOrientation.VERTICAL, // orientation
|
|
||||||
isDisplayLegend(), // include legend
|
|
||||||
true, // tooltips?
|
|
||||||
true // URLs?
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
setupCategoryChart(chart);
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupCategoryChart(JFreeChart chart) {
|
|
||||||
CategoryPlot plot = chart.getCategoryPlot();
|
|
||||||
CategoryAxis xAxis = (CategoryAxis)plot.getDomainAxis();
|
|
||||||
xAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
|
|
||||||
|
|
||||||
CategoryItemRenderer renderer = plot.getRenderer();
|
|
||||||
renderer.setSeriesPaint(0, Color.RED);
|
|
||||||
renderer.setSeriesPaint(1, Color.BLUE);
|
|
||||||
renderer.setSeriesPaint(2, Color.YELLOW);
|
|
||||||
renderer.setSeriesPaint(3, Color.GREEN);
|
|
||||||
renderer.setSeriesPaint(4, Color.ORANGE);
|
|
||||||
renderer.setSeriesPaint(5, Color.CYAN);
|
|
||||||
renderer.setSeriesPaint(6, Color.MAGENTA);
|
|
||||||
renderer.setSeriesPaint(7, Color.GRAY);
|
|
||||||
renderer.setSeriesPaint(8, Color.PINK);
|
|
||||||
|
|
||||||
plot.setRenderer(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,29 +3,14 @@ package org.compiere.model;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import org.adempiere.exceptions.DBException;
|
import org.adempiere.exceptions.DBException;
|
||||||
import org.compiere.util.DB;
|
import org.compiere.util.DB;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.compiere.util.Util;
|
import org.compiere.util.Util;
|
||||||
import org.jfree.data.category.DefaultCategoryDataset;
|
|
||||||
import org.jfree.data.general.Dataset;
|
|
||||||
import org.jfree.data.general.DefaultPieDataset;
|
|
||||||
import org.jfree.data.time.Day;
|
|
||||||
import org.jfree.data.time.Month;
|
|
||||||
import org.jfree.data.time.Quarter;
|
|
||||||
import org.jfree.data.time.RegularTimePeriod;
|
|
||||||
import org.jfree.data.time.TimeSeries;
|
|
||||||
import org.jfree.data.time.TimeSeriesCollection;
|
|
||||||
import org.jfree.data.time.Week;
|
|
||||||
import org.jfree.data.time.Year;
|
|
||||||
|
|
||||||
public class MChartDatasource extends X_AD_ChartDatasource {
|
public class MChartDatasource extends X_AD_ChartDatasource {
|
||||||
|
|
||||||
|
@ -43,209 +28,6 @@ public class MChartDatasource extends X_AD_ChartDatasource {
|
||||||
super(ctx, rs, trxName);
|
super(ctx, rs, trxName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addData(MChart parent) {
|
|
||||||
|
|
||||||
String value = getValueColumn();
|
|
||||||
String category;
|
|
||||||
String unit = "D";
|
|
||||||
|
|
||||||
if ( !parent.isTimeSeries() )
|
|
||||||
category = getCategoryColumn();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( parent.getTimeUnit().equals(MChart.TIMEUNIT_Week))
|
|
||||||
{
|
|
||||||
unit = "W";
|
|
||||||
}
|
|
||||||
else if ( parent.getTimeUnit().equals(MChart.TIMEUNIT_Month))
|
|
||||||
{
|
|
||||||
unit = "MM";
|
|
||||||
}
|
|
||||||
else if ( parent.getTimeUnit().equals(MChart.TIMEUNIT_Quarter))
|
|
||||||
{
|
|
||||||
unit = "Q";
|
|
||||||
}
|
|
||||||
else if ( parent.getTimeUnit().equals(MChart.TIMEUNIT_Year))
|
|
||||||
{
|
|
||||||
unit = "Y";
|
|
||||||
}
|
|
||||||
|
|
||||||
category = " TRUNC(" + getDateColumn() + ", '" + unit + "') ";
|
|
||||||
}
|
|
||||||
|
|
||||||
String series = DB.TO_STRING(getName());
|
|
||||||
boolean hasSeries = false;
|
|
||||||
if (getSeriesColumn() != null)
|
|
||||||
{
|
|
||||||
series = getSeriesColumn();
|
|
||||||
hasSeries = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String where = getWhereClause();
|
|
||||||
if ( !Util.isEmpty(where))
|
|
||||||
{
|
|
||||||
where = Env.parseContext(getCtx(), parent.getWindowNo(), where, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean hasWhere = false;
|
|
||||||
|
|
||||||
String sql = "SELECT " + value + ", " + category + ", " + series
|
|
||||||
+ " FROM " + getFromClause();
|
|
||||||
if ( !Util.isEmpty(where))
|
|
||||||
{
|
|
||||||
sql += " WHERE " + where;
|
|
||||||
hasWhere = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Date currentDate = Env.getContextAsDate(getCtx(), "#Date");
|
|
||||||
Date startDate = null;
|
|
||||||
Date endDate = null;
|
|
||||||
|
|
||||||
int scope = parent.getTimeScope();
|
|
||||||
int offset = getTimeOffset();
|
|
||||||
|
|
||||||
if ( parent.isTimeSeries() && scope != 0 )
|
|
||||||
{
|
|
||||||
offset += -scope;
|
|
||||||
startDate = increment(currentDate, parent.getTimeUnit(), offset);
|
|
||||||
endDate = increment(startDate, parent.getTimeUnit(), scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( startDate != null && endDate != null )
|
|
||||||
{
|
|
||||||
sql += hasWhere ? " AND " : " WHERE ";
|
|
||||||
sql += category + ">=TRUNC(" + DB.TO_DATE(new Timestamp(startDate.getTime())) + ", '" + unit + "') AND ";
|
|
||||||
sql += category + "<=TRUNC(" + DB.TO_DATE(new Timestamp(endDate.getTime())) + ", '" + unit + "') ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sql.indexOf('@') >= 0) {
|
|
||||||
sql = Env.parseContext(getCtx(), 0, sql, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
MRole role = MRole.getDefault(getCtx(), false);
|
|
||||||
sql = role.addAccessSQL(sql, null, true, false);
|
|
||||||
|
|
||||||
if (hasSeries)
|
|
||||||
sql += " GROUP BY " + series + ", " + category + " ORDER BY " + series + ", " + category;
|
|
||||||
else
|
|
||||||
sql += " GROUP BY " + category + " ORDER BY " + category;
|
|
||||||
|
|
||||||
log.log(Level.FINE, sql);
|
|
||||||
|
|
||||||
PreparedStatement pstmt = null;
|
|
||||||
ResultSet rs = null;
|
|
||||||
TimeSeries tseries = null;
|
|
||||||
Dataset dataset = parent.getDataset();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
pstmt = DB.prepareStatement(sql, null);
|
|
||||||
rs = pstmt.executeQuery();
|
|
||||||
while(rs.next())
|
|
||||||
{
|
|
||||||
|
|
||||||
String key = rs.getString(2);
|
|
||||||
String seriesName = rs.getString(3);
|
|
||||||
if (seriesName == null)
|
|
||||||
seriesName = getName();
|
|
||||||
String queryWhere = "";
|
|
||||||
if ( hasWhere )
|
|
||||||
queryWhere += where + " AND ";
|
|
||||||
|
|
||||||
queryWhere += series + " = " + DB.TO_STRING(seriesName) + " AND " + category + " = " ;
|
|
||||||
|
|
||||||
if ( parent.isTimeSeries() && dataset instanceof TimeSeriesCollection )
|
|
||||||
{
|
|
||||||
|
|
||||||
if ( tseries == null || !tseries.getKey().equals(seriesName))
|
|
||||||
{
|
|
||||||
if (tseries != null)
|
|
||||||
((TimeSeriesCollection) dataset).addSeries(tseries);
|
|
||||||
|
|
||||||
tseries = new TimeSeries(seriesName);
|
|
||||||
}
|
|
||||||
|
|
||||||
Date date = rs.getDate(2);
|
|
||||||
RegularTimePeriod period = null;
|
|
||||||
|
|
||||||
if ( parent.getTimeUnit().equals(MChart.TIMEUNIT_Day))
|
|
||||||
period = new Day(date);
|
|
||||||
else if ( parent.getTimeUnit().equals(MChart.TIMEUNIT_Week))
|
|
||||||
period = new Week(date);
|
|
||||||
else if ( parent.getTimeUnit().equals(MChart.TIMEUNIT_Month))
|
|
||||||
period = new Month(date);
|
|
||||||
else if ( parent.getTimeUnit().equals(MChart.TIMEUNIT_Quarter))
|
|
||||||
period = new Quarter(date);
|
|
||||||
else if ( parent.getTimeUnit().equals(MChart.TIMEUNIT_Year))
|
|
||||||
period = new Year(date);
|
|
||||||
|
|
||||||
tseries.add(period, rs.getBigDecimal(1));
|
|
||||||
key = period.toString();
|
|
||||||
queryWhere += DB.TO_DATE(new Timestamp(date.getTime()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
queryWhere += DB.TO_STRING(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
MQuery query = new MQuery(getAD_Table_ID());
|
|
||||||
String keyCol = MTable.get(getCtx(), getAD_Table_ID()).getKeyColumns()[0];
|
|
||||||
String whereClause = keyCol + " IN (SELECT " + getKeyColumn() + " FROM "
|
|
||||||
+ getFromClause() + " WHERE " + queryWhere + " )";
|
|
||||||
query.addRestriction(whereClause.toString());
|
|
||||||
query.setRecordCount(1);
|
|
||||||
|
|
||||||
HashMap<String, MQuery> map = parent.getQueries();
|
|
||||||
|
|
||||||
if ( dataset instanceof DefaultPieDataset) {
|
|
||||||
((DefaultPieDataset) dataset).setValue(key, rs.getBigDecimal(1));
|
|
||||||
map.put(key, query);
|
|
||||||
}
|
|
||||||
else if ( dataset instanceof DefaultCategoryDataset ) {
|
|
||||||
((DefaultCategoryDataset) dataset).addValue(rs.getBigDecimal(1), seriesName, key);
|
|
||||||
map.put(seriesName + "__" + key, query);
|
|
||||||
}
|
|
||||||
else if (dataset instanceof TimeSeriesCollection )
|
|
||||||
{
|
|
||||||
map.put(seriesName + "__" + key, query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (SQLException e)
|
|
||||||
{
|
|
||||||
throw new DBException(e, sql);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
DB.close(rs, pstmt);
|
|
||||||
rs = null; pstmt = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tseries != null)
|
|
||||||
((TimeSeriesCollection) dataset).addSeries(tseries);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private Date increment(Date lastDate, String timeUnit, int qty) {
|
|
||||||
|
|
||||||
if ( lastDate == null )
|
|
||||||
return null;
|
|
||||||
|
|
||||||
Calendar cal = Calendar.getInstance();
|
|
||||||
cal.setTime(lastDate);
|
|
||||||
|
|
||||||
if ( timeUnit.equals(MChart.TIMEUNIT_Day))
|
|
||||||
cal.add(Calendar.DAY_OF_YEAR, qty);
|
|
||||||
else if ( timeUnit.equals(MChart.TIMEUNIT_Week))
|
|
||||||
cal.add(Calendar.WEEK_OF_YEAR, qty);
|
|
||||||
else if ( timeUnit.equals(MChart.TIMEUNIT_Month))
|
|
||||||
cal.add(Calendar.MONTH, qty);
|
|
||||||
else if ( timeUnit.equals(MChart.TIMEUNIT_Quarter))
|
|
||||||
cal.add(Calendar.MONTH, 3*qty);
|
|
||||||
else if ( timeUnit.equals(MChart.TIMEUNIT_Year))
|
|
||||||
cal.add(Calendar.YEAR, qty);
|
|
||||||
|
|
||||||
return cal.getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert date formatted as yyyy-MM to yyyy-QQ
|
* Convert date formatted as yyyy-MM to yyyy-QQ
|
||||||
|
|
|
@ -8,6 +8,7 @@ import java.awt.event.ActionListener;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.VetoableChangeListener;
|
import java.beans.VetoableChangeListener;
|
||||||
|
|
||||||
|
import org.adempiere.apps.graph.ChartBuilder;
|
||||||
import org.compiere.apps.AEnv;
|
import org.compiere.apps.AEnv;
|
||||||
import org.compiere.model.GridField;
|
import org.compiere.model.GridField;
|
||||||
import org.compiere.model.MChart;
|
import org.compiere.model.MChart;
|
||||||
|
@ -34,6 +35,7 @@ public class VChart extends CPanel implements ChartMouseListener, VEditor {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
ChartPanel chartPanel;
|
ChartPanel chartPanel;
|
||||||
MChart chartModel;
|
MChart chartModel;
|
||||||
|
private ChartBuilder chartBuilder;
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
|
@ -52,7 +54,8 @@ public class VChart extends CPanel implements ChartMouseListener, VEditor {
|
||||||
|
|
||||||
public void createChart()
|
public void createChart()
|
||||||
{
|
{
|
||||||
JFreeChart chart = chartModel.createChart();
|
chartBuilder = new ChartBuilder(chartModel);
|
||||||
|
JFreeChart chart = chartBuilder.createChart();
|
||||||
if (chartPanel != null)
|
if (chartPanel != null)
|
||||||
remove(chartPanel);
|
remove(chartPanel);
|
||||||
|
|
||||||
|
@ -131,7 +134,7 @@ public class VChart extends CPanel implements ChartMouseListener, VEditor {
|
||||||
if ( key == null )
|
if ( key == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MQuery query = chartModel.getQuery(seriesName == null ? key : seriesName+"__"+key);
|
MQuery query = chartBuilder.getQuery(seriesName == null ? key : seriesName+"__"+key);
|
||||||
|
|
||||||
if (query != null)
|
if (query != null)
|
||||||
AEnv.zoom(query);
|
AEnv.zoom(query);
|
||||||
|
|
|
@ -34,6 +34,7 @@ Export-Package: fi.jawsy.jawwa.zk.atmosphere,
|
||||||
org.adempiere.webui.apps,
|
org.adempiere.webui.apps,
|
||||||
org.adempiere.webui.apps.form,
|
org.adempiere.webui.apps.form,
|
||||||
org.adempiere.webui.apps.graph,
|
org.adempiere.webui.apps.graph,
|
||||||
|
org.adempiere.webui.apps.graph.model,
|
||||||
org.adempiere.webui.apps.wf,
|
org.adempiere.webui.apps.wf,
|
||||||
org.adempiere.webui.component,
|
org.adempiere.webui.component,
|
||||||
org.adempiere.webui.component.test,
|
org.adempiere.webui.component.test,
|
||||||
|
@ -85,4 +86,4 @@ Bundle-Activator: org.adempiere.webui.WebUIActivator
|
||||||
Eclipse-ExtensibleAPI: true
|
Eclipse-ExtensibleAPI: true
|
||||||
Eclipse-RegisterBuddy: org.zkoss.zk.library
|
Eclipse-RegisterBuddy: org.zkoss.zk.library
|
||||||
Web-ContextPath: webui
|
Web-ContextPath: webui
|
||||||
Service-Component: OSGI-INF/reportviewerprovider.xml, OSGI-INF/defaultinfofactory.xml, OSGI-INF/defaulteditorfactory.xml, OSGI-INF/jrviewerprovider.xml, OSGI-INF/resourcefinder.xml, OSGI-INF/defaultpaymentformfactory.xml, OSGI-INF/processfactory.xml, OSGI-INF/defaultprintshippinglabel.xml, OSGI-INF/defaultcreatefromfactory.xml, OSGI-INF/defaultformfactory.xml, OSGI-INF/feedbackservice.xml, OSGI-INF/zulgadgetfactory.xml
|
Service-Component: OSGI-INF/reportviewerprovider.xml, OSGI-INF/defaultinfofactory.xml, OSGI-INF/defaulteditorfactory.xml, OSGI-INF/jrviewerprovider.xml, OSGI-INF/resourcefinder.xml, OSGI-INF/defaultpaymentformfactory.xml, OSGI-INF/processfactory.xml, OSGI-INF/defaultprintshippinglabel.xml, OSGI-INF/defaultcreatefromfactory.xml, OSGI-INF/defaultformfactory.xml, OSGI-INF/feedbackservice.xml, OSGI-INF/zulgadgetfactory.xml, OSGI-INF/jfgchartrenderer.xml
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.adempiere.webui.apps.graph.jfreegraph.ChartRendererServiceImpl">
|
||||||
|
<implementation class="org.adempiere.webui.apps.graph.jfreegraph.ChartRendererServiceImpl"/>
|
||||||
|
<property name="service.ranking" type="Integer" value="0"/>
|
||||||
|
<service>
|
||||||
|
<provide interface="org.adempiere.webui.apps.graph.IChartRendererService"/>
|
||||||
|
</service>
|
||||||
|
</scr:component>
|
|
@ -0,0 +1,54 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2013 Heng Sin Low *
|
||||||
|
* Copyright (C) 2013 Trek Global *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. 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, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.adempiere.webui.apps.graph;
|
||||||
|
|
||||||
|
import org.adempiere.webui.apps.graph.model.ChartModel;
|
||||||
|
import org.adempiere.webui.apps.graph.model.GoalModel;
|
||||||
|
import org.adempiere.webui.apps.graph.model.IndicatorModel;
|
||||||
|
import org.zkoss.zk.ui.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chart renderer service. Note that implementation must be thread safe.
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface IChartRendererService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* render indicator chart for PA_Goal
|
||||||
|
* @param parent
|
||||||
|
* @param chartWidth
|
||||||
|
* @param chartHeight
|
||||||
|
* @param model
|
||||||
|
*/
|
||||||
|
public void renderPerformanceIndicator(Component parent, int chartWidth, int chartHeight, IndicatorModel model);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* render chart for PA_Goal
|
||||||
|
* @param parent
|
||||||
|
* @param chartWidth
|
||||||
|
* @param chartHeight
|
||||||
|
* @param goalModel
|
||||||
|
*/
|
||||||
|
public void renderPerformanceGraph(Component parent, int chartWidth, int chartHeight, GoalModel goalModel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* render chart for AD_Chart
|
||||||
|
* @param parent
|
||||||
|
* @param width
|
||||||
|
* @param height
|
||||||
|
* @param chartModel
|
||||||
|
*/
|
||||||
|
public void renderChart(Component parent, int width, int height, ChartModel chartModel);
|
||||||
|
}
|
|
@ -14,15 +14,14 @@
|
||||||
package org.adempiere.webui.apps.graph;
|
package org.adempiere.webui.apps.graph;
|
||||||
|
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Collections;
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import org.adempiere.apps.graph.GraphBuilder;
|
|
||||||
import org.adempiere.apps.graph.GraphColumn;
|
import org.adempiere.apps.graph.GraphColumn;
|
||||||
|
import org.adempiere.base.Service;
|
||||||
import org.adempiere.webui.apps.AEnv;
|
import org.adempiere.webui.apps.AEnv;
|
||||||
|
import org.adempiere.webui.apps.graph.model.GoalModel;
|
||||||
import org.adempiere.webui.editor.WTableDirEditor;
|
import org.adempiere.webui.editor.WTableDirEditor;
|
||||||
import org.adempiere.webui.event.ValueChangeEvent;
|
import org.adempiere.webui.event.ValueChangeEvent;
|
||||||
import org.adempiere.webui.event.ValueChangeListener;
|
import org.adempiere.webui.event.ValueChangeListener;
|
||||||
|
@ -30,19 +29,10 @@ import org.compiere.model.MGoal;
|
||||||
import org.compiere.model.MLookup;
|
import org.compiere.model.MLookup;
|
||||||
import org.compiere.model.MLookupFactory;
|
import org.compiere.model.MLookupFactory;
|
||||||
import org.compiere.model.MLookupInfo;
|
import org.compiere.model.MLookupInfo;
|
||||||
import org.compiere.model.MQuery;
|
import org.compiere.model.MMeasure;
|
||||||
import org.compiere.util.CLogger;
|
import org.compiere.util.CLogger;
|
||||||
import org.compiere.util.DB;
|
import org.compiere.util.DB;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.jfree.chart.ChartMouseEvent;
|
|
||||||
import org.jfree.chart.ChartRenderingInfo;
|
|
||||||
import org.jfree.chart.JFreeChart;
|
|
||||||
import org.jfree.chart.encoders.EncoderUtil;
|
|
||||||
import org.jfree.chart.encoders.ImageFormat;
|
|
||||||
import org.jfree.chart.entity.CategoryItemEntity;
|
|
||||||
import org.jfree.chart.entity.ChartEntity;
|
|
||||||
import org.jfree.chart.entity.PieSectionEntity;
|
|
||||||
import org.zkoss.image.AImage;
|
|
||||||
import org.zkoss.zhtml.A;
|
import org.zkoss.zhtml.A;
|
||||||
import org.zkoss.zhtml.Br;
|
import org.zkoss.zhtml.Br;
|
||||||
import org.zkoss.zhtml.Table;
|
import org.zkoss.zhtml.Table;
|
||||||
|
@ -54,13 +44,10 @@ import org.zkoss.zk.ui.IdSpace;
|
||||||
import org.zkoss.zk.ui.event.Event;
|
import org.zkoss.zk.ui.event.Event;
|
||||||
import org.zkoss.zk.ui.event.EventListener;
|
import org.zkoss.zk.ui.event.EventListener;
|
||||||
import org.zkoss.zk.ui.event.Events;
|
import org.zkoss.zk.ui.event.Events;
|
||||||
import org.zkoss.zk.ui.event.MouseEvent;
|
|
||||||
import org.zkoss.zul.Borderlayout;
|
import org.zkoss.zul.Borderlayout;
|
||||||
import org.zkoss.zul.Center;
|
import org.zkoss.zul.Center;
|
||||||
import org.zkoss.zul.East;
|
import org.zkoss.zul.East;
|
||||||
import org.zkoss.zul.Area;
|
|
||||||
import org.zkoss.zul.Div;
|
import org.zkoss.zul.Div;
|
||||||
import org.zkoss.zul.Imagemap;
|
|
||||||
import org.zkoss.zul.Panel;
|
import org.zkoss.zul.Panel;
|
||||||
import org.zkoss.zul.Panelchildren;
|
import org.zkoss.zul.Panelchildren;
|
||||||
import org.zkoss.zul.Toolbar;
|
import org.zkoss.zul.Toolbar;
|
||||||
|
@ -100,18 +87,21 @@ public class WGraph extends Div implements IdSpace {
|
||||||
*/
|
*/
|
||||||
ArrayList<GraphColumn> list = new ArrayList<GraphColumn>();
|
ArrayList<GraphColumn> list = new ArrayList<GraphColumn>();
|
||||||
|
|
||||||
private GraphBuilder builder;
|
|
||||||
|
|
||||||
private boolean m_chartSelection;
|
private boolean m_chartSelection;
|
||||||
|
|
||||||
private int zoomFactor = 0;
|
private int zoomFactor = 0;
|
||||||
|
|
||||||
|
private MGoal m_goal;
|
||||||
|
|
||||||
|
private String m_xAxisLabel;
|
||||||
|
|
||||||
|
private String m_yAxisLabel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
public WGraph() {
|
public WGraph() {
|
||||||
super();
|
super();
|
||||||
builder = new GraphBuilder();
|
|
||||||
panel = new Panel();
|
panel = new Panel();
|
||||||
} // BarGraph
|
} // BarGraph
|
||||||
|
|
||||||
|
@ -154,9 +144,9 @@ public class WGraph extends Div implements IdSpace {
|
||||||
*/
|
*/
|
||||||
public void setGoal(MGoal goal)
|
public void setGoal(MGoal goal)
|
||||||
{
|
{
|
||||||
builder.setMGoal(goal);
|
m_goal = goal;
|
||||||
builder.setYAxisLabel(goal.getName());
|
m_yAxisLabel = goal.getName();
|
||||||
builder.setXAxisLabel(goal.getXAxisText());
|
m_xAxisLabel = goal.getXAxisText();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -194,10 +184,7 @@ public class WGraph extends Div implements IdSpace {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_renderChart) {
|
if (m_renderChart) {
|
||||||
JFreeChart chart = builder.createChart(builder.getMGoal()
|
renderChart((String)null);
|
||||||
.getChartType());
|
|
||||||
|
|
||||||
render(chart);
|
|
||||||
}
|
}
|
||||||
if (m_renderTable) {
|
if (m_renderTable) {
|
||||||
if (m_renderChart) {
|
if (m_renderChart) {
|
||||||
|
@ -218,8 +205,16 @@ public class WGraph extends Div implements IdSpace {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadData() {
|
private void loadData() {
|
||||||
list = builder.loadData();
|
// Calculated
|
||||||
|
MMeasure measure = m_goal.getMeasure();
|
||||||
|
if (measure == null)
|
||||||
|
{
|
||||||
|
log.warning("No Measure for " + m_goal);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = measure.getGraphColumnList(m_goal);
|
||||||
|
|
||||||
if (m_renderChart && m_chartSelection) {
|
if (m_renderChart && m_chartSelection) {
|
||||||
Toolbar toolbar = new Toolbar();
|
Toolbar toolbar = new Toolbar();
|
||||||
panel.appendChild(toolbar);
|
panel.appendChild(toolbar);
|
||||||
|
@ -239,95 +234,32 @@ public class WGraph extends Div implements IdSpace {
|
||||||
Object value = evt.getNewValue();
|
Object value = evt.getNewValue();
|
||||||
if (value == null || value.toString().trim().length() == 0)
|
if (value == null || value.toString().trim().length() == 0)
|
||||||
return;
|
return;
|
||||||
JFreeChart chart = null;
|
renderChart(value.toString());
|
||||||
chart = builder.createChart(value.toString());
|
|
||||||
if (chart != null)
|
|
||||||
render(chart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} // loadData
|
} // loadData
|
||||||
|
|
||||||
private void render(JFreeChart chart) {
|
private void renderChart(String type) {
|
||||||
ChartRenderingInfo info = new ChartRenderingInfo();
|
|
||||||
int width = 560;
|
int width = 560;
|
||||||
int height = 400;
|
int height = 400;
|
||||||
if (zoomFactor > 0) {
|
if (panel.getPanelchildren() != null) {
|
||||||
width = width * zoomFactor / 100;
|
panel.getPanelchildren().getChildren().clear();
|
||||||
height = height * zoomFactor / 100;
|
} else {
|
||||||
}
|
Panelchildren pc = new Panelchildren();
|
||||||
if (m_hideTitle) {
|
panel.appendChild(pc);
|
||||||
chart.setTitle("");
|
|
||||||
}
|
|
||||||
BufferedImage bi = chart.createBufferedImage(width, height,
|
|
||||||
BufferedImage.TRANSLUCENT, info);
|
|
||||||
try {
|
|
||||||
byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true);
|
|
||||||
|
|
||||||
AImage image = new AImage("", bytes);
|
|
||||||
Imagemap myImage = new Imagemap();
|
|
||||||
|
|
||||||
myImage.setContent(image);
|
|
||||||
if (panel.getPanelchildren() != null) {
|
|
||||||
panel.getPanelchildren().getChildren().clear();
|
|
||||||
panel.getPanelchildren().appendChild(myImage);
|
|
||||||
} else {
|
|
||||||
Panelchildren pc = new Panelchildren();
|
|
||||||
panel.appendChild(pc);
|
|
||||||
pc.appendChild(myImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
for (Iterator<?> it = info.getEntityCollection().getEntities()
|
|
||||||
.iterator(); it.hasNext();) {
|
|
||||||
ChartEntity entity = (ChartEntity) it.next();
|
|
||||||
|
|
||||||
String key = null;
|
|
||||||
if (entity instanceof CategoryItemEntity) {
|
|
||||||
Comparable<?> colKey = ((CategoryItemEntity) entity)
|
|
||||||
.getColumnKey();
|
|
||||||
if (colKey != null) {
|
|
||||||
key = colKey.toString();
|
|
||||||
}
|
|
||||||
} else if (entity instanceof PieSectionEntity) {
|
|
||||||
Comparable<?> sectionKey = ((PieSectionEntity) entity)
|
|
||||||
.getSectionKey();
|
|
||||||
if (sectionKey != null) {
|
|
||||||
key = sectionKey.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (key == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Area area = new Area();
|
|
||||||
myImage.appendChild(area);
|
|
||||||
area.setCoords(entity.getShapeCoords());
|
|
||||||
area.setShape(entity.getShapeType());
|
|
||||||
area.setTooltiptext(entity.getToolTipText());
|
|
||||||
area.setId(count+"_WG_" + key);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
myImage.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
|
|
||||||
public void onEvent(Event event) throws Exception {
|
|
||||||
MouseEvent me = (MouseEvent) event;
|
|
||||||
String areaId = me.getArea();
|
|
||||||
if (areaId != null) {
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
|
||||||
String s = "_WG_" + list.get(i).getLabel();
|
|
||||||
if (areaId.endsWith(s)) {
|
|
||||||
chartMouseClicked(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.log(Level.SEVERE, "", e);
|
|
||||||
}
|
}
|
||||||
|
IChartRendererService renderer = Service.locator().locate(IChartRendererService.class).getService();
|
||||||
|
GoalModel goalModel = new GoalModel();
|
||||||
|
goalModel.goal = m_goal;
|
||||||
|
goalModel.chartType = type != null ? type : m_goal.getChartType();
|
||||||
|
goalModel.columnList = Collections.unmodifiableList(list);
|
||||||
|
goalModel.showTitle = !m_hideTitle;
|
||||||
|
goalModel.xAxisLabel = m_xAxisLabel;
|
||||||
|
goalModel.yAxisLabel = m_yAxisLabel;
|
||||||
|
goalModel.zoomFactor = zoomFactor;
|
||||||
|
renderer.renderPerformanceGraph(panel.getPanelchildren(), width, height, goalModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -343,7 +275,7 @@ public class WGraph extends Div implements IdSpace {
|
||||||
* @return Returns the x_AxisLabel.
|
* @return Returns the x_AxisLabel.
|
||||||
*/
|
*/
|
||||||
public String getX_AxisLabel() {
|
public String getX_AxisLabel() {
|
||||||
return builder.getXAxisLabel();
|
return m_xAxisLabel;
|
||||||
} // getX_AxisLabel
|
} // getX_AxisLabel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -351,14 +283,14 @@ public class WGraph extends Div implements IdSpace {
|
||||||
* The x_AxisLabel to set.
|
* The x_AxisLabel to set.
|
||||||
*/
|
*/
|
||||||
public void setX_AxisLabel(String axisLabel) {
|
public void setX_AxisLabel(String axisLabel) {
|
||||||
builder.setXAxisLabel(axisLabel);
|
m_xAxisLabel = axisLabel;
|
||||||
} // setX_AxisLabel
|
} // setX_AxisLabel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns the y_AxisLabel.
|
* @return Returns the y_AxisLabel.
|
||||||
*/
|
*/
|
||||||
public String getY_AxisLabel() {
|
public String getY_AxisLabel() {
|
||||||
return builder.getYAxisLabel();
|
return m_yAxisLabel;
|
||||||
} // getY_AxisLabel
|
} // getY_AxisLabel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -366,7 +298,7 @@ public class WGraph extends Div implements IdSpace {
|
||||||
* The y_AxisLabel to set.
|
* The y_AxisLabel to set.
|
||||||
*/
|
*/
|
||||||
public void setY_AxisLabel(String axisLabel) {
|
public void setY_AxisLabel(String axisLabel) {
|
||||||
builder.setYAxisLabel(axisLabel);
|
m_yAxisLabel = axisLabel;
|
||||||
} // setY_AxisLabel
|
} // setY_AxisLabel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -431,27 +363,6 @@ public class WGraph extends Div implements IdSpace {
|
||||||
m_renderChart = mRenderChart;
|
m_renderChart = mRenderChart;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
* Paint Component
|
|
||||||
*
|
|
||||||
* @param g
|
|
||||||
* graphics
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void chartMouseClicked(int index) {
|
|
||||||
GraphColumn bgc = list.get(index);
|
|
||||||
if (null == bgc)
|
|
||||||
return;
|
|
||||||
MQuery query = bgc.getMQuery(builder.getMGoal());
|
|
||||||
if (query != null)
|
|
||||||
AEnv.zoom(query);
|
|
||||||
else
|
|
||||||
log.warning("Nothing to zoom to - " + bgc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void chartMouseMoved(ChartMouseEvent event) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return GraphColumn[]
|
* @return GraphColumn[]
|
||||||
|
@ -484,7 +395,7 @@ public class WGraph extends Div implements IdSpace {
|
||||||
td.setDynamicProperty("colspan", "2");
|
td.setDynamicProperty("colspan", "2");
|
||||||
td.setSclass("pa-tdcontent");
|
td.setSclass("pa-tdcontent");
|
||||||
tr.appendChild(td);
|
tr.appendChild(td);
|
||||||
text = new Text(builder.getMGoal().getMeasureTarget().setScale(2,
|
text = new Text(m_goal.getMeasureTarget().setScale(2,
|
||||||
BigDecimal.ROUND_HALF_UP).toPlainString());
|
BigDecimal.ROUND_HALF_UP).toPlainString());
|
||||||
td.appendChild(text);
|
td.appendChild(text);
|
||||||
|
|
||||||
|
@ -499,7 +410,7 @@ public class WGraph extends Div implements IdSpace {
|
||||||
td.setDynamicProperty("colspan", "2");
|
td.setDynamicProperty("colspan", "2");
|
||||||
td.setSclass("pa-tdcontent");
|
td.setSclass("pa-tdcontent");
|
||||||
tr.appendChild(td);
|
tr.appendChild(td);
|
||||||
text = new Text(builder.getMGoal().getMeasureActual().setScale(2,
|
text = new Text(m_goal.getMeasureActual().setScale(2,
|
||||||
BigDecimal.ROUND_HALF_UP).toPlainString());
|
BigDecimal.ROUND_HALF_UP).toPlainString());
|
||||||
td.appendChild(text);
|
td.appendChild(text);
|
||||||
|
|
||||||
|
@ -512,7 +423,7 @@ public class WGraph extends Div implements IdSpace {
|
||||||
td.setDynamicProperty("rowspan", bList.length);
|
td.setDynamicProperty("rowspan", bList.length);
|
||||||
td.setSclass("pa-label");
|
td.setSclass("pa-label");
|
||||||
td.setDynamicProperty("valign", "top");
|
td.setDynamicProperty("valign", "top");
|
||||||
text = new Text(builder.getMGoal().getXAxisText());
|
text = new Text(m_goal.getXAxisText());
|
||||||
td.appendChild(text);
|
td.appendChild(text);
|
||||||
|
|
||||||
for (int k = 0; k < bList.length; k++) {
|
for (int k = 0; k < bList.length; k++) {
|
||||||
|
@ -531,7 +442,7 @@ public class WGraph extends Div implements IdSpace {
|
||||||
td.setSclass("pa-tdvalue");
|
td.setSclass("pa-tdvalue");
|
||||||
tr.appendChild(td);
|
tr.appendChild(td);
|
||||||
BigDecimal value = BigDecimal.valueOf(bgc.getValue());
|
BigDecimal value = BigDecimal.valueOf(bgc.getValue());
|
||||||
if (bgc.getMQuery(builder.getMGoal()) != null) {
|
if (bgc.getMQuery(m_goal) != null) {
|
||||||
A a = new A();
|
A a = new A();
|
||||||
a.setSclass("pa-hrefNode");
|
a.setSclass("pa-hrefNode");
|
||||||
td.appendChild(a);
|
td.appendChild(a);
|
||||||
|
@ -545,8 +456,7 @@ public class WGraph extends Div implements IdSpace {
|
||||||
int index = Integer.parseInt(String.valueOf(ss));
|
int index = Integer.parseInt(String.valueOf(ss));
|
||||||
GraphColumn[] colList = getGraphColumnList();
|
GraphColumn[] colList = getGraphColumnList();
|
||||||
if ((index >= 0) && (index < colList.length))
|
if ((index >= 0) && (index < colList.length))
|
||||||
AEnv.zoom(colList[index].getMQuery(builder
|
AEnv.zoom(colList[index].getMQuery(m_goal));
|
||||||
.getMGoal()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,11 +474,11 @@ public class WGraph extends Div implements IdSpace {
|
||||||
td = new Td();
|
td = new Td();
|
||||||
td.setDynamicProperty("colspan", "3");
|
td.setDynamicProperty("colspan", "3");
|
||||||
tr.appendChild(td);
|
tr.appendChild(td);
|
||||||
text = new Text(builder.getMGoal().getDescription());
|
text = new Text(m_goal.getDescription());
|
||||||
td.appendChild(text);
|
td.appendChild(text);
|
||||||
Br br = new Br();
|
Br br = new Br();
|
||||||
td.appendChild(br);
|
td.appendChild(br);
|
||||||
text = new Text(stripHtml(builder.getMGoal().getColorSchema()
|
text = new Text(stripHtml(m_goal.getColorSchema()
|
||||||
.getDescription(), true));
|
.getDescription(), true));
|
||||||
td.appendChild(text);
|
td.appendChild(text);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,6 @@ public class WPAPanel extends Panel implements EventListener<Event>
|
||||||
setSclass("performance-panel");
|
setSclass("performance-panel");
|
||||||
Grid grid = new Grid();
|
Grid grid = new Grid();
|
||||||
appendChild(grid);
|
appendChild(grid);
|
||||||
int gh = options != null && options.chartHeight > 0 ? options.chartHeight+60 : 180;
|
|
||||||
grid.setHeight((m_goals.length + (m_goals.length % 2)) * gh / 2 + "px");
|
|
||||||
grid.makeNoStrip();
|
grid.makeNoStrip();
|
||||||
|
|
||||||
Rows rows = new Rows();
|
Rows rows = new Rows();
|
||||||
|
|
|
@ -13,36 +13,22 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package org.adempiere.webui.apps.graph;
|
package org.adempiere.webui.apps.graph;
|
||||||
|
|
||||||
import java.awt.BasicStroke;
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Font;
|
|
||||||
import java.awt.LinearGradientPaint;
|
|
||||||
import java.awt.geom.Point2D;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.adempiere.base.Service;
|
||||||
|
import org.adempiere.webui.apps.graph.model.IndicatorModel;
|
||||||
import org.adempiere.webui.component.Panel;
|
import org.adempiere.webui.component.Panel;
|
||||||
import org.adempiere.webui.theme.ThemeManager;
|
import org.adempiere.webui.theme.ThemeManager;
|
||||||
import org.compiere.model.MColorSchema;
|
|
||||||
import org.compiere.model.MGoal;
|
import org.compiere.model.MGoal;
|
||||||
import org.compiere.util.DisplayType;
|
import org.compiere.util.DisplayType;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.compiere.util.Msg;
|
import org.compiere.util.Msg;
|
||||||
import org.jfree.chart.ChartPanel;
|
import org.jfree.chart.ChartPanel;
|
||||||
import org.jfree.chart.JFreeChart;
|
|
||||||
import org.jfree.chart.encoders.EncoderUtil;
|
|
||||||
import org.jfree.chart.encoders.ImageFormat;
|
|
||||||
import org.jfree.chart.plot.DialShape;
|
|
||||||
import org.jfree.chart.plot.MeterInterval;
|
|
||||||
import org.jfree.chart.plot.MeterPlot;
|
|
||||||
import org.jfree.data.Range;
|
|
||||||
import org.jfree.data.general.DefaultValueDataset;
|
|
||||||
import org.zkoss.image.AImage;
|
|
||||||
import org.zkoss.zk.ui.event.Event;
|
import org.zkoss.zk.ui.event.Event;
|
||||||
import org.zkoss.zk.ui.event.EventListener;
|
import org.zkoss.zk.ui.event.EventListener;
|
||||||
import org.zkoss.zk.ui.event.Events;
|
import org.zkoss.zk.ui.event.Events;
|
||||||
import org.zkoss.zul.Image;
|
|
||||||
import org.zkoss.zul.Menuitem;
|
import org.zkoss.zul.Menuitem;
|
||||||
import org.zkoss.zul.Menupopup;
|
import org.zkoss.zul.Menupopup;
|
||||||
|
|
||||||
|
@ -135,11 +121,24 @@ public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
||||||
return m_goal;
|
return m_goal;
|
||||||
} // getGoal
|
} // getGoal
|
||||||
|
|
||||||
private JFreeChart createChart()
|
/**
|
||||||
|
* Init Graph Display
|
||||||
|
* Kinamo (pelgrim)
|
||||||
|
*/
|
||||||
|
private void init()
|
||||||
{
|
{
|
||||||
JFreeChart chart = null;
|
IChartRendererService renderer = Service.locator().locate(IChartRendererService.class).getService();
|
||||||
|
IndicatorModel model = new IndicatorModel();
|
||||||
// Set Text
|
model.goalModel = m_goal;
|
||||||
|
model.chartBackground = chartBackground;
|
||||||
|
model.dialBackground = dialBackground;
|
||||||
|
model.needleColor = needleColor;
|
||||||
|
model.tickColor = tickColor;
|
||||||
|
renderer.renderPerformanceIndicator(this, chartWidth, chartHeight, model);
|
||||||
|
|
||||||
|
this.getFirstChild().addEventListener(Events.ON_CLICK, this);
|
||||||
|
|
||||||
|
// Set Text
|
||||||
StringBuilder text = new StringBuilder(m_goal.getName());
|
StringBuilder text = new StringBuilder(m_goal.getName());
|
||||||
if (m_goal.isTarget())
|
if (m_goal.isTarget())
|
||||||
text.append(": ").append(m_goal.getPercent()).append("%");
|
text.append(": ").append(m_goal.getPercent()).append("%");
|
||||||
|
@ -157,96 +156,17 @@ public class WPerformanceIndicator extends Panel implements EventListener<Event>
|
||||||
text.append(" ").append(Msg.getMsg(Env.getCtx(), "of")).append(" ")
|
text.append(" ").append(Msg.getMsg(Env.getCtx(), "of")).append(" ")
|
||||||
.append(s_format.format(m_goal.getMeasureTarget()));
|
.append(s_format.format(m_goal.getMeasureTarget()));
|
||||||
setTooltiptext(text.toString());
|
setTooltiptext(text.toString());
|
||||||
//
|
|
||||||
DefaultValueDataset data = new DefaultValueDataset((float)m_goal.getPercent());
|
invalidate();
|
||||||
MeterPlot plot = new MeterPlot(data);
|
|
||||||
|
|
||||||
MColorSchema colorSchema = m_goal.getColorSchema();
|
|
||||||
int rangeLo = 0; int rangeHi=0;
|
|
||||||
Point2D start = new Point2D.Float(0, 0);
|
|
||||||
Point2D end = new Point2D.Float(50, 50);
|
|
||||||
float[] dist = {0.0f, 0.2f, 0.45f, 0.75f, 1.0f};
|
|
||||||
for (int i=1; i<=4; i++){
|
|
||||||
switch (i) {
|
|
||||||
case 1: rangeHi = colorSchema.getMark1Percent(); break;
|
|
||||||
case 2: rangeHi = colorSchema.getMark2Percent(); break;
|
|
||||||
case 3: rangeHi = colorSchema.getMark3Percent(); break;
|
|
||||||
case 4: rangeHi = colorSchema.getMark4Percent(); break;
|
|
||||||
}
|
|
||||||
if (rangeHi==9999)
|
|
||||||
rangeHi = (int) Math.floor(rangeLo*1.5);
|
|
||||||
if (rangeLo < rangeHi) {
|
|
||||||
Color[] colors = {colorSchema.getColor(rangeHi).brighter().brighter(),
|
|
||||||
colorSchema.getColor(rangeHi).brighter(), colorSchema.getColor(rangeHi),
|
|
||||||
colorSchema.getColor(rangeHi).darker(), colorSchema.getColor(rangeHi).darker().darker()};
|
|
||||||
LinearGradientPaint p =
|
|
||||||
new LinearGradientPaint(start, end, dist, colors);
|
|
||||||
|
|
||||||
plot.addInterval(new MeterInterval("Normal", //label
|
|
||||||
new Range(rangeLo, rangeHi), //range
|
|
||||||
p,
|
|
||||||
new BasicStroke(7.0f),
|
|
||||||
dialBackground
|
|
||||||
));
|
|
||||||
rangeLo = rangeHi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
plot.setRange(new Range(0,rangeLo));
|
|
||||||
plot.setDialBackgroundPaint(dialBackground);
|
|
||||||
plot.setUnits("");
|
|
||||||
plot.setDialShape(DialShape.CHORD);
|
|
||||||
plot.setNeedlePaint(needleColor);
|
|
||||||
plot.setTickSize(2000);
|
|
||||||
plot.setTickLabelFont(new Font("SansSerif", Font.BOLD, 8));
|
|
||||||
plot.setValueFont(new Font("SansSerif", Font.BOLD, 8));
|
|
||||||
plot.setNoDataMessageFont(new Font("SansSerif", Font.BOLD, 8));
|
|
||||||
plot.setTickLabelPaint(tickColor);
|
|
||||||
plot.setValuePaint(new Color(0.0f, 0.0f, 0.0f, 0.0f));
|
|
||||||
plot.setTickPaint(tickColor);
|
|
||||||
//
|
|
||||||
chart = new JFreeChart( "", new Font("SansSerif", Font.BOLD, 9), plot,false);
|
|
||||||
|
|
||||||
return chart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Init Graph Display
|
|
||||||
* Kinamo (pelgrim)
|
|
||||||
*/
|
|
||||||
private void init()
|
|
||||||
{
|
|
||||||
JFreeChart chart = createChart();
|
|
||||||
chart.setBackgroundPaint(chartBackground);
|
|
||||||
chart.setAntiAlias(true);
|
|
||||||
BufferedImage bi = chart.createBufferedImage(chartWidth, chartHeight, BufferedImage.TRANSLUCENT , null);
|
|
||||||
try {
|
|
||||||
byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true);
|
|
||||||
|
|
||||||
AImage image = new AImage("", bytes);
|
|
||||||
Image myImage = new Image();
|
|
||||||
myImage.setContent(image);
|
|
||||||
appendChild(myImage);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update Display Data
|
|
||||||
*/
|
|
||||||
protected void updateDisplay()
|
|
||||||
{
|
|
||||||
chartPanel.setChart(createChart());
|
|
||||||
invalidate();
|
|
||||||
} // updateData
|
|
||||||
|
|
||||||
public void onEvent(Event event) throws Exception
|
public void onEvent(Event event) throws Exception
|
||||||
{
|
{
|
||||||
|
if (event.getTarget() == this.getFirstChild())
|
||||||
|
{
|
||||||
|
event.stopPropagation();
|
||||||
|
Events.sendEvent(Events.ON_CLICK, this, event.getData());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTitle()
|
public String getTitle()
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package org.adempiere.webui.util;
|
package org.adempiere.webui.apps.graph.jfreegraph;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.apps.graph.ChartBuilder;
|
||||||
import org.adempiere.webui.apps.AEnv;
|
import org.adempiere.webui.apps.AEnv;
|
||||||
import org.compiere.model.MChart;
|
import org.compiere.model.MChart;
|
||||||
import org.compiere.model.MQuery;
|
import org.compiere.model.MQuery;
|
||||||
|
@ -33,12 +34,14 @@ import org.zkoss.zul.Imagemap;
|
||||||
* @author hengsin
|
* @author hengsin
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ChartRenderer {
|
/* package */ class ChartRenderer {
|
||||||
|
|
||||||
private static final CLogger log = CLogger.getCLogger(ChartRenderer.class);
|
private static final CLogger log = CLogger.getCLogger(ChartRenderer.class);
|
||||||
|
|
||||||
private MChart chartModel;
|
private MChart chartModel;
|
||||||
|
|
||||||
|
private ChartBuilder chartBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param chartModel
|
* @param chartModel
|
||||||
*/
|
*/
|
||||||
|
@ -52,7 +55,9 @@ public class ChartRenderer {
|
||||||
* @param width
|
* @param width
|
||||||
*/
|
*/
|
||||||
public void render(Component parent, int width, int height) {
|
public void render(Component parent, int width, int height) {
|
||||||
JFreeChart chart = chartModel.createChart();
|
chartBuilder = new ChartBuilder(chartModel);
|
||||||
|
JFreeChart chart = chartBuilder.createChart();
|
||||||
|
chart.getPlot().setForegroundAlpha(0.6f);
|
||||||
|
|
||||||
ChartRenderingInfo info = new ChartRenderingInfo();
|
ChartRenderingInfo info = new ChartRenderingInfo();
|
||||||
BufferedImage bi = chart.createBufferedImage(width, height,
|
BufferedImage bi = chart.createBufferedImage(width, height,
|
||||||
|
@ -136,7 +141,7 @@ public class ChartRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void chartMouseClicked(String key, String category) {
|
public void chartMouseClicked(String key, String category) {
|
||||||
MQuery query = chartModel.getQuery("null".equals(category) ? key : category + "__" + key);
|
MQuery query = chartBuilder.getQuery("null".equals(category) ? key : category + "__" + key);
|
||||||
if (query != null)
|
if (query != null)
|
||||||
AEnv.zoom(query);
|
AEnv.zoom(query);
|
||||||
}
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. 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, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.adempiere.webui.apps.graph.jfreegraph;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.apps.graph.GraphBuilder;
|
||||||
|
import org.adempiere.apps.graph.GraphColumn;
|
||||||
|
import org.adempiere.webui.apps.AEnv;
|
||||||
|
import org.adempiere.webui.apps.graph.IChartRendererService;
|
||||||
|
import org.adempiere.webui.apps.graph.model.ChartModel;
|
||||||
|
import org.adempiere.webui.apps.graph.model.GoalModel;
|
||||||
|
import org.adempiere.webui.apps.graph.model.IndicatorModel;
|
||||||
|
import org.compiere.model.MGoal;
|
||||||
|
import org.compiere.model.MQuery;
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.jfree.chart.ChartRenderingInfo;
|
||||||
|
import org.jfree.chart.JFreeChart;
|
||||||
|
import org.jfree.chart.encoders.EncoderUtil;
|
||||||
|
import org.jfree.chart.encoders.ImageFormat;
|
||||||
|
import org.jfree.chart.entity.CategoryItemEntity;
|
||||||
|
import org.jfree.chart.entity.ChartEntity;
|
||||||
|
import org.jfree.chart.entity.PieSectionEntity;
|
||||||
|
import org.zkoss.image.AImage;
|
||||||
|
import org.zkoss.zk.ui.Component;
|
||||||
|
import org.zkoss.zk.ui.event.Event;
|
||||||
|
import org.zkoss.zk.ui.event.EventListener;
|
||||||
|
import org.zkoss.zk.ui.event.Events;
|
||||||
|
import org.zkoss.zk.ui.event.MouseEvent;
|
||||||
|
import org.zkoss.zul.Area;
|
||||||
|
import org.zkoss.zul.Image;
|
||||||
|
import org.zkoss.zul.Imagemap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ChartRendererServiceImpl implements IChartRendererService {
|
||||||
|
|
||||||
|
private final static CLogger log = CLogger.getCLogger(ChartRendererServiceImpl.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderPerformanceIndicator(Component parent, int chartWidth, int chartHeight, IndicatorModel model) {
|
||||||
|
PerformanceGraphBuilder builder = new PerformanceGraphBuilder();
|
||||||
|
JFreeChart chart = builder.createIndicatorChart(model);
|
||||||
|
chart.setBackgroundPaint(model.chartBackground);
|
||||||
|
chart.setAntiAlias(true);
|
||||||
|
BufferedImage bi = chart.createBufferedImage(chartWidth, chartHeight, BufferedImage.TRANSLUCENT , null);
|
||||||
|
try {
|
||||||
|
byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true);
|
||||||
|
|
||||||
|
AImage image = new AImage("", bytes);
|
||||||
|
Image myImage = new Image();
|
||||||
|
myImage.setContent(image);
|
||||||
|
parent.appendChild(myImage);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderPerformanceGraph(Component parent, int chartWidth, int chartHeight, final GoalModel goalModel) {
|
||||||
|
GraphBuilder builder = new GraphBuilder();
|
||||||
|
builder.setMGoal(goalModel.goal);
|
||||||
|
builder.setXAxisLabel(goalModel.xAxisLabel);
|
||||||
|
builder.setYAxisLabel(goalModel.yAxisLabel);
|
||||||
|
builder.loadDataSet(goalModel.columnList);
|
||||||
|
JFreeChart chart = builder.createChart(goalModel.chartType);
|
||||||
|
ChartRenderingInfo info = new ChartRenderingInfo();
|
||||||
|
chart.getPlot().setForegroundAlpha(0.6f);
|
||||||
|
if (goalModel.zoomFactor > 0) {
|
||||||
|
chartWidth = chartWidth * goalModel.zoomFactor / 100;
|
||||||
|
chartHeight = chartHeight * goalModel.zoomFactor / 100;
|
||||||
|
}
|
||||||
|
if (!goalModel.showTitle) {
|
||||||
|
chart.setTitle("");
|
||||||
|
}
|
||||||
|
BufferedImage bi = chart.createBufferedImage(chartWidth, chartHeight,
|
||||||
|
BufferedImage.TRANSLUCENT, info);
|
||||||
|
try {
|
||||||
|
byte[] bytes = EncoderUtil.encode(bi, ImageFormat.PNG, true);
|
||||||
|
|
||||||
|
AImage image = new AImage("", bytes);
|
||||||
|
Imagemap myImage = new Imagemap();
|
||||||
|
|
||||||
|
myImage.setContent(image);
|
||||||
|
parent.appendChild(myImage);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (Iterator<?> it = info.getEntityCollection().getEntities()
|
||||||
|
.iterator(); it.hasNext();) {
|
||||||
|
ChartEntity entity = (ChartEntity) it.next();
|
||||||
|
|
||||||
|
String key = null;
|
||||||
|
if (entity instanceof CategoryItemEntity) {
|
||||||
|
Comparable<?> colKey = ((CategoryItemEntity) entity)
|
||||||
|
.getColumnKey();
|
||||||
|
if (colKey != null) {
|
||||||
|
key = colKey.toString();
|
||||||
|
}
|
||||||
|
} else if (entity instanceof PieSectionEntity) {
|
||||||
|
Comparable<?> sectionKey = ((PieSectionEntity) entity)
|
||||||
|
.getSectionKey();
|
||||||
|
if (sectionKey != null) {
|
||||||
|
key = sectionKey.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (key == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Area area = new Area();
|
||||||
|
myImage.appendChild(area);
|
||||||
|
area.setCoords(entity.getShapeCoords());
|
||||||
|
area.setShape(entity.getShapeType());
|
||||||
|
area.setTooltiptext(entity.getToolTipText());
|
||||||
|
area.setId(count+"_WG_" + key);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
myImage.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
|
||||||
|
public void onEvent(Event event) throws Exception {
|
||||||
|
MouseEvent me = (MouseEvent) event;
|
||||||
|
String areaId = me.getArea();
|
||||||
|
if (areaId != null) {
|
||||||
|
List<GraphColumn> list = goalModel.columnList;
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
String s = "_WG_" + list.get(i).getLabel();
|
||||||
|
if (areaId.endsWith(s)) {
|
||||||
|
chartMouseClicked(goalModel.goal, list.get(i));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.log(Level.SEVERE, "", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void chartMouseClicked(MGoal goal, GraphColumn bgc) {
|
||||||
|
if (null == bgc)
|
||||||
|
return;
|
||||||
|
MQuery query = bgc.getMQuery(goal);
|
||||||
|
if (query != null)
|
||||||
|
AEnv.zoom(query);
|
||||||
|
else
|
||||||
|
log.warning("Nothing to zoom to - " + bgc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderChart(Component parent, int width, int height,
|
||||||
|
ChartModel chartModel) {
|
||||||
|
ChartRenderer renderer = new ChartRenderer(chartModel.chart);
|
||||||
|
renderer.render(parent, width, height);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2013 Heng Sin Low *
|
||||||
|
* Copyright (C) 2013 Trek Global *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. 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, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.adempiere.webui.apps.graph.jfreegraph;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.LinearGradientPaint;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
|
||||||
|
import org.adempiere.webui.apps.graph.model.IndicatorModel;
|
||||||
|
import org.compiere.model.MColorSchema;
|
||||||
|
import org.jfree.chart.JFreeChart;
|
||||||
|
import org.jfree.chart.plot.DialShape;
|
||||||
|
import org.jfree.chart.plot.MeterInterval;
|
||||||
|
import org.jfree.chart.plot.MeterPlot;
|
||||||
|
import org.jfree.data.Range;
|
||||||
|
import org.jfree.data.general.DefaultValueDataset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class PerformanceGraphBuilder {
|
||||||
|
|
||||||
|
public JFreeChart createIndicatorChart(IndicatorModel model)
|
||||||
|
{
|
||||||
|
JFreeChart chart = null;
|
||||||
|
DefaultValueDataset data = new DefaultValueDataset((float)model.goalModel.getPercent());
|
||||||
|
MeterPlot plot = new MeterPlot(data);
|
||||||
|
|
||||||
|
MColorSchema colorSchema = model.goalModel.getColorSchema();
|
||||||
|
int rangeLo = 0; int rangeHi=0;
|
||||||
|
Point2D start = new Point2D.Float(0, 0);
|
||||||
|
Point2D end = new Point2D.Float(50, 50);
|
||||||
|
float[] dist = {0.0f, 0.2f, 0.45f, 0.75f, 1.0f};
|
||||||
|
for (int i=1; i<=4; i++){
|
||||||
|
switch (i) {
|
||||||
|
case 1: rangeHi = colorSchema.getMark1Percent(); break;
|
||||||
|
case 2: rangeHi = colorSchema.getMark2Percent(); break;
|
||||||
|
case 3: rangeHi = colorSchema.getMark3Percent(); break;
|
||||||
|
case 4: rangeHi = colorSchema.getMark4Percent(); break;
|
||||||
|
}
|
||||||
|
if (rangeHi==9999)
|
||||||
|
rangeHi = (int) Math.floor(rangeLo*1.5);
|
||||||
|
if (rangeLo < rangeHi) {
|
||||||
|
Color[] colors = {colorSchema.getColor(rangeHi).brighter().brighter(),
|
||||||
|
colorSchema.getColor(rangeHi).brighter(), colorSchema.getColor(rangeHi),
|
||||||
|
colorSchema.getColor(rangeHi).darker(), colorSchema.getColor(rangeHi).darker().darker()};
|
||||||
|
LinearGradientPaint p =
|
||||||
|
new LinearGradientPaint(start, end, dist, colors);
|
||||||
|
|
||||||
|
plot.addInterval(new MeterInterval("Normal", //label
|
||||||
|
new Range(rangeLo, rangeHi), //range
|
||||||
|
p,
|
||||||
|
new BasicStroke(7.0f),
|
||||||
|
model.dialBackground
|
||||||
|
));
|
||||||
|
rangeLo = rangeHi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plot.setRange(new Range(0,rangeLo));
|
||||||
|
plot.setDialBackgroundPaint(model.dialBackground);
|
||||||
|
plot.setUnits("");
|
||||||
|
plot.setDialShape(DialShape.CHORD);
|
||||||
|
plot.setNeedlePaint(model.needleColor);
|
||||||
|
plot.setTickSize(2000);
|
||||||
|
plot.setTickLabelFont(new Font("SansSerif", Font.BOLD, 8));
|
||||||
|
plot.setValueFont(new Font("SansSerif", Font.BOLD, 8));
|
||||||
|
plot.setNoDataMessageFont(new Font("SansSerif", Font.BOLD, 8));
|
||||||
|
plot.setTickLabelPaint(model.tickColor);
|
||||||
|
plot.setValuePaint(new Color(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
|
plot.setTickPaint(model.tickColor);
|
||||||
|
//
|
||||||
|
chart = new JFreeChart( "", new Font("SansSerif", Font.BOLD, 9), plot,false);
|
||||||
|
|
||||||
|
return chart;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2013 Heng Sin Low *
|
||||||
|
* Copyright (C) 2013 Trek Global *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. 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, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.adempiere.webui.apps.graph.model;
|
||||||
|
|
||||||
|
import org.compiere.model.MChart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ChartModel {
|
||||||
|
public MChart chart;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2013 Heng Sin Low *
|
||||||
|
* Copyright (C) 2013 Trek Global *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. 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, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.adempiere.webui.apps.graph.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.adempiere.apps.graph.GraphColumn;
|
||||||
|
import org.compiere.model.MGoal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class GoalModel {
|
||||||
|
public MGoal goal;
|
||||||
|
public String chartType;
|
||||||
|
public boolean showTitle;
|
||||||
|
public List<GraphColumn> columnList;
|
||||||
|
public String xAxisLabel;
|
||||||
|
public String yAxisLabel;
|
||||||
|
public int zoomFactor;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2013 Heng Sin Low *
|
||||||
|
* Copyright (C) 2013 Trek Global *
|
||||||
|
* This program is free software; you can redistribute it and/or modify it *
|
||||||
|
* under the terms version 2 of the GNU General Public License as published *
|
||||||
|
* by the Free Software Foundation. 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, write to the Free Software Foundation, Inc., *
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.adempiere.webui.apps.graph.model;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
import org.compiere.model.MGoal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class IndicatorModel {
|
||||||
|
public MGoal goalModel;
|
||||||
|
public Color chartBackground;
|
||||||
|
public Color dialBackground;
|
||||||
|
public Color needleColor;
|
||||||
|
public Color tickColor;
|
||||||
|
}
|
|
@ -86,6 +86,7 @@ public class DPPerformance extends DashboardPanel {
|
||||||
script = script + "grid.parent().height(grid.css('height'));}, 500);";
|
script = script + "grid.parent().height(grid.css('height'));}, 500);";
|
||||||
if (Executions.getCurrent() != null)
|
if (Executions.getCurrent() != null)
|
||||||
Clients.response(new AuScript(script));
|
Clients.response(new AuScript(script));
|
||||||
|
this.getFirstChild().invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,10 @@ import java.util.logging.Level;
|
||||||
import org.adempiere.base.Service;
|
import org.adempiere.base.Service;
|
||||||
import org.adempiere.exceptions.AdempiereException;
|
import org.adempiere.exceptions.AdempiereException;
|
||||||
import org.adempiere.webui.apps.AEnv;
|
import org.adempiere.webui.apps.AEnv;
|
||||||
|
import org.adempiere.webui.apps.graph.IChartRendererService;
|
||||||
import org.adempiere.webui.apps.graph.WGraph;
|
import org.adempiere.webui.apps.graph.WGraph;
|
||||||
import org.adempiere.webui.apps.graph.WPerformanceDetail;
|
import org.adempiere.webui.apps.graph.WPerformanceDetail;
|
||||||
|
import org.adempiere.webui.apps.graph.model.ChartModel;
|
||||||
import org.adempiere.webui.component.ToolBarButton;
|
import org.adempiere.webui.component.ToolBarButton;
|
||||||
import org.adempiere.webui.dashboard.DashboardPanel;
|
import org.adempiere.webui.dashboard.DashboardPanel;
|
||||||
import org.adempiere.webui.dashboard.DashboardRunnable;
|
import org.adempiere.webui.dashboard.DashboardRunnable;
|
||||||
|
@ -38,7 +40,6 @@ import org.adempiere.webui.factory.IDashboardGadgetFactory;
|
||||||
import org.adempiere.webui.report.HTMLExtension;
|
import org.adempiere.webui.report.HTMLExtension;
|
||||||
import org.adempiere.webui.session.SessionManager;
|
import org.adempiere.webui.session.SessionManager;
|
||||||
import org.adempiere.webui.theme.ThemeManager;
|
import org.adempiere.webui.theme.ThemeManager;
|
||||||
import org.adempiere.webui.util.ChartRenderer;
|
|
||||||
import org.adempiere.webui.window.ZkReportViewerProvider;
|
import org.adempiere.webui.window.ZkReportViewerProvider;
|
||||||
import org.compiere.model.I_AD_Menu;
|
import org.compiere.model.I_AD_Menu;
|
||||||
import org.compiere.model.MChart;
|
import org.compiere.model.MChart;
|
||||||
|
@ -382,7 +383,6 @@ public class DashboardController implements EventListener<Event> {
|
||||||
chartPanel.addEventListener(Events.ON_AFTER_SIZE, new EventListener<AfterSizeEvent>() {
|
chartPanel.addEventListener(Events.ON_AFTER_SIZE, new EventListener<AfterSizeEvent>() {
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(AfterSizeEvent event) throws Exception {
|
public void onEvent(AfterSizeEvent event) throws Exception {
|
||||||
ChartRenderer renderer = new ChartRenderer(chartModel);
|
|
||||||
int width = event.getWidth()*90/100;
|
int width = event.getWidth()*90/100;
|
||||||
int height = event.getHeight();
|
int height = event.getHeight();
|
||||||
//set normal height
|
//set normal height
|
||||||
|
@ -391,7 +391,10 @@ public class DashboardController implements EventListener<Event> {
|
||||||
chartPanel.setHeight(height+"px");
|
chartPanel.setHeight(height+"px");
|
||||||
}
|
}
|
||||||
chartPanel.getChildren().clear();
|
chartPanel.getChildren().clear();
|
||||||
renderer.render(chartPanel, width, height);
|
ChartModel model = new ChartModel();
|
||||||
|
model.chart = chartModel;
|
||||||
|
IChartRendererService renderer = Service.locator().locate(IChartRendererService.class).getService();
|
||||||
|
renderer.renderChart(chartPanel, width, height, model);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
package org.adempiere.webui.editor;
|
package org.adempiere.webui.editor;
|
||||||
|
|
||||||
|
|
||||||
import org.adempiere.webui.util.ChartRenderer;
|
import org.adempiere.base.Service;
|
||||||
|
import org.adempiere.webui.apps.graph.IChartRendererService;
|
||||||
|
import org.adempiere.webui.apps.graph.model.ChartModel;
|
||||||
import org.compiere.model.GridField;
|
import org.compiere.model.GridField;
|
||||||
import org.compiere.model.MChart;
|
import org.compiere.model.MChart;
|
||||||
import org.compiere.util.CLogger;
|
import org.compiere.util.CLogger;
|
||||||
|
@ -50,7 +52,6 @@ public class WChartEditor extends WEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createChart() {
|
private void createChart() {
|
||||||
ChartRenderer renderer = new ChartRenderer(chartModel);
|
|
||||||
Panel panel = getComponent();
|
Panel panel = getComponent();
|
||||||
if (panel.getPanelchildren() != null) {
|
if (panel.getPanelchildren() != null) {
|
||||||
panel.getPanelchildren().getChildren().clear();
|
panel.getPanelchildren().getChildren().clear();
|
||||||
|
@ -59,7 +60,10 @@ public class WChartEditor extends WEditor
|
||||||
panel.appendChild(pc);
|
panel.appendChild(pc);
|
||||||
pc.setSclass("chart-field");
|
pc.setSclass("chart-field");
|
||||||
}
|
}
|
||||||
renderer.render(panel.getPanelchildren(), 400, chartModel.getWinHeight());
|
ChartModel model = new ChartModel();
|
||||||
|
model.chart = chartModel;
|
||||||
|
IChartRendererService renderer = Service.locator().locate(IChartRendererService.class).getService();
|
||||||
|
renderer.renderChart(panel.getPanelchildren(), 400, chartModel.getWinHeight(), model);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -33,7 +33,8 @@ bin.includes = META-INF/,\
|
||||||
OSGI-INF/feedbackservice.xml,\
|
OSGI-INF/feedbackservice.xml,\
|
||||||
sessiontimeout.zul,\
|
sessiontimeout.zul,\
|
||||||
*.jsp,\
|
*.jsp,\
|
||||||
labelapplet.jar
|
labelapplet.jar,\
|
||||||
|
OSGI-INF/jfgchartrenderer.xml
|
||||||
src.includes = WEB-INF/classes/,\
|
src.includes = WEB-INF/classes/,\
|
||||||
WEB-INF/tld/,\
|
WEB-INF/tld/,\
|
||||||
WEB-INF/web.xml,\
|
WEB-INF/web.xml,\
|
||||||
|
|
|
@ -1660,15 +1660,16 @@ table.z-vbox > tbody > tr > td > table {
|
||||||
.performance-indicator {
|
.performance-indicator {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 120px !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.performance-indicator img {
|
.performance-indicator img {
|
||||||
height: 120px;
|
height: 120px;
|
||||||
width: 120px;
|
width: 120px;
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-view-pi .performance-indicator {
|
.window-view-pi .performance-indicator img {
|
||||||
width: 180px !important;
|
width: 180px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue