| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.ui.actions; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IStorage; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IModelStatusConstants; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.ISourceReference; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.core.ScriptModelUtil; |
| import org.eclipse.dltk.internal.ui.actions.ActionMessages; |
| import org.eclipse.dltk.internal.ui.actions.ActionUtil; |
| import org.eclipse.dltk.internal.ui.actions.OpenActionUtil; |
| import org.eclipse.dltk.internal.ui.actions.SelectionConverter; |
| import org.eclipse.dltk.internal.ui.editor.EditorUtility; |
| import org.eclipse.dltk.ui.DLTKUIPlugin; |
| import org.eclipse.dltk.ui.util.ExceptionHandler; |
| import org.eclipse.jface.dialogs.ErrorDialog; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.text.ITextSelection; |
| import org.eclipse.jface.util.OpenStrategy; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IWorkbenchSite; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.texteditor.IEditorStatusLine; |
| |
| /** |
| * This action opens a Script editor on a Script element or file. |
| * <p> |
| * The action is applicable to selections containing elements of type |
| * <code>ISourceModule</code>, <code>IMember</code> or <code>IFile</code>. |
| * |
| * <p> |
| * This class may be instantiated; it is not intended to be subclassed. |
| * </p> |
| */ |
| public class OpenAction extends SelectionDispatchAction { |
| |
| private IEditorPart fEditor; |
| |
| /** |
| * Creates a new <code>OpenAction</code>. The action requires that the |
| * selection provided by the site's selection provider is of type <code> |
| * org.eclipse.jface.viewers.IStructuredSelection</code> . |
| * |
| * @param site |
| * the site providing context information for this action |
| */ |
| public OpenAction(IWorkbenchSite site) { |
| super(site); |
| setText(ActionMessages.OpenAction_label); |
| setToolTipText(ActionMessages.OpenAction_tooltip); |
| setDescription(ActionMessages.OpenAction_description); |
| if (DLTKCore.DEBUG) { |
| System.err.println("Add help support here..."); //$NON-NLS-1$ |
| } |
| |
| // PlatformUI.getWorkbench().getHelpSystem().setHelp(this, |
| // IScriptHelpContextIds.OPEN_ACTION); |
| } |
| |
| /** |
| * Note: This constructor is for internal use only. Clients should not call |
| * this constructor. |
| * |
| * @param editor |
| * the Script editor |
| */ |
| public OpenAction(IEditorPart editor) { |
| this(editor.getEditorSite()); |
| fEditor = editor; |
| setText(ActionMessages.OpenAction_declaration_label); |
| setEnabled(EditorUtility.getEditorInputModelElement(fEditor, |
| false) != null); |
| } |
| |
| /* |
| * (non-Javadoc) Method declared on SelectionDispatchAction. |
| */ |
| @Override |
| public void selectionChanged(ITextSelection selection) { |
| } |
| |
| /* |
| * (non-Javadoc) Method declared on SelectionDispatchAction. |
| */ |
| @Override |
| public void selectionChanged(IStructuredSelection selection) { |
| setEnabled(checkEnabled(selection)); |
| } |
| |
| private boolean checkEnabled(IStructuredSelection selection) { |
| if (selection.isEmpty()) |
| return false; |
| for (Iterator<?> iter = selection.iterator(); iter.hasNext();) { |
| Object element = iter.next(); |
| if (!checkElement(element)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| protected boolean checkElement(Object element) { |
| if ((element instanceof ISourceReference) |
| || ((element instanceof IAdaptable) && (((IAdaptable) element) |
| .getAdapter(ISourceReference.class) != null))) |
| return true; |
| if ((element instanceof IFile) || ((element instanceof IAdaptable) |
| && (((IAdaptable) element).getAdapter(IFile.class) != null))) |
| return true; |
| if ((element instanceof IStorage) || ((element instanceof IAdaptable) |
| && (((IAdaptable) element).getAdapter(IStorage.class) != null))) |
| return true; |
| return false; |
| } |
| |
| /** |
| * This method allows alternative editor implementations to override the |
| * resolution logic. |
| * |
| * @return |
| * @throws InvocationTargetException |
| * @throws InterruptedException |
| * @since 3.0 |
| */ |
| protected Object[] resolveElements() |
| throws InvocationTargetException, InterruptedException { |
| return SelectionConverter.resolveForked(fEditor, false); |
| } |
| |
| /* |
| * (non-Javadoc) Method declared on SelectionDispatchAction. |
| */ |
| @Override |
| public void run(ITextSelection selection) { |
| if (!isProcessable()) |
| return; |
| final Object[] elements; |
| try { |
| elements = resolveElements(); |
| } catch (InvocationTargetException e) { |
| showError(e); |
| return; |
| } catch (InterruptedException e) { |
| return; |
| } |
| selectAndOpen(elements); |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| public void selectAndOpen(Object[] elements) { |
| elements = filterElements(elements); |
| if (elements == null || elements.length == 0) { |
| IEditorStatusLine statusLine = null; |
| if (fEditor != null) |
| statusLine = fEditor.getAdapter(IEditorStatusLine.class); |
| if (statusLine != null) |
| statusLine.setMessage(true, |
| ActionMessages.OpenAction_error_messageBadSelection, |
| null); |
| getShell().getDisplay().beep(); |
| return; |
| } |
| Object element = elements[0]; |
| if (elements.length > 1) { |
| element = OpenActionUtil.select(elements, getShell(), |
| getDialogTitle(), ActionMessages.OpenAction_select_element); |
| if (element == null) |
| return; |
| } |
| if (element instanceof IModelElement) { |
| int type = ((IModelElement) element).getElementType(); |
| if (type == IModelElement.SCRIPT_PROJECT |
| || type == IModelElement.PROJECT_FRAGMENT |
| || type == IModelElement.SCRIPT_FOLDER) |
| element = EditorUtility.getEditorInputModelElement(fEditor, |
| false); |
| } |
| run(new Object[] { element }); |
| } |
| |
| private Object[] filterElements(Object[] elements) { |
| if (elements == null) |
| return null; |
| |
| Map<Object, Object> uniqueElements = new HashMap<>(); |
| for (int i = 0; i < elements.length; i++) { |
| Object element = elements[i]; |
| if (element instanceof IModelElement) { |
| final IModelElement module = ((IModelElement) element) |
| .getAncestor(IModelElement.SOURCE_MODULE); |
| if (module != null) { |
| if (!uniqueElements.containsKey(module)) { |
| uniqueElements.put(module, element); |
| } |
| } |
| } else { |
| uniqueElements.put(element, element); |
| } |
| } |
| return uniqueElements.values().toArray(); |
| } |
| |
| private boolean isProcessable() { |
| if (fEditor != null) { |
| IModelElement je = EditorUtility.getEditorInputModelElement(fEditor, |
| false); |
| if (je instanceof ISourceModule |
| && !ScriptModelUtil.isPrimary((ISourceModule) je)) |
| return true; // can process non-primary working copies |
| } |
| return ActionUtil.isProcessable(getShell(), fEditor); |
| } |
| |
| /* |
| * (non-Javadoc) Method declared on SelectionDispatchAction. |
| */ |
| @Override |
| public void run(IStructuredSelection selection) { |
| if (!checkEnabled(selection)) |
| return; |
| run(selection.toArray()); |
| } |
| |
| /** |
| * Note: this method is for internal use only. Clients should not call this |
| * method. |
| * |
| * @param elements |
| * the elements to process |
| */ |
| public void run(Object[] elements) { |
| if (elements == null) |
| return; |
| for (int i = 0; i < elements.length; i++) { |
| Object element = elements[i]; |
| try { |
| element = getElementToOpen(element); |
| boolean activateOnOpen = fEditor != null ? true |
| : OpenStrategy.activateOnOpen(); |
| OpenActionUtil.open(element, activateOnOpen); |
| } catch (ModelException e) { |
| DLTKUIPlugin |
| .log(new Status(IStatus.ERROR, DLTKUIPlugin.PLUGIN_ID, |
| IModelStatusConstants.INTERNAL_ERROR, |
| ActionMessages.OpenAction_error_message, e)); |
| |
| ErrorDialog.openError(getShell(), getDialogTitle(), |
| ActionMessages.OpenAction_error_messageProblems, |
| e.getStatus()); |
| |
| } catch (PartInitException x) { |
| |
| String name = null; |
| |
| if (element instanceof IModelElement) { |
| name = ((IModelElement) element).getElementName(); |
| } else if (element instanceof IStorage) { |
| name = ((IStorage) element).getName(); |
| } else if (element instanceof IResource) { |
| name = ((IResource) element).getName(); |
| } |
| |
| if (name != null) { |
| MessageDialog.openError(getShell(), |
| ActionMessages.OpenAction_error_messageProblems, |
| NLS.bind( |
| ActionMessages.OpenAction_error_messageArgs, |
| name, x.getMessage())); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Note: this method is for internal use only. Clients should not call this |
| * method. |
| * |
| * @param object |
| * the element to open |
| * @return the real element to open |
| * @throws ModelException |
| * if an error occurs while accessing the Script model |
| */ |
| public Object getElementToOpen(Object object) throws ModelException { |
| Object target = null; |
| |
| if (((object instanceof ISourceReference) != true) |
| && ((object instanceof IModelElement) != true) |
| && ((object instanceof IFile) != true) |
| && (object instanceof IAdaptable)) { |
| IAdaptable adaptable = (IAdaptable) object; |
| |
| target = adaptable.getAdapter(ISourceReference.class); |
| if (target == null) { |
| target = adaptable.getAdapter(IModelElement.class); |
| if (target == null) { |
| target = adaptable.getAdapter(IFile.class); |
| if (target == null) { |
| target = adaptable.getAdapter(IStorage.class); |
| } |
| } |
| } |
| } |
| |
| if (target == null) { |
| target = object; |
| } |
| |
| return target; |
| } |
| |
| private String getDialogTitle() { |
| return ActionMessages.OpenAction_error_title; |
| } |
| |
| private void showError(InvocationTargetException e) { |
| ExceptionHandler.handle(e, getShell(), getDialogTitle(), |
| ActionMessages.OpenAction_error_message); |
| } |
| } |