| /******************************************************************************* |
| * Copyright (c) 2000, 2019 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation |
| * (report 36180: Callers/Callees view) |
| * Michael Fraenkel (fraenkel@us.ibm.com) - patch |
| * (report 60714: Call Hierarchy: display search scope in view title) |
| * Stephan Herrmann (stephan@cs.tu-berlin.de): |
| * - bug 75800: [call hierarchy] should allow searches for fields |
| * Stephan Herrmann (stephan@cs.tu-berlin.de): |
| * - bug 206949: [call hierarchy] filter field accesses (only write or only read) |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.ui.callhierarchy; |
| |
| 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.SashForm; |
| import org.eclipse.swt.dnd.Clipboard; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.DragSourceEvent; |
| import org.eclipse.swt.dnd.DropTarget; |
| 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.graphics.Point; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.TreeItem; |
| |
| import org.eclipse.core.runtime.Assert; |
| |
| 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.dialogs.IDialogSettings; |
| import org.eclipse.jface.util.DelegatingDragAdapter; |
| import org.eclipse.jface.util.DelegatingDropAdapter; |
| import org.eclipse.jface.util.LocalSelectionTransfer; |
| import org.eclipse.jface.util.OpenStrategy; |
| 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.jface.viewers.ViewerComparator; |
| |
| import org.eclipse.ui.IActionBars; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IMemento; |
| import org.eclipse.ui.IPartListener2; |
| import org.eclipse.ui.IViewReference; |
| import org.eclipse.ui.IViewSite; |
| import org.eclipse.ui.IWorkbenchCommandConstants; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPartReference; |
| import org.eclipse.ui.IWorkbenchPartSite; |
| 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.navigator.ICommonMenuConstants; |
| 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.progress.IWorkbenchSiteProgressService; |
| |
| import org.eclipse.ui.texteditor.ITextEditor; |
| |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IMember; |
| import org.eclipse.jdt.core.search.IJavaSearchConstants; |
| import org.eclipse.jdt.core.search.IJavaSearchScope; |
| |
| import org.eclipse.jdt.internal.corext.callhierarchy.CallHierarchy; |
| import org.eclipse.jdt.internal.corext.callhierarchy.CallLocation; |
| import org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper; |
| import org.eclipse.jdt.internal.corext.callhierarchy.RealCallers; |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| |
| import org.eclipse.jdt.ui.IContextMenuConstants; |
| import org.eclipse.jdt.ui.JavaElementLabels; |
| import org.eclipse.jdt.ui.JavaUI; |
| 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.internal.ui.IJavaHelpContextIds; |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.actions.CompositeActionGroup; |
| import org.eclipse.jdt.internal.ui.dnd.EditorInputTransferDragAdapter; |
| 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.util.JavaUIHelp; |
| import org.eclipse.jdt.internal.ui.util.SelectionUtil; |
| import org.eclipse.jdt.internal.ui.viewsupport.SelectionProviderMediator; |
| import org.eclipse.jdt.internal.ui.viewsupport.StatusBarUpdater; |
| |
| |
| /** |
| * This is the main view for the callers plugin. It builds a tree of callers/callees |
| * and allows the user to double click an entry to go to the selected method. |
| * |
| */ |
| public class CallHierarchyViewPart extends ViewPart implements ICallHierarchyViewPart, ISelectionChangedListener { |
| |
| |
| private class CallHierarchySelectionProvider extends SelectionProviderMediator { |
| |
| public CallHierarchySelectionProvider(StructuredViewer[] viewers) { |
| super(viewers, null); |
| } |
| |
| @Override |
| public ISelection getSelection() { |
| ISelection selection= super.getSelection(); |
| if (!selection.isEmpty()) { |
| return CallHierarchyUI.convertSelection(selection); |
| } |
| return selection; |
| } |
| } |
| |
| |
| /* |
| * @since 3.5 |
| */ |
| private final class CallHierarchyOpenEditorHelper extends OpenAndLinkWithEditorHelper { |
| public CallHierarchyOpenEditorHelper(StructuredViewer viewer) { |
| super(viewer); |
| } |
| |
| @Override |
| protected void activate(ISelection selection) { |
| final Object selectedElement= SelectionUtil.getSingleElement(selection); |
| if (selectedElement != null) |
| CallHierarchyUI.openInEditor(selectedElement, getSite().getShell(), true); |
| } |
| |
| @Override |
| protected void linkToEditor(ISelection selection) { |
| // not supported by this part |
| } |
| |
| @Override |
| protected void open(ISelection selection, boolean activate) { |
| if (selection instanceof IStructuredSelection) { |
| for (Iterator<?> iter= ((IStructuredSelection)selection).iterator(); iter.hasNext();) { |
| boolean noError= CallHierarchyUI.openInEditor(iter.next(), getSite().getShell(), OpenStrategy.activateOnOpen()); |
| if (!noError) |
| return; |
| } |
| } |
| } |
| |
| } |
| |
| |
| private static final String DIALOGSTORE_VIEWORIENTATION = "CallHierarchyViewPart.orientation"; //$NON-NLS-1$ |
| private static final String DIALOGSTORE_CALL_MODE = "CallHierarchyViewPart.call_mode"; //$NON-NLS-1$ |
| private static final String DIALOGSTORE_FIELD_MODE = "CallHierarchyViewPart.field_mode"; //$NON-NLS-1$ |
| /** |
| * The key to be used is <code>DIALOGSTORE_RATIO + fCurrentOrientation</code>. |
| */ |
| private static final String DIALOGSTORE_RATIO= "CallHierarchyViewPart.ratio"; //$NON-NLS-1$ |
| |
| static final int VIEW_ORIENTATION_VERTICAL = 0; |
| static final int VIEW_ORIENTATION_HORIZONTAL = 1; |
| static final int VIEW_ORIENTATION_SINGLE = 2; |
| static final int VIEW_ORIENTATION_AUTOMATIC = 3; |
| static final int CALL_MODE_CALLERS = 0; |
| static final int CALL_MODE_CALLEES = 1; |
| static final String GROUP_SEARCH_SCOPE = "MENU_SEARCH_SCOPE"; //$NON-NLS-1$ |
| static final String ID_CALL_HIERARCHY = "org.eclipse.jdt.callhierarchy.view"; //$NON-NLS-1$ |
| |
| private static final String GROUP_FOCUS = "group.focus"; //$NON-NLS-1$ |
| private static final int PAGE_EMPTY = 0; |
| private static final int PAGE_VIEWER = 1; |
| private Label fNoHierarchyShownLabel; |
| private PageBook fPagebook; |
| private final IDialogSettings fDialogSettings; |
| private int fCurrentOrientation; |
| int fOrientation= VIEW_ORIENTATION_AUTOMATIC; |
| private int fCurrentCallMode; |
| private int fCurrentFieldMode; |
| private MethodWrapper[] fCalleeRoots; |
| private MethodWrapper[] fCallerRoots; |
| private IMemento fMemento; |
| private IMember[] fInputElements; |
| private CallHierarchySelectionProvider fSelectionProviderMediator; |
| private LocationViewer fLocationViewer; |
| private SashForm fHierarchyLocationSplitter; |
| private Clipboard fClipboard; |
| private SearchScopeActionGroup fSearchScopeActions; |
| private ToggleOrientationAction[] fToggleOrientationActions; |
| private ToggleCallModeAction[] fToggleCallModeActions; |
| private SelectFieldModeAction[] fToggleFieldModeActions; |
| private CallHierarchyFiltersActionGroup fFiltersActionGroup; |
| private HistoryDropDownAction fHistoryDropDownAction; |
| private RefreshElementAction fRefreshSingleElementAction; |
| private RefreshViewAction fRefreshViewAction; |
| private OpenLocationAction fOpenLocationAction; |
| private LocationCopyAction fLocationCopyAction; |
| private FocusOnSelectionAction fFocusOnSelectionAction; |
| private CopyCallHierarchyAction fCopyAction; |
| private CancelSearchAction fCancelSearchAction; |
| private ExpandWithConstructorsAction fExpandWithConstructorsAction; |
| private RemoveFromViewAction fRemoveFromViewAction; |
| private ShowSearchInDialogAction fShowSearchInDialogAction; |
| private CompositeActionGroup fActionGroups; |
| private CallHierarchyViewer fCallHierarchyViewer; |
| private boolean fShowCallDetails; |
| protected Composite fParent; |
| private IPartListener2 fPartListener; |
| private boolean fIsPinned; |
| private PinCallHierarchyViewAction fPinViewAction; |
| |
| |
| public CallHierarchyViewPart() { |
| super(); |
| |
| fDialogSettings = JavaPlugin.getDefault().getDialogSettings(); |
| |
| fIsPinned= false; |
| } |
| |
| @Override |
| public void setFocus() { |
| fPagebook.setFocus(); |
| } |
| |
| /** |
| * Sets the history entries |
| * @param entries the new history entries |
| */ |
| public void setHistoryEntries(IMember[][] entries) { |
| getMethodHistory().clear(); |
| |
| for (int i = 0; i < entries.length; i++) { |
| getMethodHistory().add(entries[i]); |
| } |
| |
| updateHistoryEntries(); |
| } |
| |
| /** |
| * Gets all history entries. |
| * @return all history entries |
| */ |
| public IMember[][] getHistoryEntries() { |
| if (getMethodHistory().size() > 0) { |
| updateHistoryEntries(); |
| } |
| |
| return getMethodHistory().toArray(new IMember[getMethodHistory().size()][]); |
| } |
| |
| public void setInputElements(IMember[] members) { |
| IMember[] oldMembers= fInputElements; |
| fInputElements= members; |
| |
| if (members == null || members.length == 0) { |
| showPage(PAGE_EMPTY); |
| return; |
| } |
| |
| if (! Arrays.equals(members, oldMembers)) { |
| addHistoryEntry(members); |
| } |
| |
| refresh(); |
| } |
| |
| public IMember[] getInputElements() { |
| return fInputElements; |
| } |
| |
| public MethodWrapper[] getCurrentMethodWrappers() { |
| if (fCurrentCallMode == CALL_MODE_CALLERS) { |
| return fCallerRoots; |
| } else { |
| return fCalleeRoots; |
| } |
| } |
| |
| /** |
| * called from ToggleOrientationAction. |
| * @param orientation VIEW_ORIENTATION_HORIZONTAL or VIEW_ORIENTATION_VERTICAL |
| */ |
| void setOrientation(int orientation) { |
| if (fCurrentOrientation != orientation) { |
| if ((fLocationViewer != null) && !fLocationViewer.getControl().isDisposed() && |
| (fHierarchyLocationSplitter != null) && |
| !fHierarchyLocationSplitter.isDisposed()) { |
| if (orientation == VIEW_ORIENTATION_SINGLE) { |
| setShowCallDetails(false); |
| } else { |
| if (fCurrentOrientation == VIEW_ORIENTATION_SINGLE) { |
| setShowCallDetails(true); |
| } |
| |
| boolean horizontal = orientation == VIEW_ORIENTATION_HORIZONTAL; |
| fHierarchyLocationSplitter.setOrientation(horizontal ? SWT.HORIZONTAL |
| : SWT.VERTICAL); |
| } |
| |
| fHierarchyLocationSplitter.layout(); |
| } |
| |
| updateCheckedState(); |
| |
| fCurrentOrientation = orientation; |
| |
| restoreSplitterRatio(); |
| } |
| } |
| |
| private void updateCheckedState() { |
| for (int i= 0; i < fToggleOrientationActions.length; i++) { |
| fToggleOrientationActions[i].setChecked(fOrientation == fToggleOrientationActions[i].getOrientation()); |
| } |
| } |
| |
| /** |
| * called from ToggleCallModeAction. |
| * @param mode CALL_MODE_CALLERS or CALL_MODE_CALLEES |
| */ |
| void setCallMode(int mode) { |
| if (fCurrentCallMode != mode) { |
| for (int i = 0; i < fToggleCallModeActions.length; i++) { |
| fToggleCallModeActions[i].setChecked(mode == fToggleCallModeActions[i].getMode()); |
| } |
| |
| fCurrentCallMode = mode; |
| fDialogSettings.put(DIALOGSTORE_CALL_MODE, mode); |
| |
| updateView(); |
| } |
| } |
| |
| /** |
| * Returns the current call mode. |
| * |
| * @return the current call mode: CALL_MODE_CALLERS or CALL_MODE_CALLEES |
| * @since 3.5 |
| */ |
| int getCallMode() { |
| return fCurrentCallMode; |
| } |
| |
| |
| /** |
| * called from SelectFieldModeAction. |
| * @param mode IJavaSearchConstants.{REFERENCES,WRITE_ACCESS,READ_ACCESS} |
| */ |
| void setFieldMode(int mode) { |
| if (fCurrentFieldMode != mode) { |
| for (int i = 0; i < fToggleFieldModeActions.length; i++) { |
| fToggleFieldModeActions[i].setChecked(mode == fToggleFieldModeActions[i].getMode()); |
| } |
| |
| fCurrentFieldMode = mode; |
| fDialogSettings.put(DIALOGSTORE_FIELD_MODE, mode); |
| |
| updateView(); |
| } |
| } |
| |
| /** |
| * Fetches the search scope with the appropriate include mask. |
| * |
| * @param includeMask the include mask |
| * @return the search scope with the appropriate include mask |
| * @since 3.7 |
| */ |
| public IJavaSearchScope getSearchScope(int includeMask) { |
| return fSearchScopeActions.getSearchScope(includeMask); |
| } |
| |
| public void setShowCallDetails(boolean show) { |
| fShowCallDetails = show; |
| showOrHideCallDetailsView(); |
| } |
| |
| private void initDragAndDrop() { |
| addDragAdapters(fCallHierarchyViewer); |
| addDropAdapters(fCallHierarchyViewer); |
| addDropAdapters(fLocationViewer); |
| |
| //dnd on empty hierarchy |
| DropTarget dropTarget = new DropTarget(fPagebook, DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_DEFAULT); |
| dropTarget.setTransfer(LocalSelectionTransfer.getTransfer()); |
| dropTarget.addDropListener(new CallHierarchyTransferDropAdapter(this, fCallHierarchyViewer)); |
| } |
| |
| private void addDropAdapters(StructuredViewer viewer) { |
| Transfer[] transfers= new Transfer[] { LocalSelectionTransfer.getTransfer(), PluginTransfer.getInstance() }; |
| int ops= DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_DEFAULT; |
| |
| DelegatingDropAdapter delegatingDropAdapter= new DelegatingDropAdapter(); |
| delegatingDropAdapter.addDropTargetListener(new CallHierarchyTransferDropAdapter(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.getTransfer(), ResourceTransfer.getInstance(), FileTransfer.getInstance()}; |
| |
| DelegatingDragAdapter dragAdapter= new DelegatingDragAdapter() { |
| @Override |
| public void dragStart(DragSourceEvent event) { |
| IStructuredSelection selection= (IStructuredSelection) fSelectionProviderMediator.getSelection(); |
| if (selection.isEmpty()) { |
| event.doit= false; |
| return; |
| } |
| super.dragStart(event); |
| } |
| }; |
| dragAdapter.addDragSourceListener(new SelectionTransferDragAdapter(fSelectionProviderMediator)); |
| dragAdapter.addDragSourceListener(new EditorInputTransferDragAdapter(fSelectionProviderMediator)); |
| dragAdapter.addDragSourceListener(new ResourceTransferDragAdapter(fSelectionProviderMediator)); |
| dragAdapter.addDragSourceListener(new FileTransferDragAdapter(fSelectionProviderMediator)); |
| |
| viewer.addDragSupport(ops, transfers, dragAdapter); |
| } |
| |
| @Override |
| public void createPartControl(Composite parent) { |
| fParent= parent; |
| addResizeListener(parent); |
| fPagebook = new PageBook(parent, SWT.NONE); |
| |
| // Page 1: Viewers |
| createHierarchyLocationSplitter(fPagebook); |
| createCallHierarchyViewer(fHierarchyLocationSplitter); |
| createLocationViewer(fHierarchyLocationSplitter); |
| |
| // Page 2: Nothing selected |
| fNoHierarchyShownLabel = new Label(fPagebook, SWT.TOP + SWT.LEFT + SWT.WRAP); |
| fNoHierarchyShownLabel.setText(CallHierarchyMessages.CallHierarchyViewPart_empty); // |
| |
| showPage(PAGE_EMPTY); |
| |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(fPagebook, IJavaHelpContextIds.CALL_HIERARCHY_VIEW); |
| |
| fSelectionProviderMediator = new CallHierarchySelectionProvider(new StructuredViewer[] { |
| fCallHierarchyViewer, fLocationViewer |
| }); |
| |
| IStatusLineManager slManager = getViewSite().getActionBars().getStatusLineManager(); |
| fSelectionProviderMediator.addSelectionChangedListener(new StatusBarUpdater(slManager)); |
| getSite().setSelectionProvider(fSelectionProviderMediator); |
| |
| fCallHierarchyViewer.initContextMenu( |
| new IMenuListener() { |
| @Override |
| public void menuAboutToShow(IMenuManager menu) { |
| fillCallHierarchyViewerContextMenu(menu); |
| } |
| }, getSite(), fSelectionProviderMediator); |
| |
| |
| fClipboard= new Clipboard(parent.getDisplay()); |
| |
| makeActions(); |
| fillViewMenu(); |
| fillActionBars(); |
| initDragAndDrop(); |
| |
| initOrientation(); |
| initCallMode(); |
| initFieldMode(); |
| |
| if (fMemento != null) { |
| restoreState(fMemento); |
| } |
| restoreSplitterRatio(); |
| addPartListener(); |
| } |
| |
| private void restoreSplitterRatio() { |
| String ratio= fDialogSettings.get(DIALOGSTORE_RATIO + fCurrentOrientation); |
| if (ratio == null) |
| return; |
| int intRatio= Integer.parseInt(ratio); |
| fHierarchyLocationSplitter.setWeights(new int[] {intRatio, 1000 - intRatio}); |
| } |
| |
| private void saveSplitterRatio() { |
| if (fHierarchyLocationSplitter != null && ! fHierarchyLocationSplitter.isDisposed()) { |
| int[] weigths = fHierarchyLocationSplitter.getWeights(); |
| int ratio = (weigths[0] * 1000) / (weigths[0] + weigths[1]); |
| String key= DIALOGSTORE_RATIO + fCurrentOrientation; |
| fDialogSettings.put(key, ratio); |
| } |
| } |
| |
| /** |
| * Tells whether the given part reference references this view. |
| * |
| * @param partRef the workbench part reference |
| * @return <code>true</code> if the given part reference references this view |
| * @since 3.7 |
| */ |
| private boolean isThisView(IWorkbenchPartReference partRef) { |
| if (!ID_CALL_HIERARCHY.equals(partRef.getId())) |
| return false; |
| String partRefSecondaryId= ((IViewReference)partRef).getSecondaryId(); |
| String thisSecondaryId= getViewSite().getSecondaryId(); |
| return thisSecondaryId == null && partRefSecondaryId == null || thisSecondaryId != null && thisSecondaryId.equals(partRefSecondaryId); |
| } |
| |
| private void addPartListener() { |
| fPartListener= new IPartListener2() { |
| @Override |
| public void partActivated(IWorkbenchPartReference partRef) { |
| if (isThisView(partRef)) |
| CallHierarchyUI.getDefault().callHierarchyViewActivated(CallHierarchyViewPart.this); |
| } |
| |
| @Override |
| public void partBroughtToTop(IWorkbenchPartReference partRef) { } |
| |
| @Override |
| public void partClosed(IWorkbenchPartReference partRef) { |
| if (isThisView(partRef)) { |
| CallHierarchyUI.getDefault().callHierarchyViewClosed(CallHierarchyViewPart.this); |
| saveViewSettings(); |
| } |
| } |
| |
| @Override |
| public void partDeactivated(IWorkbenchPartReference partRef) { |
| if (isThisView(partRef)) |
| saveViewSettings(); |
| } |
| |
| @Override |
| public void partOpened(IWorkbenchPartReference partRef) { } |
| @Override |
| public void partHidden(IWorkbenchPartReference partRef) { } |
| @Override |
| public void partVisible(IWorkbenchPartReference partRef) { } |
| @Override |
| public void partInputChanged(IWorkbenchPartReference partRef) { } |
| }; |
| getViewSite().getPage().addPartListener(fPartListener); |
| } |
| |
| protected void saveViewSettings() { |
| saveSplitterRatio(); |
| fDialogSettings.put(DIALOGSTORE_VIEWORIENTATION, fOrientation); |
| } |
| |
| private void addResizeListener(Composite parent) { |
| parent.addControlListener(new ControlListener() { |
| @Override |
| public void controlMoved(ControlEvent e) { |
| } |
| @Override |
| public void controlResized(ControlEvent e) { |
| computeOrientation(); |
| } |
| }); |
| } |
| |
| void computeOrientation() { |
| saveSplitterRatio(); |
| fDialogSettings.put(DIALOGSTORE_VIEWORIENTATION, fOrientation); |
| if (fOrientation != VIEW_ORIENTATION_AUTOMATIC) { |
| setOrientation(fOrientation); |
| } |
| else { |
| if (fOrientation == VIEW_ORIENTATION_SINGLE) |
| return; |
| Point size= fParent.getSize(); |
| if (size.x != 0 && size.y != 0) { |
| if (size.x > size.y) |
| setOrientation(VIEW_ORIENTATION_HORIZONTAL); |
| else |
| setOrientation(VIEW_ORIENTATION_VERTICAL); |
| } |
| } |
| } |
| |
| private void showPage(int page) { |
| boolean isEmpty= page == PAGE_EMPTY; |
| Control control= isEmpty ? (Control) fNoHierarchyShownLabel : fHierarchyLocationSplitter; |
| if (isEmpty) { |
| setContentDescription(""); //$NON-NLS-1$ |
| setTitleToolTip(getPartName()); |
| getViewSite().getActionBars().getStatusLineManager().setMessage(""); //$NON-NLS-1$ |
| getViewer().clearViewer(); |
| } |
| fPagebook.showPage(control); |
| if (fRefreshViewAction != null) |
| fRefreshViewAction.setEnabled(!isEmpty); |
| if (fRefreshSingleElementAction != null) |
| fRefreshSingleElementAction.setEnabled(!isEmpty); |
| } |
| |
| /** |
| * Restores the type hierarchy settings from a memento. |
| * @param memento the memento |
| */ |
| private void restoreState(IMemento memento) { |
| fSearchScopeActions.restoreState(memento); |
| } |
| |
| private void initCallMode() { |
| int mode; |
| |
| try { |
| mode = fDialogSettings.getInt(DIALOGSTORE_CALL_MODE); |
| |
| if ((mode < 0) || (mode > 1)) { |
| mode = CALL_MODE_CALLERS; |
| } |
| } catch (NumberFormatException e) { |
| mode = CALL_MODE_CALLERS; |
| } |
| |
| // force the update |
| fCurrentCallMode = -1; |
| |
| // will fill the main tool bar |
| setCallMode(mode); |
| } |
| |
| private void initFieldMode() { |
| int mode; |
| |
| try { |
| mode = fDialogSettings.getInt(DIALOGSTORE_FIELD_MODE); |
| |
| switch (mode) { |
| case IJavaSearchConstants.REFERENCES: |
| case IJavaSearchConstants.READ_ACCESSES: |
| case IJavaSearchConstants.WRITE_ACCESSES: |
| break; // OK |
| default: |
| mode = IJavaSearchConstants.REFERENCES; |
| } |
| } catch (NumberFormatException e) { |
| mode = IJavaSearchConstants.REFERENCES; |
| } |
| |
| // force the update |
| fCurrentFieldMode = -1; |
| |
| // will fill the main tool bar |
| setFieldMode(mode); |
| } |
| |
| private void initOrientation() { |
| |
| try { |
| fOrientation = fDialogSettings.getInt(DIALOGSTORE_VIEWORIENTATION); |
| |
| if ((fOrientation < 0) || (fOrientation > 3)) { |
| fOrientation = VIEW_ORIENTATION_AUTOMATIC; |
| } |
| } catch (NumberFormatException e) { |
| fOrientation = VIEW_ORIENTATION_AUTOMATIC; |
| } |
| |
| // force the update |
| fCurrentOrientation = -1; |
| setOrientation(fOrientation); |
| } |
| |
| private void fillViewMenu() { |
| IActionBars actionBars = getViewSite().getActionBars(); |
| IMenuManager viewMenu = actionBars.getMenuManager(); |
| viewMenu.add(new Separator()); |
| |
| for (int i = 0; i < fToggleCallModeActions.length; i++) { |
| viewMenu.add(fToggleCallModeActions[i]); |
| } |
| |
| viewMenu.add(new Separator()); |
| |
| MenuManager layoutSubMenu= new MenuManager(CallHierarchyMessages.CallHierarchyViewPart_layout_menu); |
| for (int i = 0; i < fToggleOrientationActions.length; i++) { |
| layoutSubMenu.add(fToggleOrientationActions[i]); |
| } |
| viewMenu.add(layoutSubMenu); |
| |
| viewMenu.add(new Separator(IContextMenuConstants.GROUP_SEARCH)); |
| |
| MenuManager fieldSubMenu= new MenuManager(CallHierarchyMessages.CallHierarchyViewPart_field_menu); |
| for (int i = 0; i < fToggleFieldModeActions.length; i++) { |
| fieldSubMenu.add(fToggleFieldModeActions[i]); |
| } |
| viewMenu.add(fieldSubMenu); |
| viewMenu.add(fShowSearchInDialogAction); |
| } |
| |
| @Override |
| public void dispose() { |
| if (fActionGroups != null) |
| fActionGroups.dispose(); |
| |
| if (fClipboard != null) |
| fClipboard.dispose(); |
| |
| if (fPartListener != null) { |
| getViewSite().getPage().removePartListener(fPartListener); |
| fPartListener= null; |
| } |
| super.dispose(); |
| } |
| |
| /** |
| * Goes to the selected entry, without updating the order of history entries. |
| * @param entry the history entry |
| */ |
| public void gotoHistoryEntry(IMember[] entry) { |
| for (Iterator<IMember[]> iter= getMethodHistory().iterator(); iter.hasNext(); ) { |
| if (Arrays.equals(entry, iter.next())) { |
| setInputElements(entry); |
| return; |
| } |
| } |
| } |
| |
| @Override |
| public void init(IViewSite site, IMemento memento) |
| throws PartInitException { |
| super.init(site, memento); |
| fMemento = memento; |
| } |
| |
| /** |
| * |
| */ |
| public void refresh() { |
| setCalleeRoots(null); |
| setCallerRoots(null); |
| |
| updateView(); |
| } |
| |
| @Override |
| public void saveState(IMemento memento) { |
| if (fPagebook == null) { |
| // part has not been created |
| if (fMemento != null) { //Keep the old state; |
| memento.putMemento(fMemento); |
| } |
| |
| return; |
| } |
| |
| fSearchScopeActions.saveState(memento); |
| } |
| |
| @Override |
| public void selectionChanged(SelectionChangedEvent e) { |
| if (e.getSelectionProvider() == fCallHierarchyViewer) { |
| methodSelectionChanged(e.getSelection()); |
| } |
| } |
| |
| private void methodSelectionChanged(ISelection selection) { |
| if (selection instanceof IStructuredSelection && ((IStructuredSelection) selection).size() == 1) { |
| Object selectedElement = ((IStructuredSelection) selection).getFirstElement(); |
| |
| if (selectedElement instanceof MethodWrapper) { |
| MethodWrapper methodWrapper = (MethodWrapper) selectedElement; |
| |
| revealElementInEditor(methodWrapper, fCallHierarchyViewer); |
| updateLocationsView(methodWrapper); |
| } else { |
| updateLocationsView(null); |
| } |
| } else { |
| updateLocationsView(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; |
| } |
| |
| if (elem instanceof MethodWrapper) { |
| CallLocation callLocation = CallHierarchy.getCallLocation(elem); |
| |
| if (callLocation != null) { |
| IEditorPart editorPart = CallHierarchyUI.isOpenInEditor(callLocation); |
| |
| if (editorPart != null) { |
| getSite().getPage().bringToTop(editorPart); |
| |
| if (editorPart instanceof ITextEditor) { |
| ITextEditor editor = (ITextEditor) editorPart; |
| editor.selectAndReveal(callLocation.getStart(), |
| (callLocation.getEnd() - callLocation.getStart())); |
| } |
| } |
| } else { |
| IEditorPart editorPart = CallHierarchyUI.isOpenInEditor(elem); |
| getSite().getPage().bringToTop(editorPart); |
| EditorUtility.revealInEditor(editorPart, |
| ((MethodWrapper) elem).getMember()); |
| } |
| } else if (elem instanceof IJavaElement) { |
| IEditorPart editorPart = EditorUtility.isOpenInEditor(elem); |
| |
| if (editorPart != null) { |
| // getSite().getPage().removePartListener(fPartListener); |
| getSite().getPage().bringToTop(editorPart); |
| EditorUtility.revealInEditor(editorPart, (IJavaElement) elem); |
| |
| // getSite().getPage().addPartListener(fPartListener); |
| } |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public <T> T getAdapter(Class<T> adapter) { |
| if (adapter == IShowInSource.class) { |
| return (T) getShowInSource(); |
| } |
| if (adapter == IContextProvider.class) { |
| return (T) JavaUIHelp.getHelpContextProvider(this, IJavaHelpContextIds.CALL_HIERARCHY_VIEW); |
| } |
| if (adapter == IShowInTargetList.class) { |
| return (T) new IShowInTargetList() { |
| @Override |
| public String[] getShowInTargetIds() { |
| return new String[] { JavaUI.ID_PACKAGES }; |
| } |
| }; |
| } |
| return super.getAdapter(adapter); |
| } |
| |
| /** |
| * @return the <code>IShowInSource</code> for this view. |
| */ |
| private IShowInSource getShowInSource() { |
| return new IShowInSource() { |
| @Override |
| public ShowInContext getShowInContext() { |
| return new ShowInContext(null, fSelectionProviderMediator.getSelection()); |
| } |
| }; |
| } |
| |
| /** |
| * Returns the current selection. |
| * @return selection |
| */ |
| protected ISelection getSelection() { |
| StructuredViewer viewerInFocus= fSelectionProviderMediator.getViewerInFocus(); |
| if (viewerInFocus != null) { |
| return viewerInFocus.getSelection(); |
| } |
| return StructuredSelection.EMPTY; |
| } |
| |
| protected void fillLocationViewerContextMenu(IMenuManager menu) { |
| JavaPlugin.createStandardGroups(menu); |
| |
| menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fOpenLocationAction); |
| menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fRefreshSingleElementAction); |
| menu.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, fLocationCopyAction); |
| } |
| |
| private IActionBars getActionBars() { |
| return getViewSite().getActionBars(); |
| } |
| |
| private void setCalleeRoots(MethodWrapper[] calleeRoots) { |
| this.fCalleeRoots = calleeRoots; |
| } |
| |
| private MethodWrapper[] getCalleeRoots() { |
| if (fCalleeRoots == null) { |
| fCalleeRoots = CallHierarchy.getDefault().getCalleeRoots(fInputElements); |
| } |
| |
| return fCalleeRoots; |
| } |
| |
| private void setCallerRoots(MethodWrapper[] callerRoots) { |
| this.fCallerRoots = callerRoots; |
| } |
| |
| private MethodWrapper[] getCallerRoots() { |
| if (fCallerRoots != null && fCallerRoots.length > 0) { |
| // all caller roots have the same field mode, just check the first: |
| if (fCallerRoots[0].getFieldSearchMode() != fCurrentFieldMode) { |
| fCallerRoots= null; // field mode changed, re-initialize below |
| } |
| } |
| if (fCallerRoots == null) { |
| fCallerRoots = CallHierarchy.getDefault().getCallerRoots(fInputElements); |
| for (int i= 0; i < fCallerRoots.length; i++) { |
| fCallerRoots[i].setFieldSearchMode(fCurrentFieldMode); |
| } |
| } |
| |
| return fCallerRoots; |
| } |
| |
| /** |
| * Adds the entry if new. Inserted at the beginning of the history entries list. |
| * @param entry the entry to add |
| */ |
| private void addHistoryEntry(IMember[] entry) { |
| |
| updateHistoryEntries(entry, entry); |
| } |
| |
| /** |
| * Updates the input, history and description for the new input. |
| * |
| * @param currentInput the current input |
| * @param entry the new input elements |
| * @since 3.7 |
| */ |
| void updateInputHistoryAndDescription(IMember[] currentInput, IMember[] entry) { |
| updateHistoryEntries(currentInput, entry); |
| fInputElements= entry; |
| setContentDescription(getIncludeMask()); |
| } |
| |
| /** |
| * Updates the history with the latest input. |
| * |
| * @param currentInput the current input |
| * @param entry the new input elements |
| * @since 3.7 |
| */ |
| private void updateHistoryEntries(IMember[] currentInput, IMember[] entry) { |
| for (Iterator<IMember[]> iter= getMethodHistory().iterator(); iter.hasNext();) { |
| if (Arrays.equals(currentInput, iter.next())) { |
| iter.remove(); |
| } |
| } |
| |
| getMethodHistory().add(0, entry); |
| fHistoryDropDownAction.setEnabled(true); |
| } |
| |
| private void createLocationViewer(Composite parent) { |
| fLocationViewer= new LocationViewer(parent); |
| |
| |
| fLocationViewer.initContextMenu(new IMenuListener() { |
| @Override |
| public void menuAboutToShow(IMenuManager menu) { |
| fillLocationViewerContextMenu(menu); |
| } |
| }, ID_CALL_HIERARCHY, getSite()); |
| } |
| |
| private void createHierarchyLocationSplitter(Composite parent) { |
| fHierarchyLocationSplitter = new SashForm(parent, SWT.NONE); |
| } |
| |
| private void createCallHierarchyViewer(Composite parent) { |
| fCallHierarchyViewer = new CallHierarchyViewer(parent, this); |
| |
| fCallHierarchyViewer.addSelectionChangedListener(this); |
| } |
| |
| protected void fillCallHierarchyViewerContextMenu(IMenuManager menu) { |
| JavaPlugin.createStandardGroups(menu); |
| |
| menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fRefreshSingleElementAction); |
| menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, new Separator(GROUP_FOCUS)); |
| |
| if (fFocusOnSelectionAction.canActionBeAdded()) { |
| menu.appendToGroup(GROUP_FOCUS, fFocusOnSelectionAction); |
| } |
| if (fExpandWithConstructorsAction.canActionBeAdded()) { |
| menu.appendToGroup(GROUP_FOCUS, fExpandWithConstructorsAction); |
| } |
| |
| if (fRemoveFromViewAction.canActionBeAdded()){ |
| menu.appendToGroup(GROUP_FOCUS, fRemoveFromViewAction); |
| } |
| |
| fActionGroups.setContext(new ActionContext(getSelection())); |
| fActionGroups.fillContextMenu(menu); |
| fActionGroups.setContext(null); |
| |
| if (fCopyAction.canActionBeAdded()) { |
| menu.appendToGroup(ICommonMenuConstants.GROUP_EDIT, fCopyAction); |
| } |
| } |
| |
| private void fillActionBars() { |
| IActionBars actionBars = getActionBars(); |
| actionBars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), fRefreshSingleElementAction); |
| actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), fRemoveFromViewAction); |
| |
| IToolBarManager toolBar = actionBars.getToolBarManager(); |
| |
| fActionGroups.fillActionBars(actionBars); |
| |
| toolBar.add(fRefreshViewAction); |
| toolBar.add(fCancelSearchAction); |
| for (int i = 0; i < fToggleCallModeActions.length; i++) { |
| toolBar.add(fToggleCallModeActions[i]); |
| } |
| toolBar.add(fHistoryDropDownAction); |
| toolBar.add(fPinViewAction); |
| } |
| |
| private void makeActions() { |
| fRefreshViewAction = new RefreshViewAction(this); |
| fRefreshSingleElementAction= new RefreshElementAction(fCallHierarchyViewer); |
| |
| new CallHierarchyOpenEditorHelper(fLocationViewer); |
| new CallHierarchyOpenEditorHelper(fCallHierarchyViewer); |
| |
| fOpenLocationAction= new OpenLocationAction(this, getSite()); |
| fLocationCopyAction= fLocationViewer.initCopyAction(getViewSite(), fClipboard); |
| fFocusOnSelectionAction = new FocusOnSelectionAction(this); |
| fCopyAction= new CopyCallHierarchyAction(this, fClipboard, fCallHierarchyViewer); |
| fSearchScopeActions = new SearchScopeActionGroup(this, fDialogSettings); |
| fShowSearchInDialogAction= new ShowSearchInDialogAction(this, fCallHierarchyViewer); |
| fFiltersActionGroup = new CallHierarchyFiltersActionGroup(this, |
| fCallHierarchyViewer); |
| fHistoryDropDownAction = new HistoryDropDownAction(this); |
| fHistoryDropDownAction.setEnabled(false); |
| fCancelSearchAction = new CancelSearchAction(this); |
| setCancelEnabled(false); |
| fExpandWithConstructorsAction= new ExpandWithConstructorsAction(this, fCallHierarchyViewer); |
| fRemoveFromViewAction= new RemoveFromViewAction(this, fCallHierarchyViewer); |
| fPinViewAction= new PinCallHierarchyViewAction(this); |
| fToggleOrientationActions = new ToggleOrientationAction[] { |
| new ToggleOrientationAction(this, VIEW_ORIENTATION_VERTICAL), |
| new ToggleOrientationAction(this, VIEW_ORIENTATION_HORIZONTAL), |
| new ToggleOrientationAction(this, VIEW_ORIENTATION_AUTOMATIC), |
| new ToggleOrientationAction(this, VIEW_ORIENTATION_SINGLE) |
| }; |
| fRemoveFromViewAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_DELETE); |
| fToggleCallModeActions = new ToggleCallModeAction[] { |
| new ToggleCallModeAction(this, CALL_MODE_CALLERS), |
| new ToggleCallModeAction(this, CALL_MODE_CALLEES) |
| }; |
| fToggleFieldModeActions = new SelectFieldModeAction[] { |
| new SelectFieldModeAction(this, IJavaSearchConstants.REFERENCES), |
| new SelectFieldModeAction(this, IJavaSearchConstants.READ_ACCESSES), |
| new SelectFieldModeAction(this, IJavaSearchConstants.WRITE_ACCESSES) |
| }; |
| fActionGroups = new CompositeActionGroup(new ActionGroup[] { |
| new OpenEditorActionGroup(this), |
| new OpenViewActionGroup(this), |
| new CCPActionGroup(this, true), |
| new GenerateActionGroup(this), |
| new RefactorActionGroup(this), |
| new JavaSearchActionGroup(this), |
| fSearchScopeActions, fFiltersActionGroup |
| }); |
| } |
| |
| private void showOrHideCallDetailsView() { |
| if (fShowCallDetails) { |
| fHierarchyLocationSplitter.setMaximizedControl(null); |
| } else { |
| fHierarchyLocationSplitter.setMaximizedControl(fCallHierarchyViewer.getControl()); |
| } |
| } |
| |
| private void updateLocationsView(MethodWrapper methodWrapper) { |
| if (methodWrapper != null && methodWrapper.getMethodCall().hasCallLocations()) { |
| fLocationViewer.setInput(methodWrapper.getMethodCall().getCallLocations()); |
| } else { |
| fLocationViewer.clearViewer(); |
| } |
| } |
| |
| private void updateHistoryEntries() { |
| for (int i = getMethodHistory().size() - 1; i >= 0; i--) { |
| IMember[] members = getMethodHistory().get(i); |
| for (int j= 0; j < members.length; j++) { |
| IMember member= members[j]; |
| if (! member.exists()) { |
| getMethodHistory().remove(i); |
| break; |
| } |
| } |
| } |
| |
| fHistoryDropDownAction.setEnabled(!getMethodHistory().isEmpty()); |
| } |
| |
| private void updateView() { |
| if (fInputElements != null) { |
| showPage(PAGE_VIEWER); |
| |
| int includeMask= getIncludeMask(); |
| CallHierarchy.getDefault().setSearchScope(getSearchScope(includeMask)); |
| |
| // set input to null so that setComparator does not cause a refresh on the old contents: |
| fCallHierarchyViewer.setInput(null); |
| if (fCurrentCallMode == CALL_MODE_CALLERS) { |
| // sort caller hierarchy alphabetically (bug 111423) and make RealCallers the last in 'Expand With Constructors' mode |
| fCallHierarchyViewer.setComparator(new ViewerComparator() { |
| @Override |
| public int category(Object element) { |
| return element instanceof RealCallers ? 1 : 0; |
| } |
| }); |
| fCallHierarchyViewer.setMethodWrappers(getCallerRoots()); |
| } else { |
| fCallHierarchyViewer.setComparator(null); |
| fCallHierarchyViewer.setMethodWrappers(getCalleeRoots()); |
| } |
| setContentDescription(includeMask); |
| } |
| } |
| |
| /** |
| * Sets the content description. |
| * |
| * @param includeMask the include mask |
| * @since 3.7 |
| */ |
| private void setContentDescription(int includeMask) { |
| setContentDescription(computeContentDescription(includeMask)); |
| } |
| |
| |
| |
| /** |
| * Gets the include mask. |
| * |
| * @return the include mask |
| * @since 3.7 |
| */ |
| private int getIncludeMask() { |
| return fShowSearchInDialogAction.getSearchInDialog().getIncludeMask(); |
| } |
| |
| /** |
| * Computes the content description for the call hierarchy computation. |
| * |
| * @param includeMask the include mask |
| * @return the content description |
| * @since 3.7 |
| */ |
| private String computeContentDescription(int includeMask) { |
| // see also HistoryAction.getElementLabel(IMember[]) |
| String scopeDescription= fSearchScopeActions.getFullDescription(includeMask); |
| |
| if (fInputElements.length == 1) { |
| IMember element= fInputElements[0]; |
| String elementName= JavaElementLabels.getElementLabel(element, JavaElementLabels.ALL_DEFAULT); |
| String[] args= new String[] { elementName, scopeDescription }; |
| if (fCurrentCallMode == CALL_MODE_CALLERS) { |
| switch (element.getElementType()) { |
| case IJavaElement.TYPE: |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToConstructors, args); |
| case IJavaElement.FIELD: |
| switch (this.fCurrentFieldMode) { |
| case IJavaSearchConstants.READ_ACCESSES: |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToFieldRead, args); |
| case IJavaSearchConstants.WRITE_ACCESSES: |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToFieldWrite, args); |
| default: // all references |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToField, args); |
| } |
| case IJavaElement.METHOD: |
| case IJavaElement.INITIALIZER: |
| default: |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToMethod, args); |
| } |
| } else { |
| switch (element.getElementType()) { |
| case IJavaElement.TYPE: |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromConstructors, args); |
| case IJavaElement.FIELD: |
| case IJavaElement.METHOD: |
| case IJavaElement.INITIALIZER: |
| default: |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromMethod, args); |
| } |
| } |
| |
| } else { |
| if (fCurrentCallMode == CALL_MODE_CALLERS) { |
| switch (fInputElements.length) { |
| case 0: |
| Assert.isTrue(false); |
| return null; |
| case 2: |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToMembers_2, |
| new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription }); |
| |
| default: |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToMembers_more, |
| new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription }); |
| } |
| } else { |
| switch (fInputElements.length) { |
| case 0: |
| Assert.isTrue(false); |
| return null; |
| case 2: |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromMembers_2, |
| new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription }); |
| |
| default: |
| return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromMembers_more, |
| new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription }); |
| } |
| } |
| } |
| } |
| |
| private static String getShortLabel(IMember member) { |
| return JavaElementLabels.getElementLabel(member, 0L); |
| } |
| |
| static CallHierarchyViewPart findAndShowCallersView(IWorkbenchPartSite site) { |
| IWorkbenchPage workbenchPage = site.getPage(); |
| CallHierarchyViewPart callersView = null; |
| |
| try { |
| callersView = (CallHierarchyViewPart) workbenchPage.showView(CallHierarchyViewPart.ID_CALL_HIERARCHY); |
| } catch (PartInitException e) { |
| JavaPlugin.log(e); |
| } |
| |
| return callersView; |
| } |
| |
| /** |
| * Cancels the caller/callee search jobs that are currently running. |
| */ |
| void cancelJobs() { |
| fCallHierarchyViewer.cancelJobs(); |
| } |
| |
| /** |
| * Sets the enablement state of the cancel button. |
| * |
| * @param enabled <code>true</code> if cancel should be enabled |
| */ |
| void setCancelEnabled(boolean enabled) { |
| fCancelSearchAction.setEnabled(enabled); |
| } |
| |
| /** |
| * Returns the call hierarchy viewer. |
| * |
| * @return the call hierarchy viewer |
| * @since 3.5 |
| */ |
| public CallHierarchyViewer getViewer() { |
| return fCallHierarchyViewer; |
| } |
| |
| /** |
| * Returns the location viewer. |
| * |
| * @return the location viewer |
| * @since 3.6 |
| */ |
| protected LocationViewer getLocationViewer() { |
| return fLocationViewer; |
| } |
| |
| /** |
| * Marks the view as pinned. |
| * |
| * @param pinned if <code>true</code> the view is marked as pinned |
| * @since 3.7 |
| */ |
| void setPinned(boolean pinned) { |
| fIsPinned= pinned; |
| } |
| |
| /** |
| * Indicates whether the Call Hierarchy view is pinned. |
| * |
| * @return <code>true</code> if the view is pinned, <code>false</code> otherwise |
| * @since 3.7 |
| */ |
| boolean isPinned() { |
| return fIsPinned; |
| } |
| |
| /** |
| * Returns the method history. |
| * |
| * @return the method history |
| * @since 3.7 |
| */ |
| private List<IMember[]>getMethodHistory() { |
| return CallHierarchyUI.getDefault().getMethodHistory(); |
| } |
| |
| /* |
| * @see org.eclipse.ui.part.WorkbenchPart#showBusy(boolean) |
| * @since 3.7 |
| */ |
| @Override |
| public void showBusy(boolean busy) { |
| super.showBusy(busy); |
| if (!busy) |
| getProgressService().warnOfContentChange(); |
| } |
| |
| /** |
| * Fetches the progress service for the workbench part site. |
| * |
| * @return the progress service for the workbench part site |
| * @since 3.7 |
| */ |
| private IWorkbenchSiteProgressService getProgressService() { |
| IWorkbenchSiteProgressService service= null; |
| Object siteService= getSite().getAdapter(IWorkbenchSiteProgressService.class); |
| if (siteService != null) |
| service= (IWorkbenchSiteProgressService)siteService; |
| return service; |
| } |
| |
| /** |
| * Adds the new input elements to the current list. |
| * |
| * @param newElements the new input elements to add |
| * @since 3.7 |
| */ |
| void addInputElements(IMember[] newElements) { |
| // Caveat: RemoveFromViewAction#run() disposes TreeItems. When we add a previously removed element, |
| // we have to consider the real Tree state, not only fInputElements. |
| |
| List<IMember> inputElements= Arrays.asList(fInputElements); |
| List<IMember> treeElements= new ArrayList<>(); |
| TreeItem[] treeItems= fCallHierarchyViewer.getTree().getItems(); |
| for (int i= 0; i < treeItems.length; i++) { |
| Object data= treeItems[i].getData(); |
| if (data instanceof MethodWrapper) |
| treeElements.add(((MethodWrapper) data).getMember()); |
| } |
| |
| List<IMember> newInput= new ArrayList<>(); |
| newInput.addAll(inputElements); |
| List<IMember> addedElements= new ArrayList<>(); |
| |
| for (int i= 0; i < newElements.length; i++) { |
| IMember newElement= newElements[i]; |
| if (! inputElements.contains(newElement)) |
| newInput.add(newElement); |
| if (! treeElements.contains(newElement)) |
| addedElements.add(newElement); |
| } |
| if (treeElements.size() == 0) |
| updateInputHistoryAndDescription(fInputElements, newElements); |
| else if (newInput.size() > fInputElements.length) |
| updateInputHistoryAndDescription(fInputElements, newInput.toArray(new IMember[newInput.size()])); |
| if (addedElements.size() > 0) |
| updateViewWithAddedElements(addedElements.toArray(new IMember[addedElements.size()])); |
| } |
| |
| /** |
| * Updates the view with the newly added input elements. |
| * |
| * @param newElements the newly added elements |
| * @since 3.7 |
| */ |
| private void updateViewWithAddedElements(IMember[] newElements) { |
| setCalleeRoots(null); |
| setCallerRoots(null); |
| MethodWrapper[] roots; |
| if (getCallMode() == CALL_MODE_CALLERS) |
| roots= CallHierarchy.getDefault().getCallerRoots(newElements); |
| else |
| roots= CallHierarchy.getDefault().getCalleeRoots(newElements); |
| CallHierarchyViewer hierarchyViewer= getViewer(); |
| TreeRoot treeRoot= hierarchyViewer.getTreeRoot(roots, true); |
| hierarchyViewer.add(treeRoot, (Object[]) roots); |
| for (int i= 0; i < roots.length; i++) { |
| hierarchyViewer.setExpandedState(roots[i], true); |
| } |
| hierarchyViewer.setSelection(new StructuredSelection(roots), true); |
| } |
| } |