package org.esa.beam.smos.ee2netcdf.visat; import com.bc.ceres.binding.*; import com.bc.ceres.swing.TableLayout; import com.bc.ceres.swing.binding.Binding; import com.bc.ceres.swing.binding.BindingContext; import com.bc.ceres.swing.selection.SelectionManager; import com.vividsolutions.jts.geom.Geometry; import org.esa.beam.framework.datamodel.Product; import org.esa.beam.framework.datamodel.ProductManager; import org.esa.beam.framework.datamodel.VectorDataNode; import org.esa.beam.framework.ui.AppContext; import org.esa.beam.framework.ui.RegionBoundsInputUI; import org.esa.beam.smos.ee2netcdf.EEToNetCDFExporterOp; import org.esa.beam.smos.ee2netcdf.ExportParameter; import org.esa.beam.smos.gui.*; import org.esa.beam.util.io.WildcardMatcher; import javax.swing.*; import java.awt.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.IOException; import java.text.MessageFormat; import java.util.*; import java.util.List; public class EEToNetCDFExportDialog extends ProductChangeAwareDialog { private static final String TARGET_DIRECTORY_BINDING = "targetDirectory"; private final ExportParameter exportParameter; private final PropertyContainer propertyContainer; private final AppContext appContext; private final BindingContext bindingContext; private final ProductSelectionListener productSelectionListener; private GeometryListener geometryListener; public EEToNetCDFExportDialog(AppContext appContext, String helpId) { super(appContext.getApplicationWindow(), "Convert SMOS EE File to NetCDF 4", ID_OK | ID_CLOSE | ID_HELP, helpId); /* I18N */ this.appContext = appContext; exportParameter = new ExportParameter(); propertyContainer = PropertyContainer.createObjectBacked(exportParameter); setAreaToGlobe(propertyContainer); bindingContext = new BindingContext(propertyContainer); createUi(); bindingContext.bindEnabledState(BindingConstants.REGION, true, BindingConstants.ROI_TYPE, BindingConstants.ROI_TYPE_GEOMETRY); try { init(propertyContainer); } catch (ValidationException e) { throw new IllegalStateException(e.getMessage()); } final ProductManager productManager = appContext.getProductManager(); productManager.addListener(new ProductManagerListener(this)); geometryListener = new GeometryListener(this); final SelectionManager selectionManager = appContext.getApplicationPage().getSelectionManager(); productSelectionListener = new ProductSelectionListener(this, selectionManager); selectionManager.addSelectionChangeListener(productSelectionListener); } // package access for testing only tb 2013-05-27 static List<File> getTargetFiles(String filePath, File targetDir) throws IOException { final ArrayList<File> targetFiles = new ArrayList<>(); final File file = new File(filePath); if (file.isFile()) { final File outputFile = EEToNetCDFExporterOp.getOutputFile(file, targetDir); targetFiles.add(outputFile); } else { final TreeSet<File> sourceFileSet = new TreeSet<>(); WildcardMatcher.glob(filePath, sourceFileSet); for (File aSourceFile : sourceFileSet) { final File outputFile = EEToNetCDFExporterOp.getOutputFile(aSourceFile, targetDir); targetFiles.add(outputFile); } } return targetFiles; } // package access for testing only tb 2013-05-27 static List<File> getExistingFiles(List<File> targetFiles) { final ArrayList<File> existingFiles = new ArrayList<>(); for (File targetFile : targetFiles) { if (targetFile.isFile()) { existingFiles.add(targetFile); } } return existingFiles; } // package access for testing only tb 2013-05-27 static String listToString(List<File> targetFiles) { int fileCount = 0; final StringBuilder stringBuilder = new StringBuilder(); for (File targetFile : targetFiles) { stringBuilder.append(targetFile.getAbsolutePath()); stringBuilder.append("\n"); fileCount++; if (fileCount >= 10) { stringBuilder.append("..."); break; } } return stringBuilder.toString(); } private void init(PropertyContainer propertyContainer) throws ValidationException { final File defaultSourceDirectory = GuiHelper.getDefaultSourceDirectory(appContext); propertyContainer.setValue(BindingConstants.SOURCE_DIRECTORY, defaultSourceDirectory); final File defaultTargetDirectory = GuiHelper.getDefaultTargetDirectory(appContext); propertyContainer.setValue(TARGET_DIRECTORY_BINDING, defaultTargetDirectory); updateSelectedProductAndGeometries(propertyContainer); } @SuppressWarnings("ConstantConditions") private void updateSelectedProductAndGeometries(PropertyContainer propertyContainer) throws ValidationException { final Product selectedSmosProduct = DialogHelper.getSelectedSmosProduct(appContext); if (selectedSmosProduct != null) { propertyContainer.setValue(BindingConstants.SELECTED_PRODUCT, true); final List<Geometry> geometries = GuiHelper.getPolygonGeometries(selectedSmosProduct); if (!geometries.isEmpty()) { GuiHelper.bindGeometries(geometries, propertyContainer); } else { removeGeometries(); } setSelectedProductButtonEnabled(true); propertyContainer.setValue(BindingConstants.SELECTED_PRODUCT, true); setSelectionToSelectedGeometry(propertyContainer); selectedSmosProduct.addProductNodeListener(geometryListener); } else { propertyContainer.setValue(BindingConstants.SELECTED_PRODUCT, false); propertyContainer.setValue(BindingConstants.ROI_TYPE, BindingConstants.ROI_TYPE_PRODUCT); } } private void removeProductAndGeometries(Product product) { final Product selectedSmosProduct = DialogHelper.getSelectedSmosProduct(appContext); if (selectedSmosProduct == null) { setSelectedProductButtonEnabled(false); final List<VectorDataNode> geometryNodeList = GuiHelper.getGeometries(product); if (!geometryNodeList.isEmpty()) { removeGeometries(); } } } @SuppressWarnings("ConstantConditions") private void setSelectedProductButtonEnabled(boolean enabled) { if (bindingContext == null) { return; } final Binding binding = bindingContext.getBinding(BindingConstants.SELECTED_PRODUCT); final JComponent[] components = binding.getComponents(); for (final JComponent component : components) { if (component instanceof JRadioButton) { if (((JRadioButton) component).getText().equals(BindingConstants.USE_SELECTED_PRODUCT_BUTTON_NAME)) { component.setEnabled(enabled); break; } } } } private void removeGeometries() { final Property geometryProperty = propertyContainer.getProperty(BindingConstants.REGION); geometryProperty.getDescriptor().setValueSet(new ValueSet(new VectorDataNode[0])); propertyContainer.setValue(BindingConstants.REGION, null); propertyContainer.setValue(BindingConstants.ROI_TYPE, BindingConstants.ROI_TYPE_AREA); } // package access for testing only tb 2014-08-04 static void setAreaToGlobe(PropertyContainer propertyContainer) { propertyContainer.setValue(RegionBoundsInputUI.PROPERTY_NORTH_BOUND, 90.0); propertyContainer.setValue(RegionBoundsInputUI.PROPERTY_EAST_BOUND, 180.0); propertyContainer.setValue(RegionBoundsInputUI.PROPERTY_SOUTH_BOUND, -90.0); propertyContainer.setValue(RegionBoundsInputUI.PROPERTY_WEST_BOUND, -180.0); } private void setSelectionToSelectedGeometry(PropertyContainer propertyContainer) { final Geometry selectedGeometry = GuiHelper.getSelectedGeometry(appContext); if (selectedGeometry != null) { propertyContainer.setValue(BindingConstants.REGION, selectedGeometry); } } private void createUi() { final JPanel mainPanel = GuiHelper.createPanelWithBoxLayout(); mainPanel.add(createSourceProductsPanel()); mainPanel.add(createRoiPanel()); mainPanel.add(createTargetDirPanel()); setContent(mainPanel); } private JComponent createSourceProductsPanel() { final TableLayout layout = GuiHelper.createWeightedTablelayout(1); final JPanel sourceProductPanel = new JPanel(layout); sourceProductPanel.setBorder(BorderFactory.createTitledBorder("Source Products")); final boolean canProductSelectionBeEnabled = DialogHelper.canProductSelectionBeEnabled(appContext); GuiHelper.addSourceProductsButtons(sourceProductPanel, canProductSelectionBeEnabled, bindingContext); final PropertyDescriptor sourceDirectoryDescriptor = propertyContainer.getDescriptor(BindingConstants.SOURCE_DIRECTORY); final JComponent fileEditor = GuiHelper.createFileEditorComponent(sourceDirectoryDescriptor, new DefaultChooserFactory(), bindingContext); layout.setCellPadding(2, 0, new Insets(0, 24, 3, 3)); sourceProductPanel.add(fileEditor); return sourceProductPanel; } private JComponent createRoiPanel() { final JRadioButton wholeProductButton = new JRadioButton("Whole Product"); final JRadioButton useGeometryButton = new JRadioButton("Geometry"); final PropertyDescriptor geometryDescriptor = propertyContainer.getDescriptor(BindingConstants.REGION); if (geometryDescriptor.getValueSet() == null) { useGeometryButton.setEnabled(false); } final JRadioButton useAreaButton = new JRadioButton("Area"); final Map<AbstractButton, Object> buttonGroupValueSet = new HashMap<>(); buttonGroupValueSet.put(wholeProductButton, BindingConstants.ROI_TYPE_PRODUCT); buttonGroupValueSet.put(useGeometryButton, BindingConstants.ROI_TYPE_GEOMETRY); buttonGroupValueSet.put(useAreaButton, BindingConstants.ROI_TYPE_AREA); final ButtonGroup buttonGroup = new ButtonGroup(); buttonGroup.add(wholeProductButton); buttonGroup.add(useGeometryButton); buttonGroup.add(useAreaButton); bindingContext.bind(BindingConstants.ROI_TYPE, buttonGroup, buttonGroupValueSet); final TableLayout layout = GuiHelper.createWeightedTablelayout(1); layout.setCellPadding(2, 0, new Insets(0, 24, 3, 3)); layout.setCellPadding(4, 0, new Insets(0, 24, 3, 3)); final JPanel roiPanel = new JPanel(layout); roiPanel.setBorder(BorderFactory.createTitledBorder("Region of Interest")); final JComboBox geometryComboBox = GuiHelper.createGeometryComboBox(geometryDescriptor, bindingContext); roiPanel.add(wholeProductButton); roiPanel.add(useGeometryButton); roiPanel.add(geometryComboBox); roiPanel.add(useAreaButton); final RegionBoundsInputUI regionBoundsInputUI = new RegionBoundsInputUI(bindingContext); bindingContext.addPropertyChangeListener(BindingConstants.ROI_TYPE, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { final int roiType = (Integer) evt.getNewValue(); if (roiType == BindingConstants.ROI_TYPE_AREA) { regionBoundsInputUI.setEnabled(true); } else { regionBoundsInputUI.setEnabled(false); } } }); regionBoundsInputUI.setEnabled(false); roiPanel.add(regionBoundsInputUI.getUI()); return roiPanel; } private JComponent createTargetDirPanel() { final TableLayout layout = GuiHelper.createWeightedTablelayout(1); final JPanel targetDirPanel = new JPanel(layout); targetDirPanel.setBorder(BorderFactory.createTitledBorder("Target Directory")); final JLabel label = new JLabel(); label.setText("Save files to directory:"); targetDirPanel.add(label); final PropertyDescriptor targetDirectoryDescriptor = propertyContainer.getDescriptor(TARGET_DIRECTORY_BINDING); final JComponent fileEditor = GuiHelper.createFileEditorComponent(targetDirectoryDescriptor, new DirectoryChooserFactory(), bindingContext, false); targetDirPanel.add(fileEditor); return targetDirPanel; } @Override protected void onOK() { try { final List<File> targetFiles; if (exportParameter.isUseSelectedProduct()) { targetFiles = getTargetFiles(appContext.getSelectedProduct().getFileLocation().getAbsolutePath(), exportParameter.getTargetDirectory()); } else { targetFiles = getTargetFiles(exportParameter.getSourceDirectory().getAbsolutePath() + File.separator + "*", exportParameter.getTargetDirectory()); } final List<File> existingFiles = getExistingFiles(targetFiles); if (!existingFiles.isEmpty()) { final String files = listToString(existingFiles); final String message = MessageFormat.format( "The selected target file(s) already exists.\n\nDo you want to overwrite the target file(s)?\n\n" + "{0}", files ); final int answer = JOptionPane.showConfirmDialog(getJDialog(), message, getTitle(), JOptionPane.YES_NO_OPTION); if (answer == JOptionPane.NO_OPTION) { return; } exportParameter.setOverwriteTarget(true); } } catch (IOException e) { showErrorDialog(e.getMessage()); return; } final ConverterSwingWorker worker = new ConverterSwingWorker(appContext, exportParameter); GuiHelper.setDefaultSourceDirectory(exportParameter.getSourceDirectory(), appContext); GuiHelper.setDefaultTargetDirectory(exportParameter.getTargetDirectory(), appContext); worker.execute(); } @Override protected void onClose() { productSelectionListener.dispose(); super.onClose(); } @Override protected void productAdded() { try { updateSelectedProductAndGeometries(propertyContainer); } catch (ValidationException e) { showErrorDialog("Internal error: " + e.getMessage()); } } @Override protected void productRemoved(Product product) { removeProductAndGeometries(product); product.removeProductNodeListener(geometryListener); } @Override protected void geometryAdded() { try { updateSelectedProductAndGeometries(propertyContainer); } catch (ValidationException e) { showErrorDialog("Internal error: " + e.getMessage()); } } @Override protected void geometryRemoved() { try { updateSelectedProductAndGeometries(propertyContainer); } catch (ValidationException e) { showErrorDialog("Internal error: " + e.getMessage()); } } @Override protected void productSelectionChanged() { try { updateSelectedProductAndGeometries(propertyContainer); } catch (ValidationException e) { showErrorDialog("Internal error: " + e.getMessage()); } } }