001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer.gpx;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.Dimension;
007import java.awt.GridBagLayout;
008
009import javax.swing.JCheckBox;
010import javax.swing.JLabel;
011import javax.swing.JList;
012import javax.swing.JOptionPane;
013import javax.swing.JPanel;
014import javax.swing.JSpinner;
015import javax.swing.SpinnerNumberModel;
016import javax.swing.event.ChangeEvent;
017import javax.swing.event.ChangeListener;
018
019import org.openstreetmap.josm.gui.HelpAwareOptionPane;
020import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
021import org.openstreetmap.josm.gui.MainApplication;
022import org.openstreetmap.josm.gui.download.OSMDownloadSource.OSMDownloadSourcePanel;
023import org.openstreetmap.josm.spi.preferences.Config;
024import org.openstreetmap.josm.tools.GBC;
025import org.openstreetmap.josm.tools.ImageProvider;
026
027/**
028 * Panel displayed in "Download along..." dialogs
029 * @since 6054
030 */
031public class DownloadAlongPanel extends JPanel {
032
033    // Preferences keys
034    private final String prefOsm;
035    private final String prefGps;
036    private final String prefDist;
037    private final String prefArea;
038    private final String prefNear;
039
040    // Data types to download
041    private final JCheckBox cbDownloadOsmData;
042    private final JCheckBox cbDownloadGpxData;
043
044    private final JSpinner buffer;
045    private final JSpinner maxRect;
046    private final JList<String> downloadNear;
047
048    /**
049     * Constructs a new {@code DownloadPanel}.
050     * @param prefOsm Preference key determining if OSM data should be downloaded
051     * @param prefGps Preference key determining if GPS data should be downloaded
052     * @param prefDist Preference key determining maximum distance
053     * @param prefArea Preference key determining maximum area
054     * @param prefNear Preference key determining "near" parameter. Can be {@code null}
055     */
056    public DownloadAlongPanel(String prefOsm, String prefGps, String prefDist, String prefArea, String prefNear) {
057        super(new GridBagLayout());
058
059        this.prefOsm = prefOsm;
060        this.prefGps = prefGps;
061        this.prefDist = prefDist;
062        this.prefArea = prefArea;
063        this.prefNear = prefNear;
064
065        add(new JLabel(tr(OSMDownloadSourcePanel.DATA_SOURCES_AND_TYPES)), GBC.std().insets(5, 5, 1, 5).anchor(GBC.CENTER));
066        cbDownloadOsmData = new JCheckBox(tr("OpenStreetMap data"), Config.getPref().getBoolean(prefOsm, true));
067        cbDownloadOsmData.setToolTipText(tr("Select to download OSM data."));
068        add(cbDownloadOsmData, GBC.std().insets(1, 5, 1, 5));
069        cbDownloadGpxData = new JCheckBox(tr("Raw GPS data"), Config.getPref().getBoolean(prefGps, false));
070        cbDownloadGpxData.setToolTipText(tr("Select to download GPS traces."));
071        add(cbDownloadGpxData, GBC.eol().insets(5, 5, 1, 5));
072
073        add(new JLabel(tr("Download everything within:")), GBC.std());
074        JPanel panel1 = new JPanel(new GridBagLayout());
075        buffer = new JSpinner(new SpinnerNumberModel(Config.getPref().getDouble(prefDist, 50.0), 1.0, 5000.0, 1.0));
076        panel1.add(buffer, GBC.std().insets(5, 5, 5, 5));
077        panel1.add(new JLabel(tr("meters")), GBC.eol());
078        add(panel1, GBC.eol());
079
080        add(new JLabel(tr("Maximum area per request:")), GBC.std());
081        JPanel panel2 = new JPanel(new GridBagLayout());
082        maxRect = new JSpinner(new SpinnerNumberModel(Config.getPref().getDouble(prefArea, 20.0), 0.01, 25.0, 0.01)) {
083            @Override
084            public Dimension getPreferredSize() {
085                return buffer.getPreferredSize();
086            }
087        };
088        panel2.add(maxRect, GBC.std().insets(5, 5, 5, 5));
089        panel2.add(new JLabel("km\u00b2"), GBC.eol());
090        add(panel2, GBC.eol());
091
092        if (prefNear != null) {
093            add(new JLabel(tr("Download near:")), GBC.eol());
094            downloadNear = new JList<>(new String[]{tr("track only"), tr("waypoints only"), tr("track and waypoints")});
095            downloadNear.setSelectedIndex(Config.getPref().getInt(prefNear, 0));
096            add(downloadNear, GBC.eol());
097        } else {
098            downloadNear = null;
099        }
100    }
101
102    /**
103     * Gets the maximum distance in meters
104     * @return The maximum distance, in meters
105     */
106    public final double getDistance() {
107        return (double) buffer.getValue();
108    }
109
110    /**
111     * Gets the maximum area in squared kilometers
112     * @return The maximum distance, in squared kilometers
113     */
114    public final double getArea() {
115        return (double) maxRect.getValue();
116    }
117
118    /**
119     * Gets the "download near" chosen value
120     * @return the "download near" chosen value (0: track only, 1: waypoints only, 2: both)
121     */
122    public final int getNear() {
123        return downloadNear.getSelectedIndex();
124    }
125
126    /**
127     * Replies true if the user selected to download OSM data
128     *
129     * @return true if the user selected to download OSM data
130     */
131    public boolean isDownloadOsmData() {
132        return cbDownloadOsmData.isSelected();
133    }
134
135    /**
136     * Replies true if the user selected to download GPX data
137     *
138     * @return true if the user selected to download GPX data
139     */
140    public boolean isDownloadGpxData() {
141        return cbDownloadGpxData.isSelected();
142    }
143
144    /**
145     * Remembers the current settings in the download panel
146     */
147    protected final void rememberSettings() {
148        Config.getPref().putBoolean(prefOsm, isDownloadOsmData());
149        Config.getPref().putBoolean(prefGps, isDownloadGpxData());
150        Config.getPref().putDouble(prefDist, getDistance());
151        Config.getPref().putDouble(prefArea, getArea());
152        if (prefNear != null) {
153            Config.getPref().putInt(prefNear, getNear());
154        }
155    }
156
157    /**
158     * Adds a change listener to comboboxes
159     * @param listener The listener that will be notified of each combobox change
160     */
161    protected final void addAndFireChangeListener(ChangeListener listener) {
162        cbDownloadGpxData.addChangeListener(listener);
163        cbDownloadOsmData.addChangeListener(listener);
164        listener.stateChanged(new ChangeEvent(this));
165    }
166
167    /**
168     * Show this panel in a new "Download along" help-aware dialog
169     * @param title The dialog title
170     * @param helpTopic The dialog help topic
171     * @return The selected button index (0 for download, 1 for cancel, 2 for dialog closure)
172     */
173    public int showInDownloadDialog(String title, String helpTopic) {
174        final ButtonSpec[] options = {
175                new ButtonSpec(
176                        tr("Download"),
177                        new ImageProvider("download"),
178                        tr("Click to download"),
179                        null // no specific help text
180                ),
181                new ButtonSpec(
182                        tr("Download as new layer"),
183                        new ImageProvider("download_new_layer"),
184                        tr("Click to download into a new data layer"),
185                        null // no specific help text
186                ),
187                new ButtonSpec(
188                        tr("Cancel"),
189                        new ImageProvider("cancel"),
190                        tr("Click to cancel"),
191                        null // no specific help text
192                )
193        };
194
195        addAndFireChangeListener(e -> {
196            boolean somethingToDownload = isDownloadOsmData() || isDownloadGpxData();
197            options[0].setEnabled(somethingToDownload && MainApplication.getLayerManager().getEditLayer() != null);
198            options[1].setEnabled(somethingToDownload);
199        });
200
201        int ret = HelpAwareOptionPane.showOptionDialog(MainApplication.getMainFrame(), this, title,
202                    JOptionPane.QUESTION_MESSAGE, null, options, options[0], helpTopic);
203        if (0 == ret || 1 == ret) {
204            rememberSettings();
205        }
206
207        return ret;
208    }
209}