/* * This file is part of Alida, a Java library for * Advanced Library for Integrated Development of Data Analysis Applications. * * Copyright (C) 2010 - @YEAR@ * * 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/>. * * Fore more information on Alida, visit * * http://www.informatik.uni-halle.de/alida/ * */ package de.unihalle.informatik.Alida.dataio.provider.swing; import de.unihalle.informatik.Alida.annotations.ALDDataIOProvider; import de.unihalle.informatik.Alida.dataio.ALDDataIOManagerSwing; import de.unihalle.informatik.Alida.dataio.ALDDataIOManagerSwing.ProviderInteractionLevel; import de.unihalle.informatik.Alida.dataio.provider.ALDDataIOSwingInitialGUIValueDefaultHandler; import de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponent; import de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDTableWindow; import de.unihalle.informatik.Alida.dataio.provider.swing.events.ALDSwingValueChangeEvent; import de.unihalle.informatik.Alida.dataio.provider.swing.events.ALDSwingValueChangeListener; import de.unihalle.informatik.Alida.dataio.provider.swing.events.ALDSwingValueChangeReporter; import de.unihalle.informatik.Alida.exceptions.*; import de.unihalle.informatik.Alida.exceptions.ALDDataIOProviderException.ALDDataIOProviderExceptionType; import de.unihalle.informatik.Alida.operator.ALDParameterDescriptor; import javax.swing.*; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.filechooser.FileFilter; import javax.swing.table.DefaultTableModel; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.util.*; /** * Class for generic loading/saving of 2D-arrays from/to GUI in Alida. * * @author moeller */ @ALDDataIOProvider public class ALDNativeArray2DDataIOSwing extends ALDDataIOSwingInitialGUIValueDefaultHandler { /** * List of supported classes. */ private static LinkedList<Class<?>> classes = null; /** * Default constructor. */ public ALDNativeArray2DDataIOSwing() { if (classes == null) { classes = new LinkedList<Class<?>>(); ALDNativeArray2DDataIOSwing.classes.add( Boolean[][].class); ALDNativeArray2DDataIOSwing.classes.add( Byte[][].class); ALDNativeArray2DDataIOSwing.classes.add( Double[][].class); ALDNativeArray2DDataIOSwing.classes.add( Float[][].class); ALDNativeArray2DDataIOSwing.classes.add( Integer[][].class); ALDNativeArray2DDataIOSwing.classes.add( Short[][].class); ALDNativeArray2DDataIOSwing.classes.add( String[][].class); ALDNativeArray2DDataIOSwing.classes.add( boolean[][].class); ALDNativeArray2DDataIOSwing.classes.add( byte[][].class); ALDNativeArray2DDataIOSwing.classes.add( double[][].class); ALDNativeArray2DDataIOSwing.classes.add( float[][].class); ALDNativeArray2DDataIOSwing.classes.add( int[][].class); ALDNativeArray2DDataIOSwing.classes.add( short[][].class); } } /** * Interface method to announce class for which IO is provided for. * * @return Collection of classes provided. */ @SuppressWarnings("unchecked") @Override public Collection<Class<?>> providedClasses() { return (Collection<Class<?>>)classes.clone(); } /** * Generic reading of 2D arrays. */ /* (non-Javadoc) * @see de.unihalle.informatik.Alida.helpers.ALDDataIOSwing#createGUIElement(java.lang.Class, java.lang.Object) */ @Override public ArrayConfigPanel createGUIElement(Field field, Class<?> cl, Object obj, ALDParameterDescriptor descr) { return new ArrayConfigPanel(field, cl, obj, descr); } /* (non-Javadoc) * @see de.unihalle.informatik.Alida.dataio.provider.ALDDataIOSwing#setValue(java.lang.reflect.Field, java.lang.Class, de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponent, java.lang.Object) */ @Override public void setValue(Field field, Class<?> cl, ALDSwingComponent guiElement, Object value) throws ALDDataIOProviderException { if (!(guiElement instanceof ArrayConfigPanel)) throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.INVALID_GUI_ELEMENT, "CollectionDataIO: setValue() received invalid GUI element!"); if (value != null && !(classes.contains(value.getClass()))) throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.INVALID_GUI_ELEMENT, "CollectionDataIO: setValue() received wrong object type!"); ((ArrayConfigPanel)guiElement).setValue(field, cl, value); } /* (non-Javadoc) * @see de.unihalle.informatik.Alida.dataio.provider.ALDDataIOSwing#readData(java.lang.reflect.Field, java.lang.Class, de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponent) */ @Override public Object readData( Field field, Class<?> cl, ALDSwingComponent guiElement) throws ALDDataIOProviderException { if (!(guiElement instanceof ArrayConfigPanel)) throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.INVALID_GUI_ELEMENT, "CollectionDataIO: readData received invalid GUI element!"); return ((ArrayConfigPanel)guiElement).readData(field, cl); } /* (non-Javadoc) * @see de.unihalle.informatik.Alida.dataio.provider.ALDDataIOSwing#writeData(java.lang.Object, de.unihalle.informatik.Alida.operator.ALDParameterDescriptor) */ @Override public JComponent writeData(Object obj, ALDParameterDescriptor descr) throws ALDDataIOProviderException { if (!(classes.contains(obj.getClass()))) throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.OBJECT_TYPE_ERROR, "NativeArray2DDataIO: object to write has wrong type!"); // return a button to show a window with the elements return new ArrayShowButton(obj, descr); } /** * GUI element for configuring collections. * <p> * This button has a collection configuration window attached to it * where specific data is stored and accessable. * * @author moeller */ private class ArrayConfigPanel extends ALDSwingComponent implements ALDSwingValueChangeListener, ActionListener { /** * GUI component associated with this Swing component. */ private JPanel configPanel; /** * Button to open configuration window. */ private JButton confButton; /** * Button to reset array. */ private JButton resetButton; /** * Collection configuration window. */ private ArrayConfigWindow confWin; /** * Class of array to configure. */ private Class<?> arrayClass; /** * Parameter field of array to configure. */ private Field arrayField; /** * Descriptor of parameter linked to array. */ private ALDParameterDescriptor arrayDescriptor; /** * Constructor. * @param field Field of collection. * @param cl Class of collection. * @param obj Default object. * @param descr Optional descriptor for additional information. */ public ArrayConfigPanel(Field field, Class<?> cl, Object obj, ALDParameterDescriptor descr) { this.arrayClass = cl; this.arrayField = field; this.arrayDescriptor = descr; this.confButton = new JButton("Configure Native Array..."); this.confButton.setActionCommand("show"); this.confButton.addActionListener(this); this.resetButton = new JButton("Reset"); this.resetButton.setActionCommand("reset"); this.resetButton.addActionListener(this); this.configPanel = new JPanel(); this.configPanel.add(this.confButton); this.configPanel.add(this.resetButton); if (obj != null) { this.confWin = new ArrayConfigWindow(field, cl, obj, descr); this.confWin.addValueChangeEventListener(this); } } /** * Gets the data from the configuration window. * * @param field Field of collection. * @param cl Class of collection. * @param value Default object value. */ public void setValue(Field field, Class<?> cl, Object value) { if (this.confWin != null) this.confWin.setValue(field, cl, value); else { this.confWin = new ArrayConfigWindow(field, cl, value, this.arrayDescriptor); this.confWin.addValueChangeEventListener(this); } } /** * Gets the data from the configuration window. * * @param field Field of collection. * @param cl Class of collection. * @return Current data. * @throws ALDDataIOProviderException Thrown on read failure. */ public Object readData(Field field, Class<?> cl) throws ALDDataIOProviderException { if (this.confWin == null) return null; return this.confWin.readData(field, cl); } /* (non-Javadoc) * @see de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponent#getJComponent() */ @Override public JComponent getJComponent() { return this.configPanel; } /* (non-Javadoc) * @see de.unihalle.informatik.Alida.dataio.provider.swing.events.ALDSwingValueChangeListener#handleValueChangeEvent(de.unihalle.informatik.Alida.dataio.provider.swing.events.ALDSwingValueChangeEvent) */ @Override public void handleValueChangeEvent(ALDSwingValueChangeEvent event) { this.fireALDSwingValueChangeEvent(event); } /* (non-Javadoc) * @see de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponent#disableComponent() */ @Override public void disableComponent() { if (this.confWin != null) this.confWin.disableComponent(); } /* (non-Javadoc) * @see de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponent#enableComponent() */ @Override public void enableComponent() { if (this.confWin != null) this.confWin.enableComponent(); } /** * Disposes all resources of this window. */ /* (non-Javadoc) * @see de.unihalle.informatik.Alida.dataio.provider.swing.components.ALDSwingComponent#dispose() */ @Override public void dispose() { if (this.confWin != null) this.confWin.dispose(); } @Override public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); if (cmd.equals("reset")) { if (this.confWin != null) this.confWin.dispose(); this.confWin = null; this.handleValueChangeEvent( new ALDSwingValueChangeEvent(this, this.arrayDescriptor)); } else if (cmd.equals("show")) { if (this.confWin != null) this.confWin.setVisible(true); else { this.confWin = new ArrayConfigWindow(this.arrayField, this.arrayClass, null, this.arrayDescriptor); this.confWin.addValueChangeEventListener(this); this.confWin.setVisible(true); this.handleValueChangeEvent( new ALDSwingValueChangeEvent(this, this.arrayDescriptor)); } } } } /** * GUI element for displaying 2D arrays. * * @author moeller */ private class ArrayShowButton extends JButton implements ActionListener{ /** * Data to be displayed. */ private Object data; /** * Optional descriptor for additional information on parameter. */ private ALDParameterDescriptor descriptor; /** * Constructor. * @param obj Object associated with this button/window. * @param descr Optional descriptor for additional information. */ public ArrayShowButton(Object obj, ALDParameterDescriptor descr) { super("Show data..."); this.setActionCommand("showButtonPressed"); this.addActionListener(this); this.data = obj; this.descriptor = descr; } /* (non-Javadoc) * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ @Override public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); if (cmd.equals("showButtonPressed")) { Class<?> cl = this.data.getClass(); DefaultTableModel outTabModel = null; if (cl.equals(Boolean[][].class)) { Boolean [][] field = (Boolean[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(field[h][w], h, w); } } } else if (cl.equals(Byte[][].class)) { Byte [][] field = (Byte[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(field[h][w], h, w); } } } else if (cl.equals(Double[][].class)) { Double [][] field = (Double[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(field[h][w], h, w); } } } else if (cl.equals(Float[][].class)) { Float [][] field = (Float[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(field[h][w], h, w); } } } else if (cl.equals(Integer[][].class)) { Integer [][] field = (Integer[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(field[h][w], h, w); } } } else if (cl.equals(Short[][].class)) { Short [][] field = (Short[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(field[h][w], h, w); } } } else if (cl.equals(String[][].class)) { String [][] field = (String[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(field[h][w], h, w); } } } else if (cl.equals(boolean[][].class)) { boolean [][] field = (boolean[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(new Boolean(field[h][w]), h, w); } } } else if (cl.equals(byte[][].class)) { byte [][] field = (byte[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(new Byte(field[h][w]), h, w); } } } else if (cl.equals(double[][].class)) { double [][] field = (double[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(new Double(field[h][w]), h, w); } } } else if (cl.equals(float[][].class)) { float [][] field = (float[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(new Float(field[h][w]), h, w); } } } else if (cl.equals(int[][].class)) { int [][] field = (int[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(new Integer(field[h][w]), h, w); } } } else if (cl.equals(short[][].class)) { short [][] field = (short[][])this.data; int height = field.length; int width = field[0].length; outTabModel = new DefaultTableModel(height, width) { @Override public boolean isCellEditable(int row, int column) { return false; }}; for (int h=0;h<height;++h) { for (int w=0;w<width;++w) { outTabModel.setValueAt(new Short(field[h][w]), h, w); } } } ALDTableWindow tabWin = new ALDTableWindow(outTabModel, this.data); String paramName = "<unknown>"; if (this.descriptor != null) paramName = "<" + this.descriptor.getLabel() + ">"; tabWin.setTitle("Result data (" + cl.getSimpleName() + ") for parameter " + paramName); tabWin.setSaveHeaders(false); tabWin.openWindow(); } } } /** * Graphical user interface window for displaying * objects of class {@link DefaultTableModel}. * * @author moeller */ private class ArrayConfigWindow extends ALDSwingValueChangeReporter implements ActionListener, TableModelListener { /** * Main window. */ private JFrame window; /** * Data table (swing tables are nicer than imageJ tables). */ protected JTable dataTab; /** * Reference object to the data. */ private DefaultTableModel dataTabModel; /** * Table component in window. */ private JPanel tabPanel; /** * Button for adding a column. */ private JButton addCol; /** * Button for adding a row. */ private JButton addRow; /** * Button for deleting a column. */ private JButton delCol; /** * Button for deleting a row. */ private JButton delRow; /** * Button to save the table. */ private JButton tabSave; /** * Button to load a table. */ private JButton tabLoad; /** * Button to clear the table. */ private JButton tabClear; /** * Scrollpane for table panel; */ private JScrollPane tableScroller; /** * For convenience: always open last directory for saving. */ private File lastDir; /** * Class of objects to be filled in the table. */ private Class<?> entryClass; /** * Optional descriptor for additional information on parameter. */ protected ALDParameterDescriptor descriptor; /** * List of currently specified values (to restore entry if check * fails). */ private Object[][] entryRefList; /** * Flag to indicate the table window has the focus. * <p> * By this multiple warnings on the same issue should be avoided. * They might happen due to table change events and focus change * events being triggered at the same time. */ protected boolean windowHasFocus = false; /** * Default constructor. * @param field Field of array. * @param cl Class of array elements. * @param obj Default object value. * @param descr Descriptor associated with parameter. */ public ArrayConfigWindow(Field field, Class<?> cl, Object obj, ALDParameterDescriptor descr) { // instantiate the configuration window this.window = new JFrame(); // remember object class this.entryClass = cl; // init dummy table... is overwritten if obj != null this.dataTabModel= new DefaultTableModel(1, 1); this.dataTabModel.addTableModelListener(this); this.entryRefList = new Object[1][1]; // store additional descriptor this.descriptor = descr; // init current directory with user directory this.lastDir= new File(System.getProperty("user.dir")); // build table window this.setupTable(); // if available, fill table with default values if (obj != null) this.setValue(field, cl, obj); // init table with the datatypes's default values else { for (int r = 0; r < this.dataTabModel.getRowCount(); ++r) for (int c = 0; c < this.dataTabModel.getColumnCount(); ++c) this.setTabEntryToDefault(r, c, cl); this.dataTabModel.addTableModelListener(this); this.dataTab.setModel(this.dataTabModel); this.tabPanel.updateUI(); } } /** * Show or hide the configuration window. * @param b If true, window is displayed, otherwise it is hidden. */ public void setVisible(boolean b) { this.window.setVisible(b); } /** * Disable table and buttons to prohibit value changes. */ public void disableComponent() { if (this.dataTab != null) this.dataTab.setEnabled(false); if (this.addCol != null) this.addCol.setEnabled(false); if (this.addRow != null) this.addRow.setEnabled(false); if (this.delCol != null) this.delCol.setEnabled(false); if (this.delRow != null) this.delRow.setEnabled(false); if (this.tabClear != null) this.tabClear.setEnabled(false); } /** * Enable table and buttons to allow for value changes. */ public void enableComponent() { if (this.dataTab != null) this.dataTab.setEnabled(true); if (this.addCol != null) this.addCol.setEnabled(true); if (this.addRow != null) this.addRow.setEnabled(true); if (this.delCol != null) this.delCol.setEnabled(true); if (this.delRow != null) this.delRow.setEnabled(true); if (this.tabClear != null) this.tabClear.setEnabled(true); } /** * Disposes all resources of this window. */ public void dispose() { this.window.dispose(); } /** * Sets the specified table entry to the class default. * @param row Row index. * @param col Column index. * @param cl Class of table elements. */ protected void setTabEntryToDefault(int row, int col, Class<?> cl) { if (cl.equals(boolean[][].class)) { boolean tmpBool = false; this.dataTabModel.setValueAt(Boolean.toString(tmpBool),row,col); } else if (cl.equals(byte[][].class)) { byte tmpByte = 0; this.dataTabModel.setValueAt(Byte.toString(tmpByte), row, col); } else if (cl.equals(double[][].class)) { double tmpDouble = 0; this.dataTabModel.setValueAt(Double.toString(tmpDouble),row,col); } else if (cl.equals(float[][].class)) { float tmpFloat = 0; this.dataTabModel.setValueAt(Float.toString(tmpFloat), row, col); } else if (cl.equals(int[][].class)) { int tmpInt = 0; this.dataTabModel.setValueAt(Integer.toString(tmpInt), row, col); } else if (cl.equals(short[][].class)) { short tmpShort = 0; this.dataTabModel.setValueAt(Short.toString(tmpShort), row, col); } else if (cl.equals(Boolean[][].class)) { Boolean tmpBool = new Boolean(false); this.dataTabModel.setValueAt(tmpBool.toString(), row, col); } else if (cl.equals(Byte[][].class)) { Byte tmpByte = new Byte((byte)0); this.dataTabModel.setValueAt(tmpByte.toString(), row, col); } else if (cl.equals(Double[][].class)) { Double tmpDouble = new Double(0); this.dataTabModel.setValueAt(tmpDouble.toString(), row, col); } else if (cl.equals(Float[][].class)) { Float tmpFloat = new Float(0); this.dataTabModel.setValueAt(tmpFloat.toString(), row, col); } else if (cl.equals(Integer[][].class)) { Integer tmpInt = new Integer(0); this.dataTabModel.setValueAt(tmpInt.toString(), row, col); } else if (cl.equals(Short[][].class)) { Short tmpShort = new Short((short)0); this.dataTabModel.setValueAt(tmpShort.toString(), row, col); } else if (cl.equals(String[][].class)) { this.dataTabModel.setValueAt(new String(), row, col); } // store the value for later value checking this.entryRefList[row][col] = this.dataTabModel.getValueAt(row,col); } /** * Set value of parameter in GUI element. * @param field Field of parameter. * @param cl Class of parameter. * @param value Value to be set in GUI. */ public void setValue(@SuppressWarnings("unused") Field field, Class<?> cl, Object value) { // nothing to be done if value is null if (value == null) return; if ( cl.equals(Boolean[][].class) || cl.equals(Byte[][].class) || cl.equals(Double[][].class) || cl.equals(Float[][].class) || cl.equals(Integer[][].class) || cl.equals(Short[][].class) || cl.equals(String[][].class)) { Object [][] array = (Object[][])value; int rows = array.length; int cols = array[0].length; this.dataTabModel = new DefaultTableModel(rows,cols); this.entryRefList = new Object[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { Object val = array[r][c]; String entry = new String(); if (val != null) entry = val.toString(); this.dataTabModel.setValueAt(entry, r, c); this.entryRefList[r][c] = this.dataTabModel.getValueAt(r,c); } } } else if (cl.equals(boolean[][].class)) { boolean [][] array = (boolean[][])value; int rows = array.length; int cols = array[0].length; this.dataTabModel = new DefaultTableModel(rows,cols); this.entryRefList = new Object[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { this.dataTabModel.setValueAt(Boolean.toString(array[r][c]), r, c); this.entryRefList[r][c] = this.dataTabModel.getValueAt(r,c); } } } else if (cl.equals(byte[][].class)) { byte [][] array = (byte[][])value; int rows = array.length; int cols = array[0].length; this.dataTabModel = new DefaultTableModel(rows,cols); this.entryRefList = new Object[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { this.dataTabModel.setValueAt(Byte.toString(array[r][c]), r, c); this.entryRefList[r][c] = this.dataTabModel.getValueAt(r,c); } } } else if (cl.equals(double[][].class)) { double [][] array = (double[][])value; int rows = array.length; int cols = array[0].length; this.dataTabModel = new DefaultTableModel(rows,cols); this.entryRefList = new Object[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { this.dataTabModel.setValueAt(Double.toString(array[r][c]), r, c); this.entryRefList[r][c] = this.dataTabModel.getValueAt(r,c); } } } else if (cl.equals(float[][].class)) { float [][] array = (float[][])value; int rows = array.length; int cols = array[0].length; this.dataTabModel = new DefaultTableModel(rows,cols); this.entryRefList = new Object[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { this.dataTabModel.setValueAt(Float.toString(array[r][c]), r, c); this.entryRefList[r][c] = this.dataTabModel.getValueAt(r,c); } } } else if (cl.equals(int[][].class)) { int [][] array = (int[][])value; int rows = array.length; int cols = array[0].length; this.dataTabModel = new DefaultTableModel(rows,cols); this.entryRefList = new Object[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { this.dataTabModel.setValueAt(Integer.toString(array[r][c]), r, c); this.entryRefList[r][c] = this.dataTabModel.getValueAt(r,c); } } } else if (cl.equals(short[][].class)) { short [][] array = (short[][])value; int rows = array.length; int cols = array[0].length; this.dataTabModel = new DefaultTableModel(rows,cols); this.entryRefList = new Object[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { this.dataTabModel.setValueAt(Short.toString(array[r][c]), r, c); this.entryRefList[r][c] = this.dataTabModel.getValueAt(r,c); } } } // update the view this.dataTabModel.addTableModelListener(this); this.dataTab.setModel(this.dataTabModel); this.tabPanel.updateUI(); } /** * Read parameter value from graphical user interface. * @param field Field of parameter to be read. * @param cl Class of parameter to be read. * @return Value of parameter in GUI. * @throws ALDDataIOProviderException Thrown in case of read failures. */ @SuppressWarnings({ "unchecked" }) public Object readData(@SuppressWarnings("unused") Field field, Class<?> cl) throws ALDDataIOProviderException { // this.dataTab.editingStopped(null); // this.dataTabModel.fireTableDataChanged(); // check if there is already data to check if (this.dataTabModel == null) return null; // list for collecting errors LinkedList<int[]> errors = new LinkedList<int[]>(); // read data Vector<Object> data = this.dataTabModel.getDataVector(); int rows = data.size(); int cols = ((Vector<Object>)(data.elementAt(0))).size(); Object entry; if (cl.equals(Boolean[][].class)) { Boolean [][] tmpfield = new Boolean[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Boolean.valueOf((String)(entry)) : null; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(Byte[][].class)) { Byte [][] tmpfield = new Byte[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Byte.valueOf((String)(entry)) : null; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(Double[][].class)) { Double [][] tmpfield = new Double[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Double.valueOf((String)(entry)) : null; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(Float[][].class)) { Float [][] tmpfield = new Float[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Float.valueOf((String)(entry)) : null; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(Integer[][].class)) { Integer [][] tmpfield = new Integer[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Integer.valueOf((String)(entry)) : null; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(Short[][].class)) { Short [][] tmpfield = new Short[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Short.valueOf((String)(entry)) : null; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(String[][].class)) { String [][] tmpfield = new String[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null) // || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { // tmpfield[r][c] = (entry != null) ? (String)entry : null; tmpfield[r][c] = (String)entry; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(boolean[][].class)) { boolean [][] tmpfield = new boolean[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Boolean.valueOf((String)(entry)).booleanValue():false; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(byte[][].class)) { byte [][] tmpfield = new byte[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Byte.valueOf((String)(entry)).byteValue() : 0; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(double[][].class)) { double [][] tmpfield = new double[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Double.valueOf((String)(entry)).doubleValue() : 0.0; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(float[][].class)) { float [][] tmpfield = new float[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Float.valueOf((String)(entry)).floatValue() : 0; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(int[][].class)) { int [][] tmpfield = new int[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Integer.valueOf((String)(entry)).intValue() : 0; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } if (cl.equals(short[][].class)) { short [][] tmpfield = new short[rows][cols]; for (int r=0;r<rows;++r) { for (int c=0;c<cols;++c) { entry = ((Vector<Object>)data.elementAt(r)).elementAt(c); if (entry == null || ((String)entry).isEmpty()) errors.add(new int[]{r,c}); try { tmpfield[r][c] = (entry != null) ? Short.valueOf((String)(entry)).shortValue() : 0; } catch (NumberFormatException ne) { errors.add(new int[]{r,c}); } } } if (errors.size() > 0) this.errorListToMessage(errors); return tmpfield; } return null; } /** * Method to resize the reference entry list. * <p> * Existing entries are preserved as far as possible. * @param newRows New number of rows for the table. * @param newCols New number of cols for the table. */ protected void resizeTableEntries(int newRows, int newCols) { Object[][] newEntries = new Object[newRows][newCols]; int commonRows = (newRows > this.entryRefList.length ? this.entryRefList.length : newRows); int commonCols; for (int r=0;r<commonRows;++r) { commonCols = (newCols > this.entryRefList[r].length ? this.entryRefList[r].length : newCols); for (int c=0;c<commonCols;++c) { newEntries[r][c] = this.entryRefList[r][c]; } } this.entryRefList = newEntries; } /** * Checks if a string can be cast to the desired class. * @param cl Target class. * @param entry String under consideration. * @return True if cast is possible. */ @SuppressWarnings({ "unused" }) protected boolean validateEntry(Class<?> cl, String entry) { if (cl.equals(String[][].class)) { return true; } if (entry == null || entry.isEmpty()) return false; if (cl.equals(Boolean[][].class)) { try { Boolean t = Boolean.valueOf((entry)); } catch (NumberFormatException ne) { return false; } } if (cl.equals(Byte[][].class)) { try { Byte t = Byte.valueOf((entry)); } catch (NumberFormatException ne) { return false; } } if (cl.equals(Double[][].class)) { try { Double t = Double.valueOf((entry)); } catch (NumberFormatException ne) { return false; } } if (cl.equals(Float[][].class)) { try { Float t = Float.valueOf((entry)); } catch (NumberFormatException ne) { return false; } } if (cl.equals(Integer[][].class)) { try { Integer t = Integer.valueOf((entry)); } catch (NumberFormatException ne) { return false; } } if (cl.equals(Short[][].class)) { try { Short t = Short.valueOf((entry)); } catch (NumberFormatException ne) { return false; } } if (cl.equals(boolean[][].class)) { try { boolean t = Boolean.valueOf((entry)).booleanValue(); } catch (NumberFormatException ne) { return false; } } if (cl.equals(byte[][].class)) { try { byte t = Byte.valueOf((entry)).byteValue(); } catch (NumberFormatException ne) { return false; } } if (cl.equals(double[][].class)) { try { double t = Double.valueOf((entry)).doubleValue(); } catch (NumberFormatException ne) { return false; } } if (cl.equals(float[][].class)) { try { float t = Float.valueOf((entry)).floatValue(); } catch (NumberFormatException ne) { return false; } } if (cl.equals(int[][].class)) { try { int t = Integer.valueOf((entry)).intValue(); } catch (NumberFormatException ne) { return false; } } if (cl.equals(short[][].class)) { try { short t = Short.valueOf((entry)).shortValue(); } catch (NumberFormatException ne) { return false; } } return true; } /** * Saves the contents of the table to a user-specified file. * <p> * The file format is TSV, i.e. tabulator-separated values. * The default ending is '.txt'. The user can select the file * name through a file open dialog which pops-up on call of the * function. */ protected void saveTable() { File file= null; JFrame dummy= new JFrame(); JFileChooser getSaveFileDialog= new JFileChooser(); getSaveFileDialog.setFileFilter(new DataTabFileFilter()); getSaveFileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY); getSaveFileDialog.setCurrentDirectory(this.lastDir); getSaveFileDialog.setSelectedFile(new File("ResultTab.txt")); getSaveFileDialog.setApproveButtonText("Speichern"); getSaveFileDialog.setDialogTitle("Select file name"); int returnVal = getSaveFileDialog.showOpenDialog(dummy); if (returnVal == JFileChooser.APPROVE_OPTION) { file = getSaveFileDialog.getSelectedFile(); this.lastDir= getSaveFileDialog.getCurrentDirectory(); } // obviously we did not get any name, can't do anything... if (file== null) return; // ... otherwise write table to selected file try{ if (file.exists()) { int ret= JOptionPane.showConfirmDialog(null, "The file exists already, " + "would you like to overwrite it?", "Warning", JOptionPane.YES_NO_OPTION); switch(ret) { case JOptionPane.NO_OPTION: case JOptionPane.CANCEL_OPTION: return; case JOptionPane.YES_OPTION: // nothing special to do, just proceed } } FileWriter ow = new FileWriter(file.getPath()); StringBuffer [] tab = ALDTableWindow.tableToString(this.dataTabModel); // note: first row contains the header which is meaningless in // this context, therefore it is ignored System.out.println(tab[0].toString()); for (int i=1;i<tab.length;++i) { ow.write(tab[i].toString()); } ow.close(); } catch (IOException e) { JOptionPane.showMessageDialog(null,"Error!!! " + "Could not open output file " + file.getPath() + "!"); } } /** * Loads contents of the table from a user-specified file. * <p> * The file format is TSV, i.e. tabulator-separated values. * The default ending is '.txt'. The user can select the file * name through a file open dialog which pops-up on call of the * function. */ protected void loadTable() { // request the file from the user File file= null; JFrame dummy= new JFrame(); JFileChooser getSaveFileDialog= new JFileChooser(); getSaveFileDialog.setFileFilter(new DataTabFileFilter()); getSaveFileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY); getSaveFileDialog.setCurrentDirectory(this.lastDir); getSaveFileDialog.setSelectedFile(new File("ResultTab.txt")); getSaveFileDialog.setApproveButtonText("Open"); getSaveFileDialog.setDialogTitle("Select file name"); int returnVal = getSaveFileDialog.showOpenDialog(dummy); if (returnVal == JFileChooser.APPROVE_OPTION) { file = getSaveFileDialog.getSelectedFile(); this.lastDir= getSaveFileDialog.getCurrentDirectory(); } // obviously we did not get any name, can't do anything... if (file== null) return; // ... otherwise load table from selected file try{ if (!file.exists()) { JOptionPane.showMessageDialog(null, "The file does not exist!", "Error reading file!", JOptionPane.ERROR_MESSAGE); return; } FileInputStream fis = new FileInputStream(file.getPath()); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); Vector<String[]> entries = new Vector<String[]>(); String line = br.readLine(); while( line != null ) { entries.add(line.split("\t")); line = br.readLine(); } int colNum = entries.elementAt(0).length; Class<?> cl = this.entryClass; if ( cl.equals(Boolean[][].class) || cl.equals(Byte[][].class) || cl.equals(Double[][].class) || cl.equals(Float[][].class) || cl.equals(Integer[][].class) || cl.equals(Short[][].class) || cl.equals(String[][].class)) { Object[][] tableData = new Object[entries.size()][colNum]; for (int i=0;i<entries.size(); ++i) { for (int j=0;j<colNum; ++j) { tableData[i][j] = entries.elementAt(i)[j]; } } this.setValue(null, this.entryClass, tableData); } else if (cl.equals(boolean[][].class)) { boolean[][] tableData = new boolean[entries.size()][colNum]; for (int i=0;i<entries.size(); ++i) { for (int j=0;j<colNum; ++j) { tableData[i][j] = new Boolean(entries.elementAt(i)[j]).booleanValue(); } } this.setValue(null, this.entryClass, tableData); } else if (cl.equals(byte[][].class)) { byte[][] tableData = new byte[entries.size()][colNum]; for (int i=0;i<entries.size(); ++i) { for (int j=0;j<colNum; ++j) { tableData[i][j] = new Byte(entries.elementAt(i)[j]).byteValue(); } } this.setValue(null, this.entryClass, tableData); } else if (cl.equals(double[][].class)) { double [][] tableData = new double[entries.size()][colNum]; for (int i=0;i<entries.size(); ++i) { for (int j=0;j<colNum; ++j) { tableData[i][j] = new Double(entries.elementAt(i)[j]).doubleValue(); } } this.setValue(null, this.entryClass, tableData); } else if (cl.equals(float[][].class)) { float[][] tableData = new float[entries.size()][colNum]; for (int i=0;i<entries.size(); ++i) { for (int j=0;j<colNum; ++j) { tableData[i][j] = new Float(entries.elementAt(i)[j]).floatValue(); } } this.setValue(null, this.entryClass, tableData); } else if (cl.equals(int[][].class)) { int[][] tableData = new int[entries.size()][colNum]; for (int i=0;i<entries.size(); ++i) { for (int j=0;j<colNum; ++j) { tableData[i][j] = new Integer(entries.elementAt(i)[j]).intValue(); } } this.setValue(null, this.entryClass, tableData); } else if (cl.equals(short[][].class)) { short[][] tableData = new short[entries.size()][colNum]; for (int i=0;i<entries.size(); ++i) { for (int j=0;j<colNum; ++j) { tableData[i][j] = new Short(entries.elementAt(i)[j]).shortValue(); } } this.setValue(null, this.entryClass, tableData); } br.close(); } catch (IOException e) { JOptionPane.showMessageDialog(null,"Error!!! " + "Could not open input file " + file.getPath() + "!"); e.printStackTrace(); } } /** * Initializes the data table window. */ private void setupTable() { // instantiate result table and put into scroll pane this.dataTab= new JTable(this.dataTabModel); this.dataTab.addFocusListener(new TableFocusListener()); this.tableScroller= new JScrollPane(this.dataTab); this.tableScroller.setPreferredSize(new Dimension (400,300)); this.dataTab.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); // add a toolbar this.addCol= new JButton("Add Column"); this.addCol.setActionCommand("addCol"); this.addCol.addActionListener(this); this.addCol.setSize(new Dimension(80,35)); this.addCol.setToolTipText("Appends a column to the table."); this.addRow= new JButton("Add Row"); this.addRow.setActionCommand("addRow"); this.addRow.addActionListener(this); this.addRow.setSize(new Dimension(80,35)); this.addRow.setToolTipText("Appends a row to the table."); this.delCol= new JButton("Delete Last Column"); this.delCol.setActionCommand("delCol"); this.delCol.addActionListener(this); this.delCol.setSize(new Dimension(80,35)); this.delCol.setToolTipText("Deletes the last column."); this.delRow= new JButton("Delete Row"); this.delRow.setActionCommand("delRow"); this.delRow.setToolTipText("Deletes selected row(s) or last " + "one if nothing is selected."); this.delRow.addActionListener(this); this.delRow.setSize(new Dimension(80,35)); this.tabSave= new JButton("Save"); this.tabSave.setActionCommand("save"); this.tabSave.addActionListener(this); this.tabSave.setSize(new Dimension(80,35)); this.tabSave.setToolTipText("Saves current table to file."); this.tabLoad= new JButton("Load"); this.tabLoad.setActionCommand("load"); this.tabLoad.addActionListener(this); this.tabLoad.setSize(new Dimension(80,35)); this.tabLoad.setToolTipText("Loads table from file."); this.tabClear= new JButton("Clear"); this.tabClear.setActionCommand("clear"); this.tabClear.addActionListener(this); this.tabClear.setSize(new Dimension(80,35)); this.tabClear.setToolTipText("Resets table to default entries."); JButton tabClose= new JButton("Close"); tabClose.setActionCommand("close"); tabClose.addActionListener(this); tabClose.setSize(new Dimension(80,35)); JPanel tabToolPanel= new JPanel(); tabToolPanel.setLayout(new FlowLayout()); tabToolPanel.add(this.addCol); tabToolPanel.add(this.addRow); tabToolPanel.add(this.delCol); tabToolPanel.add(this.delRow); tabToolPanel.add(this.tabSave); tabToolPanel.add(this.tabLoad); tabToolPanel.add(this.tabClear); tabToolPanel.add(tabClose); JToolBar tabTools= new JToolBar(""); tabTools.add(tabToolPanel); this.tabPanel= new JPanel(); this.tabPanel.setLayout(new BorderLayout()); this.tabPanel.add(this.tableScroller, BorderLayout.CENTER); this.tabPanel.add(tabTools, BorderLayout.SOUTH); this.window.setSize(900, 250); String paramName = "<unknown>"; if (this.descriptor != null) paramName = "<" + this.descriptor.getLabel() + ">"; this.window.setTitle("Array data (" + this.entryClass.getSimpleName() + ") for parameter " + paramName); this.window.add(this.tabPanel); // ... then show it! this.window.setVisible(false); } /** * Error function displaying an error message box. * @param errorList List of errors. * @throws ALDDataIOProviderException * Thrown in case of processing errors. */ private void errorListToMessage(LinkedList<int[]> errorList) throws ALDDataIOProviderException { // Object[] options = { "OK" }; // JOptionPane.showOptionDialog(null, // "Attention! Java Swing/Awt problem, some of your inputs \n" + // "may not have been saved correctly - please check again!\n"+ // "Table entry at position ( " + r + " , " + c + " )" + // " is null! Returning null object...", "Warning", // JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, // null, options, options[0]); StringBuffer errMsg = new StringBuffer(); errMsg.append("Errors in table (indices = row , col):\n"); for (int[] ee: errorList) { errMsg.append("Invalid entry at " + ee[0]+ ", " + ee[1]+ ".\n"); } throw new ALDDataIOProviderException( ALDDataIOProviderExceptionType.SYNTAX_ERROR, errMsg.toString()); } /* (non-Javadoc) * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ @Override public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); // deletes all data from the table and sets row and column counts to zero if (e.getActionCommand().equals("clear")) { for (int i=0;i<this.dataTabModel.getRowCount();++i) { for (int j=0;j<this.dataTabModel.getColumnCount();++j) { this.setTabEntryToDefault(i, j, this.entryClass); this.entryRefList[i][j] = this.dataTabModel.getValueAt(i, j); } } } // closes the GUI window if (e.getActionCommand().equals("close")) { // this.dataTab.editingStopped(null); // this.dataTabModel.fireTableDataChanged(); this.window.setVisible(false); } // saves the table data in TSV format if (e.getActionCommand().equals("save")) { this.saveTable(); } // load table data from file in TSV format else if (e.getActionCommand().equals("load")) { this.loadTable(); this.fireALDSwingValueChangeEvent( new ALDSwingValueChangeEvent(this, this.descriptor)); } // add a column if (command.equals("addCol")) { this.dataTabModel.addColumn(null); this.resizeTableEntries(this.dataTabModel.getRowCount(), this.dataTabModel.getColumnCount()); for (int j=0;j<this.dataTabModel.getRowCount();++j) this.setTabEntryToDefault(j, this.dataTabModel.getColumnCount()-1, this.entryClass); this.fireALDSwingValueChangeEvent( new ALDSwingValueChangeEvent(this, this.descriptor)); } // add a row if (command.equals("addRow")) { this.dataTabModel.addRow(new Vector<Object>()); this.resizeTableEntries(this.dataTabModel.getRowCount(), this.dataTabModel.getColumnCount()); for (int j=0;j<this.dataTabModel.getColumnCount();++j) this.setTabEntryToDefault(this.dataTabModel.getRowCount()-1, j, this.entryClass); this.fireALDSwingValueChangeEvent( new ALDSwingValueChangeEvent(this, this.descriptor)); } // delete column if (command.equals("delCol")) { if (this.dataTabModel.getColumnCount() == 1) return; this.dataTabModel.setColumnCount( this.dataTabModel.getColumnCount()-1); this.resizeTableEntries(this.dataTabModel.getRowCount(), this.dataTabModel.getColumnCount()); this.fireALDSwingValueChangeEvent( new ALDSwingValueChangeEvent(this, this.descriptor)); } // delete row if (command.equals("delRow")) { if (this.dataTabModel.getRowCount() == 1) return; // get and remove all selected rows int [] selectedRows = this.dataTab.getSelectedRows(); if (selectedRows.length == 0) { this.dataTabModel.removeRow(this.dataTabModel.getRowCount()-1); this.resizeTableEntries(this.dataTabModel.getRowCount(), this.dataTabModel.getColumnCount()); this.fireALDSwingValueChangeEvent( new ALDSwingValueChangeEvent(this, this.descriptor)); return; } for (int c = 0; c < selectedRows.length; ++c) this.dataTabModel.removeRow(this.dataTabModel.getRowCount()-1); // update the reference entry table and reset correct values // in table int newSize = this.dataTabModel.getRowCount(); Object[][] newEntries = new Object[newSize][this.dataTabModel.getColumnCount()]; int newIndex = 0; for (int i=0;i<this.entryRefList.length;++i) { // check if row was deleted int r = 0; for (r = 0; r<selectedRows.length; r++) { if (i == selectedRows[r]) { break; } } if (r == selectedRows.length) { for (int c = 0; c<this.dataTabModel.getColumnCount(); ++c) { this.dataTabModel.setValueAt(this.entryRefList[i][c], newIndex, c); newEntries[newIndex][c] = this.entryRefList[i][c]; } ++newIndex; } } this.entryRefList = newEntries; this.dataTab.clearSelection(); this.fireALDSwingValueChangeEvent( new ALDSwingValueChangeEvent(this, this.descriptor)); } } @SuppressWarnings("unchecked") @Override public void tableChanged(TableModelEvent e) { if (!this.windowHasFocus) return; int r = e.getFirstRow(); int c = e.getColumn(); Vector<Object> data = this.dataTabModel.getDataVector(); int rows = data.size(); int cols = ((Vector<Object>)(data.elementAt(0))).size(); if (r < 0 || c < 0 || r >= rows || c >= cols) return; String entry = (String)((Vector<Object>)data.elementAt(r)).elementAt(c); if (this.validateEntry(this.entryClass, entry)) this.fireALDSwingValueChangeEvent( new ALDSwingValueChangeEvent(this, this.descriptor)); else { ProviderInteractionLevel plevel = ALDDataIOManagerSwing.getInstance(). getProviderInteractionLevel(); if ( plevel.equals(ProviderInteractionLevel.ALL_ALLOWED) || plevel.equals(ProviderInteractionLevel.WARNINGS_ONLY)) { JOptionPane.showOptionDialog(null, "Attention! You just entered an invalid value!\n" + "The table entry at position ( " + r + " , " + c + " )" + " cannot be cast to class " + this.entryClass.getComponentType().getComponentType() + "!", "Warning - invalid value", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, new Object[]{"OK"}, "OK"); } // reset table to old value this.dataTabModel.setValueAt(this.entryRefList[r][c], r, c); } this.entryRefList[r][c] = this.dataTabModel.getValueAt(r, c); this.fireALDSwingValueChangeEvent( new ALDSwingValueChangeEvent(this, this.descriptor)); } /** * Internal class that realizes a FileFilter for text * files where MiToBo table data is stored. * * @author moeller */ protected class DataTabFileFilter extends FileFilter { /* (non-Javadoc) * @see javax.swing.filechooser.FileFilter#accept(java.io.File) */ @Override public boolean accept(File f) { return (f.getName().endsWith(".txt") || f.isDirectory()); } /* (non-Javadoc) * @see javax.swing.filechooser.FileFilter#getDescription() */ @Override public String getDescription() { return "MiToBo Data Table Files (*.txt)"; } } /** * Focus listener to commit edits if table looses the focus. * @author moeller */ protected class TableFocusListener implements FocusListener { @Override public void focusGained(FocusEvent e) { ArrayConfigWindow.this.windowHasFocus = true; } @Override public void focusLost(FocusEvent e) { ArrayConfigWindow.this.windowHasFocus = false; if ( ArrayConfigWindow.this.dataTab == null || ArrayConfigWindow.this.dataTab.getCellEditor() == null) return; ArrayConfigWindow.this.dataTab.getCellEditor().stopCellEditing(); ArrayConfigWindow.this.fireALDSwingValueChangeEvent( new ALDSwingValueChangeEvent(this, ArrayConfigWindow.this.descriptor)); } } } }