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, 11 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.