Java tutorial
/* * uDig - User Friendly Desktop Internet GIS client http://udig.refractions.net (C) 2004, * Refractions Research Inc. This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the Free Software * Foundation; version 2.1 of the License. This library is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ package net.refractions.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 net.refractions.udig.catalog.IGeoResource; import net.refractions.udig.core.filter.AdaptingFilter; import net.refractions.udig.core.filter.AdaptingFilterFactory; import net.refractions.udig.core.internal.ExtensionPointList; import net.refractions.udig.internal.ui.UDIGDNDProcessor; import net.refractions.udig.internal.ui.UDIGDropHandler; import net.refractions.udig.internal.ui.UDigByteAndLocalTransfer; import net.refractions.udig.internal.ui.UiPlugin; import net.refractions.udig.internal.ui.operations.OperationCategory; import net.refractions.udig.internal.ui.operations.OperationMenuFactory; import net.refractions.udig.internal.ui.operations.RunOperationsAction; import net.refractions.udig.project.EditManagerEvent; import net.refractions.udig.project.IEditManagerListener; import net.refractions.udig.project.ILayer; import net.refractions.udig.project.IMap; import net.refractions.udig.project.internal.Map; import net.refractions.udig.project.internal.ProjectPackage; import net.refractions.udig.project.internal.commands.CreateMapCommand; import net.refractions.udig.project.ui.ApplicationGIS; import net.refractions.udig.project.ui.internal.ApplicationGISInternal; import net.refractions.udig.project.ui.internal.MapEditor; import net.refractions.udig.project.ui.internal.MapEditorPart; import net.refractions.udig.project.ui.internal.MapEditorWithPalette; import net.refractions.udig.project.ui.internal.MapPart; import net.refractions.udig.project.ui.internal.Messages; import net.refractions.udig.project.ui.internal.ProjectUIPlugin; import net.refractions.udig.project.ui.internal.actions.Delete; import net.refractions.udig.project.ui.internal.tool.ToolContext; import net.refractions.udig.project.ui.internal.tool.impl.ToolContextImpl; import net.refractions.udig.project.ui.tool.IContextMenuContributionTool; import net.refractions.udig.project.ui.tool.IToolManager; import net.refractions.udig.project.ui.tool.ModalTool; import net.refractions.udig.project.ui.tool.Tool; import net.refractions.udig.project.ui.tool.ToolConstants; import net.refractions.udig.project.ui.tool.options.PreferencesShortcutToolOptionsContributionItem; import net.refractions.udig.project.ui.viewers.MapEditDomain; import net.refractions.udig.ui.IDropAction; import net.refractions.udig.ui.IDropHandlerListener; import net.refractions.udig.ui.UDIGDragDropUtilities; import net.refractions.udig.ui.ViewerDropLocation; import net.refractions.udig.ui.operations.LazyOpFilter; import net.refractions.udig.ui.operations.OpAction; import net.refractions.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 a small hack 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 hack 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) { for (ToolCategory 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 net.refractions.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("net.refractions.udig.tool.default.show.selection", "net.refractions.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 net.refractions.udig.project.ui.tool.ModalTool * @see net.refractions.udig.project.ui.tool.ActionTool */ public void contributeToCoolBar(SubCoolBarManager cbmanager, IActionBars bars) { cbmanager.setVisible(true); createActionToolToolbar(cbmanager); createModalToolToolbar(cbmanager); } /* (non-Javadoc) * @see net.refractions.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 net.refractions.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] = "net.refractions.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 net.refractions.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; } }