[2711] | 1 | // License: GPL. For details, see LICENSE file.
|
---|
| 2 | package org.openstreetmap.josm.gui.io;
|
---|
| 3 |
|
---|
| 4 | import java.awt.BorderLayout;
|
---|
| 5 | import java.util.Map;
|
---|
[11553] | 6 | import java.util.Optional;
|
---|
[2711] | 7 |
|
---|
| 8 | import javax.swing.JPanel;
|
---|
[10210] | 9 | import javax.swing.event.ChangeEvent;
|
---|
| 10 | import javax.swing.event.ChangeListener;
|
---|
[2711] | 11 | import javax.swing.event.TableModelEvent;
|
---|
| 12 | import javax.swing.event.TableModelListener;
|
---|
| 13 |
|
---|
| 14 | import org.openstreetmap.josm.data.osm.Changeset;
|
---|
[12636] | 15 | import org.openstreetmap.josm.gui.MainApplication;
|
---|
[2711] | 16 | import org.openstreetmap.josm.gui.tagging.TagEditorPanel;
|
---|
| 17 | import org.openstreetmap.josm.gui.tagging.TagModel;
|
---|
[13198] | 18 | import org.openstreetmap.josm.spi.preferences.Config;
|
---|
[3133] | 19 | import org.openstreetmap.josm.tools.CheckParameterUtil;
|
---|
[2711] | 20 |
|
---|
[9522] | 21 | /**
|
---|
| 22 | * Tag settings panel of upload dialog.
|
---|
| 23 | * @since 2599
|
---|
| 24 | */
|
---|
[3133] | 25 | public class TagSettingsPanel extends JPanel implements TableModelListener {
|
---|
[2711] | 26 |
|
---|
| 27 | /** checkbox for selecting whether an atomic upload is to be used */
|
---|
[8760] | 28 | private final TagEditorPanel pnlTagEditor = new TagEditorPanel(null, null, Changeset.MAX_CHANGESET_TAG_LENGTH);
|
---|
[3133] | 29 | /** the model for the changeset comment */
|
---|
[8308] | 30 | private final transient ChangesetCommentModel changesetCommentModel;
|
---|
| 31 | private final transient ChangesetCommentModel changesetSourceModel;
|
---|
[12719] | 32 | private final transient ChangesetReviewModel changesetReviewModel;
|
---|
[2711] | 33 |
|
---|
[3133] | 34 | /**
|
---|
| 35 | * Creates a new panel
|
---|
[3518] | 36 | *
|
---|
[3133] | 37 | * @param changesetCommentModel the changeset comment model. Must not be null.
|
---|
[6401] | 38 | * @param changesetSourceModel the changeset source model. Must not be null.
|
---|
[12719] | 39 | * @param changesetReviewModel the model for the changeset review. Must not be null.
|
---|
[8291] | 40 | * @throws IllegalArgumentException if {@code changesetCommentModel} is null
|
---|
[12719] | 41 | * @since 12719 (signature)
|
---|
[3133] | 42 | */
|
---|
[12719] | 43 | public TagSettingsPanel(ChangesetCommentModel changesetCommentModel, ChangesetCommentModel changesetSourceModel,
|
---|
| 44 | ChangesetReviewModel changesetReviewModel) {
|
---|
[3133] | 45 | CheckParameterUtil.ensureParameterNotNull(changesetCommentModel, "changesetCommentModel");
|
---|
[6401] | 46 | CheckParameterUtil.ensureParameterNotNull(changesetSourceModel, "changesetSourceModel");
|
---|
[12719] | 47 | CheckParameterUtil.ensureParameterNotNull(changesetReviewModel, "changesetReviewModel");
|
---|
[3133] | 48 | this.changesetCommentModel = changesetCommentModel;
|
---|
[6401] | 49 | this.changesetSourceModel = changesetSourceModel;
|
---|
[12719] | 50 | this.changesetReviewModel = changesetReviewModel;
|
---|
[13109] | 51 | changesetCommentModel.addChangeListener(new ChangesetCommentChangeListener("comment", "hashtags"));
|
---|
[12719] | 52 | changesetSourceModel.addChangeListener(new ChangesetCommentChangeListener("source"));
|
---|
| 53 | changesetReviewModel.addChangeListener(new ChangesetReviewChangeListener());
|
---|
[2711] | 54 | build();
|
---|
| 55 | pnlTagEditor.getModel().addTableModelListener(this);
|
---|
| 56 | }
|
---|
| 57 |
|
---|
[9522] | 58 | protected void build() {
|
---|
| 59 | setLayout(new BorderLayout());
|
---|
| 60 | add(pnlTagEditor, BorderLayout.CENTER);
|
---|
| 61 | }
|
---|
| 62 |
|
---|
[6401] | 63 | protected void setProperty(String key, String value) {
|
---|
[9522] | 64 | String val = (value == null ? "" : value).trim();
|
---|
[6401] | 65 | String commentInTag = getTagEditorValue(key);
|
---|
[9522] | 66 | if (val.equals(commentInTag))
|
---|
[2711] | 67 | return;
|
---|
| 68 |
|
---|
[9522] | 69 | if (val.isEmpty()) {
|
---|
[6401] | 70 | pnlTagEditor.getModel().delete(key);
|
---|
[2711] | 71 | return;
|
---|
| 72 | }
|
---|
[6401] | 73 | TagModel tag = pnlTagEditor.getModel().get(key);
|
---|
[2711] | 74 | if (tag == null) {
|
---|
[9522] | 75 | tag = new TagModel(key, val);
|
---|
[2711] | 76 | pnlTagEditor.getModel().add(tag);
|
---|
| 77 | } else {
|
---|
[9522] | 78 | pnlTagEditor.getModel().updateTagValue(tag, val);
|
---|
[2711] | 79 | }
|
---|
| 80 | }
|
---|
| 81 |
|
---|
[6401] | 82 | protected String getTagEditorValue(String key) {
|
---|
| 83 | TagModel tag = pnlTagEditor.getModel().get(key);
|
---|
[9522] | 84 | return tag == null ? null : tag.getValue();
|
---|
[2711] | 85 | }
|
---|
| 86 |
|
---|
[9246] | 87 | /**
|
---|
[9514] | 88 | * Initialize panel from the given tags.
|
---|
| 89 | * @param tags the tags used to initialize the panel
|
---|
[9246] | 90 | */
|
---|
[9514] | 91 | public void initFromTags(Map<String, String> tags) {
|
---|
[2711] | 92 | pnlTagEditor.getModel().initFromTags(tags);
|
---|
| 93 | }
|
---|
| 94 |
|
---|
| 95 | /**
|
---|
| 96 | * Replies the map with the current tags in the tag editor model.
|
---|
[9246] | 97 | * @param keepEmpty {@code true} to keep empty tags
|
---|
[2711] | 98 | * @return the map with the current tags in the tag editor model.
|
---|
| 99 | */
|
---|
[8510] | 100 | public Map<String, String> getTags(boolean keepEmpty) {
|
---|
[12265] | 101 | forceCommentFieldReload();
|
---|
[6309] | 102 | return pnlTagEditor.getModel().getTags(keepEmpty);
|
---|
[2711] | 103 | }
|
---|
| 104 |
|
---|
[9246] | 105 | /**
|
---|
[9522] | 106 | * Initializes the panel for user input
|
---|
| 107 | */
|
---|
[2711] | 108 | public void startUserInput() {
|
---|
[12636] | 109 | pnlTagEditor.initAutoCompletion(MainApplication.getLayerManager().getEditLayer());
|
---|
[2711] | 110 | }
|
---|
| 111 |
|
---|
| 112 | /* -------------------------------------------------------------------------- */
|
---|
| 113 | /* Interface TableChangeListener */
|
---|
| 114 | /* -------------------------------------------------------------------------- */
|
---|
[6084] | 115 | @Override
|
---|
[2711] | 116 | public void tableChanged(TableModelEvent e) {
|
---|
[6401] | 117 | changesetCommentModel.setComment(getTagEditorValue("comment"));
|
---|
| 118 | changesetSourceModel.setComment(getTagEditorValue("source"));
|
---|
[12719] | 119 | changesetReviewModel.setReviewRequested("yes".equals(getTagEditorValue("review_requested")));
|
---|
[2711] | 120 | }
|
---|
[3133] | 121 |
|
---|
| 122 | /**
|
---|
[12265] | 123 | * Force update the fields if the user is currently changing them. See #5676
|
---|
| 124 | */
|
---|
| 125 | private void forceCommentFieldReload() {
|
---|
| 126 | setProperty("comment", changesetCommentModel.getComment());
|
---|
| 127 | setProperty("source", changesetSourceModel.getComment());
|
---|
[12719] | 128 | setProperty("review_requested", changesetReviewModel.isReviewRequested() ? "yes" : null);
|
---|
[12265] | 129 | }
|
---|
| 130 |
|
---|
| 131 | /**
|
---|
[3133] | 132 | * Observes the changeset comment model and keeps the tag editor in sync
|
---|
| 133 | * with the current changeset comment
|
---|
| 134 | */
|
---|
[10210] | 135 | class ChangesetCommentChangeListener implements ChangeListener {
|
---|
[6401] | 136 |
|
---|
| 137 | private final String key;
|
---|
[13109] | 138 | private final String hashtagsKey;
|
---|
[6401] | 139 |
|
---|
[10210] | 140 | ChangesetCommentChangeListener(String key) {
|
---|
[13109] | 141 | this(key, null);
|
---|
| 142 | }
|
---|
| 143 |
|
---|
| 144 | ChangesetCommentChangeListener(String key, String hashtagsKey) {
|
---|
[6401] | 145 | this.key = key;
|
---|
[13109] | 146 | this.hashtagsKey = hashtagsKey;
|
---|
[6401] | 147 | }
|
---|
| 148 |
|
---|
[6084] | 149 | @Override
|
---|
[10210] | 150 | public void stateChanged(ChangeEvent e) {
|
---|
| 151 | if (e.getSource() instanceof ChangesetCommentModel) {
|
---|
[13109] | 152 | ChangesetCommentModel model = ((ChangesetCommentModel) e.getSource());
|
---|
| 153 | String newValue = model.getComment();
|
---|
[11553] | 154 | String oldValue = Optional.ofNullable(getTagEditorValue(key)).orElse("");
|
---|
[9522] | 155 | if (!oldValue.equals(newValue)) {
|
---|
[10210] | 156 | setProperty(key, newValue);
|
---|
[13198] | 157 | if (hashtagsKey != null && Config.getPref().getBoolean("upload.changeset.hashtags", true)) {
|
---|
[13109] | 158 | String newHashTags = String.join(";", model.findHashTags());
|
---|
| 159 | String oldHashTags = Optional.ofNullable(getTagEditorValue(hashtagsKey)).orElse("");
|
---|
| 160 | if (!oldHashTags.equals(newHashTags)) {
|
---|
| 161 | setProperty(hashtagsKey, newHashTags);
|
---|
| 162 | }
|
---|
| 163 | }
|
---|
[9522] | 164 | }
|
---|
[3133] | 165 | }
|
---|
| 166 | }
|
---|
| 167 | }
|
---|
[12719] | 168 |
|
---|
| 169 | /**
|
---|
| 170 | * Observes the changeset review model and keeps the tag editor in sync
|
---|
| 171 | * with the current changeset review request
|
---|
| 172 | */
|
---|
| 173 | class ChangesetReviewChangeListener implements ChangeListener {
|
---|
| 174 |
|
---|
[12726] | 175 | private static final String KEY = "review_requested";
|
---|
[12719] | 176 |
|
---|
| 177 | @Override
|
---|
| 178 | public void stateChanged(ChangeEvent e) {
|
---|
| 179 | if (e.getSource() instanceof ChangesetReviewModel) {
|
---|
| 180 | boolean newState = ((ChangesetReviewModel) e.getSource()).isReviewRequested();
|
---|
[12726] | 181 | boolean oldState = "yes".equals(Optional.ofNullable(getTagEditorValue(KEY)).orElse(""));
|
---|
[12719] | 182 | if (oldState != newState) {
|
---|
[12726] | 183 | setProperty(KEY, newState ? "yes" : null);
|
---|
[12719] | 184 | }
|
---|
| 185 | }
|
---|
| 186 | }
|
---|
| 187 | }
|
---|
[2711] | 188 | }
|
---|