001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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.infoviews;
011:
012: import org.eclipse.core.runtime.IAdaptable;
013:
014: import org.eclipse.swt.SWT;
015: import org.eclipse.swt.graphics.Color;
016: import org.eclipse.swt.graphics.RGB;
017: import org.eclipse.swt.widgets.Composite;
018: import org.eclipse.swt.widgets.Control;
019: import org.eclipse.swt.widgets.Display;
020: import org.eclipse.swt.widgets.Menu;
021: import org.eclipse.swt.widgets.Shell;
022:
023: import org.eclipse.jface.action.IAction;
024: import org.eclipse.jface.action.IMenuListener;
025: import org.eclipse.jface.action.IMenuManager;
026: import org.eclipse.jface.action.IToolBarManager;
027: import org.eclipse.jface.action.MenuManager;
028: import org.eclipse.jface.action.Separator;
029: import org.eclipse.jface.resource.ColorRegistry;
030: import org.eclipse.jface.resource.JFaceResources;
031: import org.eclipse.jface.util.IPropertyChangeListener;
032: import org.eclipse.jface.util.PropertyChangeEvent;
033: import org.eclipse.jface.viewers.ISelection;
034: import org.eclipse.jface.viewers.ISelectionProvider;
035: import org.eclipse.jface.viewers.IStructuredSelection;
036:
037: import org.eclipse.jface.text.ITextSelection;
038:
039: import org.eclipse.ui.IActionBars;
040: import org.eclipse.ui.IPartListener2;
041: import org.eclipse.ui.ISelectionListener;
042: import org.eclipse.ui.IWorkbenchPart;
043: import org.eclipse.ui.IWorkbenchPartReference;
044: import org.eclipse.ui.PlatformUI;
045: import org.eclipse.ui.actions.ActionFactory;
046: import org.eclipse.ui.part.ViewPart;
047: import org.eclipse.ui.texteditor.ITextEditorActionConstants;
048:
049: import org.eclipse.jdt.core.ICompilationUnit;
050: import org.eclipse.jdt.core.IJavaElement;
051: import org.eclipse.jdt.core.ILocalVariable;
052: import org.eclipse.jdt.core.IType;
053: import org.eclipse.jdt.core.JavaModelException;
054:
055: import org.eclipse.jdt.ui.IContextMenuConstants;
056: import org.eclipse.jdt.ui.JavaElementLabels;
057: import org.eclipse.jdt.ui.actions.SelectionDispatchAction;
058:
059: import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
060: import org.eclipse.jdt.internal.ui.util.SelectionUtil;
061:
062: /**
063: * Abstract class for views which show information for a given element.
064: *
065: * @since 3.0
066: */
067: public abstract class AbstractInfoView extends ViewPart implements
068: ISelectionListener, IMenuListener, IPropertyChangeListener {
069:
070: /** JavaElementLabels flags used for the title */
071: private final long TITLE_FLAGS = JavaElementLabels.ALL_FULLY_QUALIFIED
072: | JavaElementLabels.M_PRE_RETURNTYPE
073: | JavaElementLabels.M_PARAMETER_TYPES
074: | JavaElementLabels.M_PARAMETER_NAMES
075: | JavaElementLabels.M_EXCEPTIONS
076: | JavaElementLabels.F_PRE_TYPE_SIGNATURE
077: | JavaElementLabels.M_PRE_TYPE_PARAMETERS
078: | JavaElementLabels.T_TYPE_PARAMETERS
079: | JavaElementLabels.USE_RESOLVED;
080: private final long LOCAL_VARIABLE_TITLE_FLAGS = TITLE_FLAGS
081: & ~JavaElementLabels.F_FULLY_QUALIFIED
082: | JavaElementLabels.F_POST_QUALIFIED;
083:
084: /** JavaElementLabels flags used for the tool tip text */
085: private static final long TOOLTIP_LABEL_FLAGS = JavaElementLabels.DEFAULT_QUALIFIED
086: | JavaElementLabels.ROOT_POST_QUALIFIED
087: | JavaElementLabels.APPEND_ROOT_PATH
088: | JavaElementLabels.M_PARAMETER_TYPES
089: | JavaElementLabels.M_PARAMETER_NAMES
090: | JavaElementLabels.M_APP_RETURNTYPE
091: | JavaElementLabels.M_EXCEPTIONS
092: | JavaElementLabels.F_APP_TYPE_SIGNATURE
093: | JavaElementLabels.T_TYPE_PARAMETERS;
094:
095: /*
096: * @see IPartListener2
097: */
098: private IPartListener2 fPartListener = new IPartListener2() {
099: public void partVisible(IWorkbenchPartReference ref) {
100: if (ref.getId().equals(getSite().getId())) {
101: IWorkbenchPart activePart = ref.getPage()
102: .getActivePart();
103: if (activePart != null)
104: selectionChanged(activePart, ref.getPage()
105: .getSelection());
106: startListeningForSelectionChanges();
107: }
108: }
109:
110: public void partHidden(IWorkbenchPartReference ref) {
111: if (ref.getId().equals(getSite().getId()))
112: stopListeningForSelectionChanges();
113: }
114:
115: public void partInputChanged(IWorkbenchPartReference ref) {
116: if (!ref.getId().equals(getSite().getId()))
117: computeAndSetInput(ref.getPart(false));
118: }
119:
120: public void partActivated(IWorkbenchPartReference ref) {
121: }
122:
123: public void partBroughtToTop(IWorkbenchPartReference ref) {
124: }
125:
126: public void partClosed(IWorkbenchPartReference ref) {
127: }
128:
129: public void partDeactivated(IWorkbenchPartReference ref) {
130: }
131:
132: public void partOpened(IWorkbenchPartReference ref) {
133: }
134: };
135:
136: /** The current input. */
137: protected IJavaElement fCurrentViewInput;
138: /** The copy to clipboard action. */
139: private SelectionDispatchAction fCopyToClipboardAction;
140: /** The goto input action. */
141: private GotoInputAction fGotoInputAction;
142: /** Counts the number of background computation requests. */
143: private volatile int fComputeCount;
144:
145: /**
146: * Background color.
147: * @since 3.2
148: */
149: private Color fBackgroundColor;
150: private RGB fBackgroundColorRGB;
151:
152: /**
153: * Set the input of this view.
154: *
155: * @param input the input object
156: */
157: abstract protected void setInput(Object input);
158:
159: /**
160: * Computes the input for this view based on the given element.
161: *
162: * @param element the element from which to compute the input
163: * @return the input or <code>null</code> if the input was not computed successfully
164: */
165: abstract protected Object computeInput(Object element);
166:
167: /**
168: * Create the part control.
169: *
170: * @param parent the parent control
171: * @see IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
172: */
173: abstract protected void internalCreatePartControl(Composite parent);
174:
175: /**
176: * Set the view's foreground color.
177: *
178: * @param color the SWT color
179: */
180: abstract protected void setForeground(Color color);
181:
182: /**
183: * Set the view's background color.
184: *
185: * @param color the SWT color
186: */
187: abstract protected void setBackground(Color color);
188:
189: /**
190: * Returns the view's primary control.
191: *
192: * @return the primary control
193: */
194: abstract Control getControl();
195:
196: /**
197: * Returns the context ID for the Help system
198: *
199: * @return the string used as ID for the Help context
200: * @since 3.1
201: */
202: abstract protected String getHelpContextId();
203:
204: /*
205: * @see IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
206: */
207: public final void createPartControl(Composite parent) {
208: internalCreatePartControl(parent);
209: inititalizeColors();
210: getSite().getWorkbenchWindow().getPartService()
211: .addPartListener(fPartListener);
212: createContextMenu();
213: createActions();
214: fillActionBars(getViewSite().getActionBars());
215: PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
216: getHelpContextId());
217: }
218:
219: /**
220: * Creates the actions and action groups for this view.
221: */
222: protected void createActions() {
223: fGotoInputAction = new GotoInputAction(this );
224: fGotoInputAction.setEnabled(false);
225: fCopyToClipboardAction = new CopyToClipboardAction(
226: getViewSite());
227:
228: ISelectionProvider provider = getSelectionProvider();
229: if (provider != null)
230: provider
231: .addSelectionChangedListener(fCopyToClipboardAction);
232: }
233:
234: /**
235: * Creates the context menu for this view.
236: */
237: protected void createContextMenu() {
238: MenuManager menuManager = new MenuManager("#PopupMenu"); //$NON-NLS-1$
239: menuManager.setRemoveAllWhenShown(true);
240: menuManager.addMenuListener(this );
241: Menu contextMenu = menuManager.createContextMenu(getControl());
242: getControl().setMenu(contextMenu);
243: getSite().registerContextMenu(menuManager,
244: getSelectionProvider());
245: }
246:
247: /*
248: * @see IMenuListener#menuAboutToShow(org.eclipse.jface.action.IMenuManager)
249: */
250: public void menuAboutToShow(IMenuManager menu) {
251: menu.add(new Separator(IContextMenuConstants.GROUP_OPEN));
252: menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT));
253: menu.add(new Separator(IContextMenuConstants.GROUP_ADDITIONS));
254:
255: IAction action;
256:
257: action = getCopyToClipboardAction();
258: if (action != null)
259: menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT,
260: action);
261:
262: action = getSelectAllAction();
263: if (action != null)
264: menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT,
265: action);
266:
267: menu.appendToGroup(IContextMenuConstants.GROUP_OPEN,
268: fGotoInputAction);
269: }
270:
271: protected IAction getSelectAllAction() {
272: return null;
273: }
274:
275: protected IAction getCopyToClipboardAction() {
276: return fCopyToClipboardAction;
277: }
278:
279: /**
280: * Returns the input of this view.
281: *
282: * @return input the input object or <code>null</code> if not input is set
283: */
284: protected IJavaElement getInput() {
285: return fCurrentViewInput;
286: }
287:
288: // Helper method
289: ISelectionProvider getSelectionProvider() {
290: return getViewSite().getSelectionProvider();
291: }
292:
293: /**
294: * Fills the actions bars.
295: * <p>
296: * Subclasses may extend.
297: *
298: * @param actionBars the action bars
299: */
300: protected void fillActionBars(IActionBars actionBars) {
301: IToolBarManager toolBar = actionBars.getToolBarManager();
302: fillToolBar(toolBar);
303:
304: IAction action;
305:
306: action = getCopyToClipboardAction();
307: if (action != null)
308: actionBars.setGlobalActionHandler(ActionFactory.COPY
309: .getId(), action);
310:
311: action = getSelectAllAction();
312: if (action != null)
313: actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL
314: .getId(), action);
315: }
316:
317: /**
318: * Fills the tool bar.
319: * <p>
320: * Default is to do nothing.</p>
321: *
322: * @param tbm the tool bar manager
323: */
324: protected void fillToolBar(IToolBarManager tbm) {
325: tbm.add(fGotoInputAction);
326: }
327:
328: /*
329: * @see org.eclipse.jdt.internal.ui.infoviews.AbstractInfoView#inititalizeColors()
330: * @since 3.2
331: */
332: private void inititalizeColors() {
333: if (getSite().getShell().isDisposed())
334: return;
335:
336: Display display = getSite().getShell().getDisplay();
337: if (display == null || display.isDisposed())
338: return;
339:
340: setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
341:
342: ColorRegistry registry = JFaceResources.getColorRegistry();
343: registry.addListener(this );
344:
345: fBackgroundColorRGB = registry.getRGB(getBackgroundColorKey());
346: Color bgColor;
347: if (fBackgroundColorRGB == null) {
348: bgColor = display.getSystemColor(SWT.COLOR_INFO_BACKGROUND);
349: fBackgroundColorRGB = bgColor.getRGB();
350: } else {
351: bgColor = new Color(display, fBackgroundColorRGB);
352: fBackgroundColor = bgColor;
353: }
354:
355: setBackground(bgColor);
356: }
357:
358: /**
359: * The preference key for the background color.
360: *
361: * @return the background color key
362: * @since 3.2
363: */
364: abstract protected String getBackgroundColorKey();
365:
366: public void propertyChange(PropertyChangeEvent event) {
367: if (getBackgroundColorKey().equals(event.getProperty()))
368: inititalizeColors();
369: }
370:
371: /**
372: * Start to listen for selection changes.
373: */
374: protected void startListeningForSelectionChanges() {
375: getSite().getPage().addPostSelectionListener(this );
376: }
377:
378: /**
379: * Stop to listen for selection changes.
380: */
381: protected void stopListeningForSelectionChanges() {
382: getSite().getPage().removePostSelectionListener(this );
383: }
384:
385: /*
386: * @see ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
387: */
388: public void selectionChanged(IWorkbenchPart part,
389: ISelection selection) {
390: if (part.equals(this ))
391: return;
392:
393: computeAndSetInput(part);
394: }
395:
396: /**
397: * Tells whether the new input should be ignored
398: * if the current input is the same.
399: *
400: * @param je the new input
401: * @param selection the current selection from the part that provides the input
402: * @return <code>true</code> if the new input should be ignored
403: */
404: protected boolean isIgnoringNewInput(IJavaElement je,
405: IWorkbenchPart part, ISelection selection) {
406: return fCurrentViewInput != null
407: && fCurrentViewInput.equals(je) && je != null;
408: }
409:
410: /**
411: * Finds and returns the Java element selected in the given part.
412: *
413: * @param part the workbench part for which to find the selected Java element
414: * @param selection the selection
415: * @return the selected Java element
416: */
417: protected IJavaElement findSelectedJavaElement(IWorkbenchPart part,
418: ISelection selection) {
419: Object element;
420: try {
421: if (part instanceof JavaEditor
422: && selection instanceof ITextSelection) {
423: IJavaElement[] elements = TextSelectionConverter
424: .codeResolve((JavaEditor) part,
425: (ITextSelection) selection);
426: if (elements != null && elements.length > 0)
427: return elements[0];
428: else
429: return null;
430: } else if (selection instanceof IStructuredSelection) {
431: element = SelectionUtil.getSingleElement(selection);
432: } else {
433: return null;
434: }
435: } catch (JavaModelException e) {
436: return null;
437: }
438:
439: return findJavaElement(element);
440: }
441:
442: /**
443: * Tries to get a Java element out of the given element.
444: *
445: * @param element an object
446: * @return the Java element represented by the given element or <code>null</code>
447: */
448: private IJavaElement findJavaElement(Object element) {
449:
450: if (element == null)
451: return null;
452:
453: IJavaElement je = null;
454: if (element instanceof IAdaptable)
455: je = (IJavaElement) ((IAdaptable) element)
456: .getAdapter(IJavaElement.class);
457:
458: return je;
459: }
460:
461: /**
462: * Finds and returns the type for the given CU.
463: *
464: * @param cu the compilation unit
465: * @return the type with same name as the given CU or the first type in the CU
466: */
467: protected IType getTypeForCU(ICompilationUnit cu) {
468:
469: if (cu == null || !cu.exists())
470: return null;
471:
472: // Use primary type if possible
473: IType primaryType = cu.findPrimaryType();
474: if (primaryType != null)
475: return primaryType;
476:
477: // Use first top-level type
478: try {
479: IType[] types = cu.getTypes();
480: if (types.length > 0)
481: return types[0];
482: else
483: return null;
484: } catch (JavaModelException ex) {
485: return null;
486: }
487: }
488:
489: /*
490: * @see IWorkbenchPart#dispose()
491: */
492: final public void dispose() {
493: // cancel possible running computation
494: fComputeCount++;
495:
496: getSite().getWorkbenchWindow().getPartService()
497: .removePartListener(fPartListener);
498:
499: ISelectionProvider provider = getSelectionProvider();
500: if (provider != null)
501: provider
502: .removeSelectionChangedListener(fCopyToClipboardAction);
503:
504: JFaceResources.getColorRegistry().removeListener(this );
505: fBackgroundColorRGB = null;
506: if (fBackgroundColor != null) {
507: fBackgroundColor.dispose();
508: fBackgroundColor = null;
509: }
510:
511: internalDispose();
512:
513: }
514:
515: /*
516: * @see IWorkbenchPart#dispose()
517: */
518: abstract protected void internalDispose();
519:
520: /**
521: * Determines all necessary details and delegates the computation into
522: * a background thread.
523: *
524: * @param part the workbench part
525: */
526: private void computeAndSetInput(final IWorkbenchPart part) {
527:
528: final int currentCount = ++fComputeCount;
529:
530: ISelectionProvider provider = part.getSite()
531: .getSelectionProvider();
532: if (provider == null)
533: return;
534:
535: final ISelection selection = provider.getSelection();
536: if (selection == null || selection.isEmpty())
537: return;
538:
539: Thread thread = new Thread("Info view input computer") { //$NON-NLS-1$
540: public void run() {
541: if (currentCount != fComputeCount)
542: return;
543:
544: final IJavaElement je = findSelectedJavaElement(part,
545: selection);
546:
547: if (isIgnoringNewInput(je, part, selection))
548: return;
549:
550: // The actual computation
551: final Object input = computeInput(je);
552: if (input == null)
553: return;
554:
555: Shell shell = getSite().getShell();
556: if (shell.isDisposed())
557: return;
558:
559: Display display = shell.getDisplay();
560: if (display.isDisposed())
561: return;
562:
563: display.asyncExec(new Runnable() {
564: /*
565: * @see java.lang.Runnable#run()
566: */
567: public void run() {
568:
569: if (fComputeCount != currentCount
570: || getViewSite().getShell()
571: .isDisposed())
572: return;
573:
574: fCurrentViewInput = je;
575: doSetInput(input);
576: }
577: });
578: }
579: };
580:
581: thread.setDaemon(true);
582: thread.setPriority(Thread.MIN_PRIORITY);
583: thread.start();
584: }
585:
586: private void doSetInput(Object input) {
587: setInput(input);
588:
589: fGotoInputAction.setEnabled(true);
590:
591: IJavaElement inputElement = getInput();
592:
593: long flags;
594: if (inputElement instanceof ILocalVariable)
595: flags = LOCAL_VARIABLE_TITLE_FLAGS;
596: else
597: flags = TITLE_FLAGS;
598:
599: setContentDescription(JavaElementLabels.getElementLabel(
600: inputElement, flags));
601: setTitleToolTip(JavaElementLabels.getElementLabel(inputElement,
602: TOOLTIP_LABEL_FLAGS));
603: }
604: }
|