/*
* Copyright (C) 2014 by Array Systems Computing Inc. http://www.array.ca
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.snap.graphbuilder.rcp.dialogs;
import org.esa.snap.core.datamodel.Product;
import org.esa.snap.core.gpf.ui.TargetProductSelectorModel;
import org.esa.snap.core.util.SystemUtils;
import org.esa.snap.engine_utilities.db.DBSearch;
import org.esa.snap.engine_utilities.db.ProductEntry;
import org.esa.snap.engine_utilities.util.ProductFunctions;
import org.esa.snap.graphbuilder.rcp.dialogs.support.FileTable;
import org.esa.snap.graphbuilder.rcp.dialogs.support.FileTableModel;
import org.esa.snap.graphbuilder.rcp.dialogs.support.TargetFolderSelector;
import org.esa.snap.graphbuilder.rcp.utils.DialogUtils;
import org.esa.snap.rcp.SnapApp;
import org.esa.snap.rcp.actions.file.OpenProductAction;
import org.esa.snap.rcp.actions.file.SaveProductAsAction;
import org.esa.snap.rcp.util.ProgressHandleMonitor;
import org.esa.snap.tango.TangoIcons;
import org.esa.snap.ui.AppContext;
import org.esa.snap.ui.FileChooserFactory;
import org.esa.snap.ui.GridLayout2;
import org.netbeans.api.progress.ProgressUtils;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
/**
* ProductSet Panel to handle source and target selection
* User: lveci
* Date: Feb 5, 2009
*/
public class ProductSetPanel extends JPanel implements TableModelListener {
private final FileTable productSetTable;
private final TargetFolderSelector targetProductSelector;
private final AppContext appContext;
private String targetProductNameSuffix = "";
private JPanel buttonPanel = null;
private JButton addButton = null, addAllOpenButton = null, dbQueryButton = null, removeButton = null;
private JButton moveTopButton = null, moveUpButton = null, moveDownButton = null, moveBottomButton = null;
private JButton clearButton = null;
final JLabel countLabel = new JLabel();
private static final ImageIcon addIcon = TangoIcons.actions_list_add(TangoIcons.Res.R22);
private static final ImageIcon addOpenedIcon = new ImageIcon(ProductSetPanel.class.getClassLoader().
getResource("org/esa/snap/graphbuilder/icons/add-opened22.png"));
private static final ImageIcon removeIcon = TangoIcons.actions_list_remove(TangoIcons.Res.R22);
private static final ImageIcon searchIcon = TangoIcons.actions_system_search(TangoIcons.Res.R22);
private static final ImageIcon moveTopIcon = TangoIcons.actions_go_top(TangoIcons.Res.R22);
private static final ImageIcon moveUpIcon = TangoIcons.actions_go_up(TangoIcons.Res.R22);
private static final ImageIcon moveDownIcon = TangoIcons.actions_go_down(TangoIcons.Res.R22);
private static final ImageIcon moveBottomIcon = TangoIcons.actions_go_bottom(TangoIcons.Res.R22);
private static final ImageIcon clearIcon = TangoIcons.actions_edit_clear(TangoIcons.Res.R22);
public ProductSetPanel(final AppContext theAppContext, final String title) {
this(theAppContext, title, new FileTable(), false, false);
}
public ProductSetPanel(final AppContext theAppContext, final String title, final FileTableModel fileModel) {
this(theAppContext, title, new FileTable(fileModel), false, false);
}
public ProductSetPanel(final AppContext theAppContext, final String title, final FileTable fileTable,
final boolean incTrgProduct, final boolean incButtonPanel) {
super(new BorderLayout());
this.appContext = theAppContext;
this.productSetTable = fileTable;
setBorderTitle(title);
final JPanel productSetContent = createComponent(productSetTable);
if (incButtonPanel) {
buttonPanel = createButtonPanel(productSetTable);
productSetContent.add(buttonPanel, BorderLayout.EAST);
}
this.add(productSetContent, BorderLayout.CENTER);
if (incTrgProduct) {
targetProductSelector = new TargetFolderSelector();
final String homeDirPath = SystemUtils.getUserHomeDir().getPath();
final String saveDir = SnapApp.getDefault().getPreferences().get(SaveProductAsAction.PREFERENCES_KEY_LAST_PRODUCT_DIR, homeDirPath);
targetProductSelector.getModel().setProductDir(new File(saveDir));
targetProductSelector.getOpenInAppCheckBox().setText("Open in " + theAppContext.getApplicationName());
targetProductSelector.getOpenInAppCheckBox().setVisible(false);
this.add(targetProductSelector.createPanel(), BorderLayout.SOUTH);
} else {
targetProductSelector = null;
}
fileTable.getModel().addTableModelListener(this);
updateComponents();
}
public void setBorderTitle(final String title) {
if (title != null)
setBorder(BorderFactory.createTitledBorder(title));
}
public JPanel getButtonPanel() {
return buttonPanel;
}
private static JPanel createComponent(final FileTable table) {
final JPanel fileListPanel = new JPanel(new BorderLayout(4, 4));
final JScrollPane scrollPane = new JScrollPane(table);
fileListPanel.add(scrollPane, BorderLayout.CENTER);
return fileListPanel;
}
private void updateComponents() {
final int rowCount = productSetTable.getFileCount();
final boolean enableButtons = (rowCount > 0);
if (dbQueryButton != null)
dbQueryButton.setEnabled(enableButtons);
if (removeButton != null)
removeButton.setEnabled(enableButtons);
if (moveTopButton != null)
moveTopButton.setEnabled(rowCount > 1);
if (moveUpButton != null)
moveUpButton.setEnabled(rowCount > 1);
if (moveDownButton != null)
moveDownButton.setEnabled(rowCount > 1);
if (moveBottomButton != null)
moveBottomButton.setEnabled(rowCount > 1);
if (clearButton != null)
clearButton.setEnabled(enableButtons);
if (addAllOpenButton != null) {
addAllOpenButton.setEnabled(SnapApp.getDefault().getProductManager().getProducts().length > 0);
}
String cntMsg;
if (rowCount == 1) {
cntMsg = rowCount + " Product";
} else {
cntMsg = rowCount + " Products";
}
countLabel.setText(cntMsg);
}
public JPanel createButtonPanel(final FileTable table) {
final FileTableModel tableModel = table.getModel();
final JPanel panel = new JPanel(new GridLayout2(20, 1));
addButton = DialogUtils.createButton("addButton", "Add", addIcon, panel, DialogUtils.ButtonStyle.Icon);
addButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final File[] files = GetFilePath(addButton, "Add Product");
if (files != null) {
addProducts(tableModel, files);
}
}
});
addAllOpenButton = DialogUtils.createButton("addAllOpenButton", "Add Opened", addOpenedIcon, panel, DialogUtils.ButtonStyle.Icon);
addAllOpenButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
addAllOpenProducts(tableModel);
}
});
dbQueryButton = DialogUtils.createButton("dbQueryButton", "DB Query", searchIcon, panel, DialogUtils.ButtonStyle.Icon);
dbQueryButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
try {
final File mstFile = tableModel.getFileAt(0);
if (mstFile.exists()) {
final ProductEntry[] entryList = DBSearch.search(mstFile);
for (ProductEntry entry : entryList) {
if (tableModel.getIndexOf(entry.getFile()) < 0)
tableModel.addFile(entry);
}
}
} catch (Exception ex) {
appContext.handleError("Unable to query DB", ex);
}
}
});
removeButton = DialogUtils.createButton("removeButton", "Remove", removeIcon, panel, DialogUtils.ButtonStyle.Icon);
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final int rowCount = productSetTable.getFileCount();
if (rowCount == 1) {
tableModel.clear();
return;
}
final int[] selRows = table.getSelectedRows();
final java.util.List<File> filesToRemove = new ArrayList<>(selRows.length);
for (int row : selRows) {
filesToRemove.add(tableModel.getFileAt(row));
}
for (File file : filesToRemove) {
int index = tableModel.getIndexOf(file);
tableModel.removeFile(index);
}
}
});
moveTopButton = DialogUtils.createButton("moveTopButton", "Move Top", moveTopIcon, panel, DialogUtils.ButtonStyle.Icon);
moveTopButton.addActionListener(new MoveButtonActionListener(table, tableModel, MOVE.TOP));
moveUpButton = DialogUtils.createButton("moveUpButton", "Move Up", moveUpIcon, panel, DialogUtils.ButtonStyle.Icon);
moveUpButton.addActionListener(new MoveButtonActionListener(table, tableModel, MOVE.UP));
moveDownButton = DialogUtils.createButton("moveDownButton", "Move Down", moveDownIcon, panel, DialogUtils.ButtonStyle.Icon);
moveDownButton.addActionListener(new MoveButtonActionListener(table, tableModel, MOVE.DOWN));
moveBottomButton = DialogUtils.createButton("moveBottomButton", "Move Bottom", moveBottomIcon, panel, DialogUtils.ButtonStyle.Icon);
moveBottomButton.addActionListener(new MoveButtonActionListener(table, tableModel, MOVE.BOTTOM));
clearButton = DialogUtils.createButton("clearButton", "Clear", clearIcon, panel, DialogUtils.ButtonStyle.Icon);
clearButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
tableModel.clear();
}
});
panel.add(addButton);
panel.add(addAllOpenButton);
panel.add(removeButton);
//panel.add(dbQueryButton); //todo
panel.add(moveTopButton);
panel.add(moveUpButton);
panel.add(moveDownButton);
panel.add(moveBottomButton);
panel.add(clearButton);
panel.add(countLabel);
return panel;
}
private static void addProducts(final FileTableModel tableModel, final File[] files) {
final ProgressHandleMonitor pm = ProgressHandleMonitor.create("Populating table");
Runnable operation = () -> {
pm.beginTask("Populating table...", files.length);
for (File file : files) {
if (ProductFunctions.isValidProduct(file)) {
tableModel.addFile(file);
}
pm.worked(1);
}
pm.done();
};
ProgressUtils.runOffEventThreadWithProgressDialog(operation, "Adding Products", pm.getProgressHandle(), true, 50, 1000);
}
private static void addAllOpenProducts(final FileTableModel tableModel) {
final ProgressHandleMonitor pm = ProgressHandleMonitor.create("Populating table");
Runnable operation = () -> {
final Product[] products = SnapApp.getDefault().getProductManager().getProducts();
pm.beginTask("Populating table...", products.length);
for (Product prod : products) {
final File file = prod.getFileLocation();
if (file != null && file.exists()) {
tableModel.addFile(file);
}
pm.worked(1);
}
pm.done();
};
ProgressUtils.runOffEventThreadWithProgressDialog(operation, "Adding Products", pm.getProgressHandle(), true, 50, 1000);
}
/**
* This fine grain notification tells listeners the exact range
* of cells, rows, or columns that changed.
*/
public void tableChanged(TableModelEvent e) {
updateComponents();
}
private static File[] GetFilePath(Component component, String title) {
File[] files = null;
final File openDir = new File(SnapApp.getDefault().getPreferences().
get(OpenProductAction.PREFERENCES_KEY_LAST_PRODUCT_DIR, "."));
final JFileChooser chooser = FileChooserFactory.getInstance().createFileChooser(openDir);
chooser.setMultiSelectionEnabled(true);
chooser.setDialogTitle(title);
if (chooser.showDialog(component, "ok") == JFileChooser.APPROVE_OPTION) {
files = chooser.getSelectedFiles();
SnapApp.getDefault().getPreferences().
put(OpenProductAction.PREFERENCES_KEY_LAST_PRODUCT_DIR, chooser.getCurrentDirectory().getAbsolutePath());
}
return files;
}
public void setTargetProductName(final String name) {
if (targetProductSelector != null) {
final TargetProductSelectorModel targetProductSelectorModel = targetProductSelector.getModel();
targetProductSelectorModel.setProductName(name + getTargetProductNameSuffix());
}
}
public void onApply() {
if (targetProductSelector != null) {
final String productDir = targetProductSelector.getModel().getProductDir().getAbsolutePath();
SnapApp.getDefault().getPreferences().put(SaveProductAsAction.PREFERENCES_KEY_LAST_PRODUCT_DIR, productDir);
}
}
String getTargetProductNameSuffix() {
return targetProductNameSuffix;
}
public void setTargetProductNameSuffix(final String suffix) {
targetProductNameSuffix = suffix;
}
public File getTargetFolder() {
if (targetProductSelector != null) {
final TargetProductSelectorModel targetProductSelectorModel = targetProductSelector.getModel();
return targetProductSelectorModel.getProductDir();
}
return null;
}
public String getTargetFormat() {
if (targetProductSelector != null) {
final TargetProductSelectorModel targetProductSelectorModel = targetProductSelector.getModel();
return targetProductSelectorModel.getFormatName();
}
return null;
}
public void setTargetFolder(final File path) {
if (targetProductSelector != null) {
final TargetProductSelectorModel targetProductSelectorModel = targetProductSelector.getModel();
targetProductSelectorModel.setProductDir(path);
}
}
public File[] getFileList() {
return productSetTable.getFileList();
}
public File[] getSelectedFiles() {
return productSetTable.getModel().getFilesAt(productSetTable.getSelectedRows());
}
public Object getValueAt(final int r, final int c) {
return productSetTable.getModel().getValueAt(r, c);
}
public void setProductFileList(final File[] productFileList) {
productSetTable.setFiles(productFileList);
}
public void setProductEntryList(final ProductEntry[] productEntryList) {
productSetTable.setProductEntries(productEntryList);
}
public boolean isSkippingExistingTargetFiles() {
return targetProductSelector.isSkippingExistingTargetFiles();
}
private enum MOVE { UP, DOWN, TOP, BOTTOM }
private static class MoveButtonActionListener implements ActionListener {
private final FileTable table;
private final FileTableModel tableModel;
private final MOVE movement;
public MoveButtonActionListener(FileTable table, FileTableModel tableModel, MOVE movement) {
this.table = table;
this.tableModel = tableModel;
this.movement = movement;
}
public void actionPerformed(final ActionEvent e) {
final int[] selRows = table.getSelectedRows();
final java.util.List<File> filesToMove = new ArrayList<>(selRows.length);
for (int row : selRows) {
filesToMove.add(tableModel.getFileAt(row));
}
int pos = 0;
for (File file : filesToMove) {
int index = tableModel.getIndexOf(file);
if (index > 0 && movement.equals(MOVE.TOP)) {
tableModel.move(index, pos++);
} else if (index > 0 && movement.equals(MOVE.UP)) {
tableModel.move(index, index - 1);
} else if (index < tableModel.getRowCount() && movement.equals(MOVE.DOWN)) {
tableModel.move(index, index + 1);
} else if (index < tableModel.getRowCount() && movement.equals(MOVE.BOTTOM)) {
tableModel.move(index, tableModel.getRowCount()-1);
}
}
}
}
}