blob: 8418c8ffb48b0053b457e82405095bac400c35fa [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 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.typehierarchy;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.eclipse.help.IContextProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.IMenuListener;
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.ToolBarManager;
import org.eclipse.jface.commands.ActionHandler;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.util.DelegatingDropAdapter;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.IBasicPropertyConstants;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.OpenAndLinkWithEditorHelper;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.ActionGroup;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.part.IShowInSource;
import org.eclipse.ui.part.IShowInTargetList;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.part.PluginTransfer;
import org.eclipse.ui.part.ResourceTransfer;
import org.eclipse.ui.part.ShowInContext;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.ui.IContextMenuConstants;
import org.eclipse.jdt.ui.ITypeHierarchyViewPart;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.actions.CCPActionGroup;
import org.eclipse.jdt.ui.actions.GenerateActionGroup;
import org.eclipse.jdt.ui.actions.JavaSearchActionGroup;
import org.eclipse.jdt.ui.actions.OpenAction;
import org.eclipse.jdt.ui.actions.OpenEditorActionGroup;
import org.eclipse.jdt.ui.actions.OpenViewActionGroup;
import org.eclipse.jdt.ui.actions.RefactorActionGroup;
import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.actions.CompositeActionGroup;
import org.eclipse.jdt.internal.ui.actions.NewWizardsActionGroup;
import org.eclipse.jdt.internal.ui.actions.SelectAllAction;
import org.eclipse.jdt.internal.ui.dnd.EditorInputTransferDragAdapter;
import org.eclipse.jdt.internal.ui.dnd.JdtViewerDragAdapter;
import org.eclipse.jdt.internal.ui.dnd.ResourceTransferDragAdapter;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.packageview.FileTransferDragAdapter;
import org.eclipse.jdt.internal.ui.packageview.PluginTransferDropAdapter;
import org.eclipse.jdt.internal.ui.packageview.SelectionTransferDragAdapter;
import org.eclipse.jdt.internal.ui.preferences.MembersOrderPreferenceCache;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import org.eclipse.jdt.internal.ui.util.JavaUIHelp;
import org.eclipse.jdt.internal.ui.util.SelectionUtil;
import org.eclipse.jdt.internal.ui.viewsupport.IViewPartInputProvider;
import org.eclipse.jdt.internal.ui.viewsupport.JavaUILabelProvider;
import org.eclipse.jdt.internal.ui.viewsupport.SelectionProviderMediator;
import org.eclipse.jdt.internal.ui.viewsupport.StatusBarUpdater;
import org.eclipse.jdt.internal.ui.workingsets.WorkingSetFilterActionGroup;
/**
* View showing the super types/sub types of its input.
*/
public class TypeHierarchyViewPart extends ViewPart implements ITypeHierarchyViewPart, IViewPartInputProvider {
private static final String DIALOGSTORE_HIERARCHYVIEW= "TypeHierarchyViewPart.hierarchyview"; //$NON-NLS-1$
private static final String DIALOGSTORE_VIEWLAYOUT= "TypeHierarchyViewPart.orientation"; //$NON-NLS-1$
private static final String DIALOGSTORE_QUALIFIED_NAMES= "TypeHierarchyViewPart.qualifiednames"; //$NON-NLS-1$
private static final String DIALOGSTORE_LINKEDITORS= "TypeHierarchyViewPart.linkeditors"; //$NON-NLS-1$
private static final String TAG_INPUT= "input"; //$NON-NLS-1$
private static final String TAG_VIEW= "view"; //$NON-NLS-1$
private static final String TAG_LAYOUT= "orientation"; //$NON-NLS-1$
private static final String TAG_RATIO= "ratio"; //$NON-NLS-1$
private static final String TAG_SELECTION= "selection"; //$NON-NLS-1$
private static final String TAG_VERTICAL_SCROLL= "vertical_scroll"; //$NON-NLS-1$
private static final String TAG_QUALIFIED_NAMES= "qualified_names"; //$NON-NLS-1$
private static final String TAG_EDITOR_LINKING= "link_editors"; //$NON-NLS-1$
private static final String GROUP_FOCUS= "group.focus"; //$NON-NLS-1$
// the selected type in the hierarchy view
private IType fSelectedType;
// input elements or null
private IJavaElement[] fInputElements;
// history of input elements. No duplicates
private ArrayList fInputHistory;
private IMemento fMemento;
private IDialogSettings fDialogSettings;
private TypeHierarchyLifeCycle fHierarchyLifeCycle;
private ITypeHierarchyLifeCycleListener fTypeHierarchyLifeCycleListener;
private IPropertyChangeListener fPropertyChangeListener;
private SelectionProviderMediator fSelectionProviderMediator;
private ISelectionChangedListener fSelectionChangedListener;
private IPartListener2 fPartListener;
private int fCurrentLayout;
private boolean fInComputeLayout;
private boolean fLinkingEnabled;
private boolean fShowQualifiedTypeNames;
private boolean fSelectInEditor;
private boolean fIsVisible;
private boolean fNeedRefresh;
private boolean fIsEnableMemberFilter;
private boolean fIsRefreshRunnablePosted;
private int fCurrentViewerIndex;
private TypeHierarchyViewer[] fAllViewers;
private MethodsViewer fMethodsViewer;
private SashForm fTypeMethodsSplitter;
private PageBook fViewerbook;
private PageBook fPagebook;
private Label fNoHierarchyShownLabel;
private Label fEmptyTypesViewer;
private ViewForm fTypeViewerViewForm;
private ViewForm fMethodViewerViewForm;
private CLabel fMethodViewerPaneLabel;
private JavaUILabelProvider fPaneLabelProvider;
private Composite fParent;
private ToggleViewAction[] fViewActions;
private ToggleLinkingAction fToggleLinkingAction;
private HistoryDropDownAction fHistoryDropDownAction;
private ToggleOrientationAction[] fToggleOrientationActions;
private EnableMemberFilterAction fEnableMemberFilterAction;
private ShowQualifiedTypeNamesAction fShowQualifiedTypeNamesAction;
private FocusOnTypeAction fFocusOnTypeAction;
private FocusOnSelectionAction fFocusOnSelectionAction;
private CompositeActionGroup fActionGroups;
private SelectAllAction fSelectAllAction;
private WorkingSetFilterActionGroup fWorkingSetActionGroup;
private Job fRestoreStateJob;
/**
* Helper to open and activate editors.
*
* @since 3.5
*/
private OpenAndLinkWithEditorHelper fTypeOpenAndLinkWithEditorHelper;
private OpenAction fOpenAction;
/**
* Indicates whether the restore job was canceled explicitly.
*
* @since 3.6
*/
private boolean fRestoreJobCanceledExplicitly= true;
/**
* Indicates whether empty viewers should keep showing. If false, replace them with
* fEmptyTypesViewer.
*
* @since 3.6
*/
private boolean fKeepShowingEmptyViewers= true;
public TypeHierarchyViewPart() {
fSelectedType= null;
fInputElements= null;
fIsVisible= false;
fIsRefreshRunnablePosted= false;
fSelectInEditor= true;
fRestoreStateJob= null;
fHierarchyLifeCycle= new TypeHierarchyLifeCycle(this);
fTypeHierarchyLifeCycleListener= new ITypeHierarchyLifeCycleListener() {
public void typeHierarchyChanged(TypeHierarchyLifeCycle typeHierarchy, IType[] changedTypes) {
doTypeHierarchyChanged(typeHierarchy, changedTypes);
}
};
fHierarchyLifeCycle.addChangedListener(fTypeHierarchyLifeCycleListener);
fPropertyChangeListener= new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
doPropertyChange(event);
}
};
PreferenceConstants.getPreferenceStore().addPropertyChangeListener(fPropertyChangeListener);
fIsEnableMemberFilter= false;
fInputHistory= new ArrayList();
fAllViewers= null;
fViewActions= new ToggleViewAction[] {
new ToggleViewAction(this, HIERARCHY_MODE_CLASSIC),
new ToggleViewAction(this, HIERARCHY_MODE_SUPERTYPES),
new ToggleViewAction(this, HIERARCHY_MODE_SUBTYPES)
};
fDialogSettings= JavaPlugin.getDefault().getDialogSettings();
fHistoryDropDownAction= new HistoryDropDownAction(this);
fHistoryDropDownAction.setEnabled(false);
fToggleOrientationActions= new ToggleOrientationAction[] {
new ToggleOrientationAction(this, VIEW_LAYOUT_VERTICAL),
new ToggleOrientationAction(this, VIEW_LAYOUT_HORIZONTAL),
new ToggleOrientationAction(this, VIEW_LAYOUT_AUTOMATIC),
new ToggleOrientationAction(this, VIEW_LAYOUT_SINGLE)
};
fEnableMemberFilterAction= new EnableMemberFilterAction(this, false);
fShowQualifiedTypeNamesAction= new ShowQualifiedTypeNamesAction(this, false);
fFocusOnTypeAction= new FocusOnTypeAction(this);
fToggleLinkingAction= new ToggleLinkingAction(this);
fToggleLinkingAction.setActionDefinitionId(IWorkbenchCommandConstants.NAVIGATE_TOGGLE_LINK_WITH_EDITOR);
fPaneLabelProvider= new JavaUILabelProvider();
fFocusOnSelectionAction= new FocusOnSelectionAction(this);
fPartListener= new IPartListener2() {
public void partVisible(IWorkbenchPartReference ref) {
IWorkbenchPart part= ref.getPart(false);
if (part == TypeHierarchyViewPart.this) {
visibilityChanged(true);
}
}
public void partHidden(IWorkbenchPartReference ref) {
IWorkbenchPart part= ref.getPart(false);
if (part == TypeHierarchyViewPart.this) {
visibilityChanged(false);
}
}
public void partActivated(IWorkbenchPartReference ref) {
IWorkbenchPart part= ref.getPart(false);
if (part instanceof IEditorPart)
editorActivated((IEditorPart) part);
}
public void partInputChanged(IWorkbenchPartReference ref) {
IWorkbenchPart part= ref.getPart(false);
if (part instanceof IEditorPart)
editorActivated((IEditorPart) part);
}
public void partBroughtToTop(IWorkbenchPartReference ref) {}
public void partClosed(IWorkbenchPartReference ref) {}
public void partDeactivated(IWorkbenchPartReference ref) {}
public void partOpened(IWorkbenchPartReference ref) {}
};
fSelectionChangedListener= new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
doSelectionChanged(event);
}
};
}
protected void doPropertyChange(PropertyChangeEvent event) {
String property= event.getProperty();
if (fMethodsViewer != null) {
if (MembersOrderPreferenceCache.isMemberOrderProperty(event.getProperty())) {
fMethodsViewer.refresh();
}
}
if (IWorkingSetManager.CHANGE_WORKING_SET_CONTENT_CHANGE.equals(property)) {
updateHierarchyViewer(true);
updateToolTipAndDescription();
}
}
/**
* Adds the entry if new. Inserted at the beginning of the history entries list.
* @param entry The new entry
*/
private void addHistoryEntry(IJavaElement[] entry) {
for (Iterator iter= fInputHistory.iterator(); iter.hasNext();) {
IJavaElement[] elem= (IJavaElement[])iter.next();
if (Arrays.equals(elem, entry)) {
fInputHistory.remove(elem);
break;
}
}
fInputHistory.add(0, entry);
fHistoryDropDownAction.setEnabled(true);
}
private void updateHistoryEntries() {
for (int i= fInputHistory.size() - 1; i >= 0; i--) {
IJavaElement[] entries= (IJavaElement[])fInputHistory.get(i);
for (int j= 0; j < entries.length; j++) {
IJavaElement elem= entries[j];
if (elem != null && !elem.exists()) {
fInputHistory.remove(i);
break;
}
}
}
fHistoryDropDownAction.setEnabled(!fInputHistory.isEmpty());
}
/**
* Goes to the selected entry, without updating the order of history entries.
*
* @param entry the entry to open
*/
public void gotoHistoryEntry(IJavaElement[] entry) {
if (fInputHistory.contains(entry)) {
updateInput(entry);
}
}
/**
* Gets all history entries.
* @return All history entries
*/
public List getHistoryEntries() {
if (fInputHistory.size() > 0) {
updateHistoryEntries();
}
return fInputHistory;
}
/**
* Sets the history entries.
*
* @param elems the history elements to set
*/
public void setHistoryEntries(IJavaElement[] elems) {
List list= new ArrayList(1);
list.add(elems);
setHistoryEntries(list);
}
/**
* Sets the history entries.
*
* @param elems the history elements to set
* @since 3.7
*/
public void setHistoryEntries(List elems) {
fInputHistory.clear();
for (Iterator iterator= elems.iterator(); iterator.hasNext();) {
IJavaElement[] elements= (IJavaElement[])iterator.next();
if (elements != null && elements.length != 0)
fInputHistory.add(elements);
}
updateHistoryEntries();
}
/**
* Selects an member in the methods list or in the current hierarchy.
* @param member The member to select
*/
public void selectMember(IMember member) {
fSelectInEditor= false;
if (member.getElementType() != IJavaElement.TYPE) {
Control methodControl= fMethodsViewer.getControl();
if (methodControl != null && !methodControl.isDisposed()) {
methodControl.setFocus();
}
fMethodsViewer.setSelection(new StructuredSelection(member), true);
} else {
Control viewerControl= getCurrentViewer().getControl();
if (viewerControl != null && !viewerControl.isDisposed()) {
viewerControl.setFocus();
}
if (!member.equals(fSelectedType)) {
getCurrentViewer().setSelection(new StructuredSelection(member), true);
}
}
fSelectInEditor= true;
}
/**
* {@inheritDoc}
*
* @deprecated use getInputElement instead
*/
public IType getInput() {
if (fInputElements.length == 1 && fInputElements[0] instanceof IType) {
return (IType)fInputElements[0];
}
return null;
}
/**
* {@inheritDoc}
*
* @deprecated use setInputElement instead
*/
public void setInput(IType type) {
setInputElement(type);
}
/**
* Returns the input element of the type hierarchy. Can be of type <code>IType</code> or
* <code>IPackageFragment</code>
*
* @return the input element
*/
public IJavaElement getInputElement() {
return fInputElements == null ? null : (fInputElements.length == 1 ? fInputElements[0] : null);
}
/**
* Returns the input elements of the type hierarchy.
*
* @return the input elements
* @since 3.7
*/
public IJavaElement[] getInputElements() {
return fInputElements;
}
/**
* Sets the input to a new element.
* @param element the input element
*/
public void setInputElement(IJavaElement element) {
setInputElements(element == null ? null : new IJavaElement[] { element });
}
/**
* Sets the input to a new element.
*
* @param javaElements the input java elements
* @since 3.7
*/
public void setInputElements(IJavaElement[] javaElements) {
IJavaElement[] newElements= null;
IMember memberToSelect= null;
if (javaElements != null) {
newElements= new IJavaElement[javaElements.length];
for (int i= 0; i < javaElements.length; i++) {
newElements[i]= javaElements[i];
memberToSelect= null;
if (newElements[i] != null) {
if (newElements[i] instanceof IMember) {
if (newElements[i].getElementType() != IJavaElement.TYPE) {
memberToSelect= (IMember)newElements[i];
newElements[i]= memberToSelect.getDeclaringType();
}
if (!newElements[i].exists()) {
MessageDialog.openError(getSite().getShell(), TypeHierarchyMessages.TypeHierarchyViewPart_error_title, TypeHierarchyMessages.TypeHierarchyViewPart_error_message);
return;
}
} else {
int kind= newElements[i].getElementType();
if (kind != IJavaElement.JAVA_PROJECT && kind != IJavaElement.PACKAGE_FRAGMENT_ROOT && kind != IJavaElement.PACKAGE_FRAGMENT) {
newElements= null;
JavaPlugin.logErrorMessage("Invalid type hierarchy input type.");//$NON-NLS-1$
return;
}
}
}
}
if (!javaElements.equals(fInputElements)) {
addHistoryEntry(javaElements);
}
}
updateInput(newElements);
if (memberToSelect != null) {
selectMember(memberToSelect);
}
}
/*
* Changes the input to a new type
* @param inputElement
*/
private void updateInput(IJavaElement[] inputElements) {
IJavaElement[] prevInput= fInputElements;
synchronized (this) {
if (fRestoreStateJob != null) {
fRestoreStateJob.cancel();
fRestoreJobCanceledExplicitly= false;
try {
fRestoreStateJob.join();
} catch (InterruptedException e) {
// ignore
} finally {
fRestoreStateJob= null;
}
}
}
// Make sure the UI got repainted before we execute a long running
// operation. This can be removed if we refresh the hierarchy in a
// separate thread.
// Work-around for http://dev.eclipse.org/bugs/show_bug.cgi?id=30881
processOutstandingEvents();
if (inputElements == null) {
clearInput();
} else {
if (!inputElements.equals(prevInput)) {
for (int i= 0; i < fAllViewers.length; i++) {
fAllViewers[i].setInput(null);
}
}
fInputElements= inputElements;
fNoHierarchyShownLabel
.setText(Messages.format(TypeHierarchyMessages.TypeHierarchyViewPart_createinput, HistoryAction.getElementLabel(fInputElements)));
try {
fHierarchyLifeCycle.ensureRefreshedTypeHierarchy(inputElements, JavaPlugin.getActiveWorkbenchWindow());
// fHierarchyLifeCycle.ensureRefreshedTypeHierarchy(inputElement, getSite().getWorkbenchWindow());
} catch (InvocationTargetException e) {
ExceptionHandler.handle(e, getSite().getShell(), TypeHierarchyMessages.TypeHierarchyViewPart_exception_title, TypeHierarchyMessages.TypeHierarchyViewPart_exception_message);
clearInput();
return;// panic code. This code wont be executed.
} catch (InterruptedException e) {
fNoHierarchyShownLabel.setText(TypeHierarchyMessages.TypeHierarchyViewPart_empty);
return;// panic code. This code wont be executed.
}
if (inputElements.length == 1 && inputElements[0].getElementType() != IJavaElement.TYPE) {
setHierarchyMode(HIERARCHY_MODE_CLASSIC);
}
updateViewers();
}
}
/**
* Updates the viewers, toolbar buttons and tooltip.
*
* @since 3.6
*/
public void updateViewers() {
if (fInputElements == null)
return;
if (!fHierarchyLifeCycle.isRefreshJobRunning()) {
setViewersInput();
}
setViewerVisibility(true);
// turn off member filtering
fSelectInEditor= false;
setMemberFilter(null);
internalSelectType(null, false); // clear selection
fIsEnableMemberFilter= false;
updateHierarchyViewer(true);
IType root= getSelectableType(fInputElements);
internalSelectType(root, true);
updateMethodViewer(root);
updateToolbarButtons();
updateToolTipAndDescription();
showMembersInHierarchy(false);
fPagebook.showPage(fTypeMethodsSplitter);
fSelectInEditor= true;
}
private void processOutstandingEvents() {
Display display= getDisplay();
if (display != null && !display.isDisposed())
display.update();
}
private void clearInput() {
fInputElements= null;
fHierarchyLifeCycle.freeHierarchy();
updateHierarchyViewer(false);
updateToolbarButtons();
updateToolTipAndDescription();
}
/*
* @see IWorbenchPart#setFocus
*/
public void setFocus() {
fPagebook.setFocus();
}
/*
* @see IWorkbenchPart#dispose
*/
public void dispose() {
if (fHierarchyLifeCycle != null) {
fHierarchyLifeCycle.freeHierarchy();
fHierarchyLifeCycle.removeChangedListener(fTypeHierarchyLifeCycleListener);
fHierarchyLifeCycle= null;
}
fPaneLabelProvider.dispose();
if (fMethodsViewer != null) {
fMethodsViewer.dispose();
}
if (fPropertyChangeListener != null) {
JavaPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(fPropertyChangeListener);
fPropertyChangeListener= null;
}
getSite().getPage().removePartListener(fPartListener);
if (fActionGroups != null)
fActionGroups.dispose();
if (fWorkingSetActionGroup != null)
fWorkingSetActionGroup.dispose();
super.dispose();
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
*/
public Object getAdapter(Class key) {
if (key == IShowInSource.class) {
return getShowInSource();
}
if (key == IShowInTargetList.class) {
return new IShowInTargetList() {
public String[] getShowInTargetIds() {
return new String[] { JavaUI.ID_PACKAGES, JavaPlugin.ID_RES_NAV };
}
};
}
if (key == IContextProvider.class) {
return JavaUIHelp.getHelpContextProvider(this, IJavaHelpContextIds.TYPE_HIERARCHY_VIEW);
}
return super.getAdapter(key);
}
private Control createTypeViewerControl(Composite parent) {
fViewerbook= new PageBook(parent, SWT.NULL);
KeyListener keyListener= createKeyListener();
// Create the viewers
TypeHierarchyViewer superTypesViewer= new SuperTypeHierarchyViewer(fViewerbook, fHierarchyLifeCycle);
initializeTypesViewer(superTypesViewer, keyListener, IContextMenuConstants.TARGET_ID_SUPERTYPES_VIEW);
TypeHierarchyViewer subTypesViewer= new SubTypeHierarchyViewer(fViewerbook, fHierarchyLifeCycle);
initializeTypesViewer(subTypesViewer, keyListener, IContextMenuConstants.TARGET_ID_SUBTYPES_VIEW);
TypeHierarchyViewer vajViewer= new TraditionalHierarchyViewer(fViewerbook, fHierarchyLifeCycle);
initializeTypesViewer(vajViewer, keyListener, IContextMenuConstants.TARGET_ID_HIERARCHY_VIEW);
fAllViewers= new TypeHierarchyViewer[3];
fAllViewers[HIERARCHY_MODE_SUPERTYPES]= superTypesViewer;
fAllViewers[HIERARCHY_MODE_SUBTYPES]= subTypesViewer;
fAllViewers[HIERARCHY_MODE_CLASSIC]= vajViewer;
int currViewerIndex;
try {
currViewerIndex= fDialogSettings.getInt(DIALOGSTORE_HIERARCHYVIEW);
if (currViewerIndex < 0 || currViewerIndex > 2) {
currViewerIndex= HIERARCHY_MODE_CLASSIC;
}
} catch (NumberFormatException e) {
currViewerIndex= HIERARCHY_MODE_CLASSIC;
}
fEmptyTypesViewer= new Label(fViewerbook, SWT.TOP | SWT.LEFT | SWT.WRAP);
for (int i= 0; i < fAllViewers.length; i++) {
fAllViewers[i].setInput(fAllViewers[i]);
}
// force the update
fCurrentViewerIndex= -1;
setHierarchyMode(currViewerIndex);
return fViewerbook;
}
private KeyListener createKeyListener() {
return new KeyAdapter() {
public void keyReleased(KeyEvent event) {
if (event.stateMask == 0) {
if (event.keyCode == SWT.F5) {
ITypeHierarchy hierarchy= fHierarchyLifeCycle.getHierarchy();
if (hierarchy != null) {
fHierarchyLifeCycle.typeHierarchyChanged(hierarchy);
doTypeHierarchyChangedOnViewers(null);
}
updateHierarchyViewer(false);
return;
}
}
}
};
}
private void initializeTypesViewer(final TypeHierarchyViewer typesViewer, KeyListener keyListener, String cotextHelpId) {
typesViewer.getControl().setVisible(false);
typesViewer.getControl().addKeyListener(keyListener);
typesViewer.initContextMenu(new IMenuListener() {
public void menuAboutToShow(IMenuManager menu) {
fillTypesViewerContextMenu(typesViewer, menu);
}
}, cotextHelpId, getSite());
typesViewer.addPostSelectionChangedListener(fSelectionChangedListener);
typesViewer.setQualifiedTypeName(isQualifiedTypeNamesEnabled());
typesViewer.setWorkingSetFilter(fWorkingSetActionGroup.getWorkingSetFilter());
}
private Control createMethodViewerControl(Composite parent) {
fMethodsViewer= new MethodsViewer(parent, fHierarchyLifeCycle);
fMethodsViewer.initContextMenu(new IMenuListener() {
public void menuAboutToShow(IMenuManager menu) {
fillMethodsViewerContextMenu(menu);
}
}, IContextMenuConstants.TARGET_ID_MEMBERS_VIEW, getSite());
fMethodsViewer.addPostSelectionChangedListener(fSelectionChangedListener);
new OpenAndLinkWithEditorHelper(fMethodsViewer) {
protected void activate(ISelection selection) {
try {
final Object selectedElement= SelectionUtil.getSingleElement(selection);
if (EditorUtility.isOpenInEditor(selectedElement) != null)
EditorUtility.openInEditor(selectedElement, true);
} catch (PartInitException ex) {
// ignore if no editor input can be found
}
}
protected void linkToEditor(ISelection selection) {
// do nothing: this is handled in more detail by the part itself
}
protected void open(ISelection selection, boolean activate) {
if (selection instanceof IStructuredSelection)
fOpenAction.run((IStructuredSelection)selection);
}
};
Control control= fMethodsViewer.getTable();
control.addKeyListener(createKeyListener());
control.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
fSelectAllAction.setEnabled(true);
}
public void focusLost(FocusEvent e) {
fSelectAllAction.setEnabled(false);
}
});
return control;
}
private void initDragAndDrop() {
for (int i= 0; i < fAllViewers.length; i++) {
addDragAdapters(fAllViewers[i]);
addDropAdapters(fAllViewers[i]);
}
addDragAdapters(fMethodsViewer);
fMethodsViewer.addDropSupport(DND.DROP_NONE, new Transfer[0], new DropTargetAdapter());
//DND on empty hierarchy
DropTarget dropTarget = new DropTarget(fPagebook, DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_DEFAULT);
dropTarget.setTransfer(new Transfer[] { LocalSelectionTransfer.getInstance() });
dropTarget.addDropListener(new TypeHierarchyTransferDropAdapter(this, fAllViewers[0]));
}
private void addDropAdapters(AbstractTreeViewer viewer) {
Transfer[] transfers= new Transfer[] { LocalSelectionTransfer.getInstance(), PluginTransfer.getInstance() };
int ops= DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_DEFAULT;
DelegatingDropAdapter delegatingDropAdapter= new DelegatingDropAdapter();
delegatingDropAdapter.addDropTargetListener(new TypeHierarchyTransferDropAdapter(this, viewer));
delegatingDropAdapter.addDropTargetListener(new PluginTransferDropAdapter(viewer));
viewer.addDropSupport(ops, transfers, delegatingDropAdapter);
}
private void addDragAdapters(StructuredViewer viewer) {
int ops= DND.DROP_COPY | DND.DROP_LINK;
Transfer[] transfers= new Transfer[] { LocalSelectionTransfer.getInstance(), ResourceTransfer.getInstance(), FileTransfer.getInstance()};
JdtViewerDragAdapter dragAdapter= new JdtViewerDragAdapter(viewer);
dragAdapter.addDragSourceListener(new SelectionTransferDragAdapter(viewer));
dragAdapter.addDragSourceListener(new EditorInputTransferDragAdapter(viewer));
dragAdapter.addDragSourceListener(new ResourceTransferDragAdapter(viewer));
dragAdapter.addDragSourceListener(new FileTransferDragAdapter(viewer));
viewer.addDragSupport(ops, transfers, dragAdapter);
}
/**
* Returns the inner component in a workbench part.
* @see IWorkbenchPart#createPartControl(Composite)
*/
public void createPartControl(Composite container) {
fParent= container;
addResizeListener(container);
fPagebook= new PageBook(container, SWT.NONE);
fWorkingSetActionGroup= new WorkingSetFilterActionGroup(getSite(), fPropertyChangeListener);
// page 1 of page book (no hierarchy label)
fNoHierarchyShownLabel= new Label(fPagebook, SWT.TOP + SWT.LEFT + SWT.WRAP);
fNoHierarchyShownLabel.setText(TypeHierarchyMessages.TypeHierarchyViewPart_empty);
// page 2 of page book (viewers)
fTypeMethodsSplitter= new SashForm(fPagebook, SWT.VERTICAL);
fTypeMethodsSplitter.setVisible(false);
fTypeViewerViewForm= new ViewForm(fTypeMethodsSplitter, SWT.NONE);
Control typeViewerControl= createTypeViewerControl(fTypeViewerViewForm);
fTypeViewerViewForm.setContent(typeViewerControl);
fMethodViewerViewForm= new ViewForm(fTypeMethodsSplitter, SWT.NONE);
fTypeMethodsSplitter.setWeights(new int[] {35, 65});
Control methodViewerPart= createMethodViewerControl(fMethodViewerViewForm);
fMethodViewerViewForm.setContent(methodViewerPart);
fMethodViewerPaneLabel= new CLabel(fMethodViewerViewForm, SWT.NONE);
fMethodViewerViewForm.setTopLeft(fMethodViewerPaneLabel);
ToolBar methodViewerToolBar= new ToolBar(fMethodViewerViewForm, SWT.FLAT | SWT.WRAP);
fMethodViewerViewForm.setTopCenter(methodViewerToolBar);
initDragAndDrop();
MenuManager menu= new MenuManager();
menu.add(fFocusOnTypeAction);
fNoHierarchyShownLabel.setMenu(menu.createContextMenu(fNoHierarchyShownLabel));
fPagebook.showPage(fNoHierarchyShownLabel);
int layout;
try {
layout= fDialogSettings.getInt(DIALOGSTORE_VIEWLAYOUT);
if (layout < 0 || layout > 3) {
layout= VIEW_LAYOUT_AUTOMATIC;
}
} catch (NumberFormatException e) {
layout= VIEW_LAYOUT_AUTOMATIC;
}
// force the update
fCurrentLayout= -1;
// will fill the main tool bar
setViewLayout(layout);
showQualifiedTypeNames(fDialogSettings.getBoolean(DIALOGSTORE_QUALIFIED_NAMES));
setLinkingEnabled(fDialogSettings.getBoolean(DIALOGSTORE_LINKEDITORS));
// set the filter menu items
IActionBars actionBars= getViewSite().getActionBars();
IMenuManager viewMenu= actionBars.getMenuManager();
for (int i= 0; i < fViewActions.length; i++) {
ToggleViewAction action= fViewActions[i];
viewMenu.add(action);
action.setEnabled(false);
}
viewMenu.add(new Separator());
fWorkingSetActionGroup.fillViewMenu(viewMenu);
viewMenu.add(new Separator());
IMenuManager layoutSubMenu= new MenuManager(TypeHierarchyMessages.TypeHierarchyViewPart_layout_submenu);
viewMenu.add(layoutSubMenu);
for (int i= 0; i < fToggleOrientationActions.length; i++) {
layoutSubMenu.add(fToggleOrientationActions[i]);
}
viewMenu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
viewMenu.add(fShowQualifiedTypeNamesAction);
viewMenu.add(fToggleLinkingAction);
// fill the method viewer tool bar
ToolBarManager lowertbmanager= new ToolBarManager(methodViewerToolBar);
lowertbmanager.add(fEnableMemberFilterAction);
lowertbmanager.add(new Separator());
fMethodsViewer.contributeToToolBar(lowertbmanager);
lowertbmanager.update(true);
// selection provider
int nHierarchyViewers= fAllViewers.length;
StructuredViewer[] trackedViewers= new StructuredViewer[nHierarchyViewers + 1];
for (int i= 0; i < nHierarchyViewers; i++) {
trackedViewers[i]= fAllViewers[i];
}
trackedViewers[nHierarchyViewers]= fMethodsViewer;
fSelectionProviderMediator= new SelectionProviderMediator(trackedViewers, getCurrentViewer());
IStatusLineManager slManager= getViewSite().getActionBars().getStatusLineManager();
fSelectionProviderMediator.addSelectionChangedListener(new StatusBarUpdater(slManager));
getSite().setSelectionProvider(fSelectionProviderMediator);
getSite().getPage().addPartListener(fPartListener);
// see http://bugs.eclipse.org/bugs/show_bug.cgi?id=33657
IJavaElement[] input= null; //determineInputElement();
if (fMemento != null) {
restoreState(fMemento, input);
//} else if (input != null) {
// setInputElement(input);
} else {
setViewerVisibility(false);
}
PlatformUI.getWorkbench().getHelpSystem().setHelp(fPagebook, IJavaHelpContextIds.TYPE_HIERARCHY_VIEW);
fActionGroups= new CompositeActionGroup(new ActionGroup[] {
new NewWizardsActionGroup(this.getSite()),
new OpenEditorActionGroup(this),
new OpenViewActionGroup(this),
new CCPActionGroup(this),
new GenerateActionGroup(this),
new RefactorActionGroup(this),
new JavaSearchActionGroup(this)
});
fActionGroups.fillActionBars(actionBars);
fSelectAllAction= new SelectAllAction(fMethodsViewer);
fOpenAction= new OpenAction(getSite());
actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), fSelectAllAction);
IHandlerService handlerService= (IHandlerService) getViewSite().getService(IHandlerService.class);
handlerService.activateHandler(IWorkbenchCommandConstants.NAVIGATE_TOGGLE_LINK_WITH_EDITOR, new ActionHandler(fToggleLinkingAction));
}
private void addResizeListener(Composite parent) {
parent.addControlListener(new ControlListener() {
public void controlMoved(ControlEvent e) {
}
public void controlResized(ControlEvent e) {
if (getViewLayout() == VIEW_LAYOUT_AUTOMATIC && !fInComputeLayout) {
setViewLayout(VIEW_LAYOUT_AUTOMATIC);
}
}
});
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.ITypeHierarchyViewPart#setViewLayout(int)
*/
public void setViewLayout(int layout) {
if (fCurrentLayout != layout || layout == VIEW_LAYOUT_AUTOMATIC) {
fInComputeLayout= true;
try {
boolean methodViewerNeedsUpdate= false;
if (fMethodViewerViewForm != null && !fMethodViewerViewForm.isDisposed()
&& fTypeMethodsSplitter != null && !fTypeMethodsSplitter.isDisposed()) {
boolean horizontal= false;
if (layout == VIEW_LAYOUT_SINGLE) {
fMethodViewerViewForm.setVisible(false);
showMembersInHierarchy(false);
updateMethodViewer(null);
} else {
if (fCurrentLayout == VIEW_LAYOUT_SINGLE) {
fMethodViewerViewForm.setVisible(true);
methodViewerNeedsUpdate= true;
}
if (layout == VIEW_LAYOUT_AUTOMATIC) {
if (fParent != null && !fParent.isDisposed()) {
Point size= fParent.getSize();
if (size.x != 0 && size.y != 0) {
// bug 185397 - Hierarchy View flips orientation multiple times on resize
Control viewFormToolbar= fTypeViewerViewForm.getTopLeft();
if (viewFormToolbar != null && !viewFormToolbar.isDisposed() && viewFormToolbar.isVisible()) {
size.y -= viewFormToolbar.getSize().y;
}
horizontal= size.x > size.y;
}
}
if (fCurrentLayout == VIEW_LAYOUT_AUTOMATIC) {
boolean wasHorizontal= fTypeMethodsSplitter.getOrientation() == SWT.HORIZONTAL;
if (wasHorizontal == horizontal) {
return; // no real change
}
}
} else if (layout == VIEW_LAYOUT_HORIZONTAL) {
horizontal= true;
}
fTypeMethodsSplitter.setOrientation(horizontal ? SWT.HORIZONTAL : SWT.VERTICAL);
}
updateMainToolbar(horizontal);
fTypeMethodsSplitter.layout();
}
if (methodViewerNeedsUpdate) {
updateMethodViewer(fSelectedType);
}
fDialogSettings.put(DIALOGSTORE_VIEWLAYOUT, layout);
fCurrentLayout= layout;
updateCheckedState();
} finally {
fInComputeLayout= false;
}
}
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.ITypeHierarchyViewPart#getViewLayout()
*/
public int getViewLayout() {
return fCurrentLayout;
}
private void updateCheckedState() {
for (int i= 0; i < fToggleOrientationActions.length; i++) {
fToggleOrientationActions[i].setChecked(getViewLayout() == fToggleOrientationActions[i].getOrientation());
}
}
private void updateMainToolbar(boolean horizontal) {
IActionBars actionBars= getViewSite().getActionBars();
IToolBarManager tbmanager= actionBars.getToolBarManager();
if (horizontal) {
clearMainToolBar(tbmanager);
ToolBar typeViewerToolBar= new ToolBar(fTypeViewerViewForm, SWT.FLAT | SWT.WRAP);
fillMainToolBar(new ToolBarManager(typeViewerToolBar));
fTypeViewerViewForm.setTopLeft(typeViewerToolBar);
} else {
fTypeViewerViewForm.setTopLeft(null);
fillMainToolBar(tbmanager);
}
}
private void fillMainToolBar(IToolBarManager tbmanager) {
tbmanager.removeAll();
for (int i= 0; i < fViewActions.length; i++) {
tbmanager.add(fViewActions[i]);
}
tbmanager.add(fHistoryDropDownAction);
tbmanager.update(false);
}
private void clearMainToolBar(IToolBarManager tbmanager) {
tbmanager.removeAll();
tbmanager.update(false);
}
/*
* Creates the context menu for the hierarchy viewers
*/
private void fillTypesViewerContextMenu(TypeHierarchyViewer viewer, IMenuManager menu) {
JavaPlugin.createStandardGroups(menu);
menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, new Separator(GROUP_FOCUS));
// viewer entries
viewer.contributeToContextMenu(menu);
if (fFocusOnSelectionAction.canActionBeAdded())
menu.appendToGroup(GROUP_FOCUS, fFocusOnSelectionAction);
menu.appendToGroup(GROUP_FOCUS, fFocusOnTypeAction);
fActionGroups.setContext(new ActionContext(getSite().getSelectionProvider().getSelection()));
fActionGroups.fillContextMenu(menu);
fActionGroups.setContext(null);
}
/*
* Creates the context menu for the method viewer
*/
private void fillMethodsViewerContextMenu(IMenuManager menu) {
JavaPlugin.createStandardGroups(menu);
// viewer entries
fMethodsViewer.contributeToContextMenu(menu);
fActionGroups.setContext(new ActionContext(getSite().getSelectionProvider().getSelection()));
fActionGroups.fillContextMenu(menu);
fActionGroups.setContext(null);
}
/*
* Toggles between the empty viewer page and the hierarchy
*/
private void setViewerVisibility(boolean showHierarchy) {
if (showHierarchy) {
fViewerbook.showPage(getCurrentViewer().getControl());
} else {
fViewerbook.showPage(fEmptyTypesViewer);
}
}
/*
* Sets the member filter. <code>null</code> disables member filtering.
*/
private void setMemberFilter(IMember[] memberFilter) {
Assert.isNotNull(fAllViewers);
for (int i= 0; i < fAllViewers.length; i++) {
fAllViewers[i].setMemberFilter(memberFilter);
}
}
private IType getSelectableType(IJavaElement[] elem) {
if (elem[0].getElementType() != IJavaElement.TYPE) {
return getCurrentViewer().getTreeRootType();
} else {
return (IType)elem[0];
}
}
private void internalSelectType(IMember elem, boolean reveal) {
TypeHierarchyViewer viewer= getCurrentViewer();
viewer.removePostSelectionChangedListener(fSelectionChangedListener);
viewer.setSelection(elem != null ? new StructuredSelection(elem) : StructuredSelection.EMPTY, reveal);
viewer.addPostSelectionChangedListener(fSelectionChangedListener);
}
/*
* When the input changed or the hierarchy pane becomes visible,
* <code>updateHierarchyViewer<code> brings up the correct view and refreshes
* the current tree
*/
private void updateHierarchyViewer(final boolean doExpand) {
if (fInputElements == null) {
fNoHierarchyShownLabel.setText(TypeHierarchyMessages.TypeHierarchyViewPart_empty);
fPagebook.showPage(fNoHierarchyShownLabel);
} else {
if (getCurrentViewer().containsElements() != null) {
Runnable runnable= new Runnable() {
public void run() {
getCurrentViewer().updateContent(doExpand); // refresh
}
};
BusyIndicator.showWhile(getDisplay(), runnable);
if (!isChildVisible(fViewerbook, getCurrentViewer().getControl())) {
setViewerVisibility(true);
}
} else if (!isKeepShowingEmptyViewers()) {//Show the empty hierarchy viewer till fresh computation is done.
fEmptyTypesViewer.setText(Messages.format(TypeHierarchyMessages.TypeHierarchyViewPart_nodecl, HistoryAction.getElementLabel(fInputElements)));
setViewerVisibility(false);
}
}
}
private void updateMethodViewer(final IType input) {
if (!fIsEnableMemberFilter && fCurrentLayout != VIEW_LAYOUT_SINGLE) {
if (input == fMethodsViewer.getInput()) {
if (input != null) {
Runnable runnable= new Runnable() {
public void run() {
fMethodsViewer.refresh(); // refresh
}
};
BusyIndicator.showWhile(getDisplay(), runnable);
}
} else {
if (input != null) {
fMethodViewerPaneLabel.setText(fPaneLabelProvider.getText(input));
fMethodViewerPaneLabel.setImage(fPaneLabelProvider.getImage(input));
} else {
fMethodViewerPaneLabel.setText(""); //$NON-NLS-1$
fMethodViewerPaneLabel.setImage(null);
}
Runnable runnable= new Runnable() {
public void run() {
fMethodsViewer.setInput(input); // refresh
}
};
BusyIndicator.showWhile(getDisplay(), runnable);
}
}
}
protected void doSelectionChanged(SelectionChangedEvent e) {
if (e.getSelectionProvider() == fMethodsViewer) {
methodSelectionChanged(e.getSelection());
} else {
typeSelectionChanged(e.getSelection());
}
}
private void methodSelectionChanged(ISelection sel) {
if (sel instanceof IStructuredSelection) {
List selected= ((IStructuredSelection)sel).toList();
int nSelected= selected.size();
if (fIsEnableMemberFilter) {
IMember[] memberFilter= null;
if (nSelected > 0) {
memberFilter= new IMember[nSelected];
selected.toArray(memberFilter);
}
setMemberFilter(memberFilter);
updateHierarchyViewer(true);
updateToolTipAndDescription();
internalSelectType(fSelectedType, true);
}
if (nSelected == 1 && fSelectInEditor) {
revealElementInEditor(selected.get(0), fMethodsViewer);
}
}
}
private void typeSelectionChanged(ISelection sel) {
if (sel instanceof IStructuredSelection) {
List selected= ((IStructuredSelection)sel).toList();
int nSelected= selected.size();
if (nSelected != 0) {
List types= new ArrayList(nSelected);
for (int i= nSelected-1; i >= 0; i--) {
Object elem= selected.get(i);
if (elem instanceof IType && !types.contains(elem)) {
types.add(elem);
}
}
if (types.size() == 1) {
fSelectedType= (IType) types.get(0);
updateMethodViewer(fSelectedType);
} else if (types.size() == 0) {
// method selected, no change
}
if (nSelected == 1 && fSelectInEditor) {
revealElementInEditor(selected.get(0), getCurrentViewer());
}
} else {
fSelectedType= null;
updateMethodViewer(null);
}
}
}
private void revealElementInEditor(Object elem, StructuredViewer originViewer) {
// only allow revealing when the type hierarchy is the active page
// no revealing after selection events due to model changes
if (getSite().getPage().getActivePart() != this) {
return;
}
if (fSelectionProviderMediator.getViewerInFocus() != originViewer) {
return;
}
IEditorPart editorPart= EditorUtility.isOpenInEditor(elem);
if (editorPart != null && (elem instanceof IJavaElement)) {
getSite().getPage().removePartListener(fPartListener);
getSite().getPage().bringToTop(editorPart);
EditorUtility.revealInEditor(editorPart, (IJavaElement) elem);
getSite().getPage().addPartListener(fPartListener);
}
}
private Display getDisplay() {
if (fPagebook != null && !fPagebook.isDisposed()) {
return fPagebook.getDisplay();
}
return null;
}
private boolean isChildVisible(Composite pb, Control child) {
Control[] children= pb.getChildren();
for (int i= 0; i < children.length; i++) {
if (children[i] == child && children[i].isVisible())
return true;
}
return false;
}
private void updateToolTipAndDescription() {
String tooltip;
String description;
if (fInputElements != null) {
IWorkingSet workingSet= fWorkingSetActionGroup.getWorkingSet();
String elementName= HistoryAction.getElementLabel(fInputElements);
if (workingSet == null) {
description= elementName;
tooltip= Messages.format(TypeHierarchyMessages.TypeHierarchyViewPart_tooltip, elementName);
} else {
String[] args= new String[] { elementName, workingSet.getLabel() };
description= Messages.format(TypeHierarchyMessages.TypeHierarchyViewPart_ws_description, args);
tooltip= Messages.format(TypeHierarchyMessages.TypeHierarchyViewPart_ws_tooltip, args);
}
} else {
description= ""; //$NON-NLS-1$
tooltip= getPartName();
}
setContentDescription(description);
setTitleToolTip(tooltip);
}
private void updateToolbarButtons() {
boolean isNull= fInputElements == null;
boolean isType= !isNull && fInputElements.length == 1 && fInputElements[0] instanceof IType;
for (int i= 0; i < fViewActions.length; i++) {
ToggleViewAction action= fViewActions[i];
if (action.getViewerIndex() == HIERARCHY_MODE_CLASSIC) {
action.setEnabled(!isNull);
} else {
action.setEnabled(isType);
}
}
}
public void setHierarchyMode(int viewerIndex) {
Assert.isNotNull(fAllViewers);
if (viewerIndex < fAllViewers.length && fCurrentViewerIndex != viewerIndex) {
fCurrentViewerIndex= viewerIndex;
updateHierarchyViewer(true);
if (fInputElements != null) {
ISelection currSelection= getCurrentViewer().getSelection();
if (currSelection == null || currSelection.isEmpty()) {
internalSelectType(getSelectableType(fInputElements), false);
currSelection= getCurrentViewer().getSelection();
}
if (!fIsEnableMemberFilter) {
typeSelectionChanged(currSelection);
}
}
updateToolTipAndDescription();
fDialogSettings.put(DIALOGSTORE_HIERARCHYVIEW, viewerIndex);
getCurrentViewer().getTree().setFocus();
if (fTypeOpenAndLinkWithEditorHelper != null)
fTypeOpenAndLinkWithEditorHelper.dispose();
fTypeOpenAndLinkWithEditorHelper= new OpenAndLinkWithEditorHelper(getCurrentViewer()) {
protected void activate(ISelection selection) {
try {
final Object selectedElement= SelectionUtil.getSingleElement(selection);
if (EditorUtility.isOpenInEditor(selectedElement) != null)
EditorUtility.openInEditor(selectedElement, true);
} catch (PartInitException ex) {
// ignore if no editor input can be found
}
}
protected void linkToEditor(ISelection selection) {
// do nothing: this is handled in more detailed by the part itself
}
protected void open(ISelection selection, boolean activate) {
if (selection instanceof IStructuredSelection)
fOpenAction.run((IStructuredSelection)selection);
}
};
}
for (int i= 0; i < fViewActions.length; i++) {
ToggleViewAction action= fViewActions[i];
action.setChecked(fCurrentViewerIndex == action.getViewerIndex());
}
}
public int getHierarchyMode() {
return fCurrentViewerIndex;
}
private TypeHierarchyViewer getCurrentViewer() {
return fAllViewers[fCurrentViewerIndex];
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.ITypeHierarchyViewPart#showMembersInHierarchy(boolean)
*/
public void showMembersInHierarchy(boolean on) {
if (on != fIsEnableMemberFilter) {
fIsEnableMemberFilter= on;
if (!on) {
IType methodViewerInput= (IType) fMethodsViewer.getInput();
setMemberFilter(null);
updateHierarchyViewer(true);
updateToolTipAndDescription();
if (methodViewerInput != null && getCurrentViewer().isElementShown(methodViewerInput)) {
// avoid that the method view changes content by selecting the previous input
internalSelectType(methodViewerInput, true);
} else if (fSelectedType != null) {
// choose a input that exists
internalSelectType(fSelectedType, true);
updateMethodViewer(fSelectedType);
}
} else {
methodSelectionChanged(fMethodsViewer.getSelection());
}
}
fEnableMemberFilterAction.setChecked(on);
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.ITypeHierarchyViewPart#isShowMembersInHierarchy()
*/
public boolean isShowMembersInHierarchy() {
return fIsEnableMemberFilter;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.ITypeHierarchyViewPart#showQualifiedTypeNames(boolean)
*/
public void showQualifiedTypeNames(boolean on) {
if (on != fShowQualifiedTypeNames) {
fShowQualifiedTypeNames= on;
if (fAllViewers != null) {
for (int i= 0; i < fAllViewers.length; i++) {
fAllViewers[i].setQualifiedTypeName(on);
}
}
}
fShowQualifiedTypeNamesAction.setChecked(on);
fDialogSettings.put(DIALOGSTORE_QUALIFIED_NAMES, on);
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.ITypeHierarchyViewPart#isQualifiedTypeNamesEnabled()
*/
public boolean isQualifiedTypeNamesEnabled() {
return fShowQualifiedTypeNames;
}
/**
* Called from ITypeHierarchyLifeCycleListener.
* Can be called from any thread
* @param typeHierarchy Hierarchy that has changed
* @param changedTypes Types in the hierarchy that have change or <code>null</code> if the full hierarchy has changed
*/
protected void doTypeHierarchyChanged(final TypeHierarchyLifeCycle typeHierarchy, final IType[] changedTypes) {
if (!fIsVisible) {
fNeedRefresh= true;
return;
}
if (fIsRefreshRunnablePosted) {
return;
}
Display display= getDisplay();
if (display != null) {
fIsRefreshRunnablePosted= true;
display.asyncExec(new Runnable() {
public void run() {
try {
if (fPagebook != null && !fPagebook.isDisposed()) {
doTypeHierarchyChangedOnViewers(changedTypes);
}
} finally {
fIsRefreshRunnablePosted= false;
}
}
});
}
}
protected void doTypeHierarchyChangedOnViewers(IType[] changedTypes) {
if (fHierarchyLifeCycle.getHierarchy() == null || !fHierarchyLifeCycle.getHierarchy().exists()) {
clearInput();
} else {
if (changedTypes == null) {
// hierarchy change
try {
fHierarchyLifeCycle.ensureRefreshedTypeHierarchy(fInputElements, getSite().getWorkbenchWindow());
} catch (InvocationTargetException e) {
ExceptionHandler.handle(e, getSite().getShell(), TypeHierarchyMessages.TypeHierarchyViewPart_exception_title, TypeHierarchyMessages.TypeHierarchyViewPart_exception_message);
clearInput();
return;
} catch (InterruptedException e) {
return;
}
fMethodsViewer.refresh();
updateHierarchyViewer(false);
} else {
// elements in hierarchy modified
Object methodViewerInput= fMethodsViewer.getInput();
fMethodsViewer.refresh();
fMethodViewerPaneLabel.setText(fPaneLabelProvider.getText(methodViewerInput));
fMethodViewerPaneLabel.setImage(fPaneLabelProvider.getImage(methodViewerInput));
if (getCurrentViewer().isMethodFiltering()) {
if (changedTypes.length == 1) {
getCurrentViewer().refresh(changedTypes[0]);
} else {
updateHierarchyViewer(false);
}
} else {
getCurrentViewer().update(changedTypes, new String[] { IBasicPropertyConstants.P_TEXT, IBasicPropertyConstants.P_IMAGE } );
}
}
}
}
/*
* @see IViewPart#init
*/
public void init(IViewSite site, IMemento memento) throws PartInitException {
super.init(site, memento);
fMemento= memento;
}
/*
* @see ViewPart#saveState(IMemento)
*/
public void saveState(IMemento memento) {
if (fPagebook == null) {
// part has not been created
if (fMemento != null) { //Keep the old state;
memento.putMemento(fMemento);
}
return;
}
if (fInputElements != null) {
memento.putString(TAG_INPUT, fInputElements[0].getHandleIdentifier());
for (int i= 1; i < fInputElements.length; i++) {
IJavaElement element= fInputElements[i];
memento.putString(TAG_INPUT + i, element.getHandleIdentifier());
}
}
memento.putInteger(TAG_VIEW, getHierarchyMode());
memento.putInteger(TAG_LAYOUT, getViewLayout());
memento.putInteger(TAG_QUALIFIED_NAMES, isQualifiedTypeNamesEnabled() ? 1 : 0);
memento.putInteger(TAG_EDITOR_LINKING, isLinkingEnabled() ? 1 : 0);
int weigths[]= fTypeMethodsSplitter.getWeights();
int ratio= (weigths[0] * 1000) / (weigths[0] + weigths[1]);
memento.putInteger(TAG_RATIO, ratio);
ScrollBar bar= getCurrentViewer().getTree().getVerticalBar();
int position= bar != null ? bar.getSelection() : 0;
memento.putInteger(TAG_VERTICAL_SCROLL, position);
IJavaElement selection= (IJavaElement)((IStructuredSelection) getCurrentViewer().getSelection()).getFirstElement();
if (selection != null) {
memento.putString(TAG_SELECTION, selection.getHandleIdentifier());
}
fWorkingSetActionGroup.saveState(memento);
fMethodsViewer.saveState(memento);
}
/*
* Restores the type hierarchy settings from a memento.
*/
private void restoreState(final IMemento memento, IJavaElement[] defaultInput) {
IJavaElement input= null;
List inputList= new ArrayList();
String elementId= memento.getString(TAG_INPUT);
int i= 0;
while (elementId != null) {
input= JavaCore.create(elementId);
if (input == null || !input.exists()) {
inputList= null;
break;
}
inputList.add(input);
elementId= memento.getString(TAG_INPUT + ++i);
}
if (inputList == null || inputList.size() == 0) {
doRestoreState(memento, input);
} else {
final IJavaElement[] hierarchyInput= (IJavaElement[])inputList.toArray(new IJavaElement[inputList.size()]);
synchronized (this) {
String label= Messages.format(TypeHierarchyMessages.TypeHierarchyViewPart_restoreinput, HistoryAction.getElementLabel(hierarchyInput));
fNoHierarchyShownLabel.setText(label);
fRestoreStateJob= new Job(label) {
protected IStatus run(IProgressMonitor monitor) {
try {
doRestoreInBackground(memento, hierarchyInput, monitor);
} catch (JavaModelException e) {
return e.getStatus();
} catch (OperationCanceledException e) {
if (fRestoreJobCanceledExplicitly) {
showEmptyViewer();
}
return Status.CANCEL_STATUS;
}
return Status.OK_STATUS;
}
};
fRestoreStateJob.schedule();
}
}
}
private void doRestoreInBackground(final IMemento memento, final IJavaElement[] hierarchyInput, IProgressMonitor monitor) throws JavaModelException {
fHierarchyLifeCycle.doHierarchyRefresh(hierarchyInput, monitor);
final boolean doRestore= !monitor.isCanceled();
if (doRestore) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
// running async: check first if view still exists
if (fPagebook != null && !fPagebook.isDisposed()) {
doRestoreState(memento, hierarchyInput);
}
}
});
}
}
final void doRestoreState(IMemento memento, IJavaElement input) {
doRestoreState(memento, input == null ? null : new IJavaElement[] { input });
}
/**
* Restores the state of the type hierarchy view from the memento.
*
* @param memento the memento
* @param input the input java elements
* @since 3.7
*/
final void doRestoreState(IMemento memento, IJavaElement[] input) {
synchronized (this) {
if (fRestoreStateJob == null) {
return;
}
fRestoreStateJob= null;
}
fWorkingSetActionGroup.restoreState(memento);
setKeepShowingEmptyViewers(false);
setInputElements(input);
Integer viewerIndex= memento.getInteger(TAG_VIEW);
if (viewerIndex != null) {
setHierarchyMode(viewerIndex.intValue());
}
Integer layout= memento.getInteger(TAG_LAYOUT);
if (layout != null) {
setViewLayout(layout.intValue());
}
Integer val= memento.getInteger(TAG_EDITOR_LINKING);
if (val != null) {
setLinkingEnabled(val.intValue() != 0);
}
Integer showQualified= memento.getInteger(TAG_QUALIFIED_NAMES);
if (showQualified != null) {
showQualifiedTypeNames(showQualified.intValue() != 0);
}
updateCheckedState();
Integer ratio= memento.getInteger(TAG_RATIO);
if (ratio != null) {
fTypeMethodsSplitter.setWeights(new int[] { ratio.intValue(), 1000 - ratio.intValue() });
}
ScrollBar bar= getCurrentViewer().getTree().getVerticalBar();
if (bar != null) {
Integer vScroll= memento.getInteger(TAG_VERTICAL_SCROLL);
if (vScroll != null) {
bar.setSelection(vScroll.intValue());
}
}
fMethodsViewer.restoreState(memento);
}
/**
* View part becomes visible.
*
* @param isVisible <code>true</code> if visible
*/
protected void visibilityChanged(boolean isVisible) {
fIsVisible= isVisible;
if (isVisible && fNeedRefresh) {
doTypeHierarchyChangedOnViewers(null);
}
fNeedRefresh= false;
}
/**
* Link selection to active editor.
* @param editor The activated editor
*/
protected void editorActivated(IEditorPart editor) {
if (!isLinkingEnabled()) {
return;
}
if (fInputElements == null) {
// no type hierarchy shown
return;
}
IJavaElement elem= (IJavaElement)editor.getEditorInput().getAdapter(IJavaElement.class);
if (elem instanceof ITypeRoot) {
IType type= ((ITypeRoot) elem).findPrimaryType();
if (type != null) {
internalSelectType(type, true);
if (getCurrentViewer().getSelection().isEmpty()) {
updateMethodViewer(null);
} else {
updateMethodViewer(type);
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
*/
public Object getViewPartInput() {
return fInputElements;
}
/**
* @return Returns the <code>IShowInSource</code> for this view.
*/
protected IShowInSource getShowInSource() {
return new IShowInSource() {
public ShowInContext getShowInContext() {
return new ShowInContext(
null,
getSite().getSelectionProvider().getSelection());
}
};
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.ITypeHierarchyViewPart#isLinkingEnabled()
*/
public boolean isLinkingEnabled() {
return fLinkingEnabled;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.ui.ITypeHierarchyViewPart#setLinkingEnabled(boolean)
*/
public void setLinkingEnabled(boolean enabled) {
fLinkingEnabled= enabled;
fToggleLinkingAction.setChecked(enabled);
fDialogSettings.put(DIALOGSTORE_LINKEDITORS, enabled);
if (enabled) {
IWorkbenchPartSite site= getSite();
if (site != null) {
IEditorPart editor = site.getPage().getActiveEditor();
if (editor != null) {
editorActivated(editor);
}
}
}
}
public void clearNeededRefresh() {
fNeedRefresh= false;
}
/**
* Sets the empty viewer when the user cancels the computation.
*
* @since 3.6
*/
public void showEmptyViewer() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (isDisposed())
return;
clearInput();
setKeepShowingEmptyViewers(true);
}
});
}
/**
* Checks if the type hierarchy view part has been disposed.
*
* @return <code>true</code> if the type hierarchy view part has been disposed, <code>false</code> otherwise
* @since 3.6
*/
private boolean isDisposed() {
return fHierarchyLifeCycle == null;
}
/**
* Returns the type hierarchy life cycle.
*
* @return the type hierarchy life cycle
*
* @since 3.6
*/
public TypeHierarchyLifeCycle getTypeHierarchyLifeCycle() {
return fHierarchyLifeCycle;
}
/**
* Sets the input for all the hierarchy viewers with their respective viewer instances.
*
* @since 3.6
*/
public void setViewersInput() {
for (int i= 0; i < fAllViewers.length; i++) {
fAllViewers[i].setInput(fAllViewers[i]);
}
setKeepShowingEmptyViewers(false);
}
/**
* Sets whether empty viewers should keep showing. If false, replace with fEmptyTypesViewer.
*
* @param keepShowingEmptyViewers <code>true</code> if the empty viewers can be shown,
* <code>false otherwise
*
* @since 3.6
*/
public void setKeepShowingEmptyViewers(boolean keepShowingEmptyViewers) {
fKeepShowingEmptyViewers= keepShowingEmptyViewers;
}
/**
* Returns value that determines whether the empty viewers should keep showing. If false,
* replace with fEmptyTypesViewer.
*
* @return <code>true</code> if the empty viewers can be shown, <code>false otherwise
*
* @since 3.6
*/
public boolean isKeepShowingEmptyViewers() {
return fKeepShowingEmptyViewers;
}
}