/*
* Copyright (C) 2011 Peransin Nicolas.
* Use is subject to license terms.
*/
package org.mypsycho.swing.table;
import java.awt.Color;
import java.awt.Component;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;
/**
* The Editor does not rely on TableModel to fetch the class of the cell.
* The TableModel can only provide 1 class for 1 column.
*
* The expected class is provided by a constructor of class or a static getter.
*
* @author Peransin Nicolas
*/
public class GenericEditor extends DefaultCellEditor {
private static final long serialVersionUID = 3668933684480176108L;
private static final Class<?>[] argTypes = new Class[]{ String.class };
Constructor<?> constructor = null;
Method getter = null;
Object value;
public GenericEditor(Class<?> valueClass) {
this();
try {
if (constructor.getDeclaringClass() == String.class) {
constructor = valueClass.getConstructor(argTypes);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public GenericEditor(Class<?> valueClass, String staticMethod) {
this();
try {
getter = valueClass.getMethod(staticMethod, argTypes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private GenericEditor() {
super(new JTextField());
getComponent().setName("Table.editor");
}
public boolean stopCellEditing() {
String s = (String)super.getCellEditorValue();
// Here we are dealing with the case where a user
// has deleted the string value in a cell, possibly
// after a failed validation. Return null, so that
// they have the option to replace the value with
// null or use escape to restore the original.
// For Strings, return "" for backward compatibility.
if ("".equals(s)) {
if ((constructor == null) && (getter == null)) {
value = s;
}
super.stopCellEditing();
}
try {
if (constructor != null) {
value = constructor.newInstance(s);
} else {
value = getter.invoke(null, s);
}
} catch (Exception e) {
((JComponent)getComponent()).setBorder(new LineBorder(Color.red));
return false;
}
return super.stopCellEditing();
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected,
int row, int column) {
this.value = null;
((JComponent)getComponent()).setBorder(new LineBorder(Color.black));
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
public Object getCellEditorValue() {
return value;
}
public static class NumberEditor extends GenericEditor {
private static final long serialVersionUID = GenericEditor.serialVersionUID;
public NumberEditor(Class<? extends Number> numberClass) {
super(numberClass);
((JTextField)getComponent()).setHorizontalAlignment(JTextField.RIGHT);
}
}
public static class BooleanEditor extends DefaultCellEditor {
private static final long serialVersionUID = GenericEditor.serialVersionUID;
public BooleanEditor() {
super(new JCheckBox());
JCheckBox checkBox = (JCheckBox)getComponent();
checkBox.setHorizontalAlignment(JCheckBox.CENTER);
}
}
}