/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* 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.rcp.layermanager;
import com.bc.ceres.glayer.Layer;
import com.bc.ceres.glayer.support.AbstractLayerListener;
import com.bc.ceres.glayer.support.LayerUtils;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.util.WeakHashMap;
class LayerTreeModel implements TreeModel {
private final Layer rootLayer;
private final WeakHashMap<TreeModelListener, Object> treeModelListeners;
LayerTreeModel(final Layer rootLayer) {
this.rootLayer = rootLayer;
this.rootLayer.addListener(new LayerListener());
treeModelListeners = new WeakHashMap<>();
}
///////////////////////////////////////////////////////////////////////////
// TreeModel interface
@Override
public Object getRoot() {
return rootLayer;
}
@Override
public Object getChild(Object parent, int index) {
return ((Layer) parent).getChildren().get(index);
}
@Override
public int getChildCount(Object parent) {
return ((Layer) parent).getChildren().size();
}
@Override
public boolean isLeaf(Object node) {
return ((Layer) node).getChildren().isEmpty();
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
if (newValue instanceof String) {
Layer layer = (Layer) path.getLastPathComponent();
String oldName = layer.getName();
String newName = (String) newValue;
if (!oldName.equals(newName)) {
layer.setName(newName);
fireTreeNodeChanged(layer);
}
}
}
@Override
public int getIndexOfChild(Object parent, Object child) {
return ((Layer) parent).getChildren().indexOf(child);
}
@Override
public void addTreeModelListener(TreeModelListener l) {
treeModelListeners.put(l, "");
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
treeModelListeners.remove(l);
}
// TreeModel interface
///////////////////////////////////////////////////////////////////////////
public Layer getRootLayer() {
return rootLayer;
}
protected void fireTreeNodeChanged(Layer layer) {
TreeModelEvent event = createTreeModelEvent(layer);
for (TreeModelListener treeModelListener : treeModelListeners.keySet()) {
treeModelListener.treeNodesChanged(event);
}
}
protected void fireTreeStructureChanged(Layer parentLayer) {
TreeModelEvent event = createTreeModelEvent(parentLayer);
for (TreeModelListener treeModelListener : treeModelListeners.keySet()) {
treeModelListener.treeStructureChanged(event);
}
}
protected void fireTreeNodesInserted(Layer parentLayer) {
TreeModelEvent event = createTreeModelEvent(parentLayer);
for (TreeModelListener treeModelListener : treeModelListeners.keySet()) {
treeModelListener.treeNodesInserted(event);
}
}
protected void fireTreeNodesRemoved(Layer parentLayer) {
TreeModelEvent event = createTreeModelEvent(parentLayer);
for (TreeModelListener treeModelListener : treeModelListeners.keySet()) {
treeModelListener.treeNodesRemoved(event);
}
}
private TreeModelEvent createTreeModelEvent(Layer layer) {
Layer[] parentPath = LayerUtils.getLayerPath(rootLayer, layer);
return new TreeModelEvent(this, parentPath);
}
private class LayerListener extends AbstractLayerListener {
@Override
public void handleLayerPropertyChanged(Layer layer, PropertyChangeEvent event) {
SwingUtilities.invokeLater(() -> fireTreeNodeChanged(layer));
}
@Override
public void handleLayerDataChanged(Layer layer, Rectangle2D modelRegion) {
SwingUtilities.invokeLater(() -> fireTreeNodeChanged(layer));
}
@Override
public void handleLayersAdded(Layer parentLayer, Layer[] childLayers) {
SwingUtilities.invokeLater(() -> fireTreeStructureChanged(parentLayer));
}
@Override
public void handleLayersRemoved(Layer parentLayer, Layer[] childLayers) {
SwingUtilities.invokeLater(() -> fireTreeStructureChanged(parentLayer));
}
}
}