Changeset 27760 in osm for applications


Ignore:
Timestamp:
2012-02-14T21:43:28+01:00 (13 years ago)
Author:
stoecker
Message:

remove calls to deprecated Preferences.hasKey()

Location:
applications/editors/josm/plugins
Files:
1 deleted
5 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/gpxfilter/src/gpxfilter/EGpxLayer.java

    r26509 r27760  
    33package gpxfilter;
    44
    5 import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
    6 import static org.openstreetmap.josm.tools.I18n.marktr;
    75import static org.openstreetmap.josm.tools.I18n.tr;
    8 import static org.openstreetmap.josm.tools.I18n.trn;
    9 
    10 import java.awt.BasicStroke;
    11 import java.awt.Color;
    12 import java.awt.Dimension;
    13 import java.awt.Graphics2D;
    14 import java.awt.GridBagLayout;
    15 import java.awt.Point;
    16 import java.awt.event.ActionEvent;
    17 import java.awt.geom.Area;
    18 import java.awt.geom.Rectangle2D;
    19 import java.io.File;
    20 import java.net.MalformedURLException;
    21 import java.net.URL;
    22 import java.text.DateFormat;
    23 import java.util.ArrayList;
    24 import java.util.Arrays;
    25 import java.util.Collection;
    26 import java.util.Collections;
    27 import java.util.Comparator;
    28 import java.util.LinkedList;
    29 import java.util.List;
    30 import java.util.concurrent.Future;
    31 
    32 import javax.swing.AbstractAction;
    33 import javax.swing.Action;
    34 import javax.swing.Box;
    35 import javax.swing.ButtonGroup;
    36 import javax.swing.Icon;
    37 import javax.swing.JColorChooser;
    38 import javax.swing.JFileChooser;
    39 import javax.swing.JLabel;
    40 import javax.swing.JList;
    41 import javax.swing.JOptionPane;
    42 import javax.swing.JPanel;
    43 import javax.swing.JRadioButton;
    44 import javax.swing.JScrollPane;
    45 import javax.swing.SwingUtilities;
    46 import javax.swing.filechooser.FileFilter;
    476
    487import org.openstreetmap.josm.Main;
    49 import org.openstreetmap.josm.actions.RenameLayerAction;
    50 import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTaskList;
    518import org.openstreetmap.josm.data.Bounds;
    52 import org.openstreetmap.josm.data.coor.EastNorth;
    53 import org.openstreetmap.josm.data.coor.LatLon;
    549import org.openstreetmap.josm.data.gpx.GpxData;
    55 import org.openstreetmap.josm.data.gpx.GpxTrack;
    56 import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
    57 import org.openstreetmap.josm.data.gpx.WayPoint;
    58 import org.openstreetmap.josm.data.osm.DataSet;
    59 import org.openstreetmap.josm.data.osm.Node;
    60 import org.openstreetmap.josm.data.osm.Way;
    61 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
    62 import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
    63 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    64 import org.openstreetmap.josm.gui.MapView;
    65 import org.openstreetmap.josm.gui.NavigatableComponent;
    66 import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
    67 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
    68 import org.openstreetmap.josm.gui.layer.Layer;
    69 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    70 import org.openstreetmap.josm.gui.layer.markerlayer.AudioMarker;
    71 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
    72 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    73 import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
    74 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
    75 import org.openstreetmap.josm.io.JpgImporter;
    76 import org.openstreetmap.josm.tools.AudioUtil;
    77 import org.openstreetmap.josm.tools.DateUtils;
    78 import org.openstreetmap.josm.tools.GBC;
    79 import org.openstreetmap.josm.tools.ImageProvider;
    80 import org.openstreetmap.josm.tools.UrlLabel;
     10import org.openstreetmap.josm.gui.layer.GpxLayer;
    8111
    82 public class EGpxLayer extends Layer {
    83 
    84     private static final String PREF_DOWNLOAD_ALONG_TRACK_DISTANCE = "gpxLayer.downloadAlongTrack.distance";
    85     private static final String PREF_DOWNLOAD_ALONG_TRACK_AREA = "gpxLayer.downloadAlongTrack.area";
    86     private static final String PREF_DOWNLOAD_ALONG_TRACK_NEAR = "gpxLayer.downloadAlongTrack.near";
    87 
    88     public final GpxData data = new GpxData();
    89     protected static final double PHI = Math.toRadians(15);
    90     private boolean computeCacheInSync;
    91     private int computeCacheMaxLineLengthUsed;
    92     private Color computeCacheColorUsed;
    93     private colorModes computeCacheColored;
    94     private int computeCacheColorTracksTune;
    95     private boolean isLocalFile;
    96 
    97     private final List<GpxTrack> lastTracks = new ArrayList<GpxTrack>(); // List of tracks at last paint
    98     private int lastUpdateCount;
    99     private final Bounds bounds;
    100     private volatile boolean painting;
    101 
    102     private static class Markers {
    103         public boolean timedMarkersOmitted = false;
    104         public boolean untimedMarkersOmitted = false;
    105     }
    106 
    107     public EGpxLayer(Bounds b) {
    108         super("GPX Data");
    109         this.bounds = b;
     12public class EGpxLayer extends GpxLayer {
     13    public EGpxLayer(final Bounds b) {
     14        super(new GpxData(), tr("GPX Data"));
    11015        Thread t = new Thread(new Runnable()
    11116        {
    11217            @Override
    11318            public void run() {
    114                 GpxGrabber grabber = new GpxGrabber(EGpxLayer.this.bounds);
     19                GpxGrabber grabber = new GpxGrabber(b);
    11520                while (true) {
    11621                    GpxData newData;
     
    12631                    }
    12732
    128                     if (!EGpxLayer.this.painting) {
    129                         Main.map.repaint();
    130                     }
     33                    Main.map.repaint();
    13134                }
    13235                grabber.cancel();
     
    13639        t.start();
    13740    }
    138 
    139     @Override
    140     public Icon getIcon() {
    141         return ImageProvider.get("layer", "gpx_small");
    142     }
    143 
    144     @Override
    145     public synchronized Object getInfoComponent() {
    146         StringBuilder info = new StringBuilder();
    147 
    148         if (data.attr.containsKey("name")) {
    149             info.append(tr("Name: {0}", data.attr.get(GpxData.META_NAME))).append("<br>");
    150         }
    151 
    152         if (data.attr.containsKey("desc")) {
    153             info.append(tr("Description: {0}", data.attr.get(GpxData.META_DESC))).append("<br>");
    154         }
    155 
    156         if (data.tracks.size() > 0) {
    157             info.append("<table><thead align='center'><tr><td colspan='5'>"
    158                     + trn("{0} track", "{0} tracks", data.tracks.size(), data.tracks.size())
    159                     + "</td></tr><tr align='center'><td>" + tr("Name") + "</td><td>"
    160                     + tr("Description") + "</td><td>" + tr("Timespan")
    161                     + "</td><td>" + tr("Length") + "</td><td>" + tr("URL")
    162                     + "</td></tr></thead>");
    163 
    164             for (GpxTrack trk : data.tracks) {
    165                 WayPoint earliest = null, latest = null;
    166 
    167                 info.append("<tr><td>");
    168                 if (trk.getAttributes().containsKey("name")) {
    169                     info.append(trk.getAttributes().get("name"));
    170                 }
    171                 info.append("</td><td>");
    172                 if (trk.getAttributes().containsKey("desc")) {
    173                     info.append(" ").append(trk.getAttributes().get("desc"));
    174                 }
    175                 info.append("</td><td>");
    176 
    177                 for (GpxTrackSegment seg : trk.getSegments()) {
    178                     for (WayPoint pnt : seg.getWayPoints()) {
    179                         if (latest == null) {
    180                             latest = earliest = pnt;
    181                         } else {
    182                             if (pnt.compareTo(earliest) < 0) {
    183                                 earliest = pnt;
    184                             } else {
    185                                 latest = pnt;
    186                             }
    187                         }
    188                     }
    189                 }
    190 
    191                 if (earliest != null && latest != null) {
    192                     DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
    193                     String earliestDate = df.format(earliest.getTime());
    194                     String latestDate = df.format(latest.getTime());
    195 
    196                     if (earliestDate.equals(latestDate)) {
    197                         DateFormat tf = DateFormat.getTimeInstance(DateFormat.SHORT);
    198                         info.append(earliestDate).append(" ");
    199                         info.append(tf.format(earliest.getTime())).append(" - ").append(tf.format(latest.getTime()));
    200                     } else {
    201                         DateFormat dtf = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
    202                         info.append(dtf.format(earliest.getTime())).append(" - ").append(dtf.format(latest.getTime()));
    203                     }
    204 
    205                     int diff = (int) (latest.time - earliest.time);
    206                     info.append(String.format(" (%d:%02d)", diff / 3600, (diff % 3600) / 60));
    207                 }
    208 
    209                 info.append("</td><td>");
    210                 info.append(NavigatableComponent.getSystemOfMeasurement().getDistText(trk.length()));
    211                 info.append("</td><td>");
    212                 if (trk.getAttributes().containsKey("url")) {
    213                     info.append(trk.getAttributes().get("url"));
    214                 }
    215                 info.append("</td></tr>");
    216             }
    217 
    218             info.append("</table><br><br>");
    219 
    220         }
    221 
    222         info.append(tr("Length: {0}", NavigatableComponent.getSystemOfMeasurement().getDistText(data.length()))).append("<br>");
    223 
    224         info.append(trn("{0} route, ", "{0} routes, ", data.routes.size(), data.routes.size())).append(
    225                 trn("{0} waypoint", "{0} waypoints", data.waypoints.size(), data.waypoints.size())).append("<br>");
    226 
    227         final JScrollPane sp = new JScrollPane(new HtmlPanel(info.toString()), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    228         sp.setPreferredSize(new Dimension(sp.getPreferredSize().width, 350));
    229         SwingUtilities.invokeLater(new Runnable() {
    230             @Override
    231             public void run() {
    232                 sp.getVerticalScrollBar().setValue(0);
    233             }
    234         });
    235         return sp;
    236     }
    237 
    238     static public Color getColor(String name) {
    239         return Main.pref.getColor(marktr("gps point"), name != null ? "layer " + name : null, Color.gray);
    240     }
    241 
    242     @Override
    243     public Action[] getMenuEntries() {
    244         if (Main.applet)
    245             return new Action[] {
    246                 LayerListDialog.getInstance().createShowHideLayerAction(),
    247                 LayerListDialog.getInstance().createDeleteLayerAction(),
    248                 SeparatorLayerAction.INSTANCE,
    249                 new CustomizeColor(),
    250                 new CustomizeLineDrawing(),
    251                 new ConvertToDataLayerAction(),
    252                 SeparatorLayerAction.INSTANCE,
    253                 new RenameLayerAction(getAssociatedFile(), this),
    254                 SeparatorLayerAction.INSTANCE,
    255                 new LayerListPopup.InfoAction(this) };
    256         return new Action[] {
    257                 LayerListDialog.getInstance().createShowHideLayerAction(),
    258                 LayerListDialog.getInstance().createDeleteLayerAction(),
    259                 SeparatorLayerAction.INSTANCE,
    260                 new LayerSaveAction(this),
    261                 new LayerSaveAsAction(this),
    262                 new CustomizeColor(),
    263                 new CustomizeLineDrawing(),
    264                 new ImportImages(),
    265                 new ImportAudio(),
    266                 new MarkersFromNamedPoins(),
    267                 new ConvertToDataLayerAction(),
    268                 new DownloadAlongTrackAction(),
    269                 SeparatorLayerAction.INSTANCE,
    270                 new RenameLayerAction(getAssociatedFile(), this),
    271                 SeparatorLayerAction.INSTANCE,
    272                 new LayerListPopup.InfoAction(this) };
    273     }
    274 
    275     @Override
    276     public synchronized String getToolTipText() {
    277         StringBuilder info = new StringBuilder().append("<html>");
    278 
    279         if (data.attr.containsKey("name")) {
    280             info.append(tr("Name: {0}", data.attr.get(GpxData.META_NAME))).append("<br>");
    281         }
    282 
    283         if (data.attr.containsKey("desc")) {
    284             info.append(tr("Description: {0}", data.attr.get(GpxData.META_DESC))).append("<br>");
    285         }
    286 
    287         info.append(trn("{0} track, ", "{0} tracks, ", data.tracks.size(), data.tracks.size()));
    288         info.append(trn("{0} route, ", "{0} routes, ", data.routes.size(), data.routes.size()));
    289         info.append(trn("{0} waypoint", "{0} waypoints", data.waypoints.size(), data.waypoints.size())).append("<br>");
    290 
    291         info.append(tr("Length: {0}", NavigatableComponent.getSystemOfMeasurement().getDistText(data.length())));
    292         info.append("<br>");
    293 
    294         return info.append("</html>").toString();
    295     }
    296 
    297     @Override
    298     public boolean isMergable(Layer other) {
    299         return other instanceof EGpxLayer;
    300     }
    301 
    302     private synchronized int sumUpdateCount() {
    303         int updateCount = 0;
    304         for (GpxTrack track: data.tracks) {
    305             updateCount += track.getUpdateCount();
    306         }
    307         return updateCount;
    308     }
    309 
    310     @Override
    311     public synchronized boolean isChanged() {
    312         if (data.tracks.equals(lastTracks))
    313             return sumUpdateCount() != lastUpdateCount;
    314         else
    315             return true;
    316     }
    317 
    318     @Override
    319     public synchronized void mergeFrom(Layer from) {
    320         data.mergeFrom(((EGpxLayer) from).data);
    321         computeCacheInSync = false;
    322     }
    323 
    324     private static Color[] colors = new Color[256];
    325     static {
    326         for (int i = 0; i < colors.length; i++) {
    327             colors[i] = Color.getHSBColor(i / 300.0f, 1, 1);
    328         }
    329     }
    330 
    331     // lookup array to draw arrows without doing any math
    332     private static int ll0 = 9;
    333     private static int sl4 = 5;
    334     private static int sl9 = 3;
    335     private static int[][] dir = { { +sl4, +ll0, +ll0, +sl4 }, { -sl9, +ll0, +sl9, +ll0 }, { -ll0, +sl4, -sl4, +ll0 },
    336         { -ll0, -sl9, -ll0, +sl9 }, { -sl4, -ll0, -ll0, -sl4 }, { +sl9, -ll0, -sl9, -ll0 },
    337         { +ll0, -sl4, +sl4, -ll0 }, { +ll0, +sl9, +ll0, -sl9 }, { +sl4, +ll0, +ll0, +sl4 },
    338         { -sl9, +ll0, +sl9, +ll0 }, { -ll0, +sl4, -sl4, +ll0 }, { -ll0, -sl9, -ll0, +sl9 } };
    339 
    340     // the different color modes
    341     enum colorModes {
    342         none, velocity, dilution
    343     }
    344 
    345     @Override
    346     public synchronized void paint(Graphics2D g, MapView mv, Bounds box) {
    347         painting = true;
    348         lastUpdateCount = sumUpdateCount();
    349         lastTracks.clear();
    350         lastTracks.addAll(data.tracks);
    351 
    352         /****************************************************************
    353          ********** STEP 1 - GET CONFIG VALUES **************************
    354          ****************************************************************/
    355         // Long startTime = System.currentTimeMillis();
    356         Color neutralColor = getColor(getName());
    357         // also draw lines between points belonging to different segments
    358         boolean forceLines = Main.pref.getBoolean("draw.rawgps.lines.force");
    359         // draw direction arrows on the lines
    360         boolean direction = Main.pref.getBoolean("draw.rawgps.direction");
    361         // don't draw lines if longer than x meters
    362         int lineWidth = Main.pref.getInteger("draw.rawgps.linewidth",0);
    363 
    364         int maxLineLength;
    365         if (this.isLocalFile) {
    366             maxLineLength = Main.pref.getInteger("draw.rawgps.max-line-length.local", -1);
    367         } else {
    368             maxLineLength = Main.pref.getInteger("draw.rawgps.max-line-length", 200);
    369         }
    370         // draw line between points, global setting
    371         boolean lines = (Main.pref.getBoolean("draw.rawgps.lines", true) || (Main.pref
    372                 .getBoolean("draw.rawgps.lines.localfiles") && this.isLocalFile));
    373         String linesKey = "draw.rawgps.lines.layer " + getName();
    374         // draw lines, per-layer setting
    375         if (Main.pref.hasKey(linesKey)) {
    376             lines = Main.pref.getBoolean(linesKey);
    377         }
    378         // paint large dots for points
    379         boolean large = Main.pref.getBoolean("draw.rawgps.large");
    380         boolean hdopcircle = Main.pref.getBoolean("draw.rawgps.hdopcircle", true);
    381         // color the lines
    382         colorModes colored = colorModes.none;
    383         try {
    384             colored = colorModes.values()[Main.pref.getInteger("draw.rawgps.colors", 0)];
    385         } catch (Exception e) {
    386         }
    387         // paint direction arrow with alternate math. may be faster
    388         boolean alternatedirection = Main.pref.getBoolean("draw.rawgps.alternatedirection");
    389         // don't draw arrows nearer to each other than this
    390         int delta = Main.pref.getInteger("draw.rawgps.min-arrow-distance", 0);
    391         // allows to tweak line coloring for different speed levels.
    392         int colorTracksTune = Main.pref.getInteger("draw.rawgps.colorTracksTune", 45);
    393 
    394         if(lineWidth != 0)
    395         {
    396             g.setStroke(new BasicStroke(lineWidth,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
    397         }
    398 
    399         /****************************************************************
    400          ********** STEP 2a - CHECK CACHE VALIDITY **********************
    401          ****************************************************************/
    402         if ((computeCacheMaxLineLengthUsed != maxLineLength) || (!neutralColor.equals(computeCacheColorUsed))
    403                 || (computeCacheColored != colored) || (computeCacheColorTracksTune != colorTracksTune)) {
    404             // System.out.println("(re-)computing gpx line styles, reason: CCIS=" +
    405             // computeCacheInSync + " CCMLLU=" + (computeCacheMaxLineLengthUsed != maxLineLength) +
    406             // " CCCU=" + (!neutralColor.equals(computeCacheColorUsed)) + " CCC=" +
    407             // (computeCacheColored != colored));
    408             computeCacheMaxLineLengthUsed = maxLineLength;
    409             computeCacheInSync = false;
    410             computeCacheColorUsed = neutralColor;
    411             computeCacheColored = colored;
    412             computeCacheColorTracksTune = colorTracksTune;
    413         }
    414 
    415         /****************************************************************
    416          ********** STEP 2b - RE-COMPUTE CACHE DATA *********************
    417          ****************************************************************/
    418         if (!computeCacheInSync) { // don't compute if the cache is good
    419             WayPoint oldWp = null;
    420             for (GpxTrack trk : data.tracks) {
    421                 for (GpxTrackSegment segment : trk.getSegments()) {
    422                     if (!forceLines) { // don't draw lines between segments, unless forced to
    423                         oldWp = null;
    424                     }
    425                     for (WayPoint trkPnt : segment.getWayPoints()) {
    426                         LatLon c = trkPnt.getCoor();
    427                         if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
    428                             continue;
    429                         }
    430                         trkPnt.customColoring = neutralColor;
    431                         if (oldWp != null) {
    432                             double dist = c.greatCircleDistance(oldWp.getCoor());
    433 
    434                             switch (colored) {
    435                             case velocity:
    436                                 double dtime = trkPnt.time - oldWp.time;
    437                                 double vel = dist / dtime;
    438                                 double velColor = vel / colorTracksTune * 255;
    439                                 // Bad case first
    440                                 if (dtime <= 0 || vel < 0 || velColor > 255) {
    441                                     trkPnt.customColoring = colors[255];
    442                                 } else {
    443                                     trkPnt.customColoring = colors[(int) (velColor)];
    444                                 }
    445                                 break;
    446 
    447                             case dilution:
    448                                 if (trkPnt.attr.get("hdop") != null) {
    449                                     float hdop = ((Float) trkPnt.attr.get("hdop")).floatValue();
    450                                     if (hdop < 0) {
    451                                         hdop = 0;
    452                                     }
    453                                     int hdoplvl = Math.round(hdop * Main.pref.getInteger("hdop.factor", 25));
    454                                     // High hdop is bad, but high values in colors are green.
    455                                     // Therefore inverse the logic
    456                                     int hdopcolor = 255 - (hdoplvl > 255 ? 255 : hdoplvl);
    457                                     trkPnt.customColoring = colors[hdopcolor];
    458                                 }
    459                                 break;
    460                             }
    461 
    462                             if (maxLineLength == -1 || dist <= maxLineLength) {
    463                                 trkPnt.drawLine = true;
    464                                 trkPnt.dir = (int) oldWp.getCoor().heading(trkPnt.getCoor());
    465                             } else {
    466                                 trkPnt.drawLine = false;
    467                             }
    468                         } else { // make sure we reset outdated data
    469                             trkPnt.drawLine = false;
    470                         }
    471                         oldWp = trkPnt;
    472                     }
    473                 }
    474             }
    475             computeCacheInSync = true;
    476         }
    477 
    478         List<Collection<WayPoint>> visibleSegments = new ArrayList<Collection<WayPoint>>();
    479         for (GpxTrack trk: data.tracks) {
    480             for (GpxTrackSegment trkSeg: trk.getSegments()) {
    481                 if (trkSeg.getBounds() != null && trkSeg.getBounds().intersects(box)) {
    482                     visibleSegments.add(trkSeg.getWayPoints());
    483                 }
    484             }
    485         }
    486 
    487         /****************************************************************
    488          ********** STEP 3a - DRAW LINES ********************************
    489          ****************************************************************/
    490         if (lines) {
    491             Point old = null;
    492             for (Collection<WayPoint> segment : visibleSegments) {
    493                 for (WayPoint trkPnt : segment) {
    494                     LatLon c = trkPnt.getCoor();
    495                     if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
    496                         continue;
    497                     }
    498                     Point screen = mv.getPoint(trkPnt.getEastNorth());
    499                     if (trkPnt.drawLine) {
    500                         // skip points that are on the same screenposition
    501                         if (old != null && ((old.x != screen.x) || (old.y != screen.y))) {
    502                             g.setColor(trkPnt.customColoring);
    503                             g.drawLine(old.x, old.y, screen.x, screen.y);
    504                         }
    505                     }
    506                     old = screen;
    507                 } // end for trkpnt
    508             } // end for segment
    509         } // end if lines
    510 
    511         /****************************************************************
    512          ********** STEP 3b - DRAW NICE ARROWS **************************
    513          ****************************************************************/
    514         if (lines && direction && !alternatedirection) {
    515             Point old = null;
    516             Point oldA = null; // last arrow painted
    517             for (Collection<WayPoint> segment : visibleSegments) {
    518                 for (WayPoint trkPnt : segment) {
    519                     LatLon c = trkPnt.getCoor();
    520                     if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
    521                         continue;
    522                     }
    523                     if (trkPnt.drawLine) {
    524                         Point screen = mv.getPoint(trkPnt.getEastNorth());
    525                         // skip points that are on the same screenposition
    526                         if (old != null
    527                                 && (oldA == null || screen.x < oldA.x - delta || screen.x > oldA.x + delta
    528                                         || screen.y < oldA.y - delta || screen.y > oldA.y + delta)) {
    529                             g.setColor(trkPnt.customColoring);
    530                             double t = Math.atan2(screen.y - old.y, screen.x - old.x) + Math.PI;
    531                             g.drawLine(screen.x, screen.y, (int) (screen.x + 10 * Math.cos(t - PHI)),
    532                                     (int) (screen.y + 10 * Math.sin(t - PHI)));
    533                             g.drawLine(screen.x, screen.y, (int) (screen.x + 10 * Math.cos(t + PHI)),
    534                                     (int) (screen.y + 10 * Math.sin(t + PHI)));
    535                             oldA = screen;
    536                         }
    537                         old = screen;
    538                     }
    539                 } // end for trkpnt
    540             } // end for segment
    541         } // end if lines
    542 
    543         /****************************************************************
    544          ********** STEP 3c - DRAW FAST ARROWS **************************
    545          ****************************************************************/
    546         if (lines && direction && alternatedirection) {
    547             Point old = null;
    548             Point oldA = null; // last arrow painted
    549             for (Collection<WayPoint> segment : visibleSegments) {
    550                 for (WayPoint trkPnt : segment) {
    551                     LatLon c = trkPnt.getCoor();
    552                     if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
    553                         continue;
    554                     }
    555                     if (trkPnt.drawLine) {
    556                         Point screen = mv.getPoint(trkPnt.getEastNorth());
    557                         // skip points that are on the same screenposition
    558                         if (old != null
    559                                 && (oldA == null || screen.x < oldA.x - delta || screen.x > oldA.x + delta
    560                                         || screen.y < oldA.y - delta || screen.y > oldA.y + delta)) {
    561                             g.setColor(trkPnt.customColoring);
    562                             g.drawLine(screen.x, screen.y, screen.x + dir[trkPnt.dir][0], screen.y
    563                                     + dir[trkPnt.dir][1]);
    564                             g.drawLine(screen.x, screen.y, screen.x + dir[trkPnt.dir][2], screen.y
    565                                     + dir[trkPnt.dir][3]);
    566                             oldA = screen;
    567                         }
    568                         old = screen;
    569                     }
    570                 } // end for trkpnt
    571             } // end for segment
    572         } // end if lines
    573 
    574         /****************************************************************
    575          ********** STEP 3d - DRAW LARGE POINTS AND HDOP CIRCLE *********
    576          ****************************************************************/
    577         if (large || hdopcircle) {
    578             g.setColor(neutralColor);
    579             for (Collection<WayPoint> segment : visibleSegments) {
    580                 for (WayPoint trkPnt : segment) {
    581                     LatLon c = trkPnt.getCoor();
    582                     if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
    583                         continue;
    584                     }
    585                     Point screen = mv.getPoint(trkPnt.getEastNorth());
    586                     g.setColor(trkPnt.customColoring);
    587                     if (hdopcircle && trkPnt.attr.get("hdop") != null) {
    588                         // hdop value
    589                         float hdop = ((Float)trkPnt.attr.get("hdop")).floatValue();
    590                         if (hdop < 0) {
    591                             hdop = 0;
    592                         }
    593                         // hdop pixels
    594                         int hdopp = mv.getPoint(new LatLon(trkPnt.getCoor().lat(), trkPnt.getCoor().lon() + 2*6*hdop*360/40000000)).x - screen.x;
    595                         g.drawArc(screen.x-hdopp/2, screen.y-hdopp/2, hdopp, hdopp, 0, 360);
    596                     }
    597                     if (large) {
    598                         g.fillRect(screen.x-1, screen.y-1, 3, 3);
    599                     }
    600                 } // end for trkpnt
    601             } // end for segment
    602         } // end if large || hdopcircle
    603 
    604         /****************************************************************
    605          ********** STEP 3e - DRAW SMALL POINTS FOR LINES ***************
    606          ****************************************************************/
    607         if (!large && lines) {
    608             g.setColor(neutralColor);
    609             for (Collection<WayPoint> segment : visibleSegments) {
    610                 for (WayPoint trkPnt : segment) {
    611                     LatLon c = trkPnt.getCoor();
    612                     if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
    613                         continue;
    614                     }
    615                     if (!trkPnt.drawLine) {
    616                         Point screen = mv.getPoint(trkPnt.getEastNorth());
    617                         g.drawRect(screen.x, screen.y, 0, 0);
    618                     }
    619                 } // end for trkpnt
    620             } // end for segment
    621         } // end if large
    622 
    623         /****************************************************************
    624          ********** STEP 3f - DRAW SMALL POINTS INSTEAD OF LINES ********
    625          ****************************************************************/
    626         if (!large && !lines) {
    627             g.setColor(neutralColor);
    628             for (Collection<WayPoint> segment : visibleSegments) {
    629                 for (WayPoint trkPnt : segment) {
    630                     LatLon c = trkPnt.getCoor();
    631                     if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
    632                         continue;
    633                     }
    634                     Point screen = mv.getPoint(trkPnt.getEastNorth());
    635                     g.setColor(trkPnt.customColoring);
    636                     g.drawRect(screen.x, screen.y, 0, 0);
    637                 } // end for trkpnt
    638             } // end for segment
    639         } // end if large
    640 
    641         // Long duration = System.currentTimeMillis() - startTime;
    642         // System.out.println(duration);
    643         painting = false;
    644     } // end paint
    645 
    646     @Override
    647     public synchronized void visitBoundingBox(BoundingXYVisitor v) {
    648         v.visit(data.recalculateBounds());
    649     }
    650 
    651     public class ConvertToDataLayerAction extends AbstractAction {
    652         public ConvertToDataLayerAction() {
    653             super(tr("Convert to data layer"), ImageProvider.get("converttoosm"));
    654         }
    655 
    656         public void actionPerformed(ActionEvent e) {
    657             JPanel msg = new JPanel(new GridBagLayout());
    658             msg
    659             .add(
    660                     new JLabel(
    661                             tr("<html>Upload of unprocessed GPS data as map data is considered harmful.<br>If you want to upload traces, look here:")),
    662                             GBC.eol());
    663             msg.add(new UrlLabel(tr("http://www.openstreetmap.org/traces")), GBC.eop());
    664             if (!ConditionalOptionPaneUtil.showConfirmationDialog("convert_to_data", Main.parent, msg, tr("Warning"),
    665                     JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, JOptionPane.OK_OPTION))
    666                 return;
    667             DataSet ds = new DataSet();
    668             for (GpxTrack trk : data.tracks) {
    669                 for (GpxTrackSegment segment : trk.getSegments()) {
    670                     List<Node> nodes = new ArrayList<Node>();
    671                     for (WayPoint p : segment.getWayPoints()) {
    672                         Node n = new Node(p.getCoor());
    673                         String timestr = p.getString("time");
    674                         if (timestr != null) {
    675                             n.setTimestamp(DateUtils.fromString(timestr));
    676                         }
    677                         ds.addPrimitive(n);
    678                         nodes.add(n);
    679                     }
    680                     Way w = new Way();
    681                     w.setNodes(nodes);
    682                     ds.addPrimitive(w);
    683                 }
    684             }
    685             Main.main
    686             .addLayer(new OsmDataLayer(ds, tr("Converted from: {0}", EGpxLayer.this.getName()), getAssociatedFile()));
    687             Main.main.removeLayer(EGpxLayer.this);
    688         }
    689     }
    690 
    691     @Override
    692     public File getAssociatedFile() {
    693         return data.storageFile;
    694     }
    695 
    696     @Override
    697     public void setAssociatedFile(File file) {
    698         data.storageFile = file;
    699     }
    700 
    701     /**
    702      * Action that issues a series of download requests to the API, following the GPX track.
    703      *
    704      * @author fred
    705      */
    706     public class DownloadAlongTrackAction extends AbstractAction {
    707         public DownloadAlongTrackAction() {
    708             super(tr("Download from OSM along this track"), ImageProvider.get("downloadalongtrack"));
    709         }
    710 
    711         public void actionPerformed(ActionEvent e) {
    712             JPanel msg = new JPanel(new GridBagLayout());
    713             Integer dist[] = { 5000, 500, 50 };
    714             Integer area[] = { 20, 10, 5, 1 };
    715 
    716             msg.add(new JLabel(tr("Download everything within:")), GBC.eol());
    717             String s[] = new String[dist.length];
    718             for (int i = 0; i < dist.length; ++i) {
    719                 s[i] = tr("{0} meters", dist[i]);
    720             }
    721             JList buffer = new JList(s);
    722             buffer.setSelectedIndex(Main.pref.getInteger(PREF_DOWNLOAD_ALONG_TRACK_DISTANCE, 0));
    723             msg.add(buffer, GBC.eol());
    724 
    725             msg.add(new JLabel(tr("Maximum area per request:")), GBC.eol());
    726             s = new String[area.length];
    727             for (int i = 0; i < area.length; ++i) {
    728                 s[i] = tr("{0} sq km", area[i]);
    729             }
    730             JList maxRect = new JList(s);
    731             maxRect.setSelectedIndex(Main.pref.getInteger(PREF_DOWNLOAD_ALONG_TRACK_AREA, 0));
    732             msg.add(maxRect, GBC.eol());
    733 
    734             msg.add(new JLabel(tr("Download near:")), GBC.eol());
    735             JList downloadNear = new JList(new String[] { tr("track only"), tr("waypoints only"), tr("track and waypoints") });
    736             int NEAR_TRACK=0;
    737             int NEAR_WAYPOINTS=1;
    738             int NEAR_BOTH=2;
    739 
    740             downloadNear.setSelectedIndex(Main.pref.getInteger(PREF_DOWNLOAD_ALONG_TRACK_NEAR, 0));
    741             msg.add(downloadNear, GBC.eol());
    742 
    743             int ret = JOptionPane.showConfirmDialog(
    744                     Main.parent,
    745                     msg,
    746                     tr("Download from OSM along this track"),
    747                     JOptionPane.OK_CANCEL_OPTION,
    748                     JOptionPane.QUESTION_MESSAGE
    749             );
    750             switch(ret) {
    751             case JOptionPane.CANCEL_OPTION:
    752             case JOptionPane.CLOSED_OPTION:
    753                 return;
    754             default:
    755                 // continue
    756             }
    757 
    758             Main.pref.putInteger(PREF_DOWNLOAD_ALONG_TRACK_DISTANCE, buffer.getSelectedIndex());
    759             Main.pref.putInteger(PREF_DOWNLOAD_ALONG_TRACK_AREA, maxRect.getSelectedIndex());
    760             int near = downloadNear.getSelectedIndex();
    761             Main.pref.putInteger(PREF_DOWNLOAD_ALONG_TRACK_NEAR, near);
    762 
    763             /*
    764              * Find the average latitude for the data we're contemplating, so we can know how many
    765              * metres per degree of longitude we have.
    766              */
    767             double latsum = 0;
    768             int latcnt = 0;
    769 
    770             if (near == NEAR_TRACK || near == NEAR_BOTH) {
    771                 for (GpxTrack trk : data.tracks) {
    772                     for (GpxTrackSegment segment : trk.getSegments()) {
    773                         for (WayPoint p : segment.getWayPoints()) {
    774                             latsum += p.getCoor().lat();
    775                             latcnt++;
    776                         }
    777                     }
    778                 }
    779             }
    780 
    781             if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) {
    782                 for (WayPoint p : data.waypoints) {
    783                     latsum += p.getCoor().lat();
    784                     latcnt++;
    785                 }
    786             }
    787 
    788             double avglat = latsum / latcnt;
    789             double scale = Math.cos(Math.toRadians(avglat));
    790 
    791             /*
    792              * Compute buffer zone extents and maximum bounding box size. Note that the maximum we
    793              * ever offer is a bbox area of 0.002, while the API theoretically supports 0.25, but as
    794              * soon as you touch any built-up area, that kind of bounding box will download forever
    795              * and then stop because it has more than 50k nodes.
    796              */
    797             Integer i = buffer.getSelectedIndex();
    798             int buffer_dist = dist[i < 0 ? 0 : i];
    799             double buffer_y = buffer_dist / 100000.0;
    800             double buffer_x = buffer_y / scale;
    801             i = maxRect.getSelectedIndex();
    802             double max_area = area[i < 0 ? 0 : i] / 10000.0 / scale;
    803             Area a = new Area();
    804             Rectangle2D r = new Rectangle2D.Double();
    805 
    806             /*
    807              * Collect the combined area of all gpx points plus buffer zones around them. We ignore
    808              * points that lie closer to the previous point than the given buffer size because
    809              * otherwise this operation takes ages.
    810              */
    811             LatLon previous = null;
    812             if (near == NEAR_TRACK || near == NEAR_BOTH) {
    813                 for (GpxTrack trk : data.tracks) {
    814                     for (GpxTrackSegment segment : trk.getSegments()) {
    815                         for (WayPoint p : segment.getWayPoints()) {
    816                             LatLon c = p.getCoor();
    817                             if (previous == null || c.greatCircleDistance(previous) > buffer_dist) {
    818                                 // we add a buffer around the point.
    819                                 r.setRect(c.lon() - buffer_x, c.lat() - buffer_y, 2 * buffer_x, 2 * buffer_y);
    820                                 a.add(new Area(r));
    821                                 previous = c;
    822                             }
    823                         }
    824                     }
    825                 }
    826             }
    827             if (near == NEAR_WAYPOINTS || near == NEAR_BOTH) {
    828                 for (WayPoint p : data.waypoints) {
    829                     LatLon c = p.getCoor();
    830                     if (previous == null || c.greatCircleDistance(previous) > buffer_dist) {
    831                         // we add a buffer around the point.
    832                         r.setRect(c.lon() - buffer_x, c.lat() - buffer_y, 2 * buffer_x, 2 * buffer_y);
    833                         a.add(new Area(r));
    834                         previous = c;
    835                     }
    836                 }
    837             }
    838 
    839             /*
    840              * Area "a" now contains the hull that we would like to download data for. however we
    841              * can only download rectangles, so the following is an attempt at finding a number of
    842              * rectangles to download.
    843              *
    844              * The idea is simply: Start out with the full bounding box. If it is too large, then
    845              * split it in half and repeat recursively for each half until you arrive at something
    846              * small enough to download. The algorithm is improved by always using the intersection
    847              * between the rectangle and the actual desired area. For example, if you have a track
    848              * that goes like this: +----+ | /| | / | | / | |/ | +----+ then we would first look at
    849              * downloading the whole rectangle (assume it's too big), after that we split it in half
    850              * (upper and lower half), but we donot request the full upper and lower rectangle, only
    851              * the part of the upper/lower rectangle that actually has something in it.
    852              */
    853 
    854             List<Rectangle2D> toDownload = new ArrayList<Rectangle2D>();
    855 
    856             addToDownload(a, a.getBounds(), toDownload, max_area);
    857 
    858             msg = new JPanel(new GridBagLayout());
    859 
    860             msg.add(new JLabel(
    861                     tr("<html>This action will require {0} individual<br>"
    862                             + "download requests. Do you wish<br>to continue?</html>",
    863                             toDownload.size())), GBC.eol());
    864 
    865             if (toDownload.size() > 1) {
    866                 ret = JOptionPane.showConfirmDialog(
    867                         Main.parent,
    868                         msg,
    869                         tr("Download from OSM along this track"),
    870                         JOptionPane.OK_CANCEL_OPTION,
    871                         JOptionPane.PLAIN_MESSAGE
    872                 );
    873                 switch(ret) {
    874                 case JOptionPane.CANCEL_OPTION:
    875                 case JOptionPane.CLOSED_OPTION:
    876                     return;
    877                 default:
    878                     // continue
    879                 }
    880             }
    881             final PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor(tr("Download data"));
    882             final Future<?> future = new DownloadOsmTaskList().download(false, toDownload, monitor);
    883             Main.worker.submit(
    884                     new Runnable() {
    885                         public void run() {
    886                             try {
    887                                 future.get();
    888                             } catch(Exception e) {
    889                                 e.printStackTrace();
    890                                 return;
    891                             }
    892                             monitor.close();
    893                         }
    894                     }
    895             );
    896         }
    897     }
    898 
    899     private static void addToDownload(Area a, Rectangle2D r, Collection<Rectangle2D> results, double max_area) {
    900         Area tmp = new Area(r);
    901         // intersect with sought-after area
    902         tmp.intersect(a);
    903         if (tmp.isEmpty())
    904             return;
    905         Rectangle2D bounds = tmp.getBounds2D();
    906         if (bounds.getWidth() * bounds.getHeight() > max_area) {
    907             // the rectangle gets too large; split it and make recursive call.
    908             Rectangle2D r1;
    909             Rectangle2D r2;
    910             if (bounds.getWidth() > bounds.getHeight()) {
    911                 // rectangles that are wider than high are split into a left and right half,
    912                 r1 = new Rectangle2D.Double(bounds.getX(), bounds.getY(), bounds.getWidth() / 2, bounds.getHeight());
    913                 r2 = new Rectangle2D.Double(bounds.getX() + bounds.getWidth() / 2, bounds.getY(),
    914                         bounds.getWidth() / 2, bounds.getHeight());
    915             } else {
    916                 // others into a top and bottom half.
    917                 r1 = new Rectangle2D.Double(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight() / 2);
    918                 r2 = new Rectangle2D.Double(bounds.getX(), bounds.getY() + bounds.getHeight() / 2, bounds.getWidth(),
    919                         bounds.getHeight() / 2);
    920             }
    921             addToDownload(a, r1, results, max_area);
    922             addToDownload(a, r2, results, max_area);
    923         } else {
    924             results.add(bounds);
    925         }
    926     }
    927 
    928     /**
    929      * Makes a new marker layer derived from this GpxLayer containing at least one audio marker
    930      * which the given audio file is associated with. Markers are derived from the following (a)
    931      * explict waypoints in the GPX layer, or (b) named trackpoints in the GPX layer, or (d)
    932      * timestamp on the wav file (e) (in future) voice recognised markers in the sound recording (f)
    933      * a single marker at the beginning of the track
    934      * @param wavFile : the file to be associated with the markers in the new marker layer
    935      * @param markers : keeps track of warning messages to avoid repeated warnings
    936      */
    937     private void importAudio(File wavFile, MarkerLayer ml, double firstStartTime, Markers markers) {
    938         URL url = null;
    939         try {
    940             url = wavFile.toURI().toURL();
    941         } catch (MalformedURLException e) {
    942             System.err.println("Unable to convert filename " + wavFile.getAbsolutePath() + " to URL");
    943         }
    944         Collection<WayPoint> waypoints = new ArrayList<WayPoint>();
    945         boolean timedMarkersOmitted = false;
    946         boolean untimedMarkersOmitted = false;
    947         double snapDistance = Main.pref.getDouble("marker.audiofromuntimedwaypoints.distance", 1.0e-3); /*
    948          * about
    949          * 25
    950          * m
    951          */
    952         WayPoint wayPointFromTimeStamp = null;
    953 
    954         // determine time of first point in track
    955         double firstTime = -1.0;
    956         if (data.tracks != null && !data.tracks.isEmpty()) {
    957             for (GpxTrack track : data.tracks) {
    958                 for (GpxTrackSegment seg : track.getSegments()) {
    959                     for (WayPoint w : seg.getWayPoints()) {
    960                         firstTime = w.time;
    961                         break;
    962                     }
    963                     if (firstTime >= 0.0) {
    964                         break;
    965                     }
    966                 }
    967                 if (firstTime >= 0.0) {
    968                     break;
    969                 }
    970             }
    971         }
    972         if (firstTime < 0.0) {
    973             JOptionPane.showMessageDialog(
    974                     Main.parent,
    975                     tr("No GPX track available in layer to associate audio with."),
    976                     tr("Error"),
    977                     JOptionPane.ERROR_MESSAGE
    978             );
    979             return;
    980         }
    981 
    982         // (a) try explicit timestamped waypoints - unless suppressed
    983         if (Main.pref.getBoolean("marker.audiofromexplicitwaypoints", true) && data.waypoints != null
    984                 && !data.waypoints.isEmpty()) {
    985             for (WayPoint w : data.waypoints) {
    986                 if (w.time > firstTime) {
    987                     waypoints.add(w);
    988                 } else if (w.time > 0.0) {
    989                     timedMarkersOmitted = true;
    990                 }
    991             }
    992         }
    993 
    994         // (b) try explicit waypoints without timestamps - unless suppressed
    995         if (Main.pref.getBoolean("marker.audiofromuntimedwaypoints", true) && data.waypoints != null
    996                 && !data.waypoints.isEmpty()) {
    997             for (WayPoint w : data.waypoints) {
    998                 if (waypoints.contains(w)) {
    999                     continue;
    1000                 }
    1001                 WayPoint wNear = nearestPointOnTrack(w.getEastNorth(), snapDistance);
    1002                 if (wNear != null) {
    1003                     WayPoint wc = new WayPoint(w.getCoor());
    1004                     wc.time = wNear.time;
    1005                     if (w.attr.containsKey("name")) {
    1006                         wc.attr.put("name", w.getString("name"));
    1007                     }
    1008                     waypoints.add(wc);
    1009                 } else {
    1010                     untimedMarkersOmitted = true;
    1011                 }
    1012             }
    1013         }
    1014 
    1015         // (c) use explicitly named track points, again unless suppressed
    1016         if ((Main.pref.getBoolean("marker.audiofromnamedtrackpoints", false)) && data.tracks != null
    1017                 && !data.tracks.isEmpty()) {
    1018             for (GpxTrack track : data.tracks) {
    1019                 for (GpxTrackSegment seg : track.getSegments()) {
    1020                     for (WayPoint w : seg.getWayPoints()) {
    1021                         if (w.attr.containsKey("name") || w.attr.containsKey("desc")) {
    1022                             waypoints.add(w);
    1023                         }
    1024                     }
    1025                 }
    1026             }
    1027         }
    1028 
    1029         // (d) use timestamp of file as location on track
    1030         if ((Main.pref.getBoolean("marker.audiofromwavtimestamps", false)) && data.tracks != null
    1031                 && !data.tracks.isEmpty()) {
    1032             double lastModified = wavFile.lastModified() / 1000.0; // lastModified is in
    1033             // milliseconds
    1034             double duration = AudioUtil.getCalibratedDuration(wavFile);
    1035             double startTime = lastModified - duration;
    1036             startTime = firstStartTime + (startTime - firstStartTime)
    1037             / Main.pref.getDouble("audio.calibration", "1.0" /* default, ratio */);
    1038             WayPoint w1 = null;
    1039             WayPoint w2 = null;
    1040 
    1041             for (GpxTrack track : data.tracks) {
    1042                 for (GpxTrackSegment seg : track.getSegments()) {
    1043                     for (WayPoint w : seg.getWayPoints()) {
    1044                         if (startTime < w.time) {
    1045                             w2 = w;
    1046                             break;
    1047                         }
    1048                         w1 = w;
    1049                     }
    1050                     if (w2 != null) {
    1051                         break;
    1052                     }
    1053                 }
    1054             }
    1055 
    1056             if (w1 == null || w2 == null) {
    1057                 timedMarkersOmitted = true;
    1058             } else {
    1059                 wayPointFromTimeStamp = new WayPoint(w1.getCoor().interpolate(w2.getCoor(),
    1060                         (startTime - w1.time) / (w2.time - w1.time)));
    1061                 wayPointFromTimeStamp.time = startTime;
    1062                 String name = wavFile.getName();
    1063                 int dot = name.lastIndexOf(".");
    1064                 if (dot > 0) {
    1065                     name = name.substring(0, dot);
    1066                 }
    1067                 wayPointFromTimeStamp.attr.put("name", name);
    1068                 waypoints.add(wayPointFromTimeStamp);
    1069             }
    1070         }
    1071 
    1072         // (e) analyse audio for spoken markers here, in due course
    1073 
    1074         // (f) simply add a single marker at the start of the track
    1075         if ((Main.pref.getBoolean("marker.audiofromstart") || waypoints.isEmpty()) && data.tracks != null
    1076                 && !data.tracks.isEmpty()) {
    1077             boolean gotOne = false;
    1078             for (GpxTrack track : data.tracks) {
    1079                 for (GpxTrackSegment seg : track.getSegments()) {
    1080                     for (WayPoint w : seg.getWayPoints()) {
    1081                         WayPoint wStart = new WayPoint(w.getCoor());
    1082                         wStart.attr.put("name", "start");
    1083                         wStart.time = w.time;
    1084                         waypoints.add(wStart);
    1085                         gotOne = true;
    1086                         break;
    1087                     }
    1088                     if (gotOne) {
    1089                         break;
    1090                     }
    1091                 }
    1092                 if (gotOne) {
    1093                     break;
    1094                 }
    1095             }
    1096         }
    1097 
    1098         /* we must have got at least one waypoint now */
    1099 
    1100         Collections.sort((ArrayList<WayPoint>) waypoints, new Comparator<WayPoint>() {
    1101             public int compare(WayPoint a, WayPoint b) {
    1102                 return a.time <= b.time ? -1 : 1;
    1103             }
    1104         });
    1105 
    1106         firstTime = -1.0; /* this time of the first waypoint, not first trackpoint */
    1107         for (WayPoint w : waypoints) {
    1108             if (firstTime < 0.0) {
    1109                 firstTime = w.time;
    1110             }
    1111             double offset = w.time - firstTime;
    1112             AudioMarker am = new AudioMarker(w.getCoor(), w, url, ml, w.time, offset);
    1113             /*
    1114              * timeFromAudio intended for future use to shift markers of this type on
    1115              * synchronization
    1116              */
    1117             if (w == wayPointFromTimeStamp) {
    1118                 am.timeFromAudio = true;
    1119             }
    1120             ml.data.add(am);
    1121         }
    1122 
    1123         if (timedMarkersOmitted && !markers.timedMarkersOmitted) {
    1124             JOptionPane
    1125             .showMessageDialog(
    1126                     Main.parent,
    1127                     tr("Some waypoints with timestamps from before the start of the track or after the end were omitted or moved to the start."));
    1128             markers.timedMarkersOmitted = timedMarkersOmitted;
    1129         }
    1130         if (untimedMarkersOmitted && !markers.untimedMarkersOmitted) {
    1131             JOptionPane
    1132             .showMessageDialog(
    1133                     Main.parent,
    1134                     tr("Some waypoints which were too far from the track to sensibly estimate their time were omitted."));
    1135             markers.untimedMarkersOmitted = untimedMarkersOmitted;
    1136         }
    1137     }
    1138 
    1139     /**
    1140      * Makes a WayPoint at the projection of point P onto the track providing P is less than
    1141      * tolerance away from the track
    1142      *
    1143      * @param P : the point to determine the projection for
    1144      * @param tolerance : must be no further than this from the track
    1145      * @return the closest point on the track to P, which may be the first or last point if off the
    1146      * end of a segment, or may be null if nothing close enough
    1147      */
    1148     public WayPoint nearestPointOnTrack(EastNorth P, double tolerance) {
    1149         /*
    1150          * assume the coordinates of P are xp,yp, and those of a section of track between two
    1151          * trackpoints are R=xr,yr and S=xs,ys. Let N be the projected point.
    1152          *
    1153          * The equation of RS is Ax + By + C = 0 where A = ys - yr B = xr - xs C = - Axr - Byr
    1154          *
    1155          * Also, note that the distance RS^2 is A^2 + B^2
    1156          *
    1157          * If RS^2 == 0.0 ignore the degenerate section of track
    1158          *
    1159          * PN^2 = (Axp + Byp + C)^2 / RS^2 that is the distance from P to the line
    1160          *
    1161          * so if PN^2 is less than PNmin^2 (initialized to tolerance) we can reject the line;
    1162          * otherwise... determine if the projected poijnt lies within the bounds of the line: PR^2 -
    1163          * PN^2 <= RS^2 and PS^2 - PN^2 <= RS^2
    1164          *
    1165          * where PR^2 = (xp - xr)^2 + (yp-yr)^2 and PS^2 = (xp - xs)^2 + (yp-ys)^2
    1166          *
    1167          * If so, calculate N as xn = xr + (RN/RS) B yn = y1 + (RN/RS) A
    1168          *
    1169          * where RN = sqrt(PR^2 - PN^2)
    1170          */
    1171 
    1172         double PNminsq = tolerance * tolerance;
    1173         EastNorth bestEN = null;
    1174         double bestTime = 0.0;
    1175         double px = P.east();
    1176         double py = P.north();
    1177         double rx = 0.0, ry = 0.0, sx, sy, x, y;
    1178         if (data.tracks == null)
    1179             return null;
    1180         for (GpxTrack track : data.tracks) {
    1181             for (GpxTrackSegment seg : track.getSegments()) {
    1182                 WayPoint R = null;
    1183                 for (WayPoint S : seg.getWayPoints()) {
    1184                     EastNorth c = S.getEastNorth();
    1185                     if (R == null) {
    1186                         R = S;
    1187                         rx = c.east();
    1188                         ry = c.north();
    1189                         x = px - rx;
    1190                         y = py - ry;
    1191                         double PRsq = x * x + y * y;
    1192                         if (PRsq < PNminsq) {
    1193                             PNminsq = PRsq;
    1194                             bestEN = c;
    1195                             bestTime = R.time;
    1196                         }
    1197                     } else {
    1198                         sx = c.east();
    1199                         sy = c.north();
    1200                         double A = sy - ry;
    1201                         double B = rx - sx;
    1202                         double C = -A * rx - B * ry;
    1203                         double RSsq = A * A + B * B;
    1204                         if (RSsq == 0.0) {
    1205                             continue;
    1206                         }
    1207                         double PNsq = A * px + B * py + C;
    1208                         PNsq = PNsq * PNsq / RSsq;
    1209                         if (PNsq < PNminsq) {
    1210                             x = px - rx;
    1211                             y = py - ry;
    1212                             double PRsq = x * x + y * y;
    1213                             x = px - sx;
    1214                             y = py - sy;
    1215                             double PSsq = x * x + y * y;
    1216                             if (PRsq - PNsq <= RSsq && PSsq - PNsq <= RSsq) {
    1217                                 double RNoverRS = Math.sqrt((PRsq - PNsq) / RSsq);
    1218                                 double nx = rx - RNoverRS * B;
    1219                                 double ny = ry + RNoverRS * A;
    1220                                 bestEN = new EastNorth(nx, ny);
    1221                                 bestTime = R.time + RNoverRS * (S.time - R.time);
    1222                                 PNminsq = PNsq;
    1223                             }
    1224                         }
    1225                         R = S;
    1226                         rx = sx;
    1227                         ry = sy;
    1228                     }
    1229                 }
    1230                 if (R != null) {
    1231                     EastNorth c = R.getEastNorth();
    1232                     /* if there is only one point in the seg, it will do this twice, but no matter */
    1233                     rx = c.east();
    1234                     ry = c.north();
    1235                     x = px - rx;
    1236                     y = py - ry;
    1237                     double PRsq = x * x + y * y;
    1238                     if (PRsq < PNminsq) {
    1239                         PNminsq = PRsq;
    1240                         bestEN = c;
    1241                         bestTime = R.time;
    1242                     }
    1243                 }
    1244             }
    1245         }
    1246         if (bestEN == null)
    1247             return null;
    1248         WayPoint best = new WayPoint(Main.getProjection().eastNorth2latlon(bestEN));
    1249         best.time = bestTime;
    1250         return best;
    1251     }
    1252 
    1253     private class CustomizeLineDrawing extends AbstractAction {
    1254 
    1255         CustomizeLineDrawing() {
    1256             super(tr("Customize line drawing"), ImageProvider.get("mapmode/addsegment"));
    1257         }
    1258 
    1259         public void actionPerformed(ActionEvent e) {
    1260             JRadioButton[] r = new JRadioButton[3];
    1261             r[0] = new JRadioButton(tr("Use global settings."));
    1262             r[1] = new JRadioButton(tr("Draw lines between points for this layer."));
    1263             r[2] = new JRadioButton(tr("Do not draw lines between points for this layer."));
    1264             ButtonGroup group = new ButtonGroup();
    1265             Box panel = Box.createVerticalBox();
    1266             for (JRadioButton b : r) {
    1267                 group.add(b);
    1268                 panel.add(b);
    1269             }
    1270             String propName = "draw.rawgps.lines.layer " + getName();
    1271             if (Main.pref.hasKey(propName)) {
    1272                 group.setSelected(r[Main.pref.getBoolean(propName) ? 1 : 2].getModel(), true);
    1273             } else {
    1274                 group.setSelected(r[0].getModel(), true);
    1275             }
    1276             int answer = JOptionPane.showConfirmDialog(Main.parent, panel,
    1277                     tr("Select line drawing options"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
    1278             switch (answer) {
    1279             case JOptionPane.CANCEL_OPTION:
    1280             case JOptionPane.CLOSED_OPTION:
    1281                 return;
    1282             default:
    1283                 // continue
    1284             }
    1285             if (group.getSelection() == r[0].getModel()) {
    1286                 Main.pref.put(propName, null);
    1287             } else {
    1288                 Main.pref.put(propName, group.getSelection() == r[1].getModel());
    1289             }
    1290             Main.map.repaint();
    1291         }
    1292     }
    1293 
    1294     private class CustomizeColor extends AbstractAction {
    1295 
    1296         public CustomizeColor() {
    1297             super(tr("Customize Color"), ImageProvider.get("colorchooser"));
    1298             putValue("help", "Action/LayerCustomizeColor");
    1299         }
    1300 
    1301         public void actionPerformed(ActionEvent e) {
    1302             JColorChooser c = new JColorChooser(getColor(getName()));
    1303             Object[] options = new Object[] { tr("OK"), tr("Cancel"), tr("Default") };
    1304             int answer = JOptionPane.showOptionDialog(
    1305                     Main.parent,
    1306                     c,
    1307                     tr("Choose a color"),
    1308                     JOptionPane.OK_CANCEL_OPTION,
    1309                     JOptionPane.PLAIN_MESSAGE,
    1310                     null,
    1311                     options, options[0]
    1312             );
    1313             switch (answer) {
    1314             case 0:
    1315                 Main.pref.putColor("layer " + getName(), c.getColor());
    1316                 break;
    1317             case 1:
    1318                 return;
    1319             case 2:
    1320                 Main.pref.putColor("layer " + getName(), null);
    1321                 break;
    1322             }
    1323             Main.map.repaint();
    1324         }
    1325 
    1326     }
    1327 
    1328     private class MarkersFromNamedPoins extends AbstractAction {
    1329 
    1330         public MarkersFromNamedPoins() {
    1331             super(tr("Markers From Named Points"), ImageProvider.get("addmarkers"));
    1332             putValue("help", "Action/MarkersFromNamedPoints");
    1333         }
    1334 
    1335         public void actionPerformed(ActionEvent e) {
    1336             GpxData namedTrackPoints = new GpxData();
    1337             for (GpxTrack track : data.tracks) {
    1338                 for (GpxTrackSegment seg : track.getSegments()) {
    1339                     for (WayPoint point : seg.getWayPoints())
    1340                         if (point.attr.containsKey("name") || point.attr.containsKey("desc")) {
    1341                             namedTrackPoints.waypoints.add(point);
    1342                         }
    1343                 }
    1344             }
    1345 
    1346             MarkerLayer ml = new MarkerLayer(namedTrackPoints, tr("Named Trackpoints from {0}", getName()),
    1347                     getAssociatedFile(), null);
    1348             if (ml.data.size() > 0) {
    1349                 Main.main.addLayer(ml);
    1350             }
    1351 
    1352         }
    1353     }
    1354 
    1355     private class ImportAudio extends AbstractAction {
    1356 
    1357         public ImportAudio() {
    1358             super(tr("Import Audio"), ImageProvider.get("importaudio"));
    1359             putValue("help", "ImportAudio");
    1360         }
    1361 
    1362         private void warnCantImportIntoServerLayer(EGpxLayer layer) {
    1363             String msg = tr("<html>The data in the GPX layer ''{0}'' has been downloaded from the server.<br>"
    1364                     + "Because its way points do not include a timestamp we cannot correlate them with audio data.</html>",
    1365                     layer.getName()
    1366             );
    1367             HelpAwareOptionPane.showOptionDialog(
    1368                     Main.parent,
    1369                     msg,
    1370                     tr("Import not possible"),
    1371                     JOptionPane.WARNING_MESSAGE,
    1372                     ht("/Action/ImportImages#CantImportIntoGpxLayerFromServer")
    1373             );
    1374         }
    1375 
    1376         public void actionPerformed(ActionEvent e) {
    1377             if (EGpxLayer.this.data.fromServer) {
    1378                 warnCantImportIntoServerLayer(EGpxLayer.this);
    1379                 return;
    1380             }
    1381             String dir = Main.pref.get("markers.lastaudiodirectory");
    1382             JFileChooser fc = new JFileChooser(dir);
    1383             fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
    1384             fc.setAcceptAllFileFilterUsed(false);
    1385             fc.setFileFilter(new FileFilter() {
    1386                 @Override
    1387                 public boolean accept(File f) {
    1388                     return f.isDirectory() || f.getName().toLowerCase().endsWith(".wav");
    1389                 }
    1390 
    1391                 @Override
    1392                 public String getDescription() {
    1393                     return tr("Wave Audio files (*.wav)");
    1394                 }
    1395             });
    1396             fc.setMultiSelectionEnabled(true);
    1397             if (fc.showOpenDialog(Main.parent) == JFileChooser.APPROVE_OPTION) {
    1398                 if (!fc.getCurrentDirectory().getAbsolutePath().equals(dir)) {
    1399                     Main.pref.put("markers.lastaudiodirectory", fc.getCurrentDirectory().getAbsolutePath());
    1400                 }
    1401 
    1402                 File sel[] = fc.getSelectedFiles();
    1403                 // sort files in increasing order of timestamp (this is the end time, but so
    1404                 // long as they don't overlap, that's fine)
    1405                 if (sel.length > 1) {
    1406                     Arrays.sort(sel, new Comparator<File>() {
    1407                         public int compare(File a, File b) {
    1408                             return a.lastModified() <= b.lastModified() ? -1 : 1;
    1409                         }
    1410                     });
    1411                 }
    1412 
    1413                 String names = null;
    1414                 for (int i = 0; i < sel.length; i++) {
    1415                     if (names == null) {
    1416                         names = " (";
    1417                     } else {
    1418                         names += ", ";
    1419                     }
    1420                     names += sel[i].getName();
    1421                 }
    1422                 if (names != null) {
    1423                     names += ")";
    1424                 } else {
    1425                     names = "";
    1426                 }
    1427                 MarkerLayer ml = new MarkerLayer(new GpxData(), tr("Audio markers from {0}", getName()) + names,
    1428                         getAssociatedFile(), null);
    1429                 double firstStartTime = sel[0].lastModified() / 1000.0 /* ms -> seconds */
    1430                 - AudioUtil.getCalibratedDuration(sel[0]);
    1431 
    1432                 Markers m = new Markers();
    1433                 for (int i = 0; i < sel.length; i++) {
    1434                     importAudio(sel[i], ml, firstStartTime, m);
    1435                 }
    1436                 Main.main.addLayer(ml);
    1437                 Main.map.repaint();
    1438             }
    1439 
    1440         }
    1441     }
    1442 
    1443     private class ImportImages extends AbstractAction {
    1444 
    1445         public ImportImages() {
    1446             super(tr("Import images"), ImageProvider.get("dialogs/geoimage"));
    1447             putValue("help", ht("/Action/ImportImages"));
    1448         }
    1449 
    1450         private void warnCantImportIntoServerLayer(EGpxLayer layer) {
    1451             String msg = tr("<html>The data in the GPX layer ''{0}'' has been downloaded from the server.<br>"
    1452                     + "Because its way points do not include a timestamp we cannot correlate them with images.</html>",
    1453                     layer.getName()
    1454             );
    1455             HelpAwareOptionPane.showOptionDialog(
    1456                     Main.parent,
    1457                     msg,
    1458                     tr("Import not possible"),
    1459                     JOptionPane.WARNING_MESSAGE,
    1460                     ht("/Action/ImportImages#CantImportIntoGpxLayerFromServer")
    1461             );
    1462         }
    1463 
    1464         private void addRecursiveFiles(LinkedList<File> files, File[] sel) {
    1465             for (File f : sel) {
    1466                 if (f.isDirectory()) {
    1467                     addRecursiveFiles(files, f.listFiles());
    1468                 } else if (f.getName().toLowerCase().endsWith(".jpg")) {
    1469                     files.add(f);
    1470                 }
    1471             }
    1472         }
    1473 
    1474         public void actionPerformed(ActionEvent e) {
    1475 
    1476             if (EGpxLayer.this.data.fromServer) {
    1477                 warnCantImportIntoServerLayer(EGpxLayer.this);
    1478                 return;
    1479             }
    1480             String curDir = Main.pref.get("geoimage.lastdirectory", Main.pref.get("lastDirectory"));
    1481             if (curDir.equals("")) {
    1482                 curDir = ".";
    1483             }
    1484             JFileChooser fc = new JFileChooser(new File(curDir));
    1485 
    1486             fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
    1487             fc.setMultiSelectionEnabled(true);
    1488             fc.setAcceptAllFileFilterUsed(false);
    1489             JpgImporter importer = new JpgImporter();
    1490             fc.setFileFilter(importer.filter);
    1491             fc.showOpenDialog(Main.parent);
    1492             LinkedList<File> files = new LinkedList<File>();
    1493             File[] sel = fc.getSelectedFiles();
    1494             if (sel == null || sel.length == 0)
    1495                 return;
    1496             if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir)) {
    1497                 Main.pref.put("geoimage.lastdirectory", fc.getCurrentDirectory().getAbsolutePath());
    1498             }
    1499             addRecursiveFiles(files, sel);
    1500             importer.importDataHandleExceptions(files, NullProgressMonitor.INSTANCE);
    1501         }
    1502 
    1503     }
    150441}
  • applications/editors/josm/plugins/gpxfilter/src/gpxfilter/GpxFilterPlugin.java

    r23541 r27760  
    11package gpxfilter;
    2 
    3 import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
    4 import static org.openstreetmap.josm.tools.I18n.marktr;
    5 
    6 import java.awt.event.KeyEvent;
    7 
    8 import javax.swing.JMenu;
    92
    103import org.openstreetmap.josm.Main;
     
    1710    public GpxFilterPlugin(PluginInformation info) {
    1811        super(info);
    19         JMenu historyMenu = Main.main.menu.addMenu(marktr("GPX"), KeyEvent.VK_R,
    20                 Main.main.menu.defaultMenuPos,null);
    21         //MainMenu.add(historyMenu, new ObjectsHistoryAction());
    22         MainMenu.add(historyMenu, new AddEGpxLayerAction());
     12        MainMenu.add(Main.main.menu.toolsMenu, new AddEGpxLayerAction());
    2313    }
    2414
  • applications/editors/josm/plugins/graphview/src/org/openstreetmap/josm/plugins/graphview/plugin/preferences/GraphViewPreferences.java

    r26481 r27760  
    11package org.openstreetmap.josm.plugins.graphview.plugin.preferences;
     2
     3import static org.openstreetmap.josm.tools.I18n.marktr;
    24
    35import static org.openstreetmap.josm.plugins.graphview.core.property.VehiclePropertyTypes.AXLELOAD;
     
    234236        currentColorScheme = new PreferencesColorScheme(this);
    235237
    236         nodeColor = Color.WHITE;
    237         segmentColor = Color.WHITE;
    238         arrowheadFillColor = Color.BLACK;
    239 
    240238        separateDirections = false;
    241239
     
    262260        }
    263261
    264         Main.pref.put("graphview.defaultNodeColor", createColorString(nodeColor));
    265         Main.pref.put("graphview.defaultSegmentColor", createColorString(segmentColor));
    266         Main.pref.put("graphview.defaultArrowheadCoreColor", createColorString(arrowheadFillColor));
     262        Main.pref.putColor(marktr("graphview default node"), Color.WHITE);
     263        Main.pref.putColor(marktr("graphview default segment"), Color.WHITE);
     264        Main.pref.putColor(marktr("graphview arrowhead core"), Color.BLACK);
    267265
    268266        Main.pref.put("graphview.separateDirections", separateDirections);
     
    274272    private void readPreferences() {
    275273
    276         if (Main.pref.hasKey("graphview.parameterBookmarks")) {
     274        if (!Main.pref.get("graphview.parameterBookmarks").isEmpty()) {
    277275            String bookmarksString = Main.pref.get("graphview.parameterBookmarks");
    278276            parameterBookmarks = parseAccessParameterBookmarksString(bookmarksString);
    279277        }
    280278
    281         if (Main.pref.hasKey("graphview.activeBookmark")) {
     279        if (!Main.pref.get("graphview.activeBookmark").isEmpty()) {
    282280            currentParameterBookmarkName = Main.pref.get("graphview.activeBookmark");
    283281        }
     
    289287        useInternalRulesets = Main.pref.getBoolean("graphview.useInternalRulesets", true);
    290288
    291         if (Main.pref.hasKey("graphview.rulesetFolder")) {
     289        if (!Main.pref.get("graphview.rulesetFolder").isEmpty()) {
    292290            String dirString = Main.pref.get("graphview.rulesetFolder");
    293291            rulesetFolder = new File(dirString);
    294292        }
    295         if (Main.pref.hasKey("graphview.rulesetFile")) {
     293        if (!Main.pref.get("graphview.rulesetFile").isEmpty()) {
    296294            String fileString = Main.pref.get("graphview.rulesetFile");
    297295            currentRulesetFile = new File(fileString);
    298296        }
    299297
    300         if (Main.pref.hasKey("graphview.rulesetResource")) {
     298        if (!Main.pref.get("graphview.rulesetResource").isEmpty()) {
    301299            String rulesetString = Main.pref.get("graphview.rulesetResource");
    302300            //get the enum value for the string
     
    310308        }
    311309
    312         if (Main.pref.hasKey("graphview.defaultNodeColor")) {
    313             Color color = parseColorString(Main.pref.get("graphview.defaultNodeColor"));
    314             if (color != null) {
    315                 nodeColor = color;
    316             }
    317         }
    318         if (Main.pref.hasKey("graphview.defaultSegmentColor")) {
    319             Color color = parseColorString(Main.pref.get("graphview.defaultSegmentColor"));
    320             if (color != null) {
    321                 segmentColor = color;
    322             }
    323         }
    324         if (Main.pref.hasKey("graphview.defaultArrowheadCoreColor")) {
    325             Color color = parseColorString(Main.pref.get("graphview.defaultArrowheadCoreColor"));
    326             if (color != null) {
    327                 arrowheadFillColor = color;
    328             }
    329         }
    330 
     310        nodeColor = Main.pref.getColor(marktr("graphview default node"), Color.WHITE);
     311        segmentColor = Main.pref.getColor(marktr("graphview default segment"), Color.WHITE);
     312        arrowheadFillColor = Main.pref.getColor(marktr("graphview arrowhead core"), Color.BLACK);
    331313        separateDirections = Main.pref.getBoolean("graphview.separateDirections", false);
    332314
     
    503485        }
    504486    }
    505 
    506     private static final Pattern COLOR_PATTERN =
    507         Pattern.compile("^(\\d{1,3}),\\s*(\\d{1,3}),\\s*(\\d{1,3})$");
    508 
    509     private String createColorString(Color color) {
    510         return color.getRed() + ", " + color.getGreen() + ", " + color.getBlue();
    511     }
    512 
    513     private Color parseColorString(String string) {
    514         Matcher matcher = COLOR_PATTERN.matcher(string);
    515         if (!matcher.matches()) {
    516             return null;
    517         } else {
    518             int r = Integer.parseInt(matcher.group(1));
    519             int g = Integer.parseInt(matcher.group(2));
    520             int b = Integer.parseInt(matcher.group(3));
    521             return new Color(r, g, b);
    522         }
    523     }
    524 
    525487}
  • applications/editors/josm/plugins/print/src/org/openstreetmap/josm/plugins/print/PrintPlugin.java

    r27282 r27760  
    125125     */
    126126    public static void adjustPrefs() {
    127         if (! Main.pref.getBoolean("print.saved-prefs", false)) {
     127        if (!Main.pref.getBoolean("print.saved-prefs", false)) {
    128128            Main.pref.put("print.saved-prefs", true);
    129129            adjustPref("draw.data.downloaded_area", false);
     
    145145     */
    146146    protected static void adjustPref(String key, int value) {
    147         if (Main.pref.hasKey(key)) {
     147        if (!Main.pref.get(key).isEmpty()) {
    148148            Main.pref.put("print.saved-prefs."+key, Main.pref.get(key));
    149149        }
     
    160160     */
    161161    protected static void adjustPref(String key, boolean value) {
    162         if (Main.pref.hasKey(key)) {
     162        if (!Main.pref.get(key).isEmpty()) {
    163163            Main.pref.put("print.saved-prefs."+key, Main.pref.get(key));
    164164        }
     
    175175     */
    176176    protected static void adjustPref(String key, String value) {
    177         if (Main.pref.hasKey(key)) {
     177        if (!Main.pref.get(key).isEmpty()) {
    178178            Main.pref.put("print.saved-prefs."+key, Main.pref.get(key));
    179179        }
  • applications/editors/josm/plugins/routing/src/com/innovant/josm/plugin/routing/RoutingLayer.java

    r26119 r27760  
    2727
    2828package com.innovant.josm.plugin.routing;
     29
     30import static org.openstreetmap.josm.tools.I18n.marktr;
    2931
    3032import java.awt.BasicStroke;
     
    5961import org.openstreetmap.josm.tools.ImageProvider;
    6062
    61 import com.innovant.josm.jrt.core.PreferencesKeys;
    6263import com.innovant.josm.jrt.osm.OsmEdge;
    6364
     
    6970 */
    7071public class RoutingLayer extends Layer {
     72
     73    public enum PreferencesKeys {
     74        KEY_ACTIVE_ROUTE_COLOR (marktr("routing active route")),
     75        KEY_INACTIVE_ROUTE_COLOR (marktr("routing inactive route")),
     76        KEY_ROUTE_WIDTH ("routing.route.width"),
     77        KEY_ROUTE_SELECT ("routing.route.select");
     78
     79        public final String key;
     80        PreferencesKeys (String key) {
     81            this.key=key;
     82        }
     83
     84        public String getKey() {return key;};
     85    }
    7186
    7287    /**
     
    240255        // Get path stroke color from preferences
    241256        // Color is different for active and inactive layers
    242         String colorString;
     257        Color color;
    243258        if (isActiveLayer) {
    244             if (Main.pref.hasKey(PreferencesKeys.KEY_ACTIVE_ROUTE_COLOR.key))
    245                     colorString = Main.pref.get(PreferencesKeys.KEY_ACTIVE_ROUTE_COLOR.key);
    246             else {
    247                 colorString = ColorHelper.color2html(Color.RED);
    248                 Main.pref.put(PreferencesKeys.KEY_ACTIVE_ROUTE_COLOR.key, colorString);
    249             }
     259            color = Main.pref.getColor(PreferencesKeys.KEY_ACTIVE_ROUTE_COLOR.key, Color.RED);
    250260        } else {
    251             if (Main.pref.hasKey(PreferencesKeys.KEY_INACTIVE_ROUTE_COLOR.key))
    252                 colorString = Main.pref.get(PreferencesKeys.KEY_INACTIVE_ROUTE_COLOR.key);
    253             else {
    254                 colorString = ColorHelper.color2html(Color.decode("#dd2222"));
    255                 Main.pref.put(PreferencesKeys.KEY_INACTIVE_ROUTE_COLOR.key, colorString);
    256             }
    257         }
    258         Color color = ColorHelper.html2color(colorString);
     261            color = Main.pref.getColor(PreferencesKeys.KEY_INACTIVE_ROUTE_COLOR.key, Color.decode("#dd2222"));
     262        }
    259263
    260264        // Get path stroke width from preferences
Note: See TracChangeset for help on using the changeset viewer.