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

nl.cloudfarming.client.geoviewer.jxmap.map.AbstractLineDrawingContext Maven / Gradle / Ivy

Go to download

AgroSense geoviewer JXMap implementation. Contains a map/geoviewer TopComponent based on the JXMap classes from swingx.

The 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 nl.cloudfarming.client.geoviewer.jxmap.map;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import nl.cloudfarming.client.geoviewer.SingleObjectLayer;
import org.jdesktop.swingx.JXMapViewer;
import org.jdesktop.swingx.mapviewer.GeoPosition;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;


/**
 *
 * @author johan
 */
public abstract class AbstractLineDrawingContext implements DrawingContext {
    protected final List coords = new ArrayList<>();
    // FIXME: set WGS-84 SRID or CRS on factory
    protected final GeometryFactory geometryFactory = new GeometryFactory();
    private final AbstractLocationPicker locationPicker;
    private PropertyChangeSupport propertyChangeSupport;
    private SingleObjectLayer layer;

    public AbstractLineDrawingContext(SingleObjectLayer layer, JXMapViewer mapViewer) {
        this.layer = layer;
        locationPicker = new AbstractLocationPicker(mapViewer, true) {

            @Override
            public boolean select(GeoPosition position) {
                return addPoint(position);
            }
        };
        locationPicker.start();
        
    }
    
    @Override
    public SingleObjectLayer getLayer(){
        return this.layer;
    }

    
    private boolean addPoint(GeoPosition position) {
        Coordinate coord = new Coordinate(position.getLongitude(), position.getLatitude());

        if (isValidLine(coord)) {
            coords.add(coord);
            pointAdded();
            // notify panel & toolbar actions:
            getPropertyChangeSupport().firePropertyChange(PROP_DRAWING_CONTEXT, null, null);
            return true;
        }
        
        return false;
    }    
    
    /**
     * Check if adding the provided coordinate to the list will produce a valid line.
     * The new segment must not intersect any of the existing ones.
     * 
     * @param coord
     * @return 
     */
    protected boolean isValidLine(Coordinate coord) {
        int len = coords.size();
        
        // number of points in LineString must be 0 or >= 2)
        if (len < 2) {
            return true;
        }
        
        CoordinateSequence coordSequence1 = new CoordinateArraySequence(coords.toArray(new Coordinate[len]));
        CoordinateSequence coordSequence2 = new CoordinateArraySequence(new Coordinate[] {coords.get(len - 1), coord});
        LineString lineString1 = new LineString(coordSequence1, geometryFactory);
        LineString lineString2 = new LineString(coordSequence2, geometryFactory);

        return !lineString1.crosses(lineString2);
    }
    
    private void removeLastPoint() {
        if (!coords.isEmpty()) {
            coords.remove(coords.size() - 1);
            pointRemoved();
            getPropertyChangeSupport().firePropertyChange(PROP_DRAWING_CONTEXT, null, null);
        }
    }
    
    private void removeAllPoints() {
        if (!coords.isEmpty()) {
            coords.clear();
            pointRemoved();
            getPropertyChangeSupport().firePropertyChange(PROP_DRAWING_CONTEXT, null, null);
        }
    }
    
    /*
     * Alow subclasses to perform extra actions after points are added or removed
     * (but before re-rendering), because there might be other objects in the 
     * scene depending on the drawn line.
     */
    protected void pointAdded() {
    }
    protected void pointRemoved() {
    }

    protected void cleanup() {
        if (locationPicker.isActive()) {
            locationPicker.stop();
        }        
    }

    PropertyChangeSupport getPropertyChangeSupport() {
        if (propertyChangeSupport == null){
            propertyChangeSupport = new PropertyChangeSupport(this);
        }
        return propertyChangeSupport;
    }

    @Override
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        getPropertyChangeSupport().addPropertyChangeListener(listener);
    }

    @Override
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        getPropertyChangeSupport().removePropertyChangeListener(listener);
    }
    
    @Override
    public void cancel() {
        cleanup();
    }

    /**
     * Create toolbar actions.
     * 
     * @return 
     */
    @Override
    public Action[] getActions() {
        List actions = new ArrayList<>();
        // toggle drawing/navigation:
        actions.add(new DrawAction());
        actions.add(new NavigateAction());
        
        actions.add(new RemoveOneAction());
        actions.add(new RemoveAllAction());
        
        return actions.toArray(new Action[0]);
    }
    
    //
    // toolbar actions:
    //

    @NbBundle.Messages({
            "drawing_draw_action_name=Add points",
            "drawing_draw_action_tooltip=Add points",
            "drawing_draw_action_icon=nl/cloudfarming/client/geoviewer/jxmap/icons/draw_path16.png"})
    private class DrawAction extends AbstractAction {

        public DrawAction() {
            putValue(SHORT_DESCRIPTION, Bundle.drawing_draw_action_tooltip());
            putValue(LARGE_ICON_KEY, ImageUtilities.loadImageIcon(Bundle.drawing_draw_action_icon(), true));
            setEnabled(!locationPicker.isActive());
            locationPicker.addPropertyChangeListener(AbstractLocationPicker.PROP_ACTIVE, new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    setEnabled(!locationPicker.isActive());
                }
            });
        }
        
        @Override
        public void actionPerformed(ActionEvent e) {
            locationPicker.start();
        }
    }
    
    @NbBundle.Messages({
            "drawing_navigate_action_name=Navigate",
            "drawing_navigate_action_tooltip=Navigate",
            "drawing_navigate_action_icon=nl/cloudfarming/client/geoviewer/jxmap/icons/map16.png"})
    private class NavigateAction extends AbstractAction {

        public NavigateAction() {
            putValue(SHORT_DESCRIPTION, Bundle.drawing_navigate_action_tooltip());
            putValue(LARGE_ICON_KEY, ImageUtilities.loadImageIcon(Bundle.drawing_navigate_action_icon(), true));
            setEnabled(locationPicker.isActive());
            locationPicker.addPropertyChangeListener(AbstractLocationPicker.PROP_ACTIVE, new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    setEnabled(locationPicker.isActive());
                }
            });
        }
        
        @Override
        public void actionPerformed(ActionEvent e) {
            locationPicker.stop();
        }
    }

    @NbBundle.Messages({
            "drawing_remove_one_action_name=Remove one",
            "drawing_remove_one_action_tooltip=Remove the last point",
            "drawing_remove_one_action_icon=nl/cloudfarming/client/geoviewer/jxmap/icons/vector_delete16.png"})
    private class RemoveOneAction extends AbstractAction {

        public RemoveOneAction() {
            putValue(SHORT_DESCRIPTION, Bundle.drawing_remove_one_action_tooltip());
            putValue(LARGE_ICON_KEY, ImageUtilities.loadImageIcon(Bundle.drawing_remove_one_action_icon(), true));
            setEnabled(coords.size() > 0);
            AbstractLineDrawingContext.this.addPropertyChangeListener(new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    setEnabled(coords.size() > 0);
                }
            });
        }
        
        @Override
        public void actionPerformed(ActionEvent e) {
            removeLastPoint();
        }
    }
    
    @NbBundle.Messages({
            "drawing_remove_all_action_name=Remove all",
            "drawing_remove_all_action_tooltip=Remove all points",
            "drawing_remove_all_action_icon=nl/cloudfarming/client/geoviewer/jxmap/icons/delete16.png"})
    private class RemoveAllAction extends AbstractAction {

        public RemoveAllAction() {
            putValue(SHORT_DESCRIPTION, Bundle.drawing_remove_all_action_tooltip());
            putValue(LARGE_ICON_KEY, ImageUtilities.loadImageIcon(Bundle.drawing_remove_all_action_icon(), true));
            setEnabled(coords.size() > 0);
            AbstractLineDrawingContext.this.addPropertyChangeListener(new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    setEnabled(coords.size() > 0);
                }
            });
        }
        
        @Override
        public void actionPerformed(ActionEvent e) {
            removeAllPoints();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy