001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.io;
003
004import java.awt.BorderLayout;
005import java.util.HashMap;
006import java.util.Map;
007import java.util.Observable;
008import java.util.Observer;
009
010import javax.swing.JPanel;
011import javax.swing.event.TableModelEvent;
012import javax.swing.event.TableModelListener;
013
014import org.openstreetmap.josm.Main;
015import org.openstreetmap.josm.data.Version;
016import org.openstreetmap.josm.data.osm.Changeset;
017import org.openstreetmap.josm.gui.tagging.TagEditorPanel;
018import org.openstreetmap.josm.gui.tagging.TagModel;
019import org.openstreetmap.josm.tools.CheckParameterUtil;
020
021public class TagSettingsPanel extends JPanel implements TableModelListener {
022
023    /** checkbox for selecting whether an atomic upload is to be used  */
024    private final TagEditorPanel pnlTagEditor = new TagEditorPanel(null, null, Changeset.MAX_CHANGESET_TAG_LENGTH);
025    /** the model for the changeset comment */
026    private final transient ChangesetCommentModel changesetCommentModel;
027    private final transient ChangesetCommentModel changesetSourceModel;
028    /** tags that applied to uploaded changesets by default*/
029    private final transient Map<String, String> defaultTags = new HashMap<>();
030
031    protected void build() {
032        setLayout(new BorderLayout());
033        add(pnlTagEditor, BorderLayout.CENTER);
034    }
035
036    /**
037     * Creates a new panel
038     *
039     * @param changesetCommentModel the changeset comment model. Must not be null.
040     * @param changesetSourceModel the changeset source model. Must not be null.
041     * @throws IllegalArgumentException if {@code changesetCommentModel} is null
042     */
043    public TagSettingsPanel(ChangesetCommentModel changesetCommentModel, ChangesetCommentModel changesetSourceModel) {
044        CheckParameterUtil.ensureParameterNotNull(changesetCommentModel, "changesetCommentModel");
045        CheckParameterUtil.ensureParameterNotNull(changesetSourceModel, "changesetSourceModel");
046        this.changesetCommentModel = changesetCommentModel;
047        this.changesetSourceModel = changesetSourceModel;
048        this.changesetCommentModel.addObserver(new ChangesetCommentObserver("comment"));
049        this.changesetSourceModel.addObserver(new ChangesetCommentObserver("source"));
050        build();
051        pnlTagEditor.getModel().addTableModelListener(this);
052    }
053
054    protected void setProperty(String key, String value) {
055        if (value == null) {
056            value = "";
057        }
058        value = value.trim();
059        String commentInTag = getTagEditorValue(key);
060        if (value.equals(commentInTag))
061            return;
062
063        if (value.isEmpty()) {
064            pnlTagEditor.getModel().delete(key);
065            return;
066        }
067        TagModel tag = pnlTagEditor.getModel().get(key);
068        if (tag == null) {
069            tag = new TagModel(key, value);
070            pnlTagEditor.getModel().add(tag);
071        } else {
072            pnlTagEditor.getModel().updateTagValue(tag, value);
073        }
074    }
075
076    protected String getTagEditorValue(String key) {
077        TagModel tag = pnlTagEditor.getModel().get(key);
078        if (tag == null) return null;
079        return tag.getValue();
080    }
081
082    public void initFromChangeset(Changeset cs) {
083        Map<String, String> tags = getDefaultTags();
084        if (cs != null) {
085            tags.putAll(cs.getKeys());
086        }
087        if (tags.get("comment") == null) {
088            tags.put("comment", getTagEditorValue("comment"));
089        }
090        if (tags.get("source") == null) {
091            tags.put("source", getTagEditorValue("source"));
092        }
093        String agent = Version.getInstance().getAgentString(false);
094        String created_by = tags.get("created_by");
095        if (created_by == null || created_by.isEmpty()) {
096            tags.put("created_by", agent);
097        } else if (!created_by.contains(agent)) {
098            tags.put("created_by", created_by + ';' + agent);
099        }
100        pnlTagEditor.getModel().initFromTags(tags);
101    }
102
103    /**
104     * Replies the map with the current tags in the tag editor model.
105     *
106     * @return the map with the current tags in the tag editor model.
107     */
108    public Map<String, String> getTags(boolean keepEmpty) {
109        return pnlTagEditor.getModel().getTags(keepEmpty);
110    }
111
112    public Map<String, String> getDefaultTags() {
113        Map<String, String> tags = new HashMap<>();
114        tags.putAll(defaultTags);
115        return tags;
116    }
117
118    public void setDefaultTags(Map<String, String> tags) {
119        defaultTags.clear();
120        defaultTags.putAll(tags);
121        tableChanged(null);
122    }
123
124    public void startUserInput() {
125        pnlTagEditor.initAutoCompletion(Main.main.getEditLayer());
126    }
127
128    /* -------------------------------------------------------------------------- */
129    /* Interface TableChangeListener                                              */
130    /* -------------------------------------------------------------------------- */
131    @Override
132    public void tableChanged(TableModelEvent e) {
133        changesetCommentModel.setComment(getTagEditorValue("comment"));
134        changesetSourceModel.setComment(getTagEditorValue("source"));
135    }
136
137    /**
138     * Observes the changeset comment model and keeps the tag editor in sync
139     * with the current changeset comment
140     *
141     */
142    class ChangesetCommentObserver implements Observer {
143
144        private final String key;
145
146        ChangesetCommentObserver(String key) {
147            this.key = key;
148        }
149
150        @Override
151        public void update(Observable o, Object arg) {
152            if (!(o instanceof ChangesetCommentModel)) return;
153            String newValue = (String) arg;
154            String oldValue = getTagEditorValue(key);
155            if (oldValue == null) {
156                oldValue = "";
157            }
158            if (!oldValue.equals(newValue)) {
159                setProperty(key, (String) arg);
160            }
161        }
162    }
163}