/*
* 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.nodes;
import org.esa.snap.core.datamodel.Product;
import org.esa.snap.core.datamodel.ProductNode;
import org.esa.snap.core.datamodel.ProductNodeEvent;
import org.esa.snap.core.datamodel.ProductNodeListener;
import org.esa.snap.rcp.SnapApp;
import org.openide.awt.UndoRedo;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Utilities;
import javax.swing.Action;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* @author Norman
*/
abstract class PNNodeSupport implements ProductNodeListener {
static UndoRedo getUndoRedo(Node node) {
return node instanceof UndoRedo.Provider ? ((UndoRedo.Provider) node).getUndoRedo() : null;
}
static boolean isDirectChild(Children children, ProductNode productNode) {
return children != Children.LEAF
&& children.snapshot().stream()
.filter(node -> node instanceof PNNode)
.anyMatch(node -> ((PNNode) node).getProductNode() == productNode);
}
static final PNNodeSupport NONE = new PNNodeSupport() {
@Override
public void nodeChanged(ProductNodeEvent event) {
}
@Override
public void nodeDataChanged(ProductNodeEvent event) {
}
@Override
public void nodeAdded(ProductNodeEvent event) {
}
@Override
public void nodeRemoved(ProductNodeEvent event) {
}
};
static Action[] getContextActions(ProductNode productNode) {
ArrayList<Action> actionList = new ArrayList<>();
Class<?> type = productNode.getClass();
do {
List<? extends Action> actions = Utilities.actionsForPath("Context/Product/" + type.getSimpleName());
actionList.addAll(actions);
type = type.getSuperclass();
} while (type != null && ProductNode.class.isAssignableFrom(type));
return actionList.toArray(new Action[actionList.size()]);
}
static <T extends ProductNode> void performUndoableProductNodeEdit(String name, T productNode, UndoableProductNodeEdit.Edit<T> action, UndoableProductNodeEdit.Edit<T> undo) {
action.edit(productNode);
Product product = productNode.getProduct();
// be paranoid
if (product != null) {
UndoRedo.Manager undoManager = SnapApp.getDefault().getUndoManager(product);
// be paranoid again
if (undoManager != null) {
undoManager.addEdit(new UndoableProductNodeEdit<>(name, productNode, undo, action));
}
}
}
static class PNNodeSupportImpl extends PNNodeSupport {
private final PNNodeBase node;
private final PNGroupBase group;
public PNNodeSupportImpl(PNNodeBase node, PNGroupBase group) {
this.node = node;
this.group = group;
}
@Override
public void nodeChanged(ProductNodeEvent event) {
if (group.shallReactToPropertyChange(event.getPropertyName())) {
final boolean nodeExpanded = NodeExpansionManager.isNodeExpanded(node);
group.refresh();
if (nodeExpanded) {
NodeExpansionManager.expandNode(node);
}
}
delegateProductNodeEvent(l -> l.nodeChanged(event));
}
@Override
public void nodeDataChanged(ProductNodeEvent event) {
delegateProductNodeEvent(l -> l.nodeDataChanged(event));
}
@Override
public void nodeAdded(ProductNodeEvent event) {
refreshChildrenAfterAdd(event.getSourceNode());
delegateProductNodeEvent(l -> l.nodeAdded(event));
}
@Override
public void nodeRemoved(ProductNodeEvent event) {
refreshChildrenAfterRemove(event.getSourceNode());
delegateProductNodeEvent(l -> l.nodeRemoved(event));
}
private void refreshChildrenAfterAdd(ProductNode productNode) {
if (group.isDirectChild(productNode)) {
group.refresh();
}
}
private void refreshChildrenAfterRemove(ProductNode productNode) {
if (node.isDirectChild(productNode)) {
group.refresh();
}
}
private void delegateProductNodeEvent(Consumer<ProductNodeListener> action) {
node.getChildren()
.snapshot()
.stream()
.filter(node -> node instanceof ProductNodeListener)
.map(node -> (ProductNodeListener) node)
.forEach(action);
}
}
public static PNNodeSupport create(PNNodeBase tpnNode, PNGroupBase childFactory) {
return childFactory != null ? new PNNodeSupportImpl(tpnNode, childFactory) : NONE;
}
}