Index: trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 5813)
+++ trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 5815)
@@ -115,13 +115,17 @@
     
     /**
-    * returns minimum and maximum timestamps for all tracks
+    * Returns minimum and maximum timestamps for all tracks
+    * Warning: there are lot of track with broken timestamps,
+    * so we just ingore points from future and from year before 1970 in this method
+    * works correctly @since 5815
     */
     public Date[] getMinMaxTimeForAllTracks() {
-        double min=Double.MIN_VALUE, max=Double.MAX_VALUE, t;
+        double min=1e100, max=-1e100, t;
+        double now = new Date().getTime()/1000.0;
         for (GpxTrack trk: data.tracks) {
             for (GpxTrackSegment seg : trk.getSegments()) {
                 for (WayPoint pnt : seg.getWayPoints()) {
                     t = pnt.time;
-                    if (t!=0) {
+                    if (t>0 && t<=now) {
                         if (t>max) max=t;
                         if (t<min) min=t;
@@ -130,5 +134,6 @@
             }
         }
-        if (min==Double.MIN_VALUE || max==Double.MAX_VALUE) return null;
+        //System.out.println("scanning "+data.tracks.size()+" tracks, found min,max"+min+"--"+max);
+        if (min==1e100 || max==-1e100) return null;
         return new Date[]{new Date((long) (min * 1000)), new Date((long) (max * 1000)), };
     }
@@ -528,23 +533,15 @@
                 oldWp = null;
             }
+            double now = new Date().getTime()/1000.0;
             if (colored == colorModes.time) {
-                for (GpxTrack trk : data.tracks) {
-                    for (GpxTrackSegment segment : trk.getSegments()) {
-                        for (WayPoint trkPnt : segment.getWayPoints()) {
-                            double t=trkPnt.time;
-                            if (t==0) {
-                                continue; // skip non-dated trackpoints
-                            }
-                            if(t > maxval) {
-                                maxval = t;
-                            }
-                            if(t < minval) {
-                                minval = t;
-                            }
-                        }
-                    }
-                }
-            }
-
+                Date bounds[] = getMinMaxTimeForAllTracks();
+                if (bounds!=null) {
+                    minval = bounds[0].getTime()/1000.0;
+                    maxval = bounds[1].getTime()/1000.0;
+                } else {
+                    minval = 0; maxval=now;
+                }
+            }
+            
             for (GpxTrack trk : data.tracks) {
                 for (GpxTrackSegment segment : trk.getSegments()) {
@@ -592,6 +589,7 @@
                                 break;
                             case time:
-                                if (trkPnt.time>0){
-                                    int tColor = (int) Math.round((trkPnt.time-minval)*255/(maxval-minval));
+                                double t=trkPnt.time;
+                                if (t>0 && t<=now){ // skip bad timestamps
+                                    int tColor = (int) Math.round((t-minval)*255/(maxval-minval));
                                     trkPnt.customColoring = colors[tColor];
                                 } else {
Index: trunk/src/org/openstreetmap/josm/gui/layer/gpx/ChooseTrackVisibilityAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/gpx/ChooseTrackVisibilityAction.java	(revision 5813)
+++ trunk/src/org/openstreetmap/josm/gui/layer/gpx/ChooseTrackVisibilityAction.java	(revision 5815)
@@ -6,26 +6,17 @@
 import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.GregorianCalendar;
 import java.util.Map;
 import javax.swing.AbstractAction;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
 import javax.swing.JComponent;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
-import javax.swing.JSlider;
-import javax.swing.JSpinner;
 import javax.swing.JTable;
+import javax.swing.JToggleButton;
 import javax.swing.ListSelectionModel;
-import javax.swing.SpinnerDateModel;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
@@ -50,9 +41,6 @@
     private final GpxLayer layer;
  
+    DateFilterPanel dateFilter;
     JTable table;
-    JDateWithSlider dateFrom = new JDateWithSlider(tr("From"));
-    JDateWithSlider dateTo = new JDateWithSlider(tr("To"));
-    JCheckBox checkBox  = new JCheckBox(tr("No timestamp"));
-    private boolean showNoTimestamp;
     
     public ChooseTrackVisibilityAction(final GpxLayer layer) {
@@ -84,5 +72,6 @@
      * Builds an non-editable table whose 5th column will open a browser when double clicked.
      * The table will fill its parent. */
-    private JTable buildTable(String[] headers, Object[][] content) {
+    private JTable buildTable(Object[][] content) {
+        final String[] headers = {tr("Name"), tr("Description"), tr("Timespan"), tr("Length"), tr("URL")};
         final JTable t = new JTable(content, headers) {
             @Override
@@ -127,4 +116,5 @@
             }
         };
+        t.setAutoCreateRowSorter(true);
         t.addMouseListener(urlOpener);
         t.setFillsViewportHeight(true);
@@ -134,9 +124,5 @@
     boolean noUpdates=false;
     
-    private void filterTracksByDate() {
-        layer.filterTracksByDate(dateFrom.getDate(), dateTo.getDate(), checkBox.isSelected());
-    }
-    
-    /** selects all rows (=tracks) in the table that are currently visible */
+    /** selects all rows (=tracks) in the table that are currently visible on the layer*/
     private void selectVisibleTracksInTable() {
         // don't select any tracks if the layer is not visible
@@ -158,8 +144,8 @@
             @Override
             public void valueChanged(ListSelectionEvent e) {
-                if (!(e.getSource() instanceof ListSelectionModel)) {
-                    return;
-                }
-                if (!noUpdates) updateVisibilityFromTable();
+                if (noUpdates || !(e.getSource() instanceof ListSelectionModel)) {
+                    return;
+                }
+                updateVisibilityFromTable();
             }
         });
@@ -169,14 +155,9 @@
         ListSelectionModel s = (ListSelectionModel) table.getSelectionModel();
         for (int i = 0; i < layer.trackVisibility.length; i++) {
-            layer.trackVisibility[i] = s.isSelectedIndex(i);
-            System.out.printf("changed %d:=%s", i, ""+layer.trackVisibility[i]);
+            layer.trackVisibility[table.convertRowIndexToModel(i)] = s.isSelectedIndex(i);
         }
         Main.map.mapView.preferenceChanged(null);
         Main.map.repaint(100);
     }
-    
-    private static final String PREF_DATE0 = "gpx.traces.showzerotimestamp";
-    private static final String PREF_DATE1 = "gpx.traces.mintime";
-    private static final String PREF_DATE2 = "gpx.traces.maxtime";
     
     @Override
@@ -184,31 +165,34 @@
         final JPanel msg = new JPanel(new GridBagLayout());
         
-        final Date startTime, endTime;
-        Date[] bounds = layer.getMinMaxTimeForAllTracks();
+        dateFilter = new DateFilterPanel(layer, "gpx.traces", false);
+        dateFilter.setFilterAppliedListener(new ActionListener(){
+            @Override public void actionPerformed(ActionEvent e) {
+                noUpdates = true;
+                selectVisibleTracksInTable();
+                noUpdates = false;
+                Main.map.mapView.preferenceChanged(null);
+                Main.map.repaint(100);
+            }
+        });
+        dateFilter.loadFromPrefs();
         
-        startTime = (bounds==null) ? new GregorianCalendar(2000, 1, 1).getTime():bounds[0];
-        endTime = (bounds==null) ? new Date() : bounds[2];
-
-        long d1 = Main.pref.getLong(PREF_DATE1, 0);
-        if (d1==0) d1=new GregorianCalendar(2000, 1, 1).getTime().getTime();
-        long d2 = Main.pref.getLong(PREF_DATE2, 0);
-        if (d2==0) d2=System.currentTimeMillis();
+        final JToggleButton b = new JToggleButton(new AbstractAction(tr("Select by date")) {
+            @Override public void actionPerformed(ActionEvent e) {
+                if (((JToggleButton) e.getSource()).isSelected()) {
+                    dateFilter.setEnabled(true);
+                    dateFilter.applyFilter();
+                } else {
+                    dateFilter.setEnabled(false);
+                }
+            }
+        });
+        dateFilter.setEnabled(false);
+        msg.add(b, GBC.std().insets(0,0,5,0));
+        msg.add(dateFilter, GBC.eol().insets(0,0,10,0).fill(GBC.HORIZONTAL));
         
-        dateFrom.setValue(new Date(d1)); 
-        dateTo.setValue(new Date(d2)); 
-        dateFrom.setRange(startTime, endTime); 
-        dateTo.setRange(startTime, endTime); 
-        checkBox.setSelected(Main.pref.getBoolean(PREF_DATE0, true));
-        
-        JButton selectDate = new JButton();
-        msg.add(selectDate, GBC.std().grid(1,1).insets(0, 0, 20, 0));
-        msg.add(checkBox, GBC.std().grid(2,1).insets(0, 0, 20, 0));
-        msg.add(dateFrom, GBC.std().grid(3,1).fill(GBC.HORIZONTAL));
-        msg.add(dateTo, GBC.eol().grid(4,1).fill(GBC.HORIZONTAL));
-        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));
+        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.eop().fill(GBC.HORIZONTAL));
         // build table
         final boolean[] trackVisibilityBackup = layer.trackVisibility.clone();
-        final String[] headers = {tr("Name"), tr("Description"), tr("Timespan"), tr("Length"), tr("URL")};
-        table = buildTable(headers, buildTableContents());
+        table = buildTable(buildTableContents());
         selectVisibleTracksInTable();
         listenToSelectionChanges();
@@ -216,19 +200,5 @@
         JScrollPane scrollPane = new JScrollPane(table);
         msg.add(scrollPane, GBC.eol().fill(GBC.BOTH));
-        
-        selectDate.setAction(new AbstractAction(tr("Select by date")) {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                Main.pref.putLong(PREF_DATE1, dateFrom.getDate().getTime());
-                Main.pref.putLong(PREF_DATE2, dateTo.getDate().getTime());
-                Main.pref.put(PREF_DATE0, checkBox.isSelected());
-                noUpdates = true;
-                filterTracksByDate();
-                selectVisibleTracksInTable();
-                noUpdates = false;
-                updateVisibilityFromTable();
-            }
-        });
-        
+
         // build dialog
         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")});
@@ -240,4 +210,5 @@
         ed.setRememberWindowGeometry(getClass().getName() + ".geometry", WindowGeometry.centerInWindow(Main.parent, new Dimension(1000, 500)));
         ed.showDialog();
+        dateFilter.saveInPrefs();
         int v = ed.getValue();
         // cancel for unknown buttons and copy back original settings
@@ -254,60 +225,12 @@
         final boolean all = v == 1 || s.isSelectionEmpty();
         for (int i = 0; i < layer.trackVisibility.length; i++) {
-            layer.trackVisibility[i] = all || s.isSelectedIndex(i);
+            layer.trackVisibility[table.convertRowIndexToModel(i)] = all || s.isSelectedIndex(i);
         }
         // ...sync with layer visibility instead to avoid having two ways to hide everything
         layer.setVisible(v == 1 || !s.isSelectionEmpty());
+
+        Main.map.mapView.preferenceChanged(null);
         Main.map.repaint();
     }
     
-    
-    public static class JDateWithSlider extends JPanel {
-        private JSpinner spinner;
-        private JSlider slider;
-        private Date dateMin;
-        private Date dateMax;
-        private static final int MAX_SLIDER=300;
-
-        public JDateWithSlider(String msg) {
-            super(new GridBagLayout());
-            spinner = new JSpinner( new SpinnerDateModel() );
-            String pattern = ((SimpleDateFormat)DateFormat.getDateInstance()).toPattern();
-            JSpinner.DateEditor timeEditor = new JSpinner.DateEditor(spinner,pattern);
-            spinner.setEditor(timeEditor);
-            slider = new JSlider(0,MAX_SLIDER);
-            slider.addChangeListener(new ChangeListener() {
-                public void stateChanged(ChangeEvent e) {
-                    spinner.setValue(dateFromInt(slider.getValue()));
-                }
-            });
-            add(new JLabel(msg),GBC.std());
-            add(spinner,GBC.std().insets(10,0,0,0));
-            add(slider,GBC.eol().insets(10,0,0,0).fill(GBC.HORIZONTAL));
-            
-            dateMin = new Date(0); dateMax =new Date();
-        }
-
-        private Date dateFromInt(int value) {
-            double k = 1.0*value/MAX_SLIDER;
-            return new Date((long)(dateMax.getTime()*k+ dateMin.getTime()*(1-k)));
-        }
-        private int intFromDate(Date date) {
-            return (int)(300.0*(date.getTime()-dateMin.getTime()) /
-                    (dateMax.getTime()-dateMin.getTime()));
-        }
-
-        private void setRange(Date dateMin, Date dateMax) {
-            this.dateMin = dateMin;
-            this.dateMax = dateMax;
-        }
-        
-        private void setValue(Date date) {
-            spinner.setValue(date);
-        }
-
-        private Date getDate() {
-            return (Date) spinner.getValue();
-        }
-    }
-   
 }
Index: trunk/src/org/openstreetmap/josm/gui/layer/gpx/DateFilterPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/gpx/DateFilterPanel.java	(revision 5815)
+++ trunk/src/org/openstreetmap/josm/gui/layer/gpx/DateFilterPanel.java	(revision 5815)
@@ -0,0 +1,142 @@
+// License: GPL. See LICENSE file for details.
+package org.openstreetmap.josm.gui.layer.gpx;
+
+import java.awt.Component;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JPanel;
+import javax.swing.Timer;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.GBC;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import org.openstreetmap.josm.gui.layer.GpxLayer;
+import org.openstreetmap.josm.gui.widgets.DateEditorWithSlider;
+
+public class DateFilterPanel extends JPanel {
+    DateEditorWithSlider dateFrom = new DateEditorWithSlider(tr("From"));
+    DateEditorWithSlider dateTo = new DateEditorWithSlider(tr("To"));
+    JCheckBox noTimestampCb  = new JCheckBox(tr("No timestamp"));
+    GpxLayer layer;
+    
+    ActionListener filterAppliedListener;
+    
+    final String PREF_DATE_0;
+    final String PREF_DATE_MIN;
+    final String PREF_DATE_MAX;
+
+    /**
+     * Create the panel to filter tracks on GPX layer @param layer by date
+     * Preferences will be stored in @param preferencePrefix
+     * If @param enabled = true, the the panel is created as active and filtering occurs immediately.
+     */
+    public DateFilterPanel(GpxLayer layer, String preferencePrefix, boolean enabled) {
+        super(new GridBagLayout());
+        PREF_DATE_0 = preferencePrefix+".showzerotimestamp";
+        PREF_DATE_MIN = preferencePrefix+".mintime";
+        PREF_DATE_MAX = preferencePrefix+".maxtime";
+        this.layer = layer;
+        
+        final Date startTime, endTime;
+        Date[] bounds = layer.getMinMaxTimeForAllTracks();
+        startTime = (bounds==null) ? new GregorianCalendar(2000, 1, 1).getTime():bounds[0];
+        endTime = (bounds==null) ? new Date() : bounds[1];
+                
+        dateFrom.setDate(startTime); 
+        dateTo.setDate(endTime);
+        dateFrom.setRange(startTime, endTime); 
+        dateTo.setRange(startTime, endTime); 
+        
+        add(noTimestampCb, GBC.std().grid(1,1).insets(0, 0, 5, 0));
+        add(dateFrom, GBC.std().grid(2,1).fill(GBC.HORIZONTAL));
+        add(dateTo, GBC.eol().grid(3,1).fill(GBC.HORIZONTAL));
+        
+        setEnabled(enabled);
+        
+        dateFrom.addDateListener(changeListener);
+        dateTo.addDateListener(changeListener);
+        noTimestampCb.addChangeListener(changeListener);
+    }
+    
+    private ChangeListener changeListener = new ChangeListener() {
+        @Override public void stateChanged(ChangeEvent e) {
+            if (isEnabled()) applyFilterWithDelay();
+        }
+    };
+    
+    private Timer t = new Timer(200 , new ActionListener() {
+        @Override  public void actionPerformed(ActionEvent e) {
+            applyFilter();
+        }
+    });
+    
+    /**
+     * Do filtering but little bit later (to reduce cpu load)
+     */
+    public void applyFilterWithDelay() {
+        if (t.isRunning()) {
+            t.restart();
+        } else {
+            t.start();
+        }
+    }
+    
+    public void applyFilter() {
+        t.stop();
+        filterTracksByDate();
+        if (filterAppliedListener!=null)
+           filterAppliedListener.actionPerformed(null);
+    }
+    
+    /**
+     * Called by other components when it is correct time to save date filtering parameters
+     */
+    public void saveInPrefs() {
+        Main.pref.putLong(PREF_DATE_MIN, dateFrom.getDate().getTime());
+        Main.pref.putLong(PREF_DATE_MAX, dateTo.getDate().getTime());
+        Main.pref.put(PREF_DATE_0, noTimestampCb.isSelected());
+    }
+
+    /**
+     * If possible, load date ragne and "zero timestamp" option from preferences
+     * Called by other components when it is needed.
+     */
+    public void loadFromPrefs() {
+        long t1 =Main.pref.getLong(PREF_DATE_MIN, 0);
+        if (t1!=0) dateFrom.setDate(new Date(t1));
+        long t2 =Main.pref.getLong(PREF_DATE_MAX, 0);
+        if (t2!=0) dateTo.setDate(new Date(t2));
+        noTimestampCb.setSelected(Main.pref.getBoolean(PREF_DATE_0, false));
+    }
+
+    public void setFilterAppliedListener(ActionListener filterAppliedListener) {
+        this.filterAppliedListener = filterAppliedListener;
+    }
+    
+    private void filterTracksByDate() {
+        Date from = dateFrom.getDate();
+        Date to = dateTo.getDate();
+        layer.filterTracksByDate(from, to, noTimestampCb.isSelected());
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled); 
+        for (Component c: getComponents()) {
+            c.setEnabled(enabled);
+        }
+    }
+    
+    
+    
+ 
+}
Index: trunk/src/org/openstreetmap/josm/gui/widgets/DateEditorWithSlider.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/widgets/DateEditorWithSlider.java	(revision 5815)
+++ trunk/src/org/openstreetmap/josm/gui/widgets/DateEditorWithSlider.java	(revision 5815)
@@ -0,0 +1,121 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.widgets;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagLayout;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerDateModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import org.openstreetmap.josm.tools.GBC;
+
+
+/**
+ * Widget originally created for date filtering of GPX tracks. 
+ * Allows to enter the date or choose it by using slider
+ */
+public class DateEditorWithSlider extends JPanel {
+    private JSpinner spinner;
+    private JSlider slider;
+    private Date dateMin;
+    private Date dateMax;
+    private static final int MAX_SLIDER=300;
+    private boolean watchSlider = true;
+    
+    private List<ChangeListener> listeners = new ArrayList<ChangeListener>();
+
+    public DateEditorWithSlider(String labelText) {
+        super(new GridBagLayout());
+        spinner = new JSpinner( new SpinnerDateModel() );
+        String pattern = ((SimpleDateFormat)DateFormat.getDateInstance()).toPattern();
+        JSpinner.DateEditor timeEditor = new JSpinner.DateEditor(spinner,pattern);
+        spinner.setEditor(timeEditor);
+        
+
+        spinner.setPreferredSize(new Dimension(spinner.getPreferredSize().width+5,
+        spinner.getPreferredSize().height));
+        
+        slider = new JSlider(0,MAX_SLIDER);
+        spinner.addChangeListener(new ChangeListener() {
+            @Override
+            public void stateChanged(ChangeEvent e) {
+                int i = slider.getValue();
+                Date d = (Date) spinner.getValue();
+                int j = intFromDate(d);
+                if (i!=j) {
+                    watchSlider=false;
+                    slider.setValue(j);
+                    watchSlider=true;
+                }
+                for (ChangeListener l : listeners) {
+                    l.stateChanged(e);
+                }
+            }
+        });
+        slider.addChangeListener(new ChangeListener() {
+            @Override
+            public void stateChanged(ChangeEvent e) {
+                if (!watchSlider) return;
+                Date d = (Date) spinner.getValue();
+                Date d1 = dateFromInt(slider.getValue());
+                if (!d.equals(d1)) {
+                    spinner.setValue(d1);
+                }
+            }
+        });
+        add(new JLabel(labelText),GBC.std());
+        add(spinner,GBC.std().insets(10,0,0,0));
+        add(slider,GBC.eol().insets(10,0,0,0).fill(GBC.HORIZONTAL));
+
+        dateMin = new Date(0); dateMax =new Date();
+    }
+
+    protected Date dateFromInt(int value) {
+        double k = 1.0*value/MAX_SLIDER;
+        return new Date((long)(dateMax.getTime()*k+ dateMin.getTime()*(1-k)));
+    }
+    
+    protected int intFromDate(Date date) {
+        return (int)(300.0*(date.getTime()-dateMin.getTime()) /
+                (dateMax.getTime()-dateMin.getTime()));
+    }
+
+    public void setRange(Date dateMin, Date dateMax) {
+        this.dateMin = dateMin;
+        this.dateMax = dateMax;
+    }
+
+    public void setDate(Date date) {
+        spinner.setValue(date);
+    }
+
+    public Date getDate() {
+        return (Date) spinner.getValue();
+    }
+    
+    public void addDateListener(ChangeListener l) {
+        listeners.add(l);
+    }
+
+    public void removeDateListener(ChangeListener l) {
+        listeners.remove(l);
+    }
+    
+    @Override
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled); 
+        for (Component c: getComponents()) {
+            c.setEnabled(enabled);
+        }
+    }
+   
+}
