1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.gui.widgets;
|
---|
3 |
|
---|
4 | import java.awt.Component;
|
---|
5 | import java.awt.Dimension;
|
---|
6 | import java.awt.GridBagLayout;
|
---|
7 | import java.text.DateFormat;
|
---|
8 | import java.text.SimpleDateFormat;
|
---|
9 | import java.util.ArrayList;
|
---|
10 | import java.util.Date;
|
---|
11 | import java.util.List;
|
---|
12 |
|
---|
13 | import javax.swing.JLabel;
|
---|
14 | import javax.swing.JPanel;
|
---|
15 | import javax.swing.JSlider;
|
---|
16 | import javax.swing.JSpinner;
|
---|
17 | import javax.swing.SpinnerDateModel;
|
---|
18 | import javax.swing.event.ChangeListener;
|
---|
19 |
|
---|
20 | import org.openstreetmap.josm.tools.GBC;
|
---|
21 | import org.openstreetmap.josm.tools.date.DateUtils;
|
---|
22 |
|
---|
23 | /**
|
---|
24 | * Widget originally created for date filtering of GPX tracks.
|
---|
25 | * Allows to enter the date or choose it by using slider
|
---|
26 | * @since 5815
|
---|
27 | */
|
---|
28 | public class DateEditorWithSlider extends JPanel {
|
---|
29 | private final JSpinner spinner;
|
---|
30 | private final JSlider slider;
|
---|
31 | private Date dateMin;
|
---|
32 | private Date dateMax;
|
---|
33 | private static final int MAX_SLIDER = 300;
|
---|
34 | private boolean watchSlider = true;
|
---|
35 |
|
---|
36 | private final transient List<ChangeListener> listeners = new ArrayList<>();
|
---|
37 |
|
---|
38 | /**
|
---|
39 | * Constructs a new {@code DateEditorWithSlider} with a given label
|
---|
40 | * @param labelText The label to display
|
---|
41 | */
|
---|
42 | public DateEditorWithSlider(String labelText) {
|
---|
43 | super(new GridBagLayout());
|
---|
44 | spinner = new JSpinner(new SpinnerDateModel());
|
---|
45 | String pattern = ((SimpleDateFormat) DateUtils.getDateFormat(DateFormat.DEFAULT)).toPattern();
|
---|
46 | JSpinner.DateEditor timeEditor = new JSpinner.DateEditor(spinner, pattern);
|
---|
47 | spinner.setEditor(timeEditor);
|
---|
48 |
|
---|
49 | spinner.setPreferredSize(new Dimension(spinner.getPreferredSize().width+5,
|
---|
50 | spinner.getPreferredSize().height));
|
---|
51 |
|
---|
52 | slider = new JSlider(0, MAX_SLIDER);
|
---|
53 | spinner.addChangeListener(e -> {
|
---|
54 | int i = slider.getValue();
|
---|
55 | Date d = (Date) spinner.getValue();
|
---|
56 | int j = intFromDate(d);
|
---|
57 | if (i != j) {
|
---|
58 | watchSlider = false;
|
---|
59 | slider.setValue(j);
|
---|
60 | watchSlider = true;
|
---|
61 | }
|
---|
62 | for (ChangeListener l : listeners) {
|
---|
63 | l.stateChanged(e);
|
---|
64 | }
|
---|
65 | });
|
---|
66 | slider.addChangeListener(e -> {
|
---|
67 | if (!watchSlider) return;
|
---|
68 | Date d = (Date) spinner.getValue();
|
---|
69 | Date d1 = dateFromInt(slider.getValue());
|
---|
70 | if (!d.equals(d1)) {
|
---|
71 | spinner.setValue(d1);
|
---|
72 | }
|
---|
73 | });
|
---|
74 | add(new JLabel(labelText), GBC.std());
|
---|
75 | add(spinner, GBC.std().insets(10, 0, 0, 0));
|
---|
76 | add(slider, GBC.eol().insets(10, 0, 0, 0).fill(GBC.HORIZONTAL));
|
---|
77 |
|
---|
78 | dateMin = new Date(0);
|
---|
79 | dateMax = new Date();
|
---|
80 | }
|
---|
81 |
|
---|
82 | protected Date dateFromInt(int value) {
|
---|
83 | double k = 1.0*value/MAX_SLIDER;
|
---|
84 | return new Date((long) (dateMax.getTime()*k+ dateMin.getTime()*(1-k)));
|
---|
85 | }
|
---|
86 |
|
---|
87 | protected int intFromDate(Date date) {
|
---|
88 | return (int) (300.0*(date.getTime()-dateMin.getTime()) /
|
---|
89 | (dateMax.getTime()-dateMin.getTime()));
|
---|
90 | }
|
---|
91 |
|
---|
92 | /**
|
---|
93 | * Sets the date range that is available using the slider
|
---|
94 | * @param dateMin The min date
|
---|
95 | * @param dateMax The max date
|
---|
96 | */
|
---|
97 | public void setRange(Date dateMin, Date dateMax) {
|
---|
98 | this.dateMin = DateUtils.cloneDate(dateMin);
|
---|
99 | this.dateMax = DateUtils.cloneDate(dateMax);
|
---|
100 | }
|
---|
101 |
|
---|
102 | /**
|
---|
103 | * Sets the slider to the given value
|
---|
104 | * @param date The date
|
---|
105 | */
|
---|
106 | public void setDate(Date date) {
|
---|
107 | spinner.setValue(DateUtils.cloneDate(date));
|
---|
108 | }
|
---|
109 |
|
---|
110 | /**
|
---|
111 | * Gets the date that was selected by the user
|
---|
112 | * @return The date
|
---|
113 | */
|
---|
114 | public Date getDate() {
|
---|
115 | return DateUtils.cloneDate((Date) spinner.getValue());
|
---|
116 | }
|
---|
117 |
|
---|
118 | /**
|
---|
119 | * Adds a change listener to this date editor.
|
---|
120 | * @param l The listener
|
---|
121 | */
|
---|
122 | public void addDateListener(ChangeListener l) {
|
---|
123 | listeners.add(l);
|
---|
124 | }
|
---|
125 |
|
---|
126 | /**
|
---|
127 | * Removes a change listener from this date editor.
|
---|
128 | * @param l The listener
|
---|
129 | */
|
---|
130 | public void removeDateListener(ChangeListener l) {
|
---|
131 | listeners.remove(l);
|
---|
132 | }
|
---|
133 |
|
---|
134 | @Override
|
---|
135 | public void setEnabled(boolean enabled) {
|
---|
136 | super.setEnabled(enabled);
|
---|
137 | for (Component c: getComponents()) {
|
---|
138 | c.setEnabled(enabled);
|
---|
139 | }
|
---|
140 | }
|
---|
141 | }
|
---|