For a personal project i needed to have a quick and easy system to save settings from a JFrame to preferences node using jdk preference api.
// Sample class that uses SettingsManager
public class MyForm{
...
SettingsManager settingsManager;
public MyForm(){
// this will restore previously saved values + add auto save handlers
settingsManager = new SettingsManager(this);
}
...
public void onResetButtonClick(....){
// this will reset values to original values
settingsManager.reset()
}
}
package you.define.it;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import static com.google.common.collect.Iterables.all;
import com.google.common.collect.Lists;
import static com.google.common.collect.Lists.newArrayList;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.prefs.Preferences;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This piece of code is provided as is. Use at your own risk.
*
* @author nchalon
*/
public class SettingsManager {
private static final Logger LOGGER = LoggerFactory.getLogger(SettingsManager.class);
private static final String DEFAULT = "_DEFAULT";
static SettingsManager getSettingsManager(Object object) {
return new SettingsManager(object);
}
private final Object object;
private Preferences userPreferences;
private ArrayList<Field> fields;
public void reset() {
all(fields, new Predicate<Field>() {
@Override
public boolean apply(Field field) {
resetFieldContent(field);
return true;
}
});
}
private SettingsManager(Object object) {
this.object = object;
this.fields = newArrayList(object.getClass().getDeclaredFields());
userPreferences = Preferences.userNodeForPackage(object.getClass());
try {
extractFieldsContent();
} catch (Exception ex) {
LOGGER.warn("Unable to retreive class data from preferences");
}
}
private void extractFieldsContent() throws Exception {
all(fields, new Predicate<Field>() {
@Override
public boolean apply(Field field) {
extractFieldContent(field);
return true;
}
});
}
private void extractFieldContent(Field field) {
try {
field.setAccessible(true);
final Object theField = field.get(object);
if (theField != null) {
if (theField.getClass().isAssignableFrom(JTextField.class)) {
handleTextField(field, ((JTextField) theField));
} else if (theField.getClass().isAssignableFrom(JFormattedTextField.class)) {
handleTextField(field, ((JTextField) theField));
} else if (theField.getClass().isAssignableFrom(JCheckBox.class)) {
handleCheckbox(field, ((JCheckBox) theField));
} else if (theField.getClass().isAssignableFrom(JComboBox.class)) {
handleComboBox(field, ((JComboBox) theField));
}
}
} catch (IllegalAccessException | IllegalArgumentException | SecurityException ex) {
LOGGER.error("Unable to extract field content",ex);
}
}
private void handleTextField(final Field field, final JTextField textField) {
userPreferences.put(field.getName() + DEFAULT, textField.getText());
textField.setText(userPreferences.get(field.getName(), textField.getText()));
textField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
handleChange();
}
@Override
public void removeUpdate(DocumentEvent e) {
handleChange();
}
@Override
public void changedUpdate(DocumentEvent e) {
handleChange();
}
public void handleChange() {
userPreferences.put(field.getName(), textField.getText());
}
});
}
private void handleCheckbox(final Field field, final JCheckBox checkBox) {
userPreferences.putBoolean(field.getName() + DEFAULT, checkBox.isSelected());
checkBox.setSelected(userPreferences.getBoolean(field.getName(), checkBox.isSelected()));
checkBox.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
userPreferences.putBoolean(field.getName(), checkBox.isSelected());
}
});
}
private void handleComboBox(final Field field, final JComboBox comboBox) {
userPreferences.putInt(field.getName() + DEFAULT, comboBox.getSelectedIndex());
comboBox.setSelectedIndex(userPreferences.getInt(field.getName(), comboBox.getSelectedIndex()));
comboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
userPreferences.putInt(field.getName(), comboBox.getSelectedIndex());
}
});
}
private void resetFieldContent(Field field){
try {
field.setAccessible(true);
final Object theField = field.get(object);
if (theField != null) {
if (theField.getClass().isAssignableFrom(JTextField.class)) {
((JTextField) theField).setText(userPreferences.get(field.getName() + DEFAULT, ""));
} else if (theField.getClass().isAssignableFrom(JFormattedTextField.class)) {
((JTextField) theField).setText(userPreferences.get(field.getName() + DEFAULT, ""));
} else if (theField.getClass().isAssignableFrom(JCheckBox.class)) {
((JCheckBox) theField).setSelected(userPreferences.getBoolean(field.getName() + DEFAULT, false));
} else if (theField.getClass().isAssignableFrom(JComboBox.class)) {
((JComboBox) theField).setSelectedIndex(userPreferences.getInt(field.getName() + DEFAULT, 0));
}
userPreferences.remove(field.getName());
}
} catch (IllegalAccessException | IllegalArgumentException | SecurityException ex) {
LOGGER.error("Unable to reset field content",ex);
}
}
}