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

Last change on this file since 7668 was 7668, checked in by stoecker, 9 years ago

cleanup icons, mark undetected icons, set proper mimetype, delete unused icons, update geticons script

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