/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O'Reilly
*/
// CombinationFormatter.java
//Input: string of form "15-45-22" (any number of hyphen-delimeted numbers)
//
Output: int array
//
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.text.DefaultFormatter;
public class CombinationFormatter extends DefaultFormatter {
public CombinationFormatter() {
setOverwriteMode(false);
}
public Object stringToValue(String string) throws java.text.ParseException {
// input: string of form "15-45-22" (any number of hyphen-delimeted
// numbers)
// output: int array
String s[] = string.split("-");
int a[] = new int[s.length];
for (int j = 0; j < a.length; j += 1)
try {
a[j] = Integer.parseInt(s[j]);
} catch (NumberFormatException nfe) {
throw new java.text.ParseException(s[j] + " is not an int", 0);
}
return a;
}
public String valueToString(Object value) throws java.text.ParseException {
// input: int array
// output: string of numerals separated by hyphens
if (value == null)
return null;
if (!(value instanceof int[]))
throw new java.text.ParseException("expected int[]", 0);
int a[] = (int[]) value;
StringBuffer sb = new StringBuffer();
for (int j = 0; j < a.length; j += 1) {
if (j > 0)
sb.append('-');
sb.append(a[j]);
}
return sb.toString();
}
protected Action[] getActions() {
Action[] actions = { new CombinationIncrementer("increment", 1),
new CombinationIncrementer("decrement", -1) };
return actions;
}
// begin inner class ----------------------------------------
public class CombinationIncrementer extends AbstractAction {
protected int delta;
public CombinationIncrementer(String name, int delta) { // constructor
super(name); // 'name' must match something in the component's
// InputMap
// or else this Action will not get invoked automatically.
// Valid names include: "reset-field-edit", "increment",
// "decrement", and "unselect" (see appendix B)
this.delta = delta;
}
public void actionPerformed(java.awt.event.ActionEvent ae) {
JFormattedTextField ftf = getFormattedTextField(); // from
// AbstractFormtter
if (ftf == null)
return;
String text = ftf.getText();
if (text == null)
return;
int pos = ftf.getCaretPosition();
int hyphenCount = 0;
for (int j = 0; j < pos; j += 1)
// how many hyphens precede the caret?
if (text.charAt(j) == '-')
hyphenCount += 1;
try {
int a[] = (int[]) stringToValue(text);
a[hyphenCount] += delta; // change the number at caret position
if (a[hyphenCount] < 0)
a[hyphenCount] = 0;
String newText = valueToString(a);
ftf.setText(newText); // does not retain caret position
if ((text.charAt(pos) == '-')
&& (newText.length() < text.length()))
pos -= 1; // don't let caret move past '-' when '10' changes
// to '9'
ftf.setCaretPosition(pos);
} catch (Exception e) {
return;
}
}
}
// end inner class ----------------------------------------
public static void main(String argv[]) {
// a demo main() to show how CombinationFormatter could be used
int comb1[] = { 35, 11, 19 };
int comb2[] = { 10, 20, 30 };
final JFormattedTextField field1 = new JFormattedTextField(
new CombinationFormatter());
field1.setValue(comb1);
final JFormattedTextField field2 = new JFormattedTextField(
new CombinationFormatter());
field2.setValue(comb2);
JPanel pan = new JPanel();
pan.add(new JLabel("Change the combination from"));
pan.add(field1);
pan.add(new JLabel("to"));
pan.add(field2);
JButton b = new JButton("Submit");
b.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent ae) {
try {
field1.commitEdit(); // make sure current edit (if any) gets
// committed
field2.commitEdit();
} catch (java.text.ParseException pe) {
}
int oldc[] = (int[]) field1.getValue();
int newc[] = (int[]) field2.getValue();
//
// code to validate oldc[] and change to newc[] goes here
//
}
});
pan.add(b);
JFrame f = new JFrame("CombinationFormatter Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(pan);
f.setSize(360, 100);
f.setVisible(true);
}
}