// 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;
import org.openstreetmap.josm.tools.date.DateUtils;
/**
* Widget originally created for date filtering of GPX tracks.
* Allows to enter the date or choose it by using slider
* @since 5815
*/
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<>();
/**
* Constructs a new {@code DateEditorWithSlider} with a given label
* @param labelText The label to display
*/
public DateEditorWithSlider(String labelText) {
super(new GridBagLayout());
spinner = new JSpinner( new SpinnerDateModel() );
String pattern = ((SimpleDateFormat)DateUtils.getDateFormat(DateFormat.DEFAULT)).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);
}
}
}