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

Last change on this file since 17160 was 17160, checked in by simon04, 4 years ago

see #7548 - Re-organize the preference dialog (connection preferences)

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