source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/projection/CodeProjectionChoice.java@ 10619

Last change on this file since 10619 was 10619, checked in by Don-vip, 8 years ago

see #11390 - Java 8: use List.sort(Comparator) instead of Collections.sort(list, Comparator)

  • Property svn:eol-style set to native
File size: 7.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.preferences.projection;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Dimension;
7import java.awt.GridBagLayout;
8import java.awt.event.ActionListener;
9import java.io.Serializable;
10import java.util.ArrayList;
11import java.util.Collection;
12import java.util.Collections;
13import java.util.Comparator;
14import java.util.List;
15import java.util.Locale;
16import java.util.regex.Matcher;
17import java.util.regex.Pattern;
18
19import javax.swing.AbstractListModel;
20import javax.swing.JList;
21import javax.swing.JPanel;
22import javax.swing.JScrollPane;
23import javax.swing.event.DocumentEvent;
24import javax.swing.event.DocumentListener;
25import javax.swing.event.ListSelectionEvent;
26import javax.swing.event.ListSelectionListener;
27
28import org.openstreetmap.josm.data.projection.Projection;
29import org.openstreetmap.josm.data.projection.Projections;
30import org.openstreetmap.josm.gui.widgets.JosmTextField;
31import org.openstreetmap.josm.tools.GBC;
32
33/**
34 * Projection choice that lists all known projects by code.
35 */
36public class CodeProjectionChoice extends AbstractProjectionChoice implements SubPrefsOptions {
37
38 private String code;
39
40 /**
41 * Constructs a new {@code CodeProjectionChoice}.
42 */
43 public CodeProjectionChoice() {
44 super(tr("By Code (EPSG)"), /* NO-ICON */ "core:code");
45 }
46
47 private static class CodeSelectionPanel extends JPanel implements ListSelectionListener, DocumentListener {
48
49 public final JosmTextField filter = new JosmTextField(30);
50 private final ProjectionCodeListModel model = new ProjectionCodeListModel();
51 public JList<String> selectionList;
52 private final List<String> data;
53 private final List<String> filteredData;
54 private static final String DEFAULT_CODE = "EPSG:3857";
55 private String lastCode = DEFAULT_CODE;
56 private final transient ActionListener listener;
57
58 CodeSelectionPanel(String initialCode, ActionListener listener) {
59 this.listener = listener;
60 data = new ArrayList<>(Projections.getAllProjectionCodes());
61 data.sort(new CodeComparator());
62 filteredData = new ArrayList<>(data);
63 build();
64 setCode(initialCode != null ? initialCode : DEFAULT_CODE);
65 selectionList.addListSelectionListener(this);
66 }
67
68 /**
69 * List model for the filtered view on the list of all codes.
70 */
71 private class ProjectionCodeListModel extends AbstractListModel<String> {
72 @Override
73 public int getSize() {
74 return filteredData.size();
75 }
76
77 @Override
78 public String getElementAt(int index) {
79 if (index >= 0 && index < filteredData.size())
80 return filteredData.get(index);
81 else
82 return null;
83 }
84
85 public void fireContentsChanged() {
86 fireContentsChanged(this, 0, this.getSize()-1);
87 }
88 }
89
90 private void build() {
91 filter.setColumns(10);
92 filter.getDocument().addDocumentListener(this);
93
94 selectionList = new JList<>(data.toArray(new String[0]));
95 selectionList.setModel(model);
96 JScrollPane scroll = new JScrollPane(selectionList);
97 scroll.setPreferredSize(new Dimension(200, 214));
98
99 this.setLayout(new GridBagLayout());
100 this.add(filter, GBC.eol().weight(1.0, 0.0));
101 this.add(scroll, GBC.eol());
102 }
103
104 public String getCode() {
105 int idx = selectionList.getSelectedIndex();
106 if (idx == -1)
107 return lastCode;
108 return filteredData.get(selectionList.getSelectedIndex());
109 }
110
111 public final void setCode(String code) {
112 int idx = filteredData.indexOf(code);
113 if (idx != -1) {
114 selectionList.setSelectedIndex(idx);
115 selectionList.ensureIndexIsVisible(idx);
116 }
117 }
118
119 @Override
120 public void valueChanged(ListSelectionEvent e) {
121 listener.actionPerformed(null);
122 lastCode = getCode();
123 }
124
125 @Override
126 public void insertUpdate(DocumentEvent e) {
127 updateFilter();
128 }
129
130 @Override
131 public void removeUpdate(DocumentEvent e) {
132 updateFilter();
133 }
134
135 @Override
136 public void changedUpdate(DocumentEvent e) {
137 updateFilter();
138 }
139
140 private void updateFilter() {
141 filteredData.clear();
142 String filterTxt = filter.getText().trim().toLowerCase(Locale.ENGLISH);
143 for (String code : data) {
144 if (code.toLowerCase(Locale.ENGLISH).contains(filterTxt)) {
145 filteredData.add(code);
146 }
147 }
148 model.fireContentsChanged();
149 int idx = filteredData.indexOf(lastCode);
150 if (idx == -1) {
151 selectionList.clearSelection();
152 if (selectionList.getModel().getSize() > 0) {
153 selectionList.ensureIndexIsVisible(0);
154 }
155 } else {
156 selectionList.setSelectedIndex(idx);
157 selectionList.ensureIndexIsVisible(idx);
158 }
159 }
160 }
161
162 /**
163 * Comparator that compares the number part of the code numerically.
164 */
165 public static class CodeComparator implements Comparator<String>, Serializable {
166 private static final long serialVersionUID = 1L;
167 private final Pattern codePattern = Pattern.compile("([a-zA-Z]+):(\\d+)");
168
169 @Override
170 public int compare(String c1, String c2) {
171 Matcher matcher1 = codePattern.matcher(c1);
172 Matcher matcher2 = codePattern.matcher(c2);
173 if (matcher1.matches()) {
174 if (matcher2.matches()) {
175 int cmp1 = matcher1.group(1).compareTo(matcher2.group(1));
176 if (cmp1 != 0)
177 return cmp1;
178 int num1 = Integer.parseInt(matcher1.group(2));
179 int num2 = Integer.parseInt(matcher2.group(2));
180 return Integer.compare(num1, num2);
181 } else
182 return -1;
183 } else if (matcher2.matches())
184 return 1;
185 return c1.compareTo(c2);
186 }
187 }
188
189 @Override
190 public Projection getProjection() {
191 return Projections.getProjectionByCode(code);
192 }
193
194 @Override
195 public String getCurrentCode() {
196 // not needed - getProjection() is overridden
197 throw new UnsupportedOperationException();
198 }
199
200 @Override
201 public String getProjectionName() {
202 // not needed - getProjection() is overridden
203 throw new UnsupportedOperationException();
204 }
205
206 @Override
207 public void setPreferences(Collection<String> args) {
208 if (args != null && !args.isEmpty()) {
209 code = args.iterator().next();
210 }
211 }
212
213 @Override
214 public JPanel getPreferencePanel(ActionListener listener) {
215 return new CodeSelectionPanel(code, listener);
216 }
217
218 @Override
219 public Collection<String> getPreferences(JPanel panel) {
220 if (!(panel instanceof CodeSelectionPanel)) {
221 throw new IllegalArgumentException("Unsupported panel: "+panel);
222 }
223 CodeSelectionPanel csPanel = (CodeSelectionPanel) panel;
224 return Collections.singleton(csPanel.getCode());
225 }
226
227 /* don't return all possible codes - this projection choice it too generic */
228 @Override
229 public String[] allCodes() {
230 return new String[0];
231 }
232
233 /* not needed since allCodes() returns empty array */
234 @Override
235 public Collection<String> getPreferencesFromCode(String code) {
236 return null;
237 }
238
239 @Override
240 public boolean showProjectionCode() {
241 return true;
242 }
243
244 @Override
245 public boolean showProjectionName() {
246 return true;
247 }
248
249}
Note: See TracBrowser for help on using the repository browser.