1 /*******************************************************************************
2 * Copyright (c) 2000, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation
10 * (report 36180: Callers/Callees view)
11 * Michael Fraenkel (fraenkel@us.ibm.com) - patch
12 * (report 60714: Call Hierarchy: display search scope in view title)
13 * Stephan Herrmann (stephan@cs.tu-berlin.de):
14 * - bug 75800: [call hierarchy] should allow searches for fields
15 * Stephan Herrmann (stephan@cs.tu-berlin.de):
16 * - bug 206949: [call hierarchy] filter field accesses (only write or only read)
17 *******************************************************************************/
18 package org.eclipse.jdt.internal.ui.callhierarchy;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Iterator;
23 import java.util.List;
25 import org.eclipse.help.IContextProvider;
27 import org.eclipse.swt.SWT;
28 import org.eclipse.swt.custom.SashForm;
29 import org.eclipse.swt.dnd.Clipboard;
30 import org.eclipse.swt.dnd.DND;
31 import org.eclipse.swt.dnd.DragSourceEvent;
32 import org.eclipse.swt.dnd.DropTarget;
33 import org.eclipse.swt.dnd.FileTransfer;
34 import org.eclipse.swt.dnd.Transfer;
35 import org.eclipse.swt.events.ControlEvent;
36 import org.eclipse.swt.events.ControlListener;
37 import org.eclipse.swt.graphics.Point;
38 import org.eclipse.swt.widgets.Composite;
39 import org.eclipse.swt.widgets.Control;
40 import org.eclipse.swt.widgets.Label;
41 import org.eclipse.swt.widgets.TreeItem;
43 import org.eclipse.core.runtime.Assert;
45 import org.eclipse.jface.action.IMenuListener;
46 import org.eclipse.jface.action.IMenuManager;
47 import org.eclipse.jface.action.IStatusLineManager;
48 import org.eclipse.jface.action.IToolBarManager;
49 import org.eclipse.jface.action.MenuManager;
50 import org.eclipse.jface.action.Separator;
51 import org.eclipse.jface.dialogs.IDialogSettings;
52 import org.eclipse.jface.util.DelegatingDragAdapter;
53 import org.eclipse.jface.util.DelegatingDropAdapter;
54 import org.eclipse.jface.util.OpenStrategy;
55 import org.eclipse.jface.viewers.ISelection;
56 import org.eclipse.jface.viewers.ISelectionChangedListener;
57 import org.eclipse.jface.viewers.IStructuredSelection;
58 import org.eclipse.jface.viewers.SelectionChangedEvent;
59 import org.eclipse.jface.viewers.StructuredSelection;
60 import org.eclipse.jface.viewers.StructuredViewer;
61 import org.eclipse.jface.viewers.Viewer;
62 import org.eclipse.jface.viewers.ViewerComparator;
64 import org.eclipse.ui.IActionBars;
65 import org.eclipse.ui.IEditorPart;
66 import org.eclipse.ui.IMemento;
67 import org.eclipse.ui.IPartListener2;
68 import org.eclipse.ui.IViewReference;
69 import org.eclipse.ui.IViewSite;
70 import org.eclipse.ui.IWorkbenchCommandConstants;
71 import org.eclipse.ui.IWorkbenchPage;
72 import org.eclipse.ui.IWorkbenchPartReference;
73 import org.eclipse.ui.IWorkbenchPartSite;
74 import org.eclipse.ui.OpenAndLinkWithEditorHelper;
75 import org.eclipse.ui.PartInitException;
76 import org.eclipse.ui.PlatformUI;
77 import org.eclipse.ui.actions.ActionContext;
78 import org.eclipse.ui.actions.ActionFactory;
79 import org.eclipse.ui.actions.ActionGroup;
80 import org.eclipse.ui.navigator.ICommonMenuConstants;
81 import org.eclipse.ui.part.IShowInSource;
82 import org.eclipse.ui.part.IShowInTargetList;
83 import org.eclipse.ui.part.PageBook;
84 import org.eclipse.ui.part.PluginTransfer;
85 import org.eclipse.ui.part.ResourceTransfer;
86 import org.eclipse.ui.part.ShowInContext;
87 import org.eclipse.ui.part.ViewPart;
88 import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
89 import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
91 import org.eclipse.ui.texteditor.ITextEditor;
93 import org.eclipse.jdt.core.IJavaElement;
94 import org.eclipse.jdt.core.IMember;
95 import org.eclipse.jdt.core.search.IJavaSearchConstants;
96 import org.eclipse.jdt.core.search.IJavaSearchScope;
98 import org.eclipse.jdt.internal.corext.callhierarchy.CallHierarchy;
99 import org.eclipse.jdt.internal.corext.callhierarchy.CallLocation;
100 import org.eclipse.jdt.internal.corext.callhierarchy.MethodWrapper;
101 import org.eclipse.jdt.internal.corext.callhierarchy.RealCallers;
102 import org.eclipse.jdt.internal.corext.util.Messages;
104 import org.eclipse.jdt.ui.IContextMenuConstants;
105 import org.eclipse.jdt.ui.JavaElementLabels;
106 import org.eclipse.jdt.ui.JavaUI;
107 import org.eclipse.jdt.ui.actions.CCPActionGroup;
108 import org.eclipse.jdt.ui.actions.GenerateActionGroup;
109 import org.eclipse.jdt.ui.actions.JavaSearchActionGroup;
110 import org.eclipse.jdt.ui.actions.OpenEditorActionGroup;
111 import org.eclipse.jdt.ui.actions.OpenViewActionGroup;
112 import org.eclipse.jdt.ui.actions.RefactorActionGroup;
114 import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
115 import org.eclipse.jdt.internal.ui.JavaPlugin;
116 import org.eclipse.jdt.internal.ui.actions.CompositeActionGroup;
117 import org.eclipse.jdt.internal.ui.dnd.EditorInputTransferDragAdapter;
118 import org.eclipse.jdt.internal.ui.dnd.ResourceTransferDragAdapter;
119 import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
120 import org.eclipse.jdt.internal.ui.packageview.FileTransferDragAdapter;
121 import org.eclipse.jdt.internal.ui.packageview.PluginTransferDropAdapter;
122 import org.eclipse.jdt.internal.ui.packageview.SelectionTransferDragAdapter;
123 import org.eclipse.jdt.internal.ui.util.JavaUIHelp;
124 import org.eclipse.jdt.internal.ui.util.SelectionUtil;
125 import org.eclipse.jdt.internal.ui.viewsupport.SelectionProviderMediator;
126 import org.eclipse.jdt.internal.ui.viewsupport.StatusBarUpdater;
130 * This is the main view for the callers plugin. It builds a tree of callers/callees
131 * and allows the user to double click an entry to go to the selected method.
134 public class CallHierarchyViewPart extends ViewPart implements ICallHierarchyViewPart, ISelectionChangedListener {
137 private class CallHierarchySelectionProvider extends SelectionProviderMediator {
139 public CallHierarchySelectionProvider(StructuredViewer[] viewers) {
140 super(viewers, null);
144 * @see org.eclipse.jdt.internal.ui.typehierarchy.SelectionProviderMediator#getSelection()
147 public ISelection getSelection() {
148 ISelection selection= super.getSelection();
149 if (!selection.isEmpty()) {
150 return CallHierarchyUI.convertSelection(selection);
160 private final class CallHierarchyOpenEditorHelper extends OpenAndLinkWithEditorHelper {
161 public CallHierarchyOpenEditorHelper(StructuredViewer viewer) {
166 protected void activate(ISelection selection) {
167 final Object selectedElement= SelectionUtil.getSingleElement(selection);
168 if (selectedElement != null)
169 CallHierarchyUI.openInEditor(selectedElement, getSite().getShell(), true);
173 protected void linkToEditor(ISelection selection) {
174 // not supported by this part
178 protected void open(ISelection selection, boolean activate) {
179 if (selection instanceof IStructuredSelection) {
180 for (Iterator<?> iter= ((IStructuredSelection)selection).iterator(); iter.hasNext();) {
181 boolean noError= CallHierarchyUI.openInEditor(iter.next(), getSite().getShell(), OpenStrategy.activateOnOpen());
191 private static final String DIALOGSTORE_VIEWORIENTATION = "CallHierarchyViewPart.orientation"; //$NON-NLS-1$
192 private static final String DIALOGSTORE_CALL_MODE = "CallHierarchyViewPart.call_mode"; //$NON-NLS-1$
193 private static final String DIALOGSTORE_FIELD_MODE = "CallHierarchyViewPart.field_mode"; //$NON-NLS-1$
195 * The key to be used is <code>DIALOGSTORE_RATIO + fCurrentOrientation</code>.
197 private static final String DIALOGSTORE_RATIO= "CallHierarchyViewPart.ratio"; //$NON-NLS-1$
199 static final int VIEW_ORIENTATION_VERTICAL = 0;
200 static final int VIEW_ORIENTATION_HORIZONTAL = 1;
201 static final int VIEW_ORIENTATION_SINGLE = 2;
202 static final int VIEW_ORIENTATION_AUTOMATIC = 3;
203 static final int CALL_MODE_CALLERS = 0;
204 static final int CALL_MODE_CALLEES = 1;
205 static final String GROUP_SEARCH_SCOPE = "MENU_SEARCH_SCOPE"; //$NON-NLS-1$
206 static final String ID_CALL_HIERARCHY = "org.eclipse.jdt.callhierarchy.view"; //$NON-NLS-1$
208 private static final String GROUP_FOCUS = "group.focus"; //$NON-NLS-1$
209 private static final int PAGE_EMPTY = 0;
210 private static final int PAGE_VIEWER = 1;
211 private Label fNoHierarchyShownLabel;
212 private PageBook fPagebook;
213 private final IDialogSettings fDialogSettings;
214 private int fCurrentOrientation;
215 int fOrientation= VIEW_ORIENTATION_AUTOMATIC;
216 private int fCurrentCallMode;
217 private int fCurrentFieldMode;
218 private MethodWrapper[] fCalleeRoots;
219 private MethodWrapper[] fCallerRoots;
220 private IMemento fMemento;
221 private IMember[] fInputElements;
222 private CallHierarchySelectionProvider fSelectionProviderMediator;
223 private LocationViewer fLocationViewer;
224 private SashForm fHierarchyLocationSplitter;
225 private Clipboard fClipboard;
226 private SearchScopeActionGroup fSearchScopeActions;
227 private ToggleOrientationAction[] fToggleOrientationActions;
228 private ToggleCallModeAction[] fToggleCallModeActions;
229 private SelectFieldModeAction[] fToggleFieldModeActions;
230 private CallHierarchyFiltersActionGroup fFiltersActionGroup;
231 private HistoryDropDownAction fHistoryDropDownAction;
232 private RefreshElementAction fRefreshSingleElementAction;
233 private RefreshViewAction fRefreshViewAction;
234 private OpenLocationAction fOpenLocationAction;
235 private LocationCopyAction fLocationCopyAction;
236 private FocusOnSelectionAction fFocusOnSelectionAction;
237 private CopyCallHierarchyAction fCopyAction;
238 private CancelSearchAction fCancelSearchAction;
239 private ExpandWithConstructorsAction fExpandWithConstructorsAction;
240 private RemoveFromViewAction fRemoveFromViewAction;
241 private ShowSearchInDialogAction fShowSearchInDialogAction;
242 private CompositeActionGroup fActionGroups;
243 private CallHierarchyViewer fCallHierarchyViewer;
244 private boolean fShowCallDetails;
245 protected Composite fParent;
246 private IPartListener2 fPartListener;
247 private boolean fIsPinned;
248 private PinCallHierarchyViewAction fPinViewAction;
251 public CallHierarchyViewPart() {
254 fDialogSettings = JavaPlugin.getDefault().getDialogSettings();
260 public void setFocus() {
261 fPagebook.setFocus();
265 * Sets the history entries
266 * @param entries the new history entries
268 public void setHistoryEntries(IMember[][] entries) {
269 getMethodHistory().clear();
271 for (int i = 0; i < entries.length; i++) {
272 getMethodHistory().add(entries[i]);
275 updateHistoryEntries();
279 * Gets all history entries.
280 * @return all history entries
282 public IMember[][] getHistoryEntries() {
283 if (getMethodHistory().size() > 0) {
284 updateHistoryEntries();
287 return getMethodHistory().toArray(new IMember[getMethodHistory().size()][]);
290 public void setInputElements(IMember[] members) {
291 IMember[] oldMembers= fInputElements;
292 fInputElements= members;
294 if (members == null || members.length == 0) {
295 showPage(PAGE_EMPTY);
299 if (! Arrays.equals(members, oldMembers)) {
300 addHistoryEntry(members);
306 public IMember[] getInputElements() {
307 return fInputElements;
310 public MethodWrapper[] getCurrentMethodWrappers() {
311 if (fCurrentCallMode == CALL_MODE_CALLERS) {
319 * called from ToggleOrientationAction.
320 * @param orientation VIEW_ORIENTATION_HORIZONTAL or VIEW_ORIENTATION_VERTICAL
322 void setOrientation(int orientation) {
323 if (fCurrentOrientation != orientation) {
324 if ((fLocationViewer != null) && !fLocationViewer.getControl().isDisposed() &&
325 (fHierarchyLocationSplitter != null) &&
326 !fHierarchyLocationSplitter.isDisposed()) {
327 if (orientation == VIEW_ORIENTATION_SINGLE) {
328 setShowCallDetails(false);
330 if (fCurrentOrientation == VIEW_ORIENTATION_SINGLE) {
331 setShowCallDetails(true);
334 boolean horizontal = orientation == VIEW_ORIENTATION_HORIZONTAL;
335 fHierarchyLocationSplitter.setOrientation(horizontal ? SWT.HORIZONTAL
339 fHierarchyLocationSplitter.layout();
342 updateCheckedState();
344 fCurrentOrientation = orientation;
346 restoreSplitterRatio();
350 private void updateCheckedState() {
351 for (int i= 0; i < fToggleOrientationActions.length; i++) {
352 fToggleOrientationActions[i].setChecked(fOrientation == fToggleOrientationActions[i].getOrientation());
357 * called from ToggleCallModeAction.
358 * @param mode CALL_MODE_CALLERS or CALL_MODE_CALLEES
360 void setCallMode(int mode) {
361 if (fCurrentCallMode != mode) {
362 for (int i = 0; i < fToggleCallModeActions.length; i++) {
363 fToggleCallModeActions[i].setChecked(mode == fToggleCallModeActions[i].getMode());
366 fCurrentCallMode = mode;
367 fDialogSettings.put(DIALOGSTORE_CALL_MODE, mode);
374 * Returns the current call mode.
376 * @return the current call mode: CALL_MODE_CALLERS or CALL_MODE_CALLEES
380 return fCurrentCallMode;
385 * called from SelectFieldModeAction.
386 * @param mode IJavaSearchConstants.{REFERENCES,WRITE_ACCESS,READ_ACCESS}
388 void setFieldMode(int mode) {
389 if (fCurrentFieldMode != mode) {
390 for (int i = 0; i < fToggleFieldModeActions.length; i++) {
391 fToggleFieldModeActions[i].setChecked(mode == fToggleFieldModeActions[i].getMode());
394 fCurrentFieldMode = mode;
395 fDialogSettings.put(DIALOGSTORE_FIELD_MODE, mode);
402 * Fetches the search scope with the appropriate include mask.
404 * @param includeMask the include mask
405 * @return the search scope with the appropriate include mask
408 public IJavaSearchScope getSearchScope(int includeMask) {
409 return fSearchScopeActions.getSearchScope(includeMask);
412 public void setShowCallDetails(boolean show) {
413 fShowCallDetails = show;
414 showOrHideCallDetailsView();
417 private void initDragAndDrop() {
418 addDragAdapters(fCallHierarchyViewer);
419 addDropAdapters(fCallHierarchyViewer);
420 addDropAdapters(fLocationViewer);
422 //dnd on empty hierarchy
423 DropTarget dropTarget = new DropTarget(fPagebook, DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_DEFAULT);
424 dropTarget.setTransfer(new Transfer[] { LocalSelectionTransfer.getInstance() });
425 dropTarget.addDropListener(new CallHierarchyTransferDropAdapter(this, fCallHierarchyViewer));
428 private void addDropAdapters(StructuredViewer viewer) {
429 Transfer[] transfers= new Transfer[] { LocalSelectionTransfer.getInstance(), PluginTransfer.getInstance() };
430 int ops= DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_DEFAULT;
432 DelegatingDropAdapter delegatingDropAdapter= new DelegatingDropAdapter();
433 delegatingDropAdapter.addDropTargetListener(new CallHierarchyTransferDropAdapter(this, viewer));
434 delegatingDropAdapter.addDropTargetListener(new PluginTransferDropAdapter(viewer));
436 viewer.addDropSupport(ops, transfers, delegatingDropAdapter);
439 private void addDragAdapters(StructuredViewer viewer) {
440 int ops= DND.DROP_COPY | DND.DROP_LINK;
442 Transfer[] transfers= new Transfer[] { LocalSelectionTransfer.getInstance(), ResourceTransfer.getInstance(), FileTransfer.getInstance()};
444 DelegatingDragAdapter dragAdapter= new DelegatingDragAdapter() {
446 public void dragStart(DragSourceEvent event) {
447 IStructuredSelection selection= (IStructuredSelection) fSelectionProviderMediator.getSelection();
448 if (selection.isEmpty()) {
452 super.dragStart(event);
455 dragAdapter.addDragSourceListener(new SelectionTransferDragAdapter(fSelectionProviderMediator));
456 dragAdapter.addDragSourceListener(new EditorInputTransferDragAdapter(fSelectionProviderMediator));
457 dragAdapter.addDragSourceListener(new ResourceTransferDragAdapter(fSelectionProviderMediator));
458 dragAdapter.addDragSourceListener(new FileTransferDragAdapter(fSelectionProviderMediator));
460 viewer.addDragSupport(ops, transfers, dragAdapter);
464 public void createPartControl(Composite parent) {
466 addResizeListener(parent);
467 fPagebook = new PageBook(parent, SWT.NONE);
470 createHierarchyLocationSplitter(fPagebook);
471 createCallHierarchyViewer(fHierarchyLocationSplitter);
472 createLocationViewer(fHierarchyLocationSplitter);
474 // Page 2: Nothing selected
475 fNoHierarchyShownLabel = new Label(fPagebook, SWT.TOP + SWT.LEFT + SWT.WRAP);
476 fNoHierarchyShownLabel.setText(CallHierarchyMessages.CallHierarchyViewPart_empty); //
478 showPage(PAGE_EMPTY);
480 PlatformUI.getWorkbench().getHelpSystem().setHelp(fPagebook, IJavaHelpContextIds.CALL_HIERARCHY_VIEW);
482 fSelectionProviderMediator = new CallHierarchySelectionProvider(new StructuredViewer[] {
483 fCallHierarchyViewer, fLocationViewer
486 IStatusLineManager slManager = getViewSite().getActionBars().getStatusLineManager();
487 fSelectionProviderMediator.addSelectionChangedListener(new StatusBarUpdater(slManager));
488 getSite().setSelectionProvider(fSelectionProviderMediator);
490 fCallHierarchyViewer.initContextMenu(
491 new IMenuListener() {
492 public void menuAboutToShow(IMenuManager menu) {
493 fillCallHierarchyViewerContextMenu(menu);
495 }, getSite(), fSelectionProviderMediator);
498 fClipboard= new Clipboard(parent.getDisplay());
509 if (fMemento != null) {
510 restoreState(fMemento);
512 restoreSplitterRatio();
516 private void restoreSplitterRatio() {
517 String ratio= fDialogSettings.get(DIALOGSTORE_RATIO + fCurrentOrientation);
520 int intRatio= Integer.parseInt(ratio);
521 fHierarchyLocationSplitter.setWeights(new int[] {intRatio, 1000 - intRatio});
524 private void saveSplitterRatio() {
525 if (fHierarchyLocationSplitter != null && ! fHierarchyLocationSplitter.isDisposed()) {
526 int[] weigths = fHierarchyLocationSplitter.getWeights();
527 int ratio = (weigths[0] * 1000) / (weigths[0] + weigths[1]);
528 String key= DIALOGSTORE_RATIO + fCurrentOrientation;
529 fDialogSettings.put(key, ratio);
534 * Tells whether the given part reference references this view.
536 * @param partRef the workbench part reference
537 * @return <code>true</code> if the given part reference references this view
540 private boolean isThisView(IWorkbenchPartReference partRef) {
541 if (!ID_CALL_HIERARCHY.equals(partRef.getId()))
543 String partRefSecondaryId= ((IViewReference)partRef).getSecondaryId();
544 String thisSecondaryId= getViewSite().getSecondaryId();
545 return thisSecondaryId == null && partRefSecondaryId == null || thisSecondaryId != null && thisSecondaryId.equals(partRefSecondaryId);
548 private void addPartListener() {
549 fPartListener= new IPartListener2() {
551 * @see org.eclipse.ui.IPartListener2#partActivated(org.eclipse.ui.IWorkbenchPartReference)
553 public void partActivated(IWorkbenchPartReference partRef) {
554 if (isThisView(partRef))
555 CallHierarchyUI.getDefault().callHierarchyViewActivated(CallHierarchyViewPart.this);
558 public void partBroughtToTop(IWorkbenchPartReference partRef) { }
561 * @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference)
563 public void partClosed(IWorkbenchPartReference partRef) {
564 if (isThisView(partRef)) {
565 CallHierarchyUI.getDefault().callHierarchyViewClosed(CallHierarchyViewPart.this);
571 * @see org.eclipse.ui.IPartListener2#partDeactivated(org.eclipse.ui.IWorkbenchPartReference)
573 public void partDeactivated(IWorkbenchPartReference partRef) {
574 if (isThisView(partRef))
578 public void partOpened(IWorkbenchPartReference partRef) { }
579 public void partHidden(IWorkbenchPartReference partRef) { }
580 public void partVisible(IWorkbenchPartReference partRef) { }
581 public void partInputChanged(IWorkbenchPartReference partRef) { }
583 getViewSite().getPage().addPartListener(fPartListener);
586 protected void saveViewSettings() {
588 fDialogSettings.put(DIALOGSTORE_VIEWORIENTATION, fOrientation);
591 private void addResizeListener(Composite parent) {
592 parent.addControlListener(new ControlListener() {
593 public void controlMoved(ControlEvent e) {
595 public void controlResized(ControlEvent e) {
596 computeOrientation();
601 void computeOrientation() {
603 fDialogSettings.put(DIALOGSTORE_VIEWORIENTATION, fOrientation);
604 if (fOrientation != VIEW_ORIENTATION_AUTOMATIC) {
605 setOrientation(fOrientation);
608 if (fOrientation == VIEW_ORIENTATION_SINGLE)
610 Point size= fParent.getSize();
611 if (size.x != 0 && size.y != 0) {
613 setOrientation(VIEW_ORIENTATION_HORIZONTAL);
615 setOrientation(VIEW_ORIENTATION_VERTICAL);
620 private void showPage(int page) {
621 boolean isEmpty= page == PAGE_EMPTY;
622 Control control= isEmpty ? (Control) fNoHierarchyShownLabel : fHierarchyLocationSplitter;
624 setContentDescription(""); //$NON-NLS-1$
625 setTitleToolTip(getPartName());
626 getViewSite().getActionBars().getStatusLineManager().setMessage(""); //$NON-NLS-1$
627 getViewer().clearViewer();
629 fPagebook.showPage(control);
630 if (fRefreshViewAction != null)
631 fRefreshViewAction.setEnabled(!isEmpty);
632 if (fRefreshSingleElementAction != null)
633 fRefreshSingleElementAction.setEnabled(!isEmpty);
637 * Restores the type hierarchy settings from a memento.
638 * @param memento the memento
640 private void restoreState(IMemento memento) {
641 fSearchScopeActions.restoreState(memento);
644 private void initCallMode() {
648 mode = fDialogSettings.getInt(DIALOGSTORE_CALL_MODE);
650 if ((mode < 0) || (mode > 1)) {
651 mode = CALL_MODE_CALLERS;
653 } catch (NumberFormatException e) {
654 mode = CALL_MODE_CALLERS;
658 fCurrentCallMode = -1;
660 // will fill the main tool bar
664 private void initFieldMode() {
668 mode = fDialogSettings.getInt(DIALOGSTORE_FIELD_MODE);
671 case IJavaSearchConstants.REFERENCES:
672 case IJavaSearchConstants.READ_ACCESSES:
673 case IJavaSearchConstants.WRITE_ACCESSES:
676 mode = IJavaSearchConstants.REFERENCES;
678 } catch (NumberFormatException e) {
679 mode = IJavaSearchConstants.REFERENCES;
683 fCurrentFieldMode = -1;
685 // will fill the main tool bar
689 private void initOrientation() {
692 fOrientation = fDialogSettings.getInt(DIALOGSTORE_VIEWORIENTATION);
694 if ((fOrientation < 0) || (fOrientation > 3)) {
695 fOrientation = VIEW_ORIENTATION_AUTOMATIC;
697 } catch (NumberFormatException e) {
698 fOrientation = VIEW_ORIENTATION_AUTOMATIC;
702 fCurrentOrientation = -1;
703 setOrientation(fOrientation);
706 private void fillViewMenu() {
707 IActionBars actionBars = getViewSite().getActionBars();
708 IMenuManager viewMenu = actionBars.getMenuManager();
709 viewMenu.add(new Separator());
711 for (int i = 0; i < fToggleCallModeActions.length; i++) {
712 viewMenu.add(fToggleCallModeActions[i]);
715 viewMenu.add(new Separator());
717 MenuManager layoutSubMenu= new MenuManager(CallHierarchyMessages.CallHierarchyViewPart_layout_menu);
718 for (int i = 0; i < fToggleOrientationActions.length; i++) {
719 layoutSubMenu.add(fToggleOrientationActions[i]);
721 viewMenu.add(layoutSubMenu);
723 viewMenu.add(new Separator(IContextMenuConstants.GROUP_SEARCH));
725 MenuManager fieldSubMenu= new MenuManager(CallHierarchyMessages.CallHierarchyViewPart_field_menu);
726 for (int i = 0; i < fToggleFieldModeActions.length; i++) {
727 fieldSubMenu.add(fToggleFieldModeActions[i]);
729 viewMenu.add(fieldSubMenu);
730 viewMenu.add(fShowSearchInDialogAction);
734 public void dispose() {
735 if (fActionGroups != null)
736 fActionGroups.dispose();
738 if (fClipboard != null)
739 fClipboard.dispose();
741 if (fPartListener != null) {
742 getViewSite().getPage().removePartListener(fPartListener);
749 * Goes to the selected entry, without updating the order of history entries.
750 * @param entry the history entry
752 public void gotoHistoryEntry(IMember[] entry) {
753 for (Iterator<IMember[]> iter= getMethodHistory().iterator(); iter.hasNext(); ) {
754 if (Arrays.equals(entry, iter.next())) {
755 setInputElements(entry);
762 * Method declared on IViewPart.
765 public void init(IViewSite site, IMemento memento)
766 throws PartInitException {
767 super.init(site, memento);
774 public void refresh() {
775 setCalleeRoots(null);
776 setCallerRoots(null);
782 public void saveState(IMemento memento) {
783 if (fPagebook == null) {
784 // part has not been created
785 if (fMemento != null) { //Keep the old state;
786 memento.putMemento(fMemento);
792 fSearchScopeActions.saveState(memento);
795 public void selectionChanged(SelectionChangedEvent e) {
796 if (e.getSelectionProvider() == fCallHierarchyViewer) {
797 methodSelectionChanged(e.getSelection());
801 private void methodSelectionChanged(ISelection selection) {
802 if (selection instanceof IStructuredSelection && ((IStructuredSelection) selection).size() == 1) {
803 Object selectedElement = ((IStructuredSelection) selection).getFirstElement();
805 if (selectedElement instanceof MethodWrapper) {
806 MethodWrapper methodWrapper = (MethodWrapper) selectedElement;
808 revealElementInEditor(methodWrapper, fCallHierarchyViewer);
809 updateLocationsView(methodWrapper);
811 updateLocationsView(null);
814 updateLocationsView(null);
818 private void revealElementInEditor(Object elem, Viewer originViewer) {
819 // only allow revealing when the type hierarchy is the active pagae
820 // no revealing after selection events due to model changes
821 if (getSite().getPage().getActivePart() != this) {
825 if (fSelectionProviderMediator.getViewerInFocus() != originViewer) {
829 if (elem instanceof MethodWrapper) {
830 CallLocation callLocation = CallHierarchy.getCallLocation(elem);
832 if (callLocation != null) {
833 IEditorPart editorPart = CallHierarchyUI.isOpenInEditor(callLocation);
835 if (editorPart != null) {
836 getSite().getPage().bringToTop(editorPart);
838 if (editorPart instanceof ITextEditor) {
839 ITextEditor editor = (ITextEditor) editorPart;
840 editor.selectAndReveal(callLocation.getStart(),
841 (callLocation.getEnd() - callLocation.getStart()));
845 IEditorPart editorPart = CallHierarchyUI.isOpenInEditor(elem);
846 getSite().getPage().bringToTop(editorPart);
847 EditorUtility.revealInEditor(editorPart,
848 ((MethodWrapper) elem).getMember());
850 } else if (elem instanceof IJavaElement) {
851 IEditorPart editorPart = EditorUtility.isOpenInEditor(elem);
853 if (editorPart != null) {
854 // getSite().getPage().removePartListener(fPartListener);
855 getSite().getPage().bringToTop(editorPart);
856 EditorUtility.revealInEditor(editorPart, (IJavaElement) elem);
858 // getSite().getPage().addPartListener(fPartListener);
867 public Object getAdapter(Class adapter) {
868 if (adapter == IShowInSource.class) {
869 return getShowInSource();
871 if (adapter == IContextProvider.class) {
872 return JavaUIHelp.getHelpContextProvider(this, IJavaHelpContextIds.CALL_HIERARCHY_VIEW);
874 if (adapter == IShowInTargetList.class) {
875 return new IShowInTargetList() {
876 public String[] getShowInTargetIds() {
877 return new String[] { JavaUI.ID_PACKAGES, JavaPlugin.ID_RES_NAV };
881 return super.getAdapter(adapter);
885 * @return the <code>IShowInSource</code> for this view.
887 private IShowInSource getShowInSource() {
888 return new IShowInSource() {
889 public ShowInContext getShowInContext() {
890 return new ShowInContext(null, fSelectionProviderMediator.getSelection());
896 * Returns the current selection.
899 protected ISelection getSelection() {
900 StructuredViewer viewerInFocus= fSelectionProviderMediator.getViewerInFocus();
901 if (viewerInFocus != null) {
902 return viewerInFocus.getSelection();
904 return StructuredSelection.EMPTY;
907 protected void fillLocationViewerContextMenu(IMenuManager menu) {
908 JavaPlugin.createStandardGroups(menu);
910 menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fOpenLocationAction);
911 menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fRefreshSingleElementAction);
912 menu.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, fLocationCopyAction);
915 private IActionBars getActionBars() {
916 return getViewSite().getActionBars();
919 private void setCalleeRoots(MethodWrapper[] calleeRoots) {
920 this.fCalleeRoots = calleeRoots;
923 private MethodWrapper[] getCalleeRoots() {
924 if (fCalleeRoots == null) {
925 fCalleeRoots = CallHierarchy.getDefault().getCalleeRoots(fInputElements);
931 private void setCallerRoots(MethodWrapper[] callerRoots) {
932 this.fCallerRoots = callerRoots;
935 private MethodWrapper[] getCallerRoots() {
936 if (fCallerRoots != null && fCallerRoots.length > 0) {
937 // all caller roots have the same field mode, just check the first:
938 if (fCallerRoots[0].getFieldSearchMode() != fCurrentFieldMode) {
939 fCallerRoots= null; // field mode changed, re-initialize below
942 if (fCallerRoots == null) {
943 fCallerRoots = CallHierarchy.getDefault().getCallerRoots(fInputElements);
944 for (int i= 0; i < fCallerRoots.length; i++) {
945 fCallerRoots[i].setFieldSearchMode(fCurrentFieldMode);
953 * Adds the entry if new. Inserted at the beginning of the history entries list.
954 * @param entry the entry to add
956 private void addHistoryEntry(IMember[] entry) {
958 updateHistoryEntries(entry, entry);
962 * Updates the input, history and description for the new input.
964 * @param currentInput the current input
965 * @param entry the new input elements
968 void updateInputHistoryAndDescription(IMember[] currentInput, IMember[] entry) {
969 updateHistoryEntries(currentInput, entry);
970 fInputElements= entry;
971 setContentDescription(getIncludeMask());
975 * Updates the history with the latest input.
977 * @param currentInput the current input
978 * @param entry the new input elements
981 private void updateHistoryEntries(IMember[] currentInput, IMember[] entry) {
982 for (Iterator<IMember[]> iter= getMethodHistory().iterator(); iter.hasNext();) {
983 if (Arrays.equals(currentInput, iter.next())) {
988 getMethodHistory().add(0, entry);
989 fHistoryDropDownAction.setEnabled(true);
992 private void createLocationViewer(Composite parent) {
993 fLocationViewer= new LocationViewer(parent);
996 fLocationViewer.initContextMenu(new IMenuListener() {
997 public void menuAboutToShow(IMenuManager menu) {
998 fillLocationViewerContextMenu(menu);
1000 }, ID_CALL_HIERARCHY, getSite());
1003 private void createHierarchyLocationSplitter(Composite parent) {
1004 fHierarchyLocationSplitter = new SashForm(parent, SWT.NONE);
1007 private void createCallHierarchyViewer(Composite parent) {
1008 fCallHierarchyViewer = new CallHierarchyViewer(parent, this);
1010 fCallHierarchyViewer.addSelectionChangedListener(this);
1013 protected void fillCallHierarchyViewerContextMenu(IMenuManager menu) {
1014 JavaPlugin.createStandardGroups(menu);
1016 menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fRefreshSingleElementAction);
1017 menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, new Separator(GROUP_FOCUS));
1019 if (fFocusOnSelectionAction.canActionBeAdded()) {
1020 menu.appendToGroup(GROUP_FOCUS, fFocusOnSelectionAction);
1022 if (fExpandWithConstructorsAction.canActionBeAdded()) {
1023 menu.appendToGroup(GROUP_FOCUS, fExpandWithConstructorsAction);
1026 if (fRemoveFromViewAction.canActionBeAdded()){
1027 menu.appendToGroup(GROUP_FOCUS, fRemoveFromViewAction);
1030 fActionGroups.setContext(new ActionContext(getSelection()));
1031 fActionGroups.fillContextMenu(menu);
1032 fActionGroups.setContext(null);
1034 if (fCopyAction.canActionBeAdded()) {
1035 menu.appendToGroup(ICommonMenuConstants.GROUP_EDIT, fCopyAction);
1039 private void fillActionBars() {
1040 IActionBars actionBars = getActionBars();
1041 actionBars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), fRefreshSingleElementAction);
1042 actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), fRemoveFromViewAction);
1044 IToolBarManager toolBar = actionBars.getToolBarManager();
1046 fActionGroups.fillActionBars(actionBars);
1048 toolBar.add(fRefreshViewAction);
1049 toolBar.add(fCancelSearchAction);
1050 for (int i = 0; i < fToggleCallModeActions.length; i++) {
1051 toolBar.add(fToggleCallModeActions[i]);
1053 toolBar.add(fHistoryDropDownAction);
1054 toolBar.add(fPinViewAction);
1057 private void makeActions() {
1058 fRefreshViewAction = new RefreshViewAction(this);
1059 fRefreshSingleElementAction= new RefreshElementAction(fCallHierarchyViewer);
1061 new CallHierarchyOpenEditorHelper(fLocationViewer);
1062 new CallHierarchyOpenEditorHelper(fCallHierarchyViewer);
1064 fOpenLocationAction= new OpenLocationAction(this, getSite());
1065 fLocationCopyAction= fLocationViewer.initCopyAction(getViewSite(), fClipboard);
1066 fFocusOnSelectionAction = new FocusOnSelectionAction(this);
1067 fCopyAction= new CopyCallHierarchyAction(this, fClipboard, fCallHierarchyViewer);
1068 fSearchScopeActions = new SearchScopeActionGroup(this, fDialogSettings);
1069 fShowSearchInDialogAction= new ShowSearchInDialogAction(this, fCallHierarchyViewer);
1070 fFiltersActionGroup = new CallHierarchyFiltersActionGroup(this,
1071 fCallHierarchyViewer);
1072 fHistoryDropDownAction = new HistoryDropDownAction(this);
1073 fHistoryDropDownAction.setEnabled(false);
1074 fCancelSearchAction = new CancelSearchAction(this);
1075 setCancelEnabled(false);
1076 fExpandWithConstructorsAction= new ExpandWithConstructorsAction(this, fCallHierarchyViewer);
1077 fRemoveFromViewAction= new RemoveFromViewAction(this, fCallHierarchyViewer);
1078 fPinViewAction= new PinCallHierarchyViewAction(this);
1079 fToggleOrientationActions = new ToggleOrientationAction[] {
1080 new ToggleOrientationAction(this, VIEW_ORIENTATION_VERTICAL),
1081 new ToggleOrientationAction(this, VIEW_ORIENTATION_HORIZONTAL),
1082 new ToggleOrientationAction(this, VIEW_ORIENTATION_AUTOMATIC),
1083 new ToggleOrientationAction(this, VIEW_ORIENTATION_SINGLE)
1085 fRemoveFromViewAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_DELETE);
1086 fToggleCallModeActions = new ToggleCallModeAction[] {
1087 new ToggleCallModeAction(this, CALL_MODE_CALLERS),
1088 new ToggleCallModeAction(this, CALL_MODE_CALLEES)
1090 fToggleFieldModeActions = new SelectFieldModeAction[] {
1091 new SelectFieldModeAction(this, IJavaSearchConstants.REFERENCES),
1092 new SelectFieldModeAction(this, IJavaSearchConstants.READ_ACCESSES),
1093 new SelectFieldModeAction(this, IJavaSearchConstants.WRITE_ACCESSES)
1095 fActionGroups = new CompositeActionGroup(new ActionGroup[] {
1096 new OpenEditorActionGroup(this),
1097 new OpenViewActionGroup(this),
1098 new CCPActionGroup(this, true),
1099 new GenerateActionGroup(this),
1100 new RefactorActionGroup(this),
1101 new JavaSearchActionGroup(this),
1102 fSearchScopeActions, fFiltersActionGroup
1106 private void showOrHideCallDetailsView() {
1107 if (fShowCallDetails) {
1108 fHierarchyLocationSplitter.setMaximizedControl(null);
1110 fHierarchyLocationSplitter.setMaximizedControl(fCallHierarchyViewer.getControl());
1114 private void updateLocationsView(MethodWrapper methodWrapper) {
1115 if (methodWrapper != null && methodWrapper.getMethodCall().hasCallLocations()) {
1116 fLocationViewer.setInput(methodWrapper.getMethodCall().getCallLocations());
1118 fLocationViewer.clearViewer();
1122 private void updateHistoryEntries() {
1123 for (int i = getMethodHistory().size() - 1; i >= 0; i--) {
1124 IMember[] members = getMethodHistory().get(i);
1125 for (int j= 0; j < members.length; j++) {
1126 IMember member= members[j];
1127 if (! member.exists()) {
1128 getMethodHistory().remove(i);
1134 fHistoryDropDownAction.setEnabled(!getMethodHistory().isEmpty());
1137 private void updateView() {
1138 if (fInputElements != null) {
1139 showPage(PAGE_VIEWER);
1141 int includeMask= getIncludeMask();
1142 CallHierarchy.getDefault().setSearchScope(getSearchScope(includeMask));
1144 // set input to null so that setComparator does not cause a refresh on the old contents:
1145 fCallHierarchyViewer.setInput(null);
1146 if (fCurrentCallMode == CALL_MODE_CALLERS) {
1147 // sort caller hierarchy alphabetically (bug 111423) and make RealCallers the last in 'Expand With Constructors' mode
1148 fCallHierarchyViewer.setComparator(new ViewerComparator() {
1150 public int category(Object element) {
1151 return element instanceof RealCallers ? 1 : 0;
1154 fCallHierarchyViewer.setMethodWrappers(getCallerRoots());
1156 fCallHierarchyViewer.setComparator(null);
1157 fCallHierarchyViewer.setMethodWrappers(getCalleeRoots());
1159 setContentDescription(includeMask);
1164 * Sets the content description.
1166 * @param includeMask the include mask
1169 private void setContentDescription(int includeMask) {
1170 setContentDescription(computeContentDescription(includeMask));
1176 * Gets the include mask.
1178 * @return the include mask
1181 private int getIncludeMask() {
1182 return fShowSearchInDialogAction.getSearchInDialog().getIncludeMask();
1186 * Computes the content description for the call hierarchy computation.
1188 * @param includeMask the include mask
1189 * @return the content description
1192 private String computeContentDescription(int includeMask) {
1193 // see also HistoryAction.getElementLabel(IMember[])
1194 String scopeDescription= fSearchScopeActions.getFullDescription(includeMask);
1196 if (fInputElements.length == 1) {
1197 IMember element= fInputElements[0];
1198 String elementName= JavaElementLabels.getElementLabel(element, JavaElementLabels.ALL_DEFAULT);
1199 String[] args= new String[] { elementName, scopeDescription };
1200 if (fCurrentCallMode == CALL_MODE_CALLERS) {
1201 switch (element.getElementType()) {
1202 case IJavaElement.TYPE:
1203 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToConstructors, args);
1204 case IJavaElement.FIELD:
1205 switch (this.fCurrentFieldMode) {
1206 case IJavaSearchConstants.READ_ACCESSES:
1207 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToFieldRead, args);
1208 case IJavaSearchConstants.WRITE_ACCESSES:
1209 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToFieldWrite, args);
1210 default: // all references
1211 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToField, args);
1213 case IJavaElement.METHOD:
1214 case IJavaElement.INITIALIZER:
1216 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToMethod, args);
1219 switch (element.getElementType()) {
1220 case IJavaElement.TYPE:
1221 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromConstructors, args);
1222 case IJavaElement.FIELD:
1223 case IJavaElement.METHOD:
1224 case IJavaElement.INITIALIZER:
1226 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromMethod, args);
1231 if (fCurrentCallMode == CALL_MODE_CALLERS) {
1232 switch (fInputElements.length) {
1234 Assert.isTrue(false);
1237 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToMembers_2,
1238 new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription });
1241 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToMembers_more,
1242 new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription });
1245 switch (fInputElements.length) {
1247 Assert.isTrue(false);
1250 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromMembers_2,
1251 new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription });
1254 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromMembers_more,
1255 new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription });
1261 private static String getShortLabel(IMember member) {
1262 return JavaElementLabels.getElementLabel(member, 0L);
1265 static CallHierarchyViewPart findAndShowCallersView(IWorkbenchPartSite site) {
1266 IWorkbenchPage workbenchPage = site.getPage();
1267 CallHierarchyViewPart callersView = null;
1270 callersView = (CallHierarchyViewPart) workbenchPage.showView(CallHierarchyViewPart.ID_CALL_HIERARCHY);
1271 } catch (PartInitException e) {
1279 * Cancels the caller/callee search jobs that are currently running.
1282 fCallHierarchyViewer.cancelJobs();
1286 * Sets the enablement state of the cancel button.
1288 * @param enabled <code>true</code> if cancel should be enabled
1290 void setCancelEnabled(boolean enabled) {
1291 fCancelSearchAction.setEnabled(enabled);
1295 * Returns the call hierarchy viewer.
1297 * @return the call hierarchy viewer
1300 public CallHierarchyViewer getViewer() {
1301 return fCallHierarchyViewer;
1305 * Returns the location viewer.
1307 * @return the location viewer
1310 protected LocationViewer getLocationViewer() {
1311 return fLocationViewer;
1315 * Marks the view as pinned.
1317 * @param pinned if <code>true</code> the view is marked as pinned
1320 void setPinned(boolean pinned) {
1325 * Indicates whether the Call Hierarchy view is pinned.
1327 * @return <code>true</code> if the view is pinned, <code>false</code> otherwise
1330 boolean isPinned() {
1335 * Returns the method history.
1337 * @return the method history
1340 private List<IMember[]>getMethodHistory() {
1341 return CallHierarchyUI.getDefault().getMethodHistory();
1345 * @see org.eclipse.ui.part.WorkbenchPart#showBusy(boolean)
1349 public void showBusy(boolean busy) {
1350 super.showBusy(busy);
1352 getProgressService().warnOfContentChange();
1356 * Fetches the progress service for the workbench part site.
1358 * @return the progress service for the workbench part site
1361 private IWorkbenchSiteProgressService getProgressService() {
1362 IWorkbenchSiteProgressService service= null;
1363 Object siteService= getSite().getAdapter(IWorkbenchSiteProgressService.class);
1364 if (siteService != null)
1365 service= (IWorkbenchSiteProgressService)siteService;
1370 * Adds the new input elements to the current list.
1372 * @param newElements the new input elements to add
1375 void addInputElements(IMember[] newElements) {
1376 // Caveat: RemoveFromViewAction#run() disposes TreeItems. When we add a previously removed element,
1377 // we have to consider the real Tree state, not only fInputElements.
1379 List<IMember> inputElements= Arrays.asList(fInputElements);
1380 List<IMember> treeElements= new ArrayList<IMember>();
1381 TreeItem[] treeItems= fCallHierarchyViewer.getTree().getItems();
1382 for (int i= 0; i < treeItems.length; i++) {
1383 Object data= treeItems[i].getData();
1384 if (data instanceof MethodWrapper)
1385 treeElements.add(((MethodWrapper) data).getMember());
1388 List<IMember> newInput= new ArrayList<IMember>();
1389 newInput.addAll(inputElements);
1390 List<IMember> addedElements= new ArrayList<IMember>();
1392 for (int i= 0; i < newElements.length; i++) {
1393 IMember newElement= newElements[i];
1394 if (! inputElements.contains(newElement))
1395 newInput.add(newElement);
1396 if (! treeElements.contains(newElement))
1397 addedElements.add(newElement);
1399 if (treeElements.size() == 0)
1400 updateInputHistoryAndDescription(fInputElements, newElements);
1401 else if (newInput.size() > fInputElements.length)
1402 updateInputHistoryAndDescription(fInputElements, newInput.toArray(new IMember[newInput.size()]));
1403 if (addedElements.size() > 0)
1404 updateViewWithAddedElements(addedElements.toArray(new IMember[addedElements.size()]));
1408 * Updates the view with the newly added input elements.
1410 * @param newElements the newly added elements
1413 private void updateViewWithAddedElements(IMember[] newElements) {
1414 setCalleeRoots(null);
1415 setCallerRoots(null);
1416 MethodWrapper[] roots;
1417 if (getCallMode() == CALL_MODE_CALLERS)
1418 roots= CallHierarchy.getDefault().getCallerRoots(newElements);
1420 roots= CallHierarchy.getDefault().getCalleeRoots(newElements);
1421 CallHierarchyViewer hierarchyViewer= getViewer();
1422 TreeRoot treeRoot= hierarchyViewer.getTreeRoot(roots, true);
1423 hierarchyViewer.add(treeRoot, roots);
1424 for (int i= 0; i < roots.length; i++) {
1425 hierarchyViewer.setExpandedState(roots[i], true);
1427 hierarchyViewer.setSelection(new StructuredSelection(roots), true);