All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.limetri.client.mapviewer.swing.jxmap.MapDataManager Maven / Gradle / Ivy

The newest version!
/**
 *  Copyright (C) 2008-2013 LimeTri. All rights reserved.
 *
 *  AgroSense 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.
 *
 *  There are special exceptions to the terms and conditions of the GPLv3 as it
 *  is applied to this software, see the FLOSS License Exception
 *  .
 *
 *  AgroSense 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
 *  AgroSense. If not, see .
 */
package eu.limetri.client.mapviewer.swing.jxmap;

import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import nl.cloudfarming.eventbus.GuiEvent;
import nl.cloudfarming.eventbus.GuiEventBus;
import nl.cloudfarming.eventbus.GuiEventKey;
import nl.cloudfarming.eventbus.GuiEventListener;

import org.openide.explorer.ExplorerManager;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.NodeEvent;
import org.openide.nodes.NodeListener;
import org.openide.nodes.NodeMemberEvent;
import org.openide.nodes.NodeReorderEvent;

import eu.limetri.client.mapviewer.api.Layer;
import eu.limetri.client.mapviewer.api.LayerDropTarget;
import eu.limetri.client.mapviewer.api.event.GeoEvent;
import eu.limetri.client.mapviewer.swing.jxmap.layerlist.RemovableLayerListNode;

/**
 * The MapDataManager provides an optional convenience explorerManager for
 * managing data on the map. It is useful to use in combination with a MapView.
 *
 * In order to receive and manage nodes dropped on the map, the
 * MapDataManager should register itself on the {@link MapView} as
 * a {@link LayerDropTarget}.
 * mapView.addLayerDropTarget(mapDataManager);
 *
 * In order to use the MapDataManager as data manager for the map, the
 * TopComponent containing the MapView should implement {@link ExplorerManager.Provider}
 * and have getExplorerManager to return {@link MapDataManager#getExplorerManager()
 * }
 *
 * @author Timon Veenstra
 */
public class MapDataManager implements ExplorerManager.Provider, LayerDropTarget {

    private final ExplorerManager explorerManager = new ExplorerManager();
    private final List layerNodes = new ArrayList<>();
    private final MapDataRootNodeChildFactory childFactory = new MapDataRootNodeChildFactory();
    private final Node rootNode = new AbstractNode(Children.create(childFactory, false));
    private final NewLayerListener newLayerListener = new NewLayerListener();
    private final DiscardedLayerListener discardedLayerListener = new DiscardedLayerListener();
    private static final Logger LOGGER = Logger.getLogger(MapDataManager.class.getCanonicalName());
    private NodeDestroyedListener destroyedListener = new NodeDestroyedListener();

    public MapDataManager() {
        explorerManager.setRootContext(rootNode);
        explorerManager.getRootContext().setDisplayName("");
        rootNode.getChildren();
        explorerManager.setExploredContext(rootNode);

        GuiEventBus.addListener(newLayerListener);
        GuiEventBus.addListener(discardedLayerListener);

        LOGGER.log(Level.FINE, "MapDataManager::ExplorerManager: {0}", System.identityHashCode(explorerManager));

    }

    @Override
    public ExplorerManager getExplorerManager() {
        return explorerManager;
    }

    @Override
    public boolean dropNode(Node node) {
        assert node.getLookup().lookup(Layer.class) != null : "Dropped node should always have a layer in its lookup";
        addLayerNode(node);
        return true;
    }

    public void addLayerNode(Node layerNode) {
        // prevent duplicates
        if (!layerNodes.contains(layerNode)) {
            layerNodes.add(layerNode);
            
            // Listen for node destroy
            
            layerNode.addNodeListener(destroyedListener);
            childFactory.refresh();
            Children c = rootNode.getChildren();
            for (Node node : c.getNodes()) {
                explorerManager.setExploredContext(node);
            }
        }
    }

    public void removeLayerNode(Node layerNode) {
        if (layerNodes.contains(layerNode)) {
            layerNodes.remove(layerNode);
            layerNode.removeNodeListener(destroyedListener);
            childFactory.refresh();
        }
    }

    public Node[] getLayerNodes() {
        return this.layerNodes.toArray(new Node[this.layerNodes.size()]);
    }

    private class DiscardedLayerListener implements GuiEventListener {

        @Override
        public void onEvent(GuiEvent event) {
            Node eventNode = event.getContent();
            Layer layer = eventNode.getLookup().lookup(Layer.class);
            if (layer == null) {
                // no layer found, soft fail
                LOGGER.warning("Layer expected in lookup of node passed on with DiscardedLayerEvent");
                return;
            }
            for (Node node : getLayerNodes()) {
                if (layer.equals(node.getLookup().lookup(Layer.class))) {
                    removeLayerNode(node);
                }
            }
        }

        @Override
        public boolean listensTo(GuiEventKey guiEventKey) {
            return GeoEvent.DISCARD_LAYER.equals(guiEventKey);
        }

        @Override
        public String getModuleName() {
            return "nb-mapviewer-swing";
        }
    }

    /**
     * Listener registered on the {@link GuiEventBus} listening to {@link LayerEventKey.NEW_LAYER}
     * events.
     *
     */
    private class NewLayerListener implements GuiEventListener {

        @Override
        public void onEvent(GuiEvent event) {
            final Node node = event.getContent();
            if (node != null) {
                addLayerNode(node);
            }
        }

        @Override
        public boolean listensTo(GuiEventKey guiEventKey) {
            return GeoEvent.NEW_LAYER.equals(guiEventKey);
        }

        @Override
        public String getModuleName() {
            return "nb-mapviewer-swing";
        }
    }
    
    private class NodeDestroyedListener implements NodeListener{

        @Override
        public void childrenAdded(NodeMemberEvent ev) {
        }

        @Override
        public void childrenRemoved(NodeMemberEvent ev) {
        }

        @Override
        public void childrenReordered(NodeReorderEvent ev) {
        }

        @Override
        public void nodeDestroyed(NodeEvent ev) {
            removeLayerNode(ev.getNode());
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
        }
        
    }

    private class MapDataRootNodeChildFactory extends ChildFactory {

        public void refresh() {
            refresh(true);
        }

        @Override
        protected boolean createKeys(List toPopulate) {
            toPopulate.addAll(Arrays.asList(getLayerNodes()));
            return true;
        }

        @Override
        protected Node createNodeForKey(final Node key) {
            return new RemovableLayerListNode(key); 
//            return new FilterNode(key, new FilterMapDataChildren(key)); tady layerLIstNode //unable to remove node from layerlist
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy