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.event.ActionListener;
007import java.io.Serializable;
008import java.util.Collection;
009import java.util.Collections;
010import java.util.Comparator;
011import java.util.regex.Matcher;
012import java.util.regex.Pattern;
013
014import javax.swing.JPanel;
015
016import org.openstreetmap.josm.data.projection.Projection;
017import org.openstreetmap.josm.data.projection.Projections;
018import org.openstreetmap.josm.tools.Utils;
019
020/**
021 * Projection choice that lists all known projects by code.
022 * @since 5634
023 */
024public class CodeProjectionChoice extends AbstractProjectionChoice implements SubPrefsOptions {
025
026    private String code;
027
028    /**
029     * Constructs a new {@code CodeProjectionChoice}.
030     */
031    public CodeProjectionChoice() {
032        super(tr("By Code (EPSG)"), /* NO-ICON */ "core:code");
033    }
034
035    /**
036     * Comparator that compares the number part of the code numerically.
037     */
038    public static class CodeComparator implements Comparator<String>, Serializable {
039        private static final long serialVersionUID = 1L;
040        private final Pattern codePattern = Pattern.compile("([a-zA-Z]+):(\\d+)");
041
042        @Override
043        public int compare(String c1, String c2) {
044            Matcher matcher1 = codePattern.matcher(c1);
045            Matcher matcher2 = codePattern.matcher(c2);
046            if (matcher1.matches()) {
047                if (matcher2.matches()) {
048                    int cmp1 = matcher1.group(1).compareTo(matcher2.group(1));
049                    if (cmp1 != 0)
050                        return cmp1;
051                    int num1 = Integer.parseInt(matcher1.group(2));
052                    int num2 = Integer.parseInt(matcher2.group(2));
053                    return Integer.compare(num1, num2);
054                } else
055                    return -1;
056            } else if (matcher2.matches())
057                return 1;
058            return c1.compareTo(c2);
059        }
060    }
061
062    @Override
063    public Projection getProjection() {
064        return Projections.getProjectionByCode(code);
065    }
066
067    @Override
068    public String getCurrentCode() {
069        // not needed - getProjection() is overridden
070        throw new UnsupportedOperationException();
071    }
072
073    @Override
074    public String getProjectionName() {
075        // not needed - getProjection() is overridden
076        throw new UnsupportedOperationException();
077    }
078
079    @Override
080    public void setPreferences(Collection<String> args) {
081        if (!Utils.isEmpty(args)) {
082            code = args.iterator().next();
083        }
084    }
085
086    @Override
087    public JPanel getPreferencePanel(ActionListener listener) {
088        return new CodeSelectionPanel(code, listener);
089    }
090
091    @Override
092    public Collection<String> getPreferences(JPanel panel) {
093        if (!(panel instanceof CodeSelectionPanel)) {
094            throw new IllegalArgumentException("Unsupported panel: "+panel);
095        }
096        CodeSelectionPanel csPanel = (CodeSelectionPanel) panel;
097        return Collections.singleton(csPanel.getCode());
098    }
099
100    /* don't return all possible codes - this projection choice it too generic */
101    @Override
102    public String[] allCodes() {
103        return new String[0];
104    }
105
106    /* not needed since allCodes() returns empty array */
107    @Override
108    public Collection<String> getPreferencesFromCode(String code) {
109        return null;
110    }
111
112    @Override
113    public boolean showProjectionCode() {
114        return true;
115    }
116
117    @Override
118    public boolean showProjectionName() {
119        return true;
120    }
121
122}