// License: GPL. Copyright 2007 by Immanuel Scholz and others package org.openstreetmap.josm.gui.preferences; import static org.openstreetmap.josm.tools.I18n.tr; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collection; import javax.swing.BorderFactory; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.Bounds; import org.openstreetmap.josm.data.coor.CoordinateFormat; import org.openstreetmap.josm.data.projection.Mercator; import org.openstreetmap.josm.data.projection.Projection; import org.openstreetmap.josm.data.projection.ProjectionSubPrefs; import org.openstreetmap.josm.tools.GBC; public class ProjectionPreference implements PreferenceSetting { public static class Factory implements PreferenceSettingFactory { public PreferenceSetting createPreferenceSetting() { return new ProjectionPreference(); } } /** * Combobox with all projections available */ private JComboBox projectionCombo = new JComboBox(Projection.allProjections); /** * Combobox with all coordinate display possibilities */ private JComboBox coordinatesCombo = new JComboBox(CoordinateFormat.values()); /** * This variable holds the JPanel with the projection's preferences. If the * selected projection does not implement this, it will be set to an empty * Panel. */ private JPanel projSubPrefPanel; private JLabel projectionCode = new JLabel(); private JLabel bounds = new JLabel(); /** * This is the panel holding all projection preferences */ private JPanel projPanel = new JPanel(); /** * The GridBagConstraints for the Panel containing the ProjectionSubPrefs. * This is required twice in the code, creating it here keeps both occurrences * in sync */ static private GBC projSubPrefPanelGBC = GBC.eol().fill(GBC.BOTH).insets(20,5,5,5); public void addGui(PreferenceTabbedPane gui) { setupProjectionCombo(); for (int i = 0; i < coordinatesCombo.getItemCount(); ++i) { if (((CoordinateFormat)coordinatesCombo.getItemAt(i)).name().equals(Main.pref.get("coordinates"))) { coordinatesCombo.setSelectedIndex(i); break; } } projPanel.setBorder(BorderFactory.createEmptyBorder( 0, 0, 0, 0 )); projPanel.setLayout(new GridBagLayout()); projPanel.add(new JLabel(tr("Display coordinates as")), GBC.std().insets(5,5,0,5)); projPanel.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL)); projPanel.add(coordinatesCombo, GBC.eop().fill(GBC.HORIZONTAL).insets(0,5,5,5)); projPanel.add(new JLabel(tr("Projection method")), GBC.std().insets(5,5,0,5)); projPanel.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL)); projPanel.add(projectionCombo, GBC.eop().fill(GBC.HORIZONTAL).insets(0,5,5,5)); projPanel.add(new JLabel(tr("Projection code")), GBC.std().insets(25,5,0,5)); projPanel.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL)); projPanel.add(projectionCode, GBC.eop().fill(GBC.HORIZONTAL).insets(0,5,5,5)); projPanel.add(new JLabel(tr("Bounds")), GBC.std().insets(25,5,0,5)); projPanel.add(GBC.glue(5,0), GBC.std().fill(GBC.HORIZONTAL)); projPanel.add(bounds, GBC.eop().fill(GBC.HORIZONTAL).insets(0,5,5,5)); projPanel.add(projSubPrefPanel, projSubPrefPanelGBC); JScrollPane scrollpane = new JScrollPane(projPanel); gui.mapcontent.addTab(tr("Map Projection"), scrollpane); updateMeta(Main.proj); } private void updateMeta(Projection proj) { projectionCode.setText(proj.toCode()); Bounds b = proj.getWorldBoundsLatLon(); CoordinateFormat cf = CoordinateFormat.getDefaultFormat(); bounds.setText(b.getMin().latToString(cf)+"; "+b.getMin().lonToString(cf)+" : "+b.getMax().latToString(cf)+"; "+b.getMax().lonToString(cf)); } public boolean ok() { Projection proj = (Projection) projectionCombo.getSelectedItem(); String projname = proj.getClass().getName(); Collection<String> prefs = null; if(proj instanceof ProjectionSubPrefs) { prefs = ((ProjectionSubPrefs) proj).getPreferences(projSubPrefPanel); } Main.pref.put("projection", projname); setProjection(projname, prefs); if(Main.pref.put("coordinates", ((CoordinateFormat)coordinatesCombo.getSelectedItem()).name())) { CoordinateFormat.setCoordinateFormat((CoordinateFormat)coordinatesCombo.getSelectedItem()); } return false; } static public void setProjection() { setProjection(Main.pref.get("projection", Mercator.class.getName()), Main.pref.getCollection("projection.sub", null)); } static public void setProjection(String name, Collection<String> coll) { Bounds b = (Main.map != null && Main.map.mapView != null) ? Main.map.mapView.getRealBounds() : null; Projection oldProj = Main.proj; try { Main.proj = (Projection)Class.forName(name).newInstance(); } catch (final Exception e) { JOptionPane.showMessageDialog( Main.parent, tr("The projection {0} could not be activated. Using Mercator", name), tr("Error"), JOptionPane.ERROR_MESSAGE ); coll = null; Main.proj = new Mercator(); name = Main.proj.getClass().getName(); } Main.pref.putCollection("projection.sub", coll); String sname = name.substring(name.lastIndexOf(".")+1); Main.pref.putCollection("projection.sub."+sname, coll); if(Main.proj instanceof ProjectionSubPrefs) { ((ProjectionSubPrefs) Main.proj).setPreferences(coll); } if(b != null && (!Main.proj.getClass().getName().equals(oldProj.getClass().getName()) || Main.proj.hashCode() != oldProj.hashCode())) { Main.map.mapView.zoomTo(b); /* TODO - remove layers with fixed projection */ } } private class SBPanel extends JPanel { private Projection p; public SBPanel(Projection pr) { super(); p = pr; } @Override public void paint(java.awt.Graphics g) { super.paint(g); ((ProjectionSubPrefs) p).setPreferences(((ProjectionSubPrefs) p).getPreferences(this)); updateMeta(p); } } /** * Handles all the work related to update the projection-specific * preferences * @param proj */ private void selectedProjectionChanged(Projection proj) { if(!(proj instanceof ProjectionSubPrefs)) { projSubPrefPanel = new JPanel(); } else { ProjectionSubPrefs projPref = (ProjectionSubPrefs) proj; projSubPrefPanel = new SBPanel(proj); projPref.setupPreferencePanel(projSubPrefPanel); } // Don't try to update if we're still starting up int size = projPanel.getComponentCount(); if(size < 1) return; // Replace old panel with new one projPanel.remove(size - 1); projPanel.add(projSubPrefPanel, projSubPrefPanelGBC); projPanel.revalidate(); projSubPrefPanel.repaint(); updateMeta(proj); } /** * Sets up projection combobox with default values and action listener */ private void setupProjectionCombo() { for (int i = 0; i < projectionCombo.getItemCount(); ++i) { Projection proj = (Projection)projectionCombo.getItemAt(i); String name = proj.getClass().getName(); String sname = name.substring(name.lastIndexOf(".")+1); if(proj instanceof ProjectionSubPrefs) { ((ProjectionSubPrefs) proj).setPreferences(Main.pref.getCollection("projection.sub."+sname, null)); } if (name.equals(Main.pref.get("projection", Mercator.class.getName()))) { projectionCombo.setSelectedIndex(i); selectedProjectionChanged(proj); break; } } projectionCombo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JComboBox cb = (JComboBox)e.getSource(); Projection proj = (Projection)cb.getSelectedItem(); selectedProjectionChanged(proj); } }); } }