package org.esa.snap.timeseries.ui.manager; import com.bc.ceres.core.ProgressMonitor; import com.bc.ceres.swing.TableLayout; import org.esa.snap.core.datamodel.Product; import org.esa.snap.core.datamodel.ProductData; import org.esa.snap.core.ui.ModalDialog; import org.esa.snap.timeseries.core.timeseries.datamodel.AbstractTimeSeries; import org.esa.snap.timeseries.core.timeseries.datamodel.GridTimeCoding; import org.esa.snap.timeseries.core.timeseries.datamodel.ProductLocation; import org.esa.snap.timeseries.core.timeseries.datamodel.TimeCoding; import org.jdesktop.swingx.JXDatePicker; import org.openide.util.ImageUtilities; import javax.swing.AbstractAction; import javax.swing.ImageIcon; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; import java.awt.Component; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.DateFormat; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.TimeZone; import java.util.stream.Collectors; class EditTimeSpanAction extends AbstractAction { private final AbstractTimeSeries timeSeries; EditTimeSpanAction(AbstractTimeSeries timeSeries) { this.timeSeries = timeSeries; setEnabled(timeSeries != null); // putValue(NAME, "[?]"); // todo set name ImageIcon editTimeSpanIcon = ImageUtilities.loadImageIcon("org/esa/snap/timeseries/ui/icons/timeseries-rangeedit24.png", false); putValue(LARGE_ICON_KEY, editTimeSpanIcon); putValue(ACTION_COMMAND_KEY, getClass().getName()); putValue(SHORT_DESCRIPTION, "Edit time span"); putValue("componentName", "EditTimeSpan"); } @Override public void actionPerformed(ActionEvent e) { final Object source = e.getSource(); Window window = null; if (source instanceof Component) { window = SwingUtilities.getWindowAncestor((Component) source); } final ModalDialog dialog = new EditTimeSpanDialog(window, timeSeries); dialog.show(); } private static class EditTimeSpanDialog extends ModalDialog { private final DateFormat dateFormat; private AbstractTimeSeries timeSeries; private JXDatePicker startTimeBox; private JXDatePicker endTimeBox; private JLabel startTimeLabel; private JLabel endTimeLabel; private JCheckBox autoAdjustBox; private EditTimeSpanDialog(Window window, AbstractTimeSeries timeSeries) { super(window, "Edit Time Span", ModalDialog.ID_OK_CANCEL, null); dateFormat = ProductData.UTC.createDateFormat(("dd-MMM-yyyy HH:mm:ss")); this.timeSeries = timeSeries; createUserInterface(); } @Override protected void onOK() { timeSeries.setAutoAdjustingTimeCoding(autoAdjustBox.isSelected()); final ProductData.UTC startTime = ProductData.UTC.create(startTimeBox.getDate(), 0); final ProductData.UTC endTime = ProductData.UTC.create(endTimeBox.getDate(), 0); timeSeries.setTimeCoding(new GridTimeCoding(startTime, endTime)); super.onOK(); } @Override protected boolean verifyUserInput() { if (endTimeBox.getDate().compareTo(startTimeBox.getDate()) < 0) { showErrorDialog("End time is before start time."); return false; } return true; } private void createUserInterface() { boolean isAutoAdjustingTimeCoding = timeSeries.isAutoAdjustingTimeCoding(); final TableLayout tableLayout = new TableLayout(2); tableLayout.setTableAnchor(TableLayout.Anchor.NORTHWEST); tableLayout.setTableWeightX(1.0); tableLayout.setTableFill(TableLayout.Fill.BOTH); tableLayout.setTablePadding(4, 4); tableLayout.setCellColspan(0, 0, 2); JPanel content = new JPanel(tableLayout); autoAdjustBox = createAutoAdjustBox(isAutoAdjustingTimeCoding); startTimeLabel = new JLabel("Start time:"); startTimeBox = createDateComboBox(); final TimeCoding timeCoding = timeSeries.getTimeCoding(); startTimeBox.setDate(timeCoding.getStartTime().getAsDate()); endTimeLabel = new JLabel("End time:"); endTimeBox = createDateComboBox(); endTimeBox.setDate(timeCoding.getEndTime().getAsDate()); content.add(autoAdjustBox); content.add(startTimeLabel); content.add(startTimeBox); content.add(endTimeLabel); content.add(endTimeBox); setUiEnabled(!isAutoAdjustingTimeCoding); setContent(content); } private JCheckBox createAutoAdjustBox(boolean autoAdjustingTimeCoding) { final JCheckBox autoAdjustBox = new JCheckBox("Auto adjust time information", autoAdjustingTimeCoding); autoAdjustBox.addActionListener(new AutoAdjustBoxListener(autoAdjustBox)); return autoAdjustBox; } private List<Product> getCompatibleProducts() { List<Product> result = new ArrayList<>(); for (ProductLocation productLocation : timeSeries.getProductLocations()) { for (Product product : productLocation.getProducts(ProgressMonitor.NULL).values()) { result.addAll(timeSeries.getEoVariables().stream().filter(variable -> timeSeries.isProductCompatible(product, variable)).filter( timeSeries::isEoVariableSelected).map(variable -> product).collect(Collectors.toList())); } } return result; } private ProductData.UTC getMaxEndTime(final ProductData.UTC endTime1, final ProductData.UTC endTime2) { ProductData.UTC endTime; if (endTime1.getAsDate().before(endTime2.getAsDate())) { endTime = endTime2; } else { endTime = endTime1; } return endTime; } private ProductData.UTC getMinStartTime(final ProductData.UTC startTime1, final ProductData.UTC startTime2) { ProductData.UTC startTime; if (startTime1.getAsDate().after(startTime2.getAsDate())) { startTime = startTime2; } else { startTime = startTime1; } return startTime; } private JXDatePicker createDateComboBox() { TimeZone utcZone = TimeZone.getTimeZone("UTC"); Calendar utc = Calendar.getInstance(utcZone); Date date = utc.getTime(); JXDatePicker datePicker = new JXDatePicker(date); datePicker.setTimeZone(utcZone); datePicker.setFormats(dateFormat); return datePicker; } private void setUiEnabled(boolean enable) { startTimeBox.setEnabled(enable); startTimeLabel.setEnabled(enable); endTimeBox.setEnabled(enable); endTimeLabel.setEnabled(enable); } private class AutoAdjustBoxListener implements ActionListener { private final JCheckBox autoAdjustBox; private AutoAdjustBoxListener(JCheckBox autoAdjustBox) { this.autoAdjustBox = autoAdjustBox; } @Override public void actionPerformed(ActionEvent e) { final boolean selected = autoAdjustBox.isSelected(); setUiEnabled(!selected); if (!selected) { return; } ProductData.UTC autoStartTime = null; ProductData.UTC autoEndTime = null; List<Product> compatibleProducts = getCompatibleProducts(); for (Product product : compatibleProducts) { TimeCoding varTimeCoding = GridTimeCoding.create(product); if (autoStartTime == null) { TimeCoding tsTimeCoding = timeSeries.getTimeCoding(); autoStartTime = tsTimeCoding.getStartTime(); autoEndTime = tsTimeCoding.getEndTime(); } if (varTimeCoding != null) { autoStartTime = getMinStartTime(autoStartTime, varTimeCoding.getStartTime()); autoEndTime = getMaxEndTime(autoEndTime, varTimeCoding.getEndTime()); } } if (autoStartTime == null) { try { autoStartTime = ProductData.UTC.parse("1970-01-01", "yyyy-MM-dd"); autoEndTime = autoStartTime; } catch (ParseException ignore) { } } //noinspection ConstantConditions startTimeBox.setDate(autoStartTime.getAsDate()); //noinspection ConstantConditions endTimeBox.setDate(autoEndTime.getAsDate()); } } } }