blob: 46ea82fb4cefabe7435a29bacdd29fb4ad7a62f8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.dltk.internal.ui.typehierarchy;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IMember;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ITypeHierarchy;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.internal.corext.util.Messages;
import org.eclipse.dltk.internal.ui.actions.CCPActionGroup;
import org.eclipse.dltk.internal.ui.actions.CompositeActionGroup;
import org.eclipse.dltk.internal.ui.actions.NewWizardsActionGroup;
import org.eclipse.dltk.internal.ui.actions.refactoring.RefactorActionGroup;
import org.eclipse.dltk.internal.ui.editor.EditorUtility;
import org.eclipse.dltk.internal.ui.workingsets.WorkingSetFilterActionGroup;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.dltk.ui.IContextMenuConstants;
import org.eclipse.dltk.ui.ITypeHierarchyViewPart;
import org.eclipse.dltk.ui.MembersOrderPreferenceCache;
import org.eclipse.dltk.ui.PreferenceConstants;
import org.eclipse.dltk.ui.ScriptElementLabels;
import org.eclipse.dltk.ui.actions.OpenEditorActionGroup;
import org.eclipse.dltk.ui.actions.OpenViewActionGroup;
import org.eclipse.dltk.ui.actions.SelectAllAction;
import org.eclipse.dltk.ui.util.ExceptionHandler;
import org.eclipse.dltk.ui.viewsupport.IViewPartInputProvider;
import org.eclipse.dltk.ui.viewsupport.ScriptUILabelProvider;
import org.eclipse.dltk.ui.viewsupport.SelectionProviderMediator;
import org.eclipse.dltk.ui.viewsupport.StatusBarUpdater;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.IBasicPropertyConstants;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.ActionGroup;
import org.eclipse.ui.contexts.IContextActivation;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.part.IShowInSource;
import org.eclipse.ui.part.IShowInTargetList;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.part.ShowInContext;
import org.eclipse.ui.part.ViewPart;
/**
* view showing the super types/sub types of its input.
*/
public class TypeHierarchyViewPart extends ViewPart
implements ITypeHierarchyViewPart, IViewPartInputProvider {
public static final int VIEW_ID_TYPE = 2;
public static final int VIEW_ID_SUPER = 0;
public static final int VIEW_ID_SUB = 1;
public static final int VIEW_ORIENTATION_VERTICAL = 0;
public static final int VIEW_ORIENTATION_HORIZONTAL = 1;
public static final int VIEW_ORIENTATION_SINGLE = 2;
public static final int VIEW_ORIENTATION_AUTOMATIC = 3;
private static final String DIALOGSTORE_HIERARCHYVIEW = "TypeHierarchyViewPart.hierarchyview"; //$NON-NLS-1$
private static final String DIALOGSTORE_VIEWORIENTATION = "TypeHierarchyViewPart.orientation"; //$NON-NLS-1$
private static final String TAG_INPUT = "input"; //$NON-NLS-1$
private static final String TAG_VIEW = "view"; //$NON-NLS-1$
private static final String TAG_ORIENTATION = "orientation"; //$NON-NLS-1$
private static final String TAG_RATIO = "ratio"; //$NON-NLS-1$
private static final String TAG_SELECTION = "selection"; //$NON-NLS-1$
private static final String TAG_VERTICAL_SCROLL = "vertical_scroll"; //$NON-NLS-1$
private static final String GROUP_FOCUS = "group.focus"; //$NON-NLS-1$
// the selected type in the hierarchy view
private IType fSelectedType;
// input element or null
private IModelElement fInputElement;
// history of input elements. No duplicates
private ArrayList<IModelElement> fInputHistory;
private IMemento fMemento;
private IDialogSettings fDialogSettings;
private TypeHierarchyLifeCycle fHierarchyLifeCycle;
private ITypeHierarchyLifeCycleListener fTypeHierarchyLifeCycleListener;
private IPropertyChangeListener fPropertyChangeListener;
private SelectionProviderMediator fSelectionProviderMediator;
private ISelectionChangedListener fSelectionChangedListener;
private IPartListener2 fPartListener;
private int fCurrentOrientation;
int fOrientation = VIEW_ORIENTATION_AUTOMATIC;
boolean fInComputeOrientation = false;
private boolean fLinkingEnabled;
private boolean fSelectInEditor;
private boolean fIsVisible;
private boolean fNeedRefresh;
private boolean fIsEnableMemberFilter;
private boolean fIsRefreshRunnablePosted;
private int fCurrentViewerIndex;
private TypeHierarchyViewer[] fAllViewers;
private MethodsViewer fMethodsViewer;
private SashForm fTypeMethodsSplitter;
private PageBook fViewerbook;
private PageBook fPagebook;
private Label fNoHierarchyShownLabel;
private Label fEmptyTypesViewer;
private ViewForm fTypeViewerViewForm;
private ViewForm fMethodViewerViewForm;
private CLabel fMethodViewerPaneLabel;
private ScriptUILabelProvider fPaneLabelProvider;
private Composite fParent;
private ToggleViewAction[] fViewActions;
private ToggleLinkingAction fToggleLinkingAction;
private HistoryDropDownAction fHistoryDropDownAction;
private ToggleOrientationAction[] fToggleOrientationActions;
private EnableMemberFilterAction fEnableMemberFilterAction;
private ShowQualifiedTypeNamesAction fShowQualifiedTypeNamesAction;
private FocusOnTypeAction fFocusOnTypeAction;
private FocusOnSelectionAction fFocusOnSelectionAction;
private CompositeActionGroup fActionGroups;
private SelectAllAction fSelectAllAction;
private WorkingSetFilterActionGroup fWorkingSetActionGroup;
private Job fRestoreStateJob;
private IContextActivation fContextActivation;
protected IPreferenceStore getPreferenceStore() {
return DLTKUIPlugin.getDefault().getPreferenceStore();
}
public TypeHierarchyViewPart() {
fSelectedType = null;
fInputElement = null;
fIsVisible = false;
fIsRefreshRunnablePosted = false;
fSelectInEditor = true;
fRestoreStateJob = null;
fHierarchyLifeCycle = new TypeHierarchyLifeCycle();
fTypeHierarchyLifeCycleListener = (typeHierarchy,
changedTypes) -> doTypeHierarchyChanged(typeHierarchy,
changedTypes);
fHierarchyLifeCycle.addChangedListener(fTypeHierarchyLifeCycleListener);
fPropertyChangeListener = event -> doPropertyChange(event);
// getPreferenceStore().addPropertyChangeListener(fPropertyChangeListener
// );
fIsEnableMemberFilter = false;
fInputHistory = new ArrayList<>();
fAllViewers = null;
fViewActions = new ToggleViewAction[] {
new ToggleViewAction(this, VIEW_ID_TYPE),
new ToggleViewAction(this, VIEW_ID_SUPER),
new ToggleViewAction(this, VIEW_ID_SUB) };
fDialogSettings = DLTKUIPlugin.getDefault().getDialogSettings();
fHistoryDropDownAction = new HistoryDropDownAction(this);
fHistoryDropDownAction.setEnabled(false);
fToggleOrientationActions = new ToggleOrientationAction[] {
new ToggleOrientationAction(this, VIEW_ORIENTATION_VERTICAL),
new ToggleOrientationAction(this, VIEW_ORIENTATION_HORIZONTAL),
new ToggleOrientationAction(this, VIEW_ORIENTATION_AUTOMATIC),
new ToggleOrientationAction(this, VIEW_ORIENTATION_SINGLE) };
fEnableMemberFilterAction = new EnableMemberFilterAction(this, false);
fShowQualifiedTypeNamesAction = new ShowQualifiedTypeNamesAction(this,
false);
fFocusOnTypeAction = new FocusOnTypeAction(this);
// TODO: DLTK: Please fix this to support
// DLTKLanguageManager.createScriptUILabelProvider()
fPaneLabelProvider = new ScriptUILabelProvider();
fFocusOnSelectionAction = new FocusOnSelectionAction(this);
fPartListener = new IPartListener2() {
@Override
public void partVisible(IWorkbenchPartReference ref) {
IWorkbenchPart part = ref.getPart(false);
if (part == TypeHierarchyViewPart.this) {
visibilityChanged(true);
}
}
@Override
public void partHidden(IWorkbenchPartReference ref) {
IWorkbenchPart part = ref.getPart(false);
if (part == TypeHierarchyViewPart.this) {
visibilityChanged(false);
}
}
@Override
public void partActivated(IWorkbenchPartReference ref) {
IWorkbenchPart part = ref.getPart(false);
if (part instanceof IEditorPart)
editorActivated((IEditorPart) part);
}
@Override
public void partInputChanged(IWorkbenchPartReference ref) {
IWorkbenchPart part = ref.getPart(false);
if (part instanceof IEditorPart)
editorActivated((IEditorPart) part);
}
@Override
public void partBroughtToTop(IWorkbenchPartReference ref) {
}
@Override
public void partClosed(IWorkbenchPartReference ref) {
}
@Override
public void partDeactivated(IWorkbenchPartReference ref) {
}
@Override
public void partOpened(IWorkbenchPartReference ref) {
}
};
fSelectionChangedListener = event -> doSelectionChanged(event);
fLinkingEnabled = getPreferenceStore()
.getBoolean(PreferenceConstants.LINK_TYPEHIERARCHY_TO_EDITOR);
}
/**
* Method doPropertyChange.
*
* @param event
*/
protected void doPropertyChange(PropertyChangeEvent event) {
String property = event.getProperty();
if (fMethodsViewer != null) {
if (MembersOrderPreferenceCache
.isMemberOrderProperty(event.getProperty())) {
fMethodsViewer.refresh();
}
}
if (IWorkingSetManager.CHANGE_WORKING_SET_CONTENT_CHANGE
.equals(property)) {
updateHierarchyViewer(true);
updateTitle();
}
}
/**
* Adds the entry if new. Inserted at the beginning of the history entries
* list.
*
* @param entry
* The new entry
*/
private void addHistoryEntry(IModelElement entry) {
if (fInputHistory.contains(entry)) {
fInputHistory.remove(entry);
}
fInputHistory.add(0, entry);
fHistoryDropDownAction.setEnabled(true);
}
private void updateHistoryEntries() {
for (int i = fInputHistory.size() - 1; i >= 0; i--) {
IModelElement type = fInputHistory.get(i);
if (!type.exists()) {
fInputHistory.remove(i);
}
}
fHistoryDropDownAction.setEnabled(!fInputHistory.isEmpty());
}
/**
* Goes to the selected entry, without updating the order of history
* entries.
*
* @param entry
* The entry to open
*/
public void gotoHistoryEntry(IModelElement entry) {
if (fInputHistory.contains(entry)) {
updateInput(entry);
}
}
/**
* Gets all history entries.
*
* @return All history entries
*/
public IModelElement[] getHistoryEntries() {
if (fInputHistory.size() > 0) {
updateHistoryEntries();
}
return fInputHistory.toArray(new IModelElement[fInputHistory.size()]);
}
/**
* Sets the history entries
*
* @param elems
* The history elements to set
*/
public void setHistoryEntries(IModelElement[] elems) {
fInputHistory.clear();
for (int i = 0; i < elems.length; i++) {
fInputHistory.add(elems[i]);
}
updateHistoryEntries();
}
/**
* Selects an member in the methods list or in the current hierarchy.
*
* @param member
* The member to select
*/
public void selectMember(IMember member) {
fSelectInEditor = false;
if (member.getElementType() != IModelElement.TYPE) {
Control methodControl = fMethodsViewer.getControl();
if (methodControl != null && !methodControl.isDisposed()) {
methodControl.setFocus();
}
fMethodsViewer.setSelection(new StructuredSelection(member), true);
} else {
Control viewerControl = getCurrentViewer().getControl();
if (viewerControl != null && !viewerControl.isDisposed()) {
viewerControl.setFocus();
}
if (!member.equals(fSelectedType)) {
getCurrentViewer().setSelection(new StructuredSelection(member),
true);
}
}
fSelectInEditor = true;
}
/**
* @return The input type
* @deprecated
*/
@Override
@Deprecated
public IType getInput() {
if (fInputElement instanceof IType) {
return (IType) fInputElement;
}
return null;
}
/**
* Sets the input to a new type
*
* @param type
* The new input type
* @deprecated
*/
@Override
@Deprecated
public void setInput(IType type) {
setInputElement(type);
}
/**
* Returns the input element of the type hierarchy. Can be of type
* <code>IType</code> or <code>IPackageFragment</code>
*
* @return the input element
*/
@Override
public IModelElement getInputElement() {
return fInputElement;
}
/**
* Sets the input to a new element.
*
* @param element
* the input element
*/
@Override
public void setInputElement(IModelElement element) {
IMember memberToSelect = null;
if (element != null) {
if (element instanceof IMember) {
if (element.getElementType() != IModelElement.TYPE) {
memberToSelect = (IMember) element;
element = memberToSelect.getDeclaringType();
}
if (element == null || !element.exists()) {
MessageDialog.openError(getSite().getShell(),
TypeHierarchyMessages.TypeHierarchyViewPart_error_title,
TypeHierarchyMessages.TypeHierarchyViewPart_error_message);
return;
}
} else {
int kind = element.getElementType();
if (kind != IModelElement.SCRIPT_PROJECT
&& kind != IModelElement.PROJECT_FRAGMENT) {
element = null;
DLTKUIPlugin.logErrorMessage(
"Invalid type hierarchy input type.");//$NON-NLS-1$
}
}
}
if (element != null && !element.equals(fInputElement)) {
addHistoryEntry(element);
}
updateInput(element);
if (memberToSelect != null) {
selectMember(memberToSelect);
}
}
/*
* Changes the input to a new type
*
* @param inputElement
*/
private void updateInput(IModelElement inputElement) {
IModelElement prevInput = fInputElement;
synchronized (this) {
if (fRestoreStateJob != null) {
fRestoreStateJob.cancel();
try {
fRestoreStateJob.join();
} catch (InterruptedException e) {
// ignore
} finally {
fRestoreStateJob = null;
}
}
}
// Make sure the UI got repainted before we execute a long running
// operation. This can be removed if we refresh the hierarchy in a
// separate thread.
// Work-araound for http://dev.eclipse.org/bugs/show_bug.cgi?id=30881
processOutstandingEvents();
if (inputElement == null) {
clearInput();
} else {
fInputElement = inputElement;
try {
fHierarchyLifeCycle.ensureRefreshedTypeHierarchy(inputElement,
DLTKUIPlugin.getActiveWorkbenchWindow());
// fHierarchyLifeCycle.ensureRefreshedTypeHierarchy(inputElement,
// getSite().getWorkbenchWindow());
} catch (InvocationTargetException e) {
ExceptionHandler.handle(e, getSite().getShell(),
TypeHierarchyMessages.TypeHierarchyViewPart_exception_title,
TypeHierarchyMessages.TypeHierarchyViewPart_exception_message);
clearInput();
return;
} catch (InterruptedException e) {
return;
}
if (inputElement.getElementType() != IModelElement.TYPE) {
setView(VIEW_ID_TYPE);
}
// turn off member filtering
fSelectInEditor = false;
setMemberFilter(null);
internalSelectType(null, false); // clear selection
fIsEnableMemberFilter = false;
if (!inputElement.equals(prevInput)) {
updateHierarchyViewer(true);
}
IType root = getSelectableType(inputElement);
internalSelectType(root, true);
updateMethodViewer(root);
updateToolbarButtons();
updateTitle();
enableMemberFilter(false);
fPagebook.showPage(fTypeMethodsSplitter);
fSelectInEditor = true;
}
}
private void processOutstandingEvents() {
Display display = getDisplay();
if (display != null && !display.isDisposed())
display.update();
}
private void clearInput() {
fInputElement = null;
fHierarchyLifeCycle.freeHierarchy();
updateHierarchyViewer(false);
updateToolbarButtons();
}
/*
* @see IWorbenchPart#setFocus
*/
@Override
public void setFocus() {
fPagebook.setFocus();
}
/*
* @see IWorkbenchPart#dispose
*/
@Override
public void dispose() {
if (fContextActivation != null) {
IContextService ctxService = getSite()
.getService(IContextService.class);
if (ctxService != null) {
ctxService.deactivateContext(fContextActivation);
}
}
fHierarchyLifeCycle.freeHierarchy();
fHierarchyLifeCycle
.removeChangedListener(fTypeHierarchyLifeCycleListener);
fPaneLabelProvider.dispose();
if (fMethodsViewer != null) {
fMethodsViewer.dispose();
}
if (fPropertyChangeListener != null) {
DLTKUIPlugin.getDefault().getPreferenceStore()
.removePropertyChangeListener(fPropertyChangeListener);
fPropertyChangeListener = null;
}
getSite().getPage().removePartListener(fPartListener);
if (fActionGroups != null)
fActionGroups.dispose();
if (fWorkingSetActionGroup != null) {
fWorkingSetActionGroup.dispose();
}
super.dispose();
}
@SuppressWarnings("unchecked")
@Override
public <T> T getAdapter(Class<T> key) {
if (key == IShowInSource.class) {
return (T) getShowInSource();
}
if (key == IShowInTargetList.class) {
return (T) (IShowInTargetList) () -> new String[] {
DLTKUIPlugin.ID_SCRIPT_EXPLORER, IPageLayout.ID_RES_NAV };
}
// if (key == IContextProvider.class) {
// return JavaUIHelp.getHelpContextProvider(this,
// IJavaHelpContextIds.TYPE_HIERARCHY_VIEW);
// }
return super.getAdapter(key);
}
private Control createTypeViewerControl(Composite parent) {
fViewerbook = new PageBook(parent, SWT.NULL);
KeyListener keyListener = createKeyListener();
// Create the viewers
TypeHierarchyViewer superTypesViewer = new SuperTypeHierarchyViewer(
fViewerbook, fHierarchyLifeCycle, this, getPreferenceStore());
initializeTypesViewer(superTypesViewer, keyListener,
IContextMenuConstants.TARGET_ID_SUPERTYPES_VIEW);
TypeHierarchyViewer subTypesViewer = new SubTypeHierarchyViewer(
fViewerbook, fHierarchyLifeCycle, this, getPreferenceStore());
initializeTypesViewer(subTypesViewer, keyListener,
IContextMenuConstants.TARGET_ID_SUBTYPES_VIEW);
TypeHierarchyViewer vajViewer = new TraditionalHierarchyViewer(
fViewerbook, fHierarchyLifeCycle, this, getPreferenceStore());
initializeTypesViewer(vajViewer, keyListener,
IContextMenuConstants.TARGET_ID_HIERARCHY_VIEW);
fAllViewers = new TypeHierarchyViewer[3];
fAllViewers[VIEW_ID_SUPER] = superTypesViewer;
fAllViewers[VIEW_ID_SUB] = subTypesViewer;
fAllViewers[VIEW_ID_TYPE] = vajViewer;
int currViewerIndex;
try {
currViewerIndex = fDialogSettings.getInt(DIALOGSTORE_HIERARCHYVIEW);
if (currViewerIndex < 0 || currViewerIndex > 2) {
currViewerIndex = VIEW_ID_TYPE;
}
} catch (NumberFormatException e) {
currViewerIndex = VIEW_ID_TYPE;
}
fEmptyTypesViewer = new Label(fViewerbook,
SWT.TOP | SWT.LEFT | SWT.WRAP);
for (int i = 0; i < fAllViewers.length; i++) {
fAllViewers[i].setInput(fAllViewers[i]);
}
// force the update
fCurrentViewerIndex = -1;
setView(currViewerIndex);
return fViewerbook;
}
private KeyListener createKeyListener() {
return new KeyAdapter() {
@Override
public void keyReleased(KeyEvent event) {
if (event.stateMask == 0) {
if (event.keyCode == SWT.F5) {
ITypeHierarchy hierarchy = fHierarchyLifeCycle
.getHierarchy();
if (hierarchy != null) {
fHierarchyLifeCycle.typeHierarchyChanged(hierarchy);
doTypeHierarchyChangedOnViewers(null);
}
updateHierarchyViewer(false);
return;
}
}
}
};
}
private void initializeTypesViewer(final TypeHierarchyViewer typesViewer,
KeyListener keyListener, String cotextHelpId) {
typesViewer.getControl().setVisible(false);
typesViewer.getControl().addKeyListener(keyListener);
typesViewer.initContextMenu(
menu -> fillTypesViewerContextMenu(typesViewer, menu),
cotextHelpId, getSite());
typesViewer.addPostSelectionChangedListener(fSelectionChangedListener);
typesViewer.setQualifiedTypeName(isShowQualifiedTypeNames());
typesViewer.setWorkingSetFilter(
fWorkingSetActionGroup.getWorkingSetFilter());
}
private Control createMethodViewerControl(Composite parent) {
fMethodsViewer = new MethodsViewer(parent, fHierarchyLifeCycle, this,
getPreferenceStore());
fMethodsViewer.initContextMenu(
menu -> fillMethodsViewerContextMenu(menu),
IContextMenuConstants.TARGET_ID_MEMBERS_VIEW, getSite());
fMethodsViewer
.addPostSelectionChangedListener(fSelectionChangedListener);
Control control = fMethodsViewer.getTable();
control.addKeyListener(createKeyListener());
control.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
fSelectAllAction.setEnabled(true);
}
@Override
public void focusLost(FocusEvent e) {
fSelectAllAction.setEnabled(false);
}
});
return control;
}
// private void initDragAndDrop() {
// for (int i= 0; i < fAllViewers.length; i++) {
// addDragAdapters(fAllViewers[i]);
// addDropAdapters(fAllViewers[i]);
// }
// addDragAdapters(fMethodsViewer);
// fMethodsViewer.addDropSupport(DND.DROP_NONE, new Transfer[0], new
// DropTargetAdapter());
//
// //DND on empty hierarchy
// DropTarget dropTarget = new DropTarget(fPagebook, DND.DROP_MOVE |
// DND.DROP_COPY | DND.DROP_LINK | DND.DROP_DEFAULT);
// dropTarget.setTransfer(new Transfer[] {
// LocalSelectionTransfer.getInstance() });
// dropTarget.addDropListener(new TypeHierarchyTransferDropAdapter(this,
// fAllViewers[0]));
// }
//
// private void addDropAdapters(AbstractTreeViewer viewer) {
// Transfer[] transfers= new Transfer[] {
// LocalSelectionTransfer.getInstance() };
// int ops= DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK |
// DND.DROP_DEFAULT;
//
// TransferDropTargetListener[] dropListeners= new
// TransferDropTargetListener[] {
// new TypeHierarchyTransferDropAdapter(this, viewer)
// };
// viewer.addDropSupport(ops, transfers, new
// DelegatingDropAdapter(dropListeners));
// }
//
// private void addDragAdapters(StructuredViewer viewer) {
// int ops= DND.DROP_COPY | DND.DROP_LINK;
// Transfer[] transfers= new Transfer[] {
// LocalSelectionTransfer.getInstance(), ResourceTransfer.getInstance()};
//
// TransferDragSourceListener[] dragListeners= new
// TransferDragSourceListener[] {
// new SelectionTransferDragAdapter(viewer),
// new ResourceTransferDragAdapter(viewer)
// };
// viewer.addDragSupport(ops, transfers, new JdtViewerDragAdapter(viewer,
// dragListeners));
// }
/**
* Returns the inner component in a workbench part.
*
* @see IWorkbenchPart#createPartControl(Composite)
*/
@Override
public void createPartControl(Composite container) {
fParent = container;
addResizeListener(container);
fPagebook = new PageBook(container, SWT.NONE);
fWorkingSetActionGroup = new WorkingSetFilterActionGroup(getSite(),
fPropertyChangeListener);
// page 1 of page book (no hierarchy label)
fNoHierarchyShownLabel = new Label(fPagebook,
SWT.TOP + SWT.LEFT + SWT.WRAP);
fNoHierarchyShownLabel
.setText(TypeHierarchyMessages.TypeHierarchyViewPart_empty);
// page 2 of page book (viewers)
fTypeMethodsSplitter = new SashForm(fPagebook, SWT.VERTICAL);
fTypeMethodsSplitter.setVisible(false);
fTypeViewerViewForm = new ViewForm(fTypeMethodsSplitter, SWT.NONE);
Control typeViewerControl = createTypeViewerControl(
fTypeViewerViewForm);
fTypeViewerViewForm.setContent(typeViewerControl);
fMethodViewerViewForm = new ViewForm(fTypeMethodsSplitter, SWT.NONE);
fTypeMethodsSplitter.setWeights(new int[] { 35, 65 });
Control methodViewerPart = createMethodViewerControl(
fMethodViewerViewForm);
fMethodViewerViewForm.setContent(methodViewerPart);
fMethodViewerPaneLabel = new CLabel(fMethodViewerViewForm, SWT.NONE);
fMethodViewerViewForm.setTopLeft(fMethodViewerPaneLabel);
ToolBar methodViewerToolBar = new ToolBar(fMethodViewerViewForm,
SWT.FLAT | SWT.WRAP);
fMethodViewerViewForm.setTopCenter(methodViewerToolBar);
// initDragAndDrop();
MenuManager menu = new MenuManager();
menu.add(fFocusOnTypeAction);
fNoHierarchyShownLabel
.setMenu(menu.createContextMenu(fNoHierarchyShownLabel));
fPagebook.showPage(fNoHierarchyShownLabel);
try {
fOrientation = fDialogSettings.getInt(DIALOGSTORE_VIEWORIENTATION);
if (fOrientation < 0 || fOrientation > 3) {
fOrientation = VIEW_ORIENTATION_AUTOMATIC;
}
} catch (NumberFormatException e) {
fOrientation = VIEW_ORIENTATION_AUTOMATIC;
}
// force the update
fCurrentOrientation = -1;
// will fill the main tool bar
setOrientation(fOrientation);
if (fMemento != null) { // restore state before creating action
restoreLinkingEnabled(fMemento);
}
fToggleLinkingAction = new ToggleLinkingAction(this);
// set the filter menu items
IActionBars actionBars = getViewSite().getActionBars();
IMenuManager viewMenu = actionBars.getMenuManager();
for (int i = 0; i < fViewActions.length; i++) {
ToggleViewAction action = fViewActions[i];
viewMenu.add(action);
action.setEnabled(false);
}
viewMenu.add(new Separator());
fWorkingSetActionGroup.fillViewMenu(viewMenu);
viewMenu.add(new Separator());
IMenuManager layoutSubMenu = new MenuManager(
TypeHierarchyMessages.TypeHierarchyViewPart_layout_submenu);
viewMenu.add(layoutSubMenu);
for (int i = 0; i < fToggleOrientationActions.length; i++) {
layoutSubMenu.add(fToggleOrientationActions[i]);
}
viewMenu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
viewMenu.add(fShowQualifiedTypeNamesAction);
viewMenu.add(fToggleLinkingAction);
// fill the method viewer tool bar
ToolBarManager lowertbmanager = new ToolBarManager(methodViewerToolBar);
lowertbmanager.add(fEnableMemberFilterAction);
lowertbmanager.add(new Separator());
fMethodsViewer.contributeToToolBar(lowertbmanager);
lowertbmanager.update(true);
// selection provider
int nHierarchyViewers = fAllViewers.length;
StructuredViewer[] trackedViewers = new StructuredViewer[nHierarchyViewers
+ 1];
for (int i = 0; i < nHierarchyViewers; i++) {
trackedViewers[i] = fAllViewers[i];
}
trackedViewers[nHierarchyViewers] = fMethodsViewer;
fSelectionProviderMediator = new SelectionProviderMediator(
trackedViewers, getCurrentViewer());
IStatusLineManager slManager = getViewSite().getActionBars()
.getStatusLineManager();
fSelectionProviderMediator
.addSelectionChangedListener(new StatusBarUpdater(slManager));
getSite().setSelectionProvider(fSelectionProviderMediator);
getSite().getPage().addPartListener(fPartListener);
// see http://bugs.eclipse.org/bugs/show_bug.cgi?id=33657
IModelElement input = null; // determineInputElement();
if (fMemento != null) {
restoreState(fMemento, input);
} else if (input != null) {
setInputElement(input);
} else {
setViewerVisibility(false);
}
// PlatformUI.getWorkbench().getHelpSystem().setHelp(fPagebook,
// IJavaHelpContextIds.TYPE_HIERARCHY_VIEW);
fActionGroups = new CompositeActionGroup(
new ActionGroup[] { new NewWizardsActionGroup(this.getSite()),
new OpenEditorActionGroup(this),
new OpenViewActionGroup(this), new CCPActionGroup(this),
// new GenerateActionGroup(this),
new RefactorActionGroup(this,
null) /*
* , new DLTKSearchActionGroup(this,
* getLanguageToolkit())
*/
});
fActionGroups.fillActionBars(actionBars);
fSelectAllAction = new SelectAllAction(fMethodsViewer);
actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(),
fSelectAllAction);
IContextService ctxService = getSite()
.getService(IContextService.class);
if (ctxService != null) {
fContextActivation = ctxService
.activateContext(DLTKUIPlugin.CONTEXT_VIEWS);
}
}
private void addResizeListener(Composite parent) {
parent.addControlListener(new ControlListener() {
@Override
public void controlMoved(ControlEvent e) {
}
@Override
public void controlResized(ControlEvent e) {
computeOrientation();
}
});
}
void computeOrientation() {
// fix for bug: 63268 error while activating view
// avoid recursive calls of compute orientation
if (fInComputeOrientation) {
return;
}
fInComputeOrientation = true;
try {
if (fOrientation != VIEW_ORIENTATION_AUTOMATIC) {
setOrientation(fOrientation);
} else {
if (fOrientation == VIEW_ORIENTATION_SINGLE)
return;
Point size = fParent.getSize();
if (size.x != 0 && size.y != 0) {
if (size.x > size.y)
setOrientation(VIEW_ORIENTATION_HORIZONTAL);
else
setOrientation(VIEW_ORIENTATION_VERTICAL);
}
}
} finally {
fInComputeOrientation = false;
}
}
/**
* called from ToggleOrientationAction.
*
* @param orientation
* VIEW_ORIENTATION_SINGLE, VIEW_ORIENTATION_HORIZONTAL or
* VIEW_ORIENTATION_VERTICAL
*/
public void setOrientation(int orientation) {
if (fCurrentOrientation != orientation) {
boolean methodViewerNeedsUpdate = false;
if (fMethodViewerViewForm != null
&& !fMethodViewerViewForm.isDisposed()
&& fTypeMethodsSplitter != null
&& !fTypeMethodsSplitter.isDisposed()) {
if (orientation == VIEW_ORIENTATION_SINGLE) {
fMethodViewerViewForm.setVisible(false);
enableMemberFilter(false);
updateMethodViewer(null);
} else {
if (fCurrentOrientation == VIEW_ORIENTATION_SINGLE) {
fMethodViewerViewForm.setVisible(true);
methodViewerNeedsUpdate = true;
}
boolean horizontal = orientation == VIEW_ORIENTATION_HORIZONTAL;
fTypeMethodsSplitter.setOrientation(
horizontal ? SWT.HORIZONTAL : SWT.VERTICAL);
}
updateMainToolbar(orientation);
fTypeMethodsSplitter.layout();
}
updateCheckedState();
if (methodViewerNeedsUpdate) {
updateMethodViewer(fSelectedType);
}
fDialogSettings.put(DIALOGSTORE_VIEWORIENTATION, orientation);
fCurrentOrientation = orientation;
}
}
private void updateCheckedState() {
for (int i = 0; i < fToggleOrientationActions.length; i++) {
fToggleOrientationActions[i]
.setChecked(fOrientation == fToggleOrientationActions[i]
.getOrientation());
}
}
private void updateMainToolbar(int orientation) {
IActionBars actionBars = getViewSite().getActionBars();
IToolBarManager tbmanager = actionBars.getToolBarManager();
if (orientation == VIEW_ORIENTATION_HORIZONTAL) {
clearMainToolBar(tbmanager);
ToolBar typeViewerToolBar = new ToolBar(fTypeViewerViewForm,
SWT.FLAT | SWT.WRAP);
fillMainToolBar(new ToolBarManager(typeViewerToolBar));
fTypeViewerViewForm.setTopLeft(typeViewerToolBar);
} else {
fTypeViewerViewForm.setTopLeft(null);
fillMainToolBar(tbmanager);
}
}
private void fillMainToolBar(IToolBarManager tbmanager) {
tbmanager.removeAll();
for (int i = 0; i < fViewActions.length; i++) {
tbmanager.add(fViewActions[i]);
}
tbmanager.add(fHistoryDropDownAction);
tbmanager.update(false);
}
private void clearMainToolBar(IToolBarManager tbmanager) {
tbmanager.removeAll();
tbmanager.update(false);
}
/*
* Creates the context menu for the hierarchy viewers
*/
private void fillTypesViewerContextMenu(TypeHierarchyViewer viewer,
IMenuManager menu) {
DLTKUIPlugin.createStandardGroups(menu);
menu.appendToGroup(IContextMenuConstants.GROUP_SHOW,
new Separator(GROUP_FOCUS));
// viewer entries
viewer.contributeToContextMenu(menu);
if (fFocusOnSelectionAction.canActionBeAdded())
menu.appendToGroup(GROUP_FOCUS, fFocusOnSelectionAction);
menu.appendToGroup(GROUP_FOCUS, fFocusOnTypeAction);
fActionGroups.setContext(new ActionContext(
getSite().getSelectionProvider().getSelection()));
fActionGroups.fillContextMenu(menu);
fActionGroups.setContext(null);
}
/*
* Creates the context menu for the method viewer
*/
private void fillMethodsViewerContextMenu(IMenuManager menu) {
DLTKUIPlugin.createStandardGroups(menu);
// viewer entries
fMethodsViewer.contributeToContextMenu(menu);
fActionGroups.setContext(new ActionContext(
getSite().getSelectionProvider().getSelection()));
fActionGroups.fillContextMenu(menu);
fActionGroups.setContext(null);
}
/*
* Toggles between the empty viewer page and the hierarchy
*/
private void setViewerVisibility(boolean showHierarchy) {
if (showHierarchy) {
fViewerbook.showPage(getCurrentViewer().getControl());
} else {
fViewerbook.showPage(fEmptyTypesViewer);
}
}
/*
* Sets the member filter. <code>null</code> disables member filtering.
*/
private void setMemberFilter(IMember[] memberFilter) {
Assert.isNotNull(fAllViewers);
for (int i = 0; i < fAllViewers.length; i++) {
fAllViewers[i].setMemberFilter(memberFilter);
}
}
private IType getSelectableType(IModelElement elem) {
if (elem.getElementType() != IModelElement.TYPE) {
return getCurrentViewer().getTreeRootType();
} else {
return (IType) elem;
}
}
private void internalSelectType(IMember elem, boolean reveal) {
TypeHierarchyViewer viewer = getCurrentViewer();
viewer.removePostSelectionChangedListener(fSelectionChangedListener);
viewer.setSelection(elem != null ? new StructuredSelection(elem)
: StructuredSelection.EMPTY, reveal);
viewer.addPostSelectionChangedListener(fSelectionChangedListener);
}
/*
* When the input changed or the hierarchy pane becomes visible,
* <code>updateHierarchyViewer<code> brings up the correct view and
* refreshes the current tree
*/
private void updateHierarchyViewer(final boolean doExpand) {
if (fInputElement == null) {
fNoHierarchyShownLabel
.setText(TypeHierarchyMessages.TypeHierarchyViewPart_empty);
fPagebook.showPage(fNoHierarchyShownLabel);
} else {
if (getCurrentViewer().containsElements() != null) {
Runnable runnable = () -> {
final TypeHierarchyViewer viewer = getCurrentViewer();
((TypeHierarchyContentProvider) viewer.getContentProvider())
.resetState();
viewer.updateContent(doExpand); // refresh
};
BusyIndicator.showWhile(getDisplay(), runnable);
if (!isChildVisible(fViewerbook,
getCurrentViewer().getControl())) {
setViewerVisibility(true);
}
} else {
fEmptyTypesViewer.setText(Messages.format(
TypeHierarchyMessages.TypeHierarchyViewPart_nodecl,
fInputElement.getElementName()));
setViewerVisibility(false);
}
}
}
private void updateMethodViewer(final IType input) {
if (!fIsEnableMemberFilter
&& fCurrentOrientation != VIEW_ORIENTATION_SINGLE) {
if (input == fMethodsViewer.getInput()) {
if (input != null) {
Runnable runnable = () -> fMethodsViewer.refresh();
BusyIndicator.showWhile(getDisplay(), runnable);
}
} else {
if (input != null) {
fMethodViewerPaneLabel
.setText(fPaneLabelProvider.getText(input));
fMethodViewerPaneLabel
.setImage(fPaneLabelProvider.getImage(input));
} else {
fMethodViewerPaneLabel.setText(""); //$NON-NLS-1$
fMethodViewerPaneLabel.setImage(null);
}
Runnable runnable = () -> fMethodsViewer.setInput(input);
BusyIndicator.showWhile(getDisplay(), runnable);
}
}
}
protected void doSelectionChanged(SelectionChangedEvent e) {
if (e.getSelectionProvider() == fMethodsViewer) {
methodSelectionChanged(e.getSelection());
} else {
typeSelectionChanged(e.getSelection());
}
}
private void methodSelectionChanged(ISelection sel) {
if (sel instanceof IStructuredSelection) {
List<?> selected = ((IStructuredSelection) sel).toList();
int nSelected = selected.size();
if (fIsEnableMemberFilter) {
IMember[] memberFilter = null;
if (nSelected > 0) {
memberFilter = new IMember[nSelected];
selected.toArray(memberFilter);
}
setMemberFilter(memberFilter);
updateHierarchyViewer(true);
updateTitle();
internalSelectType(fSelectedType, true);
}
if (nSelected == 1 && fSelectInEditor) {
revealElementInEditor(selected.get(0), fMethodsViewer);
}
}
}
private void typeSelectionChanged(ISelection sel) {
if (sel instanceof IStructuredSelection) {
List<?> selected = ((IStructuredSelection) sel).toList();
int nSelected = selected.size();
if (nSelected != 0) {
List<IType> types = new ArrayList<>(nSelected);
for (int i = nSelected - 1; i >= 0; i--) {
Object elem = selected.get(i);
if (elem instanceof IType) {
if (!types.contains(elem)) {
types.add((IType) elem);
}
} else if (elem instanceof CumulativeType.Part) {
final CumulativeType.Part part = (CumulativeType.Part) elem;
if (!types.contains(part.type)) {
types.add(part.type);
}
}
}
if (types.size() == 1) {
fSelectedType = types.get(0);
updateMethodViewer(fSelectedType);
} else if (types.size() == 0) {
// method selected, no change
}
if (nSelected == 1 && fSelectInEditor) {
revealElementInEditor(selected.get(0), getCurrentViewer());
}
} else {
fSelectedType = null;
updateMethodViewer(null);
}
}
}
private void revealElementInEditor(Object elem,
StructuredViewer originViewer) {
// only allow revealing when the type hierarchy is the active page
// no revealing after selection events due to model changes
if (getSite().getPage().getActivePart() != this) {
return;
}
if (fSelectionProviderMediator.getViewerInFocus() != originViewer) {
return;
}
IEditorPart editorPart = EditorUtility.isOpenInEditor(elem);
if (editorPart != null && (elem instanceof IModelElement)) {
getSite().getPage().removePartListener(fPartListener);
getSite().getPage().bringToTop(editorPart);
EditorUtility.revealInEditor(editorPart, (IModelElement) elem);
getSite().getPage().addPartListener(fPartListener);
}
}
private Display getDisplay() {
if (fPagebook != null && !fPagebook.isDisposed()) {
return fPagebook.getDisplay();
}
return null;
}
private boolean isChildVisible(Composite pb, Control child) {
Control[] children = pb.getChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] == child && children[i].isVisible())
return true;
}
return false;
}
private void updateTitle() {
String viewerTitle = getCurrentViewer().getTitle();
String tooltip;
String title;
if (fInputElement != null) {
IWorkingSet workingSet = fWorkingSetActionGroup.getWorkingSet();
if (workingSet == null) {
String[] args = new String[] { viewerTitle,
ScriptElementLabels.getDefault().getElementLabel(
fInputElement,
ScriptElementLabels.ALL_DEFAULT) };
title = Messages.format(
TypeHierarchyMessages.TypeHierarchyViewPart_title,
args);
tooltip = Messages.format(
TypeHierarchyMessages.TypeHierarchyViewPart_tooltip,
args);
} else {
String[] args = new String[] { viewerTitle,
ScriptElementLabels.getDefault().getElementLabel(
fInputElement, ScriptElementLabels.ALL_DEFAULT),
workingSet.getLabel() };
title = Messages.format(
TypeHierarchyMessages.TypeHierarchyViewPart_ws_title,
args);
tooltip = Messages.format(
TypeHierarchyMessages.TypeHierarchyViewPart_ws_tooltip,
args);
}
} else {
title = ""; //$NON-NLS-1$
tooltip = viewerTitle;
}
setContentDescription(title);
setTitleToolTip(tooltip);
}
private void updateToolbarButtons() {
boolean isType = fInputElement instanceof IType;
for (int i = 0; i < fViewActions.length; i++) {
ToggleViewAction action = fViewActions[i];
if (action.getViewerIndex() == VIEW_ID_TYPE) {
action.setEnabled(fInputElement != null);
} else {
action.setEnabled(isType);
}
}
}
/*
* Sets the current view (see view id) called from ToggleViewAction. Must be
* called after creation of the view part.
*/
public void setView(int viewerIndex) {
Assert.isNotNull(fAllViewers);
if (viewerIndex < fAllViewers.length
&& fCurrentViewerIndex != viewerIndex) {
fCurrentViewerIndex = viewerIndex;
updateHierarchyViewer(true);
if (fInputElement != null) {
ISelection currSelection = getCurrentViewer().getSelection();
if (currSelection == null || currSelection.isEmpty()) {
internalSelectType(getSelectableType(fInputElement), false);
currSelection = getCurrentViewer().getSelection();
}
if (!fIsEnableMemberFilter) {
typeSelectionChanged(currSelection);
}
}
updateTitle();
fDialogSettings.put(DIALOGSTORE_HIERARCHYVIEW, viewerIndex);
getCurrentViewer().getTree().setFocus();
}
for (int i = 0; i < fViewActions.length; i++) {
ToggleViewAction action = fViewActions[i];
action.setChecked(fCurrentViewerIndex == action.getViewerIndex());
}
}
/**
* Gets the current active view index.
*
* @return The index of the current viewer
*/
public int getViewIndex() {
return fCurrentViewerIndex;
}
private TypeHierarchyViewer getCurrentViewer() {
return fAllViewers[fCurrentViewerIndex];
}
/**
* called from EnableMemberFilterAction. Must be called after creation of
* the view part.
*
* @param on
* <code>true</code> to turn the member filter on
*/
public void enableMemberFilter(boolean on) {
if (on != fIsEnableMemberFilter) {
fIsEnableMemberFilter = on;
if (!on) {
IType methodViewerInput = (IType) fMethodsViewer.getInput();
setMemberFilter(null);
updateHierarchyViewer(true);
updateTitle();
if (methodViewerInput != null && getCurrentViewer()
.isElementShown(methodViewerInput)) {
// avoid that the method view changes content by selecting
// the previous input
internalSelectType(methodViewerInput, true);
} else if (fSelectedType != null) {
// choose a input that exists
internalSelectType(fSelectedType, true);
updateMethodViewer(fSelectedType);
}
} else {
methodSelectionChanged(fMethodsViewer.getSelection());
}
}
fEnableMemberFilterAction.setChecked(on);
}
/**
* called from ShowQualifiedTypeNamesAction. Must be called after creation
* of the view part.
*
* @param on
* <code>true</code> to enable qualified type names
*/
public void showQualifiedTypeNames(boolean on) {
if (fAllViewers == null) {
return;
}
for (int i = 0; i < fAllViewers.length; i++) {
fAllViewers[i].setQualifiedTypeName(on);
}
}
private boolean isShowQualifiedTypeNames() {
return fShowQualifiedTypeNamesAction.isChecked();
}
/**
* Called from ITypeHierarchyLifeCycleListener. Can be called from any
* thread
*
* @param typeHierarchy
* Hierarchy that has changed
* @param changedTypes
* Types in the hierarchy that have change or <code>null</code>
* if the full hierarchy has changed
*/
protected void doTypeHierarchyChanged(
final TypeHierarchyLifeCycle typeHierarchy,
final IType[] changedTypes) {
if (!fIsVisible) {
fNeedRefresh = true;
return;
}
if (fIsRefreshRunnablePosted) {
return;
}
Display display = getDisplay();
if (display != null) {
fIsRefreshRunnablePosted = true;
display.asyncExec(() -> {
try {
if (fPagebook != null && !fPagebook.isDisposed()) {
doTypeHierarchyChangedOnViewers(changedTypes);
}
} finally {
fIsRefreshRunnablePosted = false;
}
});
}
}
protected void doTypeHierarchyChangedOnViewers(IType[] changedTypes) {
if (fHierarchyLifeCycle.getHierarchy() == null
|| !fHierarchyLifeCycle.getHierarchy().exists()) {
clearInput();
} else {
if (changedTypes == null) {
// hierarchy change
try {
fHierarchyLifeCycle.ensureRefreshedTypeHierarchy(
fInputElement, getSite().getWorkbenchWindow());
} catch (InvocationTargetException e) {
ExceptionHandler.handle(e, getSite().getShell(),
TypeHierarchyMessages.TypeHierarchyViewPart_exception_title,
TypeHierarchyMessages.TypeHierarchyViewPart_exception_message);
clearInput();
return;
} catch (InterruptedException e) {
return;
}
fMethodsViewer.refresh();
updateHierarchyViewer(false);
} else {
// elements in hierarchy modified
Object methodViewerInput = fMethodsViewer.getInput();
fMethodsViewer.refresh();
fMethodViewerPaneLabel
.setText(fPaneLabelProvider.getText(methodViewerInput));
fMethodViewerPaneLabel.setImage(
fPaneLabelProvider.getImage(methodViewerInput));
if (getCurrentViewer().isMethodFiltering()) {
if (changedTypes.length == 1) {
getCurrentViewer().refresh(changedTypes[0]);
} else {
updateHierarchyViewer(false);
}
} else {
getCurrentViewer().update(changedTypes,
new String[] { IBasicPropertyConstants.P_TEXT,
IBasicPropertyConstants.P_IMAGE });
}
}
}
}
/*
* @see IViewPart#init
*/
@Override
public void init(IViewSite site, IMemento memento)
throws PartInitException {
super.init(site, memento);
fMemento = memento;
}
/*
* @see ViewPart#saveState(IMemento)
*/
@Override
public void saveState(IMemento memento) {
if (fPagebook == null) {
// part has not been created
if (fMemento != null) { // Keep the old state;
memento.putMemento(fMemento);
}
return;
}
if (fInputElement != null) {
String handleIndentifier = fInputElement.getHandleIdentifier();
memento.putString(TAG_INPUT, handleIndentifier);
}
memento.putInteger(TAG_VIEW, getViewIndex());
memento.putInteger(TAG_ORIENTATION, fOrientation);
int weigths[] = fTypeMethodsSplitter.getWeights();
int ratio = (weigths[0] * 1000) / (weigths[0] + weigths[1]);
memento.putInteger(TAG_RATIO, ratio);
ScrollBar bar = getCurrentViewer().getTree().getVerticalBar();
int position = bar != null ? bar.getSelection() : 0;
memento.putInteger(TAG_VERTICAL_SCROLL, position);
IModelElement selection = toModelElement(
((IStructuredSelection) getCurrentViewer().getSelection())
.getFirstElement());
if (selection != null) {
memento.putString(TAG_SELECTION, selection.getHandleIdentifier());
}
fWorkingSetActionGroup.saveState(memento);
fMethodsViewer.saveState(memento);
saveLinkingEnabled(memento);
}
private void saveLinkingEnabled(IMemento memento) {
memento.putInteger(PreferenceConstants.LINK_TYPEHIERARCHY_TO_EDITOR,
fLinkingEnabled ? 1 : 0);
}
/**
* @param element
* @return
*/
private IModelElement toModelElement(Object element) {
if (element instanceof IModelElement) {
return (IModelElement) element;
} else if (element instanceof CumulativeType) {
return ((CumulativeType) element).getFirst();
} else if (element instanceof CumulativeType.Part) {
return ((CumulativeType.Part) element).type;
}
return null;
}
/*
* Restores the type hierarchy settings from a memento.
*/
private void restoreState(final IMemento memento,
IModelElement defaultInput) {
IModelElement input = defaultInput;
String elementId = memento.getString(TAG_INPUT);
if (elementId != null) {
input = DLTKCore.create(elementId);
if (input != null && !input.exists()) {
input = null;
}
}
if (input == null) {
doRestoreState(memento, input);
} else {
final IModelElement hierarchyInput = input;
synchronized (this) {
String label = Messages.format(
TypeHierarchyMessages.TypeHierarchyViewPart_restoreinput,
hierarchyInput.getElementName());
fNoHierarchyShownLabel.setText(label);
fRestoreStateJob = new Job(label) {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
doRestoreInBackground(memento, hierarchyInput,
monitor);
} catch (ModelException e) {
return e.getStatus();
} catch (OperationCanceledException e) {
return Status.CANCEL_STATUS;
}
return Status.OK_STATUS;
}
};
fRestoreStateJob.schedule();
}
}
}
private void doRestoreInBackground(final IMemento memento,
final IModelElement hierarchyInput, IProgressMonitor monitor)
throws ModelException {
fHierarchyLifeCycle.doHierarchyRefresh(hierarchyInput, monitor);
if (!monitor.isCanceled()) {
Display.getDefault().asyncExec(() -> {
// running async: check first if view still exists
if (fPagebook != null && !fPagebook.isDisposed()) {
doRestoreState(memento, hierarchyInput);
}
});
}
}
final void doRestoreState(IMemento memento, IModelElement input) {
synchronized (this) {
if (fRestoreStateJob == null) {
return;
}
fRestoreStateJob = null;
}
fWorkingSetActionGroup.restoreState(memento);
setInputElement(input);
Integer viewerIndex = memento.getInteger(TAG_VIEW);
if (viewerIndex != null) {
setView(viewerIndex.intValue());
}
Integer orientation = memento.getInteger(TAG_ORIENTATION);
if (orientation != null) {
fOrientation = orientation.intValue();
}
computeOrientation();
updateCheckedState();
Integer ratio = memento.getInteger(TAG_RATIO);
if (ratio != null) {
fTypeMethodsSplitter.setWeights(
new int[] { ratio.intValue(), 1000 - ratio.intValue() });
}
ScrollBar bar = getCurrentViewer().getTree().getVerticalBar();
if (bar != null) {
Integer vScroll = memento.getInteger(TAG_VERTICAL_SCROLL);
if (vScroll != null) {
bar.setSelection(vScroll.intValue());
}
}
fMethodsViewer.restoreState(memento);
}
private void restoreLinkingEnabled(IMemento memento) {
Integer val = memento
.getInteger(PreferenceConstants.LINK_TYPEHIERARCHY_TO_EDITOR);
if (val != null) {
fLinkingEnabled = val.intValue() != 0;
}
}
/**
* view part becomes visible
*
* @param isVisible
*/
protected void visibilityChanged(boolean isVisible) {
fIsVisible = isVisible;
if (isVisible && fNeedRefresh) {
doTypeHierarchyChangedOnViewers(null);
}
fNeedRefresh = false;
}
/**
* Link selection to active editor.
*
* @param editor
* The activated editor
*/
protected void editorActivated(IEditorPart editor) {
if (!isLinkingEnabled()) {
return;
}
if (fInputElement == null) {
// no type hierarchy shown
return;
}
IModelElement elem = editor.getEditorInput()
.getAdapter(IModelElement.class);
try {
IType type = null;
if (elem instanceof ISourceModule) {
// Take the first type:
IType[] allTypes = ((ISourceModule) elem).getTypes();
if (allTypes.length > 0) {
type = allTypes[0];
}
}
if (type != null) {
internalSelectType(type, true);
if (getCurrentViewer().getSelection().isEmpty()) {
updateMethodViewer(null);
} else {
updateMethodViewer(type);
}
}
} catch (ModelException e) {
DLTKUIPlugin.log(e);
}
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.jdt.internal.ui.viewsupport.IViewPartInputProvider#
* getViewPartInput()
*/
@Override
public Object getViewPartInput() {
return fInputElement;
}
/**
* @return Returns the <code>IShowInSource</code> for this view.
*/
protected IShowInSource getShowInSource() {
return () -> new ShowInContext(null,
getSite().getSelectionProvider().getSelection());
}
boolean isLinkingEnabled() {
return fLinkingEnabled;
}
public void setLinkingEnabled(boolean enabled) {
fLinkingEnabled = enabled;
getPreferenceStore().setValue(
PreferenceConstants.LINK_TYPEHIERARCHY_TO_EDITOR, enabled);
if (enabled) {
IEditorPart editor = getSite().getPage().getActiveEditor();
if (editor != null) {
editorActivated(editor);
}
}
}
public void clearNeededRefresh() {
fNeedRefresh = false;
}
}