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);
025    /** the model for the changeset comment */
026    private final ChangesetCommentModel changesetCommentModel;
027    private final ChangesetCommentModel changesetSourceModel;
028    /** tags that applied to uploaded changesets by default*/
029    private final Map<String, String> defaultTags = new HashMap<String, String>();
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 thrown if {@code changesetCommentModel} is null
042     */
043    public TagSettingsPanel(ChangesetCommentModel changesetCommentModel, ChangesetCommentModel changesetSourceModel) throws IllegalArgumentException{
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<String, String>();
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    }
122
123    public void startUserInput() {
124        pnlTagEditor.initAutoCompletion(Main.main.getEditLayer());
125    }
126
127    /* -------------------------------------------------------------------------- */
128    /* Interface TableChangeListener                                              */
129    /* -------------------------------------------------------------------------- */
130    @Override
131    public void tableChanged(TableModelEvent e) {
132        changesetCommentModel.setComment(getTagEditorValue("comment"));
133        changesetSourceModel.setComment(getTagEditorValue("source"));
134    }
135
136    /**
137     * Observes the changeset comment model and keeps the tag editor in sync
138     * with the current changeset comment
139     *
140     */
141    class ChangesetCommentObserver implements Observer {
142
143        private final String key;
144
145        ChangesetCommentObserver(String key) {
146            this.key = key;
147        }
148
149        @Override
150        public void update(Observable o, Object arg) {
151            if (!(o instanceof ChangesetCommentModel)) return;
152            String newValue = (String)arg;
153            String oldValue = getTagEditorValue(key);
154            if (oldValue == null) {
155                oldValue = "";
156            }
157            if (!oldValue.equals(newValue)) {
158                setProperty(key, (String) arg);
159            }
160        }
161    }
162}