blob: 53d83753c02707ca3fcea3020669b12ebd6982ac [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.ui.infoviews;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.JFaceResources;
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.jface.text.ITextSelection;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.IContextMenuConstants;
import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.ui.actions.SelectionDispatchAction;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jdt.internal.ui.util.SelectionUtil;
/**
* Abstract class for views which show information for a given element.
*
* @since 3.0
*/
abstract class AbstractInfoView extends ViewPart implements ISelectionListener, IMenuListener, IPropertyChangeListener {
/** JavaElementLabels flags used for the title */
private final long TITLE_FLAGS= JavaElementLabels.ALL_FULLY_QUALIFIED
| JavaElementLabels.M_PRE_RETURNTYPE | JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_EXCEPTIONS
| JavaElementLabels.F_PRE_TYPE_SIGNATURE | JavaElementLabels.M_PRE_TYPE_PARAMETERS | JavaElementLabels.T_TYPE_PARAMETERS
| JavaElementLabels.USE_RESOLVED;
private final long LOCAL_VARIABLE_TITLE_FLAGS= TITLE_FLAGS & ~JavaElementLabels.F_FULLY_QUALIFIED | JavaElementLabels.F_POST_QUALIFIED;
/** JavaElementLabels flags used for the tool tip text */
private static final long TOOLTIP_LABEL_FLAGS= JavaElementLabels.DEFAULT_QUALIFIED | JavaElementLabels.ROOT_POST_QUALIFIED | JavaElementLabels.APPEND_ROOT_PATH |
JavaElementLabels.M_PARAMETER_TYPES | JavaElementLabels.M_PARAMETER_NAMES | JavaElementLabels.M_APP_RETURNTYPE | JavaElementLabels.M_EXCEPTIONS |
JavaElementLabels.F_APP_TYPE_SIGNATURE | JavaElementLabels.T_TYPE_PARAMETERS;
/*
* @see IPartListener2
*/
private IPartListener2 fPartListener= new IPartListener2() {
public void partVisible(IWorkbenchPartReference ref) {
if (ref.getId().equals(getSite().getId())) {
IWorkbenchPart activePart= ref.getPage().getActivePart();
if (activePart != null)
selectionChanged(activePart, ref.getPage().getSelection());
startListeningForSelectionChanges();
}
}
public void partHidden(IWorkbenchPartReference ref) {
if (ref.getId().equals(getSite().getId()))
stopListeningForSelectionChanges();
}
public void partInputChanged(IWorkbenchPartReference ref) {
if (!ref.getId().equals(getSite().getId()))
computeAndSetInput(ref.getPart(false));
}
public void partActivated(IWorkbenchPartReference ref) {
}
public void partBroughtToTop(IWorkbenchPartReference ref) {
}
public void partClosed(IWorkbenchPartReference ref) {
}
public void partDeactivated(IWorkbenchPartReference ref) {
}
public void partOpened(IWorkbenchPartReference ref) {
}
};
/** The current input. */
protected IJavaElement fCurrentViewInput;
/** The copy to clipboard action. */
private SelectionDispatchAction fCopyToClipboardAction;
/** The goto input action. */
private GotoInputAction fGotoInputAction;
/** Counts the number of background computation requests. */
private volatile int fComputeCount;
/**
* Background color.
* @since 3.2
*/
private Color fBackgroundColor;
private RGB fBackgroundColorRGB;
/**
* Set the input of this view.
*
* @param input the input object
*/
abstract protected void setInput(Object input);
/**
* Computes the input for this view based on the given element.
*
* @param element the element from which to compute the input
* @return the input or <code>null</code> if the input was not computed successfully
*/
abstract protected Object computeInput(Object element);
/**
* Create the part control.
*
* @param parent the parent control
* @see IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
abstract protected void internalCreatePartControl(Composite parent);
/**
* Set the view's foreground color.
*
* @param color the SWT color
*/
abstract protected void setForeground(Color color);
/**
* Set the view's background color.
*
* @param color the SWT color
*/
abstract protected void setBackground(Color color);
/**
* Returns the view's primary control.
*
* @return the primary control
*/
abstract Control getControl();
/**
* Returns the context ID for the Help system
*
* @return the string used as ID for the Help context
* @since 3.1
*/
abstract protected String getHelpContextId();
/*
* @see IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
public final void createPartControl(Composite parent) {
internalCreatePartControl(parent);
inititalizeColors();
getSite().getWorkbenchWindow().getPartService().addPartListener(fPartListener);
createContextMenu();
createActions();
fillActionBars(getViewSite().getActionBars());
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), getHelpContextId());
}
/**
* Creates the actions and action groups for this view.
*/
protected void createActions() {
fGotoInputAction= new GotoInputAction(this);
fGotoInputAction.setEnabled(false);
fCopyToClipboardAction= new CopyToClipboardAction(getViewSite());
ISelectionProvider provider= getSelectionProvider();
if (provider != null)
provider.addSelectionChangedListener(fCopyToClipboardAction);
}
/**
* Creates the context menu for this view.
*/
protected void createContextMenu() {
MenuManager menuManager= new MenuManager("#PopupMenu"); //$NON-NLS-1$
menuManager.setRemoveAllWhenShown(true);
menuManager.addMenuListener(this);
Menu contextMenu= menuManager.createContextMenu(getControl());
getControl().setMenu(contextMenu);
getSite().registerContextMenu(menuManager, getSelectionProvider());
}
/*
* @see IMenuListener#menuAboutToShow(org.eclipse.jface.action.IMenuManager)
*/
public void menuAboutToShow(IMenuManager menu) {
menu.add(new Separator(IContextMenuConstants.GROUP_OPEN));
menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT));
menu.add(new Separator(IContextMenuConstants.GROUP_ADDITIONS));
IAction action;
action= getCopyToClipboardAction();
if (action != null)
menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, action);
action= getSelectAllAction();
if (action != null)
menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, action);
menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, fGotoInputAction);
}
protected IAction getSelectAllAction() {
return null;
}
protected IAction getCopyToClipboardAction() {
return fCopyToClipboardAction;
}
/**
* Returns the input of this view.
*
* @return input the input object or <code>null</code> if not input is set
*/
protected IJavaElement getInput() {
return fCurrentViewInput;
}
// Helper method
ISelectionProvider getSelectionProvider() {
return getViewSite().getSelectionProvider();
}
/**
* Fills the actions bars.
* <p>
* Subclasses may extend.
*
* @param actionBars the action bars
*/
protected void fillActionBars(IActionBars actionBars) {
IToolBarManager toolBar= actionBars.getToolBarManager();
fillToolBar(toolBar);
IAction action;
action= getCopyToClipboardAction();
if (action != null)
actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), action);
action= getSelectAllAction();
if (action != null)
actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), action);
}
/**
* Fills the tool bar.
* <p>
* Default is to do nothing.</p>
*
* @param tbm the tool bar manager
*/
protected void fillToolBar(IToolBarManager tbm) {
tbm.add(fGotoInputAction);
}
/*
* @see org.eclipse.jdt.internal.ui.infoviews.AbstractInfoView#inititalizeColors()
* @since 3.2
*/
private void inititalizeColors() {
if (getSite().getShell().isDisposed())
return;
Display display= getSite().getShell().getDisplay();
if (display == null || display.isDisposed())
return;
setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
ColorRegistry registry= JFaceResources.getColorRegistry();
registry.addListener(this);
fBackgroundColorRGB= registry.getRGB(getBackgroundColorKey());
Color bgColor;
if (fBackgroundColorRGB == null) {
bgColor= display.getSystemColor(SWT.COLOR_INFO_BACKGROUND);
fBackgroundColorRGB= bgColor.getRGB();
} else {
bgColor= new Color(display, fBackgroundColorRGB);
fBackgroundColor= bgColor;
}
setBackground(bgColor);
}
/**
* The preference key for the background color.
*
* @return the background color key
* @since 3.2
*/
abstract protected String getBackgroundColorKey();
public void propertyChange(PropertyChangeEvent event) {
if (getBackgroundColorKey().equals(event.getProperty()))
inititalizeColors();
}
/**
* Start to listen for selection changes.
*/
protected void startListeningForSelectionChanges() {
getSite().getPage().addPostSelectionListener(this);
}
/**
* Stop to listen for selection changes.
*/
protected void stopListeningForSelectionChanges() {
getSite().getPage().removePostSelectionListener(this);
}
/*
* @see ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
*/
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (part.equals(this))
return;
computeAndSetInput(part);
}
/**
* Tells whether the new input should be ignored
* if the current input is the same.
*
* @param je the new input
* @param selection the current selection from the part that provides the input
* @return <code>true</code> if the new input should be ignored
*/
protected boolean isIgnoringNewInput(IJavaElement je, IWorkbenchPart part, ISelection selection) {
return fCurrentViewInput != null && fCurrentViewInput.equals(je) && je != null;
}
/**
* Finds and returns the Java element selected in the given part.
*
* @param part the workbench part for which to find the selected Java element
* @param selection the selection
* @return the selected Java element
*/
protected IJavaElement findSelectedJavaElement(IWorkbenchPart part, ISelection selection) {
Object element;
try {
if (part instanceof JavaEditor && selection instanceof ITextSelection) {
IJavaElement[] elements= TextSelectionConverter.codeResolve((JavaEditor)part, (ITextSelection)selection);
if (elements != null && elements.length > 0)
return elements[0];
else
return null;
} else if (selection instanceof IStructuredSelection) {
element= SelectionUtil.getSingleElement(selection);
} else {
return null;
}
} catch (JavaModelException e) {
return null;
}
return findJavaElement(element);
}
/**
* Tries to get a Java element out of the given element.
*
* @param element an object
* @return the Java element represented by the given element or <code>null</code>
*/
private IJavaElement findJavaElement(Object element) {
if (element == null)
return null;
IJavaElement je= null;
if (element instanceof IAdaptable)
je= (IJavaElement)((IAdaptable)element).getAdapter(IJavaElement.class);
return je;
}
/**
* Finds and returns the type for the given CU.
*
* @param cu the compilation unit
* @return the type with same name as the given CU or the first type in the CU
*/
protected IType getTypeForCU(ICompilationUnit cu) {
if (cu == null || !cu.exists())
return null;
// Use primary type if possible
IType primaryType= cu.findPrimaryType();
if (primaryType != null)
return primaryType;
// Use first top-level type
try {
IType[] types= cu.getTypes();
if (types.length > 0)
return types[0];
else
return null;
} catch (JavaModelException ex) {
return null;
}
}
/*
* @see IWorkbenchPart#dispose()
*/
final public void dispose() {
// cancel possible running computation
fComputeCount++;
getSite().getWorkbenchWindow().getPartService().removePartListener(fPartListener);
ISelectionProvider provider= getSelectionProvider();
if (provider != null)
provider.removeSelectionChangedListener(fCopyToClipboardAction);
JFaceResources.getColorRegistry().removeListener(this);
fBackgroundColorRGB= null;
if (fBackgroundColor != null) {
fBackgroundColor.dispose();
fBackgroundColor= null;
}
internalDispose();
}
/*
* @see IWorkbenchPart#dispose()
*/
abstract protected void internalDispose();
/**
* Determines all necessary details and delegates the computation into
* a background thread.
*
* @param part the workbench part
*/
private void computeAndSetInput(final IWorkbenchPart part) {
final int currentCount= ++fComputeCount;
ISelectionProvider provider= part.getSite().getSelectionProvider();
if (provider == null)
return;
final ISelection selection= provider.getSelection();
if (selection == null || selection.isEmpty())
return;
Thread thread= new Thread("Info view input computer") { //$NON-NLS-1$
public void run() {
if (currentCount != fComputeCount)
return;
final IJavaElement je= findSelectedJavaElement(part, selection);
if (isIgnoringNewInput(je, part, selection))
return;
// The actual computation
final Object input= computeInput(je);
if (input == null)
return;
Shell shell= getSite().getShell();
if (shell.isDisposed())
return;
Display display= shell.getDisplay();
if (display.isDisposed())
return;
display.asyncExec(new Runnable() {
/*
* @see java.lang.Runnable#run()
*/
public void run() {
if (fComputeCount != currentCount || getViewSite().getShell().isDisposed())
return;
fCurrentViewInput= je;
doSetInput(input);
}
});
}
};
thread.setDaemon(true);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
private void doSetInput(Object input) {
setInput(input);
fGotoInputAction.setEnabled(true);
long flags;
if (getInput() instanceof ILocalVariable)
flags= LOCAL_VARIABLE_TITLE_FLAGS;
else
flags= TITLE_FLAGS;
setContentDescription(JavaElementLabels.getElementLabel(getInput(), flags));
setTitleToolTip(JavaElementLabels.getElementLabel(getInput(), TOOLTIP_LABEL_FLAGS));
}
}