Package org.locationtech.udig.project.ui.internal.tool.display

Source Code of org.locationtech.udig.project.ui.internal.tool.display.ToolManager$PasteAction

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2004-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.tool.display;

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.locationtech.udig.catalog.IGeoResource;
import org.locationtech.udig.core.filter.AdaptingFilter;
import org.locationtech.udig.core.filter.AdaptingFilterFactory;
import org.locationtech.udig.core.internal.ExtensionPointList;
import org.locationtech.udig.internal.ui.UDIGDNDProcessor;
import org.locationtech.udig.internal.ui.UDIGDropHandler;
import org.locationtech.udig.internal.ui.UDigByteAndLocalTransfer;
import org.locationtech.udig.internal.ui.UiPlugin;
import org.locationtech.udig.internal.ui.operations.OperationCategory;
import org.locationtech.udig.internal.ui.operations.OperationMenuFactory;
import org.locationtech.udig.internal.ui.operations.RunOperationsAction;
import org.locationtech.udig.project.EditManagerEvent;
import org.locationtech.udig.project.IEditManagerListener;
import org.locationtech.udig.project.ILayer;
import org.locationtech.udig.project.IMap;
import org.locationtech.udig.project.internal.Map;
import org.locationtech.udig.project.internal.ProjectPackage;
import org.locationtech.udig.project.internal.commands.CreateMapCommand;
import org.locationtech.udig.project.ui.ApplicationGIS;
import org.locationtech.udig.project.ui.internal.ApplicationGISInternal;
import org.locationtech.udig.project.ui.internal.MapEditor;
import org.locationtech.udig.project.ui.internal.MapEditorPart;
import org.locationtech.udig.project.ui.internal.MapEditorWithPalette;
import org.locationtech.udig.project.ui.internal.MapPart;
import org.locationtech.udig.project.ui.internal.Messages;
import org.locationtech.udig.project.ui.internal.ProjectUIPlugin;
import org.locationtech.udig.project.ui.internal.actions.Delete;
import org.locationtech.udig.project.ui.internal.tool.ToolContext;
import org.locationtech.udig.project.ui.internal.tool.impl.ToolContextImpl;
import org.locationtech.udig.project.ui.tool.IContextMenuContributionTool;
import org.locationtech.udig.project.ui.tool.IToolManager;
import org.locationtech.udig.project.ui.tool.ModalTool;
import org.locationtech.udig.project.ui.tool.Tool;
import org.locationtech.udig.project.ui.tool.ToolConstants;
import org.locationtech.udig.project.ui.tool.options.PreferencesShortcutToolOptionsContributionItem;
import org.locationtech.udig.project.ui.viewers.MapEditDomain;
import org.locationtech.udig.ui.IDropAction;
import org.locationtech.udig.ui.IDropHandlerListener;
import org.locationtech.udig.ui.UDIGDragDropUtilities;
import org.locationtech.udig.ui.ViewerDropLocation;
import org.locationtech.udig.ui.operations.LazyOpFilter;
import org.locationtech.udig.ui.operations.OpAction;
import org.locationtech.udig.ui.operations.OpFilter;

import org.eclipse.core.commands.Command;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.StatusLineManager;
import org.eclipse.jface.action.SubCoolBarManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.HelpListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IKeyBindingService;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.SubActionBars2;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.dialogs.PropertyDialogAction;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.part.ViewPart;
import org.opengis.filter.Filter;

/**
* Manages Edit tools activation and registration.
* <p>
* The tool manager is a used by the MapEditor to populate the
* menu and action bars. It is responsible for processing the tools
* extension point and making action contributions as needed.
* <p>
* New for uDig 1.1:
* <ul>
* <li>We will check for an ActionSet with the same name as the tool category,
* this will allow you to turn off actions that don't make sense for your current
* workflow (ie perspective change).
* </ul>
*
* @author Jesse Eichar (Refractions Research Inc)
* @since 0.6.0
*/
public class ToolManager implements IToolManager {
    /**
     * This is a list of all tool actions(buttons) that are not part of the editor toolbar. For
     * example the info view may have a tool as part of its toolbar which is a proxy for the real
     * tool on the editor view.
     */
    Set<IAction> registeredToolActions = new HashSet<IAction>();
    /**
     * List of categorieIds; these may or may not be
     * associated with an ActionSet.
     */
    protected List<String> categoryIds = new ArrayList<String>();
   
    /**
     * These represent modal tools that complete take over the map.
     */
    List<ModalToolCategory> modalCategories = new LinkedList<ModalToolCategory>();
    /**
     * These represent fire and forget actions like zoomIn and zoomOut.
     */
    List<ActionToolCategory> actionCategories = new LinkedList<ActionToolCategory>();
   
    /**
     * These represent additions made to the menu.
     */
    List<MenuToolCategory> menuCategories = new LinkedList<MenuToolCategory>();
    /**
     *
     * I think these are the tools that lurk in the background updating state
     * like the status bar.
     */
    List<ToolProxy> backgroundTools = new LinkedList<ToolProxy>();
    /**
     * Shared images assoicated with these tools; used for everything from
     * cursors to button icons.
     */
    ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
   
    /**
     * Cache of all configured cursors.
     */
    protected java.util.Map<String, CursorProxy> cursorsCache = new HashMap<String, CursorProxy>();

    /**
     * Proxy for the active tool (ie statue of the editor).
     * <p>
     * The category of this tool will behave a little like a persepctive; since
     * the nature of the editor changes complety with the current tool. As such
     * the Edit menu may change what actions are available based on what subject
     * matter this tool is working on.
     */
    private ToolProxy activeModalToolProxy;
   
    /**
     * Current active tool; this represents the state of the editor.
     * <p>
     * This is considered an internal detail of ToolManager.
     */
    private ModalTool activeTool;
   
    /**
     * Default modal tool. This tool is set during initialisation of
     * tools by ToolProxy.DEFAULT_ID.
     */
    ToolProxy defaultModalToolProxy;

    Lock redoLock=new ReentrantLock();
    Lock undoLock=new ReentrantLock();
    Lock forwardLock=new ReentrantLock();
    Lock backwardLock=new ReentrantLock();
    Lock deleteLock=new ReentrantLock();
    Lock enterLock=new ReentrantLock();
    Lock pasteLock=new ReentrantLock();
    Lock propertiesLock=new ReentrantLock();
    Lock copyLock=new ReentrantLock();
    Lock cutLock=new ReentrantLock();

    private volatile IAction redoAction;
    private volatile IAction undoAction;
    private volatile IAction forwardAction;
    private volatile IAction backwardAction;
    private volatile IAction deleteAction;
    private volatile IAction enterAction;
    private volatile IAction zoomToSelectionAction;
    private volatile IAction pasteAction;
    private volatile IAction copyAction;
    private volatile IAction cutAction;
   
    private AdapterImpl commandListener;
   
    private List<ContributionItem> optionsContribution = new ArrayList<ContributionItem>();

    /**
     * Construct <code>ToolManager</code>.
     */
    public ToolManager() {
        processCategories();
        processTools();
        removeEmptyCategories();
        Collections.sort(categoryIds, new CategorySorter());
        setCommandHandlers();
    }
   
    /**
     * Populates the categories with their associated tools
     */
    private void processTools() {
        List<IConfigurationElement> extensionList = ExtensionPointList
                .getExtensionPointList(Tool.EXTENSION_ID);
        for( IConfigurationElement element : extensionList ) {
            IExtension extension = element.getDeclaringExtension();
            String type = element.getName();

            if (type.equals("backgroundTool")) { //$NON-NLS-1$

                ToolProxy proxy = new ToolProxy(extension, element, this);
                backgroundTools.add(proxy);
            } else if (type.equals("modalTool")) { //$NON-NLS-1$
                String categoryId = getCategoryIdAttribute(element); //$NON-NLS-1$
                ToolProxy proxy = new ToolProxy(extension, element, this);

                addToModalCategory(categoryId, proxy);
            } else if (type.equals("actionTool")) { //$NON-NLS-1$
                String categoryId = getCategoryIdAttribute(element); //$NON-NLS-1$
                ToolProxy proxy = new ToolProxy(extension, element, this);

                addToActionCategory(categoryId, proxy);
                addToMenuCategory(categoryId, proxy);
            }else if(type.equals("toolCursor")){ //$NON-NLS-1$
            CursorProxy cursorProxy = new CursorProxy(element);
            cursorsCache.put(cursorProxy.getID(), cursorProxy);
            }
        }
       
        if( activeModalToolProxy  == null ){
          activeModalToolProxy = defaultModalToolProxy;
        }
    }

  private String getCategoryIdAttribute(IConfigurationElement element) {
    String id  = element.getAttribute("categoryId");
    return id == null? "" : id;
  }
   

    /**
     * Finds cursor proxy by ID in cache.
     */
    public Cursor findToolCursor(String cursorID){
     
      CursorProxy cursorProxy = cursorsCache.get(cursorID);
      if(cursorProxy != null)
        return cursorProxy.getCursor();
     
      Cursor systemCursor = CursorProxy.getSystemCursor(cursorID);
      if(systemCursor != null)
        return systemCursor;
     
     
      return null;
     
    }
   

    /**
     * Find a tool with the provided ID.
     * <p>
     * In the current implementation finds only among modal tools.
     * TODO Extend findTool to search for non modal tools
     * @param toolID toolId to search for
     * @return Modal tool if found, or null
     */
  public Tool findTool(String toolID) {
    for(ModalToolCategory category : modalCategories){
      for (ModalItem item : category) {
        if(toolID.equals(item.getId())){
          return ((ToolProxy)item).getTool();
        }
      }
    }
    return null;
  }

 
    /**
     * Find a tool proxy with the provided ID.
     * <p>This searches modal tools, background tools, and
     * action tools</p>
     * @param toolID toolId to search for
     * @return ToolProxy of tool if found or null
     */
  public ToolProxy findToolProxy(String toolID) {
    for(ModalToolCategory category : modalCategories){
      for (ModalItem item : category) {
        if(toolID.equals(item.getId())){
          return (ToolProxy)item;
        }
      }
    }
    for(ActionToolCategory category : actionCategories){
      for (ModalItem item : category) {
        if(toolID.equals(item.getId())){
          return (ToolProxy)item;
        }
      }
    }
    for(ToolProxy item : backgroundTools){
      if(toolID.equals(item.getId())){
        return (ToolProxy)item;
      }
    }
    return null;
  }
 
    private void addToModalCategory( String categoryId, ToolProxy proxy ) {
        if( filterTool(categoryId, proxy, ModalToolCategory.class) ){
            return;
        }
        ModalToolCategory modalCategory = findModalCategory(categoryId);
        if (modalCategory == null) {
            modalCategory = findModalCategory(Messages.ToolCategory_other);
            if (modalCategory == null) {
                modalCategory = new ModalToolCategory(this);
                modalCategories.add(modalCategory);
                if (!categoryIds.contains(Messages.ToolCategory_other))
                    categoryIds.add(Messages.ToolCategory_other);
            }
        }
        modalCategory.add(proxy);
    }

    /**
     * This method is called each time an action is about to be added to a category. 
     * If the message returns true the tool <b>will not</b> be added.
     * The default implementation always returns false.
     *
     * @param categoryId the id of the category that the tool will be added to, this will never be null
     * @param proxy the proxy for the tool. 
     * @param categoryType the type of category
     *
     * @return true if the tool will NOT be added to the category
     */
    protected boolean filterTool( String categoryId, ToolProxy proxy, Class<? extends ToolCategory> categoryType ) {
        return false;
    }

    private void addToMenuCategory( String categoryId, ToolProxy proxy ) {

        if( filterTool(categoryId, proxy, MenuToolCategory.class) ){
            return;
        }
        MenuToolCategory category = findMenuCategory(categoryId);
        if (category == null) {
            category = findMenuCategory(Messages.ToolCategory_other);

            if (category == null) {
                category = new MenuToolCategory(this);
                menuCategories.add(category);
                if (!categoryIds.contains(Messages.ToolCategory_other))
                    categoryIds.add(Messages.ToolCategory_other);
            }
        }
        category.add(proxy);
    }

    private void addToActionCategory( String categoryId, ToolProxy proxy ) {
        if( filterTool(categoryId, proxy, ActionToolCategory.class) ){
            return;
        }
       
        ActionToolCategory category = findActionCategory(categoryId);
        if (category == null) {
            category = findActionCategory(Messages.ToolCategory_other);

            if (category == null) {
                category = new ActionToolCategory(this);
                actionCategories.add(category);
                if (!categoryIds.contains(Messages.ToolCategory_other))
                    categoryIds.add(Messages.ToolCategory_other);
            }
        }
        category.add(proxy);
    }

    /**
     * Processes the extension point and creates all the categories.
     */
    private void processCategories() {
        List<IConfigurationElement> extension = ExtensionPointList
                .getExtensionPointList(Tool.EXTENSION_ID);
       
        for( IConfigurationElement element : extension ) {
            if (!element.getName().equals("category")) //$NON-NLS-1$
                continue;
            ModalToolCategory modalCategory;
            String id = element.getAttribute("id"); //$NON-NLS-1$
            categoryIds.add(id);
            modalCategory = findModalCategory(id);
            if (modalCategory == null) {
                modalCategory = new ModalToolCategory(element, ToolManager.this);
                modalCategories.add(modalCategory);
            }
            ActionToolCategory actionCategory;
            actionCategory = findActionCategory(id);
            if (actionCategory == null) {
                actionCategory = new ActionToolCategory(element, ToolManager.this);
                actionCategories.add(actionCategory);
            }
            MenuToolCategory category;
            category = findMenuCategory(id);
            if (category == null) {
                category = new MenuToolCategory(element, ToolManager.this);
                menuCategories.add(category);
            }
        }
    }

    private void removeEmptyCategories() {
        List<ToolCategory> toRemove = new ArrayList<ToolCategory>();
        for( ActionToolCategory category : actionCategories ) {
            if (category.items.size() == 0)
                toRemove.add(category);
        }
        actionCategories.removeAll(toRemove);
        for( ModalToolCategory category : modalCategories ) {
            if (category.items.size() == 0)
                toRemove.add(category);
        }
        modalCategories.removeAll(toRemove);
        for( MenuToolCategory category : menuCategories ) {
            if (category.items.size() == 0)
                toRemove.add(category);
        }
        menuCategories.removeAll(toRemove);
    }
    /**
     * Register commands handlers; so they can be used by the keyboard short cut system.
     */
    private void setCommandHandlers() {
        Set<String> ids = new HashSet<String>();
        ICommandService service = (ICommandService) PlatformUI.getWorkbench().getAdapter(
                ICommandService.class);
        for( ModalToolCategory category : modalCategories ) {
            if (!ids.contains(category.getId())) {
                ids.add(category.getId());
                category.setCommandHandlers(service);
            }
            registerCommands(ids, service, category);
        }
        for( ActionToolCategory category : actionCategories ) {
            if (!ids.contains(category.getId())) {
                ids.add(category.getId());
                category.setCommandHandlers(service);
            }
            registerCommands(ids, service, category);
        }
        for( MenuToolCategory category : menuCategories ) {
            if (!ids.contains(category.getId())) {
                ids.add(category.getId());
                category.setCommandHandlers(service);
            }
            registerCommands(ids, service, category);
        }
    }

    /**
     * Register commands; so they can be picked up by command handlers.
     * <p>
     * These command/handler system is used to hook our tools up to the keyboard
     * short cut system.
     * <p>
     * @param ids
     * @param service
     * @param category
     */
    private void registerCommands( Set<String> ids, ICommandService service, ToolCategory category ) {
        for( ModalItem tool : category ) {
            if (!ids.contains(tool.getId())) {
                ids.add(category.getId());

                for( String currentId : tool.getCommandIds() ) {
                    currentId=currentId.trim();
                    Command command = service.getCommand(currentId);
                    if (command != null)
                        command.setHandler(tool.getHandler(currentId));
                }
            }
        }
    }
   
    MapPart currentEditor;

    /**
     * This method is called to perform tools initialisation when
     * the map editor is selected.
     */
    public void setCurrentEditor( MapPart editor ) {
     
        if( editor==currentEditor ){
            return;
        }
        currentEditor = editor;
        if (editor != null) {
            if (editor != null) {
                setActiveTool(editor);
                setEnabled(editor.getMap(), actionCategories);
                setEnabled(editor.getMap(), menuCategories);
                setEnabled(editor.getMap(), modalCategories);
            }
        } else {
            disable(actionCategories);
            disable(menuCategories);
            disable(modalCategories);
        }  
       
       
    }
    /**
     * Churn through the category disabling all tools.
     *
     * @param categories
     */
    private void disable( List<? extends ToolCategory> categories ) {
        for( ToolCategory category : categories ) {
            for( ModalItem item : category ) {
                OpFilter enablesFor = item.getEnablesFor();
                if( enablesFor instanceof LazyOpFilter)
                    ((LazyOpFilter)enablesFor).disable();
            }
        }
    }

    EditManagerListener selectedLayerListener;

    private PropertyDialogAction propertiesAction;
   
    /**
     * Listener for EditManager.
     *
     * @author Vitalus
     *
     */
    class EditManagerListener implements IEditManagerListener{
     
      public void setCurrentMap(IMap map){
        
      }

        public void changed( EditManagerEvent event ) {
           
            if (selectedLayerListener != this) {
                event.getSource().removeListener(this);
                return;
            }
            if (event.getType() == EditManagerEvent.SELECTED_LAYER) {
                setEnabled(event.getSource().getMap(), actionCategories);
                setEnabled(event.getSource().getMap(), menuCategories);
                setEnabled(event.getSource().getMap(), modalCategories);
            }
        }
    }
    /**
     * Heads through the categories giving each tool a chance to enable/disable itself.
     * <p>
     * Specifically we grab the OpFilter and give it a chance to determine if
     * the tool is enabled; currently OpFilter is focused on the selectedLayer
     * but I hope to break this out to process more general "core expressions"
     * in the future (but we have to wait for someone to ask first).
     *
     * @param map
     * @param categories
     */
    private void setEnabled( IMap map, Collection<? extends ToolCategory> categories) {
       
        if(selectedLayerListener == null)
          selectedLayerListener = new EditManagerListener();
       
        selectedLayerListener.setCurrentMap(map);

        //One listener is enough. Say NO to listeners hell:)
        if(!map.getEditManager().containsListener(selectedLayerListener))
          map.getEditManager().addListener(selectedLayerListener);
       
        for( ToolCategory cat : categories ) {
            for( ModalItem item : cat ) {
                OpFilter enablesFor = item.getEnablesFor();
                ILayer selectedLayer = map.getEditManager().getSelectedLayer();

                // JG: I don't trust asserts in production code!
                // assert enablesFor instanceof LazyOpFilter;
               
                if( !(enablesFor instanceof LazyOpFilter) ){
                    enablesFor = new LazyOpFilter(item, enablesFor);
                }
               
                boolean accept = enablesFor.accept(selectedLayer);
                item.setEnabled(accept);
            }
        }
    }

    /**
     * Sets the context of the currently active tool and ensures that all tools are enabled.
     * <p>
     * This is called by the "support views" associated with the MapEditor,
     * it is used so the tools can be active even when the MapEditor does not have the focus.
     * Without this modification you would need to constantly select the MapEditor, change the tool
     * and then get to work.
     * <p>
     * Aside: it would be good if selecting a tool made the MapEditor grab focus.
     * <p>
     * @param editor MapEditor associated with the support view (such as the Layers view)
     */
    @SuppressWarnings("unchecked")
    void setActiveTool( MapPart editor ) {
        // ensure we are listening to this MapPart's Map
        Map map = editor.getMap();
        Adapter listener = getCommandListener(editor);
        if (!map.eAdapters().contains(listener)){
            map.eAdapters().add(listener);
        }
       
        // Define the tool context allowing tools to interact with this map
        ToolContext tools = new ToolContextImpl();
        tools.setMapInternal(map);
       
        // Provide each tool with the new tool context
        //
        setContext(modalCategories, tools); // if active a modal tool is supposed to register listeners
        setContext(actionCategories, tools);
        setContext(menuCategories, tools);
        for( ToolProxy tool : backgroundTools ) {
            tool.setContext(tools);
        }
        for( IAction action : registeredToolActions){
            action.setEnabled(true);
        }

        setCommandActions(map, editor);
       
        // wire in the current activeModalTool
        if( activeModalToolProxy != null ){
            if( !activeModalToolProxy.isActive() ){
                // work around to allow the 1st modal tool to be active
                if( activeTool == null ){
                    activeTool = activeModalToolProxy.getModalTool();
                    // add tool options to the status area
                    initToolOptionsContribution(editor.getStatusLineManager(), activeModalToolProxy);
                }
                activeModalToolProxy.getModalTool().setActive(true);               
            }
            editor.setSelectionProvider(activeModalToolProxy.getSelectionProvider());
            if( editor instanceof MapEditorWithPalette){
                // temporary cast while we sort out if MapPart can own an MapEditDomain
                MapEditorWithPalette editor2 = (MapEditorWithPalette) editor;
                MapEditDomain editDomain = editor2.getEditDomain();
                editDomain.setActiveTool( activeModalToolProxy.getId() );
            }

        }
    }
    /**
     * Go through List of ToolCategory and update each Tool with the new tool context.
     * @param categories
     * @param tools
     */
    private void setContext( List<? extends ToolCategory> categories, ToolContext tools ) {
        forToolCategory category : categories ) {
            for(ModalItem item : category.items ) {
                ToolProxy tool = (ToolProxy) item;
                tool.setContext(tools);
            }
        }
    }

    /**
     * Adds an Action that executes a tool to the toolbar.
     *
     * @param action
     */
    public void addToolAction( IAction action ) {
        registeredToolActions.add(action);
        action.setEnabled(ApplicationGIS.getActiveMap() != ApplicationGIS.NO_MAP);
    }

    /**
     * Creates a action that acts as a proxy for the tool in the editor toolbar.
     * <p>
     * The client code must set the name image descriptor etc... of the Action
     * </p>
     *
     * @param toolID the id of the tool
     * @param categoryID the category the tool is part of
     * @return a proxy action that can be put in other toolbars
     */
    public IAction createToolAction( final String toolID, final String categoryID ) {
        final IAction toolAction = new Action(){
            @Override
            public void runWithEvent( Event event ) {
                IAction action = getTool(toolID, categoryID);
                if (action != null && action.isEnabled()) {
                    action.runWithEvent(event );
                }
            }
        };
        toolAction.addPropertyChangeListener(new IPropertyChangeListener(){

            public void propertyChange( PropertyChangeEvent event ) {
                if( event.getProperty().equals(IAction.ENABLED)){
                    toolAction.setEnabled((Boolean) event.getNewValue());
                }
            }
           
        });
        toolAction.setEnabled(getTool(toolID, categoryID).isEnabled());
        addToolAction(toolAction);
        return toolAction;
    }
    public ActionToolCategory findActionCategory( String id ) {
        for( ActionToolCategory category : actionCategories ) {
            if (category.getId().equals(id))
                return category;
        }
        return null;
    }
    MenuToolCategory findMenuCategory( String id ) {
        for( MenuToolCategory category : menuCategories ) {
            if (category.getId().equals(id))
                return category;
        }
        return null;
    }
    protected ModalToolCategory findModalCategory( String id ) {
        for( ModalToolCategory category : modalCategories ) {
            String id2 = category.getId();
            if (id2.equals(id))
                return category;
        }
        return null;
    }

    /**
     * Used to contribute Tools to the provided menu manger.
     * <p>
     * The following contributions are made:
     * <ul>
     * <li>navigate: forward and backward buttons
     * <li>map: an entry for each tool category
     * </ul>
     */
    public void contributeToMenu( IMenuManager manager ) {
        IMenuManager navigateMenu = manager.findMenuUsingPath(IWorkbenchActionConstants.M_NAVIGATE);
       
        if (navigateMenu == null) {
            // I would like to arrange for the Navigate menu to already
            // be in place before the ToolManager is kicked into action
            // (this is part of the missions to have uDig plugins walk
            //  softly when being hosted in other RCP applications)
            // See UDIGActionBarAdvisor for hosting requirements.
          navigateMenu = new MenuManager(
              Messages.ToolManager_menu_manager_title, IWorkbenchActionConstants.M_NAVIGATE);

          IContributionItem additions = manager.find(IWorkbenchActionConstants.MB_ADDITIONS);
      if( additions==null || !(additions instanceof GroupMarker) ){
        manager.add(navigateMenu);
          }else{
            manager.appendToGroup(IWorkbenchActionConstants.MB_ADDITIONS, navigateMenu);
          }     
            navigateMenu.add(new GroupMarker(IWorkbenchActionConstants.NAV_START));
            navigateMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));           
            navigateMenu.add(new GroupMarker(IWorkbenchActionConstants.NAV_END));
        }
        IWorkbench workbench = PlatformUI.getWorkbench();
        IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
        // we are using the global BACK and FORWARD actions here
        // and will register "handlers" for these commands
        navigateMenu.appendToGroup(IWorkbenchActionConstants.NAV_END,
            ActionFactory.BACK.create(window));
        navigateMenu.appendToGroup(IWorkbenchActionConstants.NAV_END,
            ActionFactory.FORWARD.create(window));
       
        if (!manager.isVisible()){
            // since this is the top level menu bar why would it not be visible?
            manager.setVisible(true);
        }       
        IMenuManager mapMenu = manager.findMenuUsingPath("map");       
        if( mapMenu == null ){
            // Once again the hosting RCP application should of provided
            // us with a Map menu; but let's be careful and make our own here
            // if needed.
            // See UDIGActionBarAdvisor for hosting requirements.
            mapMenu = new MenuManager(Messages.ToolManager_menu_manager_title, "map");
            manager.add(mapMenu);
            mapMenu.add(new GroupMarker("mapStart"));
            mapMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
            mapMenu.add(new GroupMarker("mapEnd"));
        }       
        // churn through each category and add stuff as needed
        // note we check with the cmdService to see what we if the actionSet
        // associated with this cateogry is turned on by the
        // current perspective.
        for( MenuToolCategory category : menuCategories ) {
            category.contribute(manager);
        }
    }
   
   
   

    /** (non-Javadoc)
     *
     * @see org.locationtech.udig.project.ui.tool.IToolManager#contributeActiveModalTool(org.eclipse.jface.action.IMenuManager)
     */
    public void contributeActiveModalTool( IMenuManager manager ) {
       
        Tool activeTool = getActiveTool();
        if(activeTool instanceof IContextMenuContributionTool){
            IContextMenuContributionTool contributionTool = (IContextMenuContributionTool)activeTool;
            ArrayList<IContributionItem> contributions = new ArrayList<IContributionItem>();
            contributionTool.contributeContextMenu(contributions);
           
            if(!contributions.isEmpty()){
                manager.add(new Separator());
                for( IContributionItem item : contributions ) {
                    manager.add(item);
                }
            }
        }
    }

    /**
     * Retrieves the redo action that is used by much of the map components such as the MapEditor
     * and the LayersView. redoes the last undone command sent to the currently active map.
     */
    public IAction getREDOAction() {
        Map activeMap = ApplicationGISInternal.getActiveMap();
        redoLock.lock();
        try{
            if (redoAction == null) {
                redoAction = new Action(){
                    /**
                     * @see org.eclipse.jface.action.Action#run()
                     */
                    public void run() {
                        Map activeMap = ApplicationGISInternal.getActiveMap();
                        if (activeMap != ApplicationGIS.NO_MAP)
                            activeMap.redo();
                    }
                };
                redoAction.setImageDescriptor(sharedImages
                        .getImageDescriptor(ISharedImages.IMG_TOOL_REDO));
                redoAction.setText(Messages.ToolManager_redoAction);
                redoAction.setActionDefinitionId("org.eclipse.ui.edit.redo"); //$NON-NLS-1$
            }
            if (activeMap != ApplicationGIS.NO_MAP)
                redoAction.setEnabled(activeMap.getCommandStack().canRedo());
            else
                redoAction.setEnabled(false);

        return redoAction;
        }finally{
            redoLock.unlock();
        }
    }

    /**
     *
     */
    public void setREDOAction( IAction action, IWorkbenchPart part ) {
        if( action == null )
            throw new NullPointerException("action must not be null"); //$NON-NLS-1$
        if( part == null )
            throw new NullPointerException("part must not be null"); //$NON-NLS-1$
        redoLock.lock();
        try {
            redoAction = action;
            redoAction.setActionDefinitionId("org.eclipse.ui.edit.redo"); //$NON-NLS-1$
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(redoAction);
        } finally {
            redoLock.unlock();
        }
    }
    /**
     * Retrieves the undo action that is used by much of the map components such as the MapEditor
     * and the LayersView. Undoes the last command sent to the currently active map.
     *
     * @param part
     */
    public IAction getUNDOAction() {
        Map activeMap = ApplicationGISInternal.getActiveMap();
        undoLock.lock();
        try{
            if (undoAction == null) {
                undoAction = new Action(){
                    /**
                     * @see org.eclipse.jface.action.Action#run()
                     */
                    public void run() {
                        Map activeMap = ApplicationGISInternal.getActiveMap();
                        if (activeMap != ApplicationGIS.NO_MAP)
                            activeMap.undo();
                    }
                };
                undoAction.setImageDescriptor(sharedImages
                        .getImageDescriptor(ISharedImages.IMG_TOOL_UNDO));
                undoAction.setText(Messages.ToolManager_undoAction);
                undoAction.setActionDefinitionId("org.eclipse.ui.edit.undo"); //$NON-NLS-1$
            }
            if (activeMap != ApplicationGIS.NO_MAP)
                undoAction.setEnabled(activeMap.getCommandStack().canUndo());
            else
                undoAction.setEnabled(false);
            return undoAction;
        }finally{
            undoLock.unlock();
        }
    }

    /**
     *
     */
    public void setUNDOAction( IAction action, IWorkbenchPart part ) {
        if( action == null )
            throw new NullPointerException("action must not be null"); //$NON-NLS-1$
        if( part == null )
            throw new NullPointerException("part must not be null"); //$NON-NLS-1$
        undoLock.lock();
        try{
            undoAction = action;
            undoAction.setActionDefinitionId("org.eclipse.ui.edit.undo"); //$NON-NLS-1$
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(undoAction);
        }finally{
            undoLock.unlock();
        }
    }
    /**
     * Retrieves the forward navigation action that is used by much of the map components such as
     * the MapEditor and the LayersView. Executes the last undone Nav command on the current map.
     */
    public IAction getFORWARD_HISTORYAction() {
        Map activeMap = ApplicationGISInternal.getActiveMap();
        forwardLock.lock();
        try{
            if (forwardAction == null) {
                forwardAction = new Action(){
                    /**
                     * @see org.eclipse.jface.action.Action#run()
                     */
                    public void run() {
                        Map activeMap = ApplicationGISInternal.getActiveMap();
                        if (activeMap != ApplicationGIS.NO_MAP)
                            activeMap.forwardHistory();
                    }
                };
                forwardAction.setImageDescriptor(sharedImages
                        .getImageDescriptor(ISharedImages.IMG_TOOL_FORWARD));
                forwardAction.setText(Messages.ToolManager_forward);
                forwardAction.setToolTipText(Messages.ToolManager_forward_tooltip);
                forwardAction.setActionDefinitionId("org.eclipse.ui.navigate.forward"); //$NON-NLS-1$
            }
            if (activeMap != ApplicationGIS.NO_MAP)
                forwardAction.setEnabled(activeMap.getCommandStack().canRedo());
            else
                forwardAction.setEnabled(false);
            return forwardAction;
        }finally{
            forwardLock.unlock();
        }

    }

    /**
     *
     */
    public void setFORWARDAction( IAction action, IWorkbenchPart part ) {
        if( action == null )
            throw new NullPointerException("action must not be null"); //$NON-NLS-1$
        if( part == null )
            throw new NullPointerException("part must not be null"); //$NON-NLS-1$
        forwardLock.lock();
        try{
            forwardAction = action;
            forwardAction.setActionDefinitionId("org.eclipse.ui.navigate.forward"); //$NON-NLS-1$
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(forwardAction);
        }finally{
            forwardLock.unlock();
        }
    }

    public void registerActionsWithPart( IWorkbenchPart part ) {

        IKeyBindingService service = part.getSite().getKeyBindingService();
        service.registerAction(getBACKWARD_HISTORYAction());
        service.registerAction(getFORWARD_HISTORYAction());
        service.registerAction(getCOPYAction(part));
        service.registerAction(getCUTAction(part));
        service.registerAction(getDELETEAction());
        service.registerAction(getPASTEAction(part));
        service.registerAction(getREDOAction());
        service.registerAction(getUNDOAction());
       
        addToolScope(part.getSite());
    }
   
    public void unregisterActions( IWorkbenchPart  part ){

        IKeyBindingService service = part.getSite().getKeyBindingService();

        service.unregisterAction(getBACKWARD_HISTORYAction());
        service.unregisterAction(getFORWARD_HISTORYAction());
        service.unregisterAction(getCOPYAction(part));
        service.unregisterAction(getCUTAction(part));
        service.unregisterAction(getDELETEAction());
        service.unregisterAction(getPASTEAction(part));
        service.unregisterAction(getREDOAction());
        service.unregisterAction(getUNDOAction());
       
        service.setScopes(new String[0]);
    }

    /**
     * Retrieves the backward navigation action that is used by much of the map components such as
     * the MapEditor and the LayersView. Undoes the last Nav command set to the current map.
     *
     * @param part
     */
    public IAction getBACKWARD_HISTORYAction() {
        Map activeMap = ApplicationGISInternal.getActiveMap();
        backwardLock.lock();
        try{
            if (backwardAction == null) {
                backwardAction = new Action(){
                    /**
                     * @see org.eclipse.jface.action.Action#run()
                     */
                    public void run() {
                        Map activeMap = ApplicationGISInternal.getActiveMap();
                        if (activeMap != ApplicationGIS.NO_MAP)
                            activeMap.backwardHistory();
                    }

                };
                backwardAction.setImageDescriptor(sharedImages
                        .getImageDescriptor(ISharedImages.IMG_TOOL_BACK));
                backwardAction.setText(Messages.ToolManager_back);
                backwardAction.setToolTipText(Messages.ToolManager_back_tooltip);
                backwardAction.setActionDefinitionId("org.eclipse.ui.navigate.back"); //$NON-NLS-1$
            }
            if (activeMap != ApplicationGIS.NO_MAP)
                backwardAction.setEnabled(activeMap.getCommandStack().canUndo());
            else
                backwardAction.setEnabled(false);
        }finally{
            backwardLock.unlock();
        }

        return backwardAction;
    }

    /**
     *
     */
    public void setBACKAction( IAction action, IWorkbenchPart part ) {
        if( action == null )
            throw new NullPointerException("action must not be null"); //$NON-NLS-1$
        if( part == null )
            throw new NullPointerException("part must not be null"); //$NON-NLS-1$
        backwardLock.lock();
        try{
            backwardAction = action;
            backwardAction.setActionDefinitionId("org.eclipse.ui.navigate.back"); //$NON-NLS-1$
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(backwardAction);
        }finally{
            backwardLock.unlock();
        }

    }
   
    /**
     *
     */
    public IAction getCUTAction( IWorkbenchPart part ) {
        cutLock.lock();
        try{
            if( cutAction==null ){
                cutAction=new Action(){
                   
                };
            }
            // JONES
            return cutAction;
        }finally{
            cutLock.unlock();
        }
    }

    public void setCUTAction( IAction action, IWorkbenchPart part ) {
        if( action == null )
            throw new NullPointerException("action must not be null"); //$NON-NLS-1$
        if( part == null )
            throw new NullPointerException("part must not be null"); //$NON-NLS-1$
        cutLock.lock();
        try{
            cutAction = action;
            cutAction.setActionDefinitionId("org.eclipse.ui.edit.cut"); //$NON-NLS-1$
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(cutAction);
        }finally{
            cutLock.unlock();
        }
    }

    public IAction getCOPYAction( final IWorkbenchPart part ) {
        copyLock.lock();
        try{
            if (copyAction == null) {
                copyAction = new CopyAction();
                IAction template = ActionFactory.COPY.create(part.getSite().getWorkbenchWindow());
                copyAction.setText(template.getText());
                copyAction.setToolTipText(template.getToolTipText());
                copyAction.setImageDescriptor(template.getImageDescriptor());
                copyAction.setId(template.getId());
                copyAction.setActionDefinitionId("org.eclipse.ui.edit.copy"); //$NON-NLS-1$
            }
            if (copyAction instanceof CopyAction) {
                ((CopyAction) copyAction).setPart(part);
            }
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(copyAction);
            return copyAction;
        }finally{
            copyLock.unlock();
        }
    }

    public void setCOPYAction( IAction action, IWorkbenchPart part ) {
        if( action == null )
            throw new NullPointerException("action must not be null"); //$NON-NLS-1$
        if( part == null )
            throw new NullPointerException("part must not be null"); //$NON-NLS-1$
        copyLock.lock();
        try{
            copyAction = action;
            copyAction.setActionDefinitionId("org.eclipse.ui.edit.copy"); //$NON-NLS-1$
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(copyAction);
        }finally{
            copyLock.unlock();
        }
    }
    //
    public IAction getPropertiesAction( IWorkbenchPart part, ISelectionProvider selectionProvider ) {
        propertiesLock.lock();
        try{
            if (propertiesAction == null ||
                    propertiesAction.getSelectionProvider() != selectionProvider ){
                propertiesAction  = new PropertyDialogAction( part.getSite().getWorkbenchWindow(), selectionProvider );
            }
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(propertiesAction);
            return propertiesAction;
        } finally {
            propertiesLock.unlock();
        }
    }
   
    public IAction getPASTEAction( IWorkbenchPart part ) {
        pasteLock.lock();
        try{
            if (pasteAction == null) {
                pasteAction = new PasteAction();
                IAction template = ActionFactory.PASTE.create(part.getSite().getWorkbenchWindow());
                pasteAction.setText(template.getText());
                pasteAction.setToolTipText(template.getToolTipText());
                pasteAction.setImageDescriptor(template.getImageDescriptor());
                pasteAction.setId(template.getId());
                pasteAction.setActionDefinitionId("org.eclipse.ui.edit.paste"); //$NON-NLS-1$
            }
            if (pasteAction instanceof PasteAction) {
                ((PasteAction) pasteAction).setPart(part);
            }
   
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(pasteAction);
            return pasteAction;
        }finally{
            pasteLock.unlock();
        }
    }

    public void setPASTEAction( IAction action, IWorkbenchPart part ) {
        if( action == null )
            throw new NullPointerException("action must not be null"); //$NON-NLS-1$
        if( part == null )
            throw new NullPointerException("part must not be null"); //$NON-NLS-1$
        pasteLock.lock();
        try{
            pasteAction = action;
            pasteAction.setActionDefinitionId("org.eclipse.ui.edit.paste"); //$NON-NLS-1$
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(pasteAction);
        }finally{
            pasteLock.unlock();
        }
    }

    public synchronized IAction getDELETEAction() {
        deleteLock.lock();
        try{
            if (deleteAction == null) {
                 deleteAction = new Action(){
                    @Override
                    public void run() {
                        IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                        ISelectionService selectionService = workbenchWindow.getSelectionService();
                        ISelection selection = selectionService.getSelection();
                       
                        Delete delete=new Delete( false );
                        delete.selectionChanged(this, selection);
                        delete.run(this);
                    }
                };
                deleteAction.setActionDefinitionId("org.eclipse.ui.edit.delete"); //$NON-NLS-1$
               
                IWorkbenchAction actionTemplate = ActionFactory.DELETE.create(PlatformUI.getWorkbench().getActiveWorkbenchWindow());
                deleteAction.setText(actionTemplate.getText());
                deleteAction.setToolTipText(actionTemplate.getToolTipText());
                deleteAction.setImageDescriptor(actionTemplate.getImageDescriptor());
                deleteAction.setDescription(actionTemplate.getDescription());
                deleteAction.setDisabledImageDescriptor(actionTemplate.getDisabledImageDescriptor());
            }
           
            return deleteAction;
        }finally{
            deleteLock.unlock();
        }
    }

    public synchronized void setDELETEAction( IAction action, IWorkbenchPart part ) {
        if( action == null )
            throw new NullPointerException("action must not be null"); //$NON-NLS-1$
        if( part == null )
            throw new NullPointerException("part must not be null"); //$NON-NLS-1$
        deleteLock.lock();
        try{
            deleteAction = action;
            deleteAction.setActionDefinitionId("org.eclipse.ui.edit.delete"); //$NON-NLS-1$
            IKeyBindingService service = part.getSite().getKeyBindingService();
            service.registerAction(deleteAction);
        }finally{
            deleteLock.unlock();
        }
    }
   
    public synchronized IAction getENTERAction() {
        enterLock.lock();
        try{
            if (enterAction == null) {
                enterAction = new Action(){
                    public void run() {
                        try {
                            Robot r = new Robot();
                            r.keyPress(KeyEvent.VK_ENTER);
                            r.keyRelease(KeyEvent.VK_ENTER);
                        } catch (AWTException e) {
                            e.printStackTrace();
                        }
                    }
                };
                enterAction.setText(Messages.ToolManager_enterAction);
                enterAction.setToolTipText(Messages.ToolManager_enterActionTooltip);
                enterAction.setDescription(Messages.ToolManager_enterActionTooltip);
            }
   
            return enterAction;
        }finally{
            enterLock.unlock();
        }
    }
   
    public synchronized IAction getZOOMTOSELECTEDAction() {
        enterLock.lock();
        try{
            if (zoomToSelectionAction == null) {
                zoomToSelectionAction = getToolAction("org.locationtech.udig.tool.default.show.selection", "org.locationtech.udig.tool.category.zoom");
            }
           
            return zoomToSelectionAction;
        }finally{
            enterLock.unlock();
        }
    }

    private void createModalToolToolbar( SubCoolBarManager cbmanager ) {
        ToolBarManager manager = new ToolBarManager(SWT.FLAT);

        for( String id : categoryIds ) {
            ModalToolCategory modalCategory = findModalCategory(id);
            if (modalCategory != null) {
                modalCategory.contribute(manager);
            }
        }
        if (manager != null && manager.getItems().length > 0)
            cbmanager.add(manager);
    }

    private void createActionToolToolbar( SubCoolBarManager cbmanager ) {
        ToolBarManager manager = new ToolBarManager(SWT.FLAT);

        manager.add(getBACKWARD_HISTORYAction());
        manager.add(getFORWARD_HISTORYAction());
        for( String id : categoryIds ) {
            ActionToolCategory category = findActionCategory(id);
            if (category != null)
                category.contribute(manager);
        }
        if (manager != null && manager.getItems().length > 0)
            cbmanager.add(manager);
    }

    /**
     * Adds both action tools and modal tools to the manager
     *
     * @deprecated
     *
     * @see contributeActionTools(IToolBarManager toolBarManager, IActionBars bars )
     * @see contributeModalTools(IToolBarManager toolBarManager, IActionBars bars )
     *
     * @param cbmanager
     * @param bars
     * @see org.locationtech.udig.project.ui.tool.ModalTool
     * @see org.locationtech.udig.project.ui.tool.ActionTool
     */
    public void contributeToCoolBar( SubCoolBarManager cbmanager, IActionBars bars ) {
        cbmanager.setVisible(true);
        createActionToolToolbar(cbmanager);
        createModalToolToolbar(cbmanager);
    }
   
   


    /* (non-Javadoc)
     * @see org.locationtech.udig.project.ui.tool.IToolManager#contributeActionTools(org.eclipse.jface.action.IToolBarManager, org.eclipse.ui.IActionBars)
     */
    public void contributeActionTools(IToolBarManager toolBarManager, IActionBars bars ) {
        toolBarManager.add(getBACKWARD_HISTORYAction());
        toolBarManager.add(getFORWARD_HISTORYAction());
        for( String id : categoryIds ) {
            ActionToolCategory category = findActionCategory(id);
            if (category != null)
                category.contribute(toolBarManager);
        }
    }

    /* (non-Javadoc)
     * @see org.locationtech.udig.project.ui.tool.IToolManager#contributeModalTools(org.eclipse.jface.action.IToolBarManager, org.eclipse.ui.IActionBars)
     */
    public void contributeModalTools(IToolBarManager toolBarManager, IActionBars bars ) {
        for( String id : categoryIds ) {
            ModalToolCategory modalCategory = findModalCategory(id);
            if (modalCategory != null) {
                modalCategory.contribute(toolBarManager);
            }
        }
    }

    SubActionBars2 getActionBars() {
        if (ApplicationGISInternal.getActiveMap() == ApplicationGIS.NO_MAP)
            return null;
        MapPart active = ApplicationGISInternal.getActiveEditor();

        if( active instanceof MapEditorPart){
            MapEditorPart editor = (MapEditorPart) active;
            return (SubActionBars2) editor.getMapEditorSite().getActionBars();
        }
        else if( active instanceof ViewPart){
            ViewPart view = (ViewPart) active;
            return (SubActionBars2) view.getViewSite().getActionBars();
        }
        return null;
    }
   
    private IAction actionCLOSE;
    private IAction actionSAVE;
    private IAction actionCLOSE_ALL;
    private PreferencesShortcutToolOptionsContributionItem preferencesShortcutToolOptions;

    /**
     * Contributes the common global actions.
     * @param part WorkbenchPart such as a view or editor
     * @param bars Actionbar used to register global actions
     */
    public void contributeGlobalActions( IWorkbenchPart part, IActionBars bars ) {
        IKeyBindingService service = part.getSite().getKeyBindingService();
        bars.setGlobalActionHandler(ActionFactory.BACK.getId(), getBACKWARD_HISTORYAction());
        bars.setGlobalActionHandler(ActionFactory.FORWARD.getId(), getFORWARD_HISTORYAction());
        bars.setGlobalActionHandler(ActionFactory.UNDO.getId(), getUNDOAction());
        bars.setGlobalActionHandler(ActionFactory.REDO.getId(), getREDOAction());
        bars.setGlobalActionHandler(ActionFactory.CUT.getId(), getCUTAction(part));
        bars.setGlobalActionHandler(ActionFactory.COPY.getId(), getCOPYAction(part));
        bars.setGlobalActionHandler(ActionFactory.PASTE.getId(), getPASTEAction(part));
        bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), getDELETEAction());
       
        ISelectionProvider selection = part.getSite().getSelectionProvider();
        if( selection != null ){
            bars.setGlobalActionHandler(ActionFactory.PROPERTIES.getId(), getPropertiesAction(part,selection));
        }
       
        if(actionCLOSE == null)
          actionCLOSE = ActionFactory.CLOSE.create(part.getSite().getWorkbenchWindow());
        service.registerAction(actionCLOSE);
        bars.setGlobalActionHandler(ActionFactory.CLOSE.getId(), actionCLOSE);

        if(actionSAVE == null)
          actionSAVE = ActionFactory.SAVE.create(part.getSite().getWorkbenchWindow());
        service.registerAction(actionSAVE);
        bars.setGlobalActionHandler(ActionFactory.SAVE.getId(), actionSAVE);

        if(actionCLOSE_ALL == null)
          actionCLOSE_ALL = ActionFactory.CLOSE_ALL.create(part.getSite().getWorkbenchWindow());
        bars.setGlobalActionHandler(ActionFactory.CLOSE_ALL.getId(), actionCLOSE_ALL);

    }

    void dispose() {
        for( ToolCategory category : modalCategories ) {
            category.dispose(ApplicationGISInternal.getActiveEditor().getMapEditorSite()
                    .getActionBars());
        }
        for( ToolCategory category : actionCategories ) {
            category.dispose(ApplicationGISInternal.getActiveEditor().getMapEditorSite()
                    .getActionBars());
        }
        for( ToolCategory category : menuCategories ) {
            category.dispose(ApplicationGISInternal.getActiveEditor().getMapEditorSite()
                    .getActionBars());
        }
        for( ToolProxy tool : backgroundTools ) {
            tool.dispose();
        }
       
    }

    Adapter getCommandListener( final MapPart editor ) {
        if (commandListener == null) {
            commandListener = new AdapterImpl(){
                /**
                 * @see org.eclipse.emf.common.notify.impl.AdapterImpl#notifyChanged(org.eclipse.emf.common.notify.Notification)
                 */
                public void notifyChanged( Notification msg ) {
                    // Map map = (Map) getTarget();
                    /*
                     * While this adapter is a singlton and added to all opened maps, each time
                     * target variable is reset.
                     */
                    Map map = null;
                    switch( msg.getFeatureID(msg.getNotifier().getClass()) ) {
                    case ProjectPackage.MAP__COMMAND_STACK:
                        map = (Map) msg.getNotifier();
                        setCommandActions(map, editor);
                        break;
                    case ProjectPackage.MAP__NAV_COMMAND_STACK:
                        map = (Map) msg.getNotifier();
                        setCommandActions(map, editor);
                        break;
                    }

                }
            };
        }
        return commandListener;
    }
    /**
     * Hook up the usual actions (UNDO,REDO,BACKWARDS_HISTORY,FORWARD_HISTORY) to the provided
     * editor.
     *
     * @param map
     * @param editor
     */
    void setCommandActions( Map map, MapPart editor ) {
        if (map.getCommandStack().canRedo())
            getREDOAction().setEnabled(true);
        else
            getREDOAction().setEnabled(false);

        if (map.getCommandStack().canUndo())
            getUNDOAction().setEnabled(true);
        else
            getUNDOAction().setEnabled(false);
       
        if (map.getNavCommandStack().hasBackHistory())
            getBACKWARD_HISTORYAction().setEnabled(true);
        else
            getBACKWARD_HISTORYAction().setEnabled(false);
       
        if (map.getNavCommandStack().hasForwardHistory())
            getFORWARD_HISTORYAction().setEnabled(true);
        else
            getFORWARD_HISTORYAction().setEnabled(false);
    }

    public IAction getTool( String toolID, String categoryID ) {
        return getToolAction(toolID, categoryID);
    }
   
    public IAction getToolAction( String toolID, String categoryID ) {
        final IAction tool = getToolInteral(toolID, categoryID);

        if( tool == null )
            return null;
       
        return new IAction(){
            IAction wrapped=tool;

            public void addPropertyChangeListener( IPropertyChangeListener listener ) {
                wrapped.addPropertyChangeListener(listener);
            }

            public int getAccelerator() {
                return wrapped.getAccelerator();
            }

            public String getActionDefinitionId() {
                return wrapped.getActionDefinitionId();
            }

            public String getDescription() {
                return wrapped.getDescription();
            }

            public ImageDescriptor getDisabledImageDescriptor() {
                return wrapped.getDisabledImageDescriptor();
            }

            public HelpListener getHelpListener() {
                return wrapped.getHelpListener();
            }

            public ImageDescriptor getHoverImageDescriptor() {
                return wrapped.getHoverImageDescriptor();
            }

            public String getId() {
                return wrapped.getId();
            }

            public ImageDescriptor getImageDescriptor() {
                return wrapped.getImageDescriptor();
            }

            public IMenuCreator getMenuCreator() {
                return wrapped.getMenuCreator();
            }

            public int getStyle() {
                return wrapped.getStyle();
            }

            public String getText() {
                return wrapped.getText();
            }

            public String getToolTipText() {
                return wrapped.getToolTipText();
            }

            public boolean isChecked() {
                return wrapped.isChecked();
            }

            public boolean isEnabled() {
                return wrapped.isEnabled();
            }

            public boolean isHandled() {
                return wrapped.isHandled();
            }

            public void removePropertyChangeListener( IPropertyChangeListener listener ) {
                wrapped.removePropertyChangeListener(listener);
            }

            public void runWithEvent( Event event ) {
                wrapped.runWithEvent(event);
            }

            public void run() {
                wrapped.run();
            }

            public void setAccelerator( int keycode ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setActionDefinitionId( String id ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setChecked( boolean checked ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setDescription( String text ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setDisabledImageDescriptor( ImageDescriptor newImage ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setEnabled( boolean enabled ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setHelpListener( HelpListener listener ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setHoverImageDescriptor( ImageDescriptor newImage ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setId( String id ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setImageDescriptor( ImageDescriptor newImage ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setMenuCreator( IMenuCreator creator ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setText( String text ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }

            public void setToolTipText( String text ) {
                throw new UnsupportedOperationException("This is an unmodifiable action"); //$NON-NLS-1$
            }
        };
    }

    /**
     * returns the actual tool action. 
     */
    private IAction getToolInteral( String toolID, String categoryID ) {
        ToolCategory category = findModalCategory(categoryID);
        if (category != null) {
            IAction tool = searchCategoryForTool(toolID, category);
            if( tool!=null )
                return tool;
        }
       
        category = findActionCategory(categoryID);
        if (category != null) {
            IAction tool = searchCategoryForTool(toolID, category);
            if( tool!=null )
                return tool;
        }
       
        category = findMenuCategory(categoryID);
        if (category != null) {
            IAction tool = searchCategoryForTool(toolID, category);
            if( tool!=null )
                return tool;
        }
        return null;
    }

    /**
     *
     * @param toolID
     * @param category
     * @return
     */
    private IAction searchCategoryForTool( String toolID, ToolCategory category ) {
        for( Iterator iter2 = category.iterator(); iter2.hasNext(); ) {
            ToolProxy tool = (ToolProxy) iter2.next();
            String id = tool.getId();
            if (id.equals(toolID))
                return tool.getAction();
        }
        return null;
    }

    /**
     * Returns the list of categories containing modal tools.
     *
     * @return the list of categories containing modal tools.
     */
    public List<ModalToolCategory> getModalToolCategories() {
        return modalCategories;
    }
   
//   
//    public Tool getActiveModalTool(){
//     
//    }

    /**
     * Returns the tool category that is currently active.
     *
     * @return the tool category that is currently active.
     */
    public ToolCategory getActiveCategory() {
        return findModalCategory(activeModalToolProxy.getCategoryId());
    }

    private static class CategorySorter implements Comparator<String>, Serializable {

        /** long serialVersionUID field */
        private static final long serialVersionUID = 1L;
        private final static java.util.Map<String, Integer> values = new HashMap<String, Integer>();
        static {
            values.put(ToolConstants.RENDER_CA, 5);
            values.put(ToolConstants.ZOOM_CA, 4);
            values.put(ToolConstants.PAN_CA, 3);
            values.put(ToolConstants.SELECTION_CA, 2);
            values.put(ToolConstants.INFO_CA, 1);
            values.put(ToolConstants.EDIT_CA, 0);
        }

        private static final int max = -1;
        private static final int min = 1;
        /**
         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
         */
        public int compare( String arg0, String arg1 ) {
            Integer value0 = values.get(arg0);
            Integer value1 = values.get(arg1);
            if (value0 == null && value1 == null)
                return 0;
            if (value1 == null)
                return max;
            if (value0 == null )
                return min;
            if (value0.equals(value1))
                return 0;

            return value0.intValue() > value1.intValue() ? max : min;
        }

    }

    /**
     * This method enables the context that allows tool keybinding to work.
     *
     * @param site
     */
    public void addToolScope( IWorkbenchPartSite site ) {
        String[] scopes = site.getKeyBindingService().getScopes();
        String[] newScopes = new String[scopes.length + 1];
        System.arraycopy(scopes, 0, newScopes, 1, scopes.length);
        newScopes[0] = "org.locationtech.udig.project.ui.tool"; //$NON-NLS-1$
        site.getKeyBindingService().setScopes(newScopes);
    }

    /*
     * This allows for customized operation menus that are based on the currently selected tool.
     */
    public MenuManager createOperationsContextMenu(ISelection selection) {
        try {
            MenuManager contextManager = getOperationMenuFactory().createMenuManager();

            List<OperationCategory> primaryCategories = activeModalToolProxy.getOperationCategories();
            Collection<OperationCategory> secondaryCategories = getOperationMenuFactory()
                    .getCategories().values();

            for( int i = 0; i < primaryCategories.size(); i++ ) {
                OperationCategory category = primaryCategories.get(i);

                // Limit the size of the context menu to 20, but don't ever display a portion of
                // a category, only always the entire thing.
                if (contextManager.getItems().length >= 15 && category.getActions().size() > 5) {
                    break;
                }

                MenuManager menu = category.createContextMenu();

                if ((i != 0 && menu.getItems().length != 0)
                        && (secondaryCategories.size() != 0 || getOperationMenuFactory()
                                .getActions().size() != 0)) {

                    contextManager.add(new Separator());
                }

                for( IContributionItem item : menu.getItems() ) {
                    contextManager.add(item);
                }
            }

            // if primaryCategories are present, create an "Other" submenu
            if (contextManager.getItems().length != 0) {
                RunOperationsAction action = new RunOperationsAction();
                action.setText(Messages.ToolCategory_other);

                contextManager.add(new Separator());
                contextManager.add(action);
            } else {
                Iterator iter = secondaryCategories.iterator();
                while( iter.hasNext() ) {
                    OperationCategory category = (OperationCategory) iter.next();

                    for( OpAction action : category.getActions() ) {
                        if( selection instanceof IStructuredSelection )
                            action.updateEnablement((IStructuredSelection) selection, true);
                        if (action.isEnabled())
                            contextManager.add(action);
                    }
                    if (iter.hasNext())
                        contextManager.add(new Separator());
                }

                if (getOperationMenuFactory().getActions().size() != 0) {
                    contextManager.add(new Separator());
                }
                for( OpAction action : getOperationMenuFactory().getActions() ) {
                    if( selection instanceof IStructuredSelection )
                        action.updateEnablement((IStructuredSelection) selection, true);
                    if (action.isEnabled()) {
                        contextManager.add(action);
                    }
                }
            }

            return contextManager;
        } catch (Throwable e) {
            ProjectUIPlugin.log("error creating the Operations ContextMenu", e);//$NON-NLS-1$
            return new MenuManager();
        }
    }

    private OperationMenuFactory getOperationMenuFactory() {
        return UiPlugin.getDefault().getOperationMenuFactory();
    }

    /**
     *  (non-Javadoc)
     * @see org.locationtech.udig.project.ui.tool.IToolManager#getActiveTool()
     */
    public Tool getActiveTool() {
      return activeModalToolProxy.getTool();
    }
   
    /**
     * Returns active tool proxy object.
     *
     * @return
     */
    public ToolProxy getActiveToolProxy(){
      return activeModalToolProxy;
    }
   
    /**
     * Sets the current active modal tool; please note that the provided
     * tool must be visible / enabled and available in the user interface
     * for this operation to work.
     *
     * @param activeModalToolProxy
     */
  public void setActiveModalToolProxy(ToolProxy modalToolProxy) {
    if( modalToolProxy == null ){
      // we will have to use the default then
      modalToolProxy = defaultModalToolProxy;
    }
    if(activeModalToolProxy != null && activeModalToolProxy.getId() == modalToolProxy.getId() ){
        return; // no change required
    }
    this.activeModalToolProxy = modalToolProxy;
   
    // connect the tools to the map area
    setActiveModalTool( modalToolProxy.getModalTool() );
    currentEditor.setSelectionProvider(modalToolProxy.getSelectionProvider());
   
    // add tool options to the status area
        initToolOptionsContribution(currentEditor.getStatusLineManager(), getActiveToolProxy());
  }
 
  /**
   * This method goes through the steps of deactivating the current tool option contribution and
   * activating the new tool option contribution.
   *
   * @param statusLine
   * @param modalToolProxy
   */
  private void initToolOptionsContribution(IStatusLineManager statusLine, ToolProxy modalToolProxy){
      if(statusLine != null ){
           
            if(preferencesShortcutToolOptions == null || preferencesShortcutToolOptions.isDisposed()){
                preferencesShortcutToolOptions = new PreferencesShortcutToolOptionsContributionItem();
                statusLine.appendToGroup(StatusLineManager.BEGIN_GROUP, preferencesShortcutToolOptions);
                preferencesShortcutToolOptions.setVisible(true);
            }
            preferencesShortcutToolOptions.update(modalToolProxy);
           
            //TODO, cache contributions instead of destroying them and recreating them
           
            //remove old tool contribution
            for(ContributionItem contribution : optionsContribution){
                statusLine.remove(contribution.getId());
            }
           
            //get the new contributions
            optionsContribution = modalToolProxy.getOptionsContribution();
           
            //set all new contributions
            for(ContributionItem contribution : optionsContribution){
                statusLine.appendToGroup(StatusLineManager.BEGIN_GROUP, contribution);
                contribution.setVisible(true);
            }      
           
            statusLine.update(true);
        }
  }
 
  /**
   * This method goes through the steps of deactivating the current tool
   * and activating the new one.
   *
   * @param modalTool
   */
    private void setActiveModalTool( ModalTool modalTool ) {
        if (modalTool == null) {
            // we cannot run with out a tool; so we will sue the default!
            modalTool = defaultModalToolProxy.getModalTool();
        }

        if (activeTool == modalTool) {
            return; // no change required!
        }

        if (activeTool != null) {
            // ask the current tool to stop listening etc...
            activeTool.setActive(false);
            activeTool = null;
        }
       
        if( modalTool.getContext() == null ){
            // the tool cannot be activated as it has not been connected to the map yet
            // Could we perform activeTool.setContext( toolContext )?
            return;
        }
       
        try {
            activeTool = modalTool;
           
            activeTool.setActive(true);// this should register itself with the tool manager

            // this was normally handled by the ToolProxy which we cannot get a hold of
            String currentCursorID = activeTool.getCursorID();
      Cursor toolCursor = findToolCursor(currentCursorID);
     
      activeTool.getContext().getViewportPane().setCursor(toolCursor);
        }
        catch (Throwable eek){
            System.err.println("Trouble activating "+modalTool+":"+eek);
            try {
                activeTool.setActive(false); // hope it does a better at cleaning up
            }
            catch (Throwable t){
                // no it did not do a better job cleaning up
            }
            activeTool = defaultModalToolProxy.getModalTool();
            activeTool.setActive(true);
        }
    }
//   
//    static class CopyAction extends Action {
//        final Set<Transfer> transfers = UDIGDragDropUtilities.getTransfers();
//        IWorkbenchPart part;
//        public IWorkbenchPart getPart() {
//            return part;
//        }
//        public void setPart( IWorkbenchPart part ) {
//            this.part = part;
//        }
//        @Override
//        public void runWithEvent( Event event ) {
//            Clipboard clipBoard = new Clipboard(event.display);
//            try {
//                IStructuredSelection selection = (IStructuredSelection) part.getSite()
//                        .getSelectionProvider().getSelection();
//                if (selection.isEmpty())
//                    return;
//                List<Object> data = new ArrayList<Object>();
//                List<Transfer> dataTransfers = new ArrayList<Transfer>();
//                Object[] testData = new Object[1];
//                Transfer[] testTransfer = new Transfer[1];
//                for( Iterator iter = selection.iterator(); iter.hasNext(); ) {
//                    Object element = iter.next();
//                    for( Transfer transfer : transfers ) {
//                        try {
//                            testData[0] = element;
//                            testTransfer[0] = transfer;
//                            clipBoard.setContents(testData, testTransfer);
//                        } catch (Exception e) {
//                            continue;
//                        }
//                        data.add(element);
//                        dataTransfers.add(transfer);
//                    }
//                }
//                clipBoard.setContents(data.toArray(), dataTransfers
//                        .toArray(new Transfer[dataTransfers.size()]));
//            } finally {
//                clipBoard.dispose();
//            }
//
//        }
//    }

    static class CopyAction extends Action {
        final Set<Transfer> transfers = UDIGDragDropUtilities.getTransfers();
        IWorkbenchPart part;
        public IWorkbenchPart getPart() {
            return part;
        }
        public void setPart( IWorkbenchPart part ) {
            this.part = part;
        }
        @Override
        public void runWithEvent( Event event ) {
            Clipboard clipBoard = new Clipboard(event.display);
            try {
                IMap map = ApplicationGIS.getActiveMap();
                if( map == ApplicationGIS.NO_MAP )
                    return;
                ILayer selectedLayer = map.getEditManager().getSelectedLayer();
                if( selectedLayer == null )
                    return;
               
                Filter layerFilter = selectedLayer.getFilter();
                if ( layerFilter==Filter.INCLUDE || layerFilter == org.geotools.filter.Filter.ALL ){
                    return;
                }
                AdaptingFilter filter = null;

                if( layerFilter instanceof AdaptingFilter){
                    AdaptingFilter adapting = (AdaptingFilter) layerFilter;
                    if( adapting.getAdapter(ILayer.class)!=null ){
                        filter = adapting;
                    }
                }
               
                if( filter == null ){
                    filter = AdaptingFilterFactory.createAdaptingFilter(layerFilter, selectedLayer);
                }
               
                clipBoard.setContents(new Object[]{filter},
                        new Transfer[]{UDigByteAndLocalTransfer.getInstance()});
            }finally {
                clipBoard.dispose();
            }

        }
    }
   
//    static class PasteAction extends Action {
//        IWorkbenchPart part;
//        public IWorkbenchPart getPart() {
//            return part;
//        }
//        public void setPart( IWorkbenchPart part ) {
//            this.part = part;
//        }
//        @Override
//        public void run() {
//            MapEditor activeEditor = ApplicationGISInternal.getActiveEditor();
//            Object targetObject = activeEditor;
//            IStructuredSelection selection = (IStructuredSelection) part.getSite()
//                    .getSelectionProvider().getSelection();
//            if (!selection.isEmpty()) {
//                targetObject = selection.iterator().next();
//
//            }
//            Clipboard clipboard = new Clipboard(activeEditor.getSite().getShell().getDisplay());
//            Set<Transfer> transfers = UDIGDNDProcessor.getTransfers();
//            Object contents = null;
//            for( Transfer transfer : transfers ) {
//                contents = clipboard.getContents(transfer);
//                if (contents != null)
//                    break;
//            }
//            if (contents != null) {
//                UDIGDropHandler dropHandler = activeEditor.getDropHandler();
//                dropHandler.setTarget(targetObject);
//                dropHandler.setViewerLocation(ViewerDropLocation.NONE);
//                dropHandler.performDrop(contents, null);
//            }
//        }
//    }

    static class PasteAction extends Action {
        IWorkbenchPart part;
        public IWorkbenchPart getPart() {
            return part;
        }
        public void setPart( IWorkbenchPart part ) {
            this.part = part;
        }
        @Override
        public void run() {
            Clipboard clipboard = new Clipboard(part.getSite().getShell().getDisplay());
            Set<Transfer> transfers = UDIGDNDProcessor.getTransfers();
            Object contents = null;
            for( Transfer transfer : transfers ) {
                contents = clipboard.getContents(transfer);
                if (contents != null)
                    break;
            }
           
            Object selection = firstSelectedElement();

            if (contents != null) {
                MapEditorPart activeEditor = ApplicationGISInternal.getActiveEditor();
                final Map finalMap;
                final UDIGDropHandler finalDropHandler;
                if( selection instanceof Map){
                    finalMap = (Map)selection;
                    finalDropHandler = new UDIGDropHandler();
                    activeEditor=null;
                } else if( activeEditor==null ){
                    CreateMapCommand command = new CreateMapCommand(null,Collections.<IGeoResource>emptyList(), null);
                    try {
                        command.run(new NullProgressMonitor());
                    } catch (Exception e) {
                        throw (RuntimeException) new RuntimeException( ).initCause( e );
                    }
                    finalMap = (Map) command.getCreatedMap();
                    finalDropHandler = new UDIGDropHandler();
                } else {
                    finalDropHandler = activeEditor.getDropHandler();
                    finalMap = activeEditor.getMap();
                }
               
                final MapEditorPart finalActiveEditor = activeEditor;
                ILayer selectedLayer = finalMap.getEditManager().getSelectedLayer();
                if( selectedLayer==null ){
                    finalDropHandler.setTarget(finalMap);
                }else{
                    finalDropHandler.setTarget(selectedLayer);
                }
                finalDropHandler.addListener(new IDropHandlerListener(){

                    public void done( IDropAction action, Throwable error ) {

                        if( finalActiveEditor==null && finalMap.getMapLayers().size()==0 ){
                            finalMap.getProjectInternal().getElementsInternal().remove(finalMap);
                        }
                       
                        finalDropHandler.removeListener(this);
                    }

                    public void noAction( Object data ) {
                        if( finalActiveEditor==null && finalMap.getMapLayers().size()==0 ){
                            finalMap.getProjectInternal().getElementsInternal().remove(finalMap);
                        }
                        finalDropHandler.removeListener(this);
                    }

                    public void starting( IDropAction action ) {
                    }
                   
                });
                finalDropHandler.setViewerLocation(ViewerDropLocation.ON);
                finalDropHandler.performDrop(contents, null);
            }
        }
        private Object firstSelectedElement() {
            ISelection selection = part.getSite().getSelectionProvider().getSelection();
            if( selection.isEmpty() || !(selection instanceof IStructuredSelection)){
                return null;
            }else{
                return ((IStructuredSelection)selection).getFirstElement();
            }
        }
    }

    public List<ActionToolCategory> getActiveToolCategories() {
        return actionCategories;
    }

}
TOP

Related Classes of org.locationtech.udig.project.ui.internal.tool.display.ToolManager$PasteAction

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.