001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.io;
003
004import java.awt.BorderLayout;
005import java.util.Map;
006
007import javax.swing.JPanel;
008import javax.swing.event.ChangeEvent;
009import javax.swing.event.ChangeListener;
010import javax.swing.event.TableModelEvent;
011import javax.swing.event.TableModelListener;
012
013import org.openstreetmap.josm.Main;
014import org.openstreetmap.josm.data.osm.Changeset;
015import org.openstreetmap.josm.gui.tagging.TagEditorPanel;
016import org.openstreetmap.josm.gui.tagging.TagModel;
017import org.openstreetmap.josm.tools.CheckParameterUtil;
018
019/**
020 * Tag settings panel of upload dialog.
021 * @since 2599
022 */
023public class TagSettingsPanel extends JPanel implements TableModelListener {
024
025    /** checkbox for selecting whether an atomic upload is to be used  */
026    private final TagEditorPanel pnlTagEditor = new TagEditorPanel(null, null, Changeset.MAX_CHANGESET_TAG_LENGTH);
027    /** the model for the changeset comment */
028    private final transient ChangesetCommentModel changesetCommentModel;
029    private final transient ChangesetCommentModel changesetSourceModel;
030
031    /**
032     * Creates a new panel
033     *
034     * @param changesetCommentModel the changeset comment model. Must not be null.
035     * @param changesetSourceModel the changeset source model. Must not be null.
036     * @throws IllegalArgumentException if {@code changesetCommentModel} is null
037     */
038    public TagSettingsPanel(ChangesetCommentModel changesetCommentModel, ChangesetCommentModel changesetSourceModel) {
039        CheckParameterUtil.ensureParameterNotNull(changesetCommentModel, "changesetCommentModel");
040        CheckParameterUtil.ensureParameterNotNull(changesetSourceModel, "changesetSourceModel");
041        this.changesetCommentModel = changesetCommentModel;
042        this.changesetSourceModel = changesetSourceModel;
043        this.changesetCommentModel.addChangeListener(new ChangesetCommentChangeListener("comment"));
044        this.changesetSourceModel.addChangeListener(new ChangesetCommentChangeListener("source"));
045        build();
046        pnlTagEditor.getModel().addTableModelListener(this);
047    }
048
049    protected void build() {
050        setLayout(new BorderLayout());
051        add(pnlTagEditor, BorderLayout.CENTER);
052    }
053
054    protected void setProperty(String key, String value) {
055        String val = (value == null ? "" : value).trim();
056        String commentInTag = getTagEditorValue(key);
057        if (val.equals(commentInTag))
058            return;
059
060        if (val.isEmpty()) {
061            pnlTagEditor.getModel().delete(key);
062            return;
063        }
064        TagModel tag = pnlTagEditor.getModel().get(key);
065        if (tag == null) {
066            tag = new TagModel(key, val);
067            pnlTagEditor.getModel().add(tag);
068        } else {
069            pnlTagEditor.getModel().updateTagValue(tag, val);
070        }
071    }
072
073    protected String getTagEditorValue(String key) {
074        TagModel tag = pnlTagEditor.getModel().get(key);
075        return tag == null ? null : tag.getValue();
076    }
077
078    /**
079     * Initialize panel from the given tags.
080     * @param tags the tags used to initialize the panel
081     */
082    public void initFromTags(Map<String, String> tags) {
083        pnlTagEditor.getModel().initFromTags(tags);
084    }
085
086    /**
087     * Replies the map with the current tags in the tag editor model.
088     * @param keepEmpty {@code true} to keep empty tags
089     * @return the map with the current tags in the tag editor model.
090     */
091    public Map<String, String> getTags(boolean keepEmpty) {
092        return pnlTagEditor.getModel().getTags(keepEmpty);
093    }
094
095    /**
096     * Initializes the panel for user input
097     */
098    public void startUserInput() {
099        pnlTagEditor.initAutoCompletion(Main.main.getEditLayer());
100    }
101
102    /* -------------------------------------------------------------------------- */
103    /* Interface TableChangeListener                                              */
104    /* -------------------------------------------------------------------------- */
105    @Override
106    public void tableChanged(TableModelEvent e) {
107        changesetCommentModel.setComment(getTagEditorValue("comment"));
108        changesetSourceModel.setComment(getTagEditorValue("source"));
109    }
110
111    /**
112     * Observes the changeset comment model and keeps the tag editor in sync
113     * with the current changeset comment
114     */
115    class ChangesetCommentChangeListener implements ChangeListener {
116
117        private final String key;
118
119        ChangesetCommentChangeListener(String key) {
120            this.key = key;
121        }
122
123        @Override
124        public void stateChanged(ChangeEvent e) {
125            if (e.getSource() instanceof ChangesetCommentModel) {
126                String newValue = ((ChangesetCommentModel) e.getSource()).getComment();
127                String oldValue = getTagEditorValue(key);
128                if (oldValue == null) {
129                    oldValue = "";
130                }
131                if (!oldValue.equals(newValue)) {
132                    setProperty(key, newValue);
133                }
134            }
135        }
136    }
137}