org.hsh.bfr.db.gui.dbtable.editoren.MyChartDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.hsh.bfr.db.gui.dbtable.editoren.MyChartDialog.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Federal Institute for Risk Assessment (BfR), Germany
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Department Biological Safety - BfR
 *******************************************************************************/
package org.hsh.bfr.db.gui.dbtable.editoren;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.StringTokenizer;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.WindowConstants;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

import org.hsh.bfr.db.DBKernel;
import org.hsh.bfr.db.MyLogger;
import org.hsh.bfr.db.gui.InfoBox;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.lsmp.djep.djep.DJep;
import org.lsmp.djep.djep.diffRules.MacroDiffRules;
import org.lsmp.djep.xjep.MacroFunction;
import org.nfunk.jep.Node;
import org.nfunk.jep.ParseException;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * @author Armin Weiser
 */
class MyChartDialog extends JDialog {

    /**
    * 
    */
    private static final long serialVersionUID = 1L;
    private XYDataset dataset;
    private XYSeries series2;
    private String Datenpunkte = "";
    private String origDatenpunkte;

    MyChartDialog(JDialog owner, String Datenpunkte, String xAxis, String yAxis) {
        super(owner);
        this.Datenpunkte = Datenpunkte;
        origDatenpunkte = Datenpunkte;
        initComponents();

        series2 = new XYSeries("Datenpunkte");
        fillTable(xAxis, yAxis);
        dataset = createDataset();
        final JFreeChart chart = createChart(dataset, xAxis, yAxis);
        final ChartPanel chartPanel = new ChartPanel(chart);
        panel1.remove(button1);
        panel1.add(chartPanel, new CellConstraints().xywh(1, 1, 1, 1, CellConstraints.FILL, CellConstraints.FILL));
        this.setTitle(xAxis + "-" + yAxis + "-Profil");

        table1.getModel().addTableModelListener(new TableModelListener() {
            public void tableChanged(TableModelEvent e) {
                dataset = createDataset();
            }
        });
    }

    public String getDatenpunkte() {
        return Datenpunkte;
    }

    public static void main(final String[] args) {

        JDialog f = new JDialog();
        final MyChartDialog demo = new MyChartDialog(f, null, "Temperatur", "Zeit");
        demo.pack();
        demo.setVisible(true);

    }

    private void button2ActionPerformed(ActionEvent e) {
        dispose();
    }

    private void button3ActionPerformed(ActionEvent e) {
        Datenpunkte = origDatenpunkte;
        dispose();
    }

    private void button4ActionPerformed(ActionEvent e) {
        String hilfe = "In der linken Spalte der Tabelle knnen einzelne Punkte fr die x-Achse angegeben werden.\n"
                + "In der rechten Spalte die zugehrigen Werte.\n"
                + "Es ist mglich fr die x-Achse Intervalle einzugeben mit '-' als Trennzeichen (z.B. 3-5).\n"
                + "Auerdem ist es mglich verschiedene Einheiten fr Zeiten anzugeben, z.B. 3d 13h 13m 5s\n"
                + "Fr die y-Achse knnen einfache Zahlen angegeben werden oder auch Funktionen (mit x als Variable),\n"
                + "z.B. x^2, 2*x, exp(x), log10(x), ln(x)";
        if (DBKernel.getLanguage().equals("en")) {
            hilfe = "In this table values for time (x-axis) and conditions (e.g. temperature; y-axis) can be entered.\n"
                    + "Define time intervals using - (e.g. 3-5).\n"
                    + "Assign time units using d (day), h (hour), m (minute) or s (second), e.g. 3d 13h 13m 5s.\n"
                    + "Values on the y-axis may be numerical data or functions with x as variable, e.g. x^2, 2*x, exp(x), log10(x), ln(x).\n"
                    + "Please note that it is necessary to use * to indicate that x is multiplied.";
        }
        InfoBox ib = new InfoBox(this, hilfe, true, new Dimension(750, 300), null, true);
        ib.setVisible(true);
    }

    private void initComponents() {
        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents
        splitPane1 = new JSplitPane();
        scrollPane1 = new JScrollPane();
        table1 = new JTable();
        panel1 = new JPanel();
        button1 = new JButton();
        panel2 = new JPanel();
        button2 = new JButton();
        button3 = new JButton();
        button4 = new JButton();
        CellConstraints cc = new CellConstraints();

        //======== this ========
        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        Container contentPane = getContentPane();
        contentPane.setLayout(new FormLayout("default:grow", "2*(default, $lgap), default"));

        //======== splitPane1 ========
        {
            splitPane1.setDividerLocation(200);

            //======== scrollPane1 ========
            {
                scrollPane1.setPreferredSize(new Dimension(200, 423));

                //---- table1 ----
                table1.setModel(
                        new DefaultTableModel(
                                new Object[][] { { "3.0", "5" }, { null, null }, { null, null }, { null, null },
                                        { null, null }, { null, null }, { null, null }, { null, null },
                                        { null, null }, { null, null }, { null, null }, { null, null },
                                        { null, null }, { null, null }, { null, null }, { null, null },
                                        { null, null }, { null, null }, { null, null }, { null, null }, },
                                new String[] { "Zeit (h)", "Temperatur" }) {
                            /**
                             * 
                             */
                            private static final long serialVersionUID = 1L;
                            Class<?>[] columnTypes = new Class<?>[] { String.class, String.class };

                            @Override
                            public Class<?> getColumnClass(int columnIndex) {
                                return columnTypes[columnIndex];
                            }
                        });
                {
                    TableColumnModel cm = table1.getColumnModel();
                    cm.getColumn(0).setPreferredWidth(100);
                }
                scrollPane1.setViewportView(table1);
            }
            splitPane1.setLeftComponent(scrollPane1);

            //======== panel1 ========
            {
                panel1.setLayout(new FormLayout("default:grow", "fill:default:grow"));

                //---- button1 ----
                button1.setText("text");
                panel1.add(button1, cc.xy(1, 1));
            }
            splitPane1.setRightComponent(panel1);
        }
        contentPane.add(splitPane1, cc.xy(1, 1));

        //======== panel2 ========
        {
            panel2.setLayout(new FormLayout("3*(default:grow, $lcgap), default:grow", "default"));
            ((FormLayout) panel2.getLayout()).setColumnGroups(new int[][] { { 1, 3, 5, 7 } });

            //---- button2 ----
            button2.setText("OK");
            button2.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    button2ActionPerformed(e);
                }
            });
            panel2.add(button2, cc.xy(3, 1));

            //---- button3 ----
            button3.setText("Abbrechen");
            button3.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    button3ActionPerformed(e);
                }
            });
            panel2.add(button3, cc.xy(5, 1));

            //---- button4 ----
            button4.setText("Hilfe");
            button4.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    button4ActionPerformed(e);
                }
            });
            panel2.add(button4, cc.xy(7, 1));
        }
        contentPane.add(panel2, cc.xy(1, 5));
        setSize(555, 390);
        setLocationRelativeTo(null);
        // JFormDesigner - End of component initialization  //GEN-END:initComponents
    }

    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables
    private JSplitPane splitPane1;
    private JScrollPane scrollPane1;
    private JTable table1;
    private JPanel panel1;
    private JButton button1;
    private JPanel panel2;
    private JButton button2;
    private JButton button3;
    private JButton button4;
    // JFormDesigner - End of variables declaration  //GEN-END:variables

    private void fillTable(String xAxis, String yAxis) {
        table1.getColumnModel().getColumn(0).setHeaderValue(xAxis);
        table1.getColumnModel().getColumn(1).setHeaderValue(yAxis);
        int row = 0;
        for (int i = 0; i < table1.getModel().getRowCount(); i++) {
            table1.getModel().setValueAt(null, i, 0);
            table1.getModel().setValueAt(null, i, 1);
        }
        if (Datenpunkte != null) {
            StringTokenizer tok = new StringTokenizer(Datenpunkte, "\n");
            while (tok.hasMoreTokens()) {
                String vals = tok.nextToken();
                int index = vals.indexOf("\t");
                if (index > 0) {
                    table1.getModel().setValueAt(vals.substring(0, index), row, 0);
                    table1.getModel().setValueAt(vals.substring(index + 1), row, 1);
                } else {
                    MyLogger.handleMessage("java.lang.StringIndexOutOfBoundsException - fillTable - index <= 0: "
                            + vals + "\n" + Datenpunkte);
                }
                row++;
                if (row == table1.getModel().getRowCount())
                    break;
            }
        }
    }

    /**
     * Creates a sample dataset.
     * 
     * @return a sample dataset.
     */
    private XYDataset createDataset() {

        series2.clear();
        Datenpunkte = "";
        for (int i = 0; i < table1.getModel().getRowCount(); i++) {
            Object o1 = table1.getModel().getValueAt(i, 0);
            Object o2 = table1.getModel().getValueAt(i, 1);
            if (o1 == null || o2 == null || o1.toString().trim().length() == 0
                    || o2.toString().trim().length() == 0) {
                break;
            } else {
                String interval = o1.toString().trim();
                String function = o2.toString().trim();
                Datenpunkte += "\n" + interval + "\t" + function;
                Double tVal = getDouble(interval);
                Double val = getDouble(function);
                if (val != null && tVal != null)
                    series2.add(tVal, val);
                else {
                    try {
                        parseString(series2, function, interval); // z.B. sin(x)+2*cos(3*x)
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        if (Datenpunkte.length() > 0)
            Datenpunkte = Datenpunkte.substring(1);

        final XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(series2);

        return dataset;

    }

    private Double getDouble(String val) {
        Double result = null;
        try {
            if (val.indexOf("d") < 0 && val.indexOf("D") < 0)
                result = Double.parseDouble(val.trim());
            else
                Double.parseDouble("wsd");
        } catch (Exception e) {
            // es ist erlaubt d: Tage, h: Stunden, m: Minuten, s: Sekunden dranzuschreiben
            try {
                Double res = 0.0;
                String tVal = val.trim();
                if (tVal.length() > 0) {
                    int index = tVal.indexOf("d");
                    if (index >= 0) {
                        res += Double.parseDouble(tVal.substring(0, index).trim()) * 24;
                        tVal = tVal.substring(index + 1).trim();
                    }
                    index = tVal.indexOf("h");
                    if (index >= 0) {
                        res += Double.parseDouble(tVal.substring(0, index).trim());
                        tVal = tVal.substring(index + 1).trim();
                    }
                    index = tVal.indexOf("m");
                    if (index >= 0) {
                        res += Double.parseDouble(tVal.substring(0, index).trim()) / 60;
                        tVal = tVal.substring(index + 1).trim();
                    }
                    index = tVal.indexOf("s");
                    if (index >= 0) {
                        res += Double.parseDouble(tVal.substring(0, index).trim()) / 60 / 60;
                        tVal = tVal.substring(index + 1).trim();
                    }
                }
                if (tVal.length() == 0)
                    result = res;
            } catch (Exception e1) {
            }
        }
        return result;
    }

    private void parseString(XYSeries series, String function, String interval) throws ParseException {
        DJep parser = createParser();

        parser.addVariable("x", 0.0);

        Node f = parser.parse(function);

        int index = interval.indexOf("-", interval.charAt(0) == '-' ? 1 : 0);
        if (index > 0) {
            Double min = getDouble(interval.substring(0, index));
            Double max = getDouble(interval.substring(index + 1));
            if (min != null && max != null) {
                int numPoints = 50;
                double iv = (max - min) / numPoints;
                for (int i = 0; i < numPoints + 1; i++) {
                    double t = min + i * iv;

                    parser.setVarValue("x", t);

                    Object number = parser.evaluate(f);

                    if (number instanceof Double) {
                        series.add(t, (Double) number);
                    }
                }
            }
        }
    }

    private static DJep createParser() {
        DJep parser = new DJep();

        parser.setAllowAssignment(true);
        parser.setAllowUndeclared(true);
        parser.setImplicitMul(true);
        parser.addStandardFunctions();
        parser.addStandardDiffRules();
        parser.removeVariable("x");

        try {
            parser.addFunction("log10", new MacroFunction("log10", 1, "ln(x)/ln(10)", parser));
            parser.addDiffRule(new MacroDiffRules(parser, "log10", "1/(x*ln(10))"));
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return parser;
    }

    /**
     * Creates a chart.
     * 
     * @param dataset  the data for the chart.
     * 
     * @return a chart.
     */
    private JFreeChart createChart(final XYDataset dataset, String xAxis, String yAxis) {

        // create the chart...
        final JFreeChart chart = ChartFactory.createXYLineChart("", // chart title
                xAxis, // x axis label
                yAxis, // y axis label
                dataset, // data
                PlotOrientation.VERTICAL, false, // include legend
                true, // tooltips
                false // urls
        );

        // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...
        chart.setBackgroundPaint(Color.white);

        //        final StandardLegend legend = (StandardLegend) chart.getLegend();
        //      legend.setDisplaySeriesShapes(true);

        // get a reference to the plot for further customisation...
        final XYPlot plot = chart.getXYPlot();
        plot.setBackgroundPaint(Color.lightGray);
        //plot.setAxisOffset(new Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0));
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);

        final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
        renderer.setSeriesLinesVisible(0, true);
        renderer.setSeriesShapesVisible(0, false);
        plot.setRenderer(renderer);

        // change the auto tick unit selection to integer units only...
        final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        // OPTIONAL CUSTOMISATION COMPLETED.

        return chart;

    }
}