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

Last change on this file since 15020 was 15020, checked in by GerdP, 5 years ago

fix checkstyle issues

  • Property svn:eol-style set to native
File size: 11.0 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.Insets;
10import java.awt.event.ActionEvent;
11import java.awt.event.ActionListener;
12import java.awt.event.FocusAdapter;
13import java.awt.event.FocusEvent;
14import java.awt.event.ItemEvent;
15import java.awt.event.ItemListener;
16import java.util.Arrays;
17
18import javax.swing.AbstractAction;
19import javax.swing.JButton;
20import javax.swing.JCheckBox;
21import javax.swing.JComponent;
22import javax.swing.JLabel;
23import javax.swing.JPanel;
24import javax.swing.SwingUtilities;
25import javax.swing.event.DocumentEvent;
26import javax.swing.event.DocumentListener;
27import javax.swing.text.JTextComponent;
28
29import org.openstreetmap.josm.data.preferences.ListProperty;
30import org.openstreetmap.josm.gui.MainApplication;
31import org.openstreetmap.josm.gui.help.HelpUtil;
32import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
33import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
34import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
35import org.openstreetmap.josm.io.OsmApi;
36import org.openstreetmap.josm.io.OsmApiInitializationException;
37import org.openstreetmap.josm.io.OsmTransferCanceledException;
38import org.openstreetmap.josm.spi.preferences.Config;
39import org.openstreetmap.josm.spi.preferences.IUrls;
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 GridBagConstraints gc = new GridBagConstraints();
85
86 // the checkbox for the default UL
87 gc.fill = GridBagConstraints.HORIZONTAL;
88 gc.anchor = GridBagConstraints.NORTHWEST;
89 gc.weightx = 1.0;
90 gc.insets = new Insets(0, 0, 0, 0);
91 gc.gridwidth = 4;
92 add(buildDefaultServerUrlPanel(), gc);
93
94
95 // the input field for the URL
96 gc.gridx = 0;
97 gc.gridy = 1;
98 gc.gridwidth = 1;
99 gc.weightx = 0.0;
100 gc.insets = new Insets(0, 0, 0, 3);
101 add(lblApiUrl, gc);
102
103 gc.gridx = 1;
104 gc.weightx = 1.0;
105 add(tfOsmServerUrl, gc);
106 lblApiUrl.setLabelFor(tfOsmServerUrl);
107 SelectAllOnFocusGainedDecorator.decorate(tfOsmServerUrl.getEditorComponent());
108 valOsmServerUrl = new ApiUrlValidator(tfOsmServerUrl.getEditorComponent());
109 valOsmServerUrl.validate();
110 propagator = new ApiUrlPropagator();
111 tfOsmServerUrl.addActionListener(propagator);
112 tfOsmServerUrl.addFocusListener(propagator);
113
114 gc.gridx = 2;
115 gc.weightx = 0.0;
116 add(lblValid, gc);
117
118 gc.gridx = 3;
119 gc.weightx = 0.0;
120 ValidateApiUrlAction actTest = new ValidateApiUrlAction();
121 tfOsmServerUrl.getEditorComponent().getDocument().addDocumentListener(actTest);
122 btnTest = new JButton(actTest);
123 add(btnTest, gc);
124 }
125
126 /**
127 * Initializes the configuration panel with values from the preferences
128 */
129 public void initFromPreferences() {
130 String url = OsmApi.getOsmApi().getServerUrl();
131 tfOsmServerUrl.setPossibleItems(SERVER_URL_HISTORY.get());
132 if (Config.getUrls().getDefaultOsmApiUrl().equals(url.trim())) {
133 cbUseDefaultServerUrl.setSelected(true);
134 propagator.propagate(Config.getUrls().getDefaultOsmApiUrl());
135 } else {
136 cbUseDefaultServerUrl.setSelected(false);
137 tfOsmServerUrl.setText(url);
138 propagator.propagate(url);
139 }
140 }
141
142 /**
143 * Saves the values to the preferences
144 */
145 public void saveToPreferences() {
146 String oldUrl = OsmApi.getOsmApi().getServerUrl();
147 String hmiUrl = getStrippedApiUrl();
148 if (cbUseDefaultServerUrl.isSelected() || Config.getUrls().getDefaultOsmApiUrl().equals(hmiUrl)) {
149 Config.getPref().put("osm-server.url", null);
150 } else {
151 Config.getPref().put("osm-server.url", hmiUrl);
152 tfOsmServerUrl.addCurrentItemToHistory();
153 SERVER_URL_HISTORY.put(tfOsmServerUrl.getHistory());
154 }
155 String newUrl = OsmApi.getOsmApi().getServerUrl();
156
157 // When API URL changes, re-initialize API connection so we may adjust server-dependent settings.
158 if (!oldUrl.equals(newUrl)) {
159 try {
160 OsmApi.getOsmApi().initialize(null);
161 } catch (OsmTransferCanceledException | OsmApiInitializationException ex) {
162 Logging.warn(ex);
163 }
164 }
165 }
166
167 /**
168 * Returns the entered API URL, stripped of leading and trailing white characters.
169 * @return the entered API URL, stripped of leading and trailing white characters. May be an empty string
170 * if nothing has been entered. In this case, it means the user wants to use {@link IUrls#getDefaultOsmApiUrl}.
171 * @see Utils#strip(String)
172 * @since 6602
173 */
174 public final String getStrippedApiUrl() {
175 return Utils.strip(tfOsmServerUrl.getText());
176 }
177
178 class ValidateApiUrlAction extends AbstractAction implements DocumentListener {
179 private String lastTestedUrl;
180
181 ValidateApiUrlAction() {
182 putValue(NAME, tr("Validate"));
183 putValue(SHORT_DESCRIPTION, tr("Test the API URL"));
184 updateEnabledState();
185 }
186
187 @Override
188 public void actionPerformed(ActionEvent arg0) {
189 final String url = getStrippedApiUrl();
190 final ApiUrlTestTask task = new ApiUrlTestTask(OsmApiUrlInputPanel.this, url);
191 MainApplication.worker.submit(task);
192 Runnable r = () -> {
193 if (task.isCanceled())
194 return;
195 Runnable r1 = () -> {
196 if (task.isSuccess()) {
197 lblValid.setIcon(ImageProvider.get("misc", "green_check"));
198 lblValid.setToolTipText(tr("The API URL is valid."));
199 lastTestedUrl = url;
200 updateEnabledState();
201 } else {
202 lblValid.setIcon(ImageProvider.get("warning-small"));
203 lblValid.setToolTipText(tr("Validation failed. The API URL seems to be invalid."));
204 }
205 };
206 SwingUtilities.invokeLater(r1);
207 };
208 MainApplication.worker.submit(r);
209 }
210
211 protected final void updateEnabledState() {
212 String url = getStrippedApiUrl();
213 boolean enabled = !url.isEmpty() && !url.equals(lastTestedUrl);
214 if (enabled) {
215 lblValid.setIcon(null);
216 }
217 setEnabled(enabled);
218 }
219
220 @Override
221 public void changedUpdate(DocumentEvent arg0) {
222 updateEnabledState();
223 }
224
225 @Override
226 public void insertUpdate(DocumentEvent arg0) {
227 updateEnabledState();
228 }
229
230 @Override
231 public void removeUpdate(DocumentEvent arg0) {
232 updateEnabledState();
233 }
234 }
235
236 /**
237 * Enables or disables the API URL input.
238 * @param enabled {@code true} to enable input, {@code false} otherwise
239 */
240 public void setApiUrlInputEnabled(boolean enabled) {
241 lblApiUrl.setEnabled(enabled);
242 tfOsmServerUrl.setEnabled(enabled);
243 lblValid.setEnabled(enabled);
244 btnTest.setEnabled(enabled);
245 }
246
247 private static class ApiUrlValidator extends AbstractTextComponentValidator {
248 ApiUrlValidator(JTextComponent tc) {
249 super(tc);
250 }
251
252 @Override
253 public boolean isValid() {
254 if (getComponent().getText().trim().isEmpty())
255 return false;
256 return Utils.isValidUrl(getComponent().getText().trim());
257 }
258
259 @Override
260 public void validate() {
261 if (getComponent().getText().trim().isEmpty()) {
262 feedbackInvalid(tr("OSM API URL must not be empty. Please enter the OSM API URL."));
263 return;
264 }
265 if (!isValid()) {
266 feedbackInvalid(tr("The current value is not a valid URL"));
267 } else {
268 feedbackValid(tr("Please enter the OSM API URL."));
269 }
270 }
271 }
272
273 /**
274 * Handles changes in the default URL
275 */
276 class UseDefaultServerUrlChangeHandler implements ItemListener {
277 @Override
278 public void itemStateChanged(ItemEvent e) {
279 switch(e.getStateChange()) {
280 case ItemEvent.SELECTED:
281 setApiUrlInputEnabled(false);
282 propagator.propagate(Config.getUrls().getDefaultOsmApiUrl());
283 break;
284 case ItemEvent.DESELECTED:
285 setApiUrlInputEnabled(true);
286 valOsmServerUrl.validate();
287 tfOsmServerUrl.requestFocusInWindow();
288 propagator.propagate();
289 break;
290 default: // Do nothing
291 }
292 }
293 }
294
295 class ApiUrlPropagator extends FocusAdapter implements ActionListener {
296 protected void propagate() {
297 propagate(getStrippedApiUrl());
298 }
299
300 protected void propagate(String url) {
301 firePropertyChange(API_URL_PROP, null, url);
302 }
303
304 @Override
305 public void actionPerformed(ActionEvent e) {
306 propagate();
307 }
308
309 @Override
310 public void focusLost(FocusEvent arg0) {
311 propagate();
312 }
313 }
314}
Note: See TracBrowser for help on using the repository browser.