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

eu.limetri.client.mapviewer.nb.jxmap.MapView Maven / Gradle / Ivy

There is a newer version: 1.4.4
Show newest version
/**
 * Copyright (C) 2008-2012 AgroSense Foundation.
 *
 * 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.nb.jxmap;

import java.awt.BorderLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.util.HashSet;
import java.util.Set;

import javax.swing.ActionMap;
import javax.swing.JComponent;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;


import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
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 org.openide.util.Lookup;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;

import eu.limetri.client.mapviewer.api.Layer;
import eu.limetri.client.mapviewer.api.LayerDropTarget;
import eu.limetri.client.mapviewer.api.LayerInfo;
import eu.limetri.client.mapviewer.nb.jxmap.layerlist.LayerListController;
import eu.limetri.client.mapviewer.nb.jxmap.map.RootMapPanelController;

/**
 * A view on data managed by an explorer manager. The nodes are represented on a
 * map.
 *
 * Layer nodes are displayed in a layerlist LayerObject nodes contain the
 * capability to be displayed on the map
 *
 *
 *
 * @author Timon Veenstra
 */
//FIXME cleanup
public class MapView extends JComponent implements Lookup.Provider {

    private final LayerListController layerListController = new LayerListController();
    private final RootMapPanelController mapPanelController = new RootMapPanelController(layerListController);
    private final RootNodeListener rootNodeListener = new RootNodeListener();
//    private final Map layerInfoMap = new HashMap();
    /**
     * Listener to nearly everything
     */
    transient MapView.Listener managerListener;
    /**
     * weak variation of the listener for property change on the explorer
     * manager
     */
    transient PropertyChangeListener wlpc;
    /**
     * weak variation of the listener for vetoable change on the explorer
     * manager
     */
    transient VetoableChangeListener wlvc;
    /**
     * Explorer manager to work with. Is not null only if the component is
     * showing in components hierarchy
     */
    private transient ExplorerManager manager;
    private final LookupManager lookupManager = new LookupManager();

    /*
     * Initilizes the view.
     */
    @Override
    public void addNotify() {
        super.addNotify();

        ExplorerManager em = ExplorerManager.find(this);

        if (em != manager) {
            if (manager != null) {
                manager.removeVetoableChangeListener(wlvc);
                manager.removePropertyChangeListener(wlpc);
            }

            manager = em;

            lookupManager.update();

            manager.getRootContext().addNodeListener(rootNodeListener);


            Node root = manager.getRootContext();
            if (root != null) {
                addLayersForNewNodes(root);
            }


            manager.addVetoableChangeListener(wlvc = WeakListeners.vetoableChange(managerListener, manager));
            manager.addPropertyChangeListener(wlpc = WeakListeners.propertyChange(managerListener, manager));
            updateSelection();
        }
    }

    public MapView() {
        setLayout(new BorderLayout());
        add(mapPanelController.getPanel(), BorderLayout.CENTER);
    }

    @Override
    public void removeNotify() {
        super.removeNotify();
    }

    public void addLayerDropTarget(LayerDropTarget dropTarget) {
        mapPanelController.addLayerDropTarget(dropTarget);
    }

    @Override
    public Lookup getLookup() {
        return lookupManager.getProxy();
    }

    /**
     * manages internal lookup and provides proxy
     */
    private class LookupManager implements Lookup.Provider {

        private Lookup internal = Lookup.EMPTY;
        private Lookup proxy = Lookups.proxy(this);

        public LookupManager() {
        }

        void update() {
            internal = new ProxyLookup(ExplorerUtils.createLookup(manager, new ActionMap()), layerListController.getLookup());
        }

        @Override
        public Lookup getLookup() {
            return internal;
        }

        public Lookup getProxy() {
            return proxy;
        }
    }

    /**
     * Recurse through nodes starting from root and add all LayerNodes (which
     * are nodes with a Layer object in their lookup)
     *
     * @param root
     */
    void addLayersForNewNodes(Node root) {
        Layer layer = root.getLookup().lookup(Layer.class);
        // only add nodes with a layer in their lookup
        if (layer != null) {
            //
            // add a property change listener to the layer to respond to propertychanges (refresh)
            //
//            LayerPropertyChangeListener lpcl = new LayerPropertyChangeListener();
//            layer.addPropertyChangeListener(lpcl);
            //
            // add a layernode listener to listen to changes in the layer node 
            //
            LayerNodeListener layerNodeListener = new LayerNodeListener();
            root.addNodeListener(layerNodeListener);
            // sync the map explorer manager on the Layer
            Layer.Sync.SyncMapExplorer(layer, manager);
            //
            // add the layer node to the mapPanel through its controller
            //
            LayerInfo layerInfo = root.getLookup().lookup(LayerInfo.class);
            if (layerInfo == null) {
                layerInfo = new LayerInfo();
            }


            mapPanelController.addLayerNode(root, layerInfo);
            layerListController.addLayerNode(root, layerInfo);
        }
        //Expand the node so the children are created
        root.getChildren().getNodes();
    }

    /**
     * Removes layers related to provided nodes and childnodes from the map.
     *
     * @param layerNodes
     */
    void removeLayers(Node... layerNodes) {
        for (Node root : layerNodes) {
            Layer layer = root.getLookup().lookup(Layer.class);
            // only add nodes with a layer in their lookup
            if (layer != null) {
                mapPanelController.removeLayerNode(root);
                layerListController.removeLayerNode(root);
            }
        }
    }

    /**
     * listener for changes in nodes in the explorer manager
     */
    private class RootNodeListener implements NodeListener {

        @Override
        public void childrenAdded(NodeMemberEvent ev) {
            for (Node node : ev.getDelta()) {
                addLayersForNewNodes(node);
            }
        }

        @Override
        public void childrenRemoved(NodeMemberEvent ev) {
            removeLayers(ev.getDelta());
        }

        @Override
        public void childrenReordered(NodeReorderEvent ev) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void nodeDestroyed(NodeEvent ev) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

    /**
     * Listens to changes on a layernode
     *
     */
    private class LayerNodeListener implements NodeListener {

        private void refreshAffectedLayerNodes(NodeMemberEvent ev) {
            Set layerNodes = new HashSet<>();
            for (Node node : ev.getDelta()) {
                Node layerNode = Layer.Finder.findNodeWithLayer(node);
                if (layerNode != null) {
                    layerNodes.add(layerNode);
                }
            }
            for (Node node : layerNodes) {
                mapPanelController.refreshLayerNode(node);
            }
        }

        @Override
        public void childrenAdded(NodeMemberEvent ev) {
            refreshAffectedLayerNodes(ev);
        }

        @Override
        public void childrenRemoved(NodeMemberEvent ev) {
            refreshAffectedLayerNodes(ev);
        }

        @Override
        public void childrenReordered(NodeReorderEvent ev) {
            // not implemented
        }

        @Override
        public void nodeDestroyed(NodeEvent ev) {
            // not implemented
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            // not implemented
        }
    }

    private final class Listener implements ListDataListener, ListSelectionListener, PropertyChangeListener,
            VetoableChangeListener {

        Listener() {
        }

        /**
         * Implements
         * ListDataListener interface.
         */
        @Override
        public void intervalAdded(ListDataEvent evt) {
            updateSelection();
        }

        /**
         * Implements
         * ListDataListener.
         */
        @Override
        public void intervalRemoved(ListDataEvent evt) {
            updateSelection();
        }

        /**
         * Implemetns
         * ListDataListener.
         */
        @Override
        public void contentsChanged(ListDataEvent evt) {
            updateSelection();
        }

        @Override
        public void vetoableChange(PropertyChangeEvent evt)
                throws PropertyVetoException {
            if (ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())) {
                Node[] newNodes = (Node[]) evt.getNewValue();

                if (!selectionAccept(newNodes)) {
                    throw new PropertyVetoException("", evt); // NOI18N
                }
            }
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())) {
                updateSelection();
            }
        }

        @Override
        public void valueChanged(ListSelectionEvent e) {
            throw new UnsupportedOperationException("valueChanged");

//            // forwarding TO E.M., so we won't listen to its cries for a while
//            manager.removePropertyChangeListener(wlpc);
//            manager.removeVetoableChangeListener(wlvc);
//
////            try {
////                selectionChanged(nodes, manager);
//            } catch (PropertyVetoException ex) {
//                // selection vetoed - restore previous selection
//                updateSelection();
//            } finally {
//                manager.addPropertyChangeListener(wlpc);
//                manager.addVetoableChangeListener(wlvc);
//            }
        }
    }

    private boolean selectionAccept(Node[] newNodes) {
        throw new UnsupportedOperationException("selectionAccept");
    }

    private void updateSelection() {
        //FIXME do we need to track selection here??
        // base and map explorer manager as synced on the layer
        // layer panel is listening to selection changes on the layer
//        throw new UnsupportedOperationException("updateSelection");
//        for (Node node:manager.getSelectedNodes()){
//            LayerObject lo = node.getLookup().lookup(LayerObject.class);
//            if (lo != null){
//                
//            }
//        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy