package org.eclipse.jdt.internal.ui.javaeditor; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
import java.util.Enumeration; | |
import java.util.Hashtable; | |
import java.util.List; | |
import java.util.Vector; | |
import org.eclipse.swt.SWT; | |
import org.eclipse.swt.events.KeyAdapter; | |
import org.eclipse.swt.events.KeyEvent; | |
import org.eclipse.swt.widgets.Composite; | |
import org.eclipse.swt.widgets.Control; | |
import org.eclipse.swt.widgets.Display; | |
import org.eclipse.swt.widgets.Item; | |
import org.eclipse.swt.widgets.Menu; | |
import org.eclipse.swt.widgets.Tree; | |
import org.eclipse.swt.widgets.Widget; | |
import org.eclipse.jface.action.Action; | |
import org.eclipse.jface.action.IAction; | |
import org.eclipse.jface.action.IMenuListener; | |
import org.eclipse.jface.action.IMenuManager; | |
import org.eclipse.jface.action.IStatusLineManager; | |
import org.eclipse.jface.action.IToolBarManager; | |
import org.eclipse.jface.action.MenuManager; | |
import org.eclipse.jface.util.Assert; | |
import org.eclipse.jface.util.ListenerList; | |
import org.eclipse.jface.viewers.DecoratingLabelProvider; | |
import org.eclipse.jface.viewers.ISelection; | |
import org.eclipse.jface.viewers.ISelectionChangedListener; | |
import org.eclipse.jface.viewers.IStructuredSelection; | |
import org.eclipse.jface.viewers.ITreeContentProvider; | |
import org.eclipse.jface.viewers.StructuredSelection; | |
import org.eclipse.jface.viewers.TreeViewer; | |
import org.eclipse.jface.viewers.Viewer; | |
import org.eclipse.jface.viewers.ViewerFilter; | |
import org.eclipse.ui.IActionBars; | |
import org.eclipse.ui.IWorkbenchWindow; | |
import org.eclipse.ui.PlatformUI; | |
import org.eclipse.ui.actions.ActionGroup; | |
import org.eclipse.ui.part.IPageSite; | |
import org.eclipse.ui.part.Page; | |
import org.eclipse.ui.texteditor.IUpdate; | |
import org.eclipse.ui.texteditor.TextOperationAction; | |
import org.eclipse.ui.views.contentoutline.IContentOutlinePage; | |
import org.eclipse.jdt.core.ElementChangedEvent; | |
import org.eclipse.jdt.core.ICompilationUnit; | |
import org.eclipse.jdt.core.IElementChangedListener; | |
import org.eclipse.jdt.core.IJavaElement; | |
import org.eclipse.jdt.core.IJavaElementDelta; | |
import org.eclipse.jdt.core.IMember; | |
import org.eclipse.jdt.core.IMethod; | |
import org.eclipse.jdt.core.IParent; | |
import org.eclipse.jdt.core.ISourceRange; | |
import org.eclipse.jdt.core.ISourceReference; | |
import org.eclipse.jdt.core.IType; | |
import org.eclipse.jdt.core.JavaCore; | |
import org.eclipse.jdt.core.JavaModelException; | |
import org.eclipse.jdt.internal.corext.util.JavaModelUtil; | |
import org.eclipse.jdt.internal.ui.JavaPlugin; | |
import org.eclipse.jdt.internal.ui.JavaPluginImages; | |
import org.eclipse.jdt.internal.ui.actions.CompositeActionGroup; | |
import org.eclipse.jdt.internal.ui.actions.ContextMenuGroup; | |
import org.eclipse.jdt.internal.ui.actions.GenerateGroup; | |
import org.eclipse.jdt.internal.ui.actions.OpenHierarchyAction; | |
import org.eclipse.jdt.internal.ui.actions.RetargetActionIDs; | |
import org.eclipse.jdt.internal.ui.refactoring.actions.IRefactoringAction; | |
import org.eclipse.jdt.internal.ui.refactoring.actions.RefactoringGroup; | |
import org.eclipse.jdt.internal.ui.reorg.ReorgGroup; | |
import org.eclipse.jdt.internal.ui.search.JavaSearchGroup; | |
import org.eclipse.jdt.internal.ui.util.OpenTypeHierarchyUtil; | |
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLabels; | |
import org.eclipse.jdt.internal.ui.viewsupport.MemberFilterActionGroup; | |
import org.eclipse.jdt.internal.ui.viewsupport.OverrideAdornmentProvider; | |
import org.eclipse.jdt.internal.ui.viewsupport.StandardJavaUILabelProvider; | |
import org.eclipse.jdt.internal.ui.viewsupport.StatusBarUpdater; | |
import org.eclipse.jdt.ui.IContextMenuConstants; | |
import org.eclipse.jdt.ui.JavaElementSorter; | |
import org.eclipse.jdt.ui.actions.GenerateActionGroup; | |
import org.eclipse.jdt.ui.actions.OpenActionGroup; | |
import org.eclipse.jdt.ui.actions.ShowActionGroup; | |
/** | |
* The content outline page of the Java editor. The viewer implements a proprietary | |
* update mechanism based on Java model deltas. It does not react on domain changes. | |
* It is specified to show the content of ICompilationUnits and IClassFiles. | |
* Pulishes its context menu under <code>JavaPlugin.getDefault().getPluginId() + ".outliner"</code>. | |
*/ | |
class JavaOutlinePage extends Page implements IContentOutlinePage { | |
/** | |
* The element change listener of the java outline viewer. | |
* @see IElementChangedListener | |
*/ | |
class ElementChangedListener implements IElementChangedListener { | |
public void elementChanged(final ElementChangedEvent e) { | |
Display d= getControl().getDisplay(); | |
if (d != null) { | |
d.asyncExec(new Runnable() { | |
public void run() { | |
IJavaElementDelta delta= findElement( (ICompilationUnit) fInput, e.getDelta()); | |
if (delta != null && fOutlineViewer != null) { | |
fOutlineViewer.reconcile(delta); | |
} | |
} | |
}); | |
} | |
} | |
protected IJavaElementDelta findElement(ICompilationUnit unit, IJavaElementDelta delta) { | |
if (delta == null || unit == null) | |
return null; | |
IJavaElement element= delta.getElement(); | |
if (unit.equals(element)) | |
return delta; | |
if (element.getElementType() > IJavaElement.CLASS_FILE) | |
return null; | |
IJavaElementDelta[] children= delta.getAffectedChildren(); | |
if (children == null || children.length == 0) | |
return null; | |
for (int i= 0; i < children.length; i++) { | |
IJavaElementDelta d= findElement(unit, children[i]); | |
if (d != null) | |
return d; | |
} | |
return null; | |
} | |
}; | |
/** | |
* Content provider for the children of an ICompilationUnit or | |
* an IClassFile | |
* @see ITreeContentProvider | |
*/ | |
class ChildrenProvider implements ITreeContentProvider { | |
private ElementChangedListener fListener; | |
private JavaOutlineErrorTickUpdater fErrorTickUpdater; | |
protected boolean matches(IJavaElement element) { | |
if (element.getElementType() == IJavaElement.METHOD) { | |
String name= element.getElementName(); | |
return (name != null && name.indexOf('<') >= 0); | |
} | |
return false; | |
} | |
protected IJavaElement[] filter(IJavaElement[] children) { | |
boolean initializers= false; | |
for (int i= 0; i < children.length; i++) { | |
if (matches(children[i])) { | |
initializers= true; | |
break; | |
} | |
} | |
if (!initializers) | |
return children; | |
Vector v= new Vector(); | |
for (int i= 0; i < children.length; i++) { | |
if (matches(children[i])) | |
continue; | |
v.addElement(children[i]); | |
} | |
IJavaElement[] result= new IJavaElement[v.size()]; | |
v.copyInto(result); | |
return result; | |
} | |
public Object[] getChildren(Object parent) { | |
if (parent instanceof IParent) { | |
IParent c= (IParent) parent; | |
try { | |
return filter(c.getChildren()); | |
} catch (JavaModelException x) { | |
JavaPlugin.getDefault().logErrorStatus(JavaEditorMessages.getString("JavaOutlinePage.error.ChildrenProvider.getChildren.message1"), x.getStatus()); //$NON-NLS-1$ | |
} | |
} | |
return new Object[0]; | |
} | |
public Object[] getElements(Object parent) { | |
return getChildren(parent); | |
} | |
public Object getParent(Object child) { | |
if (child instanceof IJavaElement) { | |
IJavaElement e= (IJavaElement) child; | |
return e.getParent(); | |
} | |
return null; | |
} | |
public boolean hasChildren(Object parent) { | |
if (parent instanceof IParent) { | |
IParent c= (IParent) parent; | |
try { | |
IJavaElement[] children= filter(c.getChildren()); | |
return (children != null && children.length > 0); | |
} catch (JavaModelException x) { | |
JavaPlugin.getDefault().logErrorStatus(JavaEditorMessages.getString("JavaOutlinePage.error.ChildrenProvider.hasChildren.message1"), x.getStatus()); //$NON-NLS-1$ | |
} | |
} | |
return false; | |
} | |
public boolean isDeleted(Object o) { | |
return false; | |
} | |
public void dispose() { | |
if (fListener != null) { | |
JavaCore.removeElementChangedListener(fListener); | |
fListener= null; | |
} | |
if (fErrorTickUpdater != null) { | |
fErrorTickUpdater.setAnnotationModel(null); | |
fErrorTickUpdater= null; | |
} | |
} | |
/* | |
* @see IContentProvider#inputChanged(Viewer, Object, Object) | |
*/ | |
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { | |
boolean isCU= (newInput instanceof ICompilationUnit); | |
if (isCU && fListener == null) { | |
fListener= new ElementChangedListener(); | |
JavaCore.addElementChangedListener(fListener); | |
fErrorTickUpdater= new JavaOutlineErrorTickUpdater(fOutlineViewer); | |
fErrorTickUpdater.setAnnotationModel(fEditor.getDocumentProvider().getAnnotationModel(fEditor.getEditorInput())); | |
} else if (isCU && fErrorTickUpdater != null) { | |
fErrorTickUpdater.setAnnotationModel(fEditor.getDocumentProvider().getAnnotationModel(fEditor.getEditorInput())); | |
} else if (!isCU && fListener != null) { | |
JavaCore.removeElementChangedListener(fListener); | |
fListener= null; | |
fErrorTickUpdater.setAnnotationModel(null); | |
fErrorTickUpdater= null; | |
} | |
} | |
}; | |
class JavaOutlineViewer extends TreeViewer { | |
/** | |
* Indicates an item which has been reused. At the point of | |
* its reuse it has been expanded. This field is used to | |
* communicate between <code>internalExpandToLevel</code> and | |
* <code>reuseTreeItem</code>. | |
*/ | |
private Item fReusedExpandedItem; | |
public JavaOutlineViewer(Tree tree) { | |
super(tree); | |
setAutoExpandLevel(ALL_LEVELS); | |
} | |
/** | |
* Investigates the given element change event and if affected incrementally | |
* updates the outline. | |
*/ | |
public void reconcile(IJavaElementDelta delta) { | |
if (getSorter() == null) { | |
Widget w= findItem(fInput); | |
if (w != null) | |
update(w, delta); | |
} else { | |
// just for now | |
refresh(); | |
} | |
} | |
/* | |
* @see TreeViewer#internalExpandToLevel | |
*/ | |
protected void internalExpandToLevel(Widget node, int level) { | |
if (node instanceof Item) { | |
Item i= (Item) node; | |
if (i.getData() instanceof IJavaElement) { | |
IJavaElement je= (IJavaElement) i.getData(); | |
if (je.getElementType() == IJavaElement.IMPORT_CONTAINER || isInnerType(je)) { | |
if (i != fReusedExpandedItem) { | |
setExpanded(i, false); | |
return; | |
} | |
} | |
} | |
} | |
super.internalExpandToLevel(node, level); | |
} | |
protected void reuseTreeItem(Item item, Object element) { | |
// remove children | |
Item[] c= getChildren(item); | |
if (c != null && c.length > 0) { | |
if (getExpanded(item)) | |
fReusedExpandedItem= item; | |
for (int k= 0; k < c.length; k++) { | |
if (c[k].getData() != null) | |
disassociate(c[k]); | |
c[k].dispose(); | |
} | |
} | |
updateItem(item, element); | |
updatePlus(item, element); | |
internalExpandToLevel(item, ALL_LEVELS); | |
fReusedExpandedItem= null; | |
} | |
protected boolean mustUpdateParent(IJavaElementDelta delta, IJavaElement element) { | |
if (element instanceof IMethod) { | |
if ((delta.getKind() & IJavaElementDelta.ADDED) != 0) { | |
try { | |
return JavaModelUtil.isMainMethod((IMethod)element); | |
} catch (JavaModelException e) { | |
JavaPlugin.log(e.getStatus()); | |
} | |
} | |
return "main".equals(element.getElementName()); //$NON-NLS-1$ | |
} | |
return false; | |
} | |
protected ISourceRange getSourceRange(IJavaElement element) throws JavaModelException { | |
if (element instanceof IMember) | |
return ((IMember) element).getNameRange(); | |
if (element instanceof ISourceReference) | |
return ((ISourceReference) element).getSourceRange(); | |
return null; | |
} | |
protected boolean overlaps(ISourceRange range, int start, int end) { | |
return start <= (range.getOffset() + range.getLength() - 1) && range.getOffset() <= end; | |
} | |
protected boolean filtered(IJavaElement parent, IJavaElement child) { | |
Object[] result= new Object[] { child }; | |
ViewerFilter[] filters= getFilters(); | |
for (int i= 0; i < filters.length; i++) { | |
result= filters[i].filter(this, parent, result); | |
if (result.length == 0) | |
return true; | |
} | |
return false; | |
} | |
protected void update(Widget w, IJavaElementDelta delta) { | |
Item item; | |
IJavaElement parent= delta.getElement(); | |
IJavaElementDelta[] affected= delta.getAffectedChildren(); | |
Item[] children= getChildren(w); | |
boolean doUpdateParent= false; | |
Vector deletions= new Vector(); | |
Vector additions= new Vector(); | |
for (int i= 0; i < affected.length; i++) { | |
IJavaElementDelta affectedDelta= affected[i]; | |
IJavaElement affectedElement= affectedDelta.getElement(); | |
int status= affected[i].getKind(); | |
// find tree item with affected element | |
int j; | |
for (j= 0; j < children.length; j++) | |
if (affectedElement.equals(children[j].getData())) | |
break; | |
if (j == children.length) { | |
// addition | |
if ((status & IJavaElementDelta.CHANGED) != 0 && | |
(affectedDelta.getFlags() & IJavaElementDelta.F_MODIFIERS) != 0 && | |
!filtered(parent, affectedElement)) | |
{ | |
additions.addElement(affectedDelta); | |
} | |
continue; | |
} | |
item= children[j]; | |
// removed | |
if ((status & IJavaElementDelta.REMOVED) != 0) { | |
deletions.addElement(item); | |
doUpdateParent= doUpdateParent || mustUpdateParent(affectedDelta, affectedElement); | |
// changed | |
} else if ((status & IJavaElementDelta.CHANGED) != 0) { | |
int change= affectedDelta.getFlags(); | |
doUpdateParent= doUpdateParent || mustUpdateParent(affectedDelta, affectedElement); | |
if ((change & IJavaElementDelta.F_MODIFIERS) != 0) { | |
if (filtered(parent, affectedElement)) | |
deletions.addElement(item); | |
else | |
updateItem(item, affectedElement); | |
} | |
if ((change & IJavaElementDelta.F_CONTENT) != 0) | |
updateItem(item, affectedElement); | |
if ((change & IJavaElementDelta.F_CHILDREN) != 0) | |
update(item, affectedDelta); | |
} | |
} | |
// find all elements to add | |
IJavaElementDelta[] add= delta.getAddedChildren(); | |
if (additions.size() > 0) { | |
IJavaElementDelta[] tmp= new IJavaElementDelta[add.length + additions.size()]; | |
System.arraycopy(add, 0, tmp, 0, add.length); | |
for (int i= 0; i < additions.size(); i++) | |
tmp[i + add.length]= (IJavaElementDelta) additions.elementAt(i); | |
add= tmp; | |
} | |
// add at the right position | |
go2: for (int i= 0; i < add.length; i++) { | |
try { | |
IJavaElement e= add[i].getElement(); | |
if (filtered(parent, e)) | |
continue go2; | |
doUpdateParent= doUpdateParent || mustUpdateParent(add[i], e); | |
ISourceRange rng= getSourceRange(e); | |
int start= rng.getOffset(); | |
int end= start + rng.getLength() - 1; | |
Item last= null; | |
item= null; | |
children= getChildren(w); | |
for (int j= 0; j < children.length; j++) { | |
item= children[j]; | |
IJavaElement r= (IJavaElement) item.getData(); | |
if (r == null) { | |
// parent node collapsed and not be opened before -> do nothing | |
continue go2; | |
} | |
try { | |
rng= getSourceRange(r); | |
if (overlaps(rng, start, end)) { | |
// be tolerant if the delta is not correct, or if | |
// the tree has been updated other than by a delta | |
reuseTreeItem(item, e); | |
continue go2; | |
} else if (rng.getOffset() > start) { | |
if (last != null && deletions.contains(last)) { | |
// reuse item | |
deletions.removeElement(last); | |
reuseTreeItem(last, (Object) e); | |
} else { | |
// nothing to reuse | |
createTreeItem(w, (Object) e, j); | |
} | |
continue go2; | |
} | |
} catch (JavaModelException x) { | |
// stumbled over deleted element | |
} | |
last= item; | |
} | |
// add at the end of the list | |
if (last != null && deletions.contains(last)) { | |
// reuse item | |
deletions.removeElement(last); | |
reuseTreeItem(last, e); | |
} else { | |
// nothing to reuse | |
createTreeItem(w, e, -1); | |
} | |
} catch (JavaModelException x) { | |
// the element to be added is not present -> don't add it | |
} | |
} | |
// remove items which haven't been reused | |
Enumeration e= deletions.elements(); | |
while (e.hasMoreElements()) { | |
item= (Item) e.nextElement(); | |
disassociate(item); | |
item.dispose(); | |
} | |
if (doUpdateParent) | |
updateItem(w, delta.getElement()); | |
} | |
}; | |
class LexicalSortingAction extends Action { | |
private JavaElementSorter fSorter= new JavaElementSorter(); | |
public LexicalSortingAction() { | |
super(); | |
setText(JavaEditorMessages.getString("JavaOutlinePage.Sort.label")); //$NON-NLS-1$ | |
JavaPluginImages.setLocalImageDescriptors(this, "alphab_sort_co.gif"); //$NON-NLS-1$ | |
boolean checked= JavaPlugin.getDefault().getPreferenceStore().getBoolean("LexicalSortingAction.isChecked"); //$NON-NLS-1$ | |
valueChanged(checked, false); | |
} | |
public void run() { | |
valueChanged(isChecked(), true); | |
} | |
private void valueChanged(boolean on, boolean store) { | |
setChecked(on); | |
fOutlineViewer.setSorter(on ? fSorter : null); | |
setToolTipText(on ? JavaEditorMessages.getString("JavaOutlinePage.Sort.tooltip.checked") : JavaEditorMessages.getString("JavaOutlinePage.Sort.tooltip.unchecked")); //$NON-NLS-2$ //$NON-NLS-1$ | |
setDescription(on ? JavaEditorMessages.getString("JavaOutlinePage.Sort.description.checked") : JavaEditorMessages.getString("JavaOutlinePage.Sort.description.unchecked")); //$NON-NLS-2$ //$NON-NLS-1$ | |
if (store) | |
JavaPlugin.getDefault().getPreferenceStore().setValue("LexicalSortingAction.isChecked", on); //$NON-NLS-1$ | |
} | |
}; | |
private IJavaElement fInput; | |
private String fContextMenuID; | |
private Menu fMenu; | |
private JavaOutlineViewer fOutlineViewer; | |
private JavaEditor fEditor; | |
private MemberFilterActionGroup fMemberFilterActionGroup; | |
private ListenerList fSelectionChangedListeners= new ListenerList(); | |
private Hashtable fActions= new Hashtable(); | |
private ContextMenuGroup[] fActionGroups; | |
private TogglePresentationAction fTogglePresentation; | |
private ToggleTextHoverAction fToggleTextHover; | |
private GotoErrorAction fPreviousError; | |
private GotoErrorAction fNextError; | |
private TextOperationAction fShowJavadoc; | |
private CompositeActionGroup fStandardActionGroups; | |
public JavaOutlinePage(String contextMenuID, JavaEditor editor) { | |
super(); | |
Assert.isNotNull(editor); | |
fContextMenuID= contextMenuID; | |
fEditor= editor; | |
fTogglePresentation= new TogglePresentationAction(); | |
fToggleTextHover= new ToggleTextHoverAction(); | |
fPreviousError= new GotoErrorAction("PreviousError.", false); //$NON-NLS-1$ | |
fNextError= new GotoErrorAction("NextError.", true); //$NON-NLS-1$ | |
fShowJavadoc= (TextOperationAction) fEditor.getAction("ShowJavaDoc"); | |
fTogglePresentation.setEditor(editor); | |
fToggleTextHover.setEditor(editor); | |
fPreviousError.setEditor(editor); | |
fNextError.setEditor(editor); | |
} | |
/* (non-Javadoc) | |
* Method declared on Page | |
*/ | |
public void init(IPageSite pageSite) { | |
super.init(pageSite); | |
} | |
/* | |
* @see ISelectionProvider#addSelectionChangedListener(ISelectionChangedListener) | |
*/ | |
public void addSelectionChangedListener(ISelectionChangedListener listener) { | |
if (fOutlineViewer != null) | |
fOutlineViewer.addSelectionChangedListener(listener); | |
else | |
fSelectionChangedListeners.add(listener); | |
} | |
/* | |
* @see ISelectionProvider#removeSelectionChangedListener(ISelectionChangedListener) | |
*/ | |
public void removeSelectionChangedListener(ISelectionChangedListener listener) { | |
if (fOutlineViewer != null) | |
fOutlineViewer.removeSelectionChangedListener(listener); | |
else | |
fSelectionChangedListeners.remove(listener); | |
} | |
/* | |
* @see ISelectionProvider#setSelection(ISelection) | |
*/ | |
public void setSelection(ISelection selection) { | |
if (fOutlineViewer != null) | |
fOutlineViewer.setSelection(selection); | |
} | |
/* | |
* @see ISelectionProvider#getSelection() | |
*/ | |
public ISelection getSelection() { | |
if (fOutlineViewer == null) | |
return StructuredSelection.EMPTY; | |
return fOutlineViewer.getSelection(); | |
} | |
private void registerToolbarActions() { | |
IToolBarManager toolBarManager= getSite().getActionBars().getToolBarManager(); | |
if (toolBarManager != null) { | |
Action action= new LexicalSortingAction(); | |
toolBarManager.add(action); | |
fMemberFilterActionGroup= new MemberFilterActionGroup(fOutlineViewer, "JavaOutlineViewer"); | |
fMemberFilterActionGroup.contributeToToolBar(toolBarManager); | |
} | |
} | |
/* | |
* @see IPage#createControl | |
*/ | |
public void createControl(Composite parent) { | |
Tree tree= new Tree(parent, SWT.MULTI); | |
StandardJavaUILabelProvider lprovider= new StandardJavaUILabelProvider( | |
StandardJavaUILabelProvider.DEFAULT_TEXTFLAGS | JavaElementLabels.F_APP_TYPE_SIGNATURE, | |
StandardJavaUILabelProvider.DEFAULT_IMAGEFLAGS, | |
StandardJavaUILabelProvider.getAdornmentProviders(true, new OverrideAdornmentProvider()) | |
); | |
fOutlineViewer= new JavaOutlineViewer(tree); | |
fOutlineViewer.setContentProvider(new ChildrenProvider()); | |
fOutlineViewer.setLabelProvider(new DecoratingLabelProvider( | |
lprovider, PlatformUI.getWorkbench().getDecoratorManager())); | |
Object[] listeners= fSelectionChangedListeners.getListeners(); | |
for (int i= 0; i < listeners.length; i++) { | |
fSelectionChangedListeners.remove(listeners[i]); | |
fOutlineViewer.addSelectionChangedListener((ISelectionChangedListener) listeners[i]); | |
} | |
MenuManager manager= new MenuManager(fContextMenuID, fContextMenuID); | |
manager.setRemoveAllWhenShown(true); | |
manager.addMenuListener(new IMenuListener() { | |
public void menuAboutToShow(IMenuManager manager) { | |
contextMenuAboutToShow(manager); | |
} | |
}); | |
fMenu= manager.createContextMenu(tree); | |
tree.setMenu(fMenu); | |
getSite().registerContextMenu(JavaPlugin.getDefault().getPluginId() + ".outline", manager, fOutlineViewer); | |
getSite().setSelectionProvider(fOutlineViewer); | |
// we must create the groups after we have set the selection provider to the site | |
fStandardActionGroups= new CompositeActionGroup(new ActionGroup[] { | |
new OpenActionGroup(this), new ShowActionGroup(this), new GenerateActionGroup(this)}); | |
// register global actions | |
IActionBars bars= getSite().getActionBars(); | |
bars.setGlobalActionHandler(RetargetActionIDs.SHOW_PREVIOUS_PROBLEM, fPreviousError); | |
bars.setGlobalActionHandler(RetargetActionIDs.SHOW_NEXT_PROBLEM, fNextError); | |
bars.setGlobalActionHandler(RetargetActionIDs.SHOW_JAVA_DOC, fShowJavadoc); | |
bars.setGlobalActionHandler(IJavaEditorActionConstants.TOGGLE_PRESENTATION, fTogglePresentation); | |
bars.setGlobalActionHandler(IJavaEditorActionConstants.TOGGLE_TEXT_HOVER, fToggleTextHover); | |
fStandardActionGroups.fillActionBars(bars); | |
IStatusLineManager statusLineManager= getSite().getActionBars().getStatusLineManager(); | |
if (statusLineManager != null) { | |
StatusBarUpdater updater= new StatusBarUpdater(statusLineManager); | |
fOutlineViewer.addSelectionChangedListener(updater); | |
} | |
registerToolbarActions(); | |
fActionGroups= new ContextMenuGroup[] { new GenerateGroup(), new JavaSearchGroup(), new ReorgGroup() }; | |
ReorgGroup.addGlobalReorgActions(getSite().getActionBars(), fOutlineViewer); | |
fOutlineViewer.setInput(fInput); | |
fOutlineViewer.getControl().addKeyListener(new KeyAdapter() { | |
public void keyPressed(KeyEvent e) { | |
handleKeyReleased(e); | |
} | |
}); | |
} | |
public void dispose() { | |
if (fEditor == null) | |
return; | |
fEditor.outlinePageClosed(); | |
fEditor= null; | |
Object[] listeners= fSelectionChangedListeners.getListeners(); | |
for (int i= 0; i < listeners.length; i++) | |
fSelectionChangedListeners.remove(listeners[i]); | |
fSelectionChangedListeners= null; | |
if (fMenu != null && !fMenu.isDisposed()) { | |
fMenu.dispose(); | |
fMenu= null; | |
} | |
super.dispose(); | |
} | |
public Control getControl() { | |
if (fOutlineViewer != null) | |
return fOutlineViewer.getControl(); | |
return null; | |
} | |
public void setInput(IJavaElement inputElement) { | |
fInput= inputElement; | |
if (fOutlineViewer != null) | |
fOutlineViewer.setInput(fInput); | |
} | |
public void select(ISourceReference reference) { | |
if (fOutlineViewer != null) { | |
ISelection s= fOutlineViewer.getSelection(); | |
if (s instanceof IStructuredSelection) { | |
IStructuredSelection ss= (IStructuredSelection) s; | |
List elements= ss.toList(); | |
if (!elements.contains(reference)) { | |
s= (reference == null ? StructuredSelection.EMPTY : new StructuredSelection(reference)); | |
fOutlineViewer.setSelection(s, true); | |
} | |
} | |
} | |
} | |
public void setAction(String actionID, IAction action) { | |
Assert.isNotNull(actionID); | |
if (action == null) | |
fActions.remove(actionID); | |
else | |
fActions.put(actionID, action); | |
} | |
public IAction getAction(String actionID) { | |
Assert.isNotNull(actionID); | |
return (IAction) fActions.get(actionID); | |
} | |
/** | |
* Convenience method to add the action installed under the given actionID to the | |
* specified group of the menu. | |
*/ | |
protected void addAction(IMenuManager menu, String group, String actionID) { | |
IAction action= getAction(actionID); | |
if (action != null) { | |
if (action instanceof IUpdate) | |
((IUpdate) action).update(); | |
if (action.isEnabled()) { | |
IMenuManager subMenu= menu.findMenuUsingPath(group); | |
if (subMenu != null) | |
subMenu.add(action); | |
else | |
menu.appendToGroup(group, action); | |
} | |
} | |
} | |
private void addRefactoring(IMenuManager menu){ | |
MenuManager refactoring= new MenuManager(JavaEditorMessages.getString("JavaOutlinePage.ContextMenu.refactoring.label")); //$NON-NLS-1$ | |
ContextMenuGroup.add(refactoring, new ContextMenuGroup[] { new RefactoringGroup() }, fOutlineViewer); | |
if (!refactoring.isEmpty()) | |
menu.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, refactoring); | |
} | |
private void addOpenPerspectiveItem(IMenuManager menu) { | |
ISelection s= getSelection(); | |
if (s.isEmpty() || ! (s instanceof IStructuredSelection)) | |
return; | |
IStructuredSelection selection= (IStructuredSelection)s; | |
if (selection.size() != 1) | |
return; | |
Object element= selection.getFirstElement(); | |
if (!(element instanceof IType)) | |
return; | |
IType[] input= {(IType)element}; | |
IWorkbenchWindow w= getSite().getWorkbenchWindow(); | |
menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, new OpenHierarchyAction(w, input)); | |
} | |
protected void contextMenuAboutToShow(IMenuManager menu) { | |
JavaPlugin.createStandardGroups(menu); | |
if (OrganizeImportsAction.canActionBeAdded(getSelection())) { | |
addAction(menu, IContextMenuConstants.GROUP_REORGANIZE, "OrganizeImports"); //$NON-NLS-1$ | |
} | |
addAction(menu, IContextMenuConstants.GROUP_OPEN, "OpenImportDeclaration"); //$NON-NLS-1$ | |
addAction(menu, IContextMenuConstants.GROUP_SHOW, "ShowInPackageView"); //$NON-NLS-1$ | |
ContextMenuGroup.add(menu, fActionGroups, fOutlineViewer); | |
// XXX fill the show menu. This is a workaround until we have converted all context menus to the | |
// new action groups. | |
fStandardActionGroups.get(1).fillContextMenu(menu); | |
addRefactoring(menu); | |
addOpenPerspectiveItem(menu); | |
} | |
/* | |
* @see Page#setFocus() | |
*/ | |
public void setFocus() { | |
if (fOutlineViewer != null) | |
fOutlineViewer.getControl().setFocus(); | |
} | |
/** | |
* Checkes whether a given Java element is an inner type. | |
*/ | |
private boolean isInnerType(IJavaElement element) { | |
if (element.getElementType() == IJavaElement.TYPE) { | |
IJavaElement parent= element.getParent(); | |
int type= parent.getElementType(); | |
return (type != IJavaElement.COMPILATION_UNIT && type != IJavaElement.CLASS_FILE); | |
} | |
return false; | |
} | |
/** | |
* Handles key events in viewer. | |
*/ | |
private void handleKeyReleased(KeyEvent event) { | |
if (event.stateMask != 0) | |
return; | |
IAction action= null; | |
if (event.character == SWT.DEL) { | |
action= getAction("DeleteElement"); //$NON-NLS-1$ | |
if (action instanceof IRefactoringAction){ | |
//special case - DeleteAction is not a ISelectionChangedListener | |
((IRefactoringAction)action).update(); | |
if (! action.isEnabled()) | |
return; | |
} | |
} | |
if (action != null && action.isEnabled()) | |
action.run(); | |
} | |
} |