001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.widgets; 003 004import java.awt.Component; 005import java.awt.Dimension; 006import java.awt.GridBagLayout; 007import java.text.DateFormat; 008import java.text.SimpleDateFormat; 009import java.util.ArrayList; 010import java.util.Date; 011import java.util.List; 012import javax.swing.JLabel; 013import javax.swing.JPanel; 014import javax.swing.JSlider; 015import javax.swing.JSpinner; 016import javax.swing.SpinnerDateModel; 017import javax.swing.event.ChangeEvent; 018import javax.swing.event.ChangeListener; 019import org.openstreetmap.josm.tools.GBC; 020 021 022/** 023 * Widget originally created for date filtering of GPX tracks. 024 * Allows to enter the date or choose it by using slider 025 */ 026public class DateEditorWithSlider extends JPanel { 027 private JSpinner spinner; 028 private JSlider slider; 029 private Date dateMin; 030 private Date dateMax; 031 private static final int MAX_SLIDER=300; 032 private boolean watchSlider = true; 033 034 private List<ChangeListener> listeners = new ArrayList<ChangeListener>(); 035 036 public DateEditorWithSlider(String labelText) { 037 super(new GridBagLayout()); 038 spinner = new JSpinner( new SpinnerDateModel() ); 039 String pattern = ((SimpleDateFormat)DateFormat.getDateInstance()).toPattern(); 040 JSpinner.DateEditor timeEditor = new JSpinner.DateEditor(spinner,pattern); 041 spinner.setEditor(timeEditor); 042 043 044 spinner.setPreferredSize(new Dimension(spinner.getPreferredSize().width+5, 045 spinner.getPreferredSize().height)); 046 047 slider = new JSlider(0,MAX_SLIDER); 048 spinner.addChangeListener(new ChangeListener() { 049 @Override 050 public void stateChanged(ChangeEvent e) { 051 int i = slider.getValue(); 052 Date d = (Date) spinner.getValue(); 053 int j = intFromDate(d); 054 if (i!=j) { 055 watchSlider=false; 056 slider.setValue(j); 057 watchSlider=true; 058 } 059 for (ChangeListener l : listeners) { 060 l.stateChanged(e); 061 } 062 } 063 }); 064 slider.addChangeListener(new ChangeListener() { 065 @Override 066 public void stateChanged(ChangeEvent e) { 067 if (!watchSlider) return; 068 Date d = (Date) spinner.getValue(); 069 Date d1 = dateFromInt(slider.getValue()); 070 if (!d.equals(d1)) { 071 spinner.setValue(d1); 072 } 073 } 074 }); 075 add(new JLabel(labelText),GBC.std()); 076 add(spinner,GBC.std().insets(10,0,0,0)); 077 add(slider,GBC.eol().insets(10,0,0,0).fill(GBC.HORIZONTAL)); 078 079 dateMin = new Date(0); dateMax =new Date(); 080 } 081 082 protected Date dateFromInt(int value) { 083 double k = 1.0*value/MAX_SLIDER; 084 return new Date((long)(dateMax.getTime()*k+ dateMin.getTime()*(1-k))); 085 } 086 087 protected int intFromDate(Date date) { 088 return (int)(300.0*(date.getTime()-dateMin.getTime()) / 089 (dateMax.getTime()-dateMin.getTime())); 090 } 091 092 public void setRange(Date dateMin, Date dateMax) { 093 this.dateMin = dateMin; 094 this.dateMax = dateMax; 095 } 096 097 public void setDate(Date date) { 098 spinner.setValue(date); 099 } 100 101 public Date getDate() { 102 return (Date) spinner.getValue(); 103 } 104 105 public void addDateListener(ChangeListener l) { 106 listeners.add(l); 107 } 108 109 public void removeDateListener(ChangeListener l) { 110 listeners.remove(l); 111 } 112 113 @Override 114 public void setEnabled(boolean enabled) { 115 super.setEnabled(enabled); 116 for (Component c: getComponents()) { 117 c.setEnabled(enabled); 118 } 119 } 120 121}