Changeset 4282 in josm


Ignore:
Timestamp:
07.08.2011 09:08:29 (10 months ago)
Author:
jttt
Message:

Allow to specify custom pattern for marker text labels

Location:
trunk
Files:
22 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/.classpath

    r4236 r4282  
    1717        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> 
    1818        <classpathentry exported="true" kind="con" path="GROOVY_SUPPORT"/> 
     19        <classpathentry kind="lib" path="test/lib/unitils-core/commons-collections-3.2.jar"/> 
     20        <classpathentry kind="lib" path="test/lib/unitils-core/commons-lang-2.3.jar"/> 
     21        <classpathentry kind="lib" path="test/lib/unitils-core/commons-logging-1.1.jar"/> 
     22        <classpathentry kind="lib" path="test/lib/unitils-core/junit-4.4.jar"/> 
     23        <classpathentry kind="lib" path="test/lib/unitils-core/ognl-2.6.9.jar"/> 
     24        <classpathentry kind="lib" path="test/lib/unitils-core/unitils-core-3.1.jar"/> 
    1925        <classpathentry kind="output" path="bin"/> 
    2026</classpath> 
  • trunk/src/org/openstreetmap/josm/data/gpx/WayPoint.java

    r4129 r4282  
    55 
    66import java.awt.Color; 
     7import java.util.ArrayList; 
    78import java.util.Date; 
     9import java.util.List; 
    810 
    911import org.openstreetmap.josm.Main; 
     12import org.openstreetmap.josm.actions.search.SearchCompiler.Match; 
    1013import org.openstreetmap.josm.data.coor.EastNorth; 
    1114import org.openstreetmap.josm.data.coor.LatLon; 
    1215import org.openstreetmap.josm.data.projection.Projections; 
    1316import org.openstreetmap.josm.tools.PrimaryDateParser; 
     17import org.openstreetmap.josm.tools.template_engine.TemplateEngineDataProvider; 
    1418 
    15 public class WayPoint extends WithAttributes implements Comparable<WayPoint> { 
     19public class WayPoint extends WithAttributes implements Comparable<WayPoint>, TemplateEngineDataProvider { 
    1620 
    1721    private static ThreadLocal<PrimaryDateParser> dateParser = new ThreadLocal<PrimaryDateParser>() { 
     
    117121        return new Date((long) (time * 1000)); 
    118122    } 
     123 
     124    @Override 
     125    public Object getTemplateValue(String name) { 
     126        return attr.get(name); 
     127    } 
     128 
     129    @Override 
     130    public boolean evaluateCondition(Match condition) { 
     131        throw new UnsupportedOperationException(); 
     132    } 
     133 
     134    @Override 
     135    public List<String> getTemplateKeys() { 
     136        return new ArrayList<String>(attr.keySet()); 
     137    } 
    119138} 
  • trunk/src/org/openstreetmap/josm/data/preferences/AbstractProperty.java

    r3730 r4282  
    77 * captures the common functionality of preference properties 
    88 */ 
    9 public class AbstractProperty { 
     9public abstract class AbstractProperty<T> { 
    1010    protected final String key; 
    1111 
     
    2121        return Main.pref.hasKey(key); 
    2222    } 
     23 
     24    public abstract T getDefaultValue(); 
     25 
     26    public void remove() { 
     27        Main.pref.put(getKey(), String.valueOf(getDefaultValue())); 
     28    } 
     29 
    2330} 
  • trunk/src/org/openstreetmap/josm/data/preferences/BooleanProperty.java

    r3730 r4282  
    44import org.openstreetmap.josm.Main; 
    55 
    6 public class BooleanProperty extends AbstractProperty { 
     6public class BooleanProperty extends AbstractProperty<Boolean> { 
    77 
    88    protected final boolean defaultValue; 
     
    1414 
    1515    public boolean get() { 
    16         return Main.pref.getBoolean(getKey(), isDefaultValue()); 
     16        return Main.pref.getBoolean(getKey(), defaultValue); 
    1717    } 
    1818 
     
    2121    } 
    2222 
    23     public boolean isDefaultValue() { 
     23    @Override 
     24    public Boolean getDefaultValue() { 
    2425        return defaultValue; 
    2526    } 
  • trunk/src/org/openstreetmap/josm/data/preferences/CollectionProperty.java

    r3730 r4282  
    66import org.openstreetmap.josm.Main; 
    77 
    8 public class CollectionProperty extends AbstractProperty { 
     8public class CollectionProperty extends AbstractProperty<Collection<String>> { 
    99    protected final Collection<String> defaultValue; 
    1010 
     
    2222    } 
    2323 
     24    @Override 
    2425    public Collection<String> getDefaultValue() { 
    2526        return defaultValue; 
  • trunk/src/org/openstreetmap/josm/data/preferences/IntegerProperty.java

    r3730 r4282  
    44import org.openstreetmap.josm.Main; 
    55 
    6 public class IntegerProperty extends AbstractProperty { 
     6public class IntegerProperty extends AbstractProperty<Integer> { 
    77 
    88    protected final int defaultValue; 
     
    3737    } 
    3838 
    39     public int getDefaultValue() { 
     39    @Override 
     40    public Integer getDefaultValue() { 
    4041        return defaultValue; 
    4142    } 
  • trunk/src/org/openstreetmap/josm/data/preferences/StringProperty.java

    r3730 r4282  
    44import org.openstreetmap.josm.Main; 
    55 
    6 public class StringProperty extends AbstractProperty { 
     6public class StringProperty extends AbstractProperty<String> { 
    77 
    88    protected final String defaultValue; 
     
    2121    } 
    2222 
     23    @Override 
    2324    public String getDefaultValue() { 
    2425        return defaultValue; 
  • trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java

    r4276 r4282  
    2020import java.awt.geom.Rectangle2D; 
    2121import java.io.File; 
     22import java.net.MalformedURLException; 
     23import java.net.URL; 
    2224import java.text.DateFormat; 
    2325import java.util.ArrayList; 
     
    2628import java.util.Collections; 
    2729import java.util.Comparator; 
    28 import java.util.Date; 
    29 import java.util.HashMap; 
    3030import java.util.LinkedList; 
    3131import java.util.List; 
    32 import java.util.Map; 
    3332import java.util.concurrent.Future; 
    3433 
    3534import javax.swing.AbstractAction; 
    3635import javax.swing.Action; 
    37 import javax.swing.Box; 
    38 import javax.swing.ButtonGroup; 
    39 import javax.swing.ButtonModel; 
    4036import javax.swing.Icon; 
    4137import javax.swing.JFileChooser; 
     
    4541import javax.swing.JOptionPane; 
    4642import javax.swing.JPanel; 
    47 import javax.swing.JRadioButton; 
    4843import javax.swing.JScrollPane; 
    4944import javax.swing.SwingUtilities; 
     
    358353 
    359354    /** 
    360      * transition function:  
     355     * transition function: 
    361356     *  w(0)=1, w(1)=0, 0<=w(x)<=1 
    362357     * @param x number: 0<=x<=1 
     
    364359     */ 
    365360    private static float w(float x) { 
    366         if (x < 0.5) { 
     361        if (x < 0.5) 
    367362            return 1 - 2*x*x; 
    368         } else { 
    369         return 2*(1-x)*(1-x); 
    370         } 
    371     } 
    372      
     363        else 
     364            return 2*(1-x)*(1-x); 
     365    } 
     366 
    373367    // lookup array to draw arrows without doing any math 
    374368    private final static int ll0 = 9; 
     
    463457                    for (GpxTrack trk : data.tracks) { 
    464458                        for (GpxTrackSegment segment : trk.getSegments()) { 
    465                             if(!forceLines) oldWp = null; 
     459                            if(!forceLines) { 
     460                                oldWp = null; 
     461                            } 
    466462                            for (WayPoint trkPnt : segment.getWayPoints()) { 
    467463                                LatLon c = trkPnt.getCoor(); 
     
    472468                                    double vel = c.greatCircleDistance(oldWp.getCoor()) 
    473469                                            / (trkPnt.time - oldWp.time); 
    474                                     if(vel > maxval) maxval = vel; 
    475                                     if(vel < minval) minval = vel; 
     470                                    if(vel > maxval) { 
     471                                        maxval = vel; 
     472                                    } 
     473                                    if(vel < minval) { 
     474                                        minval = vel; 
     475                                    } 
    476476                                } 
    477477                                oldWp = trkPnt; 
     
    486486                                if (val != null) { 
    487487                                    double hdop = ((Float) val).doubleValue(); 
    488                                     if(hdop > maxval) maxval = hdop; 
    489                                     if(hdop < minval) minval = hdop; 
     488                                    if(hdop > maxval) { 
     489                                        maxval = hdop; 
     490                                    } 
     491                                    if(hdop < minval) { 
     492                                        minval = hdop; 
     493                                    } 
    490494                                } 
    491495                            } 
     
    496500            } 
    497501            if (colored == colorModes.time) { 
    498                     for (GpxTrack trk : data.tracks) { 
    499                         for (GpxTrackSegment segment : trk.getSegments()) { 
    500                             for (WayPoint trkPnt : segment.getWayPoints()) { 
    501                                double t=trkPnt.time; 
    502                                if (t==0) continue; // skip non-dated trackpoints 
    503                                if(t > maxval) maxval = t; 
    504                                if(t < minval) minval = t; 
     502                for (GpxTrack trk : data.tracks) { 
     503                    for (GpxTrackSegment segment : trk.getSegments()) { 
     504                        for (WayPoint trkPnt : segment.getWayPoints()) { 
     505                            double t=trkPnt.time; 
     506                            if (t==0) { 
     507                                continue; // skip non-dated trackpoints 
    505508                            } 
    506                         } 
    507                     } 
    508                 } 
    509              
     509                            if(t > maxval) { 
     510                                maxval = t; 
     511                            } 
     512                            if(t < minval) { 
     513                                minval = t; 
     514                            } 
     515                        } 
     516                    } 
     517                } 
     518            } 
     519 
    510520            for (GpxTrack trk : data.tracks) { 
    511521                for (GpxTrackSegment segment : trk.getSegments()) { 
     
    522532                            float hdop = ((Float) trkPnt.attr.get("hdop")).floatValue(); 
    523533                            int hdoplvl =(int) Math.round(colorModeDynamic ? ((hdop-minval)*255/(maxval-minval)) 
    524                             : (hdop <= 0 ? 0 : hdop * hdopfactor)); 
     534                                    : (hdop <= 0 ? 0 : hdop * hdopfactor)); 
    525535                            // High hdop is bad, but high values in colors are green. 
    526536                            // Therefore inverse the logic 
     
    537547                                    float vel = (float) (dist / dtime); 
    538548                                    int velColor =(int) Math.round(colorModeDynamic ? ((vel-minval)*255/(maxval-minval)) 
    539                                     : (vel <= 0 ? 0 : vel / colorTracksTune * 255)); 
     549                                            : (vel <= 0 ? 0 : vel / colorTracksTune * 255)); 
    540550                                    trkPnt.customColoring = colors[velColor > 255 ? 255 : velColor]; 
    541551                                } else { 
     
    561571                                break; 
    562572                            } 
    563                              
     573 
    564574                            if (!noDraw && (maxLineLength == -1 || dist <= maxLineLength)) { 
    565575                                trkPnt.drawLine = true; 
     
    585595                { 
    586596                    Bounds b = new Bounds(pt.getCoor()); 
    587                     if(pt.drawLine) // last should never be null when this is true! 
     597                    // last should never be null when this is true! 
     598                    if(pt.drawLine) { 
    588599                        b.extend(last.getCoor()); 
     600                    } 
    589601                    if(b.intersects(box)) 
    590602                    { 
    591603                        if(last != null && (visibleSegments.isEmpty() 
    592                         || visibleSegments.getLast() != last)) { 
     604                                || visibleSegments.getLast() != last)) { 
    593605                            if(last.drawLine) { 
    594606                                WayPoint l = new WayPoint(last); 
     
    646658                    if (old != null 
    647659                            && (oldA == null || screen.x < oldA.x - delta || screen.x > oldA.x + delta 
    648                                     || screen.y < oldA.y - delta || screen.y > oldA.y + delta)) { 
     660                            || screen.y < oldA.y - delta || screen.y > oldA.y + delta)) { 
    649661                        g.setColor(trkPnt.customColoring); 
    650662                        double t = Math.atan2(screen.y - old.y, screen.x - old.x) + Math.PI; 
     
    676688                    if (old != null 
    677689                            && (oldA == null || screen.x < oldA.x - delta || screen.x > oldA.x + delta 
    678                                     || screen.y < oldA.y - delta || screen.y > oldA.y + delta)) { 
     690                            || screen.y < oldA.y - delta || screen.y > oldA.y + delta)) { 
    679691                        g.setColor(trkPnt.customColoring); 
    680692                        g.drawLine(screen.x, screen.y, screen.x + dir[trkPnt.dir][0], screen.y 
     
    859871                    JOptionPane.OK_CANCEL_OPTION, 
    860872                    JOptionPane.QUESTION_MESSAGE 
    861             ); 
     873                    ); 
    862874            switch(ret) { 
    863875            case JOptionPane.CANCEL_OPTION: 
     
    982994                        JOptionPane.OK_CANCEL_OPTION, 
    983995                        JOptionPane.PLAIN_MESSAGE 
    984                 ); 
     996                        ); 
    985997                switch(ret) { 
    986998                case JOptionPane.CANCEL_OPTION: 
     
    10061018                        } 
    10071019                    } 
    1008             ); 
     1020                    ); 
    10091021        } 
    10101022    } 
     
    10491061     */ 
    10501062    private void importAudio(File wavFile, MarkerLayer ml, double firstStartTime, Markers markers) { 
    1051         String uri = "file:".concat(wavFile.getAbsolutePath()); 
     1063        URL url = null; 
     1064        try { 
     1065            url = wavFile.toURI().toURL(); 
     1066        } catch (MalformedURLException e) { 
     1067            System.err.println("Unable to convert filename " + wavFile.getAbsolutePath() + " to URL"); 
     1068        } 
    10521069        Collection<WayPoint> waypoints = new ArrayList<WayPoint>(); 
    10531070        boolean timedMarkersOmitted = false; 
     
    10841101                    tr("Error"), 
    10851102                    JOptionPane.ERROR_MESSAGE 
    1086             ); 
     1103                    ); 
    10871104            return; 
    10881105        } 
     
    11431160            double startTime = lastModified - duration; 
    11441161            startTime = firstStartTime + (startTime - firstStartTime) 
    1145             / Main.pref.getDouble("audio.calibration", "1.0" /* default, ratio */); 
     1162                    / Main.pref.getDouble("audio.calibration", "1.0" /* default, ratio */); 
    11461163            WayPoint w1 = null; 
    11471164            WayPoint w2 = null; 
     
    12191236            } 
    12201237            double offset = w.time - firstTime; 
    1221             String name; 
    1222             if (w.attr.containsKey("name")) { 
    1223                 name = w.getString("name"); 
    1224             } else if (w.attr.containsKey("desc")) { 
    1225                 name = w.getString("desc"); 
    1226             } else { 
    1227                 name = AudioMarker.inventName(offset); 
    1228             } 
    1229             AudioMarker am = AudioMarker.create(w.getCoor(), name, uri, ml, w.time, offset); 
     1238            AudioMarker am = new AudioMarker(w.getCoor(), w, url, ml, w.time, offset); 
    12301239            /* 
    12311240             * timeFromAudio intended for future use to shift markers of this type on 
     
    13791388            this(); 
    13801389            layers = new LinkedList<Layer>(); 
    1381             layers.add(l);  
     1390            layers.add(l); 
    13821391        } 
    13831392 
     
    14101419            for (Layer layer : layers) { 
    14111420                if (layer instanceof GpxLayer) { 
    1412                     if (((GpxLayer) layer).isLocalFile) hasLocal = true; 
    1413                     else hasNonlocal = true; 
    1414                 } 
    1415             } 
    1416             GPXSettingsPanel panel=new GPXSettingsPanel(getName(), hasLocal, hasNonlocal);  
     1421                    if (((GpxLayer) layer).isLocalFile) { 
     1422                        hasLocal = true; 
     1423                    } else { 
     1424                        hasNonlocal = true; 
     1425                    } 
     1426                } 
     1427            } 
     1428            GPXSettingsPanel panel=new GPXSettingsPanel(getName(), hasLocal, hasNonlocal); 
    14171429 
    14181430            int answer = JOptionPane.showConfirmDialog(Main.parent, panel, 
     
    14211433            for(Layer layer : layers) { 
    14221434                // save preferences for all layers 
    1423                 boolean f=false;  
    1424                 if (layer instanceof GpxLayer) f=((GpxLayer)layer).isLocalFile; 
    1425                     panel.savePreferences(layer.getName(),f); 
     1435                boolean f=false; 
     1436                if (layer instanceof GpxLayer) { 
     1437                    f=((GpxLayer)layer).isLocalFile; 
     1438                } 
     1439                panel.savePreferences(layer.getName(),f); 
    14261440            } 
    14271441            Main.map.repaint(); 
     
    14681482                    + "Because its way points do not include a timestamp we cannot correlate them with audio data.</html>", 
    14691483                    layer.getName() 
    1470             ); 
     1484                    ); 
    14711485            HelpAwareOptionPane.showOptionDialog( 
    14721486                    Main.parent, 
     
    14751489                    JOptionPane.WARNING_MESSAGE, 
    14761490                    ht("/Action/ImportAudio#CantImportIntoGpxLayerFromServer") 
    1477             ); 
     1491                    ); 
    14781492        } 
    14791493 
     
    15341548                        getAssociatedFile(), GpxLayer.this); 
    15351549                double firstStartTime = sel[0].lastModified() / 1000.0 /* ms -> seconds */ 
    1536                 - AudioUtil.getCalibratedDuration(sel[0]); 
     1550                        - AudioUtil.getCalibratedDuration(sel[0]); 
    15371551 
    15381552                Markers m = new Markers(); 
     
    15581572                    + "Because its way points do not include a timestamp we cannot correlate them with images.</html>", 
    15591573                    layer.getName() 
    1560             ); 
     1574                    ); 
    15611575            HelpAwareOptionPane.showOptionDialog( 
    15621576                    Main.parent, 
     
    15651579                    JOptionPane.WARNING_MESSAGE, 
    15661580                    ht("/Action/ImportImages#CantImportIntoGpxLayerFromServer") 
    1567             ); 
     1581                    ); 
    15681582        } 
    15691583 
  • trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/AudioMarker.java

    r1685 r4282  
    88import org.openstreetmap.josm.data.coor.LatLon; 
    99import org.openstreetmap.josm.tools.AudioPlayer; 
     10import org.openstreetmap.josm.tools.template_engine.TemplateEngineDataProvider; 
    1011 
    1112/** 
     
    2223    public boolean timeFromAudio = false; // as opposed to from the GPX track 
    2324 
    24     /** 
    25      * Verifies the parameter whether a new AudioMarker can be created and return 
    26      * one or return <code>null</code>. 
    27      */ 
    28     public static AudioMarker create(LatLon ll, String text, String url, MarkerLayer parentLayer, double time, double offset) { 
    29         try { 
    30             return new AudioMarker(ll, text, new URL(url), parentLayer, time, offset); 
    31         } catch (Exception ex) { 
    32             return null; 
    33         } 
    34     } 
    35  
    36     private AudioMarker(LatLon ll, String text, URL audioUrl, MarkerLayer parentLayer, double time, double offset) { 
    37         super(ll, text, "speech.png", parentLayer, time, offset); 
     25    public AudioMarker(LatLon ll, TemplateEngineDataProvider dataProvider, URL audioUrl, MarkerLayer parentLayer, double time, double offset) { 
     26        super(ll, dataProvider, "speech.png", parentLayer, time, offset); 
    3827        this.audioUrl = audioUrl; 
    3928        this.syncOffset = 0.0; 
     
    8473    } 
    8574 
    86     public static String inventName (double offset) { 
    87         int wholeSeconds = (int)(offset + 0.5); 
    88         if (wholeSeconds < 60) 
    89             return Integer.toString(wholeSeconds); 
    90         else if (wholeSeconds < 3600) 
    91             return String.format("%d:%02d", wholeSeconds / 60, wholeSeconds % 60); 
    92         else 
    93             return String.format("%d:%02d:%02d", wholeSeconds / 3600, (wholeSeconds % 3600)/60, wholeSeconds % 60); 
     75    @Override 
     76    protected TemplateEntryProperty getTextTemplate() { 
     77        return TemplateEntryProperty.forAudioMarker(parentLayer.getName()); 
    9478    } 
    9579} 
  • trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/ButtonMarker.java

    r3396 r4282  
    1414import org.openstreetmap.josm.data.coor.LatLon; 
    1515import org.openstreetmap.josm.gui.MapView; 
     16import org.openstreetmap.josm.tools.template_engine.TemplateEngineDataProvider; 
    1617 
    1718/** 
     
    2627 
    2728    public ButtonMarker(LatLon ll, String buttonImage, MarkerLayer parentLayer, double time, double offset) { 
    28         super(ll, "", buttonImage, parentLayer, time, offset); 
     29        super(ll, null, buttonImage, parentLayer, time, offset); 
    2930        buttonRectangle = new Rectangle(0, 0, symbol.getIconWidth(), symbol.getIconHeight()); 
    3031    } 
    3132 
    32     public ButtonMarker(LatLon ll, String text, String buttonImage, MarkerLayer parentLayer, double time, double offset) { 
    33         super(ll, text, buttonImage, parentLayer, time, offset); 
     33    public ButtonMarker(LatLon ll, TemplateEngineDataProvider dataProvider, String buttonImage, MarkerLayer parentLayer, double time, double offset) { 
     34        super(ll, dataProvider, buttonImage, parentLayer, time, offset); 
    3435        buttonRectangle = new Rectangle(0, 0, symbol.getIconWidth(), symbol.getIconHeight()); 
    3536    } 
  • trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/ImageMarker.java

    r1847 r4282  
    3434    public URL imageUrl; 
    3535 
    36     public static ImageMarker create(LatLon ll, String url, MarkerLayer parentLayer, double time, double offset) { 
    37         try { 
    38             return new ImageMarker(ll, new URL(url), parentLayer, time, offset); 
    39         } catch (Exception ex) { 
    40             return null; 
    41         } 
    42     } 
    43  
    44     private ImageMarker(LatLon ll, URL imageUrl, MarkerLayer parentLayer, double time, double offset) { 
     36    public ImageMarker(LatLon ll, URL imageUrl, MarkerLayer parentLayer, double time, double offset) { 
    4537        super(ll, "photo.png", parentLayer, time, offset); 
    4638        this.imageUrl = imageUrl; 
  • trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java

    r4172 r4282  
    55import java.awt.Point; 
    66import java.awt.event.ActionEvent; 
    7 import java.awt.event.ActionListener; 
    87import java.io.File; 
    98import java.net.MalformedURLException; 
    109import java.net.URL; 
     10import java.util.ArrayList; 
    1111import java.util.Collection; 
    1212import java.util.HashMap; 
    1313import java.util.LinkedList; 
     14import java.util.List; 
    1415import java.util.Map; 
    1516 
    1617import javax.swing.Icon; 
    1718 
     19import org.openstreetmap.josm.actions.search.SearchCompiler.Match; 
     20import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent; 
    1821import org.openstreetmap.josm.data.coor.CachedLatLon; 
    1922import org.openstreetmap.josm.data.coor.EastNorth; 
     
    2225import org.openstreetmap.josm.data.gpx.GpxLink; 
    2326import org.openstreetmap.josm.data.gpx.WayPoint; 
     27import org.openstreetmap.josm.data.preferences.CachedProperty; 
    2428import org.openstreetmap.josm.data.preferences.IntegerProperty; 
    2529import org.openstreetmap.josm.gui.MapView; 
    2630import org.openstreetmap.josm.tools.ImageProvider; 
     31import org.openstreetmap.josm.tools.template_engine.ParseError; 
     32import org.openstreetmap.josm.tools.template_engine.TemplateEngineDataProvider; 
     33import org.openstreetmap.josm.tools.template_engine.TemplateEntry; 
     34import org.openstreetmap.josm.tools.template_engine.TemplateParser; 
    2735 
    2836/** 
     
    6169 * @author Frederik Ramm <frederik@remote.org> 
    6270 */ 
    63 public class Marker implements ActionListener { 
    64     public final String text; 
    65     public final Map<String,String> textMap = new HashMap<String,String>(); 
    66     public final Icon symbol; 
    67     public final MarkerLayer parentLayer; 
    68     public double time; /* absolute time of marker since epoch */ 
    69     public double offset; /* time offset in seconds from the gpx point from which it was derived, 
    70                              may be adjusted later to sync with other data, so not final */ 
    71  
    72     private CachedLatLon coor; 
    73  
    74     public final void setCoor(LatLon coor) { 
    75         if(this.coor == null) { 
    76             this.coor = new CachedLatLon(coor); 
    77         } else { 
    78             this.coor.setCoor(coor); 
    79         } 
    80     } 
    81  
    82     public final LatLon getCoor() { 
    83         return coor; 
    84     } 
    85  
    86     public final void setEastNorth(EastNorth eastNorth) { 
    87         coor.setEastNorth(eastNorth); 
    88     } 
    89  
    90     public final EastNorth getEastNorth() { 
    91         return coor.getEastNorth(); 
    92     } 
     71public class Marker implements TemplateEngineDataProvider { 
     72 
     73    public static class TemplateEntryProperty extends CachedProperty<TemplateEntry> { 
     74        // This class is a bit complicated because it supports both global and per layer settings. I've added per layer settings because 
     75        // GPXSettingsPanel had possibility to set waypoint label but then I've realized that markers use different layer then gpx data 
     76        // so per layer settings is useless. Anyway it's possible to specify marker layer pattern in Einstein preferences and maybe somebody 
     77        // will make gui for it so I'm keeping it here 
     78 
     79        private final static Map<String, TemplateEntryProperty> cache = new HashMap<String, Marker.TemplateEntryProperty>(); 
     80 
     81        // Legacy code - convert label from int to template engine expression 
     82        private static final IntegerProperty PROP_LABEL = new IntegerProperty("draw.rawgps.layer.wpt", 0 ); 
     83        private static String getDefaultLabelPattern() { 
     84            switch (PROP_LABEL.get()) { 
     85            case 1: 
     86                return LABEL_PATTERN_NAME; 
     87            case 2: 
     88                return LABEL_PATTERN_DESC; 
     89            case 0: 
     90            case 3: 
     91                return LABEL_PATTERN_AUTO; 
     92            default: 
     93                return ""; 
     94            } 
     95        } 
     96 
     97        public static TemplateEntryProperty forMarker(String layerName) { 
     98            String key = "draw.rawgps.layer.wpt.pattern"; 
     99            if (layerName != null) { 
     100                key += "." + layerName; 
     101            } 
     102            TemplateEntryProperty result = cache.get(key); 
     103            if (result == null) { 
     104                String defaultValue = layerName == null?getDefaultLabelPattern():""; 
     105                TemplateEntryProperty parent = layerName == null?null:forMarker(null); 
     106                result = new TemplateEntryProperty(key, defaultValue, parent); 
     107                cache.put(key, result); 
     108            } 
     109            return result; 
     110        } 
     111 
     112        public static TemplateEntryProperty forAudioMarker(String layerName) { 
     113            String key = "draw.rawgps.layer.audiowpt.pattern"; 
     114            if (layerName != null) { 
     115                key += "." + layerName; 
     116            } 
     117            TemplateEntryProperty result = cache.get(key); 
     118            if (result == null) { 
     119                String defaultValue = layerName == null?"?{ '{name}' | '{desc}' | '{" + Marker.MARKER_FORMATTED_OFFSET + "}' }":""; 
     120                TemplateEntryProperty parent = layerName == null?null:forAudioMarker(null); 
     121                result = new TemplateEntryProperty(key, defaultValue, parent); 
     122                cache.put(key, result); 
     123            } 
     124            return result; 
     125        } 
     126 
     127        private TemplateEntryProperty parent; 
     128 
     129 
     130        private TemplateEntryProperty(String key, String defaultValue, TemplateEntryProperty parent) { 
     131            super(key, defaultValue); 
     132            this.parent = parent; 
     133            updateValue(); // Needs to be called because parent wasn't know in super constructor 
     134        } 
     135 
     136        @Override 
     137        protected TemplateEntry fromString(String s) { 
     138            try { 
     139                return new TemplateParser(s).parse(); 
     140            } catch (ParseError e) { 
     141                System.out.println(String.format("Unable to parse template engine pattern '%s' for property %s. Using default ('%s') instead", 
     142                        s, getKey(), defaultValue)); 
     143                return getDefaultValue(); 
     144            } 
     145        } 
     146 
     147        @Override 
     148        public String getDefaultValueAsString() { 
     149            if (parent == null) 
     150                return super.getDefaultValueAsString(); 
     151            else 
     152                return parent.getAsString(); 
     153        } 
     154 
     155        @Override 
     156        public void preferenceChanged(PreferenceChangeEvent e) { 
     157            if (e.getKey().equals(key) || (parent != null && e.getKey().equals(parent.getKey()))) { 
     158                updateValue(); 
     159            } 
     160        } 
     161    } 
     162 
    93163 
    94164    /** 
     
    97167     * stuff). 
    98168     */ 
    99     public static LinkedList<MarkerProducers> markerProducers = new LinkedList<MarkerProducers>(); 
    100  
    101     private static final IntegerProperty PROP_LABEL = new IntegerProperty("draw.rawgps.layer.wpt", 0 ); 
    102     private static final String[] labelAttributes = new String[] {"name", "desc"}; 
     169    public static List<MarkerProducers> markerProducers = new LinkedList<MarkerProducers>(); 
    103170 
    104171    // Add one Maker specifying the default behaviour. 
     
    110177                // cheapest way to check whether "link" object exists and is a non-empty 
    111178                // collection of GpxLink objects... 
    112                 try { 
    113                     for (GpxLink oneLink : (Collection<GpxLink>) wpt.attr.get(GpxData.META_LINKS)) { 
     179                Collection<GpxLink> links = (Collection<GpxLink>)wpt.attr.get(GpxData.META_LINKS); 
     180                if (links != null) { 
     181                    for (GpxLink oneLink : links ) { 
    114182                        uri = oneLink.uri; 
    115183                        break; 
    116184                    } 
    117                 } catch (Exception ex) {} 
    118  
    119                 // Try a relative file:// url, if the link is not in an URL-compatible form 
    120                 if (relativePath != null && uri != null && !isWellFormedAddress(uri)) { 
    121                     uri = new File(relativePath.getParentFile(), uri).toURI().toString(); 
    122185                } 
    123186 
    124                 Map<String,String> nameDesc = new HashMap<String,String>(); 
    125                 for(String attribute : labelAttributes) { 
    126                     if (wpt.attr.containsKey(attribute)) { 
    127                         nameDesc.put(attribute, wpt.getString(attribute)); 
     187                URL url = null; 
     188                if (uri != null) { 
     189                    try { 
     190                        url = new URL(uri); 
     191                    } catch (MalformedURLException e) { 
     192                        // Try a relative file:// url, if the link is not in an URL-compatible form 
     193                        if (relativePath != null) { 
     194                            try { 
     195                                url = new File(relativePath.getParentFile(), uri).toURI().toURL(); 
     196                            } catch (MalformedURLException e1) { 
     197                                System.err.println("Unable to convert uri " + uri + " to URL: "  + e1.getMessage()); 
     198                            } 
     199                        } 
    128200                    } 
    129201                } 
    130202 
    131                 if (uri == null) { 
     203 
     204                if (url == null) { 
    132205                    String symbolName = wpt.getString("symbol"); 
    133206                    if (symbolName == null) { 
    134207                        symbolName = wpt.getString("sym"); 
    135208                    } 
    136                     return new Marker(wpt.getCoor(), nameDesc, symbolName, parentLayer, time, offset); 
     209                    return new Marker(wpt.getCoor(), wpt, symbolName, parentLayer, time, offset); 
    137210                } 
    138                 else if (uri.endsWith(".wav")) 
    139                     return AudioMarker.create(wpt.getCoor(), getText(nameDesc), uri, parentLayer, time, offset); 
    140                 else if (uri.endsWith(".png") || uri.endsWith(".jpg") || uri.endsWith(".jpeg") || uri.endsWith(".gif")) 
    141                     return ImageMarker.create(wpt.getCoor(), uri, parentLayer, time, offset); 
     211                else if (url.toString().endsWith(".wav")) 
     212                    return new AudioMarker(wpt.getCoor(), wpt, url, parentLayer, time, offset); 
     213                else if (url.toString().endsWith(".png") || url.toString().endsWith(".jpg") || url.toString().endsWith(".jpeg") || url.toString().endsWith(".gif")) 
     214                    return new ImageMarker(wpt.getCoor(), url, parentLayer, time, offset); 
    142215                else 
    143                     return WebMarker.create(wpt.getCoor(), uri, parentLayer, time, offset); 
    144             } 
    145  
    146             private boolean isWellFormedAddress(String link) { 
    147                 try { 
    148                     new URL(link); 
    149                     return true; 
    150                 } catch (MalformedURLException x) { 
    151                     return false; 
    152                 } 
     216                    return new WebMarker(wpt.getCoor(), url, parentLayer, time, offset); 
    153217            } 
    154218        }); 
    155     } 
    156  
    157     public Marker(LatLon ll, String text, String iconName, MarkerLayer parentLayer, double time, double offset) { 
    158         setCoor(ll); 
    159         if (text == null || text.length() == 0) { 
    160             this.text = null; 
    161         } 
    162         else { 
    163             this.text = text; 
    164         } 
    165         this.offset = offset; 
    166         this.time = time; 
    167         this.symbol = ImageProvider.getIfAvailable("markers",iconName); 
    168         this.parentLayer = parentLayer; 
    169     } 
    170  
    171     public Marker(LatLon ll, Map<String,String> textMap, String iconName, MarkerLayer parentLayer, double time, double offset) { 
    172         setCoor(ll); 
    173         if (textMap != null) { 
    174             this.textMap.clear(); 
    175             this.textMap.putAll(textMap); 
    176         } 
    177  
    178         this.text = null; 
    179         this.offset = offset; 
    180         this.time = time; 
    181         // /* ICON(markers/) */"Bridge" 
    182         // /* ICON(markers/) */"Crossing" 
    183         this.symbol = ImageProvider.getIfAvailable("markers",iconName); 
    184         this.parentLayer = parentLayer; 
    185     } 
    186  
    187     /** 
    188      * Checks whether the marker display area contains the given point. 
    189      * Markers not interested in mouse clicks may always return false. 
    190      * 
    191      * @param p The point to check 
    192      * @return <code>true</code> if the marker "hotspot" contains the point. 
    193      */ 
    194     public boolean containsPoint(Point p) { 
    195         return false; 
    196     } 
    197  
    198     /** 
    199      * Called when the mouse is clicked in the marker's hotspot. Never 
    200      * called for markers which always return false from containsPoint. 
    201      * 
    202      * @param ev A dummy ActionEvent 
    203      */ 
    204     public void actionPerformed(ActionEvent ev) { 
    205     } 
    206  
    207     /** 
    208      * Paints the marker. 
    209      * @param g graphics context 
    210      * @param mv map view 
    211      * @param mousePressed true if the left mouse button is pressed 
    212      */ 
    213     public void paint(Graphics g, MapView mv, boolean mousePressed, boolean showTextOrIcon) { 
    214         Point screen = mv.getPoint(getEastNorth()); 
    215         if (symbol != null && showTextOrIcon) { 
    216             symbol.paintIcon(mv, g, screen.x-symbol.getIconWidth()/2, screen.y-symbol.getIconHeight()/2); 
    217         } else { 
    218             g.drawLine(screen.x-2, screen.y-2, screen.x+2, screen.y+2); 
    219             g.drawLine(screen.x+2, screen.y-2, screen.x-2, screen.y+2); 
    220         } 
    221  
    222         String labelText = getText(); 
    223         if ((labelText != null) && showTextOrIcon) { 
    224             g.drawString(labelText, screen.x+4, screen.y+2); 
    225         } 
    226219    } 
    227220 
     
    246239    } 
    247240 
    248     /** 
    249      * Returns an AudioMarker derived from this Marker and the provided uri 
    250      * Subclasses of specific marker types override this to return null as they can't 
    251      * be turned into AudioMarkers. This includes AudioMarkers themselves, as they 
    252      * already have audio. 
     241    public static final String MARKER_OFFSET = "waypointOffset"; 
     242    public static final String MARKER_FORMATTED_OFFSET = "formattedWaypointOffset"; 
     243 
     244    public static final String LABEL_PATTERN_AUTO = "?{ '{name} - {desc}' | '{name}' | '{desc}' }"; 
     245    public static final String LABEL_PATTERN_NAME = "{name}"; 
     246    public static final String LABEL_PATTERN_DESC = "{desc}"; 
     247 
     248 
     249    private final TemplateEngineDataProvider dataProvider; 
     250    public final Icon symbol; 
     251    public final MarkerLayer parentLayer; 
     252    public double time; /* absolute time of marker since epoch */ 
     253    public double offset; /* time offset in seconds from the gpx point from which it was derived, 
     254                             may be adjusted later to sync with other data, so not final */ 
     255 
     256    private String cachedText; 
     257    private int textVersion = -1; 
     258    private CachedLatLon coor; 
     259 
     260    public Marker(LatLon ll, TemplateEngineDataProvider dataProvider, String iconName, MarkerLayer parentLayer, double time, double offset) { 
     261        setCoor(ll); 
     262 
     263        this.offset = offset; 
     264        this.time = time; 
     265        // /* ICON(markers/) */"Bridge" 
     266        // /* ICON(markers/) */"Crossing" 
     267        this.symbol = ImageProvider.getIfAvailable("markers",iconName); 
     268        this.parentLayer = parentLayer; 
     269 
     270        this.dataProvider = dataProvider; 
     271    } 
     272 
     273    public final void setCoor(LatLon coor) { 
     274        if(this.coor == null) { 
     275            this.coor = new CachedLatLon(coor); 
     276        } else { 
     277            this.coor.setCoor(coor); 
     278        } 
     279    } 
     280 
     281    public final LatLon getCoor() { 
     282        return coor; 
     283    } 
     284 
     285    public final void setEastNorth(EastNorth eastNorth) { 
     286        coor.setEastNorth(eastNorth); 
     287    } 
     288 
     289    public final EastNorth getEastNorth() { 
     290        return coor.getEastNorth(); 
     291    } 
     292 
     293 
     294    /** 
     295     * Checks whether the marker display area contains the given point. 
     296     * Markers not interested in mouse clicks may always return false. 
    253297     * 
    254      * @param uri uri of wave file 
    255      * @return AudioMarker 
    256      */ 
    257  
    258     public AudioMarker audioMarkerFromMarker(String uri) { 
    259         AudioMarker audioMarker = AudioMarker.create(getCoor(), this.getText(), uri, this.parentLayer, this.time, this.offset); 
    260         return audioMarker; 
     298     * @param p The point to check 
     299     * @return <code>true</code> if the marker "hotspot" contains the point. 
     300     */ 
     301    public boolean containsPoint(Point p) { 
     302        return false; 
     303    } 
     304 
     305    /** 
     306     * Called when the mouse is clicked in the marker's hotspot. Never 
     307     * called for markers which always return false from containsPoint. 
     308     * 
     309     * @param ev A dummy ActionEvent 
     310     */ 
     311    public void actionPerformed(ActionEvent ev) { 
     312    } 
     313 
     314 
     315    /** 
     316     * Paints the marker. 
     317     * @param g graphics context 
     318     * @param mv map view 
     319     * @param mousePressed true if the left mouse button is pressed 
     320     */ 
     321    public void paint(Graphics g, MapView mv, boolean mousePressed, boolean showTextOrIcon) { 
     322        Point screen = mv.getPoint(getEastNorth()); 
     323        if (symbol != null && showTextOrIcon) { 
     324            symbol.paintIcon(mv, g, screen.x-symbol.getIconWidth()/2, screen.y-symbol.getIconHeight()/2); 
     325        } else { 
     326            g.drawLine(screen.x-2, screen.y-2, screen.x+2, screen.y+2); 
     327            g.drawLine(screen.x+2, screen.y-2, screen.x-2, screen.y+2); 
     328        } 
     329 
     330        String labelText = getText(); 
     331        if ((labelText != null) && showTextOrIcon) { 
     332            g.drawString(labelText, screen.x+4, screen.y+2); 
     333        } 
     334    } 
     335 
     336 
     337    protected TemplateEntryProperty getTextTemplate() { 
     338        return TemplateEntryProperty.forMarker(parentLayer.getName()); 
    261339    } 
    262340 
     
    266344     */ 
    267345    public String getText() { 
    268         if (this.text != null ) 
    269             return this.text; 
     346        TemplateEntryProperty property = getTextTemplate(); 
     347        if (property.getUpdateCount() != textVersion) { 
     348            TemplateEntry templateEntry = property.get(); 
     349            StringBuilder sb = new StringBuilder(); 
     350            templateEntry.appendText(sb, this); 
     351 
     352            cachedText = sb.toString(); 
     353            textVersion = property.getUpdateCount(); 
     354        } 
     355        return cachedText; 
     356    } 
     357 
     358    @Override 
     359    public List<String> getTemplateKeys() { 
     360        List<String> result; 
     361        if (dataProvider != null) { 
     362            result = dataProvider.getTemplateKeys(); 
     363        } else { 
     364            result = new ArrayList<String>(); 
     365        } 
     366        result.add(MARKER_FORMATTED_OFFSET); 
     367        result.add(MARKER_OFFSET); 
     368        return result; 
     369    } 
     370 
     371    private String formatOffset () { 
     372        int wholeSeconds = (int)(offset + 0.5); 
     373        if (wholeSeconds < 60) 
     374            return Integer.toString(wholeSeconds); 
     375        else if (wholeSeconds < 3600) 
     376            return String.format("%d:%02d", wholeSeconds / 60, wholeSeconds % 60); 
    270377        else 
    271             return getText(this.textMap); 
    272     } 
    273  
    274     /** 
    275      * Returns the Text which should be displayed, depending on chosen preference. 
    276      * The possible attributes are read from textMap. 
    277      * 
    278      * @param textMap A map with available texts/attributes 
    279      * @return Text 
    280      */ 
    281     private static String getText(Map<String,String> textMap) { 
    282         String text = ""; 
    283  
    284         if (textMap != null && !textMap.isEmpty()) { 
    285             switch(PROP_LABEL.get()) 
    286             { 
    287                 // name 
    288                 case 1: 
    289                 { 
    290                     if (textMap.containsKey("name")) { 
    291                         text = textMap.get("name"); 
    292                     } 
    293                     break; 
    294                 } 
    295  
    296                 // desc 
    297                 case 2: 
    298                 { 
    299                     if (textMap.containsKey("desc")) { 
    300                         text = textMap.get("desc"); 
    301                     } 
    302                     break; 
    303                 } 
    304  
    305                 // auto 
    306                 case 0: 
    307                 // both 
    308                 case 3: 
    309                 { 
    310                     if (textMap.containsKey("name")) { 
    311                         text = textMap.get("name"); 
    312  
    313                         if (textMap.containsKey("desc")) { 
    314                             if (PROP_LABEL.get() != 0 || !text.equals(textMap.get("desc"))) { 
    315                                 text += " - " + textMap.get("desc"); 
    316                             } 
    317                         } 
    318                     } 
    319                     else if (textMap.containsKey("desc")) { 
    320                         text = textMap.get("desc"); 
    321                     } 
    322                     break; 
    323                 } 
    324  
    325                 // none 
    326                 case 4: 
    327                 default: 
    328                 { 
    329                     text = ""; 
    330                     break; 
    331                 } 
    332             } 
    333         } 
    334  
    335         return text; 
     378            return String.format("%d:%02d:%02d", wholeSeconds / 3600, (wholeSeconds % 3600)/60, wholeSeconds % 60); 
     379    } 
     380 
     381    @Override 
     382    public Object getTemplateValue(String name) { 
     383        if (MARKER_FORMATTED_OFFSET.equals(name)) 
     384            return formatOffset(); 
     385        else if (MARKER_OFFSET.equals(name)) 
     386            return offset; 
     387        else if (dataProvider != null) 
     388            return dataProvider.getTemplateValue(name); 
     389        else 
     390            return null; 
     391    } 
     392 
     393    @Override 
     394    public boolean evaluateCondition(Match condition) { 
     395        throw new UnsupportedOperationException(); 
    336396    } 
    337397} 
  • trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java

    r4230 r4282  
    3232import org.openstreetmap.josm.data.coor.LatLon; 
    3333import org.openstreetmap.josm.data.gpx.GpxData; 
    34 import org.openstreetmap.josm.data.gpx.GpxLink; 
    3534import org.openstreetmap.josm.data.gpx.WayPoint; 
    3635import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; 
     
    7271        this.fromLayer = fromLayer; 
    7372        double firstTime = -1.0; 
    74         String lastLinkedFile = ""; 
    7573 
    7674        for (WayPoint wpt : indata.waypoints) { 
    77             /* calculate time differences in waypoints */ 
    7875            double time = wpt.time; 
    79             boolean wpt_has_link = wpt.attr.containsKey(GpxData.META_LINKS); 
    80             if (firstTime < 0 && wpt_has_link) { 
     76            if (firstTime < 0) { 
    8177                firstTime = time; 
    82                 for (GpxLink oneLink : (Collection<GpxLink>) wpt.attr.get(GpxData.META_LINKS)) { 
    83                     lastLinkedFile = oneLink.uri; 
    84                     break; 
    85                 } 
    86             } 
    87             if (wpt_has_link) { 
    88                 for (GpxLink oneLink : (Collection<GpxLink>) wpt.attr.get(GpxData.META_LINKS)) { 
    89                     if (!oneLink.uri.equals(lastLinkedFile)) { 
    90                         firstTime = time; 
    91                     } 
    92                     lastLinkedFile = oneLink.uri; 
    93                     break; 
    94                 } 
    9578            } 
    9679            Marker m = Marker.createMarker(wpt, indata.storageFile, this, time, time - firstTime); 
     
    274257                    tr("Error"), 
    275258                    JOptionPane.ERROR_MESSAGE 
    276             ); 
     259                    ); 
    277260            return null; 
    278261        } 
    279262 
    280263        // make our new marker 
    281         AudioMarker newAudioMarker = AudioMarker.create(coor, 
    282                 AudioMarker.inventName(offset), AudioPlayer.url().toString(), this, time, offset); 
     264        AudioMarker newAudioMarker = new AudioMarker(coor, 
     265                null, AudioPlayer.url(), this, time, offset); 
    283266 
    284267        // insert it at the right place in a copy the collection 
     
    425408                        tr("Warning"), 
    426409                        JOptionPane.WARNING_MESSAGE 
    427                 ); 
     410                        ); 
    428411                return; 
    429412            } 
     
    432415                JOptionPane.showMessageDialog( 
    433416                        Main.parent, 
    434                         tr("Audio synchronized at point {0}.", recent.text), 
     417                        tr("Audio synchronized at point {0}.", recent.getText()), 
    435418                        tr("Information"), 
    436419                        JOptionPane.INFORMATION_MESSAGE 
    437                 ); 
     420                        ); 
    438421            } else { 
    439422                JOptionPane.showMessageDialog( 
     
    442425                        tr("Error"), 
    443426                        JOptionPane.ERROR_MESSAGE 
    444                 ); 
     427                        ); 
    445428            } 
    446429        } 
     
    462445                        tr("Warning"), 
    463446                        JOptionPane.WARNING_MESSAGE 
    464                 ); 
     447                        ); 
    465448                return; 
    466449            } 
  • trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/PlayHeadMarker.java

    r2907 r4282  
    5959 
    6060    private PlayHeadMarker() { 
    61         super(new LatLon(0.0,0.0), "", 
     61        super(new LatLon(0.0,0.0), null, 
    6262                Main.pref.get("marker.audiotracericon", "audio-tracer"), 
    6363                null, -1.0, 0.0); 
     
    171171                    tr("Warning"), 
    172172                    JOptionPane.WARNING_MESSAGE 
    173             ); 
     173                    ); 
    174174            endDrag(true); 
    175175        } else { 
     
    226226                        tr("Warning"), 
    227227                        JOptionPane.WARNING_MESSAGE 
    228                 ); 
     228                        ); 
    229229                endDrag(true); 
    230230                return; 
     
    241241                    tr("Error"), 
    242242                    JOptionPane.ERROR_MESSAGE 
    243             ); 
     243                    ); 
    244244            endDrag(true); 
    245245        } 
     
    247247            JOptionPane.showMessageDialog( 
    248248                    Main.parent, 
    249                     tr("Audio synchronized at point {0}.", ca.text), 
     249                    tr("Audio synchronized at point {0}.", ca.getText()), 
    250250                    tr("Information"), 
    251251                    JOptionPane.INFORMATION_MESSAGE 
    252             ); 
     252                    ); 
    253253            setCoor(ca.getCoor()); 
    254254            endDrag(false); 
     
    259259                    tr("Error"), 
    260260                    JOptionPane.ERROR_MESSAGE 
    261             ); 
     261                    ); 
    262262            endDrag(true); 
    263263        } 
     
    294294            return; 
    295295        double audioTime = recentlyPlayedMarker.time + 
    296         AudioPlayer.position() - 
    297         recentlyPlayedMarker.offset - 
    298         recentlyPlayedMarker.syncOffset; 
     296                AudioPlayer.position() - 
     297                recentlyPlayedMarker.offset - 
     298                recentlyPlayedMarker.syncOffset; 
    299299        if (Math.abs(audioTime - time) < animationInterval) 
    300300            return; 
  • trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/WebMarker.java

    r2017 r4282  
    2121public class WebMarker extends ButtonMarker { 
    2222 
    23     public URL webUrl; 
     23    public final URL webUrl; 
    2424 
    25     public static WebMarker create (LatLon ll, String url, MarkerLayer parentLayer, double time, double offset) { 
    26         try { 
    27             return new WebMarker(ll, new URL(url), parentLayer, time, offset); 
    28         } catch (Exception ex) { 
    29             return null; 
    30         } 
    31     } 
    32  
    33     private WebMarker(LatLon ll, URL webUrl, MarkerLayer parentLayer, double time, double offset) { 
     25    public WebMarker(LatLon ll, URL webUrl, MarkerLayer parentLayer, double time, double offset) { 
    3426        super(ll, "web.png", parentLayer, time, offset); 
    3527        this.webUrl = webUrl; 
     
    4133            JOptionPane.showMessageDialog(Main.parent, 
    4234                    "<html><b>" + 
    43                     tr("There was an error while trying to display the URL for this marker") + 
    44                     "</b><br>" + tr("(URL was: ") + webUrl.toString() + ")" + "<br>" + error, 
    45                     tr("Error displaying URL"), JOptionPane.ERROR_MESSAGE); 
     35                            tr("There was an error while trying to display the URL for this marker") + 
     36                            "</b><br>" + tr("(URL was: ") + webUrl.toString() + ")" + "<br>" + error, 
     37                            tr("Error displaying URL"), JOptionPane.ERROR_MESSAGE); 
    4638        } 
    4739    } 
  • trunk/src/org/openstreetmap/josm/gui/preferences/AudioPreference.java

    r3719 r4282  
    6060 
    6161        // buttonLabels 
    62         markerButtonLabels.setSelected(Main.pref.getBoolean("marker.buttonlabels")); 
     62        markerButtonLabels.setSelected(Main.pref.getBoolean("marker.buttonlabels", true)); 
    6363        markerButtonLabels.setToolTipText(tr("Put text labels against audio (and image and web) markers as well as their button icons.")); 
    6464        gui.audio.add(markerButtonLabels, GBC.eol().insets(0,0,0,0)); 
  • trunk/src/org/openstreetmap/josm/gui/preferences/GPXSettingsPanel.java

    r4276 r4282  
    11package org.openstreetmap.josm.gui.preferences; 
    22 
    3 import javax.swing.AbstractButton; 
     3import static org.openstreetmap.josm.tools.I18n.tr; 
     4import static org.openstreetmap.josm.tools.I18n.trc; 
     5 
     6import java.awt.GridBagLayout; 
     7import java.awt.event.ActionEvent; 
     8import java.awt.event.ActionListener; 
     9 
     10import javax.swing.BorderFactory; 
    411import javax.swing.Box; 
    5 import javax.swing.event.ChangeEvent; 
    6 import javax.swing.event.ChangeListener; 
    7 import java.awt.event.ActionEvent; 
    8 import javax.swing.JLabel; 
    9 import javax.swing.BorderFactory; 
    10 import org.openstreetmap.josm.Main; 
    11 import org.openstreetmap.josm.tools.GBC; 
    12 import java.awt.GridBagLayout; 
    13 import java.awt.event.ActionListener; 
    1412import javax.swing.ButtonGroup; 
    1513import javax.swing.JCheckBox; 
    1614import javax.swing.JComboBox; 
     15import javax.swing.JLabel; 
    1716import javax.swing.JPanel; 
    1817import javax.swing.JRadioButton; 
    1918import javax.swing.JTextField; 
    20  
    21 import static org.openstreetmap.josm.tools.I18n.tr; 
    22 import static org.openstreetmap.josm.tools.I18n.trc; 
     19import javax.swing.event.ChangeEvent; 
     20import javax.swing.event.ChangeListener; 
     21 
     22import org.openstreetmap.josm.Main; 
     23import org.openstreetmap.josm.gui.layer.markerlayer.Marker; 
     24import org.openstreetmap.josm.gui.layer.markerlayer.Marker.TemplateEntryProperty; 
     25import org.openstreetmap.josm.tools.GBC; 
    2326 
    2427public class GPXSettingsPanel extends JPanel { 
     28 
     29    private static final int WAYPOINT_LABEL_CUSTOM = 6; 
     30    private static final String[] LABEL_PATTERN_TEMPLATE = new String[] {Marker.LABEL_PATTERN_AUTO, Marker.LABEL_PATTERN_NAME, 
     31        Marker.LABEL_PATTERN_DESC, "{*}", "?{ '{name}' | '{desc}' | '{formattedWaypointOffset}' }", ""}; 
     32    private static final String[] LABEL_PATTERN_DESC = new String[] {tr("Auto"), /* gpx data field name */ trc("gpx_field", "Name"), 
     33        /* gpx data field name */ trc("gpx_field", "Desc(ription)"), tr("Everything"), tr("Name or offset"), tr("None"), tr("Custom")}; 
     34 
     35 
    2536    private JRadioButton drawRawGpsLinesGlobal = new JRadioButton(tr("Use global settings.")); 
    2637    private JRadioButton drawRawGpsLinesAll = new JRadioButton(tr("All")); 
     
    4657    private JTextField drawGpsArrowsMinDist = new JTextField(8); 
    4758    private JCheckBox colorDynamic = new JCheckBox(tr("Dynamic color range based on data limits")); 
    48     private JComboBox waypointLabel = new JComboBox(new String[] {tr("Auto"), /* gpx data field name */ trc("gpx_field", "Name"), 
    49             /* gpx data field name */ trc("gpx_field", "Desc(ription)"), tr("Both"), tr("None")}); 
     59    private JComboBox waypointLabel = new JComboBox(LABEL_PATTERN_DESC); 
     60    private JTextField waypointLabelPattern = new JTextField(); 
     61    private JComboBox audioWaypointLabel = new JComboBox(LABEL_PATTERN_DESC); 
     62    private JTextField audioWaypointLabelPattern = new JTextField(); 
     63 
    5064    private String layerName; 
    51     private boolean local; // flag to display LocalOnly checkbox  
    52     private boolean nonlocal; // flag to display AllLines checkbox  
     65    private boolean local; // flag to display LocalOnly checkbox 
     66    private boolean nonlocal; // flag to display AllLines checkbox 
    5367 
    5468    public GPXSettingsPanel(String layerName, boolean local, boolean nonlocal) { 
     
    7690        // drawRawGpsLines 
    7791        ButtonGroup gpsLinesGroup = new ButtonGroup(); 
    78         if (layerName!=null) gpsLinesGroup.add(drawRawGpsLinesGlobal); 
     92        if (layerName!=null) { 
     93            gpsLinesGroup.add(drawRawGpsLinesGlobal); 
     94        } 
    7995        gpsLinesGroup.add(drawRawGpsLinesNone); 
    8096        gpsLinesGroup.add(drawRawGpsLinesLocal); 
     
    84100 
    85101        add(new JLabel(tr("Draw lines between raw GPS points")), GBC.eol().insets(20,0,0,0)); 
    86         if (layerName!=null) add(drawRawGpsLinesGlobal, GBC.eol().insets(40,0,0,0)); 
     102        if (layerName!=null) { 
     103            add(drawRawGpsLinesGlobal, GBC.eol().insets(40,0,0,0)); 
     104        } 
    87105        add(drawRawGpsLinesNone, GBC.eol().insets(40,0,0,0)); 
    88         if (layerName==null || local) add(drawRawGpsLinesLocal, GBC.eol().insets(40,0,0,0));  
    89         if (layerName==null || nonlocal) add(drawRawGpsLinesAll, GBC.eol().insets(40,0,0,0));  
     106        if (layerName==null || local) { 
     107            add(drawRawGpsLinesLocal, GBC.eol().insets(40,0,0,0)); 
     108        } 
     109        if (layerName==null || nonlocal) { 
     110            add(drawRawGpsLinesAll, GBC.eol().insets(40,0,0,0)); 
     111        } 
    90112 
    91113        drawRawGpsLinesActionListener = new ActionListener(){ 
     
    149171        // colorTracks 
    150172        colorGroup = new ButtonGroup(); 
    151         if (layerName!=null) colorGroup.add(colorTypeGlobal); 
     173        if (layerName!=null) { 
     174            colorGroup.add(colorTypeGlobal); 
     175        } 
    152176        colorGroup.add(colorTypeNone); 
    153177        colorGroup.add(colorTypeVelocity); 
     
    180204 
    181205        add(new JLabel(tr("Track and Point Coloring")), GBC.eol().insets(20,0,0,0)); 
    182         if (layerName!=null) add(colorTypeGlobal, GBC.eol().insets(40,0,0,0)); 
     206        if (layerName!=null) { 
     207            add(colorTypeGlobal, GBC.eol().insets(40,0,0,0)); 
     208        } 
    183209        add(colorTypeNone, GBC.eol().insets(40,0,0,0)); 
    184210        add(colorTypeVelocity, GBC.std().insets(40,0,0,0)); 
     
    191217        add(colorDynamic, GBC.eop().insets(40,0,0,0)); 
    192218 
    193         // waypointLabel 
    194         add(Box.createVerticalGlue(), GBC.eol().insets(0, 20, 0, 0)); 
    195         add(new JLabel(tr("Waypoint labelling")), GBC.std().insets(20,0,0,0)); 
    196         if(layerName!= null) 
    197             waypointLabel.addItem(tr("Global settings")); 
    198         add(waypointLabel, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5)); 
     219        if (layerName == null) { 
     220            // Setting waypoints for gpx layer doesn't make sense - waypoints are shown in marker layer that has different name - so show 
     221            // this only for global config 
     222 
     223            // waypointLabel 
     224            add(new JLabel(tr("Waypoint labelling")), GBC.std().insets(20,0,0,0)); 
     225            add(waypointLabel, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5)); 
     226            waypointLabel.addActionListener(new ActionListener() { 
     227                @Override 
     228                public void actionPerformed(ActionEvent e) { 
     229                    updateWaypointPattern(waypointLabel, waypointLabelPattern); 
     230                } 
     231            }); 
     232            updateWaypointLabelCombobox(waypointLabel, waypointLabelPattern, TemplateEntryProperty.forMarker(layerName)); 
     233            add(waypointLabelPattern, GBC.eol().fill(GBC.HORIZONTAL).insets(20,0,0,5)); 
     234 
     235            // audioWaypointLabel 
     236            add(Box.createVerticalGlue(), GBC.eol().insets(0, 20, 0, 0)); 
     237 
     238            add(new JLabel(tr("Audio waypoint labelling")), GBC.std().insets(20,0,0,0)); 
     239            add(audioWaypointLabel, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5)); 
     240            audioWaypointLabel.addActionListener(new ActionListener() { 
     241                @Override 
     242                public void actionPerformed(ActionEvent e) { 
     243                    updateWaypointPattern(audioWaypointLabel, audioWaypointLabelPattern); 
     244                } 
     245            }); 
     246            updateWaypointLabelCombobox(audioWaypointLabel, audioWaypointLabelPattern, TemplateEntryProperty.forAudioMarker(layerName)); 
     247            add(audioWaypointLabelPattern, GBC.eol().fill(GBC.HORIZONTAL).insets(20,0,0,5)); 
     248        } 
     249 
    199250        add(Box.createVerticalGlue(), GBC.eol().fill(GBC.BOTH)); 
    200251    } 
     
    235286            colorDynamic.setEnabled(false); 
    236287        } else { 
    237          switch(Main.pref.getInteger("draw.rawgps.colors",layerName, 0)) { 
     288            switch(Main.pref.getInteger("draw.rawgps.colors",layerName, 0)) { 
    238289            case 0: colorTypeNone.setSelected(true);   break; 
    239290            case 1: colorTypeVelocity.setSelected(true);  break; 
     
    248299            colorDynamic.setEnabled(colorTypeVelocity.isSelected() || colorTypeDilution.isSelected()); 
    249300        } 
    250         if(layerName != null) 
    251           waypointLabel.setSelectedIndex(Main.pref.getInteger("draw.rawgps.layer.wpt."+layerName, 5)); 
    252         else 
    253           waypointLabel.setSelectedIndex(Main.pref.getInteger("draw.rawgps.layer.wpt", 0)); 
    254301    } 
    255302 
     
    261308    public boolean savePreferences (String layerName, boolean locLayer) { 
    262309        String layerNameDot = ".layer "+layerName; 
    263         if (layerName==null) layerNameDot=""; 
     310        if (layerName==null) { 
     311            layerNameDot=""; 
     312        } 
    264313        Main.pref.put("marker.makeautomarkers"+layerNameDot, makeAutoMarkers.isSelected()); 
    265314        if (drawRawGpsLinesGlobal.isSelected()) { 
     
    289338        Main.pref.put("draw.rawgps.hdopcircle"+layerNameDot, hdopCircleGpsPoints.isSelected()); 
    290339        Main.pref.put("draw.rawgps.large"+layerNameDot, largeGpsPoints.isSelected()); 
    291         if (waypointLabel.getSelectedIndex()==5) Main.pref.put("draw.rawgps.layer.wpt"+layerNameDot,null); 
    292         else Main.pref.putInteger("draw.rawgps.layer.wpt"+layerNameDot, waypointLabel.getSelectedIndex()); 
     340 
     341        TemplateEntryProperty.forMarker(layerName).put(waypointLabelPattern.getText()); 
     342        TemplateEntryProperty.forAudioMarker(layerName).put(audioWaypointLabelPattern.getText()); 
    293343 
    294344        if(colorTypeGlobal.isSelected()) { 
     
    320370        savePreferences(null, false); 
    321371    } 
     372 
     373    private void updateWaypointLabelCombobox(JComboBox cb, JTextField tf, TemplateEntryProperty property) { 
     374        String labelPattern = property.getAsString(); 
     375        boolean found = false; 
     376        for (int i=0; i<LABEL_PATTERN_TEMPLATE.length; i++) { 
     377            if (LABEL_PATTERN_TEMPLATE[i].equals(labelPattern)) { 
     378                cb.setSelectedIndex(i); 
     379                found = true; 
     380                break; 
     381            } 
     382        } 
     383        if (!found) { 
     384            cb.setSelectedIndex(WAYPOINT_LABEL_CUSTOM); 
     385            tf.setEnabled(true); 
     386            tf.setText(labelPattern); 
     387        } 
     388    } 
     389 
     390    private void updateWaypointPattern(JComboBox cb, JTextField tf) { 
     391        if (cb.getSelectedIndex() == WAYPOINT_LABEL_CUSTOM) { 
     392            tf.setEnabled(true); 
     393        } else { 
     394            tf.setEnabled(false); 
     395            tf.setText(LABEL_PATTERN_TEMPLATE[cb.getSelectedIndex()]); 
     396        } 
     397    } 
     398 
    322399} 
Note: See TracChangeset for help on using the changeset viewer.