Changeset 12486 in josm


Ignore:
Timestamp:
2017-07-22T14:25:19+02:00 (4 weeks ago)
Author:
bastiK
Message:

see #15013, see #14877 - remember projection when session is saved to a .jos/.joz file

Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/SessionLoadAction.java

    r11848 r12486  
    2020
    2121import org.openstreetmap.josm.Main;
    22 import org.openstreetmap.josm.data.ViewportData;
    2322import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    2423import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    2524import org.openstreetmap.josm.gui.layer.Layer;
     25import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
    2626import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    2727import org.openstreetmap.josm.gui.util.FileFilterAllFiles;
     
    3030import org.openstreetmap.josm.io.session.SessionImporter;
    3131import org.openstreetmap.josm.io.session.SessionReader;
     32import org.openstreetmap.josm.io.session.SessionReader.SessionProjectionChoiceData;
     33import org.openstreetmap.josm.io.session.SessionReader.SessionViewportData;
    3234import org.openstreetmap.josm.tools.CheckParameterUtil;
    3335import org.openstreetmap.josm.tools.JosmRuntimeException;
     
    7375        private Layer active;
    7476        private List<Runnable> postLoadTasks;
    75         private ViewportData viewport;
     77        private SessionViewportData viewport;
     78        private SessionProjectionChoiceData projectionChoice;
    7679
    7780        /**
     
    116119                if (canceled)
    117120                    return;
     121                if (projectionChoice != null) {
     122                    ProjectionPreference.setProjection(
     123                            projectionChoice.getProjectionChoiceId(),
     124                            projectionChoice.getSubPreferences(),
     125                            false);
     126                }
    118127                addLayers();
    119128                runPostLoadTasks();
     
    132141                    Main.getLayerManager().setActiveLayer(active);
    133142                }
    134                 if (noMap) {
    135                     Main.map.mapView.scheduleZoomTo(viewport);
     143                if (noMap && viewport != null) {
     144                    Main.map.mapView.scheduleZoomTo(viewport.getEastNorthViewport(Main.getProjection()));
    136145                }
    137146            }
     
    169178                    postLoadTasks = reader.getPostLoadTasks();
    170179                    viewport = reader.getViewport();
     180                    projectionChoice = reader.getProjectionChoice();
    171181                } finally {
    172182                    if (tempFile) {
  • trunk/src/org/openstreetmap/josm/gui/preferences/projection/ProjectionPreference.java

    r12485 r12486  
    501501     */
    502502    private ProjectionChoice setupProjectionCombo() {
    503         String pcId = projectionChoice != null ? projectionChoice : PROP_PROJECTION_DEFAULT.get();
     503        String pcId = getCurrentProjectionChoiceId();
    504504        ProjectionChoice pc = null;
    505505        for (int i = 0; i < projectionCombo.getItemCount(); ++i) {
    506506            ProjectionChoice pc1 = projectionCombo.getItemAt(i);
    507             pc1.setPreferences(getSubprojectionPreference(pc1));
     507            pc1.setPreferences(getSubprojectionPreference(pc1.getId()));
    508508            if (pc1.getId().equals(pcId)) {
    509509                projectionCombo.setSelectedIndex(i);
     
    524524    }
    525525
    526     private static Collection<String> getSubprojectionPreference(ProjectionChoice pc) {
    527         return Main.pref.getCollection("projection.sub."+pc.getId(), null);
     526    /**
     527     * Get the id of the projection choice that is currently set.
     528     * @return id of the projection choice that is currently set
     529     */
     530    public static String getCurrentProjectionChoiceId() {
     531        return projectionChoice != null ? projectionChoice : PROP_PROJECTION_DEFAULT.get();
     532    }
     533
     534    /**
     535     * Get the preferences that have been selected the last time for the given
     536     * projection choice.
     537     * @param pcId id of the projection choice
     538     * @return projection choice parameters that have been selected by the user
     539     * the last time; null if user has never selected the given projection choice
     540     */
     541    public static Collection<String> getSubprojectionPreference(String pcId) {
     542        return Main.pref.getCollection("projection.sub."+pcId, null);
    528543    }
    529544
  • trunk/src/org/openstreetmap/josm/io/session/SessionReader.java

    r12279 r12486  
    1616import java.nio.charset.StandardCharsets;
    1717import java.util.ArrayList;
     18import java.util.Collection;
    1819import java.util.Collections;
    1920import java.util.Enumeration;
     
    4344import org.openstreetmap.josm.io.Compression;
    4445import org.openstreetmap.josm.io.IllegalDataException;
     46import org.openstreetmap.josm.tools.CheckParameterUtil;
    4547import org.openstreetmap.josm.tools.JosmRuntimeException;
    4648import org.openstreetmap.josm.tools.MultiMap;
     
    5860public class SessionReader {
    5961
     62    /**
     63     * Data class for projection saved in the session file.
     64     */
     65    public static class SessionProjectionChoiceData {
     66        private final String projectionChoiceId;
     67        private final Collection<String> subPreferences;
     68
     69        /**
     70         * Construct a new SessionProjectionChoiceData.
     71         * @param projectionChoiceId projection choice id
     72         * @param subPreferences parameters for the projection choice
     73         */
     74        public SessionProjectionChoiceData(String projectionChoiceId, Collection<String> subPreferences) {
     75            this.projectionChoiceId = projectionChoiceId;
     76            this.subPreferences = subPreferences;
     77        }
     78
     79        /**
     80         * Get the projection choice id.
     81         * @return the projection choice id
     82         */
     83        public String getProjectionChoiceId() {
     84            return projectionChoiceId;
     85        }
     86
     87        /**
     88         * Get the parameters for the projection choice
     89         * @return parameters for the projection choice
     90         */
     91        public Collection<String> getSubPreferences() {
     92            return subPreferences;
     93        }
     94    }
     95
     96    /**
     97     * Data class for viewport saved in the session file.
     98     */
     99    public static class SessionViewportData {
     100        private final LatLon center;
     101        private final double meterPerPixel;
     102
     103        /**
     104         * Construct a new SessionViewportData.
     105         * @param center the lat/lon coordinates of the screen center
     106         * @param meterPerPixel scale in meters per pixel
     107         */
     108        public SessionViewportData(LatLon center, double meterPerPixel) {
     109            CheckParameterUtil.ensureParameterNotNull(center);
     110            this.center = center;
     111            this.meterPerPixel = meterPerPixel;
     112        }
     113
     114        /**
     115         * Get the lat/lon coordinates of the screen center.
     116         * @return lat/lon coordinates of the screen center
     117         */
     118        public LatLon getCenter() {
     119            return center;
     120        }
     121
     122        /**
     123         * Get the scale in meters per pixel.
     124         * @return scale in meters per pixel
     125         */
     126        public double getScale() {
     127            return meterPerPixel;
     128        }
     129
     130        /**
     131         * Convert this viewport data to a {@link ViewportData} object (with projected coordinates).
     132         * @param proj the projection to convert from lat/lon to east/north
     133         * @return the corresponding ViewportData object
     134         */
     135        public ViewportData getEastNorthViewport(Projection proj) {
     136            EastNorth centerEN = proj.latlon2eastNorth(center);
     137            // Get a "typical" distance in east/north units that
     138            // corresponds to a couple of pixels. Shouldn't be too
     139            // large, to keep it within projection bounds and
     140            // not too small to avoid rounding errors.
     141            double dist = 0.01 * proj.getDefaultZoomInPPD();
     142            LatLon ll1 = proj.eastNorth2latlon(new EastNorth(centerEN.east() - dist, centerEN.north()));
     143            LatLon ll2 = proj.eastNorth2latlon(new EastNorth(centerEN.east() + dist, centerEN.north()));
     144            double meterPerEasting = ll1.greatCircleDistance(ll2) / dist / 2;
     145            double scale = meterPerPixel / meterPerEasting; // unit: easting per pixel
     146            return new ViewportData(centerEN, scale);
     147        }
     148    }
     149
    60150    private static final Map<String, Class<? extends SessionLayerImporter>> sessionLayerImporters = new HashMap<>();
    61151
     
    66156    private int active = -1;
    67157    private final List<Runnable> postLoadTasks = new ArrayList<>();
    68     private ViewportData viewport;
     158    private SessionViewportData viewport;
     159    private SessionProjectionChoiceData projectionChoice;
    69160
    70161    static {
     
    130221    /**
    131222     * Return the viewport (map position and scale).
    132      * @return The viewport. Can be null when no viewport info is found in the file.
    133      */
    134     public ViewportData getViewport() {
     223     * @return the viewport; can be null when no viewport info is found in the file
     224     */
     225    public SessionViewportData getViewport() {
    135226        return viewport;
     227    }
     228
     229    /**
     230     * Return the projection choice data.
     231     * @return the projection; can be null when no projection info is found in the file
     232     */
     233    public SessionProjectionChoiceData getProjectionChoice() {
     234        return projectionChoice;
    136235    }
    137236
     
    339438        }
    340439
    341         Element viewportEl = getElementByTagName(root, "viewport");
    342         if (viewportEl != null) {
    343             EastNorth center = null;
    344             Element centerEl = getElementByTagName(viewportEl, "center");
    345             if (centerEl != null && centerEl.hasAttribute("lat") && centerEl.hasAttribute("lon")) {
    346                 try {
    347                     LatLon centerLL = new LatLon(Double.parseDouble(centerEl.getAttribute("lat")),
    348                             Double.parseDouble(centerEl.getAttribute("lon")));
    349                     center = Projections.project(centerLL);
    350                 } catch (NumberFormatException ex) {
    351                     Main.warn(ex);
    352                 }
    353             }
    354             if (center != null) {
    355                 Element scaleEl = getElementByTagName(viewportEl, "scale");
    356                 if (scaleEl != null && scaleEl.hasAttribute("meter-per-pixel")) {
    357                     try {
    358                         double meterPerPixel = Double.parseDouble(scaleEl.getAttribute("meter-per-pixel"));
    359                         Projection proj = Main.getProjection();
    360                         // Get a "typical" distance in east/north units that
    361                         // corresponds to a couple of pixels. Shouldn't be too
    362                         // large, to keep it within projection bounds and
    363                         // not too small to avoid rounding errors.
    364                         double dist = 0.01 * proj.getDefaultZoomInPPD();
    365                         LatLon ll1 = proj.eastNorth2latlon(new EastNorth(center.east() - dist, center.north()));
    366                         LatLon ll2 = proj.eastNorth2latlon(new EastNorth(center.east() + dist, center.north()));
    367                         double meterPerEasting = ll1.greatCircleDistance(ll2) / dist / 2;
    368                         double scale = meterPerPixel / meterPerEasting; // unit: easting per pixel
    369                         viewport = new ViewportData(center, scale);
    370                     } catch (NumberFormatException ex) {
    371                         Main.warn(ex);
    372                     }
    373                 }
    374             }
    375         }
     440        viewport = readViewportData(root);
     441        projectionChoice = readProjectionChoiceData(root);
    376442
    377443        Element layersEl = getElementByTagName(root, "layers");
     
    550616    }
    551617
     618    private SessionViewportData readViewportData(Element root) {
     619        Element viewportEl = getElementByTagName(root, "viewport");
     620        if (viewportEl == null) return null;
     621        LatLon center = null;
     622        Element centerEl = getElementByTagName(viewportEl, "center");
     623        if (centerEl == null || !centerEl.hasAttribute("lat") || !centerEl.hasAttribute("lon")) return null;
     624        try {
     625            center = new LatLon(Double.parseDouble(centerEl.getAttribute("lat")),
     626                    Double.parseDouble(centerEl.getAttribute("lon")));
     627        } catch (NumberFormatException ex) {
     628            Main.warn(ex);
     629        }
     630        if (center == null) return null;
     631        Element scaleEl = getElementByTagName(viewportEl, "scale");
     632        if (scaleEl == null || !scaleEl.hasAttribute("meter-per-pixel")) return null;
     633        try {
     634            double scale = Double.parseDouble(scaleEl.getAttribute("meter-per-pixel"));
     635            return new SessionViewportData(center, scale);
     636        } catch (NumberFormatException ex) {
     637            Main.warn(ex);
     638            return null;
     639        }
     640    }
     641
     642    private SessionProjectionChoiceData readProjectionChoiceData(Element root) {
     643        Element projectionEl = getElementByTagName(root, "projection");
     644        if (projectionEl == null) return null;
     645        Element projectionChoiceEl = getElementByTagName(projectionEl, "projection-choice");
     646        if (projectionChoiceEl == null) return null;
     647        Element idEl = getElementByTagName(projectionChoiceEl, "id");
     648        if (idEl == null) return null;
     649        String id = idEl.getTextContent();
     650        Element parametersEl = getElementByTagName(projectionChoiceEl, "parameters");
     651        if (parametersEl == null) return null;
     652        Collection<String> parameters = new ArrayList<>();
     653        NodeList paramNl = parametersEl.getElementsByTagName("param");
     654        for (int i=0; i<paramNl.getLength(); i++) {
     655            Element paramEl = (Element) paramNl.item(i);
     656            parameters.add(paramEl.getTextContent());
     657        }
     658        return new SessionProjectionChoiceData(id, parameters);
     659    }
     660
    552661    /**
    553662     * Show Dialog when there is an error for one layer.
  • trunk/src/org/openstreetmap/josm/io/session/SessionWriter.java

    r11795 r12486  
    1111import java.nio.charset.StandardCharsets;
    1212import java.util.ArrayList;
     13import java.util.Collection;
    1314import java.util.HashMap;
    1415import java.util.List;
     
    4041import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
    4142import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
     43import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
    4244import org.openstreetmap.josm.tools.JosmRuntimeException;
    4345import org.openstreetmap.josm.tools.MultiMap;
     
    213215        doc.appendChild(root);
    214216
    215         Element viewportEl = doc.createElement("viewport");
    216         root.appendChild(viewportEl);
    217         Element centerEl = doc.createElement("center");
    218         viewportEl.appendChild(centerEl);
    219         EastNorth center = Main.map.mapView.getCenter();
    220         LatLon centerLL = Projections.inverseProject(center);
    221         centerEl.setAttribute("lat", Double.toString(centerLL.lat()));
    222         centerEl.setAttribute("lon", Double.toString(centerLL.lon()));
    223         Element scale = doc.createElement("scale");
    224         viewportEl.appendChild(scale);
    225         double dist100px = Main.map.mapView.getDist100Pixel();
    226         scale.setAttribute("meter-per-pixel", Double.toString(dist100px / 100));
     217        writeViewPort(root);
     218        writeProjection(root);
    227219
    228220        Element layersEl = doc.createElement("layers");
     
    263255    }
    264256
     257    private void writeViewPort(Element root) {
     258        Document doc = root.getOwnerDocument();
     259        Element viewportEl = doc.createElement("viewport");
     260        root.appendChild(viewportEl);
     261        Element centerEl = doc.createElement("center");
     262        viewportEl.appendChild(centerEl);
     263        EastNorth center = Main.map.mapView.getCenter();
     264        LatLon centerLL = Projections.inverseProject(center);
     265        centerEl.setAttribute("lat", Double.toString(centerLL.lat()));
     266        centerEl.setAttribute("lon", Double.toString(centerLL.lon()));
     267        Element scale = doc.createElement("scale");
     268        viewportEl.appendChild(scale);
     269        double dist100px = Main.map.mapView.getDist100Pixel();
     270        scale.setAttribute("meter-per-pixel", Double.toString(dist100px / 100));
     271    }
     272
     273    private void writeProjection(Element root) {
     274        Document doc = root.getOwnerDocument();
     275        Element projectionEl = doc.createElement("projection");
     276        root.appendChild(projectionEl);
     277        String pcId = ProjectionPreference.getCurrentProjectionChoiceId();
     278        Element projectionChoiceEl = doc.createElement("projection-choice");
     279        projectionEl.appendChild(projectionChoiceEl);
     280        Element idEl = doc.createElement("id");
     281        projectionChoiceEl.appendChild(idEl);
     282        idEl.setTextContent(pcId);
     283        Collection<String> parameters = ProjectionPreference.getSubprojectionPreference(pcId);
     284        Element parametersEl = doc.createElement("parameters");
     285        projectionChoiceEl.appendChild(parametersEl);
     286        for (String param : parameters) {
     287            Element paramEl = doc.createElement("param");
     288            parametersEl.appendChild(paramEl);
     289            paramEl.setTextContent(param);
     290        }
     291        String code = Main.getProjection().toCode();
     292        Element codeEl = doc.createElement("code");
     293        projectionEl.appendChild(codeEl);
     294        codeEl.setTextContent(code);
     295    }
     296
    265297    /**
    266298     * Writes given .jos document to an output stream.
Note: See TracChangeset for help on using the changeset viewer.