source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/server/OsmApiUrlInputPanel.java

Last change on this file was 19050, checked in by taylor.smock, 3 days ago

Revert most var changes from r19048, fix most new compile warnings and checkstyle issues

Also, document why various ErrorProne checks were originally disabled and fix
generic SonarLint issues.

  • Property svn:eol-style set to native
File size: 10.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.server;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Font;
7import java.awt.GridBagConstraints;
8import java.awt.GridBagLayout;
9import java.awt.event.ActionEvent;
10import java.awt.event.ActionListener;
11import java.awt.event.FocusAdapter;
12import java.awt.event.FocusEvent;
13import java.awt.event.ItemEvent;
14import java.awt.event.ItemListener;
15import java.util.Arrays;
16
17import javax.swing.AbstractAction;
18import javax.swing.JButton;
19import javax.swing.JCheckBox;
20import javax.swing.JComponent;
21import javax.swing.JLabel;
22import javax.swing.JPanel;
23import javax.swing.SwingUtilities;
24import javax.swing.event.DocumentEvent;
25import javax.swing.event.DocumentListener;
26import javax.swing.text.JTextComponent;
27
28import org.openstreetmap.josm.data.preferences.ListProperty;
29import org.openstreetmap.josm.gui.MainApplication;
30import org.openstreetmap.josm.gui.help.HelpUtil;
31import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
32import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
33import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
34import org.openstreetmap.josm.io.OsmApi;
35import org.openstreetmap.josm.io.OsmApiInitializationException;
36import org.openstreetmap.josm.io.OsmTransferCanceledException;
37import org.openstreetmap.josm.spi.preferences.Config;
38import org.openstreetmap.josm.spi.preferences.IUrls;
39import org.openstreetmap.josm.tools.GBC;
40import org.openstreetmap.josm.tools.ImageProvider;
41import org.openstreetmap.josm.tools.Logging;
42import org.openstreetmap.josm.tools.Utils;
43
44/**
45 * Component allowing input os OSM API URL.
46 */
47public class OsmApiUrlInputPanel extends JPanel {
48
49 /**
50 * OSM API URL property key.
51 */
52 public static final String API_URL_PROP = OsmApiUrlInputPanel.class.getName() + ".apiUrl";
53
54 private final JLabel lblValid = new JLabel();
55 private final JLabel lblApiUrl = new JLabel(tr("OSM Server URL:"));
56 private final HistoryComboBox tfOsmServerUrl = new HistoryComboBox();
57 private transient ApiUrlValidator valOsmServerUrl;
58 private JButton btnTest;
59 /** indicates whether to use the default OSM URL or not */
60 private JCheckBox cbUseDefaultServerUrl;
61 private final transient ListProperty SERVER_URL_HISTORY = new ListProperty("osm-server.url-history", Arrays.asList(
62 "https://api06.dev.openstreetmap.org/api", "https://master.apis.dev.openstreetmap.org/api"));
63
64 private transient ApiUrlPropagator propagator;
65
66 /**
67 * Constructs a new {@code OsmApiUrlInputPanel}.
68 */
69 public OsmApiUrlInputPanel() {
70 build();
71 HelpUtil.setHelpContext(this, HelpUtil.ht("/Preferences/Connection#ApiUrl"));
72 }
73
74 protected JComponent buildDefaultServerUrlPanel() {
75 cbUseDefaultServerUrl = new JCheckBox(
76 tr("<html>Use the default OSM server URL (<strong>{0}</strong>)</html>", Config.getUrls().getDefaultOsmApiUrl()));
77 cbUseDefaultServerUrl.addItemListener(new UseDefaultServerUrlChangeHandler());
78 cbUseDefaultServerUrl.setFont(cbUseDefaultServerUrl.getFont().deriveFont(Font.PLAIN));
79 return cbUseDefaultServerUrl;
80 }
81
82 protected final void build() {
83 setLayout(new GridBagLayout());
84
85 // the checkbox for the default UL
86 add(buildDefaultServerUrlPanel(), GBC.eop().fill(GridBagConstraints.HORIZONTAL));
87
88 // the input field for the URL
89 add(lblApiUrl, GBC.std().insets(0, 0, 3, 0));
90 add(tfOsmServerUrl, GBC.std().fill(GridBagConstraints.HORIZONTAL).insets(0, 0, 3, 0));
91 lblApiUrl.setLabelFor(tfOsmServerUrl);
92 SelectAllOnFocusGainedDecorator.decorate(tfOsmServerUrl.getEditorComponent());
93 valOsmServerUrl = new ApiUrlValidator(tfOsmServerUrl.getEditorComponent());
94 valOsmServerUrl.validate();
95 propagator = new ApiUrlPropagator();
96 tfOsmServerUrl.addActionListener(propagator);
97 tfOsmServerUrl.addFocusListener(propagator);
98
99 add(lblValid, GBC.std().insets(0, 0, 3, 0));
100
101 ValidateApiUrlAction actTest = new ValidateApiUrlAction();
102 tfOsmServerUrl.getEditorComponent().getDocument().addDocumentListener(actTest);
103 btnTest = new JButton(actTest);
104 add(btnTest, GBC.eop());
105 }
106
107 /**
108 * Initializes the configuration panel with values from the preferences
109 */
110 public void initFromPreferences() {
111 String url = OsmApi.getOsmApi().getServerUrl();
112 tfOsmServerUrl.getModel().prefs().load(SERVER_URL_HISTORY);
113 if (Config.getUrls().getDefaultOsmApiUrl().equals(url.trim())) {
114 cbUseDefaultServerUrl.setSelected(true);
115 propagator.propagate(Config.getUrls().getDefaultOsmApiUrl());
116 } else {
117 cbUseDefaultServerUrl.setSelected(false);
118 tfOsmServerUrl.setText(url);
119 propagator.propagate(url);
120 }
121 }
122
123 /**
124 * Saves the values to the preferences
125 */
126 public void saveToPreferences() {
127 String oldUrl = OsmApi.getOsmApi().getServerUrl();
128 String hmiUrl = getStrippedApiUrl();
129 if (cbUseDefaultServerUrl.isSelected() || Config.getUrls().getDefaultOsmApiUrl().equals(hmiUrl)) {
130 Config.getPref().put("osm-server.url", null);
131 } else {
132 Config.getPref().put("osm-server.url", hmiUrl);
133 tfOsmServerUrl.addCurrentItemToHistory();
134 tfOsmServerUrl.getModel().prefs().save(SERVER_URL_HISTORY);
135 }
136 String newUrl = OsmApi.getOsmApi().getServerUrl();
137
138 // When API URL changes, re-initialize API connection so we may adjust server-dependent settings.
139 if (!oldUrl.equals(newUrl)) {
140 try {
141 OsmApi.getOsmApi().initialize(null);
142 } catch (OsmTransferCanceledException | OsmApiInitializationException ex) {
143 Logging.warn(ex);
144 }
145 }
146 }
147
148 /**
149 * Returns the entered API URL, stripped of leading and trailing white characters.
150 * @return the entered API URL, stripped of leading and trailing white characters. May be an empty string
151 * if nothing has been entered. In this case, it means the user wants to use {@link IUrls#getDefaultOsmApiUrl}.
152 * @see Utils#strip(String)
153 * @since 6602
154 */
155 public final String getStrippedApiUrl() {
156 return Utils.strip(tfOsmServerUrl.getText());
157 }
158
159 class ValidateApiUrlAction extends AbstractAction implements DocumentListener {
160 private String lastTestedUrl;
161
162 ValidateApiUrlAction() {
163 putValue(NAME, tr("Validate"));
164 putValue(SHORT_DESCRIPTION, tr("Test the API URL"));
165 updateEnabledState();
166 }
167
168 @Override
169 public void actionPerformed(ActionEvent arg0) {
170 final String url = getStrippedApiUrl();
171 final ApiUrlTestTask task = new ApiUrlTestTask(OsmApiUrlInputPanel.this, url);
172 MainApplication.worker.submit(task);
173 Runnable r = () -> {
174 if (task.isCanceled())
175 return;
176 Runnable r1 = () -> {
177 if (task.isSuccess()) {
178 lblValid.setIcon(ImageProvider.get("misc", "green_check"));
179 lblValid.setToolTipText(tr("The API URL is valid."));
180 lastTestedUrl = url;
181 updateEnabledState();
182 } else {
183 lblValid.setIcon(ImageProvider.get("warning-small"));
184 lblValid.setToolTipText(tr("Validation failed. The API URL seems to be invalid."));
185 }
186 };
187 SwingUtilities.invokeLater(r1);
188 };
189 MainApplication.worker.submit(r);
190 }
191
192 protected final void updateEnabledState() {
193 String url = getStrippedApiUrl();
194 boolean enabled = !url.isEmpty() && !url.equals(lastTestedUrl);
195 if (enabled) {
196 lblValid.setIcon(null);
197 }
198 setEnabled(enabled);
199 }
200
201 @Override
202 public void changedUpdate(DocumentEvent arg0) {
203 updateEnabledState();
204 }
205
206 @Override
207 public void insertUpdate(DocumentEvent arg0) {
208 updateEnabledState();
209 }
210
211 @Override
212 public void removeUpdate(DocumentEvent arg0) {
213 updateEnabledState();
214 }
215 }
216
217 /**
218 * Enables or disables the API URL input.
219 * @param enabled {@code true} to enable input, {@code false} otherwise
220 */
221 public void setApiUrlInputEnabled(boolean enabled) {
222 lblApiUrl.setEnabled(enabled);
223 tfOsmServerUrl.setEnabled(enabled);
224 lblValid.setEnabled(enabled);
225 btnTest.setEnabled(enabled);
226 }
227
228 private static class ApiUrlValidator extends AbstractTextComponentValidator {
229 ApiUrlValidator(JTextComponent tc) {
230 super(tc);
231 }
232
233 @Override
234 public boolean isValid() {
235 if (getComponent().getText().trim().isEmpty())
236 return false;
237 return Utils.isValidUrl(getComponent().getText().trim());
238 }
239
240 @Override
241 public void validate() {
242 if (getComponent().getText().trim().isEmpty()) {
243 feedbackInvalid(tr("OSM API URL must not be empty. Please enter the OSM API URL."));
244 return;
245 }
246 if (!isValid()) {
247 feedbackInvalid(tr("The current value is not a valid URL"));
248 } else {
249 feedbackValid(tr("Please enter the OSM API URL."));
250 }
251 }
252 }
253
254 /**
255 * Handles changes in the default URL
256 */
257 class UseDefaultServerUrlChangeHandler implements ItemListener {
258 @Override
259 public void itemStateChanged(ItemEvent e) {
260 switch (e.getStateChange()) {
261 case ItemEvent.SELECTED:
262 setApiUrlInputEnabled(false);
263 propagator.propagate(Config.getUrls().getDefaultOsmApiUrl());
264 break;
265 case ItemEvent.DESELECTED:
266 setApiUrlInputEnabled(true);
267 valOsmServerUrl.validate();
268 tfOsmServerUrl.requestFocusInWindow();
269 propagator.propagate();
270 break;
271 default: // Do nothing
272 }
273 }
274 }
275
276 class ApiUrlPropagator extends FocusAdapter implements ActionListener {
277 protected void propagate() {
278 propagate(getStrippedApiUrl());
279 }
280
281 protected void propagate(String url) {
282 firePropertyChange(API_URL_PROP, null, url);
283 }
284
285 @Override
286 public void actionPerformed(ActionEvent e) {
287 propagate();
288 }
289
290 @Override
291 public void focusLost(FocusEvent arg0) {
292 propagate();
293 }
294 }
295}
Note: See TracBrowser for help on using the repository browser.