001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.layer.gpx; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Component; 007import java.awt.GridBagLayout; 008import java.awt.event.ActionEvent; 009import java.awt.event.ActionListener; 010import java.util.Date; 011import java.util.GregorianCalendar; 012 013import javax.swing.JCheckBox; 014import javax.swing.JPanel; 015import javax.swing.Timer; 016import javax.swing.event.ChangeEvent; 017import javax.swing.event.ChangeListener; 018 019import org.openstreetmap.josm.Main; 020import org.openstreetmap.josm.gui.layer.GpxLayer; 021import org.openstreetmap.josm.gui.widgets.DateEditorWithSlider; 022import org.openstreetmap.josm.tools.GBC; 023 024public class DateFilterPanel extends JPanel { 025 private DateEditorWithSlider dateFrom = new DateEditorWithSlider(tr("From")); 026 private DateEditorWithSlider dateTo = new DateEditorWithSlider(tr("To")); 027 private JCheckBox noTimestampCb = new JCheckBox(tr("No timestamp")); 028 private transient GpxLayer layer; 029 030 private transient ActionListener filterAppliedListener; 031 032 private final String prefDate0; 033 private final String prefDateMin; 034 private final String prefDateMax; 035 036 /** 037 * Create the panel to filter tracks on GPX layer @param layer by date 038 * Preferences will be stored in @param preferencePrefix 039 * If @param enabled = true, the the panel is created as active and filtering occurs immediately. 040 */ 041 public DateFilterPanel(GpxLayer layer, String preferencePrefix, boolean enabled) { 042 super(new GridBagLayout()); 043 prefDate0 = preferencePrefix+".showzerotimestamp"; 044 prefDateMin = preferencePrefix+".mintime"; 045 prefDateMax = preferencePrefix+".maxtime"; 046 this.layer = layer; 047 048 final Date startTime, endTime; 049 Date[] bounds = layer.data.getMinMaxTimeForAllTracks(); 050 startTime = (bounds.length == 0) ? new GregorianCalendar(2000, 1, 1).getTime() : bounds[0]; 051 endTime = (bounds.length == 0) ? new Date() : bounds[1]; 052 053 dateFrom.setDate(startTime); 054 dateTo.setDate(endTime); 055 dateFrom.setRange(startTime, endTime); 056 dateTo.setRange(startTime, endTime); 057 058 add(noTimestampCb, GBC.std().grid(1, 1).insets(0, 0, 5, 0)); 059 add(dateFrom, GBC.std().grid(2, 1).fill(GBC.HORIZONTAL)); 060 add(dateTo, GBC.eol().grid(3, 1).fill(GBC.HORIZONTAL)); 061 062 setEnabled(enabled); 063 064 dateFrom.addDateListener(changeListener); 065 dateTo.addDateListener(changeListener); 066 noTimestampCb.addChangeListener(changeListener); 067 } 068 069 private transient ChangeListener changeListener = new ChangeListener() { 070 @Override public void stateChanged(ChangeEvent e) { 071 if (isEnabled()) applyFilterWithDelay(); 072 } 073 }; 074 075 private Timer t = new Timer(200, new ActionListener() { 076 @Override public void actionPerformed(ActionEvent e) { 077 applyFilter(); 078 } 079 }); 080 081 /** 082 * Do filtering but little bit later (to reduce cpu load) 083 */ 084 public void applyFilterWithDelay() { 085 if (t.isRunning()) { 086 t.restart(); 087 } else { 088 t.start(); 089 } 090 } 091 092 public void applyFilter() { 093 t.stop(); 094 filterTracksByDate(); 095 if (filterAppliedListener != null) 096 filterAppliedListener.actionPerformed(null); 097 } 098 099 /** 100 * Called by other components when it is correct time to save date filtering parameters 101 */ 102 public void saveInPrefs() { 103 Main.pref.putLong(prefDateMin, dateFrom.getDate().getTime()); 104 Main.pref.putLong(prefDateMax, dateTo.getDate().getTime()); 105 Main.pref.put(prefDate0, noTimestampCb.isSelected()); 106 } 107 108 /** 109 * If possible, load date ragne and "zero timestamp" option from preferences 110 * Called by other components when it is needed. 111 */ 112 public void loadFromPrefs() { 113 long t1 = Main.pref.getLong(prefDateMin, 0); 114 if (t1 != 0) dateFrom.setDate(new Date(t1)); 115 long t2 = Main.pref.getLong(prefDateMax, 0); 116 if (t2 != 0) dateTo.setDate(new Date(t2)); 117 noTimestampCb.setSelected(Main.pref.getBoolean(prefDate0, false)); 118 } 119 120 public void setFilterAppliedListener(ActionListener filterAppliedListener) { 121 this.filterAppliedListener = filterAppliedListener; 122 } 123 124 private void filterTracksByDate() { 125 Date from = dateFrom.getDate(); 126 Date to = dateTo.getDate(); 127 layer.filterTracksByDate(from, to, noTimestampCb.isSelected()); 128 } 129 130 @Override 131 public final void setEnabled(boolean enabled) { 132 super.setEnabled(enabled); 133 for (Component c: getComponents()) { 134 c.setEnabled(enabled); 135 } 136 } 137}