001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.actions;
011:
012: import java.lang.reflect.InvocationTargetException;
013: import java.util.Iterator;
014:
015: import org.eclipse.core.runtime.IProgressMonitor;
016:
017: import org.eclipse.swt.widgets.Shell;
018:
019: import org.eclipse.jface.operation.IRunnableWithProgress;
020: import org.eclipse.jface.viewers.ISelection;
021: import org.eclipse.jface.viewers.ISelectionProvider;
022: import org.eclipse.jface.viewers.IStructuredSelection;
023: import org.eclipse.jface.viewers.StructuredSelection;
024: import org.eclipse.jface.window.Window;
025:
026: import org.eclipse.jface.text.ITextSelection;
027:
028: import org.eclipse.ui.IWorkbenchPart;
029: import org.eclipse.ui.PlatformUI;
030: import org.eclipse.ui.dialogs.ElementListSelectionDialog;
031:
032: import org.eclipse.jdt.core.IClassFile;
033: import org.eclipse.jdt.core.ICodeAssist;
034: import org.eclipse.jdt.core.ICompilationUnit;
035: import org.eclipse.jdt.core.IJavaElement;
036: import org.eclipse.jdt.core.ISourceRange;
037: import org.eclipse.jdt.core.ISourceReference;
038: import org.eclipse.jdt.core.IType;
039: import org.eclipse.jdt.core.ITypeRoot;
040: import org.eclipse.jdt.core.JavaModelException;
041:
042: import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
043:
044: import org.eclipse.jdt.ui.JavaElementLabelProvider;
045:
046: import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
047: import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
048:
049: public class SelectionConverter {
050:
051: private static final IJavaElement[] EMPTY_RESULT = new IJavaElement[0];
052:
053: private SelectionConverter() {
054: // no instance
055: }
056:
057: /**
058: * Converts the selection provided by the given part into a structured selection.
059: * The following conversion rules are used:
060: * <ul>
061: * <li><code>part instanceof JavaEditor</code>: returns a structured selection
062: * using code resolve to convert the editor's text selection.</li>
063: * <li><code>part instanceof IWorkbenchPart</code>: returns the part's selection
064: * if it is a structured selection.</li>
065: * <li><code>default</code>: returns an empty structured selection.</li>
066: * </ul>
067: */
068: public static IStructuredSelection getStructuredSelection(
069: IWorkbenchPart part) throws JavaModelException {
070: if (part instanceof JavaEditor)
071: return new StructuredSelection(
072: codeResolve((JavaEditor) part));
073: ISelectionProvider provider = part.getSite()
074: .getSelectionProvider();
075: if (provider != null) {
076: ISelection selection = provider.getSelection();
077: if (selection instanceof IStructuredSelection)
078: return (IStructuredSelection) selection;
079: }
080: return StructuredSelection.EMPTY;
081: }
082:
083: /**
084: * Converts the given structured selection into an array of Java elements.
085: * An empty array is returned if one of the elements stored in the structured
086: * selection is not of type <code>IJavaElement</code>
087: */
088: public static IJavaElement[] getElements(
089: IStructuredSelection selection) {
090: if (!selection.isEmpty()) {
091: IJavaElement[] result = new IJavaElement[selection.size()];
092: int i = 0;
093: for (Iterator iter = selection.iterator(); iter.hasNext(); i++) {
094: Object element = iter.next();
095: if (!(element instanceof IJavaElement))
096: return EMPTY_RESULT;
097: result[i] = (IJavaElement) element;
098: }
099: return result;
100: }
101: return EMPTY_RESULT;
102: }
103:
104: public static boolean canOperateOn(JavaEditor editor) {
105: if (editor == null)
106: return false;
107: return getInput(editor) != null;
108:
109: }
110:
111: public static IJavaElement[] codeResolveOrInputForked(
112: JavaEditor editor) throws InvocationTargetException,
113: InterruptedException {
114: IJavaElement input = getInput(editor);
115: ITextSelection selection = (ITextSelection) editor
116: .getSelectionProvider().getSelection();
117: IJavaElement[] result = performForkedCodeResolve(input,
118: selection);
119: if (result.length == 0) {
120: result = new IJavaElement[] { input };
121: }
122: return result;
123: }
124:
125: public static IJavaElement[] codeResolve(JavaEditor editor)
126: throws JavaModelException {
127: return codeResolve(editor, true);
128: }
129:
130: /**
131: * @param primaryOnly if <code>true</code> only primary working copies will be returned
132: * @since 3.2
133: */
134: public static IJavaElement[] codeResolve(JavaEditor editor,
135: boolean primaryOnly) throws JavaModelException {
136: return codeResolve(getInput(editor, primaryOnly),
137: (ITextSelection) editor.getSelectionProvider()
138: .getSelection());
139: }
140:
141: /**
142: * Perform a code resolve in a separate thread.
143: * @param primaryOnly if <code>true</code> only primary working copies will be returned
144: * @throws InterruptedException
145: * @throws InvocationTargetException
146: * @since 3.2
147: */
148: public static IJavaElement[] codeResolveForked(JavaEditor editor,
149: boolean primaryOnly) throws InvocationTargetException,
150: InterruptedException {
151: return performForkedCodeResolve(getInput(editor, primaryOnly),
152: (ITextSelection) editor.getSelectionProvider()
153: .getSelection());
154: }
155:
156: public static IJavaElement getElementAtOffset(JavaEditor editor)
157: throws JavaModelException {
158: return getElementAtOffset(editor, true);
159: }
160:
161: /**
162: * @param primaryOnly if <code>true</code> only primary working copies will be returned
163: * @since 3.2
164: */
165: private static IJavaElement getElementAtOffset(JavaEditor editor,
166: boolean primaryOnly) throws JavaModelException {
167: return getElementAtOffset(getInput(editor, primaryOnly),
168: (ITextSelection) editor.getSelectionProvider()
169: .getSelection());
170: }
171:
172: public static IType getTypeAtOffset(JavaEditor editor)
173: throws JavaModelException {
174: IJavaElement element = SelectionConverter
175: .getElementAtOffset(editor);
176: IType type = (IType) element.getAncestor(IJavaElement.TYPE);
177: if (type == null) {
178: ICompilationUnit unit = SelectionConverter
179: .getInputAsCompilationUnit(editor);
180: if (unit != null)
181: type = unit.findPrimaryType();
182: }
183: return type;
184: }
185:
186: public static IJavaElement getInput(JavaEditor editor) {
187: return getInput(editor, true);
188: }
189:
190: /**
191: * @param primaryOnly if <code>true</code> only primary working copies will be returned
192: * @since 3.2
193: */
194: private static IJavaElement getInput(JavaEditor editor,
195: boolean primaryOnly) {
196: if (editor == null)
197: return null;
198: return EditorUtility.getEditorInputJavaElement(editor,
199: primaryOnly);
200: }
201:
202: public static ITypeRoot getInputAsTypeRoot(JavaEditor editor) {
203: Object editorInput = SelectionConverter.getInput(editor);
204: if (editorInput instanceof ITypeRoot)
205: return (ITypeRoot) editorInput;
206: return null;
207: }
208:
209: public static ICompilationUnit getInputAsCompilationUnit(
210: JavaEditor editor) {
211: Object editorInput = SelectionConverter.getInput(editor);
212: if (editorInput instanceof ICompilationUnit)
213: return (ICompilationUnit) editorInput;
214: return null;
215: }
216:
217: public static IClassFile getInputAsClassFile(JavaEditor editor) {
218: Object editorInput = SelectionConverter.getInput(editor);
219: if (editorInput instanceof IClassFile)
220: return (IClassFile) editorInput;
221: return null;
222: }
223:
224: private static IJavaElement[] performForkedCodeResolve(
225: final IJavaElement input, final ITextSelection selection)
226: throws InvocationTargetException, InterruptedException {
227: final class CodeResolveRunnable implements
228: IRunnableWithProgress {
229: IJavaElement[] result;
230:
231: public void run(IProgressMonitor monitor)
232: throws InvocationTargetException {
233: try {
234: result = codeResolve(input, selection);
235: } catch (JavaModelException e) {
236: throw new InvocationTargetException(e);
237: }
238: }
239: }
240: CodeResolveRunnable runnable = new CodeResolveRunnable();
241: PlatformUI.getWorkbench().getProgressService().busyCursorWhile(
242: runnable);
243: return runnable.result;
244: }
245:
246: public static IJavaElement[] codeResolve(IJavaElement input,
247: ITextSelection selection) throws JavaModelException {
248: if (input instanceof ICodeAssist) {
249: if (input instanceof ICompilationUnit) {
250: JavaModelUtil.reconcile((ICompilationUnit) input);
251: }
252: IJavaElement[] elements = ((ICodeAssist) input).codeSelect(
253: selection.getOffset() + selection.getLength(), 0);
254: if (elements.length > 0) {
255: return elements;
256: }
257: }
258: return EMPTY_RESULT;
259: }
260:
261: public static IJavaElement getElementAtOffset(IJavaElement input,
262: ITextSelection selection) throws JavaModelException {
263: if (input instanceof ICompilationUnit) {
264: ICompilationUnit cunit = (ICompilationUnit) input;
265: JavaModelUtil.reconcile(cunit);
266: IJavaElement ref = cunit
267: .getElementAt(selection.getOffset());
268: if (ref == null)
269: return input;
270: else
271: return ref;
272: } else if (input instanceof IClassFile) {
273: IJavaElement ref = ((IClassFile) input)
274: .getElementAt(selection.getOffset());
275: if (ref == null)
276: return input;
277: else
278: return ref;
279: }
280: return null;
281: }
282:
283: // public static IJavaElement[] resolveSelectedElements(IJavaElement input, ITextSelection selection) throws JavaModelException {
284: // IJavaElement enclosing= resolveEnclosingElement(input, selection);
285: // if (enclosing == null)
286: // return EMPTY_RESULT;
287: // if (!(enclosing instanceof ISourceReference))
288: // return EMPTY_RESULT;
289: // ISourceRange sr= ((ISourceReference)enclosing).getSourceRange();
290: // if (selection.getOffset() == sr.getOffset() && selection.getLength() == sr.getLength())
291: // return new IJavaElement[] {enclosing};
292: // }
293:
294: public static IJavaElement resolveEnclosingElement(
295: JavaEditor editor, ITextSelection selection)
296: throws JavaModelException {
297: return resolveEnclosingElement(getInput(editor), selection);
298: }
299:
300: public static IJavaElement resolveEnclosingElement(
301: IJavaElement input, ITextSelection selection)
302: throws JavaModelException {
303: IJavaElement atOffset = null;
304: if (input instanceof ICompilationUnit) {
305: ICompilationUnit cunit = (ICompilationUnit) input;
306: JavaModelUtil.reconcile(cunit);
307: atOffset = cunit.getElementAt(selection.getOffset());
308: } else if (input instanceof IClassFile) {
309: IClassFile cfile = (IClassFile) input;
310: atOffset = cfile.getElementAt(selection.getOffset());
311: } else {
312: return null;
313: }
314: if (atOffset == null) {
315: return input;
316: } else {
317: int selectionEnd = selection.getOffset()
318: + selection.getLength();
319: IJavaElement result = atOffset;
320: if (atOffset instanceof ISourceReference) {
321: ISourceRange range = ((ISourceReference) atOffset)
322: .getSourceRange();
323: while (range.getOffset() + range.getLength() < selectionEnd) {
324: result = result.getParent();
325: if (!(result instanceof ISourceReference)) {
326: result = input;
327: break;
328: }
329: range = ((ISourceReference) result)
330: .getSourceRange();
331: }
332: }
333: return result;
334: }
335: }
336:
337: /**
338: * Shows a dialog for resolving an ambiguous java element.
339: * Utility method that can be called by subclasses.
340: */
341: public static IJavaElement selectJavaElement(
342: IJavaElement[] elements, Shell shell, String title,
343: String message) {
344: int nResults = elements.length;
345: if (nResults == 0)
346: return null;
347: if (nResults == 1)
348: return elements[0];
349:
350: int flags = JavaElementLabelProvider.SHOW_DEFAULT
351: | JavaElementLabelProvider.SHOW_QUALIFIED
352: | JavaElementLabelProvider.SHOW_ROOT;
353:
354: ElementListSelectionDialog dialog = new ElementListSelectionDialog(
355: shell, new JavaElementLabelProvider(flags));
356: dialog.setTitle(title);
357: dialog.setMessage(message);
358: dialog.setElements(elements);
359:
360: if (dialog.open() == Window.OK) {
361: return (IJavaElement) dialog.getFirstResult();
362: }
363: return null;
364: }
365: }
|