Changeset 13210 in josm


Ignore:
Timestamp:
2017-12-17T15:37:11+01:00 (4 months ago)
Author:
Don-vip
Message:

fix #15606 - export relation to GPX file or convert to a new GPX layer (patch by cmuelle8, modified)

Location:
trunk
Files:
1 added
8 edited

Legend:

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

    r12671 r13210  
    3737                Shortcut.registerShortcut("file:exportgpx", tr("Export to GPX..."), KeyEvent.VK_E, Shortcut.CTRL));
    3838        putValue("help", ht("/Action/GpxExport"));
     39    }
     40
     41    /**
     42     * Deferring constructor for child classes.
     43     *
     44     * @param name see {@code DiskAccessAction}
     45     * @param iconName see {@code DiskAccessAction}
     46     * @param tooltip see {@code DiskAccessAction}
     47     * @param shortcut see {@code DiskAccessAction}
     48     * @param register see {@code DiskAccessAction}
     49     * @param toolbarId see {@code DiskAccessAction}
     50     * @param installAdapters see {@code DiskAccessAction}
     51     *
     52     * @since 13210
     53     */
     54    protected GpxExportAction(String name, String iconName, String tooltip, Shortcut shortcut,
     55            boolean register, String toolbarId, boolean installAdapters) {
     56        super(name, iconName, tooltip, shortcut, register, toolbarId, installAdapters);
    3957    }
    4058
  • trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java

    r13136 r13210  
    55import java.text.MessageFormat;
    66import java.util.ArrayList;
     7import java.util.Arrays;
    78import java.util.Collection;
    89import java.util.Collections;
    910import java.util.Date;
    1011import java.util.DoubleSummaryStatistics;
     12import java.util.HashMap;
    1113import java.util.HashSet;
    1214import java.util.Iterator;
     15import java.util.List;
    1316import java.util.Map;
    1417import java.util.NoSuchElementException;
    1518import java.util.Set;
     19import java.util.stream.Collectors;
    1620import java.util.stream.Stream;
    1721
     
    2226import org.openstreetmap.josm.data.coor.EastNorth;
    2327import org.openstreetmap.josm.data.gpx.GpxTrack.GpxTrackChangeListener;
     28import org.openstreetmap.josm.gui.MainApplication;
     29import org.openstreetmap.josm.gui.layer.GpxLayer;
    2430import org.openstreetmap.josm.tools.ListenerList;
    2531import org.openstreetmap.josm.tools.ListeningCollection;
     
    141147
    142148    /**
     149     * Get Stream<> of track segments as introduced in Java 8.
     150     * @return {@code Stream<GPXTrack>}
     151     */
     152    private synchronized Stream<GpxTrackSegment> getTrackSegmentsStream() {
     153        return getTracks().stream().flatMap(trk -> trk.getSegments().stream());
     154    }
     155
     156    /**
     157     * Clear all tracks, empties the current privateTracks container,
     158     * helper method for some gpx manipulations.
     159     */
     160    private synchronized void clearTracks() {
     161        privateTracks.forEach(t -> t.removeListener(proxy));
     162        privateTracks.clear();
     163    }
     164
     165    /**
    143166     * Add a new track
    144167     * @param track The new track
     
    165188        track.removeListener(proxy);
    166189        fireInvalidate();
     190    }
     191
     192    /**
     193     * Combine tracks into a single, segmented track.
     194     * The attributes of the first track are used, the rest discarded.
     195     *
     196     * @since 13210
     197     */
     198    public synchronized void combineTracksToSegmentedTrack() {
     199        List<GpxTrackSegment> segs = getTrackSegmentsStream()
     200                .collect(Collectors.toCollection(ArrayList<GpxTrackSegment>::new));
     201        Map<String, Object> attrs = new HashMap<>(privateTracks.get(0).getAttributes());
     202
     203        // do not let the name grow if split / combine operations are called iteratively
     204        attrs.put("name", attrs.get("name").toString().replaceFirst(" #\\d+$", ""));
     205
     206        clearTracks();
     207        addTrack(new ImmutableGpxTrack(segs, attrs));
     208    }
     209
     210    /**
     211     * @param attrs attributes of/for an gpx track, written to if the name appeared previously in {@code counts}.
     212     * @param counts a {@code HashMap} of previously seen names, associated with their count.
     213     * @return the unique name for the gpx track.
     214     *
     215     * @since 13210
     216     */
     217    public static String ensureUniqueName(Map<String, Object> attrs, Map<String, Integer> counts) {
     218        String name = attrs.getOrDefault("name", "GPX split result").toString();
     219        Integer count = counts.getOrDefault(name, 0) + 1;
     220        counts.put(name, count);
     221
     222        attrs.put("name", MessageFormat.format("{0}{1}", name, (count > 1) ? " #"+count : ""));
     223        return attrs.get("name").toString();
     224    }
     225
     226    /**
     227     * Split tracks so that only single-segment tracks remain.
     228     * Each segment will make up one individual track after this operation.
     229     *
     230     * @since 13210
     231     */
     232    public synchronized void splitTrackSegmentsToTracks() {
     233        final HashMap<String, Integer> counts = new HashMap<>();
     234
     235        List<GpxTrack> trks = getTracks().stream()
     236            .flatMap(trk -> {
     237                return trk.getSegments().stream().map(seg -> {
     238                    HashMap<String, Object> attrs = new HashMap<>(trk.getAttributes());
     239                    ensureUniqueName(attrs, counts);
     240                    return new ImmutableGpxTrack(Arrays.asList(seg), attrs);
     241                });
     242            })
     243            .collect(Collectors.toCollection(ArrayList<GpxTrack>::new));
     244
     245        clearTracks();
     246        trks.stream().forEachOrdered(trk -> addTrack(trk));
     247    }
     248
     249    /**
     250     * Split tracks into layers, the result is one layer for each track.
     251     * If this layer currently has only one GpxTrack this is a no-operation.
     252     *
     253     * The new GpxLayers are added to the LayerManager, the original GpxLayer
     254     * is untouched as to preserve potential route or wpt parts.
     255     *
     256     * @since 13210
     257     */
     258    public synchronized void splitTracksToLayers() {
     259        final HashMap<String, Integer> counts = new HashMap<>();
     260
     261        getTracks().stream()
     262            .filter(trk -> privateTracks.size() > 1)
     263            .map(trk -> {
     264                HashMap<String, Object> attrs = new HashMap<>(trk.getAttributes());
     265                GpxData d = new GpxData();
     266                d.addTrack(trk);
     267                return new GpxLayer(d, ensureUniqueName(attrs, counts)); })
     268            .forEachOrdered(layer -> MainApplication.getLayerManager().addLayer(layer));
     269    }
     270
     271    /**
     272     * Replies the current number of tracks in this GpxData
     273     * @return track count
     274     * @since 13210
     275     */
     276    public synchronized int getTrackCount() {
     277        return privateTracks.size();
     278    }
     279
     280    /**
     281     * Replies the accumulated total of all track segments,
     282     * the sum of segment counts for each track present.
     283     * @return track segments count
     284     * @since 13210
     285     */
     286    public synchronized int getTrackSegsCount() {
     287        return privateTracks.stream().collect(Collectors.summingInt(t -> t.getSegments().size()));
    167288    }
    168289
  • trunk/src/org/openstreetmap/josm/data/gpx/ImmutableGpxTrack.java

    r12289 r13210  
    3535        this.attr = Collections.unmodifiableMap(new HashMap<>(attributes));
    3636        this.segments = Collections.unmodifiableList(newSegments);
     37        this.length = calculateLength();
     38        this.bounds = calculateBounds();
     39    }
     40
     41    /**
     42     * Constructs a new {@code ImmutableGpxTrack} from {@code GpxTrackSegment} objects.
     43     * @param segments The segments to build the track from.  Input is not deep-copied,
     44     *                 which means the caller may reuse the same segments to build
     45     *                 multiple ImmutableGpxTrack instances from.  This should not be
     46     *                 a problem, since this object cannot modify {@code this.segments}.
     47     * @param attributes Attributes for the GpxTrack, the input map is copied.
     48     * @since 13210
     49     */
     50    public ImmutableGpxTrack(List<GpxTrackSegment> segments, Map<String, Object> attributes) {
     51        this.attr = Collections.unmodifiableMap(new HashMap<>(attributes));
     52        this.segments = Collections.unmodifiableList(segments);
    3753        this.length = calculateLength();
    3854        this.bounds = calculateBounds();
  • trunk/src/org/openstreetmap/josm/data/gpx/WayPoint.java

    r12656 r13210  
    143143    public void setTime() {
    144144        setTimeFromAttribute();
     145    }
     146
     147    /**
     148     * Set the the time stamp of the waypoint into seconds from the epoch,
     149     * @param time millisecond from the epoch
     150     * @since 13210
     151     */
     152    public void setTime(long time) {
     153        this.time = time / 1000.;
    145154    }
    146155
  • trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java

    r12846 r13210  
    1313import java.util.Collection;
    1414import java.util.Collections;
     15import java.util.EnumSet;
    1516import java.util.HashSet;
    1617import java.util.List;
     
    2930import javax.swing.KeyStroke;
    3031import javax.swing.ListSelectionModel;
     32import javax.swing.event.PopupMenuEvent;
     33import javax.swing.event.PopupMenuListener;
    3134
    3235import org.openstreetmap.josm.Main;
    3336import org.openstreetmap.josm.actions.ExpertToggleAction;
     37import org.openstreetmap.josm.actions.OsmPrimitiveAction;
    3438import org.openstreetmap.josm.actions.relation.AddSelectionToRelations;
    3539import org.openstreetmap.josm.actions.relation.DeleteRelationsAction;
     
    3842import org.openstreetmap.josm.actions.relation.DuplicateRelationAction;
    3943import org.openstreetmap.josm.actions.relation.EditRelationAction;
     44import org.openstreetmap.josm.actions.relation.ExportRelationToGpxAction;
     45import org.openstreetmap.josm.actions.relation.ExportRelationToGpxAction.Mode;
    4046import org.openstreetmap.josm.actions.relation.RecentRelationsAction;
    4147import org.openstreetmap.josm.actions.relation.SelectMembersAction;
     
    122128    private transient JMenuItem addSelectionToRelationMenuItem;
    123129
     130    /** export relation to GPX track action */
     131    private final ExportRelationToGpxAction exportRelationFromFirstAction =
     132            new ExportRelationToGpxAction(EnumSet.of(Mode.FROM_FIRST_MEMBER, Mode.TO_FILE));
     133    private final ExportRelationToGpxAction exportRelationFromLastAction =
     134            new ExportRelationToGpxAction(EnumSet.of(Mode.FROM_LAST_MEMBER, Mode.TO_FILE));
     135    private final ExportRelationToGpxAction exportRelationFromFirstToLayerAction =
     136            new ExportRelationToGpxAction(EnumSet.of(Mode.FROM_FIRST_MEMBER, Mode.TO_LAYER));
     137    private final ExportRelationToGpxAction exportRelationFromLastToLayerAction =
     138            new ExportRelationToGpxAction(EnumSet.of(Mode.FROM_LAST_MEMBER, Mode.TO_LAYER));
     139
    124140    private final transient HighlightHelper highlightHelper = new HighlightHelper();
    125141    private final boolean highlightEnabled = Config.getPref().getBoolean("draw.target-highlight", true);
     
    603619
    604620    private void setupPopupMenuHandler() {
     621        List<JMenuItem> checkDisabled = new ArrayList<>();
    605622
    606623        // -- select action
     
    612629        popupMenuHandler.addAction(addMembersToSelectionAction);
    613630
     631        // -- download members action
    614632        popupMenuHandler.addSeparator();
    615         // -- download members action
    616633        popupMenuHandler.addAction(downloadMembersAction);
    617 
    618         // -- download incomplete members action
    619634        popupMenuHandler.addAction(downloadSelectedIncompleteMembersAction);
     635
     636        // -- export relation to gpx action
     637        popupMenuHandler.addSeparator();
     638        checkDisabled.add(popupMenuHandler.addAction(exportRelationFromFirstAction));
     639        checkDisabled.add(popupMenuHandler.addAction(exportRelationFromLastAction));
     640        popupMenuHandler.addSeparator();
     641        checkDisabled.add(popupMenuHandler.addAction(exportRelationFromFirstToLayerAction));
     642        checkDisabled.add(popupMenuHandler.addAction(exportRelationFromLastToLayerAction));
    620643
    621644        popupMenuHandler.addSeparator();
     
    625648
    626649        addSelectionToRelationMenuItem = popupMenuHandler.addAction(addSelectionToRelations);
     650
     651        popupMenuHandler.addListener(new PopupMenuListener() {
     652            @Override
     653            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
     654                for (JMenuItem mi: checkDisabled) {
     655                    mi.setVisible(((OsmPrimitiveAction) mi.getAction()).isEnabled());
     656
     657                    Component sep = popupMenu.getComponent(
     658                            Math.max(0, popupMenu.getComponentIndex(mi)-1));
     659                    if (!(sep instanceof JMenuItem)) {
     660                        sep.setVisible(mi.isVisible());
     661                    }
     662                }
     663            }
     664
     665            @Override
     666            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
     667            }
     668
     669            @Override
     670            public void popupMenuCanceled(PopupMenuEvent e) {
     671            }
     672        });
    627673    }
    628674
  • trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java

    r12987 r13210  
    77import java.awt.Dimension;
    88import java.awt.Graphics2D;
     9import java.awt.event.ActionEvent;
    910import java.io.File;
    1011import java.text.DateFormat;
     12import java.util.ArrayList;
    1113import java.util.Arrays;
    1214import java.util.Date;
    13 
     15import java.util.List;
     16
     17import javax.swing.AbstractAction;
    1418import javax.swing.Action;
    1519import javax.swing.Icon;
     
    1721import javax.swing.SwingUtilities;
    1822
     23import org.openstreetmap.josm.actions.ExpertToggleAction;
     24import org.openstreetmap.josm.actions.ExpertToggleAction.ExpertModeChangeListener;
    1925import org.openstreetmap.josm.actions.RenameLayerAction;
    2026import org.openstreetmap.josm.actions.SaveActionBase;
     
    4854 * A layer that displays data from a Gpx file / the OSM gpx downloads.
    4955 */
    50 public class GpxLayer extends Layer {
     56public class GpxLayer extends Layer implements ExpertModeChangeListener {
    5157
    5258    /** GPX data */
    5359    public GpxData data;
    5460    private final boolean isLocalFile;
     61    private boolean isExpertMode;
    5562    /**
    5663     * used by {@link ChooseTrackVisibilityAction} to determine which tracks to show/hide
     
    8491
    8592    /**
    86      * Constructs a new {@code GpxLayer} with a given name, thah can be attached to a local file.
     93     * Constructs a new {@code GpxLayer} with a given name, that can be attached to a local file.
    8794     * @param d GPX data
    8895     * @param name layer name
     
    97104        setName(name);
    98105        isLocalFile = isLocal;
     106        ExpertToggleAction.addExpertModeChangeListener(this, true);
    99107    }
    100108
     
    139147    @Override
    140148    public Object getInfoComponent() {
    141         StringBuilder info = new StringBuilder(48).append("<html>");
     149        StringBuilder info = new StringBuilder(128)
     150                .append("<html><head><style>")
     151                .append("td { padding: 4px 16px; }")
     152                .append("</style></head><body>");
    142153
    143154        if (data.attr.containsKey("name")) {
     
    151162        if (!data.getTracks().isEmpty()) {
    152163            info.append("<table><thead align='center'><tr><td colspan='5'>")
    153                 .append(trn("{0} track", "{0} tracks", data.tracks.size(), data.tracks.size()))
    154                 .append("</td></tr><tr align='center'><td>").append(tr("Name")).append("</td><td>")
    155                 .append(tr("Description")).append("</td><td>").append(tr("Timespan"))
    156                 .append("</td><td>").append(tr("Length")).append("</td><td>").append(tr("URL"))
     164                .append(trn("{0} track, {1} track segments", "{0} tracks, {1} track segments",
     165                        data.getTrackCount(), data.getTrackCount(),
     166                        data.getTrackSegsCount(), data.getTrackSegsCount()))
     167                .append("</td></tr><tr align='center'><td>").append(tr("Name"))
     168                .append("</td><td>").append(tr("Description"))
     169                .append("</td><td>").append(tr("Timespan"))
     170                .append("</td><td>").append(tr("Length"))
     171                .append("</td><td>").append(tr("Number of<br/>Segments"))
     172                .append("</td><td>").append(tr("URL"))
    157173                .append("</td></tr></thead>");
    158174
     
    171187                info.append(SystemOfMeasurement.getSystemOfMeasurement().getDistText(trk.length()));
    172188                info.append("</td><td>");
     189                info.append(trk.getSegments().size());
     190                info.append("</td><td>");
    173191                if (trk.getAttributes().containsKey("url")) {
    174192                    info.append(trk.get("url"));
     
    181199        info.append(tr("Length: {0}", SystemOfMeasurement.getSystemOfMeasurement().getDistText(data.length()))).append("<br>")
    182200            .append(trn("{0} route, ", "{0} routes, ", data.getRoutes().size(), data.getRoutes().size()))
    183             .append(trn("{0} waypoint", "{0} waypoints", data.getWaypoints().size(), data.getWaypoints().size())).append("<br></html>");
     201            .append(trn("{0} waypoint", "{0} waypoints", data.getWaypoints().size(), data.getWaypoints().size()))
     202            .append("<br></body></html>");
    184203
    185204        final JScrollPane sp = new JScrollPane(new HtmlPanel(info.toString()));
     
    196215    @Override
    197216    public Action[] getMenuEntries() {
    198         return new Action[] {
     217        List<Action> entries = new ArrayList<>(Arrays.asList(
    199218                LayerListDialog.getInstance().createShowHideLayerAction(),
    200219                LayerListDialog.getInstance().createDeleteLayerAction(),
     
    213232                SeparatorLayerAction.INSTANCE,
    214233                new ChooseTrackVisibilityAction(this),
    215                 new RenameLayerAction(getAssociatedFile(), this),
    216                 SeparatorLayerAction.INSTANCE,
    217                 new LayerListPopup.InfoAction(this) };
     234                new RenameLayerAction(getAssociatedFile(), this)));
     235
     236        List<Action> expert = Arrays.asList(
     237                new CombineTracksToSegmentedTrackAction(this),
     238                new SplitTrackSegementsToTracksAction(this),
     239                new SplitTracksToLayersAction(this));
     240
     241        if (isExpertMode && expert.stream().anyMatch(t -> t.isEnabled())) {
     242            entries.add(SeparatorLayerAction.INSTANCE);
     243            expert.stream().filter(t -> t.isEnabled()).forEach(t -> entries.add(t));
     244        }
     245
     246        entries.add(SeparatorLayerAction.INSTANCE);
     247        entries.add(new LayerListPopup.InfoAction(this));
     248        return entries.toArray(new Action[0]);
    218249    }
    219250
     
    238269        }
    239270
    240         info.append(trn("{0} track, ", "{0} tracks, ", data.getTracks().size(), data.getTracks().size()))
     271        info.append(trn("{0} track", "{0} tracks", data.getTrackCount(), data.getTrackCount()))
     272            .append(trn(" ({0} segment)", " ({0} segments)", data.getTrackSegsCount(), data.getTrackSegsCount()))
     273            .append(", ")
    241274            .append(trn("{0} route, ", "{0} routes, ", data.getRoutes().size(), data.getRoutes().size()))
    242275            .append(trn("{0} waypoint", "{0} waypoints", data.getWaypoints().size(), data.getWaypoints().size())).append("<br>")
     
    330363        return new GpxDrawHelper(this);
    331364    }
     365
     366    /**
     367     * Action to merge tracks into a single segmented track
     368     *
     369     * @since 13210
     370     */
     371    public static class CombineTracksToSegmentedTrackAction extends AbstractAction {
     372        private final transient GpxLayer layer;
     373
     374        /**
     375         * Create a new CombineTracksToSegmentedTrackAction
     376         * @param layer The layer with the data to work on.
     377         */
     378        public CombineTracksToSegmentedTrackAction(GpxLayer layer) {
     379            // FIXME: icon missing, create a new icon for this action
     380            //new ImageProvider("gpx_tracks_to_segmented_track").getResource().attachImageIcon(this, true);
     381            putValue(SHORT_DESCRIPTION, tr("Collect segments of all tracks and combine in a single track."));
     382            putValue(NAME, tr("Combine tracks of this layer"));
     383            this.layer = layer;
     384        }
     385
     386        @Override
     387        public void actionPerformed(ActionEvent e) {
     388            layer.data.combineTracksToSegmentedTrack();
     389            layer.invalidate();
     390        }
     391
     392        @Override
     393        public boolean isEnabled() {
     394            return layer.data.getTrackCount() > 1;
     395        }
     396    }
     397
     398    /**
     399     * Action to split track segments into a multiple tracks with one segment each
     400     *
     401     * @since 13210
     402     */
     403    public static class SplitTrackSegementsToTracksAction extends AbstractAction {
     404        private final transient GpxLayer layer;
     405
     406        /**
     407         * Create a new SplitTrackSegementsToTracksAction
     408         * @param layer The layer with the data to work on.
     409         */
     410        public SplitTrackSegementsToTracksAction(GpxLayer layer) {
     411            // FIXME: icon missing, create a new icon for this action
     412            //new ImageProvider("gpx_segmented_track_to_tracks").getResource().attachImageIcon(this, true);
     413            putValue(SHORT_DESCRIPTION, tr("Split multiple track segments of one track into multiple tracks."));
     414            putValue(NAME, tr("Split track segments to tracks"));
     415            this.layer = layer;
     416        }
     417
     418        @Override
     419        public void actionPerformed(ActionEvent e) {
     420            layer.data.splitTrackSegmentsToTracks();
     421            layer.invalidate();
     422        }
     423
     424        @Override
     425        public boolean isEnabled() {
     426            return layer.data.getTrackSegsCount() > layer.data.getTrackCount();
     427        }
     428    }
     429
     430    /**
     431     * Action to split tracks of one gpx layer into multiple gpx layers,
     432     * the result is one GPX track per gpx layer.
     433     *
     434     * @since 13210
     435     */
     436    public static class SplitTracksToLayersAction extends AbstractAction {
     437        private final transient GpxLayer layer;
     438
     439        /**
     440         * Create a new SplitTrackSegementsToTracksAction
     441         * @param layer The layer with the data to work on.
     442         */
     443        public SplitTracksToLayersAction(GpxLayer layer) {
     444            // FIXME: icon missing, create a new icon for this action
     445            //new ImageProvider("gpx_split_tracks_to_layers").getResource().attachImageIcon(this, true);
     446            putValue(SHORT_DESCRIPTION, tr("Split the tracks of this layer to one new layer each."));
     447            putValue(NAME, tr("Split tracks to new layers"));
     448            this.layer = layer;
     449        }
     450
     451        @Override
     452        public void actionPerformed(ActionEvent e) {
     453            layer.data.splitTracksToLayers();
     454            // layer is not modified by this action
     455        }
     456
     457        @Override
     458        public boolean isEnabled() {
     459            return layer.data.getTrackCount() > 1;
     460        }
     461    }
     462
     463    @Override
     464    public void expertChanged(boolean isExpert) {
     465        this.isExpertMode = isExpert;
     466    }
    332467}
  • trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java

    r13206 r13210  
    740740    }
    741741
    742     private static WayPoint nodeToWayPoint(Node n) {
     742    /**
     743     * @param n the {@code Node} to convert
     744     * @return {@code WayPoint} object
     745     * @since 13210
     746     */
     747    public static WayPoint nodeToWayPoint(Node n) {
     748        return nodeToWayPoint(n, 0);
     749    }
     750
     751    /**
     752     * @param n the {@code Node} to convert
     753     * @param time a time value in milliseconds from the epoch.
     754     * @return {@code WayPoint} object
     755     * @since 13210
     756     */
     757    public static WayPoint nodeToWayPoint(Node n, long time) {
    743758        WayPoint wpt = new WayPoint(n.getCoor());
    744759
     
    747762        addDoubleIfPresent(wpt, n, GpxConstants.PT_ELE);
    748763
    749         if (!n.isTimestampEmpty()) {
     764        if (time > 0) {
     765            wpt.setTime(time);
     766        } else if (!n.isTimestampEmpty()) {
    750767            wpt.put("time", DateUtils.fromTimestamp(n.getRawTimestamp()));
    751768            wpt.setTime();
  • trunk/test/unit/org/openstreetmap/josm/data/gpx/GpxDataTest.java

    r13079 r13210  
    1010import java.util.ArrayList;
    1111import java.util.Arrays;
     12import java.util.Collection;
    1213import java.util.Collections;
    1314import java.util.Date;
     
    424425
    425426    private static ImmutableGpxTrack emptyGpxTrack() {
    426         return new ImmutableGpxTrack(Collections.emptyList(), Collections.emptyMap());
     427        return new ImmutableGpxTrack(Collections.<Collection<WayPoint>>emptyList(), Collections.emptyMap());
    427428    }
    428429
Note: See TracChangeset for help on using the changeset viewer.