/* * 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 javax.swing.table.AbstractTableModel; /** * A table model for a 1D and 2D ArrayTable. * * Column names, column locks, and transposed property added in version 1.1. * * @author Douglas Brown * @author Wolfgang Christian * @version 1.1 */ public class ArrayTableModel extends AbstractTableModel { double[] doubleArray1; double[][] doubleArray2; int[] intArray1; int[][] intArray2; String[] stringArray1; String[][] stringArray2; boolean[] booleanArray1; boolean[][] booleanArray2; boolean editable = false; String[] columnNames; boolean showRowNumber = true; int firstRow = 0, firstCol = 0; boolean transposed = false; java.util.Dictionary<Integer, Boolean> lockedColumns = new java.util.Hashtable<Integer, Boolean>(); /** * Constructor ArrayTableModel * @param array */ public ArrayTableModel(int[] array) { intArray1 = array; } /** * Constructor ArrayTableModel * @param array */ public ArrayTableModel(int[][] array) { intArray2 = array; } /** * Constructor ArrayTableModel * @param array */ public ArrayTableModel(double[] array) { doubleArray1 = array; } /** * Constructor ArrayTableModel * @param array */ public ArrayTableModel(double[][] array) { doubleArray2 = array; } /** * Constructor ArrayTableModel * @param array */ public ArrayTableModel(String[] array) { stringArray1 = array; } /** * Constructor ArrayTableModel * @param array */ public ArrayTableModel(String[][] array) { stringArray2 = array; } /** * Constructor ArrayTableModel * @param array */ public ArrayTableModel(boolean[] array) { booleanArray1 = array; } /** * Constructor ArrayTableModel * @param array */ public ArrayTableModel(boolean[][] array) { booleanArray2 = array; } /** * Allows changing the array with minimal changes * @param arrayObj */ public void setArray(Object arrayObj) { if(arrayObj instanceof double[]) { doubleArray1 = (double[]) arrayObj; } else if(arrayObj instanceof double[][]) { doubleArray2 = (double[][]) arrayObj; } else if(arrayObj instanceof int[]) { intArray1 = (int[]) arrayObj; } else if(arrayObj instanceof int[][]) { intArray2 = (int[][]) arrayObj; } else if(arrayObj instanceof String[]) { stringArray1 = (String[]) arrayObj; } else if(arrayObj instanceof String[][]) { stringArray2 = (String[][]) arrayObj; } else if(arrayObj instanceof boolean[]) { booleanArray1 = (boolean[]) arrayObj; } else if(arrayObj instanceof boolean[][]) { booleanArray2 = (boolean[][]) arrayObj; } } /** * Sets the column's lock flag. Returns true if the column's lock changes. * * @param column int * @param locked boolean * @return true if change occurred */ public boolean setColumnLock(int columnIndex, boolean locked) { Boolean val = lockedColumns.get(columnIndex); if((val!=null)&&(locked==val)) { return false; // nothing changed } lockedColumns.put(columnIndex, locked); return true; } /** * Sets the lock flag for multiple columns. Previously set locks are cleared. * * @param locked boolean array * @return true if change occurred */ public boolean setColumnLocks(boolean[] locked) { boolean change = false; if(lockedColumns.size()!=locked.length) { change = true; } else { // lengths are correct so check values for(int i = 0, n = locked.length; i<n; i++) { Boolean val = lockedColumns.get(i); if(!Boolean.valueOf(locked[i]).equals(val)) { change = true; break; } } } if(!change) { return false; } // locked columns have changed; clear old values and add new values ((java.util.Hashtable<Integer, Boolean>) lockedColumns).clear(); for(int i = 0, n = locked.length; i<n; i++) { lockedColumns.put(i, locked[i]); } return true; } /** * Sets the first row's index. * * @param index */ public void setFirstRowIndex(int index) { firstRow = index; } /** * Sets the first column's index. * * @param index */ public void setFirstColIndex(int index) { firstRow = index; } /** * Sets the display row number flag. Table displays row number. * * @param vis <code>true<\code> if table display row number */ public void setRowNumberVisible(boolean vis) { showRowNumber = vis; } /** * Sets the transposed property for the array. * A transposed array switches its row and column values in the display. * * @param transposed */ public void setTransposed(boolean transposed) { this.transposed = transposed; } /** * Returns true of the table's row and column values are interchanged. * @return */ public boolean isTransposed() { return transposed; } /** * Sets the editable property. * * @param editable true allows editing of the cell values that are not locked. */ public void setEditable(boolean editable) { this.editable = editable; } /** * Gets the number of columns. * * @return the column count */ public int getColumnCount() { if(getArrayRowCount()==0) { return 0; // don't show columns if there aren't any rows } int offset = showRowNumber // row numbers add a column ? 1 : 0; if(transposed) { return getArrayRowCount()+offset; } return getArrayColumnCount()+offset; } /** * Gets the number of columns in the matrix. * The second index is the column index in 2D arrays. * * @return the column count */ int getArrayColumnCount() { if((intArray1!=null)||(doubleArray1!=null)||(stringArray1!=null)||(booleanArray1!=null)) { return 1; } if(intArray2!=null) { return intArray2[0].length; } if(doubleArray2!=null) { return doubleArray2[0].length; } if(stringArray2!=null) { return stringArray2[0].length; } if(booleanArray2!=null) { return booleanArray2[0].length; } return 0; } /** * Sets columns names. Returns true if the table has changed. * @param names * @return changed */ public boolean setColumnNames(String[] names) { if((names==null)&&(columnNames==null)) { return false; // neither array exists but there is no change } if(names!=null) { names = names.clone(); // clone the array as the TeX parser may change string values } boolean changed = false; if((names!=null)&&(columnNames!=null)&&(columnNames.length==names.length)) { // arrays exist and have same length for(int i = 0, n = names.length; i<n; i++) { names[i] = TeXParser.parseTeX(names[i]); // convert TeX within each string if(!names[i].equals(columnNames[i])) { // check each name for a change changed = true; // the i-th column name has changed } } } else { // arrays have different lengths changed = true; if(names!=null) { for(int i = 0, n = names.length; i<n; i++) { names[i] = TeXParser.parseTeX(names[i]); // convert TeX within each string } } } columnNames = names; return changed; } /** * Gets the name of the specified column. * * @param column the column index * @return the column name */ public String getColumnName(int column) { if(!showRowNumber) { column++; } if((columnNames!=null)&&(column<columnNames.length)) { return columnNames[column]; } if(column==0) { return ""; //$NON-NLS-1$ } if((intArray1!=null)||(doubleArray1!=null)||(stringArray1!=null)||(booleanArray1!=null)) { return "value"; //$NON-NLS-1$ } return ""+(column-1+firstCol); //$NON-NLS-1$ } /** * Gets the number of rows. * * @return the row count */ public int getRowCount() { if(transposed) { return getArrayColumnCount(); } return getArrayRowCount(); } /** * Gets the number of rows in the array. * The first index is the row index. * * @return the row count */ int getArrayRowCount() { if(intArray1!=null) { return intArray1.length; } if(intArray2!=null) { return intArray2.length; } if(doubleArray1!=null) { return doubleArray1.length; } if(doubleArray2!=null) { return doubleArray2.length; } if(stringArray1!=null) { return stringArray1.length; } if(stringArray2!=null) { return stringArray2.length; } if(booleanArray1!=null) { return booleanArray1.length; } if(booleanArray2!=null) { return booleanArray2.length; } return 0; } /** * Gets the value at the given cell. * * @param row the row index * @param column the column index * @return the value */ public Object getValueAt(int row, int column) { if(showRowNumber&&(column==0)) { return new Integer(row+firstRow); } int offset = showRowNumber ? 1 : 0; if(transposed) { int temp = row; row = column-offset; column = temp; } if(intArray1!=null) { return new Integer(intArray1[row]); } if(intArray2!=null) { int col = transposed ? column : column-offset; if((row>intArray2.length-1)||(col>intArray2[row].length-1)||(col<0)) { return null; } return new Integer(intArray2[row][col]); } if(doubleArray1!=null) { return new Double(doubleArray1[row]); } if(doubleArray2!=null) { int col = transposed ? column : column-offset; if((row>doubleArray2.length-1)||(col>doubleArray2[row].length-1)||(col<0)) { return null; } return new Double(doubleArray2[row][col]); } if(stringArray1!=null) { return stringArray1[row]; } if(stringArray2!=null) { int col = transposed ? column : column-offset; if((row>stringArray2.length-1)||(col>stringArray2[row].length-1)||(col<0)) { return null; } return stringArray2[row][col]; } if(booleanArray1!=null) { return new Boolean(booleanArray1[row]); } if(booleanArray2!=null) { int col = transposed ? column : column-offset; if((row>booleanArray2.length-1)||(col>booleanArray2[row].length-1)||(col<0)) { return null; } return new Boolean(booleanArray2[row][col]); } return null; } /** * Sets the value at the given cell. * * @param value the value * @param row the row index * @param col the column index */ public void setValueAt(Object value, int row, int col) { int offset = showRowNumber ? 1 : 0; // added by WC if(transposed) { int temp = row; row = col-offset; col = temp; } try { if(value instanceof String) { String val = (String) value; col = transposed ? col : col-offset; // added by WC if(intArray1!=null) { intArray1[row] = Integer.parseInt(val); } else if(intArray2!=null) { intArray2[row][col] = Integer.parseInt(val); } else if(doubleArray1!=null) { doubleArray1[row] = Double.parseDouble(val); } else if(doubleArray2!=null) { doubleArray2[row][col] = Double.parseDouble(val); } else if(stringArray1!=null) { stringArray1[row] = val; } else if(stringArray2!=null) { stringArray2[row][col] = val; } else if(booleanArray1!=null) { booleanArray1[row] = val.toLowerCase().startsWith("t"); //$NON-NLS-1$ } else if(booleanArray2!=null) { booleanArray2[row][col] = val.toLowerCase().startsWith("t"); //$NON-NLS-1$ } if(transposed)fireTableCellUpdated(col, row); else fireTableCellUpdated(row, col); } } catch(Exception ex) { //System.out.println("set value exception "+ex); // do nothing on numeric format exceptions and out of bounds exceptions } } /** * Determines whether the given cell is editable. * * @param row the row index * @param col the column index * @return true if editable */ public boolean isCellEditable(int row, int col) { if(showRowNumber&&(col==0)) { return false; // row numbers are never editable } col = showRowNumber ? col-1 : col; Boolean val = lockedColumns.get(col); if(val==null) { // columns that are not in the dictionary are editable return editable; } return !val&&editable; } } /* * 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 */