package org.yamcs.ui.datepicker;
import net.sourceforge.jdatepicker.JDateComponentFactory;
import net.sourceforge.jdatepicker.impl.JDatePickerImpl;
import net.sourceforge.jdatepicker.impl.UtilCalendarModel;
import org.yamcs.TimeInterval;
import org.yamcs.utils.TimeEncoding;
import javax.swing.*;
import javax.swing.JFormattedTextField.AbstractFormatter;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import static java.util.Calendar.*;
/**
* DatePicker class.
* @author es
*
*/
public final class DatePicker extends JPanel {
MyDatePicker start, end;
JComboBox<String> fixedRangesComboBox;
public DatePicker() {
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
final String[] fixedRanges = {"Select Last...", "day", "week", "month", "3 months", "6 months", "12 months"};
final int[][] fixedRangesTime = {{}, {Calendar.DAY_OF_MONTH, 1}, {Calendar.WEEK_OF_YEAR, 1}, {Calendar.MONTH, 1}
, {Calendar.MONTH, 3}, {Calendar.MONTH, 6}, {Calendar.MONTH, 12}};
fixedRangesComboBox = new JComboBox<>(fixedRanges);
fixedRangesComboBox.setSelectedIndex(0);
start=new MyDatePicker();
end=new MyDatePicker();
fixedRangesComboBox.addActionListener(e -> {
int idx = fixedRangesComboBox.getSelectedIndex();
if (idx != 0) {
Calendar startCal = Calendar.getInstance();
startCal.set(Calendar.HOUR_OF_DAY, 0);
startCal.set(Calendar.MINUTE, 0);
startCal.set(Calendar.SECOND, 0);
startCal.set(Calendar.MILLISECOND, 0);
startCal.add(Calendar.DAY_OF_MONTH, 1);
end.setTime(startCal);
Calendar endCal = Calendar.getInstance();
int[] x =fixedRangesTime[idx];
endCal.add(x[0], -x[1]);
start.setTime(endCal);
}
});
add(start.datePicker);
add(end.datePicker);
add(fixedRangesComboBox);
}
/**
* Returns the starting date.
*/
public long getStartTimestamp() {
if(start.getValue()==null) {
return TimeEncoding.INVALID_INSTANT;
}
return TimeEncoding.fromCalendar(start.getValue());
}
/**
* Returns the ending date.
*/
public long getEndTimestamp() {
if(end.getValue()==null) {
return TimeEncoding.INVALID_INSTANT;
}
return TimeEncoding.fromCalendar(end.getValue());
}
public TimeInterval getInterval() {
TimeInterval ti=new TimeInterval();
Calendar calStart=start.getValue();
Calendar calEnd=end.getValue();
if(calStart!=null) {
ti.setStart(TimeEncoding.fromCalendar(calStart));
}
if(calEnd!=null) {
ti.setStop(TimeEncoding.fromCalendar(calEnd));
}
return ti;
}
public void setStartTimestamp(long t) {
start.setTime(TimeEncoding.toCalendar(t));
}
public void setEndTimestamp(long t) {
end.setTime(TimeEncoding.toCalendar(t));
}
/**
* wraps a date picker with a formatter that remembers hh:mm:ss.SSS in a private calendar
*/
class MyDatePicker {
JDatePickerImpl datePicker;
YamcsDateTimeFormatter formatter=new YamcsDateTimeFormatter();
UtilCalendarModel calendarModel = new UtilCalendarModel();
Calendar calendar=null; //null means no value set
MyDatePicker() {
datePicker = (JDatePickerImpl) JDateComponentFactory.createJDatePicker(calendarModel, formatter);
datePicker.getModel().setSelected(true);
datePicker.setTextEditable(true);
datePicker.addActionListener(e-> {
// if the date range is changed by date picker the fixed combo box becomes irrelevant,
if (fixedRangesComboBox.getSelectedIndex() != 0) {
fixedRangesComboBox.setSelectedIndex(0);
}
});
}
public Calendar getValue() {
if(calendar==null) {
return null;
}
Calendar cal=calendarModel.getValue();
copyHhMmSs(calendar, cal);
return cal;
}
public void setTime(Calendar cal) {
if(cal==null) {
calendar=null;
calendarModel.setValue(null);
} else {
if(calendar==null) {
calendar=Calendar.getInstance();
}
calendar.setTime(cal.getTime());
calendarModel.setValue(cal);
}
}
/**
* this remembers the hh:mm:ss.SS
*/
private class YamcsDateTimeFormatter extends AbstractFormatter {
private static final long serialVersionUID = -4371640422279341322L;
@Override
public Object stringToValue(final String dateString) throws ParseException {
if(dateString.isEmpty()) {
calendar=null;
return null;
}
Calendar cal = Calendar.getInstance();
SimpleDateFormat simpleDateFormatter = new SimpleDateFormat();
simpleDateFormatter.setCalendar(calendar);
String[] patterns={"yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd"};
for(String p:patterns) {
simpleDateFormatter.applyPattern(p);
try {
Date date = simpleDateFormatter.parse(dateString);
cal.setTime(date);
copyHhMmSs(cal, calendar);
return cal;
} catch (ParseException pe) { }
}
JOptionPane.showMessageDialog(null,
"The date can only be in one of the following formats:\n"
+ "yyyy-mm-dd\n"
+ "yyyy-mm-ddThh:mm:ss\n"
+ "yyyy-mm-ddThh:mm:ss.sss.",
"Unparseable date error!",
JOptionPane.ERROR_MESSAGE);
throw new ParseException("Not a valid YAMCS DateTime string", 0);
}
@Override
public String valueToString(final Object value) {
if(calendar==null) {
calendar=Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
if (value != null) {
Calendar cal = (Calendar) value;
copyHhMmSs(calendar, cal);
SimpleDateFormat simpleDateFormatter = new SimpleDateFormat();
simpleDateFormatter.applyPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
return simpleDateFormatter.format(cal.getTime());
} else {
calendar=null;
return null;
}
}
}
void copyHhMmSs(Calendar from, Calendar to) {
to.set(HOUR_OF_DAY, from.get(HOUR_OF_DAY));
to.set(MINUTE, from.get(MINUTE));
to.set(SECOND, from.get(SECOND));
to.set(MILLISECOND, from.get(MILLISECOND));
}
}
}