X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;ds=sidebyside;f=src%2Fbe%2Fnikiroo%2Futils%2Fui%2FConfigItem.java;h=f974969335c2a5b2d725e5682cfe04e8e47420ad;hb=cd3d510fdeb0ad53ae39e1fda34acf328c70c345;hp=8545485d0dc2a98196796bb2ec305c502acb2755;hpb=db31c35860081535d6e7ddc83ab4af573bb0522e;p=nikiroo-utils.git diff --git a/src/be/nikiroo/utils/ui/ConfigItem.java b/src/be/nikiroo/utils/ui/ConfigItem.java index 8545485..f974969 100644 --- a/src/be/nikiroo/utils/ui/ConfigItem.java +++ b/src/be/nikiroo/utils/ui/ConfigItem.java @@ -1,21 +1,39 @@ package be.nikiroo.utils.ui; import java.awt.BorderLayout; +import java.awt.Cursor; import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.IOException; import java.util.ArrayList; import java.util.List; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; -import javax.swing.border.EmptyBorder; +import be.nikiroo.utils.Image; +import be.nikiroo.utils.StringUtils; +import be.nikiroo.utils.StringUtils.Alignment; import be.nikiroo.utils.resources.Bundle; -import be.nikiroo.utils.resources.Meta; +import be.nikiroo.utils.resources.MetaInfo; /** * A graphical item that reflect a configuration option from the given * {@link Bundle}. + *
+ * This graphical item can be edited, and the result will be saved back into the
+ * linked {@link MetaInfo}; you still have to save the {@link MetaInfo} should
+ * you wish to, of course.
*
* @author niki
*
@@ -24,92 +42,482 @@ import be.nikiroo.utils.resources.Meta;
*/
public class ConfigItem
+ * Note that {@link ConfigItem#reload(int)} will be called after it was
+ * created.
+ *
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
+ *
+ * @return the graphical component
+ */
+ protected JComponent createField(@SuppressWarnings("unused") int item) {
+ // Not used by the main class, only the sublasses
+ return null;
+ }
+
+ /**
+ * Get the information from the {@link MetaInfo} in the subclass preferred
+ * format.
+ *
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
+ *
+ * @return the information in the subclass preferred format
+ */
+ protected Object getFromInfo(@SuppressWarnings("unused") int item) {
+ // Not used by the main class, only the subclasses
+ return null;
+ }
+
+ /**
+ * Set the value to the {@link MetaInfo}.
+ *
+ * @param value
+ * the value in the subclass preferred format
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
+ */
+ protected void setToInfo(@SuppressWarnings("unused") Object value,
+ @SuppressWarnings("unused") int item) {
+ // Not used by the main class, only the subclasses
+ }
+
+ /**
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
+ *
+ * @return
+ */
+ protected Object getFromField(@SuppressWarnings("unused") int item) {
+ // Not used by the main class, only the subclasses
+ return null;
+ }
+
+ /**
+ * Set the value (in the subclass preferred format) into the field.
+ *
+ * @param value
+ * the value in the subclass preferred format
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
+ */
+ protected void setToField(@SuppressWarnings("unused") Object value,
+ @SuppressWarnings("unused") int item) {
+ // Not used by the main class, only the subclasses
+ }
+
+ /**
+ * Create a new field for the given graphical component at the given index
+ * (note that the component is usually created by
+ * {@link ConfigItem#createField(int)}).
+ *
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
+ * @param field
+ * the graphical component
+ */
+ private void setField(int item, JComponent field) {
+ if (item < 0) {
+ this.field = field;
+ return;
+ }
+
+ for (int i = fields.size(); i <= item; i++) {
+ fields.add(null);
+ }
+
+ fields.set(item, field);
+ }
+
+ /**
+ * Retrieve the associated graphical component that was created with
+ * {@link ConfigItem#createField(int)}.
+ *
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
+ *
+ * @return the graphical component
+ */
+ protected JComponent getField(int item) {
+ if (item < 0) {
+ return field;
+ }
+
+ if (item < fields.size()) {
+ return fields.get(item);
}
- String name = id.toString();
- if (name.length() > 1) {
- name = name.substring(0, 1) + name.substring(1).toLowerCase();
- name = name.replace("_", " ");
+ return null;
+ }
+
+ /**
+ * Manually specify that the given item is "dirty" and thus should be saved
+ * when asked.
+ *
+ * Has no effect if the class is using automatic dirty handling (see
+ * {@link ConfigItem#ConfigItem(MetaInfo, boolean)}).
+ *
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
+ */
+ protected void setDirtyItem(int item) {
+ if (dirtyBits != null) {
+ dirtyBits.add(item);
}
+ }
- JLabel nameLabel = new JLabel(name);
- nameLabel.setToolTipText(tooltip);
- nameLabel.setPreferredSize(new Dimension(400, 0));
- this.add(nameLabel, BorderLayout.WEST);
+ /**
+ * Check if the value changed since the last load/save into the linked
+ * {@link MetaInfo}.
+ *
+ * Note that we consider NULL and an Empty {@link String} to be equals.
+ *
+ * @param value
+ * the value to test
+ *
+ * @return TRUE if it has
+ */
+ protected boolean hasValueChanged(Object value) {
+ // We consider "" and NULL to be equals
+ return !orig.equals(value == null ? "" : value);
+ }
- valueField = new JTextField();
- valueField.setText(value);
+ /**
+ * Reload the values to what they currently are in the {@link MetaInfo}.
+ *
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
+ */
+ protected void reload(int item) {
+ Object value = getFromInfo(item);
+ setToField(value, item);
- reload();
- this.add(valueField, BorderLayout.CENTER);
+ // We consider "" and NULL to be equals
+ orig = (value == null ? "" : value);
}
/**
- * Reload the value from the {@link Bundle}.
+ * If the item has been modified, set the {@link MetaInfo} to dirty then
+ * modify it to, reflect the changes so it can be saved later.
+ *
+ * This method does not call {@link MetaInfo#save(boolean)}.
+ *
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
*/
- public void reload() {
- value = bundle.getString(id);
- valueField.setText(value);
+ protected void save(int item) {
+ Object value = getFromField(item);
+
+ boolean dirty = false;
+ if (dirtyBits != null) {
+ dirty = dirtyBits.remove((Integer) item);
+ } else {
+ // We consider "" and NULL to be equals
+ dirty = hasValueChanged(value);
+ }
+
+ if (dirty) {
+ info.setDirty();
+ setToInfo(value, item);
+ orig = (value == null ? "" : value);
+ }
}
/**
- * Save the current value to the {@link Bundle}.
+ *
+ * @param item
+ * the item number to get for an array of values, or -1 to get
+ * the whole value (has no effect if {@link MetaInfo#isArray()}
+ * is FALSE)
+ * @param addTo
+ * @param nhgap
*/
- public void save() {
- value = valueField.getText();
- bundle.setString(id, value);
+ protected JComponent createComponent(final int item) {
+ setField(item, createField(item));
+ reload(item);
+
+ info.addReloadedListener(new Runnable() {
+ @Override
+ public void run() {
+ reload(item);
+ }
+ });
+ info.addSaveListener(new Runnable() {
+ @Override
+ public void run() {
+ save(item);
+ }
+ });
+
+ JComponent field = getField(item);
+ setPreferredSize(field);
+
+ return field;
}
/**
- * Create a list of {@link ConfigItem}, one for each of the item in the
- * given {@link Bundle}.
+ * Create a label which width is constrained in lock steps.
*
- * @param