Package org.locationtech.udig.project.ui.internal.actions

Source Code of org.locationtech.udig.project.ui.internal.actions.LegendDropAction

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2012, Refractions Research Inc.
*
* 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 Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.project.ui.internal.actions;

import java.util.ArrayList;
import java.util.List;

import org.locationtech.udig.project.ILegendItem;
import org.locationtech.udig.project.internal.Folder;
import org.locationtech.udig.project.internal.LayerLegendItem;
import org.locationtech.udig.project.internal.Map;
import org.locationtech.udig.project.ui.ApplicationGIS;
import org.locationtech.udig.ui.IDropAction;
import org.locationtech.udig.ui.ViewerDropLocation;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.swt.dnd.DropTargetEvent;

/**
* Action that moves legend items within the legend items list. This moves layers in and out of
* folders. And moves layers and folders up and down the order in the view.
*
* @author Naz Chan (LISAsoft)
* @since 1.3.1
*/
public class LegendDropAction extends IDropAction {

    /**
     * Flags if source object is a layer.
     */
    private boolean isLayerSource;

    /**
     * Flags if source object is a folder.
     */
    private boolean isFolderSource;

    /**
     * Flags if source object is a mix of layers and/or folders.
     */
    private boolean isMixedSource;

    /**
     * Flags if target object is a layer.
     */
    private boolean isLayerTarget;

    /**
     * Flags if target object is a folder.
     */
    private boolean isFolderTarget;

    /**
     * Source objects.
     */
    private List<Object> sources;

    /**
     * Target object.
     */
    private Object target;

    /**
     * Creates a legend item drop action
     */
    public LegendDropAction() {
        // Nothing
    }

    @Override
    public void init(IConfigurationElement element2, DropTargetEvent event2,
            ViewerDropLocation location2, Object destination2, Object data2) {
        super.init(element2, event2, location2, destination2, data2);
        initDropConditions();
    }
   
    @Override
    public boolean accept() {
        if (isValidObjects() && isValidDropLocation(getViewerLocation())) {
            return true;
        }
        return false;
    }

    /**
     * Checks if the source and target objects are valid for drag and drop action.
     *
     * @return trur if valid, otherwise false
     */
    private boolean isValidObjects() {
        // Check if either source or destination is null
        if (sources == null || target == null) {
            return false;
        }
        // Check if selection is more than 1
        if (sources.size() > 1) {
            return false;
        }
        // Check if source and destination is the same
        if (sources.size() == 1 && sources.get(0) == getDestination()) {
            return false;
        }
        return true;
    }
   
    /**
     * Checks if the drop location if valid relative to the source and target objects.
     *
     * @param location
     * @return true if valid, otherwise false
     */
    private boolean isValidDropLocation(ViewerDropLocation location) {
        // Check if there is a drop location
        if (location == ViewerDropLocation.NONE) {
            return false;
        } else if (location == ViewerDropLocation.ON) {
            // Check if data being put inside is mixed
            if (isMixedSource) {
                return false;
            }
            // Check if layer data is being put inside another layer
            if (isLayerSource && isLayerTarget) {
                return false;
            }
            // Check if layer data is being put inside another layer
            if (isFolderSource && isLayerTarget) {
                return false;
            }
            // Check if data is being put inside its own parent
            if (isParent(getData(), getDestination())) {
                return false;
            }
            // Check if folder is being put inside its own descendant
            if (isDescendant(getData(), getDestination())) {
                return false;
            }
        } else {
            // Check if folder is being moved its own descendant
            if (isDescendant(getData(), getDestination())) {
                return false;
            }
        }
        return true;
    }
   
    @Override
    public void perform(IProgressMonitor monitor) {

        for (Object source : sources) {

            final ViewerDropLocation location = getViewerLocation();
            if (ViewerDropLocation.NONE == location) {
                // Do nothing
            } else if (ViewerDropLocation.ON == location) {
                moveIn(source);
            } else {
                move(source, location);
            }

        }

    }

    /**
     * Performs moving in the source object into a folder.
     *
     * @param source
     */
    private void moveIn(Object source) {
        final ILegendItem sourceItem = (ILegendItem) source;
        final Folder folder = (Folder) target;
        folder.getItems().add(sourceItem);
    }

    /**
     * Performs moving the source object below or above another object. This can also move objects
     * in and out of a folder with a specific drop location.
     *
     * @param source
     * @param location
     */
    private void move(Object source, ViewerDropLocation location) {

        final ILegendItem sourceItem = (ILegendItem) source;
       
        final List<ILegendItem> sourceSiblings = getSiblings(source);
        final List<ILegendItem> targetSiblings = getSiblings(target);

        if (sourceSiblings == targetSiblings) {

            sourceSiblings.remove(source);
            int targetIndexNew = targetSiblings.indexOf(getDestination());

            if (location == ViewerDropLocation.BEFORE) {
                targetSiblings.add(targetIndexNew, sourceItem);
            } else if (location == ViewerDropLocation.AFTER) {
                targetSiblings.add(targetIndexNew + 1, sourceItem);
            }

        } else {
            int targetIndex = targetSiblings.indexOf(getDestination());
            if (location == ViewerDropLocation.AFTER) {
                targetIndex++;
            }
            targetSiblings.add(targetIndex, sourceItem);
        }

    }
   
    /**
     * Gets siblings of the object. This includes the object in the correct order in their
     * containing list.
     * <p>
     * Examples: map.getLegend() or folder.getItems()
     *
     * @param object
     * @return siblings
     */
    private List<ILegendItem> getSiblings(Object object) {
        final Object parent = getParent(object);
        if (parent instanceof Map) {
            return ((Map) parent).getLegend();
        } else if (parent instanceof Folder) {
            return ((Folder) parent).getItems();
        }
        return null;
    }
   
    /**
     * Gets the parent of the object inside the legend items list. This returns null if the object
     * is not a descendant of the list.
     *
     * @param object
     * @return parent
     */
    private Object getParent(Object object) {
        final Map map = getActiveMap();
        final List<ILegendItem> items = map.getLegend();
        if (items.contains(object)) {
            return map;
        }
        for (ILegendItem item : items) {
            if (item instanceof Folder) {
                final Object parent = getParent((Folder) item, object);
                if (parent != null) {
                    return parent;
                }
            }
        }
        return null;
    }
   
    /**
     * Gets the parent of the object inside the folder. This returns null if the object is not a
     * descendant of the folder.
     *
     * @param folder
     * @param object
     * @return parent
     */
    private Object getParent(Folder folder, Object object) {
        if (folder.getItems().contains(object)) {
            return folder;
        }
        for (ILegendItem folderItem : folder.getItems()) {
            if (folderItem instanceof Folder) {
                final Object parent = getParent((Folder) folderItem, object);
                if (parent != null) {
                    return parent;
                }
            }
        }
        return null;
    }
   
    /**
     * Checks if the target is the parent of the source.
     *
     * @param source
     * @param target
     * @return true if parent, otherwise false
     */
    private boolean isParent(Object source, Object target) {
        return getParent(source) == target;
    }
   
    /**
     * Checks if the target is a descendant of the source.
     *
     * @param source
     * @param target
     * @return true if descendant, otherwise false
     */
    private boolean isDescendant(Object source, Object target) {
        if (source instanceof Folder) {
            final Folder folder = (Folder) source;
            for (ILegendItem folderItem : folder.getItems()) {
                if (folderItem == target) {
                    return true;
                } else if (folderItem instanceof Folder) {
                    if (isDescendant(folderItem, target)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * Gets the active map.
     *
     * @return map
     */
    private Map getActiveMap() {
        return (Map) ApplicationGIS.getActiveMap();
    }
   
    /**
     * Initialises the drag/drop conditions and flags to process the action.
     */
    private void initDropConditions() {
        checkSource(getData());
        checkTarget(getDestination());
    }

    /**
     * Checks the source data then sets flags and variables to process the drop/drop action.
     *
     * @param data
     */
    private void checkSource(Object data) {

        sources = null;
        isFolderSource = false;
        isLayerSource = false;
        isMixedSource = false;

        if (data != null) {
            sources = new ArrayList<Object>();
            if (data instanceof Object[]) {
                for (Object dataItem : (Object[]) data) {
                    sources.add(dataItem);
                }
                isMixedSource = true;
            } else {
                if (data instanceof LayerLegendItem) {
                    sources.add(data);
                    isLayerSource = true;
                } else if (data instanceof Folder) {
                    sources.add(data);
                    isFolderSource = true;
                }
            }
        }

    }

    /**
     * Checks the target data then sets flags and variables to process the drop/drop action.
     *
     * @param data
     */
    private void checkTarget(Object data) {

        target = null;
        isFolderTarget = false;
        isLayerTarget = false;

        if (data != null) {
            if (data instanceof LayerLegendItem) {
                target = data;
                isLayerTarget = true;
            } else if (data instanceof Folder) {
                target = data;
                isFolderTarget = true;
            }
        }

    }

}
TOP

Related Classes of org.locationtech.udig.project.ui.internal.actions.LegendDropAction

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.