From 6fa6a2e8824b3e5d241698392e0dadcf77baf184 Mon Sep 17 00:00:00 2001 From: axelcl Date: Mon, 7 Feb 2005 22:01:03 +0000 Subject: [PATCH] fixed outline refresh bug --- .../phpdt/internal/core/JavaModelManager.java | 28 +- .../phpdt/internal/core/JavaModelOperation.java | 7 +- .../phpdt/internal/core/ModelUpdater.java | 242 ++ .../phpdt/internal/corext/util/JdtFlags.java | 291 +++ .../preferences/MembersOrderPreferenceCache.java | 115 +- .../sourceforge/phpdt/ui/JavaElementSorter.java | 132 +- .../sourceforge/phpdt/ui/PreferenceConstants.java | 39 +- .../ui/text/PHPSourceViewerConfiguration.java | 1 + .../phpeclipse/phpeditor/GotoAnnotationAction.java | 48 + .../phpeclipse/phpeditor/JavaOutlinePage.java | 2341 ++++++++++---------- 10 files changed, 2030 insertions(+), 1214 deletions(-) create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/ModelUpdater.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/JdtFlags.java create mode 100644 net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/GotoAnnotationAction.java diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelManager.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelManager.java index 9285302..6ed2fdb 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelManager.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelManager.java @@ -52,6 +52,7 @@ import net.sourceforge.phpeclipse.PHPeclipsePlugin; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; @@ -83,8 +84,7 @@ import org.eclipse.core.runtime.Preferences.PropertyChangeEvent; * the static method JavaModelManager.getJavaModelManager(). */ public class JavaModelManager implements ISaveParticipant { - - /** + /** * Unique handle onto the JavaModel */ final JavaModel javaModel = new JavaModel(); @@ -519,7 +519,7 @@ public class JavaModelManager implements ISaveParticipant { /** * Used to update the JavaModel for IJavaElementDeltas. */ -// private final ModelUpdater modelUpdater =new ModelUpdater(); + private final ModelUpdater modelUpdater =new ModelUpdater(); /** * Workaround for bug 15168 circular errors not reported * This is a cache of the projects before any project addition/deletion has started. @@ -1827,17 +1827,17 @@ public class JavaModelManager implements ISaveParticipant { /** * Update Java Model given some delta */ -// public void updateJavaModel(IJavaElementDelta customDelta) { -// -// if (customDelta == null){ -// for (int i = 0, length = this.javaModelDeltas.size(); i < length; i++){ -// IJavaElementDelta delta = (IJavaElementDelta)this.javaModelDeltas.get(i); -// this.modelUpdater.processJavaDelta(delta); -// } -// } else { -// this.modelUpdater.processJavaDelta(customDelta); -// } -// } + public void updateJavaModel(IJavaElementDelta customDelta) { + + if (customDelta == null){ + for (int i = 0, length = this.javaModelDeltas.size(); i < length; i++){ + IJavaElementDelta delta = (IJavaElementDelta)this.javaModelDeltas.get(i); + this.modelUpdater.processJavaDelta(delta); + } + } else { + this.modelUpdater.processJavaDelta(customDelta); + } + } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelOperation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelOperation.java index 2d18786..752990c 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelOperation.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelOperation.java @@ -755,11 +755,10 @@ public abstract class JavaModelOperation implements IWorkspaceRunnable, IProgres } finally { try { - // TODO jsurfer temp-del // update JavaModel using deltas that were recorded during this operation - // for (int i = previousDeltaCount, size = manager.javaModelDeltas.size(); i < size; i++) { - // manager.updateJavaModel((IJavaElementDelta)manager.javaModelDeltas.get(i)); - // } + for (int i = previousDeltaCount, size = manager.javaModelDeltas.size(); i < size; i++) { + manager.updateJavaModel((IJavaElementDelta)manager.javaModelDeltas.get(i)); + } // fire only iff: // - the operation is a top level operation diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/ModelUpdater.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/ModelUpdater.java new file mode 100644 index 0000000..f6eb8f3 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/ModelUpdater.java @@ -0,0 +1,242 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 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.phpdt.internal.core; + +import java.util.HashSet; +import java.util.Iterator; + +import net.sourceforge.phpdt.core.*; + +/** + * This class is used by JavaModelManager to update the JavaModel + * based on some IJavaElementDeltas. + */ +public class ModelUpdater { + + HashSet projectsToUpdate = new HashSet(); + + /** + * Adds the given child handle to its parent's cache of children. + */ + protected void addToParentInfo(Openable child) { + + Openable parent = (Openable) child.getParent(); + if (parent != null && parent.isOpen()) { + try { + JavaElementInfo info = (JavaElementInfo)parent.getElementInfo(); + info.addChild(child); + } catch (JavaModelException e) { + // do nothing - we already checked if open + } + } + } + + /** + * Closes the given element, which removes it from the cache of open elements. + */ + protected static void close(Openable element) { + + try { + element.close(); + } catch (JavaModelException e) { + // do nothing + } + } + + /** + * Processing for an element that has been added: + */ + protected void elementAdded(Openable element) { + + int elementType = element.getElementType(); + if (elementType == IJavaElement.JAVA_PROJECT) { + // project add is handled by JavaProject.configure() because + // when a project is created, it does not yet have a java nature + addToParentInfo(element); + this.projectsToUpdate.add(element); + } else { + addToParentInfo(element); + + // Force the element to be closed as it might have been opened + // before the resource modification came in and it might have a new child + // For example, in an IWorkspaceRunnable: + // 1. create a package fragment p using a java model operation + // 2. open package p + // 3. add file X.java in folder p + // When the resource delta comes in, only the addition of p is notified, + // but the package p is already opened, thus its children are not recomputed + // and it appears empty. + close(element); + } + + switch (elementType) { + case IJavaElement.PACKAGE_FRAGMENT_ROOT : + // when a root is added, and is on the classpath, the project must be updated + this.projectsToUpdate.add(element.getJavaProject()); + break; + case IJavaElement.PACKAGE_FRAGMENT : + // get rid of package fragment cache + JavaProject project = (JavaProject) element.getJavaProject(); +// project.resetCaches(); + break; + } + } + + /** + * Generic processing for elements with changed contents: + */ + protected void elementChanged(Openable element) { + + close(element); + } + + /** + * Generic processing for a removed element: + */ + protected void elementRemoved(Openable element) { + + if (element.isOpen()) { + close(element); + } + removeFromParentInfo(element); + int elementType = element.getElementType(); + + switch (elementType) { + case IJavaElement.JAVA_MODEL : +// JavaModelManager.getJavaModelManager().getIndexManager().reset(); + break; + case IJavaElement.JAVA_PROJECT : + JavaModelManager.getJavaModelManager().removePerProjectInfo( + (JavaProject) element); + break; + case IJavaElement.PACKAGE_FRAGMENT_ROOT : + this.projectsToUpdate.add(element.getJavaProject()); + break; + case IJavaElement.PACKAGE_FRAGMENT : + // get rid of package fragment cache + JavaProject project = (JavaProject) element.getJavaProject(); +// project.resetCaches(); + break; + } + } + + /** + * Converts a IResourceDelta rooted in a Workspace into + * the corresponding set of IJavaElementDelta, rooted in the + * relevant JavaModels. + */ + public void processJavaDelta(IJavaElementDelta delta) { + +// if (DeltaProcessor.VERBOSE){ +// System.out.println("UPDATING Model with Delta: ["+Thread.currentThread()+":" + delta + "]:");//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ +// } + + try { + this.traverseDelta(delta, null, null); // traverse delta + + // update package fragment roots of projects that were affected + Iterator iterator = this.projectsToUpdate.iterator(); + while (iterator.hasNext()) { + JavaProject project = (JavaProject) iterator.next(); + project.updatePackageFragmentRoots(); + } + } finally { + this.projectsToUpdate = new HashSet(); + } + } + + /** + * Removes the given element from its parents cache of children. If the + * element does not have a parent, or the parent is not currently open, + * this has no effect. + */ + protected void removeFromParentInfo(Openable child) { + + Openable parent = (Openable) child.getParent(); + if (parent != null && parent.isOpen()) { + try { + JavaElementInfo info = (JavaElementInfo)parent.getElementInfo(); + info.removeChild(child); + } catch (JavaModelException e) { + // do nothing - we already checked if open + } + } + } + + /** + * Converts an IResourceDelta and its children into + * the corresponding IJavaElementDeltas. + * Return whether the delta corresponds to a resource on the classpath. + * If it is not a resource on the classpath, it will be added as a non-java + * resource by the sender of this method. + */ + protected void traverseDelta( + IJavaElementDelta delta, + IPackageFragmentRoot root, + IJavaProject project) { + + boolean processChildren = true; + + Openable element = (Openable) delta.getElement(); + switch (element.getElementType()) { + case IJavaElement.JAVA_PROJECT : + project = (IJavaProject) element; + break; + case IJavaElement.PACKAGE_FRAGMENT_ROOT : + root = (IPackageFragmentRoot) element; + break; + case IJavaElement.COMPILATION_UNIT : + // filter out working copies that are not primary (we don't want to add/remove them to/from the package fragment + CompilationUnit cu = (CompilationUnit)element; + if (cu.isWorkingCopy() && !cu.isPrimary()) { + return; + } + case IJavaElement.CLASS_FILE : + processChildren = false; + break; + } + + switch (delta.getKind()) { + case IJavaElementDelta.ADDED : + elementAdded(element); + break; + case IJavaElementDelta.REMOVED : + elementRemoved(element); + break; + case IJavaElementDelta.CHANGED : + if ((delta.getFlags() & IJavaElementDelta.F_CONTENT) != 0){ + elementChanged(element); + } + break; + } + if (processChildren) { + IJavaElementDelta[] children = delta.getAffectedChildren(); + for (int i = 0; i < children.length; i++) { + IJavaElementDelta childDelta = children[i]; + this.traverseDelta(childDelta, root, project); + } + } + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/JdtFlags.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/JdtFlags.java new file mode 100644 index 0000000..9b70220 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/util/JdtFlags.java @@ -0,0 +1,291 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 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.phpdt.internal.corext.util; + +import java.lang.reflect.Modifier; + +import net.sourceforge.phpdt.core.Flags; +import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.IMember; +import net.sourceforge.phpdt.core.IType; +import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.internal.corext.Assert; +import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration; + +public class JdtFlags { + private JdtFlags(){ + } + + public static final String VISIBILITY_STRING_PRIVATE= "private"; //$NON-NLS-1$ + public static final String VISIBILITY_STRING_PACKAGE= ""; //$NON-NLS-1$ + public static final String VISIBILITY_STRING_PROTECTED= "protected"; //$NON-NLS-1$ + public static final String VISIBILITY_STRING_PUBLIC= "public"; //$NON-NLS-1$ + + + public static final int VISIBILITY_CODE_INVALID= -1; + + public static boolean isAbstract(IMember member) throws JavaModelException{ + if (isInterfaceMethod(member)) + return true; + return Flags.isAbstract(member.getFlags()); + } + +// public static boolean isAbstract(IMethodBinding member) { +// if (isInterfaceMember(member)) +// return true; +// return Modifier.isAbstract(member.getModifiers()); +// } + + public static boolean isDeprecated(IMember member) throws JavaModelException{ + return Flags.isDeprecated(member.getFlags()); + } + + public static boolean isFinal(IMember member) throws JavaModelException{ + if (isInterfaceField(member)) + return true; + if (isAnonymousType(member)) + return true; + return Flags.isFinal(member.getFlags()); + } + +// public static boolean isNative(IMember member) throws JavaModelException{ +// return Flags.isNative(member.getFlags()); +// } + + public static boolean isPackageVisible(IMember member) throws JavaModelException{ + return (! isPrivate(member) && ! isProtected(member) && ! isPublic(member)); + } + +// public static boolean isPackageVisible(BodyDeclaration bodyDeclaration) { +// return (! isPrivate(bodyDeclaration) && ! isProtected(bodyDeclaration) && ! isPublic(bodyDeclaration)); +// } +// +// public static boolean isPackageVisible(IBinding binding) { +// return (! isPrivate(binding) && ! isProtected(binding) && ! isPublic(binding)); +// } + + public static boolean isPrivate(IMember member) throws JavaModelException{ + return Flags.isPrivate(member.getFlags()); + } + +// public static boolean isPrivate(BodyDeclaration bodyDeclaration) { +// return Modifier.isPrivate(bodyDeclaration.getModifiers()); +// } +// +// public static boolean isPrivate(IBinding binding) { +// return Modifier.isPrivate(binding.getModifiers()); +// } + + public static boolean isProtected(IMember member) throws JavaModelException{ + return Flags.isProtected(member.getFlags()); + } + +// public static boolean isProtected(BodyDeclaration bodyDeclaration) { +// return Modifier.isProtected(bodyDeclaration.getModifiers()); +// } +// +// public static boolean isProtected(IBinding binding) { +// return Modifier.isProtected(binding.getModifiers()); +// } + + public static boolean isPublic(IMember member) throws JavaModelException{ + if (isInterfaceMember(member)) + return true; + return Flags.isPublic(member.getFlags()); + } + +// public static boolean isPublic(IBinding binding) { +// if (isInterfaceMember(binding)) +// return true; +// return Modifier.isPublic(binding.getModifiers()); +// } +// +// +// public static boolean isPublic(BodyDeclaration bodyDeclaration) { +// if (isInterfaceMember(bodyDeclaration)) +// return true; +// return Modifier.isPublic(bodyDeclaration.getModifiers()); +// } + + public static boolean isStatic(IMember member) throws JavaModelException{ + if (isNestedInterface(member)) + return true; + if (member.getElementType() != IJavaElement.METHOD && isInterfaceMember(member)) + return true; + return Flags.isStatic(member.getFlags()); + } + +// public static boolean isStatic(IMethodBinding methodBinding){ +// return Modifier.isStatic(methodBinding.getModifiers()); +// } +// +// public static boolean isStatic(IVariableBinding variableBinding){ +// if (isInterfaceMember(variableBinding)) +// return true; +// return Modifier.isStatic(variableBinding.getModifiers()); +// } + +// public static boolean isStrictfp(IMember member) throws JavaModelException{ +// return Flags.isStrictfp(member.getFlags()); +// } +// +// public static boolean isSynchronized(IMember member) throws JavaModelException{ +// return Flags.isSynchronized(member.getFlags()); +// } +// +// public static boolean isSynthetic(IMember member) throws JavaModelException{ +// return Flags.isSynthetic(member.getFlags()); +// } +// +// public static boolean isTransient(IMember member) throws JavaModelException{ +// return Flags.isTransient(member.getFlags()); +// } + +// public static boolean isVolatile(IMember member) throws JavaModelException{ +// return Flags.isVolatile(member.getFlags()); +// } + + private static boolean isInterfaceMethod(IMember member) throws JavaModelException { + return member.getElementType() == IJavaElement.METHOD && isInterfaceMember(member); + } + + private static boolean isInterfaceField(IMember member) throws JavaModelException { + return member.getElementType() == IJavaElement.FIELD && isInterfaceMember(member); + } + + private static boolean isInterfaceMember(IMember member) throws JavaModelException { + return member.getDeclaringType() != null && member.getDeclaringType().isInterface(); + } + +// private static boolean isInterfaceMember(IBinding binding) { +// ITypeBinding declaringType= null; +// if (binding instanceof IVariableBinding) { +// declaringType= ((IVariableBinding) binding).getDeclaringClass(); +// } else if (binding instanceof IMethodBinding) { +// declaringType= ((IMethodBinding) binding).getDeclaringClass(); +// } else if (binding instanceof ITypeBinding) { +// declaringType= ((ITypeBinding) binding).getDeclaringClass(); +// } +// return declaringType != null && declaringType.isInterface(); +// } + +// private static boolean isInterfaceMember(BodyDeclaration bodyDeclaration) { +// return (bodyDeclaration.getParent() instanceof TypeDeclaration) && +// ((TypeDeclaration)bodyDeclaration.getParent()).isInterface(); +// } + + private static boolean isNestedInterface(IMember member) throws JavaModelException{ + return member.getElementType() == IJavaElement.TYPE && + member.getDeclaringType() != null && + ((IType)member).isInterface(); + } + + private static boolean isAnonymousType(IMember member) throws JavaModelException { + return member.getElementType() == IJavaElement.TYPE && + ((IType)member).isAnonymous(); + } + + public static int getVisibilityCode(IMember member) throws JavaModelException { + if (isPublic(member)) + return Modifier.PUBLIC; + else if (isProtected(member)) + return Modifier.PROTECTED; +// else if (isPackageVisible(member)) +// return Modifier.NONE; + else if (isPrivate(member)) + return Modifier.PRIVATE; +// Assert.isTrue(false); +// return VISIBILITY_CODE_INVALID; + return Modifier.PUBLIC; + } + +// public static int getVisibilityCode(BodyDeclaration bodyDeclaration) { +// if (isPublic(bodyDeclaration)) +// return Modifier.PUBLIC; +// else if (isProtected(bodyDeclaration)) +// return Modifier.PROTECTED; +// else if (isPackageVisible(bodyDeclaration)) +// return Modifier.NONE; +// else if (isPrivate(bodyDeclaration)) +// return Modifier.PRIVATE; +// Assert.isTrue(false); +// return VISIBILITY_CODE_INVALID; +// } + +// public static int getVisibilityCode(IBinding binding) { +// if (isPublic(binding)) +// return Modifier.PUBLIC; +// else if (isProtected(binding)) +// return Modifier.PROTECTED; +// else if (isPackageVisible(binding)) +// return Modifier.NONE; +// else if (isPrivate(binding)) +// return Modifier.PRIVATE; +// Assert.isTrue(false); +// return VISIBILITY_CODE_INVALID; +// } + + + public static String getVisibilityString(int visibilityCode){ + if (Modifier.isPublic(visibilityCode)) + return VISIBILITY_STRING_PUBLIC; + if (Modifier.isProtected(visibilityCode)) + return VISIBILITY_STRING_PROTECTED; + if (Modifier.isPrivate(visibilityCode)) + return VISIBILITY_STRING_PRIVATE; + return VISIBILITY_STRING_PACKAGE; + } + + public static void assertVisibility(int visibility){ + Assert.isTrue( visibility == Modifier.PUBLIC || + visibility == Modifier.PROTECTED || +// visibility == Modifier.NONE || + visibility == Modifier.PRIVATE); + } + + public static boolean isHigherVisibility(int newVisibility, int oldVisibility){ + assertVisibility(oldVisibility); + assertVisibility(newVisibility); + switch (oldVisibility) { + case Modifier.PRIVATE : + return //newVisibility == Modifier.NONE || + newVisibility == Modifier.PUBLIC + || newVisibility == Modifier.PROTECTED; +// case Modifier.NONE : +// return newVisibility == Modifier.PUBLIC +// || newVisibility == Modifier.PROTECTED; + + case Modifier.PROTECTED : + return newVisibility == Modifier.PUBLIC; + + case Modifier.PUBLIC : + return false; + default: +// Assert.isTrue(false); + return false; + } + } + + public static int getLowerVisibility(int visibility1, int visibility2) { + if (isHigherVisibility(visibility1, visibility2)) + return visibility2; + else + return visibility1; + } + + public static int clearAccessModifiers(int flags) { + return clearFlag(Modifier.PROTECTED | Modifier.PUBLIC | Modifier.PRIVATE, flags); + } + + public static int clearFlag(int flag, int flags){ + return flags & ~ flag; + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/preferences/MembersOrderPreferenceCache.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/preferences/MembersOrderPreferenceCache.java index af66a6f..7223502 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/preferences/MembersOrderPreferenceCache.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/preferences/MembersOrderPreferenceCache.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2003 IBM Corporation and others. + * Copyright (c) 2000, 2004 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 @@ -12,12 +12,13 @@ package net.sourceforge.phpdt.internal.ui.preferences; import java.util.StringTokenizer; -import net.sourceforge.phpdt.ui.PreferenceConstants; - import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; +import net.sourceforge.phpdt.core.Flags; + +import net.sourceforge.phpdt.ui.PreferenceConstants; /** */ @@ -31,36 +32,63 @@ public class MembersOrderPreferenceCache implements IPropertyChangeListener { public static final int STATIC_FIELDS_INDEX= 5; public static final int STATIC_INIT_INDEX= 6; public static final int STATIC_METHODS_INDEX= 7; - public static final int N_ENTRIES= STATIC_METHODS_INDEX + 1; + public static final int N_CATEGORIES= STATIC_METHODS_INDEX + 1; + + private static final int PUBLIC_INDEX= 0; + private static final int PRIVATE_INDEX= 1; + private static final int PROTECTED_INDEX= 2; + private static final int DEFAULT_INDEX= 3; + private static final int N_VISIBILITIES= DEFAULT_INDEX + 1; + + private int[] fCategoryOffsets= null; + + private boolean fSortByVisibility; + private int[] fVisibilityOffsets= null; + + public MembersOrderPreferenceCache() { + fCategoryOffsets= null; + fSortByVisibility= PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER); + fVisibilityOffsets= null; + } - private int[] fOffsets= null; + public static boolean isMemberOrderProperty(String property) { + return PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER.equals(property) + || PreferenceConstants.APPEARANCE_VISIBILITY_SORT_ORDER.equals(property) + || PreferenceConstants.APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER.equals(property); + } public void propertyChange(PropertyChangeEvent event) { - if (PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER.equals(event.getProperty())) { - fOffsets= null; + String property= event.getProperty(); + + if (PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER.equals(property)) { + fCategoryOffsets= null; + } else if (PreferenceConstants.APPEARANCE_VISIBILITY_SORT_ORDER.equals(property)) { + fVisibilityOffsets= null; + } else if (PreferenceConstants.APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER.equals(property)) { + fSortByVisibility= PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER); } } - public int getIndex(int kind) { - if (fOffsets == null) { - fOffsets= getOffsets(); + public int getCategoryIndex(int kind) { + if (fCategoryOffsets == null) { + fCategoryOffsets= getCategoryOffsets(); } - return fOffsets[kind]; + return fCategoryOffsets[kind]; } - private int[] getOffsets() { - int[] offsets= new int[N_ENTRIES]; + private int[] getCategoryOffsets() { + int[] offsets= new int[N_CATEGORIES]; IPreferenceStore store= PreferenceConstants.getPreferenceStore(); String key= PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER; - boolean success= fillOffsetsFromPreferenceString(store.getString(key), offsets); + boolean success= fillCategoryOffsetsFromPreferenceString(store.getString(key), offsets); if (!success) { store.setToDefault(key); - fillOffsetsFromPreferenceString(store.getDefaultString(key), offsets); + fillCategoryOffsetsFromPreferenceString(store.getDefaultString(key), offsets); } return offsets; - } + } - private boolean fillOffsetsFromPreferenceString(String str, int[] offsets) { + private boolean fillCategoryOffsetsFromPreferenceString(String str, int[] offsets) { StringTokenizer tokenizer= new StringTokenizer(str, ","); //$NON-NLS-1$ int i= 0; while (tokenizer.hasMoreTokens()) { @@ -83,7 +111,58 @@ public class MembersOrderPreferenceCache implements IPropertyChangeListener { offsets[CONSTRUCTORS_INDEX]= i++; } } - return i == N_ENTRIES; + return i == N_CATEGORIES; + } + + public boolean isSortByVisibility() { + return fSortByVisibility; + } + + + public int getVisibilityIndex(int modifierFlags) { + if (fVisibilityOffsets == null) { + fVisibilityOffsets= getVisibilityOffsets(); + } + int kind= DEFAULT_INDEX; + if (Flags.isPublic(modifierFlags)) { + kind= PUBLIC_INDEX; + } else if (Flags.isProtected(modifierFlags)) { + kind= PROTECTED_INDEX; + } else if (Flags.isPrivate(modifierFlags)) { + kind= PRIVATE_INDEX; + } + + return fVisibilityOffsets[kind]; + } + + private int[] getVisibilityOffsets() { + int[] offsets= new int[N_VISIBILITIES]; + IPreferenceStore store= PreferenceConstants.getPreferenceStore(); + String key= PreferenceConstants.APPEARANCE_VISIBILITY_SORT_ORDER; + boolean success= fillVisibilityOffsetsFromPreferenceString(store.getString(key), offsets); + if (!success) { + store.setToDefault(key); + fillVisibilityOffsetsFromPreferenceString(store.getDefaultString(key), offsets); + } + return offsets; + } + + private boolean fillVisibilityOffsetsFromPreferenceString(String str, int[] offsets) { + StringTokenizer tokenizer= new StringTokenizer(str, ","); //$NON-NLS-1$ + int i= 0; + while (tokenizer.hasMoreTokens()) { + String token= tokenizer.nextToken().trim(); + if ("B".equals(token)) { //$NON-NLS-1$ + offsets[PUBLIC_INDEX]= i++; + } else if ("V".equals(token)) { //$NON-NLS-1$ + offsets[PRIVATE_INDEX]= i++; + } else if ("R".equals(token)) { //$NON-NLS-1$ + offsets[PROTECTED_INDEX]= i++; + } else if ("D".equals(token)) { //$NON-NLS-1$ + offsets[DEFAULT_INDEX]= i++; + } + } + return i == N_VISIBILITIES; } diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/JavaElementSorter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/JavaElementSorter.java index 95bcc5e..ce6061d 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/JavaElementSorter.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/JavaElementSorter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2003 IBM Corporation and others. + * Copyright (c) 2000, 2004 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 @@ -15,11 +15,15 @@ import java.text.Collator; import net.sourceforge.phpdt.core.Flags; import net.sourceforge.phpdt.core.IField; import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.IMember; import net.sourceforge.phpdt.core.IMethod; import net.sourceforge.phpdt.core.IPackageFragment; import net.sourceforge.phpdt.core.IPackageFragmentRoot; +import net.sourceforge.phpdt.core.IType; import net.sourceforge.phpdt.core.JavaModelException; import net.sourceforge.phpdt.core.Signature; +import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil; +import net.sourceforge.phpdt.internal.corext.util.JdtFlags; import net.sourceforge.phpdt.internal.ui.preferences.MembersOrderPreferenceCache; import net.sourceforge.phpeclipse.PHPeclipsePlugin; @@ -28,6 +32,7 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; import org.eclipse.jface.viewers.ContentViewer; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.ILabelProvider; @@ -70,8 +75,14 @@ public class JavaElementSorter extends ViewerSorter { private static final int JAVAELEMENTS= 50; private static final int OTHERS= 51; - public JavaElementSorter() { + private MembersOrderPreferenceCache fMemberOrderCache; + + /** + * Constructor. + */ + public JavaElementSorter() { super(null); // delay initialization of collator + fMemberOrderCache= PHPeclipsePlugin.getDefault().getMemberOrderPreferenceCache(); } /** @@ -144,7 +155,8 @@ public class JavaElementSorter extends ViewerSorter { } } catch (JavaModelException e) { - PHPeclipsePlugin.log(e); + if (!e.isDoesNotExist()) + PHPeclipsePlugin.log(e); } return JAVAELEMENTS; } else if (element instanceof IFile) { @@ -155,17 +167,18 @@ public class JavaElementSorter extends ViewerSorter { return RESOURCEFOLDERS; } else if (element instanceof IStorage) { return STORAGE; -// } else if (element instanceof ClassPathContainer) { + } +// else if (element instanceof ClassPathContainer) { // return PACKAGEFRAGMENTROOTS; - } +// } return OTHERS; } private int getMemberCategory(int kind) { - int offset= PHPeclipsePlugin.getDefault().getMemberOrderPreferenceCache().getIndex(kind); + int offset= fMemberOrderCache.getCategoryIndex(kind); return offset + MEMBERSOFFSET; - } - + } + /* * @see ViewerSorter#compare */ @@ -182,26 +195,66 @@ public class JavaElementSorter extends ViewerSorter { return getCollator().compare(a1.getLabel(e1), a2.getLabel(e2)); } -// if (cat1 == PACKAGEFRAGMENTROOTS) { -// IPackageFragmentRoot root1= getPackageFragmentRoot(e1); -// IPackageFragmentRoot root2= getPackageFragmentRoot(e2); -// if (!root1.getPath().equals(root2.getPath())) { -// int p1= getClassPathIndex(root1); -// int p2= getClassPathIndex(root2); -// if (p1 != p2) { -// return p1 - p2; -// } -// } -// } + if (cat1 == PACKAGEFRAGMENTROOTS) { + IPackageFragmentRoot root1= getPackageFragmentRoot(e1); + IPackageFragmentRoot root2= getPackageFragmentRoot(e2); + if (root1 == null) { + if (root2 == null) { + return 0; + } else { + return 1; + } + } else if (root2 == null) { + return -1; + } + if (!root1.getPath().equals(root2.getPath())) { + int p1= getClassPathIndex(root1); + int p2= getClassPathIndex(root2); + if (p1 != p2) { + return p1 - p2; + } + } + e1= root1; // normalize classpath container to root + e2= root2; + } // non - java resources are sorted using the label from the viewers label provider if (cat1 == PROJECTS || cat1 == RESOURCES || cat1 == RESOURCEFOLDERS || cat1 == STORAGE || cat1 == OTHERS) { return compareWithLabelProvider(viewer, e1, e2); } + if (e1 instanceof IMember) { + if (fMemberOrderCache.isSortByVisibility()) { + try { + int flags1= JdtFlags.getVisibilityCode((IMember) e1); + int flags2= JdtFlags.getVisibilityCode((IMember) e2); + int vis= fMemberOrderCache.getVisibilityIndex(flags1) - fMemberOrderCache.getVisibilityIndex(flags2); + if (vis != 0) { + return vis; + } + } catch (JavaModelException ignore) { + } + } + } + String name1= ((IJavaElement) e1).getElementName(); String name2= ((IJavaElement) e2).getElementName(); - // java element are sorted by name + if (e1 instanceof IType) { // handle anonymous types + if (name1.length() == 0) { + if (name2.length() == 0) { + try { + return getCollator().compare(((IType) e1).getSuperclassName(), ((IType) e2).getSuperclassName()); + } catch (JavaModelException e) { + return 0; + } + } else { + return 1; + } + } else if (name2.length() == 0) { + return -1; + } + } + int cmp= getCollator().compare(name1, name2); if (cmp != 0) { return cmp; @@ -221,19 +274,20 @@ public class JavaElementSorter extends ViewerSorter { } return 0; } + -// private IPackageFragmentRoot getPackageFragmentRoot(Object element) { + private IPackageFragmentRoot getPackageFragmentRoot(Object element) { // if (element instanceof ClassPathContainer) { // // return first package fragment root from the container // ClassPathContainer cp= (ClassPathContainer)element; // Object[] roots= cp.getPackageFragmentRoots(); // if (roots.length > 0) // return (IPackageFragmentRoot)roots[0]; -// // non resolvable - return a dummy package fragment root -// return cp.getJavaProject().getPackageFragmentRoot("Non-Resolvable"); //$NON-NLS-1$ +// // non resolvable - return null +// return null; // } -// return JavaModelUtil.getPackageFragmentRoot((IJavaElement)element); -// } + return JavaModelUtil.getPackageFragmentRoot((IJavaElement)element); + } private int compareWithLabelProvider(Viewer viewer, Object e1, Object e2) { if (viewer == null || !(viewer instanceof ContentViewer)) { @@ -250,20 +304,20 @@ public class JavaElementSorter extends ViewerSorter { return 0; // can't compare } -// private int getClassPathIndex(IPackageFragmentRoot root) { -// try { -// IPath rootPath= root.getPath(); -// IPackageFragmentRoot[] roots= root.getJavaProject().getPackageFragmentRoots(); -// for (int i= 0; i < roots.length; i++) { -// if (roots[i].getPath().equals(rootPath)) { -// return i; -// } -// } -// } catch (JavaModelException e) { -// } -// -// return Integer.MAX_VALUE; -// } + private int getClassPathIndex(IPackageFragmentRoot root) { + try { + IPath rootPath= root.getPath(); + IPackageFragmentRoot[] roots= root.getJavaProject().getPackageFragmentRoots(); + for (int i= 0; i < roots.length; i++) { + if (roots[i].getPath().equals(rootPath)) { + return i; + } + } + } catch (JavaModelException e) { + } + + return Integer.MAX_VALUE; + } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ViewerSorter#getCollator() diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/PreferenceConstants.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/PreferenceConstants.java index c2b5815..8a27f28 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/PreferenceConstants.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/PreferenceConstants.java @@ -20,9 +20,7 @@ import org.eclipse.jface.action.Action; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.widgets.Display; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import org.eclipse.ui.texteditor.AbstractTextEditor; @@ -108,6 +106,34 @@ public class PreferenceConstants { public static final String APPEARANCE_MEMBER_SORT_ORDER = "outlinesortoption"; //$NON-NLS-1$ /** + * A named preference that defines how member elements are ordered by visibility in the Java views using the + * JavaElementSorter. + *

+ * Value is of type String: A comma separated list of the following entries. Each entry must be in the list, no + * duplication. List order defines the sort order. + *

+ *

+ * + * @since 3.0 + */ + public static final String APPEARANCE_VISIBILITY_SORT_ORDER = "net.sourceforge.phpdt.ui.visibility.order"; //$NON-NLS-1$ + + /** + * A named preferences that controls if Java elements are also sorted by visibility. + *

+ * Value is of type Boolean. + *

+ * + * @since 3.0 + */ + public static final String APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER = "net.sourceforge.phpdt.ui.enable.visibility.order"; //$NON-NLS-1$ + + /** * A named preference that controls if prefix removal during setter/getter generation is turned on or off. *

* Value is of type Boolean. @@ -515,7 +541,8 @@ public class PreferenceConstants { *

*/ public final static String EDITOR_TAB_WIDTH = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH; //"net.sourceforge.phpdt.ui.editor.tab.width"; - // //$NON-NLS-1$ + + // //$NON-NLS-1$ /** * A named preference that controls whether the outline view selection should stay in sync with with the element at the current @@ -2248,12 +2275,14 @@ public class PreferenceConstants { store.setDefault(PreferenceConstants.CODEGEN__FILE_COMMENTS, false); // MembersOrderPreferencePage - store.setDefault(PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER, "T,SI,SF,SM,I,F,C,M"); //$NON-NLS-1$ + store.setDefault(PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER, "T,SF,SI,SM,I,F,C,M"); //$NON-NLS-1$ + store.setDefault(PreferenceConstants.APPEARANCE_VISIBILITY_SORT_ORDER, "B,V,R,D"); //$NON-NLS-1$ + store.setDefault(PreferenceConstants.APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER, false); // must add here to guarantee that it is the first in the listener list store.addPropertyChangeListener(PHPeclipsePlugin.getDefault().getMemberOrderPreferenceCache()); store.setDefault(PreferenceConstants.EDITOR_MATCHING_BRACKETS, true); - PreferenceConverter.setDefault(store, PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR, new RGB(192, 192,192)); + PreferenceConverter.setDefault(store, PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR, new RGB(192, 192, 192)); store.setDefault(PreferenceConstants.EDITOR_CURRENT_LINE, true); PreferenceConverter.setDefault(store, PreferenceConstants.EDITOR_CURRENT_LINE_COLOR, new RGB(225, 235, 224)); diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/text/PHPSourceViewerConfiguration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/text/PHPSourceViewerConfiguration.java index aa3c70b..7708050 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/text/PHPSourceViewerConfiguration.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/text/PHPSourceViewerConfiguration.java @@ -992,6 +992,7 @@ public class PHPSourceViewerConfiguration extends SourceViewerConfiguration { presenter.setAnchor(InformationPresenter.ANCHOR_GLOBAL); IInformationProvider provider = new JavaElementProvider(getEditor(), doCodeResolve); presenter.setInformationProvider(provider, IDocument.DEFAULT_CONTENT_TYPE); + presenter.setInformationProvider(provider, PHPDocumentPartitioner.PHP_SCRIPT_CODE); presenter.setInformationProvider(provider, IPHPPartitions.PHP_PARTITIONING); presenter.setInformationProvider(provider, IPHPPartitions.PHP_PHPDOC_COMMENT); presenter.setInformationProvider(provider, IPHPPartitions.SMARTY_MULTILINE_COMMENT); diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/GotoAnnotationAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/GotoAnnotationAction.java new file mode 100644 index 0000000..f3bf5cb --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/GotoAnnotationAction.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 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 org.eclipse.ui.help.WorkbenchHelp; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.TextEditorAction; + +import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds; + + +public class GotoAnnotationAction extends TextEditorAction { + + private boolean fForward; + + public GotoAnnotationAction(String prefix, boolean forward) { + super(PHPEditorMessages.getResourceBundle(), prefix, null); + fForward= forward; + if (forward) + WorkbenchHelp.setHelp(this, IJavaHelpContextIds.GOTO_NEXT_ERROR_ACTION); + else + WorkbenchHelp.setHelp(this, IJavaHelpContextIds.GOTO_PREVIOUS_ERROR_ACTION); + } + + public void run() { + PHPEditor e= (PHPEditor) getTextEditor(); + e.gotoAnnotation(fForward); + } + + public void setEditor(ITextEditor editor) { + if (editor instanceof PHPEditor) + super.setEditor(editor); + update(); + } + + public void update() { + setEnabled(getTextEditor() instanceof PHPEditor); + } +} diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/JavaOutlinePage.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/JavaOutlinePage.java index ed2a133..6a23ef8 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/JavaOutlinePage.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/JavaOutlinePage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2003 IBM Corporation and others. + * Copyright (c) 2000, 2004 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 @@ -10,6 +10,7 @@ *******************************************************************************/ package net.sourceforge.phpeclipse.phpeditor; + import java.util.Enumeration; import java.util.Hashtable; import java.util.List; @@ -18,21 +19,26 @@ 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.IField; 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.JavaCore; import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil; +import net.sourceforge.phpdt.internal.ui.IJavaHelpContextIds; import net.sourceforge.phpdt.internal.ui.PHPUiImages; import net.sourceforge.phpdt.internal.ui.actions.AbstractToggleLinkingAction; import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup; import net.sourceforge.phpdt.internal.ui.dnd.JdtViewerDragAdapter; import net.sourceforge.phpdt.internal.ui.dnd.TransferDragSourceListener; import net.sourceforge.phpdt.internal.ui.packageview.SelectionTransferDragAdapter; +import net.sourceforge.phpdt.internal.ui.preferences.MembersOrderPreferenceCache; import net.sourceforge.phpdt.internal.ui.viewsupport.AppearanceAwareLabelProvider; import net.sourceforge.phpdt.internal.ui.viewsupport.DecoratingJavaLabelProvider; import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementLabels; @@ -44,6 +50,7 @@ import net.sourceforge.phpdt.ui.ProblemsLabelDecorator.ProblemsLabelChangedEvent import net.sourceforge.phpdt.ui.actions.CustomFiltersActionGroup; import net.sourceforge.phpdt.ui.actions.GenerateActionGroup; import net.sourceforge.phpdt.ui.actions.MemberFilterActionGroup; +import net.sourceforge.phpdt.ui.actions.PHPdtActionConstants; import net.sourceforge.phpeclipse.PHPeclipsePlugin; import org.eclipse.core.resources.IResource; @@ -78,7 +85,6 @@ 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.KeyEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; @@ -89,6 +95,7 @@ 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.help.WorkbenchHelp; import org.eclipse.ui.model.IWorkbenchAdapter; import org.eclipse.ui.model.WorkbenchAdapter; import org.eclipse.ui.part.IPageSite; @@ -98,1172 +105,1238 @@ 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.ITextEditorActionDefinitionIds; 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; +import org.eclipse.ui.views.navigator.RefactorActionGroup; + /** - * 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". + * 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. + * Publishes its context menu under PHPeclipsePlugin.getDefault().getPluginId() + ".outline". */ -public class JavaOutlinePage extends Page implements IContentOutlinePage, IAdaptable, IPostSelectionProvider { - - 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 class JavaOutlinePage extends Page implements IContentOutlinePage, IAdaptable , IPostSelectionProvider { + + 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); +// } + } + }); + } + } + + private boolean isPossibleStructuralChange(IJavaElementDelta cuDelta) { + if (cuDelta.getKind() != IJavaElementDelta.CHANGED) { + return true; // add or remove + } + int flags= cuDelta.getFlags(); + if ((flags & IJavaElementDelta.F_CHILDREN) != 0) { + return true; + } + return (flags & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_FINE_GRAINED)) == IJavaElementDelta.F_CONTENT; + } + + protected IJavaElementDelta findElement(IJavaElement unit, IJavaElementDelta delta) { + + if (delta == null || unit == null) + return null; + + IJavaElement element= delta.getElement(); + + if (unit.equals(element)) { + if (isPossibleStructuralChange(delta)) { + return delta; + } + return null; + } + + + 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) { + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=38341 + // don't log NotExist exceptions as this is a valid case + // since we might have been posted and the element + // removed in the meantime. + if (PHPeclipsePlugin.isDebug() || !x.isDoesNotExist()) + 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) { +// PHPeclipsePlugin.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) { + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=38341 + // don't log NotExist exceptions as this is a valid case + // since we might have been posted and the element + // removed in the meantime. + if (PHPeclipsePlugin.isDebug() || !x.isDoesNotExist()) + PHPeclipsePlugin.log(x); + } + } + return false; + } + + public boolean isDeleted(Object o) { + return false; + } + + public void dispose() { + if (fListener != null) { + JavaCore.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(); + JavaCore.addElementChangedListener(fListener); + } else if (!isCU && fListener != null) { + JavaCore.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; + private boolean fForceFireSelectionChanged; + + public JavaOutlineViewer(Tree tree) { + super(tree); + setAutoExpandLevel(ALL_LEVELS); + setUseHashlookup(true); + } + + /** + * Investigates the given element change event and if affected + * incrementally updates the Java outline. + * + * @param delta the Java element delta used to reconcile the Java outline + */ + public void reconcile(IJavaElementDelta delta) { + fReorderedMembers= false; + fForceFireSelectionChanged= 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 (fForceFireSelectionChanged) + fireSelectionChanged(new SelectionChangedEvent(getSite().getSelectionProvider(), this.getSelection())); + 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; + fForceFireSelectionChanged= true; + } + + 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; + } + + /* + * @see org.eclipse.jface.viewers.AbstractTreeViewer#isExpandable(java.lang.Object) + */ + public boolean isExpandable(Object element) { + if (hasFilters()) { + return getFilteredChildren(element).length > 0; + } + return super.isExpandable(element); + } + + protected ISourceRange getSourceRange(IJavaElement element) throws JavaModelException { + if (element instanceof ISourceReference) + return ((ISourceReference) element).getSourceRange(); + if (element instanceof IMember)// && !(element instanceof IInitializer)) + return ((IMember) element).getNameRange(); + 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; + boolean doUpdateParentsPlus= 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) { + // remove from collapsed parent + if ((status & IJavaElementDelta.REMOVED) != 0) { + doUpdateParentsPlus= true; + continue; + } + // 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; + int nameOffset= Integer.MAX_VALUE; + if (e instanceof IField) { + ISourceRange nameRange= ((IField) e).getNameRange(); + if (nameRange != null) + nameOffset= nameRange.getOffset(); + } + + 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); + + // multi-field declarations always start at + // the same offset. They also have the same + // end offset if the field sequence is terminated + // with a semicolon. If not, the source range + // ends behind the identifier / initializer + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=51851 + boolean multiFieldDeclaration= + r.getElementType() == IJavaElement.FIELD + && e.getElementType() == IJavaElement.FIELD + && rng.getOffset() == start; + + // elements are inserted by occurrence + // however, multi-field declarations have + // equal source ranges offsets, therefore we + // compare name-range offsets. + boolean multiFieldOrderBefore= false; + if (multiFieldDeclaration) { + if (r instanceof IField) { + ISourceRange nameRange= ((IField) r).getNameRange(); + if (nameRange != null) { + if (nameRange.getOffset() > nameOffset) + multiFieldOrderBefore= true; + } + } + } + + if (!multiFieldDeclaration && 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 (multiFieldOrderBefore || rng.getOffset() > start) { + + if (last != null && deletions.contains(last)) { + // reuse item + deletions.removeElement(last); + reuseTreeItem(last, e); + } else { + // nothing to reuse + createTreeItem(w, 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()); + if (!doUpdateParent && doUpdateParentsPlus && w instanceof Item) + updatePlus((Item)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; + cu= JavaModelUtil.toOriginal(cu); + return cu.getResource(); + } +// else if (input instanceof IClassFile) { +// return ((IClassFile) input).getResource(); +// } + 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; - } + } + + 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$ + } + } - public boolean isDeleted(Object o) { - return false; - } + class ClassOnlyAction extends Action { - public void dispose() { - if (fListener != null) { - JavaCore.removeElementChangedListener(fListener); - fListener = null; - } - } + 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$ - /* - * @see IContentProvider#inputChanged(Viewer, Object, Object) - */ - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - boolean isCU = (newInput instanceof ICompilationUnit); + IPreferenceStore preferenceStore= PHPeclipsePlugin.getDefault().getPreferenceStore(); + boolean showclass= preferenceStore.getBoolean("GoIntoTopLevelTypeAction.isChecked"); //$NON-NLS-1$ + setTopLevelTypeOnly(showclass); + } - if (isCU && fListener == null) { - fListener = new ElementChangedListener(); - JavaCore.addElementChangedListener(fListener); - } else if (!isCU && fListener != null) { - JavaCore.removeElementChangedListener(fListener); - fListener = null; - } - } - }; + /* + * @see org.eclipse.jface.action.Action#run() + */ + public void run() { + setTopLevelTypeOnly(!fTopLevelTypeOnly); + } - class JavaOutlineViewer extends TreeViewer { + 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$ + } + } - /** - * 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; + /** + * This action toggles whether this Java Outline page links + * its selection to the active editor. + * + * @since 3.0 + */ + public class ToggleLinkingAction extends AbstractToggleLinkingAction { + + JavaOutlinePage fJavaOutlinePage; + + /** + * Constructs a new action. + * + * @param outlinePage the Java outline page + */ + public ToggleLinkingAction(JavaOutlinePage outlinePage) { + boolean isLinkingEnabled= PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE); + setChecked(isLinkingEnabled); + fJavaOutlinePage= outlinePage; + } + + /** + * Runs the action. + */ + public void run() { + PreferenceConstants.getPreferenceStore().setValue(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE, isChecked()); + if (isChecked() && fEditor != null) + fEditor.synchronizeOutlinePage(fEditor.computeHighlightRangeSourceReference(), false); + } + + } - private boolean fReorderedMembers; - private boolean fForceFireSelectionChanged; - public JavaOutlineViewer(Tree tree) { - super(tree); - setAutoExpandLevel(ALL_LEVELS); - } + /** 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 ListenerList fPostSelectionChangedListeners= new ListenerList(); + private Hashtable fActions= new Hashtable(); + + private TogglePresentationAction fTogglePresentation; + private GotoAnnotationAction fPreviousAnnotation; + private GotoAnnotationAction fNextAnnotation; + private TextEditorAction fShowJavadoc; + private TextOperationAction fUndo; + private TextOperationAction fRedo; + + private ToggleLinkingAction fToggleLinkingAction; + + private CompositeActionGroup fActionGroups; - /** - * Investigates the given element change event and if affected - * incrementally updates the Java outline. + private IPropertyChangeListener fPropertyChangeListener; + /** + * Custom filter action group. + * @since 3.0 + */ + private CustomFiltersActionGroup fCustomFiltersActionGroup; + + public JavaOutlinePage(String contextMenuID, PHPEditor editor) { + super(); + + Assert.isNotNull(editor); + + fContextMenuID= contextMenuID; + fEditor= editor; + + fTogglePresentation= new TogglePresentationAction(); + fPreviousAnnotation= new GotoAnnotationAction("PreviousAnnotation.", false); //$NON-NLS-1$ + fNextAnnotation= new GotoAnnotationAction("NextAnnotation.", true); //$NON-NLS-1$ + fShowJavadoc= (TextEditorAction) fEditor.getAction("ShowJavaDoc"); //$NON-NLS-1$ + fUndo= (TextOperationAction) fEditor.getAction(ITextEditorActionConstants.UNDO); + fRedo= (TextOperationAction) fEditor.getAction(ITextEditorActionConstants.REDO); + + fTogglePresentation.setEditor(editor); + fPreviousAnnotation.setEditor(editor); + fNextAnnotation.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 delta the Java element delta used to reconcile the Java outline + * @param compilationUnit the compilation unit + * @return returns the primary type of the compilation unit, or + * null if is does not have one */ - public void reconcile(IJavaElementDelta delta) { - fReorderedMembers= false; - fForceFireSelectionChanged= false; - if (getSorter() == null) { - if (fTopLevelTypeOnly - && delta.getElement() instanceof IType - && (delta.getKind() & IJavaElementDelta.ADDED) != 0) - { - refresh(true); + protected IType getMainType(ICompilationUnit compilationUnit) { + + if (compilationUnit == null) + return null; + + 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; + } - } else { - Widget w= findItem(fInput); - if (w != null && !w.isDisposed()) - update(w, delta); - if (fForceFireSelectionChanged) - fireSelectionChanged(new SelectionChangedEvent(getSite().getSelectionProvider(), this.getSelection())); - if (fReorderedMembers) { - refresh(false); - fReorderedMembers= false; - } + /** + * 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 (MembersOrderPreferenceCache.isMemberOrderProperty(event.getProperty())) { + fOutlineViewer.refresh(false); } - } else { - // just for now - refresh(true); } + } + + /* + * @see ISelectionProvider#addSelectionChangedListener(ISelectionChangedListener) + */ + public void addSelectionChangedListener(ISelectionChangedListener listener) { + if (fOutlineViewer != null) + fOutlineViewer.addSelectionChangedListener(listener); + else + fSelectionChangedListeners.add(listener); } - - /* - * @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; - fForceFireSelectionChanged= true; - } - - 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; - } - /* - * @see org.eclipse.jface.viewers.AbstractTreeViewer#isExpandable(java.lang.Object) + + /* + * @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(); + } + + /* + * @see org.eclipse.jface.text.IPostSelectionProvider#addPostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) */ - public boolean isExpandable(Object element) { - if (hasFilters()) { - return getFilteredChildren(element).length > 0; + public void addPostSelectionChangedListener(ISelectionChangedListener listener) { + if (fOutlineViewer != null) + fOutlineViewer.addPostSelectionChangedListener(listener); + else + fPostSelectionChangedListeners.add(listener); + } + + /* + * @see org.eclipse.jface.text.IPostSelectionProvider#removePostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) + */ + public void removePostSelectionChangedListener(ISelectionChangedListener listener) { + if (fOutlineViewer != null) + fOutlineViewer.removePostSelectionChangedListener(listener); + else + fPostSelectionChangedListeners.remove(listener); + } + + private void registerToolbarActions(IActionBars actionBars) { + + IToolBarManager toolBarManager= actionBars.getToolBarManager(); + if (toolBarManager != null) { + toolBarManager.add(new LexicalSortingAction()); + + fMemberFilterActionGroup= new MemberFilterActionGroup(fOutlineViewer, "net.sourceforge.phpeclipse.JavaOutlinePage"); //$NON-NLS-1$ + fMemberFilterActionGroup.contributeToToolBar(toolBarManager); + + fCustomFiltersActionGroup.fillActionBars(actionBars); + + IMenuManager menu= actionBars.getMenuManager(); + menu.add(new Separator("EndFilterGroup")); //$NON-NLS-1$ + + fToggleLinkingAction= new ToggleLinkingAction(this); + menu.add(new ClassOnlyAction()); + menu.add(fToggleLinkingAction); } - return super.isExpandable(element); } - 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; - boolean doUpdateParentsPlus = 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) { - // remove from collapsed parent - if ((status & IJavaElementDelta.REMOVED) != 0) { - doUpdateParentsPlus = true; - continue; - } - // 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()); - if (!doUpdateParent && doUpdateParentsPlus && w instanceof Item) - updatePlus((Item) 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$ - } - }; - - /** - * This action toggles whether this Java Outline page links its selection to the active editor. - * - * @since 3.0 - */ - public class ToggleLinkingAction extends AbstractToggleLinkingAction { - - JavaOutlinePage fJavaOutlinePage; - - /** - * Constructs a new action. - * - * @param outlinePage - * the Java outline page - */ - public ToggleLinkingAction(JavaOutlinePage outlinePage) { - boolean isLinkingEnabled = PreferenceConstants.getPreferenceStore().getBoolean( - PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE); - setChecked(isLinkingEnabled); - fJavaOutlinePage = outlinePage; - } - - /** - * Runs the action. - */ - public void run() { - PreferenceConstants.getPreferenceStore().setValue(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE, isChecked()); - if (isChecked() && fEditor != null) - fEditor.synchronizeOutlinePage(fEditor.computeHighlightRangeSourceReference(), false); - } - - } - - /** 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 ListenerList fPostSelectionChangedListeners = new ListenerList(); - - private Hashtable fActions = new Hashtable(); - - private TogglePresentationAction fTogglePresentation; - - private GotoErrorAction fPreviousError; - - private GotoErrorAction fNextError; - - private TextEditorAction fShowJavadoc; + + /* + * @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); + initDragAndDrop(); + 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.addSelectionChangedListener((ISelectionChangedListener) listeners[i]); + } + + listeners= fPostSelectionChangedListeners.getListeners(); + for (int i= 0; i < listeners.length; i++) { + fPostSelectionChangedListeners.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 m) { + contextMenuAboutToShow(m); + } + }); + 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), +// 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, fPreviousAnnotation); + bars.setGlobalActionHandler(ITextEditorActionConstants.NEXT, fNextAnnotation); + bars.setGlobalActionHandler(PHPdtActionConstants.SHOW_JAVA_DOC, fShowJavadoc); + bars.setGlobalActionHandler(ITextEditorActionDefinitionIds.TOGGLE_SHOW_SELECTED_ELEMENT_ONLY, fTogglePresentation); + bars.setGlobalActionHandler(ITextEditorActionDefinitionIds.GOTO_NEXT_ANNOTATION, fNextAnnotation); + bars.setGlobalActionHandler(ITextEditorActionDefinitionIds.GOTO_PREVIOUS_ANNOTATION, fPreviousAnnotation); + + + fActionGroups.fillActionBars(bars); + + IStatusLineManager statusLineManager= bars.getStatusLineManager(); + if (statusLineManager != null) { + StatusBarUpdater updater= new StatusBarUpdater(statusLineManager); + fOutlineViewer.addPostSelectionChangedListener(updater); + } + // Custom filter group + fCustomFiltersActionGroup= new CustomFiltersActionGroup("net.sourceforge.phpdt.ui.JavaOutlinePage", fOutlineViewer); //$NON-NLS-1$ - private TextOperationAction fUndo; + registerToolbarActions(bars); + + fOutlineViewer.setInput(fInput); + } - private TextOperationAction fRedo; + public void dispose() { + + if (fEditor == null) + return; + + if (fMemberFilterActionGroup != null) { + fMemberFilterActionGroup.dispose(); + fMemberFilterActionGroup= null; + } + + if (fCustomFiltersActionGroup != null) { + fCustomFiltersActionGroup.dispose(); + fCustomFiltersActionGroup= null; + } + + + fEditor.outlinePageClosed(); + fEditor= null; + + fSelectionChangedListeners.clear(); + fSelectionChangedListeners= null; + + fPostSelectionChangedListeners.clear(); + fPostSelectionChangedListeners= 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); + fPreviousAnnotation.setEditor(null); + fNextAnnotation.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); + } - private ToggleLinkingAction fToggleLinkingAction; + /* + * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) + */ + 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 }; + } - private CompositeActionGroup fActionGroups; + }; + } + if (key == IShowInTarget.class) { + return getShowInTarget(); + } - // private CCPActionGroup fCCPActionGroup; + return null; + } - private IPropertyChangeListener fPropertyChangeListener; - /** - * Custom filter action group. - * @since 3.0 + /** + * Convenience method to add the action installed under the given actionID to the + * specified group of the menu. + * + * @param menu the menu manager + * @param group the group to which to add the action + * @param actionID the ID of the new action */ - private CustomFiltersActionGroup fCustomFiltersActionGroup; + 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); + } - 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; - } - - /* - * (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); - // - // } - // } - - private void registerToolbarActions(IActionBars actionBars) { - - IToolBarManager toolBarManager = actionBars.getToolBarManager(); - if (toolBarManager != null) { - toolBarManager.add(new LexicalSortingAction()); - - fMemberFilterActionGroup = new MemberFilterActionGroup(fOutlineViewer, "net.sourceforge.phpeclipse.JavaOutlinePage"); //$NON-NLS-1$ - fMemberFilterActionGroup.contributeToToolBar(toolBarManager); - - fCustomFiltersActionGroup.fillActionBars(actionBars); - - IMenuManager menu = actionBars.getMenuManager(); - menu.add(new Separator("EndFilterGroup")); //$NON-NLS-1$ - - fToggleLinkingAction = new ToggleLinkingAction(this); - menu.add(new ClassOnlyAction()); - menu.add(fToggleLinkingAction); - } - } - - /* - * @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]); - } - - listeners = fPostSelectionChangedListeners.getListeners(); - for (int i = 0; i < listeners.length; i++) { - fPostSelectionChangedListeners.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); - } - -// Custom filter group - fCustomFiltersActionGroup= new CustomFiltersActionGroup("net.sourceforge.phpeclipse.JavaOutlinePage", fOutlineViewer); //$NON-NLS-1$ - - registerToolbarActions(bars); - - 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; - } - - if (fCustomFiltersActionGroup != null) { - fCustomFiltersActionGroup.dispose(); - fCustomFiltersActionGroup= null; + /* + * @see Page#setFocus() + */ + public void setFocus() { + if (fOutlineViewer != null) + fOutlineViewer.getControl().setFocus(); + } + + /** + * Checks whether a given Java element is an inner type. + * + * @param element the java element + * @return true iff the given element is an inner type + */ + private boolean isInnerType(IJavaElement element) { + + if (element != null && element.getElementType() == IJavaElement.TYPE) { + IType type= (IType)element; + try { + return type.isMember(); + } catch (JavaModelException e) { + IJavaElement parent= type.getParent(); + if (parent != null) { + int parentElementType= parent.getElementType(); + return (parentElementType != IJavaElement.COMPILATION_UNIT && parentElementType != IJavaElement.CLASS_FILE); + } + } + } + + return false; + } + + /** + * Returns the IShowInSource for this view. + * + * @return the {@link IShowInSource} + */ + protected IShowInSource getShowInSource() { + return new IShowInSource() { + public ShowInContext getShowInContext() { + return new ShowInContext( + null, + getSite().getSelectionProvider().getSelection()); + } + }; } - - fEditor.outlinePageClosed(); - fEditor = null; - - fSelectionChangedListeners.clear(); - fSelectionChangedListeners = null; - - fPostSelectionChangedListeners.clear(); - fPostSelectionChangedListeners = 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)); - } - - /* - * @see org.eclipse.jface.text.IPostSelectionProvider#addPostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) - */ - public void addPostSelectionChangedListener(ISelectionChangedListener listener) { - if (fOutlineViewer != null) - fOutlineViewer.addPostSelectionChangedListener(listener); - else - fPostSelectionChangedListeners.add(listener); - } - /* - * @see org.eclipse.jface.text.IPostSelectionProvider#removePostSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) - */ - public void removePostSelectionChangedListener(ISelectionChangedListener listener) { - if (fOutlineViewer != null) - fOutlineViewer.removePostSelectionChangedListener(listener); - else - fPostSelectionChangedListeners.remove(listener); - } -} \ No newline at end of file + /** + * Returns the IShowInTarget for this view. + * + * @return the {@link IShowInTarget} + */ + 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)); + } +} -- 1.7.1