]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/callhierarchy/CallHierarchyViewPart.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / internal / ui / callhierarchy / CallHierarchyViewPart.java
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
7  *
8  * Contributors:
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;
19
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Iterator;
23 import java.util.List;
24
25 import org.eclipse.help.IContextProvider;
26
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;
42
43 import org.eclipse.core.runtime.Assert;
44
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;
63
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;
90
91 import org.eclipse.ui.texteditor.ITextEditor;
92
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;
97
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;
103
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;
113
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;
127
128
129 /**
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.
132  *
133  */
134 public class CallHierarchyViewPart extends ViewPart implements ICallHierarchyViewPart, ISelectionChangedListener {
135
136
137         private class CallHierarchySelectionProvider extends SelectionProviderMediator {
138
139                 public CallHierarchySelectionProvider(StructuredViewer[] viewers) {
140                         super(viewers, null);
141                 }
142
143                 /* (non-Javadoc)
144                  * @see org.eclipse.jdt.internal.ui.typehierarchy.SelectionProviderMediator#getSelection()
145                  */
146                 @Override
147                 public ISelection getSelection() {
148                         ISelection selection= super.getSelection();
149                         if (!selection.isEmpty()) {
150                                 return CallHierarchyUI.convertSelection(selection);
151                         }
152                         return selection;
153                 }
154         }
155
156
157         /*
158          * @since 3.5
159          */
160         private final class CallHierarchyOpenEditorHelper extends OpenAndLinkWithEditorHelper {
161                 public CallHierarchyOpenEditorHelper(StructuredViewer viewer) {
162                         super(viewer);
163                 }
164
165                 @Override
166                 protected void activate(ISelection selection) {
167                         final Object selectedElement= SelectionUtil.getSingleElement(selection);
168                         if (selectedElement != null)
169                                 CallHierarchyUI.openInEditor(selectedElement, getSite().getShell(), true);
170                 }
171
172                 @Override
173                 protected void linkToEditor(ISelection selection) {
174                         // not supported by this part
175                 }
176
177                 @Override
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());
182                                         if (!noError)
183                                                 return;
184                                 }
185                         }
186                 }
187
188         }
189
190
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$
194         /**
195          * The key to be used is <code>DIALOGSTORE_RATIO + fCurrentOrientation</code>.
196          */
197         private static final String DIALOGSTORE_RATIO= "CallHierarchyViewPart.ratio"; //$NON-NLS-1$
198
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$
207
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;
249
250
251     public CallHierarchyViewPart() {
252         super();
253
254         fDialogSettings = JavaPlugin.getDefault().getDialogSettings();
255
256         fIsPinned= false;
257     }
258
259     @Override
260         public void setFocus() {
261         fPagebook.setFocus();
262     }
263
264     /**
265      * Sets the history entries
266      * @param entries the new history entries
267      */
268     public void setHistoryEntries(IMember[][] entries) {
269         getMethodHistory().clear();
270
271         for (int i = 0; i < entries.length; i++) {
272             getMethodHistory().add(entries[i]);
273         }
274
275         updateHistoryEntries();
276     }
277
278     /**
279      * Gets all history entries.
280      * @return all history entries
281      */
282     public IMember[][] getHistoryEntries() {
283         if (getMethodHistory().size() > 0) {
284             updateHistoryEntries();
285         }
286
287         return getMethodHistory().toArray(new IMember[getMethodHistory().size()][]);
288     }
289
290     public void setInputElements(IMember[] members) {
291         IMember[] oldMembers= fInputElements;
292         fInputElements= members;
293
294         if (members == null || members.length == 0) {
295             showPage(PAGE_EMPTY);
296             return;
297         }
298
299         if (! Arrays.equals(members, oldMembers)) {
300                 addHistoryEntry(members);
301         }
302
303         refresh();
304     }
305
306     public IMember[] getInputElements() {
307         return fInputElements;
308     }
309
310     public MethodWrapper[] getCurrentMethodWrappers() {
311         if (fCurrentCallMode == CALL_MODE_CALLERS) {
312             return fCallerRoots;
313         } else {
314             return fCalleeRoots;
315         }
316     }
317
318     /**
319      * called from ToggleOrientationAction.
320      * @param orientation VIEW_ORIENTATION_HORIZONTAL or VIEW_ORIENTATION_VERTICAL
321      */
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);
329                 } else {
330                     if (fCurrentOrientation == VIEW_ORIENTATION_SINGLE) {
331                         setShowCallDetails(true);
332                     }
333
334                     boolean horizontal = orientation == VIEW_ORIENTATION_HORIZONTAL;
335                     fHierarchyLocationSplitter.setOrientation(horizontal ? SWT.HORIZONTAL
336                                                                          : SWT.VERTICAL);
337                 }
338
339                 fHierarchyLocationSplitter.layout();
340             }
341
342             updateCheckedState();
343
344             fCurrentOrientation = orientation;
345
346                         restoreSplitterRatio();
347         }
348     }
349
350         private void updateCheckedState() {
351                 for (int i= 0; i < fToggleOrientationActions.length; i++) {
352                         fToggleOrientationActions[i].setChecked(fOrientation == fToggleOrientationActions[i].getOrientation());
353                 }
354         }
355
356     /**
357      * called from ToggleCallModeAction.
358      * @param mode CALL_MODE_CALLERS or CALL_MODE_CALLEES
359      */
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());
364             }
365
366             fCurrentCallMode = mode;
367             fDialogSettings.put(DIALOGSTORE_CALL_MODE, mode);
368
369             updateView();
370         }
371     }
372
373         /**
374          * Returns the current call mode.
375          * 
376          * @return the current call mode: CALL_MODE_CALLERS or CALL_MODE_CALLEES
377          * @since 3.5
378          */
379         int getCallMode() {
380                 return fCurrentCallMode;
381         }
382
383
384     /**
385      * called from SelectFieldModeAction.
386      * @param mode IJavaSearchConstants.{REFERENCES,WRITE_ACCESS,READ_ACCESS}
387      */
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());
392             }
393
394             fCurrentFieldMode = mode;
395             fDialogSettings.put(DIALOGSTORE_FIELD_MODE, mode);
396
397             updateView();
398         }
399     }
400
401         /**
402          * Fetches the search scope with the appropriate include mask.
403          * 
404          * @param includeMask the include mask
405          * @return the search scope with the appropriate include mask
406          * @since 3.7
407          */
408     public IJavaSearchScope getSearchScope(int includeMask) {
409         return fSearchScopeActions.getSearchScope(includeMask);
410     }
411
412     public void setShowCallDetails(boolean show) {
413         fShowCallDetails = show;
414         showOrHideCallDetailsView();
415     }
416
417     private void initDragAndDrop() {
418         addDragAdapters(fCallHierarchyViewer);
419         addDropAdapters(fCallHierarchyViewer);
420         addDropAdapters(fLocationViewer);
421
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));
426     }
427
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;
431
432                 DelegatingDropAdapter delegatingDropAdapter= new DelegatingDropAdapter();
433                 delegatingDropAdapter.addDropTargetListener(new CallHierarchyTransferDropAdapter(this, viewer));
434                 delegatingDropAdapter.addDropTargetListener(new PluginTransferDropAdapter(viewer));
435
436                 viewer.addDropSupport(ops, transfers, delegatingDropAdapter);
437         }
438
439         private void addDragAdapters(StructuredViewer viewer) {
440                 int ops= DND.DROP_COPY | DND.DROP_LINK;
441
442                 Transfer[] transfers= new Transfer[] { LocalSelectionTransfer.getInstance(), ResourceTransfer.getInstance(), FileTransfer.getInstance()};
443
444                 DelegatingDragAdapter dragAdapter= new DelegatingDragAdapter() {
445                         @Override
446                         public void dragStart(DragSourceEvent event) {
447                                 IStructuredSelection selection= (IStructuredSelection) fSelectionProviderMediator.getSelection();
448                                 if (selection.isEmpty()) {
449                                         event.doit= false;
450                                         return;
451                                 }
452                                 super.dragStart(event);
453                         }
454                 };
455                 dragAdapter.addDragSourceListener(new SelectionTransferDragAdapter(fSelectionProviderMediator));
456                 dragAdapter.addDragSourceListener(new EditorInputTransferDragAdapter(fSelectionProviderMediator));
457                 dragAdapter.addDragSourceListener(new ResourceTransferDragAdapter(fSelectionProviderMediator));
458                 dragAdapter.addDragSourceListener(new FileTransferDragAdapter(fSelectionProviderMediator));
459
460                 viewer.addDragSupport(ops, transfers, dragAdapter);
461         }
462
463     @Override
464         public void createPartControl(Composite parent) {
465         fParent= parent;
466         addResizeListener(parent);
467         fPagebook = new PageBook(parent, SWT.NONE);
468
469         // Page 1: Viewers
470         createHierarchyLocationSplitter(fPagebook);
471         createCallHierarchyViewer(fHierarchyLocationSplitter);
472         createLocationViewer(fHierarchyLocationSplitter);
473
474         // Page 2: Nothing selected
475         fNoHierarchyShownLabel = new Label(fPagebook, SWT.TOP + SWT.LEFT + SWT.WRAP);
476         fNoHierarchyShownLabel.setText(CallHierarchyMessages.CallHierarchyViewPart_empty); //
477
478         showPage(PAGE_EMPTY);
479
480         PlatformUI.getWorkbench().getHelpSystem().setHelp(fPagebook, IJavaHelpContextIds.CALL_HIERARCHY_VIEW);
481
482         fSelectionProviderMediator = new CallHierarchySelectionProvider(new StructuredViewer[] {
483                     fCallHierarchyViewer, fLocationViewer
484                 });
485
486         IStatusLineManager slManager = getViewSite().getActionBars().getStatusLineManager();
487         fSelectionProviderMediator.addSelectionChangedListener(new StatusBarUpdater(slManager));
488         getSite().setSelectionProvider(fSelectionProviderMediator);
489
490         fCallHierarchyViewer.initContextMenu(
491                         new IMenuListener() {
492                             public void menuAboutToShow(IMenuManager menu) {
493                                 fillCallHierarchyViewerContextMenu(menu);
494                             }
495                         }, getSite(), fSelectionProviderMediator);
496
497
498         fClipboard= new Clipboard(parent.getDisplay());
499
500         makeActions();
501         fillViewMenu();
502         fillActionBars();
503                 initDragAndDrop();
504
505         initOrientation();
506         initCallMode();
507         initFieldMode();
508
509         if (fMemento != null) {
510             restoreState(fMemento);
511         }
512                 restoreSplitterRatio();
513                 addPartListener();
514    }
515
516         private void restoreSplitterRatio() {
517                 String ratio= fDialogSettings.get(DIALOGSTORE_RATIO + fCurrentOrientation);
518                 if (ratio == null)
519                         return;
520                 int intRatio= Integer.parseInt(ratio);
521         fHierarchyLocationSplitter.setWeights(new int[] {intRatio, 1000 - intRatio});
522         }
523
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);
530                 }
531         }
532
533         /**
534          * Tells whether the given part reference references this view.
535          * 
536          * @param partRef the workbench part reference
537          * @return <code>true</code> if the given part reference references this view
538          * @since 3.7
539          */
540         private boolean isThisView(IWorkbenchPartReference partRef) {
541                 if (!ID_CALL_HIERARCHY.equals(partRef.getId()))
542                         return false;
543                 String partRefSecondaryId= ((IViewReference)partRef).getSecondaryId();
544                 String thisSecondaryId= getViewSite().getSecondaryId();
545                 return thisSecondaryId == null && partRefSecondaryId == null || thisSecondaryId != null && thisSecondaryId.equals(partRefSecondaryId);
546         }
547
548         private void addPartListener() {
549                 fPartListener= new IPartListener2() {
550                         /* (non-Javadoc)
551                          * @see org.eclipse.ui.IPartListener2#partActivated(org.eclipse.ui.IWorkbenchPartReference)
552                          */
553                         public void partActivated(IWorkbenchPartReference partRef) {
554                                 if (isThisView(partRef))
555                                         CallHierarchyUI.getDefault().callHierarchyViewActivated(CallHierarchyViewPart.this);
556                         }
557
558                         public void partBroughtToTop(IWorkbenchPartReference partRef) { }
559
560                         /* (non-Javadoc)
561                          * @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference)
562                          */
563                         public void partClosed(IWorkbenchPartReference partRef) {
564                                 if (isThisView(partRef)) {
565                                         CallHierarchyUI.getDefault().callHierarchyViewClosed(CallHierarchyViewPart.this);
566                                         saveViewSettings();
567                                 }
568                         }
569
570                         /* (non-Javadoc)
571                          * @see org.eclipse.ui.IPartListener2#partDeactivated(org.eclipse.ui.IWorkbenchPartReference)
572                          */
573                         public void partDeactivated(IWorkbenchPartReference partRef) {
574                                 if (isThisView(partRef))
575                                         saveViewSettings();
576                         }
577
578                         public void partOpened(IWorkbenchPartReference partRef) { }
579                         public void partHidden(IWorkbenchPartReference partRef) { }
580                         public void partVisible(IWorkbenchPartReference partRef) { }
581                         public void partInputChanged(IWorkbenchPartReference partRef) { }
582                 };
583                 getViewSite().getPage().addPartListener(fPartListener);
584         }
585
586         protected void saveViewSettings() {
587                 saveSplitterRatio();
588                 fDialogSettings.put(DIALOGSTORE_VIEWORIENTATION, fOrientation);
589         }
590
591         private void addResizeListener(Composite parent) {
592                 parent.addControlListener(new ControlListener() {
593                         public void controlMoved(ControlEvent e) {
594                         }
595                         public void controlResized(ControlEvent e) {
596                                 computeOrientation();
597                         }
598                 });
599         }
600
601         void computeOrientation() {
602                 saveSplitterRatio();
603                 fDialogSettings.put(DIALOGSTORE_VIEWORIENTATION, fOrientation);
604                 if (fOrientation != VIEW_ORIENTATION_AUTOMATIC) {
605                         setOrientation(fOrientation);
606                 }
607                 else {
608                         if (fOrientation == VIEW_ORIENTATION_SINGLE)
609                                 return;
610                         Point size= fParent.getSize();
611                         if (size.x != 0 && size.y != 0) {
612                                 if (size.x > size.y)
613                                         setOrientation(VIEW_ORIENTATION_HORIZONTAL);
614                                 else
615                                         setOrientation(VIEW_ORIENTATION_VERTICAL);
616                         }
617                 }
618         }
619
620     private void showPage(int page) {
621                 boolean isEmpty= page == PAGE_EMPTY;
622                 Control control= isEmpty ? (Control) fNoHierarchyShownLabel : fHierarchyLocationSplitter;
623                 if (isEmpty) {
624                         setContentDescription(""); //$NON-NLS-1$
625                         setTitleToolTip(getPartName());
626                         getViewSite().getActionBars().getStatusLineManager().setMessage(""); //$NON-NLS-1$
627                         getViewer().clearViewer();
628                 }
629                 fPagebook.showPage(control);
630                 if (fRefreshViewAction != null)
631                         fRefreshViewAction.setEnabled(!isEmpty);
632                 if (fRefreshSingleElementAction != null)
633                         fRefreshSingleElementAction.setEnabled(!isEmpty);
634     }
635
636     /**
637      * Restores the type hierarchy settings from a memento.
638      * @param memento the memento
639      */
640     private void restoreState(IMemento memento) {
641         fSearchScopeActions.restoreState(memento);
642     }
643
644     private void initCallMode() {
645         int mode;
646
647         try {
648             mode = fDialogSettings.getInt(DIALOGSTORE_CALL_MODE);
649
650             if ((mode < 0) || (mode > 1)) {
651                 mode = CALL_MODE_CALLERS;
652             }
653         } catch (NumberFormatException e) {
654             mode = CALL_MODE_CALLERS;
655         }
656
657         // force the update
658         fCurrentCallMode = -1;
659
660         // will fill the main tool bar
661         setCallMode(mode);
662     }
663
664     private void initFieldMode() {
665         int mode;
666
667         try {
668             mode = fDialogSettings.getInt(DIALOGSTORE_FIELD_MODE);
669
670             switch (mode) {
671                 case IJavaSearchConstants.REFERENCES:
672                 case IJavaSearchConstants.READ_ACCESSES:
673                 case IJavaSearchConstants.WRITE_ACCESSES:
674                         break; // OK
675             default:
676                 mode = IJavaSearchConstants.REFERENCES;
677             }
678         } catch (NumberFormatException e) {
679             mode = IJavaSearchConstants.REFERENCES;
680         }
681
682         // force the update
683         fCurrentFieldMode = -1;
684
685         // will fill the main tool bar
686         setFieldMode(mode);
687     }
688
689     private void initOrientation() {
690
691         try {
692             fOrientation = fDialogSettings.getInt(DIALOGSTORE_VIEWORIENTATION);
693
694             if ((fOrientation < 0) || (fOrientation > 3)) {
695                 fOrientation = VIEW_ORIENTATION_AUTOMATIC;
696             }
697         } catch (NumberFormatException e) {
698                 fOrientation = VIEW_ORIENTATION_AUTOMATIC;
699         }
700
701         // force the update
702         fCurrentOrientation = -1;
703         setOrientation(fOrientation);
704     }
705
706     private void fillViewMenu() {
707         IActionBars actionBars = getViewSite().getActionBars();
708         IMenuManager viewMenu = actionBars.getMenuManager();
709         viewMenu.add(new Separator());
710
711         for (int i = 0; i < fToggleCallModeActions.length; i++) {
712             viewMenu.add(fToggleCallModeActions[i]);
713         }
714
715         viewMenu.add(new Separator());
716
717         MenuManager layoutSubMenu= new MenuManager(CallHierarchyMessages.CallHierarchyViewPart_layout_menu);
718         for (int i = 0; i < fToggleOrientationActions.length; i++) {
719                 layoutSubMenu.add(fToggleOrientationActions[i]);
720         }
721         viewMenu.add(layoutSubMenu);
722
723                 viewMenu.add(new Separator(IContextMenuConstants.GROUP_SEARCH));
724
725         MenuManager fieldSubMenu= new MenuManager(CallHierarchyMessages.CallHierarchyViewPart_field_menu);
726         for (int i = 0; i < fToggleFieldModeActions.length; i++) {
727                 fieldSubMenu.add(fToggleFieldModeActions[i]);
728         }
729         viewMenu.add(fieldSubMenu);
730         viewMenu.add(fShowSearchInDialogAction);
731     }
732
733         @Override
734         public void dispose() {
735                 if (fActionGroups != null)
736                         fActionGroups.dispose();
737
738                 if (fClipboard != null)
739                         fClipboard.dispose();
740
741                 if (fPartListener != null) {
742                         getViewSite().getPage().removePartListener(fPartListener);
743                         fPartListener= null;
744                 }
745                 super.dispose();
746         }
747
748     /**
749      * Goes to the selected entry, without updating the order of history entries.
750      * @param entry the history entry
751      */
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);
756                                 return;
757                         }
758                 }
759     }
760
761     /* (non-Javadoc)
762      * Method declared on IViewPart.
763      */
764     @Override
765         public void init(IViewSite site, IMemento memento)
766         throws PartInitException {
767         super.init(site, memento);
768         fMemento = memento;
769     }
770
771     /**
772      *
773      */
774     public void refresh() {
775         setCalleeRoots(null);
776         setCallerRoots(null);
777
778         updateView();
779     }
780
781     @Override
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);
787             }
788
789             return;
790         }
791
792         fSearchScopeActions.saveState(memento);
793     }
794
795     public void selectionChanged(SelectionChangedEvent e) {
796         if (e.getSelectionProvider() == fCallHierarchyViewer) {
797             methodSelectionChanged(e.getSelection());
798         }
799     }
800
801     private void methodSelectionChanged(ISelection selection) {
802         if (selection instanceof IStructuredSelection && ((IStructuredSelection) selection).size() == 1) {
803             Object selectedElement = ((IStructuredSelection) selection).getFirstElement();
804
805             if (selectedElement instanceof MethodWrapper) {
806                 MethodWrapper methodWrapper = (MethodWrapper) selectedElement;
807
808                 revealElementInEditor(methodWrapper, fCallHierarchyViewer);
809                 updateLocationsView(methodWrapper);
810             } else {
811                 updateLocationsView(null);
812             }
813         } else {
814                 updateLocationsView(null);
815         }
816     }
817
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) {
822             return;
823         }
824
825         if (fSelectionProviderMediator.getViewerInFocus() != originViewer) {
826             return;
827         }
828
829         if (elem instanceof MethodWrapper) {
830             CallLocation callLocation = CallHierarchy.getCallLocation(elem);
831
832             if (callLocation != null) {
833                 IEditorPart editorPart = CallHierarchyUI.isOpenInEditor(callLocation);
834
835                 if (editorPart != null) {
836                     getSite().getPage().bringToTop(editorPart);
837
838                     if (editorPart instanceof ITextEditor) {
839                         ITextEditor editor = (ITextEditor) editorPart;
840                         editor.selectAndReveal(callLocation.getStart(),
841                             (callLocation.getEnd() - callLocation.getStart()));
842                     }
843                 }
844             } else {
845                 IEditorPart editorPart = CallHierarchyUI.isOpenInEditor(elem);
846                 getSite().getPage().bringToTop(editorPart);
847                 EditorUtility.revealInEditor(editorPart,
848                     ((MethodWrapper) elem).getMember());
849             }
850         } else if (elem instanceof IJavaElement) {
851             IEditorPart editorPart = EditorUtility.isOpenInEditor(elem);
852
853             if (editorPart != null) {
854                 //            getSite().getPage().removePartListener(fPartListener);
855                 getSite().getPage().bringToTop(editorPart);
856                 EditorUtility.revealInEditor(editorPart, (IJavaElement) elem);
857
858                 //            getSite().getPage().addPartListener(fPartListener);
859             }
860         }
861     }
862
863     /**
864          * {@inheritDoc}
865          */
866     @Override
867         public Object getAdapter(Class adapter) {
868         if (adapter == IShowInSource.class) {
869                 return getShowInSource();
870         }
871         if (adapter == IContextProvider.class) {
872                 return JavaUIHelp.getHelpContextProvider(this, IJavaHelpContextIds.CALL_HIERARCHY_VIEW);
873         }
874                 if (adapter == IShowInTargetList.class) {
875                         return new IShowInTargetList() {
876                                 public String[] getShowInTargetIds() {
877                                         return new String[] { JavaUI.ID_PACKAGES, JavaPlugin.ID_RES_NAV };
878                                 }
879                         };
880                 }
881         return super.getAdapter(adapter);
882     }
883
884         /**
885          * @return the <code>IShowInSource</code> for this view.
886          */
887         private IShowInSource getShowInSource() {
888                 return new IShowInSource() {
889                         public ShowInContext getShowInContext() {
890                                 return new ShowInContext(null, fSelectionProviderMediator.getSelection());
891                         }
892                 };
893         }
894         
895     /**
896      * Returns the current selection.
897      * @return selection
898      */
899     protected ISelection getSelection() {
900         StructuredViewer viewerInFocus= fSelectionProviderMediator.getViewerInFocus();
901                 if (viewerInFocus != null) {
902                         return viewerInFocus.getSelection();
903                 }
904                 return StructuredSelection.EMPTY;
905     }
906
907     protected void fillLocationViewerContextMenu(IMenuManager menu) {
908         JavaPlugin.createStandardGroups(menu);
909
910         menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fOpenLocationAction);
911                 menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fRefreshSingleElementAction);
912         menu.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, fLocationCopyAction);
913     }
914
915     private IActionBars getActionBars() {
916         return getViewSite().getActionBars();
917     }
918
919     private void setCalleeRoots(MethodWrapper[] calleeRoots) {
920         this.fCalleeRoots = calleeRoots;
921     }
922
923     private MethodWrapper[] getCalleeRoots() {
924         if (fCalleeRoots == null) {
925             fCalleeRoots = CallHierarchy.getDefault().getCalleeRoots(fInputElements);
926         }
927
928         return fCalleeRoots;
929     }
930
931     private void setCallerRoots(MethodWrapper[] callerRoots) {
932         this.fCallerRoots = callerRoots;
933     }
934
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
940                 }
941         }
942         if (fCallerRoots == null) {
943             fCallerRoots = CallHierarchy.getDefault().getCallerRoots(fInputElements);
944                 for (int i= 0; i < fCallerRoots.length; i++) {
945                         fCallerRoots[i].setFieldSearchMode(fCurrentFieldMode);
946                         }
947         }
948
949         return fCallerRoots;
950     }
951
952     /**
953      * Adds the entry if new. Inserted at the beginning of the history entries list.
954      * @param entry the entry to add
955      */
956     private void addHistoryEntry(IMember[] entry) {
957
958                 updateHistoryEntries(entry, entry);
959     }
960
961         /**
962          * Updates the input, history and description for the new input.
963          * 
964          * @param currentInput the current input
965          * @param entry the new input elements
966          * @since 3.7
967          */
968         void updateInputHistoryAndDescription(IMember[] currentInput, IMember[] entry) {
969                 updateHistoryEntries(currentInput, entry);
970                 fInputElements= entry;
971                 setContentDescription(getIncludeMask());
972         }
973
974         /**
975          * Updates the history with the latest input.
976          * 
977          * @param currentInput the current input
978          * @param entry the new input elements
979          * @since 3.7
980          */
981         private void updateHistoryEntries(IMember[] currentInput, IMember[] entry) {
982                 for (Iterator<IMember[]> iter= getMethodHistory().iterator(); iter.hasNext();) {
983                         if (Arrays.equals(currentInput, iter.next())) {
984                                 iter.remove();
985                         }
986                 }
987
988         getMethodHistory().add(0, entry);
989         fHistoryDropDownAction.setEnabled(true);
990     }
991
992     private void createLocationViewer(Composite parent) {
993         fLocationViewer= new LocationViewer(parent);
994
995
996         fLocationViewer.initContextMenu(new IMenuListener() {
997                 public void menuAboutToShow(IMenuManager menu) {
998                     fillLocationViewerContextMenu(menu);
999                 }
1000             }, ID_CALL_HIERARCHY, getSite());
1001     }
1002
1003     private void createHierarchyLocationSplitter(Composite parent) {
1004         fHierarchyLocationSplitter = new SashForm(parent, SWT.NONE);
1005     }
1006
1007     private void createCallHierarchyViewer(Composite parent) {
1008         fCallHierarchyViewer = new CallHierarchyViewer(parent, this);
1009
1010         fCallHierarchyViewer.addSelectionChangedListener(this);
1011     }
1012
1013     protected void fillCallHierarchyViewerContextMenu(IMenuManager menu) {
1014         JavaPlugin.createStandardGroups(menu);
1015
1016                 menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, fRefreshSingleElementAction);
1017         menu.appendToGroup(IContextMenuConstants.GROUP_SHOW, new Separator(GROUP_FOCUS));
1018
1019         if (fFocusOnSelectionAction.canActionBeAdded()) {
1020             menu.appendToGroup(GROUP_FOCUS, fFocusOnSelectionAction);
1021         }
1022         if (fExpandWithConstructorsAction.canActionBeAdded()) {
1023                 menu.appendToGroup(GROUP_FOCUS, fExpandWithConstructorsAction);
1024         }
1025         
1026         if (fRemoveFromViewAction.canActionBeAdded()){
1027                 menu.appendToGroup(GROUP_FOCUS, fRemoveFromViewAction);
1028         }
1029
1030         fActionGroups.setContext(new ActionContext(getSelection()));
1031         fActionGroups.fillContextMenu(menu);
1032         fActionGroups.setContext(null);
1033
1034                 if (fCopyAction.canActionBeAdded()) {
1035                         menu.appendToGroup(ICommonMenuConstants.GROUP_EDIT, fCopyAction);
1036                 }
1037     }
1038
1039     private void fillActionBars() {
1040         IActionBars actionBars = getActionBars();
1041                 actionBars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), fRefreshSingleElementAction);
1042                 actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), fRemoveFromViewAction);
1043
1044         IToolBarManager toolBar = actionBars.getToolBarManager();
1045
1046         fActionGroups.fillActionBars(actionBars);
1047
1048         toolBar.add(fRefreshViewAction);
1049         toolBar.add(fCancelSearchAction);
1050         for (int i = 0; i < fToggleCallModeActions.length; i++) {
1051             toolBar.add(fToggleCallModeActions[i]);
1052         }
1053         toolBar.add(fHistoryDropDownAction);
1054         toolBar.add(fPinViewAction);
1055     }
1056
1057     private void makeActions() {
1058         fRefreshViewAction = new RefreshViewAction(this);
1059         fRefreshSingleElementAction= new RefreshElementAction(fCallHierarchyViewer);
1060
1061                 new CallHierarchyOpenEditorHelper(fLocationViewer);
1062                 new CallHierarchyOpenEditorHelper(fCallHierarchyViewer);
1063
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)
1084             };
1085                 fRemoveFromViewAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_DELETE);
1086         fToggleCallModeActions = new ToggleCallModeAction[] {
1087                 new ToggleCallModeAction(this, CALL_MODE_CALLERS),
1088                 new ToggleCallModeAction(this, CALL_MODE_CALLEES)
1089             };
1090         fToggleFieldModeActions = new SelectFieldModeAction[] {
1091                 new SelectFieldModeAction(this, IJavaSearchConstants.REFERENCES),
1092                 new SelectFieldModeAction(this, IJavaSearchConstants.READ_ACCESSES),
1093                 new SelectFieldModeAction(this, IJavaSearchConstants.WRITE_ACCESSES)
1094             };
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
1103                 });
1104     }
1105
1106     private void showOrHideCallDetailsView() {
1107         if (fShowCallDetails) {
1108             fHierarchyLocationSplitter.setMaximizedControl(null);
1109         } else {
1110             fHierarchyLocationSplitter.setMaximizedControl(fCallHierarchyViewer.getControl());
1111         }
1112     }
1113
1114     private void updateLocationsView(MethodWrapper methodWrapper) {
1115         if (methodWrapper != null && methodWrapper.getMethodCall().hasCallLocations()) {
1116             fLocationViewer.setInput(methodWrapper.getMethodCall().getCallLocations());
1117         } else {
1118             fLocationViewer.clearViewer();
1119         }
1120     }
1121
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);
1129                                         break;
1130                                 }
1131                         }
1132         }
1133
1134         fHistoryDropDownAction.setEnabled(!getMethodHistory().isEmpty());
1135     }
1136
1137         private void updateView() {
1138                 if (fInputElements != null) {
1139                         showPage(PAGE_VIEWER);
1140
1141                         int includeMask= getIncludeMask();
1142                         CallHierarchy.getDefault().setSearchScope(getSearchScope(includeMask));
1143
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() {
1149                                         @Override
1150                                         public int category(Object element) {
1151                                                 return element instanceof RealCallers ? 1 : 0;
1152                                         }
1153                                 });
1154                         fCallHierarchyViewer.setMethodWrappers(getCallerRoots());
1155                         } else {
1156                                 fCallHierarchyViewer.setComparator(null);
1157                                 fCallHierarchyViewer.setMethodWrappers(getCalleeRoots());
1158                         }
1159                         setContentDescription(includeMask);
1160                 }
1161     }
1162
1163         /**
1164          * Sets the content description.
1165          * 
1166          * @param includeMask the include mask
1167          * @since 3.7
1168          */
1169         private void setContentDescription(int includeMask) {
1170                 setContentDescription(computeContentDescription(includeMask));
1171         }
1172
1173
1174
1175         /**
1176          * Gets the include mask.
1177          * 
1178          * @return the include mask
1179          * @since 3.7
1180          */
1181         private int getIncludeMask() {
1182                 return fShowSearchInDialogAction.getSearchInDialog().getIncludeMask();
1183         }
1184
1185         /**
1186          * Computes the content description for the call hierarchy computation.
1187          * 
1188          * @param includeMask the include mask
1189          * @return the content description
1190          * @since 3.7
1191          */
1192         private String computeContentDescription(int includeMask) {
1193                 // see also HistoryAction.getElementLabel(IMember[])
1194                 String scopeDescription= fSearchScopeActions.getFullDescription(includeMask);
1195
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);
1212                                                 }
1213                                         case IJavaElement.METHOD:
1214                                         case IJavaElement.INITIALIZER:
1215                                         default:
1216                                                 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToMethod, args);
1217                                 }
1218                         } else {
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:
1225                                         default:
1226                                                 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromMethod, args);
1227                                 }
1228                         }
1229
1230                 } else {
1231                         if (fCurrentCallMode == CALL_MODE_CALLERS) {
1232                                 switch (fInputElements.length) {
1233                                 case 0:
1234                                         Assert.isTrue(false);
1235                                         return null;
1236                                 case 2:
1237                                         return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToMembers_2,
1238                                                         new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription });
1239
1240                                 default:
1241                                         return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsToMembers_more,
1242                                                         new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription });
1243                                 }
1244                         } else {
1245                                 switch (fInputElements.length) {
1246                                         case 0:
1247                                                 Assert.isTrue(false);
1248                                                 return null;
1249                                         case 2:
1250                                                 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromMembers_2,
1251                                                                 new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription });
1252
1253                                         default:
1254                                                 return Messages.format(CallHierarchyMessages.CallHierarchyViewPart_callsFromMembers_more,
1255                                                                 new String[] { getShortLabel(fInputElements[0]), getShortLabel(fInputElements[1]), scopeDescription });
1256                                 }
1257                         }
1258                 }
1259         }
1260
1261         private static String getShortLabel(IMember member) {
1262                 return JavaElementLabels.getElementLabel(member, 0L);
1263         }
1264
1265     static CallHierarchyViewPart findAndShowCallersView(IWorkbenchPartSite site) {
1266         IWorkbenchPage workbenchPage = site.getPage();
1267         CallHierarchyViewPart callersView = null;
1268
1269         try {
1270             callersView = (CallHierarchyViewPart) workbenchPage.showView(CallHierarchyViewPart.ID_CALL_HIERARCHY);
1271         } catch (PartInitException e) {
1272             JavaPlugin.log(e);
1273         }
1274
1275         return callersView;
1276     }
1277
1278     /**
1279      * Cancels the caller/callee search jobs that are currently running.
1280      */
1281     void cancelJobs() {
1282         fCallHierarchyViewer.cancelJobs();
1283     }
1284
1285         /**
1286          * Sets the enablement state of the cancel button.
1287          *
1288          * @param enabled <code>true</code> if cancel should be enabled
1289          */
1290     void setCancelEnabled(boolean enabled) {
1291         fCancelSearchAction.setEnabled(enabled);
1292     }
1293
1294     /**
1295      * Returns the call hierarchy viewer.
1296      * 
1297      * @return the call hierarchy viewer
1298      * @since 3.5
1299      */
1300     public CallHierarchyViewer getViewer() {
1301         return fCallHierarchyViewer;
1302     }
1303
1304         /**
1305          * Returns the location viewer.
1306          * 
1307          * @return the location viewer
1308          * @since 3.6
1309          */
1310         protected LocationViewer getLocationViewer() {
1311                 return fLocationViewer;
1312         }
1313
1314         /**
1315          * Marks the view as pinned.
1316          * 
1317          * @param pinned if <code>true</code> the view is marked as pinned
1318          * @since 3.7
1319          */
1320         void setPinned(boolean pinned) {
1321                 fIsPinned= pinned;
1322         }
1323
1324         /**
1325          * Indicates whether the Call Hierarchy view is pinned.
1326          * 
1327          * @return <code>true</code> if the view is pinned, <code>false</code> otherwise
1328          * @since 3.7
1329          */
1330         boolean isPinned() {
1331                 return fIsPinned;
1332         }
1333
1334         /**
1335          * Returns the method history.
1336          * 
1337          * @return the method history
1338          * @since 3.7
1339          */
1340         private List<IMember[]>getMethodHistory() {
1341                 return CallHierarchyUI.getDefault().getMethodHistory();
1342         }
1343
1344         /*
1345          * @see org.eclipse.ui.part.WorkbenchPart#showBusy(boolean)
1346          * @since 3.7
1347          */
1348         @Override
1349         public void showBusy(boolean busy) {
1350                 super.showBusy(busy);
1351                 if (!busy)
1352                         getProgressService().warnOfContentChange();
1353         }
1354
1355         /**
1356          * Fetches the progress service for the workbench part site.
1357          * 
1358          * @return the progress service for the workbench part site
1359          * @since 3.7
1360          */
1361         private IWorkbenchSiteProgressService getProgressService() {
1362                 IWorkbenchSiteProgressService service= null;
1363                 Object siteService= getSite().getAdapter(IWorkbenchSiteProgressService.class);
1364                 if (siteService != null)
1365                         service= (IWorkbenchSiteProgressService)siteService;
1366                 return service;
1367         }
1368
1369         /**
1370          * Adds the new input elements to the current list.
1371          * 
1372          * @param newElements the new input elements to add
1373          * @since 3.7
1374          */
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.
1378                 
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());
1386                 }
1387                 
1388                 List<IMember> newInput= new ArrayList<IMember>();
1389                 newInput.addAll(inputElements);
1390                 List<IMember> addedElements= new ArrayList<IMember>();
1391                 
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);
1398                 }
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()]));
1405         }
1406
1407         /**
1408          * Updates the view with the newly added input elements.
1409          * 
1410          * @param newElements the newly added elements
1411          * @since 3.7
1412          */
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);
1419                 else
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);
1426                 }
1427                 hierarchyViewer.setSelection(new StructuredSelection(roots), true);
1428         }
1429 }