X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/JavaOutlinePage.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/JavaOutlinePage.java new file mode 100644 index 0000000..98681fa --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/JavaOutlinePage.java @@ -0,0 +1,1171 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package net.sourceforge.phpeclipse.phpeditor; + + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.List; +import java.util.Vector; + +import net.sourceforge.phpdt.core.ElementChangedEvent; +import net.sourceforge.phpdt.core.ICompilationUnit; +import net.sourceforge.phpdt.core.IElementChangedListener; +import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.IJavaElementDelta; +import net.sourceforge.phpdt.core.IMember; +import net.sourceforge.phpdt.core.IMethod; +import net.sourceforge.phpdt.core.IParent; +import net.sourceforge.phpdt.core.ISourceRange; +import net.sourceforge.phpdt.core.ISourceReference; +import net.sourceforge.phpdt.core.IType; +import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.internal.ui.PHPUiImages; +import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup; +import net.sourceforge.phpdt.internal.ui.packageview.SelectionTransferDragAdapter; +import net.sourceforge.phpdt.internal.ui.viewsupport.AppearanceAwareLabelProvider; +import net.sourceforge.phpdt.internal.ui.viewsupport.DecoratingJavaLabelProvider; +import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementLabels; +import net.sourceforge.phpdt.internal.ui.viewsupport.StatusBarUpdater; +import net.sourceforge.phpdt.ui.JavaElementSorter; +import net.sourceforge.phpdt.ui.JavaUI; +import net.sourceforge.phpdt.ui.PreferenceConstants; +import net.sourceforge.phpdt.ui.ProblemsLabelDecorator.ProblemsLabelChangedEvent; +import net.sourceforge.phpdt.ui.actions.GenerateActionGroup; +import net.sourceforge.phpdt.ui.actions.MemberFilterActionGroup; +import net.sourceforge.phpeclipse.PHPCore; +import net.sourceforge.phpeclipse.PHPeclipsePlugin; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; +import net.sourceforge.phpdt.internal.ui.dnd.JdtViewerDragAdapter; +import net.sourceforge.phpdt.internal.ui.dnd.TransferDragSourceListener; +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.preference.IPreferenceStore; +import org.eclipse.jface.text.Assert; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.ListenerList; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.IBaseLabelProvider; +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.LabelProviderChangedEvent; +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.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.Transfer; +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.ui.IActionBars; +import org.eclipse.ui.actions.ActionContext; +import org.eclipse.ui.actions.ActionGroup; +import org.eclipse.ui.internal.model.WorkbenchAdapter; +import org.eclipse.ui.model.IWorkbenchAdapter; +import org.eclipse.ui.part.IPageSite; +import org.eclipse.ui.part.IShowInSource; +import org.eclipse.ui.part.IShowInTarget; +import org.eclipse.ui.part.IShowInTargetList; +import org.eclipse.ui.part.Page; +import org.eclipse.ui.part.ShowInContext; +import org.eclipse.ui.texteditor.ITextEditorActionConstants; +import org.eclipse.ui.texteditor.IUpdate; +import org.eclipse.ui.texteditor.TextEditorAction; +import org.eclipse.ui.texteditor.TextOperationAction; +import org.eclipse.ui.views.contentoutline.IContentOutlinePage; +import org.eclipse.ui.views.navigator.LocalSelectionTransfer; + + + + + +/** + * 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 JavaPlugin.getDefault().getPluginId() + ".outline". + */ +public class JavaOutlinePage extends Page implements IContentOutlinePage, IAdaptable { + + static Object[] NO_CHILDREN= new Object[0]; + + /** + * The element change listener of the java outline viewer. + * @see IElementChangedListener + */ + class ElementChangedListener implements IElementChangedListener { + + public void elementChanged(final ElementChangedEvent e) { + + if (getControl() == null) + return; + + Display d= getControl().getDisplay(); + if (d != null) { + d.asyncExec(new Runnable() { + public void run() { + ICompilationUnit cu= (ICompilationUnit) fInput; + IJavaElement base= cu; + if (fTopLevelTypeOnly) { + base= getMainType(cu); + if (base == null) { + if (fOutlineViewer != null) + fOutlineViewer.refresh(true); + return; + } + } + IJavaElementDelta delta= findElement(base, e.getDelta()); + if (delta != null && fOutlineViewer != null) { + fOutlineViewer.reconcile(delta); + } + } + }); + } + } + + protected IJavaElementDelta findElement(IJavaElement 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; + } + }; + + static class NoClassElement extends WorkbenchAdapter implements IAdaptable { + /* + * @see java.lang.Object#toString() + */ + public String toString() { + return PHPEditorMessages.getString("JavaOutlinePage.error.NoTopLevelType"); //$NON-NLS-1$ + } + + /* + * @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class) + */ + public Object getAdapter(Class clas) { + if (clas == IWorkbenchAdapter.class) + return this; + return null; + } + } + + /** + * Content provider for the children of an ICompilationUnit or + * an IClassFile + * @see ITreeContentProvider + */ + class ChildrenProvider implements ITreeContentProvider { + + private Object[] NO_CLASS= new Object[] {new NoClassElement()}; + private ElementChangedListener fListener; + + 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) { + PHPeclipsePlugin.log(x); + } + } + return NO_CHILDREN; + } + + public Object[] getElements(Object parent) { + if (fTopLevelTypeOnly) { + if (parent instanceof ICompilationUnit) { + try { + IType type= getMainType((ICompilationUnit) parent); + return type != null ? type.getChildren() : NO_CLASS; + } catch (JavaModelException e) { + PHPeclipsePlugin.log(e); + } + } +// else if (parent instanceof IClassFile) { +// try { +// IType type= getMainType((IClassFile) parent); +// return type != null ? type.getChildren() : NO_CLASS; +// } catch (JavaModelException e) { +// JavaPlugin.log(e); +// } +// } + } + 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) { + PHPeclipsePlugin.log(x); + } + } + return false; + } + + public boolean isDeleted(Object o) { + return false; + } + + public void dispose() { + if (fListener != null) { + PHPCore.removeElementChangedListener(fListener); + fListener= 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(); + PHPCore.addElementChangedListener(fListener); + } else if (!isCU && fListener != null) { + PHPCore.removeElementChangedListener(fListener); + fListener= 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 internalExpandToLevel and + * reuseTreeItem. + */ + private Item fReusedExpandedItem; + private boolean fReorderedMembers; + + 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) { + fReorderedMembers= false; + if (getSorter() == null) { + if (fTopLevelTypeOnly + && delta.getElement() instanceof IType + && (delta.getKind() & IJavaElementDelta.ADDED) != 0) + { + refresh(true); + + } else { + Widget w= findItem(fInput); + if (w != null && !w.isDisposed()) + update(w, delta); + if (fReorderedMembers) { + refresh(false); + fReorderedMembers= false; + } + } + } else { + // just for now + refresh(true); + } + } + + /* + * @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 ((IMethod)element).isMainMethod(); + } catch (JavaModelException e) { + PHPeclipsePlugin.log(e.getStatus()); + } + } + return "main".equals(element.getElementName()); //$NON-NLS-1$ + } + return false; + } + + protected ISourceRange getSourceRange(IJavaElement element) throws JavaModelException { + if (element instanceof IMember)// && !(element instanceof IInitializer)) + 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); + + if ((change & IJavaElementDelta.F_REORDER) != 0) + fReorderedMembers= true; + } + } + + // 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()); + } + + + + /* + * @see ContentViewer#handleLabelProviderChanged(LabelProviderChangedEvent) + */ + protected void handleLabelProviderChanged(LabelProviderChangedEvent event) { + Object input= getInput(); + if (event instanceof ProblemsLabelChangedEvent) { + ProblemsLabelChangedEvent e= (ProblemsLabelChangedEvent) event; + if (e.isMarkerChange() && input instanceof ICompilationUnit) { + return; // marker changes can be ignored + } + } + // look if the underlying resource changed + Object[] changed= event.getElements(); + if (changed != null) { + IResource resource= getUnderlyingResource(); + if (resource != null) { + for (int i= 0; i < changed.length; i++) { + if (changed[i] != null && changed[i].equals(resource)) { + // change event to a full refresh + event= new LabelProviderChangedEvent((IBaseLabelProvider) event.getSource()); + break; + } + } + } + } + super.handleLabelProviderChanged(event); + } + + private IResource getUnderlyingResource() { + Object input= getInput(); + if (input instanceof ICompilationUnit) { + ICompilationUnit cu= (ICompilationUnit) input; + if (cu.isWorkingCopy()) { + return cu.getOriginalElement().getResource(); + } else { + return cu.getResource(); + } + } +// else if (input instanceof IClassFile) { +// return ((IClassFile) input).getResource(); +// } + return null; + } + + + }; + + class LexicalSortingAction extends Action { + + private JavaElementSorter fSorter= new JavaElementSorter(); + + public LexicalSortingAction() { + super(); +// WorkbenchHelp.setHelp(this, IJavaHelpContextIds.LEXICAL_SORTING_OUTLINE_ACTION); + setText(PHPEditorMessages.getString("JavaOutlinePage.Sort.label")); //$NON-NLS-1$ + PHPUiImages.setLocalImageDescriptors(this, "alphab_sort_co.gif"); //$NON-NLS-1$ + setToolTipText(PHPEditorMessages.getString("JavaOutlinePage.Sort.tooltip")); //$NON-NLS-1$ + setDescription(PHPEditorMessages.getString("JavaOutlinePage.Sort.description")); //$NON-NLS-1$ + + boolean checked= PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean("LexicalSortingAction.isChecked"); //$NON-NLS-1$ + valueChanged(checked, false); + } + + public void run() { + valueChanged(isChecked(), true); + } + + private void valueChanged(final boolean on, boolean store) { + setChecked(on); + BusyIndicator.showWhile(fOutlineViewer.getControl().getDisplay(), new Runnable() { + public void run() { + fOutlineViewer.setSorter(on ? fSorter : null); } + }); + + if (store) + PHPeclipsePlugin.getDefault().getPreferenceStore().setValue("LexicalSortingAction.isChecked", on); //$NON-NLS-1$ + } + }; + + class ClassOnlyAction extends Action { + + public ClassOnlyAction() { + super(); +// WorkbenchHelp.setHelp(this, IJavaHelpContextIds.GO_INTO_TOP_LEVEL_TYPE_ACTION); + setText(PHPEditorMessages.getString("JavaOutlinePage.GoIntoTopLevelType.label")); //$NON-NLS-1$ + setToolTipText(PHPEditorMessages.getString("JavaOutlinePage.GoIntoTopLevelType.tooltip")); //$NON-NLS-1$ + setDescription(PHPEditorMessages.getString("JavaOutlinePage.GoIntoTopLevelType.description")); //$NON-NLS-1$ + PHPUiImages.setLocalImageDescriptors(this, "gointo_toplevel_type.gif"); //$NON-NLS-1$ + + IPreferenceStore preferenceStore= PHPeclipsePlugin.getDefault().getPreferenceStore(); + boolean showclass= preferenceStore.getBoolean("GoIntoTopLevelTypeAction.isChecked"); //$NON-NLS-1$ + setTopLevelTypeOnly(showclass); + } + + /* + * @see org.eclipse.jface.action.Action#run() + */ + public void run() { + setTopLevelTypeOnly(!fTopLevelTypeOnly); + } + + private void setTopLevelTypeOnly(boolean show) { + fTopLevelTypeOnly= show; + setChecked(show); + fOutlineViewer.refresh(false); + + IPreferenceStore preferenceStore= PHPeclipsePlugin.getDefault().getPreferenceStore(); + preferenceStore.setValue("GoIntoTopLevelTypeAction.isChecked", show); //$NON-NLS-1$ + } + }; + + /** A flag to show contents of top level type only */ + private boolean fTopLevelTypeOnly; + + private IJavaElement fInput; + private String fContextMenuID; + private Menu fMenu; + private JavaOutlineViewer fOutlineViewer; + private PHPEditor fEditor; + + private MemberFilterActionGroup fMemberFilterActionGroup; + + private ListenerList fSelectionChangedListeners= new ListenerList(); + private Hashtable fActions= new Hashtable(); + + private TogglePresentationAction fTogglePresentation; + private GotoErrorAction fPreviousError; + private GotoErrorAction fNextError; + private TextEditorAction fShowJavadoc; + private TextOperationAction fUndo; + private TextOperationAction fRedo; + + private CompositeActionGroup fActionGroups; +// private CCPActionGroup fCCPActionGroup; + + private IPropertyChangeListener fPropertyChangeListener; + + public JavaOutlinePage(String contextMenuID, PHPEditor editor) { + super(); + + Assert.isNotNull(editor); + + fContextMenuID= contextMenuID; + fEditor= editor; + + fTogglePresentation= new TogglePresentationAction(); + fPreviousError= new GotoErrorAction("PreviousError.", false); //$NON-NLS-1$ + fPreviousError.setImageDescriptor(PHPUiImages.DESC_TOOL_GOTO_PREV_ERROR); + fNextError= new GotoErrorAction("NextError.", true); //$NON-NLS-1$ + fNextError.setImageDescriptor(PHPUiImages.DESC_TOOL_GOTO_NEXT_ERROR); + fShowJavadoc= (TextEditorAction) fEditor.getAction("ShowJavaDoc"); //$NON-NLS-1$ + fUndo= (TextOperationAction) fEditor.getAction(ITextEditorActionConstants.UNDO); + fRedo= (TextOperationAction) fEditor.getAction(ITextEditorActionConstants.REDO); + + fTogglePresentation.setEditor(editor); + fPreviousError.setEditor(editor); + fNextError.setEditor(editor); + + fPropertyChangeListener= new IPropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + doPropertyChange(event); + } + }; + PHPeclipsePlugin.getDefault().getPreferenceStore().addPropertyChangeListener(fPropertyChangeListener); + } + + /** + * Returns the primary type of a compilation unit (has the same + * name as the compilation unit). + * + * @param compilationUnit the compilation unit + * @return returns the primary type of the compilation unit, or + * null if is does not have one + */ + protected IType getMainType(ICompilationUnit compilationUnit) { + String name= compilationUnit.getElementName(); + int index= name.indexOf('.'); + if (index != -1) + name= name.substring(0, index); + IType type= compilationUnit.getType(name); + return type.exists() ? type : null; + } + + /** + * Returns the primary type of a class file. + * + * @param classFile the class file + * @return returns the primary type of the class file, or null + * if is does not have one + */ +// protected IType getMainType(IClassFile classFile) { +// try { +// IType type= classFile.getType(); +// return type != null && type.exists() ? type : null; +// } catch (JavaModelException e) { +// return null; +// } +// } + + /* (non-Javadoc) + * Method declared on Page + */ + public void init(IPageSite pageSite) { + super.init(pageSite); + } + + private void doPropertyChange(PropertyChangeEvent event) { + if (fOutlineViewer != null) { + if (PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER.equals(event.getProperty())) { + fOutlineViewer.refresh(false); + } + } + } + + /* + * @see ISelectionProvider#addSelectionChangedListener(ISelectionChangedListener) + */ + public void addSelectionChangedListener(ISelectionChangedListener listener) { + if (fOutlineViewer != null) + fOutlineViewer.addPostSelectionChangedListener(listener); + else + fSelectionChangedListeners.add(listener); + } + + /* + * @see ISelectionProvider#removeSelectionChangedListener(ISelectionChangedListener) + */ + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + if (fOutlineViewer != null) + fOutlineViewer.removePostSelectionChangedListener(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) { + toolBarManager.add(new ClassOnlyAction()); + toolBarManager.add(new LexicalSortingAction()); + + fMemberFilterActionGroup= new MemberFilterActionGroup(fOutlineViewer, "JavaOutlineViewer"); //$NON-NLS-1$ + fMemberFilterActionGroup.contributeToToolBar(toolBarManager); + } + } + + /* + * @see IPage#createControl + */ + public void createControl(Composite parent) { + + Tree tree= new Tree(parent, SWT.MULTI); + + AppearanceAwareLabelProvider lprovider= new AppearanceAwareLabelProvider( + AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS | JavaElementLabels.F_APP_TYPE_SIGNATURE, + AppearanceAwareLabelProvider.DEFAULT_IMAGEFLAGS + ); + + fOutlineViewer= new JavaOutlineViewer(tree); + fOutlineViewer.setContentProvider(new ChildrenProvider()); + fOutlineViewer.setLabelProvider(new DecoratingJavaLabelProvider(lprovider)); + + Object[] listeners= fSelectionChangedListeners.getListeners(); + for (int i= 0; i < listeners.length; i++) { + fSelectionChangedListeners.remove(listeners[i]); + fOutlineViewer.addPostSelectionChangedListener((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); + + IPageSite site= getSite(); + site.registerContextMenu(PHPeclipsePlugin.getPluginId() + ".outline", manager, fOutlineViewer); //$NON-NLS-1$ + site.setSelectionProvider(fOutlineViewer); + + // we must create the groups after we have set the selection provider to the site + fActionGroups= new CompositeActionGroup(new ActionGroup[] { +// new OpenViewActionGroup(this), +// fCCPActionGroup= new CCPActionGroup(this), + new GenerateActionGroup(this)}); +// new RefactorActionGroup(this), +// new JavaSearchActionGroup(this)}); + + // register global actions + IActionBars bars= site.getActionBars(); + + bars.setGlobalActionHandler(ITextEditorActionConstants.UNDO, fUndo); + bars.setGlobalActionHandler(ITextEditorActionConstants.REDO, fRedo); + bars.setGlobalActionHandler(ITextEditorActionConstants.PREVIOUS, fPreviousError); + bars.setGlobalActionHandler(ITextEditorActionConstants.NEXT, fNextError); +// bars.setGlobalActionHandler(PHPdtActionConstants.SHOW_PHP_DOC, fShowJavadoc); + bars.setGlobalActionHandler(IJavaEditorActionConstants.TOGGLE_PRESENTATION, fTogglePresentation); + // http://dev.eclipse.org/bugs/show_bug.cgi?id=18968 + bars.setGlobalActionHandler(IJavaEditorActionConstants.PREVIOUS_ERROR, fPreviousError); + bars.setGlobalActionHandler(IJavaEditorActionConstants.NEXT_ERROR, fNextError); + + fActionGroups.fillActionBars(bars); + + IStatusLineManager statusLineManager= site.getActionBars().getStatusLineManager(); + if (statusLineManager != null) { + StatusBarUpdater updater= new StatusBarUpdater(statusLineManager); + fOutlineViewer.addPostSelectionChangedListener(updater); + } + + registerToolbarActions(); + + fOutlineViewer.setInput(fInput); + fOutlineViewer.getControl().addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + handleKeyReleased(e); + } + }); + + initDragAndDrop(); + } + + public void dispose() { + + if (fEditor == null) + return; + + if (fMemberFilterActionGroup != null) { + fMemberFilterActionGroup.dispose(); + fMemberFilterActionGroup= null; + } + + + fEditor.outlinePageClosed(); + fEditor= null; + + fSelectionChangedListeners.clear(); + fSelectionChangedListeners= null; + + if (fPropertyChangeListener != null) { + PHPeclipsePlugin.getDefault().getPreferenceStore().removePropertyChangeListener(fPropertyChangeListener); + fPropertyChangeListener= null; + } + + if (fMenu != null && !fMenu.isDisposed()) { + fMenu.dispose(); + fMenu= null; + } + + if (fActionGroups != null) + fActionGroups.dispose(); + + fTogglePresentation.setEditor(null); + fPreviousError.setEditor(null); + fNextError.setEditor(null); + + fOutlineViewer= 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); + } + + /** + * Answer the property defined by key. + */ + public Object getAdapter(Class key) { + if (key == IShowInSource.class) { + return getShowInSource(); + } + if (key == IShowInTargetList.class) { + return new IShowInTargetList() { + public String[] getShowInTargetIds() { + return new String[] { JavaUI.ID_PACKAGES }; + } + + }; + } + if (key == IShowInTarget.class) { + return getShowInTarget(); + } + + return null; + } + + /** + * 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); + } + } + } + + protected void contextMenuAboutToShow(IMenuManager menu) { + + PHPeclipsePlugin.createStandardGroups(menu); + + IStructuredSelection selection= (IStructuredSelection)getSelection(); + fActionGroups.setContext(new ActionContext(selection)); + fActionGroups.fillContextMenu(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= fCCPActionGroup.getDeleteAction(); +// } + + if (action != null && action.isEnabled()) + action.run(); + } + + /** + * Returns the IShowInSource for this view. + */ + protected IShowInSource getShowInSource() { + return new IShowInSource() { + public ShowInContext getShowInContext() { + return new ShowInContext( + null, + getSite().getSelectionProvider().getSelection()); + } + }; + } + + /** + * Returns the IShowInTarget for this view. + */ + protected IShowInTarget getShowInTarget() { + return new IShowInTarget() { + public boolean show(ShowInContext context) { + ISelection sel= context.getSelection(); + if (sel instanceof ITextSelection) { + ITextSelection tsel= (ITextSelection) sel; + int offset= tsel.getOffset(); + IJavaElement element= fEditor.getElementAt(offset); + if (element != null) { + setSelection(new StructuredSelection(element)); + return true; + } + } + return false; + } + }; + } + + private void initDragAndDrop() { + int ops= DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK; + Transfer[] transfers= new Transfer[] { + LocalSelectionTransfer.getInstance() + }; + + // Drop Adapter +// TransferDropTargetListener[] dropListeners= new TransferDropTargetListener[] { +// new SelectionTransferDropAdapter(fOutlineViewer) +// }; +// fOutlineViewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers, new DelegatingDropAdapter(dropListeners)); + + // Drag Adapter + TransferDragSourceListener[] dragListeners= new TransferDragSourceListener[] { + new SelectionTransferDragAdapter(fOutlineViewer) + }; + fOutlineViewer.addDragSupport(ops, transfers, new JdtViewerDragAdapter(fOutlineViewer, dragListeners)); + } +}