blob: 0de3c94fc41539d9203d5e2cb13acda75ceceb57 [file] [log] [blame]
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
package org.eclipse.jdt.internal.ui.typehierarchy;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
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.DragSource;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
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.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.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.util.Assert;
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.jface.viewers.Viewer;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.actions.ActionGroup;
import org.eclipse.ui.actions.OpenWithMenu;
import org.eclipse.ui.help.WorkbenchHelp;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
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.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.IContextMenuConstants;
import org.eclipse.jdt.ui.ITypeHierarchyViewPart;
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.OpenEditorActionGroup;
import org.eclipse.jdt.ui.actions.OpenViewActionGroup;
import org.eclipse.jdt.ui.actions.RefactorActionGroup;
import org.eclipse.jdt.ui.actions.ShowActionGroup;
import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.actions.AddMethodStubAction;
import org.eclipse.jdt.internal.ui.actions.CompositeActionGroup;
import org.eclipse.jdt.internal.ui.dnd.DelegatingDragAdapter;
import org.eclipse.jdt.internal.ui.dnd.DelegatingDropAdapter;
import org.eclipse.jdt.internal.ui.dnd.LocalSelectionTransfer;
import org.eclipse.jdt.internal.ui.dnd.TransferDragSourceListener;
import org.eclipse.jdt.internal.ui.dnd.TransferDropTargetListener;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.packageview.SelectionTransferDragAdapter;
import org.eclipse.jdt.internal.ui.preferences.JavaBasePreferencePage;
import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLabels;
import org.eclipse.jdt.internal.ui.viewsupport.JavaUILabelProvider;
import org.eclipse.jdt.internal.ui.viewsupport.StatusBarUpdater;
/**
* view showing the supertypes/subtypes of its input.
*/
public class TypeHierarchyViewPart extends ViewPart implements ITypeHierarchyViewPart {
public static final int VIEW_ID_TYPE= 2;
public static final int VIEW_ID_SUPER= 0;
public static final int VIEW_ID_SUB= 1;
public static final int VIEW_ORIENTATION_VERTICAL= 0;
public static final int VIEW_ORIENTATION_HORIZONTAL= 1;
public static final int VIEW_ORIENTATION_SINGLE= 2;
private static final String DIALOGSTORE_HIERARCHYVIEW= "TypeHierarchyViewPart.hierarchyview"; //$NON-NLS-1$
private static final String DIALOGSTORE_VIEWORIENTATION= "TypeHierarchyViewPart.orientation"; //$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_ORIENTATION= "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 GROUP_FOCUS= "group.focus"; //$NON-NLS-1$
// the selected type in the hierarchy view
private IType fSelectedType;
// input element or null
private IJavaElement fInputElement;
// history of inut elements. No duplicates
private ArrayList fInputHistory;
private IMemento fMemento;
private TypeHierarchyLifeCycle fHierarchyLifeCycle;
private ITypeHierarchyLifeCycleListener fTypeHierarchyLifeCycleListener;
private MethodsViewer fMethodsViewer;
private int fCurrentViewerIndex;
private TypeHierarchyViewer[] fAllViewers;
private SelectionProviderMediator fSelectionProviderMediator;
private ISelectionChangedListener fSelectionChangedListener;
private boolean fIsEnableMemberFilter;
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 IDialogSettings fDialogSettings;
private ToggleViewAction[] fViewActions;
private HistoryDropDownAction fHistoryDropDownAction;
private ToggleOrientationAction[] fToggleOrientationActions;
private int fCurrentOrientation;
private EnableMemberFilterAction fEnableMemberFilterAction;
private AddMethodStubAction fAddStubAction;
private FocusOnTypeAction fFocusOnTypeAction;
private FocusOnSelectionAction fFocusOnSelectionAction;
private IPartListener fPartListener;
private CompositeActionGroup fActionGroups;
private CCPActionGroup fCCPActionGroup;
public TypeHierarchyViewPart() {
fSelectedType= null;
fInputElement= null;
fHierarchyLifeCycle= new TypeHierarchyLifeCycle();
fHierarchyLifeCycle.setReconciled(JavaBasePreferencePage.reconcileJavaViews());
fTypeHierarchyLifeCycleListener= new ITypeHierarchyLifeCycleListener() {
public void typeHierarchyChanged(TypeHierarchyLifeCycle typeHierarchy, IType[] changedTypes) {
doTypeHierarchyChanged(typeHierarchy, changedTypes);
}
};
fHierarchyLifeCycle.addChangedListener(fTypeHierarchyLifeCycleListener);
fIsEnableMemberFilter= false;
fInputHistory= new ArrayList();
fAllViewers= null;
fViewActions= new ToggleViewAction[] {
new ToggleViewAction(this, VIEW_ID_TYPE),
new ToggleViewAction(this, VIEW_ID_SUPER),
new ToggleViewAction(this, VIEW_ID_SUB)
};
fDialogSettings= JavaPlugin.getDefault().getDialogSettings();
fHistoryDropDownAction= new HistoryDropDownAction(this);
fHistoryDropDownAction.setEnabled(false);
fToggleOrientationActions= new ToggleOrientationAction[] {
new ToggleOrientationAction(this, VIEW_ORIENTATION_VERTICAL),
new ToggleOrientationAction(this, VIEW_ORIENTATION_HORIZONTAL),
new ToggleOrientationAction(this, VIEW_ORIENTATION_SINGLE)
};
fEnableMemberFilterAction= new EnableMemberFilterAction(this, false);
fFocusOnTypeAction= new FocusOnTypeAction(this);
fPaneLabelProvider= new JavaUILabelProvider();
fAddStubAction= new AddMethodStubAction();
fFocusOnSelectionAction= new FocusOnSelectionAction(this);
fPartListener= new IPartListener() {
public void partActivated(IWorkbenchPart part) {
if (part instanceof IEditorPart)
editorActivated((IEditorPart) part);
}
public void partBroughtToTop(IWorkbenchPart part) {}
public void partClosed(IWorkbenchPart part) {}
public void partDeactivated(IWorkbenchPart part) {}
public void partOpened(IWorkbenchPart part) {}
};
fSelectionChangedListener= new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
doSelectionChanged(event);
}
};
}
/**
* Adds the entry if new. Inserted at the beginning of the history entries list.
*/
private void addHistoryEntry(IJavaElement entry) {
if (fInputHistory.contains(entry)) {
fInputHistory.remove(entry);
}
fInputHistory.add(0, entry);
fHistoryDropDownAction.setEnabled(true);
}
private void updateHistoryEntries() {
for (int i= fInputHistory.size() - 1; i >= 0; i--) {
IJavaElement type= (IJavaElement) fInputHistory.get(i);
if (!type.exists()) {
fInputHistory.remove(i);
}
}
fHistoryDropDownAction.setEnabled(!fInputHistory.isEmpty());
}
/**
* Goes to the selected entry, without updating the order of history entries.
*/
public void gotoHistoryEntry(IJavaElement entry) {
if (fInputHistory.contains(entry)) {
updateInput(entry);
}
}
/**
* Gets all history entries.
*/
public IJavaElement[] getHistoryEntries() {
if (fInputHistory.size() > 0) {
updateHistoryEntries();
}
return (IJavaElement[]) fInputHistory.toArray(new IJavaElement[fInputHistory.size()]);
}
/**
* Sets the history entries
*/
public void setHistoryEntries(IJavaElement[] elems) {
fInputHistory.clear();
for (int i= 0; i < elems.length; i++) {
fInputHistory.add(elems[i]);
}
updateHistoryEntries();
}
/**
* Selects an member in the methods list or in the current hierarchy.
*/
public void selectMember(IMember member) {
ICompilationUnit cu= member.getCompilationUnit();
if (cu != null && cu.isWorkingCopy()) {
member= (IMember) cu.getOriginal(member);
if (member == null) {
return;
}
}
if (member.getElementType() != IJavaElement.TYPE) {
if (fHierarchyLifeCycle.isReconciled() && cu != null) {
try {
member= (IMember) EditorUtility.getWorkingCopy(member);
if (member == null) {
return;
}
} catch (JavaModelException e) {
JavaPlugin.log(e);
return;
}
}
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();
}
getCurrentViewer().setSelection(new StructuredSelection(member), true);
}
}
/**
* @deprecated
*/
public IType getInput() {
if (fInputElement instanceof IType) {
return (IType) fInputElement;
}
return null;
}
/**
* Sets the input to a new type
* @deprecated
*/
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>
*/
public IJavaElement getInputElement() {
return fInputElement;
}
/**
* Sets the input to a new element.
*/
public void setInputElement(IJavaElement element) {
if (element != null) {
if (element instanceof IMember) {
if (element.getElementType() != IJavaElement.TYPE) {
element= ((IMember) element).getDeclaringType();
}
ICompilationUnit cu= ((IMember) element).getCompilationUnit();
if (cu != null && cu.isWorkingCopy()) {
element= cu.getOriginal(element);
if (!element.exists()) {
MessageDialog.openError(getSite().getShell(), TypeHierarchyMessages.getString("TypeHierarchyViewPart.error.title"), TypeHierarchyMessages.getString("TypeHierarchyViewPart.error.message")); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
}
} else {
int kind= element.getElementType();
if (kind != IJavaElement.JAVA_PROJECT && kind != IJavaElement.PACKAGE_FRAGMENT_ROOT && kind != IJavaElement.PACKAGE_FRAGMENT) {
element= null;
JavaPlugin.logErrorMessage("Invalid type hierarchy input type.");//$NON-NLS-1$
}
}
}
if (element != null && !element.equals(fInputElement)) {
addHistoryEntry(element);
}
updateInput(element);
}
/**
* Changes the input to a new type
*/
private void updateInput(IJavaElement inputElement) {
IJavaElement prevInput= fInputElement;
fInputElement= inputElement;
if (fInputElement == null) {
clearInput();
} else {
try {
fHierarchyLifeCycle.ensureRefreshedTypeHierarchy(fInputElement, new BusyIndicatorRunnableContext());
} catch (JavaModelException e) {
JavaPlugin.log(e);
clearInput();
return;
}
fPagebook.showPage(fTypeMethodsSplitter);
if (inputElement.getElementType() != IJavaElement.TYPE) {
setView(VIEW_ID_TYPE);
}
// turn off member filtering
setMemberFilter(null);
fIsEnableMemberFilter= false;
if (!fInputElement.equals(prevInput)) {
updateHierarchyViewer();
}
IType root= getSelectableType(fInputElement);
internalSelectType(root, true);
updateMethodViewer(root);
updateToolbarButtons();
updateTitle();
enableMemberFilter(false);
}
}
private void clearInput() {
fInputElement= null;
fHierarchyLifeCycle.freeHierarchy();
updateHierarchyViewer();
updateToolbarButtons();
}
/*
* @see IWorbenchPart#setFocus
*/
public void setFocus() {
fPagebook.setFocus();
}
/*
* @see IWorkbenchPart#dispose
*/
public void dispose() {
fHierarchyLifeCycle.freeHierarchy();
fHierarchyLifeCycle.removeChangedListener(fTypeHierarchyLifeCycleListener);
fPaneLabelProvider.dispose();
getSite().getPage().removePartListener(fPartListener);
if (fActionGroups != null)
fActionGroups.dispose();
super.dispose();
}
private Control createTypeViewerControl(Composite parent) {
fViewerbook= new PageBook(parent, SWT.NULL);
KeyListener keyListener= createKeyListener();
// Create the viewers
TypeHierarchyViewer superTypesViewer= new SuperTypeHierarchyViewer(fViewerbook, fHierarchyLifeCycle, this);
initializeTypesViewer(superTypesViewer, keyListener, IContextMenuConstants.TARGET_ID_SUPERTYPES_VIEW);
TypeHierarchyViewer subTypesViewer= new SubTypeHierarchyViewer(fViewerbook, fHierarchyLifeCycle, this);
initializeTypesViewer(subTypesViewer, keyListener, IContextMenuConstants.TARGET_ID_SUBTYPES_VIEW);
TypeHierarchyViewer vajViewer= new TraditionalHierarchyViewer(fViewerbook, fHierarchyLifeCycle, this);
initializeTypesViewer(vajViewer, keyListener, IContextMenuConstants.TARGET_ID_HIERARCHY_VIEW);
fAllViewers= new TypeHierarchyViewer[3];
fAllViewers[VIEW_ID_SUPER]= superTypesViewer;
fAllViewers[VIEW_ID_SUB]= subTypesViewer;
fAllViewers[VIEW_ID_TYPE]= vajViewer;
int currViewerIndex;
try {
currViewerIndex= fDialogSettings.getInt(DIALOGSTORE_HIERARCHYVIEW);
if (currViewerIndex < 0 || currViewerIndex > 2) {
currViewerIndex= VIEW_ID_TYPE;
}
} catch (NumberFormatException e) {
currViewerIndex= VIEW_ID_TYPE;
}
fEmptyTypesViewer= new Label(fViewerbook, SWT.LEFT);
for (int i= 0; i < fAllViewers.length; i++) {
fAllViewers[i].setInput(fAllViewers[i]);
}
// force the update
fCurrentViewerIndex= -1;
setView(currViewerIndex);
return fViewerbook;
}
private KeyListener createKeyListener() {
return new KeyAdapter() {
public void keyReleased(KeyEvent event) {
if (event.stateMask == 0) {
if (event.keyCode == SWT.F5) {
updateHierarchyViewer();
return;
} else if (event.character == SWT.DEL){
if (fCCPActionGroup.getDeleteAction().isEnabled())
fCCPActionGroup.getDeleteAction().run();
return;
}
}
viewPartKeyShortcuts(event);
}
};
}
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.addSelectionChangedListener(fSelectionChangedListener);
}
private Control createMethodViewerControl(Composite parent) {
fMethodsViewer= new MethodsViewer(parent, fHierarchyLifeCycle, this);
fMethodsViewer.initContextMenu(new IMenuListener() {
public void menuAboutToShow(IMenuManager menu) {
fillMethodsViewerContextMenu(menu);
}
}, IContextMenuConstants.TARGET_ID_MEMBERS_VIEW, getSite());
fMethodsViewer.addSelectionChangedListener(fSelectionChangedListener);
Control control= fMethodsViewer.getTable();
control.addKeyListener(createKeyListener());
return control;
}
private void initDragAndDrop() {
Transfer[] transfers= new Transfer[] { LocalSelectionTransfer.getInstance() };
int ops= DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
for (int i= 0; i < fAllViewers.length; i++) {
addDragAdapters(fAllViewers[i], ops, transfers);
addDropAdapters(fAllViewers[i], ops | DND.DROP_DEFAULT, transfers);
}
addDragAdapters(fMethodsViewer, ops, transfers);
//dnd on empty hierarchy
DropTarget dropTarget = new DropTarget(fNoHierarchyShownLabel, ops | DND.DROP_DEFAULT);
dropTarget.setTransfer(transfers);
dropTarget.addDropListener(new TypeHierarchyTransferDropAdapter(this, fAllViewers[0]));
}
private void addDropAdapters(AbstractTreeViewer viewer, int ops, Transfer[] transfers){
TransferDropTargetListener[] dropListeners= new TransferDropTargetListener[] {
new TypeHierarchyTransferDropAdapter(this, viewer)
};
viewer.addDropSupport(ops, transfers, new DelegatingDropAdapter(dropListeners));
}
private void addDragAdapters(StructuredViewer viewer, int ops, Transfer[] transfers){
Control control= viewer.getControl();
TransferDragSourceListener[] dragListeners= new TransferDragSourceListener[] {
new SelectionTransferDragAdapter(viewer)
};
DragSource source= new DragSource(control, ops);
// Note, that the transfer agents are set by the delegating drag adapter itself.
source.addDragListener(new DelegatingDragAdapter(dragListeners));
}
private void viewPartKeyShortcuts(KeyEvent event) {
if (event.stateMask == SWT.CTRL) {
if (event.character == '1') {
setView(VIEW_ID_TYPE);
} else if (event.character == '2') {
setView(VIEW_ID_SUPER);
} else if (event.character == '3') {
setView(VIEW_ID_SUB);
}
}
}
/**
* Returns the inner component in a workbench part.
* @see IWorkbenchPart#createPartControl
*/
public void createPartControl(Composite container) {
fPagebook= new PageBook(container, SWT.NONE);
// page 1 of pagebook (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);
// page 2 of pagebook (no hierarchy label)
fNoHierarchyShownLabel= new Label(fPagebook, SWT.TOP + SWT.LEFT + SWT.WRAP);
fNoHierarchyShownLabel.setText(TypeHierarchyMessages.getString("TypeHierarchyViewPart.empty")); //$NON-NLS-1$
MenuManager menu= new MenuManager();
menu.add(fFocusOnTypeAction);
fNoHierarchyShownLabel.setMenu(menu.createContextMenu(fNoHierarchyShownLabel));
fPagebook.showPage(fNoHierarchyShownLabel);
int orientation;
try {
orientation= fDialogSettings.getInt(DIALOGSTORE_VIEWORIENTATION);
if (orientation < 0 || orientation > 2) {
orientation= VIEW_ORIENTATION_VERTICAL;
}
} catch (NumberFormatException e) {
orientation= VIEW_ORIENTATION_VERTICAL;
}
// force the update
fCurrentOrientation= -1;
// will fill the main tool bar
setOrientation(orientation);
// set the filter menu items
IActionBars actionBars= getViewSite().getActionBars();
IMenuManager viewMenu= actionBars.getMenuManager();
for (int i= 0; i < fToggleOrientationActions.length; i++) {
viewMenu.add(fToggleOrientationActions[i]);
}
viewMenu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
// fill the method viewer toolbar
ToolBarManager lowertbmanager= new ToolBarManager(methodViewerToolBar);
lowertbmanager.add(fEnableMemberFilterAction);
lowertbmanager.add(new Separator());
fMethodsViewer.contributeToToolBar(lowertbmanager);
lowertbmanager.update(true);
// selection provider
int nHierarchyViewers= fAllViewers.length;
Viewer[] trackedViewers= new Viewer[nHierarchyViewers + 1];
for (int i= 0; i < nHierarchyViewers; i++) {
trackedViewers[i]= fAllViewers[i];
}
trackedViewers[nHierarchyViewers]= fMethodsViewer;
fSelectionProviderMediator= new SelectionProviderMediator(trackedViewers);
IStatusLineManager slManager= getViewSite().getActionBars().getStatusLineManager();
fSelectionProviderMediator.addSelectionChangedListener(new StatusBarUpdater(slManager));
getSite().setSelectionProvider(fSelectionProviderMediator);
getSite().getPage().addPartListener(fPartListener);
IJavaElement input= determineInputElement();
if (fMemento != null) {
restoreState(fMemento, input);
} else if (input != null) {
setInputElement(input);
} else {
setViewerVisibility(false);
}
WorkbenchHelp.setHelp(fPagebook, IJavaHelpContextIds.TYPE_HIERARCHY_VIEW);
fActionGroups= new CompositeActionGroup(new ActionGroup[] {
new OpenEditorActionGroup(this),
new OpenViewActionGroup(this),
new ShowActionGroup(this),
fCCPActionGroup= new CCPActionGroup(this),
new RefactorActionGroup(this),
new GenerateActionGroup(this),
new JavaSearchActionGroup(this)});
fActionGroups.fillActionBars(getViewSite().getActionBars());
initDragAndDrop();
}
/**
* called from ToggleOrientationAction.
* @param orientation VIEW_ORIENTATION_SINGLE, VIEW_ORIENTATION_HORIZONTAL or VIEW_ORIENTATION_VERTICAL
*/
public void setOrientation(int orientation) {
if (fCurrentOrientation != orientation) {
boolean methodViewerNeedsUpdate= false;
if (fMethodViewerViewForm != null && !fMethodViewerViewForm.isDisposed()
&& fTypeMethodsSplitter != null && !fTypeMethodsSplitter.isDisposed()) {
if (orientation == VIEW_ORIENTATION_SINGLE) {
fMethodViewerViewForm.setVisible(false);
enableMemberFilter(false);
updateMethodViewer(null);
} else {
if (fCurrentOrientation == VIEW_ORIENTATION_SINGLE) {
fMethodViewerViewForm.setVisible(true);
methodViewerNeedsUpdate= true;
}
boolean horizontal= orientation == VIEW_ORIENTATION_HORIZONTAL;
fTypeMethodsSplitter.setOrientation(horizontal ? SWT.HORIZONTAL : SWT.VERTICAL);
}
updateMainToolbar(orientation);
fTypeMethodsSplitter.layout();
}
for (int i= 0; i < fToggleOrientationActions.length; i++) {
fToggleOrientationActions[i].setChecked(orientation == fToggleOrientationActions[i].getOrientation());
}
fCurrentOrientation= orientation;
if (methodViewerNeedsUpdate) {
updateMethodViewer(fSelectedType);
}
fDialogSettings.put(DIALOGSTORE_VIEWORIENTATION, orientation);
}
}
private void updateMainToolbar(int orientation) {
IActionBars actionBars= getViewSite().getActionBars();
IToolBarManager tbmanager= actionBars.getToolBarManager();
if (orientation == VIEW_ORIENTATION_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();
tbmanager.add(fHistoryDropDownAction);
for (int i= 0; i < fViewActions.length; i++) {
tbmanager.add(fViewActions[i]);
}
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);
// IStructuredSelection selection= (IStructuredSelection)viewer.getSelection();
// if (JavaBasePreferencePage.openTypeHierarchyInPerspective()) {
// addOpenPerspectiveItem(menu, selection);
// }
// addOpenWithMenu(menu, selection);
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);
//
// ContextMenuGroup.add(menu, new ContextMenuGroup[] { new BuildGroup(this, false)}, viewer);
//
// // XXX workaround until we have fully converted the code to use the new action groups
// fActionGroups.get(2).fillContextMenu(menu);
// fActionGroups.get(3).fillContextMenu(menu);
// fActionGroups.get(4).fillContextMenu(menu);
}
/**
* Creates the context menu for the method viewer
*/
private void fillMethodsViewerContextMenu(IMenuManager menu) {
JavaPlugin.createStandardGroups(menu);
// viewer entries
fMethodsViewer.contributeToContextMenu(menu);
if (fSelectedType != null && fAddStubAction.init(fSelectedType, fMethodsViewer.getSelection())) {
menu.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, fAddStubAction);
}
fActionGroups.setContext(new ActionContext(getSite().getSelectionProvider().getSelection()));
fActionGroups.fillContextMenu(menu);
fActionGroups.setContext(null);
// //menu.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, new JavaReplaceWithEditionAction(fMethodsViewer));
// addOpenWithMenu(menu, (IStructuredSelection)fMethodsViewer.getSelection());
// ContextMenuGroup.add(menu, new ContextMenuGroup[] { new BuildGroup(this, false)}, fMethodsViewer);
//
// // XXX workaround until we have fully converted the code to use the new action groups
// fActionGroups.get(2).fillContextMenu(menu);
// fActionGroups.get(3).fillContextMenu(menu);
// fActionGroups.get(4).fillContextMenu(menu);
}
private void addOpenWithMenu(IMenuManager menu, IStructuredSelection selection) {
// If one file is selected get it.
// Otherwise, do not show the "open with" menu.
if (selection.size() != 1)
return;
Object element= selection.getFirstElement();
if (!(element instanceof IJavaElement))
return;
IResource resource= null;
try {
resource= ((IJavaElement)element).getUnderlyingResource();
} catch(JavaModelException e) {
// ignore
}
if (!(resource instanceof IFile))
return;
// Create a menu flyout.
MenuManager submenu= new MenuManager(TypeHierarchyMessages.getString("TypeHierarchyViewPart.menu.open")); //$NON-NLS-1$
submenu.add(new OpenWithMenu(getSite().getPage(), (IFile) resource));
// Add the submenu.
menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, submenu);
}
/**
* 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) {
ISelection sel= null;
if (elem.getElementType() != IJavaElement.TYPE) {
return (IType) getCurrentViewer().getTreeRootType();
} else {
return (IType) elem;
}
}
private void internalSelectType(IMember elem, boolean reveal) {
TypeHierarchyViewer viewer= getCurrentViewer();
viewer.removeSelectionChangedListener(fSelectionChangedListener);
viewer.setSelection(elem != null ? new StructuredSelection(elem) : StructuredSelection.EMPTY, reveal);
viewer.addSelectionChangedListener(fSelectionChangedListener);
}
private void internalSelectMember(IMember member) {
fMethodsViewer.removeSelectionChangedListener(fSelectionChangedListener);
fMethodsViewer.setSelection(member != null ? new StructuredSelection(member) : StructuredSelection.EMPTY);
fMethodsViewer.addSelectionChangedListener(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() {
if (fInputElement == null) {
fPagebook.showPage(fNoHierarchyShownLabel);
} else {
if (getCurrentViewer().containsElements() != null) {
Runnable runnable= new Runnable() {
public void run() {
getCurrentViewer().updateContent(); // refresh
}
};
BusyIndicator.showWhile(getDisplay(), runnable);
if (!isChildVisible(fViewerbook, getCurrentViewer().getControl())) {
setViewerVisibility(true);
}
} else {
fEmptyTypesViewer.setText(TypeHierarchyMessages.getFormattedString("TypeHierarchyViewPart.nodecl", fInputElement.getElementName())); //$NON-NLS-1$
setViewerVisibility(false);
}
}
}
private void updateMethodViewer(IType input) {
if (input != fMethodsViewer.getInput() && !fIsEnableMemberFilter && fCurrentOrientation != VIEW_ORIENTATION_SINGLE) {
if (input != null) {
fMethodViewerPaneLabel.setText(fPaneLabelProvider.getText(input));
fMethodViewerPaneLabel.setImage(fPaneLabelProvider.getImage(input));
} else {
fMethodViewerPaneLabel.setText(""); //$NON-NLS-1$
fMethodViewerPaneLabel.setImage(null);
}
fMethodsViewer.setInput(input);
}
}
private 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();
updateTitle();
internalSelectType(fSelectedType, true);
}
if (nSelected == 1) {
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) {
revealElementInEditor(selected.get(0), getCurrentViewer());
}
} else {
fSelectedType= null;
updateMethodViewer(null);
}
}
}
private void revealElementInEditor(Object elem, Viewer originViewer) {
// only allow revealing when the type hierarchy is the active pagae
// 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)) {
try {
getSite().getPage().removePartListener(fPartListener);
EditorUtility.openInEditor(elem, false);
EditorUtility.revealInEditor(editorPart, (IJavaElement) elem);
getSite().getPage().addPartListener(fPartListener);
} catch (CoreException e) {
JavaPlugin.log(e);
}
}
}
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 updateTitle() {
String viewerTitle= getCurrentViewer().getTitle();
String tooltip;
String title;
if (fInputElement != null) {
String[] args= new String[] { viewerTitle, JavaElementLabels.getElementLabel(fInputElement, JavaElementLabels.ALL_DEFAULT) };
title= TypeHierarchyMessages.getFormattedString("TypeHierarchyViewPart.title", args); //$NON-NLS-1$
tooltip= TypeHierarchyMessages.getFormattedString("TypeHierarchyViewPart.tooltip", args); //$NON-NLS-1$
} else {
title= viewerTitle;
tooltip= viewerTitle;
}
setTitle(title);
setTitleToolTip(tooltip);
}
private void updateToolbarButtons() {
boolean isType= fInputElement instanceof IType;
for (int i= 0; i < fViewActions.length; i++) {
ToggleViewAction action= fViewActions[i];
if (action.getViewerIndex() == VIEW_ID_TYPE) {
action.setEnabled(fInputElement != null);
} else {
action.setEnabled(isType);
}
}
}
/**
* Sets the current view (see view id)
* called from ToggleViewAction. Must be called after creation of the viewpart.
*/
public void setView(int viewerIndex) {
Assert.isNotNull(fAllViewers);
if (viewerIndex < fAllViewers.length && fCurrentViewerIndex != viewerIndex) {
fCurrentViewerIndex= viewerIndex;
updateHierarchyViewer();
if (fInputElement != null) {
ISelection currSelection= getCurrentViewer().getSelection();
if (currSelection == null || currSelection.isEmpty()) {
internalSelectType(getSelectableType(fInputElement), false);
currSelection= getCurrentViewer().getSelection();
}
if (!fIsEnableMemberFilter) {
typeSelectionChanged(currSelection);
}
}
updateTitle();
fDialogSettings.put(DIALOGSTORE_HIERARCHYVIEW, viewerIndex);
getCurrentViewer().getTree().setFocus();
}
for (int i= 0; i < fViewActions.length; i++) {
ToggleViewAction action= fViewActions[i];
action.setChecked(fCurrentViewerIndex == action.getViewerIndex());
}
}
/**
* Gets the curret active view index.
*/
public int getViewIndex() {
return fCurrentViewerIndex;
}
private TypeHierarchyViewer getCurrentViewer() {
return fAllViewers[fCurrentViewerIndex];
}
/**
* called from EnableMemberFilterAction.
* Must be called after creation of the viewpart.
*/
public void enableMemberFilter(boolean on) {
if (on != fIsEnableMemberFilter) {
fIsEnableMemberFilter= on;
if (!on) {
IType methodViewerInput= (IType) fMethodsViewer.getInput();
setMemberFilter(null);
updateHierarchyViewer();
updateTitle();
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);
}
/**
* Called from ITypeHierarchyLifeCycleListener.
* Can be called from any thread
*/
private void doTypeHierarchyChanged(final TypeHierarchyLifeCycle typeHierarchy, final IType[] changedTypes) {
Display display= getDisplay();
if (display != null) {
display.asyncExec(new Runnable() {
public void run() {
if (fPagebook != null && !fPagebook.isDisposed()) {
doTypeHierarchyChangedOnViewers(changedTypes);
}
}
});
}
}
private void doTypeHierarchyChangedOnViewers(IType[] changedTypes) {
if (fHierarchyLifeCycle.getHierarchy() == null || !fHierarchyLifeCycle.getHierarchy().exists()) {
clearInput();
} else {
if (changedTypes == null) {
// hierarchy change
try {
fHierarchyLifeCycle.ensureRefreshedTypeHierarchy(fInputElement, new BusyIndicatorRunnableContext());
} catch (JavaModelException e) {
JavaPlugin.log(e.getStatus());
clearInput();
return;
}
updateHierarchyViewer();
} else {
// elements in hierarchy modified
if (getCurrentViewer().isMethodFiltering()) {
if (changedTypes.length == 1) {
getCurrentViewer().refresh(changedTypes[0]);
} else {
updateHierarchyViewer();
}
} else {
getCurrentViewer().update(changedTypes, new String[] { IBasicPropertyConstants.P_TEXT, IBasicPropertyConstants.P_IMAGE } );
}
}
fMethodsViewer.refresh();
}
}
/**
* Determines the input element to be used initially .
*/
private IJavaElement determineInputElement() {
Object input= getSite().getPage().getInput();
if (input instanceof IJavaElement) {
IJavaElement elem= (IJavaElement) input;
if (elem instanceof IMember) {
return elem;
} else {
int kind= elem.getElementType();
if (kind == IJavaElement.JAVA_PROJECT || kind == IJavaElement.PACKAGE_FRAGMENT_ROOT || kind == IJavaElement.PACKAGE_FRAGMENT) {
return elem;
}
}
}
return null;
}
/*
* @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 (fInputElement != null) {
String handleIndentifier= fInputElement.getHandleIdentifier();
if (fInputElement instanceof IType) {
ITypeHierarchy hierarchy= fHierarchyLifeCycle.getHierarchy();
if (hierarchy != null && hierarchy.getSubtypes((IType) fInputElement).length > 1000) {
// for startup performance reasons do not try to recover huge hierarchies
handleIndentifier= null;
}
}
memento.putString(TAG_INPUT, handleIndentifier);
}
memento.putInteger(TAG_VIEW, getViewIndex());
memento.putInteger(TAG_ORIENTATION, fCurrentOrientation);
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());
}
fMethodsViewer.saveState(memento);
}
/**
* Restores the type hierarchy settings from a memento.
*/
private void restoreState(IMemento memento, IJavaElement defaultInput) {
IJavaElement input= defaultInput;
String elementId= memento.getString(TAG_INPUT);
if (elementId != null) {
input= JavaCore.create(elementId);
if (input != null && !input.exists()) {
input= null;
}
}
setInputElement(input);
Integer viewerIndex= memento.getInteger(TAG_VIEW);
if (viewerIndex != null) {
setView(viewerIndex.intValue());
}
Integer orientation= memento.getInteger(TAG_ORIENTATION);
if (orientation != null) {
setOrientation(orientation.intValue());
}
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());
}
}
String selectionId= memento.getString(TAG_SELECTION);
// do not restore type hierarchy contents
// if (selectionId != null) {
// IJavaElement elem= JavaCore.create(selectionId);
// if (getCurrentViewer().isElementShown(elem) && elem instanceof IMember) {
// internalSelectType((IMember)elem, false);
// }
// }
fMethodsViewer.restoreState(memento);
}
/**
* Link selection to active editor.
*/
private void editorActivated(IEditorPart editor) {
if (!JavaBasePreferencePage.linkTypeHierarchySelectionToEditor()) {
return;
}
if (fInputElement == null) {
// no type hierarchy shown
return;
}
IJavaElement elem= (IJavaElement)editor.getEditorInput().getAdapter(IJavaElement.class);
try {
TypeHierarchyViewer currentViewer= getCurrentViewer();
if (elem instanceof IClassFile) {
IType type= ((IClassFile)elem).getType();
if (currentViewer.isElementShown(type)) {
internalSelectType(type, true);
updateMethodViewer(type);
}
} else if (elem instanceof ICompilationUnit) {
IType[] allTypes= ((ICompilationUnit)elem).getAllTypes();
for (int i= 0; i < allTypes.length; i++) {
if (currentViewer.isElementShown(allTypes[i])) {
internalSelectType(allTypes[i], true);
updateMethodViewer(allTypes[i]);
return;
}
}
}
} catch (JavaModelException e) {
JavaPlugin.log(e.getStatus());
}
}
}