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

Last change on this file since 6653 was 6653, checked in by simon04, 10 years ago

Preference dialog: allow to toggle the "Use the default OSM server URL" check box by clicking on the text

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