hr.restart.util.chart.ChartXY.java Source code

Java tutorial

Introduction

Here is the source code for hr.restart.util.chart.ChartXY.java

Source

/****license*****************************************************************
**   file: ChartXY.java
**   Copyright 2006 Rest Art
**
**   Licensed under the Apache License, Version 2.0 (the "License");
**   you may not use this file except in compliance with the License.
**   You may obtain a copy of the License at
**
**       http://www.apache.org/licenses/LICENSE-2.0
**
**   Unless required by applicable law or agreed to in writing, software
**   distributed under the License is distributed on an "AS IS" BASIS,
**   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
**   See the License for the specific language governing permissions and
**   limitations under the License.
**
****************************************************************************/
/*
 * Created on 30-Jul-2004
 *
 */

// TODO this class should allow to construct a graph directly from a Map

package hr.restart.util.chart;

import hr.restart.util.OKpanel;
import hr.restart.util.raImages;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Paint;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Locale;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPosition;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.CategoryLabelWidthType;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.BarRenderer;
import org.jfree.chart.renderer.CategoryItemRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.CategoryDataset;
import org.jfree.data.DatasetUtilities;
import org.jfree.data.DefaultCategoryDataset;
import org.jfree.data.PieDataset;
import org.jfree.text.TextBlockAnchor;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.TextAnchor;

import com.borland.dx.dataset.Column;
import com.borland.dx.dataset.DataSet;
import com.borland.dx.dataset.SortDescriptor;
import com.borland.dx.dataset.StorageDataSet;
import com.borland.dx.dataset.Variant;

/**
 * All the objects that want to be able to give a graphical representation should extends this class.
 * It allows to show a graphical view of a DataSet component in a 2D X-Y manner.
 * @author gradecak
 *
 */
abstract public class ChartXY extends ChartBase implements ActionListener {

    /**
     * static variable wich should be used to select a PIE CHART.
     */
    public static final String PIE_CHART = "Tortni Grafikon";

    private boolean instanciated = false;

    //private variables
    private ArrayList charts = null;
    private JComboBox jcb = null;
    private JComboBox comboBox = null;
    private JComboBox comboBoxQuantity = null;
    private JComboBox comboBoxOrientation = null;
    private CategoryDataset barDataset = null;
    private PieDataset pieDataset = null;
    private JFreeChart barChart = null;
    private JFreeChart pieChart = null;
    private ChartPanel chartPanel = null;
    private JPanel buttonsPanel = null;
    private JPanel mainPanel = null;
    private String[] colNamesY = null;

    /**
     * This constructor calls the super constructor from #hr.restart.util.chart.ChartBase
     *
     */
    public ChartXY() {
        super();

    }

    /* (non-Javadoc)
     * @see hr.restart.util.chart.IChart#dataSetToMap()
     */
    public CategoryDataset createDataSet() throws NullPointerException {

        final DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        DataSet ds = getDataSet();
        SortDescriptor old = ds.getSort();
        String key = getAxisX();
        String value = jcb == null ? getAxisY() : colNamesY[jcb.getSelectedIndex()];

        ds.setSort(new SortDescriptor(new String[] { value }, true, true));

        StorageDataSet scoped = new StorageDataSet();
        scoped.setLocale(Locale.getDefault());
        scoped.setColumns(new Column[] { ds.getColumn(key).cloneColumn(), ds.getColumn(value).cloneColumn(), });
        scoped.open();

        BigDecimal ostali = new BigDecimal(0);

        int maxElements = getNumberOfElements();

        if (comboBoxQuantity != null)
            maxElements = new Integer(comboBoxQuantity.getSelectedItem().toString()).intValue();

        int i = 0;
        for (ds.first(); ds.inBounds(); ds.next()) {
            i++;
            if (i > maxElements) {
                try {

                    ostali = ostali.add(ds.getBigDecimal(value));
                } catch (Exception e) {
                    System.out.println("(ChartXY) : method --> dataSetToMap : " + e);
                    break;
                }
            } else {
                scoped.insertRow(false);

                scoped.setString(key, ds.getString(key));
                scoped.setBigDecimal(value, ds.getBigDecimal(value));
            }
        }

        if (ostali.signum() > 0) {
            scoped.insertRow(false);

            scoped.setString(key, "OSTALI");
            scoped.setBigDecimal(value, ostali);
        }
        scoped.post();

        if (sortByValue())
            scoped.setSort(ds.getSort());
        else
            scoped.setSort(new SortDescriptor(new String[] { key }));

        ds.setSort(old);

        for (scoped.first(); scoped.inBounds(); scoped.next())
            dataset.addValue(scoped.getBigDecimal(value).doubleValue(), "", scoped.getString(key));
        return dataset;
        //return initMapTest();
    }

    /* (non-Javadoc)
     * @see hr.restart.util.chart.IChart#getChartPanel()
     */
    public ChartPanel getChartPanel() {
        return this.chartPanel;
    }

    /* (non-Javadoc)
     * @see hr.restart.util.chart.IChart#initFrame()
     */
    public void initFrame() throws Exception {

        if (isInstanciated()) {
            if (chartPanel != null)
                mainPanel.remove(chartPanel);
            chartPanel = initGraph();
            mainPanel.add(chartPanel, BorderLayout.CENTER);
            return;
        }

        setInstanciated(true);

        verifyDialog();

        charts = new ArrayList();
        charts.add(BAR_CHART);
        charts.add(PIE_CHART);

        mainPanel = new JPanel(new BorderLayout());

        buttonsPanel = new JPanel(new FlowLayout());

        JPanel actionsPanel = new JPanel(new BorderLayout());
        JPanel savePanel = new JPanel();

        //adding combobox
        comboBox = new JComboBox(charts.toArray());
        comboBox.addActionListener(this);

        buttonsPanel.add(comboBox);

        //adding filechooser
        JButton btSave = new JButton("Snimi");
        btSave.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent ev) {

                try {
                    chartPanel.doSaveAs();
                } catch (IOException e) {
                    // 
                    e.printStackTrace();
                    System.out.println(e);
                }
            }
        });
        savePanel.add(btSave);

        //adding printing button
        JButton btPrint = new JButton("Ispis");
        btPrint.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ev) {

                chartPanel.createChartPrintJob();
            }
        });
        savePanel.add(btPrint);

        //creates datasets
        barDataset = createDataSet();
        pieDataset = DatasetUtilities.createPieDatasetForRow(barDataset, 0);

        String value;
        if (jcb == null)
            value = getAxisY();
        else
            value = colNamesY[jcb.getSelectedIndex()];

        PlotOrientation orientation = PlotOrientation.VERTICAL;

        pieChart = createPieChart(pieDataset, value);
        barChart = createBarChart(barDataset, value, orientation);

        //adding orientation box
        String[] orientations = { "Vertikalni", "Horizontalni" };
        comboBoxOrientation = new JComboBox(orientations);
        comboBoxOrientation.setVisible(false);
        comboBoxOrientation.addItemListener(new ItemListener() {

            /* (non-Javadoc)
               * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
               */
            public void itemStateChanged(ItemEvent e) {
                // TODO Auto-generated method stub
                if (comboBoxOrientation.getSelectedItem() == "Vertikalni")
                    selectionChanged(PlotOrientation.VERTICAL);
                else
                    selectionChanged(PlotOrientation.HORIZONTAL);
            }
        });

        buttonsPanel.add(comboBoxOrientation);

        // adding combobox
        String[] quantity = { "5", "10", "15" };
        comboBoxQuantity = new JComboBox(quantity);
        comboBoxQuantity.setEditable(true);
        comboBoxQuantity.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ev) {

                try {
                    mainPanel.remove(chartPanel);
                } catch (RuntimeException e1) {
                    //e1.printStackTrace();               
                }

                selectionChanged(PlotOrientation.VERTICAL);
            }

        });

        comboBoxQuantity.setSelectedItem(new Integer(getNumberOfElements()).toString());
        buttonsPanel.add(comboBoxQuantity);

        if (jcb != null) {
            if (getDefaultSelectedItem() != null) {
                if (getDefaultSelectedItem().compareTo("") != 0)
                    jcb.setSelectedItem(getDefaultSelectedItem());
            }

            buttonsPanel.add(jcb);
        }

        // adding OKPanel
        final OKpanel okPanel = new OKpanel() {
            public void jBOK_actionPerformed() {
                //ok_action();
                chartPanel.createChartPrintJob();
            }

            public void jPrekid_actionPerformed() {
                //            firstESC();
                cancelPressed();

            }
        };

        okPanel.addAncestorListener(new AncestorListener() {
            public void ancestorAdded(AncestorEvent e) {
                //                register the keys action

                okPanel.registerOKPanelKeys(getJdialog());
            }

            public void ancestorMoved(AncestorEvent e) {

            }

            public void ancestorRemoved(AncestorEvent e) {
                okPanel.unregisterOKPanelKeys(getJdialog());
            }
        });

        okPanel.jBOK.setText("Ispis");
        okPanel.jBOK.setIcon(raImages.getImageIcon(raImages.IMGPRINT));

        JButton btSnimi = new JButton("Snimi");
        btSnimi.setIcon(raImages.getImageIcon(raImages.IMGSAVE));
        btSnimi.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ev) {
                try {
                    chartPanel.doSaveAs();
                } catch (IOException e) {
                    // 
                    e.printStackTrace();
                    System.out.println(e);
                }
            }

        });
        okPanel.add(btSnimi, BorderLayout.WEST);
        mainPanel.add(okPanel, BorderLayout.SOUTH);

        actionsPanel.add(buttonsPanel, BorderLayout.CENTER);
        //actionsPanel.add(savePanel,BorderLayout.SOUTH);   
        actionsPanel.add(okPanel, BorderLayout.SOUTH);
        mainPanel.add(actionsPanel, BorderLayout.SOUTH);

        chartPanel = initGraph();
        mainPanel.add(chartPanel, BorderLayout.CENTER);

        this.getContentPane().add(mainPanel);
    }

    private void cancelPressed() {
        //hide();
        getJdialog().dispose();

    }

    /* (non-Javadoc)
     * @see hr.restart.util.chart.IChart#initGraph()
     */
    public ChartPanel initGraph() {

        //creates dataset      
        barDataset = createDataSet();
        pieDataset = DatasetUtilities.createPieDatasetForRow(barDataset, 0);

        PlotOrientation orientation = PlotOrientation.VERTICAL;
        //creates chart panels
        barChart = createBarChart(barDataset, this.getChartTitle(), orientation);
        pieChart = createPieChart(pieDataset, this.getChartTitle());

        //default      HAS TO BE CHANGED
        return new ChartPanel(barChart);
    }

    /* (non-Javadoc)
     * @see hr.restart.util.chart.IChart#repaintGraph()
     */
    public void repaintGraph() {

        this.chartPanel.repaint();
        this.chartPanel.validate();

        this.buttonsPanel.repaint();
        this.buttonsPanel.validate();

        this.getWindow().repaint();
        this.getWindow().validate();

        this.chartPanel.repaint();
        this.chartPanel.validate();

        this.buttonsPanel.repaint();
        this.buttonsPanel.validate();

        this.getWindow().repaint();
        this.getWindow().validate();
    }

    /**
     * Creates a PIE CHART
     * @param dataset The org.jfree.data.PieDataset
     * @param title The title
     * @return org.jfree.chart.JFreeChart
     */
    private JFreeChart createPieChart(final PieDataset dataset, String title) {

        final JFreeChart chart = ChartFactory.createPieChart(title, // chart title
                dataset, // data
                false, // include legend
                true, false);

        chart.setBackgroundPaint(Color.white);

        Plot plot = chart.getPlot();

        // the subtitle from the combobox        
        if (jcb != null)
            chart.addSubtitle(new TextTitle(jcb.getSelectedItem().toString()));

        //subtitles setted by the user.
        if (getSubtitles() != null)
            for (int i = 0; i < getSubtitles().size(); i++) {
                chart.addSubtitle(new TextTitle(getSubtitles().get(i).toString()));
            }

        final PiePlot piePlot = (PiePlot) plot;
        piePlot.setLabelFont(new Font("SansSerif", Font.PLAIN, 12));
        piePlot.setNoDataMessage("NO DATA!");
        piePlot.setCircular(false);
        piePlot.setLabelLinkPaint(Color.red);
        piePlot.setLabelGap(0.02);

        return chart;
    }

    /**
     * Creates a BAR CHART
     * @param dataset The org.jfree.data.CategoryDataset
     * @param title The title
     * @return org.jfree.chart.JFreeChart
     */
    private JFreeChart createBarChart(final CategoryDataset dataset, String title, PlotOrientation orientation) {

        final JFreeChart chart = ChartFactory.createBarChart(title, // chart title
                "", // domain axis label
                "", // range axis label
                dataset, // data
                orientation, // the plot orientation
                false, // include legend
                true, false);

        chart.setBackgroundPaint(Color.white);

        // the subtitle from the combobox        
        if (jcb != null)
            chart.addSubtitle(new TextTitle(jcb.getSelectedItem().toString()));

        //subtitles setted by the user.
        if (getSubtitles() != null)
            for (int i = 0; i < getSubtitles().size(); i++) {
                chart.addSubtitle(new TextTitle(getSubtitles().get(i).toString()));
            }

        final Plot plot = chart.getPlot();

        // get a reference to the plot for further customisation...
        final CategoryPlot categoryPlot = (CategoryPlot) plot;

        categoryPlot.setNoDataMessage("NO DATA!");

        categoryPlot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);

        final CategoryItemRenderer renderer = new CustomRenderer(new Paint[] { Color.red, Color.blue, Color.green,
                Color.yellow, Color.orange, Color.cyan, Color.magenta, Color.blue });
        categoryPlot.setRenderer(renderer);

        renderer.setLabelGenerator(new StandardCategoryLabelGenerator());
        renderer.setItemLabelsVisible(true);

        // inside
        //renderer.setBaseItemLabelPaint(Color.white);
        Font font = new Font("SansSerif", Font.PLAIN, 7);
        Font derive = font.deriveFont(Font.BOLD);
        renderer.setBaseItemLabelFont(derive);

        // margin
        final CategoryAxis domainAxis = categoryPlot.getDomainAxis();
        domainAxis.setLowerMargin(0.0);
        domainAxis.setUpperMargin(0.0);
        //domainAxis.setBottomCategoryLabelPosition(new CategoryLabelPosition(RectangleAnchor.BOTTOM, TextBlockAnchor.BOTTOM_CENTER));
        domainAxis.setCategoryLabelPositions(new CategoryLabelPositions(
                new CategoryLabelPosition(RectangleAnchor.TOP, TextBlockAnchor.TOP_CENTER), // TOP
                new CategoryLabelPosition(RectangleAnchor.BOTTOM, TextBlockAnchor.BOTTOM_CENTER), // BOTTOM
                new CategoryLabelPosition(RectangleAnchor.LEFT, TextBlockAnchor.CENTER_LEFT,
                        CategoryLabelWidthType.RANGE, 0.30f), // LEFT
                new CategoryLabelPosition(RectangleAnchor.RIGHT, TextBlockAnchor.CENTER_RIGHT,
                        CategoryLabelWidthType.RANGE, 0.30f) // RIGHT) 
        ));

        final ItemLabelPosition p = new ItemLabelPosition(ItemLabelAnchor.CENTER, TextAnchor.CENTER,
                TextAnchor.CENTER, 0.0);
        renderer.setPositiveItemLabelPosition(p);

        if (comboBoxOrientation != null) {
            if (comboBoxOrientation.getSelectedItem() == "Vertikalni") {

                domainAxis.setCategoryLabelPositions(
                        CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 4.0));
            }
        }

        return chart;

    }

    /**
     * A custom renderer that returns a different color for each item in a single series.
     */
    private class CustomRenderer extends BarRenderer {

        /** The colors. */
        private Paint[] colors;

        /**
         * Creates a new renderer.
         *
         * @param colors  the colors.
         */
        public CustomRenderer(final Paint[] colors) {
            this.colors = colors;
        }

        /**
         * Returns the paint for an item.  Overrides the default behaviour inherited from
         * AbstractSeriesRenderer.
         *
         * @param row  the series.
         * @param column  the category.
         *
         * @return The item color.
         */
        public Paint getItemPaint(final int row, final int column) {
            return this.colors[column % this.colors.length];
        }
    }

    /*public CategoryDataset createDataSet(Map map) {
      //creates the dataset...
      final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
          
      Set set = map.keySet();       
      Iterator iterator = set.iterator();       
      while(iterator.hasNext()){
         
      String element = (String)iterator.next();
     BigDecimal value = (BigDecimal)map.get(element);
     System.out.println("element "+element+": "+value);
     dataset.addValue(value.doubleValue(), "", element);
                            
      }
          
      return dataset;
    }*/

    private PieDataset createPieDataset() {
        return DatasetUtilities.createPieDatasetForRow(createDataSet(), 0);

    }

    /** Listens to the combo box. */
    public void actionPerformed(ActionEvent e) {

        try {
            mainPanel.remove(chartPanel);
        } catch (RuntimeException e1) {
            //e1.printStackTrace();
            //System.out.println(e);
            System.out.println("(ChartXY) : method --> actionPerformed : " + e);
        }

        /*if(jcb != null)
          AXISY = colNamesY[jcb.getSelectedIndex()];
        */

        if (comboBox.getSelectedItem() == PIE_CHART) {
            pieDataset = createPieDataset();
            pieChart = createPieChart(pieDataset, getChartTitle());
            chartPanel = new ChartPanel(pieChart);
            mainPanel.add(chartPanel, 0);
            comboBoxOrientation.setVisible(false);
        } else {
            if (comboBox.getSelectedItem() == BAR_CHART) {
                barDataset = createDataSet();

                PlotOrientation orientation = PlotOrientation.VERTICAL;

                if (comboBoxOrientation.getSelectedItem() == "Vertikalni")
                    orientation = PlotOrientation.VERTICAL;
                else
                    orientation = PlotOrientation.HORIZONTAL;

                barChart = createBarChart(barDataset, getChartTitle(), orientation);

                chartPanel = new ChartPanel(barChart);
                mainPanel.add(chartPanel, 0);
                comboBoxOrientation.setVisible(true);
            } else {
                //add other charts
            }
        }

        repaintGraph();
    }

    /**
     * Fire some actions when an input component has changed.
     *
     */
    private void selectionChanged(PlotOrientation orientation) {

        /*if(jcb != null)
          AXISY = colNamesY[jcb.getSelectedIndex()];
          */

        if (comboBox.getSelectedItem() == PIE_CHART) {
            //         pieDataset = createPieDataset();
            //                       
            //           pieChart = createPieChart(pieDataset,getChartTitle());          
            //           chartPanel = new ChartPanel(pieChart);      
            //          mainPanel.add(chartPanel,0);   

            comboBox.setSelectedItem(PIE_CHART);

            //raCommonClass.getraCommonClass().setLabelLaF(comboBoxOrientation,false);
            //comboBoxOrientation.setVisible(false);

        } else {
            if (comboBox.getSelectedItem() == BAR_CHART) {
                //            barDataset = createDataSet(dataSetToMap());
                //            
                //            //PlotOrientation orientation = PlotOrientation.VERTICAL;
                //              barChart = createBarChart(barDataset,getChartTitle(), orientation);                 
                //              chartPanel = new ChartPanel(barChart);      
                //             mainPanel.add(chartPanel,0);   

                comboBox.setSelectedItem(BAR_CHART);

                //raCommonClass.getraCommonClass().setLabelLaF(comboBoxOrientation,true);
                //comboBoxOrientation.setVisible(true);
            }
        }
    }

    /**
     * 
     * @return String[], with all captions from the DataSet
     */
    private String[] makeCaptions() {

        Hashtable hcols = new Hashtable();
        Column[] ccols = getDataSet().getColumns();
        for (int i = 0; i < ccols.length; i++) {
            //System.out.println("checking "+ccols[i].getColumnName());
            if (ccols[i].getDataType() == Variant.BIGDECIMAL) {
                hcols.put(ccols[i].getColumnName(), ccols[i].getCaption());
            }
        }

        colNamesY = (String[]) hcols.keySet().toArray(new String[0]);
        String[] colCaptionsY = new String[hcols.size()];
        for (int i = 0; i < colNamesY.length; i++) {
            colCaptionsY[i] = hcols.get(colNamesY[i]).toString();
        }

        return colCaptionsY;
    }

    /**
     * Verify if a JComboBox should be added to the panel or not.
     *
     */
    private void verifyDialog() {

        if (getAxisY() == null) {

            String[] colCaptionsY = makeCaptions();

            jcb = new JComboBox(colCaptionsY);
            jcb.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent ev) {

                    selectionChanged(PlotOrientation.VERTICAL);
                }
            });
        } else {
            Column col = getDataSet().getColumn(getAxisY());

            ArrayList subs = new ArrayList();
            subs.add(col.getCaption());

            setSubtitles(subs);
        }

    }

    /**
     * @return Returns the instanciated.
     */
    private boolean isInstanciated() {
        return instanciated;
    }

    /**
     * @param instanciated The instanciated to set.
     */
    private void setInstanciated(boolean instanciated) {
        this.instanciated = instanciated;
    }

    /**
     * this method should be overwrited by the programmer. You do not must to overwrite but 
     * if you want a specific element to be selected then return its name.
     * 
     * @return null. if null is returned than the first element is selected in the combobox. 
     */
    public String getDefaultSelectedItem() {
        return null;
    }

    public boolean sortByValue() {
        return false;
    }

}