--- /dev/null
+package be.nikiroo.utils.ui;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.util.List;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.border.EmptyBorder;
+
+import be.nikiroo.utils.resources.Bundle;
+
+/**
+ * A configuration panel for a {@link Bundle}.
+ * <p>
+ * All the items in the given {@link Bundle} will be displayed in editable
+ * controls, with options to Save, Reset and/or Reset to the application default
+ * values.
+ *
+ * @author niki
+ *
+ * @param <E>
+ * the type of {@link Bundle} to edit
+ */
+public class ConfigEditor<E extends Enum<E>> extends JPanel {
+ private static final long serialVersionUID = 1L;
+ private List<ConfigItem<E>> items;
+
+ /**
+ * Create a new {@link ConfigEditor} for this {@link Bundle}.
+ *
+ * @param type
+ * a class instance of the item type to work on
+ * @param bundle
+ * the {@link Bundle} to sort through
+ */
+ public ConfigEditor(Class<E> type, final Bundle<E> bundle) {
+ this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
+
+ items = ConfigItem.getItems(type, bundle);
+ for (ConfigItem<E> item : items) {
+ this.add(item);
+ }
+
+ addButton("Reset", new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ for (ConfigItem<E> item : items) {
+ item.reload();
+ }
+ }
+ });
+
+ addButton("Default", new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ Object snap = bundle.takeSnapshot();
+ bundle.reload(true);
+ for (ConfigItem<E> item : items) {
+ item.reload();
+ }
+ bundle.reload(false);
+ bundle.restoreSnapshot(snap);
+ }
+ });
+
+ addButton("Save", new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ for (ConfigItem<E> item : items) {
+ item.save();
+ }
+
+ try {
+ bundle.updateFile();
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ }
+ });
+ }
+
+ /**
+ * Add an action button for this action.
+ *
+ * @param title
+ * the action title
+ * @param listener
+ * the action
+ */
+ private void addButton(String title, ActionListener listener) {
+ JButton button = new JButton(title);
+ button.addActionListener(listener);
+
+ JPanel panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.setBorder(new EmptyBorder(2, 10, 2, 10));
+ panel.add(button, BorderLayout.CENTER);
+
+ this.add(panel);
+ }
+}
--- /dev/null
+package be.nikiroo.utils.ui;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.EmptyBorder;
+
+import be.nikiroo.utils.resources.Bundle;
+
+/**
+ * A graphical item that reflect a configuration option from the given
+ * {@link Bundle}.
+ *
+ * @author niki
+ *
+ * @param <E>
+ * the type of {@link Bundle} to edit
+ */
+public class ConfigItem<E extends Enum<E>> extends JPanel {
+ private static final long serialVersionUID = 1L;
+ private final Bundle<E> bundle;
+ private final E id;
+ private String value;
+
+ private JTextField valueField;
+
+ public ConfigItem(Class<E> type, Bundle<E> bundle, E id) {
+ this.bundle = bundle;
+ this.id = id;
+
+ this.setLayout(new BorderLayout());
+ this.setBorder(new EmptyBorder(2, 10, 2, 10));
+
+ JLabel nameLabel = new JLabel(id.toString());
+ nameLabel.setPreferredSize(new Dimension(400, 0));
+ this.add(nameLabel, BorderLayout.WEST);
+
+ valueField = new JTextField();
+ valueField.setText(value);
+
+ reload();
+ this.add(valueField, BorderLayout.CENTER);
+ }
+
+ /**
+ * Reload the value from the {@link Bundle}.
+ */
+ public void reload() {
+ value = bundle.getString(id);
+ valueField.setText(value);
+ }
+
+ /**
+ * Save the current value to the {@link Bundle}.
+ */
+ public void save() {
+ value = valueField.getText();
+ bundle.setString(id, value);
+ }
+
+ /**
+ * Create a list of {@link ConfigItem}, one for each of the item in the
+ * given {@link Bundle}.
+ *
+ * @param type
+ * a class instance of the item type to work on
+ * @param bundle
+ * the {@link Bundle} to sort through
+ *
+ * @return the list
+ */
+ static public <E extends Enum<E>> List<ConfigItem<E>> getItems(
+ Class<E> type, Bundle<E> bundle) {
+ List<ConfigItem<E>> list = new ArrayList<ConfigItem<E>>();
+ for (E id : type.getEnumConstants()) {
+ list.add(new ConfigItem<E>(type, bundle, id));
+ }
+
+ return list;
+ }
+}