package jeql.command.chart; import jeql.api.row.Row; import jeql.api.row.RowIterator; import jeql.api.row.SchemaUtil; import jeql.api.table.Table; import jeql.util.TypeUtil; 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.labels.ItemLabelPosition; import org.jfree.chart.labels.StandardCategoryItemLabelGenerator; import org.jfree.chart.plot.CategoryPlot; 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.ui.TextAnchor; public class CategoryChart extends BaseChart { public CategoryChart(String chartType) { } public JFreeChart createChart() throws Exception { if (param.getNumSeries() == 0) { JFreeChart chart = createChart(createDataset(param.getFirstDataTable(), param.getSeriesKey(0))); return chart; } // create multiple series dataset JFreeChart chart = createChart(createDataset(param)); return chart; } private CategoryDataset createDataset(ChartParameters param) { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); for (int i = 0; i < param.getNumSeries(); i++) { addSeries(dataset, param.getSeriesKey(i), param.getSeries(i)); } return dataset; } private void addSeries(DefaultCategoryDataset dataset, String datasetKey, Table tbl) { int keyIndex = findColumnIndex(tbl, DATA_COL_KEY, DATA_COL_X, -1); if (keyIndex < 0) keyIndex = SchemaUtil.getColumnWithType(tbl.getRows().getSchema(), String.class); // if no named key and no string key, just use first column if (keyIndex < 0) keyIndex = 0; int valueIndex = findRangeIndex(tbl, DATA_COL_VALUE, DATA_COL_Y, keyIndex); int rowCount = 0; for (RowIterator i = tbl.getRows().iterator(); ; ) { Row row = i.next(); if (row == null) break; String key = "" + rowCount++; if (keyIndex >= 0) { Object keyObj = row.getValue(keyIndex); // guard against bad data if (keyObj == null) continue; key = keyObj.toString(); double value = TypeUtil.toDouble(row.getValue(valueIndex)); dataset.setValue(new Double(value), datasetKey, key); } } } private CategoryDataset createDataset(Table tbl, String datasetKey) { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); if (tbl == null) return dataset; addSeries(dataset, datasetKey, tbl); return dataset; } private CategoryDataset OLDcreateDataset(Table tbl, String datasetKey) { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); if (tbl == null) return dataset; int keyIndex = findColumnIndex(tbl, DATA_COL_KEY, DATA_COL_X, -1); if (keyIndex < 0) keyIndex = SchemaUtil.getColumnWithType(tbl.getRows().getSchema(), String.class); // if no named key and no string key, just use first column if (keyIndex < 0) keyIndex = 0; int valueIndex = findRangeIndex(tbl, DATA_COL_VALUE, DATA_COL_Y, keyIndex); int rowCount = 0; for (RowIterator i = tbl.getRows().iterator(); ; ) { Row row = i.next(); if (row == null) break; String key = "" + rowCount++; if (keyIndex >= 0) { Object keyObj = row.getValue(keyIndex); // guard against bad data if (keyObj == null) continue; key = keyObj.toString(); double value = TypeUtil.toDouble(row.getValue(valueIndex)); dataset.setValue(new Double(value), datasetKey, key); } } return dataset; } public String getChartType() { String chartType = param.chartType; return chartType; } /** * Creates a chart. * * @param dataset the dataset. * * @return A chart. */ private JFreeChart createChart(CategoryDataset dataset) { String chartType = getChartType(); JFreeChart chart = null; if (chartType == CHART_TYPE_LINE && param.isExtruded) { chart = ChartFactory.createLineChart3D( param.title, param.axisXTitle, param.axisYTitle, dataset, param.plotOrientation, param.showLegend, false, false); } else if (chartType == CHART_TYPE_LINE && param.isFilled) chart = ChartFactory.createAreaChart( param.title, param.axisXTitle, param.axisYTitle, dataset, param.plotOrientation, param.showLegend, false, false); else if (chartType == CHART_TYPE_BAR && param.isExtruded) chart = ChartFactory.createBarChart3D( param.title, param.axisXTitle, param.axisYTitle, dataset, param.plotOrientation, param.showLegend, false, false); else if (chartType == CHART_TYPE_LINE) { chart = ChartFactory.createLineChart( param.title, param.axisXTitle, param.axisYTitle, dataset, param.plotOrientation, param.showLegend, false, false); } else if (chartType == CHART_TYPE_BAR) { // Create a simple Bar chart chart = ChartFactory.createBarChart( param.title, param.axisXTitle, param.axisYTitle, dataset, param.plotOrientation, param.showLegend, false, false); } else if (chartType == CHART_TYPE_BAR_STACKED && param.isExtruded) { chart = ChartFactory.createStackedBarChart3D( param.title, param.axisXTitle, param.axisYTitle, dataset, param.plotOrientation, param.showLegend, false, false); } else if (chartType == CHART_TYPE_BAR_STACKED) { chart = ChartFactory.createStackedBarChart( param.title, param.axisXTitle, param.axisYTitle, dataset, param.plotOrientation, param.showLegend, false, false); } CategoryPlot plot = chart.getCategoryPlot(); // set X axis label angles if (param.axisXLabelRotation != 0.0) { CategoryAxis axis = plot.getDomainAxis(); axis.setCategoryLabelPositions(getCategoryLabelPosition(param.axisXLabelRotation)); } CategoryItemRenderer renderer = plot.getRenderer(); if (param.showItemLabels) { renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator()); renderer.setBaseItemLabelsVisible(true); if (param.itemLabelRotation != 0.0) { double ang = -1 * Math.PI / 2 * param.itemLabelRotation; ItemLabelPosition pos = renderer.getBasePositiveItemLabelPosition(); ItemLabelPosition pos2 = new ItemLabelPosition(pos.getItemLabelAnchor(), TextAnchor.CENTER_LEFT, TextAnchor.CENTER_LEFT, ang); renderer.setBasePositiveItemLabelPosition(pos2); } } // TODO: expose some of these as parameters (eg barColor: clr, shadow: boolean // set up bar painting if (param.color != null) renderer.setSeriesPaint(0, param.color); if (renderer instanceof BarRenderer) { BarRenderer barRend = (BarRenderer) renderer; // don't draw shadow barRend.setShadowVisible(false); barRend.setDrawBarOutline(false); // use flat filled bar rather than rounded bar with sheen barRend.setBarPainter(new StandardBarPainter()); } chart.getCategoryPlot().setRenderer(renderer); return chart; } public static CategoryLabelPositions getCategoryLabelPosition(double angle) { if (angle == 0.0) return CategoryLabelPositions.STANDARD; if (angle > 0.0 && angle < 1.0) return CategoryLabelPositions.UP_45; if (angle >= 1.0) return CategoryLabelPositions.UP_90; if (angle < 0.0 && angle > -1.0) return CategoryLabelPositions.DOWN_45; if (angle <= -1.0) return CategoryLabelPositions.DOWN_90; return CategoryLabelPositions.STANDARD; } }