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<>(); 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<>(); 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}