/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.esa.snap.rcp.windows;
import org.esa.snap.core.datamodel.Product;
import org.esa.snap.core.util.DummyProductBuilder;
import org.esa.snap.core.util.SystemUtils;
import org.esa.snap.rcp.SnapApp;
import org.esa.snap.rcp.actions.file.OpenProductAction;
import org.esa.snap.rcp.nodes.ProductGroupNode;
import org.esa.snap.runtime.Config;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.explorer.view.BeanTreeView;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.openide.windows.IOProvider;
import org.openide.windows.InputOutput;
import org.openide.windows.TopComponent;
import javax.swing.ActionMap;
import javax.swing.text.DefaultEditorKit;
import java.awt.BorderLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
/**
* The product explorer tool window.
*
* @author Norman
*/
@TopComponent.Description(
preferredID = "ProductExplorerTopComponent",
iconBase = "org/esa/snap/rcp/icons/RsProduct16.gif",
persistenceType = TopComponent.PERSISTENCE_ALWAYS
)
@TopComponent.Registration(
mode = "explorer",
openAtStartup = true,
position = 10)
@ActionID(category = "Window", id = "org.esa.snap.rcp.window.ProductExplorerTopComponent")
@ActionReference(path = "Menu/View/Tool Windows", position = 0)
@TopComponent.OpenActionRegistration(
displayName = "#CTL_ProductExplorerTopComponentName",
preferredID = "ProductExplorerTopComponent"
)
@NbBundle.Messages({
"CTL_ProductExplorerTopComponentName=Product Explorer",
"CTL_ProductExplorerTopComponentDescription=Lists all open products",
})
public class ProductExplorerTopComponent extends TopComponent implements ExplorerManager.Provider {
private final ExplorerManager explorerManager = new ExplorerManager();
private DndBeanTreeView treeView;
public ProductExplorerTopComponent() {
initComponents();
setName("Product_Explorer");
setDisplayName(Bundle.CTL_ProductExplorerTopComponentName());
setToolTipText(Bundle.CTL_ProductExplorerTopComponentDescription());
putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, Boolean.TRUE);
putClientProperty(TopComponent.PROP_KEEP_PREFERRED_SIZE_WHEN_SLIDED_IN, Boolean.TRUE);
}
private void initComponents() {
setLayout(new BorderLayout());
// 1. Add an explorer view, in this case BeanTreeView:
// DndBeanTreeView has the purpose to enable Drag&Drop an the tree
treeView = new DndBeanTreeView();
treeView.setRootVisible(false);
add(treeView, BorderLayout.CENTER);
// 2. Create a node hierarchy:
if (Config.instance().preferences().getBoolean("snap.debug.loadTestProducts", false)) {
//Product[] products = TestProducts.createProducts();
SystemUtils.LOG.info("Loading test products...");
Product[] products = DummyProductBuilder.createTestProducts();
for (Product product : products) {
SystemUtils.LOG.info("Loading test product " + product.getName());
SnapApp.getDefault().getProductManager().addProduct(product);
}
}
Node rootNode = new ProductGroupNode(SnapApp.getDefault().getProductManager());
// 3. Set the root of the node hierarchy on the ExplorerManager:
explorerManager.setRootContext(rootNode);
ActionMap map = this.getActionMap();
map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(explorerManager));
map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(explorerManager));
map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(explorerManager));
map.put("delete", ExplorerUtils.actionDelete(explorerManager, true));
associateLookup(ExplorerUtils.createLookup(explorerManager, map));
final InputOutput io = IOProvider.getDefault().getIO("Explorer Selection", true);
explorerManager.addPropertyChangeListener(new PropertyChangeListener() {
final DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("selectedNodes")) {
Node[] selectedNode = (Node[]) evt.getNewValue();
for (Node node : selectedNode) {
String timeText = timeFormat.format(System.currentTimeMillis());
io.getOut().println(timeText + ": " + node.getDisplayName());
}
}
}
});
}
@Override
public ExplorerManager getExplorerManager() {
return explorerManager;
}
@Override
public void componentOpened() {
// add custom code on component opening
}
@Override
public void componentClosed() {
// add custom code on component closing
}
void writeProperties(java.util.Properties p) {
// better to version settings since initial version as advocated at
// http://wiki.apidesign.org/wiki/PropertyFiles
p.setProperty("version", "1.0");
// store your settings
}
void readProperties(java.util.Properties p) {
String version = p.getProperty("version");
// read your settings according to their version
}
public boolean isNodeExpanded(Node node) {
return treeView.isExpanded(node);
}
public void expandNode(Node node) {
treeView.expandNode(node);
}
private static class DndBeanTreeView extends BeanTreeView {
public DndBeanTreeView() {
tree.setDropTarget(new DropTarget(tree, new ProductExplorerDropTarget()));
}
}
private static class ProductExplorerDropTarget extends DropTargetAdapter {
@Override
public void drop(DropTargetDropEvent dtde) {
try {
final Transferable transferable = dtde.getTransferable();
if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
final List<File> fileList = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor);
if (fileList.size() > 0) {
final OpenProductAction open = new OpenProductAction();
open.setFiles(fileList.toArray(new File[fileList.size()]));
dtde.dropComplete(Boolean.TRUE.equals(open.execute()));
}
} else {
dtde.rejectDrop();
}
} catch (UnsupportedFlavorException | IOException ignored) {
dtde.rejectDrop();
}
}
}
}