1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.gui.io;
|
---|
3 |
|
---|
4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
5 |
|
---|
6 | import java.util.Collection;
|
---|
7 | import java.util.Collections;
|
---|
8 | import java.util.Objects;
|
---|
9 |
|
---|
10 | import javax.swing.JLabel;
|
---|
11 | import javax.swing.text.JTextComponent;
|
---|
12 |
|
---|
13 | import org.openstreetmap.josm.data.osm.BBox;
|
---|
14 | import org.openstreetmap.josm.data.osm.IPrimitive;
|
---|
15 | import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
|
---|
16 | import org.openstreetmap.josm.spi.preferences.Config;
|
---|
17 | import org.openstreetmap.josm.tools.Utils;
|
---|
18 |
|
---|
19 | /**
|
---|
20 | * Input validators for {@link UploadDialog}
|
---|
21 | */
|
---|
22 | abstract class UploadTextComponentValidator extends AbstractTextComponentValidator {
|
---|
23 | private final JLabel feedback;
|
---|
24 | protected boolean uploadRejected;
|
---|
25 |
|
---|
26 | UploadTextComponentValidator(JTextComponent tc, JLabel feedback) {
|
---|
27 | super(tc);
|
---|
28 | this.feedback = feedback;
|
---|
29 | this.feedback.setOpaque(true);
|
---|
30 | validate();
|
---|
31 | }
|
---|
32 |
|
---|
33 | @Override
|
---|
34 | protected void feedbackValid(String msg) {
|
---|
35 | msg = msg != null ? "<html>\u2714 " + msg : null;
|
---|
36 | super.feedbackValid(msg);
|
---|
37 | if (!Objects.equals(msg, feedback.getText())) {
|
---|
38 | feedback.setText(msg);
|
---|
39 | feedback.setForeground(VALID_COLOR);
|
---|
40 | feedback.setBackground(null);
|
---|
41 | feedback.setBorder(null);
|
---|
42 | }
|
---|
43 | }
|
---|
44 |
|
---|
45 | @Override
|
---|
46 | protected void feedbackWarning(String msg) {
|
---|
47 | msg = msg != null ? "<html>" + msg : null;
|
---|
48 | super.feedbackWarning(msg);
|
---|
49 | if (!Objects.equals(msg, feedback.getText())) {
|
---|
50 | feedback.setText(msg);
|
---|
51 | feedback.setForeground(WARNING_FOREGROUND);
|
---|
52 | feedback.setBackground(WARNING_BACKGROUND);
|
---|
53 | feedback.setBorder(WARNING_BORDER);
|
---|
54 | }
|
---|
55 | }
|
---|
56 |
|
---|
57 | @Override
|
---|
58 | public boolean isValid() {
|
---|
59 | throw new UnsupportedOperationException();
|
---|
60 | }
|
---|
61 |
|
---|
62 | /**
|
---|
63 | * Determines if the input validator considers the violation bad enough to reject upload.
|
---|
64 | * @return {@code true} if the input validator considers the violation bad enough to reject upload
|
---|
65 | * @since 17238
|
---|
66 | */
|
---|
67 | public final boolean isUploadRejected() {
|
---|
68 | return uploadRejected;
|
---|
69 | }
|
---|
70 |
|
---|
71 | /**
|
---|
72 | * Validator for the changeset {@code comment} tag
|
---|
73 | */
|
---|
74 | static class UploadCommentValidator extends UploadTextComponentValidator {
|
---|
75 |
|
---|
76 | UploadCommentValidator(JTextComponent tc, JLabel feedback) {
|
---|
77 | super(tc, feedback);
|
---|
78 | }
|
---|
79 |
|
---|
80 | @Override
|
---|
81 | public void validate() {
|
---|
82 | if (!Config.getPref().getBoolean("message.upload_comment_is_empty_or_very_short", true)) {
|
---|
83 | feedbackDisabled();
|
---|
84 | return;
|
---|
85 | }
|
---|
86 | final String uploadComment = getComponent().getText();
|
---|
87 | final String rejection = UploadDialog.UploadAction.validateUploadTag(uploadComment, "upload.comment",
|
---|
88 | Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
|
---|
89 |
|
---|
90 | // Reject the upload if tags are required and are not in the input. If the tags exist or are not
|
---|
91 | // required, then check the length of the input and warn if it's too short (a short msg is not a rejection)
|
---|
92 | uploadRejected = rejection != null;
|
---|
93 |
|
---|
94 | if (uploadRejected) {
|
---|
95 | feedbackWarning(tr("Your upload comment is <i>rejected</i>.") + "<br />" + rejection);
|
---|
96 | } else if (UploadDialog.UploadAction.isUploadCommentTooShort(uploadComment)) {
|
---|
97 | feedbackWarning(tr("Your upload comment is <i>empty</i>, or <i>very short</i>.<br /><br />" +
|
---|
98 | "This is technically allowed, but please consider that many users who are<br />" +
|
---|
99 | "watching changes in their area depend on meaningful changeset comments<br />" +
|
---|
100 | "to understand what is going on!<br /><br />" +
|
---|
101 | "If you spend a minute now to explain your change, you will make life<br />" +
|
---|
102 | "easier for many other mappers.").replace("<br />", " "));
|
---|
103 | } else {
|
---|
104 | feedbackValid(tr("Thank you for providing a changeset comment! " +
|
---|
105 | "This gives other mappers a better understanding of your intent."));
|
---|
106 | }
|
---|
107 | }
|
---|
108 | }
|
---|
109 |
|
---|
110 | /**
|
---|
111 | * Validator for the changeset {@code source} tag
|
---|
112 | */
|
---|
113 | static class UploadSourceValidator extends UploadTextComponentValidator {
|
---|
114 |
|
---|
115 | UploadSourceValidator(JTextComponent tc, JLabel feedback) {
|
---|
116 | super(tc, feedback);
|
---|
117 | }
|
---|
118 |
|
---|
119 | @Override
|
---|
120 | public void validate() {
|
---|
121 | if (!Config.getPref().getBoolean("message.upload_source_is_empty", true)) {
|
---|
122 | feedbackDisabled();
|
---|
123 | return;
|
---|
124 | }
|
---|
125 | final String uploadSource = getComponent().getText();
|
---|
126 | final String rejection = UploadDialog.UploadAction.validateUploadTag(
|
---|
127 | uploadSource, "upload.source", Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
|
---|
128 |
|
---|
129 | // Reject the upload only if tags are required and are not in the input. If the tags exist or are not
|
---|
130 | // required, then check the length of the input and warn if it's too short (a short msg is not a rejection)
|
---|
131 | uploadRejected = rejection != null;
|
---|
132 |
|
---|
133 | if (uploadRejected) {
|
---|
134 | feedbackWarning(tr("Your changeset source is <i>rejected</i>.") + "<br />" + rejection);
|
---|
135 | } else if (Utils.isStripEmpty(uploadSource)) {
|
---|
136 | feedbackWarning(tr("You did not specify a source for your changes.<br />" +
|
---|
137 | "It is technically allowed, but this information helps<br />" +
|
---|
138 | "other users to understand the origins of the data.<br /><br />" +
|
---|
139 | "If you spend a minute now to explain your change, you will make life<br />" +
|
---|
140 | "easier for many other mappers.").replace("<br />", " "));
|
---|
141 | } else {
|
---|
142 | feedbackValid(tr("Thank you for providing the data source!"));
|
---|
143 | }
|
---|
144 | }
|
---|
145 | }
|
---|
146 |
|
---|
147 | /**
|
---|
148 | * Validator for the changeset area
|
---|
149 | */
|
---|
150 | static class UploadAreaValidator extends UploadTextComponentValidator {
|
---|
151 | private double area = Double.NaN;
|
---|
152 |
|
---|
153 | UploadAreaValidator(JTextComponent tc, JLabel feedback) {
|
---|
154 | super(tc, feedback);
|
---|
155 | }
|
---|
156 |
|
---|
157 | void computeArea(Collection<? extends IPrimitive> primitives) {
|
---|
158 | this.area = primitives.stream()
|
---|
159 | .map(IPrimitive::getBBox)
|
---|
160 | .reduce(new BBox(), (b1, b2) -> {
|
---|
161 | b1.add(b2);
|
---|
162 | return b1;
|
---|
163 | }).area();
|
---|
164 | validate();
|
---|
165 | }
|
---|
166 |
|
---|
167 | @Override
|
---|
168 | public void validate() {
|
---|
169 | if (Double.isFinite(area) && area <= Config.getPref().getDouble("upload.max-area", 3.)) {
|
---|
170 | feedbackValid(null);
|
---|
171 | } else {
|
---|
172 | feedbackWarning(tr("The bounding box of this changeset is very large – please consider splitting your changes!"));
|
---|
173 | }
|
---|
174 | }
|
---|
175 | }
|
---|
176 | }
|
---|