source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java@ 5429

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

fix #7917 - Control the number of items displayed at once in all comboboxes (20 by default, configurable with gui.combobox.maximum-row-count)

  • Property svn:eol-style set to native
File size: 14.1 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui.preferences.projection;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.GridBagLayout;
8import java.awt.event.ActionEvent;
9import java.awt.event.ActionListener;
10import java.util.ArrayList;
11import java.util.Collection;
12import java.util.Collections;
13import java.util.HashMap;
14import java.util.List;
15import java.util.Map;
16
17import javax.swing.BorderFactory;
18import javax.swing.JLabel;
19import javax.swing.JOptionPane;
20import javax.swing.JPanel;
21import javax.swing.JScrollPane;
22import javax.swing.JSeparator;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.data.Bounds;
26import org.openstreetmap.josm.data.coor.CoordinateFormat;
27import org.openstreetmap.josm.data.preferences.CollectionProperty;
28import org.openstreetmap.josm.data.preferences.StringProperty;
29import org.openstreetmap.josm.data.projection.BelgianLambert1972;
30import org.openstreetmap.josm.data.projection.BelgianLambert2008;
31import org.openstreetmap.josm.data.projection.Epsg3008;
32import org.openstreetmap.josm.data.projection.Epsg4326;
33import org.openstreetmap.josm.data.projection.Lambert93;
34import org.openstreetmap.josm.data.projection.LambertEST;
35import org.openstreetmap.josm.data.projection.Mercator;
36import org.openstreetmap.josm.data.projection.Projection;
37import org.openstreetmap.josm.data.projection.TransverseMercatorLV;
38import org.openstreetmap.josm.gui.NavigatableComponent;
39import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
40import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
41import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
42import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
43import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
44import org.openstreetmap.josm.gui.widgets.JosmComboBox;
45import org.openstreetmap.josm.tools.GBC;
46
47public class ProjectionPreference implements SubPreferenceSetting {
48
49 public static class Factory implements PreferenceSettingFactory {
50 public PreferenceSetting createPreferenceSetting() {
51 return new ProjectionPreference();
52 }
53 }
54
55 private static List<ProjectionChoice> projectionChoices = new ArrayList<ProjectionChoice>();
56 private static Map<String, ProjectionChoice> projectionChoicesById = new HashMap<String, ProjectionChoice>();
57 private static Map<String, String> aliasNormalizer = new HashMap<String, String>();
58
59 public static ProjectionChoice mercator = new SingleProjectionChoice("core:mercator", new Mercator());
60 static {
61 // global projections
62 registerProjectionChoice("core:wgs84", new Epsg4326());
63 registerProjectionChoice(mercator);
64 registerProjectionChoice(new UTMProjectionChoice());
65 // regional - alphabetical order by country code
66 registerProjectionChoice("core:belambert1972", new BelgianLambert1972()); // BE
67 registerProjectionChoice("core:belambert2008", new BelgianLambert2008()); // BE
68 registerProjectionChoice(new SwissGridProjectionChoice()); // CH
69 registerProjectionChoice(new GaussKruegerProjectionChoice()); // DE
70 registerProjectionChoice("core:lambertest", new LambertEST()); // EE
71 registerProjectionChoice(new LambertProjectionChoice()); // FR
72 registerProjectionChoice("core:lambert93", new Lambert93()); // FR
73 registerProjectionChoice(new LambertCC9ZonesProjectionChoice()); // FR
74 registerProjectionChoice(new UTM_France_DOM_ProjectionChoice()); // FR
75 registerProjectionChoice("core:tmerclv", new TransverseMercatorLV()); // LV
76 registerProjectionChoice(new PuwgProjectionChoice()); // PL
77 registerProjectionChoice("core:sweref99", new Epsg3008()); // SE
78 registerProjectionChoice(new CustomProjectionChoice());
79 }
80
81 public static void registerProjectionChoice(ProjectionChoice c) {
82 projectionChoices.add(c);
83 projectionChoicesById.put(c.getId(), c);
84 aliasNormalizer.put(c.getId(), c.getId());
85 if (c instanceof Alias) {
86 String alias = ((Alias) c).getAlias();
87 projectionChoicesById.put(alias, c);
88 aliasNormalizer.put(alias, c.getId());
89 }
90 }
91
92 public static void registerProjectionChoice(String id, Projection projection) {
93 registerProjectionChoice(new SingleProjectionChoice(id, projection));
94 }
95
96 public static List<ProjectionChoice> getProjectionChoices() {
97 return Collections.unmodifiableList(projectionChoices);
98 }
99
100 private static final StringProperty PROP_PROJECTION = new StringProperty("projection", mercator.getId());
101 private static final StringProperty PROP_COORDINATES = new StringProperty("coordinates", null);
102 private static final CollectionProperty PROP_SUB_PROJECTION = new CollectionProperty("projection.sub", null);
103 public static final StringProperty PROP_SYSTEM_OF_MEASUREMENT = new StringProperty("system_of_measurement", "Metric");
104 private static final String[] unitsValues = (new ArrayList<String>(NavigatableComponent.SYSTEMS_OF_MEASUREMENT.keySet())).toArray(new String[0]);
105 private static final String[] unitsValuesTr = new String[unitsValues.length];
106 static {
107 for (int i=0; i<unitsValues.length; ++i) {
108 unitsValuesTr[i] = tr(unitsValues[i]);
109 }
110 }
111
112 /**
113 * Combobox with all projections available
114 */
115 private JosmComboBox projectionCombo = new JosmComboBox(projectionChoices.toArray());
116
117 /**
118 * Combobox with all coordinate display possibilities
119 */
120 private JosmComboBox coordinatesCombo = new JosmComboBox(CoordinateFormat.values());
121
122 private JosmComboBox unitsCombo = new JosmComboBox(unitsValuesTr);
123
124 /**
125 * This variable holds the JPanel with the projection's preferences. If the
126 * selected projection does not implement this, it will be set to an empty
127 * Panel.
128 */
129 private JPanel projSubPrefPanel;
130 private JPanel projSubPrefPanelWrapper = new JPanel(new GridBagLayout());
131
132 private JLabel projectionCodeLabel;
133 private Component projectionCodeGlue;
134 private JLabel projectionCode = new JLabel();
135 private JLabel bounds = new JLabel();
136
137 /**
138 * This is the panel holding all projection preferences
139 */
140 private JPanel projPanel = new JPanel(new GridBagLayout());
141
142 /**
143 * The GridBagConstraints for the Panel containing the ProjectionSubPrefs.
144 * This is required twice in the code, creating it here keeps both occurrences
145 * in sync
146 */
147 static private GBC projSubPrefPanelGBC = GBC.std().fill(GBC.BOTH).weight(1.0, 1.0);
148
149 public void addGui(PreferenceTabbedPane gui) {
150 ProjectionChoice pc = setupProjectionCombo();
151
152 for (int i = 0; i < coordinatesCombo.getItemCount(); ++i) {
153 if (((CoordinateFormat)coordinatesCombo.getItemAt(i)).name().equals(PROP_COORDINATES.get())) {
154 coordinatesCombo.setSelectedIndex(i);
155 break;
156 }
157 }
158
159 for (int i = 0; i < unitsValues.length; ++i) {
160 if (unitsValues[i].equals(PROP_SYSTEM_OF_MEASUREMENT.get())) {
161 unitsCombo.setSelectedIndex(i);
162 break;
163 }
164 }
165
166 projPanel.setBorder(BorderFactory.createEmptyBorder( 0, 0, 0, 0 ));
167 projPanel.setLayout(new GridBagLayout());
168 projPanel.add(new JLabel(tr("Projection method")), GBC.std().insets(5,5,0,5));
169 projPanel.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
170 projPanel.add(projectionCombo, GBC.eop().fill(GBC.HORIZONTAL).insets(0,5,5,5));
171 projPanel.add(projectionCodeLabel = new JLabel(tr("Projection code")), GBC.std().insets(25,5,0,5));
172 projPanel.add(projectionCodeGlue = GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
173 projPanel.add(projectionCode, GBC.eop().fill(GBC.HORIZONTAL).insets(0,5,5,5));
174 projPanel.add(new JLabel(tr("Bounds")), GBC.std().insets(25,5,0,5));
175 projPanel.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
176 projPanel.add(bounds, GBC.eop().fill(GBC.HORIZONTAL).insets(0,5,5,5));
177 projPanel.add(projSubPrefPanelWrapper, GBC.eol().fill(GBC.HORIZONTAL).insets(20,5,5,5));
178
179 projPanel.add(new JSeparator(), GBC.eol().fill(GBC.HORIZONTAL).insets(0,5,0,10));
180 projPanel.add(new JLabel(tr("Display coordinates as")), GBC.std().insets(5,5,0,5));
181 projPanel.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
182 projPanel.add(coordinatesCombo, GBC.eop().fill(GBC.HORIZONTAL).insets(0,5,5,5));
183 projPanel.add(new JLabel(tr("System of measurement")), GBC.std().insets(5,5,0,5));
184 projPanel.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL));
185 projPanel.add(unitsCombo, GBC.eop().fill(GBC.HORIZONTAL).insets(0,5,5,5));
186 projPanel.add(GBC.glue(1,1), GBC.std().fill(GBC.HORIZONTAL).weight(1.0, 1.0));
187
188 JScrollPane scrollpane = new JScrollPane(projPanel);
189 gui.getMapPreference().mapcontent.addTab(tr("Map Projection"), scrollpane);
190
191 selectedProjectionChanged(pc);
192 }
193
194 private void updateMeta(ProjectionChoice pc) {
195 pc.setPreferences(pc.getPreferences(projSubPrefPanel));
196 Projection proj = pc.getProjection();
197 projectionCode.setText(proj.toCode());
198 Bounds b = proj.getWorldBoundsLatLon();
199 CoordinateFormat cf = CoordinateFormat.getDefaultFormat();
200 bounds.setText(b.getMin().lonToString(cf)+", "+b.getMin().latToString(cf)+" : "+b.getMax().lonToString(cf)+", "+b.getMax().latToString(cf));
201 boolean showCode = true;
202 if (pc instanceof SubPrefsOptions) {
203 showCode = ((SubPrefsOptions) pc).showProjectionCode();
204 }
205 projectionCodeLabel.setVisible(showCode);
206 projectionCodeGlue.setVisible(showCode);
207 projectionCode.setVisible(showCode);
208 }
209
210 @Override
211 public boolean ok() {
212 ProjectionChoice pc = (ProjectionChoice) projectionCombo.getSelectedItem();
213
214 String id = pc.getId();
215 Collection<String> prefs = pc.getPreferences(projSubPrefPanel);
216
217 setProjection(id, prefs);
218
219 if(PROP_COORDINATES.put(((CoordinateFormat)coordinatesCombo.getSelectedItem()).name())) {
220 CoordinateFormat.setCoordinateFormat((CoordinateFormat)coordinatesCombo.getSelectedItem());
221 }
222
223 int i = unitsCombo.getSelectedIndex();
224 PROP_SYSTEM_OF_MEASUREMENT.put(unitsValues[i]);
225
226 return false;
227 }
228
229 static public void setProjection() {
230 setProjection(PROP_PROJECTION.get(), PROP_SUB_PROJECTION.get());
231 }
232
233 static public void setProjection(String id, Collection<String> pref) {
234 ProjectionChoice pc = projectionChoicesById.get(id);
235
236 if (pc == null) {
237 JOptionPane.showMessageDialog(
238 Main.parent,
239 tr("The projection {0} could not be activated. Using Mercator", id),
240 tr("Error"),
241 JOptionPane.ERROR_MESSAGE
242 );
243 pref = null;
244 pc = mercator;
245 }
246 id = pc.getId();
247 PROP_PROJECTION.put(id);
248 PROP_SUB_PROJECTION.put(pref);
249 Main.pref.putCollection("projection.sub."+id, pref);
250 pc.setPreferences(pref);
251 Projection proj = pc.getProjection();
252 Main.setProjection(proj);
253 }
254
255 /**
256 * Handles all the work related to update the projection-specific
257 * preferences
258 * @param proj
259 */
260 private void selectedProjectionChanged(final ProjectionChoice pc) {
261 // Don't try to update if we're still starting up
262 int size = projPanel.getComponentCount();
263 if(size < 1)
264 return;
265
266 final ActionListener listener = new ActionListener() {
267 @Override
268 public void actionPerformed(ActionEvent e) {
269 updateMeta(pc);
270 }
271 };
272
273 // Replace old panel with new one
274 projSubPrefPanelWrapper.removeAll();
275 projSubPrefPanel = pc.getPreferencePanel(listener);
276 projSubPrefPanelWrapper.add(projSubPrefPanel, projSubPrefPanelGBC);
277 projPanel.revalidate();
278 projSubPrefPanel.repaint();
279 updateMeta(pc);
280 }
281
282 /**
283 * Sets up projection combobox with default values and action listener
284 */
285 private ProjectionChoice setupProjectionCombo() {
286 ProjectionChoice pc = null;
287 for (int i = 0; i < projectionCombo.getItemCount(); ++i) {
288 ProjectionChoice pc1 = (ProjectionChoice) projectionCombo.getItemAt(i);
289 pc1.setPreferences(getSubprojectionPreference(pc1));
290 if (pc1.getId().equals(aliasNormalizer.get(PROP_PROJECTION.get()))) {
291 projectionCombo.setSelectedIndex(i);
292 selectedProjectionChanged(pc1);
293 pc = pc1;
294 }
295 }
296 // If the ProjectionChoice from the preferences is not available, it
297 // should have been set to Mercator at JOSM start.
298 if (pc == null)
299 throw new RuntimeException("Couldn't find the current projection in the list of available projections!");
300
301 projectionCombo.addActionListener(new ActionListener() {
302 public void actionPerformed(ActionEvent e) {
303 ProjectionChoice pc = (ProjectionChoice) projectionCombo.getSelectedItem();
304 selectedProjectionChanged(pc);
305 }
306 });
307 return pc;
308 }
309
310 private Collection<String> getSubprojectionPreference(ProjectionChoice pc) {
311 Collection<String> c1 = Main.pref.getCollection("projection.sub."+pc.getId(), null);
312 if (c1 != null)
313 return c1;
314 if (pc instanceof Alias) {
315 String alias = ((Alias) pc).getAlias();
316 String sname = alias.substring(alias.lastIndexOf(".")+1);
317 return Main.pref.getCollection("projection.sub."+sname, null);
318 }
319 return null;
320 }
321
322 @Override
323 public boolean isExpert() {
324 return false;
325 }
326
327 @Override
328 public TabPreferenceSetting getTabPreferenceSetting(final PreferenceTabbedPane gui) {
329 return gui.getMapPreference();
330 }
331}
Note: See TracBrowser for help on using the repository browser.