/*
* RapidMiner
*
* Copyright (C) 2001-2014 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.gui.properties.celleditors.value;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JPasswordField;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.text.JTextComponent;
import com.rapidminer.gui.properties.DefaultRMCellEditor;
import com.rapidminer.gui.properties.PropertyTable;
import com.rapidminer.gui.tools.CharTextField;
import com.rapidminer.gui.tools.ExtendedJComboBox;
import com.rapidminer.gui.tools.autocomplete.AutoCompleteComboBoxAddition;
import com.rapidminer.operator.Operator;
import com.rapidminer.parameter.ParameterType;
import com.rapidminer.parameter.ParameterTypeBoolean;
import com.rapidminer.parameter.ParameterTypeCategory;
import com.rapidminer.parameter.ParameterTypeChar;
import com.rapidminer.parameter.ParameterTypeDouble;
import com.rapidminer.parameter.ParameterTypeInt;
import com.rapidminer.parameter.ParameterTypePassword;
import com.rapidminer.parameter.ParameterTypeStringCategory;
import com.rapidminer.tools.Tools;
/**
* Editor for parameter values string, int, double, category, and boolean. This can be used in all {@link PropertyTable}s
* to show or editing the properties / parameters. For more special parameter types other solutions exist.
*
* @see FileValueCellEditor
* @see ListValueCellEditor
* @see ColorValueCellEditor
* @see OperatorValueValueCellEditor
* @author Ingo Mierswa, Simon Fischer, Nils Woehler
*/
public class DefaultPropertyValueCellEditor extends DefaultRMCellEditor implements PropertyValueCellEditor {
private static final long serialVersionUID = 3594466409311826645L;
private static final int TEXT_FIELD_WIDTH = 10;
private boolean useEditorAsRenderer = false;
private boolean rendersLabel = false;
public DefaultPropertyValueCellEditor(final ParameterTypeCategory type) {
super(new ExtendedJComboBox(type.getValues()));
useEditorAsRenderer = true;
((JComboBox) editorComponent).removeItemListener(this.delegate);
this.delegate = new EditorDelegate() {
private static final long serialVersionUID = -2104662561680969750L;
@Override
public void setValue(Object x) {
if (x == null) {
super.setValue(null);
((JComboBox) editorComponent).setSelectedIndex(-1);
} else {
try {
Integer index = Integer.valueOf(x.toString());
super.setValue(index);
((JComboBox) editorComponent).setSelectedIndex(index);
} catch (NumberFormatException e) {
// try to get index from string...
int index = type.getIndex(x.toString());
super.setValue(index);
((JComboBox) editorComponent).setSelectedIndex(index);
}
}
}
@Override
public Object getCellEditorValue() {
return ((JComboBox) editorComponent).getSelectedItem();
}
};
((JComboBox) editorComponent).addItemListener(delegate);
}
public DefaultPropertyValueCellEditor(final ParameterTypeStringCategory type) {
super(new JComboBox(type.getValues()));
if (type.isEditable()) {
AutoCompleteComboBoxAddition autoCompleteCBA = new AutoCompleteComboBoxAddition((JComboBox) editorComponent);
autoCompleteCBA.setCaseSensitive(false);
}
final JTextComponent textField = (JTextComponent) ((JComboBox) editorComponent).getEditor().getEditorComponent();
useEditorAsRenderer = true;
((JComboBox) editorComponent).removeItemListener(this.delegate);
((JComboBox) editorComponent).setEditable(type.isEditable());
this.delegate = new EditorDelegate() {
private static final long serialVersionUID = -5592150438626222295L;
@Override
public void setValue(Object x) {
if (x == null) {
super.setValue(null);
((JComboBox) editorComponent).setSelectedItem(null);
} else {
String value = x.toString();
super.setValue(value);
((JComboBox) editorComponent).setSelectedItem(value);
if (value != null) {
textField.setText(value.toString());
} else {
textField.setText("");
}
}
}
@Override
public Object getCellEditorValue() {
if (type.isEditable()) {
String selected = textField.getText();
if ((selected != null) && (selected.trim().length() == 0)) {
selected = null;
}
return selected;
} else {
return ((JComboBox) editorComponent).getSelectedItem();
}
}
};
editorComponent.setToolTipText(type.getDescription());
((JComboBox) editorComponent).addItemListener(delegate);
}
public DefaultPropertyValueCellEditor(final ParameterTypeBoolean type) {
super(new JCheckBox());
rendersLabel = true;
((JCheckBox) editorComponent).setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
((JCheckBox) editorComponent).setText(type.getKey().replace('_', ' '));
if (type.isExpert()) {
editorComponent.setFont(editorComponent.getFont().deriveFont(Font.ITALIC));
}
// editorComponent.setBackground(javax.swing.UIManager.getColor("Table.cellBackground"));
this.delegate = new EditorDelegate() {
private static final long serialVersionUID = 152467444047540403L;
@Override
public void setValue(Object x) {
if (x == null) {
super.setValue(null);
((JCheckBox) editorComponent).setSelected((Boolean) type.getDefaultValue());
} else {
Boolean value = Tools.booleanValue(x.toString(), (Boolean) type.getDefaultValue());
super.setValue(value);
((JCheckBox) editorComponent).setSelected(value);
}
}
@Override
public Object getCellEditorValue() {
return Boolean.valueOf(Tools.booleanValue(Boolean.valueOf(((JCheckBox) editorComponent).isSelected()).toString(), (Boolean) type.getDefaultValue())).toString();
}
};
useEditorAsRenderer = true;
}
public DefaultPropertyValueCellEditor(final ParameterTypeInt type) {
super(new JTextField(TEXT_FIELD_WIDTH));
setClickCountToStart(1);
editorComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {}
@Override
public void focusLost(FocusEvent e) {
if (!e.isTemporary()) {
fireEditingStopped();
}
}
});
((JTextField) editorComponent).setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
// ((JTextField) editorComponent).setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3));
this.delegate = new EditorDelegate() {
private static final long serialVersionUID = 152467444047540403L;
@Override
public void setValue(Object x) {
if (x == null) {
super.setValue(null);
((JTextField) editorComponent).setText(null);
} else {
super.setValue(x.toString());
try {
if (value != null) {
Integer value = Integer.valueOf(x.toString());
((JTextField) editorComponent).setText(value.toString());
} else {
Integer defaultValue = (Integer) type.getDefaultValue();
if (defaultValue != null) {
((JTextField) editorComponent).setText(type.getDefaultValue().toString());
} else {
((JTextField) editorComponent).setText(null);
}
}
} catch (NumberFormatException e) {
String text = x.toString();
// try macro...
if ((text.startsWith("%{")) && (text.endsWith("}"))) {
((JTextField) editorComponent).setText(text);
} else {
// no macro --> set to default
Integer defaultValue = (Integer) type.getDefaultValue();
if (defaultValue != null) {
((JTextField) editorComponent).setText(type.getDefaultValue().toString());
} else {
((JTextField) editorComponent).setText(null);
}
}
}
}
}
@Override
public Object getCellEditorValue() {
String text = ((JTextField) editorComponent).getText();
try {
int i = Integer.parseInt(text);
if (i < type.getMinValue())
i = (int) type.getMinValue();
if (i > type.getMaxValue())
i = (int) type.getMaxValue();
((JTextField) editorComponent).setText(Integer.valueOf(i).toString());
return Integer.valueOf(i).toString();
} catch (NumberFormatException e) {
// try macro...
if ((text.startsWith("%{")) && (text.endsWith("}"))) {
return text;
} else {
// no macro --> set to default
Integer defaultValue = (Integer) type.getDefaultValue();
if (defaultValue != null) {
((JTextField) editorComponent).setText(type.getDefaultValue().toString());
return type.getDefaultValue(); // .toString();
} else {
((JTextField) editorComponent).setText("");
// no default --> return null
return null;
}
}
}
}
};
editorComponent.setToolTipText(type.getDescription() + " (" + type.getRange() + ")");
useEditorAsRenderer = true;
}
public DefaultPropertyValueCellEditor(final ParameterTypeDouble type) {
super(new JTextField(TEXT_FIELD_WIDTH));
setClickCountToStart(1);
editorComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {}
@Override
public void focusLost(FocusEvent e) {
if (!e.isTemporary()) {
fireEditingStopped();
}
}
});
((JTextField) editorComponent).setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
this.delegate = new EditorDelegate() {
private static final long serialVersionUID = 5764937097891322370L;
@Override
public void setValue(Object x) {
if (x == null) {
super.setValue(null);
((JTextField) editorComponent).setText(null);
} else {
super.setValue(x.toString());
try {
if (value != null) {
Double value = Double.valueOf(x.toString());
((JTextField) editorComponent).setText(value.toString());
} else {
Double defaultValue = (Double) type.getDefaultValue();
if (defaultValue != null) {
((JTextField) editorComponent).setText(type.getDefaultValue().toString());
} else {
((JTextField) editorComponent).setText(null);
}
}
} catch (NumberFormatException e) {
String text = x.toString();
// try macro...
if ((text.startsWith("%{")) && (text.endsWith("}"))) {
((JTextField) editorComponent).setText(text);
} else {
// no macro --> set to default
Double defaultValue = (Double) type.getDefaultValue();
if (defaultValue != null) {
((JTextField) editorComponent).setText(type.getDefaultValue().toString());
} else {
((JTextField) editorComponent).setText(null);
}
}
}
}
}
@Override
public Object getCellEditorValue() {
String text = ((JTextField) editorComponent).getText();
try {
double d = Double.parseDouble(text);
if (d < type.getMinValue())
d = type.getMinValue();
if (d > type.getMaxValue())
d = type.getMaxValue();
((JTextField) editorComponent).setText(Double.valueOf(d).toString());
return Double.valueOf(d).toString();
} catch (NumberFormatException e) {
// try macro...
if ((text.startsWith("%{")) && (text.endsWith("}"))) {
return text;
} else {
// no macro --> set to default
Double defaultValue = (Double) type.getDefaultValue();
if (defaultValue != null) {
((JTextField) editorComponent).setText(type.getDefaultValue().toString());
return type.getDefaultValue(); // .toString();
} else {
((JTextField) editorComponent).setText("");
// no default --> return null
return null;
}
}
}
}
};
editorComponent.setToolTipText(type.getDescription() + " (" + type.getRange() + ")");
useEditorAsRenderer = true;
}
public DefaultPropertyValueCellEditor(final ParameterTypePassword type) {
super(new JPasswordField());
setClickCountToStart(1);
editorComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {}
@Override
public void focusLost(FocusEvent e) {
if (!e.isTemporary()) {
fireEditingStopped();
}
}
});
this.delegate = new EditorDelegate() {
private static final long serialVersionUID = -2736861014783898296L;
@Override
public void setValue(Object x) {
if (x == null) {
super.setValue(null);
((JTextField) editorComponent).setText(null);
} else {
String value = x.toString();
super.setValue(value);
((JTextField) editorComponent).setText(value.toString());
}
}
@Override
public Object getCellEditorValue() {
String text = ((JTextField) editorComponent).getText();
if ((text == null) || (text.length() == 0)) {
if (type.getDefaultValue() != null)
return type.getDefaultValue().toString();
else
return null;
} else {
return text.toString();
}
}
};
useEditorAsRenderer = true;
}
public DefaultPropertyValueCellEditor(final ParameterTypeChar type) {
super(new CharTextField());
setClickCountToStart(1);
editorComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {}
@Override
public void focusLost(FocusEvent e) {
if (!e.isTemporary()) {
fireEditingStopped();
}
}
});
}
public DefaultPropertyValueCellEditor(final ParameterType type) {
super(new JTextField(TEXT_FIELD_WIDTH));
setClickCountToStart(1);
editorComponent.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {}
@Override
public void focusLost(FocusEvent e) {
if (!e.isTemporary()) {
fireEditingStopped();
}
}
});
this.delegate = new EditorDelegate() {
private static final long serialVersionUID = -2868203350553070093L;
@Override
public void setValue(Object x) {
super.setValue(x);
if (x != null) {
((JTextField) editorComponent).setText(x.toString());
}
}
@Override
public Object getCellEditorValue() {
String text = ((JTextField) editorComponent).getText();
if ((text == null) || (text.length() == 0)) {
if (type.getDefaultValue() == null) {
return null;
} else {
return type.toString(type.getDefaultValue());
}
}
else
return text.toString();
}
};
useEditorAsRenderer = true;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
Component c;
if (table == null) {
c = editorComponent;
delegate.setValue(value);
((JComponent) c).setOpaque(!(c instanceof JCheckBox) && !(c instanceof JComboBox)); // otherwise we have a
// white border around
// check boxes
} else {
c = super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
return c;
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
delegate.setValue(value);
return editorComponent;
}
public boolean useEditorAsRenderer() {
return useEditorAsRenderer;
}
/** Does nothing. */
public void setOperator(Operator operator) {}
@Override
public boolean rendersLabel() {
return rendersLabel;
}
}