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

Last change on this file since 12841 was 12841, checked in by bastiK, 5 weeks ago

see #15229 - fix deprecations caused by [12840]

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