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 /** 083 * Initialize panel from changeset. 084 * @param cs changeset 085 */ 086 public void initFromChangeset(Changeset cs) { 087 Map<String, String> tags = getDefaultTags(); 088 if (cs != null) { 089 tags.putAll(cs.getKeys()); 090 } 091 if (tags.get("comment") == null) { 092 tags.put("comment", getTagEditorValue("comment")); 093 } 094 if (tags.get("source") == null) { 095 tags.put("source", getTagEditorValue("source")); 096 } 097 String agent = Version.getInstance().getAgentString(false); 098 String created_by = tags.get("created_by"); 099 if (created_by == null || created_by.isEmpty()) { 100 tags.put("created_by", agent); 101 } else if (!created_by.contains(agent)) { 102 tags.put("created_by", created_by + ';' + agent); 103 } 104 pnlTagEditor.getModel().initFromTags(tags); 105 } 106 107 /** 108 * Replies the map with the current tags in the tag editor model. 109 * @param keepEmpty {@code true} to keep empty tags 110 * @return the map with the current tags in the tag editor model. 111 */ 112 public Map<String, String> getTags(boolean keepEmpty) { 113 return pnlTagEditor.getModel().getTags(keepEmpty); 114 } 115 116 /** 117 * Replies the map with the default tags. 118 * @return the map with the default tags 119 */ 120 public Map<String, String> getDefaultTags() { 121 Map<String, String> tags = new HashMap<>(); 122 tags.putAll(defaultTags); 123 return tags; 124 } 125 126 /** 127 * Sets the map with the default tags. 128 * @param tags the map with the default tags 129 */ 130 public void setDefaultTags(Map<String, String> tags) { 131 defaultTags.clear(); 132 defaultTags.putAll(tags); 133 tableChanged(null); 134 } 135 136 public void startUserInput() { 137 pnlTagEditor.initAutoCompletion(Main.main.getEditLayer()); 138 } 139 140 /* -------------------------------------------------------------------------- */ 141 /* Interface TableChangeListener */ 142 /* -------------------------------------------------------------------------- */ 143 @Override 144 public void tableChanged(TableModelEvent e) { 145 changesetCommentModel.setComment(getTagEditorValue("comment")); 146 changesetSourceModel.setComment(getTagEditorValue("source")); 147 } 148 149 /** 150 * Observes the changeset comment model and keeps the tag editor in sync 151 * with the current changeset comment 152 * 153 */ 154 class ChangesetCommentObserver implements Observer { 155 156 private final String key; 157 158 ChangesetCommentObserver(String key) { 159 this.key = key; 160 } 161 162 @Override 163 public void update(Observable o, Object arg) { 164 if (!(o instanceof ChangesetCommentModel)) return; 165 String newValue = (String) arg; 166 String oldValue = getTagEditorValue(key); 167 if (oldValue == null) { 168 oldValue = ""; 169 } 170 if (!oldValue.equals(newValue)) { 171 setProperty(key, (String) arg); 172 } 173 } 174 } 175}