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

eu.limetri.client.mapviewer.nb.jxmap.RootMapPanel 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.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import net.miginfocom.swing.MigLayout;

import org.jdesktop.swingx.JXPanel;

import eu.limetri.client.mapviewer.api.LayerInfo;
import eu.limetri.client.mapviewer.api.event.GeoEvent;
import eu.limetri.client.mapviewer.data.TileFactoryInfo;
import eu.limetri.client.mapviewer.data.common.TileFactoryInfoSelectionEventHandler;
import eu.limetri.client.mapviewer.data.tilefactory.OSMTileFactoryInfo;
import eu.limetri.client.mapviewer.data.tilefactory.VirtualEarthTileFactoryInfo;
import eu.limetri.client.mapviewer.nb.jxmap.component.SelectionComponent;
import eu.limetri.client.mapviewer.swing.JXMapViewer;
import eu.limetri.client.mapviewer.swing.MapTypeSelectionPanelSwing;
import eu.limetri.client.mapviewer.swing.ZoomPanel;
import eu.limetri.client.mapviewer.swing.impl.OfflineTileFactorySwing;
import eu.limetri.client.mapviewer.swing.jxmap.map.FillLayout;
import eu.limetri.client.mapviewer.swing.jxmap.map.JXMapPanel;
import eu.limetri.client.mapviewer.nb.jxmap.map.LegendPanel;
import eu.limetri.client.mapviewer.swing.jxmap.map.MapMouseEvent;
import eu.limetri.client.mapviewer.swing.jxmap.map.component.LayerSelectionComponent;
import eu.limetri.client.mapviewer.swing.jxmap.map.component.LegendContainer;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Collection;
import nl.cloudfarming.eventbus.GuiEvent;
import nl.cloudfarming.eventbus.GuiEventBus;
import nl.cloudfarming.eventbus.GuiEventKey;
import nl.cloudfarming.eventbus.GuiEventListener;
import org.openide.util.NbBundle;

/**
 * The root map panel, containing a layered pane with all the layers. A
 * JXMapPanel is used as the bottom layer.
 *
 * @author Timon Veenstra
 */
@NbBundle.Messages({
            "measure_selection_title=Measure",
            "measure_length=Length",
            "measure_area=Area"})
public class RootMapPanel extends JXPanel implements MapMouseListener {

    public enum LayerGroup {

        LAYER_MAP(Integer.valueOf(1)),
        LAYER_IMAGE(Integer.valueOf(10)),
        LAYER_PASSIVE(Integer.valueOf(20)),
        LAYER_ACTIVE(Integer.valueOf(29)),
        LAYER_DRAWING(Integer.valueOf(30)),
        LAYER_LEGEND(Integer.valueOf(50)),
        LAYER_TOOLS(Integer.valueOf(52)),
        LAYER_LAYERLIST(Integer.valueOf(51)),
        LAYER_TOP(Integer.valueOf(49));
        private final Integer value;

        public Integer getValue() {
            return value;
        }

        private LayerGroup(Integer value) {
            this.value = value;
        }
    }
    // swing container holding all layerPanels and the map panel
    private final JLayeredPane layerPanelContainer;
    // layers
    private JXMapPanel mapPanel;
    private final JXPanel topPanel = new JXPanel();
   
    //
    // map with layerpanels for components
    //
    private final Set layerPanels = new HashSet<>();
    private final MapMouseHandler mouseHandler;
    private final ZoomPanel zoomPanel;
    private final MapTypeSelectionPanelSwing mapTypeSelectionPanel;
    
    private ToolsPanelEventListener toolsPanelEventListener = new ToolsPanelEventListener();
    private static final int ON_TOP = 0;
    CardLayout cardLayout;
    JPanel panel;
    
    private LayerSelectionComponent layerSelectionComponent;
    
    private LegendContainer legendContainer;

//    private Map layerInfoMap = new HashMap();
    public RootMapPanel(final JComponent layerList) {
        setLayout(new BorderLayout());
        //
        // initialize the mouse handler
        //
        mouseHandler = new MapMouseHandler(this);
        //
        // the layered pane which will contain the layers of the map
        //
        layerPanelContainer = new JLayeredPane();
        layerPanelContainer.setLayout(new FillLayout());
        add(layerPanelContainer, BorderLayout.CENTER);
        //
        // the map layer
        //
        mapPanel = new JXMapPanel();
        mapPanel.setZoomEnabled(false);
        layerPanelContainer.add(mapPanel, LayerGroup.LAYER_MAP.getValue());
        //
        //zoom controls layer
        //
        zoomPanel = new ZoomPanel(mapPanel);
        zoomPanel.attach();
        JPanel mapControlsPanel = new JPanel(new GridBagLayout());
        mapControlsPanel.setOpaque(false);

        GridBagConstraints gc = new GridBagConstraints();
        gc.gridx = 3;
        gc.gridy = 1;
        gc.weightx = 0;
        gc.insets = new Insets(2, 2, 2, 2);
        gc.anchor = GridBagConstraints.EAST;
        
        mapControlsPanel.add(zoomPanel, gc); //FIXME miglayout
        
        mapTypeSelectionPanel = new MapTypeSelectionPanelSwing();
        VirtualEarthTileFactoryInfo bingMapInfo = new VirtualEarthTileFactoryInfo(VirtualEarthTileFactoryInfo.MAP);
        VirtualEarthTileFactoryInfo bingSatelliteInfo = new VirtualEarthTileFactoryInfo(VirtualEarthTileFactoryInfo.SATELLITE);
        VirtualEarthTileFactoryInfo bingHybridInfo = new VirtualEarthTileFactoryInfo(VirtualEarthTileFactoryInfo.HYBRID);
        TileFactoryInfo openStreetMapInfo = new OSMTileFactoryInfo();
        
        openStreetMapInfo.setIconUrl(RootMapPanel.class.getResource("icons/osm.png"));
        bingMapInfo.setIconUrl(RootMapPanel.class.getResource("icons/vem.png"));
        bingSatelliteInfo.setIconUrl(RootMapPanel.class.getResource("icons/ves.png"));
        bingHybridInfo.setIconUrl(RootMapPanel.class.getResource("icons/veh.png"));
        
        mapTypeSelectionPanel.setItems(new TileFactoryInfo[]{openStreetMapInfo, bingMapInfo, bingSatelliteInfo, bingHybridInfo});
        mapTypeSelectionPanel.setOnSelectionChange(new TileFactoryInfoSelectionEventHandler() {
            @Override
            public void itemSelected(TileFactoryInfo tileFactoryInfo) {
                mapPanel.setTileFactory(new OfflineTileFactorySwing(tileFactoryInfo));
            }
        });
        mapTypeSelectionPanel.setActiveTileFactoryInfo(mapPanel.getTileFactory().getInfo());
        
        gc = new GridBagConstraints();
        gc.gridx = 2;
        gc.gridy = 0;
        gc.gridwidth = 2;
        gc.insets = new Insets(0, 2, 2, 2);
        
        mapControlsPanel.add(mapTypeSelectionPanel, gc);
        
        layerSelectionComponent = new LayerSelectionComponent();
        
        gc = new GridBagConstraints();
        gc.gridx = 1;
        gc.gridy = 0;
        gc.gridwidth = 1;
        gc.insets = new Insets(1, 0, 0, 10);
        
        mapControlsPanel.add(layerSelectionComponent, gc);
        
        legendContainer = new LegendContainer();
        
        gc = new GridBagConstraints();
        gc.gridx = 2;
        gc.gridy = 11;
        gc.gridwidth = 2;
        gc.insets = new Insets(1, 0, 0, 0);
        gc.anchor = GridBagConstraints.LAST_LINE_END;
        
        mapControlsPanel.add(legendContainer, gc);
        
        gc = new GridBagConstraints();
        gc.gridx = 0;
        gc.gridy = 10;
        gc.weighty = 1;
        gc.weightx = 1;
        gc.fill = GridBagConstraints.BOTH;

        //TODO replace with miglayout
        JPanel fillPanel = new JPanel();
        fillPanel.setOpaque(false);
        mapControlsPanel.add(fillPanel, gc);
        layerPanelContainer.add(mapControlsPanel, LayerGroup.LAYER_TOOLS.getValue());
        //
        // add the layerlist panel
        //
        JXPanel layerListPanel = new JXPanel();;
        if (layerList != null) {
            layerListPanel.setOpaque(false);
            layerListPanel.setLayout(new MigLayout());
            layerListPanel.add(layerList, "wrap");
            layerPanelContainer.add(layerListPanel, LayerGroup.LAYER_LAYERLIST.getValue());
            mouseHandler.addMapMouseListener(new MapMouseListener() {

                @Override
                public LayerGroup getGroup() {
                    return LayerGroup.LAYER_LAYERLIST;
                }

                @Override
                public int getId() {
                    return 1;
                }

                @Override
                public void onMapMouseEvent(MapMouseEvent mapMouseEvent) {
                    layerList.dispatchEvent(mapMouseEvent.getEvent());
                }

                @Override
                public void mapMousePressed(MapMouseEvent mapMouseEvent) {
                }

                @Override
                public void mapMouseReleased(MapMouseEvent mapMouseEvent) {
                }

                @Override
                public void mapMouseDragged(MapMouseEvent mapMouseEvent) {
                }
            });
            
        }

        layerPanelContainer.add(new LegendPanel(), LayerGroup.LAYER_LEGEND.getValue());

        DrawingController drawingController = new DrawingController(mapPanel);
        
        DrawingPanel drawingPanel = drawingController.getDrawingPanel();
        layerPanelContainer.add(drawingPanel, LayerGroup.LAYER_DRAWING.getValue());

        JXPanel toolsPanel = drawingController.getToolsPanel();
        //layerPanelContainer.add(toolsPanel, LayerGroup.LAYER_TOOLS.getValue());
        
        panel = new JPanel();
        cardLayout = new CardLayout();
        panel.setLayout(cardLayout);
        
        //TODO FP moving controls panel to same container as zoom component. better solution?
        gc = new GridBagConstraints();
        gc.gridx = 3;
        gc.gridy = 0;
        gc.gridheight = 2;
        gc.insets = new Insets(0, 2, 2, 0);
        gc.anchor = GridBagConstraints.FIRST_LINE_END;
        
        layerListPanel.add(panel, "gaptop 15");
        panel.add(toolsPanel, "toolsPanel");

        final SelectionComponent combo = new SelectionComponent<>(Bundle.measure_selection_title());
        combo.addItem(Bundle.measure_length());
        combo.addItem(Bundle.measure_area());
        combo.setSelectedIndex(-1);
        combo.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if (combo.getSelectedIndex() == 0) {
                     GeoEvent.getProducer().triggerEvent(GeoEvent.MEASURE_LENGTH, null);
                } else if (combo.getSelectedIndex() == 1) {
                     GeoEvent.getProducer().triggerEvent(GeoEvent.MEASURE_AREA, null);
                }
            }
            
        });
        panel.add(combo, "measureCombo");
        cardLayout.show(panel, "measureCombo");
        
        topPanel.setOpaque(false);
        layerPanelContainer.add(topPanel, LayerGroup.LAYER_TOP.getValue());

        topPanel.addMouseListener(mouseHandler);
        topPanel.addMouseMotionListener(mouseHandler);
        topPanel.addMouseWheelListener(mouseHandler);
        
        GuiEventBus.addListener(toolsPanelEventListener);
        
        setDoubleBuffered(true);
    }

    public JPanel getTopPanel() {
        return topPanel;
    }

    /**
     * returns the mapviewer
     *
     * @return
     */
    public JXMapViewer getMapViewer() {
        //FIXME change back to package access
        return this.mapPanel;

    }

    /**
     * internal method to add a layerpanel. Only call from the AWT thread.
     *
     * @param layerPanel
     */
    private void internalAddLayerPanel(final LayerPanel layerPanel) {
        //
        // add interactive layers to the interaction layer
        // and add non interactive layer to the object layer
        //
        mouseHandler.addMapMouseListener(layerPanel);
        layerPanels.add(layerPanel);
        layerPanelContainer.add(layerPanel, layerPanel.getGroup().getValue(), layerPanel.getInfo().getOrder());

        layerPanel.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (LayerInfo.PROPERTY_VISIBLE.equals(evt.getPropertyName())) {
                    layerPanel.setVisible((Boolean) evt.getNewValue());
                }
            }
        });
    }

    /**
     * add a layer panel
     *
     * @param layerPanel
     */
    public void addLayerPanel(final LayerPanel layerPanel) {
        //
        // do actual adding in the AWT thread because the scene could be validating and cause
        // concurrent modification exception
        //
        if (EventQueue.isDispatchThread()) {
            internalAddLayerPanel(layerPanel);
        } else {
            EventQueue.invokeLater(new Runnable() {

                @Override
                public void run() {
                    internalAddLayerPanel(layerPanel);
                }
            });
        }
    }

    /**
     * remove a layer panel
     *
     * @param layerPanel
     */
    public void removeLayerPanel(final LayerPanel layerPanel) {
        //
        // do actual removing in the AWT thread because the scene could be validating and cause
        // concurrent modification exception
        //
        if (EventQueue.isDispatchThread()) {
            internalRemoveLayerPanel(layerPanel);
        } else {
            EventQueue.invokeLater(new Runnable() {

                @Override
                public void run() {
                    internalRemoveLayerPanel(layerPanel);
                }
            });
        }

    }

    /**
     * checks if this panel contains the supplied layerPanel
     *
     * @param layerPanel
     * @return if the supplied layerPanel is contained in this RootMapPanel
     */
    boolean contains(final LayerPanel layerPanel) {
        return layerPanels.contains(layerPanel);
    }

    /**
     * internal method to remove a layerpanel. Only call from the AWT thread.
     *
     * @param layerPanel
     */
    private void internalRemoveLayerPanel(final LayerPanel layerPanel) {
        if (this.layerPanels.contains(layerPanel)) {
            this.layerPanels.remove(layerPanel);
        }
        for (Component c : layerPanelContainer.getComponents()) {
            if (c.equals(layerPanel)) {
                layerPanelContainer.remove(layerPanel);
            }
        }

        mouseHandler.removeMapMouseListener(layerPanel);
        getMapViewer().repaint();
    }

    @Override
    public LayerGroup getGroup() {
        return LayerGroup.LAYER_MAP;
    }

    @Override
    public int getId() {
        return 1;
    }

    /**
     * dispatches all mouse events to the map when they contain a point
     *
     * @param mapMouseEvent
     */
    @Override
    public void onMapMouseEvent(MapMouseEvent mapMouseEvent) {
        if (mapMouseEvent.getEvent().getPoint() != null
                && mapPanel.contains(mapMouseEvent.getEvent().getPoint())
                && !SwingUtilities.isRightMouseButton(mapMouseEvent.getEvent())) {
            mapPanel.dispatchEvent(mapMouseEvent.getEvent());
        }
    }

    @Override
    public void mapMousePressed(MapMouseEvent mapMouseEvent) {
    }

    @Override
    public void mapMouseReleased(MapMouseEvent mapMouseEvent) {
    }

    @Override
    public void mapMouseDragged(MapMouseEvent mapMouseEvent) {
    }
    
    private class ToolsPanelEventListener implements GuiEventListener {

        Dimension comboDimension;
        Dimension toolsDimension = new Dimension(33, 195);
        
        @Override
        public void onEvent(GuiEvent event) {
           mapPanel.setDoubleClickZoomEnabled(!event.getContent().booleanValue());
           if (event.getContent().booleanValue()) {
               if (comboDimension == null) {
                   comboDimension = panel.getSize();
               }
               panel.setMaximumSize(toolsDimension);
               panel.setMinimumSize(toolsDimension);
               cardLayout.show(panel, "toolsPanel");
           } else {
               panel.setMaximumSize(comboDimension);
               panel.setMinimumSize(comboDimension);
               cardLayout.show(panel, "measureCombo");
           }
        }

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

        @Override
        public String getModuleName() {
            return Module.MODULE_NAME;
        }
    }
    
    public void repaintReorder(Collection values) {
        for (LayerPanel layerPanel: values) {
            layerPanelContainer.setPosition(layerPanel, (int)layerPanel.getInfo().getOrder()/2);
        }
        revalidate();
    }
    
    public void refreshSelectedLayer() {
        for (LayerPanel layerPanel : layerPanels) {
            if (layerPanel.getInfo() != null && layerPanel.getInfo().isSelected()) {
                layerPanelContainer.setPosition(layerPanel, ON_TOP);
            } else {
                layerPanelContainer.setPosition(layerPanel, ((int)layerPanel.getInfo().getOrder()/2) + 1); 
            }
        }
        revalidate();
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy