001    /* ======================================================
002     * Orson : a free chart beans library based on JFreeChart
003     * ======================================================
004     *
005     * (C) Copyright 2007, by Object Refinery Limited.
006     *
007     * Project Info:  not-yet-released
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     * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
025     * in the United States and other countries.]
026     */
027    
028    package org.jfree.beans.editors;
029    
030    import java.awt.BorderLayout;
031    
032    import javax.swing.JFrame;
033    import javax.swing.JPanel;
034    import javax.swing.JScrollPane;
035    import javax.swing.JSplitPane;
036    import javax.swing.JTable;
037    import javax.swing.border.EmptyBorder;
038    import javax.swing.event.TableModelEvent;
039    import javax.swing.event.TableModelListener;
040    import javax.swing.table.AbstractTableModel;
041    import javax.swing.table.TableModel;
042    
043    import org.jfree.chart.ChartFactory;
044    import org.jfree.chart.ChartPanel;
045    import org.jfree.chart.JFreeChart;
046    import org.jfree.data.general.DefaultPieDataset;
047    
048    /**
049     * A GUI for editing a pie dataset.
050     */
051    public class PieDatasetGUI extends JPanel implements TableModelListener {
052    
053        class MyPieDatasetTableModel extends AbstractTableModel 
054                implements TableModel {
055    
056            /* (non-Javadoc)
057             * @see javax.swing.table.AbstractTableModel#setValueAt(java.lang.Object, int, int)
058             */
059            public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
060                if (columnIndex == 0) {
061                    if (aValue == null) {
062                        throw new IllegalArgumentException("'aValue' is null.");
063                    }
064                    Comparable key = aValue.toString();
065                    int keyIndex = this.dataset.getIndex(key);
066                    Comparable oldKey = this.dataset.getKey(rowIndex);
067                    if (keyIndex == rowIndex) {
068                        return;  // nothing to do
069                    } 
070                    if (keyIndex >= 0) {
071                        throw new IllegalArgumentException("Key already exists!");
072                    }
073                    Number value = this.dataset.getValue(rowIndex);
074                    this.dataset.insertValue(rowIndex, key, value);
075                    this.dataset.remove(oldKey);
076                    fireTableCellUpdated(rowIndex, columnIndex);
077                }
078                else if (columnIndex == 1) {
079                    Comparable key = this.dataset.getKey(rowIndex);
080                    Double value = Double.valueOf(aValue.toString());
081                    this.dataset.insertValue(rowIndex, key, value);
082                    fireTableCellUpdated(rowIndex, columnIndex);
083                }
084            }
085    
086            public boolean isCellEditable(int rowIndex, int columnIndex) {
087                return true;
088            }
089    
090            private DefaultPieDataset dataset;
091            
092            private int editingRow;
093            
094            private Comparable newKey;
095            
096            private Number newValue;
097            
098            /**
099             * Creates a new table model.
100             * 
101             * @param dataset
102             */
103            public MyPieDatasetTableModel(DefaultPieDataset dataset) {
104                this.dataset = dataset;
105                this.editingRow = -1;
106            }
107            
108            public int getColumnCount() {
109                return 2;
110            }
111    
112            /**
113             * Returns the current row count.
114             * 
115             * @return The row count.
116             */
117            public int getRowCount() {
118                int result = this.dataset.getItemCount();
119                if (this.editingRow >= 0) {
120                    result++;
121                }
122                return result;
123            }
124    
125            /**
126             * Returns a value from the table model.
127             * 
128             * @param rowIndex  the row index.
129             * @param columnIndex  the column index.
130             * 
131             * @return The value.
132             */
133            public Object getValueAt(int rowIndex, int columnIndex) {
134                
135                // if there is no editing row, or rowIndex is less than the current
136                // editing row, we can just fetch directly from the dataset...
137                if (this.editingRow < 0 || rowIndex < this.editingRow) {
138                    if (columnIndex == 0) {
139                        return this.dataset.getKey(rowIndex);
140                    }
141                    else if (columnIndex == 1) {
142                        return this.dataset.getValue(rowIndex);
143                    }
144                }
145                
146                // ...otherwise, if rowIndex is the current editing row, we should
147                // return the edit values...
148                else if (rowIndex == this.editingRow) {
149                    if (columnIndex == 0) {
150                        return this.newKey;
151                    }
152                    else if (columnIndex ==1) {
153                        return this.newValue;
154                    }
155                    
156                }
157                
158                // ...finally, this is the case where there is an editing row, but
159                // we're looking for an item further on...
160                else {
161                    if (columnIndex == 0) {
162                        return this.dataset.getKey(rowIndex - 1);
163                    }
164                    else if (columnIndex == 1) {
165                        return this.dataset.getValue(rowIndex - 1);
166                    }
167                }
168      
169                // we really shouldn't get this far...
170                return null;
171            }
172    
173            
174        }
175    
176        /**
177         * Creates a new instance.
178         * 
179         * @param dataset  the dataset.
180         */
181        public PieDatasetGUI(DefaultPieDataset dataset) {
182            super(new BorderLayout());
183            setBorder(new EmptyBorder(2, 2, 2, 2));
184            JTable table = new JTable();
185            table.setModel(new MyPieDatasetTableModel(dataset));
186            table.getModel().addTableModelListener(this);
187            add(new JScrollPane(table));
188        }
189    
190        /* (non-Javadoc)
191         * @see javax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent)
192         */
193        public void tableChanged(TableModelEvent e) {
194            System.out.println(e.toString());
195        }
196        
197        /**
198         * Starting point for a test app.
199         * 
200         * @param args  ignored.
201         */
202        public static void main(String[] args) {
203            JFrame app = new JFrame("PieDataset Editor");
204            JSplitPane gui = new JSplitPane();
205            DefaultPieDataset dataset = new DefaultPieDataset();
206            dataset.setValue("A", 1.0);
207            dataset.setValue("B", 3.0);
208            dataset.setValue("C", 3.0);
209            dataset.setValue("D", 3.0);
210            dataset.setValue("E", 3.0);
211            dataset.setValue("F", 3.0);
212            dataset.setValue("G", 3.0);
213            dataset.setValue("H", 3.0);
214            dataset.setValue("I", 3.0);
215            dataset.setValue("J", 3.0);
216            JFreeChart chart = ChartFactory.createPieChart("Pie Chart", dataset, 
217                    true, true, false);
218            ChartPanel chartPanel = new ChartPanel(chart);
219            PieDatasetGUI datasetTable = new PieDatasetGUI(dataset);
220            gui.add(chartPanel, JSplitPane.TOP);
221            gui.add(datasetTable, JSplitPane.BOTTOM);
222            app.getContentPane().add(gui);
223            app.pack();
224            app.setVisible(true);
225        }
226    }