/* * Open Source Physics software is free software as described near the bottom of this code file. * * For additional information and documentation on Open Source Physics please see: * <http://www.opensourcephysics.org/> */ package org.opensourcephysics.display; import java.util.Arrays; import java.util.Comparator; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.TableModel; /** * Sorts table column based on their numeric values if the table's values are * numeric. Otherwise sorts using toString. * * @author W. Christian * @version 1.0 */ public class SortDecorator implements TableModel, TableModelListener { private TableModel realModel; private int indexes[]; private int sortedColumn; // added by D Brown 2010-10-24 /** * Constructor SortDecorator * @param model */ public SortDecorator(TableModel model) { if(model==null) { throw new IllegalArgumentException("null models are not allowed"); //$NON-NLS-1$ } this.realModel = model; realModel.addTableModelListener(this); allocate(); } public Object getValueAt(int row, int column) { if (column>=getColumnCount()) { return null; } if(indexes.length<=row) { allocate(); } return realModel.getValueAt(indexes[row], column); } public void setValueAt(Object aValue, int row, int column) { if(indexes.length<=row) { allocate(); } realModel.setValueAt(aValue, indexes[row], column); } public void tableChanged(TableModelEvent e) { allocate(); } public void sort(int column) { sortedColumn = column; int rowCount = getRowCount(); if(indexes.length<=rowCount) { allocate(); } // new faster sort method added by D Brown 2015-05-16 if (realModel.getColumnClass(column)==Double.class || realModel.getColumnClass(column)==Integer.class) { Double[][] sortArray = new Double[rowCount][2]; if (realModel.getColumnClass(column)==Double.class) { for(int i = 0; i<rowCount; i++) { sortArray[i][0] = (Double)realModel.getValueAt(i, column); sortArray[i][1] = 1.0*indexes[i]; } } else { for(int i = 0; i<rowCount; i++) { sortArray[i][0] = ((Integer)realModel.getValueAt(i, column)).doubleValue(); sortArray[i][1] = 1.0*indexes[i]; } } Arrays.sort(sortArray, new Comparator<Double[]>() { public int compare(Double[] a, Double[] b) { if (a[0]==null || b[0]==null) { return b[0]==a[0]? 0: b[0]==null? -1: 1; } return(b[0]<a[0]) ? 1 : ((b[0]>a[0]) ? -1 : 0); } }); for(int i = 0; i<rowCount; i++) { indexes[i] = sortArray[i][1].intValue(); } } else { // use older sort method for String data for(int i = 0; i<rowCount; i++) { for(int j = i+1; j<rowCount; j++) { if(compare(indexes[i], indexes[j], column)<0) { swap(i, j); } } } } } // added by D Brown 2010-10-24 public int getSortedColumn() { return sortedColumn; } public void swap(int i, int j) { int tmp = indexes[i]; indexes[i] = indexes[j]; indexes[j] = tmp; } public int compare(int i, int j, int column) { Object io = realModel.getValueAt(i, column); Object jo = realModel.getValueAt(j, column); if((io!=null)&&(jo==null)) { return 1; } if((io==null)&&(jo!=null)) { return -1; } if((io==null)&&(jo==null)) { return 0; } if((io instanceof Integer)&&(jo instanceof Integer)) { int a = ((Integer) io).intValue(); int b = ((Integer) jo).intValue(); return(b<a) ? -1 : ((b>a) ? 1 : 0); } else if((io instanceof Double)&&(jo instanceof Double)) { double a = ((Double) io).doubleValue(); double b = ((Double) jo).doubleValue(); return(b<a) ? -1 : ((b>a) ? 1 : 0); } else if((io instanceof Integer)&&(jo instanceof Double)) { int a = ((Integer) io).intValue(); double b = ((Double) jo).doubleValue(); return(b<a) ? -1 : ((b>a) ? 1 : 0); } else if((io instanceof Double)&&(jo instanceof Integer)) { double a = ((Double) io).doubleValue(); int b = ((Integer) jo).intValue(); return(b<a) ? -1 : ((b>a) ? 1 : 0); } int c = jo.toString().compareTo(io.toString()); return(c<0) ? -1 : ((c>0) ? 1 : 0); } private void allocate() { indexes = new int[getRowCount()]; for(int i = 0; i<indexes.length; ++i) { indexes[i] = i; } } public int getRowCount() { return realModel.getRowCount(); } public int getColumnCount() { return realModel.getColumnCount(); } public String getColumnName(int columnIndex) { if (columnIndex>=getColumnCount()) { return "unknown"; } //$NON-NLS-1$ return realModel.getColumnName(columnIndex); } public Class<?> getColumnClass(int columnIndex) { if (columnIndex>=getColumnCount()) { return Object.class; } return realModel.getColumnClass(columnIndex); } public boolean isCellEditable(int rowIndex, int columnIndex) { if (columnIndex>=getColumnCount()) { return false; } return realModel.isCellEditable(rowIndex, columnIndex); } public void addTableModelListener(TableModelListener l) { realModel.addTableModelListener(l); } public void removeTableModelListener(TableModelListener l) { realModel.removeTableModelListener(l); } } /* * Open Source Physics software is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public License (GPL) as * published by the Free Software Foundation; either version 2 of the License, * or(at your option) any later version. * Code that uses any portion of the code in the org.opensourcephysics package * or any subpackage (subdirectory) of this package must must also be be released * under the GNU GPL license. * * This software 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; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * Copyright (c) 2007 The Open Source Physics project * http://www.opensourcephysics.org */