001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2013, by Object Refinery Limited and Contributors.
006 *
007 * Project Info:  http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
025 * Other names may be trademarks of their respective owners.]
026 *
027 * ------------------------
028 * XYDatasetTableModel.java
029 * ------------------------
030 * (C)opyright 2003-2008, by Bryan Scott and Contributors.
031 *
032 * Original Author:  Bryan Scott ;
033 * Contributor(s):   David Gilbert (for Object Refinery Limited);
034 *
035 * Changes
036 * -------
037 * 01-Jul-2003 : Version 1 contributed by Bryan Scott (DG);
038 * 27-Apr-2005 : Change XYDataset --> TableXYDataset because the table model
039 *               assumes all series share the same x-values, and this is not
040 *               enforced by XYDataset.  Also fixed bug 1191046, a problem
041 *               in the getValueAt() method (DG);
042 *
043 */
044
045package org.jfree.data.xy;
046
047import javax.swing.table.AbstractTableModel;
048import javax.swing.table.TableModel;
049
050import org.jfree.data.general.DatasetChangeEvent;
051import org.jfree.data.general.DatasetChangeListener;
052
053/**
054 * A READ-ONLY wrapper around a {@link TableXYDataset} to convert it to a
055 * table model for use in a JTable.  The first column of the table shows the
056 * x-values, the remaining columns show the y-values for each series (series 0
057 * appears in column 1, series 1 appears in column 2, etc).
058 * <P>
059 * TO DO:
060 * <ul>
061 * <li>implement proper naming for x axis (getColumnName)</li>
062 * <li>implement setValueAt to remove READ-ONLY constraint (not sure how)</li>
063 * </ul>
064 */
065public class XYDatasetTableModel extends AbstractTableModel
066        implements TableModel, DatasetChangeListener  {
067
068    /** The dataset. */
069    TableXYDataset model = null;
070
071    /**
072     * Default constructor.
073     */
074    public XYDatasetTableModel() {
075        super();
076    }
077
078    /**
079     * Creates a new table model based on the specified dataset.
080     *
081     * @param dataset  the dataset.
082     */
083    public XYDatasetTableModel(TableXYDataset dataset) {
084        this();
085        this.model = dataset;
086        this.model.addChangeListener(this);
087    }
088
089    /**
090     * Sets the model (dataset).
091     *
092     * @param dataset  the dataset.
093     */
094    public void setModel(TableXYDataset dataset) {
095        this.model = dataset;
096        this.model.addChangeListener(this);
097        fireTableDataChanged();
098    }
099
100    /**
101     * Returns the number of rows.
102     *
103     * @return The row count.
104     */
105    @Override
106    public int getRowCount() {
107        if (this.model == null) {
108            return 0;
109        }
110        return this.model.getItemCount();
111    }
112
113    /**
114     * Gets the number of columns in the model.
115     *
116     * @return The number of columns in the model.
117     */
118    @Override
119    public int getColumnCount() {
120        if (this.model == null) {
121            return 0;
122        }
123        return this.model.getSeriesCount() + 1;
124    }
125
126    /**
127     * Returns the column name.
128     *
129     * @param column  the column index.
130     *
131     * @return The column name.
132     */
133    @Override
134    public String getColumnName(int column) {
135        if (this.model == null) {
136            return super.getColumnName(column);
137        }
138        if (column < 1) {
139            return "X Value";
140        }
141        else {
142            return this.model.getSeriesKey(column - 1).toString();
143        }
144    }
145
146    /**
147     * Returns a value of the specified cell.
148     * Column 0 is the X axis, Columns 1 and over are the Y axis
149     *
150     * @param row  the row number.
151     * @param column  the column number.
152     *
153     * @return The value of the specified cell.
154     */
155    @Override
156    public Object getValueAt(int row, int column) {
157        if (this.model == null) {
158            return null;
159        }
160        if (column < 1) {
161            return this.model.getX(0, row);
162        }
163        else {
164            return this.model.getY(column - 1, row);
165        }
166    }
167
168    /**
169     * Receives notification that the underlying dataset has changed.
170    *
171     * @param event  the event
172     *
173     * @see DatasetChangeListener
174     */
175    @Override
176    public void datasetChanged(DatasetChangeEvent event) {
177        fireTableDataChanged();
178    }
179
180    /**
181     * Returns a flag indicating whether or not the specified cell is editable.
182     *
183     * @param row  the row number.
184     * @param column  the column number.
185     *
186     * @return {@code true} if the specified cell is editable.
187     */
188    @Override
189    public boolean isCellEditable(int row, int column) {
190        return false;
191   }
192
193    /**
194     * Updates the {@link XYDataset} if allowed.
195     *
196     * @param value  the new value.
197     * @param row  the row.
198     * @param column  the column.
199     */
200    @Override
201    public void setValueAt(Object value, int row, int column) {
202        if (isCellEditable(row, column)) {
203            // XYDataset only provides methods for reading a dataset...
204        }
205    }
206
207//    /**
208//     * Run a demonstration of the table model interface.
209//     *
210//     * @param args  ignored.
211//     *
212//     * @throws Exception when an error occurs.
213//     */
214//    public static void main(String args[]) throws Exception {
215//        JFrame frame = new JFrame();
216//        JPanel panel = new JPanel();
217//        panel.setLayout(new BorderLayout());
218//
219//        XYSeries s1 = new XYSeries("Series 1", true, false);
220//        for (int i = 0; i < 10; i++) {
221//            s1.add(i, Math.random());
222//        }
223//        XYSeries s2 = new XYSeries("Series 2", true, false);
224//        for (int i = 0; i < 15; i++) {
225//            s2.add(i, Math.random());
226//        }
227//        DefaultTableXYDataset dataset = new DefaultTableXYDataset();
228//        dataset.addSeries(s1);
229//        dataset.addSeries(s2);
230//        XYDatasetTableModel tablemodel = new XYDatasetTableModel();
231//
232//        tablemodel.setModel(dataset);
233//
234//        JTable dataTable = new JTable(tablemodel);
235//        JScrollPane scroll = new JScrollPane(dataTable);
236//        scroll.setPreferredSize(new Dimension(600, 150));
237//
238//        JFreeChart chart = ChartFactory.createXYLineChart(
239//            "XY Series Demo",
240//            "X", "Y", dataset, PlotOrientation.VERTICAL,
241//            true,
242//            true,
243//            false
244//        );
245//
246//        ChartPanel chartPanel = new ChartPanel(chart);
247//
248//        panel.add(chartPanel, BorderLayout.CENTER);
249//        panel.add(scroll, BorderLayout.SOUTH);
250//
251//        frame.setContentPane(panel);
252//        frame.setSize(600, 500);
253//        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
254//        frame.show();
255//        RefineryUtilities.centerFrameOnScreen(frame);
256//    }
257
258}