Changeset 5717 in josm for trunk/src


Ignore:
Timestamp:
2013-02-14T13:26:03+01:00 (11 years ago)
Author:
akks
Message:

see #8416: allow to filter gpx traces by age (layer context menu, filter dialog)

Location:
trunk/src/org/openstreetmap/josm/gui/layer
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java

    r5715 r5717  
    1717import java.text.DateFormat;
    1818import java.util.ArrayList;
     19import java.util.Date;
    1920import java.util.LinkedList;
    2021import java.util.List;
     
    9192
    9293    /**
    93      * returns a human readable string that shows the timespan of the given track
     94     * returns minimum and maximum timestamps in the track
    9495     */
    95     public static String getTimespanForTrack(GpxTrack trk) {
     96    public static Date[] getMinMaxTimeForTrack(GpxTrack trk) {
    9697        WayPoint earliest = null, latest = null;
    9798
     
    109110            }
    110111        }
    111 
     112        if (earliest==null || latest==null) return null;
     113        return new Date[]{earliest.getTime(), latest.getTime()};
     114    }
     115   
     116    /**
     117    * returns minimum and maximum timestamps for all tracks
     118    */
     119    public Date[] getMinMaxTimeForAllTracks() {
     120        double min=Double.MIN_VALUE, max=Double.MAX_VALUE, t;
     121        for (GpxTrack trk: data.tracks) {
     122            for (GpxTrackSegment seg : trk.getSegments()) {
     123                for (WayPoint pnt : seg.getWayPoints()) {
     124                    t = pnt.time;
     125                    if (t!=0) {
     126                        if (t>max) max=t;
     127                        if (t<min) min=t;
     128                    }
     129                }
     130            }
     131        }
     132        if (min==Double.MIN_VALUE || max==Double.MAX_VALUE) return null;
     133        return new Date[]{new Date((long) (min * 1000)), new Date((long) (max * 1000)), };
     134    }
     135   
     136   
     137    /**
     138     * returns a human readable string that shows the timespan of the given track
     139     */
     140    public static String getTimespanForTrack(GpxTrack trk) {
     141        Date[] bounds = getMinMaxTimeForTrack(trk);
    112142        String ts = "";
    113 
    114         if (earliest != null && latest != null) {
     143        if (bounds != null) {
    115144            DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
    116             String earliestDate = df.format(earliest.getTime());
    117             String latestDate = df.format(latest.getTime());
     145            String earliestDate = df.format(bounds[0]);
     146            String latestDate = df.format(bounds[1]);
    118147
    119148            if (earliestDate.equals(latestDate)) {
    120149                DateFormat tf = DateFormat.getTimeInstance(DateFormat.SHORT);
    121150                ts += earliestDate + " ";
    122                 ts += tf.format(earliest.getTime()) + " - " + tf.format(latest.getTime());
     151                ts += tf.format(bounds[0]) + " - " + tf.format(bounds[1]);
    123152            } else {
    124153                DateFormat dtf = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
    125                 ts += dtf.format(earliest.getTime()) + " - " + dtf.format(latest.getTime());
    126             }
    127 
    128             int diff = (int) (latest.time - earliest.time);
     154                ts += dtf.format(bounds[0]) + " - " + dtf.format(bounds[1]);
     155            }
     156
     157            int diff = (int) (bounds[1].getTime() - bounds[0].getTime());
    129158            ts += String.format(" (%d:%02d)", diff / 3600, (diff % 3600) / 60);
    130159        }
     
    300329        else
    301330            return true;
     331    }
     332   
     333    public void filterTracksByDate(Date fromDate, Date toDate, boolean showWithoutDate) {
     334        int i = 0;
     335        long from = fromDate.getTime();
     336        long to = toDate.getTime();
     337        for (GpxTrack trk : data.tracks) {
     338            Date[] t = GpxLayer.getMinMaxTimeForTrack(trk);
     339           
     340            if (t==null) continue;
     341            long tm = t[1].getTime();
     342            trackVisibility[i]= (tm==0 && showWithoutDate) || (from<=tm && tm <= to);
     343            i++;
     344        }
    302345    }
    303346
     
    839882        return SaveActionBase.createAndOpenSaveFileChooser(tr("Save GPX file"), GpxImporter.FILE_FILTER);
    840883    }
     884   
    841885}
  • trunk/src/org/openstreetmap/josm/gui/layer/gpx/ChooseTrackVisibilityAction.java

    r5715 r5717  
    99import java.awt.event.MouseEvent;
    1010import java.awt.event.MouseListener;
     11import java.text.DateFormat;
     12import java.text.SimpleDateFormat;
     13import java.util.Date;
     14import java.util.GregorianCalendar;
    1115import java.util.Map;
    1216import javax.swing.AbstractAction;
     17import javax.swing.JButton;
     18import javax.swing.JCheckBox;
    1319import javax.swing.JComponent;
    1420import javax.swing.JLabel;
    1521import javax.swing.JPanel;
    1622import javax.swing.JScrollPane;
     23import javax.swing.JSlider;
     24import javax.swing.JSpinner;
    1725import javax.swing.JTable;
    1826import javax.swing.ListSelectionModel;
     27import javax.swing.SpinnerDateModel;
     28import javax.swing.event.ChangeEvent;
     29import javax.swing.event.ChangeListener;
    1930import javax.swing.event.ListSelectionEvent;
    2031import javax.swing.event.ListSelectionListener;
     
    3849public class ChooseTrackVisibilityAction extends AbstractAction {
    3950    private final GpxLayer layer;
     51 
     52    JTable table;
     53    JDateWithSlider dateFrom = new JDateWithSlider(tr("From"));
     54    JDateWithSlider dateTo = new JDateWithSlider(tr("To"));
     55    JCheckBox checkBox  = new JCheckBox(tr("No timestamp"));
     56    private boolean showNoTimestamp;
    4057   
    4158    public ChooseTrackVisibilityAction(final GpxLayer layer) {
     
    114131        return t;
    115132    }
    116 
     133   
     134    boolean noUpdates=false;
     135   
     136    private void filterTracksByDate() {
     137        layer.filterTracksByDate(dateFrom.getDate(), dateTo.getDate(), checkBox.isSelected());
     138    }
     139   
    117140    /** selects all rows (=tracks) in the table that are currently visible */
    118     private void selectVisibleTracksInTable(JTable table) {
     141    private void selectVisibleTracksInTable() {
    119142        // don't select any tracks if the layer is not visible
    120143        if (!layer.isVisible()) {
     
    131154
    132155    /** listens to selection changes in the table and redraws the map */
    133     private void listenToSelectionChanges(JTable table) {
     156    private void listenToSelectionChanges() {
    134157        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
    135158            @Override
     
    138161                    return;
    139162                }
    140                 ListSelectionModel s = (ListSelectionModel) e.getSource();
    141                 for (int i = 0; i < layer.trackVisibility.length; i++) {
    142                     layer.trackVisibility[i] = s.isSelectedIndex(i);
    143                 }
    144                 Main.map.mapView.preferenceChanged(null);
    145                 Main.map.repaint(100);
     163                if (!noUpdates) updateVisibilityFromTable();
    146164            }
    147165        });
    148166    }
    149 
     167   
     168    private void updateVisibilityFromTable() {
     169        ListSelectionModel s = (ListSelectionModel) table.getSelectionModel();
     170        for (int i = 0; i < layer.trackVisibility.length; i++) {
     171            layer.trackVisibility[i] = s.isSelectedIndex(i);
     172            System.out.printf("changed %d:=%s", i, ""+layer.trackVisibility[i]);
     173        }
     174        Main.map.mapView.preferenceChanged(null);
     175        Main.map.repaint(100);
     176    }
     177   
     178    private static final String PREF_DATE0 = "gpx.traces.showzerotimestamp";
     179    private static final String PREF_DATE1 = "gpx.traces.mintime";
     180    private static final String PREF_DATE2 = "gpx.traces.maxtime";
     181   
    150182    @Override
    151183    public void actionPerformed(ActionEvent arg0) {
    152184        final JPanel msg = new JPanel(new GridBagLayout());
     185       
     186        final Date startTime, endTime;
     187        Date[] bounds = layer.getMinMaxTimeForAllTracks();
     188       
     189        startTime = (bounds==null) ? new GregorianCalendar(2000, 1, 1).getTime():bounds[0];
     190        endTime = (bounds==null) ? new Date() : bounds[2];
     191
     192        long d1 = Main.pref.getLong(PREF_DATE1, 0);
     193        if (d1==0) d1=new GregorianCalendar(2000, 1, 1).getTime().getTime();
     194        long d2 = Main.pref.getLong(PREF_DATE2, 0);
     195        if (d2==0) d2=System.currentTimeMillis();
     196       
     197        dateFrom.setValue(new Date(d1));
     198        dateTo.setValue(new Date(d2));
     199        dateFrom.setRange(startTime, endTime);
     200        dateTo.setRange(startTime, endTime);
     201        checkBox.setSelected(Main.pref.getBoolean(PREF_DATE0, true));
     202       
     203        JButton selectDate = new JButton();
     204        msg.add(selectDate, GBC.std().grid(1,1).insets(0, 0, 20, 0));
     205        msg.add(checkBox, GBC.std().grid(2,1).insets(0, 0, 20, 0));
     206        msg.add(dateFrom, GBC.std().grid(3,1).fill(GBC.HORIZONTAL));
     207        msg.add(dateTo, GBC.eol().grid(4,1).fill(GBC.HORIZONTAL));
    153208        msg.add(new JLabel(tr("<html>Select all tracks that you want to be displayed. You can drag select a " + "range of tracks or use CTRL+Click to select specific ones. The map is updated live in the " + "background. Open the URLs by double clicking them.</html>")), GBC.eol().fill(GBC.HORIZONTAL));
    154209        // build table
    155210        final boolean[] trackVisibilityBackup = layer.trackVisibility.clone();
    156211        final String[] headers = {tr("Name"), tr("Description"), tr("Timespan"), tr("Length"), tr("URL")};
    157         final JTable table = buildTable(headers, buildTableContents());
    158         selectVisibleTracksInTable(table);
    159         listenToSelectionChanges(table);
     212        table = buildTable(headers, buildTableContents());
     213        selectVisibleTracksInTable();
     214        listenToSelectionChanges();
    160215        // make the table scrollable
    161216        JScrollPane scrollPane = new JScrollPane(table);
    162217        msg.add(scrollPane, GBC.eol().fill(GBC.BOTH));
     218       
     219        selectDate.setAction(new AbstractAction(tr("Select by date")) {
     220            @Override
     221            public void actionPerformed(ActionEvent e) {
     222                Main.pref.putLong(PREF_DATE1, dateFrom.getDate().getTime());
     223                Main.pref.putLong(PREF_DATE2, dateTo.getDate().getTime());
     224                Main.pref.put(PREF_DATE0, checkBox.isSelected());
     225                noUpdates = true;
     226                filterTracksByDate();
     227                selectVisibleTracksInTable();
     228                noUpdates = false;
     229                updateVisibilityFromTable();
     230            }
     231        });
     232       
    163233        // build dialog
    164234        ExtendedDialog ed = new ExtendedDialog(Main.parent, tr("Set track visibility for {0}", layer.getName()), new String[]{tr("Show all"), tr("Show selected only"), tr("Cancel")});
     
    191261    }
    192262   
     263   
     264    public static class JDateWithSlider extends JPanel {
     265        private JSpinner spinner;
     266        private JSlider slider;
     267        private Date dateMin;
     268        private Date dateMax;
     269        private static final int MAX_SLIDER=300;
     270
     271        public JDateWithSlider(String msg) {
     272            super(new GridBagLayout());
     273            spinner = new JSpinner( new SpinnerDateModel() );
     274            String pattern = ((SimpleDateFormat)DateFormat.getDateInstance()).toPattern();
     275            JSpinner.DateEditor timeEditor = new JSpinner.DateEditor(spinner,pattern);
     276            spinner.setEditor(timeEditor);
     277            slider = new JSlider(0,MAX_SLIDER);
     278            slider.addChangeListener(new ChangeListener() {
     279                public void stateChanged(ChangeEvent e) {
     280                    spinner.setValue(dateFromInt(slider.getValue()));
     281                }
     282            });
     283            add(new JLabel(msg),GBC.std());
     284            add(spinner,GBC.std().insets(10,0,0,0));
     285            add(slider,GBC.eol().insets(10,0,0,0).fill(GBC.HORIZONTAL));
     286           
     287            dateMin = new Date(0); dateMax =new Date();
     288        }
     289
     290        private Date dateFromInt(int value) {
     291            double k = 1.0*value/MAX_SLIDER;
     292            return new Date((long)(dateMax.getTime()*k+ dateMin.getTime()*(1-k)));
     293        }
     294        private int intFromDate(Date date) {
     295            return (int)(300.0*(date.getTime()-dateMin.getTime()) /
     296                    (dateMax.getTime()-dateMin.getTime()));
     297        }
     298
     299        private void setRange(Date dateMin, Date dateMax) {
     300            this.dateMin = dateMin;
     301            this.dateMax = dateMax;
     302        }
     303       
     304        private void setValue(Date date) {
     305            spinner.setValue(date);
     306        }
     307
     308        private Date getDate() {
     309            return (Date) spinner.getValue();
     310        }
     311    }
     312   
    193313}
Note: See TracChangeset for help on using the changeset viewer.