/*******************************************************************************
* Copyright (c) 2008 Dennis Schenk, Peter Siska.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Dennis Schenk - initial implementation
* Peter Siska - initial implementation
*******************************************************************************/
package ch.unibe.iam.scg.archie.controller;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.experimental.chart.swt.ChartComposite;
import ch.rgw.tools.Money;
import ch.unibe.iam.scg.archie.ArchieActivator;
import ch.unibe.iam.scg.archie.i18n.Messages;
import ch.unibe.iam.scg.archie.model.ChartModel;
import ch.unibe.iam.scg.archie.model.DataSet;
import ch.unibe.iam.scg.archie.ui.GraphicalMessage;
/**
* <p>
* Factory singleton object for creating chart composited based on JFreeChart
* charts and our custom chart model.
* </p>
*
* $Id: ProviderChartFactory.java 747 2009-07-23 09:14:53Z peschehimself $
*
* @author Peter Siska
* @author Dennis Schenk
* @version $Rev: 747 $
*/
public class ProviderChartFactory {
/**
* Instance of this chart factory. There's always only one through the
* entire lifecycle of this application.
*/
private static ProviderChartFactory INSTANCE;
/**
* The currently managed data provider
*/
private ChartModel model;
/**
* Private constructor.
*/
private ProviderChartFactory() {
this.model = null;
}
/**
* Returns an instance of this provider manager.
*
* @return An instance of this provider manager.
*/
public static ProviderChartFactory getInstance() {
if (ProviderChartFactory.INSTANCE == null) {
ProviderChartFactory.INSTANCE = new ProviderChartFactory();
}
return ProviderChartFactory.INSTANCE;
}
/**
* @param model
*/
public void setChartModel(ChartModel model) {
this.model = model;
assert (this.model != null);
}
/**
* Creates a chart from the currently set chart model and attaches it to the
* given parent.
*
* @param parent
* Chart composite cotainer.
* @return Composite containing the chart just created.
*/
public Composite createChart(Composite parent) {
// set layout of parent container
parent.setLayout(new GridLayout());
parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
// create an error message if no model present
if (this.model == null) {
return new GraphicalMessage(parent, ArchieActivator.getImage(ArchieActivator.IMG_ERROR),
Messages.NO_CHART_MODEL);
}
// else return a chart composite based on the chart type
if (this.model.getChartType() == ChartModel.CHART_PIE) {
return this.createPieChart(parent);
}
return this.createBarChart(parent);
}
/**
* @param parent
* @return Composite with a Chart
*/
private Composite createPieChart(Composite parent) {
// create the dataset...
DataSet dataset = this.model.getDataSet();
DefaultPieDataset pieDataset = this.createJFreePieDataset(dataset);
// create the chart...
JFreeChart chart = this.createJFreePieChart(pieDataset);
// add subtitles
TextTitle subtitle = new TextTitle(dataset.getHeadings().get(this.model.getValuesIndex()) + " per "
+ dataset.getHeadings().get(this.model.getKeysIndex()));
chart.addSubtitle(subtitle);
ChartComposite chartComposite = new ChartComposite(parent, SWT.NONE, chart);
chartComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
return chartComposite;
}
/**
*
* @param pieDataset
* @return
*/
private JFreeChart createJFreePieChart(PieDataset pieDataset) {
if (this.model.isThreeDimensional()) {
return ChartFactory.createPieChart3D(this.model.getChartName(), pieDataset, false, true, false);
}
return ChartFactory.createPieChart(this.model.getChartName(), pieDataset, false, true, false);
}
/**
*
* @param dataset
* @return
*/
private DefaultPieDataset createJFreePieDataset(DataSet dataset) {
DefaultPieDataset pieDataset = new DefaultPieDataset();
Object[] keys = dataset.getColumn(this.model.getKeysIndex());
Object[] values = dataset.getColumn(this.model.getValuesIndex());
int[] rows = this.model.getRows();
for (int i = 0; i < rows.length; i++) {
double value = 0.0;
int rowIndex = rows[i];
if (values[rowIndex] instanceof Money) {
value = ((Money) values[rowIndex]).doubleValue();
} else {
value = new Double(values[rowIndex].toString());
}
pieDataset.setValue(keys[rowIndex].toString(), value);
}
return pieDataset;
}
/**
*
* @param parent
* @return Composite with a Chart
*/
private Composite createBarChart(Composite parent) {
// create a dataset...
DataSet dataset = this.model.getDataSet();
DefaultCategoryDataset barDataset = this.createJFreeBarDataset(dataset);
// create the chart
JFreeChart chart = this.createJFreeBarChart(barDataset);
ChartComposite chartComposite = new ChartComposite(parent, SWT.NONE, chart);
chartComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
return chartComposite;
}
/**
* @param dataset
* @return
*/
private DefaultCategoryDataset createJFreeBarDataset(DataSet dataset) {
DefaultCategoryDataset categoryDataSet = new DefaultCategoryDataset();
int[] rows = this.model.getRows();
int[] columns = this.model.getColumns();
int rowTitleColumnIndex = this.model.getCategoryColumnIndex();
for (int i = 0; i < rows.length; i++) {
int rowIndex = rows[i];
Comparable<?>[] row = dataset.getRow(rowIndex);
String rowTitle = row[rowTitleColumnIndex].toString();
for (int j = 0; j < columns.length; j++) {
double value = 0.0;
int columnIndex = columns[j];
String columnTitle = (String) dataset.getHeadings().get(columnIndex);
Comparable<?> cell = dataset.getCell(rowIndex, columnIndex);
if (cell instanceof Money) {
value = ((Money) cell).doubleValue();
} else {
value = new Double(cell.toString());
}
categoryDataSet.addValue(value, columnTitle, rowTitle);
}
}
return categoryDataSet;
}
/**
*
* @param pieDataset
* @return
*/
@SuppressWarnings("deprecation")
private JFreeChart createJFreeBarChart(CategoryDataset barDataset) {
if (this.model.isThreeDimensional() && this.model.isLineChart()) {
return ChartFactory.createLineChart3D(this.model.getChartName(), "Category", "Value", barDataset,
PlotOrientation.VERTICAL, true, true, false);
} else if (this.model.isThreeDimensional() && !this.model.isLineChart()) {
return ChartFactory.createBarChart3D(this.model.getChartName(), "Category", "Value", barDataset,
PlotOrientation.VERTICAL, true, true, false);
} else if (this.model.isLineChart()) {
JFreeChart chart = ChartFactory.createLineChart(this.model.getChartName(), "Category", "Value", barDataset,
PlotOrientation.VERTICAL, true, true, false);
LineAndShapeRenderer renderer = (LineAndShapeRenderer) ((CategoryPlot) chart.getPlot()).getRenderer();
renderer.setShapesVisible(true);
renderer.setShapesFilled(true);
return chart;
}
return ChartFactory.createBarChart(this.model.getChartName(), "Category", "Value", barDataset,
PlotOrientation.VERTICAL, true, true, false);
}
}