| /******************************************************************************* |
| * Copyright (c) 2000, 2017 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 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.ui.callhierarchy; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.DLTKLanguageManager; |
| import org.eclipse.dltk.core.IDLTKLanguageToolkit; |
| import org.eclipse.dltk.core.IMember; |
| import org.eclipse.dltk.core.IMethod; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.search.IDLTKSearchScope; |
| import org.eclipse.dltk.internal.corext.callhierarchy.CallHierarchy; |
| import org.eclipse.dltk.internal.corext.callhierarchy.CallLocation; |
| import org.eclipse.dltk.internal.corext.callhierarchy.MethodWrapper; |
| import org.eclipse.dltk.internal.corext.util.Messages; |
| import org.eclipse.dltk.internal.ui.actions.CCPActionGroup; |
| import org.eclipse.dltk.internal.ui.actions.CompositeActionGroup; |
| import org.eclipse.dltk.internal.ui.actions.refactoring.RefactorActionGroup; |
| import org.eclipse.dltk.internal.ui.dnd.DelegatingDropAdapter; |
| import org.eclipse.dltk.internal.ui.dnd.ResourceTransferDragAdapter; |
| import org.eclipse.dltk.internal.ui.editor.EditorUtility; |
| import org.eclipse.dltk.internal.ui.scriptview.SelectionTransferDragAdapter; |
| import org.eclipse.dltk.ui.DLTKUIPlugin; |
| import org.eclipse.dltk.ui.IContextMenuConstants; |
| import org.eclipse.dltk.ui.ScriptElementLabels; |
| import org.eclipse.dltk.ui.actions.OpenEditorActionGroup; |
| import org.eclipse.dltk.ui.actions.OpenViewActionGroup; |
| import org.eclipse.dltk.ui.viewsupport.SelectionProviderMediator; |
| import org.eclipse.dltk.ui.viewsupport.StatusBarUpdater; |
| 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.LocalSelectionTransfer; |
| import org.eclipse.jface.util.TransferDragSourceListener; |
| import org.eclipse.jface.util.TransferDropTargetListener; |
| 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.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.DropTarget; |
| import org.eclipse.swt.dnd.Transfer; |
| import org.eclipse.swt.events.ControlEvent; |
| import org.eclipse.swt.events.ControlListener; |
| 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.Label; |
| 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.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPartReference; |
| import org.eclipse.ui.IWorkbenchPartSite; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.actions.ActionContext; |
| import org.eclipse.ui.actions.ActionGroup; |
| import org.eclipse.ui.contexts.IContextActivation; |
| import org.eclipse.ui.contexts.IContextService; |
| import org.eclipse.ui.part.PageBook; |
| import org.eclipse.ui.part.ResourceTransfer; |
| import org.eclipse.ui.part.ViewPart; |
| import org.eclipse.ui.texteditor.ITextEditor; |
| |
| /** |
| * 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; |
| } |
| } |
| |
| private static final String DIALOGSTORE_VIEWORIENTATION = "CallHierarchyViewPart.orientation"; //$NON-NLS-1$ |
| private static final String DIALOGSTORE_CALL_MODE = "CallHierarchyViewPart.call_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.dltk.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 IDialogSettings fDialogSettings; |
| private int fCurrentOrientation; |
| int fOrientation = CallHierarchyViewPart.VIEW_ORIENTATION_AUTOMATIC; |
| private int fCurrentCallMode; |
| private MethodWrapper fCalleeRoot; |
| private MethodWrapper fCallerRoot; |
| private IMemento fMemento; |
| private IMethod fShownMethod; |
| private CallHierarchySelectionProvider fSelectionProviderMediator; |
| private List fMethodHistory; |
| private LocationViewer fLocationViewer; |
| private SashForm fHierarchyLocationSplitter; |
| private Clipboard fClipboard; |
| private SearchScopeActionGroup fSearchScopeActions; |
| private ToggleOrientationAction[] fToggleOrientationActions; |
| private ToggleCallModeAction[] fToggleCallModeActions; |
| private CallHierarchyFiltersActionGroup fFiltersActionGroup; |
| private HistoryDropDownAction fHistoryDropDownAction; |
| private RefreshAction fRefreshAction; |
| private OpenLocationAction fOpenLocationAction; |
| private FocusOnSelectionAction fFocusOnSelectionAction; |
| private CopyCallHierarchyAction fCopyAction; |
| private CancelSearchAction fCancelSearchAction; |
| private CompositeActionGroup fActionGroups; |
| private CallHierarchyViewer fCallHierarchyViewer; |
| private boolean fShowCallDetails; |
| protected Composite fParent; |
| private IPartListener2 fPartListener; |
| private IContextActivation fContextActivation; |
| |
| public CallHierarchyViewPart() { |
| super(); |
| |
| fDialogSettings = DLTKUIPlugin.getDefault().getDialogSettings(); |
| |
| fMethodHistory = new ArrayList(); |
| } |
| |
| @Override |
| public void setFocus() { |
| fPagebook.setFocus(); |
| } |
| |
| /** |
| * Sets the history entries |
| */ |
| public void setHistoryEntries(IMethod[] elems) { |
| fMethodHistory.clear(); |
| |
| for (int i = 0; i < elems.length; i++) { |
| fMethodHistory.add(elems[i]); |
| } |
| |
| updateHistoryEntries(); |
| } |
| |
| /** |
| * Gets all history entries. |
| */ |
| public IMethod[] getHistoryEntries() { |
| if (fMethodHistory.size() > 0) { |
| updateHistoryEntries(); |
| } |
| |
| return (IMethod[]) fMethodHistory |
| .toArray(new IMethod[fMethodHistory.size()]); |
| } |
| |
| /** |
| * Method setMethod. |
| * |
| * @param method |
| */ |
| public void setMethod(IMethod method) { |
| if (method == null) { |
| showPage(CallHierarchyViewPart.PAGE_EMPTY); |
| |
| return; |
| } |
| if (!method.equals(fShownMethod)) { |
| addHistoryEntry(method); |
| } |
| |
| this.fShownMethod = method; |
| |
| refresh(); |
| } |
| |
| public void setInputElements(IMember[] members) { |
| // IMember[] oldMembers= fInputElements; |
| // fInputElements= members; |
| |
| if (members == null || members.length == 0) { |
| showPage(PAGE_EMPTY); |
| return; |
| } |
| if (members.length == 1 && members[0] instanceof IMethod) { |
| this.fShownMethod = (IMethod) members[0]; |
| } |
| |
| refresh(); |
| } |
| |
| public IMethod getMethod() { |
| return fShownMethod; |
| } |
| |
| public MethodWrapper getCurrentMethodWrapper() { |
| if (fCurrentCallMode == CallHierarchyViewPart.CALL_MODE_CALLERS) { |
| return fCallerRoot; |
| } else { |
| return fCalleeRoot; |
| } |
| } |
| |
| /** |
| * 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 == CallHierarchyViewPart.VIEW_ORIENTATION_SINGLE) { |
| setShowCallDetails(false); |
| } else { |
| if (fCurrentOrientation == CallHierarchyViewPart.VIEW_ORIENTATION_SINGLE) { |
| setShowCallDetails(true); |
| } |
| |
| boolean horizontal = orientation == CallHierarchyViewPart.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(CallHierarchyViewPart.DIALOGSTORE_CALL_MODE, |
| mode); |
| |
| updateView(); |
| } |
| } |
| |
| public IDLTKSearchScope getSearchScope() { |
| return fSearchScopeActions.getSearchScope(); |
| } |
| |
| 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( |
| new Transfer[] { LocalSelectionTransfer.getTransfer() }); |
| dropTarget.addDropListener(new CallHierarchyTransferDropAdapter(this, |
| fCallHierarchyViewer)); |
| } |
| |
| private void addDropAdapters(StructuredViewer viewer) { |
| Transfer[] transfers = new Transfer[] { |
| LocalSelectionTransfer.getTransfer() }; |
| int ops = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK |
| | DND.DROP_DEFAULT; |
| |
| TransferDropTargetListener[] dropListeners = new TransferDropTargetListener[] { |
| new CallHierarchyTransferDropAdapter(this, viewer) }; |
| viewer.addDropSupport(ops, transfers, |
| new DelegatingDropAdapter(dropListeners)); |
| } |
| |
| private void addDragAdapters(StructuredViewer viewer) { |
| int ops = DND.DROP_COPY | DND.DROP_LINK; |
| Transfer[] transfers = new Transfer[] { |
| LocalSelectionTransfer.getTransfer(), |
| ResourceTransfer.getInstance() }; |
| |
| TransferDragSourceListener[] dragListeners = new TransferDragSourceListener[] { |
| new SelectionTransferDragAdapter(viewer), |
| new ResourceTransferDragAdapter(viewer) }; |
| // viewer.addDragSupport(ops, transfers, new |
| // DLTKViewerDragAdapter(viewer, dragListeners)); |
| } |
| |
| @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); // |
| |
| initDragAndDrop(); |
| |
| showPage(CallHierarchyViewPart.PAGE_EMPTY); |
| |
| // PlatformUI.getWorkbench().getHelpSystem().setHelp(fPagebook, |
| // IJavaHelpContextIds.CALL_HIERARCHY_VIEW); |
| if (DLTKCore.DEBUG) { |
| System.err.println("Add help support here..."); //$NON-NLS-1$ |
| } |
| |
| fSelectionProviderMediator = new CallHierarchySelectionProvider( |
| new StructuredViewer[] { fCallHierarchyViewer, |
| fLocationViewer }); |
| |
| IStatusLineManager slManager = getViewSite().getActionBars() |
| .getStatusLineManager(); |
| fSelectionProviderMediator |
| .addSelectionChangedListener(new StatusBarUpdater(slManager)); |
| getSite().setSelectionProvider(fSelectionProviderMediator); |
| |
| fCallHierarchyViewer.initContextMenu( |
| menu -> fillCallHierarchyViewerContextMenu(menu), getSite(), |
| fSelectionProviderMediator); |
| |
| fClipboard = new Clipboard(parent.getDisplay()); |
| |
| makeActions(); |
| fillViewMenu(); |
| fillActionBars(); |
| |
| initOrientation(); |
| initCallMode(); |
| |
| if (fMemento != null) { |
| restoreState(fMemento); |
| } |
| restoreSplitterRatio(); |
| addPartListener(); |
| IContextService ctxService = getSite() |
| .getService(IContextService.class); |
| if (ctxService != null) { |
| fContextActivation = ctxService |
| .activateContext(DLTKUIPlugin.CONTEXT_VIEWS); |
| } |
| } |
| |
| private void restoreSplitterRatio() { |
| String ratio = fDialogSettings.get( |
| CallHierarchyViewPart.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 = CallHierarchyViewPart.DIALOGSTORE_RATIO |
| + fCurrentOrientation; |
| fDialogSettings.put(key, ratio); |
| } |
| } |
| |
| private void addPartListener() { |
| fPartListener = new IPartListener2() { |
| @Override |
| public void partActivated(IWorkbenchPartReference partRef) { |
| } |
| |
| @Override |
| public void partBroughtToTop(IWorkbenchPartReference partRef) { |
| } |
| |
| @Override |
| public void partClosed(IWorkbenchPartReference partRef) { |
| if (CallHierarchyViewPart.ID_CALL_HIERARCHY |
| .equals(partRef.getId())) { |
| saveViewSettings(); |
| } |
| } |
| |
| @Override |
| public void partDeactivated(IWorkbenchPartReference partRef) { |
| if (CallHierarchyViewPart.ID_CALL_HIERARCHY |
| .equals(partRef.getId())) { |
| 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(CallHierarchyViewPart.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(CallHierarchyViewPart.DIALOGSTORE_VIEWORIENTATION, |
| fOrientation); |
| if (fOrientation != CallHierarchyViewPart.VIEW_ORIENTATION_AUTOMATIC) { |
| setOrientation(fOrientation); |
| } else { |
| if (fOrientation == CallHierarchyViewPart.VIEW_ORIENTATION_SINGLE) { |
| return; |
| } |
| Point size = fParent.getSize(); |
| if (size.x != 0 && size.y != 0) { |
| if (size.x > size.y) { |
| setOrientation( |
| CallHierarchyViewPart.VIEW_ORIENTATION_HORIZONTAL); |
| } else { |
| setOrientation( |
| CallHierarchyViewPart.VIEW_ORIENTATION_VERTICAL); |
| } |
| } |
| } |
| } |
| |
| private void showPage(int page) { |
| if (page == CallHierarchyViewPart.PAGE_EMPTY) { |
| fPagebook.showPage(fNoHierarchyShownLabel); |
| } else { |
| fPagebook.showPage(fHierarchyLocationSplitter); |
| } |
| } |
| |
| /** |
| * Restores the type hierarchy settings from a memento. |
| */ |
| private void restoreState(IMemento memento) { |
| fSearchScopeActions.restoreState(memento); |
| } |
| |
| private void initCallMode() { |
| int mode; |
| |
| try { |
| mode = fDialogSettings |
| .getInt(CallHierarchyViewPart.DIALOGSTORE_CALL_MODE); |
| |
| if ((mode < 0) || (mode > 1)) { |
| mode = CallHierarchyViewPart.CALL_MODE_CALLERS; |
| } |
| } catch (NumberFormatException e) { |
| mode = CallHierarchyViewPart.CALL_MODE_CALLERS; |
| } |
| |
| // force the update |
| fCurrentCallMode = -1; |
| |
| // will fill the main tool bar |
| setCallMode(mode); |
| } |
| |
| private void initOrientation() { |
| |
| try { |
| fOrientation = fDialogSettings |
| .getInt(CallHierarchyViewPart.DIALOGSTORE_VIEWORIENTATION); |
| |
| if ((fOrientation < 0) || (fOrientation > 3)) { |
| fOrientation = CallHierarchyViewPart.VIEW_ORIENTATION_AUTOMATIC; |
| } |
| } catch (NumberFormatException e) { |
| fOrientation = CallHierarchyViewPart.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); |
| } |
| |
| /** |
| * |
| */ |
| @Override |
| public void dispose() { |
| if (fContextActivation != null) { |
| IContextService ctxService = getSite() |
| .getService(IContextService.class); |
| if (ctxService != null) { |
| ctxService.deactivateContext(fContextActivation); |
| } |
| } |
| 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. |
| */ |
| public void gotoHistoryEntry(IMethod entry) { |
| if (fMethodHistory.contains(entry)) { |
| setMethod(entry); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) Method declared on IViewPart. |
| */ |
| @Override |
| public void init(IViewSite site, IMemento memento) |
| throws PartInitException { |
| super.init(site, memento); |
| fMemento = memento; |
| } |
| |
| /** |
| * |
| */ |
| public void refresh() { |
| setCalleeRoot(null); |
| setCallerRoot(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()); |
| } |
| } |
| |
| /** |
| * @param selection |
| */ |
| 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 IModelElement) { |
| IEditorPart editorPart = EditorUtility.isOpenInEditor(elem); |
| |
| if (editorPart != null) { |
| // getSite().getPage().removePartListener(fPartListener); |
| getSite().getPage().bringToTop(editorPart); |
| EditorUtility.revealInEditor(editorPart, (IModelElement) elem); |
| |
| // getSite().getPage().addPartListener(fPartListener); |
| } |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public <T> T getAdapter(Class<T> adapter) { |
| // if (adapter == IContextProvider.class) { |
| // return JavaUIHelp.getHelpContextProvider(this, |
| // IJavaHelpContextIds.CALL_HIERARCHY_VIEW); |
| // } |
| if (DLTKCore.DEBUG) { |
| System.err.println("Add help support here..."); //$NON-NLS-1$ |
| } |
| return super.getAdapter(adapter); |
| } |
| |
| /** |
| * Returns the current selection. |
| */ |
| protected ISelection getSelection() { |
| StructuredViewer viewerInFocus = fSelectionProviderMediator |
| .getViewerInFocus(); |
| if (viewerInFocus != null) { |
| return viewerInFocus.getSelection(); |
| } |
| return StructuredSelection.EMPTY; |
| } |
| |
| protected void fillLocationViewerContextMenu(IMenuManager menu) { |
| DLTKUIPlugin.createStandardGroups(menu); |
| |
| menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, |
| fOpenLocationAction); |
| menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fRefreshAction); |
| } |
| |
| protected void handleKeyEvent(KeyEvent event) { |
| if (event.stateMask == 0) { |
| if (event.keyCode == SWT.F5) { |
| if ((fRefreshAction != null) && fRefreshAction.isEnabled()) { |
| fRefreshAction.run(); |
| |
| return; |
| } |
| } |
| } |
| } |
| |
| private IActionBars getActionBars() { |
| return getViewSite().getActionBars(); |
| } |
| |
| private void setCalleeRoot(MethodWrapper calleeRoot) { |
| this.fCalleeRoot = calleeRoot; |
| } |
| |
| private MethodWrapper getCalleeRoot() { |
| if (fCalleeRoot == null) { |
| fCalleeRoot = CallHierarchy.getDefault() |
| .getCalleeRoot(fShownMethod); |
| } |
| |
| return fCalleeRoot; |
| } |
| |
| private void setCallerRoot(MethodWrapper callerRoot) { |
| this.fCallerRoot = callerRoot; |
| } |
| |
| private MethodWrapper getCallerRoot() { |
| if (fCallerRoot == null) { |
| fCallerRoot = CallHierarchy.getDefault() |
| .getCallerRoot(fShownMethod); |
| } |
| |
| return fCallerRoot; |
| } |
| |
| /** |
| * Adds the entry if new. Inserted at the beginning of the history entries |
| * list. |
| */ |
| private void addHistoryEntry(IModelElement entry) { |
| if (fMethodHistory.contains(entry)) { |
| fMethodHistory.remove(entry); |
| } |
| |
| fMethodHistory.add(0, entry); |
| fHistoryDropDownAction.setEnabled(!fMethodHistory.isEmpty()); |
| } |
| |
| /** |
| * @param parent |
| */ |
| private void createLocationViewer(Composite parent) { |
| fLocationViewer = new LocationViewer(parent); |
| |
| fLocationViewer.getControl().addKeyListener(createKeyListener()); |
| |
| fLocationViewer.initContextMenu( |
| menu -> fillLocationViewerContextMenu(menu), |
| CallHierarchyViewPart.ID_CALL_HIERARCHY, getSite()); |
| } |
| |
| private void createHierarchyLocationSplitter(Composite parent) { |
| fHierarchyLocationSplitter = new SashForm(parent, SWT.NONE); |
| |
| fHierarchyLocationSplitter.addKeyListener(createKeyListener()); |
| } |
| |
| private void createCallHierarchyViewer(Composite parent) { |
| fCallHierarchyViewer = new CallHierarchyViewer(parent, this); |
| |
| fCallHierarchyViewer.addKeyListener(createKeyListener()); |
| fCallHierarchyViewer.addSelectionChangedListener(this); |
| } |
| |
| /** |
| * @param menu |
| */ |
| protected void fillCallHierarchyViewerContextMenu(IMenuManager menu) { |
| DLTKUIPlugin.createStandardGroups(menu); |
| |
| menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fRefreshAction); |
| menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, |
| new Separator(CallHierarchyViewPart.GROUP_FOCUS)); |
| |
| if (fFocusOnSelectionAction.canActionBeAdded()) { |
| menu.appendToGroup(CallHierarchyViewPart.GROUP_FOCUS, |
| fFocusOnSelectionAction); |
| } |
| if (fCopyAction.canActionBeAdded()) { |
| menu.appendToGroup(CallHierarchyViewPart.GROUP_FOCUS, fCopyAction); |
| } |
| |
| fActionGroups.setContext(new ActionContext(getSelection())); |
| fActionGroups.fillContextMenu(menu); |
| fActionGroups.setContext(null); |
| } |
| |
| private void fillActionBars() { |
| IActionBars actionBars = getActionBars(); |
| IToolBarManager toolBar = actionBars.getToolBarManager(); |
| |
| fActionGroups.fillActionBars(actionBars); |
| |
| toolBar.add(fCancelSearchAction); |
| for (int i = 0; i < fToggleCallModeActions.length; i++) { |
| toolBar.add(fToggleCallModeActions[i]); |
| } |
| toolBar.add(fHistoryDropDownAction); |
| } |
| |
| private KeyListener createKeyListener() { |
| KeyListener keyListener = new KeyAdapter() { |
| @Override |
| public void keyReleased(KeyEvent event) { |
| handleKeyEvent(event); |
| } |
| }; |
| |
| return keyListener; |
| } |
| |
| /** |
| * |
| */ |
| private void makeActions() { |
| fRefreshAction = new RefreshAction(this); |
| |
| fOpenLocationAction = new OpenLocationAction(this, getSite()); |
| fLocationViewer.addOpenListener(event -> fOpenLocationAction.run()); |
| |
| fFocusOnSelectionAction = new FocusOnSelectionAction(this); |
| fCopyAction = new CopyCallHierarchyAction(this, fClipboard, |
| fCallHierarchyViewer); |
| fSearchScopeActions = new SearchScopeActionGroup(this, |
| fDialogSettings) { |
| @Override |
| protected IDLTKLanguageToolkit getLangaugeToolkit() { |
| return getMethodLanguageToolkit(); |
| } |
| }; |
| fFiltersActionGroup = new CallHierarchyFiltersActionGroup(this, |
| fCallHierarchyViewer); |
| fHistoryDropDownAction = new HistoryDropDownAction(this); |
| fHistoryDropDownAction.setEnabled(false); |
| fCancelSearchAction = new CancelSearchAction(this); |
| setCancelEnabled(false); |
| fToggleOrientationActions = new ToggleOrientationAction[] { |
| new ToggleOrientationAction(this, |
| CallHierarchyViewPart.VIEW_ORIENTATION_VERTICAL), |
| new ToggleOrientationAction(this, |
| CallHierarchyViewPart.VIEW_ORIENTATION_HORIZONTAL), |
| new ToggleOrientationAction(this, |
| CallHierarchyViewPart.VIEW_ORIENTATION_AUTOMATIC), |
| new ToggleOrientationAction(this, |
| CallHierarchyViewPart.VIEW_ORIENTATION_SINGLE) }; |
| fToggleCallModeActions = new ToggleCallModeAction[] { |
| new ToggleCallModeAction(this, |
| CallHierarchyViewPart.CALL_MODE_CALLERS), |
| new ToggleCallModeAction(this, |
| CallHierarchyViewPart.CALL_MODE_CALLEES) }; |
| fActionGroups = new CompositeActionGroup( |
| new ActionGroup[] { new OpenEditorActionGroup(this), |
| new OpenViewActionGroup(this), new CCPActionGroup(this), |
| // new GenerateActionGroup(this), |
| new RefactorActionGroup(this, null), |
| // new DLTKSearchActionGroup(this), |
| fSearchScopeActions, fFiltersActionGroup }); |
| } |
| |
| protected IDLTKLanguageToolkit getMethodLanguageToolkit() { |
| if (getMethod() != null) { |
| return DLTKLanguageManager.getLanguageToolkit(getMethod()); |
| } |
| return null; |
| } |
| |
| 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 = fMethodHistory.size() - 1; i >= 0; i--) { |
| IMethod method = (IMethod) fMethodHistory.get(i); |
| |
| if (!method.exists()) { |
| fMethodHistory.remove(i); |
| } |
| } |
| |
| fHistoryDropDownAction.setEnabled(!fMethodHistory.isEmpty()); |
| } |
| |
| /** |
| * Method updateView. |
| */ |
| private void updateView() { |
| if ((fShownMethod != null)) { |
| showPage(CallHierarchyViewPart.PAGE_VIEWER); |
| |
| CallHierarchy.getDefault().setSearchScope(getSearchScope()); |
| |
| String elementName = ScriptElementLabels.getDefault() |
| .getElementLabel(fShownMethod, |
| ScriptElementLabels.ALL_DEFAULT); |
| String scopeDescription = fSearchScopeActions.getFullDescription(); |
| String[] args = new String[] { elementName, scopeDescription }; |
| // set input to null so that setSorter does not cause a refresh on |
| // the old contents: |
| fCallHierarchyViewer.setInput(null); |
| if (fCurrentCallMode == CallHierarchyViewPart.CALL_MODE_CALLERS) { |
| setContentDescription(Messages.format( |
| CallHierarchyMessages.CallHierarchyViewPart_callsToMethod, |
| args)); |
| fCallHierarchyViewer.setComparator(new ViewerComparator()); // bug |
| // 111423: |
| // sort |
| // caller |
| // hierarchy |
| // alphabetically |
| fCallHierarchyViewer.setMethodWrapper(getCallerRoot()); |
| } else { |
| setContentDescription(Messages.format( |
| CallHierarchyMessages.CallHierarchyViewPart_callsFromMethod, |
| args)); |
| fCallHierarchyViewer.setComparator(null); |
| fCallHierarchyViewer.setMethodWrapper(getCalleeRoot()); |
| } |
| } |
| } |
| |
| static CallHierarchyViewPart findAndShowCallersView( |
| IWorkbenchPartSite site) { |
| IWorkbenchPage workbenchPage = site.getPage(); |
| CallHierarchyViewPart callersView = null; |
| |
| try { |
| callersView = (CallHierarchyViewPart) workbenchPage |
| .showView(CallHierarchyViewPart.ID_CALL_HIERARCHY); |
| } catch (PartInitException e) { |
| DLTKUIPlugin.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 |
| */ |
| void setCancelEnabled(boolean enabled) { |
| fCancelSearchAction.setEnabled(enabled); |
| } |
| } |