Package org.locationtech.udig.tools.merge

Source Code of org.locationtech.udig.tools.merge.MergeTool

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2012, Refractions Research Inc.
* (C) 2006, Axios Engineering S.L. (Axios)
* (C) 2006, County Council of Gipuzkoa, Department of Environment and Planning
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Axios BSD
* License v1.0 (http://udig.refractions.net/files/asd3-v10.html).
*/
package org.locationtech.udig.tools.merge;

import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;

import org.locationtech.udig.project.ILayer;
import org.locationtech.udig.project.command.MapCommand;
import org.locationtech.udig.project.internal.commands.selection.BBoxSelectionCommand;
import org.locationtech.udig.project.render.IViewportModel;
import org.locationtech.udig.project.ui.AnimationUpdater;
import org.locationtech.udig.project.ui.ApplicationGIS;
import org.locationtech.udig.project.ui.commands.SelectionBoxCommand;
import org.locationtech.udig.project.ui.render.displayAdapter.MapMouseEvent;
import org.locationtech.udig.project.ui.tool.ModalTool;
import org.locationtech.udig.project.ui.tool.SimpleTool;
import org.locationtech.udig.tools.edit.animation.MessageBubble;
import org.locationtech.udig.tools.edit.preferences.PreferenceUtil;

import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.filter.Filter;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;

import org.locationtech.udig.tools.internal.i18n.Messages;
import org.locationtech.udig.tools.internal.ui.util.StatusBar;
import org.locationtech.udig.tools.merge.internal.view.MergeView;

/**
* Merge the features in bounding box
* <p>
* This implementation is based in BBoxSelection. The extension add behavior object which displays
* the merge dialog.
* </p>
*
* @author Aritz Davila (www.axios.es)
* @author Mauricio Pazos (www.axios.es)
* @author Marco Foi (www.mcfoi.it)
*/
public class MergeTool extends SimpleTool implements ModalTool {

    /**
     * Comment for <code>ID</code>
     */
    public static final String ID = "org.locationtech.udig.tools.merge.MergeTool"; //$NON-NLS-1$

    private static final Logger LOGGER = Logger.getLogger(MergeTool.class.getName());

    private MergeContext mergeContext;

    private SelectionBoxCommand selectionBoxCommand = null;

    /**
     * The tool will respond to the mouse event and map motion stimulus.
     */
    public MergeTool() {
        super(MOUSE | MOTION);
    }

    /**
     * When the Merge tool is activated by a click in the toolbar, if the Merge View is opened, it
     * will be closed.
     */
    @Override
    public void setActive(final boolean active) {

        super.setActive(active);

        if (active) {
            this.mergeContext = MergeContext.getInstance();
            this.mergeContext.setToolContext(getContext());

            // Check if MergeTool has been previously executed in Operation mode and, in the case,
            // close the MergeView
            if (this.mergeContext.getMergeMode() == MergeContext.MERGEMODE_OPERATION) {
                closeMergeView();
            }

            // Set tool mode (also set in MergeOperation.op to MERGEMODE_OPERATION)
            this.mergeContext.setMergeMode(MergeContext.MERGEMODE_TOOL);

            // feedback to the user indeed that he can select some features to merege
            StatusBar.setStatusBarMessage(this.mergeContext.getToolContext(), "");//$NON-NLS-1$
            if (this.mergeContext.getToolContext().getMapLayers().size() > 0) {

                String message = Messages.MergeTool_select_features_to_merge;
                StatusBar.setStatusBarMessage(this.mergeContext.getToolContext(), message);

            } else {

                String message = "The current Map has no layers. The tool cannot operate.";//$NON-NLS-1$
                StatusBar.setStatusBarMessage(this.mergeContext.getToolContext(), message);
            }
        } else {
            // if the merge view is opened it will be closed
            if (this.mergeContext.isMergeViewActive()) {

                closeMergeView();
            }
            this.mergeContext = null;
        }
    }

    /**
     * Hide the merge view.
     */
    private void closeMergeView() {
        Display.getCurrent().asyncExec(new Runnable() {

            public void run() {

                // When the tool is deactivated, hide the view.
                ApplicationGIS.getView(false, MergeView.ID);
                IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
                        .getActivePage();
                IViewPart viewPart = page.findView(MergeView.ID);
                page.hideView(viewPart);
                mergeContext.disposeMergeView();
            }
        });
    }

    /**
     * Begins the bbox selection. Saves in the merge context the start point of bbox
     */
    @Override
    protected void onMousePressed(MapMouseEvent e) {

        if (!isActive())
            return;

        if (e.button != MapMouseEvent.BUTTON1) {
            return;
        }
        // Draw the initial bbox
        selectionBoxCommand = new SelectionBoxCommand(); // this.mergeContext.getSelectionBoxCommand();

        Point start = e.getPoint();
        this.mergeContext.setBBoxStartPoint(start);

        selectionBoxCommand.setValid(true);
        selectionBoxCommand.setShape(new Rectangle(start.x, start.y, 0, 0));
        context.sendASyncCommand(selectionBoxCommand);
    }

    /**
     * Uses the position of last event as second corner of bbox drawn to select one or more
     * features.
     */
    @Override
    protected void onMouseDragged(MapMouseEvent e) {

        if (!isActive())
            return;

        // draw the selection box
        Point start = this.mergeContext.getBBoxStartPoint();
        if (start == null) {
            start = e.getPoint();
        }

        selectionBoxCommand.setShape(new Rectangle(Math.min(start.x, e.x), Math.min(start.y, e.y),
                Math.abs(e.x - start.x), Math.abs(start.y - e.y)));
        context.getViewportPane().repaint();

    }

    /**
     * Remove the bbox drawn
     *
     * @param start
     * @param end
     */
    private void removeBBox(final Point start, final Point end) {

        int x1 = Math.min(start.x, end.x);
        int y1 = Math.min(start.y, end.y);
        int x2 = Math.abs(end.x - start.x);
        int y2 = Math.abs(start.y - end.y);

        Coordinate c1 = context.getMap().getViewportModel().pixelToWorld(x1, y1);
        Coordinate c2 = context.getMap().getViewportModel().pixelToWorld(x2, y2);

        Envelope bounds = new Envelope(c1, c2);

        // remove the bounding box selection
        MapCommand cmd = new BBoxSelectionCommand(bounds, BBoxSelectionCommand.NONE);
        getContext().sendASyncCommand(cmd);

        selectionBoxCommand.setValid(false);
        getContext().getViewportPane().repaint();
    }

    /**
     * This hook is used to catch two events: <lu> <li>Bbox drawing action to select one or more
     * features was finished</li> <li>select individual feature for click (press and release in the
     * same position)</li> <li>Unselect one feature using control key and mouse pressed.</li> </lu>
     */
    @Override
    protected void onMouseReleased(MapMouseEvent mouseEvent) {

        if (!isActive())
            return;

        if (mouseEvent.button != MapMouseEvent.BUTTON1) {
            return;
        }
        // draw the selection box
        Point start = this.mergeContext.getBBoxStartPoint();

        // search an existent view or open a new one
        if (!this.mergeContext.isMergeViewActive()) {
            openMergeView(mouseEvent.x, mouseEvent.y, this.mergeContext);
        }
        MergeView mergeView = this.mergeContext.getMergeView();

        assert mergeView != null;

        // presents the selected features in the map and the merge view
        ILayer selectedLayer = getContext().getSelectedLayer();
        if (!start.equals(mouseEvent.getPoint())) { // selection using a bbox

            removeBBox(start, mouseEvent.getPoint());
            displayFeaturesUnderBBox(mouseEvent.getPoint(), selectedLayer, mergeView);

        } else { // selection using click over the a feature
            if (start.equals(mouseEvent.getPoint()) && !mouseEvent.isControlDown()) {
                displayFeatureOnView(mouseEvent, selectedLayer, mergeView);
            }
        }
    }

    /**
     * Display the feature selected on the view
     *
     * @param e mouse event
     * @param selectedLayer
     * @param mergeView
     */
    private void displayFeatureOnView(MapMouseEvent e, ILayer selectedLayer, MergeView mergeView) {

        Envelope bound = buildBoundForPoint(e.getPoint());

        // show selection in Map
        Filter filterSelectedFeatures = selectFeaturesUnderBBox(bound, BBoxSelectionCommand.NONE);

        // retrieve the feature and present its data in the merge view
        try {
            List<SimpleFeature> selectedFeatures = Util.retrieveFeatures(filterSelectedFeatures,
                    selectedLayer);

            mergeView.addSourceFeatures(selectedFeatures);

        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

    }

    private Envelope buildBoundForPoint(Point p) {
        return getContext().getBoundingBox(p, 3);
    }

    /**
     * Presents the features selected using the bbox interaction in the merge view
     *
     * @param xyMouse
     * @param selectedLayer
     * @param mergeView
     */
    private void displayFeaturesUnderBBox(Point xyMouse, ILayer selectedLayer, MergeView mergeView) {

        Filter filterSelectedFeatures;
        Envelope bound;
        // select features using the drawn bbox
        IViewportModel viewportModel = getContext().getMap().getViewportModel();
        Coordinate startPoint = viewportModel.pixelToWorld(mergeContext.getBBoxStartPoint().x,
                mergeContext.getBBoxStartPoint().y);
        Coordinate endPoint = viewportModel.pixelToWorld(xyMouse.x, xyMouse.y);

        if (startPoint.equals2D(endPoint)) {
            // when it was a click(start and end coordinates are equal)
            // get a little bbox around this point.
            bound = getContext().getBoundingBox(xyMouse, 3);
        } else {
            bound = new Envelope(startPoint, endPoint);
        }

        // builds a command to show the features selected to merge
        try {
            filterSelectedFeatures = selectFeaturesUnderBBox(bound, BBoxSelectionCommand.NONE);
            List<SimpleFeature> selectedFeatures = Util.retrieveFeatures(filterSelectedFeatures,
                    selectedLayer);

            mergeView.addSourceFeatures(selectedFeatures);

            mergeView.display();

        } catch (IOException e1) {
            LOGGER.warning(e1.getMessage());
            return;
        }
    }

    /**
     * Opens the Merge view
     *
     * @param eventX
     * @param eventY
     * @param context
     */
    private void openMergeView(int eventX, int eventY, MergeContext mergeContext) {

        try {
            MergeView view = (MergeView) ApplicationGIS.getView(true, MergeView.ID);
            if (view == null) {
                // crates a new merge view
                IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
                        .getActivePage();
                view = (MergeView) page.findView(MergeView.ID);
            }
            assert view != null : "view is null"; //$NON-NLS-1$

            // associates this the merge view with the merge context
            view.setMergeContext(mergeContext);
            mergeContext.activeMergeView(view);

        } catch (Exception ex) {
            AnimationUpdater.runTimer(getContext().getMapDisplay(), new MessageBubble(eventX,
                    eventY, "It cannot be merge", //$NON-NLS-1$
                    PreferenceUtil.instance().getMessageDisplayDelay()));
        }

    }

    /**
     * Selects the features under the bbox. This method builds a command to show the features
     * selected to merge
     *
     * @param boundDrawn the drawn bbox by the usr
     * @param context
     *
     * @return {@link Filter} filter that contains the selected features
     */
    private Filter selectFeaturesUnderBBox(Envelope boundDrawn, int SelectionType) {

        // updates the merge context with bounds
        this.mergeContext.addBound(boundDrawn);

        MapCommand command = context.getSelectionFactory().createBBoxSelectionCommand(boundDrawn,
                SelectionType);
        getContext().sendSyncCommand(command);

        // SelectionBoxCommand selectionBoxCommand = this.mergeContext.getSelectionBoxCommand();
        // selectionBoxCommand.setValid(true);

        getContext().getViewportPane().repaint();

        Filter filterSelectedFeatures = getContext().getSelectedLayer().getFilter();

        return filterSelectedFeatures;
    }

}
TOP

Related Classes of org.locationtech.udig.tools.merge.MergeTool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.