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(new GridBagLayout());
066
067            bPanel.add(new JLabel(tr("North")), GBC.std().insets(5, 5, 0, 5));
068            bPanel.add(north, GBC.std().fill(GBC.HORIZONTAL));
069            bPanel.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL));
070            bPanel.add(new JLabel(tr("South")), GBC.std().insets(5, 5, 0, 5));
071            bPanel.add(south, GBC.std().fill(GBC.HORIZONTAL));
072            bPanel.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH));
073
074            this.add(new JLabel(tr("Hemisphere")), GBC.std().insets(5, 5, 0, 5));
075            this.add(GBC.glue(1, 0), GBC.std().fill(GBC.HORIZONTAL));
076            this.add(bPanel, GBC.eop().fill(GBC.HORIZONTAL));
077            this.add(GBC.glue(1, 1), GBC.eol().fill(GBC.BOTH));
078
079            if (listener != null) {
080                north.addActionListener(listener);
081                south.addActionListener(listener);
082            }
083        }
084    }
085
086    @Override
087    public JPanel getPreferencePanel(ActionListener listener) {
088        return new UTMPanel(entries, index, label, listener);
089    }
090
091    @Override
092    public String getCurrentCode() {
093        int zone = index + 1;
094        int code = 32600 + zone + (hemisphere == Hemisphere.South ? 100 : 0);
095        return "EPSG:" + Integer.toString(code);
096    }
097
098    @Override
099    public String getProjectionName() {
100        return tr("UTM");
101    }
102
103    @Override
104    public Collection<String> getPreferences(JPanel panel) {
105        if (!(panel instanceof UTMPanel)) {
106            throw new IllegalArgumentException("Unsupported panel: "+panel);
107        }
108        UTMPanel p = (UTMPanel) panel;
109        int idx = p.prefcb.getSelectedIndex();
110        Hemisphere hem = p.south.isSelected() ? Hemisphere.South : Hemisphere.North;
111        return Arrays.asList(indexToZone(idx), hem.toString());
112    }
113
114    @Override
115    public String[] allCodes() {
116        List<String> projections = new ArrayList<>(60*4);
117        for (int zone = 1; zone <= 60; zone++) {
118            for (Hemisphere hem : Hemisphere.values()) {
119                projections.add("EPSG:" + (32600 + zone + (hem == Hemisphere.South ? 100 : 0)));
120            }
121        }
122        return projections.toArray(new String[projections.size()]);
123    }
124
125    @Override
126    public Collection<String> getPreferencesFromCode(String code) {
127
128        if (code.startsWith("EPSG:326") || code.startsWith("EPSG:327")) {
129            try {
130                Hemisphere hem = code.charAt(7) == '6' ? Hemisphere.North : Hemisphere.South;
131                String zonestring = code.substring(8);
132                int zoneval = Integer.parseInt(zonestring);
133                if (zoneval > 0 && zoneval <= 60)
134                    return Arrays.asList(zonestring, hem.toString());
135            } catch (NumberFormatException e) {
136                Main.warn(e);
137            }
138        }
139        return null;
140    }
141
142    @Override
143    public void setPreferences(Collection<String> args) {
144        super.setPreferences(args);
145        Hemisphere hem = DEFAULT_HEMISPHERE;
146
147        if (args != null) {
148            String[] array = args.toArray(new String[args.size()]);
149
150            if (array.length > 1) {
151                hem = Hemisphere.valueOf(array[1]);
152            }
153        }
154        this.hemisphere = hem;
155    }
156
157    @Override
158    protected String indexToZone(int idx) {
159        return Integer.toString(idx + 1);
160    }
161
162    @Override
163    protected int zoneToIndex(String zone) {
164        try {
165            return Integer.parseInt(zone) - 1;
166        } catch (NumberFormatException e) {
167            Main.warn(e);
168        }
169        return defaultIndex;
170    }
171}