/*
* Copyright (C) 2015 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.productlibrary.rcp.toolviews;
import org.esa.snap.engine_utilities.db.ProductEntry;
import org.esa.snap.engine_utilities.util.ResourceUtils;
import org.esa.snap.graphbuilder.rcp.dialogs.BatchGraphDialog;
import org.esa.snap.graphbuilder.rcp.progress.LabelBarProgressMonitor;
import org.esa.snap.graphbuilder.rcp.utils.ClipboardUtils;
import org.esa.snap.graphbuilder.rcp.utils.DialogUtils;
import org.esa.snap.productlibrary.rcp.toolviews.extensions.ProductLibraryActionExt;
import org.esa.snap.productlibrary.rcp.toolviews.extensions.ProductLibraryActionExtDescriptor;
import org.esa.snap.productlibrary.rcp.toolviews.extensions.ProductLibraryActionExtRegistry;
import org.esa.snap.productlibrary.rcp.toolviews.model.SortingDecorator;
import org.esa.snap.productlibrary.rcp.utils.ProductOpener;
import org.esa.snap.rcp.SnapApp;
import org.esa.snap.rcp.util.Dialogs;
import org.esa.snap.ui.SnapFileChooser;
import org.esa.snap.ui.UIUtils;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
/**
* actions on product entry selections
*/
public class ProductLibraryActions {
private static final ImageIcon selectAllIcon = UIUtils.loadImageIcon("/org/esa/snap/productlibrary/icons/select-all24.png", ProductLibraryToolView.class);
private static final ImageIcon openIcon = UIUtils.loadImageIcon("/org/esa/snap/productlibrary/icons/open24.png", ProductLibraryToolView.class);
private static final ImageIcon copyIcon = UIUtils.loadImageIcon("/org/esa/snap/productlibrary/icons/copy24.png", ProductLibraryToolView.class);
private static final ImageIcon batchIcon = UIUtils.loadImageIcon("/org/esa/snap/productlibrary/icons/batch24.png", ProductLibraryToolView.class);
private final ProductLibraryToolView toolView;
private JButton selectAllButton, openAllSelectedButton, copySelectedButton, batchProcessButton;
private List<ProductLibraryActionExt> actionExtList = new ArrayList<>();
private JMenuItem copyToItem, moveToItem, deleteItem;
private File currentDirectory;
private final java.util.List<ProductLibraryActionListener> listenerList = new ArrayList<>(1);
public ProductLibraryActions(final ProductLibraryToolView toolView) {
this.toolView = toolView;
}
public JPanel createCommandPanel() {
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
selectAllButton = DialogUtils.createButton("selectAllButton", "Select all", selectAllIcon, panel, DialogUtils.ButtonStyle.Icon);
selectAllButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
toolView.selectAll();
}
});
openAllSelectedButton = DialogUtils.createButton("openAllSelectedButton", "Open selected", openIcon, panel, DialogUtils.ButtonStyle.Icon);
openAllSelectedButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
performOpenAction();
}
});
copySelectedButton = DialogUtils.createButton("copySelectedButton", "Copy to clipboard", copyIcon, panel, DialogUtils.ButtonStyle.Icon);
copySelectedButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
performCopyAction();
}
});
batchProcessButton = DialogUtils.createButton("batchProcessButton", "Batch", batchIcon, panel, DialogUtils.ButtonStyle.Icon);
batchProcessButton.setToolTipText("Right click to select a graph");
batchProcessButton.setComponentPopupMenu(createGraphPopup());
batchProcessButton.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
batchProcess(toolView.getSelectedProductEntries(), null);
}
});
panel.add(selectAllButton);
panel.add(openAllSelectedButton);
panel.add(copySelectedButton);
panel.add(batchProcessButton);
panel.add(Box.createRigidArea(new Dimension(24,24))); // separator
for(ProductLibraryActionExtDescriptor desc : ProductLibraryActionExtRegistry.getInstance().getDescriptors()) {
final ProductLibraryActionExt action = desc.createActionExt(this);
actionExtList.add(action);
final JButton button = action.getButton(panel);
panel.add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
action.performAction();
}
});
}
return panel;
}
private static void batchProcess(final ProductEntry[] productEntryList, final File graphFile) {
final BatchGraphDialog batchDlg = new BatchGraphDialog(SnapApp.getDefault().getAppContext(),
"Batch Processing", "batchProcessing", false);
batchDlg.setInputFiles(productEntryList);
if (graphFile != null) {
batchDlg.LoadGraph(graphFile);
}
batchDlg.show();
}
public void selectionChanged(final ProductEntry[] selections) {
final boolean enable = selections.length > 0;
openAllSelectedButton.setEnabled(enable);
copySelectedButton.setEnabled(enable);
batchProcessButton.setEnabled(enable);
for(ProductLibraryActionExt action : actionExtList) {
action.selectionChanged(selections);
}
}
/**
* Copy the selected file list to the clipboard
*/
private void performCopyAction() {
final File[] fileList = toolView.getSelectedFiles();
if (fileList.length != 0)
ClipboardUtils.copyToClipboard(fileList);
}
private void performFileAction(final ProductFileHandler.TYPE operationType) {
final File targetFolder;
if(operationType.equals(ProductFileHandler.TYPE.DELETE)) {
targetFolder = null;
} else {
targetFolder = promptForRepositoryBaseDir();
if (targetFolder == null) return;
}
final ProductEntry[] entries = toolView.getSelectedProductEntries();
final LabelBarProgressMonitor progMon = toolView.createLabelBarProgressMonitor();
final ProductFileHandler fileHandler = new ProductFileHandler(entries, operationType, targetFolder, progMon);
fileHandler.addListener(new MyFileHandlerListener());
fileHandler.execute();
}
public File[] getSelectedFiles() {
return toolView.getSelectedFiles();
}
public ProductEntry[] getSelectedProductEntries() {
return toolView.getSelectedProductEntries();
}
public void performOpenAction() {
ProductOpener.openProducts(getSelectedFiles());
}
public void findSlices(final int dataTakeId) {
toolView.findSlices(dataTakeId);
}
public File promptForRepositoryBaseDir() {
final JFileChooser fileChooser = createDirectoryChooser();
fileChooser.setCurrentDirectory(currentDirectory);
final int response = fileChooser.showOpenDialog(SnapApp.getDefault().getMainFrame());
currentDirectory = fileChooser.getCurrentDirectory();
File selectedDir = fileChooser.getSelectedFile();
if (selectedDir != null && selectedDir.isFile())
selectedDir = selectedDir.getParentFile();
if (response == JFileChooser.APPROVE_OPTION) {
return selectedDir;
}
return null;
}
private static JFileChooser createDirectoryChooser() {
final JFileChooser fileChooser = new SnapFileChooser();
fileChooser.setAcceptAllFileFilterUsed(false);
fileChooser.setFileFilter(new FileFilter() {
@Override
public boolean accept(final File f) {
return f.isDirectory();
}
@Override
public String getDescription() {
return "Directories"; /* I18N */
}
});
fileChooser.setDialogTitle("Select Directory"); /* I18N */
fileChooser.setMultiSelectionEnabled(false);
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChooser.setApproveButtonText("Select"); /* I18N */
fileChooser.setApproveButtonMnemonic('S');
return fileChooser;
}
// Context Menu
public JPopupMenu createEntryTablePopup() {
final JPopupMenu popup = new JPopupMenu();
final JMenuItem selectAllItem = new JMenuItem("Select All");
selectAllItem.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
toolView.selectAll();
}
});
popup.add(selectAllItem);
final JMenuItem selectNoneItem = new JMenuItem("Select None");
selectNoneItem.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
toolView.selectNone();
}
});
popup.add(selectNoneItem);
final JMenuItem openSelectedItem = new JMenuItem("Open Selected");
openSelectedItem.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
performOpenAction();
}
});
popup.add(openSelectedItem);
final JMenuItem copySelectedItem = new JMenuItem("Copy Selected");
copySelectedItem.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
performCopyAction();
}
});
popup.add(copySelectedItem);
popup.addSeparator();
copyToItem = new JMenuItem("Copy Selected Files To...");
copyToItem.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
performFileAction(ProductFileHandler.TYPE.COPY_TO);
}
});
popup.add(copyToItem);
moveToItem = new JMenuItem("Move Selected Files To...");
moveToItem.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
performFileAction(ProductFileHandler.TYPE.MOVE_TO);
}
});
popup.add(moveToItem);
deleteItem = new JMenuItem("Delete Selected Files");
deleteItem.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final Dialogs.Answer status = Dialogs.requestDecision("Deleting selected files",
"Are you sure you want to delete these products",
true, null);
if (status == Dialogs.Answer.YES)
performFileAction(ProductFileHandler.TYPE.DELETE);
}
});
popup.add(deleteItem);
final JMenuItem exploreItem = new JMenuItem("Browse Folder");
exploreItem.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
final ProductEntry entry = toolView.getEntryOverMouse();
if (entry != null && entry instanceof ProductEntry) {
final ProductEntry prodEntry = (ProductEntry) entry;
try {
Desktop.getDesktop().open(prodEntry.getFile().getParentFile());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}
});
popup.add(exploreItem);
popup.addSeparator();
final JMenu sortMenu = new JMenu("Sort By");
popup.add(sortMenu);
sortMenu.add(createSortItem("Product Name", SortingDecorator.SORT_BY.NAME));
sortMenu.add(createSortItem("Product Type", SortingDecorator.SORT_BY.TYPE));
sortMenu.add(createSortItem("Acquisition Date", SortingDecorator.SORT_BY.DATE));
sortMenu.add(createSortItem("Mission", SortingDecorator.SORT_BY.MISSON));
sortMenu.add(createSortItem("File Size", SortingDecorator.SORT_BY.FILESIZE));
return popup;
}
private JMenuItem createSortItem(final String name, final SortingDecorator.SORT_BY sortBy) {
final JMenuItem item = new JMenuItem(name);
item.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
toolView.sort(sortBy);
}
});
return item;
}
public JPopupMenu createGraphPopup() {
final Path graphPath = ResourceUtils.getGraphFolder("");
final JPopupMenu popup = new JPopupMenu();
if (Files.exists(graphPath)) {
createGraphMenu(popup, graphPath.toFile());
}
return popup;
}
private void createGraphMenu(final JPopupMenu menu, final File path) {
final File[] filesList = path.listFiles();
if (filesList == null || filesList.length == 0) return;
for (final File file : filesList) {
final String name = file.getName();
if (file.isDirectory() && !file.isHidden() && !name.equalsIgnoreCase("internal")) {
final JMenu subMenu = new JMenu(name);
menu.add(subMenu);
createGraphMenu(subMenu, file);
} else if (name.toLowerCase().endsWith(".xml")) {
final JMenuItem item = new JMenuItem(name.substring(0, name.indexOf(".xml")));
item.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
//todo
if (batchProcessButton.isEnabled())
batchProcess(toolView.getSelectedProductEntries(), file);
}
});
menu.add(item);
}
}
}
private void createGraphMenu(final JMenu menu, final File path) {
final File[] filesList = path.listFiles();
if (filesList == null || filesList.length == 0) return;
for (final File file : filesList) {
final String name = file.getName();
if (file.isDirectory() && !file.isHidden() && !name.equalsIgnoreCase("internal")) {
final JMenu subMenu = new JMenu(name);
menu.add(subMenu);
createGraphMenu(subMenu, file);
} else if (name.toLowerCase().endsWith(".xml")) {
final JMenuItem item = new JMenuItem(name.substring(0, name.indexOf(".xml")));
item.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
//todo
if (batchProcessButton.isEnabled())
batchProcess(toolView.getSelectedProductEntries(), file);
}
});
menu.add(item);
}
}
}
public void updateContextMenu(final ProductEntry[] selections) {
boolean allValid = true;
for (ProductEntry entry : selections) {
if (!ProductFileHandler.canMove(entry)) {
allValid = false;
break;
}
}
copyToItem.setEnabled(allValid);
moveToItem.setEnabled(allValid);
deleteItem.setEnabled(allValid);
}
public void addListener(final ProductLibraryActionListener listener) {
if (!listenerList.contains(listener)) {
listenerList.add(listener);
}
}
private void notifyDirectoryChanged() {
for(ProductLibraryActionListener listener : listenerList) {
listener.notifyDirectoryChanged();
}
}
private void notifySelectionChanged() {
for(ProductLibraryActionListener listener : listenerList) {
listener.notifySelectionChanged();
}
}
public interface ProductLibraryActionListener {
void notifyDirectoryChanged();
void notifySelectionChanged();
}
private class MyFileHandlerListener implements ProductFileHandler.ProductFileHandlerListener {
public void notifyMSG(final ProductFileHandler fileHandler, final MSG msg) {
if (msg.equals(ProductFileHandler.ProductFileHandlerListener.MSG.DONE)) {
final java.util.List<DBScanner.ErrorFile> errorList = fileHandler.getErrorList();
if (!errorList.isEmpty()) {
toolView.handleErrorList(errorList);
}
if(fileHandler.getOperationType().equals(ProductFileHandler.TYPE.MOVE_TO) ||
fileHandler.getOperationType().equals(ProductFileHandler.TYPE.DELETE)) {
notifyDirectoryChanged();
}
}
toolView.UpdateUI();
}
}
}