In the main / detailed view, I have a series of text fields (and one or two other controls) that all relate to the details of the currently selected item. They all have the same one DocumentListener, therefore, if you change any of them, pairs of save / discard buttons become available. The buttons invoke the method, and I can happily save / delete elements.
However, when I use InputMapand ActionMap(works for all saveAction) for the connection of shared saveAction file to enter the keys, and shared discardAction command to the control key, discardAction command only works with certain fields.
When registering, I see that for fields that work, the discardAction function is first run, and then the corresponding combination of removeUpdate and insertUpdate.
For fields that do not work, the discardAction function never runs. Stop chatting, chatting - this is the local code (copy and paste, not rephrase):
docChangeListener = new DocumentListener() {
public void insertUpdate(DocumentEvent de) {
System.out.println("\t insertUpdate just got triggered");
memberDetailsChanged(de);
}
public void removeUpdate(DocumentEvent de) {
System.out.println("\t removeUpdate just got triggered");
memberDetailsChanged(de);
}
public void changedUpdate(DocumentEvent de) {
}
};
saveAction = new AbstractAction() {
public void actionPerformed(ActionEvent ae) {
System.out.println("\t saveAction just got triggered");
saveChanges();
}
};
discardAction = new AbstractAction() {
public void actionPerformed(ActionEvent ae) {
System.out.println("\t discardAction just got triggered");
discardChanges();
}
};
private void registerDetailField(final JTextField field) {
field.getDocument().putProperty("field", field);
field.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "saveActionKey");
field.getActionMap().put("saveActionKey", saveAction);
field.getInputMap().put(KeyStroke.getKeyStroke("ESCAPE"), "discardActionKey");
field.getActionMap().put("discardActionKey", discardAction);
field.getDocument().addDocumentListener(docChangeListener);
}
All text fields are registered the same way (with registerDetailField()). They also have a putClientPropertycaller to assign them a type to test (see below).
The only difference between fields that work and fields that don't, is the actual validation process. I will cut it because it takes so long, but I feel I have to turn it on. discardAction SEEMS run first for fields that work, but fields that don't work have a common check.
private void verifyField(final JTextField field) {
int fieldType = ((Integer)field.getClientProperty("type")).intValue();
String fieldValue = field.getText();
switch (fieldType) {
case STANDARD_FIELD:
return;
case MEMBER_NUMBER_FIELD:
if (fieldValue.length() == 0) {
field.setBackground(REQUIRED_COLOUR);
field.setToolTipText("This is a required field");
invalidFields.add(field);
return;
}
if (customTableModel.memberNumStringIsValid(fieldValue,
selectedMember.getMemberNumber())) {
field.setBackground(NORMAL_COLOUR);
field.setToolTipText(null);
invalidFields.remove(field);
} else {
field.setBackground(ERROR_COLOUR);
field.setToolTipText("This value must be a unique,
positive number");
invalidFields.add(field);
}
return;
default:
return;
}
}
, verifyField, - , .