blob: 791f1a83663ceb46d958c566a4ceea5fe32c9df2 [file] [log] [blame]
package net.sf.taverna.t2.lang.uibuilder;
import java.awt.BorderLayout;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.lang.reflect.Constructor;
import java.util.Properties;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;
/**
* Abstract superclass for all bean property editors based on text components
*
* @author Tom Oinn
*/
public abstract class BeanTextComponent extends BeanComponent {
private static final long serialVersionUID = -9133735782847457090L;
private String regex = null;
private JTextComponent text;
private String originalValue = null;
private boolean edited = false;
protected BeanTextComponent(Object target, String propertyName,
Properties props) throws NoSuchMethodException {
this(target, propertyName, true, props);
}
protected BeanTextComponent(Object target, String propertyName,
boolean useLabel, Properties props) throws NoSuchMethodException {
super(target, propertyName, useLabel, props);
setLayout(new BorderLayout());
if (propertyType.equals(Boolean.class)) {
setRegex("\\A((true)|(false))\\Z");
} else if (propertyType.equals(Character.class)) {
setRegex("\\A.\\Z");
}
text = getTextComponent();
originalValue = getPropertyAsString();
text.setText(originalValue);
text.setEditable(editable);
add(text, BorderLayout.CENTER);
if (editable) {
text.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
valueChangedInEditor();
}
public void insertUpdate(DocumentEvent e) {
valueChangedInEditor();
}
public void removeUpdate(DocumentEvent e) {
valueChangedInEditor();
}
private void valueChangedInEditor() {
BeanTextComponent.this.valueChangedInEditor();
}
});
text.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
//
}
public void focusLost(FocusEvent e) {
// System.out.println("Focus lost : valid = "
// + currentValueValid);
if (currentValueValid) {
if (isEdited()) {
BeanTextComponent.this.setProperty();
originalValue = text.getText();
}
} else {
originalValue = getPropertyAsString();
text.setText(originalValue);
}
setEdited(false);
}
});
}
addLabel();
}
private boolean isEdited() {
return this.edited;
}
private void setEdited(boolean edited) {
if (edited == this.edited) {
return;
}
this.edited = edited;
text.setBackground(edited ? editedColour : uneditedColour);
if (!edited) {
setValid(true);
}
}
public void updateComponent() {
originalValue = getPropertyAsString();
text.setText(originalValue);
setEdited(false);
}
private void valueChangedInEditor() {
if (text.getText().equals(originalValue)) {
setEdited(false);
return;
}
setEdited(true);
// Check for regex
if (regex != null) {
if (text.getText().matches(regex) == false) {
// System.out.println(text.getText() + ".matches(" + regex
// + ")==false");
setValid(false);
return;
}
}
// Delegate to constructor for non-string classes
if (!propertyType.equals(String.class)) {
try {
Constructor<?> cons = null;
if (propertyType.equals(Character.class)
&& text.getText().length() > 0) {
currentObjectValue = text.getText().toCharArray()[0];
} else {
cons = propertyType.getConstructor(String.class);
currentObjectValue = cons.newInstance(text.getText());
}
} catch (Throwable t) {
setValid(false);
return;
}
} else {
currentObjectValue = text.getText();
}
setValid(true);
}
private void setValid(final boolean valid) {
if (valid == currentValueValid) {
return;
}
currentValueValid = valid;
text.setForeground(valid ? validColour : invalidColour);
setLabelColour(valid ? validColour : invalidColour);
text.repaint();
}
/**
* Implement this to provide the actual UI component used to show the
* content of the field. Done this way so you can choose what component to
* use.
*
* @return
*/
protected abstract JTextComponent getTextComponent();
/**
* Set the regular expression used to validate the contents of the text
* field
*
* @param regex
*/
public void setRegex(String regex) {
this.regex = regex;
}
}