001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences.projection;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.GridBagLayout;
007import java.awt.event.ActionListener;
008import java.util.ArrayList;
009import java.util.Arrays;
010import java.util.Collection;
011import java.util.List;
012
013import javax.swing.ButtonGroup;
014import javax.swing.JLabel;
015import javax.swing.JPanel;
016import javax.swing.JRadioButton;
017
018import org.openstreetmap.josm.Main;
019import org.openstreetmap.josm.tools.GBC;
020
021public class UTMProjectionChoice extends ListProjectionChoice {
022
023    /** Earth emispheres **/
024    public enum Hemisphere {
025        /** North emisphere */
026        North,
027        /** South emisphere */
028        South
029    }
030
031    private static final Hemisphere DEFAULT_HEMISPHERE = Hemisphere.North;
032
033    private Hemisphere hemisphere;
034
035    private static final List<String> cbEntries = new ArrayList<>();
036    static {
037        for (int i = 1; i <= 60; i++) {
038            cbEntries.add(Integer.toString(i));
039        }
040    }
041
042    /**
043     * Constructs a new {@code UTMProjectionChoice}.
044     */
045    public UTMProjectionChoice() {
046        super(tr("UTM"), /* NO-ICON */ "core:utm", cbEntries.toArray(new String[0]), tr("UTM Zone"));
047    }
048
049    private class UTMPanel extends CBPanel {
050
051        public JRadioButton north, south;
052
053        UTMPanel(String[] entries, int initialIndex, String label, ActionListener listener) {
054            super(entries, initialIndex, label, listener);
055
056            north = new JRadioButton();
057            north.setSelected(hemisphere == Hemisphere.North);
058            south = new JRadioButton();
059            south.setSelected(hemisphere == Hemisphere.South);
060
061            ButtonGroup group = new ButtonGroup();
062            group.add(north);
063            group.add(south);
064
065            JPanel bPanel = new JPanel();
066            bPanel.setLayout(new GridBagLayout());
067
068            bPanel.add(new JLabel(tr("North")), GBC.std().insets(5, 5, 0, 5));
069            bPanel.add(north, GBC.std().fill(GBC.HORIZONTAL));
070            bPanel.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL));
071            bPanel.add(new JLabel(tr("South")), GBC.std().insets(5, 5, 0, 5));
072            bPanel.add(south, GBC.std().fill(GBC.HORIZONTAL));
073            bPanel.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH));
074
075            this.add(new JLabel(tr("Hemisphere")), GBC.std().insets(5, 5, 0, 5));
076            this.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL));
077            this.add(bPanel, GBC.eop().fill(GBC.HORIZONTAL));
078            this.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH));
079
080            if (listener != null) {
081                north.addActionListener(listener);
082                south.addActionListener(listener);
083            }
084        }
085    }
086
087    @Override
088    public JPanel getPreferencePanel(ActionListener listener) {
089        return new UTMPanel(entries, index, label, listener);
090    }
091
092    @Override
093    public String getCurrentCode() {
094        int zone = index + 1;
095        int code = 32600 + zone + (hemisphere == Hemisphere.South ? 100 : 0);
096        return "EPSG:" + Integer.toString(code);
097    }
098
099    @Override
100    public String getProjectionName() {
101        return tr("UTM");
102    }
103
104    @Override
105    public Collection<String> getPreferences(JPanel panel) {
106        if (!(panel instanceof UTMPanel)) {
107            throw new IllegalArgumentException("Unsupported panel: "+panel);
108        }
109        UTMPanel p = (UTMPanel) panel;
110        int idx = p.prefcb.getSelectedIndex();
111        Hemisphere hem = p.south.isSelected() ? Hemisphere.South : Hemisphere.North;
112        return Arrays.asList(indexToZone(idx), hem.toString());
113    }
114
115    @Override
116    public String[] allCodes() {
117        List<String> projections = new ArrayList<>(60*4);
118        for (int zone = 1; zone <= 60; zone++) {
119            for (Hemisphere hem : Hemisphere.values()) {
120                projections.add("EPSG:" + (32600 + zone + (hem == Hemisphere.South ? 100 : 0)));
121            }
122        }
123        return projections.toArray(new String[projections.size()]);
124    }
125
126    @Override
127    public Collection<String> getPreferencesFromCode(String code) {
128
129        if (code.startsWith("EPSG:326") || code.startsWith("EPSG:327")) {
130            try {
131                Hemisphere hem = code.charAt(7) == '6' ? Hemisphere.North : Hemisphere.South;
132                String zonestring = code.substring(8);
133                int zoneval = Integer.parseInt(zonestring);
134                if (zoneval > 0 && zoneval <= 60)
135                    return Arrays.asList(zonestring, hem.toString());
136            } catch (NumberFormatException e) {
137                Main.warn(e);
138            }
139        }
140        return null;
141    }
142
143    @Override
144    public void setPreferences(Collection<String> args) {
145        super.setPreferences(args);
146        Hemisphere hem = DEFAULT_HEMISPHERE;
147
148        if (args != null) {
149            String[] array = args.toArray(new String[args.size()]);
150
151            if (array.length > 1) {
152                hem = Hemisphere.valueOf(array[1]);
153            }
154        }
155        this.hemisphere = hem;
156    }
157
158    @Override
159    protected String indexToZone(int idx) {
160        return Integer.toString(idx + 1);
161    }
162
163    @Override
164    protected int zoneToIndex(String zone) {
165        try {
166            return Integer.parseInt(zone) - 1;
167        } catch (NumberFormatException e) {
168            Main.warn(e);
169        }
170        return defaultIndex;
171    }
172}