Fixed race condition in access to underlying text field.
@@ -12,6 +12,8 @@ import java.text.ParseException;
import javax.swing.JTextField;
+import net.finmath.time.TimeDiscretizationInterface;
+
/**
* A Java swing bean to represent a number field in a GUI. Features admissible values.
*
@@ -24,6 +26,10 @@ public class JNumberField extends JTextField implements ActionListener {
Number value = new Double(0.0);
DecimalFormat formatter = new DecimalFormat("0.000");
+ // Guards access to read or write of the text field
+ Object updateLock = new Object();
+
+ double preferedValueIncrement = 0.0;
double[] admissibleValues = null;
double lowerBound = -Double.MAX_VALUE;
double upperBound = Double.MAX_VALUE;
@@ -75,7 +81,6 @@ public class JNumberField extends JTextField implements ActionListener {
public void setRange(double lowerBound, double upperBound) {
this.lowerBound = lowerBound;
this.upperBound = upperBound;
- parseField();
updateData();
}
@@ -83,16 +88,34 @@ public class JNumberField extends JTextField implements ActionListener {
this.admissibleValues = admissibleValues;
}
+ public void setAdmissibleValues(TimeDiscretizationInterface timeDiscretization) {
+ this.admissibleValues = new double[timeDiscretization.getNumberOfTimeSteps()+1];
+ for(int i=0; i<admissibleValues.length; i++) this.admissibleValues[i] = timeDiscretization.getTime(i);
+ }
+
+ public double getPreferedValueIncrement() {
+ return preferedValueIncrement;
+ }
+
+ public void setPreferedValueIncrement(double preferedValueIncrement) {
+ this.preferedValueIncrement = preferedValueIncrement;
+ }
+
public void add(double increment) {
setValue(getDoubleValue() + increment);
}
public void addToAdmissibleValueIndex(int increment) {
+ if(admissibleValues != null) {
int index = getAdmissibleValueIndex();
if(index < 0) return; // Admissible values not set
index = Math.max(0,Math.min(index + increment, admissibleValues.length-1));
value = admissibleValues[index];
+ }
+ else {
+ add(increment * preferedValueIncrement);
+ }
updateData();
}
@@ -105,25 +128,29 @@ public class JNumberField extends JTextField implements ActionListener {
return getValue().intValue();
}
- @Override
public void actionPerformed(ActionEvent arg0) {
parseField();
updateData();
}
private void parseField() {
- // Parse field
+ Double valueNumber = Double.NaN;
+ synchronized (updateLock) {
+ String valueText = this.getText();
+
+ if(valueText != null) {
try {
- setValue(formatter.parse(this.getText()).doubleValue());
- } catch (ParseException e) {
- // Reset field to previous value
- if(value != null) setValue(value.doubleValue());
- else setValue(0.0);
+ valueNumber = formatter.parse(this.getText()).doubleValue();
+ } catch (ParseException e) {}
}
}
+ setValue(valueNumber);
+ }
+
private void updateData() {
if(value == null) parseField();
+ synchronized (updateLock) {
// Constrain to admissibleValues
int index = getAdmissibleValueIndex();
@@ -137,6 +164,8 @@ public class JNumberField extends JTextField implements ActionListener {
if(lowerBound != -Double.MAX_VALUE && upperBound != Double.MAX_VALUE) this.setColumns(1+Math.max(formatter.format(lowerBound).length(), formatter.format(upperBound).length()));
else this.setColumns(1+this.getText().length());
+
+ }
}
private int getAdmissibleValueIndex() {
