001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences.projection;
003
004import java.awt.GridBagLayout;
005import java.awt.event.ActionListener;
006import java.util.Collection;
007import java.util.Collections;
008
009import javax.swing.JLabel;
010import javax.swing.JPanel;
011
012import org.openstreetmap.josm.gui.widgets.JosmComboBox;
013import org.openstreetmap.josm.tools.GBC;
014import org.openstreetmap.josm.tools.Utils;
015
016/**
017 * A projection choice, that offers a list of projections in a combo-box.
018 */
019public abstract class ListProjectionChoice extends AbstractProjectionChoice {
020
021    protected int index;        // 0-based index
022    protected int defaultIndex;
023    protected String[] entries;
024    protected String label;
025
026    /**
027     * Constructs a new {@code ListProjectionChoice}.
028     *
029     * @param name the display name
030     * @param id the unique id for this ProjectionChoice
031     * @param entries the list of display entries for the combo-box
032     * @param label a label shown left to the combo-box
033     * @param defaultIndex the default index for the combo-box
034     */
035    protected ListProjectionChoice(String name, String id, String[] entries, String label, int defaultIndex) {
036        super(name, id);
037        this.entries = Utils.copyArray(entries);
038        this.label = label;
039        this.defaultIndex = defaultIndex;
040    }
041
042    /**
043     * Constructs a new {@code ListProjectionChoice}.
044     * @param name the display name
045     * @param id the unique id for this ProjectionChoice
046     * @param entries the list of display entries for the combo-box
047     * @param label a label shown left to the combo-box
048     */
049    protected ListProjectionChoice(String name, String id, String[] entries, String label) {
050        this(name, id, entries, label, 0);
051    }
052
053    /**
054     * Convert 0-based index to preference value.
055     * @param idx 0-based index
056     * @return preference value
057     * @see #zoneToIndex
058     */
059    protected abstract String indexToZone(int idx);
060
061    /**
062     * Convert preference value to 0-based index.
063     * @param zone preference value
064     * @return 0-based index
065     * @see #indexToZone
066     */
067    protected abstract int zoneToIndex(String zone);
068
069    @Override
070    public void setPreferences(Collection<String> args) {
071        String zone = null;
072        if (!Utils.isEmpty(args)) {
073            zone = args.iterator().next();
074        }
075        int idx;
076        if (zone == null) {
077            idx = defaultIndex;
078        } else {
079            idx = zoneToIndex(zone);
080            if (idx < 0 || idx >= entries.length) {
081                idx = defaultIndex;
082            }
083        }
084        this.index = idx;
085    }
086
087    protected static class CBPanel extends JPanel {
088        public JosmComboBox<String> prefcb;
089
090        public CBPanel(String[] entries, int initialIndex, String label, final ActionListener listener) {
091            prefcb = new JosmComboBox<>(entries);
092
093            prefcb.setSelectedIndex(initialIndex);
094            this.setLayout(new GridBagLayout());
095            this.add(new JLabel(label), GBC.std().insets(5, 5, 0, 5));
096            this.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL));
097            this.add(prefcb, GBC.eop().fill(GBC.HORIZONTAL));
098            this.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH));
099
100            if (listener != null) {
101                prefcb.addActionListener(listener);
102            }
103        }
104    }
105
106    @Override
107    public JPanel getPreferencePanel(ActionListener listener) {
108        return new CBPanel(entries, index, label, listener);
109    }
110
111    @Override
112    public Collection<String> getPreferences(JPanel panel) {
113        if (!(panel instanceof CBPanel)) {
114            throw new IllegalArgumentException("Unsupported panel: "+panel);
115        }
116        CBPanel p = (CBPanel) panel;
117        int idx = p.prefcb.getSelectedIndex();
118        return Collections.singleton(indexToZone(idx));
119    }
120}