/* * 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 com.bc.ceres.swing.selection.Selection; import com.bc.ceres.swing.selection.SelectionChangeEvent; import com.bc.ceres.swing.selection.SelectionChangeListener; import org.esa.snap.core.datamodel.ProductNode; import org.esa.snap.core.datamodel.ProductNodeEvent; import org.esa.snap.core.datamodel.ProductNodeListenerAdapter; import org.esa.snap.netbeans.docwin.DocumentTopComponent; import org.esa.snap.netbeans.docwin.WindowUtilities; import org.esa.snap.rcp.actions.edit.SelectionActions; import org.esa.snap.rcp.util.ContextGlobalExtender; import org.esa.snap.ui.product.ProductSceneView; import org.openide.awt.UndoRedo; import org.openide.util.Exceptions; import org.openide.util.ImageUtilities; import org.openide.util.Utilities; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.JComponent; import javax.swing.JLayer; import javax.swing.plaf.LayerUI; import javax.swing.text.DefaultEditorKit; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.io.IOException; import java.util.logging.Logger; /** * A document window which displays images. * * @author Norman Fomferra */ public class ProductSceneViewTopComponent extends DocumentTopComponent<ProductNode, ProductSceneView> implements UndoRedo.Provider, SelectionChangeListener { private static final Logger LOG = Logger.getLogger(ProductSceneViewTopComponent.class.getName()); private final ProductSceneView view; private UndoRedo undoRedo; private final ProductNodeListenerAdapter nodeRenameHandler; private Selection selection; public ProductSceneViewTopComponent(ProductSceneView view, UndoRedo undoRedo) { super(view.getRaster()); this.view = view; this.undoRedo = undoRedo != null ? undoRedo : UndoRedo.NONE; this.nodeRenameHandler = new NodeRenameHandler(); this.selection = Selection.EMPTY; setToolTipText(view.getRaster().getDescription()); setIcon(ImageUtilities.loadImage("org/esa/snap/rcp/icons/RsBandAsSwath.gif")); updateDisplayName(); setName(getDisplayName()); /* // checkme - this is ugly and not wanted (nf), the node will either passed in or we'll have // a central node factory, e.g. via an ExtensionObject Node node = null; try { if (raster instanceof Mask) { node = new MNode((Mask) raster, undoRedo); } else if (raster instanceof Band) { node = new BNode((Band) raster, undoRedo); } else if (raster instanceof TiePointGrid) { node = new TPGNode((TiePointGrid) raster, undoRedo); } } catch (IntrospectionException e) { Exceptions.printStackTrace(e); } if (node != null) { setActivatedNodes(new Node[]{node}); } */ setLayout(new BorderLayout()); add(new JLayer<>(this.view, new ProductSceneViewLayerUI()), BorderLayout.CENTER); } /** * Retrieves the ProductSceneView displayed. * @return the scene view, never null */ public ProductSceneView getView() { return view; } @Override public UndoRedo getUndoRedo() { return undoRedo; } @Override public void selectionChanged(SelectionChangeEvent event) { setSelection(event.getSelection()); } @Override public void selectionContextChanged(SelectionChangeEvent event) { } @Override public void componentOpened() { LOG.info(">> componentOpened"); getDocument().getProduct().addProductNodeListener(nodeRenameHandler); } @Override public void componentClosed() { LOG.info(">> componentClosed"); getDocument().getProduct().removeProductNodeListener(nodeRenameHandler); } @Override public void componentSelected() { LOG.info(">> componentSelected"); updateSelectedState(); ContextGlobalExtender contextGlobalExtender = Utilities.actionsGlobalContext().lookup(ContextGlobalExtender.class); if (contextGlobalExtender != null) { contextGlobalExtender.put("view", getView()); } setSelection(getView().getFigureEditor().getSelectionContext().getSelection()); getView().getFigureEditor().getSelectionContext().addSelectionChangeListener(this); } @Override public void componentDeselected() { LOG.info(">> componentDeselected"); updateSelectedState(); getView().getFigureEditor().getSelectionContext().removeSelectionChangeListener(this); setSelection(Selection.EMPTY); ContextGlobalExtender contextGlobalExtender = Utilities.actionsGlobalContext().lookup(ContextGlobalExtender.class); if (contextGlobalExtender != null) { contextGlobalExtender.remove("view"); } } @Override public void documentClosing() { super.documentClosing(); getView().disposeLayers(); getView().dispose(); } private class ProductSceneViewLayerUI extends LayerUI<ProductSceneView> { @Override public void paint(Graphics g, JComponent c) { super.paint(g, c); if (isSelected()) { final int N = 6; final int A = 220; final Color C = new Color(255, 213, 79); for (int i = 0; i < N; i++) { g.setColor(new Color(C.getRed(), C.getGreen(), C.getBlue(), A - i * A / N)); g.drawRect(i, i, getWidth() - 2 * i, getHeight() - 2 * i); } } } } private void updateDisplayName() { setDisplayName(WindowUtilities.getUniqueTitle(getView().getSceneName(), ProductSceneViewTopComponent.class)); } private void setSelection(Selection newSelection) { Selection oldSelection = this.selection; getDynamicContent().remove(oldSelection); if (!newSelection.isEmpty()) { this.selection = newSelection.clone(); getDynamicContent().add(newSelection); } updateActionMap(newSelection); } private void updateActionMap(Selection newSelection) { ActionMap actionMap = getActionMap(); actionMap.put(SelectionActions.SELECT_ALL, new SelectAllAction()); actionMap.put(DefaultEditorKit.pasteAction, new PasteAction()); if (!newSelection.isEmpty()) { actionMap.put(DefaultEditorKit.cutAction, new CutAction()); actionMap.put(DefaultEditorKit.copyAction, new CopyAction()); actionMap.put("delete", new DeleteAction()); actionMap.put(SelectionActions.DESELECT_ALL, new DeselectAllAction()); } else { actionMap.remove(DefaultEditorKit.cutAction); actionMap.remove(DefaultEditorKit.copyAction); actionMap.remove("delete"); actionMap.remove(SelectionActions.DESELECT_ALL); } getDynamicContent().remove(actionMap); getDynamicContent().add(actionMap); } private class CutAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { Selection selection = getLookup().lookup(Selection.class); if (selection != null && !selection.isEmpty()) { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Transferable transferable = getView().getFigureEditor().getFigureSelection().createTransferable(false); clipboard.setContents(transferable, selection); getView().getFigureEditor().deleteSelection(); //JOptionPane.showMessage(WindowManager.getDefault().getMainWindow(), "Cut: " + transferable); } } } private class CopyAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { Selection selection = getLookup().lookup(Selection.class); if (selection != null && !selection.isEmpty()) { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); // todo - when we copy, we actually don't clone the SimpleFeature. Then, if we paste, two figures refer // to the same SimpleFeature. Transferable transferable = getView().getFigureEditor().getFigureSelection().createTransferable(true); clipboard.setContents(transferable, selection); //JOptionPane.showMessage(WindowManager.getDefault().getMainWindow(), "Copy: " + transferable); } } } private class PasteAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Transferable contents = clipboard.getContents(getView()); //JOptionPane.showMessage(WindowManager.getDefault().getMainWindow(), "Paste: " + contents); try { getView().getSelectionContext().insert(contents); } catch (IOException | UnsupportedFlavorException ex) { Exceptions.printStackTrace(ex); } } } private class DeleteAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { getView().getFigureEditor().deleteSelection(); } } private class SelectAllAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { getView().getFigureEditor().selectAll(); } } private class DeselectAllAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { getView().getFigureEditor().setSelection(Selection.EMPTY); } } private class NodeRenameHandler extends ProductNodeListenerAdapter { @Override public void nodeChanged(final ProductNodeEvent event) { if (event.getSourceNode() == getDocument() && event.getPropertyName().equalsIgnoreCase(ProductNode.PROPERTY_NAME_NAME)) { updateDisplayName(); } } } }